0023022: This is desirable to access OpenGl extensions and core API (1.2+) in one...
[occt.git] / src / OpenGl / OpenGl_Context.cxx
1 // File:      OpenGl_Context.cxx
2 // Created:   26 January 2012
3 // Author:    Kirill GAVRILOV
4 // Copyright: OPEN CASCADE 2012
5
6 #if (defined(_WIN32) || defined(__WIN32__))
7   #include <windows.h>
8 #endif
9
10 #include <OpenGl_Context.hxx>
11
12 #include <OpenGl_ArbVBO.hxx>
13 #include <OpenGl_ExtFBO.hxx>
14 #include <OpenGl_GlCore20.hxx>
15
16 #if (defined(_WIN32) || defined(__WIN32__))
17   //
18 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
19   #include <dlfcn.h>
20 #else
21   #include <GL/glx.h> // glXGetProcAddress()
22 #endif
23
24 IMPLEMENT_STANDARD_HANDLE (OpenGl_Context, Standard_Transient)
25 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Context, Standard_Transient)
26
27 //! Make record shorter to retrieve function pointer using variable with same name
28 #define FindProcShort(theStruct, theFunc) FindProc(#theFunc, theStruct->theFunc)
29
30 // =======================================================================
31 // function : OpenGl_Context
32 // purpose  :
33 // =======================================================================
34 OpenGl_Context::OpenGl_Context()
35 : core12 (NULL),
36   core13 (NULL),
37   core14 (NULL),
38   core15 (NULL),
39   core20 (NULL),
40   arbVBO (NULL),
41   extFBO (NULL),
42   myGlLibHandle (NULL),
43   myGlCore20 (NULL),
44   myGlVerMajor (0),
45   myGlVerMinor (0),
46   myIsInitialized (Standard_False)
47 {
48 #if defined(MAC_OS_X_VERSION_10_3) && !defined(MACOSX_USE_GLX)
49   // Vendors can not extend functionality on this system
50   // and developers are limited to OpenGL support provided by Mac OS X SDK.
51   // We retrieve function pointers from system library
52   // to generalize extensions support on all platforms.
53   // In this way we also reach binary compatibility benefit between OS releases
54   // if some newest functionality is optionally used.
55   // Notice that GL version / extension availability checks are required
56   // because function pointers may be available but not functionality itself
57   // (depends on renderer).
58   myGlLibHandle = dlopen ("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY);
59 #endif
60 }
61
62 // =======================================================================
63 // function : ~OpenGl_Context
64 // purpose  :
65 // =======================================================================
66 OpenGl_Context::~OpenGl_Context()
67 {
68   delete myGlCore20;
69   delete arbVBO;
70   delete extFBO;
71 }
72
73 // =======================================================================
74 // function : findProc
75 // purpose  :
76 // =======================================================================
77 void* OpenGl_Context::findProc (const char* theFuncName)
78 {
79 #if (defined(_WIN32) || defined(__WIN32__))
80   return wglGetProcAddress (theFuncName);
81 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
82   return (myGlLibHandle != NULL) ? dlsym (myGlLibHandle, theFuncName) : NULL;
83 #else
84   return (void* )glXGetProcAddress ((const GLubyte* )theFuncName);
85 #endif
86 }
87
88 // =======================================================================
89 // function : CheckExtension
90 // purpose  :
91 // =======================================================================
92 Standard_Boolean OpenGl_Context::CheckExtension (const char* theExtName)
93 {
94   if (theExtName  == NULL)
95   {
96     std::cerr << "CheckExtension called with NULL string!\n";
97     return Standard_False;
98   }
99   int anExtNameLen = strlen (theExtName);
100
101   // available since OpenGL 3.0
102   // and the ONLY way to check extensions with OpenGL 3.1+ core profile
103   /**if (IsGlUpperEqual (3, 0))
104   {
105     GLint anExtNb = 0;
106     glGetIntegerv (GL_NUM_EXTENSIONS, &anExtNb);
107     for (GLint anIter = 0; anIter < anExtNb; ++anIter)
108     {
109       const char* anExtension = (const char* )core30->glGetStringi (GL_EXTENSIONS, (GLuint )anIter);
110       if (anExtension[anExtNameLen] == '\0' &&
111           strncmp (anExtension, theExtName, anExtNameLen) == 0)
112       {
113         return Standard_True;
114       }
115     }
116     return Standard_False;
117   }*/
118
119   // use old way with huge string for all extensions
120   const char* anExtString = (const char* )glGetString (GL_EXTENSIONS);
121   if (anExtString == NULL)
122   {
123     std::cerr << "glGetString (GL_EXTENSIONS) returns NULL! No GL context?\n";
124     return Standard_False;
125   }
126
127   // Search for theExtName in the extensions string.
128   // Use of strstr() is not sufficient because extension names can be prefixes of other extension names.
129   char* aPtrIter = (char* )anExtString;
130   const char* aPtrEnd = aPtrIter + strlen (anExtString);
131   while (aPtrIter < aPtrEnd)
132   {
133     int n = strcspn (aPtrIter, " ");
134     if ((n == anExtNameLen) && (strncmp (aPtrIter, theExtName, anExtNameLen) == 0))
135     {
136       return Standard_True;
137     }
138     aPtrIter += (n + 1);
139   }
140   return Standard_False;
141 }
142
143 // =======================================================================
144 // function : Init
145 // purpose  :
146 // =======================================================================
147 void OpenGl_Context::Init()
148 {
149   if (!myIsInitialized)
150   {
151     init();
152     myIsInitialized = Standard_True;
153   }
154 }
155
156 // =======================================================================
157 // function : ResetErrors
158 // purpose  :
159 // =======================================================================
160 void OpenGl_Context::ResetErrors()
161 {
162   while (glGetError() != GL_NO_ERROR)
163   {
164     //
165   }
166 }
167
168 // =======================================================================
169 // function : readGlVersion
170 // purpose  :
171 // =======================================================================
172 void OpenGl_Context::readGlVersion()
173 {
174   // reset values
175   myGlVerMajor = 0;
176   myGlVerMinor = 0;
177
178   // available since OpenGL 3.0
179   GLint aMajor, aMinor;
180   glGetIntegerv (GL_MAJOR_VERSION, &aMajor);
181   glGetIntegerv (GL_MINOR_VERSION, &aMinor);
182   if (glGetError() == GL_NO_ERROR)
183   {
184     myGlVerMajor = aMajor;
185     myGlVerMinor = aMinor;
186     return;
187   }
188   ResetErrors();
189
190   // Read version string.
191   // Notice that only first two numbers splitted by point '2.1 XXXXX' are significant.
192   // Following trash (after space) is vendor-specific.
193   // New drivers also returns micro version of GL like '3.3.0' which has no meaning
194   // and should be considered as vendor-specific too.
195   const char* aVerStr = (const char* )glGetString (GL_VERSION);
196   if (aVerStr == NULL || *aVerStr == '\0')
197   {
198     // invalid GL context
199     return;
200   }
201
202   // parse string for major number
203   char aMajorStr[32];
204   char aMinorStr[32];
205   size_t aMajIter = 0;
206   while (aVerStr[aMajIter] >= '0' && aVerStr[aMajIter] <= '9')
207   {
208     ++aMajIter;
209   }
210   if (aMajIter == 0 || aMajIter >= sizeof(aMajorStr))
211   {
212     return;
213   }
214   memcpy (aMajorStr, aVerStr, aMajIter);
215   aMajorStr[aMajIter] = '\0';
216
217   // parse string for minor number
218   size_t aMinIter = aMajIter + 1;
219   while (aVerStr[aMinIter] >= '0' && aVerStr[aMinIter] <= '9')
220   {
221     ++aMinIter;
222   }
223   size_t aMinLen = aMinIter - aMajIter - 1;
224   if (aMinLen == 0 || aMinLen >= sizeof(aMinorStr))
225   {
226     return;
227   }
228   memcpy (aMinorStr, aVerStr, aMinLen);
229   aMinorStr[aMinLen] = '\0';
230
231   // read numbers
232   myGlVerMajor = atoi (aMajorStr);
233   myGlVerMinor = atoi (aMinorStr);
234
235   if (myGlVerMajor <= 0)
236   {
237     myGlVerMajor = 0;
238     myGlVerMinor = 0;
239   }
240 }
241
242 // =======================================================================
243 // function : init
244 // purpose  :
245 // =======================================================================
246 void OpenGl_Context::init()
247 {
248   // read version
249   readGlVersion();
250
251   // initialize VBO extension (ARB)
252   if (CheckExtension ("GL_ARB_vertex_buffer_object"))
253   {
254     arbVBO = new OpenGl_ArbVBO();
255     memset (arbVBO, 0, sizeof(OpenGl_ArbVBO)); // nullify whole structure
256     if (!FindProcShort (arbVBO, glGenBuffersARB)
257      || !FindProcShort (arbVBO, glBindBufferARB)
258      || !FindProcShort (arbVBO, glBufferDataARB)
259      || !FindProcShort (arbVBO, glDeleteBuffersARB))
260     {
261       delete arbVBO;
262       arbVBO = NULL;
263     }
264   }
265
266   // initialize FBO extension (EXT)
267   if (CheckExtension ("GL_EXT_framebuffer_object"))
268   {
269     extFBO = new OpenGl_ExtFBO();
270     memset (extFBO, 0, sizeof(OpenGl_ExtFBO)); // nullify whole structure
271     if (!FindProcShort (extFBO, glGenFramebuffersEXT)
272      || !FindProcShort (extFBO, glDeleteFramebuffersEXT)
273      || !FindProcShort (extFBO, glBindFramebufferEXT)
274      || !FindProcShort (extFBO, glFramebufferTexture2DEXT)
275      || !FindProcShort (extFBO, glCheckFramebufferStatusEXT)
276      || !FindProcShort (extFBO, glGenRenderbuffersEXT)
277      || !FindProcShort (extFBO, glDeleteRenderbuffersEXT)
278      || !FindProcShort (extFBO, glBindRenderbufferEXT)
279      || !FindProcShort (extFBO, glRenderbufferStorageEXT)
280      || !FindProcShort (extFBO, glFramebufferRenderbufferEXT))
281     {
282       delete extFBO;
283       extFBO = NULL;
284     }
285   }
286
287   myGlCore20 = new OpenGl_GlCore20();
288   memset (myGlCore20, 0, sizeof(OpenGl_GlCore20)); // nullify whole structure
289
290   // initialize OpenGL 1.2 core functionality
291   if (IsGlUpperEqual (1, 2))
292   {
293     if (!FindProcShort (myGlCore20, glBlendColor)
294      || !FindProcShort (myGlCore20, glBlendEquation)
295      || !FindProcShort (myGlCore20, glDrawRangeElements)
296      || !FindProcShort (myGlCore20, glTexImage3D)
297      || !FindProcShort (myGlCore20, glTexSubImage3D)
298      || !FindProcShort (myGlCore20, glCopyTexSubImage3D))
299     {
300       myGlVerMajor = 1;
301       myGlVerMinor = 1;
302     }
303   }
304
305   // initialize OpenGL 1.3 core functionality
306   if (IsGlUpperEqual (1, 3))
307   {
308     if (!FindProcShort (myGlCore20, glActiveTexture)
309      || !FindProcShort (myGlCore20, glSampleCoverage)
310      || !FindProcShort (myGlCore20, glCompressedTexImage3D)
311      || !FindProcShort (myGlCore20, glCompressedTexImage2D)
312      || !FindProcShort (myGlCore20, glCompressedTexImage1D)
313      || !FindProcShort (myGlCore20, glCompressedTexSubImage3D)
314      || !FindProcShort (myGlCore20, glCompressedTexSubImage2D)
315      || !FindProcShort (myGlCore20, glCompressedTexSubImage1D)
316      || !FindProcShort (myGlCore20, glGetCompressedTexImage)
317      // deprecated
318      || !FindProcShort (myGlCore20, glClientActiveTexture)
319      || !FindProcShort (myGlCore20, glMultiTexCoord1d)
320      || !FindProcShort (myGlCore20, glMultiTexCoord1dv)
321      || !FindProcShort (myGlCore20, glMultiTexCoord1f)
322      || !FindProcShort (myGlCore20, glMultiTexCoord1fv)
323      || !FindProcShort (myGlCore20, glMultiTexCoord1i)
324      || !FindProcShort (myGlCore20, glMultiTexCoord1iv)
325      || !FindProcShort (myGlCore20, glMultiTexCoord1s)
326      || !FindProcShort (myGlCore20, glMultiTexCoord1sv)
327      || !FindProcShort (myGlCore20, glMultiTexCoord2d)
328      || !FindProcShort (myGlCore20, glMultiTexCoord2dv)
329      || !FindProcShort (myGlCore20, glMultiTexCoord2f)
330      || !FindProcShort (myGlCore20, glMultiTexCoord2fv)
331      || !FindProcShort (myGlCore20, glMultiTexCoord2i)
332      || !FindProcShort (myGlCore20, glMultiTexCoord2iv)
333      || !FindProcShort (myGlCore20, glMultiTexCoord2s)
334      || !FindProcShort (myGlCore20, glMultiTexCoord2sv)
335      || !FindProcShort (myGlCore20, glMultiTexCoord3d)
336      || !FindProcShort (myGlCore20, glMultiTexCoord3dv)
337      || !FindProcShort (myGlCore20, glMultiTexCoord3f)
338      || !FindProcShort (myGlCore20, glMultiTexCoord3fv)
339      || !FindProcShort (myGlCore20, glMultiTexCoord3i)
340      || !FindProcShort (myGlCore20, glMultiTexCoord3iv)
341      || !FindProcShort (myGlCore20, glMultiTexCoord3s)
342      || !FindProcShort (myGlCore20, glMultiTexCoord3sv)
343      || !FindProcShort (myGlCore20, glMultiTexCoord4d)
344      || !FindProcShort (myGlCore20, glMultiTexCoord4dv)
345      || !FindProcShort (myGlCore20, glMultiTexCoord4f)
346      || !FindProcShort (myGlCore20, glMultiTexCoord4fv)
347      || !FindProcShort (myGlCore20, glMultiTexCoord4i)
348      || !FindProcShort (myGlCore20, glMultiTexCoord4iv)
349      || !FindProcShort (myGlCore20, glMultiTexCoord4s)
350      || !FindProcShort (myGlCore20, glMultiTexCoord4sv)
351      || !FindProcShort (myGlCore20, glLoadTransposeMatrixf)
352      || !FindProcShort (myGlCore20, glLoadTransposeMatrixd)
353      || !FindProcShort (myGlCore20, glMultTransposeMatrixf)
354      || !FindProcShort (myGlCore20, glMultTransposeMatrixd))
355     {
356       myGlVerMajor = 1;
357       myGlVerMinor = 2;
358       core12 = myGlCore20;
359     }
360   }
361
362   // initialize OpenGL 1.4 core functionality
363   if (IsGlUpperEqual (1, 4))
364   {
365     if (!FindProcShort (myGlCore20, glBlendFuncSeparate)
366      || !FindProcShort (myGlCore20, glMultiDrawArrays)
367      || !FindProcShort (myGlCore20, glMultiDrawElements)
368      || !FindProcShort (myGlCore20, glPointParameterf)
369      || !FindProcShort (myGlCore20, glPointParameterfv)
370      || !FindProcShort (myGlCore20, glPointParameteri)
371      || !FindProcShort (myGlCore20, glPointParameteriv))
372     {
373       myGlVerMajor = 1;
374       myGlVerMinor = 3;
375       core12 = myGlCore20;
376       core13 = myGlCore20;
377     }
378   }
379
380   // initialize OpenGL 1.5 core functionality
381   if (IsGlUpperEqual (1, 5))
382   {
383     if (!FindProcShort (myGlCore20, glGenQueries)
384      || !FindProcShort (myGlCore20, glDeleteQueries)
385      || !FindProcShort (myGlCore20, glIsQuery)
386      || !FindProcShort (myGlCore20, glBeginQuery)
387      || !FindProcShort (myGlCore20, glEndQuery)
388      || !FindProcShort (myGlCore20, glGetQueryiv)
389      || !FindProcShort (myGlCore20, glGetQueryObjectiv)
390      || !FindProcShort (myGlCore20, glGetQueryObjectuiv)
391      || !FindProcShort (myGlCore20, glBindBuffer)
392      || !FindProcShort (myGlCore20, glDeleteBuffers)
393      || !FindProcShort (myGlCore20, glGenBuffers)
394      || !FindProcShort (myGlCore20, glIsBuffer)
395      || !FindProcShort (myGlCore20, glBufferData)
396      || !FindProcShort (myGlCore20, glBufferSubData)
397      || !FindProcShort (myGlCore20, glGetBufferSubData)
398      || !FindProcShort (myGlCore20, glMapBuffer)
399      || !FindProcShort (myGlCore20, glUnmapBuffer)
400      || !FindProcShort (myGlCore20, glGetBufferParameteriv)
401      || !FindProcShort (myGlCore20, glGetBufferPointerv))
402     {
403       myGlVerMajor = 1;
404       myGlVerMinor = 4;
405       core12 = myGlCore20;
406       core13 = myGlCore20;
407       core14 = myGlCore20;
408     }
409   }
410
411   // initialize OpenGL 2.0 core functionality
412   if (IsGlUpperEqual (2, 0))
413   {
414     if (!FindProcShort (myGlCore20, glBlendEquationSeparate)
415      || !FindProcShort (myGlCore20, glDrawBuffers)
416      || !FindProcShort (myGlCore20, glStencilOpSeparate)
417      || !FindProcShort (myGlCore20, glStencilFuncSeparate)
418      || !FindProcShort (myGlCore20, glStencilMaskSeparate)
419      || !FindProcShort (myGlCore20, glAttachShader)
420      || !FindProcShort (myGlCore20, glBindAttribLocation)
421      || !FindProcShort (myGlCore20, glCompileShader)
422      || !FindProcShort (myGlCore20, glCreateProgram)
423      || !FindProcShort (myGlCore20, glCreateShader)
424      || !FindProcShort (myGlCore20, glDeleteProgram)
425      || !FindProcShort (myGlCore20, glDeleteShader)
426      || !FindProcShort (myGlCore20, glDetachShader)
427      || !FindProcShort (myGlCore20, glDisableVertexAttribArray)
428      || !FindProcShort (myGlCore20, glEnableVertexAttribArray)
429      || !FindProcShort (myGlCore20, glGetActiveAttrib)
430      || !FindProcShort (myGlCore20, glGetActiveUniform)
431      || !FindProcShort (myGlCore20, glGetAttachedShaders)
432      || !FindProcShort (myGlCore20, glGetAttribLocation)
433      || !FindProcShort (myGlCore20, glGetProgramiv)
434      || !FindProcShort (myGlCore20, glGetProgramInfoLog)
435      || !FindProcShort (myGlCore20, glGetShaderiv)
436      || !FindProcShort (myGlCore20, glGetShaderInfoLog)
437      || !FindProcShort (myGlCore20, glGetShaderSource)
438      || !FindProcShort (myGlCore20, glGetUniformLocation)
439      || !FindProcShort (myGlCore20, glGetUniformfv)
440      || !FindProcShort (myGlCore20, glGetUniformiv)
441      || !FindProcShort (myGlCore20, glGetVertexAttribdv)
442      || !FindProcShort (myGlCore20, glGetVertexAttribfv)
443      || !FindProcShort (myGlCore20, glGetVertexAttribiv)
444      || !FindProcShort (myGlCore20, glGetVertexAttribPointerv)
445      || !FindProcShort (myGlCore20, glIsProgram)
446      || !FindProcShort (myGlCore20, glIsShader)
447      || !FindProcShort (myGlCore20, glLinkProgram)
448      || !FindProcShort (myGlCore20, glShaderSource)
449      || !FindProcShort (myGlCore20, glUseProgram)
450      || !FindProcShort (myGlCore20, glUniform1f)
451      || !FindProcShort (myGlCore20, glUniform2f)
452      || !FindProcShort (myGlCore20, glUniform3f)
453      || !FindProcShort (myGlCore20, glUniform4f)
454      || !FindProcShort (myGlCore20, glUniform1i)
455      || !FindProcShort (myGlCore20, glUniform2i)
456      || !FindProcShort (myGlCore20, glUniform3i)
457      || !FindProcShort (myGlCore20, glUniform4i)
458      || !FindProcShort (myGlCore20, glUniform1fv)
459      || !FindProcShort (myGlCore20, glUniform2fv)
460      || !FindProcShort (myGlCore20, glUniform3fv)
461      || !FindProcShort (myGlCore20, glUniform4fv)
462      || !FindProcShort (myGlCore20, glUniform1iv)
463      || !FindProcShort (myGlCore20, glUniform2iv)
464      || !FindProcShort (myGlCore20, glUniform3iv)
465      || !FindProcShort (myGlCore20, glUniform4iv)
466      || !FindProcShort (myGlCore20, glUniformMatrix2fv)
467      || !FindProcShort (myGlCore20, glUniformMatrix3fv)
468      || !FindProcShort (myGlCore20, glUniformMatrix4fv)
469      || !FindProcShort (myGlCore20, glValidateProgram)
470      || !FindProcShort (myGlCore20, glVertexAttrib1d)
471      || !FindProcShort (myGlCore20, glVertexAttrib1dv)
472      || !FindProcShort (myGlCore20, glVertexAttrib1f)
473      || !FindProcShort (myGlCore20, glVertexAttrib1fv)
474      || !FindProcShort (myGlCore20, glVertexAttrib1s)
475      || !FindProcShort (myGlCore20, glVertexAttrib1sv)
476      || !FindProcShort (myGlCore20, glVertexAttrib2d)
477      || !FindProcShort (myGlCore20, glVertexAttrib2dv)
478      || !FindProcShort (myGlCore20, glVertexAttrib2f)
479      || !FindProcShort (myGlCore20, glVertexAttrib2fv)
480      || !FindProcShort (myGlCore20, glVertexAttrib2s)
481      || !FindProcShort (myGlCore20, glVertexAttrib2sv)
482      || !FindProcShort (myGlCore20, glVertexAttrib3d)
483      || !FindProcShort (myGlCore20, glVertexAttrib3dv)
484      || !FindProcShort (myGlCore20, glVertexAttrib3f)
485      || !FindProcShort (myGlCore20, glVertexAttrib3fv)
486      || !FindProcShort (myGlCore20, glVertexAttrib3s)
487      || !FindProcShort (myGlCore20, glVertexAttrib3sv)
488      || !FindProcShort (myGlCore20, glVertexAttrib4Nbv)
489      || !FindProcShort (myGlCore20, glVertexAttrib4Niv)
490      || !FindProcShort (myGlCore20, glVertexAttrib4Nsv)
491      || !FindProcShort (myGlCore20, glVertexAttrib4Nub)
492      || !FindProcShort (myGlCore20, glVertexAttrib4Nubv)
493      || !FindProcShort (myGlCore20, glVertexAttrib4Nuiv)
494      || !FindProcShort (myGlCore20, glVertexAttrib4Nusv)
495      || !FindProcShort (myGlCore20, glVertexAttrib4bv)
496      || !FindProcShort (myGlCore20, glVertexAttrib4d)
497      || !FindProcShort (myGlCore20, glVertexAttrib4dv)
498      || !FindProcShort (myGlCore20, glVertexAttrib4f)
499      || !FindProcShort (myGlCore20, glVertexAttrib4fv)
500      || !FindProcShort (myGlCore20, glVertexAttrib4iv)
501      || !FindProcShort (myGlCore20, glVertexAttrib4s)
502      || !FindProcShort (myGlCore20, glVertexAttrib4sv)
503      || !FindProcShort (myGlCore20, glVertexAttrib4ubv)
504      || !FindProcShort (myGlCore20, glVertexAttrib4uiv)
505      || !FindProcShort (myGlCore20, glVertexAttrib4usv)
506      || !FindProcShort (myGlCore20, glVertexAttribPointer))
507     {
508       myGlVerMajor = 1;
509       myGlVerMinor = 5;
510       core12 = myGlCore20;
511       core13 = myGlCore20;
512       core14 = myGlCore20;
513       core15 = myGlCore20;
514     }
515   }
516
517   if (IsGlUpperEqual (2, 0))
518   {
519     core12 = myGlCore20;
520     core13 = myGlCore20;
521     core14 = myGlCore20;
522     core15 = myGlCore20;
523     core20 = myGlCore20;
524   }
525 }