]> git.saurik.com Git - wxWidgets.git/blame - src/mac/classic/glcanvas.cpp
use WX_DEFINE_ARRAY_INT for an array of ints (bug 1536482)
[wxWidgets.git] / src / mac / classic / glcanvas.cpp
CommitLineData
2646f485 1/////////////////////////////////////////////////////////////////////////////
0ba6a836 2// Name: src/mac/classic/glcanvas.cpp
77ffb593 3// Purpose: wxGLCanvas, for using OpenGL with wxWidgets under Macintosh
2646f485
SC
4// Author: Stefan Csomor
5// Modified by:
6// Created: 1998-01-01
7// RCS-ID: $Id$
8// Copyright: (c) Stefan Csomor
e4db172a 9// Licence: wxWindows licence
2646f485
SC
10/////////////////////////////////////////////////////////////////////////////
11
2646f485
SC
12#include "wx/wxprec.h"
13
14#if defined(__BORLANDC__)
e4db172a 15 #pragma hdrstop
2646f485
SC
16#endif
17
2646f485
SC
18#if wxUSE_GLCANVAS
19
e4db172a
WS
20#include "wx/glcanvas.h"
21
2646f485 22#ifndef WX_PRECOMP
e4db172a
WS
23 #include "wx/frame.h"
24 #include "wx/log.h"
9eddec69 25 #include "wx/settings.h"
2646f485
SC
26#endif
27
2646f485
SC
28#include "wx/mac/uma.h"
29
30// DLL options compatibility check:
31#include "wx/build.h"
32WX_CHECK_BUILD_OPTIONS("wxGL")
33
34/*
35* GLContext implementation
36*/
37
38wxGLContext::wxGLContext(
39 AGLPixelFormat fmt, wxGLCanvas *win,
40 const wxPalette& palette,
41 const wxGLContext *other /* for sharing display lists */
42 )
43{
44 m_window = win;
0ba6a836 45
2646f485 46 m_drawable = (AGLDrawable) UMAGetWindowPort(MAC_WXHWND(win->MacGetRootWindow()));
0ba6a836 47
2646f485
SC
48 m_glContext = aglCreateContext(fmt, other ? other->m_glContext : NULL);
49 wxCHECK_RET( m_glContext, wxT("Couldn't create OpenGl context") );
0ba6a836 50
2646f485
SC
51 GLboolean b;
52 b = aglSetDrawable(m_glContext, m_drawable);
53 wxCHECK_RET( b, wxT("Couldn't bind OpenGl context") );
54 aglEnable(m_glContext , AGL_BUFFER_RECT ) ;
55 b = aglSetCurrentContext(m_glContext);
56 wxCHECK_RET( b, wxT("Couldn't activate OpenGl context") );
57}
58
59wxGLContext::~wxGLContext()
60{
61 if (m_glContext)
62 {
63 aglSetCurrentContext(NULL);
64 aglDestroyContext(m_glContext);
65 }
66}
67
68void wxGLContext::SwapBuffers()
69{
70 if (m_glContext)
71 {
72 aglSwapBuffers(m_glContext);
73 }
74}
75
76void wxGLContext::SetCurrent()
77{
78 if (m_glContext)
79 {
80 aglSetCurrentContext(m_glContext);
81 }
82}
83
84void wxGLContext::Update()
85{
86 if (m_glContext)
87 {
88 aglUpdateContext(m_glContext);
89 }
90}
91
92void wxGLContext::SetColour(const wxChar *colour)
93{
94 wxColour col = wxTheColourDatabase->Find(colour);
95 if (col.Ok())
96 {
97 float r = (float)(col.Red()/256.0);
98 float g = (float)(col.Green()/256.0);
99 float b = (float)(col.Blue()/256.0);
100 glColor3f( r, g, b);
101 }
102}
103
104
105/*
106* wxGLCanvas implementation
107*/
108
109IMPLEMENT_CLASS(wxGLCanvas, wxWindow)
110
111BEGIN_EVENT_TABLE(wxGLCanvas, wxWindow)
112 EVT_SIZE(wxGLCanvas::OnSize)
113END_EVENT_TABLE()
114
115wxGLCanvas::wxGLCanvas(wxWindow *parent, wxWindowID id,
116 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
117 int *attribList, const wxPalette& palette)
118{
119 Create(parent, NULL, id, pos, size, style, name, attribList, palette);
120}
121
122wxGLCanvas::wxGLCanvas( wxWindow *parent,
123 const wxGLContext *shared, wxWindowID id,
124 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
125 int *attribList, const wxPalette& palette )
126{
127 Create(parent, shared, id, pos, size, style, name, attribList, palette);
128}
129
130wxGLCanvas::wxGLCanvas( wxWindow *parent, const wxGLCanvas *shared, wxWindowID id,
131 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
132 int *attribList, const wxPalette& palette )
133{
134 Create(parent, shared ? shared->GetContext() : NULL, id, pos, size, style, name, attribList, palette);
135}
136
137wxGLCanvas::~wxGLCanvas()
138{
139 if (m_glContext != NULL) {
140 delete m_glContext;
141 m_glContext = NULL;
142 }
143}
144
145static AGLPixelFormat ChoosePixelFormat(const int *attribList)
146{
147 GLint data[512];
0ba6a836
WS
148 GLint defaultAttribs[] = { AGL_RGBA,
149 AGL_DOUBLEBUFFER,
150 AGL_MINIMUM_POLICY,
2646f485 151 AGL_DEPTH_SIZE, 1, // use largest available depth buffer
0ba6a836
WS
152 AGL_RED_SIZE, 1,
153 AGL_GREEN_SIZE, 1,
154 AGL_BLUE_SIZE, 1,
155 AGL_ALPHA_SIZE, 0,
2646f485
SC
156 AGL_NONE };
157 GLint *attribs;
158 if (!attribList)
159 {
160 attribs = defaultAttribs;
161 }
162 else
163 {
164 int arg=0, p=0;
0ba6a836 165
2646f485
SC
166 data[p++] = AGL_MINIMUM_POLICY; // make _SIZE tags behave more like GLX
167 while( (attribList[arg]!=0) && (p<512) )
168 {
169 switch( attribList[arg++] )
170 {
171 case WX_GL_RGBA: data[p++] = AGL_RGBA; break;
172 case WX_GL_BUFFER_SIZE:
173 data[p++]=AGL_BUFFER_SIZE; data[p++]=attribList[arg++]; break;
174 case WX_GL_LEVEL:
175 data[p++]=AGL_LEVEL; data[p++]=attribList[arg++]; break;
176 case WX_GL_DOUBLEBUFFER: data[p++] = AGL_DOUBLEBUFFER; break;
177 case WX_GL_STEREO: data[p++] = AGL_STEREO; break;
178 case WX_GL_AUX_BUFFERS:
179 data[p++]=AGL_AUX_BUFFERS; data[p++]=attribList[arg++]; break;
180 case WX_GL_MIN_RED:
181 data[p++]=AGL_RED_SIZE; data[p++]=attribList[arg++]; break;
182 case WX_GL_MIN_GREEN:
183 data[p++]=AGL_GREEN_SIZE; data[p++]=attribList[arg++]; break;
184 case WX_GL_MIN_BLUE:
185 data[p++]=AGL_BLUE_SIZE; data[p++]=attribList[arg++]; break;
186 case WX_GL_MIN_ALPHA:
187 data[p++]=AGL_ALPHA_SIZE; data[p++]=attribList[arg++]; break;
0ba6a836 188 case WX_GL_DEPTH_SIZE:
2646f485 189 data[p++]=AGL_DEPTH_SIZE; data[p++]=attribList[arg++]; break;
0ba6a836 190 case WX_GL_STENCIL_SIZE:
2646f485
SC
191 data[p++]=AGL_STENCIL_SIZE; data[p++]=attribList[arg++]; break;
192 case WX_GL_MIN_ACCUM_RED:
193 data[p++]=AGL_ACCUM_RED_SIZE; data[p++]=attribList[arg++]; break;
194 case WX_GL_MIN_ACCUM_GREEN:
195 data[p++]=AGL_ACCUM_GREEN_SIZE; data[p++]=attribList[arg++]; break;
196 case WX_GL_MIN_ACCUM_BLUE:
197 data[p++]=AGL_ACCUM_BLUE_SIZE; data[p++]=attribList[arg++]; break;
198 case WX_GL_MIN_ACCUM_ALPHA:
199 data[p++]=AGL_ACCUM_ALPHA_SIZE; data[p++]=attribList[arg++]; break;
200 default:
201 break;
202 }
0ba6a836
WS
203 }
204 data[p] = 0;
205
2646f485
SC
206 attribs = data;
207 }
0ba6a836 208
2646f485
SC
209 return aglChoosePixelFormat(NULL, 0, attribs);
210}
211
212bool wxGLCanvas::Create(wxWindow *parent, const wxGLContext *shared, wxWindowID id,
213 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
214 int *attribList, const wxPalette& palette)
215{
216 wxWindow::Create( parent, id, pos, size, style, name );
0ba6a836 217
2646f485
SC
218 AGLPixelFormat fmt = ChoosePixelFormat(attribList);
219 wxCHECK_MSG( fmt, false, wxT("Couldn't create OpenGl pixel format") );
0ba6a836 220
2646f485
SC
221 m_glContext = new wxGLContext(fmt, this, palette, shared);
222 m_macCanvasIsShown = true ;
223 aglDestroyPixelFormat(fmt);
0ba6a836 224
2646f485
SC
225 return true;
226}
227
228void wxGLCanvas::SwapBuffers()
229{
230 if (m_glContext)
231 m_glContext->SwapBuffers();
232}
233
234void wxGLCanvas::UpdateContext()
235{
236 if (m_glContext)
237 m_glContext->Update();
238}
239
240void wxGLCanvas::SetViewport()
241{
242 // viewport is initially set to entire port
243 // adjust glViewport to just this window
244 int x = 0 ;
245 int y = 0 ;
0ba6a836 246
2646f485
SC
247 wxWindow* iter = this ;
248 while( iter->GetParent() )
249 {
0ba6a836 250 iter = iter->GetParent() ;
2646f485 251 }
0ba6a836 252
2646f485
SC
253 if ( iter && iter->IsTopLevel() )
254 {
0ba6a836
WS
255 MacClientToRootWindow( &x , &y ) ;
256 int width, height;
257 GetClientSize(& width, & height);
258 Rect bounds ;
259 GetWindowPortBounds( MAC_WXHWND(MacGetRootWindow()) , &bounds ) ;
260 GLint parms[4] ;
261 parms[0] = x ;
262 parms[1] = bounds.bottom - bounds.top - ( y + height ) ;
263 parms[2] = width ;
264 parms[3] = height ;
265
266 if ( !m_macCanvasIsShown )
267 parms[0] += 20000 ;
268 aglSetInteger( m_glContext->m_glContext , AGL_BUFFER_RECT , parms ) ;
269 }
2646f485
SC
270}
271
272void wxGLCanvas::OnSize(wxSizeEvent& event)
273{
274 MacUpdateView() ;
275}
276
277void wxGLCanvas::MacUpdateView()
278{
279 if (m_glContext)
280 {
281 UpdateContext();
282 m_glContext->SetCurrent();
283 SetViewport();
284 }
285}
286
287void wxGLCanvas::MacSuperChangedPosition()
288{
289 MacUpdateView() ;
290 wxWindow::MacSuperChangedPosition() ;
291}
292
293void wxGLCanvas::MacTopLevelWindowChangedPosition()
294{
295 MacUpdateView() ;
296 wxWindow::MacTopLevelWindowChangedPosition() ;
297}
298
299void wxGLCanvas::SetCurrent()
300{
301 if (m_glContext)
302 {
303 m_glContext->SetCurrent();
304 }
305}
306
307void wxGLCanvas::SetColour(const wxChar *colour)
308{
309 if (m_glContext)
310 m_glContext->SetColour(colour);
311}
312
0ba6a836 313bool wxGLCanvas::Show(bool show)
2646f485
SC
314{
315 if ( !wxWindow::Show( show ) )
0ba6a836
WS
316 return false ;
317
2646f485
SC
318 if ( !show )
319 {
320 if ( m_macCanvasIsShown )
321 {
322 m_macCanvasIsShown = false ;
323 SetViewport() ;
324 }
325 }
326 else
327 {
328 if ( MacIsReallyShown() && !m_macCanvasIsShown )
329 {
330 m_macCanvasIsShown = true ;
331 SetViewport() ;
332 }
333 }
0ba6a836 334 return true ;
2646f485
SC
335}
336
0ba6a836 337void wxGLCanvas::MacSuperShown( bool show )
2646f485
SC
338{
339 if ( !show )
340 {
341 if ( m_macCanvasIsShown )
342 {
343 m_macCanvasIsShown = false ;
344 SetViewport() ;
345 }
346 }
347 else
348 {
349 if ( MacIsReallyShown() && !m_macCanvasIsShown )
350 {
351 m_macCanvasIsShown = true ;
352 SetViewport() ;
353 }
354 }
0ba6a836 355
2646f485
SC
356 wxWindow::MacSuperShown( show ) ;
357}
358
359//---------------------------------------------------------------------------
360// wxGLApp
361//---------------------------------------------------------------------------
362
363IMPLEMENT_CLASS(wxGLApp, wxApp)
364
365bool wxGLApp::InitGLVisual(int *attribList)
366{
367 AGLPixelFormat fmt = ChoosePixelFormat(attribList);
368 if (fmt != NULL) {
369 aglDestroyPixelFormat(fmt);
370 return true;
371 } else
372 return false;
373}
374
375wxGLApp::~wxGLApp(void)
376{
377}
378
379#endif // wxUSE_GLCANVAS