]> git.saurik.com Git - wxWidgets.git/blob - src/motif/glcanvas.cpp
Fix for bug where the cell highlight was not cleared from a cell
[wxWidgets.git] / src / 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 "wx/setup.h"
18
19 #if wxUSE_GLCANVAS
20
21 #include "wx/glcanvas.h"
22 #include "wx/utils.h"
23 #include "wx/app.h"
24
25 #include <Xm/Xm.h>
26 #include "wx/motif/private.h"
27
28 #ifdef OLD_MESA
29 // workaround for bug in Mesa's glx.c
30 static int bitcount( unsigned long n )
31 {
32 int bits;
33 for (bits=0; n>0;) {
34 if(n & 1) bits++;
35 n = n >> 1;
36 }
37 return bits;
38 }
39 #endif
40
41 /*
42 * GLCanvas implementation
43 */
44
45 IMPLEMENT_CLASS(wxGLCanvas, wxScrolledWindow)
46
47 wxGLCanvas::wxGLCanvas(wxWindow *parent, wxWindowID id = -1, const wxPoint& pos,
48 const wxSize& size, long style,
49 const wxString& name, int *attribList, const wxPalette& palette):
50 wxScrolledWindow(parent, id, pos, size, style, name)
51 {
52 XVisualInfo *vi, vi_templ;
53 XWindowAttributes xwa;
54 int val, n;
55
56 Display* display = (Display*) GetXDisplay();
57
58 glx_cx = 0;
59 // Check for the presence of the GLX extension
60 if(!glXQueryExtension(display, NULL, NULL)) {
61 wxDebugMsg("wxGLCanvas: GLX extension is missing\n");
62 return;
63 }
64
65 if(attribList) {
66 int data[512], arg=0, p=0;
67
68 while( (attribList[arg]!=0) && (p<512) )
69 {
70 switch( attribList[arg++] )
71 {
72 case WX_GL_RGBA: data[p++] = GLX_RGBA; break;
73 case WX_GL_BUFFER_SIZE:
74 data[p++]=GLX_BUFFER_SIZE; data[p++]=attribList[arg++]; break;
75 case WX_GL_LEVEL:
76 data[p++]=GLX_LEVEL; data[p++]=attribList[arg++]; break;
77 case WX_GL_DOUBLEBUFFER: data[p++] = GLX_DOUBLEBUFFER; break;
78 case WX_GL_STEREO: data[p++] = GLX_STEREO; break;
79 case WX_GL_AUX_BUFFERS:
80 data[p++]=GLX_AUX_BUFFERS; data[p++]=attribList[arg++]; break;
81 case WX_GL_MIN_RED:
82 data[p++]=GLX_RED_SIZE; data[p++]=attribList[arg++]; break;
83 case WX_GL_MIN_GREEN:
84 data[p++]=GLX_GREEN_SIZE; data[p++]=attribList[arg++]; break;
85 case WX_GL_MIN_BLUE:
86 data[p++]=GLX_BLUE_SIZE; data[p++]=attribList[arg++]; break;
87 case WX_GL_MIN_ALPHA:
88 data[p++]=GLX_ALPHA_SIZE; data[p++]=attribList[arg++]; break;
89 case WX_GL_DEPTH_SIZE:
90 data[p++]=GLX_DEPTH_SIZE; data[p++]=attribList[arg++]; break;
91 case WX_GL_STENCIL_SIZE:
92 data[p++]=GLX_STENCIL_SIZE; data[p++]=attribList[arg++]; break;
93 case WX_GL_MIN_ACCUM_RED:
94 data[p++]=GLX_ACCUM_RED_SIZE; data[p++]=attribList[arg++]; break;
95 case WX_GL_MIN_ACCUM_GREEN:
96 data[p++]=GLX_ACCUM_GREEN_SIZE; data[p++]=attribList[arg++]; break;
97 case WX_GL_MIN_ACCUM_BLUE:
98 data[p++]=GLX_ACCUM_BLUE_SIZE; data[p++]=attribList[arg++]; break;
99 case WX_GL_MIN_ACCUM_ALPHA:
100 data[p++]=GLX_ACCUM_ALPHA_SIZE; data[p++]=attribList[arg++]; break;
101 default:
102 break;
103 }
104 }
105 data[p] = 0;
106
107 attribList = (int*) data;
108 // Get an appropriate visual
109 vi = glXChooseVisual(display, DefaultScreen(display), attribList);
110 if(!vi) return;
111
112 // Here we should make sure that vi is the same visual as the
113 // one used by the xwindow drawable in wxCanvas. However,
114 // there is currently no mechanism for this in wx_canvs.cc.
115 } else {
116 // By default, we use the visual of xwindow
117 // NI: is this really senseful ? opengl in e.g. color index mode ?
118 XGetWindowAttributes(display, (Window) GetXWindow(), &xwa);
119 vi_templ.visualid = XVisualIDFromVisual(xwa.visual);
120 vi = XGetVisualInfo(display, VisualIDMask, &vi_templ, &n);
121 if(!vi) return;
122 glXGetConfig(display, vi, GLX_USE_GL, &val);
123 if(!val) return;
124 // Basically, this is it. It should be possible to use vi
125 // in glXCreateContext() below. But this fails with Mesa.
126 // I notified the Mesa author about it; there may be a fix.
127 #ifdef OLD_MESA
128 // Construct an attribute list matching the visual
129 int a_list[32];
130 n = 0;
131 if(vi->c_class==TrueColor || vi->c_class==DirectColor) { // RGBA visual
132 a_list[n++] = GLX_RGBA;
133 a_list[n++] = GLX_RED_SIZE;
134 a_list[n++] = bitcount(vi->red_mask);
135 a_list[n++] = GLX_GREEN_SIZE;
136 a_list[n++] = bitcount(vi->green_mask);
137 a_list[n++] = GLX_BLUE_SIZE;
138 a_list[n++] = bitcount(vi->blue_mask);
139 glXGetConfig(display, vi, GLX_ALPHA_SIZE, &val);
140 a_list[n++] = GLX_ALPHA_SIZE;
141 a_list[n++] = val;
142 } else { // Color index visual
143 glXGetConfig(display, vi, GLX_BUFFER_SIZE, &val);
144 a_list[n++] = GLX_BUFFER_SIZE;
145 a_list[n++] = val;
146 }
147 a_list[n] = None;
148 XFree(vi);
149 vi = glXChooseVisual(display, DefaultScreen(display), a_list);
150 if(!vi) return;
151 #endif /* OLD_MESA */
152 }
153
154 // Create the GLX context and make it current
155 glx_cx = glXCreateContext(display, vi, 0, GL_TRUE);
156 #ifndef OLD_MESA
157 XFree(vi);
158 #endif
159 SetCurrent();
160 }
161
162 wxGLCanvas::~wxGLCanvas(void)
163 {
164 Display* display = (Display*) GetXDisplay();
165 if(glx_cx) glXDestroyContext(display, glx_cx);
166 }
167
168 void wxGLCanvas::SwapBuffers()
169 {
170 Display* display = (Display*) GetXDisplay();
171 if(glx_cx) glXSwapBuffers(display, (Window) GetXWindow());
172 }
173
174 void wxGLCanvas::SetCurrent()
175 {
176 Display* display = (Display*) GetXDisplay();
177 if(glx_cx) glXMakeCurrent(display, (Window) GetXWindow(), glx_cx);
178 }
179
180 void wxGLCanvas::SetColour(const char *col)
181 {
182 wxColour *the_colour = wxTheColourDatabase->FindColour(col);
183 if(the_colour) {
184 GLboolean b;
185 glGetBooleanv(GL_RGBA_MODE, &b);
186 if(b) {
187 glColor3ub(the_colour->Red(),
188 the_colour->Green(),
189 the_colour->Blue());
190 } else {
191 GLint pix = (GLint)the_colour->m_pixel;
192 if(pix == -1) {
193 XColor exact_def;
194 exact_def.red = (unsigned short)the_colour->Red() << 8;
195 exact_def.green = (unsigned short)the_colour->Green() << 8;
196 exact_def.blue = (unsigned short)the_colour->Blue() << 8;
197 exact_def.flags = DoRed | DoGreen | DoBlue;
198 if(!XAllocColor((Display*) GetXDisplay(), (Colormap) wxTheApp->GetMainColormap(GetXDisplay()), &exact_def)) {
199 wxDebugMsg("wxGLCanvas: cannot allocate color\n");
200 return;
201 }
202 pix = the_colour->m_pixel = exact_def.pixel;
203 }
204 glIndexi(pix);
205 }
206 }
207 }
208
209 #endif
210 // wxUSE_GLCANVAS
211