]> git.saurik.com Git - wxWidgets.git/blobdiff - utils/glcanvas/motif/glcanvas.cpp
Made wxGTK dataobj.cpp compile; removed flashing from wxGLCanvas samples;
[wxWidgets.git] / utils / glcanvas / motif / glcanvas.cpp
diff --git a/utils/glcanvas/motif/glcanvas.cpp b/utils/glcanvas/motif/glcanvas.cpp
new file mode 100644 (file)
index 0000000..0933fb7
--- /dev/null
@@ -0,0 +1,161 @@
+/////////////////////////////////////////////////////////////////////////////
+// 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 <Xm/Xm.h>
+#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);
+       }
+    }
+}
+