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 #ifndef wxHAS_OPENGL_ES
67 bool wxGLCanvasBase::SetColour(const wxString
& colour
)
69 wxColour col
= wxTheColourDatabase
->Find(colour
);
74 glGetBooleanv(GL_RGBA_MODE
, &isRGBA
);
77 glColor3f(col
.Red() / 256., col
.Green() / 256., col
.Blue() / 256.);
79 else // indexed colour
81 GLint pix
= GetColourIndex(col
);
84 wxLogError(_("Failed to allocate colour for OpenGL"));
95 wxGLCanvasBase::~wxGLCanvasBase()
97 #if WXWIN_COMPATIBILITY_2_8
99 #endif // WXWIN_COMPATIBILITY_2_8
102 #if WXWIN_COMPATIBILITY_2_8
104 wxGLContext
*wxGLCanvasBase::GetContext() const
109 void wxGLCanvasBase::SetCurrent()
112 SetCurrent(*m_glContext
);
115 void wxGLCanvasBase::OnSize(wxSizeEvent
& WXUNUSED(event
))
119 #endif // WXWIN_COMPATIBILITY_2_8
122 bool wxGLCanvasBase::IsExtensionInList(const char *list
, const char *extension
)
127 for ( const char *p
= list
; *p
; p
++ )
129 // advance up to the next possible match
130 p
= wxStrstr(p
, extension
);
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] == ' ') )
139 char c
= p
[strlen(extension
)];
140 if ( c
== '\0' || c
== ' ' )
148 // ============================================================================
149 // compatibility layer for OpenGL 3 and OpenGL ES
150 // ============================================================================
152 static wxGLAPI s_glAPI
;
154 #if wxUSE_OPENGL_EMULATION
156 #include "wx/vector.h"
158 static GLenum s_mode
;
160 static GLfloat s_currentTexCoord
[2];
161 static GLfloat s_currentColor
[4];
162 static GLfloat s_currentNormal
[3];
164 // TODO move this into a different construct with locality for all attributes
167 static wxVector
<GLfloat
> s_texCoords
;
168 static wxVector
<GLfloat
> s_vertices
;
169 static wxVector
<GLfloat
> s_normals
;
170 static wxVector
<GLfloat
> s_colors
;
172 static bool s_texCoordsUsed
;
173 static bool s_colorsUsed
;
174 static bool s_normalsUsed
;
176 bool SetState( int flag
, bool desired
)
178 bool former
= glIsEnabled( flag
);
179 if ( former
!= desired
)
182 glEnableClientState(flag
);
184 glDisableClientState(flag
);
189 void RestoreState( int flag
, bool desired
)
192 glEnableClientState(flag
);
194 glDisableClientState(flag
);
200 #if wxUSE_OPENGL_EMULATION
209 void wxGLAPI::glBegin(GLenum mode
)
211 #if wxUSE_OPENGL_EMULATION
212 if ( s_mode
!= 0xFF )
214 wxFAIL_MSG("nested glBegin");
218 s_texCoordsUsed
= false;
219 s_colorsUsed
= false;
220 s_normalsUsed
= false;
231 void wxGLAPI::glTexCoord2f(GLfloat s
, GLfloat t
)
233 #if wxUSE_OPENGL_EMULATION
234 if ( s_mode
== 0xFF )
236 wxFAIL_MSG("glTexCoord2f called outside glBegin/glEnd");
241 s_texCoordsUsed
= true;
242 s_currentTexCoord
[0] = s
;
243 s_currentTexCoord
[1] = t
;
250 void wxGLAPI::glVertex3f(GLfloat x
, GLfloat y
, GLfloat z
)
252 #if wxUSE_OPENGL_EMULATION
253 if ( s_mode
== 0xFF )
255 wxFAIL_MSG("glVertex3f called outside glBegin/glEnd");
259 s_texCoords
.push_back(s_currentTexCoord
[0]);
260 s_texCoords
.push_back(s_currentTexCoord
[1]);
262 s_normals
.push_back(s_currentNormal
[0]);
263 s_normals
.push_back(s_currentNormal
[1]);
264 s_normals
.push_back(s_currentNormal
[2]);
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]);
271 s_vertices
.push_back(x
);
272 s_vertices
.push_back(y
);
273 s_vertices
.push_back(z
);
280 void wxGLAPI::glNormal3f(GLfloat nx
, GLfloat ny
, GLfloat nz
)
282 #if wxUSE_OPENGL_EMULATION
283 if ( s_mode
== 0xFF )
284 ::glNormal3f(nx
,ny
,nz
);
287 s_normalsUsed
= true;
288 s_currentNormal
[0] = nx
;
289 s_currentNormal
[1] = ny
;
290 s_currentNormal
[2] = nz
;
293 ::glNormal3f(nx
,ny
,nz
);
297 void wxGLAPI::glColor4f(GLfloat r
, GLfloat g
, GLfloat b
, GLfloat a
)
299 #if wxUSE_OPENGL_EMULATION
300 if ( s_mode
== 0xFF )
301 ::glColor4f(r
,g
,b
,a
);
305 s_currentColor
[0] = r
;
306 s_currentColor
[1] = g
;
307 s_currentColor
[2] = b
;
308 s_currentColor
[3] = a
;
311 ::glColor4f(r
,g
,b
,a
);
315 void wxGLAPI::glColor3f(GLfloat r
, GLfloat g
, GLfloat b
)
317 #if wxUSE_OPENGL_EMULATION
318 glColor4f(r
,g
,b
,1.0);
324 void wxGLAPI::glEnd()
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
);
333 glEnableClientState(GL_VERTEX_ARRAY
);
336 glColorPointer( 4, GL_FLOAT
, 0, &s_colors
[0] );
339 glNormalPointer( GL_FLOAT
, 0, &s_normals
[0] );
341 if ( s_texCoordsUsed
)
342 glTexCoordPointer( 2, GL_FLOAT
, 0, &s_texCoords
[0] );
344 glVertexPointer(3, GL_FLOAT
, 0, &s_vertices
[0]);
345 glDrawArrays( s_mode
, 0, s_vertices
.size() / 3 );
347 if ( s_colorsUsed
!= formerColors
)
348 RestoreState( GL_COLOR_ARRAY
, formerColors
);
350 if ( s_normalsUsed
!= formerNormals
)
351 RestoreState( GL_NORMAL_ARRAY
, formerColors
);
353 if ( s_texCoordsUsed
!= formerTexCoords
)
354 RestoreState( GL_TEXTURE_COORD_ARRAY
, formerColors
);
357 glDisableClientState(GL_VERTEX_ARRAY
);
365 #endif // wxUSE_GLCANVAS