]> git.saurik.com Git - wxWidgets.git/blob - src/mac/glcanvas.cpp
Check wxSIZE_ALLOW_MINUS_ONE for x and y too.
[wxWidgets.git] / src / mac / glcanvas.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: glcanvas.cpp
3 // Purpose: wxGLCanvas, for using OpenGL with wxWindows 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->MacGetRootWindow()));
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 float r = 0.0;
101 float g = 0.0;
102 float b = 0.0;
103 wxColour *col = wxTheColourDatabase->FindColour(colour);
104 if (col)
105 {
106 r = (float)(col->Red()/256.0);
107 g = (float)(col->Green()/256.0);
108 b = (float)(col->Blue()/256.0);
109 glColor3f( r, g, b);
110 }
111 }
112
113
114 /*
115 * wxGLCanvas implementation
116 */
117
118 IMPLEMENT_CLASS(wxGLCanvas, wxWindow)
119
120 BEGIN_EVENT_TABLE(wxGLCanvas, wxWindow)
121 EVT_SIZE(wxGLCanvas::OnSize)
122 END_EVENT_TABLE()
123
124 wxGLCanvas::wxGLCanvas(wxWindow *parent, wxWindowID id,
125 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
126 int *attribList, const wxPalette& palette)
127 {
128 Create(parent, NULL, id, pos, size, style, name, attribList, palette);
129 }
130
131 wxGLCanvas::wxGLCanvas( wxWindow *parent,
132 const wxGLContext *shared, wxWindowID id,
133 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
134 int *attribList, const wxPalette& palette )
135 {
136 Create(parent, shared, id, pos, size, style, name, attribList, palette);
137 }
138
139 wxGLCanvas::wxGLCanvas( wxWindow *parent, const wxGLCanvas *shared, wxWindowID id,
140 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
141 int *attribList, const wxPalette& palette )
142 {
143 Create(parent, shared ? shared->GetContext() : NULL, id, pos, size, style, name, attribList, palette);
144 }
145
146 wxGLCanvas::~wxGLCanvas()
147 {
148 if (m_glContext != NULL) {
149 delete m_glContext;
150 m_glContext = NULL;
151 }
152 }
153
154 static AGLPixelFormat ChoosePixelFormat(const int *attribList)
155 {
156 GLint data[512];
157 GLint defaultAttribs[] = { AGL_RGBA,
158 AGL_DOUBLEBUFFER,
159 AGL_MINIMUM_POLICY,
160 AGL_DEPTH_SIZE, 1, // use largest available depth buffer
161 AGL_RED_SIZE, 1,
162 AGL_GREEN_SIZE, 1,
163 AGL_BLUE_SIZE, 1,
164 AGL_ALPHA_SIZE, 0,
165 AGL_NONE };
166 GLint *attribs;
167 if (!attribList)
168 {
169 attribs = defaultAttribs;
170 }
171 else
172 {
173 int arg=0, p=0;
174
175 data[p++] = AGL_MINIMUM_POLICY; // make _SIZE tags behave more like GLX
176 while( (attribList[arg]!=0) && (p<512) )
177 {
178 switch( attribList[arg++] )
179 {
180 case WX_GL_RGBA: data[p++] = AGL_RGBA; break;
181 case WX_GL_BUFFER_SIZE:
182 data[p++]=AGL_BUFFER_SIZE; data[p++]=attribList[arg++]; break;
183 case WX_GL_LEVEL:
184 data[p++]=AGL_LEVEL; data[p++]=attribList[arg++]; break;
185 case WX_GL_DOUBLEBUFFER: data[p++] = AGL_DOUBLEBUFFER; break;
186 case WX_GL_STEREO: data[p++] = AGL_STEREO; break;
187 case WX_GL_AUX_BUFFERS:
188 data[p++]=AGL_AUX_BUFFERS; data[p++]=attribList[arg++]; break;
189 case WX_GL_MIN_RED:
190 data[p++]=AGL_RED_SIZE; data[p++]=attribList[arg++]; break;
191 case WX_GL_MIN_GREEN:
192 data[p++]=AGL_GREEN_SIZE; data[p++]=attribList[arg++]; break;
193 case WX_GL_MIN_BLUE:
194 data[p++]=AGL_BLUE_SIZE; data[p++]=attribList[arg++]; break;
195 case WX_GL_MIN_ALPHA:
196 data[p++]=AGL_ALPHA_SIZE; data[p++]=attribList[arg++]; break;
197 case WX_GL_DEPTH_SIZE:
198 data[p++]=AGL_DEPTH_SIZE; data[p++]=attribList[arg++]; break;
199 case WX_GL_STENCIL_SIZE:
200 data[p++]=AGL_STENCIL_SIZE; data[p++]=attribList[arg++]; break;
201 case WX_GL_MIN_ACCUM_RED:
202 data[p++]=AGL_ACCUM_RED_SIZE; data[p++]=attribList[arg++]; break;
203 case WX_GL_MIN_ACCUM_GREEN:
204 data[p++]=AGL_ACCUM_GREEN_SIZE; data[p++]=attribList[arg++]; break;
205 case WX_GL_MIN_ACCUM_BLUE:
206 data[p++]=AGL_ACCUM_BLUE_SIZE; data[p++]=attribList[arg++]; break;
207 case WX_GL_MIN_ACCUM_ALPHA:
208 data[p++]=AGL_ACCUM_ALPHA_SIZE; data[p++]=attribList[arg++]; break;
209 default:
210 break;
211 }
212 }
213 data[p] = 0;
214
215 attribs = data;
216 }
217
218 return aglChoosePixelFormat(NULL, 0, attribs);
219 }
220
221 bool wxGLCanvas::Create(wxWindow *parent, const wxGLContext *shared, wxWindowID id,
222 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
223 int *attribList, const wxPalette& palette)
224 {
225 wxWindow::Create( parent, id, pos, size, style, name );
226
227 AGLPixelFormat fmt = ChoosePixelFormat(attribList);
228 wxCHECK_MSG( fmt, false, wxT("Couldn't create OpenGl pixel format") );
229
230 m_glContext = new wxGLContext(fmt, this, palette, shared);
231 m_macCanvasIsShown = true ;
232 aglDestroyPixelFormat(fmt);
233
234 return true;
235 }
236
237 void wxGLCanvas::SwapBuffers()
238 {
239 if (m_glContext)
240 m_glContext->SwapBuffers();
241 }
242
243 void wxGLCanvas::UpdateContext()
244 {
245 if (m_glContext)
246 m_glContext->Update();
247 }
248
249 void wxGLCanvas::SetViewport()
250 {
251 // viewport is initially set to entire port
252 // adjust glViewport to just this window
253 int x = 0 ;
254 int y = 0 ;
255
256 wxWindow* iter = this ;
257 while( iter->GetParent() )
258 {
259 iter = iter->GetParent() ;
260 }
261
262 if ( iter && iter->IsTopLevel() )
263 {
264 MacClientToRootWindow( &x , &y ) ;
265 int width, height;
266 GetClientSize(& width, & height);
267 Rect bounds ;
268 GetWindowPortBounds( MAC_WXHWND(MacGetRootWindow()) , &bounds ) ;
269 GLint parms[4] ;
270 parms[0] = x ;
271 parms[1] = bounds.bottom - bounds.top - ( y + height ) ;
272 parms[2] = width ;
273 parms[3] = height ;
274
275 if ( !m_macCanvasIsShown )
276 parms[0] += 20000 ;
277 aglSetInteger( m_glContext->m_glContext , AGL_BUFFER_RECT , parms ) ;
278 }
279 }
280
281 void wxGLCanvas::OnSize(wxSizeEvent& event)
282 {
283 MacUpdateView() ;
284 }
285
286 void wxGLCanvas::MacUpdateView()
287 {
288 if (m_glContext)
289 {
290 UpdateContext();
291 m_glContext->SetCurrent();
292 SetViewport();
293 }
294 }
295
296 void wxGLCanvas::MacSuperChangedPosition()
297 {
298 MacUpdateView() ;
299 wxWindow::MacSuperChangedPosition() ;
300 }
301
302 void wxGLCanvas::MacTopLevelWindowChangedPosition()
303 {
304 MacUpdateView() ;
305 wxWindow::MacTopLevelWindowChangedPosition() ;
306 }
307
308 void wxGLCanvas::SetCurrent()
309 {
310 if (m_glContext)
311 {
312 m_glContext->SetCurrent();
313 }
314 }
315
316 void wxGLCanvas::SetColour(const wxChar *colour)
317 {
318 if (m_glContext)
319 m_glContext->SetColour(colour);
320 }
321
322 bool wxGLCanvas::Show(bool show)
323 {
324 if ( !wxWindow::Show( show ) )
325 return FALSE ;
326
327 if ( !show )
328 {
329 if ( m_macCanvasIsShown )
330 {
331 m_macCanvasIsShown = false ;
332 SetViewport() ;
333 }
334 }
335 else
336 {
337 if ( MacIsReallyShown() && !m_macCanvasIsShown )
338 {
339 m_macCanvasIsShown = true ;
340 SetViewport() ;
341 }
342 }
343 return TRUE ;
344 }
345
346 void wxGLCanvas::MacSuperShown( bool show )
347 {
348 if ( !show )
349 {
350 if ( m_macCanvasIsShown )
351 {
352 m_macCanvasIsShown = false ;
353 SetViewport() ;
354 }
355 }
356 else
357 {
358 if ( MacIsReallyShown() && !m_macCanvasIsShown )
359 {
360 m_macCanvasIsShown = true ;
361 SetViewport() ;
362 }
363 }
364
365 wxWindow::MacSuperShown( show ) ;
366 }
367
368 //---------------------------------------------------------------------------
369 // wxGLApp
370 //---------------------------------------------------------------------------
371
372 IMPLEMENT_CLASS(wxGLApp, wxApp)
373
374 bool wxGLApp::InitGLVisual(int *attribList)
375 {
376 AGLPixelFormat fmt = ChoosePixelFormat(attribList);
377 if (fmt != NULL) {
378 aglDestroyPixelFormat(fmt);
379 return true;
380 } else
381 return false;
382 }
383
384 wxGLApp::~wxGLApp(void)
385 {
386 }
387
388 #endif // wxUSE_GLCANVAS