///////////////////////////////////////////////////////////////////////////// // Name: glcanvas.cpp // Purpose: wxGLCanvas, for using OpenGL with wxWindows 2.0 for Motif. // Uses the GLX extension. // Author: Julian Smart and Wolfram Gloger // Modified by: // Created: 1995, 1999 // RCS-ID: $Id$ // Copyright: (c) Julian Smart, Wolfram Gloger // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #ifdef __GNUG__ #pragma implementation "glcanvas.h" #endif #include "glcanvas.h" #include "wx/utils.h" #include "wx/app.h" #include #include "wx/motif/private.h" #ifdef OLD_MESA // workaround for bug in Mesa's glx.c static int bitcount( unsigned long n ) { int bits; for (bits=0; n>0;) { if(n & 1) bits++; n = n >> 1; } return bits; } #endif /* * GLCanvas implementation */ IMPLEMENT_CLASS(wxGLCanvas, wxScrolledWindow) wxGLCanvas::wxGLCanvas(wxWindow *parent, wxWindowID id = -1, const wxPoint& pos, const wxSize& size, long style, const wxString& name, int *attrib_list, const wxPalette& palette): wxScrolledWindow(parent, id, pos, size, style, name) { XVisualInfo *vi, vi_templ; XWindowAttributes xwa; int val, n; Display* display = (Display*) GetXDisplay(); glx_cx = 0; // Check for the presence of the GLX extension if(!glXQueryExtension(display, NULL, NULL)) { wxDebugMsg("wxGLCanvas: GLX extension is missing\n"); return; } if(attrib_list) { // Get an appropriate visual vi = glXChooseVisual(display, DefaultScreen(display), attrib_list); if(!vi) return; // Here we should make sure that vi is the same visual as the // one used by the xwindow drawable in wxCanvas. However, // there is currently no mechanism for this in wx_canvs.cc. } else { // By default, we use the visual of xwindow XGetWindowAttributes(display, (Window) GetXWindow(), &xwa); vi_templ.visualid = XVisualIDFromVisual(xwa.visual); vi = XGetVisualInfo(display, VisualIDMask, &vi_templ, &n); if(!vi) return; glXGetConfig(display, vi, GLX_USE_GL, &val); if(!val) return; // Basically, this is it. It should be possible to use vi // in glXCreateContext() below. But this fails with Mesa. // I notified the Mesa author about it; there may be a fix. #ifdef OLD_MESA // Construct an attribute list matching the visual int a_list[32]; n = 0; if(vi->c_class==TrueColor || vi->c_class==DirectColor) { // RGBA visual a_list[n++] = GLX_RGBA; a_list[n++] = GLX_RED_SIZE; a_list[n++] = bitcount(vi->red_mask); a_list[n++] = GLX_GREEN_SIZE; a_list[n++] = bitcount(vi->green_mask); a_list[n++] = GLX_BLUE_SIZE; a_list[n++] = bitcount(vi->blue_mask); glXGetConfig(display, vi, GLX_ALPHA_SIZE, &val); a_list[n++] = GLX_ALPHA_SIZE; a_list[n++] = val; } else { // Color index visual glXGetConfig(display, vi, GLX_BUFFER_SIZE, &val); a_list[n++] = GLX_BUFFER_SIZE; a_list[n++] = val; } a_list[n] = None; XFree(vi); vi = glXChooseVisual(display, DefaultScreen(display), a_list); if(!vi) return; #endif /* OLD_MESA */ } // Create the GLX context and make it current glx_cx = glXCreateContext(display, vi, 0, GL_TRUE); #ifndef OLD_MESA XFree(vi); #endif SetCurrent(); } wxGLCanvas::~wxGLCanvas(void) { Display* display = (Display*) GetXDisplay(); if(glx_cx) glXDestroyContext(display, glx_cx); } void wxGLCanvas::SwapBuffers() { Display* display = (Display*) GetXDisplay(); if(glx_cx) glXSwapBuffers(display, (Window) GetXWindow()); } void wxGLCanvas::SetCurrent() { Display* display = (Display*) GetXDisplay(); if(glx_cx) glXMakeCurrent(display, (Window) GetXWindow(), glx_cx); } void wxGLCanvas::SetColour(const char *col) { wxColour *the_colour = wxTheColourDatabase->FindColour(col); if(the_colour) { GLboolean b; glGetBooleanv(GL_RGBA_MODE, &b); if(b) { glColor3ub(the_colour->Red(), the_colour->Green(), the_colour->Blue()); } else { GLint pix = (GLint)the_colour->m_pixel; if(pix == -1) { XColor exact_def; exact_def.red = (unsigned short)the_colour->Red() << 8; exact_def.green = (unsigned short)the_colour->Green() << 8; exact_def.blue = (unsigned short)the_colour->Blue() << 8; exact_def.flags = DoRed | DoGreen | DoBlue; if(!XAllocColor((Display*) GetXDisplay(), (Colormap) wxTheApp->GetMainColormap(GetXDisplay()), &exact_def)) { wxDebugMsg("wxGLCanvas: cannot allocate color\n"); return; } pix = the_colour->m_pixel = exact_def.pixel; } glIndexi(pix); } } }