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((GLfloat
) (col
.Red() / 256.), (GLfloat
) (col
.Green() / 256.),
74 (GLfloat
) (col
.Blue() / 256.));
77 glGetBooleanv(GL_RGBA_MODE
, &isRGBA
);
80 glColor3f((GLfloat
) (col
.Red() / 256.), (GLfloat
) (col
.Green() / 256.),
81 (GLfloat
) (col
.Blue() / 256.));
83 else // indexed colour
85 GLint pix
= GetColourIndex(col
);
88 wxLogError(_("Failed to allocate colour for OpenGL"));
98 wxGLCanvasBase::~wxGLCanvasBase()
100 #if WXWIN_COMPATIBILITY_2_8
102 #endif // WXWIN_COMPATIBILITY_2_8
105 #if WXWIN_COMPATIBILITY_2_8
107 wxGLContext
*wxGLCanvasBase::GetContext() const
112 void wxGLCanvasBase::SetCurrent()
115 SetCurrent(*m_glContext
);
118 void wxGLCanvasBase::OnSize(wxSizeEvent
& WXUNUSED(event
))
122 #endif // WXWIN_COMPATIBILITY_2_8
125 bool wxGLCanvasBase::IsExtensionInList(const char *list
, const char *extension
)
130 for ( const char *p
= list
; *p
; p
++ )
132 // advance up to the next possible match
133 p
= wxStrstr(p
, extension
);
137 // check that the extension appears at the beginning/ending of the list
138 // or is preceded/followed by a space to avoid mistakenly finding
139 // "glExtension" in a list containing some "glFunkyglExtension"
140 if ( (p
== list
|| p
[-1] == ' ') )
142 char c
= p
[strlen(extension
)];
143 if ( c
== '\0' || c
== ' ' )
151 // ============================================================================
152 // compatibility layer for OpenGL 3 and OpenGL ES
153 // ============================================================================
155 static wxGLAPI s_glAPI
;
157 #if wxUSE_OPENGL_EMULATION
159 #include "wx/vector.h"
161 static GLenum s_mode
;
163 static GLfloat s_currentTexCoord
[2];
164 static GLfloat s_currentColor
[4];
165 static GLfloat s_currentNormal
[3];
167 // TODO move this into a different construct with locality for all attributes
170 static wxVector
<GLfloat
> s_texCoords
;
171 static wxVector
<GLfloat
> s_vertices
;
172 static wxVector
<GLfloat
> s_normals
;
173 static wxVector
<GLfloat
> s_colors
;
175 static bool s_texCoordsUsed
;
176 static bool s_colorsUsed
;
177 static bool s_normalsUsed
;
179 bool SetState( int flag
, bool desired
)
181 bool former
= glIsEnabled( flag
);
182 if ( former
!= desired
)
185 glEnableClientState(flag
);
187 glDisableClientState(flag
);
192 void RestoreState( int flag
, bool desired
)
195 glEnableClientState(flag
);
197 glDisableClientState(flag
);
203 #if wxUSE_OPENGL_EMULATION
212 void wxGLAPI::glFrustum(GLfloat left
, GLfloat right
, GLfloat bottom
,
213 GLfloat top
, GLfloat zNear
, GLfloat zFar
)
215 #if wxUSE_OPENGL_EMULATION
216 ::glFrustumf(left
, right
, bottom
, top
, zNear
, zFar
);
218 ::glFrustum(left
, right
, bottom
, top
, zNear
, zFar
);
222 void wxGLAPI::glBegin(GLenum mode
)
224 #if wxUSE_OPENGL_EMULATION
225 if ( s_mode
!= 0xFF )
227 wxFAIL_MSG("nested glBegin");
231 s_texCoordsUsed
= false;
232 s_colorsUsed
= false;
233 s_normalsUsed
= false;
244 void wxGLAPI::glTexCoord2f(GLfloat s
, GLfloat t
)
246 #if wxUSE_OPENGL_EMULATION
247 if ( s_mode
== 0xFF )
249 wxFAIL_MSG("glTexCoord2f called outside glBegin/glEnd");
254 s_texCoordsUsed
= true;
255 s_currentTexCoord
[0] = s
;
256 s_currentTexCoord
[1] = t
;
263 void wxGLAPI::glVertex3f(GLfloat x
, GLfloat y
, GLfloat z
)
265 #if wxUSE_OPENGL_EMULATION
266 if ( s_mode
== 0xFF )
268 wxFAIL_MSG("glVertex3f called outside glBegin/glEnd");
272 s_texCoords
.push_back(s_currentTexCoord
[0]);
273 s_texCoords
.push_back(s_currentTexCoord
[1]);
275 s_normals
.push_back(s_currentNormal
[0]);
276 s_normals
.push_back(s_currentNormal
[1]);
277 s_normals
.push_back(s_currentNormal
[2]);
279 s_colors
.push_back(s_currentColor
[0]);
280 s_colors
.push_back(s_currentColor
[1]);
281 s_colors
.push_back(s_currentColor
[2]);
282 s_colors
.push_back(s_currentColor
[3]);
284 s_vertices
.push_back(x
);
285 s_vertices
.push_back(y
);
286 s_vertices
.push_back(z
);
293 void wxGLAPI::glNormal3f(GLfloat nx
, GLfloat ny
, GLfloat nz
)
295 #if wxUSE_OPENGL_EMULATION
296 if ( s_mode
== 0xFF )
297 ::glNormal3f(nx
,ny
,nz
);
300 s_normalsUsed
= true;
301 s_currentNormal
[0] = nx
;
302 s_currentNormal
[1] = ny
;
303 s_currentNormal
[2] = nz
;
306 ::glNormal3f(nx
,ny
,nz
);
310 void wxGLAPI::glColor4f(GLfloat r
, GLfloat g
, GLfloat b
, GLfloat a
)
312 #if wxUSE_OPENGL_EMULATION
313 if ( s_mode
== 0xFF )
314 ::glColor4f(r
,g
,b
,a
);
318 s_currentColor
[0] = r
;
319 s_currentColor
[1] = g
;
320 s_currentColor
[2] = b
;
321 s_currentColor
[3] = a
;
324 ::glColor4f(r
,g
,b
,a
);
328 void wxGLAPI::glColor3f(GLfloat r
, GLfloat g
, GLfloat b
)
330 #if wxUSE_OPENGL_EMULATION
331 glColor4f(r
,g
,b
,1.0);
337 void wxGLAPI::glEnd()
339 #if wxUSE_OPENGL_EMULATION
340 bool formerColors
= SetState( GL_COLOR_ARRAY
, s_colorsUsed
);
341 bool formerNormals
= SetState( GL_NORMAL_ARRAY
, s_normalsUsed
);
342 bool formerTexCoords
= SetState( GL_TEXTURE_COORD_ARRAY
, s_texCoordsUsed
);
343 bool formerVertex
= glIsEnabled(GL_VERTEX_ARRAY
);
346 glEnableClientState(GL_VERTEX_ARRAY
);
349 glColorPointer( 4, GL_FLOAT
, 0, &s_colors
[0] );
352 glNormalPointer( GL_FLOAT
, 0, &s_normals
[0] );
354 if ( s_texCoordsUsed
)
355 glTexCoordPointer( 2, GL_FLOAT
, 0, &s_texCoords
[0] );
357 glVertexPointer(3, GL_FLOAT
, 0, &s_vertices
[0]);
358 glDrawArrays( s_mode
, 0, s_vertices
.size() / 3 );
360 if ( s_colorsUsed
!= formerColors
)
361 RestoreState( GL_COLOR_ARRAY
, formerColors
);
363 if ( s_normalsUsed
!= formerNormals
)
364 RestoreState( GL_NORMAL_ARRAY
, formerColors
);
366 if ( s_texCoordsUsed
!= formerTexCoords
)
367 RestoreState( GL_TEXTURE_COORD_ARRAY
, formerColors
);
370 glDisableClientState(GL_VERTEX_ARRAY
);
378 #endif // wxUSE_GLCANVAS