1 //  ---------------------------------------------------------------------------
2 //
3 //  @file       TwOpenGL.cpp
4 //  @author     Philippe Decaudin
5 //  @license    This file is part of the AntTweakBar library.
6 //              For conditions of distribution and use, see License.txt
7 //
8 //  ---------------------------------------------------------------------------
9 
10 
11 #include "TwPrecomp.h"
12 #include "LoadOGL.h"
13 #include "TwOpenGL.h"
14 #include "TwMgr.h"
15 
16 using namespace std;
17 
18 const char *g_ErrCantLoadOGL    = "Cannot load OpenGL library dynamically";
19 const char *g_ErrCantUnloadOGL  = "Cannot unload OpenGL library";
20 
21 GLuint g_SmallFontTexID = 0;
22 GLuint g_NormalFontTexID = 0;
23 GLuint g_LargeFontTexID = 0;
24 
25 //  ---------------------------------------------------------------------------
26 //  Extensions
27 
28 typedef void (APIENTRY * PFNGLBindBufferARB)(GLenum target, GLuint buffer);
29 typedef void (APIENTRY * PFNGLBindProgramARB)(GLenum target, GLuint program);
30 typedef GLuint (APIENTRY * PFNGLGetHandleARB)(GLenum pname);
31 typedef void (APIENTRY * PFNGLUseProgramObjectARB)(GLuint programObj);
32 typedef void (APIENTRY * PFNGLTexImage3D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
33 typedef void (APIENTRY * PFNGLActiveTextureARB)(GLenum texture);
34 typedef void (APIENTRY * PFNGLClientActiveTextureARB)(GLenum texture);
35 typedef void (APIENTRY * PFNGLBlendEquation)(GLenum mode);
36 typedef void (APIENTRY * PFNGLBlendEquationSeparate)(GLenum srcMode, GLenum dstMode);
37 typedef void (APIENTRY * PFNGLBlendFuncSeparate)(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
38 typedef void (APIENTRY * PFNGLBindVertexArray)(GLuint array);
39 typedef void (APIENTRY * PFNGLEnableVertexAttribArray) (GLuint index);
40 typedef void (APIENTRY * PFNGLDisableVertexAttribArray) (GLuint index);
41 typedef void (APIENTRY * PFNGLGetVertexAttribiv) (GLuint, GLenum, GLint*);
42 PFNGLBindBufferARB _glBindBufferARB = NULL;
43 PFNGLBindProgramARB _glBindProgramARB = NULL;
44 PFNGLGetHandleARB _glGetHandleARB = NULL;
45 PFNGLUseProgramObjectARB _glUseProgramObjectARB = NULL;
46 PFNGLTexImage3D _glTexImage3D = NULL;
47 PFNGLActiveTextureARB _glActiveTextureARB = NULL;
48 PFNGLClientActiveTextureARB _glClientActiveTextureARB = NULL;
49 PFNGLBlendEquation _glBlendEquation = NULL;
50 PFNGLBlendEquationSeparate _glBlendEquationSeparate = NULL;
51 PFNGLBlendFuncSeparate _glBlendFuncSeparate = NULL;
52 PFNGLBindVertexArray _glBindVertexArray = NULL;
53 PFNGLEnableVertexAttribArray _glEnableVertexAttribArray = NULL;
54 PFNGLDisableVertexAttribArray _glDisableVertexAttribArray = NULL;
55 PFNGLGetVertexAttribiv _glGetVertexAttribiv = NULL;
56 #ifndef GL_ARRAY_BUFFER_ARB
57 #   define GL_ARRAY_BUFFER_ARB 0x8892
58 #endif
59 #ifndef GL_ELEMENT_ARRAY_BUFFER_ARB
60 #   define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893
61 #endif
62 #ifndef GL_ARRAY_BUFFER_BINDING_ARB
63 #   define GL_ARRAY_BUFFER_BINDING_ARB 0x8894
64 #endif
65 #ifndef GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB
66 #   define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895
67 #endif
68 #ifndef GL_VERTEX_PROGRAM_ARB
69 #   define GL_VERTEX_PROGRAM_ARB 0x8620
70 #endif
71 #ifndef GL_FRAGMENT_PROGRAM_ARB
72 #   define GL_FRAGMENT_PROGRAM_ARB 0x8804
73 #endif
74 #ifndef GL_PROGRAM_OBJECT_ARB
75 #   define GL_PROGRAM_OBJECT_ARB 0x8B40
76 #endif
77 #ifndef GL_TEXTURE_3D
78 #   define GL_TEXTURE_3D 0x806F
79 #endif
80 #ifndef GL_TEXTURE0_ARB
81 #   define GL_TEXTURE0_ARB 0x84C0
82 #endif
83 #ifndef GL_ACTIVE_TEXTURE_ARB
84 #   define GL_ACTIVE_TEXTURE_ARB 0x84E0
85 #endif
86 #ifndef GL_CLIENT_ACTIVE_TEXTURE_ARB
87 #   define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1
88 #endif
89 #ifndef GL_MAX_TEXTURE_UNITS_ARB
90 #   define GL_MAX_TEXTURE_UNITS_ARB 0x84E2
91 #endif
92 #ifndef GL_MAX_TEXTURE_COORDS
93 #   define GL_MAX_TEXTURE_COORDS 0x8871
94 #endif
95 #ifndef GL_TEXTURE_RECTANGLE_ARB
96 #   define GL_TEXTURE_RECTANGLE_ARB 0x84F5
97 #endif
98 #ifndef GL_FUNC_ADD
99 #   define GL_FUNC_ADD 0x8006
100 #endif
101 #ifndef GL_BLEND_EQUATION
102 #   define GL_BLEND_EQUATION 0x8009
103 #endif
104 #ifndef GL_BLEND_EQUATION_RGB
105 #   define GL_BLEND_EQUATION_RGB GL_BLEND_EQUATION
106 #endif
107 #ifndef GL_BLEND_EQUATION_ALPHA
108 #   define GL_BLEND_EQUATION_ALPHA 0x883D
109 #endif
110 #ifndef GL_BLEND_SRC_RGB
111 #   define GL_BLEND_SRC_RGB 0x80C9
112 #endif
113 #ifndef GL_BLEND_DST_RGB
114 #   define GL_BLEND_DST_RGB 0x80C8
115 #endif
116 #ifndef GL_BLEND_SRC_ALPHA
117 #   define GL_BLEND_SRC_ALPHA 0x80CB
118 #endif
119 #ifndef GL_BLEND_DST_ALPHA
120 #   define GL_BLEND_DST_ALPHA 0x80CA
121 #endif
122 #ifndef GL_VERTEX_ARRAY_BINDING
123 #   define GL_VERTEX_ARRAY_BINDING 0x85B5
124 #endif
125 #ifndef GL_MAX_VERTEX_ATTRIBS
126 #    define GL_MAX_VERTEX_ATTRIBS 0x8869
127 #endif
128 #ifndef GL_VERTEX_ATTRIB_ARRAY_ENABLED
129 #    define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
130 #endif
131 
132 //  ---------------------------------------------------------------------------
133 
134 #ifdef _DEBUG
CheckGLError(const char * file,int line,const char * func)135     static void CheckGLError(const char *file, int line, const char *func)
136     {
137         int err=0;
138         char msg[256];
139         while( (err=_glGetError())!=0 )
140         {
141             sprintf(msg, "%s(%d) : [%s] GL_ERROR=0x%x\n", file, line, func, err);
142             #ifdef ANT_WINDOWS
143                 OutputDebugString(msg);
144             #endif
145             fprintf(stderr, msg);
146         }
147     }
148 #   ifdef __FUNCTION__
149 #       define CHECK_GL_ERROR CheckGLError(__FILE__, __LINE__, __FUNCTION__)
150 #   else
151 #       define CHECK_GL_ERROR CheckGLError(__FILE__, __LINE__, "")
152 #   endif
153 #else
154 #   define CHECK_GL_ERROR ((void)(0))
155 #endif
156 
157 //  ---------------------------------------------------------------------------
158 
BindFont(const CTexFont * _Font)159 static GLuint BindFont(const CTexFont *_Font)
160 {
161     GLuint TexID = 0;
162     _glGenTextures(1, &TexID);
163     _glBindTexture(GL_TEXTURE_2D, TexID);
164     _glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
165     _glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
166     _glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
167     _glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
168     _glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
169     _glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
170     _glPixelTransferf(GL_ALPHA_SCALE, 1);
171     _glPixelTransferf(GL_ALPHA_BIAS, 0);
172     _glPixelTransferf(GL_RED_BIAS, 1);
173     _glPixelTransferf(GL_GREEN_BIAS, 1);
174     _glPixelTransferf(GL_BLUE_BIAS, 1);
175     _glTexImage2D(GL_TEXTURE_2D, 0, 4, _Font->m_TexWidth, _Font->m_TexHeight, 0, GL_ALPHA, GL_UNSIGNED_BYTE, _Font->m_TexBytes);
176     _glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
177     _glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
178     _glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_NEAREST);
179     _glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST);
180     _glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
181     _glBindTexture(GL_TEXTURE_2D, 0);
182     _glPixelTransferf(GL_ALPHA_BIAS, 0);
183     _glPixelTransferf(GL_RED_BIAS, 0);
184     _glPixelTransferf(GL_GREEN_BIAS, 0);
185     _glPixelTransferf(GL_BLUE_BIAS, 0);
186 
187     return TexID;
188 }
189 
UnbindFont(GLuint _FontTexID)190 static void UnbindFont(GLuint _FontTexID)
191 {
192     if( _FontTexID>0 )
193         _glDeleteTextures(1, &_FontTexID);
194 }
195 
196 //  ---------------------------------------------------------------------------
197 
Init()198 int CTwGraphOpenGL::Init()
199 {
200     m_Drawing = false;
201     m_FontTexID = 0;
202     m_FontTex = NULL;
203     m_MaxClipPlanes = -1;
204 
205     if( LoadOpenGL()==0 )
206     {
207         g_TwMgr->SetLastError(g_ErrCantLoadOGL);
208         return 0;
209     }
210 
211     // Get extensions
212     _glBindBufferARB = reinterpret_cast<PFNGLBindBufferARB>(_glGetProcAddress("glBindBufferARB"));
213     _glBindProgramARB = reinterpret_cast<PFNGLBindProgramARB>(_glGetProcAddress("glBindProgramARB"));
214     _glGetHandleARB = reinterpret_cast<PFNGLGetHandleARB>(_glGetProcAddress("glGetHandleARB"));
215     _glUseProgramObjectARB = reinterpret_cast<PFNGLUseProgramObjectARB>(_glGetProcAddress("glUseProgramObjectARB"));
216     _glTexImage3D = reinterpret_cast<PFNGLTexImage3D>(_glGetProcAddress("glTexImage3D"));
217     _glActiveTextureARB = reinterpret_cast<PFNGLActiveTextureARB>(_glGetProcAddress("glActiveTextureARB"));
218     _glClientActiveTextureARB = reinterpret_cast<PFNGLClientActiveTextureARB>(_glGetProcAddress("glClientActiveTextureARB"));
219     _glBlendEquation = reinterpret_cast<PFNGLBlendEquation>(_glGetProcAddress("glBlendEquation"));
220     _glBlendEquationSeparate = reinterpret_cast<PFNGLBlendEquationSeparate>(_glGetProcAddress("glBlendEquationSeparate"));
221     _glBlendFuncSeparate = reinterpret_cast<PFNGLBlendFuncSeparate>(_glGetProcAddress("glBlendFuncSeparate"));
222     _glBindVertexArray = reinterpret_cast<PFNGLBindVertexArray>(_glGetProcAddress("glBindVertexArray"));
223     _glEnableVertexAttribArray = reinterpret_cast<PFNGLEnableVertexAttribArray>(_glGetProcAddress("glEnableVertexAttribArray"));
224     _glDisableVertexAttribArray = reinterpret_cast<PFNGLDisableVertexAttribArray>(_glGetProcAddress("glDisableVertexAttribArray"));
225     _glGetVertexAttribiv = reinterpret_cast<PFNGLGetVertexAttribiv>(_glGetProcAddress("glGetVertexAttribiv"));
226 
227     m_SupportTexRect = false; // updated in BeginDraw
228 
229     return 1;
230 }
231 
232 //  ---------------------------------------------------------------------------
233 
Shut()234 int CTwGraphOpenGL::Shut()
235 {
236     assert(m_Drawing==false);
237 
238     UnbindFont(m_FontTexID);
239 
240     int Res = 1;
241     if( UnloadOpenGL()==0 )
242     {
243         g_TwMgr->SetLastError(g_ErrCantUnloadOGL);
244         Res = 0;
245     }
246 
247     return Res;
248 }
249 
250 //  ---------------------------------------------------------------------------
251 
BeginDraw(int _WndWidth,int _WndHeight)252 void CTwGraphOpenGL::BeginDraw(int _WndWidth, int _WndHeight)
253 {
254     assert(m_Drawing==false && _WndWidth>0 && _WndHeight>0);
255     m_Drawing = true;
256     m_WndWidth = _WndWidth;
257     m_WndHeight = _WndHeight;
258 
259     CHECK_GL_ERROR;
260 
261 //#if !defined(ANT_OSX)
262     static bool s_SupportTexRectChecked = false;
263     if (!s_SupportTexRectChecked)
264     {
265         const char *ext = (const char *)_glGetString(GL_EXTENSIONS);
266         if( ext!=0 && strlen(ext)>0 )
267             m_SupportTexRect = (strstr(ext, "GL_ARB_texture_rectangle")!=NULL);
268         s_SupportTexRectChecked = true;
269     }
270 //#endif
271 
272     _glPushAttrib(GL_ALL_ATTRIB_BITS);
273     _glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);
274 
275     if( _glActiveTextureARB )
276     {
277         _glGetIntegerv(GL_ACTIVE_TEXTURE_ARB, &m_PrevActiveTextureARB);
278         _glGetIntegerv(GL_CLIENT_ACTIVE_TEXTURE_ARB, &m_PrevClientActiveTextureARB);
279         GLint maxTexUnits = 1;
280         _glGetIntegerv(GL_MAX_TEXTURE_COORDS, &maxTexUnits); // was GL_MAX_TEXTURE_UNITS_ARB
281         if( maxTexUnits<1 )
282             maxTexUnits = 1;
283         else if( maxTexUnits > MAX_TEXTURES )
284             maxTexUnits = MAX_TEXTURES;
285         GLint i;
286         for( i=0; i<maxTexUnits; ++i )
287         {
288             _glActiveTextureARB(GL_TEXTURE0_ARB+i);
289             m_PrevActiveTexture1D[i] = _glIsEnabled(GL_TEXTURE_1D);
290             m_PrevActiveTexture2D[i] = _glIsEnabled(GL_TEXTURE_2D);
291             m_PrevActiveTexture3D[i] = _glIsEnabled(GL_TEXTURE_3D);
292             _glDisable(GL_TEXTURE_1D);
293             _glDisable(GL_TEXTURE_2D);
294             _glDisable(GL_TEXTURE_3D);
295         }
296         _glActiveTextureARB(GL_TEXTURE0_ARB);
297 
298         for( i=0; i<maxTexUnits; i++ )
299         {
300             _glClientActiveTextureARB(GL_TEXTURE0_ARB+i);
301             m_PrevClientTexCoordArray[i] = _glIsEnabled(GL_TEXTURE_COORD_ARRAY);
302             _glDisableClientState(GL_TEXTURE_COORD_ARRAY);
303         }
304         _glClientActiveTextureARB(GL_TEXTURE0_ARB);
305     }
306 
307     _glMatrixMode(GL_TEXTURE);
308     _glPushMatrix();
309     _glLoadIdentity();
310     _glMatrixMode(GL_MODELVIEW);
311     _glPushMatrix();
312     _glLoadIdentity();
313     _glMatrixMode(GL_PROJECTION);
314     _glPushMatrix();
315     GLint Vp[4];
316     _glGetIntegerv(GL_VIEWPORT, Vp);
317     /*
318     if( _WndWidth>0 && _WndHeight>0 )
319     {
320         Vp[0] = 0;
321         Vp[1] = 0;
322         Vp[2] = _WndWidth;
323         Vp[3] = _WndHeight;
324         _glViewport(Vp[0], Vp[1], Vp[2], Vp[3]);
325     }
326     _glLoadIdentity();
327     //_glOrtho(Vp[0], Vp[0]+Vp[2]-1, Vp[1]+Vp[3]-1, Vp[1], -1, 1); // Doesn't work
328     _glOrtho(Vp[0], Vp[0]+Vp[2], Vp[1]+Vp[3], Vp[1], -1, 1);
329     */
330     if( _WndWidth>0 && _WndHeight>0 )
331     {
332         Vp[0] = 0;
333         Vp[1] = 0;
334         Vp[2] = _WndWidth-1;
335         Vp[3] = _WndHeight-1;
336         _glViewport(Vp[0], Vp[1], Vp[2], Vp[3]);
337     }
338     _glLoadIdentity();
339     _glOrtho(Vp[0], Vp[0]+Vp[2], Vp[1]+Vp[3], Vp[1], -1, 1);
340     _glGetIntegerv(GL_VIEWPORT, m_ViewportInit);
341     _glGetFloatv(GL_PROJECTION_MATRIX, m_ProjMatrixInit);
342 
343     _glGetFloatv(GL_LINE_WIDTH, &m_PrevLineWidth);
344     _glDisable(GL_POLYGON_STIPPLE);
345     _glLineWidth(1);
346     _glDisable(GL_LINE_SMOOTH);
347     _glDisable(GL_LINE_STIPPLE);
348     _glDisable(GL_CULL_FACE);
349     _glDisable(GL_DEPTH_TEST);
350     _glDisable(GL_LIGHTING);
351     _glEnable(GL_BLEND);
352     _glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
353     _glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &m_PrevTexEnv);
354     _glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
355     _glGetIntegerv(GL_POLYGON_MODE, m_PrevPolygonMode);
356     _glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
357     _glDisable(GL_ALPHA_TEST);
358     //_glEnable(GL_ALPHA_TEST);
359     //_glAlphaFunc(GL_GREATER, 0);
360     _glDisable(GL_FOG);
361     _glDisable(GL_LOGIC_OP);
362     _glDisable(GL_SCISSOR_TEST);
363     if( m_MaxClipPlanes<0 )
364     {
365         _glGetIntegerv(GL_MAX_CLIP_PLANES, &m_MaxClipPlanes);
366         if( m_MaxClipPlanes<0 || m_MaxClipPlanes>255 )
367             m_MaxClipPlanes = 6;
368     }
369     for( GLint i=0; i<m_MaxClipPlanes; ++i )
370         _glDisable(GL_CLIP_PLANE0+i);
371     m_PrevTexture = 0;
372     _glGetIntegerv(GL_TEXTURE_BINDING_2D, &m_PrevTexture);
373 
374     _glDisableClientState(GL_VERTEX_ARRAY);
375     _glDisableClientState(GL_NORMAL_ARRAY);
376     _glDisableClientState(GL_TEXTURE_COORD_ARRAY);
377     _glDisableClientState(GL_INDEX_ARRAY);
378     _glDisableClientState(GL_COLOR_ARRAY);
379     _glDisableClientState(GL_EDGE_FLAG_ARRAY);
380 
381     if( _glBindVertexArray!=NULL )
382     {
383         m_PrevVertexArray = 0;
384         _glGetIntegerv(GL_VERTEX_ARRAY_BINDING, (GLint*)&m_PrevVertexArray);
385         _glBindVertexArray(0);
386     }
387     if( _glBindBufferARB!=NULL )
388     {
389         m_PrevArrayBufferARB = m_PrevElementArrayBufferARB = 0;
390         _glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &m_PrevArrayBufferARB);
391         _glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &m_PrevElementArrayBufferARB);
392         _glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
393         _glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
394     }
395     if( _glBindProgramARB!=NULL )
396     {
397         m_PrevVertexProgramARB = _glIsEnabled(GL_VERTEX_PROGRAM_ARB);
398         m_PrevFragmentProgramARB = _glIsEnabled(GL_FRAGMENT_PROGRAM_ARB);
399         _glDisable(GL_VERTEX_PROGRAM_ARB);
400         _glDisable(GL_FRAGMENT_PROGRAM_ARB);
401     }
402     if( _glGetHandleARB!=NULL && _glUseProgramObjectARB!=NULL )
403     {
404         m_PrevProgramObjectARB = _glGetHandleARB(GL_PROGRAM_OBJECT_ARB);
405         _glUseProgramObjectARB(0);
406     }
407     _glDisable(GL_TEXTURE_1D);
408     _glDisable(GL_TEXTURE_2D);
409     if( _glTexImage3D!=NULL )
410     {
411         m_PrevTexture3D = _glIsEnabled(GL_TEXTURE_3D);
412         _glDisable(GL_TEXTURE_3D);
413     }
414 
415     if( m_SupportTexRect )
416     {
417         m_PrevTexRectARB = _glIsEnabled(GL_TEXTURE_RECTANGLE_ARB);
418         _glDisable(GL_TEXTURE_RECTANGLE_ARB);
419     }
420     if( _glBlendEquationSeparate!=NULL )
421     {
422         _glGetIntegerv(GL_BLEND_EQUATION_RGB, &m_PrevBlendEquationRGB);
423         _glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &m_PrevBlendEquationAlpha);
424         _glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
425     }
426     if( _glBlendFuncSeparate!=NULL )
427     {
428         _glGetIntegerv(GL_BLEND_SRC_RGB, &m_PrevBlendSrcRGB);
429         _glGetIntegerv(GL_BLEND_DST_RGB, &m_PrevBlendDstRGB);
430         _glGetIntegerv(GL_BLEND_SRC_ALPHA, &m_PrevBlendSrcAlpha);
431         _glGetIntegerv(GL_BLEND_DST_ALPHA, &m_PrevBlendDstAlpha);
432         _glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
433     }
434     if( _glBlendEquation!=NULL )
435     {
436         _glGetIntegerv(GL_BLEND_EQUATION, &m_PrevBlendEquation);
437         _glBlendEquation(GL_FUNC_ADD);
438     }
439     if( _glDisableVertexAttribArray!=NULL )
440     {
441         GLint maxVertexAttribs;
442         _glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
443         if(maxVertexAttribs>MAX_VERTEX_ATTRIBS)
444             maxVertexAttribs=MAX_VERTEX_ATTRIBS;
445 
446         for(int i=0; i<maxVertexAttribs; i++)
447         {
448             _glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &m_PrevEnabledVertexAttrib[i]);
449             _glDisableVertexAttribArray(i);
450         }
451     }
452 
453     CHECK_GL_ERROR;
454 }
455 
456 //  ---------------------------------------------------------------------------
457 
EndDraw()458 void CTwGraphOpenGL::EndDraw()
459 {
460     assert(m_Drawing==true);
461     m_Drawing = false;
462 
463     _glBindTexture(GL_TEXTURE_2D, m_PrevTexture);
464     if( _glBindVertexArray!=NULL )
465         _glBindVertexArray(m_PrevVertexArray);
466     if( _glBindBufferARB!=NULL )
467     {
468         _glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_PrevArrayBufferARB);
469         _glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, m_PrevElementArrayBufferARB);
470     }
471     if( _glBindProgramARB!=NULL )
472     {
473         if( m_PrevVertexProgramARB )
474             _glEnable(GL_VERTEX_PROGRAM_ARB);
475         if( m_PrevFragmentProgramARB )
476             _glEnable(GL_FRAGMENT_PROGRAM_ARB);
477     }
478     if( _glGetHandleARB!=NULL && _glUseProgramObjectARB!=NULL )
479         _glUseProgramObjectARB(m_PrevProgramObjectARB);
480     if( _glTexImage3D!=NULL && m_PrevTexture3D )
481         _glEnable(GL_TEXTURE_3D);
482     if( m_SupportTexRect && m_PrevTexRectARB )
483         _glEnable(GL_TEXTURE_RECTANGLE_ARB);
484     if( _glBlendEquation!=NULL )
485         _glBlendEquation(m_PrevBlendEquation);
486     if( _glBlendEquationSeparate!=NULL )
487         _glBlendEquationSeparate(m_PrevBlendEquationRGB, m_PrevBlendEquationAlpha);
488     if( _glBlendFuncSeparate!=NULL )
489         _glBlendFuncSeparate(m_PrevBlendSrcRGB, m_PrevBlendDstRGB, m_PrevBlendSrcAlpha, m_PrevBlendDstAlpha);
490 
491     _glPolygonMode(GL_FRONT, m_PrevPolygonMode[0]);
492     _glPolygonMode(GL_BACK, m_PrevPolygonMode[1]);
493     _glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, m_PrevTexEnv);
494     _glLineWidth(m_PrevLineWidth);
495     _glMatrixMode(GL_PROJECTION);
496     _glPopMatrix();
497     _glMatrixMode(GL_MODELVIEW);
498     _glPopMatrix();
499     _glMatrixMode(GL_TEXTURE);
500     _glPopMatrix();
501     _glPopClientAttrib();
502     _glPopAttrib();
503 
504     if( _glActiveTextureARB )
505     {
506         GLint maxTexUnits = 1;
507         _glGetIntegerv(GL_MAX_TEXTURE_COORDS, &maxTexUnits); // was GL_MAX_TEXTURE_UNITS_ARB
508         if( maxTexUnits<1 )
509             maxTexUnits = 1;
510         else if( maxTexUnits > MAX_TEXTURES )
511             maxTexUnits = MAX_TEXTURES;
512         GLint i;
513         for( i=0; i<maxTexUnits; ++i )
514         {
515             _glActiveTextureARB(GL_TEXTURE0_ARB+i);
516             if( m_PrevActiveTexture1D[i] )
517                 _glEnable(GL_TEXTURE_1D);
518             if( m_PrevActiveTexture2D[i] )
519                 _glEnable(GL_TEXTURE_2D);
520             if( m_PrevActiveTexture3D[i] )
521                 _glEnable(GL_TEXTURE_3D);
522         }
523         _glActiveTextureARB(m_PrevActiveTextureARB);
524 
525         for( i=0; i<maxTexUnits; ++i )
526         {
527             _glClientActiveTextureARB(GL_TEXTURE0_ARB+i);
528             if( m_PrevClientTexCoordArray[i] )
529                 _glEnableClientState(GL_TEXTURE_COORD_ARRAY);
530         }
531         _glClientActiveTextureARB(m_PrevClientActiveTextureARB);
532     }
533     if(_glEnableVertexAttribArray)
534     {
535         GLint maxVertexAttribs;
536         _glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
537         if(maxVertexAttribs>MAX_VERTEX_ATTRIBS)
538             maxVertexAttribs=MAX_VERTEX_ATTRIBS;
539 
540         for(int i=0; i<maxVertexAttribs; i++)
541         {
542             if(m_PrevEnabledVertexAttrib[i]!=0)
543                 _glEnableVertexAttribArray(i);
544         }
545     }
546 
547     CHECK_GL_ERROR;
548 }
549 
550 //  ---------------------------------------------------------------------------
551 
IsDrawing()552 bool CTwGraphOpenGL::IsDrawing()
553 {
554     return m_Drawing;
555 }
556 
557 //  ---------------------------------------------------------------------------
558 
Restore()559 void CTwGraphOpenGL::Restore()
560 {
561     UnbindFont(m_FontTexID);
562     m_FontTexID = 0;
563     m_FontTex = NULL;
564 }
565 
566 
567 //  ---------------------------------------------------------------------------
568 
DrawLine(int _X0,int _Y0,int _X1,int _Y1,color32 _Color0,color32 _Color1,bool _AntiAliased)569 void CTwGraphOpenGL::DrawLine(int _X0, int _Y0, int _X1, int _Y1, color32 _Color0, color32 _Color1, bool _AntiAliased)
570 {
571     assert(m_Drawing==true);
572     /*
573     // border adjustment NO!!
574     if(_X0<_X1)
575         ++_X1;
576     else if(_X0>_X1)
577         ++_X0;
578     if(_Y0<_Y1)
579         ++_Y1;
580     else if(_Y0>_Y1)
581         ++_Y0;
582     */
583     //const GLfloat dx = +0.0f;
584     const GLfloat dx = +0.5f;
585     //GLfloat dy = -0.2f;
586     const GLfloat dy = -0.5f;
587     if( _AntiAliased )
588         _glEnable(GL_LINE_SMOOTH);
589     else
590         _glDisable(GL_LINE_SMOOTH);
591     _glDisable(GL_TEXTURE_2D);
592     _glMatrixMode(GL_MODELVIEW);
593     _glLoadIdentity();
594     _glBegin(GL_LINES);
595         _glColor4ub(GLubyte(_Color0>>16), GLubyte(_Color0>>8), GLubyte(_Color0), GLubyte(_Color0>>24));
596         _glVertex2f((GLfloat)_X0+dx, (GLfloat)_Y0+dy);
597         _glColor4ub(GLubyte(_Color1>>16), GLubyte(_Color1>>8), GLubyte(_Color1), GLubyte(_Color1>>24));
598         _glVertex2f((GLfloat)_X1+dx, (GLfloat)_Y1+dy);
599         //_glVertex2i(_X0, _Y0);
600         //_glVertex2i(_X1, _Y1);
601     _glEnd();
602     _glDisable(GL_LINE_SMOOTH);
603 }
604 
605 //  ---------------------------------------------------------------------------
606 
DrawRect(int _X0,int _Y0,int _X1,int _Y1,color32 _Color00,color32 _Color10,color32 _Color01,color32 _Color11)607 void CTwGraphOpenGL::DrawRect(int _X0, int _Y0, int _X1, int _Y1, color32 _Color00, color32 _Color10, color32 _Color01, color32 _Color11)
608 {
609     assert(m_Drawing==true);
610 
611     /*
612     // border adjustment
613     if(_X0<_X1)
614         ++_X1;
615     else if(_X0>_X1)
616         ++_X0;
617     if(_Y0<_Y1)
618         ++_Y1;
619     else if(_Y0>_Y1)
620         ++_Y0;
621     */
622     // border adjustment
623     if(_X0<_X1)
624         ++_X1;
625     else if(_X0>_X1)
626         ++_X0;
627     if(_Y0<_Y1)
628         --_Y0;
629     else if(_Y0>_Y1)
630         --_Y1;
631     const GLfloat dx = +0.0f;
632     const GLfloat dy = +0.0f;
633 
634     _glDisable(GL_TEXTURE_2D);
635     _glMatrixMode(GL_MODELVIEW);
636     _glLoadIdentity();
637     //GLubyte r = GLubyte(_Color>>16);
638     //GLubyte g = GLubyte(_Color>>8);
639     //GLubyte b = GLubyte(_Color);
640     //GLubyte a = GLubyte(_Color>>24);
641     //_glColor4ub(GLubyte(_Color>>16), GLubyte(_Color>>8), GLubyte(_Color), GLubyte(_Color>>24));
642     //_glColor4ub(r, g, b, a);
643     _glBegin(GL_QUADS);
644         _glColor4ub(GLubyte(_Color00>>16), GLubyte(_Color00>>8), GLubyte(_Color00), GLubyte(_Color00>>24));
645         _glVertex2f((GLfloat)_X0+dx, (GLfloat)_Y0+dy);
646         _glColor4ub(GLubyte(_Color10>>16), GLubyte(_Color10>>8), GLubyte(_Color10), GLubyte(_Color10>>24));
647         _glVertex2f((GLfloat)_X1+dx, (GLfloat)_Y0+dy);
648         _glColor4ub(GLubyte(_Color11>>16), GLubyte(_Color11>>8), GLubyte(_Color11), GLubyte(_Color11>>24));
649         _glVertex2f((GLfloat)_X1+dx, (GLfloat)_Y1+dy);
650         _glColor4ub(GLubyte(_Color01>>16), GLubyte(_Color01>>8), GLubyte(_Color01), GLubyte(_Color01>>24));
651         _glVertex2f((GLfloat)_X0+dx, (GLfloat)_Y1+dy);
652     _glEnd();
653 }
654 
655 //  ---------------------------------------------------------------------------
656 
NewTextObj()657 void *CTwGraphOpenGL::NewTextObj()
658 {
659     return new CTextObj;
660 }
661 
662 //  ---------------------------------------------------------------------------
663 
DeleteTextObj(void * _TextObj)664 void CTwGraphOpenGL::DeleteTextObj(void *_TextObj)
665 {
666     assert(_TextObj!=NULL);
667     delete static_cast<CTextObj *>(_TextObj);
668 }
669 
670 //  ---------------------------------------------------------------------------
671 
BuildText(void * _TextObj,const std::string * _TextLines,color32 * _LineColors,color32 * _LineBgColors,int _NbLines,const CTexFont * _Font,int _Sep,int _BgWidth)672 void CTwGraphOpenGL::BuildText(void *_TextObj, const std::string *_TextLines, color32 *_LineColors, color32 *_LineBgColors, int _NbLines, const CTexFont *_Font, int _Sep, int _BgWidth)
673 {
674     assert(m_Drawing==true);
675     assert(_TextObj!=NULL);
676     assert(_Font!=NULL);
677 
678     if( _Font != m_FontTex )
679     {
680         UnbindFont(m_FontTexID);
681         m_FontTexID = BindFont(_Font);
682         m_FontTex = _Font;
683     }
684     CTextObj *TextObj = static_cast<CTextObj *>(_TextObj);
685     TextObj->m_TextVerts.resize(0);
686     TextObj->m_TextUVs.resize(0);
687     TextObj->m_BgVerts.resize(0);
688     TextObj->m_Colors.resize(0);
689     TextObj->m_BgColors.resize(0);
690 
691     int x, x1, y, y1, i, Len;
692     unsigned char ch;
693     const unsigned char *Text;
694     color32 LineColor = COLOR32_RED;
695     for( int Line=0; Line<_NbLines; ++Line )
696     {
697         x = 0;
698         y = Line * (_Font->m_CharHeight+_Sep);
699         y1 = y+_Font->m_CharHeight;
700         Len = (int)_TextLines[Line].length();
701         Text = (const unsigned char *)(_TextLines[Line].c_str());
702         if( _LineColors!=NULL )
703             LineColor = (_LineColors[Line]&0xff00ff00) | GLubyte(_LineColors[Line]>>16) | (GLubyte(_LineColors[Line])<<16);
704 
705         for( i=0; i<Len; ++i )
706         {
707             ch = Text[i];
708             x1 = x + _Font->m_CharWidth[ch];
709 
710             TextObj->m_TextVerts.push_back(Vec2(x , y ));
711             TextObj->m_TextVerts.push_back(Vec2(x1, y ));
712             TextObj->m_TextVerts.push_back(Vec2(x , y1));
713             TextObj->m_TextVerts.push_back(Vec2(x1, y ));
714             TextObj->m_TextVerts.push_back(Vec2(x1, y1));
715             TextObj->m_TextVerts.push_back(Vec2(x , y1));
716 
717             TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU0[ch], _Font->m_CharV0[ch]));
718             TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU1[ch], _Font->m_CharV0[ch]));
719             TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU0[ch], _Font->m_CharV1[ch]));
720             TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU1[ch], _Font->m_CharV0[ch]));
721             TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU1[ch], _Font->m_CharV1[ch]));
722             TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU0[ch], _Font->m_CharV1[ch]));
723 
724             if( _LineColors!=NULL )
725             {
726                 TextObj->m_Colors.push_back(LineColor);
727                 TextObj->m_Colors.push_back(LineColor);
728                 TextObj->m_Colors.push_back(LineColor);
729                 TextObj->m_Colors.push_back(LineColor);
730                 TextObj->m_Colors.push_back(LineColor);
731                 TextObj->m_Colors.push_back(LineColor);
732             }
733 
734             x = x1;
735         }
736         if( _BgWidth>0 )
737         {
738             TextObj->m_BgVerts.push_back(Vec2(-1        , y ));
739             TextObj->m_BgVerts.push_back(Vec2(_BgWidth+1, y ));
740             TextObj->m_BgVerts.push_back(Vec2(-1        , y1));
741             TextObj->m_BgVerts.push_back(Vec2(_BgWidth+1, y ));
742             TextObj->m_BgVerts.push_back(Vec2(_BgWidth+1, y1));
743             TextObj->m_BgVerts.push_back(Vec2(-1        , y1));
744 
745             if( _LineBgColors!=NULL )
746             {
747                 color32 LineBgColor = (_LineBgColors[Line]&0xff00ff00) | GLubyte(_LineBgColors[Line]>>16) | (GLubyte(_LineBgColors[Line])<<16);
748                 TextObj->m_BgColors.push_back(LineBgColor);
749                 TextObj->m_BgColors.push_back(LineBgColor);
750                 TextObj->m_BgColors.push_back(LineBgColor);
751                 TextObj->m_BgColors.push_back(LineBgColor);
752                 TextObj->m_BgColors.push_back(LineBgColor);
753                 TextObj->m_BgColors.push_back(LineBgColor);
754             }
755         }
756     }
757 }
758 
759 //  ---------------------------------------------------------------------------
760 
DrawText(void * _TextObj,int _X,int _Y,color32 _Color,color32 _BgColor)761 void CTwGraphOpenGL::DrawText(void *_TextObj, int _X, int _Y, color32 _Color, color32 _BgColor)
762 {
763     assert(m_Drawing==true);
764     assert(_TextObj!=NULL);
765     CTextObj *TextObj = static_cast<CTextObj *>(_TextObj);
766 
767     if( TextObj->m_TextVerts.size()<4 && TextObj->m_BgVerts.size()<4 )
768         return; // nothing to draw
769 
770     _glMatrixMode(GL_MODELVIEW);
771     _glLoadIdentity();
772     _glTranslatef((GLfloat)_X, (GLfloat)_Y, 0);
773     _glEnableClientState(GL_VERTEX_ARRAY);
774     if( (_BgColor!=0 || TextObj->m_BgColors.size()==TextObj->m_BgVerts.size()) && TextObj->m_BgVerts.size()>=4 )
775     {
776         _glDisable(GL_TEXTURE_2D);
777         _glVertexPointer(2, GL_FLOAT, 0, &(TextObj->m_BgVerts[0]));
778         if( TextObj->m_BgColors.size()==TextObj->m_BgVerts.size() && _BgColor==0 )
779         {
780             _glEnableClientState(GL_COLOR_ARRAY);
781             _glColorPointer(4, GL_UNSIGNED_BYTE, 0, &(TextObj->m_BgColors[0]));
782         }
783         else
784         {
785             _glDisableClientState(GL_COLOR_ARRAY);
786             _glColor4ub(GLubyte(_BgColor>>16), GLubyte(_BgColor>>8), GLubyte(_BgColor), GLubyte(_BgColor>>24));
787         }
788         _glDrawArrays(GL_TRIANGLES, 0, (int)TextObj->m_BgVerts.size());
789     }
790     _glEnable(GL_TEXTURE_2D);
791     _glBindTexture(GL_TEXTURE_2D, m_FontTexID);
792     _glEnableClientState(GL_TEXTURE_COORD_ARRAY);
793     if( TextObj->m_TextVerts.size()>=4 )
794     {
795         _glVertexPointer(2, GL_FLOAT, 0, &(TextObj->m_TextVerts[0]));
796         _glTexCoordPointer(2, GL_FLOAT, 0, &(TextObj->m_TextUVs[0]));
797         if( TextObj->m_Colors.size()==TextObj->m_TextVerts.size() && _Color==0 )
798         {
799             _glEnableClientState(GL_COLOR_ARRAY);
800             _glColorPointer(4, GL_UNSIGNED_BYTE, 0, &(TextObj->m_Colors[0]));
801         }
802         else
803         {
804             _glDisableClientState(GL_COLOR_ARRAY);
805             _glColor4ub(GLubyte(_Color>>16), GLubyte(_Color>>8), GLubyte(_Color), GLubyte(_Color>>24));
806         }
807 
808         _glDrawArrays(GL_TRIANGLES, 0, (int)TextObj->m_TextVerts.size());
809     }
810 
811     _glDisableClientState(GL_VERTEX_ARRAY);
812     _glDisableClientState(GL_TEXTURE_COORD_ARRAY);
813     _glDisableClientState(GL_COLOR_ARRAY);
814 }
815 
816 //  ---------------------------------------------------------------------------
817 
ChangeViewport(int _X0,int _Y0,int _Width,int _Height,int _OffsetX,int _OffsetY)818 void CTwGraphOpenGL::ChangeViewport(int _X0, int _Y0, int _Width, int _Height, int _OffsetX, int _OffsetY)
819 {
820     if( _Width>0 && _Height>0 )
821     {
822         GLint vp[4];
823         vp[0] = _X0;
824         vp[1] = _Y0;
825         vp[2] = _Width-1;
826         vp[3] = _Height-1;
827         _glViewport(vp[0], m_WndHeight-vp[1]-vp[3], vp[2], vp[3]);
828 
829         GLint matrixMode = 0;
830         _glGetIntegerv(GL_MATRIX_MODE, &matrixMode);
831         _glMatrixMode(GL_PROJECTION);
832         _glLoadIdentity();
833         _glOrtho(_OffsetX, _OffsetX+vp[2], vp[3]-_OffsetY, -_OffsetY, -1, 1);
834         _glMatrixMode(matrixMode);
835     }
836 }
837 
838 //  ---------------------------------------------------------------------------
839 
RestoreViewport()840 void CTwGraphOpenGL::RestoreViewport()
841 {
842     _glViewport(m_ViewportInit[0], m_ViewportInit[1], m_ViewportInit[2], m_ViewportInit[3]);
843 
844     GLint matrixMode = 0;
845     _glGetIntegerv(GL_MATRIX_MODE, &matrixMode);
846     _glMatrixMode(GL_PROJECTION);
847     _glLoadMatrixf(m_ProjMatrixInit);
848     _glMatrixMode(matrixMode);
849 }
850 
851 //  ---------------------------------------------------------------------------
852 
SetScissor(int _X0,int _Y0,int _Width,int _Height)853 void CTwGraphOpenGL::SetScissor(int _X0, int _Y0, int _Width, int _Height)
854 {
855     if( _Width>0 && _Height>0 )
856     {
857         _glScissor(_X0-1, m_WndHeight-_Y0-_Height, _Width-1, _Height);
858         _glEnable(GL_SCISSOR_TEST);
859     }
860     else
861         _glDisable(GL_SCISSOR_TEST);
862 }
863 
864 //  ---------------------------------------------------------------------------
865 
DrawTriangles(int _NumTriangles,int * _Vertices,color32 * _Colors,Cull _CullMode)866 void CTwGraphOpenGL::DrawTriangles(int _NumTriangles, int *_Vertices, color32 *_Colors, Cull _CullMode)
867 {
868     assert(m_Drawing==true);
869 
870     const GLfloat dx = +0.0f;
871     const GLfloat dy = +0.0f;
872 
873     GLint prevCullFaceMode, prevFrontFace;
874     _glGetIntegerv(GL_CULL_FACE_MODE, &prevCullFaceMode);
875     _glGetIntegerv(GL_FRONT_FACE, &prevFrontFace);
876     GLboolean prevCullEnable = _glIsEnabled(GL_CULL_FACE);
877     _glCullFace(GL_BACK);
878     _glEnable(GL_CULL_FACE);
879     if( _CullMode==CULL_CW )
880         _glFrontFace(GL_CCW);
881     else if( _CullMode==CULL_CCW )
882         _glFrontFace(GL_CW);
883     else
884         _glDisable(GL_CULL_FACE);
885 
886     _glDisable(GL_TEXTURE_2D);
887     _glMatrixMode(GL_MODELVIEW);
888     _glLoadIdentity();
889     _glBegin(GL_TRIANGLES);
890     for(int i=0; i<3*_NumTriangles; ++i)
891     {
892         color32 col = _Colors[i];
893         _glColor4ub(GLubyte(col>>16), GLubyte(col>>8), GLubyte(col), GLubyte(col>>24));
894         _glVertex2f((GLfloat)_Vertices[2*i+0]+dx, (GLfloat)_Vertices[2*i+1]+dy);
895     }
896     _glEnd();
897 
898     _glCullFace(prevCullFaceMode);
899     _glFrontFace(prevFrontFace);
900     if( prevCullEnable )
901         _glEnable(GL_CULL_FACE);
902     else
903         _glDisable(GL_CULL_FACE);
904 }
905 
906 //  ---------------------------------------------------------------------------
907