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