0024671: TKOpenGl, OpenGl_Context - glGetPointerv might be called without GL context
[occt.git] / src / OpenGl / OpenGl_Context.cxx
1 // Created on: 2012-01-26
2 // Created by: Kirill GAVRILOV
3 // Copyright (c) 2012-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #if defined(_WIN32)
17   #include <windows.h>
18 #endif
19
20 #include <OpenGl_Context.hxx>
21
22 #include <OpenGl_ArbVBO.hxx>
23 #include <OpenGl_ArbTBO.hxx>
24 #include <OpenGl_ArbIns.hxx>
25 #include <OpenGl_ArbDbg.hxx>
26 #include <OpenGl_ExtFBO.hxx>
27 #include <OpenGl_ExtGS.hxx>
28 #include <OpenGl_GlCore20.hxx>
29 #include <OpenGl_ShaderManager.hxx>
30
31 #include <Message_Messenger.hxx>
32
33 #include <NCollection_Vector.hxx>
34
35 #include <Standard_ProgramError.hxx>
36
37 #if defined(_WIN32)
38   //
39 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
40   #include <dlfcn.h>
41 #else
42   #include <GL/glx.h> // glXGetProcAddress()
43 #endif
44
45 // GL_NVX_gpu_memory_info
46 #ifndef GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX
47   enum
48   {
49     GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX         = 0x9047,
50     GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX   = 0x9048,
51     GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX = 0x9049,
52     GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX           = 0x904A,
53     GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX           = 0x904B
54   };
55 #endif
56
57 IMPLEMENT_STANDARD_HANDLE (OpenGl_Context, Standard_Transient)
58 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Context, Standard_Transient)
59
60 //! Make record shorter to retrieve function pointer using variable with same name
61 #define FindProcShort(theStruct, theFunc) FindProc(#theFunc, theStruct->theFunc)
62
63 namespace
64 {
65   static const Handle(OpenGl_Resource) NULL_GL_RESOURCE;
66   static const GLdouble OpenGl_DefaultPlaneEq[] = {0.0, 0.0, 0.0, 0.0};
67 };
68
69 // =======================================================================
70 // function : OpenGl_Context
71 // purpose  :
72 // =======================================================================
73 OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps)
74 : core12 (NULL),
75   core13 (NULL),
76   core14 (NULL),
77   core15 (NULL),
78   core20 (NULL),
79   caps   (!theCaps.IsNull() ? theCaps : new OpenGl_Caps()),
80   arbNPTW(Standard_False),
81   arbVBO (NULL),
82   arbTBO (NULL),
83   arbIns (NULL),
84   arbDbg (NULL),
85   extFBO (NULL),
86   extGS  (NULL),
87   extBgra(Standard_False),
88   extAnis(Standard_False),
89   extPDS (Standard_False),
90   atiMem (Standard_False),
91   nvxMem (Standard_False),
92   mySharedResources (new OpenGl_ResourcesMap()),
93   myDelayed         (new OpenGl_DelayReleaseMap()),
94   myReleaseQueue    (new OpenGl_ResourcesQueue()),
95   myClippingState (),
96   myGlLibHandle (NULL),
97   myGlCore20 (NULL),
98   myAnisoMax   (1),
99   myMaxTexDim  (1024),
100   myMaxClipPlanes (6),
101   myGlVerMajor (0),
102   myGlVerMinor (0),
103   myRenderMode (GL_RENDER),
104   myIsInitialized (Standard_False),
105   myIsStereoBuffers (Standard_False),
106   myDrawBuffer (0)
107 {
108 #if defined(MAC_OS_X_VERSION_10_3) && !defined(MACOSX_USE_GLX)
109   // Vendors can not extend functionality on this system
110   // and developers are limited to OpenGL support provided by Mac OS X SDK.
111   // We retrieve function pointers from system library
112   // to generalize extensions support on all platforms.
113   // In this way we also reach binary compatibility benefit between OS releases
114   // if some newest functionality is optionally used.
115   // Notice that GL version / extension availability checks are required
116   // because function pointers may be available but not functionality itself
117   // (depends on renderer).
118   myGlLibHandle = dlopen ("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY);
119 #endif
120
121   myShaderManager = new OpenGl_ShaderManager (this);
122 }
123
124 // =======================================================================
125 // function : ~OpenGl_Context
126 // purpose  :
127 // =======================================================================
128 OpenGl_Context::~OpenGl_Context()
129 {
130   // release clean up queue
131   ReleaseDelayed();
132
133   // release shared resources if any
134   if (((const Handle(Standard_Transient)& )mySharedResources)->GetRefCount() <= 1)
135   {
136     myShaderManager.Nullify();
137     for (NCollection_DataMap<TCollection_AsciiString, Handle(OpenGl_Resource)>::Iterator anIter (*mySharedResources);
138          anIter.More(); anIter.Next())
139     {
140       anIter.Value()->Release (this);
141     }
142   }
143   else
144   {
145     myShaderManager->SetContext (NULL);
146   }
147   mySharedResources.Nullify();
148   myDelayed.Nullify();
149
150   if (arbDbg != NULL
151    && caps->contextDebug
152    && IsValid())
153   {
154     // reset callback
155     void* aPtr = NULL;
156     glGetPointerv (GL_DEBUG_CALLBACK_USER_PARAM_ARB, &aPtr);
157     if (aPtr == this)
158     {
159       arbDbg->glDebugMessageCallbackARB (NULL, NULL);
160     }
161   }
162
163   delete myGlCore20;
164   delete arbVBO;
165   delete arbTBO;
166   delete arbIns;
167   delete arbDbg;
168   delete extFBO;
169   delete extGS;
170 }
171
172 // =======================================================================
173 // function : MaxDegreeOfAnisotropy
174 // purpose  :
175 // =======================================================================
176 Standard_Integer OpenGl_Context::MaxDegreeOfAnisotropy() const
177 {
178   return myAnisoMax;
179 }
180
181 // =======================================================================
182 // function : MaxTextureSize
183 // purpose  :
184 // =======================================================================
185 Standard_Integer OpenGl_Context::MaxTextureSize() const
186 {
187   return myMaxTexDim;
188 }
189
190 // =======================================================================
191 // function : MaxClipPlanes
192 // purpose  :
193 // =======================================================================
194 Standard_Integer OpenGl_Context::MaxClipPlanes() const
195 {
196   return myMaxClipPlanes;
197 }
198
199 // =======================================================================
200 // function : SetDrawBufferLeft
201 // purpose  :
202 // =======================================================================
203 void OpenGl_Context::SetDrawBufferLeft()
204 {
205   switch (myDrawBuffer)
206   {
207     case GL_BACK_RIGHT :
208     case GL_BACK :
209       glDrawBuffer (GL_BACK_LEFT);
210       myDrawBuffer = GL_BACK_LEFT;
211       break;
212
213     case GL_FRONT_RIGHT :
214     case GL_FRONT :
215       glDrawBuffer (GL_FRONT_LEFT);
216       myDrawBuffer = GL_FRONT_LEFT;
217       break;
218
219     case GL_FRONT_AND_BACK :
220     case GL_RIGHT :
221       glDrawBuffer (GL_LEFT);
222       myDrawBuffer = GL_LEFT;
223       break;
224   }
225 }
226
227 // =======================================================================
228 // function : SetDrawBufferRight
229 // purpose  :
230 // =======================================================================
231 void OpenGl_Context::SetDrawBufferRight()
232 {
233   switch (myDrawBuffer)
234   {
235     case GL_BACK_LEFT :
236     case GL_BACK :
237       glDrawBuffer (GL_BACK_RIGHT);
238       myDrawBuffer = GL_BACK_RIGHT;
239       break;
240
241     case GL_FRONT_LEFT :
242     case GL_FRONT :
243       glDrawBuffer (GL_FRONT_RIGHT);
244       myDrawBuffer = GL_FRONT_RIGHT;
245       break;
246
247     case GL_FRONT_AND_BACK :
248     case GL_LEFT :
249       glDrawBuffer (GL_RIGHT);
250       myDrawBuffer = GL_RIGHT;
251       break;
252   }
253 }
254
255 // =======================================================================
256 // function : SetDrawBufferMono
257 // purpose  :
258 // =======================================================================
259 void OpenGl_Context::SetDrawBufferMono()
260 {
261   switch (myDrawBuffer)
262   {
263     case GL_BACK_LEFT :
264     case GL_BACK_RIGHT :
265       glDrawBuffer (GL_BACK);
266       myDrawBuffer = GL_BACK;
267       break;
268
269     case GL_FRONT_LEFT :
270     case GL_FRONT_RIGHT :
271       glDrawBuffer (GL_FRONT);
272       myDrawBuffer = GL_FRONT;
273       break;
274
275     case GL_LEFT :
276     case GL_RIGHT :
277       glDrawBuffer (GL_FRONT_AND_BACK);
278       myDrawBuffer = GL_FRONT_AND_BACK;
279       break;
280   }
281 }
282
283 // =======================================================================
284 // function : FetchState
285 // purpose  :
286 // =======================================================================
287 void OpenGl_Context::FetchState()
288 {
289   // cache feedback mode state
290   glGetIntegerv (GL_RENDER_MODE, &myRenderMode);
291
292   // cache draw buffer state
293   glGetIntegerv (GL_DRAW_BUFFER, &myDrawBuffer);
294 }
295
296 // =======================================================================
297 // function : Share
298 // purpose  :
299 // =======================================================================
300 void OpenGl_Context::Share (const Handle(OpenGl_Context)& theShareCtx)
301 {
302   if (!theShareCtx.IsNull())
303   {
304     mySharedResources = theShareCtx->mySharedResources;
305     myDelayed         = theShareCtx->myDelayed;
306     myReleaseQueue    = theShareCtx->myReleaseQueue;
307     myShaderManager   = theShareCtx->myShaderManager;
308   }
309 }
310
311 #if !defined(__APPLE__) || defined(MACOSX_USE_GLX)
312
313 // =======================================================================
314 // function : IsCurrent
315 // purpose  :
316 // =======================================================================
317 Standard_Boolean OpenGl_Context::IsCurrent() const
318 {
319 #if defined(_WIN32)
320   if (myWindowDC == NULL || myGContext == NULL)
321   {
322     return Standard_False;
323   }
324   return (( (HDC )myWindowDC == wglGetCurrentDC())
325       && ((HGLRC )myGContext == wglGetCurrentContext()));
326 #else
327   if (myDisplay == NULL || myWindow == 0 || myGContext == 0)
328   {
329     return Standard_False;
330   }
331
332   return (   ((Display* )myDisplay  == glXGetCurrentDisplay())
333        &&  ((GLXContext )myGContext == glXGetCurrentContext())
334        && ((GLXDrawable )myWindow   == glXGetCurrentDrawable()));
335 #endif
336 }
337
338 // =======================================================================
339 // function : MakeCurrent
340 // purpose  :
341 // =======================================================================
342 Standard_Boolean OpenGl_Context::MakeCurrent()
343 {
344 #if defined(_WIN32)
345   if (myWindowDC == NULL || myGContext == NULL)
346   {
347     Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called before!");
348     return Standard_False;
349   }
350
351   // technically it should be safe to activate already bound GL context
352   // however some drivers (Intel etc.) may FAIL doing this for unknown reason
353   if (IsCurrent())
354   {
355     myShaderManager->SetContext (this);
356     return Standard_True;
357   }
358   else if (wglMakeCurrent ((HDC )myWindowDC, (HGLRC )myGContext) != TRUE)
359   {
360     // notice that glGetError() couldn't be used here!
361     wchar_t* aMsgBuff = NULL;
362     DWORD anErrorCode = GetLastError();
363     FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
364                     NULL, anErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (wchar_t* )&aMsgBuff, 0, NULL);
365     TCollection_ExtendedString aMsg ("wglMakeCurrent() has failed. ");
366     if (aMsgBuff != NULL)
367     {
368       aMsg += (Standard_ExtString )aMsgBuff;
369       LocalFree (aMsgBuff);
370     }
371     PushMessage (GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB, GL_DEBUG_TYPE_ERROR_ARB, (unsigned int )anErrorCode, GL_DEBUG_SEVERITY_HIGH_ARB, aMsg);
372     myIsInitialized = Standard_False;
373     return Standard_False;
374   }
375 #else
376   if (myDisplay == NULL || myWindow == 0 || myGContext == 0)
377   {
378     Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called before!");
379     return Standard_False;
380   }
381
382   if (!glXMakeCurrent ((Display* )myDisplay, (GLXDrawable )myWindow, (GLXContext )myGContext))
383   {
384     // if there is no current context it might be impossible to use glGetError() correctly
385     PushMessage (GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB, GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB,
386                  "glXMakeCurrent() has failed!");
387     myIsInitialized = Standard_False;
388     return Standard_False;
389   }
390 #endif
391   myShaderManager->SetContext (this);
392   return Standard_True;
393 }
394
395 // =======================================================================
396 // function : SwapBuffers
397 // purpose  :
398 // =======================================================================
399 void OpenGl_Context::SwapBuffers()
400 {
401 #if defined(_WIN32)
402   if ((HDC )myWindowDC != NULL)
403   {
404     ::SwapBuffers ((HDC )myWindowDC);
405     glFlush();
406   }
407 #else
408   if ((Display* )myDisplay != NULL)
409   {
410     glXSwapBuffers ((Display* )myDisplay, (GLXDrawable )myWindow);
411   }
412 #endif
413 }
414
415 #endif // __APPLE__
416
417 // =======================================================================
418 // function : findProc
419 // purpose  :
420 // =======================================================================
421 void* OpenGl_Context::findProc (const char* theFuncName)
422 {
423 #if defined(_WIN32)
424   return wglGetProcAddress (theFuncName);
425 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
426   return (myGlLibHandle != NULL) ? dlsym (myGlLibHandle, theFuncName) : NULL;
427 #else
428   return (void* )glXGetProcAddress ((const GLubyte* )theFuncName);
429 #endif
430 }
431
432 // =======================================================================
433 // function : CheckExtension
434 // purpose  :
435 // =======================================================================
436 Standard_Boolean OpenGl_Context::CheckExtension (const char* theExtName) const
437 {
438   if (theExtName  == NULL)
439   {
440     std::cerr << "CheckExtension called with NULL string!\n";
441     return Standard_False;
442   }
443
444   // available since OpenGL 3.0
445   // and the ONLY way to check extensions with OpenGL 3.1+ core profile
446   /**if (IsGlGreaterEqual (3, 0))
447   {
448     GLint anExtNb = 0;
449     glGetIntegerv (GL_NUM_EXTENSIONS, &anExtNb);
450     for (GLint anIter = 0; anIter < anExtNb; ++anIter)
451     {
452       const char* anExtension = (const char* )core30->glGetStringi (GL_EXTENSIONS, (GLuint )anIter);
453       if (anExtension[anExtNameLen] == '\0' &&
454           strncmp (anExtension, theExtName, anExtNameLen) == 0)
455       {
456         return Standard_True;
457       }
458     }
459     return Standard_False;
460   }*/
461
462   // use old way with huge string for all extensions
463   const char* anExtString = (const char* )glGetString (GL_EXTENSIONS);
464   if (anExtString == NULL)
465   {
466     Messenger()->Send ("TKOpenGL: glGetString (GL_EXTENSIONS) has returned NULL! No GL context?", Message_Warning);
467     return Standard_False;
468   }
469   return CheckExtension (anExtString, theExtName);
470 }
471
472 // =======================================================================
473 // function : CheckExtension
474 // purpose  :
475 // =======================================================================
476 Standard_Boolean OpenGl_Context::CheckExtension (const char* theExtString,
477                                                  const char* theExtName)
478 {
479   if (theExtString == NULL)
480   {
481     return Standard_False;
482   }
483
484   // Search for theExtName in the extensions string.
485   // Use of strstr() is not sufficient because extension names can be prefixes of other extension names.
486   char* aPtrIter = (char* )theExtString;
487   const char*  aPtrEnd      = aPtrIter + strlen (theExtString);
488   const size_t anExtNameLen = strlen (theExtName);
489   while (aPtrIter < aPtrEnd)
490   {
491     const size_t n = strcspn (aPtrIter, " ");
492     if ((n == anExtNameLen) && (strncmp (aPtrIter, theExtName, anExtNameLen) == 0))
493     {
494       return Standard_True;
495     }
496     aPtrIter += (n + 1);
497   }
498   return Standard_False;
499 }
500
501 #if !defined(__APPLE__) || defined(MACOSX_USE_GLX)
502
503 // =======================================================================
504 // function : Init
505 // purpose  :
506 // =======================================================================
507 Standard_Boolean OpenGl_Context::Init()
508 {
509   if (myIsInitialized)
510   {
511     return Standard_True;
512   }
513
514 #if defined(_WIN32)
515   myWindowDC = (Aspect_Handle )wglGetCurrentDC();
516   myGContext = (Aspect_RenderingContext )wglGetCurrentContext();
517 #else
518   myDisplay  = (Aspect_Display )glXGetCurrentDisplay();
519   myGContext = (Aspect_RenderingContext )glXGetCurrentContext();
520   myWindow   = (Aspect_Drawable )glXGetCurrentDrawable();
521 #endif
522   if (myGContext == NULL)
523   {
524     return Standard_False;
525   }
526
527   init();
528   myIsInitialized = Standard_True;
529   return Standard_True;
530 }
531
532 #endif // __APPLE__
533
534 // =======================================================================
535 // function : Init
536 // purpose  :
537 // =======================================================================
538 #if defined(_WIN32)
539 Standard_Boolean OpenGl_Context::Init (const Aspect_Handle           theWindow,
540                                        const Aspect_Handle           theWindowDC,
541                                        const Aspect_RenderingContext theGContext)
542 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
543 Standard_Boolean OpenGl_Context::Init (const void*                   theGContext)
544 #else
545 Standard_Boolean OpenGl_Context::Init (const Aspect_Drawable         theWindow,
546                                        const Aspect_Display          theDisplay,
547                                        const Aspect_RenderingContext theGContext)
548 #endif
549 {
550   Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called only once!");
551 #if defined(_WIN32)
552   myWindow   = theWindow;
553   myGContext = theGContext;
554   myWindowDC = theWindowDC;
555 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
556   myGContext = (void* )theGContext;
557 #else
558   myWindow   = theWindow;
559   myGContext = theGContext;
560   myDisplay  = theDisplay;
561 #endif
562   if (myGContext == NULL || !MakeCurrent())
563   {
564     return Standard_False;
565   }
566
567   init();
568   myIsInitialized = Standard_True;
569   return Standard_True;
570 }
571
572 // =======================================================================
573 // function : ResetErrors
574 // purpose  :
575 // =======================================================================
576 void OpenGl_Context::ResetErrors()
577 {
578   while (glGetError() != GL_NO_ERROR)
579   {
580     //
581   }
582 }
583
584 // =======================================================================
585 // function : readGlVersion
586 // purpose  :
587 // =======================================================================
588 void OpenGl_Context::readGlVersion()
589 {
590   // reset values
591   myGlVerMajor = 0;
592   myGlVerMinor = 0;
593
594   // available since OpenGL 3.0
595   GLint aMajor = 0, aMinor = 0;
596   glGetIntegerv (GL_MAJOR_VERSION, &aMajor);
597   glGetIntegerv (GL_MINOR_VERSION, &aMinor);
598   // glGetError() sometimes does not report an error here even if
599   // GL does not know GL_MAJOR_VERSION and GL_MINOR_VERSION constants.
600   // This happens on some rendereres like e.g. Cygwin MESA.
601   // Thus checking additionally if GL has put anything to
602   // the output variables.
603   if (glGetError() == GL_NO_ERROR && aMajor != 0 && aMinor != 0)
604   {
605     myGlVerMajor = aMajor;
606     myGlVerMinor = aMinor;
607     return;
608   }
609   ResetErrors();
610
611   // Read version string.
612   // Notice that only first two numbers splitted by point '2.1 XXXXX' are significant.
613   // Following trash (after space) is vendor-specific.
614   // New drivers also returns micro version of GL like '3.3.0' which has no meaning
615   // and should be considered as vendor-specific too.
616   const char* aVerStr = (const char* )glGetString (GL_VERSION);
617   if (aVerStr == NULL || *aVerStr == '\0')
618   {
619     // invalid GL context
620     return;
621   }
622
623   // parse string for major number
624   char aMajorStr[32];
625   char aMinorStr[32];
626   size_t aMajIter = 0;
627   while (aVerStr[aMajIter] >= '0' && aVerStr[aMajIter] <= '9')
628   {
629     ++aMajIter;
630   }
631   if (aMajIter == 0 || aMajIter >= sizeof(aMajorStr))
632   {
633     return;
634   }
635   memcpy (aMajorStr, aVerStr, aMajIter);
636   aMajorStr[aMajIter] = '\0';
637
638   // parse string for minor number
639   aVerStr += aMajIter + 1;
640   size_t aMinIter = 0;
641   while (aVerStr[aMinIter] >= '0' && aVerStr[aMinIter] <= '9')
642   {
643     ++aMinIter;
644   }
645   if (aMinIter == 0 || aMinIter >= sizeof(aMinorStr))
646   {
647     return;
648   }
649   memcpy (aMinorStr, aVerStr, aMinIter);
650   aMinorStr[aMinIter] = '\0';
651
652   // read numbers
653   myGlVerMajor = atoi (aMajorStr);
654   myGlVerMinor = atoi (aMinorStr);
655
656   if (myGlVerMajor <= 0)
657   {
658     myGlVerMajor = 0;
659     myGlVerMinor = 0;
660   }
661 }
662
663 static Standard_CString THE_DBGMSG_UNKNOWN = "UNKNOWN";
664 static Standard_CString THE_DBGMSG_SOURCES[] =
665 {
666   ".OpenGL",    // GL_DEBUG_SOURCE_API_ARB
667   ".WinSystem", // GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB
668   ".GLSL",      // GL_DEBUG_SOURCE_SHADER_COMPILER_ARB
669   ".3rdParty",  // GL_DEBUG_SOURCE_THIRD_PARTY_ARB
670   "",           // GL_DEBUG_SOURCE_APPLICATION_ARB
671   ".Other"      // GL_DEBUG_SOURCE_OTHER_ARB
672 };
673
674 static Standard_CString THE_DBGMSG_TYPES[] =
675 {
676   "Error",           // GL_DEBUG_TYPE_ERROR_ARB
677   "Deprecated",      // GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB
678   "Undef. behavior", // GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB
679   "Portability",     // GL_DEBUG_TYPE_PORTABILITY_ARB
680   "Performance",     // GL_DEBUG_TYPE_PERFORMANCE_ARB
681   "Other"            // GL_DEBUG_TYPE_OTHER_ARB
682 };
683
684 static Standard_CString THE_DBGMSG_SEV_HIGH   = "High";   // GL_DEBUG_SEVERITY_HIGH_ARB
685 static Standard_CString THE_DBGMSG_SEV_MEDIUM = "Medium"; // GL_DEBUG_SEVERITY_MEDIUM_ARB
686 static Standard_CString THE_DBGMSG_SEV_LOW    = "Low";    // GL_DEBUG_SEVERITY_LOW_ARB
687
688 //! Callback for GL_ARB_debug_output extension
689 static void APIENTRY debugCallbackWrap(unsigned int theSource,
690                                        unsigned int theType,
691                                        unsigned int theId,
692                                        unsigned int theSeverity,
693                                        int          /*theLength*/,
694                                        const char*  theMessage,
695                                        const void*  theUserParam)
696 {
697   OpenGl_Context* aCtx = (OpenGl_Context* )theUserParam;
698   aCtx->PushMessage (theSource, theType, theId, theSeverity, theMessage);
699 }
700
701 // =======================================================================
702 // function : PushMessage
703 // purpose  :
704 // =======================================================================
705 void OpenGl_Context::PushMessage (const unsigned int theSource,
706                                   const unsigned int theType,
707                                   const unsigned int theId,
708                                   const unsigned int theSeverity,
709                                   const TCollection_ExtendedString& theMessage)
710 {
711   //OpenGl_Context* aCtx = (OpenGl_Context* )theUserParam;
712   Standard_CString& aSrc = (theSource >= GL_DEBUG_SOURCE_API_ARB
713                          && theSource <= GL_DEBUG_SOURCE_OTHER_ARB)
714                          ? THE_DBGMSG_SOURCES[theSource - GL_DEBUG_SOURCE_API_ARB]
715                          : THE_DBGMSG_UNKNOWN;
716   Standard_CString& aType = (theType >= GL_DEBUG_TYPE_ERROR_ARB
717                           && theType <= GL_DEBUG_TYPE_OTHER_ARB)
718                           ? THE_DBGMSG_TYPES[theType - GL_DEBUG_TYPE_ERROR_ARB]
719                           : THE_DBGMSG_UNKNOWN;
720   Standard_CString& aSev = theSeverity == GL_DEBUG_SEVERITY_HIGH_ARB
721                          ? THE_DBGMSG_SEV_HIGH
722                          : (theSeverity == GL_DEBUG_SEVERITY_MEDIUM_ARB
723                           ? THE_DBGMSG_SEV_MEDIUM
724                           : THE_DBGMSG_SEV_LOW);
725   Message_Gravity aGrav = theSeverity == GL_DEBUG_SEVERITY_HIGH_ARB
726                         ? Message_Alarm
727                         : (theSeverity == GL_DEBUG_SEVERITY_MEDIUM_ARB
728                          ? Message_Warning
729                          : Message_Info);
730
731   TCollection_ExtendedString aMsg;
732   aMsg += "TKOpenGl"; aMsg += aSrc;
733   aMsg += " | Type: ";        aMsg += aType;
734   aMsg += " | ID: ";          aMsg += (Standard_Integer )theId;
735   aMsg += " | Severity: ";    aMsg += aSev;
736   aMsg += " | Message:\n  ";
737   aMsg += theMessage;
738
739   Messenger()->Send (aMsg, aGrav);
740 }
741
742 // =======================================================================
743 // function : init
744 // purpose  :
745 // =======================================================================
746 void OpenGl_Context::init()
747 {
748   // read version
749   readGlVersion();
750
751   arbNPTW = CheckExtension ("GL_ARB_texture_non_power_of_two");
752   extBgra = CheckExtension ("GL_EXT_bgra");
753   extAnis = CheckExtension ("GL_EXT_texture_filter_anisotropic");
754   extPDS  = CheckExtension ("GL_EXT_packed_depth_stencil");
755   atiMem  = CheckExtension ("GL_ATI_meminfo");
756   nvxMem  = CheckExtension ("GL_NVX_gpu_memory_info");
757
758   // get number of maximum clipping planes
759   glGetIntegerv (GL_MAX_CLIP_PLANES, &myMaxClipPlanes);
760   glGetIntegerv (GL_MAX_TEXTURE_SIZE, &myMaxTexDim);
761
762   GLint aStereo;
763   glGetIntegerv (GL_STEREO, &aStereo);
764   myIsStereoBuffers = aStereo == 1;
765
766   if (extAnis)
767   {
768     glGetIntegerv (GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &myAnisoMax);
769   }
770
771   myClippingState.Init (myMaxClipPlanes);
772
773   // initialize debug context extension
774   if (CheckExtension ("GL_ARB_debug_output"))
775   {
776     arbDbg = new OpenGl_ArbDbg();
777     memset (arbDbg, 0, sizeof(OpenGl_ArbDbg)); // nullify whole structure
778     if (!FindProcShort (arbDbg, glDebugMessageControlARB)
779      || !FindProcShort (arbDbg, glDebugMessageInsertARB)
780      || !FindProcShort (arbDbg, glDebugMessageCallbackARB)
781      || !FindProcShort (arbDbg, glGetDebugMessageLogARB))
782     {
783       delete arbDbg;
784       arbDbg = NULL;
785     }
786     if (arbDbg != NULL
787      && caps->contextDebug)
788     {
789       // setup default callback
790       arbDbg->glDebugMessageCallbackARB (debugCallbackWrap, this);
791     #ifdef DEB
792       glEnable (GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
793     #endif
794     }
795   }
796
797   // initialize VBO extension (ARB)
798   if (CheckExtension ("GL_ARB_vertex_buffer_object"))
799   {
800     arbVBO = new OpenGl_ArbVBO();
801     memset (arbVBO, 0, sizeof(OpenGl_ArbVBO)); // nullify whole structure
802     if (!FindProcShort (arbVBO, glGenBuffersARB)
803      || !FindProcShort (arbVBO, glBindBufferARB)
804      || !FindProcShort (arbVBO, glBufferDataARB)
805      || !FindProcShort (arbVBO, glDeleteBuffersARB))
806     {
807       delete arbVBO;
808       arbVBO = NULL;
809     }
810   }
811
812   // initialize TBO extension (ARB)
813   if (CheckExtension ("GL_ARB_texture_buffer_object"))
814   {
815     arbTBO = new OpenGl_ArbTBO();
816     memset (arbTBO, 0, sizeof(OpenGl_ArbTBO)); // nullify whole structure
817     if (!FindProcShort (arbTBO, glTexBufferARB))
818     {
819       delete arbTBO;
820       arbTBO = NULL;
821     }
822   }
823
824   // initialize hardware instancing extension (ARB)
825   if (CheckExtension ("GL_ARB_draw_instanced"))
826   {
827     arbIns = new OpenGl_ArbIns();
828     memset (arbIns, 0, sizeof(OpenGl_ArbIns)); // nullify whole structure
829     if (!FindProcShort (arbIns, glDrawArraysInstancedARB)
830      || !FindProcShort (arbIns, glDrawElementsInstancedARB))
831     {
832       delete arbIns;
833       arbIns = NULL;
834     }
835   }
836
837   // initialize FBO extension (EXT)
838   if (CheckExtension ("GL_EXT_framebuffer_object"))
839   {
840     extFBO = new OpenGl_ExtFBO();
841     memset (extFBO, 0, sizeof(OpenGl_ExtFBO)); // nullify whole structure
842     if (!FindProcShort (extFBO, glGenFramebuffersEXT)
843      || !FindProcShort (extFBO, glDeleteFramebuffersEXT)
844      || !FindProcShort (extFBO, glBindFramebufferEXT)
845      || !FindProcShort (extFBO, glFramebufferTexture2DEXT)
846      || !FindProcShort (extFBO, glCheckFramebufferStatusEXT)
847      || !FindProcShort (extFBO, glGenRenderbuffersEXT)
848      || !FindProcShort (extFBO, glDeleteRenderbuffersEXT)
849      || !FindProcShort (extFBO, glBindRenderbufferEXT)
850      || !FindProcShort (extFBO, glRenderbufferStorageEXT)
851      || !FindProcShort (extFBO, glFramebufferRenderbufferEXT)
852      || !FindProcShort (extFBO, glGenerateMipmapEXT))
853     {
854       delete extFBO;
855       extFBO = NULL;
856     }
857   }
858
859   // initialize GS extension (EXT)
860   if (CheckExtension ("GL_EXT_geometry_shader4"))
861   {
862     extGS = new OpenGl_ExtGS();
863     memset (extGS, 0, sizeof(OpenGl_ExtGS)); // nullify whole structure
864     if (!FindProcShort (extGS, glProgramParameteriEXT))
865     {
866       delete extGS;
867       extGS = NULL;
868     }
869   }
870
871   myGlCore20 = new OpenGl_GlCore20();
872   memset (myGlCore20, 0, sizeof(OpenGl_GlCore20)); // nullify whole structure
873
874   // Check if OpenGL 1.2 core functionality is actually present
875   Standard_Boolean hasGlCore12 = IsGlGreaterEqual (1, 2)
876     && FindProcShort (myGlCore20, glBlendColor)
877     && FindProcShort (myGlCore20, glBlendEquation)
878     && FindProcShort (myGlCore20, glDrawRangeElements)
879     && FindProcShort (myGlCore20, glTexImage3D)
880     && FindProcShort (myGlCore20, glTexSubImage3D)
881     && FindProcShort (myGlCore20, glCopyTexSubImage3D);
882
883   // Check if OpenGL 1.3 core functionality is actually present
884   Standard_Boolean hasGlCore13 = IsGlGreaterEqual (1, 3)
885     && FindProcShort (myGlCore20, glActiveTexture)
886     && FindProcShort (myGlCore20, glSampleCoverage)
887     && FindProcShort (myGlCore20, glCompressedTexImage3D)
888     && FindProcShort (myGlCore20, glCompressedTexImage2D)
889     && FindProcShort (myGlCore20, glCompressedTexImage1D)
890     && FindProcShort (myGlCore20, glCompressedTexSubImage3D)
891     && FindProcShort (myGlCore20, glCompressedTexSubImage2D)
892     && FindProcShort (myGlCore20, glCompressedTexSubImage1D)
893     && FindProcShort (myGlCore20, glGetCompressedTexImage)
894      // deprecated
895     && FindProcShort (myGlCore20, glClientActiveTexture)
896     && FindProcShort (myGlCore20, glMultiTexCoord1d)
897     && FindProcShort (myGlCore20, glMultiTexCoord1dv)
898     && FindProcShort (myGlCore20, glMultiTexCoord1f)
899     && FindProcShort (myGlCore20, glMultiTexCoord1fv)
900     && FindProcShort (myGlCore20, glMultiTexCoord1i)
901     && FindProcShort (myGlCore20, glMultiTexCoord1iv)
902     && FindProcShort (myGlCore20, glMultiTexCoord1s)
903     && FindProcShort (myGlCore20, glMultiTexCoord1sv)
904     && FindProcShort (myGlCore20, glMultiTexCoord2d)
905     && FindProcShort (myGlCore20, glMultiTexCoord2dv)
906     && FindProcShort (myGlCore20, glMultiTexCoord2f)
907     && FindProcShort (myGlCore20, glMultiTexCoord2fv)
908     && FindProcShort (myGlCore20, glMultiTexCoord2i)
909     && FindProcShort (myGlCore20, glMultiTexCoord2iv)
910     && FindProcShort (myGlCore20, glMultiTexCoord2s)
911     && FindProcShort (myGlCore20, glMultiTexCoord2sv)
912     && FindProcShort (myGlCore20, glMultiTexCoord3d)
913     && FindProcShort (myGlCore20, glMultiTexCoord3dv)
914     && FindProcShort (myGlCore20, glMultiTexCoord3f)
915     && FindProcShort (myGlCore20, glMultiTexCoord3fv)
916     && FindProcShort (myGlCore20, glMultiTexCoord3i)
917     && FindProcShort (myGlCore20, glMultiTexCoord3iv)
918     && FindProcShort (myGlCore20, glMultiTexCoord3s)
919     && FindProcShort (myGlCore20, glMultiTexCoord3sv)
920     && FindProcShort (myGlCore20, glMultiTexCoord4d)
921     && FindProcShort (myGlCore20, glMultiTexCoord4dv)
922     && FindProcShort (myGlCore20, glMultiTexCoord4f)
923     && FindProcShort (myGlCore20, glMultiTexCoord4fv)
924     && FindProcShort (myGlCore20, glMultiTexCoord4i)
925     && FindProcShort (myGlCore20, glMultiTexCoord4iv)
926     && FindProcShort (myGlCore20, glMultiTexCoord4s)
927     && FindProcShort (myGlCore20, glMultiTexCoord4sv)
928     && FindProcShort (myGlCore20, glLoadTransposeMatrixf)
929     && FindProcShort (myGlCore20, glLoadTransposeMatrixd)
930     && FindProcShort (myGlCore20, glMultTransposeMatrixf)
931     && FindProcShort (myGlCore20, glMultTransposeMatrixd);
932
933   // Check if OpenGL 1.4 core functionality is actually present
934   Standard_Boolean hasGlCore14 = IsGlGreaterEqual (1, 4)
935     && FindProcShort (myGlCore20, glBlendFuncSeparate)
936     && FindProcShort (myGlCore20, glMultiDrawArrays)
937     && FindProcShort (myGlCore20, glMultiDrawElements)
938     && FindProcShort (myGlCore20, glPointParameterf)
939     && FindProcShort (myGlCore20, glPointParameterfv)
940     && FindProcShort (myGlCore20, glPointParameteri)
941     && FindProcShort (myGlCore20, glPointParameteriv);
942
943   // Check if OpenGL 1.5 core functionality is actually present
944   Standard_Boolean hasGlCore15 = IsGlGreaterEqual (1, 5)
945     && FindProcShort (myGlCore20, glGenQueries)
946     && FindProcShort (myGlCore20, glDeleteQueries)
947     && FindProcShort (myGlCore20, glIsQuery)
948     && FindProcShort (myGlCore20, glBeginQuery)
949     && FindProcShort (myGlCore20, glEndQuery)
950     && FindProcShort (myGlCore20, glGetQueryiv)
951     && FindProcShort (myGlCore20, glGetQueryObjectiv)
952     && FindProcShort (myGlCore20, glGetQueryObjectuiv)
953     && FindProcShort (myGlCore20, glBindBuffer)
954     && FindProcShort (myGlCore20, glDeleteBuffers)
955     && FindProcShort (myGlCore20, glGenBuffers)
956     && FindProcShort (myGlCore20, glIsBuffer)
957     && FindProcShort (myGlCore20, glBufferData)
958     && FindProcShort (myGlCore20, glBufferSubData)
959     && FindProcShort (myGlCore20, glGetBufferSubData)
960     && FindProcShort (myGlCore20, glMapBuffer)
961     && FindProcShort (myGlCore20, glUnmapBuffer)
962     && FindProcShort (myGlCore20, glGetBufferParameteriv)
963     && FindProcShort (myGlCore20, glGetBufferPointerv);
964
965   // Check if OpenGL 2.0 core functionality is actually present
966   Standard_Boolean hasGlCore20 = IsGlGreaterEqual (2, 0)
967     && FindProcShort (myGlCore20, glBlendEquationSeparate)
968     && FindProcShort (myGlCore20, glDrawBuffers)
969     && FindProcShort (myGlCore20, glStencilOpSeparate)
970     && FindProcShort (myGlCore20, glStencilFuncSeparate)
971     && FindProcShort (myGlCore20, glStencilMaskSeparate)
972     && FindProcShort (myGlCore20, glAttachShader)
973     && FindProcShort (myGlCore20, glBindAttribLocation)
974     && FindProcShort (myGlCore20, glCompileShader)
975     && FindProcShort (myGlCore20, glCreateProgram)
976     && FindProcShort (myGlCore20, glCreateShader)
977     && FindProcShort (myGlCore20, glDeleteProgram)
978     && FindProcShort (myGlCore20, glDeleteShader)
979     && FindProcShort (myGlCore20, glDetachShader)
980     && FindProcShort (myGlCore20, glDisableVertexAttribArray)
981     && FindProcShort (myGlCore20, glEnableVertexAttribArray)
982     && FindProcShort (myGlCore20, glGetActiveAttrib)
983     && FindProcShort (myGlCore20, glGetActiveUniform)
984     && FindProcShort (myGlCore20, glGetAttachedShaders)
985     && FindProcShort (myGlCore20, glGetAttribLocation)
986     && FindProcShort (myGlCore20, glGetProgramiv)
987     && FindProcShort (myGlCore20, glGetProgramInfoLog)
988     && FindProcShort (myGlCore20, glGetShaderiv)
989     && FindProcShort (myGlCore20, glGetShaderInfoLog)
990     && FindProcShort (myGlCore20, glGetShaderSource)
991     && FindProcShort (myGlCore20, glGetUniformLocation)
992     && FindProcShort (myGlCore20, glGetUniformfv)
993     && FindProcShort (myGlCore20, glGetUniformiv)
994     && FindProcShort (myGlCore20, glGetVertexAttribdv)
995     && FindProcShort (myGlCore20, glGetVertexAttribfv)
996     && FindProcShort (myGlCore20, glGetVertexAttribiv)
997     && FindProcShort (myGlCore20, glGetVertexAttribPointerv)
998     && FindProcShort (myGlCore20, glIsProgram)
999     && FindProcShort (myGlCore20, glIsShader)
1000     && FindProcShort (myGlCore20, glLinkProgram)
1001     && FindProcShort (myGlCore20, glShaderSource)
1002     && FindProcShort (myGlCore20, glUseProgram)
1003     && FindProcShort (myGlCore20, glUniform1f)
1004     && FindProcShort (myGlCore20, glUniform2f)
1005     && FindProcShort (myGlCore20, glUniform3f)
1006     && FindProcShort (myGlCore20, glUniform4f)
1007     && FindProcShort (myGlCore20, glUniform1i)
1008     && FindProcShort (myGlCore20, glUniform2i)
1009     && FindProcShort (myGlCore20, glUniform3i)
1010     && FindProcShort (myGlCore20, glUniform4i)
1011     && FindProcShort (myGlCore20, glUniform1fv)
1012     && FindProcShort (myGlCore20, glUniform2fv)
1013     && FindProcShort (myGlCore20, glUniform3fv)
1014     && FindProcShort (myGlCore20, glUniform4fv)
1015     && FindProcShort (myGlCore20, glUniform1iv)
1016     && FindProcShort (myGlCore20, glUniform2iv)
1017     && FindProcShort (myGlCore20, glUniform3iv)
1018     && FindProcShort (myGlCore20, glUniform4iv)
1019     && FindProcShort (myGlCore20, glUniformMatrix2fv)
1020     && FindProcShort (myGlCore20, glUniformMatrix3fv)
1021     && FindProcShort (myGlCore20, glUniformMatrix4fv)
1022     && FindProcShort (myGlCore20, glValidateProgram)
1023     && FindProcShort (myGlCore20, glVertexAttrib1d)
1024     && FindProcShort (myGlCore20, glVertexAttrib1dv)
1025     && FindProcShort (myGlCore20, glVertexAttrib1f)
1026     && FindProcShort (myGlCore20, glVertexAttrib1fv)
1027     && FindProcShort (myGlCore20, glVertexAttrib1s)
1028     && FindProcShort (myGlCore20, glVertexAttrib1sv)
1029     && FindProcShort (myGlCore20, glVertexAttrib2d)
1030     && FindProcShort (myGlCore20, glVertexAttrib2dv)
1031     && FindProcShort (myGlCore20, glVertexAttrib2f)
1032     && FindProcShort (myGlCore20, glVertexAttrib2fv)
1033     && FindProcShort (myGlCore20, glVertexAttrib2s)
1034     && FindProcShort (myGlCore20, glVertexAttrib2sv)
1035     && FindProcShort (myGlCore20, glVertexAttrib3d)
1036     && FindProcShort (myGlCore20, glVertexAttrib3dv)
1037     && FindProcShort (myGlCore20, glVertexAttrib3f)
1038     && FindProcShort (myGlCore20, glVertexAttrib3fv)
1039     && FindProcShort (myGlCore20, glVertexAttrib3s)
1040     && FindProcShort (myGlCore20, glVertexAttrib3sv)
1041     && FindProcShort (myGlCore20, glVertexAttrib4Nbv)
1042     && FindProcShort (myGlCore20, glVertexAttrib4Niv)
1043     && FindProcShort (myGlCore20, glVertexAttrib4Nsv)
1044     && FindProcShort (myGlCore20, glVertexAttrib4Nub)
1045     && FindProcShort (myGlCore20, glVertexAttrib4Nubv)
1046     && FindProcShort (myGlCore20, glVertexAttrib4Nuiv)
1047     && FindProcShort (myGlCore20, glVertexAttrib4Nusv)
1048     && FindProcShort (myGlCore20, glVertexAttrib4bv)
1049     && FindProcShort (myGlCore20, glVertexAttrib4d)
1050     && FindProcShort (myGlCore20, glVertexAttrib4dv)
1051     && FindProcShort (myGlCore20, glVertexAttrib4f)
1052     && FindProcShort (myGlCore20, glVertexAttrib4fv)
1053     && FindProcShort (myGlCore20, glVertexAttrib4iv)
1054     && FindProcShort (myGlCore20, glVertexAttrib4s)
1055     && FindProcShort (myGlCore20, glVertexAttrib4sv)
1056     && FindProcShort (myGlCore20, glVertexAttrib4ubv)
1057     && FindProcShort (myGlCore20, glVertexAttrib4uiv)
1058     && FindProcShort (myGlCore20, glVertexAttrib4usv)
1059     && FindProcShort (myGlCore20, glVertexAttribPointer);
1060
1061   if (!hasGlCore12)
1062   {
1063     myGlVerMajor = 1;
1064     myGlVerMinor = 1;
1065     return;
1066   }
1067   else
1068   {
1069     core12 = myGlCore20;
1070   }
1071   if (!hasGlCore13)
1072   {
1073     myGlVerMajor = 1;
1074     myGlVerMinor = 2;
1075     return;
1076   }
1077   else
1078   {
1079     core13 = myGlCore20;
1080   }
1081   if(!hasGlCore14)
1082   {
1083     myGlVerMajor = 1;
1084     myGlVerMinor = 3;
1085     return;
1086   }
1087   else
1088   {
1089     core14 = myGlCore20;
1090   }
1091   if(!hasGlCore15)
1092   {
1093     myGlVerMajor = 1;
1094     myGlVerMinor = 4;
1095     return;
1096   }
1097   else
1098   {
1099     core15 = myGlCore20;
1100   }
1101   if(!hasGlCore20)
1102   {
1103     myGlVerMajor = 1;
1104     myGlVerMinor = 5;
1105   }
1106   else
1107   {
1108     core20 = myGlCore20;
1109   }
1110 }
1111
1112 // =======================================================================
1113 // function : MemoryInfo
1114 // purpose  :
1115 // =======================================================================
1116 Standard_Size OpenGl_Context::AvailableMemory() const
1117 {
1118   if (atiMem)
1119   {
1120     // this is actually information for VBO pool
1121     // however because pools are mostly shared
1122     // it can be used for total GPU memory estimations
1123     GLint aMemInfo[4];
1124     aMemInfo[0] = 0;
1125     glGetIntegerv (GL_VBO_FREE_MEMORY_ATI, aMemInfo);
1126     // returned value is in KiB, however this maybe changed in future
1127     return Standard_Size(aMemInfo[0]) * 1024;
1128   }
1129   else if (nvxMem)
1130   {
1131     // current available dedicated video memory (in KiB), currently unused GPU memory
1132     GLint aMemInfo = 0;
1133     glGetIntegerv (GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &aMemInfo);
1134     return Standard_Size(aMemInfo) * 1024;
1135   }
1136   return 0;
1137 }
1138
1139 // =======================================================================
1140 // function : MemoryInfo
1141 // purpose  :
1142 // =======================================================================
1143 TCollection_AsciiString OpenGl_Context::MemoryInfo() const
1144 {
1145   TCollection_AsciiString anInfo;
1146   if (atiMem)
1147   {
1148     GLint aValues[4];
1149     memset (aValues, 0, sizeof(aValues));
1150     glGetIntegerv (GL_VBO_FREE_MEMORY_ATI, aValues);
1151
1152     // total memory free in the pool
1153     anInfo += TCollection_AsciiString ("  GPU free memory:    ") + (aValues[0] / 1024) + " MiB\n";
1154
1155     // largest available free block in the pool
1156     anInfo += TCollection_AsciiString ("  Largest free block: ") + (aValues[1] / 1024) + " MiB\n";
1157     if (aValues[2] != aValues[0])
1158     {
1159       // total auxiliary memory free
1160       anInfo += TCollection_AsciiString ("  Free memory:        ") + (aValues[2] / 1024) + " MiB\n";
1161     }
1162   }
1163   else if (nvxMem)
1164   {
1165     //current available dedicated video memory (in KiB), currently unused GPU memory
1166     GLint aValue = 0;
1167     glGetIntegerv (GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &aValue);
1168     anInfo += TCollection_AsciiString ("  GPU free memory:    ") + (aValue / 1024) + " MiB\n";
1169
1170     // dedicated video memory, total size (in KiB) of the GPU memory
1171     GLint aDedicated = 0;
1172     glGetIntegerv (GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, &aDedicated);
1173     anInfo += TCollection_AsciiString ("  GPU memory:         ") + (aDedicated / 1024) + " MiB\n";
1174
1175     // total available memory, total size (in KiB) of the memory available for allocations
1176     glGetIntegerv (GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, &aValue);
1177     if (aValue != aDedicated)
1178     {
1179       // different only for special configurations
1180       anInfo += TCollection_AsciiString ("  Total memory:       ") + (aValue / 1024) + " MiB\n";
1181     }
1182   }
1183   return anInfo;
1184 }
1185
1186
1187 // =======================================================================
1188 // function : GetResource
1189 // purpose  :
1190 // =======================================================================
1191 const Handle(OpenGl_Resource)& OpenGl_Context::GetResource (const TCollection_AsciiString& theKey) const
1192 {
1193   return mySharedResources->IsBound (theKey) ? mySharedResources->Find (theKey) : NULL_GL_RESOURCE;
1194 }
1195
1196 // =======================================================================
1197 // function : ShareResource
1198 // purpose  :
1199 // =======================================================================
1200 Standard_Boolean OpenGl_Context::ShareResource (const TCollection_AsciiString& theKey,
1201                                                 const Handle(OpenGl_Resource)& theResource)
1202 {
1203   if (theKey.IsEmpty() || theResource.IsNull())
1204   {
1205     return Standard_False;
1206   }
1207   return mySharedResources->Bind (theKey, theResource);
1208 }
1209
1210 // =======================================================================
1211 // function : ReleaseResource
1212 // purpose  :
1213 // =======================================================================
1214 void OpenGl_Context::ReleaseResource (const TCollection_AsciiString& theKey,
1215                                       const Standard_Boolean         theToDelay)
1216 {
1217   if (!mySharedResources->IsBound (theKey))
1218   {
1219     return;
1220   }
1221   const Handle(OpenGl_Resource)& aRes = mySharedResources->Find (theKey);
1222   if (aRes->GetRefCount() > 1)
1223   {
1224     return;
1225   }
1226
1227   if (theToDelay)
1228   {
1229     myDelayed->Bind (theKey, 1);
1230   }
1231   else
1232   {
1233     aRes->Release (this);
1234     mySharedResources->UnBind (theKey);
1235   }
1236 }
1237
1238 // =======================================================================
1239 // function : DelayedRelease
1240 // purpose  :
1241 // =======================================================================
1242 void OpenGl_Context::DelayedRelease (Handle(OpenGl_Resource)& theResource)
1243 {
1244   myReleaseQueue->Push (theResource);
1245   theResource.Nullify();
1246 }
1247
1248 // =======================================================================
1249 // function : ReleaseDelayed
1250 // purpose  :
1251 // =======================================================================
1252 void OpenGl_Context::ReleaseDelayed()
1253 {
1254   // release queued elements
1255   while (!myReleaseQueue->IsEmpty())
1256   {
1257     myReleaseQueue->Front()->Release (this);
1258     myReleaseQueue->Pop();
1259   }
1260
1261   // release delayed shared resources
1262   NCollection_Vector<TCollection_AsciiString> aDeadList;
1263   for (NCollection_DataMap<TCollection_AsciiString, Standard_Integer>::Iterator anIter (*myDelayed);
1264        anIter.More(); anIter.Next())
1265   {
1266     if (++anIter.ChangeValue() <= 2)
1267     {
1268       continue; // postpone release one more frame to ensure noone use it periodically
1269     }
1270
1271     const TCollection_AsciiString& aKey = anIter.Key();
1272     if (!mySharedResources->IsBound (aKey))
1273     {
1274       // mixed unshared strategy delayed/undelayed was used!
1275       aDeadList.Append (aKey);
1276       continue;
1277     }
1278
1279     Handle(OpenGl_Resource)& aRes = mySharedResources->ChangeFind (aKey);
1280     if (aRes->GetRefCount() > 1)
1281     {
1282       // should be only 1 instance in mySharedResources
1283       // if not - resource was reused again
1284       aDeadList.Append (aKey);
1285       continue;
1286     }
1287
1288     // release resource if no one requiested it more than 2 redraw calls
1289     aRes->Release (this);
1290     mySharedResources->UnBind (aKey);
1291     aDeadList.Append (aKey);
1292   }
1293
1294   for (Standard_Integer anIter = 0; anIter < aDeadList.Length(); ++anIter)
1295   {
1296     myDelayed->UnBind (aDeadList.Value (anIter));
1297   }
1298 }