]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/glcanvas.cpp
Test for wxUSE_UXTHEME
[wxWidgets.git] / src / mac / carbon / glcanvas.cpp
CommitLineData
dc3065a5 1///////////////////////////////////////////////////////////////////////////////
e4db172a 2// Name: src/mac/carbon/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
e4db172a 9// Licence: wxWindows licence
dc3065a5
VZ
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
0a67a93b 19
0a67a93b
SC
20#include "wx/wxprec.h"
21
22#if defined(__BORLANDC__)
e4db172a 23 #pragma hdrstop
0a67a93b
SC
24#endif
25
0a67a93b
SC
26#if wxUSE_GLCANVAS
27
e4db172a
WS
28#include "wx/glcanvas.h"
29
0a67a93b 30#ifndef WX_PRECOMP
e4db172a
WS
31 #include "wx/frame.h"
32 #include "wx/log.h"
9eddec69 33 #include "wx/settings.h"
0a67a93b
SC
34#endif
35
0a67a93b
SC
36#include "wx/mac/uma.h"
37
3a5ff9b1
SC
38#include "wx/mac/private.h"
39
dc3065a5
VZ
40// ----------------------------------------------------------------------------
41// helper functions
42// ----------------------------------------------------------------------------
0a67a93b 43
dc3065a5 44static void wxLogAGLError(const char *func)
0a67a93b 45{
dc3065a5 46 const int err = aglGetError();
e4db172a 47
dc3065a5
VZ
48 wxLogError(_("OpenGL function \"%s\" failed: %s (error %d)"),
49 func, aglErrorString(err), err);
50}
e4db172a 51
dc3065a5
VZ
52// ============================================================================
53// implementation
54// ============================================================================
e4db172a 55
dc3065a5
VZ
56// ----------------------------------------------------------------------------
57// wxGLContext
58// ----------------------------------------------------------------------------
0a67a93b 59
dc3065a5 60wxGLContext::wxGLContext(wxGLCanvas *win, const wxGLContext *other)
0a67a93b 61{
dc3065a5
VZ
62 m_aglContext = aglCreateContext(win->GetAGLPixelFormat(),
63 other ? other->m_aglContext : NULL);
64 if ( !m_aglContext )
65 wxLogAGLError("aglCreateContext");
66
67 return;
68 if ( !aglEnable(m_aglContext, AGL_BUFFER_RECT) )
69 wxLogAGLError("aglEnable(AGL_BUFFER_RECT)");
0a67a93b
SC
70}
71
dc3065a5 72wxGLContext::~wxGLContext()
0a67a93b 73{
dc3065a5 74 if ( m_aglContext )
e40298d5 75 {
dc3065a5
VZ
76 // it's ok to pass the current context to this function
77 if ( !aglDestroyContext(m_aglContext) )
78 wxLogAGLError("aglDestroyContext");
e40298d5 79 }
0a67a93b
SC
80}
81
dc3065a5 82void wxGLContext::SetCurrent(const wxGLCanvas& win) const
0a67a93b 83{
dc3065a5
VZ
84 if ( !m_aglContext )
85 return;
0a67a93b 86
dc3065a5
VZ
87 AGLDrawable drawable = (AGLDrawable)UMAGetWindowPort(
88 MAC_WXHWND(win.MacGetTopLevelWindowRef()));
89 if ( !aglSetDrawable(m_aglContext, drawable) )
90 wxLogAGLError("aglSetDrawable");
0a67a93b 91
dc3065a5
VZ
92 if ( !aglSetCurrentContext(m_aglContext) )
93 wxLogAGLError("aglSetCurrentContext");
0a67a93b 94
dc3065a5
VZ
95 wx_const_cast(wxGLCanvas&, win).SetViewport();
96}
0a67a93b 97
dc3065a5
VZ
98// ----------------------------------------------------------------------------
99// wxGLCanvas
100// ----------------------------------------------------------------------------
0a67a93b 101
4660d7e5 102IMPLEMENT_CLASS(wxGLCanvas, wxWindow)
0a67a93b 103
4660d7e5 104BEGIN_EVENT_TABLE(wxGLCanvas, wxWindow)
0a67a93b
SC
105 EVT_SIZE(wxGLCanvas::OnSize)
106END_EVENT_TABLE()
107
dc3065a5
VZ
108wxGLCanvas::wxGLCanvas(wxWindow *parent,
109 wxWindowID id,
110 const int *attribList,
111 const wxPoint& pos,
112 const wxSize& size,
113 long style,
114 const wxString& name,
115 const wxPalette& palette)
0a67a93b 116{
dc3065a5 117 Create(parent, id, pos, size, style, name, attribList, palette);
0a67a93b
SC
118}
119
dc3065a5
VZ
120#if WXWIN_COMPATIBILITY_2_8
121
122wxGLCanvas::wxGLCanvas(wxWindow *parent,
123 wxWindowID id,
124 const wxPoint& pos,
125 const wxSize& size,
126 long style,
127 const wxString& name,
128 const int *attribList,
129 const wxPalette& palette)
0a67a93b 130{
dc3065a5
VZ
131 if ( Create(parent, id, pos, size, style, name, attribList, palette) )
132 m_glContext = new wxGLContext(this);
0a67a93b
SC
133}
134
dc3065a5
VZ
135wxGLCanvas::wxGLCanvas(wxWindow *parent,
136 const wxGLContext *shared,
137 wxWindowID id,
138 const wxPoint& pos,
139 const wxSize& size,
140 long style,
141 const wxString& name,
142 const int *attribList,
143 const wxPalette& palette)
0a67a93b 144{
dc3065a5
VZ
145 if ( Create(parent, id, pos, size, style, name, attribList, palette) )
146 m_glContext = new wxGLContext(this, shared);
0a67a93b
SC
147}
148
dc3065a5
VZ
149wxGLCanvas::wxGLCanvas(wxWindow *parent,
150 const wxGLCanvas *shared,
151 wxWindowID id,
152 const wxPoint& pos,
153 const wxSize& size,
154 long style,
155 const wxString& name,
156 const int *attribList,
157 const wxPalette& palette)
0a67a93b 158{
dc3065a5
VZ
159 if ( Create(parent, id, pos, size, style, name, attribList, palette) )
160 m_glContext = new wxGLContext(this, shared ? shared->m_glContext : NULL);
0a67a93b
SC
161}
162
dc3065a5
VZ
163#endif // WXWIN_COMPATIBILITY_2_8
164
16506231 165static AGLPixelFormat ChoosePixelFormat(const int *attribList)
0a67a93b 166{
0a67a93b 167 GLint data[512];
dc3065a5
VZ
168 const GLint defaultAttribs[] =
169 {
170 AGL_RGBA,
e4db172a 171 AGL_DOUBLEBUFFER,
dc3065a5 172 AGL_MINIMUM_POLICY, // never choose less than requested
e40298d5 173 AGL_DEPTH_SIZE, 1, // use largest available depth buffer
e4db172a
WS
174 AGL_RED_SIZE, 1,
175 AGL_GREEN_SIZE, 1,
176 AGL_BLUE_SIZE, 1,
177 AGL_ALPHA_SIZE, 0,
dc3065a5
VZ
178 AGL_NONE
179 };
180
181 const GLint *attribs;
182 if ( !attribList )
0a67a93b 183 {
e40298d5 184 attribs = defaultAttribs;
0a67a93b
SC
185 }
186 else
187 {
dc3065a5 188 unsigned p = 0;
e40298d5 189 data[p++] = AGL_MINIMUM_POLICY; // make _SIZE tags behave more like GLX
dc3065a5
VZ
190
191 for ( unsigned arg = 0; attribList[arg] !=0 && p < WXSIZEOF(data); )
0a67a93b 192 {
dc3065a5 193 switch ( attribList[arg++] )
e40298d5 194 {
dc3065a5
VZ
195 case WX_GL_RGBA:
196 data[p++] = AGL_RGBA;
197 break;
198
199 case WX_GL_BUFFER_SIZE:
200 data[p++] = AGL_BUFFER_SIZE;
201 data[p++] = attribList[arg++];
202 break;
203
204 case WX_GL_LEVEL:
205 data[p++]=AGL_LEVEL;
206 data[p++]=attribList[arg++];
207 break;
208
209 case WX_GL_DOUBLEBUFFER:
210 data[p++] = AGL_DOUBLEBUFFER;
211 break;
212
213 case WX_GL_STEREO:
214 data[p++] = AGL_STEREO;
215 break;
216
217 case WX_GL_AUX_BUFFERS:
218 data[p++] = AGL_AUX_BUFFERS;
219 data[p++] = attribList[arg++];
220 break;
221
222 case WX_GL_MIN_RED:
223 data[p++] = AGL_RED_SIZE;
224 data[p++] = attribList[arg++];
225 break;
226
227 case WX_GL_MIN_GREEN:
228 data[p++] = AGL_GREEN_SIZE;
229 data[p++] = attribList[arg++];
230 break;
231
232 case WX_GL_MIN_BLUE:
233 data[p++] = AGL_BLUE_SIZE;
234 data[p++] = attribList[arg++];
235 break;
236
237 case WX_GL_MIN_ALPHA:
238 data[p++] = AGL_ALPHA_SIZE;
239 data[p++] = attribList[arg++];
240 break;
241
242 case WX_GL_DEPTH_SIZE:
243 data[p++] = AGL_DEPTH_SIZE;
244 data[p++] = attribList[arg++];
245 break;
246
247 case WX_GL_STENCIL_SIZE:
248 data[p++] = AGL_STENCIL_SIZE;
249 data[p++] = attribList[arg++];
250 break;
251
252 case WX_GL_MIN_ACCUM_RED:
253 data[p++] = AGL_ACCUM_RED_SIZE;
254 data[p++] = attribList[arg++];
255 break;
256
257 case WX_GL_MIN_ACCUM_GREEN:
258 data[p++] = AGL_ACCUM_GREEN_SIZE;
259 data[p++] = attribList[arg++];
260 break;
261
262 case WX_GL_MIN_ACCUM_BLUE:
263 data[p++] = AGL_ACCUM_BLUE_SIZE;
264 data[p++] = attribList[arg++];
265 break;
266
267 case WX_GL_MIN_ACCUM_ALPHA:
268 data[p++] = AGL_ACCUM_ALPHA_SIZE;
269 data[p++] = attribList[arg++];
270 break;
e40298d5 271 }
e4db172a 272 }
dc3065a5
VZ
273
274 data[p] = AGL_NONE;
e4db172a 275
e40298d5 276 attribs = data;
0a67a93b 277 }
e4db172a 278
16506231
GD
279 return aglChoosePixelFormat(NULL, 0, attribs);
280}
281
dc3065a5
VZ
282bool wxGLCanvas::Create(wxWindow *parent,
283 wxWindowID id,
284 const wxPoint& pos,
285 const wxSize& size,
286 long style,
287 const wxString& name,
288 const int *attribList,
289 const wxPalette& WXUNUSED(palette))
16506231 290{
dc3065a5
VZ
291 m_needsUpdate = false;
292 m_macCanvasIsShown = false;
e4db172a 293
dc3065a5
VZ
294 m_aglFormat = ChoosePixelFormat(attribList);
295 if ( !m_aglFormat )
296 return false;
e4db172a 297
dc3065a5
VZ
298 if ( !wxWindow::Create(parent, id, pos, size, style, name) )
299 return false;
300
301 m_macCanvasIsShown = true;
e4db172a 302
0a67a93b
SC
303 return true;
304}
305
dc3065a5 306wxGLCanvas::~wxGLCanvas()
0a67a93b 307{
dc3065a5
VZ
308 if ( m_aglFormat )
309 aglDestroyPixelFormat(m_aglFormat);
0a67a93b
SC
310}
311
dc3065a5 312void wxGLCanvas::SwapBuffers()
0a67a93b 313{
dc3065a5
VZ
314 AGLContext context = aglGetCurrentContext();
315 wxCHECK_RET( context, _T("should have current context") );
316
317 aglSwapBuffers(context);
0a67a93b
SC
318}
319
320void wxGLCanvas::SetViewport()
321{
dc3065a5
VZ
322 if ( !m_needsUpdate )
323 return;
e4db172a 324
dc3065a5
VZ
325 m_needsUpdate = false;
326
327 AGLContext context = aglGetCurrentContext();
328 if ( !context )
329 return;
330
331 // viewport is initially set to entire port, adjust it to just this window
332 int x = 0,
333 y = 0;
334 MacClientToRootWindow(&x , &y);
335
336 int width, height;
337 GetClientSize(&width, &height);
338
339 Rect bounds;
340 GetWindowPortBounds(MAC_WXHWND(MacGetTopLevelWindowRef()) , &bounds);
e4db172a 341
3a5ff9b1 342#if 0
dc3065a5
VZ
343 // TODO in case we adopt point vs pixel coordinates, this will make the conversion
344 HIRect hiRect = CGRectMake( x, y, width, height );
345 HIRectConvert( &hiRect, kHICoordSpace72DPIGlobal, NULL, kHICoordSpaceScreenPixel, NULL);
346 HIRect hiBounds = CGRectMake( 0, 0, bounds.right - bounds.left , bounds.bottom - bounds.top );
347 HIRectConvert( &hiBounds, kHICoordSpace72DPIGlobal, NULL, kHICoordSpaceScreenPixel, NULL);
348 GLint parms[4];
349 parms[0] = hiRect.origin.x;
350 parms[1] = hiBounds.size.height - (hiRect.origin.y + hiRect.size.height);
351 parms[2] = hiRect.size.width;
352 parms[3] = hiRect.size.height;
3a5ff9b1 353#else
dc3065a5
VZ
354 GLint parms[4];
355 parms[0] = x;
356 parms[1] = bounds.bottom - bounds.top - ( y + height );
357 parms[2] = width;
358 parms[3] = height;
3a5ff9b1 359#endif
0a67a93b 360
dc3065a5
VZ
361 // move the buffer rect out of sight if we're hidden
362 if ( !m_macCanvasIsShown )
363 parms[0] += 20000;
a3bf4a62 364
dc3065a5 365 if ( !aglSetInteger(context, AGL_BUFFER_RECT, parms) )
dc3065a5 366 wxLogAGLError("aglSetInteger(AGL_BUFFER_RECT)");
1be2473f
VZ
367
368 if ( !aglUpdateContext(context) )
369 wxLogAGLError("aglUpdateContext");
0a67a93b
SC
370}
371
dc3065a5 372void wxGLCanvas::OnSize(wxSizeEvent& event)
a3bf4a62 373{
dc3065a5
VZ
374 MacUpdateView();
375 event.Skip();
a3bf4a62
SC
376}
377
dc3065a5 378void wxGLCanvas::MacUpdateView()
0a67a93b 379{
dc3065a5
VZ
380 m_needsUpdate = true;
381 Refresh(false);
0a67a93b
SC
382}
383
dc3065a5 384void wxGLCanvas::MacSuperChangedPosition()
0a67a93b 385{
dc3065a5
VZ
386 MacUpdateView();
387 wxWindow::MacSuperChangedPosition();
0a67a93b
SC
388}
389
dc3065a5 390void wxGLCanvas::MacTopLevelWindowChangedPosition()
ab89a5b5 391{
dc3065a5
VZ
392 MacUpdateView();
393 wxWindow::MacTopLevelWindowChangedPosition();
ab89a5b5
SC
394}
395
e4db172a 396void wxGLCanvas::MacVisibilityChanged()
ab89a5b5 397{
dc3065a5 398 if ( MacIsReallyShown() != m_macCanvasIsShown )
ab89a5b5 399 {
dc3065a5
VZ
400 m_macCanvasIsShown = !m_macCanvasIsShown;
401 MacUpdateView();
ab89a5b5 402 }
dc3065a5
VZ
403
404 wxWindowMac::MacVisibilityChanged();
ab89a5b5 405}
16506231 406
dc3065a5 407// ----------------------------------------------------------------------------
16506231 408// wxGLApp
dc3065a5 409// ----------------------------------------------------------------------------
16506231 410
dc3065a5 411bool wxGLApp::InitGLVisual(const int *attribList)
16506231
GD
412{
413 AGLPixelFormat fmt = ChoosePixelFormat(attribList);
dc3065a5 414 if ( !fmt )
bf44306e 415 return false;
16506231 416
dc3065a5
VZ
417 aglDestroyPixelFormat(fmt);
418 return true;
16506231
GD
419}
420
0a67a93b 421#endif // wxUSE_GLCANVAS