]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/glcanvas.cpp
make sure we are getting the gui mutex before shutting down
[wxWidgets.git] / src / mac / carbon / glcanvas.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: glcanvas.cpp
3 // Purpose: wxGLCanvas, for using OpenGL with wxWidgets under Macintosh
4 // Author: Stefan Csomor
5 // Modified by:
6 // Created: 1998-01-01
7 // RCS-ID: $Id$
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "glcanvas.h"
14 #endif
15
16 #include "wx/wxprec.h"
17
18 #if defined(__BORLANDC__)
19 #pragma hdrstop
20 #endif
21
22 #include "wx/setup.h"
23
24 #if wxUSE_GLCANVAS
25
26 #ifndef WX_PRECOMP
27 #include "wx/frame.h"
28 #endif
29
30 #include "wx/settings.h"
31 #include "wx/log.h"
32
33 #include "wx/glcanvas.h"
34 #include "wx/mac/uma.h"
35
36 // DLL options compatibility check:
37 #include "wx/build.h"
38 WX_CHECK_BUILD_OPTIONS("wxGL")
39
40 /*
41 * GLContext implementation
42 */
43
44 wxGLContext::wxGLContext(
45 AGLPixelFormat fmt, wxGLCanvas *win,
46 const wxPalette& palette,
47 const wxGLContext *other /* for sharing display lists */
48 )
49 {
50 m_window = win;
51
52 m_drawable = (AGLDrawable) UMAGetWindowPort(MAC_WXHWND(win->MacGetTopLevelWindowRef()));
53
54 m_glContext = aglCreateContext(fmt, other ? other->m_glContext : NULL);
55 wxCHECK_RET( m_glContext, wxT("Couldn't create OpenGl context") );
56
57 GLboolean b;
58 b = aglSetDrawable(m_glContext, m_drawable);
59 wxCHECK_RET( b, wxT("Couldn't bind OpenGl context") );
60 aglEnable(m_glContext , AGL_BUFFER_RECT ) ;
61 b = aglSetCurrentContext(m_glContext);
62 wxCHECK_RET( b, wxT("Couldn't activate OpenGl context") );
63 }
64
65 wxGLContext::~wxGLContext()
66 {
67 if (m_glContext)
68 {
69 aglSetCurrentContext(NULL);
70 aglDestroyContext(m_glContext);
71 }
72 }
73
74 void wxGLContext::SwapBuffers()
75 {
76 if (m_glContext)
77 {
78 aglSwapBuffers(m_glContext);
79 }
80 }
81
82 void wxGLContext::SetCurrent()
83 {
84 if (m_glContext)
85 {
86 aglSetCurrentContext(m_glContext);
87 }
88 }
89
90 void wxGLContext::Update()
91 {
92 if (m_glContext)
93 {
94 aglUpdateContext(m_glContext);
95 }
96 }
97
98 void wxGLContext::SetColour(const wxChar *colour)
99 {
100 wxColour col = wxTheColourDatabase->Find(colour);
101 if (col.Ok())
102 {
103 float r = (float)(col.Red()/256.0);
104 float g = (float)(col.Green()/256.0);
105 float b = (float)(col.Blue()/256.0);
106 glColor3f( r, g, b);
107 }
108 }
109
110
111 /*
112 * wxGLCanvas implementation
113 */
114
115 IMPLEMENT_CLASS(wxGLCanvas, wxWindow)
116
117 BEGIN_EVENT_TABLE(wxGLCanvas, wxWindow)
118 EVT_SIZE(wxGLCanvas::OnSize)
119 END_EVENT_TABLE()
120
121 wxGLCanvas::wxGLCanvas(wxWindow *parent, wxWindowID id,
122 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
123 int *attribList, const wxPalette& palette)
124 {
125 Create(parent, NULL, id, pos, size, style, name, attribList, palette);
126 }
127
128 wxGLCanvas::wxGLCanvas( wxWindow *parent,
129 const wxGLContext *shared, wxWindowID id,
130 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
131 int *attribList, const wxPalette& palette )
132 {
133 Create(parent, shared, id, pos, size, style, name, attribList, palette);
134 }
135
136 wxGLCanvas::wxGLCanvas( wxWindow *parent, const wxGLCanvas *shared, wxWindowID id,
137 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
138 int *attribList, const wxPalette& palette )
139 {
140 Create(parent, shared ? shared->GetContext() : NULL, id, pos, size, style, name, attribList, palette);
141 }
142
143 wxGLCanvas::~wxGLCanvas()
144 {
145 if (m_glContext != NULL) {
146 delete m_glContext;
147 m_glContext = NULL;
148 }
149 }
150
151 static AGLPixelFormat ChoosePixelFormat(const int *attribList)
152 {
153 GLint data[512];
154 GLint defaultAttribs[] = { AGL_RGBA,
155 AGL_DOUBLEBUFFER,
156 AGL_MINIMUM_POLICY,
157 AGL_DEPTH_SIZE, 1, // use largest available depth buffer
158 AGL_RED_SIZE, 1,
159 AGL_GREEN_SIZE, 1,
160 AGL_BLUE_SIZE, 1,
161 AGL_ALPHA_SIZE, 0,
162 AGL_NONE };
163 GLint *attribs;
164 if (!attribList)
165 {
166 attribs = defaultAttribs;
167 }
168 else
169 {
170 int arg=0, p=0;
171
172 data[p++] = AGL_MINIMUM_POLICY; // make _SIZE tags behave more like GLX
173 while( (attribList[arg]!=0) && (p<512) )
174 {
175 switch( attribList[arg++] )
176 {
177 case WX_GL_RGBA: data[p++] = AGL_RGBA; break;
178 case WX_GL_BUFFER_SIZE:
179 data[p++]=AGL_BUFFER_SIZE; data[p++]=attribList[arg++]; break;
180 case WX_GL_LEVEL:
181 data[p++]=AGL_LEVEL; data[p++]=attribList[arg++]; break;
182 case WX_GL_DOUBLEBUFFER: data[p++] = AGL_DOUBLEBUFFER; break;
183 case WX_GL_STEREO: data[p++] = AGL_STEREO; break;
184 case WX_GL_AUX_BUFFERS:
185 data[p++]=AGL_AUX_BUFFERS; data[p++]=attribList[arg++]; break;
186 case WX_GL_MIN_RED:
187 data[p++]=AGL_RED_SIZE; data[p++]=attribList[arg++]; break;
188 case WX_GL_MIN_GREEN:
189 data[p++]=AGL_GREEN_SIZE; data[p++]=attribList[arg++]; break;
190 case WX_GL_MIN_BLUE:
191 data[p++]=AGL_BLUE_SIZE; data[p++]=attribList[arg++]; break;
192 case WX_GL_MIN_ALPHA:
193 data[p++]=AGL_ALPHA_SIZE; data[p++]=attribList[arg++]; break;
194 case WX_GL_DEPTH_SIZE:
195 data[p++]=AGL_DEPTH_SIZE; data[p++]=attribList[arg++]; break;
196 case WX_GL_STENCIL_SIZE:
197 data[p++]=AGL_STENCIL_SIZE; data[p++]=attribList[arg++]; break;
198 case WX_GL_MIN_ACCUM_RED:
199 data[p++]=AGL_ACCUM_RED_SIZE; data[p++]=attribList[arg++]; break;
200 case WX_GL_MIN_ACCUM_GREEN:
201 data[p++]=AGL_ACCUM_GREEN_SIZE; data[p++]=attribList[arg++]; break;
202 case WX_GL_MIN_ACCUM_BLUE:
203 data[p++]=AGL_ACCUM_BLUE_SIZE; data[p++]=attribList[arg++]; break;
204 case WX_GL_MIN_ACCUM_ALPHA:
205 data[p++]=AGL_ACCUM_ALPHA_SIZE; data[p++]=attribList[arg++]; break;
206 default:
207 break;
208 }
209 }
210 data[p] = 0;
211
212 attribs = data;
213 }
214
215 return aglChoosePixelFormat(NULL, 0, attribs);
216 }
217
218 bool wxGLCanvas::Create(wxWindow *parent, const wxGLContext *shared, wxWindowID id,
219 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
220 int *attribList, const wxPalette& palette)
221 {
222 wxWindow::Create( parent, id, pos, size, style, name );
223
224 AGLPixelFormat fmt = ChoosePixelFormat(attribList);
225 wxCHECK_MSG( fmt, false, wxT("Couldn't create OpenGl pixel format") );
226
227 m_glContext = new wxGLContext(fmt, this, palette, shared);
228 m_macCanvasIsShown = true ;
229 aglDestroyPixelFormat(fmt);
230
231 return true;
232 }
233
234 void wxGLCanvas::SwapBuffers()
235 {
236 if (m_glContext)
237 m_glContext->SwapBuffers();
238 }
239
240 void wxGLCanvas::UpdateContext()
241 {
242 if (m_glContext)
243 m_glContext->Update();
244 }
245
246 void wxGLCanvas::SetViewport()
247 {
248 // viewport is initially set to entire port
249 // adjust glViewport to just this window
250 int x = 0 ;
251 int y = 0 ;
252
253 wxWindow* iter = this ;
254 while( iter->GetParent() )
255 {
256 iter = iter->GetParent() ;
257 }
258
259 if ( iter && iter->IsTopLevel() )
260 {
261 MacClientToRootWindow( &x , &y ) ;
262 int width, height;
263 GetClientSize(& width, & height);
264 Rect bounds ;
265 GetWindowPortBounds( MAC_WXHWND(MacGetTopLevelWindowRef()) , &bounds ) ;
266 GLint parms[4] ;
267 parms[0] = x ;
268 parms[1] = bounds.bottom - bounds.top - ( y + height ) ;
269 parms[2] = width ;
270 parms[3] = height ;
271
272 if ( !m_macCanvasIsShown )
273 parms[0] += 20000 ;
274 aglSetInteger( m_glContext->m_glContext , AGL_BUFFER_RECT , parms ) ;
275 }
276 }
277
278 void wxGLCanvas::OnSize(wxSizeEvent& event)
279 {
280 MacUpdateView() ;
281 }
282
283 void wxGLCanvas::MacUpdateView()
284 {
285 if (m_glContext)
286 {
287 UpdateContext();
288 m_glContext->SetCurrent();
289 SetViewport();
290 }
291 }
292
293 void wxGLCanvas::MacSuperChangedPosition()
294 {
295 MacUpdateView() ;
296 wxWindow::MacSuperChangedPosition() ;
297 }
298
299 void wxGLCanvas::MacTopLevelWindowChangedPosition()
300 {
301 MacUpdateView() ;
302 wxWindow::MacTopLevelWindowChangedPosition() ;
303 }
304
305 void wxGLCanvas::SetCurrent()
306 {
307 if (m_glContext)
308 {
309 m_glContext->SetCurrent();
310 }
311 }
312
313 void wxGLCanvas::SetColour(const wxChar *colour)
314 {
315 if (m_glContext)
316 m_glContext->SetColour(colour);
317 }
318
319 bool wxGLCanvas::Show(bool show)
320 {
321 if ( !wxWindow::Show( show ) )
322 return FALSE ;
323 /*
324 if ( !show )
325 {
326 if ( m_macCanvasIsShown )
327 {
328 m_macCanvasIsShown = false ;
329 SetViewport() ;
330 }
331 }
332 else
333 {
334 if ( IsControlVisible( (ControlRef) m_macControl ) && !m_macCanvasIsShown )
335 {
336 m_macCanvasIsShown = true ;
337 SetViewport() ;
338 }
339 }
340 */
341 return TRUE ;
342 }
343
344 void wxGLCanvas::MacVisibilityChanged()
345 {
346 if ( !IsControlVisible( (ControlRef) m_macControl ) )
347 {
348 if ( m_macCanvasIsShown )
349 {
350 m_macCanvasIsShown = false ;
351 SetViewport() ;
352 }
353 }
354 else
355 {
356 if ( !m_macCanvasIsShown )
357 {
358 m_macCanvasIsShown = true ;
359 SetViewport() ;
360 }
361 }
362 wxWindowMac::MacVisibilityChanged() ;
363 }
364
365 //---------------------------------------------------------------------------
366 // wxGLApp
367 //---------------------------------------------------------------------------
368
369 IMPLEMENT_CLASS(wxGLApp, wxApp)
370
371 bool wxGLApp::InitGLVisual(int *attribList)
372 {
373 AGLPixelFormat fmt = ChoosePixelFormat(attribList);
374 if (fmt != NULL) {
375 aglDestroyPixelFormat(fmt);
376 return true;
377 } else
378 return false;
379 }
380
381 wxGLApp::~wxGLApp(void)
382 {
383 }
384
385 #endif // wxUSE_GLCANVAS