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