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