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