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