]> git.saurik.com Git - wxWidgets.git/blob - src/common/glcmn.cpp
Correct wxPendingDelete declaration.
[wxWidgets.git] / src / common / glcmn.cpp
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"
36 WX_CHECK_BUILD_OPTIONS("wxGL")
37
38 IMPLEMENT_CLASS(wxGLApp, wxApp)
39
40 // ============================================================================
41 // implementation
42 // ============================================================================
43
44 wxGLCanvasBase::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
55 bool wxGLCanvasBase::SetCurrent(const wxGLContext& context) const
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
60 wxASSERT_MSG( IsShownOnScreen(), wxT("can't make hidden GL canvas current") );
61
62
63 return context.SetCurrent(*static_cast<const wxGLCanvas *>(this));
64 }
65
66 bool wxGLCanvasBase::SetColour(const wxString& colour)
67 {
68 wxColour col = wxTheColourDatabase->Find(colour);
69 if ( !col.Ok() )
70 return false;
71
72 #ifdef wxHAS_OPENGL_ES
73 wxGLAPI::glColor3f(col.Red() / 256., col.Green() / 256., col.Blue() / 256.);
74 #else
75 GLboolean isRGBA;
76 glGetBooleanv(GL_RGBA_MODE, &isRGBA);
77 if ( isRGBA )
78 {
79 glColor3f(col.Red() / 256., col.Green() / 256., col.Blue() / 256.);
80 }
81 else // indexed colour
82 {
83 GLint pix = GetColourIndex(col);
84 if ( pix == -1 )
85 {
86 wxLogError(_("Failed to allocate colour for OpenGL"));
87 return false;
88 }
89
90 glIndexi(pix);
91 }
92 #endif
93 return true;
94 }
95
96 wxGLCanvasBase::~wxGLCanvasBase()
97 {
98 #if WXWIN_COMPATIBILITY_2_8
99 delete m_glContext;
100 #endif // WXWIN_COMPATIBILITY_2_8
101 }
102
103 #if WXWIN_COMPATIBILITY_2_8
104
105 wxGLContext *wxGLCanvasBase::GetContext() const
106 {
107 return m_glContext;
108 }
109
110 void wxGLCanvasBase::SetCurrent()
111 {
112 if ( m_glContext )
113 SetCurrent(*m_glContext);
114 }
115
116 void wxGLCanvasBase::OnSize(wxSizeEvent& WXUNUSED(event))
117 {
118 }
119
120 #endif // WXWIN_COMPATIBILITY_2_8
121
122 /* static */
123 bool wxGLCanvasBase::IsExtensionInList(const char *list, const char *extension)
124 {
125 if ( !list )
126 return false;
127
128 for ( const char *p = list; *p; p++ )
129 {
130 // advance up to the next possible match
131 p = wxStrstr(p, extension);
132 if ( !p )
133 break;
134
135 // check that the extension appears at the beginning/ending of the list
136 // or is preceded/followed by a space to avoid mistakenly finding
137 // "glExtension" in a list containing some "glFunkyglExtension"
138 if ( (p == list || p[-1] == ' ') )
139 {
140 char c = p[strlen(extension)];
141 if ( c == '\0' || c == ' ' )
142 return true;
143 }
144 }
145
146 return false;
147 }
148
149 // ============================================================================
150 // compatibility layer for OpenGL 3 and OpenGL ES
151 // ============================================================================
152
153 static wxGLAPI s_glAPI;
154
155 #if wxUSE_OPENGL_EMULATION
156
157 #include "wx/vector.h"
158
159 static GLenum s_mode;
160
161 static GLfloat s_currentTexCoord[2];
162 static GLfloat s_currentColor[4];
163 static GLfloat s_currentNormal[3];
164
165 // TODO move this into a different construct with locality for all attributes
166 // of a vertex
167
168 static wxVector<GLfloat> s_texCoords;
169 static wxVector<GLfloat> s_vertices;
170 static wxVector<GLfloat> s_normals;
171 static wxVector<GLfloat> s_colors;
172
173 static bool s_texCoordsUsed;
174 static bool s_colorsUsed;
175 static bool s_normalsUsed;
176
177 bool SetState( int flag, bool desired )
178 {
179 bool former = glIsEnabled( flag );
180 if ( former != desired )
181 {
182 if ( desired )
183 glEnableClientState(flag);
184 else
185 glDisableClientState(flag);
186 }
187 return former;
188 }
189
190 void RestoreState( int flag, bool desired )
191 {
192 if ( desired )
193 glEnableClientState(flag);
194 else
195 glDisableClientState(flag);
196 }
197 #endif
198
199 wxGLAPI::wxGLAPI()
200 {
201 #if wxUSE_OPENGL_EMULATION
202 s_mode = 0xFF;
203 #endif
204 }
205
206 wxGLAPI::~wxGLAPI()
207 {
208 }
209
210 void wxGLAPI::glFrustum(GLfloat left, GLfloat right, GLfloat bottom,
211 GLfloat top, GLfloat zNear, GLfloat zFar)
212 {
213 #if wxUSE_OPENGL_EMULATION
214 ::glFrustumf(left, right, bottom, top, zNear, zFar);
215 #else
216 ::glFrustum(left, right, bottom, top, zNear, zFar);
217 #endif
218 }
219
220
221 void wxGLAPI::glBegin(GLenum mode)
222 {
223 #if wxUSE_OPENGL_EMULATION
224 if ( s_mode != 0xFF )
225 {
226 wxFAIL_MSG("nested glBegin");
227 }
228
229 s_mode = mode;
230 s_texCoordsUsed = false;
231 s_colorsUsed = false;
232 s_normalsUsed = false;
233
234 s_texCoords.clear();
235 s_normals.clear();
236 s_colors.clear();
237 s_vertices.clear();
238 #else
239 ::glBegin(mode);
240 #endif
241 }
242
243 void wxGLAPI::glTexCoord2f(GLfloat s, GLfloat t)
244 {
245 #if wxUSE_OPENGL_EMULATION
246 if ( s_mode == 0xFF )
247 {
248 wxFAIL_MSG("glTexCoord2f called outside glBegin/glEnd");
249 }
250
251 else
252 {
253 s_texCoordsUsed = true;
254 s_currentTexCoord[0] = s;
255 s_currentTexCoord[1] = t;
256 }
257 #else
258 ::glTexCoord2f(s,t);
259 #endif
260 }
261
262 void wxGLAPI::glVertex3f(GLfloat x, GLfloat y, GLfloat z)
263 {
264 #if wxUSE_OPENGL_EMULATION
265 if ( s_mode == 0xFF )
266 {
267 wxFAIL_MSG("glVertex3f called outside glBegin/glEnd");
268 }
269 else
270 {
271 s_texCoords.push_back(s_currentTexCoord[0]);
272 s_texCoords.push_back(s_currentTexCoord[1]);
273
274 s_normals.push_back(s_currentNormal[0]);
275 s_normals.push_back(s_currentNormal[1]);
276 s_normals.push_back(s_currentNormal[2]);
277
278 s_colors.push_back(s_currentColor[0]);
279 s_colors.push_back(s_currentColor[1]);
280 s_colors.push_back(s_currentColor[2]);
281 s_colors.push_back(s_currentColor[3]);
282
283 s_vertices.push_back(x);
284 s_vertices.push_back(y);
285 s_vertices.push_back(z);
286 }
287 #else
288 ::glVertex3f(x,y,z);
289 #endif
290 }
291
292 void wxGLAPI::glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz)
293 {
294 #if wxUSE_OPENGL_EMULATION
295 if ( s_mode == 0xFF )
296 ::glNormal3f(nx,ny,nz);
297 else
298 {
299 s_normalsUsed = true;
300 s_currentNormal[0] = nx;
301 s_currentNormal[1] = ny;
302 s_currentNormal[2] = nz;
303 }
304 #else
305 ::glNormal3f(nx,ny,nz);
306 #endif
307 }
308
309 void wxGLAPI::glColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
310 {
311 #if wxUSE_OPENGL_EMULATION
312 if ( s_mode == 0xFF )
313 ::glColor4f(r,g,b,a);
314 else
315 {
316 s_colorsUsed = true;
317 s_currentColor[0] = r;
318 s_currentColor[1] = g;
319 s_currentColor[2] = b;
320 s_currentColor[3] = a;
321 }
322 #else
323 ::glColor4f(r,g,b,a);
324 #endif
325 }
326
327 void wxGLAPI::glColor3f(GLfloat r, GLfloat g, GLfloat b)
328 {
329 #if wxUSE_OPENGL_EMULATION
330 glColor4f(r,g,b,1.0);
331 #else
332 ::glColor3f(r,g,b);
333 #endif
334 }
335
336 void wxGLAPI::glEnd()
337 {
338 #if wxUSE_OPENGL_EMULATION
339 bool formerColors = SetState( GL_COLOR_ARRAY, s_colorsUsed );
340 bool formerNormals = SetState( GL_NORMAL_ARRAY, s_normalsUsed );
341 bool formerTexCoords = SetState( GL_TEXTURE_COORD_ARRAY, s_texCoordsUsed );
342 bool formerVertex = glIsEnabled(GL_VERTEX_ARRAY);
343
344 if( !formerVertex )
345 glEnableClientState(GL_VERTEX_ARRAY);
346
347 if ( s_colorsUsed )
348 glColorPointer( 4, GL_FLOAT, 0, &s_colors[0] );
349
350 if ( s_normalsUsed )
351 glNormalPointer( GL_FLOAT, 0, &s_normals[0] );
352
353 if ( s_texCoordsUsed )
354 glTexCoordPointer( 2, GL_FLOAT, 0, &s_texCoords[0] );
355
356 glVertexPointer(3, GL_FLOAT, 0, &s_vertices[0]);
357 glDrawArrays( s_mode, 0, s_vertices.size() / 3 );
358
359 if ( s_colorsUsed != formerColors )
360 RestoreState( GL_COLOR_ARRAY, formerColors );
361
362 if ( s_normalsUsed != formerNormals )
363 RestoreState( GL_NORMAL_ARRAY, formerColors );
364
365 if ( s_texCoordsUsed != formerTexCoords )
366 RestoreState( GL_TEXTURE_COORD_ARRAY, formerColors );
367
368 if( !formerVertex )
369 glDisableClientState(GL_VERTEX_ARRAY);
370
371 s_mode = 0xFF;
372 #else
373 ::glEnd();
374 #endif
375 }
376
377 #endif // wxUSE_GLCANVAS
378