]>
Commit | Line | Data |
---|---|---|
dc3065a5 | 1 | /////////////////////////////////////////////////////////////////////////////// |
521bf4ff | 2 | // Name: src/x11/glcanvas.cpp |
77ffb593 | 3 | // Purpose: wxGLCanvas, for using OpenGL with wxWidgets |
83df96d6 JS |
4 | // Uses the GLX extension. |
5 | // Author: Julian Smart and Wolfram Gloger | |
dc3065a5 | 6 | // Modified by: Vadim Zeitlin to update to new API |
83df96d6 JS |
7 | // Created: 1995, 1999 |
8 | // RCS-ID: $Id$ | |
9 | // Copyright: (c) Julian Smart, Wolfram Gloger | |
521bf4ff | 10 | // Licence: wxWindows licence |
dc3065a5 VZ |
11 | /////////////////////////////////////////////////////////////////////////////// |
12 | ||
13 | // TODO: merge this with wxGTK version in some src/unix/glcanvasx11.cpp | |
14 | ||
15 | // ============================================================================ | |
16 | // declarations | |
17 | // ============================================================================ | |
18 | ||
19 | // ---------------------------------------------------------------------------- | |
20 | // headers | |
21 | // ---------------------------------------------------------------------------- | |
83df96d6 | 22 | |
521bf4ff WS |
23 | // for compilers that support precompilation, includes "wx.h". |
24 | #include "wx/wxprec.h" | |
25 | ||
26 | #if defined(__BORLANDC__) | |
670f9935 | 27 | #pragma hdrstop |
521bf4ff | 28 | #endif |
83df96d6 JS |
29 | |
30 | #if wxUSE_GLCANVAS | |
31 | ||
32 | #include "wx/glcanvas.h" | |
e4db172a WS |
33 | |
34 | #ifndef WX_PRECOMP | |
35 | #include "wx/log.h" | |
670f9935 | 36 | #include "wx/app.h" |
de6185e2 | 37 | #include "wx/utils.h" |
e4db172a WS |
38 | #endif |
39 | ||
83df96d6 JS |
40 | #ifdef __VMS |
41 | # pragma message disable nosimpint | |
42 | #endif | |
1807c27d | 43 | #include <X11/Xlib.h> |
83df96d6 JS |
44 | #ifdef __VMS |
45 | # pragma message enable nosimpint | |
46 | #endif | |
1807c27d MB |
47 | #include "wx/x11/private.h" |
48 | ||
dc3065a5 VZ |
49 | // ---------------------------------------------------------------------------- |
50 | // local functions | |
51 | // ---------------------------------------------------------------------------- | |
34fdf762 | 52 | |
dc3065a5 | 53 | static inline Window wxGetClientAreaWindow(const wxWindow* win) |
1807c27d | 54 | { |
dc3065a5 | 55 | return (Window)win-> |
1807c27d | 56 | #ifdef __WXMOTIF__ |
dc3065a5 | 57 | GetClientXWindow(); |
1807c27d | 58 | #else |
dc3065a5 | 59 | GetClientAreaWindow(); |
1807c27d MB |
60 | #endif |
61 | } | |
83df96d6 | 62 | |
dc3065a5 VZ |
63 | // ============================================================================ |
64 | // implementation | |
65 | // ============================================================================ | |
83df96d6 | 66 | |
dc3065a5 VZ |
67 | // ---------------------------------------------------------------------------- |
68 | // wxGLContext | |
69 | // ---------------------------------------------------------------------------- | |
521bf4ff | 70 | |
dc3065a5 | 71 | IMPLEMENT_CLASS(wxGLContext, wxObject) |
83df96d6 | 72 | |
dc3065a5 | 73 | wxGLContext::wxGLContext(wxGLCanvas *win, const wxGLContext *other) |
83df96d6 | 74 | { |
dc3065a5 VZ |
75 | XVisualInfo *vi = (XVisualInfo *) win->m_vi; |
76 | wxASSERT_MSG( vi, wxT("invalid visual in wxGLCanvas") ); | |
83df96d6 | 77 | |
dc3065a5 VZ |
78 | m_glContext = glXCreateContext( (Display *)wxGetDisplay(), |
79 | vi, | |
80 | other ? other->m_glContext : None, | |
81 | GL_TRUE); | |
521bf4ff | 82 | |
dc3065a5 | 83 | wxASSERT_MSG( m_glContext, wxT("Couldn't create OpenGL context") ); |
83df96d6 JS |
84 | } |
85 | ||
86 | wxGLContext::~wxGLContext() | |
87 | { | |
dc3065a5 VZ |
88 | if (!m_glContext) |
89 | return; | |
521bf4ff | 90 | |
83df96d6 JS |
91 | if (m_glContext == glXGetCurrentContext()) |
92 | { | |
33980f0d | 93 | glXMakeCurrent( (Display*) wxGetDisplay(), None, NULL); |
83df96d6 | 94 | } |
521bf4ff | 95 | |
33980f0d | 96 | glXDestroyContext( (Display*) wxGetDisplay(), m_glContext ); |
83df96d6 JS |
97 | } |
98 | ||
dc3065a5 | 99 | void wxGLContext::SetCurrent(const wxGLCanvas& win) const |
83df96d6 JS |
100 | { |
101 | if (m_glContext) | |
102 | { | |
33980f0d | 103 | Display* display = (Display*) wxGetDisplay(); |
dc3065a5 | 104 | glXMakeCurrent(display, wxGetClientAreaWindow(&win), m_glContext); |
83df96d6 JS |
105 | } |
106 | } | |
107 | ||
dc3065a5 VZ |
108 | // ---------------------------------------------------------------------------- |
109 | // wxGLCanvas | |
110 | // ---------------------------------------------------------------------------- | |
83df96d6 | 111 | |
dc3065a5 | 112 | IMPLEMENT_CLASS(wxGLCanvas, wxWindow) |
83df96d6 | 113 | |
dc3065a5 VZ |
114 | wxGLCanvas::wxGLCanvas(wxWindow *parent, |
115 | wxWindowID id, | |
116 | const int *attribList, | |
117 | const wxPoint& pos, | |
118 | const wxSize& size, | |
119 | long style, | |
120 | const wxString& name, | |
121 | const wxPalette& palette) | |
83df96d6 | 122 | { |
dc3065a5 | 123 | Create(parent, id, pos, size, style, name, attribList, palette); |
83df96d6 JS |
124 | } |
125 | ||
dc3065a5 | 126 | bool wxGLCanvas::Create(wxWindow *parent, |
83df96d6 | 127 | wxWindowID id, |
dc3065a5 VZ |
128 | const wxPoint& pos, |
129 | const wxSize& size, | |
130 | long style, | |
131 | const wxString& name, | |
132 | const int *attribList, | |
133 | const wxPalette& palette) | |
521bf4ff | 134 | { |
dc3065a5 | 135 | m_vi = NULL; |
83df96d6 | 136 | |
dc3065a5 VZ |
137 | if ( !wxWindow::Create(parent, id, pos, size, style, name) ) |
138 | return false; | |
83df96d6 | 139 | |
83df96d6 JS |
140 | XVisualInfo *vi, vi_templ; |
141 | XWindowAttributes xwa; | |
142 | int val, n; | |
143 | ||
33980f0d | 144 | Display* display = (Display*) wxGetDisplay(); |
83df96d6 JS |
145 | |
146 | // Check for the presence of the GLX extension | |
521bf4ff WS |
147 | if(!glXQueryExtension(display, NULL, NULL)) |
148 | { | |
dc3065a5 | 149 | wxLogDebug(wxT("wxGLCanvas: GLX extension is missing")); |
521bf4ff | 150 | return false; |
83df96d6 JS |
151 | } |
152 | ||
153 | if(attribList) { | |
154 | int data[512], arg=0, p=0; | |
521bf4ff | 155 | |
83df96d6 JS |
156 | while( (attribList[arg]!=0) && (p<512) ) |
157 | { | |
158 | switch( attribList[arg++] ) | |
159 | { | |
160 | case WX_GL_RGBA: data[p++] = GLX_RGBA; break; | |
161 | case WX_GL_BUFFER_SIZE: | |
162 | data[p++]=GLX_BUFFER_SIZE; data[p++]=attribList[arg++]; break; | |
163 | case WX_GL_LEVEL: | |
164 | data[p++]=GLX_LEVEL; data[p++]=attribList[arg++]; break; | |
165 | case WX_GL_DOUBLEBUFFER: data[p++] = GLX_DOUBLEBUFFER; break; | |
166 | case WX_GL_STEREO: data[p++] = GLX_STEREO; break; | |
167 | case WX_GL_AUX_BUFFERS: | |
168 | data[p++]=GLX_AUX_BUFFERS; data[p++]=attribList[arg++]; break; | |
169 | case WX_GL_MIN_RED: | |
170 | data[p++]=GLX_RED_SIZE; data[p++]=attribList[arg++]; break; | |
171 | case WX_GL_MIN_GREEN: | |
172 | data[p++]=GLX_GREEN_SIZE; data[p++]=attribList[arg++]; break; | |
173 | case WX_GL_MIN_BLUE: | |
174 | data[p++]=GLX_BLUE_SIZE; data[p++]=attribList[arg++]; break; | |
175 | case WX_GL_MIN_ALPHA: | |
176 | data[p++]=GLX_ALPHA_SIZE; data[p++]=attribList[arg++]; break; | |
521bf4ff | 177 | case WX_GL_DEPTH_SIZE: |
83df96d6 | 178 | data[p++]=GLX_DEPTH_SIZE; data[p++]=attribList[arg++]; break; |
521bf4ff | 179 | case WX_GL_STENCIL_SIZE: |
83df96d6 JS |
180 | data[p++]=GLX_STENCIL_SIZE; data[p++]=attribList[arg++]; break; |
181 | case WX_GL_MIN_ACCUM_RED: | |
182 | data[p++]=GLX_ACCUM_RED_SIZE; data[p++]=attribList[arg++]; break; | |
183 | case WX_GL_MIN_ACCUM_GREEN: | |
184 | data[p++]=GLX_ACCUM_GREEN_SIZE; data[p++]=attribList[arg++]; break; | |
185 | case WX_GL_MIN_ACCUM_BLUE: | |
186 | data[p++]=GLX_ACCUM_BLUE_SIZE; data[p++]=attribList[arg++]; break; | |
187 | case WX_GL_MIN_ACCUM_ALPHA: | |
188 | data[p++]=GLX_ACCUM_ALPHA_SIZE; data[p++]=attribList[arg++]; break; | |
189 | default: | |
190 | break; | |
191 | } | |
521bf4ff WS |
192 | } |
193 | data[p] = 0; | |
83df96d6 | 194 | |
83df96d6 | 195 | // Get an appropriate visual |
dc3065a5 | 196 | vi = glXChooseVisual(display, DefaultScreen(display), data); |
670f9935 | 197 | if(!vi) return false; |
521bf4ff | 198 | |
83df96d6 JS |
199 | // Here we should make sure that vi is the same visual as the |
200 | // one used by the xwindow drawable in wxCanvas. However, | |
201 | // there is currently no mechanism for this in wx_canvs.cc. | |
dc3065a5 VZ |
202 | } |
203 | else // default attributes | |
204 | { | |
521bf4ff | 205 | // By default, we use the visual of xwindow |
dc3065a5 | 206 | XGetWindowAttributes(display, wxGetClientAreaWindow(this), &xwa); |
521bf4ff WS |
207 | vi_templ.visualid = XVisualIDFromVisual(xwa.visual); |
208 | vi = XGetVisualInfo(display, VisualIDMask, &vi_templ, &n); | |
670f9935 | 209 | if(!vi) return false; |
521bf4ff | 210 | glXGetConfig(display, vi, GLX_USE_GL, &val); |
670f9935 | 211 | if(!val) return false; |
83df96d6 JS |
212 | } |
213 | ||
214 | m_vi = vi; // safe for later use | |
521bf4ff | 215 | |
670f9935 | 216 | wxCHECK_MSG( m_vi, false, wxT("required visual couldn't be found") ); |
83df96d6 | 217 | |
521bf4ff | 218 | return true; |
83df96d6 JS |
219 | } |
220 | ||
dc3065a5 | 221 | wxGLCanvas::~wxGLCanvas() |
83df96d6 JS |
222 | { |
223 | XVisualInfo *vi = (XVisualInfo *) m_vi; | |
521bf4ff | 224 | |
dc3065a5 VZ |
225 | if (vi) |
226 | XFree( vi ); | |
83df96d6 JS |
227 | } |
228 | ||
229 | void wxGLCanvas::SwapBuffers() | |
230 | { | |
dc3065a5 | 231 | glXSwapBuffers((Display *)wxGetDisplay(), wxGetClientAreaWindow(this)); |
83df96d6 JS |
232 | } |
233 | ||
dc3065a5 | 234 | int wxGLCanvas::GetColourIndex(const wxColour& col_) |
83df96d6 | 235 | { |
dc3065a5 | 236 | wxColour& col = wx_const_cast(wxColour&, col_); |
83df96d6 | 237 | |
dc3065a5 VZ |
238 | #ifdef __WXMOTIF__ |
239 | col.AllocColour(GetXDisplay()); | |
240 | #else | |
241 | col.CalcPixel(wxTheApp->GetMainColormap(wxGetDisplay())); | |
242 | #endif | |
83df96d6 | 243 | |
dc3065a5 | 244 | return col.GetPixel(); |
83df96d6 JS |
245 | } |
246 | ||
dc3065a5 | 247 | #endif // wxUSE_GLCANVAS |