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