1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/glcmn.cpp
3 // Purpose: wxGLCanvasBase implementation
4 // Author: Vadim Zeitlin
7 // Copyright: (c) 2007 Vadim Zeitlin <vadim@wxwindows.org>
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
13 // ============================================================================
15 // ----------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------
19 // for compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
32 #include "wx/glcanvas.h"
34 // DLL options compatibility check:
36 WX_CHECK_BUILD_OPTIONS("wxGL")
38 IMPLEMENT_CLASS(wxGLApp
, wxApp
)
40 // ============================================================================
42 // ============================================================================
44 wxGLCanvasBase::wxGLCanvasBase()
46 #if WXWIN_COMPATIBILITY_2_8
50 // we always paint background entirely ourselves so prevent wx from erasing
51 // it to avoid flicker
52 SetBackgroundStyle(wxBG_STYLE_CUSTOM
);
55 bool wxGLCanvasBase::SetCurrent(const wxGLContext
& context
) const
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") );
63 return context
.SetCurrent(*static_cast<const wxGLCanvas
*>(this));
66 bool wxGLCanvasBase::SetColour(const wxString
& colour
)
68 wxColour col
= wxTheColourDatabase
->Find(colour
);
72 #ifdef wxHAS_OPENGL_ES
73 wxGLAPI::glColor3f(col
.Red() / 256., col
.Green() / 256., col
.Blue() / 256.);
76 glGetBooleanv(GL_RGBA_MODE
, &isRGBA
);
79 glColor3f(col
.Red() / 256., col
.Green() / 256., col
.Blue() / 256.);
81 else // indexed colour
83 GLint pix
= GetColourIndex(col
);
86 wxLogError(_("Failed to allocate colour for OpenGL"));
96 wxGLCanvasBase::~wxGLCanvasBase()
98 #if WXWIN_COMPATIBILITY_2_8
100 #endif // WXWIN_COMPATIBILITY_2_8
103 #if WXWIN_COMPATIBILITY_2_8
105 wxGLContext
*wxGLCanvasBase::GetContext() const
110 void wxGLCanvasBase::SetCurrent()
113 SetCurrent(*m_glContext
);
116 void wxGLCanvasBase::OnSize(wxSizeEvent
& WXUNUSED(event
))
120 #endif // WXWIN_COMPATIBILITY_2_8
123 bool wxGLCanvasBase::IsExtensionInList(const char *list
, const char *extension
)
128 for ( const char *p
= list
; *p
; p
++ )
130 // advance up to the next possible match
131 p
= wxStrstr(p
, extension
);
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] == ' ') )
140 char c
= p
[strlen(extension
)];
141 if ( c
== '\0' || c
== ' ' )
149 // ============================================================================
150 // compatibility layer for OpenGL 3 and OpenGL ES
151 // ============================================================================
153 static wxGLAPI s_glAPI
;
155 #if wxUSE_OPENGL_EMULATION
157 #include "wx/vector.h"
159 static GLenum s_mode
;
161 static GLfloat s_currentTexCoord
[2];
162 static GLfloat s_currentColor
[4];
163 static GLfloat s_currentNormal
[3];
165 // TODO move this into a different construct with locality for all attributes
168 static wxVector
<GLfloat
> s_texCoords
;
169 static wxVector
<GLfloat
> s_vertices
;
170 static wxVector
<GLfloat
> s_normals
;
171 static wxVector
<GLfloat
> s_colors
;
173 static bool s_texCoordsUsed
;
174 static bool s_colorsUsed
;
175 static bool s_normalsUsed
;
177 bool SetState( int flag
, bool desired
)
179 bool former
= glIsEnabled( flag
);
180 if ( former
!= desired
)
183 glEnableClientState(flag
);
185 glDisableClientState(flag
);
190 void RestoreState( int flag
, bool desired
)
193 glEnableClientState(flag
);
195 glDisableClientState(flag
);
201 #if wxUSE_OPENGL_EMULATION
210 void wxGLAPI::glFrustum(GLfloat left
, GLfloat right
, GLfloat bottom
,
211 GLfloat top
, GLfloat zNear
, GLfloat zFar
)
213 #if wxUSE_OPENGL_EMULATION
214 ::glFrustumf(left
, right
, bottom
, top
, zNear
, zFar
);
216 ::glFrustum(left
, right
, bottom
, top
, zNear
, zFar
);
221 void wxGLAPI::glBegin(GLenum mode
)
223 #if wxUSE_OPENGL_EMULATION
224 if ( s_mode
!= 0xFF )
226 wxFAIL_MSG("nested glBegin");
230 s_texCoordsUsed
= false;
231 s_colorsUsed
= false;
232 s_normalsUsed
= false;
243 void wxGLAPI::glTexCoord2f(GLfloat s
, GLfloat t
)
245 #if wxUSE_OPENGL_EMULATION
246 if ( s_mode
== 0xFF )
248 wxFAIL_MSG("glTexCoord2f called outside glBegin/glEnd");
253 s_texCoordsUsed
= true;
254 s_currentTexCoord
[0] = s
;
255 s_currentTexCoord
[1] = t
;
262 void wxGLAPI::glVertex3f(GLfloat x
, GLfloat y
, GLfloat z
)
264 #if wxUSE_OPENGL_EMULATION
265 if ( s_mode
== 0xFF )
267 wxFAIL_MSG("glVertex3f called outside glBegin/glEnd");
271 s_texCoords
.push_back(s_currentTexCoord
[0]);
272 s_texCoords
.push_back(s_currentTexCoord
[1]);
274 s_normals
.push_back(s_currentNormal
[0]);
275 s_normals
.push_back(s_currentNormal
[1]);
276 s_normals
.push_back(s_currentNormal
[2]);
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]);
283 s_vertices
.push_back(x
);
284 s_vertices
.push_back(y
);
285 s_vertices
.push_back(z
);
292 void wxGLAPI::glNormal3f(GLfloat nx
, GLfloat ny
, GLfloat nz
)
294 #if wxUSE_OPENGL_EMULATION
295 if ( s_mode
== 0xFF )
296 ::glNormal3f(nx
,ny
,nz
);
299 s_normalsUsed
= true;
300 s_currentNormal
[0] = nx
;
301 s_currentNormal
[1] = ny
;
302 s_currentNormal
[2] = nz
;
305 ::glNormal3f(nx
,ny
,nz
);
309 void wxGLAPI::glColor4f(GLfloat r
, GLfloat g
, GLfloat b
, GLfloat a
)
311 #if wxUSE_OPENGL_EMULATION
312 if ( s_mode
== 0xFF )
313 ::glColor4f(r
,g
,b
,a
);
317 s_currentColor
[0] = r
;
318 s_currentColor
[1] = g
;
319 s_currentColor
[2] = b
;
320 s_currentColor
[3] = a
;
323 ::glColor4f(r
,g
,b
,a
);
327 void wxGLAPI::glColor3f(GLfloat r
, GLfloat g
, GLfloat b
)
329 #if wxUSE_OPENGL_EMULATION
330 glColor4f(r
,g
,b
,1.0);
336 void wxGLAPI::glEnd()
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
);
345 glEnableClientState(GL_VERTEX_ARRAY
);
348 glColorPointer( 4, GL_FLOAT
, 0, &s_colors
[0] );
351 glNormalPointer( GL_FLOAT
, 0, &s_normals
[0] );
353 if ( s_texCoordsUsed
)
354 glTexCoordPointer( 2, GL_FLOAT
, 0, &s_texCoords
[0] );
356 glVertexPointer(3, GL_FLOAT
, 0, &s_vertices
[0]);
357 glDrawArrays( s_mode
, 0, s_vertices
.size() / 3 );
359 if ( s_colorsUsed
!= formerColors
)
360 RestoreState( GL_COLOR_ARRAY
, formerColors
);
362 if ( s_normalsUsed
!= formerNormals
)
363 RestoreState( GL_NORMAL_ARRAY
, formerColors
);
365 if ( s_texCoordsUsed
!= formerTexCoords
)
366 RestoreState( GL_TEXTURE_COORD_ARRAY
, formerColors
);
369 glDisableClientState(GL_VERTEX_ARRAY
);
377 #endif // wxUSE_GLCANVAS