Made wxGTK dataobj.cpp compile; removed flashing from wxGLCanvas samples;
[wxWidgets.git] / utils / glcanvas / motif / glcanvas.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: glcanvas.cpp
3 // Purpose: wxGLCanvas, for using OpenGL with wxWindows 2.0 for Motif.
4 // Uses the GLX extension.
5 // Author: Julian Smart and Wolfram Gloger
6 // Modified by:
7 // Created: 1995, 1999
8 // RCS-ID: $Id$
9 // Copyright: (c) Julian Smart, Wolfram Gloger
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
12
13 #ifdef __GNUG__
14 #pragma implementation "glcanvas.h"
15 #endif
16
17 #include "glcanvas.h"
18 #include "wx/utils.h"
19 #include "wx/app.h"
20
21 #include <Xm/Xm.h>
22 #include "wx/motif/private.h"
23
24 #ifdef OLD_MESA
25 // workaround for bug in Mesa's glx.c
26 static int bitcount( unsigned long n )
27 {
28 int bits;
29 for (bits=0; n>0;) {
30 if(n & 1) bits++;
31 n = n >> 1;
32 }
33 return bits;
34 }
35 #endif
36
37 /*
38 * GLCanvas implementation
39 */
40
41 IMPLEMENT_CLASS(wxGLCanvas, wxScrolledWindow)
42
43 wxGLCanvas::wxGLCanvas(wxWindow *parent, wxWindowID id = -1, const wxPoint& pos,
44 const wxSize& size, long style,
45 const wxString& name, int *attrib_list, const wxPalette& palette):
46 wxScrolledWindow(parent, id, pos, size, style, name)
47 {
48 XVisualInfo *vi, vi_templ;
49 XWindowAttributes xwa;
50 int val, n;
51
52 Display* display = (Display*) GetXDisplay();
53
54 glx_cx = 0;
55 // Check for the presence of the GLX extension
56 if(!glXQueryExtension(display, NULL, NULL)) {
57 wxDebugMsg("wxGLCanvas: GLX extension is missing\n");
58 return;
59 }
60
61 if(attrib_list) {
62 // Get an appropriate visual
63 vi = glXChooseVisual(display, DefaultScreen(display), attrib_list);
64 if(!vi) return;
65
66 // Here we should make sure that vi is the same visual as the
67 // one used by the xwindow drawable in wxCanvas. However,
68 // there is currently no mechanism for this in wx_canvs.cc.
69 } else {
70 // By default, we use the visual of xwindow
71 XGetWindowAttributes(display, (Window) GetXWindow(), &xwa);
72 vi_templ.visualid = XVisualIDFromVisual(xwa.visual);
73 vi = XGetVisualInfo(display, VisualIDMask, &vi_templ, &n);
74 if(!vi) return;
75 glXGetConfig(display, vi, GLX_USE_GL, &val);
76 if(!val) return;
77 // Basically, this is it. It should be possible to use vi
78 // in glXCreateContext() below. But this fails with Mesa.
79 // I notified the Mesa author about it; there may be a fix.
80 #ifdef OLD_MESA
81 // Construct an attribute list matching the visual
82 int a_list[32];
83 n = 0;
84 if(vi->c_class==TrueColor || vi->c_class==DirectColor) { // RGBA visual
85 a_list[n++] = GLX_RGBA;
86 a_list[n++] = GLX_RED_SIZE;
87 a_list[n++] = bitcount(vi->red_mask);
88 a_list[n++] = GLX_GREEN_SIZE;
89 a_list[n++] = bitcount(vi->green_mask);
90 a_list[n++] = GLX_BLUE_SIZE;
91 a_list[n++] = bitcount(vi->blue_mask);
92 glXGetConfig(display, vi, GLX_ALPHA_SIZE, &val);
93 a_list[n++] = GLX_ALPHA_SIZE;
94 a_list[n++] = val;
95 } else { // Color index visual
96 glXGetConfig(display, vi, GLX_BUFFER_SIZE, &val);
97 a_list[n++] = GLX_BUFFER_SIZE;
98 a_list[n++] = val;
99 }
100 a_list[n] = None;
101 XFree(vi);
102 vi = glXChooseVisual(display, DefaultScreen(display), a_list);
103 if(!vi) return;
104 #endif /* OLD_MESA */
105 }
106
107 // Create the GLX context and make it current
108 glx_cx = glXCreateContext(display, vi, 0, GL_TRUE);
109 #ifndef OLD_MESA
110 XFree(vi);
111 #endif
112 SetCurrent();
113 }
114
115 wxGLCanvas::~wxGLCanvas(void)
116 {
117 Display* display = (Display*) GetXDisplay();
118 if(glx_cx) glXDestroyContext(display, glx_cx);
119 }
120
121 void wxGLCanvas::SwapBuffers()
122 {
123 Display* display = (Display*) GetXDisplay();
124 if(glx_cx) glXSwapBuffers(display, (Window) GetXWindow());
125 }
126
127 void wxGLCanvas::SetCurrent()
128 {
129 Display* display = (Display*) GetXDisplay();
130 if(glx_cx) glXMakeCurrent(display, (Window) GetXWindow(), glx_cx);
131 }
132
133 void wxGLCanvas::SetColour(const char *col)
134 {
135 wxColour *the_colour = wxTheColourDatabase->FindColour(col);
136 if(the_colour) {
137 GLboolean b;
138 glGetBooleanv(GL_RGBA_MODE, &b);
139 if(b) {
140 glColor3ub(the_colour->Red(),
141 the_colour->Green(),
142 the_colour->Blue());
143 } else {
144 GLint pix = (GLint)the_colour->m_pixel;
145 if(pix == -1) {
146 XColor exact_def;
147 exact_def.red = (unsigned short)the_colour->Red() << 8;
148 exact_def.green = (unsigned short)the_colour->Green() << 8;
149 exact_def.blue = (unsigned short)the_colour->Blue() << 8;
150 exact_def.flags = DoRed | DoGreen | DoBlue;
151 if(!XAllocColor((Display*) GetXDisplay(), (Colormap) wxTheApp->GetMainColormap(GetXDisplay()), &exact_def)) {
152 wxDebugMsg("wxGLCanvas: cannot allocate color\n");
153 return;
154 }
155 pix = the_colour->m_pixel = exact_def.pixel;
156 }
157 glIndexi(pix);
158 }
159 }
160 }
161