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