]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/glcanvas.cpp
otherwise we always fall back to blitting, even if we can provide better results
[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
3d1a4878 12#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
0a67a93b
SC
13#pragma implementation "glcanvas.h"
14#endif
15
16#include "wx/wxprec.h"
17
18#if defined(__BORLANDC__)
19#pragma hdrstop
20#endif
21
0a67a93b
SC
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
34fdf762
VS
34// DLL options compatibility check:
35#include "wx/build.h"
36WX_CHECK_BUILD_OPTIONS("wxGL")
37
0a67a93b 38/*
e40298d5
JS
39* GLContext implementation
40*/
0a67a93b
SC
41
42wxGLContext::wxGLContext(
e40298d5
JS
43 AGLPixelFormat fmt, wxGLCanvas *win,
44 const wxPalette& palette,
45 const wxGLContext *other /* for sharing display lists */
46 )
0a67a93b
SC
47{
48 m_window = win;
e40298d5 49
facd6764 50 m_drawable = (AGLDrawable) UMAGetWindowPort(MAC_WXHWND(win->MacGetTopLevelWindowRef()));
e40298d5 51
0a67a93b
SC
52 m_glContext = aglCreateContext(fmt, other ? other->m_glContext : NULL);
53 wxCHECK_RET( m_glContext, wxT("Couldn't create OpenGl context") );
e40298d5
JS
54
55 GLboolean b;
0a67a93b
SC
56 b = aglSetDrawable(m_glContext, m_drawable);
57 wxCHECK_RET( b, wxT("Couldn't bind OpenGl context") );
e40298d5 58 aglEnable(m_glContext , AGL_BUFFER_RECT ) ;
0a67a93b
SC
59 b = aglSetCurrentContext(m_glContext);
60 wxCHECK_RET( b, wxT("Couldn't activate OpenGl context") );
61}
62
63wxGLContext::~wxGLContext()
64{
e40298d5
JS
65 if (m_glContext)
66 {
67 aglSetCurrentContext(NULL);
68 aglDestroyContext(m_glContext);
69 }
0a67a93b
SC
70}
71
72void wxGLContext::SwapBuffers()
73{
e40298d5
JS
74 if (m_glContext)
75 {
76 aglSwapBuffers(m_glContext);
77 }
0a67a93b
SC
78}
79
80void wxGLContext::SetCurrent()
81{
e40298d5
JS
82 if (m_glContext)
83 {
84 aglSetCurrentContext(m_glContext);
85 }
0a67a93b
SC
86}
87
88void wxGLContext::Update()
89{
e40298d5
JS
90 if (m_glContext)
91 {
92 aglUpdateContext(m_glContext);
93 }
0a67a93b
SC
94}
95
427ff662 96void wxGLContext::SetColour(const wxChar *colour)
0a67a93b 97{
564a150b
VZ
98 wxColour col = wxTheColourDatabase->Find(colour);
99 if (col.Ok())
e40298d5 100 {
564a150b
VZ
101 float r = (float)(col.Red()/256.0);
102 float g = (float)(col.Green()/256.0);
103 float b = (float)(col.Blue()/256.0);
e40298d5
JS
104 glColor3f( r, g, b);
105 }
0a67a93b
SC
106}
107
108
109/*
e40298d5
JS
110* wxGLCanvas implementation
111*/
0a67a93b 112
4660d7e5 113IMPLEMENT_CLASS(wxGLCanvas, wxWindow)
0a67a93b 114
4660d7e5 115BEGIN_EVENT_TABLE(wxGLCanvas, wxWindow)
0a67a93b
SC
116 EVT_SIZE(wxGLCanvas::OnSize)
117END_EVENT_TABLE()
118
119wxGLCanvas::wxGLCanvas(wxWindow *parent, wxWindowID id,
e40298d5
JS
120 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
121 int *attribList, const wxPalette& palette)
0a67a93b
SC
122{
123 Create(parent, NULL, id, pos, size, style, name, attribList, palette);
124}
125
126wxGLCanvas::wxGLCanvas( wxWindow *parent,
e40298d5
JS
127 const wxGLContext *shared, wxWindowID id,
128 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
129 int *attribList, const wxPalette& palette )
0a67a93b
SC
130{
131 Create(parent, shared, id, pos, size, style, name, attribList, palette);
132}
133
134wxGLCanvas::wxGLCanvas( wxWindow *parent, const wxGLCanvas *shared, wxWindowID id,
e40298d5
JS
135 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
136 int *attribList, const wxPalette& palette )
0a67a93b
SC
137{
138 Create(parent, shared ? shared->GetContext() : NULL, id, pos, size, style, name, attribList, palette);
139}
140
141wxGLCanvas::~wxGLCanvas()
142{
f5bb2251
GD
143 if (m_glContext != NULL) {
144 delete m_glContext;
145 m_glContext = NULL;
146 }
0a67a93b
SC
147}
148
16506231 149static AGLPixelFormat ChoosePixelFormat(const int *attribList)
0a67a93b 150{
0a67a93b 151 GLint data[512];
16506231 152 GLint defaultAttribs[] = { AGL_RGBA,
e40298d5
JS
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 };
0a67a93b
SC
161 GLint *attribs;
162 if (!attribList)
163 {
e40298d5 164 attribs = defaultAttribs;
0a67a93b
SC
165 }
166 else
167 {
e40298d5
JS
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) )
0a67a93b 172 {
e40298d5
JS
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;
0a67a93b 211 }
16506231
GD
212
213 return aglChoosePixelFormat(NULL, 0, attribs);
214}
215
216bool wxGLCanvas::Create(wxWindow *parent, const wxGLContext *shared, wxWindowID id,
e40298d5
JS
217 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
218 int *attribList, const wxPalette& palette)
16506231 219{
4660d7e5 220 wxWindow::Create( parent, id, pos, size, style, name );
e40298d5 221
16506231 222 AGLPixelFormat fmt = ChoosePixelFormat(attribList);
0a67a93b 223 wxCHECK_MSG( fmt, false, wxT("Couldn't create OpenGl pixel format") );
e40298d5 224
0a67a93b 225 m_glContext = new wxGLContext(fmt, this, palette, shared);
ab89a5b5 226 m_macCanvasIsShown = true ;
0a67a93b
SC
227 aglDestroyPixelFormat(fmt);
228
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 ;
250
ab89a5b5
SC
251 wxWindow* iter = this ;
252 while( iter->GetParent() )
253 {
254 iter = iter->GetParent() ;
255 }
e40298d5 256
ab89a5b5
SC
257 if ( iter && iter->IsTopLevel() )
258 {
259 MacClientToRootWindow( &x , &y ) ;
260 int width, height;
261 GetClientSize(& width, & height);
262 Rect bounds ;
facd6764 263 GetWindowPortBounds( MAC_WXHWND(MacGetTopLevelWindowRef()) , &bounds ) ;
ab89a5b5
SC
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 }
0a67a93b
SC
274}
275
276void wxGLCanvas::OnSize(wxSizeEvent& event)
a3bf4a62 277{
e40298d5 278 MacUpdateView() ;
a3bf4a62
SC
279}
280
281void wxGLCanvas::MacUpdateView()
0a67a93b 282{
e40298d5
JS
283 if (m_glContext)
284 {
285 UpdateContext();
286 m_glContext->SetCurrent();
287 SetViewport();
288 }
0a67a93b
SC
289}
290
a3bf4a62
SC
291void wxGLCanvas::MacSuperChangedPosition()
292{
e40298d5
JS
293 MacUpdateView() ;
294 wxWindow::MacSuperChangedPosition() ;
a3bf4a62
SC
295}
296
297void wxGLCanvas::MacTopLevelWindowChangedPosition()
298{
e40298d5
JS
299 MacUpdateView() ;
300 wxWindow::MacTopLevelWindowChangedPosition() ;
a3bf4a62
SC
301}
302
0a67a93b
SC
303void wxGLCanvas::SetCurrent()
304{
e40298d5
JS
305 if (m_glContext)
306 {
307 m_glContext->SetCurrent();
308 }
0a67a93b
SC
309}
310
427ff662 311void wxGLCanvas::SetColour(const wxChar *colour)
0a67a93b 312{
e40298d5
JS
313 if (m_glContext)
314 m_glContext->SetColour(colour);
0a67a93b
SC
315}
316
ab89a5b5
SC
317bool wxGLCanvas::Show(bool show)
318{
319 if ( !wxWindow::Show( show ) )
320 return FALSE ;
c40f44ba 321/*
ab89a5b5
SC
322 if ( !show )
323 {
324 if ( m_macCanvasIsShown )
325 {
326 m_macCanvasIsShown = false ;
327 SetViewport() ;
328 }
329 }
330 else
331 {
5ca0d812 332 if ( m_peer->IsVisible()&& !m_macCanvasIsShown )
ab89a5b5
SC
333 {
334 m_macCanvasIsShown = true ;
335 SetViewport() ;
336 }
337 }
c40f44ba 338*/
ab89a5b5
SC
339 return TRUE ;
340}
341
c40f44ba 342void wxGLCanvas::MacVisibilityChanged()
ab89a5b5 343{
5ca0d812 344 if ( !MacIsReallyShown() )
ab89a5b5
SC
345 {
346 if ( m_macCanvasIsShown )
347 {
348 m_macCanvasIsShown = false ;
349 SetViewport() ;
350 }
351 }
352 else
353 {
c40f44ba 354 if ( !m_macCanvasIsShown )
ab89a5b5
SC
355 {
356 m_macCanvasIsShown = true ;
357 SetViewport() ;
358 }
359 }
c40f44ba 360 wxWindowMac::MacVisibilityChanged() ;
ab89a5b5 361}
16506231
GD
362
363//---------------------------------------------------------------------------
364// wxGLApp
365//---------------------------------------------------------------------------
366
367IMPLEMENT_CLASS(wxGLApp, wxApp)
368
369bool wxGLApp::InitGLVisual(int *attribList)
370{
371 AGLPixelFormat fmt = ChoosePixelFormat(attribList);
bf44306e
GD
372 if (fmt != NULL) {
373 aglDestroyPixelFormat(fmt);
374 return true;
375 } else
376 return false;
16506231
GD
377}
378
379wxGLApp::~wxGLApp(void)
380{
381}
382
0a67a93b 383#endif // wxUSE_GLCANVAS