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