0023428: Extend OpenGl_Context to use Geometry Shaders extension
[occt.git] / src / OpenGl / OpenGl_Context.cxx
1 // Created on: 2012-01-26
2 // Created by: Kirill GAVRILOV
3 // Copyright (c) 2012-2012 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20
21 #if (defined(_WIN32) || defined(__WIN32__))
22   #include <windows.h>
23 #endif
24
25 #include <OpenGl_Context.hxx>
26
27 #include <OpenGl_ArbVBO.hxx>
28 #include <OpenGl_ArbTBO.hxx>
29 #include <OpenGl_ArbIns.hxx>
30 #include <OpenGl_ExtFBO.hxx>
31 #include <OpenGl_ExtGS.hxx>
32 #include <OpenGl_GlCore20.hxx>
33
34 #include <Standard_ProgramError.hxx>
35
36 #if (defined(_WIN32) || defined(__WIN32__))
37   //
38 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
39   #include <dlfcn.h>
40 #else
41   #include <GL/glx.h> // glXGetProcAddress()
42 #endif
43
44 // GL_NVX_gpu_memory_info
45 #ifndef GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX
46   enum
47   {
48     GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX         = 0x9047,
49     GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX   = 0x9048,
50     GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX = 0x9049,
51     GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX           = 0x904A,
52     GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX           = 0x904B
53   };
54 #endif
55
56 IMPLEMENT_STANDARD_HANDLE (OpenGl_Context, Standard_Transient)
57 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Context, Standard_Transient)
58
59 //! Make record shorter to retrieve function pointer using variable with same name
60 #define FindProcShort(theStruct, theFunc) FindProc(#theFunc, theStruct->theFunc)
61
62 namespace
63 {
64   static const Handle(OpenGl_Resource) NULL_GL_RESOURCE;
65 };
66
67 // =======================================================================
68 // function : OpenGl_Context
69 // purpose  :
70 // =======================================================================
71 OpenGl_Context::OpenGl_Context()
72 : core12 (NULL),
73   core13 (NULL),
74   core14 (NULL),
75   core15 (NULL),
76   core20 (NULL),
77   arbVBO (NULL),
78   arbTBO (NULL),
79   arbIns (NULL),
80   extFBO (NULL),
81   extGS  (NULL),
82   atiMem (Standard_False),
83   nvxMem (Standard_False),
84   mySharedResources (new OpenGl_ResourcesMap()),
85   myReleaseQueue (new OpenGl_ResourcesQueue()),
86   myGlLibHandle (NULL),
87   myGlCore20 (NULL),
88   myGlVerMajor (0),
89   myGlVerMinor (0),
90   myIsFeedback (Standard_False),
91   myIsInitialized (Standard_False)
92 {
93 #if defined(MAC_OS_X_VERSION_10_3) && !defined(MACOSX_USE_GLX)
94   // Vendors can not extend functionality on this system
95   // and developers are limited to OpenGL support provided by Mac OS X SDK.
96   // We retrieve function pointers from system library
97   // to generalize extensions support on all platforms.
98   // In this way we also reach binary compatibility benefit between OS releases
99   // if some newest functionality is optionally used.
100   // Notice that GL version / extension availability checks are required
101   // because function pointers may be available but not functionality itself
102   // (depends on renderer).
103   myGlLibHandle = dlopen ("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY);
104 #endif
105 }
106
107 // =======================================================================
108 // function : ~OpenGl_Context
109 // purpose  :
110 // =======================================================================
111 OpenGl_Context::~OpenGl_Context()
112 {
113   // release clean up queue
114   ReleaseDelayed();
115
116   // release shared resources if any
117   if (((const Handle(Standard_Transient)& )mySharedResources)->GetRefCount() <= 1)
118   {
119     for (NCollection_DataMap<TCollection_AsciiString, Handle(OpenGl_Resource)>::Iterator anIter (*mySharedResources);
120          anIter.More(); anIter.Next())
121     {
122       anIter.Value()->Release (this);
123     }
124   }
125   mySharedResources.Nullify();
126
127   delete myGlCore20;
128   delete arbVBO;
129   delete extFBO;
130   delete extGS;
131 }
132
133 // =======================================================================
134 // function : Share
135 // purpose  :
136 // =======================================================================
137 void OpenGl_Context::Share (const Handle(OpenGl_Context)& theShareCtx)
138 {
139   if (!theShareCtx.IsNull())
140   {
141     mySharedResources = theShareCtx->mySharedResources;
142     myReleaseQueue    = theShareCtx->myReleaseQueue;
143   }
144 }
145
146 // =======================================================================
147 // function : IsCurrent
148 // purpose  :
149 // =======================================================================
150 Standard_Boolean OpenGl_Context::IsCurrent() const
151 {
152 #if (defined(_WIN32) || defined(__WIN32__))
153   if (myWindowDC == NULL || myGContext == NULL)
154   {
155     return Standard_False;
156   }
157   return (( (HDC )myWindowDC == wglGetCurrentDC())
158       && ((HGLRC )myGContext == wglGetCurrentContext()));
159 #else
160   if (myDisplay == NULL || myWindow == 0 || myGContext == 0)
161   {
162     return Standard_False;
163   }
164
165   return (   ((Display* )myDisplay  == glXGetCurrentDisplay())
166        &&  ((GLXContext )myGContext == glXGetCurrentContext())
167        && ((GLXDrawable )myWindow   == glXGetCurrentDrawable()));
168 #endif
169 }
170
171 // =======================================================================
172 // function : MakeCurrent
173 // purpose  :
174 // =======================================================================
175 Standard_Boolean OpenGl_Context::MakeCurrent()
176 {
177 #if (defined(_WIN32) || defined(__WIN32__))
178   if (myWindowDC == NULL || myGContext == NULL)
179   {
180     Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called before!");
181     return Standard_False;
182   }
183
184   // technically it should be safe to activate already bound GL context
185   // however some drivers (Intel etc.) may FAIL doing this for unknown reason
186   if (IsCurrent())
187   {
188     return Standard_True;
189   }
190   else if (wglMakeCurrent ((HDC )myWindowDC, (HGLRC )myGContext) != TRUE)
191   {
192     // notice that glGetError() couldn't be used here!
193     wchar_t* aMsgBuff = NULL;
194     DWORD anErrorCode = GetLastError();
195     FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
196                     NULL, anErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (wchar_t* )&aMsgBuff, 0, NULL);
197     if (aMsgBuff != NULL)
198     {
199       std::wcerr << L"OpenGL interface: wglMakeCurrent() failed. " << aMsgBuff << L" (" << int(anErrorCode) << L")\n";
200       LocalFree (aMsgBuff);
201     }
202     else
203     {
204       std::wcerr << L"OpenGL interface: wglMakeCurrent() failed with #" << int(anErrorCode) << L" error code\n";
205     }
206     return Standard_False;
207   }
208 #else
209   if (myDisplay == NULL || myWindow == 0 || myGContext == 0)
210   {
211     Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called before!");
212     return Standard_False;
213   }
214
215   if (!glXMakeCurrent ((Display* )myDisplay, (GLXDrawable )myWindow, (GLXContext )myGContext))
216   {
217     // if there is no current context it might be impossible to use glGetError() correctly
218     //std::cerr << "glXMakeCurrent() failed!\n";
219     return Standard_False;
220   }
221 #endif
222   return Standard_True;
223 }
224
225 // =======================================================================
226 // function : SwapBuffers
227 // purpose  :
228 // =======================================================================
229 void OpenGl_Context::SwapBuffers()
230 {
231 #if (defined(_WIN32) || defined(__WIN32__))
232   if ((HDC )myWindowDC != NULL)
233   {
234     ::SwapBuffers ((HDC )myWindowDC);
235     glFlush();
236   }
237 #else
238   if ((Display* )myDisplay != NULL)
239   {
240     glXSwapBuffers ((Display* )myDisplay, (GLXDrawable )myWindow);
241   }
242 #endif
243 }
244
245 // =======================================================================
246 // function : findProc
247 // purpose  :
248 // =======================================================================
249 void* OpenGl_Context::findProc (const char* theFuncName)
250 {
251 #if (defined(_WIN32) || defined(__WIN32__))
252   return wglGetProcAddress (theFuncName);
253 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
254   return (myGlLibHandle != NULL) ? dlsym (myGlLibHandle, theFuncName) : NULL;
255 #else
256   return (void* )glXGetProcAddress ((const GLubyte* )theFuncName);
257 #endif
258 }
259
260 // =======================================================================
261 // function : CheckExtension
262 // purpose  :
263 // =======================================================================
264 Standard_Boolean OpenGl_Context::CheckExtension (const char* theExtName) const
265 {
266   if (theExtName  == NULL)
267   {
268     std::cerr << "CheckExtension called with NULL string!\n";
269     return Standard_False;
270   }
271   int anExtNameLen = strlen (theExtName);
272
273   // available since OpenGL 3.0
274   // and the ONLY way to check extensions with OpenGL 3.1+ core profile
275   /**if (IsGlGreaterEqual (3, 0))
276   {
277     GLint anExtNb = 0;
278     glGetIntegerv (GL_NUM_EXTENSIONS, &anExtNb);
279     for (GLint anIter = 0; anIter < anExtNb; ++anIter)
280     {
281       const char* anExtension = (const char* )core30->glGetStringi (GL_EXTENSIONS, (GLuint )anIter);
282       if (anExtension[anExtNameLen] == '\0' &&
283           strncmp (anExtension, theExtName, anExtNameLen) == 0)
284       {
285         return Standard_True;
286       }
287     }
288     return Standard_False;
289   }*/
290
291   // use old way with huge string for all extensions
292   const char* anExtString = (const char* )glGetString (GL_EXTENSIONS);
293   if (anExtString == NULL)
294   {
295     std::cerr << "glGetString (GL_EXTENSIONS) returns NULL! No GL context?\n";
296     return Standard_False;
297   }
298
299   // Search for theExtName in the extensions string.
300   // Use of strstr() is not sufficient because extension names can be prefixes of other extension names.
301   char* aPtrIter = (char* )anExtString;
302   const char* aPtrEnd = aPtrIter + strlen (anExtString);
303   while (aPtrIter < aPtrEnd)
304   {
305     int n = strcspn (aPtrIter, " ");
306     if ((n == anExtNameLen) && (strncmp (aPtrIter, theExtName, anExtNameLen) == 0))
307     {
308       return Standard_True;
309     }
310     aPtrIter += (n + 1);
311   }
312   return Standard_False;
313 }
314
315 // =======================================================================
316 // function : Init
317 // purpose  :
318 // =======================================================================
319 Standard_Boolean OpenGl_Context::Init()
320 {
321   if (myIsInitialized)
322   {
323     return Standard_True;
324   }
325
326 #if (defined(_WIN32) || defined(__WIN32__))
327   myWindowDC = (Aspect_Handle )wglGetCurrentDC();
328   myGContext = (Aspect_RenderingContext )wglGetCurrentContext();
329 #else
330   myDisplay  = (Aspect_Display )glXGetCurrentDisplay();
331   myGContext = (Aspect_RenderingContext )glXGetCurrentContext();
332   myWindow   = (Aspect_Drawable )glXGetCurrentDrawable();
333 #endif
334   if (myGContext == NULL)
335   {
336     return Standard_False;
337   }
338
339   init();
340   myIsInitialized = Standard_True;
341   return Standard_True;
342 }
343
344 // =======================================================================
345 // function : Init
346 // purpose  :
347 // =======================================================================
348 #if (defined(_WIN32) || defined(__WIN32__))
349 Standard_Boolean OpenGl_Context::Init (const Aspect_Handle           theWindow,
350                                        const Aspect_Handle           theWindowDC,
351                                        const Aspect_RenderingContext theGContext)
352 #else
353 Standard_Boolean OpenGl_Context::Init (const Aspect_Drawable         theWindow,
354                                        const Aspect_Display          theDisplay,
355                                        const Aspect_RenderingContext theGContext)
356 #endif
357 {
358   Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called only once!");
359
360   myWindow   = theWindow;
361   myGContext = theGContext;
362 #if (defined(_WIN32) || defined(__WIN32__))
363   myWindowDC = theWindowDC;
364 #else
365   myDisplay  = theDisplay;
366 #endif
367   if (myGContext == NULL || !MakeCurrent())
368   {
369     return Standard_False;
370   }
371
372   init();
373   myIsInitialized = Standard_True;
374   return Standard_True;
375 }
376
377 // =======================================================================
378 // function : ResetErrors
379 // purpose  :
380 // =======================================================================
381 void OpenGl_Context::ResetErrors()
382 {
383   while (glGetError() != GL_NO_ERROR)
384   {
385     //
386   }
387 }
388
389 // =======================================================================
390 // function : readGlVersion
391 // purpose  :
392 // =======================================================================
393 void OpenGl_Context::readGlVersion()
394 {
395   // reset values
396   myGlVerMajor = 0;
397   myGlVerMinor = 0;
398
399   // available since OpenGL 3.0
400   GLint aMajor, aMinor;
401   glGetIntegerv (GL_MAJOR_VERSION, &aMajor);
402   glGetIntegerv (GL_MINOR_VERSION, &aMinor);
403   if (glGetError() == GL_NO_ERROR)
404   {
405     myGlVerMajor = aMajor;
406     myGlVerMinor = aMinor;
407     return;
408   }
409   ResetErrors();
410
411   // Read version string.
412   // Notice that only first two numbers splitted by point '2.1 XXXXX' are significant.
413   // Following trash (after space) is vendor-specific.
414   // New drivers also returns micro version of GL like '3.3.0' which has no meaning
415   // and should be considered as vendor-specific too.
416   const char* aVerStr = (const char* )glGetString (GL_VERSION);
417   if (aVerStr == NULL || *aVerStr == '\0')
418   {
419     // invalid GL context
420     return;
421   }
422
423   // parse string for major number
424   char aMajorStr[32];
425   char aMinorStr[32];
426   size_t aMajIter = 0;
427   while (aVerStr[aMajIter] >= '0' && aVerStr[aMajIter] <= '9')
428   {
429     ++aMajIter;
430   }
431   if (aMajIter == 0 || aMajIter >= sizeof(aMajorStr))
432   {
433     return;
434   }
435   memcpy (aMajorStr, aVerStr, aMajIter);
436   aMajorStr[aMajIter] = '\0';
437
438   // parse string for minor number
439   size_t aMinIter = aMajIter + 1;
440   while (aVerStr[aMinIter] >= '0' && aVerStr[aMinIter] <= '9')
441   {
442     ++aMinIter;
443   }
444   size_t aMinLen = aMinIter - aMajIter - 1;
445   if (aMinLen == 0 || aMinLen >= sizeof(aMinorStr))
446   {
447     return;
448   }
449   memcpy (aMinorStr, aVerStr, aMinLen);
450   aMinorStr[aMinLen] = '\0';
451
452   // read numbers
453   myGlVerMajor = atoi (aMajorStr);
454   myGlVerMinor = atoi (aMinorStr);
455
456   if (myGlVerMajor <= 0)
457   {
458     myGlVerMajor = 0;
459     myGlVerMinor = 0;
460   }
461 }
462
463 // =======================================================================
464 // function : init
465 // purpose  :
466 // =======================================================================
467 void OpenGl_Context::init()
468 {
469   // read version
470   readGlVersion();
471
472   atiMem = CheckExtension ("GL_ATI_meminfo");
473   nvxMem = CheckExtension ("GL_NVX_gpu_memory_info");
474
475   // initialize VBO extension (ARB)
476   if (CheckExtension ("GL_ARB_vertex_buffer_object"))
477   {
478     arbVBO = new OpenGl_ArbVBO();
479     memset (arbVBO, 0, sizeof(OpenGl_ArbVBO)); // nullify whole structure
480     if (!FindProcShort (arbVBO, glGenBuffersARB)
481      || !FindProcShort (arbVBO, glBindBufferARB)
482      || !FindProcShort (arbVBO, glBufferDataARB)
483      || !FindProcShort (arbVBO, glDeleteBuffersARB))
484     {
485       delete arbVBO;
486       arbVBO = NULL;
487     }
488   }
489
490   // initialize TBO extension (ARB)
491   if (CheckExtension ("GL_ARB_texture_buffer_object"))
492   {
493     arbTBO = new OpenGl_ArbTBO();
494     memset (arbTBO, 0, sizeof(OpenGl_ArbTBO)); // nullify whole structure
495     if (!FindProcShort (arbTBO, glTexBufferARB))
496     {
497       delete arbTBO;
498       arbTBO = NULL;
499     }
500   }
501
502   // initialize hardware instancing extension (ARB)
503   if (CheckExtension ("GL_ARB_draw_instanced"))
504   {
505     arbIns = new OpenGl_ArbIns();
506     memset (arbIns, 0, sizeof(OpenGl_ArbIns)); // nullify whole structure
507     if (!FindProcShort (arbIns, glDrawArraysInstancedARB)
508      || !FindProcShort (arbIns, glDrawElementsInstancedARB))
509     {
510       delete arbIns;
511       arbIns = NULL;
512     }
513   }
514
515   // initialize FBO extension (EXT)
516   if (CheckExtension ("GL_EXT_framebuffer_object"))
517   {
518     extFBO = new OpenGl_ExtFBO();
519     memset (extFBO, 0, sizeof(OpenGl_ExtFBO)); // nullify whole structure
520     if (!FindProcShort (extFBO, glGenFramebuffersEXT)
521      || !FindProcShort (extFBO, glDeleteFramebuffersEXT)
522      || !FindProcShort (extFBO, glBindFramebufferEXT)
523      || !FindProcShort (extFBO, glFramebufferTexture2DEXT)
524      || !FindProcShort (extFBO, glCheckFramebufferStatusEXT)
525      || !FindProcShort (extFBO, glGenRenderbuffersEXT)
526      || !FindProcShort (extFBO, glDeleteRenderbuffersEXT)
527      || !FindProcShort (extFBO, glBindRenderbufferEXT)
528      || !FindProcShort (extFBO, glRenderbufferStorageEXT)
529      || !FindProcShort (extFBO, glFramebufferRenderbufferEXT))
530     {
531       delete extFBO;
532       extFBO = NULL;
533     }
534   }
535
536   // initialize GS extension (EXT)
537   if (CheckExtension ("GL_EXT_geometry_shader4"))
538   {
539     extGS = new OpenGl_ExtGS();
540     memset (extGS, 0, sizeof(OpenGl_ExtGS)); // nullify whole structure
541     if (!FindProcShort (extGS, glProgramParameteriEXT))
542     {
543       delete extGS;
544       extGS = NULL;
545     }
546   }
547
548   myGlCore20 = new OpenGl_GlCore20();
549   memset (myGlCore20, 0, sizeof(OpenGl_GlCore20)); // nullify whole structure
550
551   // initialize OpenGL 1.2 core functionality
552   if (IsGlGreaterEqual (1, 2))
553   {
554     if (!FindProcShort (myGlCore20, glBlendColor)
555      || !FindProcShort (myGlCore20, glBlendEquation)
556      || !FindProcShort (myGlCore20, glDrawRangeElements)
557      || !FindProcShort (myGlCore20, glTexImage3D)
558      || !FindProcShort (myGlCore20, glTexSubImage3D)
559      || !FindProcShort (myGlCore20, glCopyTexSubImage3D))
560     {
561       myGlVerMajor = 1;
562       myGlVerMinor = 1;
563     }
564   }
565
566   // initialize OpenGL 1.3 core functionality
567   if (IsGlGreaterEqual (1, 3))
568   {
569     if (!FindProcShort (myGlCore20, glActiveTexture)
570      || !FindProcShort (myGlCore20, glSampleCoverage)
571      || !FindProcShort (myGlCore20, glCompressedTexImage3D)
572      || !FindProcShort (myGlCore20, glCompressedTexImage2D)
573      || !FindProcShort (myGlCore20, glCompressedTexImage1D)
574      || !FindProcShort (myGlCore20, glCompressedTexSubImage3D)
575      || !FindProcShort (myGlCore20, glCompressedTexSubImage2D)
576      || !FindProcShort (myGlCore20, glCompressedTexSubImage1D)
577      || !FindProcShort (myGlCore20, glGetCompressedTexImage)
578      // deprecated
579      || !FindProcShort (myGlCore20, glClientActiveTexture)
580      || !FindProcShort (myGlCore20, glMultiTexCoord1d)
581      || !FindProcShort (myGlCore20, glMultiTexCoord1dv)
582      || !FindProcShort (myGlCore20, glMultiTexCoord1f)
583      || !FindProcShort (myGlCore20, glMultiTexCoord1fv)
584      || !FindProcShort (myGlCore20, glMultiTexCoord1i)
585      || !FindProcShort (myGlCore20, glMultiTexCoord1iv)
586      || !FindProcShort (myGlCore20, glMultiTexCoord1s)
587      || !FindProcShort (myGlCore20, glMultiTexCoord1sv)
588      || !FindProcShort (myGlCore20, glMultiTexCoord2d)
589      || !FindProcShort (myGlCore20, glMultiTexCoord2dv)
590      || !FindProcShort (myGlCore20, glMultiTexCoord2f)
591      || !FindProcShort (myGlCore20, glMultiTexCoord2fv)
592      || !FindProcShort (myGlCore20, glMultiTexCoord2i)
593      || !FindProcShort (myGlCore20, glMultiTexCoord2iv)
594      || !FindProcShort (myGlCore20, glMultiTexCoord2s)
595      || !FindProcShort (myGlCore20, glMultiTexCoord2sv)
596      || !FindProcShort (myGlCore20, glMultiTexCoord3d)
597      || !FindProcShort (myGlCore20, glMultiTexCoord3dv)
598      || !FindProcShort (myGlCore20, glMultiTexCoord3f)
599      || !FindProcShort (myGlCore20, glMultiTexCoord3fv)
600      || !FindProcShort (myGlCore20, glMultiTexCoord3i)
601      || !FindProcShort (myGlCore20, glMultiTexCoord3iv)
602      || !FindProcShort (myGlCore20, glMultiTexCoord3s)
603      || !FindProcShort (myGlCore20, glMultiTexCoord3sv)
604      || !FindProcShort (myGlCore20, glMultiTexCoord4d)
605      || !FindProcShort (myGlCore20, glMultiTexCoord4dv)
606      || !FindProcShort (myGlCore20, glMultiTexCoord4f)
607      || !FindProcShort (myGlCore20, glMultiTexCoord4fv)
608      || !FindProcShort (myGlCore20, glMultiTexCoord4i)
609      || !FindProcShort (myGlCore20, glMultiTexCoord4iv)
610      || !FindProcShort (myGlCore20, glMultiTexCoord4s)
611      || !FindProcShort (myGlCore20, glMultiTexCoord4sv)
612      || !FindProcShort (myGlCore20, glLoadTransposeMatrixf)
613      || !FindProcShort (myGlCore20, glLoadTransposeMatrixd)
614      || !FindProcShort (myGlCore20, glMultTransposeMatrixf)
615      || !FindProcShort (myGlCore20, glMultTransposeMatrixd))
616     {
617       myGlVerMajor = 1;
618       myGlVerMinor = 2;
619       core12 = myGlCore20;
620     }
621   }
622
623   // initialize OpenGL 1.4 core functionality
624   if (IsGlGreaterEqual (1, 4))
625   {
626     if (!FindProcShort (myGlCore20, glBlendFuncSeparate)
627      || !FindProcShort (myGlCore20, glMultiDrawArrays)
628      || !FindProcShort (myGlCore20, glMultiDrawElements)
629      || !FindProcShort (myGlCore20, glPointParameterf)
630      || !FindProcShort (myGlCore20, glPointParameterfv)
631      || !FindProcShort (myGlCore20, glPointParameteri)
632      || !FindProcShort (myGlCore20, glPointParameteriv))
633     {
634       myGlVerMajor = 1;
635       myGlVerMinor = 3;
636       core12 = myGlCore20;
637       core13 = myGlCore20;
638     }
639   }
640
641   // initialize OpenGL 1.5 core functionality
642   if (IsGlGreaterEqual (1, 5))
643   {
644     if (!FindProcShort (myGlCore20, glGenQueries)
645      || !FindProcShort (myGlCore20, glDeleteQueries)
646      || !FindProcShort (myGlCore20, glIsQuery)
647      || !FindProcShort (myGlCore20, glBeginQuery)
648      || !FindProcShort (myGlCore20, glEndQuery)
649      || !FindProcShort (myGlCore20, glGetQueryiv)
650      || !FindProcShort (myGlCore20, glGetQueryObjectiv)
651      || !FindProcShort (myGlCore20, glGetQueryObjectuiv)
652      || !FindProcShort (myGlCore20, glBindBuffer)
653      || !FindProcShort (myGlCore20, glDeleteBuffers)
654      || !FindProcShort (myGlCore20, glGenBuffers)
655      || !FindProcShort (myGlCore20, glIsBuffer)
656      || !FindProcShort (myGlCore20, glBufferData)
657      || !FindProcShort (myGlCore20, glBufferSubData)
658      || !FindProcShort (myGlCore20, glGetBufferSubData)
659      || !FindProcShort (myGlCore20, glMapBuffer)
660      || !FindProcShort (myGlCore20, glUnmapBuffer)
661      || !FindProcShort (myGlCore20, glGetBufferParameteriv)
662      || !FindProcShort (myGlCore20, glGetBufferPointerv))
663     {
664       myGlVerMajor = 1;
665       myGlVerMinor = 4;
666       core12 = myGlCore20;
667       core13 = myGlCore20;
668       core14 = myGlCore20;
669     }
670   }
671
672   // initialize OpenGL 2.0 core functionality
673   if (IsGlGreaterEqual (2, 0))
674   {
675     if (!FindProcShort (myGlCore20, glBlendEquationSeparate)
676      || !FindProcShort (myGlCore20, glDrawBuffers)
677      || !FindProcShort (myGlCore20, glStencilOpSeparate)
678      || !FindProcShort (myGlCore20, glStencilFuncSeparate)
679      || !FindProcShort (myGlCore20, glStencilMaskSeparate)
680      || !FindProcShort (myGlCore20, glAttachShader)
681      || !FindProcShort (myGlCore20, glBindAttribLocation)
682      || !FindProcShort (myGlCore20, glCompileShader)
683      || !FindProcShort (myGlCore20, glCreateProgram)
684      || !FindProcShort (myGlCore20, glCreateShader)
685      || !FindProcShort (myGlCore20, glDeleteProgram)
686      || !FindProcShort (myGlCore20, glDeleteShader)
687      || !FindProcShort (myGlCore20, glDetachShader)
688      || !FindProcShort (myGlCore20, glDisableVertexAttribArray)
689      || !FindProcShort (myGlCore20, glEnableVertexAttribArray)
690      || !FindProcShort (myGlCore20, glGetActiveAttrib)
691      || !FindProcShort (myGlCore20, glGetActiveUniform)
692      || !FindProcShort (myGlCore20, glGetAttachedShaders)
693      || !FindProcShort (myGlCore20, glGetAttribLocation)
694      || !FindProcShort (myGlCore20, glGetProgramiv)
695      || !FindProcShort (myGlCore20, glGetProgramInfoLog)
696      || !FindProcShort (myGlCore20, glGetShaderiv)
697      || !FindProcShort (myGlCore20, glGetShaderInfoLog)
698      || !FindProcShort (myGlCore20, glGetShaderSource)
699      || !FindProcShort (myGlCore20, glGetUniformLocation)
700      || !FindProcShort (myGlCore20, glGetUniformfv)
701      || !FindProcShort (myGlCore20, glGetUniformiv)
702      || !FindProcShort (myGlCore20, glGetVertexAttribdv)
703      || !FindProcShort (myGlCore20, glGetVertexAttribfv)
704      || !FindProcShort (myGlCore20, glGetVertexAttribiv)
705      || !FindProcShort (myGlCore20, glGetVertexAttribPointerv)
706      || !FindProcShort (myGlCore20, glIsProgram)
707      || !FindProcShort (myGlCore20, glIsShader)
708      || !FindProcShort (myGlCore20, glLinkProgram)
709      || !FindProcShort (myGlCore20, glShaderSource)
710      || !FindProcShort (myGlCore20, glUseProgram)
711      || !FindProcShort (myGlCore20, glUniform1f)
712      || !FindProcShort (myGlCore20, glUniform2f)
713      || !FindProcShort (myGlCore20, glUniform3f)
714      || !FindProcShort (myGlCore20, glUniform4f)
715      || !FindProcShort (myGlCore20, glUniform1i)
716      || !FindProcShort (myGlCore20, glUniform2i)
717      || !FindProcShort (myGlCore20, glUniform3i)
718      || !FindProcShort (myGlCore20, glUniform4i)
719      || !FindProcShort (myGlCore20, glUniform1fv)
720      || !FindProcShort (myGlCore20, glUniform2fv)
721      || !FindProcShort (myGlCore20, glUniform3fv)
722      || !FindProcShort (myGlCore20, glUniform4fv)
723      || !FindProcShort (myGlCore20, glUniform1iv)
724      || !FindProcShort (myGlCore20, glUniform2iv)
725      || !FindProcShort (myGlCore20, glUniform3iv)
726      || !FindProcShort (myGlCore20, glUniform4iv)
727      || !FindProcShort (myGlCore20, glUniformMatrix2fv)
728      || !FindProcShort (myGlCore20, glUniformMatrix3fv)
729      || !FindProcShort (myGlCore20, glUniformMatrix4fv)
730      || !FindProcShort (myGlCore20, glValidateProgram)
731      || !FindProcShort (myGlCore20, glVertexAttrib1d)
732      || !FindProcShort (myGlCore20, glVertexAttrib1dv)
733      || !FindProcShort (myGlCore20, glVertexAttrib1f)
734      || !FindProcShort (myGlCore20, glVertexAttrib1fv)
735      || !FindProcShort (myGlCore20, glVertexAttrib1s)
736      || !FindProcShort (myGlCore20, glVertexAttrib1sv)
737      || !FindProcShort (myGlCore20, glVertexAttrib2d)
738      || !FindProcShort (myGlCore20, glVertexAttrib2dv)
739      || !FindProcShort (myGlCore20, glVertexAttrib2f)
740      || !FindProcShort (myGlCore20, glVertexAttrib2fv)
741      || !FindProcShort (myGlCore20, glVertexAttrib2s)
742      || !FindProcShort (myGlCore20, glVertexAttrib2sv)
743      || !FindProcShort (myGlCore20, glVertexAttrib3d)
744      || !FindProcShort (myGlCore20, glVertexAttrib3dv)
745      || !FindProcShort (myGlCore20, glVertexAttrib3f)
746      || !FindProcShort (myGlCore20, glVertexAttrib3fv)
747      || !FindProcShort (myGlCore20, glVertexAttrib3s)
748      || !FindProcShort (myGlCore20, glVertexAttrib3sv)
749      || !FindProcShort (myGlCore20, glVertexAttrib4Nbv)
750      || !FindProcShort (myGlCore20, glVertexAttrib4Niv)
751      || !FindProcShort (myGlCore20, glVertexAttrib4Nsv)
752      || !FindProcShort (myGlCore20, glVertexAttrib4Nub)
753      || !FindProcShort (myGlCore20, glVertexAttrib4Nubv)
754      || !FindProcShort (myGlCore20, glVertexAttrib4Nuiv)
755      || !FindProcShort (myGlCore20, glVertexAttrib4Nusv)
756      || !FindProcShort (myGlCore20, glVertexAttrib4bv)
757      || !FindProcShort (myGlCore20, glVertexAttrib4d)
758      || !FindProcShort (myGlCore20, glVertexAttrib4dv)
759      || !FindProcShort (myGlCore20, glVertexAttrib4f)
760      || !FindProcShort (myGlCore20, glVertexAttrib4fv)
761      || !FindProcShort (myGlCore20, glVertexAttrib4iv)
762      || !FindProcShort (myGlCore20, glVertexAttrib4s)
763      || !FindProcShort (myGlCore20, glVertexAttrib4sv)
764      || !FindProcShort (myGlCore20, glVertexAttrib4ubv)
765      || !FindProcShort (myGlCore20, glVertexAttrib4uiv)
766      || !FindProcShort (myGlCore20, glVertexAttrib4usv)
767      || !FindProcShort (myGlCore20, glVertexAttribPointer))
768     {
769       myGlVerMajor = 1;
770       myGlVerMinor = 5;
771       core12 = myGlCore20;
772       core13 = myGlCore20;
773       core14 = myGlCore20;
774       core15 = myGlCore20;
775     }
776   }
777
778   if (IsGlGreaterEqual (2, 0))
779   {
780     core12 = myGlCore20;
781     core13 = myGlCore20;
782     core14 = myGlCore20;
783     core15 = myGlCore20;
784     core20 = myGlCore20;
785   }
786 }
787 // =======================================================================
788 // function : IsFeedback
789 // purpose  :
790 // =======================================================================
791 Standard_Boolean OpenGl_Context::IsFeedback() const
792 {
793   return myIsFeedback;
794 }
795
796 // =======================================================================
797 // function : SetFeedback
798 // purpose  :
799 // =======================================================================
800 void OpenGl_Context::SetFeedback (const Standard_Boolean theFeedbackOn)
801 {
802   myIsFeedback = theFeedbackOn;
803 }
804
805 // =======================================================================
806 // function : MemoryInfo
807 // purpose  :
808 // =======================================================================
809 Standard_Size OpenGl_Context::AvailableMemory() const
810 {
811   if (atiMem)
812   {
813     // this is actually information for VBO pool
814     // however because pools are mostly shared
815     // it can be used for total GPU memory estimations
816     GLint aMemInfo[4];
817     aMemInfo[0] = 0;
818     glGetIntegerv (GL_VBO_FREE_MEMORY_ATI, aMemInfo);
819     // returned value is in KiB, however this maybe changed in future
820     return Standard_Size(aMemInfo[0]) * 1024;
821   }
822   else if (nvxMem)
823   {
824     // current available dedicated video memory (in KiB), currently unused GPU memory
825     GLint aMemInfo = 0;
826     glGetIntegerv (GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &aMemInfo);
827     return Standard_Size(aMemInfo) * 1024;
828   }
829   return 0;
830 }
831
832 // =======================================================================
833 // function : MemoryInfo
834 // purpose  :
835 // =======================================================================
836 TCollection_AsciiString OpenGl_Context::MemoryInfo() const
837 {
838   TCollection_AsciiString anInfo;
839   if (atiMem)
840   {
841     GLint aValues[4];
842     memset (aValues, 0, sizeof(aValues));
843     glGetIntegerv (GL_VBO_FREE_MEMORY_ATI, aValues);
844
845     // total memory free in the pool
846     anInfo += TCollection_AsciiString ("  GPU free memory:    ") + (aValues[0] / 1024) + " MiB\n";
847
848     // largest available free block in the pool
849     anInfo += TCollection_AsciiString ("  Largest free block: ") + (aValues[1] / 1024) + " MiB\n";
850     if (aValues[2] != aValues[0])
851     {
852       // total auxiliary memory free
853       anInfo += TCollection_AsciiString ("  Free memory:        ") + (aValues[2] / 1024) + " MiB\n";
854     }
855   }
856   else if (nvxMem)
857   {
858     //current available dedicated video memory (in KiB), currently unused GPU memory
859     GLint aValue = 0;
860     glGetIntegerv (GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &aValue);
861     anInfo += TCollection_AsciiString ("  GPU free memory:    ") + (aValue / 1024) + " MiB\n";
862
863     // dedicated video memory, total size (in KiB) of the GPU memory
864     GLint aDedicated = 0;
865     glGetIntegerv (GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, &aDedicated);
866     anInfo += TCollection_AsciiString ("  GPU memory:         ") + (aDedicated / 1024) + " MiB\n";
867
868     // total available memory, total size (in KiB) of the memory available for allocations
869     glGetIntegerv (GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, &aValue);
870     if (aValue != aDedicated)
871     {
872       // different only for special configurations
873       anInfo += TCollection_AsciiString ("  Total memory:       ") + (aValue / 1024) + " MiB\n";
874     }
875   }
876   return anInfo;
877 }
878
879
880 // =======================================================================
881 // function : GetResource
882 // purpose  :
883 // =======================================================================
884 const Handle(OpenGl_Resource)& OpenGl_Context::GetResource (const TCollection_AsciiString& theKey) const
885 {
886   return mySharedResources->IsBound (theKey) ? mySharedResources->Find (theKey) : NULL_GL_RESOURCE;
887 }
888
889 // =======================================================================
890 // function : ShareResource
891 // purpose  :
892 // =======================================================================
893 Standard_Boolean OpenGl_Context::ShareResource (const TCollection_AsciiString& theKey,
894                                                 const Handle(OpenGl_Resource)& theResource)
895 {
896   if (theKey.IsEmpty() || theResource.IsNull())
897   {
898     return Standard_False;
899   }
900   return mySharedResources->Bind (theKey, theResource);
901 }
902
903 // =======================================================================
904 // function : ReleaseResource
905 // purpose  :
906 // =======================================================================
907 void OpenGl_Context::ReleaseResource (const TCollection_AsciiString& theKey)
908 {
909   if (!mySharedResources->IsBound (theKey))
910   {
911     return;
912   }
913   const Handle(OpenGl_Resource)& aRes = mySharedResources->Find (theKey);
914   if (aRes->GetRefCount() > 1)
915   {
916     return;
917   }
918
919   aRes->Release (this);
920   mySharedResources->UnBind (theKey);
921 }
922
923 // =======================================================================
924 // function : DelayedRelease
925 // purpose  :
926 // =======================================================================
927 void OpenGl_Context::DelayedRelease (Handle(OpenGl_Resource)& theResource)
928 {
929   myReleaseQueue->Push (theResource);
930   theResource.Nullify();
931 }
932
933 // =======================================================================
934 // function : ReleaseDelayed
935 // purpose  :
936 // =======================================================================
937 void OpenGl_Context::ReleaseDelayed()
938 {
939   while (!myReleaseQueue->IsEmpty())
940   {
941     myReleaseQueue->Front()->Release (this);
942     myReleaseQueue->Pop();
943   }
944 }