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