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 #ifndef __GRAPHICS_OUTPUT_DEVICE_GL_CANVAS_H__
|
tomwalters@397
|
28 #define __GRAPHICS_OUTPUT_DEVICE_GL_CANVAS_H__
|
tomwalters@397
|
29
|
tomwalters@397
|
30 // Precompiled wxWidgets headers
|
tomwalters@397
|
31 #include "stdwx.h"
|
tomwalters@397
|
32
|
tomwalters@397
|
33 // Make sure GLCANVAS is compiled into wxWidgets
|
tomwalters@397
|
34 #if !wxUSE_GLCANVAS
|
tomwalters@398
|
35 # error "OpenGL required: set wxUSE_GLCANVAS to 1 and rebuild the library"
|
tomwalters@397
|
36 #endif
|
tomwalters@397
|
37
|
tomwalters@397
|
38 #if defined (_MACOSX)
|
tomwalters@398
|
39 # include <OpenGL/gl.h>
|
tomwalters@398
|
40 # include <OpenGl/glext.h>
|
tomwalters@397
|
41 #elif defined (_WINDOWS)
|
tomwalters@398
|
42 # include <GL/gl.h>
|
tomwalters@398
|
43 # define GL_GET_PROC_ADDRESS wglGetProcAddress
|
tomwalters@397
|
44 #else
|
tomwalters@398
|
45 # include <GL/gl.h>
|
tomwalters@398
|
46 # define GL_GET_PROC_ADDRESS(x) glXGetProcAddress((const GLubyte*)x)
|
tomwalters@397
|
47 #endif
|
tomwalters@397
|
48 /* Define them just ourselves, easiest way to get it working cross-platform
|
tomwalters@397
|
49 * and -Mesa/OpenGL-version. */
|
tomwalters@397
|
50 #ifndef APIENTRY
|
tomwalters@398
|
51 # define APIENTRY
|
tomwalters@397
|
52 #endif
|
tomwalters@397
|
53 typedef void (APIENTRY * LOCAL_PFNGLLOCKARRAYSEXTPROC) (GLint first, GLsizei count);
|
tomwalters@397
|
54 typedef void (APIENTRY * LOCAL_PFNGLUNLOCKARRAYSEXTPROC) (void);
|
tomwalters@397
|
55
|
tomwalters@397
|
56 #ifdef FTGL_SUBDIR
|
tomwalters@398
|
57 # include <FTGL/FTGLBitmapFont.h>
|
tomwalters@397
|
58 #else
|
tomwalters@398
|
59 # include <FTGLBitmapFont.h>
|
tomwalters@397
|
60 #endif
|
tomwalters@397
|
61
|
tomwalters@397
|
62 #include "Output/GraphicsOutputDevice.h"
|
tomwalters@397
|
63
|
tomwalters@397
|
64 // Use by default
|
tomwalters@397
|
65 #define WITH_GL_VERTEX_ARRAYS
|
tomwalters@397
|
66
|
tomwalters@397
|
67 /*!
|
tomwalters@397
|
68 * \class GraphicsOutputDevicewxGLCanvas "Output/GraphicsOutputDevicewxGLCanvas.h"
|
tomwalters@397
|
69 * \brief Output class for output to a wxWidgets OpenGL canvas
|
tomwalters@397
|
70 *
|
tomwalters@397
|
71 * On windows, OpenGL needs a different context when two different threads
|
tomwalters@397
|
72 * want to issue OpenGL commands. This is handled automatically for two
|
tomwalters@397
|
73 * wxThread s.
|
tomwalters@397
|
74 */
|
tomwalters@397
|
75 class GraphicsOutputDevicewxGLCanvas : public wxGLCanvas,
|
tomwalters@397
|
76 public GraphicsOutputDevice {
|
tomwalters@397
|
77 public:
|
tomwalters@397
|
78 GraphicsOutputDevicewxGLCanvas(Parameters *pParam,
|
tomwalters@398
|
79 wxWindow *parent,
|
tomwalters@397
|
80 wxWindowID id = wxID_ANY,
|
tomwalters@397
|
81 const wxPoint& pos = wxDefaultPosition,
|
tomwalters@397
|
82 const wxSize& size = wxDefaultSize,
|
tomwalters@397
|
83 long style = 0,
|
tomwalters@397
|
84 const wxString& name
|
tomwalters@397
|
85 = _T("GraphicsOutputDeviceGLCanvas"));
|
tomwalters@397
|
86 virtual ~GraphicsOutputDevicewxGLCanvas();
|
tomwalters@397
|
87 void OnPaint(wxPaintEvent& event);
|
tomwalters@397
|
88 void OnSize(wxSizeEvent& event);
|
tomwalters@397
|
89 void OnEraseBackground(wxEraseEvent& event);
|
tomwalters@397
|
90
|
tomwalters@398
|
91 /*! \param iVerticesMax Maximum number of vertices to be draw inside a gBegin()..gEnd()
|
tomwalters@398
|
92 *
|
tomwalters@398
|
93 * When iVerticesMax is zero, this variable will not be updated. Note that is _has_
|
tomwalters@398
|
94 * to be set at least once before using this class.
|
tomwalters@398
|
95 */
|
tomwalters@398
|
96 bool Initialize(unsigned int iVerticesMax);
|
tomwalters@398
|
97 bool Initialize();
|
tomwalters@397
|
98
|
tomwalters@398
|
99 void Start();
|
tomwalters@397
|
100
|
tomwalters@397
|
101 void gGrab();
|
tomwalters@397
|
102 void gBeginLineStrip();
|
tomwalters@397
|
103 void gBeginQuadStrip();
|
tomwalters@398
|
104 using GraphicsOutputDevice::gVertex3f; // Because we overload it
|
tomwalters@398
|
105 void gVertex3f(float x, float y, float z);
|
tomwalters@398
|
106 void gColor3f(float r, float g, float b);
|
tomwalters@397
|
107 void gEnd();
|
tomwalters@398
|
108 void gText3f(float x, float y, float z, const char *sStr, bool bRotated = false);
|
tomwalters@398
|
109 void gRelease();
|
tomwalters@397
|
110 protected:
|
tomwalters@398
|
111 /*! \brief Smarter SetCurrent() replacement
|
tomwalters@398
|
112 * \return true on success, false on error
|
tomwalters@398
|
113 *
|
tomwalters@398
|
114 * This function tries GetContext() first. If that fails, it returns false.
|
tomwalters@398
|
115 */
|
tomwalters@398
|
116 bool SetCurrent();
|
tomwalters@398
|
117 void Render();
|
tomwalters@397
|
118
|
tomwalters@398
|
119 /*! \brief Initialize the OpenGL environment.
|
tomwalters@398
|
120 *
|
tomwalters@398
|
121 * This must be called after the canvas is realized but before any other
|
tomwalters@398
|
122 * OpenGL operation is done. Make sure to run SetCurrent() beforehand.
|
tomwalters@398
|
123 * Usually only needed when m_init is false.
|
tomwalters@398
|
124 */
|
tomwalters@397
|
125 void InitGL();
|
tomwalters@397
|
126
|
tomwalters@398
|
127 /*! \brief Handle a resize (notify OpenGL of the new area)
|
tomwalters@398
|
128 *
|
tomwalters@398
|
129 * This is a separate function, because in multi-threading environments
|
tomwalters@398
|
130 * multiple contexts have to call it.
|
tomwalters@398
|
131 */
|
tomwalters@398
|
132 void DoResize();
|
tomwalters@397
|
133
|
tomwalters@398
|
134 /*! \brief Only need to initialize OpenGL once.
|
tomwalters@398
|
135 *
|
tomwalters@398
|
136 * This is false at start and true when OpenGL has been initialized.
|
tomwalters@398
|
137 * No mutex needed, since it's set once at InitGL() and only read afterwards.
|
tomwalters@398
|
138 */
|
tomwalters@397
|
139 bool m_init;
|
tomwalters@397
|
140
|
tomwalters@398
|
141 /*! \brief Vertex list for last drawing so it can be updated on repaint.
|
tomwalters@398
|
142 *
|
tomwalters@398
|
143 * No mutex needed, since it's set once at InitGL() and only read afterwards.
|
tomwalters@398
|
144 */
|
tomwalters@397
|
145 GLuint m_gllist;
|
tomwalters@397
|
146
|
tomwalters@398
|
147 //! \brief OpenGL context for worker thread, use when wxIsMainThread() returns false.
|
tomwalters@398
|
148 wxGLContext *m_pWorkerContext;
|
tomwalters@397
|
149
|
tomwalters@398
|
150 //! \brief Mutex for inter-thread communication
|
tomwalters@398
|
151 wxMutex s_mutexOpenGL;
|
tomwalters@397
|
152
|
tomwalters@398
|
153 //! \brief When true, OpenGL needs to be reinitialized (in the worker thread)
|
tomwalters@398
|
154 bool s_bWorkerNeedsInit;
|
tomwalters@397
|
155
|
tomwalters@398
|
156 //! \brief OpenGL attributes used for initialization.
|
tomwalters@397
|
157 static int GLAttrlist[];
|
tomwalters@397
|
158
|
tomwalters@398
|
159 //! \brief Whether to use anti-aliasing or not
|
tomwalters@398
|
160 bool m_bAntialiasing;
|
tomwalters@397
|
161
|
tomwalters@398
|
162 //! \brief FTGL Font class
|
tomwalters@398
|
163 FTFont *m_pFont;
|
tomwalters@398
|
164 //! \brief Current font filename
|
tomwalters@398
|
165 const char *m_sFontFile;
|
tomwalters@398
|
166 //! \brief Current font size
|
tomwalters@398
|
167 int m_iFontsize;
|
tomwalters@397
|
168
|
tomwalters@397
|
169 #if defined(WITH_GL_VERTEX_ARRAYS) || defined(DOXYGEN)
|
tomwalters@398
|
170 //! \brief OpenGL vertex type of the current m_pVertices, or 0xffff is outside gBegin()..gEnd()
|
tomwalters@398
|
171 int m_iVertexType;
|
tomwalters@398
|
172 //! \brief Maximum number of vertices begin gBegin()..gEnd()
|
tomwalters@398
|
173 unsigned int m_iVerticesMax;
|
tomwalters@398
|
174 //! \brief Vertex array to draw at gEnd(), this becomes m_pVertices[m_iVerticesMax*3]
|
tomwalters@398
|
175 GLfloat *m_pVertices;
|
tomwalters@398
|
176 //! \brief The current number of vertices inside m_pVertices
|
tomwalters@398
|
177 unsigned int m_iVertexCount;
|
tomwalters@397
|
178
|
tomwalters@398
|
179 /*! \brief Whether to use coloring in vertex lists
|
tomwalters@398
|
180 *
|
tomwalters@398
|
181 * This variable must not change after Initialize(), or the program may crash.
|
tomwalters@398
|
182 * When this variable is true, color information is stored in vertex lists. If
|
tomwalters@398
|
183 * it is false, only vertex data is stored.
|
tomwalters@398
|
184 *
|
tomwalters@398
|
185 * This variable exists for performance reasons, but is currently only set in
|
tomwalters@398
|
186 * the constructor of this object.
|
tomwalters@398
|
187 */
|
tomwalters@398
|
188 bool m_bStaticColor;
|
tomwalters@398
|
189 //! \brief Current color for vertex list drawing
|
tomwalters@398
|
190 float m_fCurColorR, m_fCurColorG, m_fCurColorB;
|
tomwalters@397
|
191
|
tomwalters@398
|
192 //! \brief Whether to use vertex array locking or not
|
tomwalters@398
|
193 bool m_bVertexArrayLock;
|
tomwalters@398
|
194 //! \brief Pointer to vertex array locking function; can be NULL.
|
tomwalters@398
|
195 LOCAL_PFNGLLOCKARRAYSEXTPROC m_glLockArraysEXT;
|
tomwalters@398
|
196 //! \brief Pointer to vertex array unlocking function; can be NULL.
|
tomwalters@398
|
197 LOCAL_PFNGLUNLOCKARRAYSEXTPROC m_glUnlockArraysEXT;
|
tomwalters@397
|
198 #endif
|
tomwalters@397
|
199
|
tomwalters@398
|
200 /*! \brief wxMutexGuiEnter() / wxMutexGuiLeave() wrapper
|
tomwalters@398
|
201 *
|
tomwalters@398
|
202 * This is a wxMutexLocker-alike for the main gui mutex. Any method that
|
tomwalters@398
|
203 * is public, can be called from within another thread and does OpenGL or
|
tomwalters@398
|
204 * other gui calls must use this. Example:
|
tomwalters@398
|
205 * \code
|
tomwalters@398
|
206 * void DoFoo() {
|
tomwalters@398
|
207 * AimwxGuiLocker __lock__;
|
tomwalters@398
|
208 * glAmazingMethod();
|
tomwalters@398
|
209 * }
|
tomwalters@398
|
210 * \endcode
|
tomwalters@398
|
211 *
|
tomwalters@398
|
212 * It is mostly on X-Windows (Xorg/XFree86) that the gui mutex appears to
|
tomwalters@398
|
213 * be needed. Otherwise the error "Xlib: unexpected async reply" can occur.
|
tomwalters@398
|
214 *
|
tomwalters@398
|
215 * On windows, the ui may occasionally lock up for a short while with these
|
tomwalters@398
|
216 * mutexes. Since they aren't really needed on that platform, it's left out
|
tomwalters@398
|
217 * alltogether.
|
tomwalters@398
|
218 */
|
tomwalters@398
|
219 class AimwxGuiLocker {
|
tomwalters@398
|
220 public:
|
tomwalters@398
|
221 inline AimwxGuiLocker() {
|
tomwalters@397
|
222 #ifndef _WINDOWS
|
tomwalters@398
|
223 if (!wxIsMainThread()) wxMutexGuiEnter();
|
tomwalters@397
|
224 #endif
|
tomwalters@398
|
225 }
|
tomwalters@398
|
226 inline ~AimwxGuiLocker() {
|
tomwalters@397
|
227 #ifndef _WINDOWS
|
tomwalters@398
|
228 if (!wxIsMainThread()) wxMutexGuiLeave();
|
tomwalters@397
|
229 #endif
|
tomwalters@398
|
230 }
|
tomwalters@398
|
231 };
|
tomwalters@397
|
232 DECLARE_EVENT_TABLE()
|
tomwalters@397
|
233 };
|
tomwalters@397
|
234 #endif /* __GRAPHICS_OUTPUT_DEVICE_GL_CANVAS_H__ */
|