]> git.saurik.com Git - wxWidgets.git/blame - src/mac/glcanvas.cpp
several patches and extensions
[wxWidgets.git] / src / mac / glcanvas.cpp
CommitLineData
0a67a93b
SC
1/////////////////////////////////////////////////////////////////////////////
2// Name: glcanvas.cpp
3// Purpose: wxGLCanvas, for using OpenGL with wxWindows 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
e40298d5 9// Licence: wxWindows licence
0a67a93b
SC
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
34fdf762
VS
36// DLL options compatibility check:
37#include "wx/build.h"
38WX_CHECK_BUILD_OPTIONS("wxGL")
39
0a67a93b 40/*
e40298d5
JS
41* GLContext implementation
42*/
0a67a93b
SC
43
44wxGLContext::wxGLContext(
e40298d5
JS
45 AGLPixelFormat fmt, wxGLCanvas *win,
46 const wxPalette& palette,
47 const wxGLContext *other /* for sharing display lists */
48 )
0a67a93b
SC
49{
50 m_window = win;
e40298d5 51
76a5e5d2 52 m_drawable = (AGLDrawable) UMAGetWindowPort(MAC_WXHWND(win->MacGetRootWindow()));
e40298d5 53
0a67a93b
SC
54 m_glContext = aglCreateContext(fmt, other ? other->m_glContext : NULL);
55 wxCHECK_RET( m_glContext, wxT("Couldn't create OpenGl context") );
e40298d5
JS
56
57 GLboolean b;
0a67a93b
SC
58 b = aglSetDrawable(m_glContext, m_drawable);
59 wxCHECK_RET( b, wxT("Couldn't bind OpenGl context") );
e40298d5 60 aglEnable(m_glContext , AGL_BUFFER_RECT ) ;
0a67a93b
SC
61 b = aglSetCurrentContext(m_glContext);
62 wxCHECK_RET( b, wxT("Couldn't activate OpenGl context") );
63}
64
65wxGLContext::~wxGLContext()
66{
e40298d5
JS
67 if (m_glContext)
68 {
69 aglSetCurrentContext(NULL);
70 aglDestroyContext(m_glContext);
71 }
0a67a93b
SC
72}
73
74void wxGLContext::SwapBuffers()
75{
e40298d5
JS
76 if (m_glContext)
77 {
78 aglSwapBuffers(m_glContext);
79 }
0a67a93b
SC
80}
81
82void wxGLContext::SetCurrent()
83{
e40298d5
JS
84 if (m_glContext)
85 {
86 aglSetCurrentContext(m_glContext);
87 }
0a67a93b
SC
88}
89
90void wxGLContext::Update()
91{
e40298d5
JS
92 if (m_glContext)
93 {
94 aglUpdateContext(m_glContext);
95 }
0a67a93b
SC
96}
97
427ff662 98void wxGLContext::SetColour(const wxChar *colour)
0a67a93b 99{
e40298d5
JS
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 }
0a67a93b
SC
111}
112
113
114/*
e40298d5
JS
115* wxGLCanvas implementation
116*/
0a67a93b 117
4660d7e5 118IMPLEMENT_CLASS(wxGLCanvas, wxWindow)
0a67a93b 119
4660d7e5 120BEGIN_EVENT_TABLE(wxGLCanvas, wxWindow)
0a67a93b
SC
121 EVT_SIZE(wxGLCanvas::OnSize)
122END_EVENT_TABLE()
123
124wxGLCanvas::wxGLCanvas(wxWindow *parent, wxWindowID id,
e40298d5
JS
125 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
126 int *attribList, const wxPalette& palette)
0a67a93b
SC
127{
128 Create(parent, NULL, id, pos, size, style, name, attribList, palette);
129}
130
131wxGLCanvas::wxGLCanvas( wxWindow *parent,
e40298d5
JS
132 const wxGLContext *shared, wxWindowID id,
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, id, pos, size, style, name, attribList, palette);
137}
138
139wxGLCanvas::wxGLCanvas( wxWindow *parent, const wxGLCanvas *shared, wxWindowID id,
e40298d5
JS
140 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
141 int *attribList, const wxPalette& palette )
0a67a93b
SC
142{
143 Create(parent, shared ? shared->GetContext() : NULL, id, pos, size, style, name, attribList, palette);
144}
145
146wxGLCanvas::~wxGLCanvas()
147{
f5bb2251
GD
148 if (m_glContext != NULL) {
149 delete m_glContext;
150 m_glContext = NULL;
151 }
0a67a93b
SC
152}
153
16506231 154static AGLPixelFormat ChoosePixelFormat(const int *attribList)
0a67a93b 155{
0a67a93b 156 GLint data[512];
16506231 157 GLint defaultAttribs[] = { AGL_RGBA,
e40298d5
JS
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 };
0a67a93b
SC
166 GLint *attribs;
167 if (!attribList)
168 {
e40298d5 169 attribs = defaultAttribs;
0a67a93b
SC
170 }
171 else
172 {
e40298d5
JS
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) )
0a67a93b 177 {
e40298d5
JS
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;
0a67a93b 216 }
16506231
GD
217
218 return aglChoosePixelFormat(NULL, 0, attribs);
219}
220
221bool wxGLCanvas::Create(wxWindow *parent, const wxGLContext *shared, wxWindowID id,
e40298d5
JS
222 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
223 int *attribList, const wxPalette& palette)
16506231 224{
4660d7e5 225 wxWindow::Create( parent, id, pos, size, style, name );
e40298d5 226
16506231 227 AGLPixelFormat fmt = ChoosePixelFormat(attribList);
0a67a93b 228 wxCHECK_MSG( fmt, false, wxT("Couldn't create OpenGl pixel format") );
e40298d5 229
0a67a93b 230 m_glContext = new wxGLContext(fmt, this, palette, shared);
ab89a5b5 231 m_macCanvasIsShown = true ;
0a67a93b
SC
232 aglDestroyPixelFormat(fmt);
233
234 return true;
235}
236
237void wxGLCanvas::SwapBuffers()
238{
e40298d5
JS
239 if (m_glContext)
240 m_glContext->SwapBuffers();
0a67a93b
SC
241}
242
243void wxGLCanvas::UpdateContext()
244{
e40298d5
JS
245 if (m_glContext)
246 m_glContext->Update();
0a67a93b
SC
247}
248
249void wxGLCanvas::SetViewport()
250{
e40298d5
JS
251 // viewport is initially set to entire port
252 // adjust glViewport to just this window
0a67a93b
SC
253 int x = 0 ;
254 int y = 0 ;
255
ab89a5b5
SC
256 wxWindow* iter = this ;
257 while( iter->GetParent() )
258 {
259 iter = iter->GetParent() ;
260 }
e40298d5 261
ab89a5b5
SC
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 }
0a67a93b
SC
279}
280
281void wxGLCanvas::OnSize(wxSizeEvent& event)
a3bf4a62 282{
e40298d5 283 MacUpdateView() ;
a3bf4a62
SC
284}
285
286void wxGLCanvas::MacUpdateView()
0a67a93b 287{
e40298d5
JS
288 if (m_glContext)
289 {
290 UpdateContext();
291 m_glContext->SetCurrent();
292 SetViewport();
293 }
0a67a93b
SC
294}
295
a3bf4a62
SC
296void wxGLCanvas::MacSuperChangedPosition()
297{
e40298d5
JS
298 MacUpdateView() ;
299 wxWindow::MacSuperChangedPosition() ;
a3bf4a62
SC
300}
301
302void wxGLCanvas::MacTopLevelWindowChangedPosition()
303{
e40298d5
JS
304 MacUpdateView() ;
305 wxWindow::MacTopLevelWindowChangedPosition() ;
a3bf4a62
SC
306}
307
0a67a93b
SC
308void wxGLCanvas::SetCurrent()
309{
e40298d5
JS
310 if (m_glContext)
311 {
312 m_glContext->SetCurrent();
313 }
0a67a93b
SC
314}
315
427ff662 316void wxGLCanvas::SetColour(const wxChar *colour)
0a67a93b 317{
e40298d5
JS
318 if (m_glContext)
319 m_glContext->SetColour(colour);
0a67a93b
SC
320}
321
ab89a5b5
SC
322bool 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
346void 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}
16506231
GD
367
368//---------------------------------------------------------------------------
369// wxGLApp
370//---------------------------------------------------------------------------
371
372IMPLEMENT_CLASS(wxGLApp, wxApp)
373
374bool wxGLApp::InitGLVisual(int *attribList)
375{
376 AGLPixelFormat fmt = ChoosePixelFormat(attribList);
bf44306e
GD
377 if (fmt != NULL) {
378 aglDestroyPixelFormat(fmt);
379 return true;
380 } else
381 return false;
16506231
GD
382}
383
384wxGLApp::~wxGLApp(void)
385{
386}
387
0a67a93b 388#endif // wxUSE_GLCANVAS