]> git.saurik.com Git - wxWidgets.git/blame - src/common/glcmn.cpp
Document wxGridCellAttrProvider.
[wxWidgets.git] / src / common / glcmn.cpp
CommitLineData
dc3065a5
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/common/glcmn.cpp
3// Purpose: wxGLCanvasBase implementation
4// Author: Vadim Zeitlin
5// Created: 2007-04-09
6// RCS-ID: $Id$
7// Copyright: (c) 2007 Vadim Zeitlin <vadim@wxwindows.org>
8// Licence: wxWindows licence
9///////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
19// for compilers that support precompilation, includes "wx.h".
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
23 #pragma hdrstop
24#endif
25
26#if wxUSE_GLCANVAS
27
28#ifndef WX_PRECOMP
29 #include "wx/log.h"
30#endif // WX_PRECOMP
31
32#include "wx/glcanvas.h"
33
34// DLL options compatibility check:
35#include "wx/build.h"
36WX_CHECK_BUILD_OPTIONS("wxGL")
37
38IMPLEMENT_CLASS(wxGLApp, wxApp)
39
40// ============================================================================
41// implementation
42// ============================================================================
43
15b239c0
VZ
44wxGLCanvasBase::wxGLCanvasBase()
45{
46#if WXWIN_COMPATIBILITY_2_8
47 m_glContext = NULL;
48#endif
49
50 // we always paint background entirely ourselves so prevent wx from erasing
51 // it to avoid flicker
52 SetBackgroundStyle(wxBG_STYLE_CUSTOM);
53}
54
5ec69e96 55bool wxGLCanvasBase::SetCurrent(const wxGLContext& context) const
dc3065a5
VZ
56{
57 // although on MSW it works even if the window is still hidden, it doesn't
58 // work in other ports (notably X11-based ones) and documentation mentions
59 // that SetCurrent() can only be called for a shown window, so check for it
9a83f860 60 wxASSERT_MSG( IsShownOnScreen(), wxT("can't make hidden GL canvas current") );
dc3065a5 61
e7ee4873 62
5c33522f 63 return context.SetCurrent(*static_cast<const wxGLCanvas *>(this));
dc3065a5
VZ
64}
65
03647350 66#ifndef wxHAS_OPENGL_ES
35f1f4f7 67bool wxGLCanvasBase::SetColour(const wxString& colour)
dc3065a5
VZ
68{
69 wxColour col = wxTheColourDatabase->Find(colour);
70 if ( !col.Ok() )
71 return false;
72
73 GLboolean isRGBA;
74 glGetBooleanv(GL_RGBA_MODE, &isRGBA);
75 if ( isRGBA )
76 {
77 glColor3f(col.Red() / 256., col.Green() / 256., col.Blue() / 256.);
78 }
79 else // indexed colour
80 {
81 GLint pix = GetColourIndex(col);
82 if ( pix == -1 )
83 {
84 wxLogError(_("Failed to allocate colour for OpenGL"));
85 return false;
86 }
87
88 glIndexi(pix);
89 }
90
91 return true;
92}
04ce16a8 93#endif
dc3065a5
VZ
94
95wxGLCanvasBase::~wxGLCanvasBase()
96{
97#if WXWIN_COMPATIBILITY_2_8
98 delete m_glContext;
99#endif // WXWIN_COMPATIBILITY_2_8
100}
101
102#if WXWIN_COMPATIBILITY_2_8
103
104wxGLContext *wxGLCanvasBase::GetContext() const
105{
106 return m_glContext;
107}
108
109void wxGLCanvasBase::SetCurrent()
110{
111 if ( m_glContext )
112 SetCurrent(*m_glContext);
113}
114
115void wxGLCanvasBase::OnSize(wxSizeEvent& WXUNUSED(event))
116{
117}
118
119#endif // WXWIN_COMPATIBILITY_2_8
120
c39d2e0a
VZ
121/* static */
122bool wxGLCanvasBase::IsExtensionInList(const char *list, const char *extension)
123{
442e842e
VZ
124 if ( !list )
125 return false;
126
c39d2e0a
VZ
127 for ( const char *p = list; *p; p++ )
128 {
129 // advance up to the next possible match
130 p = wxStrstr(p, extension);
131 if ( !p )
132 break;
133
134 // check that the extension appears at the beginning/ending of the list
135 // or is preceded/followed by a space to avoid mistakenly finding
136 // "glExtension" in a list containing some "glFunkyglExtension"
137 if ( (p == list || p[-1] == ' ') )
138 {
139 char c = p[strlen(extension)];
140 if ( c == '\0' || c == ' ' )
141 return true;
142 }
143 }
144
145 return false;
146}
147
e7ee4873
SC
148// ============================================================================
149// compatibility layer for OpenGL 3 and OpenGL ES
150// ============================================================================
151
152static wxGLAPI s_glAPI;
153
154#if wxUSE_OPENGL_EMULATION
155
156#include "wx/vector.h"
157
158static GLenum s_mode;
159
160static GLfloat s_currentTexCoord[2];
161static GLfloat s_currentColor[4];
162static GLfloat s_currentNormal[3];
163
164// TODO move this into a different construct with locality for all attributes
165// of a vertex
166
167static wxVector<GLfloat> s_texCoords;
168static wxVector<GLfloat> s_vertices;
169static wxVector<GLfloat> s_normals;
170static wxVector<GLfloat> s_colors;
171
172static bool s_texCoordsUsed;
173static bool s_colorsUsed;
174static bool s_normalsUsed;
175
176bool SetState( int flag, bool desired )
177{
178 bool former = glIsEnabled( flag );
179 if ( former != desired )
180 {
181 if ( desired )
182 glEnableClientState(flag);
183 else
184 glDisableClientState(flag);
185 }
186 return former;
187}
188
189void RestoreState( int flag, bool desired )
190{
191 if ( desired )
192 glEnableClientState(flag);
193 else
194 glDisableClientState(flag);
195}
196#endif
197
198wxGLAPI::wxGLAPI()
199{
200#if wxUSE_OPENGL_EMULATION
201 s_mode = 0xFF;
202#endif
203}
204
205wxGLAPI::~wxGLAPI()
206{
207}
208
209void wxGLAPI::glBegin(GLenum mode)
210{
211#if wxUSE_OPENGL_EMULATION
212 if ( s_mode != 0xFF )
213 {
214 wxFAIL_MSG("nested glBegin");
215 }
216
217 s_mode = mode;
218 s_texCoordsUsed = false;
219 s_colorsUsed = false;
220 s_normalsUsed = false;
221
222 s_texCoords.clear();
223 s_normals.clear();
224 s_colors.clear();
225 s_vertices.clear();
226#else
227 ::glBegin(mode);
228#endif
229}
230
231void wxGLAPI::glTexCoord2f(GLfloat s, GLfloat t)
232{
233#if wxUSE_OPENGL_EMULATION
234 if ( s_mode == 0xFF )
235 {
236 wxFAIL_MSG("glTexCoord2f called outside glBegin/glEnd");
237 }
238
239 else
240 {
241 s_texCoordsUsed = true;
242 s_currentTexCoord[0] = s;
243 s_currentTexCoord[1] = t;
244 }
245#else
246 ::glTexCoord2f(s,t);
247#endif
248}
249
250void wxGLAPI::glVertex3f(GLfloat x, GLfloat y, GLfloat z)
251{
252#if wxUSE_OPENGL_EMULATION
253 if ( s_mode == 0xFF )
254 {
255 wxFAIL_MSG("glVertex3f called outside glBegin/glEnd");
256 }
257 else
258 {
259 s_texCoords.push_back(s_currentTexCoord[0]);
260 s_texCoords.push_back(s_currentTexCoord[1]);
261
262 s_normals.push_back(s_currentNormal[0]);
263 s_normals.push_back(s_currentNormal[1]);
264 s_normals.push_back(s_currentNormal[2]);
265
266 s_colors.push_back(s_currentColor[0]);
267 s_colors.push_back(s_currentColor[1]);
268 s_colors.push_back(s_currentColor[2]);
269 s_colors.push_back(s_currentColor[3]);
270
271 s_vertices.push_back(x);
272 s_vertices.push_back(y);
273 s_vertices.push_back(z);
274 }
275#else
276 ::glVertex3f(x,y,z);
277#endif
278}
279
280void wxGLAPI::glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz)
281{
282#if wxUSE_OPENGL_EMULATION
283 if ( s_mode == 0xFF )
284 ::glNormal3f(nx,ny,nz);
285 else
286 {
287 s_normalsUsed = true;
288 s_currentNormal[0] = nx;
289 s_currentNormal[1] = ny;
290 s_currentNormal[2] = nz;
291 }
292#else
293 ::glNormal3f(nx,ny,nz);
294#endif
295}
296
297void wxGLAPI::glColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
298{
299#if wxUSE_OPENGL_EMULATION
300 if ( s_mode == 0xFF )
301 ::glColor4f(r,g,b,a);
302 else
303 {
304 s_colorsUsed = true;
305 s_currentColor[0] = r;
306 s_currentColor[1] = g;
307 s_currentColor[2] = b;
308 s_currentColor[3] = a;
309 }
310#else
311 ::glColor4f(r,g,b,a);
312#endif
313}
314
315void wxGLAPI::glColor3f(GLfloat r, GLfloat g, GLfloat b)
316{
317#if wxUSE_OPENGL_EMULATION
318 glColor4f(r,g,b,1.0);
319#else
320 ::glColor3f(r,g,b);
321#endif
322}
323
324void wxGLAPI::glEnd()
325{
326#if wxUSE_OPENGL_EMULATION
327 bool formerColors = SetState( GL_COLOR_ARRAY, s_colorsUsed );
328 bool formerNormals = SetState( GL_NORMAL_ARRAY, s_normalsUsed );
329 bool formerTexCoords = SetState( GL_TEXTURE_COORD_ARRAY, s_texCoordsUsed );
330 bool formerVertex = glIsEnabled(GL_VERTEX_ARRAY);
331
332 if( !formerVertex )
333 glEnableClientState(GL_VERTEX_ARRAY);
334
335 if ( s_colorsUsed )
336 glColorPointer( 4, GL_FLOAT, 0, &s_colors[0] );
337
338 if ( s_normalsUsed )
339 glNormalPointer( GL_FLOAT, 0, &s_normals[0] );
340
341 if ( s_texCoordsUsed )
342 glTexCoordPointer( 2, GL_FLOAT, 0, &s_texCoords[0] );
343
344 glVertexPointer(3, GL_FLOAT, 0, &s_vertices[0]);
345 glDrawArrays( s_mode, 0, s_vertices.size() / 3 );
346
347 if ( s_colorsUsed != formerColors )
348 RestoreState( GL_COLOR_ARRAY, formerColors );
349
350 if ( s_normalsUsed != formerNormals )
351 RestoreState( GL_NORMAL_ARRAY, formerColors );
352
353 if ( s_texCoordsUsed != formerTexCoords )
354 RestoreState( GL_TEXTURE_COORD_ARRAY, formerColors );
355
356 if( !formerVertex )
357 glDisableClientState(GL_VERTEX_ARRAY);
358
359 s_mode = 0xFF;
360#else
361 ::glEnd();
362#endif
363}
364
dc3065a5
VZ
365#endif // wxUSE_GLCANVAS
366