]> git.saurik.com Git - wxWidgets.git/blob - src/mac/glcanvas.cpp
improved memory liberation (explicitly set to NULL after delete)
[wxWidgets.git] / src / mac / glcanvas.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: glcanvas.cpp
3 // Purpose: wxGLCanvas, for using OpenGL with wxWindows under Macintosh
4 // Author: AUTHOR
5 // Modified by:
6 // Created: ??/??/98
7 // RCS-ID: $Id$
8 // Copyright: (c) AUTHOR
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "glcanvas.h"
14 #endif
15
16 #include "wx/wxprec.h"
17
18 #if defined(__BORLANDC__)
19 #pragma hdrstop
20 #endif
21
22 #include "wx/setup.h"
23
24 #if wxUSE_GLCANVAS
25
26 #ifndef WX_PRECOMP
27 #include "wx/frame.h"
28 #endif
29
30 #include "wx/settings.h"
31 #include "wx/log.h"
32
33 #include "wx/glcanvas.h"
34 #include "wx/mac/uma.h"
35
36 /*
37 * GLContext implementation
38 */
39
40 wxGLContext::wxGLContext(
41 AGLPixelFormat fmt, wxGLCanvas *win,
42 const wxPalette& palette,
43 const wxGLContext *other /* for sharing display lists */
44 )
45 {
46 m_window = win;
47
48 m_drawable = (AGLDrawable) UMAGetWindowPort(MAC_WXHWND(win->MacGetRootWindow()));
49
50 m_glContext = aglCreateContext(fmt, other ? other->m_glContext : NULL);
51 wxCHECK_RET( m_glContext, wxT("Couldn't create OpenGl context") );
52
53 GLboolean b;
54 b = aglSetDrawable(m_glContext, m_drawable);
55 wxCHECK_RET( b, wxT("Couldn't bind OpenGl context") );
56 aglEnable(m_glContext , AGL_BUFFER_RECT ) ;
57 b = aglSetCurrentContext(m_glContext);
58 wxCHECK_RET( b, wxT("Couldn't activate OpenGl context") );
59 }
60
61 wxGLContext::~wxGLContext()
62 {
63 if (m_glContext)
64 {
65 aglSetCurrentContext(NULL);
66 aglDestroyContext(m_glContext);
67 }
68 }
69
70 void wxGLContext::SwapBuffers()
71 {
72 if (m_glContext)
73 {
74 aglSwapBuffers(m_glContext);
75 }
76 }
77
78 void wxGLContext::SetCurrent()
79 {
80 if (m_glContext)
81 {
82 aglSetCurrentContext(m_glContext);
83 }
84 }
85
86 void wxGLContext::Update()
87 {
88 if (m_glContext)
89 {
90 aglUpdateContext(m_glContext);
91 }
92 }
93
94 void wxGLContext::SetColour(const char *colour)
95 {
96 float r = 0.0;
97 float g = 0.0;
98 float b = 0.0;
99 wxColour *col = wxTheColourDatabase->FindColour(colour);
100 if (col)
101 {
102 r = (float)(col->Red()/256.0);
103 g = (float)(col->Green()/256.0);
104 b = (float)(col->Blue()/256.0);
105 glColor3f( r, g, b);
106 }
107 }
108
109
110 /*
111 * wxGLCanvas implementation
112 */
113
114 IMPLEMENT_CLASS(wxGLCanvas, wxWindow)
115
116 BEGIN_EVENT_TABLE(wxGLCanvas, wxWindow)
117 EVT_SIZE(wxGLCanvas::OnSize)
118 END_EVENT_TABLE()
119
120 wxGLCanvas::wxGLCanvas(wxWindow *parent, wxWindowID id,
121 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
122 int *attribList, const wxPalette& palette)
123 {
124 Create(parent, NULL, id, pos, size, style, name, attribList, palette);
125 }
126
127 wxGLCanvas::wxGLCanvas( wxWindow *parent,
128 const wxGLContext *shared, wxWindowID id,
129 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
130 int *attribList, const wxPalette& palette )
131 {
132 Create(parent, shared, id, pos, size, style, name, attribList, palette);
133 }
134
135 wxGLCanvas::wxGLCanvas( wxWindow *parent, const wxGLCanvas *shared, wxWindowID id,
136 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
137 int *attribList, const wxPalette& palette )
138 {
139 Create(parent, shared ? shared->GetContext() : NULL, id, pos, size, style, name, attribList, palette);
140 }
141
142 wxGLCanvas::~wxGLCanvas()
143 {
144 if (m_glContext != NULL) {
145 delete m_glContext;
146 m_glContext = NULL;
147 }
148 }
149
150 static AGLPixelFormat ChoosePixelFormat(const int *attribList)
151 {
152 GLint data[512];
153 GLint defaultAttribs[] = { AGL_RGBA,
154 AGL_DOUBLEBUFFER,
155 AGL_MINIMUM_POLICY,
156 AGL_DEPTH_SIZE, 1, // use largest available depth buffer
157 AGL_RED_SIZE, 1,
158 AGL_GREEN_SIZE, 1,
159 AGL_BLUE_SIZE, 1,
160 AGL_ALPHA_SIZE, 0,
161 AGL_NONE };
162 GLint *attribs;
163 if (!attribList)
164 {
165 attribs = defaultAttribs;
166 }
167 else
168 {
169 int arg=0, p=0;
170
171 data[p++] = AGL_MINIMUM_POLICY; // make _SIZE tags behave more like GLX
172 while( (attribList[arg]!=0) && (p<512) )
173 {
174 switch( attribList[arg++] )
175 {
176 case WX_GL_RGBA: data[p++] = AGL_RGBA; break;
177 case WX_GL_BUFFER_SIZE:
178 data[p++]=AGL_BUFFER_SIZE; data[p++]=attribList[arg++]; break;
179 case WX_GL_LEVEL:
180 data[p++]=AGL_LEVEL; data[p++]=attribList[arg++]; break;
181 case WX_GL_DOUBLEBUFFER: data[p++] = AGL_DOUBLEBUFFER; break;
182 case WX_GL_STEREO: data[p++] = AGL_STEREO; break;
183 case WX_GL_AUX_BUFFERS:
184 data[p++]=AGL_AUX_BUFFERS; data[p++]=attribList[arg++]; break;
185 case WX_GL_MIN_RED:
186 data[p++]=AGL_RED_SIZE; data[p++]=attribList[arg++]; break;
187 case WX_GL_MIN_GREEN:
188 data[p++]=AGL_GREEN_SIZE; data[p++]=attribList[arg++]; break;
189 case WX_GL_MIN_BLUE:
190 data[p++]=AGL_BLUE_SIZE; data[p++]=attribList[arg++]; break;
191 case WX_GL_MIN_ALPHA:
192 data[p++]=AGL_ALPHA_SIZE; data[p++]=attribList[arg++]; break;
193 case WX_GL_DEPTH_SIZE:
194 data[p++]=AGL_DEPTH_SIZE; data[p++]=attribList[arg++]; break;
195 case WX_GL_STENCIL_SIZE:
196 data[p++]=AGL_STENCIL_SIZE; data[p++]=attribList[arg++]; break;
197 case WX_GL_MIN_ACCUM_RED:
198 data[p++]=AGL_ACCUM_RED_SIZE; data[p++]=attribList[arg++]; break;
199 case WX_GL_MIN_ACCUM_GREEN:
200 data[p++]=AGL_ACCUM_GREEN_SIZE; data[p++]=attribList[arg++]; break;
201 case WX_GL_MIN_ACCUM_BLUE:
202 data[p++]=AGL_ACCUM_BLUE_SIZE; data[p++]=attribList[arg++]; break;
203 case WX_GL_MIN_ACCUM_ALPHA:
204 data[p++]=AGL_ACCUM_ALPHA_SIZE; data[p++]=attribList[arg++]; break;
205 default:
206 break;
207 }
208 }
209 data[p] = 0;
210
211 attribs = data;
212 }
213
214 return aglChoosePixelFormat(NULL, 0, attribs);
215 }
216
217 bool wxGLCanvas::Create(wxWindow *parent, const wxGLContext *shared, wxWindowID id,
218 const wxPoint& pos, const wxSize& size, long style, const wxString& name,
219 int *attribList, const wxPalette& palette)
220 {
221 wxWindow::Create( parent, id, pos, size, style, name );
222
223 AGLPixelFormat fmt = ChoosePixelFormat(attribList);
224 wxCHECK_MSG( fmt, false, wxT("Couldn't create OpenGl pixel format") );
225
226 m_glContext = new wxGLContext(fmt, this, palette, shared);
227
228 aglDestroyPixelFormat(fmt);
229
230 return true;
231 }
232
233 void wxGLCanvas::SwapBuffers()
234 {
235 if (m_glContext)
236 m_glContext->SwapBuffers();
237 }
238
239 void wxGLCanvas::UpdateContext()
240 {
241 if (m_glContext)
242 m_glContext->Update();
243 }
244
245 void wxGLCanvas::SetViewport()
246 {
247 // viewport is initially set to entire port
248 // adjust glViewport to just this window
249 int x = 0 ;
250 int y = 0 ;
251
252 MacClientToRootWindow( &x , &y ) ;
253 int width, height;
254 GetClientSize(& width, & height);
255 Rect bounds ;
256 GetWindowPortBounds( MAC_WXHWND(MacGetRootWindow()) , &bounds ) ;
257 GLint parms[4] ;
258 parms[0] = x ;
259 parms[1] = bounds.bottom - bounds.top - ( y + height ) ;
260 parms[2] = width ;
261 parms[3] = height ;
262
263 aglSetInteger( m_glContext->m_glContext , AGL_BUFFER_RECT , parms ) ;
264 }
265
266 void wxGLCanvas::OnSize(wxSizeEvent& event)
267 {
268 MacUpdateView() ;
269 }
270
271 void wxGLCanvas::MacUpdateView()
272 {
273 if (m_glContext)
274 {
275 UpdateContext();
276 m_glContext->SetCurrent();
277 SetViewport();
278 }
279 }
280
281 void wxGLCanvas::MacSuperChangedPosition()
282 {
283 MacUpdateView() ;
284 wxWindow::MacSuperChangedPosition() ;
285 }
286
287 void wxGLCanvas::MacTopLevelWindowChangedPosition()
288 {
289 MacUpdateView() ;
290 wxWindow::MacTopLevelWindowChangedPosition() ;
291 }
292
293 void wxGLCanvas::SetCurrent()
294 {
295 if (m_glContext)
296 {
297 m_glContext->SetCurrent();
298 }
299 }
300
301 void wxGLCanvas::SetColour(const char *colour)
302 {
303 if (m_glContext)
304 m_glContext->SetColour(colour);
305 }
306
307
308 //---------------------------------------------------------------------------
309 // wxGLApp
310 //---------------------------------------------------------------------------
311
312 IMPLEMENT_CLASS(wxGLApp, wxApp)
313
314 bool wxGLApp::InitGLVisual(int *attribList)
315 {
316 AGLPixelFormat fmt = ChoosePixelFormat(attribList);
317 if (fmt != NULL) {
318 aglDestroyPixelFormat(fmt);
319 return true;
320 } else
321 return false;
322 }
323
324 wxGLApp::~wxGLApp(void)
325 {
326 }
327
328 #endif // wxUSE_GLCANVAS