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