]>
git.saurik.com Git - wxWidgets.git/blob - src/motif/glcanvas.cpp
1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxGLCanvas, for using OpenGL with wxWindows 2.0 for Motif.
4 // Uses the GLX extension.
5 // Author: Julian Smart and Wolfram Gloger
9 // Copyright: (c) Julian Smart, Wolfram Gloger
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
14 #pragma implementation "glcanvas.h"
21 #include "wx/glcanvas.h"
26 #include "wx/motif/private.h"
29 // workaround for bug in Mesa's glx.c
30 static int bitcount( unsigned long n
)
42 * GLCanvas implementation
45 IMPLEMENT_CLASS(wxGLCanvas
, wxScrolledWindow
)
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
)
52 XVisualInfo
*vi
, vi_templ
;
53 XWindowAttributes xwa
;
56 Display
* display
= (Display
*) GetXDisplay();
59 // Check for the presence of the GLX extension
60 if(!glXQueryExtension(display
, NULL
, NULL
)) {
61 wxDebugMsg("wxGLCanvas: GLX extension is missing\n");
66 int data
[512], arg
=0, p
=0;
68 while( (attribList
[arg
]!=0) && (p
<512) )
70 switch( attribList
[arg
++] )
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;
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;
82 data
[p
++]=GLX_RED_SIZE
; data
[p
++]=attribList
[arg
++]; break;
84 data
[p
++]=GLX_GREEN_SIZE
; data
[p
++]=attribList
[arg
++]; break;
86 data
[p
++]=GLX_BLUE_SIZE
; data
[p
++]=attribList
[arg
++]; break;
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;
107 attribList
= (int*) data
;
108 // Get an appropriate visual
109 vi
= glXChooseVisual(display
, DefaultScreen(display
), attribList
);
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.
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
);
122 glXGetConfig(display
, vi
, GLX_USE_GL
, &val
);
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.
128 // Construct an attribute list matching the visual
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
;
142 } else { // Color index visual
143 glXGetConfig(display
, vi
, GLX_BUFFER_SIZE
, &val
);
144 a_list
[n
++] = GLX_BUFFER_SIZE
;
149 vi
= glXChooseVisual(display
, DefaultScreen(display
), a_list
);
151 #endif /* OLD_MESA */
154 // Create the GLX context and make it current
155 glx_cx
= glXCreateContext(display
, vi
, 0, GL_TRUE
);
162 wxGLCanvas::~wxGLCanvas(void)
164 Display
* display
= (Display
*) GetXDisplay();
165 if(glx_cx
) glXDestroyContext(display
, glx_cx
);
168 void wxGLCanvas::SwapBuffers()
170 Display
* display
= (Display
*) GetXDisplay();
171 if(glx_cx
) glXSwapBuffers(display
, (Window
) GetXWindow());
174 void wxGLCanvas::SetCurrent()
176 Display
* display
= (Display
*) GetXDisplay();
177 if(glx_cx
) glXMakeCurrent(display
, (Window
) GetXWindow(), glx_cx
);
180 void wxGLCanvas::SetColour(const char *col
)
182 wxColour
*the_colour
= wxTheColourDatabase
->FindColour(col
);
185 glGetBooleanv(GL_RGBA_MODE
, &b
);
187 glColor3ub(the_colour
->Red(),
191 GLint pix
= (GLint
)the_colour
->m_pixel
;
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");
202 pix
= the_colour
->m_pixel
= exact_def
.pixel
;