]>
git.saurik.com Git - wxWidgets.git/blob - src/x11/glcanvas.cpp
   1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxGLCanvas, for using OpenGL with wxWidgets 
   4 //              Uses the GLX extension. 
   5 // Author:      Julian Smart and Wolfram Gloger 
   9 // Copyright:   (c) Julian Smart, Wolfram Gloger 
  10 // Licence:     wxWindows licence 
  11 ///////////////////////////////////////////////////////////////////////////// 
  13 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  14 #pragma implementation "glcanvas.h" 
  21 #include "wx/glcanvas.h" 
  27 # pragma message disable nosimpint 
  31 # pragma message enable nosimpint 
  33 #include "wx/x11/private.h" 
  35 // DLL options compatibility check: 
  37 WX_CHECK_BUILD_OPTIONS("wxGL") 
  39 static inline WXWindow 
wxGetClientAreaWindow(wxWindow
* win
) 
  42     return win
->GetClientXWindow(); 
  44     return win
->GetClientAreaWindow(); 
  49 // workaround for bug in Mesa's glx.c 
  50 static int bitcount( unsigned long n 
) 
  62  * GLContext implementation 
  65 IMPLEMENT_CLASS(wxGLContext
,wxObject
) 
  67 wxGLContext::wxGLContext( bool WXUNUSED(isRGB
), wxWindow 
*win
,  
  68                           const wxPalette
& WXUNUSED(palette
) ) 
  71     // m_widget = win->m_wxwindow; 
  73     wxGLCanvas 
*gc 
= (wxGLCanvas
*) win
; 
  74     XVisualInfo 
*vi 
= (XVisualInfo 
*) gc
->m_vi
; 
  76     wxCHECK_RET( vi
, wxT("invalid visual for OpenGL") ); 
  78     m_glContext 
