0023418: Crash on the object displaying when running DRAW on remote station. OpenGL...
[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 = 0, aMinor = 0;
401   glGetIntegerv (GL_MAJOR_VERSION, &aMajor);
402   glGetIntegerv (GL_MINOR_VERSION, &aMinor);
403   // glGetError() sometimes does not report an error here even if 
404   // GL does not know GL_MAJOR_VERSION and GL_MINOR_VERSION constants.
405   // This happens on some rendereres like e.g. Cygwin MESA.
406   // Thus checking additionally if GL has put anything to
407   // the output variables.
408   if (glGetError() == GL_NO_ERROR && aMajor != 0 && aMinor != 0)
409   {
410     myGlVerMajor = aMajor;
411     myGlVerMinor = aMinor;
412     return;
413   }
414   ResetErrors();
415
416   // Read version string.
417   // Notice that only first two numbers splitted by point '2.1 XXXXX' are significant.
418   // Following trash (after space) is vendor-specific.
419   // New drivers also returns micro version of GL like '3.3.0' which has no meaning
420   // and should be considered as vendor-specific too.
421   const char* aVerStr = (const char* )glGetString (GL_VERSION);
422   if (aVerStr == NULL || *aVerStr == '\0')
423   {
424     // invalid GL context
425     return;
426   }
427
428   // parse string for major number
429   char aMajorStr[32];
430   char aMinorStr[32];
431   size_t aMajIter = 0;
432   while (aVerStr[aMajIter] >= '0' && aVerStr[aMajIter] <= '9')
433   {
434     ++aMajIter;
435   }
436   if (aMajIter == 0 || aMajIter >= sizeof(aMajorStr))
437   {
438     return;
439   }
440   memcpy (aMajorStr, aVerStr, aMajIter);
441   aMajorStr[aMajIter] = '\0';
442
443   // parse string for minor number
444   aVerStr += aMajIter + 1;
445   size_t aMinIter = 0;
446   while (aVerStr[aMinIter] >= '0' && aVerStr[aMinIter] <= '9')
447   {
448     ++aMinIter;
449   }
450   if (aMinIter == 0 || aMinIter >= sizeof(aMinorStr))
451   {
452     return;
453   }
454   memcpy (aMinorStr, aVerStr, aMinIter);
455   aMinorStr[aMinIter] = '\0';
456
457   // read numbers
458   myGlVerMajor = atoi (aMajorStr);
459   myGlVerMinor = atoi (aMinorStr);
460
461   if (myGlVerMajor <= 0)
462   {
463     myGlVerMajor = 0;
464     myGlVerMinor = 0;
465   }
466 }
467
468 // =======================================================================
469 // function : init
470 // purpose  :
471 // =======================================================================
472 void OpenGl_Context::init()
473 {
474   // read version
475   readGlVersion();
476
477   atiMem = CheckExtension ("GL_ATI_meminfo");
478   nvxMem = CheckExtension ("GL_NVX_gpu_memory_info");
479
480   // initialize VBO extension (ARB)
481   if (CheckExtension ("GL_ARB_vertex_buffer_object"))
482   {
483     arbVBO = new OpenGl_ArbVBO();
484     memset (arbVBO, 0, sizeof(OpenGl_ArbVBO)); // nullify whole structure
485     if (!FindProcShort (arbVBO, glGenBuffersARB)
486      || !FindProcShort (arbVBO, glBindBufferARB)
487      || !FindProcShort (arbVBO, glBufferDataARB)
488      || !FindProcShort (arbVBO, glDeleteBuffersARB))
489     {
490       delete arbVBO;
491       arbVBO = NULL;
492     }
493   }
494
495   // initialize TBO extension (ARB)
496   if (CheckExtension ("GL_ARB_texture_buffer_object"))
497   {
498     arbTBO = new OpenGl_ArbTBO();
499     memset (arbTBO, 0, sizeof(OpenGl_ArbTBO)); // nullify whole structure
500     if (!FindProcShort (arbTBO, glTexBufferARB))
501     {
502       delete arbTBO;
503       arbTBO = NULL;
504     }
505   }
506
507   // initialize hardware instancing extension (ARB)
508   if (CheckExtension ("GL_ARB_draw_instanced"))
509   {
510     arbIns = new OpenGl_ArbIns();
511     memset (arbIns, 0, sizeof(OpenGl_ArbIns)); // nullify whole structure
512     if (!FindProcShort (arbIns, glDrawArraysInstancedARB)
513      || !FindProcShort (arbIns, glDrawElementsInstancedARB))
514     {
515       delete arbIns;
516       arbIns = NULL;
517     }
518   }
519
520   // initialize FBO extension (EXT)
521   if (CheckExtension ("GL_EXT_framebuffer_object"))
522   {
523     extFBO = new OpenGl_ExtFBO();
524     memset (extFBO, 0, sizeof(OpenGl_ExtFBO)); // nullify whole structure
525     if (!FindProcShort (extFBO, glGenFramebuffersEXT)
526      || !FindProcShort (extFBO, glDeleteFramebuffersEXT)
527      || !FindProcShort (extFBO, glBindFramebufferEXT)
528      || !FindProcShort (extFBO, glFramebufferTexture2DEXT)
529      || !FindProcShort (extFBO, glCheckFramebufferStatusEXT)
530      || !FindProcShort (extFBO, glGenRenderbuffersEXT)
531      || !FindProcShort (extFBO, glDeleteRenderbuffersEXT)
532      || !FindProcShort (extFBO, glBindRenderbufferEXT)
533      || !FindProcShort (extFBO, glRenderbufferStorageEXT)
534      || !FindProcShort (extFBO, glFramebufferRenderbufferEXT))
535     {
536       delete extFBO;
537       extFBO = NULL;
538     }
539   }
540
541   // initialize GS extension (EXT)
542   if (CheckExtension ("GL_EXT_geometry_shader4"))
543   {
544     extGS = new OpenGl_ExtGS();
545     memset (extGS, 0, sizeof(OpenGl_ExtGS)); // nullify whole structure
546     if (!FindProcShort (extGS, glProgramParameteriEXT))
547     {
548       delete extGS;
549       extGS = NULL;
550     }
551   }
552
553   myGlCore20 = new OpenGl_GlCore20();
554   memset (myGlCore20, 0, sizeof(OpenGl_GlCore20)); // nullify whole structure
555
556   // Check if OpenGL 1.2 core functionality is actually present
557   Standard_Boolean hasGlCore12 = IsGlGreaterEqual (1, 2)
558     && FindProcShort (myGlCore20, glBlendColor)
559     && FindProcShort (myGlCore20, glBlendEquation)
560     && FindProcShort (myGlCore20, glDrawRangeElements)
561     && FindProcShort (myGlCore20, glTexImage3D)
562     && FindProcShort (myGlCore20, glTexSubImage3D)
563     && FindProcShort (myGlCore20, glCopyTexSubImage3D);
564
565   // Check if OpenGL 1.3 core functionality is actually present
566   Standard_Boolean hasGlCore13 = IsGlGreaterEqual (1, 3)
567     && FindProcShort (myGlCore20, glActiveTexture)
568     && FindProcShort (myGlCore20, glSampleCoverage)
569     && FindProcShort (myGlCore20, glCompressedTexImage3D)
570     && FindProcShort (myGlCore20, glCompressedTexImage2D)
571     && FindProcShort (myGlCore20, glCompressedTexImage1D)
572     && FindProcShort (myGlCore20, glCompressedTexSubImage3D)
573     && FindProcShort (myGlCore20, glCompressedTexSubImage2D)
574     && FindProcShort (myGlCore20, glCompressedTexSubImage1D)
575     && FindProcShort (myGlCore20, glGetCompressedTexImage)
576      // deprecated
577     && FindProcShort (myGlCore20, glClientActiveTexture)
578     && FindProcShort (myGlCore20, glMultiTexCoord1d)
579     && FindProcShort (myGlCore20, glMultiTexCoord1dv)
580     && FindProcShort (myGlCore20, glMultiTexCoord1f)
581     && FindProcShort (myGlCore20, glMultiTexCoord1fv)
582     && FindProcShort (myGlCore20, glMultiTexCoord1i)
583     && FindProcShort (myGlCore20, glMultiTexCoord1iv)
584     && FindProcShort (myGlCore20, glMultiTexCoord1s)
585     && FindProcShort (myGlCore20, glMultiTexCoord1sv)
586     && FindProcShort (myGlCore20, glMultiTexCoord2d)
587     && FindProcShort (myGlCore20, glMultiTexCoord2dv)
588     && FindProcShort (myGlCore20, glMultiTexCoord2f)
589     && FindProcShort (myGlCore20, glMultiTexCoord2fv)
590     && FindProcShort (myGlCore20, glMultiTexCoord2i)
591     && FindProcShort (myGlCore20, glMultiTexCoord2iv)
592     && FindProcShort (myGlCore20, glMultiTexCoord2s)
593     && FindProcShort (myGlCore20, glMultiTexCoord2sv)
594     && FindProcShort (myGlCore20, glMultiTexCoord3d)
595     && FindProcShort (myGlCore20, glMultiTexCoord3dv)
596     && FindProcShort (myGlCore20, glMultiTexCoord3f)
597     && FindProcShort (myGlCore20, glMultiTexCoord3fv)
598     && FindProcShort (myGlCore20, glMultiTexCoord3i)
599     && FindProcShort (myGlCore20, glMultiTexCoord3iv)
600     && FindProcShort (myGlCore20, glMultiTexCoord3s)
601     && FindProcShort (myGlCore20, glMultiTexCoord3sv)
602     && FindProcShort (myGlCore20, glMultiTexCoord4d)
603     && FindProcShort (myGlCore20, glMultiTexCoord4dv)
604     && FindProcShort (myGlCore20, glMultiTexCoord4f)
605     && FindProcShort (myGlCore20, glMultiTexCoord4fv)
606     && FindProcShort (myGlCore20, glMultiTexCoord4i)
607     && FindProcShort (myGlCore20, glMultiTexCoord4iv)
608     && FindProcShort (myGlCore20, glMultiTexCoord4s)
609     && FindProcShort (myGlCore20, glMultiTexCoord4sv)
610     && FindProcShort (myGlCore20, glLoadTransposeMatrixf)
611     && FindProcShort (myGlCore20, glLoadTransposeMatrixd)
612     && FindProcShort (myGlCore20, glMultTransposeMatrixf)
613     && FindProcShort (myGlCore20, glMultTransposeMatrixd);
614   
615   // Check if OpenGL 1.4 core functionality is actually present
616   Standard_Boolean hasGlCore14 = IsGlGreaterEqual (1, 4)
617     && FindProcShort (myGlCore20, glBlendFuncSeparate)
618     && FindProcShort (myGlCore20, glMultiDrawArrays)
619     && FindProcShort (myGlCore20, glMultiDrawElements)
620     && FindProcShort (myGlCore20, glPointParameterf)
621     && FindProcShort (myGlCore20, glPointParameterfv)
622     && FindProcShort (myGlCore20, glPointParameteri)
623     && FindProcShort (myGlCore20, glPointParameteriv);
624
625   // Check if OpenGL 1.5 core functionality is actually present
626   Standard_Boolean hasGlCore15 = IsGlGreaterEqual (1, 5)
627     && FindProcShort (myGlCore20, glGenQueries)
628     && FindProcShort (myGlCore20, glDeleteQueries)
629     && FindProcShort (myGlCore20, glIsQuery)
630     && FindProcShort (myGlCore20, glBeginQuery)
631     && FindProcShort (myGlCore20, glEndQuery)
632     && FindProcShort (myGlCore20, glGetQueryiv)
633     && FindProcShort (myGlCore20, glGetQueryObjectiv)
634     && FindProcShort (myGlCore20, glGetQueryObjectuiv)
635     && FindProcShort (myGlCore20, glBindBuffer)
636     && FindProcShort (myGlCore20, glDeleteBuffers)
637     && FindProcShort (myGlCore20, glGenBuffers)
638     && FindProcShort (myGlCore20, glIsBuffer)
639     && FindProcShort (myGlCore20, glBufferData)
640     && FindProcShort (myGlCore20, glBufferSubData)
641     && FindProcShort (myGlCore20, glGetBufferSubData)
642     && FindProcShort (myGlCore20, glMapBuffer)
643     && FindProcShort (myGlCore20, glUnmapBuffer)
644     && FindProcShort (myGlCore20, glGetBufferParameteriv)
645     && FindProcShort (myGlCore20, glGetBufferPointerv);
646
647   // Check if OpenGL 2.0 core functionality is actually present
648   Standard_Boolean hasGlCore20 = IsGlGreaterEqual (2, 0)
649     && FindProcShort (myGlCore20, glBlendEquationSeparate)
650     && FindProcShort (myGlCore20, glDrawBuffers)
651     && FindProcShort (myGlCore20, glStencilOpSeparate)
652     && FindProcShort (myGlCore20, glStencilFuncSeparate)
653     && FindProcShort (myGlCore20, glStencilMaskSeparate)
654     && FindProcShort (myGlCore20, glAttachShader)
655     && FindProcShort (myGlCore20, glBindAttribLocation)
656     && FindProcShort (myGlCore20, glCompileShader)
657     && FindProcShort (myGlCore20, glCreateProgram)
658     && FindProcShort (myGlCore20, glCreateShader)
659     && FindProcShort (myGlCore20, glDeleteProgram)
660     && FindProcShort (myGlCore20, glDeleteShader)
661     && FindProcShort (myGlCore20, glDetachShader)
662     && FindProcShort (myGlCore20, glDisableVertexAttribArray)
663     && FindProcShort (myGlCore20, glEnableVertexAttribArray)
664     && FindProcShort (myGlCore20, glGetActiveAttrib)
665     && FindProcShort (myGlCore20, glGetActiveUniform)
666     && FindProcShort (myGlCore20, glGetAttachedShaders)
667     && FindProcShort (myGlCore20, glGetAttribLocation)
668     && FindProcShort (myGlCore20, glGetProgramiv)
669     && FindProcShort (myGlCore20, glGetProgramInfoLog)
670     && FindProcShort (myGlCore20, glGetShaderiv)
671     && FindProcShort (myGlCore20, glGetShaderInfoLog)
672     && FindProcShort (myGlCore20, glGetShaderSource)
673     && FindProcShort (myGlCore20, glGetUniformLocation)
674     && FindProcShort (myGlCore20, glGetUniformfv)
675     && FindProcShort (myGlCore20, glGetUniformiv)
676     && FindProcShort (myGlCore20, glGetVertexAttribdv)
677     && FindProcShort (myGlCore20, glGetVertexAttribfv)
678     && FindProcShort (myGlCore20, glGetVertexAttribiv)
679     && FindProcShort (myGlCore20, glGetVertexAttribPointerv)
680     && FindProcShort (myGlCore20, glIsProgram)
681     && FindProcShort (myGlCore20, glIsShader)
682     && FindProcShort (myGlCore20, glLinkProgram)
683     && FindProcShort (myGlCore20, glShaderSource)
684     && FindProcShort (myGlCore20, glUseProgram)
685     && FindProcShort (myGlCore20, glUniform1f)
686     && FindProcShort (myGlCore20, glUniform2f)
687     && FindProcShort (myGlCore20, glUniform3f)
688     && FindProcShort (myGlCore20, glUniform4f)
689     && FindProcShort (myGlCore20, glUniform1i)
690     && FindProcShort (myGlCore20, glUniform2i)
691     && FindProcShort (myGlCore20, glUniform3i)
692     && FindProcShort (myGlCore20, glUniform4i)
693     && FindProcShort (myGlCore20, glUniform1fv)
694     && FindProcShort (myGlCore20, glUniform2fv)
695     && FindProcShort (myGlCore20, glUniform3fv)
696     && FindProcShort (myGlCore20, glUniform4fv)
697     && FindProcShort (myGlCore20, glUniform1iv)
698     && FindProcShort (myGlCore20, glUniform2iv)
699     && FindProcShort (myGlCore20, glUniform3iv)
700     && FindProcShort (myGlCore20, glUniform4iv)
701     && FindProcShort (myGlCore20, glUniformMatrix2fv)
702     && FindProcShort (myGlCore20, glUniformMatrix3fv)
703     && FindProcShort (myGlCore20, glUniformMatrix4fv)
704     && FindProcShort (myGlCore20, glValidateProgram)
705     && FindProcShort (myGlCore20, glVertexAttrib1d)
706     && FindProcShort (myGlCore20, glVertexAttrib1dv)
707     && FindProcShort (myGlCore20, glVertexAttrib1f)
708     && FindProcShort (myGlCore20, glVertexAttrib1fv)
709     && FindProcShort (myGlCore20, glVertexAttrib1s)
710     && FindProcShort (myGlCore20, glVertexAttrib1sv)
711     && FindProcShort (myGlCore20, glVertexAttrib2d)
712     && FindProcShort (myGlCore20, glVertexAttrib2dv)
713     && FindProcShort (myGlCore20, glVertexAttrib2f)
714     && FindProcShort (myGlCore20, glVertexAttrib2fv)
715     && FindProcShort (myGlCore20, glVertexAttrib2s)
716     && FindProcShort (myGlCore20, glVertexAttrib2sv)
717     && FindProcShort (myGlCore20, glVertexAttrib3d)
718     && FindProcShort (myGlCore20, glVertexAttrib3dv)
719     && FindProcShort (myGlCore20, glVertexAttrib3f)
720     && FindProcShort (myGlCore20, glVertexAttrib3fv)
721     && FindProcShort (myGlCore20, glVertexAttrib3s)
722     && FindProcShort (myGlCore20, glVertexAttrib3sv)
723     && FindProcShort (myGlCore20, glVertexAttrib4Nbv)
724     && FindProcShort (myGlCore20, glVertexAttrib4Niv)
725     && FindProcShort (myGlCore20, glVertexAttrib4Nsv)
726     && FindProcShort (myGlCore20, glVertexAttrib4Nub)
727     && FindProcShort (myGlCore20, glVertexAttrib4Nubv)
728     && FindProcShort (myGlCore20, glVertexAttrib4Nuiv)
729     && FindProcShort (myGlCore20, glVertexAttrib4Nusv)
730     && FindProcShort (myGlCore20, glVertexAttrib4bv)
731     && FindProcShort (myGlCore20, glVertexAttrib4d)
732     && FindProcShort (myGlCore20, glVertexAttrib4dv)
733     && FindProcShort (myGlCore20, glVertexAttrib4f)
734     && FindProcShort (myGlCore20, glVertexAttrib4fv)
735     && FindProcShort (myGlCore20, glVertexAttrib4iv)
736     && FindProcShort (myGlCore20, glVertexAttrib4s)
737     && FindProcShort (myGlCore20, glVertexAttrib4sv)
738     && FindProcShort (myGlCore20, glVertexAttrib4ubv)
739     && FindProcShort (myGlCore20, glVertexAttrib4uiv)
740     && FindProcShort (myGlCore20, glVertexAttrib4usv)
741     && FindProcShort (myGlCore20, glVertexAttribPointer);
742
743   if (!hasGlCore12)
744   {
745     myGlVerMajor = 1;
746     myGlVerMinor = 1;
747     return;
748   }
749   else
750   {
751     core12 = myGlCore20;
752   }
753   if (!hasGlCore13)
754   {
755     myGlVerMajor = 1;
756     myGlVerMinor = 2;
757     return;
758   }
759   else
760   {
761     core13 = myGlCore20;
762   }
763   if(!hasGlCore14)
764   {
765     myGlVerMajor = 1;
766     myGlVerMinor = 3;
767     return;
768   }
769   else
770   {
771     core14 = myGlCore20;
772   }
773   if(!hasGlCore15)
774   {
775     myGlVerMajor = 1;
776     myGlVerMinor = 4;
777     return;
778   }
779   else
780   {
781     core15 = myGlCore20;
782   }
783   if(!hasGlCore20)
784   {
785     myGlVerMajor = 1;
786     myGlVerMinor = 5;
787   }
788   else
789   {
790     core20 = myGlCore20;
791   }
792 }
793 // =======================================================================
794 // function : IsFeedback
795 // purpose  :
796 // =======================================================================
797 Standard_Boolean OpenGl_Context::IsFeedback() const
798 {
799   return myIsFeedback;
800 }
801
802 // =======================================================================
803 // function : SetFeedback
804 // purpose  :
805 // =======================================================================
806 void OpenGl_Context::SetFeedback (const Standard_Boolean theFeedbackOn)
807 {
808   myIsFeedback = theFeedbackOn;
809 }
810
811 // =======================================================================
812 // function : MemoryInfo
813 // purpose  :
814 // =======================================================================
815 Standard_Size OpenGl_Context::AvailableMemory() const
816 {
817   if (atiMem)
818   {
819     // this is actually information for VBO pool
820     // however because pools are mostly shared
821     // it can be used for total GPU memory estimations
822     GLint aMemInfo[4];
823     aMemInfo[0] = 0;
824     glGetIntegerv (GL_VBO_FREE_MEMORY_ATI, aMemInfo);
825     // returned value is in KiB, however this maybe changed in future
826     return Standard_Size(aMemInfo[0]) * 1024;
827   }
828   else if (nvxMem)
829   {
830     // current available dedicated video memory (in KiB), currently unused GPU memory
831     GLint aMemInfo = 0;
832     glGetIntegerv (GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &aMemInfo);
833     return Standard_Size(aMemInfo) * 1024;
834   }
835   return 0;
836 }
837
838 // =======================================================================
839 // function : MemoryInfo
840 // purpose  :
841 // =======================================================================
842 TCollection_AsciiString OpenGl_Context::MemoryInfo() const
843 {
844   TCollection_AsciiString anInfo;
845   if (atiMem)
846   {
847     GLint aValues[4];
848     memset (aValues, 0, sizeof(aValues));
849     glGetIntegerv (GL_VBO_FREE_MEMORY_ATI, aValues);
850
851     // total memory free in the pool
852     anInfo += TCollection_AsciiString ("  GPU free memory:    ") + (aValues[0] / 1024) + " MiB\n";
853
854     // largest available free block in the pool
855     anInfo += TCollection_AsciiString ("  Largest free block: ") + (aValues[1] / 1024) + " MiB\n";
856     if (aValues[2] != aValues[0])
857     {
858       // total auxiliary memory free
859       anInfo += TCollection_AsciiString ("  Free memory:        ") + (aValues[2] / 1024) + " MiB\n";
860     }
861   }
862   else if (nvxMem)
863   {
864     //current available dedicated video memory (in KiB), currently unused GPU memory
865     GLint aValue = 0;
866     glGetIntegerv (GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &aValue);
867     anInfo += TCollection_AsciiString ("  GPU free memory:    ") + (aValue / 1024) + " MiB\n";
868
869     // dedicated video memory, total size (in KiB) of the GPU memory
870     GLint aDedicated = 0;
871     glGetIntegerv (GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, &aDedicated);
872     anInfo += TCollection_AsciiString ("  GPU memory:         ") + (aDedicated / 1024) + " MiB\n";
873
874     // total available memory, total size (in KiB) of the memory available for allocations
875     glGetIntegerv (GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, &aValue);
876     if (aValue != aDedicated)
877     {
878       // different only for special configurations
879       anInfo += TCollection_AsciiString ("  Total memory:       ") + (aValue / 1024) + " MiB\n";
880     }
881   }
882   return anInfo;
883 }
884
885
886 // =======================================================================
887 // function : GetResource
888 // purpose  :
889 // =======================================================================
890 const Handle(OpenGl_Resource)& OpenGl_Context::GetResource (const TCollection_AsciiString& theKey) const
891 {
892   return mySharedResources->IsBound (theKey) ? mySharedResources->Find (theKey) : NULL_GL_RESOURCE;
893 }
894
895 // =======================================================================
896 // function : ShareResource
897 // purpose  :
898 // =======================================================================
899 Standard_Boolean OpenGl_Context::ShareResource (const TCollection_AsciiString& theKey,
900                                                 const Handle(OpenGl_Resource)& theResource)
901 {
902   if (theKey.IsEmpty() || theResource.IsNull())
903   {
904     return Standard_False;
905   }
906   return mySharedResources->Bind (theKey, theResource);
907 }
908
909 // =======================================================================
910 // function : ReleaseResource
911 // purpose  :
912 // =======================================================================
913 void OpenGl_Context::ReleaseResource (const TCollection_AsciiString& theKey)
914 {
915   if (!mySharedResources->IsBound (theKey))
916   {
917     return;
918   }
919   const Handle(OpenGl_Resource)& aRes = mySharedResources->Find (theKey);
920   if (aRes->GetRefCount() > 1)
921   {
922     return;
923   }
924
925   aRes->Release (this);
926   mySharedResources->UnBind (theKey);
927 }
928
929 // =======================================================================
930 // function : DelayedRelease
931 // purpose  :
932 // =======================================================================
933 void OpenGl_Context::DelayedRelease (Handle(OpenGl_Resource)& theResource)
934 {
935   myReleaseQueue->Push (theResource);
936   theResource.Nullify();
937 }
938
939 // =======================================================================
940 // function : ReleaseDelayed
941 // purpose  :
942 // =======================================================================
943 void OpenGl_Context::ReleaseDelayed()
944 {
945   while (!myReleaseQueue->IsEmpty())
946   {
947     myReleaseQueue->Front()->Release (this);
948     myReleaseQueue->Pop();
949   }
950 }