]> git.saurik.com Git - wxWidgets.git/blame - src/motif/glcanvas.cpp
Applied the patch by Garrick Meeker
[wxWidgets.git] / src / motif / glcanvas.cpp
CommitLineData
8b089c5e
JS
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
f6bcfd97 10// Licence: wxWindows licence
8b089c5e
JS
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
30static int bitcount( unsigned long n )
31{
32 int bits;
33 for (bits=0; n>0;) {
f6bcfd97
BP
34 if(n & 1) bits++;
35 n = n >> 1;
8b089c5e
JS
36 }
37 return bits;
38}
39#endif
40
41/*
42 * GLCanvas implementation
43 */
44
45IMPLEMENT_CLASS(wxGLCanvas, wxScrolledWindow)
46
f6bcfd97
BP
47wxGLCanvas::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)
8b089c5e
JS
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)) {
f6bcfd97
BP
65 wxDebugMsg("wxGLCanvas: GLX extension is missing\n");
66 return;
8b089c5e
JS
67 }
68
69 if(attrib_list) {
f6bcfd97
BP
70 // Get an appropriate visual
71 vi = glXChooseVisual(display, DefaultScreen(display), attrib_list);
72 if(!vi) return;
8b089c5e 73
f6bcfd97
BP
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.
8b089c5e 77 } else {
f6bcfd97
BP
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.
8b089c5e 88#ifdef OLD_MESA
f6bcfd97
BP
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;
8b089c5e
JS
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
123wxGLCanvas::~wxGLCanvas(void)
124{
125 Display* display = (Display*) GetXDisplay();
126 if(glx_cx) glXDestroyContext(display, glx_cx);
127}
128
129void wxGLCanvas::SwapBuffers()
130{
131 Display* display = (Display*) GetXDisplay();
132 if(glx_cx) glXSwapBuffers(display, (Window) GetXWindow());
133}
134
135void wxGLCanvas::SetCurrent()
136{
137 Display* display = (Display*) GetXDisplay();
138 if(glx_cx) glXMakeCurrent(display, (Window) GetXWindow(), glx_cx);
139}
140
141void wxGLCanvas::SetColour(const char *col)
142{
143 wxColour *the_colour = wxTheColourDatabase->FindColour(col);
144 if(the_colour) {
f6bcfd97
BP
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 }
8b089c5e
JS
167 }
168}
169
170#endif
171 // wxUSE_GLCANVAS
172