= glXCreateContext( (Display 
*)wxGetDisplay(), vi
, 
  81     wxCHECK_RET( m_glContext
, wxT("Couldn't create OpenGL context") ); 
  84 wxGLContext::wxGLContext(  
  85                bool WXUNUSED(isRGB
), wxWindow 
*win
,  
  86                const wxPalette
& WXUNUSED(palette
), 
  87                const wxGLContext 
*other        
/* for sharing display lists */ 
  91     // m_widget = win->m_wxwindow; 
  93     wxGLCanvas 
*gc 
= (wxGLCanvas
*) win
; 
  94     XVisualInfo 
*vi 
= (XVisualInfo 
*) gc
->m_vi
; 
  96     wxCHECK_RET( vi
, wxT("invalid visual for OpenGL") ); 
  99         m_glContext 
= glXCreateContext( (Display 
*)wxGetDisplay(), vi
,  
 100                                         other
->m_glContext
, GL_TRUE 
); 
 102         m_glContext 
= glXCreateContext( (Display 
*)wxGetDisplay(), vi
, 
 105     wxCHECK_RET( m_glContext
, wxT("Couldn't create OpenGL context") ); 
 108 wxGLContext::~wxGLContext() 
 110     if (!m_glContext
) return; 
 112     if (m_glContext 
== glXGetCurrentContext()) 
 114         glXMakeCurrent( (Display
*) wxGetDisplay(), None
, NULL
); 
 117     glXDestroyContext( (Display
*) wxGetDisplay(), m_glContext 
); 
 120 void wxGLContext::SwapBuffers() 
 124         Display
* display 
= (Display
*) wxGetDisplay(); 
 125         glXSwapBuffers(display
, (Window
) wxGetClientAreaWindow(m_window
)); 
 129 void wxGLContext::SetCurrent() 
 133         Display
* display 
= (Display
*) wxGetDisplay(); 
 134         glXMakeCurrent(display
, (Window
) wxGetClientAreaWindow(m_window
),  
 139 void wxGLContext::SetColour(const wxChar 
*colour
) 
 141     wxColour the_colour 
= wxTheColourDatabase
->Find(colour
); 
 145         glGetBooleanv(GL_RGBA_MODE
, &b
); 
 148             glColor3ub(the_colour
.Red(), 
 155             the_colour
.AllocColour(m_window
->GetXDisplay()); 
 157             the_colour
.CalcPixel(wxTheApp
->GetMainColormap(wxGetDisplay())); 
 159             GLint pix 
= (GLint
)the_colour
.GetPixel(); 
 162                 wxLogError(wxT("wxGLCanvas: cannot allocate color\n")); 
 170 void wxGLContext::SetupPixelFormat() 
 174 void wxGLContext::SetupPalette( const wxPalette
& WXUNUSED(palette
) ) 
 178 wxPalette 
wxGLContext::CreateDefaultPalette() 
 180     return wxNullPalette
; 
 187  * GLCanvas implementation 
 190 IMPLEMENT_CLASS(wxGLCanvas
, wxScrolledWindow
) 
 192 BEGIN_EVENT_TABLE(wxGLCanvas
, wxScrolledWindow
) 
 193 //    EVT_SIZE(wxGLCanvas::OnSize) 
 197 wxGLCanvas::wxGLCanvas( wxWindow 
*parent
, wxWindowID id
, 
 198                         const wxPoint
& pos
, const wxSize
& size
,  
 199                         long style
, const wxString
& name
, 
 201                         const wxPalette
& palette 
) 
 202 : wxScrolledWindow(parent
, id
, pos
, size
, style
, name
) 
 204     Create( parent
, NULL
, NULL
, id
, pos
, size
, style
, name
, attribList
, palette 
); 
 207 wxGLCanvas::wxGLCanvas( wxWindow 
*parent
,  
 208                         const wxGLContext 
*shared
, 
 210                         const wxPoint
& pos
, const wxSize
& size
,  
 211                         long style
, const wxString
& name
, 
 213                         const wxPalette
& palette 
) 
 214 : wxScrolledWindow(parent
, id
, pos
, size
, style
, name
) 
 216     Create( parent
, shared
, NULL
, id
, pos
, size
, style
, name
, attribList
, palette 
); 
 219 wxGLCanvas::wxGLCanvas( wxWindow 
*parent
,  
 220                         const wxGLCanvas 
*shared
, 
 222                         const wxPoint
& pos
, const wxSize
& size
,  
 223                         long style
, const wxString
& name
, 
 225                         const wxPalette
& palette 
) 
 226 : wxScrolledWindow(parent
, id
, pos
, size
, style
, name
) 
 228     Create( parent
, NULL
, shared
, id
, pos
, size
, style
, name
, attribList
, palette 
); 
 233 bool wxGLCanvas::Create(wxWindow *parent, 
 234   const wxGLContext *shared, const wxGLCanvas *shared_context_of, 
 235   wxWindowID id = -1, const wxPoint& pos, 
 236   const wxSize& size, long style,  
 237   const wxString& name, int *attribList, const wxPalette& palette): 
 238     wxScrolledWindow(parent, id, pos, size, style, name) 
 241 bool wxGLCanvas::Create( wxWindow 
*parent
,  
 242                          const wxGLContext 
*shared
, 
 243                          const wxGLCanvas 
*shared_context_of
, 
 245                          const wxPoint
& pos
, const wxSize
& size
,  
 246                          long style
, const wxString
& name
, 
 248                          const wxPalette
& palette
) 
 250     XVisualInfo 
*vi
, vi_templ
; 
 251     XWindowAttributes xwa
; 
 254     m_sharedContext 
= (wxGLContext
*)shared
;  // const_cast 
 255     m_sharedContextOf 
= (wxGLCanvas
*)shared_context_of
;  // const_cast 
 256     m_glContext 
= (wxGLContext
*) NULL
; 
 258     Display
* display 
= (Display
*) wxGetDisplay(); 
 260     // Check for the presence of the GLX extension 
 261     if(!glXQueryExtension(display
, NULL
, NULL
)) { 
 262         wxLogDebug(wxT("wxGLCanvas: GLX extension is missing\n")); 
 267       int data
[512], arg
=0, p
=0; 
 269       while( (attribList
[arg
]!=0) && (p
<512) ) 
 271         switch( attribList
[arg
++] ) 
 273           case WX_GL_RGBA
: data
[p
++] = GLX_RGBA
; break; 
 274           case WX_GL_BUFFER_SIZE
: 
 275             data
[p
++]=GLX_BUFFER_SIZE
; data
[p
++]=attribList
[arg
++]; break; 
 277             data
[p
++]=GLX_LEVEL
; data
[p
++]=attribList
[arg
++]; break; 
 278           case WX_GL_DOUBLEBUFFER
: data
[p
++] = GLX_DOUBLEBUFFER
; break; 
 279           case WX_GL_STEREO
: data
[p
++] = GLX_STEREO
; break; 
 280           case WX_GL_AUX_BUFFERS
: 
 281             data
[p
++]=GLX_AUX_BUFFERS
; data
[p
++]=attribList
[arg
++]; break; 
 283             data
[p
++]=GLX_RED_SIZE
; data
[p
++]=attribList
[arg
++]; break; 
 284           case WX_GL_MIN_GREEN
: 
 285             data
[p
++]=GLX_GREEN_SIZE
; data
[p
++]=attribList
[arg
++]; break; 
 287             data
[p
++]=GLX_BLUE_SIZE
; data
[p
++]=attribList
[arg
++]; break; 
 288           case WX_GL_MIN_ALPHA
: 
 289             data
[p
++]=GLX_ALPHA_SIZE
; data
[p
++]=attribList
[arg
++]; break; 
 290           case WX_GL_DEPTH_SIZE
:  
 291             data
[p
++]=GLX_DEPTH_SIZE
; data
[p
++]=attribList
[arg
++]; break; 
 292           case WX_GL_STENCIL_SIZE
:  
 293             data
[p
++]=GLX_STENCIL_SIZE
; data
[p
++]=attribList
[arg
++]; break; 
 294           case WX_GL_MIN_ACCUM_RED
: 
 295             data
[p
++]=GLX_ACCUM_RED_SIZE
; data
[p
++]=attribList
[arg
++]; break; 
 296           case WX_GL_MIN_ACCUM_GREEN
: 
 297             data
[p
++]=GLX_ACCUM_GREEN_SIZE
; data
[p
++]=attribList
[arg
++]; break; 
 298           case WX_GL_MIN_ACCUM_BLUE
: 
 299             data
[p
++]=GLX_ACCUM_BLUE_SIZE
; data
[p
++]=attribList
[arg
++]; break; 
 300           case WX_GL_MIN_ACCUM_ALPHA
: 
 301             data
[p
++]=GLX_ACCUM_ALPHA_SIZE
; data
[p
++]=attribList
[arg
++]; break; 
 308       attribList 
= (int*) data
; 
 309       // Get an appropriate visual 
 310       vi 
= glXChooseVisual(display
, DefaultScreen(display
), attribList
); 
 311       if(!vi
) return FALSE
; 
 313       // Here we should make sure that vi is the same visual as the 
 314       // one used by the xwindow drawable in wxCanvas.  However, 
 315       // there is currently no mechanism for this in wx_canvs.cc. 
 317         // By default, we use the visual of xwindow 
 318         // NI: is this really senseful ? opengl in e.g. color index mode ? 
 319         XGetWindowAttributes(display
, (Window
)wxGetClientAreaWindow(this), &xwa
); 
 320         vi_templ
.visualid 
= XVisualIDFromVisual(xwa
.visual
); 
 321         vi 
= XGetVisualInfo(display
, VisualIDMask
, &vi_templ
, &n
); 
 322         if(!vi
) return FALSE
; 
 323         glXGetConfig(display
, vi
, GLX_USE_GL
, &val
); 
 324         if(!val
) return FALSE
; 
 325         // Basically, this is it.  It should be possible to use vi 
 326         // in glXCreateContext() below.  But this fails with Mesa. 
 327         // I notified the Mesa author about it; there may be a fix. 
 329         // Construct an attribute list matching the visual 
 332         if(vi
->c_class
==TrueColor 
|| vi
->c_class
==DirectColor
) { // RGBA visual 
 333             a_list
[n
++] = GLX_RGBA
; 
 334             a_list
[n
++] = GLX_RED_SIZE
; 
 335             a_list
[n
++] = bitcount(vi
->red_mask
); 
 336             a_list
[n
++] = GLX_GREEN_SIZE
; 
 337             a_list
[n
++] = bitcount(vi
->green_mask
); 
 338             a_list
[n
++] = GLX_BLUE_SIZE
; 
 339             a_list
[n
++] = bitcount(vi
->blue_mask
); 
 340             glXGetConfig(display
, vi
, GLX_ALPHA_SIZE
, &val
); 
 341             a_list
[n
++] = GLX_ALPHA_SIZE
; 
 343         } else { // Color index visual 
 344             glXGetConfig(display
, vi
, GLX_BUFFER_SIZE
, &val
); 
 345             a_list
[n
++] = GLX_BUFFER_SIZE
; 
 350         vi 
= glXChooseVisual(display
, DefaultScreen(display
), a_list
); 
 351         if(!vi
) return FALSE
; 
 352 #endif /* OLD_MESA */ 
 355     m_vi 
= vi
;  // safe for later use 
 357     wxCHECK_MSG( m_vi
, FALSE
, wxT("required visual couldn't be found") ); 
 359     // Create the GLX context and make it current 
 361     wxGLContext 
*share
= m_sharedContext
; 
 362     if (share
==NULL 
&& m_sharedContextOf
)  
 363         share 
= m_sharedContextOf
->GetContext(); 
 365     m_glContext 
= new wxGLContext( TRUE
, this, wxNullPalette
, share 
); 
 375 wxGLCanvas::~wxGLCanvas(void) 
 377     XVisualInfo 
*vi 
= (XVisualInfo 
*) m_vi
; 
 380     if (m_glContext
) delete m_glContext
; 
 382     // Display* display = (Display*) GetXDisplay(); 
 383     // if(glx_cx) glXDestroyContext(display, glx_cx); 
 386 void wxGLCanvas::SwapBuffers() 
 388     if( m_glContext 
) m_glContext
->SwapBuffers(); 
 390     // Display* display = (Display*) GetXDisplay(); 
 391     // if(glx_cx) glXSwapBuffers(display, (Window) GetClientAreaWindow()); 
 394 void wxGLCanvas::SetCurrent() 
 396     if( m_glContext 
) m_glContext
->SetCurrent(); 
 398     // Display* display = (Display*) GetXDisplay(); 
 399     // if(glx_cx) glXMakeCurrent(display, (Window) GetClientAreaWindow(), glx_cx); 
 402 void wxGLCanvas::SetColour(const wxChar 
*col
) 
 404     if( m_glContext 
) m_glContext
->SetColour(col
);