1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/glcmn.cpp
3 // Purpose: wxGLCanvasBase implementation
4 // Author: Vadim Zeitlin
6 // Copyright: (c) 2007 Vadim Zeitlin <vadim@wxwindows.org>
7 // Licence: wxWindows licence
8 ///////////////////////////////////////////////////////////////////////////////
10 // ============================================================================
12 // ============================================================================
14 // ----------------------------------------------------------------------------
16 // ----------------------------------------------------------------------------
18 // for compilers that support precompilation, includes "wx.h".
19 #include "wx/wxprec.h"
31 #include "wx/glcanvas.h"
33 // DLL options compatibility check:
35 WX_CHECK_BUILD_OPTIONS("wxGL")
37 IMPLEMENT_CLASS(wxGLApp
, wxApp
)
39 // ============================================================================
41 // ============================================================================
43 wxGLCanvasBase::wxGLCanvasBase()
45 #if WXWIN_COMPATIBILITY_2_8
49 // we always paint background entirely ourselves so prevent wx from erasing
50 // it to avoid flicker
51 SetBackgroundStyle(wxBG_STYLE_CUSTOM
);
54 bool wxGLCanvasBase::SetCurrent(const wxGLContext
& context
) const
56 // although on MSW it works even if the window is still hidden, it doesn't
57 // work in other ports (notably X11-based ones) and documentation mentions
58 // that SetCurrent() can only be called for a shown window, so check for it
59 wxASSERT_MSG( IsShownOnScreen(), wxT("can't make hidden GL canvas current") );
62 return context
.SetCurrent(*static_cast<const wxGLCanvas
*>(this));
65 bool wxGLCanvasBase::SetColour(const wxString
& colour
)
67 wxColour col
= wxTheColourDatabase
->Find(colour
);
71 #ifdef wxHAS_OPENGL_ES
72 wxGLAPI::glColor3f((GLfloat
) (col
.Red() / 256.), (GLfloat
) (col
.Green() / 256.),
73 (GLfloat
) (col
.Blue() / 256.));
76 glGetBooleanv(GL_RGBA_MODE
, &isRGBA
);
79 glColor3f((GLfloat
) (col
.Red() / 256.), (GLfloat
) (col
.Green() / 256.),
80 (GLfloat
) (col
.Blue() / 256.));
82 else // indexed colour
84 GLint pix
= GetColourIndex(col
);
87 wxLogError(_("Failed to allocate colour for OpenGL"));
97 wxGLCanvasBase::~wxGLCanvasBase()
99 #if WXWIN_COMPATIBILITY_2_8
101 #endif // WXWIN_COMPATIBILITY_2_8
104 #if WXWIN_COMPATIBILITY_2_8
106 wxGLContext
*wxGLCanvasBase::GetContext() const
111 void wxGLCanvasBase::SetCurrent()
114 SetCurrent(*m_glContext
);
117 void wxGLCanvasBase::OnSize(wxSizeEvent
& WXUNUSED(event
))
121 #endif // WXWIN_COMPATIBILITY_2_8
124 bool wxGLCanvasBase::IsExtensionInList(const char *list
, const char *extension
)
129 for ( const char *p
= list
; *p
; p
++ )
131 // advance up to the next possible match
132 p
= wxStrstr(p
, extension
);
136 // check that the extension appears at the beginning/ending of the list
137 // or is preceded/followed by a space to avoid mistakenly finding
138 // "glExtension" in a list containing some "glFunkyglExtension"
139 if ( (p
== list
|| p
[-1] == ' ') )
141 char c
= p
[strlen(extension
)];
142 if ( c
== '\0' || c
== ' ' )
150 // ============================================================================
151 // compatibility layer for OpenGL 3 and OpenGL ES
152 // ============================================================================
154 static wxGLAPI s_glAPI
;
156 #if wxUSE_OPENGL_EMULATION
158 #include "wx/vector.h"
160 static GLenum s_mode
;
162 static GLfloat s_currentTexCoord
[2];
163 static GLfloat s_currentColor
[4];
164 static GLfloat s_currentNormal
[3];
166 // TODO move this into a different construct with locality for all attributes
169 static wxVector
<GLfloat
> s_texCoords
;
170 static wxVector
<GLfloat
> s_vertices
;
171 static wxVector
<GLfloat
> s_normals
;
172 static wxVector
<GLfloat
> s_colors
;
174 static bool s_texCoordsUsed
;
175 static bool s_colorsUsed
;
176 static bool s_normalsUsed
;
178 bool SetState( int flag
, bool desired
)
180 bool former
= glIsEnabled( flag
);
181 if ( former
!= desired
)
184 glEnableClientState(flag
);
186 glDisableClientState(flag
);
191 void RestoreState( int flag
, bool desired
)
194 glEnableClientState(flag
);
196 glDisableClientState(flag
);
202 #if wxUSE_OPENGL_EMULATION
211 void wxGLAPI::glFrustum(GLfloat left
, GLfloat right
, GLfloat bottom
,
212 GLfloat top
, GLfloat zNear
, GLfloat zFar
)
214 #if wxUSE_OPENGL_EMULATION
215 ::glFrustumf(left
, right
, bottom
, top
, zNear
, zFar
);
217 ::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