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