tomwalters@397
|
1 // Copyright 2006, Willem van Engen
|
tomwalters@397
|
2 //
|
tomwalters@397
|
3 // AIM-C: A C++ implementation of the Auditory Image Model
|
tomwalters@397
|
4 // http://www.acousticscale.org/AIMC
|
tomwalters@397
|
5 //
|
tomwalters@397
|
6 // Licensed under the Apache License, Version 2.0 (the "License");
|
tomwalters@397
|
7 // you may not use this file except in compliance with the License.
|
tomwalters@397
|
8 // You may obtain a copy of the License at
|
tomwalters@397
|
9 //
|
tomwalters@397
|
10 // http://www.apache.org/licenses/LICENSE-2.0
|
tomwalters@397
|
11 //
|
tomwalters@397
|
12 // Unless required by applicable law or agreed to in writing, software
|
tomwalters@397
|
13 // distributed under the License is distributed on an "AS IS" BASIS,
|
tomwalters@397
|
14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
tomwalters@397
|
15 // See the License for the specific language governing permissions and
|
tomwalters@397
|
16 // limitations under the License.
|
tomwalters@397
|
17
|
tomwalters@397
|
18 /*!
|
tomwalters@397
|
19 * \file
|
tomwalters@397
|
20 * \brief Output device for output to a wxWidgets OpenGL canvas
|
tomwalters@397
|
21 *
|
tomwalters@397
|
22 * \author Willem van Engen <cnbh@willem.engen.nl>
|
tomwalters@397
|
23 * \date created 2006/09/21
|
tomwalters@397
|
24 * \version \$Id: $
|
tomwalters@397
|
25 */
|
tomwalters@397
|
26
|
tomwalters@397
|
27 #include "Support/Common.h"
|
tomwalters@397
|
28
|
tomwalters@397
|
29 /*! \class GraphicsOutputDevicewxGLCanvas
|
tomwalters@397
|
30 *
|
tomwalters@397
|
31 * Graphics output takes a large part of the application's performance at the
|
tomwalters@397
|
32 * moment when it is inline with the Process() loop. Much is gained by
|
tomwalters@397
|
33 * putting it in a separate thread, which can be done using ShotTargetThreaded.
|
tomwalters@397
|
34 *
|
tomwalters@397
|
35 * OpenGL-related documents:
|
tomwalters@397
|
36 * - http://www.opengl.org/
|
tomwalters@397
|
37 * - http://www.sgi.com/products/software/opengl/
|
tomwalters@397
|
38 * - http://developer.apple.com/graphicsimaging/opengl/
|
tomwalters@397
|
39 * - http://developer.nvidia.com/page/documentation.html
|
tomwalters@397
|
40 * - Vertex arrays
|
tomwalters@397
|
41 * - http://www.opengl.org/registry/specs/EXT/vertex_array.txt
|
tomwalters@397
|
42 * - http://www.awprofessional.com/articles/article.asp?p=461848&seqNum=2&rl=1
|
tomwalters@397
|
43 * - http://jdobry.webpark.cz/opengl/opengl_maximum_performance.html
|
tomwalters@397
|
44 * - Fonts and OpenGL
|
tomwalters@397
|
45 * - http://gltt.sourceforge.net/
|
tomwalters@397
|
46 */
|
tomwalters@397
|
47
|
tomwalters@397
|
48 // And finally our own
|
tomwalters@397
|
49 #include "Support/util.h"
|
tomwalters@397
|
50 #include "Output/GraphicsOutputDevice.h"
|
tomwalters@397
|
51 #include "Output/GraphicsOutputDevicewxGLCanvas.h"
|
tomwalters@397
|
52
|
tomwalters@397
|
53 BEGIN_EVENT_TABLE(GraphicsOutputDevicewxGLCanvas, wxGLCanvas)
|
tomwalters@397
|
54 EVT_SIZE(GraphicsOutputDevicewxGLCanvas::OnSize)
|
tomwalters@397
|
55 EVT_PAINT(GraphicsOutputDevicewxGLCanvas::OnPaint)
|
tomwalters@397
|
56 EVT_ERASE_BACKGROUND(GraphicsOutputDevicewxGLCanvas::OnEraseBackground)
|
tomwalters@397
|
57 END_EVENT_TABLE()
|
tomwalters@397
|
58
|
tomwalters@397
|
59 // wxGLCanvas attributes
|
tomwalters@397
|
60 int GraphicsOutputDevicewxGLCanvas::GLAttrlist[] = {
|
tomwalters@397
|
61 WX_GL_RGBA, 1,
|
tomwalters@397
|
62 WX_GL_DOUBLEBUFFER, 1,
|
tomwalters@397
|
63 WX_GL_MIN_RED, 5,
|
tomwalters@397
|
64 WX_GL_MIN_GREEN, 5,
|
tomwalters@397
|
65 WX_GL_MIN_BLUE, 5,
|
tomwalters@397
|
66 WX_GL_MIN_ALPHA, 3,
|
tomwalters@397
|
67 WX_GL_DEPTH_SIZE, 16,
|
tomwalters@397
|
68 0
|
tomwalters@397
|
69 };
|
tomwalters@397
|
70
|
tomwalters@397
|
71 // OpenGL get procaddress function pointer, differs across platforms
|
tomwalters@397
|
72 typedef void (*(*glGetProcAddressPtr_t)(const char*))();
|
tomwalters@397
|
73
|
tomwalters@397
|
74 GraphicsOutputDevicewxGLCanvas::GraphicsOutputDevicewxGLCanvas(Parameters *pParam,
|
tomwalters@398
|
75 wxWindow *parent,
|
tomwalters@397
|
76 wxWindowID id,
|
tomwalters@397
|
77 const wxPoint& pos,
|
tomwalters@397
|
78 const wxSize& size,
|
tomwalters@397
|
79 long style,
|
tomwalters@397
|
80 const wxString& name)
|
tomwalters@398
|
81 : wxGLCanvas(parent, (wxGLCanvas*) NULL, id, pos, size,
|
tomwalters@397
|
82 style|wxFULL_REPAINT_ON_RESIZE, name, GLAttrlist),
|
tomwalters@398
|
83 GraphicsOutputDevice(pParam) {
|
tomwalters@398
|
84 m_init = false;
|
tomwalters@398
|
85 m_gllist = 0;
|
tomwalters@398
|
86 m_pWorkerContext = NULL;
|
tomwalters@398
|
87 m_bAntialiasing = true;
|
tomwalters@398
|
88 m_pFont = NULL;
|
tomwalters@398
|
89 m_sFontFile = NULL;
|
tomwalters@398
|
90 m_iFontsize = -1;
|
tomwalters@397
|
91 #if !defined(_MACOSX)
|
tomwalters@398
|
92 s_bWorkerNeedsInit = false;
|
tomwalters@397
|
93 #endif
|
tomwalters@397
|
94
|
tomwalters@397
|
95 #ifdef WITH_GL_VERTEX_ARRAYS
|
tomwalters@398
|
96 m_iVertexType = 0xffff; // no gBegin() has happened yet
|
tomwalters@398
|
97 m_bStaticColor = false;
|
tomwalters@398
|
98 m_pVertices = NULL;
|
tomwalters@398
|
99 m_iVerticesMax = 0;
|
tomwalters@398
|
100 // Enable vertex arrays if possible
|
tomwalters@397
|
101 #ifdef _MACOSX
|
tomwalters@398
|
102 m_glLockArraysEXT = ::glLockArraysEXT;
|
tomwalters@398
|
103 m_glUnlockArraysEXT = ::glUnlockArraysEXT;
|
tomwalters@398
|
104 m_bVertexArrayLock = true;
|
tomwalters@397
|
105 #else
|
tomwalters@398
|
106 m_bVertexArrayLock = false;
|
tomwalters@398
|
107 // OpenGL command needed to fetch entry point, do it in InitGL()
|
tomwalters@397
|
108 #endif /* _MACOSX */
|
tomwalters@397
|
109 #endif /* WITH_GL_VERTEX_ARRAYS */
|
tomwalters@397
|
110 }
|
tomwalters@397
|
111
|
tomwalters@397
|
112 GraphicsOutputDevicewxGLCanvas::~GraphicsOutputDevicewxGLCanvas() {
|
tomwalters@398
|
113 // Cleanup OpenGL display list
|
tomwalters@398
|
114 if (m_init) {
|
tomwalters@398
|
115 glDeleteLists(m_gllist, 1);
|
tomwalters@398
|
116 }
|
tomwalters@398
|
117 DELETE_IF_NONNULL(m_pWorkerContext);
|
tomwalters@398
|
118 DELETE_IF_NONNULL(m_pFont);
|
tomwalters@397
|
119 #ifdef WITH_GL_VERTEX_ARRAYS
|
tomwalters@398
|
120 DELETE_ARRAY_IF_NONNULL(m_pVertices);
|
tomwalters@397
|
121 #endif
|
tomwalters@397
|
122 }
|
tomwalters@397
|
123
|
tomwalters@397
|
124 void GraphicsOutputDevicewxGLCanvas::Start() {
|
tomwalters@398
|
125 // This seems to be needed to prevent a crash on windows, but why????
|
tomwalters@398
|
126 SetCurrent();
|
tomwalters@398
|
127 return GraphicsOutputDevice::Start();
|
tomwalters@397
|
128 }
|
tomwalters@397
|
129
|
tomwalters@397
|
130 bool GraphicsOutputDevicewxGLCanvas::Initialize(unsigned int iVerticesMax) {
|
tomwalters@398
|
131 AIM_ASSERT(m_pParam);
|
tomwalters@398
|
132 // Give a chance to update anti-aliasing settings
|
tomwalters@398
|
133 if (m_bAntialiasing != m_pParam->GetBool("output.antialias")) {
|
tomwalters@398
|
134 m_bAntialiasing = m_pParam->GetBool("output.antialias");
|
tomwalters@398
|
135 if (SetCurrent()) {
|
tomwalters@398
|
136 InitGL();
|
tomwalters@397
|
137 #if !defined(_MACOSX)
|
tomwalters@398
|
138 {
|
tomwalters@398
|
139 wxMutexLocker lock(s_mutexOpenGL);
|
tomwalters@398
|
140 s_bWorkerNeedsInit = true;
|
tomwalters@398
|
141 }
|
tomwalters@397
|
142 #endif
|
tomwalters@398
|
143 }
|
tomwalters@398
|
144 }
|
tomwalters@397
|
145
|
tomwalters@397
|
146 #ifdef WITH_GL_VERTEX_ARRAYS
|
tomwalters@398
|
147 // Re-allocate vertices
|
tomwalters@398
|
148 if (iVerticesMax > m_iVerticesMax) {
|
tomwalters@398
|
149 DELETE_IF_NONNULL(m_pVertices);
|
tomwalters@398
|
150 m_iVerticesMax = iVerticesMax;
|
tomwalters@398
|
151 // If color is static, we need not store the color
|
tomwalters@398
|
152 if (m_bStaticColor)
|
tomwalters@398
|
153 m_pVertices = new GLfloat[(iVerticesMax+1)*3];
|
tomwalters@398
|
154 else
|
tomwalters@398
|
155 m_pVertices = new GLfloat[(iVerticesMax+1)*6];
|
tomwalters@398
|
156 }
|
tomwalters@397
|
157 #endif
|
tomwalters@397
|
158
|
tomwalters@397
|
159 // Change font if requested
|
tomwalters@398
|
160 const char *sFontFile = m_pParam->GetString("output.gl.fontfile");
|
tomwalters@398
|
161 unsigned int iFontsize = m_pParam->GetUInt("output.fontsize");
|
tomwalters@398
|
162 if (!m_sFontFile
|
tomwalters@397
|
163 || !strcmp(m_sFontFile,sFontFile)==0
|
tomwalters@397
|
164 || m_iFontsize!=(int)iFontsize) {
|
tomwalters@398
|
165 wxMutexLocker lock(s_mutexOpenGL);
|
tomwalters@398
|
166 DELETE_IF_NONNULL(m_pFont);
|
tomwalters@398
|
167 wxString sWorkingFontFilename = wxString::FromAscii(sFontFile);
|
tomwalters@398
|
168 if (!wxFileExists(sWorkingFontFilename)) {
|
tomwalters@398
|
169 sWorkingFontFilename = wxString::FromAscii(aimDataDir());
|
tomwalters@398
|
170 sWorkingFontFilename += _T("/");
|
tomwalters@398
|
171 sWorkingFontFilename += wxString::FromAscii(sFontFile);
|
tomwalters@398
|
172 }
|
tomwalters@398
|
173 //if (!wxFileExists(sWorkingFontFilename))
|
tomwalters@398
|
174 //sWorkingFontFilename.replace("Font:").append(sFontFile);
|
tomwalters@398
|
175 m_pFont = static_cast<FTFont*>(new FTGLBitmapFont(sWorkingFontFilename.fn_str()));
|
tomwalters@398
|
176 if (!m_pFont || m_pFont->Error()) {
|
tomwalters@398
|
177 aimERROR(_T("Couldn't load font '%s'"), sFontFile);
|
tomwalters@398
|
178 DELETE_IF_NONNULL(m_pFont);
|
tomwalters@398
|
179 } else {
|
tomwalters@398
|
180 // Display lists don't mix with our own usage :(
|
tomwalters@398
|
181 // May not be needed for a Bitmap font
|
tomwalters@398
|
182 //m_pFont->UseDisplayList(false);
|
tomwalters@398
|
183 if ( !m_pFont->FaceSize(iFontsize) ) {
|
tomwalters@398
|
184 AIM_ERROR(_T("Couldn't select font size %u on font '%s'"), iFontsize, sFontFile);
|
tomwalters@398
|
185 DELETE_IF_NONNULL(m_pFont);
|
tomwalters@398
|
186 }
|
tomwalters@398
|
187 }
|
tomwalters@398
|
188 m_sFontFile = sFontFile;
|
tomwalters@398
|
189 m_iFontsize = iFontsize;
|
tomwalters@398
|
190 }
|
tomwalters@398
|
191 return true;
|
tomwalters@397
|
192 }
|
tomwalters@397
|
193 bool GraphicsOutputDevicewxGLCanvas::Initialize() {
|
tomwalters@398
|
194 return Initialize(0);
|
tomwalters@397
|
195 }
|
tomwalters@397
|
196
|
tomwalters@397
|
197 void GraphicsOutputDevicewxGLCanvas::Render() {
|
tomwalters@398
|
198 wxPaintDC dc(this);
|
tomwalters@398
|
199 // We want to initialize first from main thread.
|
tomwalters@398
|
200 if (!m_init) {
|
tomwalters@398
|
201 if (!SetCurrent()) return;
|
tomwalters@398
|
202 InitGL();
|
tomwalters@398
|
203 }
|
tomwalters@398
|
204 // Render saved list only if not animating (redrawn anyway in that case)
|
tomwalters@398
|
205 if (!m_bRunning) {
|
tomwalters@398
|
206 if (!SetCurrent()) {
|
tomwalters@397
|
207 return;
|
tomwalters@397
|
208 }
|
tomwalters@398
|
209 glClear(GL_COLOR_BUFFER_BIT/*|GL_DEPTH_BUFFER_BIT*/);
|
tomwalters@398
|
210 glCallList(m_gllist);
|
tomwalters@398
|
211 SwapBuffers();
|
tomwalters@398
|
212 }
|
tomwalters@397
|
213 }
|
tomwalters@397
|
214
|
tomwalters@397
|
215 void GraphicsOutputDevicewxGLCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
|
tomwalters@397
|
216 Render();
|
tomwalters@397
|
217 }
|
tomwalters@397
|
218
|
tomwalters@397
|
219 void GraphicsOutputDevicewxGLCanvas::OnSize(wxSizeEvent& event) {
|
tomwalters@397
|
220 // this is also necessary to update the context on some platforms
|
tomwalters@397
|
221 wxGLCanvas::OnSize(event);
|
tomwalters@397
|
222
|
tomwalters@397
|
223 // set GL viewport
|
tomwalters@398
|
224 // (not called by wxGLCanvas::OnSize on all platforms...)
|
tomwalters@397
|
225 if (SetCurrent()) {
|
tomwalters@398
|
226 DoResize();
|
tomwalters@398
|
227 // It is only sensible to update the other thread when it's running
|
tomwalters@398
|
228 // Don't acquire the mutex when s_bWorkerNeedsInit already to avoid deadlock
|
tomwalters@398
|
229 if (/*m_bRunning &&*/ !s_bWorkerNeedsInit) {
|
tomwalters@398
|
230 wxMutexLocker lock(s_mutexOpenGL);
|
tomwalters@398
|
231 s_bWorkerNeedsInit = true;
|
tomwalters@398
|
232 }
|
tomwalters@398
|
233 }
|
tomwalters@397
|
234 }
|
tomwalters@397
|
235
|
tomwalters@397
|
236 void GraphicsOutputDevicewxGLCanvas::OnEraseBackground(wxEraseEvent& WXUNUSED(event)) {
|
tomwalters@397
|
237 }
|
tomwalters@397
|
238
|
tomwalters@397
|
239 bool GraphicsOutputDevicewxGLCanvas::SetCurrent() {
|
tomwalters@397
|
240 bool bRet=true;
|
tomwalters@397
|
241
|
tomwalters@397
|
242 #ifndef __WXMOTIF__
|
tomwalters@398
|
243 bRet = (GetContext()!=NULL);
|
tomwalters@398
|
244 if (bRet)
|
tomwalters@397
|
245 #endif
|
tomwalters@398
|
246 {
|
tomwalters@398
|
247 wxGLCanvas::SetCurrent();
|
tomwalters@398
|
248 }
|
tomwalters@398
|
249 return bRet;
|
tomwalters@397
|
250 }
|
tomwalters@397
|
251
|
tomwalters@397
|
252 void GraphicsOutputDevicewxGLCanvas::DoResize() {
|
tomwalters@397
|
253 int w, h;
|
tomwalters@398
|
254 GetClientSize(&w, &h);
|
tomwalters@398
|
255 glViewport(0, 0, (GLint)w, (GLint)h);
|
tomwalters@397
|
256 }
|
tomwalters@397
|
257
|
tomwalters@397
|
258 void GraphicsOutputDevicewxGLCanvas::InitGL() {
|
tomwalters@397
|
259 /* No SetCurrent() here, because this can be called from different GL contexts.
|
tomwalters@398
|
260 * Convenient for multi-threaded operation. */
|
tomwalters@397
|
261 //aimERROR(_T("InitGL Called"));
|
tomwalters@397
|
262 #if defined(WITH_GL_VERTEX_ARRAYS) && !defined(_MACOSX)
|
tomwalters@398
|
263 if (!m_init) {
|
tomwalters@398
|
264 /* This needs to be done here, because OpenGL commands may need SetCurrent()
|
tomwalters@398
|
265 * and an already shown window. */
|
tomwalters@398
|
266 char *extensions = (char *)glGetString(GL_EXTENSIONS);
|
tomwalters@398
|
267 if (!extensions) {
|
tomwalters@398
|
268 AIM_INFO(_T("Could not query OpenGL extensions, vertex arrays disabled"));
|
tomwalters@398
|
269 } else if (strstr(extensions, "GL_EXT_compiled_vertex_array")) {
|
tomwalters@398
|
270 m_glLockArraysEXT = (LOCAL_PFNGLLOCKARRAYSEXTPROC)GL_GET_PROC_ADDRESS("glLockArraysEXT");
|
tomwalters@398
|
271 m_glUnlockArraysEXT = (LOCAL_PFNGLUNLOCKARRAYSEXTPROC)GL_GET_PROC_ADDRESS("glUnlockArraysEXT");
|
tomwalters@411
|
272 if (!m_glLockArraysEXT || !m_glUnlockArraysEXT)
|
tomwalters@398
|
273 AIM_ERROR(_T("OpenGL error on GL_EXT_compiled_vertex_array"));
|
tomwalters@398
|
274 else
|
tomwalters@398
|
275 m_bVertexArrayLock = true;
|
tomwalters@398
|
276 }
|
tomwalters@398
|
277 }
|
tomwalters@397
|
278 #endif
|
tomwalters@398
|
279 DoResize();
|
tomwalters@398
|
280 glClearColor(0, 0, 0, 1);
|
tomwalters@398
|
281 glMatrixMode( GL_PROJECTION );
|
tomwalters@398
|
282 glLoadIdentity( );
|
tomwalters@397
|
283
|
tomwalters@398
|
284 glEnable(GL_VERTEX_ARRAY);
|
tomwalters@397
|
285
|
tomwalters@398
|
286 // Window limits in OpenGL co-ordiantes
|
tomwalters@398
|
287 //! \todo Make this configurable, or change and document fixed values
|
tomwalters@398
|
288 glOrtho(0.0, 1.0, 0.0, 1.0, 0.0, 1.0);
|
tomwalters@398
|
289 glTranslatef(0.0, 0.0, 0.0);
|
tomwalters@397
|
290
|
tomwalters@398
|
291 if (m_bAntialiasing) {
|
tomwalters@398
|
292 glEnable(GL_LINE_SMOOTH);
|
tomwalters@398
|
293 glEnable(GL_BLEND);
|
tomwalters@398
|
294 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
tomwalters@398
|
295 //glBlendFunc(GL_ONE, GL_ONE);
|
tomwalters@398
|
296 glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
|
tomwalters@398
|
297 } else {
|
tomwalters@398
|
298 glDisable(GL_LINE_SMOOTH);
|
tomwalters@398
|
299 glDisable(GL_BLEND);
|
tomwalters@398
|
300 }
|
tomwalters@398
|
301 glLineWidth(1.0);
|
tomwalters@397
|
302
|
tomwalters@398
|
303 // Get a free display list only the first time
|
tomwalters@398
|
304 if (!m_init) {
|
tomwalters@397
|
305 #if !defined(_MACOSX)
|
tomwalters@398
|
306 // Windows and Linux need a separate worker context
|
tomwalters@398
|
307 aimASSERT(wxIsMainThread());
|
tomwalters@397
|
308 #if wxCHECK_VERSION(2,8,0)
|
tomwalters@398
|
309 m_pWorkerContext = new wxGLContext(this, m_glContext);
|
tomwalters@397
|
310 #else
|
tomwalters@398
|
311 m_pWorkerContext = new wxGLContext(true,
|
tomwalters@397
|
312 this,
|
tomwalters@397
|
313 wxNullPalette,
|
tomwalters@397
|
314 m_glContext);
|
tomwalters@397
|
315 #endif
|
tomwalters@398
|
316 aimASSERT(m_pWorkerContext);
|
tomwalters@398
|
317 s_bWorkerNeedsInit = true;
|
tomwalters@397
|
318 #endif
|
tomwalters@398
|
319 m_gllist = glGenLists(1);
|
tomwalters@398
|
320 aimASSERT(m_gllist);
|
tomwalters@398
|
321 // Empty window at start
|
tomwalters@398
|
322 glNewList(m_gllist, GL_COMPILE_AND_EXECUTE);
|
tomwalters@398
|
323 glEndList();
|
tomwalters@398
|
324 m_init = true;
|
tomwalters@398
|
325 }
|
tomwalters@397
|
326 }
|
tomwalters@397
|
327
|
tomwalters@397
|
328 // Call before any other render* functions
|
tomwalters@397
|
329 void GraphicsOutputDevicewxGLCanvas::gGrab() {
|
tomwalters@398
|
330 AimwxGuiLocker __lock__;
|
tomwalters@397
|
331 #if !defined(_MACOSX)
|
tomwalters@398
|
332 // Detect if we're the main thread or not.
|
tomwalters@398
|
333 if (!wxIsMainThread()) {
|
tomwalters@398
|
334 // We're called by a worker thread, make sure there's a right context
|
tomwalters@398
|
335 AIM_ASSERT(m_pWorkerContext);
|
tomwalters@397
|
336 #if wxCHECK_VERSION(2,8,0)
|
tomwalters@398
|
337 m_pWorkerContext->SetCurrent(*this);
|
tomwalters@397
|
338 #else
|
tomwalters@398
|
339 m_pWorkerContext->SetCurrent();
|
tomwalters@397
|
340 #endif
|
tomwalters@398
|
341 // Update OpenGL settings if needed
|
tomwalters@398
|
342 wxMutexLocker lock(s_mutexOpenGL);
|
tomwalters@398
|
343 if (s_bWorkerNeedsInit) {
|
tomwalters@398
|
344 InitGL();
|
tomwalters@398
|
345 s_bWorkerNeedsInit = false;
|
tomwalters@398
|
346 }
|
tomwalters@398
|
347 } else
|
tomwalters@397
|
348 #endif
|
tomwalters@398
|
349 {
|
tomwalters@398
|
350 // Either called by main thread, or we need no special worker glContext
|
tomwalters@398
|
351 if (!SetCurrent()) {
|
tomwalters@398
|
352 return;
|
tomwalters@398
|
353 }
|
tomwalters@398
|
354 // Init OpenGL once, but after SetCurrent
|
tomwalters@398
|
355 if (!m_init) {
|
tomwalters@398
|
356 InitGL();
|
tomwalters@398
|
357 }
|
tomwalters@398
|
358 }
|
tomwalters@398
|
359 glClear(GL_COLOR_BUFFER_BIT);
|
tomwalters@397
|
360
|
tomwalters@398
|
361 // Start and store in a display list for redrawing
|
tomwalters@398
|
362 glNewList(m_gllist, GL_COMPILE);
|
tomwalters@397
|
363 }
|
tomwalters@397
|
364
|
tomwalters@397
|
365 void GraphicsOutputDevicewxGLCanvas::gBeginLineStrip() {
|
tomwalters@397
|
366 #ifdef WITH_GL_VERTEX_ARRAYS
|
tomwalters@398
|
367 aimASSERT(m_iVertexType == 0xffff); // Previous gBegin*() must be gEnd()ed
|
tomwalters@398
|
368 // New lines vertex array
|
tomwalters@398
|
369 m_iVertexCount = 0;
|
tomwalters@398
|
370 m_iVertexType = GL_LINE_STRIP;
|
tomwalters@397
|
371 #else
|
tomwalters@398
|
372 AimwxGuiLocker __lock__;
|
tomwalters@398
|
373 glBegin(GL_LINE_STRIP);
|
tomwalters@397
|
374 #endif
|
tomwalters@397
|
375 }
|
tomwalters@397
|
376
|
tomwalters@397
|
377 void GraphicsOutputDevicewxGLCanvas::gBeginQuadStrip() {
|
tomwalters@397
|
378 #ifdef WITH_GL_VERTEX_ARRAYS
|
tomwalters@398
|
379 aimASSERT(m_iVertexType == 0xffff); // Previous gBegin*() must be gEnd()ed
|
tomwalters@398
|
380 // New quads vertex array
|
tomwalters@398
|
381 m_iVertexCount = 0;
|
tomwalters@398
|
382 m_iVertexType = GL_QUAD_STRIP;
|
tomwalters@397
|
383 #else
|
tomwalters@398
|
384 AimwxGuiLocker __lock__;
|
tomwalters@398
|
385 glBegin(GL_QUAD_STRIP);
|
tomwalters@397
|
386 #endif
|
tomwalters@397
|
387 }
|
tomwalters@397
|
388
|
tomwalters@397
|
389 void GraphicsOutputDevicewxGLCanvas::gVertex3f(float x, float y, float z) {
|
tomwalters@397
|
390 #ifdef WITH_GL_VERTEX_ARRAYS
|
tomwalters@398
|
391 aimASSERT(m_iVertexType != 0xffff); // Must be inside gBegin*()
|
tomwalters@398
|
392 if (m_iVertexCount>=m_iVerticesMax) {
|
tomwalters@398
|
393 static bool errShown=false;
|
tomwalters@398
|
394 if (!errShown) {
|
tomwalters@398
|
395 aimERROR(_T("Error: max vertex count reached: %d"), m_iVertexCount);
|
tomwalters@398
|
396 errShown=true;
|
tomwalters@398
|
397 }
|
tomwalters@398
|
398 return;
|
tomwalters@398
|
399 }
|
tomwalters@398
|
400 if (m_bStaticColor) {
|
tomwalters@398
|
401 m_pVertices[m_iVertexCount*3+0] = x;
|
tomwalters@398
|
402 m_pVertices[m_iVertexCount*3+1] = y;
|
tomwalters@398
|
403 m_pVertices[m_iVertexCount*3+2] = z;
|
tomwalters@398
|
404 } else {
|
tomwalters@398
|
405 m_pVertices[m_iVertexCount*6+0] = m_fCurColorR;
|
tomwalters@398
|
406 m_pVertices[m_iVertexCount*6+1] = m_fCurColorG;
|
tomwalters@398
|
407 m_pVertices[m_iVertexCount*6+2] = m_fCurColorB;
|
tomwalters@398
|
408 m_pVertices[m_iVertexCount*6+3] = x;
|
tomwalters@398
|
409 m_pVertices[m_iVertexCount*6+4] = y;
|
tomwalters@398
|
410 m_pVertices[m_iVertexCount*6+5] = z;
|
tomwalters@398
|
411 }
|
tomwalters@398
|
412 m_iVertexCount++;
|
tomwalters@397
|
413 #else
|
tomwalters@398
|
414 AimwxGuiLocker __lock__;
|
tomwalters@398
|
415 glVertex3f(x,y,z);
|
tomwalters@397
|
416 #endif
|
tomwalters@397
|
417 }
|
tomwalters@397
|
418
|
tomwalters@397
|
419 void GraphicsOutputDevicewxGLCanvas::gColor3f(float r, float g, float b) {
|
tomwalters@397
|
420 #ifdef WITH_GL_VERTEX_ARRAYS
|
tomwalters@398
|
421 if (m_iVertexType==0xffff || m_bStaticColor) {
|
tomwalters@398
|
422 // If not inside vertex array run, use the ordinary command
|
tomwalters@398
|
423 glColor3f(r, g, b);
|
tomwalters@398
|
424 }
|
tomwalters@398
|
425 if (!m_bStaticColor) {
|
tomwalters@398
|
426 // Set current color for vertex array usage
|
tomwalters@398
|
427 m_fCurColorR = r;
|
tomwalters@398
|
428 m_fCurColorG = g;
|
tomwalters@398
|
429 m_fCurColorB = b;
|
tomwalters@398
|
430 }
|
tomwalters@397
|
431 #else
|
tomwalters@398
|
432 AimwxGuiLocker __lock__;
|
tomwalters@397
|
433 glColor3f(r, g, b);
|
tomwalters@397
|
434 #endif
|
tomwalters@397
|
435 }
|
tomwalters@397
|
436
|
tomwalters@397
|
437 void GraphicsOutputDevicewxGLCanvas::gEnd() {
|
tomwalters@397
|
438 #ifdef WITH_GL_VERTEX_ARRAYS
|
tomwalters@398
|
439 aimASSERT(m_iVertexType != 0xffff); // Must be inside gBegin*()
|
tomwalters@398
|
440 AimwxGuiLocker __lock__;
|
tomwalters@397
|
441
|
tomwalters@398
|
442 // Draw the vertex array
|
tomwalters@398
|
443 glEnableClientState(GL_VERTEX_ARRAY);
|
tomwalters@397
|
444
|
tomwalters@398
|
445 // Draw vertices
|
tomwalters@398
|
446 if (m_bStaticColor)
|
tomwalters@398
|
447 glVertexPointer(3, GL_FLOAT, 0, m_pVertices);
|
tomwalters@398
|
448 else
|
tomwalters@398
|
449 glInterleavedArrays(GL_C3F_V3F, 0, m_pVertices);
|
tomwalters@398
|
450 if (m_bVertexArrayLock) m_glLockArraysEXT(0, m_iVertexCount);
|
tomwalters@398
|
451 glDrawArrays(m_iVertexType, 0, m_iVertexCount);
|
tomwalters@398
|
452 if (m_bVertexArrayLock) m_glUnlockArraysEXT();
|
tomwalters@397
|
453
|
tomwalters@398
|
454 glDisableClientState(GL_VERTEX_ARRAY);
|
tomwalters@397
|
455
|
tomwalters@398
|
456 // Remember we're outside a gBegin()..gEnd() loop
|
tomwalters@398
|
457 m_iVertexType = 0xffff;
|
tomwalters@397
|
458 #else
|
tomwalters@398
|
459 AimwxGuiLocker __lock__;
|
tomwalters@398
|
460 glEnd();
|
tomwalters@397
|
461 #endif
|
tomwalters@397
|
462 }
|
tomwalters@397
|
463
|
tomwalters@397
|
464 void GraphicsOutputDevicewxGLCanvas::gText3f(float x,
|
tomwalters@397
|
465 float y,
|
tomwalters@397
|
466 float z,
|
tomwalters@397
|
467 const char *sStr,
|
tomwalters@397
|
468 bool bRotated) {
|
tomwalters@397
|
469 #ifdef WITH_GL_VERTEX_ARRAYS
|
tomwalters@398
|
470 aimASSERT(m_iVertexType == 0xffff); // Must be outside gBegin*()
|
tomwalters@397
|
471 #endif
|
tomwalters@397
|
472
|
tomwalters@398
|
473 if (!m_pFont)
|
tomwalters@398
|
474 return;
|
tomwalters@397
|
475
|
tomwalters@398
|
476 //! \todo make rotation work
|
tomwalters@398
|
477 if (bRotated)
|
tomwalters@398
|
478 return;
|
tomwalters@397
|
479
|
tomwalters@398
|
480 {
|
tomwalters@398
|
481 AimwxGuiLocker __lock__;
|
tomwalters@398
|
482 /*
|
tomwalters@398
|
483 if (bRotated) {
|
tomwalters@398
|
484 glPushMatrix();
|
tomwalters@398
|
485 glTranslatef(x,y,z);
|
tomwalters@398
|
486 glRotatef(90.0f, 0, 0, 1.0f);
|
tomwalters@398
|
487 glRasterPos3f(0,0,0);
|
tomwalters@398
|
488 m_pFont->Render(sStr);
|
tomwalters@398
|
489 glPopMatrix();
|
tomwalters@398
|
490 } else {
|
tomwalters@398
|
491 */
|
tomwalters@398
|
492 glRasterPos3f(x, y, z);
|
tomwalters@398
|
493 m_pFont->Render(sStr);
|
tomwalters@398
|
494 }
|
tomwalters@397
|
495 }
|
tomwalters@397
|
496
|
tomwalters@397
|
497 void GraphicsOutputDevicewxGLCanvas::gRelease() {
|
tomwalters@397
|
498 #ifdef WITH_GL_VERTEX_ARRAYS
|
tomwalters@398
|
499 aimASSERT(m_iVertexType == 0xffff); // Must be gEnd()ed
|
tomwalters@397
|
500 #endif
|
tomwalters@398
|
501 AimwxGuiLocker __lock__;
|
tomwalters@398
|
502 glEndList();
|
tomwalters@398
|
503 glCallList(m_gllist);
|
tomwalters@398
|
504 //glFlush();
|
tomwalters@398
|
505 SwapBuffers(); // Doesn't matter in what context
|
tomwalters@397
|
506 }
|