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