]>
git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/glcanvas.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/carbon/glcanvas.cpp
3 // Purpose: wxGLCanvas, for using OpenGL with wxWidgets under Macintosh
4 // Author: Stefan Csomor
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 #include "wx/wxprec.h"
22 #if defined(__BORLANDC__)
28 #include "wx/glcanvas.h"
33 #include "wx/settings.h"
36 #include "wx/mac/uma.h"
38 #include "wx/mac/private.h"
40 // ----------------------------------------------------------------------------
42 // ----------------------------------------------------------------------------
44 static void wxLogAGLError(const char *func
)
46 const int err
= aglGetError();
48 wxLogError(_("OpenGL function \"%s\" failed: %s (error %d)"),
49 func
, aglErrorString(err
), err
);
52 // ============================================================================
54 // ============================================================================
56 // ----------------------------------------------------------------------------
58 // ----------------------------------------------------------------------------
60 wxGLContext::wxGLContext(wxGLCanvas
*win
, const wxGLContext
*other
)
62 m_aglContext
= aglCreateContext(win
->GetAGLPixelFormat(),
63 other
? other
->m_aglContext
: NULL
);
65 wxLogAGLError("aglCreateContext");
68 if ( !aglEnable(m_aglContext
, AGL_BUFFER_RECT
) )
69 wxLogAGLError("aglEnable(AGL_BUFFER_RECT)");
72 wxGLContext::~wxGLContext()
76 // it's ok to pass the current context to this function
77 if ( !aglDestroyContext(m_aglContext
) )
78 wxLogAGLError("aglDestroyContext");
82 void wxGLContext::SetCurrent(const wxGLCanvas
& win
) const
87 AGLDrawable drawable
= (AGLDrawable
)UMAGetWindowPort(
88 MAC_WXHWND(win
.MacGetTopLevelWindowRef()));
89 if ( !aglSetDrawable(m_aglContext
, drawable
) )
90 wxLogAGLError("aglSetDrawable");
92 if ( !aglSetCurrentContext(m_aglContext
) )
93 wxLogAGLError("aglSetCurrentContext");
95 wx_const_cast(wxGLCanvas
&, win
).SetViewport();
98 // ----------------------------------------------------------------------------
100 // ----------------------------------------------------------------------------
102 IMPLEMENT_CLASS(wxGLCanvas
, wxWindow
)
104 BEGIN_EVENT_TABLE(wxGLCanvas
, wxWindow
)
105 EVT_SIZE(wxGLCanvas::OnSize
)
108 wxGLCanvas::wxGLCanvas(wxWindow
*parent
,
110 const int *attribList
,
114 const wxString
& name
,
115 const wxPalette
& palette
)
117 Create(parent
, id
, pos
, size
, style
, name
, attribList
, palette
);
120 #if WXWIN_COMPATIBILITY_2_8
122 wxGLCanvas::wxGLCanvas(wxWindow
*parent
,
127 const wxString
& name
,
128 const int *attribList
,
129 const wxPalette
& palette
)
131 if ( Create(parent
, id
, pos
, size
, style
, name
, attribList
, palette
) )
132 m_glContext
= new wxGLContext(this);
135 wxGLCanvas::wxGLCanvas(wxWindow
*parent
,
136 const wxGLContext
*shared
,
141 const wxString
& name
,
142 const int *attribList
,
143 const wxPalette
& palette
)
145 if ( Create(parent
, id
, pos
, size
, style
, name
, attribList
, palette
) )
146 m_glContext
= new wxGLContext(this, shared
);
149 wxGLCanvas::wxGLCanvas(wxWindow
*parent
,
150 const wxGLCanvas
*shared
,
155 const wxString
& name
,
156 const int *attribList
,
157 const wxPalette
& palette
)
159 if ( Create(parent
, id
, pos
, size
, style
, name
, attribList
, palette
) )
160 m_glContext
= new wxGLContext(this, shared
? shared
->m_glContext
: NULL
);
163 #endif // WXWIN_COMPATIBILITY_2_8
165 static AGLPixelFormat
ChoosePixelFormat(const int *attribList
)
168 const GLint defaultAttribs
[] =
172 AGL_MINIMUM_POLICY
, // never choose less than requested
173 AGL_DEPTH_SIZE
, 1, // use largest available depth buffer
181 const GLint
*attribs
;
184 attribs
= defaultAttribs
;
189 data
[p
++] = AGL_MINIMUM_POLICY
; // make _SIZE tags behave more like GLX
191 for ( unsigned arg
= 0; attribList
[arg
] !=0 && p
< WXSIZEOF(data
); )
193 switch ( attribList
[arg
++] )
196 data
[p
++] = AGL_RGBA
;
199 case WX_GL_BUFFER_SIZE
:
200 data
[p
++] = AGL_BUFFER_SIZE
;
201 data
[p
++] = attribList
[arg
++];
206 data
[p
++]=attribList
[arg
++];
209 case WX_GL_DOUBLEBUFFER
:
210 data
[p
++] = AGL_DOUBLEBUFFER
;
214 data
[p
++] = AGL_STEREO
;
217 case WX_GL_AUX_BUFFERS
:
218 data
[p
++] = AGL_AUX_BUFFERS
;
219 data
[p
++] = attribList
[arg
++];
223 data
[p
++] = AGL_RED_SIZE
;
224 data
[p
++] = attribList
[arg
++];
227 case WX_GL_MIN_GREEN
:
228 data
[p
++] = AGL_GREEN_SIZE
;
229 data
[p
++] = attribList
[arg
++];
233 data
[p
++] = AGL_BLUE_SIZE
;
234 data
[p
++] = attribList
[arg
++];
237 case WX_GL_MIN_ALPHA
:
238 data
[p
++] = AGL_ALPHA_SIZE
;
239 data
[p
++] = attribList
[arg
++];
242 case WX_GL_DEPTH_SIZE
:
243 data
[p
++] = AGL_DEPTH_SIZE
;
244 data
[p
++] = attribList
[arg
++];
247 case WX_GL_STENCIL_SIZE
:
248 data
[p
++] = AGL_STENCIL_SIZE
;
249 data
[p
++] = attribList
[arg
++];
252 case WX_GL_MIN_ACCUM_RED
:
253 data
[p
++] = AGL_ACCUM_RED_SIZE
;
254 data
[p
++] = attribList
[arg
++];
257 case WX_GL_MIN_ACCUM_GREEN
:
258 data
[p
++] = AGL_ACCUM_GREEN_SIZE
;
259 data
[p
++] = attribList
[arg
++];
262 case WX_GL_MIN_ACCUM_BLUE
:
263 data
[p
++] = AGL_ACCUM_BLUE_SIZE
;
264 data
[p
++] = attribList
[arg
++];
267 case WX_GL_MIN_ACCUM_ALPHA
:
268 data
[p
++] = AGL_ACCUM_ALPHA_SIZE
;
269 data
[p
++] = attribList
[arg
++];
279 return aglChoosePixelFormat(NULL
, 0, attribs
);
282 bool wxGLCanvas::Create(wxWindow
*parent
,
287 const wxString
& name
,
288 const int *attribList
,
289 const wxPalette
& WXUNUSED(palette
))
291 m_needsUpdate
= false;
292 m_macCanvasIsShown
= false;
294 m_aglFormat
= ChoosePixelFormat(attribList
);
298 if ( !wxWindow::Create(parent
, id
, pos
, size
, style
, name
) )
301 m_macCanvasIsShown
= true;
306 wxGLCanvas::~wxGLCanvas()
309 aglDestroyPixelFormat(m_aglFormat
);
312 void wxGLCanvas::SwapBuffers()
314 AGLContext context
= aglGetCurrentContext();
315 wxCHECK_RET( context
, _T("should have current context") );
317 aglSwapBuffers(context
);
320 void wxGLCanvas::SetViewport()
322 if ( !m_needsUpdate
)
325 m_needsUpdate
= false;
327 AGLContext context
= aglGetCurrentContext();
331 // viewport is initially set to entire port, adjust it to just this window
334 MacClientToRootWindow(&x
, &y
);
337 GetClientSize(&width
, &height
);
340 GetWindowPortBounds(MAC_WXHWND(MacGetTopLevelWindowRef()) , &bounds
);
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
);
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
;
356 parms
[1] = bounds
.bottom
- bounds
.top
- ( y
+ height
);
361 // move the buffer rect out of sight if we're hidden
362 if ( !m_macCanvasIsShown
)
365 if ( !aglSetInteger(context
, AGL_BUFFER_RECT
, parms
) )
366 wxLogAGLError("aglSetInteger(AGL_BUFFER_RECT)");
368 if ( !aglUpdateContext(context
) )
369 wxLogAGLError("aglUpdateContext");
372 void wxGLCanvas::OnSize(wxSizeEvent
& event
)
378 void wxGLCanvas::MacUpdateView()
380 m_needsUpdate
= true;
384 void wxGLCanvas::MacSuperChangedPosition()
387 wxWindow::MacSuperChangedPosition();
390 void wxGLCanvas::MacTopLevelWindowChangedPosition()
393 wxWindow::MacTopLevelWindowChangedPosition();
396 void wxGLCanvas::MacVisibilityChanged()
398 if ( MacIsReallyShown() != m_macCanvasIsShown
)
400 m_macCanvasIsShown
= !m_macCanvasIsShown
;
404 wxWindowMac::MacVisibilityChanged();
407 // ----------------------------------------------------------------------------
409 // ----------------------------------------------------------------------------
411 bool wxGLApp::InitGLVisual(const int *attribList
)
413 AGLPixelFormat fmt
= ChoosePixelFormat(attribList
);
417 aglDestroyPixelFormat(fmt
);
421 #endif // wxUSE_GLCANVAS