]> git.saurik.com Git - wxWidgets.git/blame - src/mac/glcanvas.cpp
multilib mode
[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
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;
e40298d5 47
76a5e5d2 48 m_drawable = (AGLDrawable) UMAGetWindowPort(MAC_WXHWND(win->MacGetRootWindow()));
e40298d5 49
0a67a93b
SC
50 m_glContext = aglCreateContext(fmt, other ? other->m_glContext : NULL);
51 wxCHECK_RET( m_glContext, wxT("Couldn't create OpenGl context") );
e40298d5
JS
52
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{
e40298d5
JS
96 float r = 0.0;
97 float g = 0.0;
98 float b = 0.0;
99 wxColour *col = wxTheColourDatabase->FindColour(colour);
100 if (col)
101 {
102 r = (float)(col->Red()/256.0);
103 g = (float)(col->Green()/256.0);
104 b = (float)(col->Blue()/256.0);
105 glColor3f( r, g, b);
106 }
0a67a93b
SC
107}
108
109
110/*
e40298d5
JS
111* wxGLCanvas implementation
112*/
0a67a93b 113
4660d7e5 114IMPLEMENT_CLASS(wxGLCanvas, wxWindow)
0a67a93b 115
4660d7e5 116BEGIN_EVENT_TABLE(wxGLCanvas, wxWindow)
0a67a93b
SC
117 EVT_SIZE(wxGLCanvas::OnSize)
118END_EVENT_TABLE()
119
120wxGLCanvas::wxGLCanvas(wxWindow *parent, wxWindowID id,
e40298d5
JS
121 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
122 int *attribList, const wxPalette& palette)
0a67a93b
SC
123{
124 Create(parent, NULL, id, pos, size, style, name, attribList, palette);
125}
126
127wxGLCanvas::wxGLCanvas( wxWindow *parent,
e40298d5
JS
128 const wxGLContext *shared, wxWindowID id,
129 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
130 int *attribList, const wxPalette& palette )
0a67a93b
SC
131{
132 Create(parent, shared, id, pos, size, style, name, attribList, palette);
133}
134
135wxGLCanvas::wxGLCanvas( wxWindow *parent, const wxGLCanvas *shared, wxWindowID id,
e40298d5
JS
136 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
137 int *attribList, const wxPalette& palette )
0a67a93b
SC
138{
139 Create(parent, shared ? shared->GetContext() : NULL, id, pos, size, style, name, attribList, palette);
140}
141
142wxGLCanvas::~wxGLCanvas()
143{
f5bb2251
GD
144 if (m_glContext != NULL) {
145 delete m_glContext;
146 m_glContext = NULL;
147 }
0a67a93b
SC
148}
149
16506231 150static AGLPixelFormat ChoosePixelFormat(const int *attribList)
0a67a93b 151{
0a67a93b 152 GLint data[512];
16506231 153 GLint defaultAttribs[] = { AGL_RGBA,
e40298d5
JS
154 AGL_DOUBLEBUFFER,
155 AGL_MINIMUM_POLICY,
156 AGL_DEPTH_SIZE, 1, // use largest available depth buffer
157 AGL_RED_SIZE, 1,
158 AGL_GREEN_SIZE, 1,
159 AGL_BLUE_SIZE, 1,
160 AGL_ALPHA_SIZE, 0,
161 AGL_NONE };
0a67a93b
SC
162 GLint *attribs;
163 if (!attribList)
164 {
e40298d5 165 attribs = defaultAttribs;
0a67a93b
SC
166 }
167 else
168 {
e40298d5
JS
169 int arg=0, p=0;
170
171 data[p++] = AGL_MINIMUM_POLICY; // make _SIZE tags behave more like GLX
172 while( (attribList[arg]!=0) && (p<512) )
0a67a93b 173 {
e40298d5
JS
174 switch( attribList[arg++] )
175 {
176 case WX_GL_RGBA: data[p++] = AGL_RGBA; break;
177 case WX_GL_BUFFER_SIZE:
178 data[p++]=AGL_BUFFER_SIZE; data[p++]=attribList[arg++]; break;
179 case WX_GL_LEVEL:
180 data[p++]=AGL_LEVEL; data[p++]=attribList[arg++]; break;
181 case WX_GL_DOUBLEBUFFER: data[p++] = AGL_DOUBLEBUFFER; break;
182 case WX_GL_STEREO: data[p++] = AGL_STEREO; break;
183 case WX_GL_AUX_BUFFERS:
184 data[p++]=AGL_AUX_BUFFERS; data[p++]=attribList[arg++]; break;
185 case WX_GL_MIN_RED:
186 data[p++]=AGL_RED_SIZE; data[p++]=attribList[arg++]; break;
187 case WX_GL_MIN_GREEN:
188 data[p++]=AGL_GREEN_SIZE; data[p++]=attribList[arg++]; break;
189 case WX_GL_MIN_BLUE:
190 data[p++]=AGL_BLUE_SIZE; data[p++]=attribList[arg++]; break;
191 case WX_GL_MIN_ALPHA:
192 data[p++]=AGL_ALPHA_SIZE; data[p++]=attribList[arg++]; break;
193 case WX_GL_DEPTH_SIZE:
194 data[p++]=AGL_DEPTH_SIZE; data[p++]=attribList[arg++]; break;
195 case WX_GL_STENCIL_SIZE:
196 data[p++]=AGL_STENCIL_SIZE; data[p++]=attribList[arg++]; break;
197 case WX_GL_MIN_ACCUM_RED:
198 data[p++]=AGL_ACCUM_RED_SIZE; data[p++]=attribList[arg++]; break;
199 case WX_GL_MIN_ACCUM_GREEN:
200 data[p++]=AGL_ACCUM_GREEN_SIZE; data[p++]=attribList[arg++]; break;
201 case WX_GL_MIN_ACCUM_BLUE:
202 data[p++]=AGL_ACCUM_BLUE_SIZE; data[p++]=attribList[arg++]; break;
203 case WX_GL_MIN_ACCUM_ALPHA:
204 data[p++]=AGL_ACCUM_ALPHA_SIZE; data[p++]=attribList[arg++]; break;
205 default:
206 break;
207 }
208 }
209 data[p] = 0;
210
211 attribs = data;
0a67a93b 212 }
16506231
GD
213
214 return aglChoosePixelFormat(NULL, 0, attribs);
215}
216
217bool wxGLCanvas::Create(wxWindow *parent, const wxGLContext *shared, wxWindowID id,
e40298d5
JS
218 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
219 int *attribList, const wxPalette& palette)
16506231 220{
4660d7e5 221 wxWindow::Create( parent, id, pos, size, style, name );
e40298d5 222
16506231 223 AGLPixelFormat fmt = ChoosePixelFormat(attribList);
0a67a93b 224 wxCHECK_MSG( fmt, false, wxT("Couldn't create OpenGl pixel format") );
e40298d5 225
0a67a93b 226 m_glContext = new wxGLContext(fmt, this, palette, shared);
ab89a5b5 227 m_macCanvasIsShown = true ;
0a67a93b
SC
228 aglDestroyPixelFormat(fmt);
229
230 return true;
231}
232
233void wxGLCanvas::SwapBuffers()
234{
e40298d5
JS
235 if (m_glContext)
236 m_glContext->SwapBuffers();
0a67a93b
SC
237}
238
239void wxGLCanvas::UpdateContext()
240{
e40298d5
JS
241 if (m_glContext)
242 m_glContext->Update();
0a67a93b
SC
243}
244
245void wxGLCanvas::SetViewport()
246{
e40298d5
JS
247 // viewport is initially set to entire port
248 // adjust glViewport to just this window
0a67a93b
SC
249 int x = 0 ;
250 int y = 0 ;
251
ab89a5b5
SC
252 wxWindow* iter = this ;
253 while( iter->GetParent() )
254 {
255 iter = iter->GetParent() ;
256 }
e40298d5 257
ab89a5b5
SC
258 if ( iter && iter->IsTopLevel() )
259 {
260 MacClientToRootWindow( &x , &y ) ;
261 int width, height;
262 GetClientSize(& width, & height);
263 Rect bounds ;
264 GetWindowPortBounds( MAC_WXHWND(MacGetRootWindow()) , &bounds ) ;
265 GLint parms[4] ;
266 parms[0] = x ;
267 parms[1] = bounds.bottom - bounds.top - ( y + height ) ;
268 parms[2] = width ;
269 parms[3] = height ;
270
271 if ( !m_macCanvasIsShown )
272 parms[0] += 20000 ;
273 aglSetInteger( m_glContext->m_glContext , AGL_BUFFER_RECT , parms ) ;
274 }
0a67a93b
SC
275}
276
277void wxGLCanvas::OnSize(wxSizeEvent& event)
a3bf4a62 278{
e40298d5 279 MacUpdateView() ;
a3bf4a62
SC
280}
281
282void wxGLCanvas::MacUpdateView()
0a67a93b 283{
e40298d5
JS
284 if (m_glContext)
285 {
286 UpdateContext();
287 m_glContext->SetCurrent();
288 SetViewport();
289 }
0a67a93b
SC
290}
291
a3bf4a62
SC
292void wxGLCanvas::MacSuperChangedPosition()
293{
e40298d5
JS
294 MacUpdateView() ;
295 wxWindow::MacSuperChangedPosition() ;
a3bf4a62
SC
296}
297
298void wxGLCanvas::MacTopLevelWindowChangedPosition()
299{
e40298d5
JS
300 MacUpdateView() ;
301 wxWindow::MacTopLevelWindowChangedPosition() ;
a3bf4a62
SC
302}
303
0a67a93b
SC
304void wxGLCanvas::SetCurrent()
305{
e40298d5
JS
306 if (m_glContext)
307 {
308 m_glContext->SetCurrent();
309 }
0a67a93b
SC
310}
311
427ff662 312void wxGLCanvas::SetColour(const wxChar *colour)
0a67a93b 313{
e40298d5
JS
314 if (m_glContext)
315 m_glContext->SetColour(colour);
0a67a93b
SC
316}
317
ab89a5b5
SC
318bool wxGLCanvas::Show(bool show)
319{
320 if ( !wxWindow::Show( show ) )
321 return FALSE ;
322
323 if ( !show )
324 {
325 if ( m_macCanvasIsShown )
326 {
327 m_macCanvasIsShown = false ;
328 SetViewport() ;
329 }
330 }
331 else
332 {
333 if ( MacIsReallyShown() && !m_macCanvasIsShown )
334 {
335 m_macCanvasIsShown = true ;
336 SetViewport() ;
337 }
338 }
339 return TRUE ;
340}
341
342void wxGLCanvas::MacSuperShown( bool show )
343{
344 if ( !show )
345 {
346 if ( m_macCanvasIsShown )
347 {
348 m_macCanvasIsShown = false ;
349 SetViewport() ;
350 }
351 }
352 else
353 {
354 if ( MacIsReallyShown() && !m_macCanvasIsShown )
355 {
356 m_macCanvasIsShown = true ;
357 SetViewport() ;
358 }
359 }
360
361 wxWindow::MacSuperShown( show ) ;
362}
16506231
GD
363
364//---------------------------------------------------------------------------
365// wxGLApp
366//---------------------------------------------------------------------------
367
368IMPLEMENT_CLASS(wxGLApp, wxApp)
369
370bool wxGLApp::InitGLVisual(int *attribList)
371{
372 AGLPixelFormat fmt = ChoosePixelFormat(attribList);
bf44306e
GD
373 if (fmt != NULL) {
374 aglDestroyPixelFormat(fmt);
375 return true;
376 } else
377 return false;
16506231
GD
378}
379
380wxGLApp::~wxGLApp(void)
381{
382}
383
0a67a93b 384#endif // wxUSE_GLCANVAS