]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/glcanvas.cpp
Fixing compilation on Mac, and attempting to better calculate the bottom position...
[wxWidgets.git] / src / mac / carbon / glcanvas.cpp
CommitLineData
0a67a93b 1/////////////////////////////////////////////////////////////////////////////
e4db172a 2// Name: src/mac/carbon/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
e4db172a 9// Licence: wxWindows licence
0a67a93b
SC
10/////////////////////////////////////////////////////////////////////////////
11
0a67a93b
SC
12#include "wx/wxprec.h"
13
14#if defined(__BORLANDC__)
e4db172a 15 #pragma hdrstop
0a67a93b
SC
16#endif
17
0a67a93b
SC
18#if wxUSE_GLCANVAS
19
e4db172a
WS
20#include "wx/glcanvas.h"
21
0a67a93b 22#ifndef WX_PRECOMP
e4db172a
WS
23 #include "wx/frame.h"
24 #include "wx/log.h"
9eddec69 25 #include "wx/settings.h"
0a67a93b
SC
26#endif
27
0a67a93b
SC
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
3a5ff9b1
SC
34#include "wx/mac/private.h"
35
0a67a93b 36/*
e40298d5
JS
37* GLContext implementation
38*/
0a67a93b
SC
39
40wxGLContext::wxGLContext(
e40298d5
JS
41 AGLPixelFormat fmt, wxGLCanvas *win,
42 const wxPalette& palette,
43 const wxGLContext *other /* for sharing display lists */
44 )
0a67a93b
SC
45{
46 m_window = win;
e4db172a 47
facd6764 48 m_drawable = (AGLDrawable) UMAGetWindowPort(MAC_WXHWND(win->MacGetTopLevelWindowRef()));
e4db172a 49
0a67a93b
SC
50 m_glContext = aglCreateContext(fmt, other ? other->m_glContext : NULL);
51 wxCHECK_RET( m_glContext, wxT("Couldn't create OpenGl context") );
e4db172a 52
e40298d5 53 GLboolean b;
0a67a93b
SC
54 b = aglSetDrawable(m_glContext, m_drawable);
55 wxCHECK_RET( b, wxT("Couldn't bind OpenGl context") );
e40298d5 56 aglEnable(m_glContext , AGL_BUFFER_RECT ) ;
0a67a93b
SC
57 b = aglSetCurrentContext(m_glContext);
58 wxCHECK_RET( b, wxT("Couldn't activate OpenGl context") );
59}
60
61wxGLContext::~wxGLContext()
62{
e40298d5
JS
63 if (m_glContext)
64 {
65 aglSetCurrentContext(NULL);
66 aglDestroyContext(m_glContext);
67 }
0a67a93b
SC
68}
69
70void wxGLContext::SwapBuffers()
71{
e40298d5
JS
72 if (m_glContext)
73 {
74 aglSwapBuffers(m_glContext);
75 }
0a67a93b
SC
76}
77
78void wxGLContext::SetCurrent()
79{
e40298d5
JS
80 if (m_glContext)
81 {
82 aglSetCurrentContext(m_glContext);
83 }
0a67a93b
SC
84}
85
86void wxGLContext::Update()
87{
e40298d5
JS
88 if (m_glContext)
89 {
90 aglUpdateContext(m_glContext);
91 }
0a67a93b
SC
92}
93
427ff662 94void wxGLContext::SetColour(const wxChar *colour)
0a67a93b 95{
564a150b
VZ
96 wxColour col = wxTheColourDatabase->Find(colour);
97 if (col.Ok())
e40298d5 98 {
564a150b
VZ
99 float r = (float)(col.Red()/256.0);
100 float g = (float)(col.Green()/256.0);
101 float b = (float)(col.Blue()/256.0);
e40298d5
JS
102 glColor3f( r, g, b);
103 }
0a67a93b
SC
104}
105
106
107/*
e40298d5
JS
108* wxGLCanvas implementation
109*/
0a67a93b 110
4660d7e5 111IMPLEMENT_CLASS(wxGLCanvas, wxWindow)
0a67a93b 112
4660d7e5 113BEGIN_EVENT_TABLE(wxGLCanvas, wxWindow)
0a67a93b
SC
114 EVT_SIZE(wxGLCanvas::OnSize)
115END_EVENT_TABLE()
116
117wxGLCanvas::wxGLCanvas(wxWindow *parent, wxWindowID id,
e40298d5
JS
118 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
119 int *attribList, const wxPalette& palette)
0a67a93b
SC
120{
121 Create(parent, NULL, id, pos, size, style, name, attribList, palette);
122}
123
124wxGLCanvas::wxGLCanvas( wxWindow *parent,
e40298d5
JS
125 const wxGLContext *shared, wxWindowID id,
126 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
127 int *attribList, const wxPalette& palette )
0a67a93b
SC
128{
129 Create(parent, shared, id, pos, size, style, name, attribList, palette);
130}
131
132wxGLCanvas::wxGLCanvas( wxWindow *parent, const wxGLCanvas *shared, wxWindowID id,
e40298d5
JS
133 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
134 int *attribList, const wxPalette& palette )
0a67a93b
SC
135{
136 Create(parent, shared ? shared->GetContext() : NULL, id, pos, size, style, name, attribList, palette);
137}
138
139wxGLCanvas::~wxGLCanvas()
140{
f5bb2251
GD
141 if (m_glContext != NULL) {
142 delete m_glContext;
143 m_glContext = NULL;
144 }
0a67a93b
SC
145}
146
16506231 147static AGLPixelFormat ChoosePixelFormat(const int *attribList)
0a67a93b 148{
0a67a93b 149 GLint data[512];
e4db172a
WS
150 GLint defaultAttribs[] = { AGL_RGBA,
151 AGL_DOUBLEBUFFER,
152 AGL_MINIMUM_POLICY,
e40298d5 153 AGL_DEPTH_SIZE, 1, // use largest available depth buffer
e4db172a
WS
154 AGL_RED_SIZE, 1,
155 AGL_GREEN_SIZE, 1,
156 AGL_BLUE_SIZE, 1,
157 AGL_ALPHA_SIZE, 0,
e40298d5 158 AGL_NONE };
0a67a93b
SC
159 GLint *attribs;
160 if (!attribList)
161 {
e40298d5 162 attribs = defaultAttribs;
0a67a93b
SC
163 }
164 else
165 {
e40298d5 166 int arg=0, p=0;
e4db172a 167
e40298d5
JS
168 data[p++] = AGL_MINIMUM_POLICY; // make _SIZE tags behave more like GLX
169 while( (attribList[arg]!=0) && (p<512) )
0a67a93b 170 {
e40298d5
JS
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;
e4db172a 190 case WX_GL_DEPTH_SIZE:
e40298d5 191 data[p++]=AGL_DEPTH_SIZE; data[p++]=attribList[arg++]; break;
e4db172a 192 case WX_GL_STENCIL_SIZE:
e40298d5
JS
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 }
e4db172a
WS
205 }
206 data[p] = 0;
207
e40298d5 208 attribs = data;
0a67a93b 209 }
e4db172a 210
16506231
GD
211 return aglChoosePixelFormat(NULL, 0, attribs);
212}
213
214bool wxGLCanvas::Create(wxWindow *parent, const wxGLContext *shared, wxWindowID id,
e40298d5
JS
215 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
216 int *attribList, const wxPalette& palette)
16506231 217{
e7ead9d7
SC
218 m_macCanvasIsShown = false ;
219 m_glContext = 0 ;
4660d7e5 220 wxWindow::Create( parent, id, pos, size, style, name );
e4db172a 221
16506231 222 AGLPixelFormat fmt = ChoosePixelFormat(attribList);
0a67a93b 223 wxCHECK_MSG( fmt, false, wxT("Couldn't create OpenGl pixel format") );
e4db172a 224
0a67a93b 225 m_glContext = new wxGLContext(fmt, this, palette, shared);
ab89a5b5 226 m_macCanvasIsShown = true ;
0a67a93b 227 aglDestroyPixelFormat(fmt);
e4db172a 228
0a67a93b
SC
229 return true;
230}
231
232void wxGLCanvas::SwapBuffers()
233{
e40298d5
JS
234 if (m_glContext)
235 m_glContext->SwapBuffers();
0a67a93b
SC
236}
237
238void wxGLCanvas::UpdateContext()
239{
e40298d5
JS
240 if (m_glContext)
241 m_glContext->Update();
0a67a93b
SC
242}
243
244void wxGLCanvas::SetViewport()
245{
e40298d5
JS
246 // viewport is initially set to entire port
247 // adjust glViewport to just this window
0a67a93b
SC
248 int x = 0 ;
249 int y = 0 ;
e4db172a 250
ab89a5b5
SC
251 wxWindow* iter = this ;
252 while( iter->GetParent() )
253 {
e4db172a 254 iter = iter->GetParent() ;
ab89a5b5 255 }
e4db172a 256
ab89a5b5
SC
257 if ( iter && iter->IsTopLevel() )
258 {
e4db172a
WS
259 MacClientToRootWindow( &x , &y ) ;
260 int width, height;
261 GetClientSize(& width, & height);
262 Rect bounds ;
3a5ff9b1
SC
263#if 0
264 // TODO in case we adopt point vs pixel coordinates, this will make the conversion
265 GetWindowPortBounds( MAC_WXHWND(MacGetTopLevelWindowRef()) , &bounds ) ;
266 HIRect hiRect = CGRectMake( x, y, width, height ) ;
267 HIRectConvert( &hiRect, kHICoordSpace72DPIGlobal, NULL, kHICoordSpaceScreenPixel, NULL) ;
268 HIRect hiBounds = CGRectMake( 0, 0, bounds.right - bounds.left , bounds.bottom - bounds.top ) ;
269 HIRectConvert( &hiBounds, kHICoordSpace72DPIGlobal, NULL, kHICoordSpaceScreenPixel, NULL) ;
270 GLint parms[4] ;
271 parms[0] = hiRect.origin.x ;
272 parms[1] = hiBounds.size.height - (hiRect.origin.y + hiRect.size.height) ;
273 parms[2] = hiRect.size.width ;
274 parms[3] = hiRect.size.height ;
275#else
e4db172a
WS
276 GetWindowPortBounds( MAC_WXHWND(MacGetTopLevelWindowRef()) , &bounds ) ;
277 GLint parms[4] ;
278 parms[0] = x ;
279 parms[1] = bounds.bottom - bounds.top - ( y + height ) ;
280 parms[2] = width ;
281 parms[3] = height ;
3a5ff9b1 282#endif
e4db172a
WS
283 if ( !m_macCanvasIsShown )
284 parms[0] += 20000 ;
285 aglSetInteger( m_glContext->m_glContext , AGL_BUFFER_RECT , parms ) ;
286 }
0a67a93b
SC
287}
288
289void wxGLCanvas::OnSize(wxSizeEvent& event)
a3bf4a62 290{
e40298d5 291 MacUpdateView() ;
a3bf4a62
SC
292}
293
294void wxGLCanvas::MacUpdateView()
0a67a93b 295{
e40298d5
JS
296 if (m_glContext)
297 {
298 UpdateContext();
299 m_glContext->SetCurrent();
300 SetViewport();
301 }
0a67a93b
SC
302}
303
a3bf4a62
SC
304void wxGLCanvas::MacSuperChangedPosition()
305{
e40298d5
JS
306 MacUpdateView() ;
307 wxWindow::MacSuperChangedPosition() ;
a3bf4a62
SC
308}
309
310void wxGLCanvas::MacTopLevelWindowChangedPosition()
311{
e40298d5
JS
312 MacUpdateView() ;
313 wxWindow::MacTopLevelWindowChangedPosition() ;
a3bf4a62
SC
314}
315
0a67a93b
SC
316void wxGLCanvas::SetCurrent()
317{
e40298d5
JS
318 if (m_glContext)
319 {
320 m_glContext->SetCurrent();
321 }
0a67a93b
SC
322}
323
427ff662 324void wxGLCanvas::SetColour(const wxChar *colour)
0a67a93b 325{
e40298d5
JS
326 if (m_glContext)
327 m_glContext->SetColour(colour);
0a67a93b
SC
328}
329
e4db172a 330bool wxGLCanvas::Show(bool show)
ab89a5b5
SC
331{
332 if ( !wxWindow::Show( show ) )
9eddec69 333 return false ;
e4db172a 334/*
ab89a5b5
SC
335 if ( !show )
336 {
337 if ( m_macCanvasIsShown )
338 {
339 m_macCanvasIsShown = false ;
340 SetViewport() ;
341 }
342 }
343 else
344 {
5ca0d812 345 if ( m_peer->IsVisible()&& !m_macCanvasIsShown )
ab89a5b5
SC
346 {
347 m_macCanvasIsShown = true ;
348 SetViewport() ;
349 }
350 }
c40f44ba 351*/
9eddec69 352 return true ;
ab89a5b5
SC
353}
354
e4db172a 355void wxGLCanvas::MacVisibilityChanged()
ab89a5b5 356{
5ca0d812 357 if ( !MacIsReallyShown() )
ab89a5b5
SC
358 {
359 if ( m_macCanvasIsShown )
360 {
361 m_macCanvasIsShown = false ;
362 SetViewport() ;
363 }
364 }
365 else
366 {
c40f44ba 367 if ( !m_macCanvasIsShown )
ab89a5b5
SC
368 {
369 m_macCanvasIsShown = true ;
370 SetViewport() ;
371 }
372 }
c40f44ba 373 wxWindowMac::MacVisibilityChanged() ;
ab89a5b5 374}
16506231
GD
375
376//---------------------------------------------------------------------------
377// wxGLApp
378//---------------------------------------------------------------------------
379
380IMPLEMENT_CLASS(wxGLApp, wxApp)
381
382bool wxGLApp::InitGLVisual(int *attribList)
383{
384 AGLPixelFormat fmt = ChoosePixelFormat(attribList);
bf44306e
GD
385 if (fmt != NULL) {
386 aglDestroyPixelFormat(fmt);
387 return true;
388 } else
389 return false;
16506231
GD
390}
391
392wxGLApp::~wxGLApp(void)
393{
394}
395
0a67a93b 396#endif // wxUSE_GLCANVAS