]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/mac/carbon/glcanvas.cpp
fix wxBrush for the mac build
[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
78bool wxGLContext::SetCurrent(const wxGLCanvas& win) const
79{
80 if ( !m_aglContext )
81 return false;
82
83 AGLDrawable drawable = (AGLDrawable)GetWindowPort(
84 MAC_WXHWND(win.MacGetTopLevelWindowRef()));
85 if ( !aglSetDrawable(m_aglContext, drawable) )
86 {
87 wxLogAGLError("aglSetDrawable");
88 return false;
89 }
90
91 if ( !aglSetCurrentContext(m_aglContext) )
92 {
93 wxLogAGLError("aglSetCurrentContext");
94 return false;
95 }
96
97 wx_const_cast(wxGLCanvas&, win).SetViewport();
98 return true;
99}
100
101// ----------------------------------------------------------------------------
102// wxGLCanvas
103// ----------------------------------------------------------------------------
104
105IMPLEMENT_CLASS(wxGLCanvas, wxWindow)
106
107BEGIN_EVENT_TABLE(wxGLCanvas, wxWindow)
108 EVT_SIZE(wxGLCanvas::OnSize)
109END_EVENT_TABLE()
110
111wxGLCanvas::wxGLCanvas(wxWindow *parent,
112 wxWindowID id,
113 const int *attribList,
114 const wxPoint& pos,
115 const wxSize& size,
116 long style,
117 const wxString& name,
118 const wxPalette& palette)
119{
120 Create(parent, id, pos, size, style, name, attribList, palette);
121}
122
123#if WXWIN_COMPATIBILITY_2_8
124
125wxGLCanvas::wxGLCanvas(wxWindow *parent,
126 wxWindowID id,
127 const wxPoint& pos,
128 const wxSize& size,
129 long style,
130 const wxString& name,
131 const int *attribList,
132 const wxPalette& palette)
133{
134 if ( Create(parent, id, pos, size, style, name, attribList, palette) )
135 m_glContext = new wxGLContext(this);
136}
137
138wxGLCanvas::wxGLCanvas(wxWindow *parent,
139 const wxGLContext *shared,
140 wxWindowID id,
141 const wxPoint& pos,
142 const wxSize& size,
143 long style,
144 const wxString& name,
145 const int *attribList,
146 const wxPalette& palette)
147{
148 if ( Create(parent, id, pos, size, style, name, attribList, palette) )
149 m_glContext = new wxGLContext(this, shared);
150}
151
152wxGLCanvas::wxGLCanvas(wxWindow *parent,
153 const wxGLCanvas *shared,
154 wxWindowID id,
155 const wxPoint& pos,
156 const wxSize& size,
157 long style,
158 const wxString& name,
159 const int *attribList,
160 const wxPalette& palette)
161{
162 if ( Create(parent, id, pos, size, style, name, attribList, palette) )
163 m_glContext = new wxGLContext(this, shared ? shared->m_glContext : NULL);
164}
165
166#endif // WXWIN_COMPATIBILITY_2_8
167
168static AGLPixelFormat ChoosePixelFormat(const int *attribList)
169{
170 GLint data[512];
171 const GLint defaultAttribs[] =
172 {
173 AGL_RGBA,
174 AGL_DOUBLEBUFFER,
175 AGL_MINIMUM_POLICY, // never choose less than requested
176 AGL_DEPTH_SIZE, 1, // use largest available depth buffer
177 AGL_RED_SIZE, 1,
178 AGL_GREEN_SIZE, 1,
179 AGL_BLUE_SIZE, 1,
180 AGL_ALPHA_SIZE, 0,
181 AGL_NONE
182 };
183
184 const GLint *attribs;
185 if ( !attribList )
186 {
187 attribs = defaultAttribs;
188 }
189 else
190 {
191 unsigned p = 0;
192 data[p++] = AGL_MINIMUM_POLICY; // make _SIZE tags behave more like GLX
193
194 for ( unsigned arg = 0; attribList[arg] !=0 && p < WXSIZEOF(data); )
195 {
196 switch ( attribList[arg++] )
197 {
198 case WX_GL_RGBA:
199 data[p++] = AGL_RGBA;
200 break;
201
202 case WX_GL_BUFFER_SIZE:
203 data[p++] = AGL_BUFFER_SIZE;
204 data[p++] = attribList[arg++];
205 break;
206
207 case WX_GL_LEVEL:
208 data[p++]=AGL_LEVEL;
209 data[p++]=attribList[arg++];
210 break;
211
212 case WX_GL_DOUBLEBUFFER:
213 data[p++] = AGL_DOUBLEBUFFER;
214 break;
215
216 case WX_GL_STEREO:
217 data[p++] = AGL_STEREO;
218 break;
219
220 case WX_GL_AUX_BUFFERS:
221 data[p++] = AGL_AUX_BUFFERS;
222 data[p++] = attribList[arg++];
223 break;
224
225 case WX_GL_MIN_RED:
226 data[p++] = AGL_RED_SIZE;
227 data[p++] = attribList[arg++];
228 break;
229
230 case WX_GL_MIN_GREEN:
231 data[p++] = AGL_GREEN_SIZE;
232 data[p++] = attribList[arg++];
233 break;
234
235 case WX_GL_MIN_BLUE:
236 data[p++] = AGL_BLUE_SIZE;
237 data[p++] = attribList[arg++];
238 break;
239
240 case WX_GL_MIN_ALPHA:
241 data[p++] = AGL_ALPHA_SIZE;
242 data[p++] = attribList[arg++];
243 break;
244
245 case WX_GL_DEPTH_SIZE:
246 data[p++] = AGL_DEPTH_SIZE;
247 data[p++] = attribList[arg++];
248 break;
249
250 case WX_GL_STENCIL_SIZE:
251 data[p++] = AGL_STENCIL_SIZE;
252 data[p++] = attribList[arg++];
253 break;
254
255 case WX_GL_MIN_ACCUM_RED:
256 data[p++] = AGL_ACCUM_RED_SIZE;
257 data[p++] = attribList[arg++];
258 break;
259
260 case WX_GL_MIN_ACCUM_GREEN:
261 data[p++] = AGL_ACCUM_GREEN_SIZE;
262 data[p++] = attribList[arg++];
263 break;
264
265 case WX_GL_MIN_ACCUM_BLUE:
266 data[p++] = AGL_ACCUM_BLUE_SIZE;
267 data[p++] = attribList[arg++];
268 break;
269
270 case WX_GL_MIN_ACCUM_ALPHA:
271 data[p++] = AGL_ACCUM_ALPHA_SIZE;
272 data[p++] = attribList[arg++];
273 break;
274 }
275 }
276
277 data[p] = AGL_NONE;
278
279 attribs = data;
280 }
281
282 return aglChoosePixelFormat(NULL, 0, attribs);
283}
284
285bool wxGLCanvas::Create(wxWindow *parent,
286 wxWindowID id,
287 const wxPoint& pos,
288 const wxSize& size,
289 long style,
290 const wxString& name,
291 const int *attribList,
292 const wxPalette& WXUNUSED(palette))
293{
294 m_needsUpdate = false;
295 m_macCanvasIsShown = false;
296
297 m_aglFormat = ChoosePixelFormat(attribList);
298 if ( !m_aglFormat )
299 return false;
300
301 if ( !wxWindow::Create(parent, id, pos, size, style, name) )
302 return false;
303
304 m_macCanvasIsShown = true;
305
306 return true;
307}
308
309wxGLCanvas::~wxGLCanvas()
310{
311 if ( m_aglFormat )
312 aglDestroyPixelFormat(m_aglFormat);
313}
314
315/* static */
316bool wxGLCanvasBase::IsDisplaySupported(const int *attribList)
317{
318 AGLPixelFormat aglFormat = ChoosePixelFormat(attribList);
319
320 if ( !aglFormat )
321 return false;
322
323 aglDestroyPixelFormat(aglFormat);
324
325 return true;
326}
327
328bool wxGLCanvas::SwapBuffers()
329{
330 AGLContext context = aglGetCurrentContext();
331 wxCHECK_MSG(context, false, _T("should have current context"));
332
333 aglSwapBuffers(context);
334 return true;
335}
336
337void wxGLCanvas::SetViewport()
338{
339 if ( !m_needsUpdate )
340 return;
341
342 m_needsUpdate = false;
343
344 AGLContext context = aglGetCurrentContext();
345 if ( !context )
346 return;
347
348 // viewport is initially set to entire port, adjust it to just this window
349 int x = 0,
350 y = 0;
351 MacClientToRootWindow(&x , &y);
352
353 int width, height;
354 GetClientSize(&width, &height);
355
356 Rect bounds;
357 GetWindowPortBounds(MAC_WXHWND(MacGetTopLevelWindowRef()) , &bounds);
358
359#if 0
360 // TODO in case we adopt point vs pixel coordinates, this will make the conversion
361 HIRect hiRect = CGRectMake( x, y, width, height );
362 HIRectConvert( &hiRect, kHICoordSpace72DPIGlobal, NULL, kHICoordSpaceScreenPixel, NULL);
363 HIRect hiBounds = CGRectMake( 0, 0, bounds.right - bounds.left , bounds.bottom - bounds.top );
364 HIRectConvert( &hiBounds, kHICoordSpace72DPIGlobal, NULL, kHICoordSpaceScreenPixel, NULL);
365 GLint parms[4];
366 parms[0] = hiRect.origin.x;
367 parms[1] = hiBounds.size.height - (hiRect.origin.y + hiRect.size.height);
368 parms[2] = hiRect.size.width;
369 parms[3] = hiRect.size.height;
370#else
371 GLint parms[4];
372 parms[0] = x;
373 parms[1] = bounds.bottom - bounds.top - ( y + height );
374 parms[2] = width;
375 parms[3] = height;
376#endif
377
378 // move the buffer rect out of sight if we're hidden
379 if ( !m_macCanvasIsShown )
380 parms[0] += 20000;
381
382 if ( !aglSetInteger(context, AGL_BUFFER_RECT, parms) )
383 wxLogAGLError("aglSetInteger(AGL_BUFFER_RECT)");
384
385 if ( !aglEnable(context, AGL_BUFFER_RECT) )
386 wxLogAGLError("aglEnable(AGL_BUFFER_RECT)");
387
388 if ( !aglUpdateContext(context) )
389 wxLogAGLError("aglUpdateContext");
390}
391
392void wxGLCanvas::OnSize(wxSizeEvent& event)
393{
394 MacUpdateView();
395 event.Skip();
396}
397
398void wxGLCanvas::MacUpdateView()
399{
400 m_needsUpdate = true;
401 Refresh(false);
402}
403
404void wxGLCanvas::MacSuperChangedPosition()
405{
406 MacUpdateView();
407 wxWindow::MacSuperChangedPosition();
408}
409
410void wxGLCanvas::MacTopLevelWindowChangedPosition()
411{
412 MacUpdateView();
413 wxWindow::MacTopLevelWindowChangedPosition();
414}
415
416void wxGLCanvas::MacVisibilityChanged()
417{
418 if ( IsShownOnScreen() != m_macCanvasIsShown )
419 {
420 m_macCanvasIsShown = !m_macCanvasIsShown;
421 MacUpdateView();
422 }
423
424 wxWindowMac::MacVisibilityChanged();
425}
426
427// ----------------------------------------------------------------------------
428// wxGLApp
429// ----------------------------------------------------------------------------
430
431bool wxGLApp::InitGLVisual(const int *attribList)
432{
433 AGLPixelFormat fmt = ChoosePixelFormat(attribList);
434 if ( !fmt )
435 return false;
436
437 aglDestroyPixelFormat(fmt);
438 return true;
439}
440
441#endif // wxUSE_GLCANVAS