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