]> git.saurik.com Git - wxWidgets.git/blob - src/motif/glcanvas.cpp
0c1f9780d2c76c365fb6e1d8d4d2a64a6de23e14
[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,
48 wxWindowID id,
49 const wxPoint& pos,
50 const wxSize& size,
51 long style,
52 const wxString& name,
53 int *attrib_list, const wxPalette& palette)
54 : wxScrolledWindow(parent, id, pos, size, style, name)
55 {
56 XVisualInfo *vi, vi_templ;
57 XWindowAttributes xwa;
58 int val, n;
59
60 Display* display = (Display*) GetXDisplay();
61
62 glx_cx = 0;
63 // Check for the presence of the GLX extension
64 if(!glXQueryExtension(display, NULL, NULL)) {
65 wxDebugMsg("wxGLCanvas: GLX extension is missing\n");
66 return;
67 }
68
69 if(attrib_list) {
70 // Get an appropriate visual
71 vi = glXChooseVisual(display, DefaultScreen(display), attrib_list);
72 if(!vi) return;
73
74 // Here we should make sure that vi is the same visual as the
75 // one used by the xwindow drawable in wxCanvas. However,
76 // there is currently no mechanism for this in wx_canvs.cc.
77 } else {
78 // By default, we use the visual of xwindow
79 XGetWindowAttributes(display, (Window) GetXWindow(), &xwa);
80 vi_templ.visualid = XVisualIDFromVisual(xwa.visual);
81 vi = XGetVisualInfo(display, VisualIDMask, &vi_templ, &n);
82 if(!vi) return;
83 glXGetConfig(display, vi, GLX_USE_GL, &val);
84 if(!val) return;
85 // Basically, this is it. It should be possible to use vi
86 // in glXCreateContext() below. But this fails with Mesa.
87 // I notified the Mesa author about it; there may be a fix.
88 #ifdef OLD_MESA
89 // Construct an attribute list matching the visual
90 int a_list[32];
91 n = 0;
92 if(vi->c_class==TrueColor || vi->c_class==DirectColor) { // RGBA visual
93 a_list[n++] = GLX_RGBA;
94 a_list[n++] = GLX_RED_SIZE;
95 a_list[n++] = bitcount(vi->red_mask);
96 a_list[n++] = GLX_GREEN_SIZE;
97 a_list[n++] = bitcount(vi->green_mask);
98 a_list[n++] = GLX_BLUE_SIZE;
99 a_list[n++] = bitcount(vi->blue_mask);
100 glXGetConfig(display, vi, GLX_ALPHA_SIZE, &val);
101 a_list[n++] = GLX_ALPHA_SIZE;
102 a_list[n++] = val;
103 } else { // Color index visual
104 glXGetConfig(display, vi, GLX_BUFFER_SIZE, &val);
105 a_list[n++] = GLX_BUFFER_SIZE;
106 a_list[n++] = val;
107 }
108 a_list[n] = None;
109 XFree(vi);
110 vi = glXChooseVisual(display, DefaultScreen(display), a_list);
111 if(!vi) return;
112 #endif /* OLD_MESA */
113 }
114
115 // Create the GLX context and make it current
116 glx_cx = glXCreateContext(display, vi, 0, GL_TRUE);
117 #ifndef OLD_MESA
118 XFree(vi);
119 #endif
120 SetCurrent();
121 }
122
123 wxGLCanvas::~wxGLCanvas(void)
124 {
125 Display* display = (Display*) GetXDisplay();
126 if(glx_cx) glXDestroyContext(display, glx_cx);
127 }
128
129 void wxGLCanvas::SwapBuffers()
130 {
131 Display* display = (Display*) GetXDisplay();
132 if(glx_cx) glXSwapBuffers(display, (Window) GetXWindow());
133 }
134
135 void wxGLCanvas::SetCurrent()
136 {
137 Display* display = (Display*) GetXDisplay();
138 if(glx_cx) glXMakeCurrent(display, (Window) GetXWindow(), glx_cx);
139 }
140
141 void wxGLCanvas::SetColour(const char *col)
142 {
143 wxColour *the_colour = wxTheColourDatabase->FindColour(col);
144 if(the_colour) {
145 GLboolean b;
146 glGetBooleanv(GL_RGBA_MODE, &b);
147 if(b) {
148 glColor3ub(the_colour->Red(),
149 the_colour->Green(),
150 the_colour->Blue());
151 } else {
152 GLint pix = (GLint)the_colour->m_pixel;
153 if(pix == -1) {
154 XColor exact_def;
155 exact_def.red = (unsigned short)the_colour->Red() << 8;
156 exact_def.green = (unsigned short)the_colour->Green() << 8;
157 exact_def.blue = (unsigned short)the_colour->Blue() << 8;
158 exact_def.flags = DoRed | DoGreen | DoBlue;
159 if(!XAllocColor((Display*) GetXDisplay(), (Colormap) wxTheApp->GetMainColormap(GetXDisplay()), &exact_def)) {
160 wxDebugMsg("wxGLCanvas: cannot allocate color\n");
161 return;
162 }
163 pix = the_colour->m_pixel = exact_def.pixel;
164 }
165 glIndexi(pix);
166 }
167 }
168 }
169
170 #endif
171 // wxUSE_GLCANVAS
172