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