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