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