0031478: Visualization, TKOpenGl - allow uploading Cubemap in compressed DDS format...
[occt.git] / src / OpenGl / OpenGl_Context.cxx
1 // Created on: 2012-01-26
2 // Created by: Kirill GAVRILOV
3 // Copyright (c) 2012-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #if defined(_WIN32)
17   #include <windows.h>
18 #endif
19
20 #include <OpenGl_Context.hxx>
21
22 #include <OpenGl_ArbTBO.hxx>
23 #include <OpenGl_ArbIns.hxx>
24 #include <OpenGl_ArbDbg.hxx>
25 #include <OpenGl_ArbFBO.hxx>
26 #include <OpenGl_ExtGS.hxx>
27 #include <OpenGl_ArbSamplerObject.hxx>
28 #include <OpenGl_ArbTexBindless.hxx>
29 #include <OpenGl_GlCore45.hxx>
30 #include <OpenGl_FrameBuffer.hxx>
31 #include <OpenGl_FrameStats.hxx>
32 #include <OpenGl_Sampler.hxx>
33 #include <OpenGl_ShaderManager.hxx>
34 #include <OpenGl_TextureSetPairIterator.hxx>
35 #include <OpenGl_Workspace.hxx>
36 #include <OpenGl_Aspects.hxx>
37
38 #include <Graphic3d_TransformUtils.hxx>
39 #include <Graphic3d_RenderingParams.hxx>
40 #include <Image_SupportedFormats.hxx>
41 #include <Message_Messenger.hxx>
42 #include <NCollection_Vector.hxx>
43 #include <Standard_ProgramError.hxx>
44 #include <Standard_WarningDisableFunctionCast.hxx>
45
46 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Context,Standard_Transient)
47
48 #if defined(HAVE_EGL)
49   #include <EGL/egl.h>
50   #ifdef _MSC_VER
51     #pragma comment(lib, "libEGL.lib")
52   #endif
53 #elif defined(_WIN32)
54   //
55 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
56   #include <dlfcn.h>
57   #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
58     //
59   #else
60     #include <OpenGL/OpenGL.h>
61     #include <CoreGraphics/CoreGraphics.h>
62   #endif
63 #else
64   #include <GL/glx.h> // glXGetProcAddress()
65 #endif
66
67 #ifdef __EMSCRIPTEN__
68   #include <emscripten/html5.h>
69
70   //! Check if WebGL extension is available and activate it
71   //! (usage of extension without activation will generate errors).
72   static bool checkEnableWebGlExtension (const OpenGl_Context& theCtx,
73                                          const char* theExtName)
74   {
75     if (!theCtx.CheckExtension (theExtName))
76     {
77       return false;
78     }
79     if (EMSCRIPTEN_WEBGL_CONTEXT_HANDLE aWebGlCtx = emscripten_webgl_get_current_context())
80     {
81       if (emscripten_webgl_enable_extension (aWebGlCtx, theExtName))
82       {
83         return true;
84       }
85     }
86     return false;
87   }
88 #endif
89
90 namespace
91 {
92   static const Handle(OpenGl_Resource) NULL_GL_RESOURCE;
93   static const OpenGl_Mat4 THE_IDENTITY_MATRIX;
94
95   //! Add key-value pair to the dictionary.
96   static void addInfo (TColStd_IndexedDataMapOfStringString& theDict,
97                        const TCollection_AsciiString& theKey,
98                        const TCollection_AsciiString& theValue)
99   {
100     theDict.ChangeFromIndex (theDict.Add (theKey, theValue)) = theValue;
101   }
102
103   //! Add key-value pair to the dictionary.
104   static void addInfo (TColStd_IndexedDataMapOfStringString& theDict,
105                        const TCollection_AsciiString& theKey,
106                        const char* theValue)
107   {
108     TCollection_AsciiString aValue (theValue != NULL ? theValue : "");
109     theDict.ChangeFromIndex (theDict.Add (theKey, aValue)) = aValue;
110   }
111 }
112
113 // =======================================================================
114 // function : OpenGl_Context
115 // purpose  :
116 // =======================================================================
117 OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps)
118 : core11     (NULL),
119   core11fwd  (NULL),
120   core15     (NULL),
121   core15fwd  (NULL),
122   core20     (NULL),
123   core20fwd  (NULL),
124   core32     (NULL),
125   core32back (NULL),
126   core33     (NULL),
127   core33back (NULL),
128   core41     (NULL),
129   core41back (NULL),
130   core42     (NULL),
131   core42back (NULL),
132   core43     (NULL),
133   core43back (NULL),
134   core44     (NULL),
135   core44back (NULL),
136   core45     (NULL),
137   core45back (NULL),
138   caps   (!theCaps.IsNull() ? theCaps : new OpenGl_Caps()),
139 #if defined(GL_ES_VERSION_2_0)
140   hasHighp   (Standard_False),
141   hasUintIndex(Standard_False),
142   hasTexRGBA8(Standard_False),
143 #else
144   hasHighp   (Standard_True),
145   hasUintIndex(Standard_True),
146   hasTexRGBA8(Standard_True),
147 #endif
148   hasTexFloatLinear (Standard_False),
149   hasTexSRGB (Standard_False),
150   hasFboSRGB (Standard_False),
151   hasSRGBControl (Standard_False),
152 #if defined(GL_ES_VERSION_2_0)
153   hasFlatShading (OpenGl_FeatureNotAvailable),
154 #else
155   hasFlatShading (OpenGl_FeatureInCore),
156 #endif
157   hasGlslBitwiseOps  (OpenGl_FeatureNotAvailable),
158   hasDrawBuffers     (OpenGl_FeatureNotAvailable),
159   hasFloatBuffer     (OpenGl_FeatureNotAvailable),
160   hasHalfFloatBuffer (OpenGl_FeatureNotAvailable),
161   hasSampleVariables (OpenGl_FeatureNotAvailable),
162   hasGeometryStage   (OpenGl_FeatureNotAvailable),
163   arbDrawBuffers (Standard_False),
164   arbNPTW  (Standard_False),
165   arbTexRG (Standard_False),
166   arbTexFloat (Standard_False),
167   arbSamplerObject (NULL),
168   arbTexBindless (NULL),
169   arbTBO (NULL),
170   arbTboRGB32 (Standard_False),
171   arbIns (NULL),
172   arbDbg (NULL),
173   arbFBO (NULL),
174   arbFBOBlit (NULL),
175   arbSampleShading (Standard_False),
176   extFragDepth (Standard_False),
177   extDrawBuffers (Standard_False),
178   extGS  (NULL),
179   extBgra(Standard_False),
180   extAnis(Standard_False),
181   extPDS (Standard_False),
182   atiMem (Standard_False),
183   nvxMem (Standard_False),
184   oesSampleVariables (Standard_False),
185   oesStdDerivatives (Standard_False),
186   mySharedResources (new OpenGl_ResourcesMap()),
187   myDelayed         (new OpenGl_DelayReleaseMap()),
188   myUnusedResources (new OpenGl_ResourcesStack()),
189   myClippingState (),
190   myGlLibHandle (NULL),
191   myFuncs (new OpenGl_GlFunctions()),
192   mySupportedFormats (new Image_SupportedFormats()),
193   myAnisoMax   (1),
194   myTexClamp   (GL_CLAMP_TO_EDGE),
195   myMaxTexDim  (1024),
196   myMaxTexCombined (1),
197   myMaxTexUnitsFFP (1),
198   myMaxDumpSizeX (1024),
199   myMaxDumpSizeY (1024),
200   myMaxClipPlanes (6),
201   myMaxMsaaSamples(0),
202   myMaxDrawBuffers (1),
203   myMaxColorAttachments (1),
204   myGlVerMajor (0),
205   myGlVerMinor (0),
206   myIsInitialized (Standard_False),
207   myIsStereoBuffers (Standard_False),
208   myIsGlNormalizeEnabled (Standard_False),
209   mySpriteTexUnit (Graphic3d_TextureUnit_PointSprite),
210   myHasRayTracing (Standard_False),
211   myHasRayTracingTextures (Standard_False),
212   myHasRayTracingAdaptiveSampling (Standard_False),
213   myHasRayTracingAdaptiveSamplingAtomic (Standard_False),
214   myHasPBR (Standard_False),
215   myPBREnvLUTTexUnit       (Graphic3d_TextureUnit_PbrEnvironmentLUT),
216   myPBRDiffIBLMapSHTexUnit (Graphic3d_TextureUnit_PbrIblDiffuseSH),
217   myPBRSpecIBLMapTexUnit   (Graphic3d_TextureUnit_PbrIblSpecular),
218   myFrameStats (new OpenGl_FrameStats()),
219   myActiveMockTextures (0),
220 #if !defined(GL_ES_VERSION_2_0)
221   myPointSpriteOrig (GL_UPPER_LEFT),
222   myRenderMode (GL_RENDER),
223   myShadeModel (GL_SMOOTH),
224   myPolygonMode (GL_FILL),
225 #else
226   myPointSpriteOrig (0),
227   myRenderMode (0),
228   myShadeModel (0),
229   myPolygonMode (0),
230 #endif
231   myToCullBackFaces (false),
232   myReadBuffer (0),
233   myDrawBuffers (0, 7),
234   myDefaultVao (0),
235   myColorMask (true),
236   myAlphaToCoverage (false),
237   myIsGlDebugCtx (false),
238   myIsSRgbWindow (false),
239   myResolution (Graphic3d_RenderingParams::THE_DEFAULT_RESOLUTION),
240   myResolutionRatio (1.0f),
241   myLineWidthScale (1.0f),
242   myLineFeather (1.0f),
243   myRenderScale (1.0f),
244   myRenderScaleInv (1.0f)
245 {
246   myViewport[0] = 0;
247   myViewport[1] = 0;
248   myViewport[2] = 0;
249   myViewport[3] = 0;
250   myViewportVirt[0] = 0;
251   myViewportVirt[1] = 0;
252   myViewportVirt[2] = 0;
253   myViewportVirt[3] = 0;
254
255   myPolygonOffset.Mode   = Aspect_POM_Off;
256   myPolygonOffset.Factor = 0.0f;
257   myPolygonOffset.Units  = 0.0f;
258
259   // system-dependent fields
260 #if defined(HAVE_EGL)
261   myDisplay  = (Aspect_Display          )EGL_NO_DISPLAY;
262   myWindow   = (Aspect_Drawable         )EGL_NO_SURFACE;
263   myGContext = (Aspect_RenderingContext )EGL_NO_CONTEXT;
264 #elif defined(_WIN32)
265   myWindow   = NULL;
266   myWindowDC = NULL;
267   myGContext = NULL;
268 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
269   // Vendors can not extend functionality on this system
270   // and developers are limited to OpenGL support provided by Mac OS X SDK.
271   // We retrieve function pointers from system library
272   // to generalize extensions support on all platforms.
273   // In this way we also reach binary compatibility benefit between OS releases
274   // if some newest functionality is optionally used.
275   // Notice that GL version / extension availability checks are required
276   // because function pointers may be available but not functionality itself
277   // (depends on renderer).
278 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
279   myGContext    = NULL;
280   myGlLibHandle = dlopen ("/System/Library/Frameworks/OpenGLES.framework/OpenGLES", RTLD_LAZY);
281 #else
282   myGContext    = NULL;
283   myGlLibHandle = dlopen ("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY);
284 #endif
285 #else
286   myDisplay =  NULL;
287   myWindow   = 0;
288   myGContext = 0;
289 #endif
290
291   memset (myFuncs.operator->(), 0, sizeof(OpenGl_GlFunctions));
292   myShaderManager = new OpenGl_ShaderManager (this);
293 }
294
295 // =======================================================================
296 // function : ~OpenGl_Context
297 // purpose  :
298 // =======================================================================
299 OpenGl_Context::~OpenGl_Context()
300 {
301   // release clean up queue
302   ReleaseDelayed();
303
304 #if !defined(GL_ES_VERSION_2_0)
305   // release default VAO
306   if (myDefaultVao != 0
307    && IsValid()
308    && core32 != NULL)
309   {
310     core32->glDeleteVertexArrays (1, &myDefaultVao);
311   }
312   myDefaultVao = 0;
313 #endif
314
315   // release mock textures
316   if (!myTextureRgbaBlack.IsNull())
317   {
318     myTextureRgbaBlack->Release (this);
319     myTextureRgbaBlack.Nullify();
320   }
321   if (!myTextureRgbaWhite.IsNull())
322   {
323     myTextureRgbaWhite->Release (this);
324     myTextureRgbaWhite.Nullify();
325   }
326
327   // release default FBO
328   if (!myDefaultFbo.IsNull())
329   {
330     myDefaultFbo->Release (this);
331     myDefaultFbo.Nullify();
332   }
333
334   // release shared resources if any
335   if (mySharedResources->GetRefCount() <= 1)
336   {
337     myShaderManager.Nullify();
338     for (NCollection_DataMap<TCollection_AsciiString, Handle(OpenGl_Resource)>::Iterator anIter (*mySharedResources);
339          anIter.More(); anIter.Next())
340     {
341       anIter.Value()->Release (this);
342     }
343
344     // release delayed resources added during deletion of shared resources
345     while (!myUnusedResources->IsEmpty())
346     {
347       myUnusedResources->First()->Release (this);
348       myUnusedResources->RemoveFirst();
349     }
350   }
351   else if (myShaderManager->IsSameContext (this))
352   {
353     myShaderManager->SetContext (NULL);
354   }
355   mySharedResources.Nullify();
356   myDelayed.Nullify();
357
358   if (arbDbg != NULL
359    && myIsGlDebugCtx
360    && IsValid())
361   {
362     // reset callback
363   #if !defined(GL_ES_VERSION_2_0)
364     void* aPtr = NULL;
365     glGetPointerv (GL_DEBUG_CALLBACK_USER_PARAM, &aPtr);
366     if (aPtr == this)
367   #endif
368     {
369       arbDbg->glDebugMessageCallback (NULL, NULL);
370     }
371     myIsGlDebugCtx = Standard_False;
372   }
373 }
374
375 // =======================================================================
376 // function : forcedRelease
377 // purpose  :
378 // =======================================================================
379 void OpenGl_Context::forcedRelease()
380 {
381   ReleaseDelayed();
382   for (NCollection_DataMap<TCollection_AsciiString, Handle(OpenGl_Resource)>::Iterator anIter (*mySharedResources);
383        anIter.More(); anIter.Next())
384   {
385     anIter.Value()->Release (this);
386   }
387   mySharedResources->Clear();
388   myShaderManager->clear();
389   myShaderManager->SetContext (NULL);
390
391   // release delayed resources added during deletion of shared resources
392   while (!myUnusedResources->IsEmpty())
393   {
394     myUnusedResources->First()->Release (this);
395     myUnusedResources->RemoveFirst();
396   }
397 }
398
399 // =======================================================================
400 // function : ResizeViewport
401 // purpose  :
402 // =======================================================================
403 void OpenGl_Context::ResizeViewport (const Standard_Integer* theRect)
404 {
405   core11fwd->glViewport (theRect[0], theRect[1], theRect[2], theRect[3]);
406   myViewport[0] = theRect[0];
407   myViewport[1] = theRect[1];
408   myViewport[2] = theRect[2];
409   myViewport[3] = theRect[3];
410   if (HasRenderScale())
411   {
412     myViewportVirt[0] = Standard_Integer(theRect[0] * myRenderScaleInv);
413     myViewportVirt[1] = Standard_Integer(theRect[1] * myRenderScaleInv);
414     myViewportVirt[2] = Standard_Integer(theRect[2] * myRenderScaleInv);
415     myViewportVirt[3] = Standard_Integer(theRect[3] * myRenderScaleInv);
416   }
417   else
418   {
419     myViewportVirt[0] = theRect[0];
420     myViewportVirt[1] = theRect[1];
421     myViewportVirt[2] = theRect[2];
422     myViewportVirt[3] = theRect[3];
423   }
424 }
425
426 #if !defined(GL_ES_VERSION_2_0)
427 inline Standard_Integer stereoToMonoBuffer (const Standard_Integer theBuffer)
428 {
429   switch (theBuffer)
430   {
431     case GL_BACK_LEFT:
432     case GL_BACK_RIGHT:
433       return GL_BACK;
434     case GL_FRONT_LEFT:
435     case GL_FRONT_RIGHT:
436       return GL_FRONT;
437     default:
438       return theBuffer;
439   }
440 }
441 #endif
442
443 // =======================================================================
444 // function : SetReadBuffer
445 // purpose  :
446 // =======================================================================
447 void OpenGl_Context::SetReadBuffer (const Standard_Integer theReadBuffer)
448 {
449 #if !defined(GL_ES_VERSION_2_0)
450   myReadBuffer = !myIsStereoBuffers ? stereoToMonoBuffer (theReadBuffer) : theReadBuffer;
451   if (myReadBuffer < GL_COLOR_ATTACHMENT0
452    && arbFBO != NULL)
453   {
454     arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
455   }
456   ::glReadBuffer (myReadBuffer);
457 #else
458   (void )theReadBuffer;
459 #endif
460 }
461
462 // =======================================================================
463 // function : SetDrawBuffer
464 // purpose  :
465 // =======================================================================
466 void OpenGl_Context::SetDrawBuffer (const Standard_Integer theDrawBuffer)
467 {
468 #if !defined(GL_ES_VERSION_2_0)
469   const Standard_Integer aDrawBuffer = !myIsStereoBuffers ? stereoToMonoBuffer (theDrawBuffer) : theDrawBuffer;
470   if (aDrawBuffer < GL_COLOR_ATTACHMENT0
471    && arbFBO != NULL)
472   {
473     arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
474   }
475   ::glDrawBuffer (aDrawBuffer);
476
477   myDrawBuffers.Init (GL_NONE);
478   myDrawBuffers.SetValue (0, aDrawBuffer);
479 #else
480   (void )theDrawBuffer;
481 #endif
482 }
483
484 // =======================================================================
485 // function : SetDrawBuffers
486 // purpose  :
487 // =======================================================================
488 void OpenGl_Context::SetDrawBuffers (const Standard_Integer theNb, const Standard_Integer* theDrawBuffers)
489 {
490   Standard_ASSERT_RETURN (hasDrawBuffers, "Multiple draw buffers feature is not supported by the context", Standard_ASSERT_DO_NOTHING());
491
492   if (myDrawBuffers.Length() < theNb)
493   {
494     // should actually never happen here
495     myDrawBuffers.Resize (0, theNb - 1, false);
496   }
497   myDrawBuffers.Init (GL_NONE);
498
499   Standard_Boolean useDefaultFbo = Standard_False;
500   for (Standard_Integer anI = 0; anI < theNb; ++anI)
501   {
502     if (theDrawBuffers[anI] < GL_COLOR_ATTACHMENT0 && theDrawBuffers[anI] != GL_NONE)
503     {
504       useDefaultFbo = Standard_True;
505     }
506     else
507     {
508       myDrawBuffers.SetValue (anI, theDrawBuffers[anI]);
509     }
510   }
511   if (arbFBO != NULL && useDefaultFbo)
512   {
513     arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
514   }
515
516   myFuncs->glDrawBuffers (theNb, (const GLenum*)theDrawBuffers);
517 }
518
519 // =======================================================================
520 // function : SetFrameBufferSRGB
521 // purpose  :
522 // =======================================================================
523 void OpenGl_Context::SetFrameBufferSRGB (bool theIsFbo, bool theIsFboSRgb)
524 {
525   if (!hasFboSRGB)
526   {
527     myIsSRgbActive = false;
528     return;
529   }
530   myIsSRgbActive = ToRenderSRGB()
531                && (theIsFbo || myIsSRgbWindow)
532                && theIsFboSRgb;
533   if (!hasSRGBControl)
534   {
535     return;
536   }
537
538   if (myIsSRgbActive)
539   {
540     core11fwd->glEnable (GL_FRAMEBUFFER_SRGB);
541   }
542   else
543   {
544     core11fwd->glDisable (GL_FRAMEBUFFER_SRGB);
545   }
546 }
547
548 // =======================================================================
549 // function : SetCullBackFaces
550 // purpose  :
551 // =======================================================================
552 void OpenGl_Context::SetCullBackFaces (bool theToEnable)
553 {
554   if (myToCullBackFaces == theToEnable)
555   {
556     return;
557   }
558
559   myToCullBackFaces = theToEnable;
560   if (theToEnable)
561   {
562     //glCullFace (GL_BACK); GL_BACK by default
563     core11fwd->glEnable (GL_CULL_FACE);
564   }
565   else
566   {
567     core11fwd->glDisable (GL_CULL_FACE);
568   }
569 }
570
571 // =======================================================================
572 // function : FetchState
573 // purpose  :
574 // =======================================================================
575 void OpenGl_Context::FetchState()
576 {
577 #if !defined(GL_ES_VERSION_2_0)
578   // cache feedback mode state
579   if (core11 != NULL)
580   {
581     ::glGetIntegerv (GL_RENDER_MODE, &myRenderMode);
582     ::glGetIntegerv (GL_SHADE_MODEL, &myShadeModel);
583   }
584
585   // cache read buffers state
586   ::glGetIntegerv (GL_READ_BUFFER, &myReadBuffer);
587
588   // cache draw buffers state
589   if (myDrawBuffers.Length() < myMaxDrawBuffers)
590   {
591     myDrawBuffers.Resize (0, myMaxDrawBuffers - 1, false);
592   }
593   myDrawBuffers.Init (GL_NONE);
594
595   Standard_Integer aDrawBuffer = GL_NONE;
596   if (myMaxDrawBuffers == 1)
597   {
598     ::glGetIntegerv (GL_DRAW_BUFFER, &aDrawBuffer);
599     myDrawBuffers.SetValue (0, aDrawBuffer);
600   }
601   else
602   {
603     for (Standard_Integer anI = 0; anI < myMaxDrawBuffers; ++anI)
604     {
605       ::glGetIntegerv (GL_DRAW_BUFFER0 + anI, &aDrawBuffer);
606       myDrawBuffers.SetValue (anI, aDrawBuffer);
607     }
608   }
609 #endif
610 }
611
612 // =======================================================================
613 // function : Share
614 // purpose  :
615 // =======================================================================
616 void OpenGl_Context::Share (const Handle(OpenGl_Context)& theShareCtx)
617 {
618   if (!theShareCtx.IsNull())
619   {
620     mySharedResources = theShareCtx->mySharedResources;
621     myDelayed         = theShareCtx->myDelayed;
622     myUnusedResources = theShareCtx->myUnusedResources;
623     myShaderManager   = theShareCtx->myShaderManager;
624   }
625 }
626
627 #if !defined(__APPLE__) || defined(MACOSX_USE_GLX)
628
629 // =======================================================================
630 // function : IsCurrent
631 // purpose  :
632 // =======================================================================
633 Standard_Boolean OpenGl_Context::IsCurrent() const
634 {
635 #if defined(HAVE_EGL)
636   if ((EGLDisplay )myDisplay  == EGL_NO_DISPLAY
637    || (EGLContext )myGContext == EGL_NO_CONTEXT)
638   {
639     return Standard_False;
640   }
641
642   return (((EGLDisplay )myDisplay  == eglGetCurrentDisplay())
643        && ((EGLContext )myGContext == eglGetCurrentContext())
644        && ((EGLSurface )myWindow   == eglGetCurrentSurface (EGL_DRAW)));
645 #elif defined(_WIN32)
646   if (myWindowDC == NULL || myGContext == NULL)
647   {
648     return Standard_False;
649   }
650   return (( (HDC )myWindowDC == wglGetCurrentDC())
651       && ((HGLRC )myGContext == wglGetCurrentContext()));
652 #else
653   if (myDisplay == NULL || myWindow == 0 || myGContext == 0)
654   {
655     return Standard_False;
656   }
657
658   return (   ((Display* )myDisplay  == glXGetCurrentDisplay())
659        &&  ((GLXContext )myGContext == glXGetCurrentContext())
660        && ((GLXDrawable )myWindow   == glXGetCurrentDrawable()));
661 #endif
662 }
663
664 // =======================================================================
665 // function : MakeCurrent
666 // purpose  :
667 // =======================================================================
668 Standard_Boolean OpenGl_Context::MakeCurrent()
669 {
670 #if defined(HAVE_EGL)
671   if ((EGLDisplay )myDisplay  == EGL_NO_DISPLAY
672    || (EGLContext )myGContext == EGL_NO_CONTEXT)
673   {
674     Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called before!");
675     return Standard_False;
676   }
677
678   if (eglMakeCurrent ((EGLDisplay )myDisplay, (EGLSurface )myWindow, (EGLSurface )myWindow, (EGLContext )myGContext) != EGL_TRUE)
679   {
680     // if there is no current context it might be impossible to use glGetError() correctly
681     PushMessage (GL_DEBUG_SOURCE_WINDOW_SYSTEM, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
682                  "eglMakeCurrent() has failed!");
683     myIsInitialized = Standard_False;
684     return Standard_False;
685   }
686 #elif defined(_WIN32)
687   if (myWindowDC == NULL || myGContext == NULL)
688   {
689     Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called before!");
690     return Standard_False;
691   }
692
693   // technically it should be safe to activate already bound GL context
694   // however some drivers (Intel etc.) may FAIL doing this for unknown reason
695   if (IsCurrent())
696   {
697     myShaderManager->SetContext (this);
698     return Standard_True;
699   }
700   else if (wglMakeCurrent ((HDC )myWindowDC, (HGLRC )myGContext) != TRUE)
701   {
702     // notice that glGetError() couldn't be used here!
703     wchar_t* aMsgBuff = NULL;
704     DWORD anErrorCode = GetLastError();
705     FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
706                     NULL, anErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (wchar_t* )&aMsgBuff, 0, NULL);
707     TCollection_ExtendedString aMsg ("wglMakeCurrent() has failed. ");
708     if (aMsgBuff != NULL)
709     {
710       aMsg += (Standard_ExtString )aMsgBuff;
711       LocalFree (aMsgBuff);
712     }
713     PushMessage (GL_DEBUG_SOURCE_WINDOW_SYSTEM, GL_DEBUG_TYPE_ERROR, (unsigned int )anErrorCode, GL_DEBUG_SEVERITY_HIGH, aMsg);
714     myIsInitialized = Standard_False;
715     return Standard_False;
716   }
717 #else
718   if (myDisplay == NULL || myWindow == 0 || myGContext == 0)
719   {
720     Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called before!");
721     return Standard_False;
722   }
723
724   if (!glXMakeCurrent ((Display* )myDisplay, (GLXDrawable )myWindow, (GLXContext )myGContext))
725   {
726     // if there is no current context it might be impossible to use glGetError() correctly
727     PushMessage (GL_DEBUG_SOURCE_WINDOW_SYSTEM, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
728                  "glXMakeCurrent() has failed!");
729     myIsInitialized = Standard_False;
730     return Standard_False;
731   }
732 #endif
733   myShaderManager->SetContext (this);
734   return Standard_True;
735 }
736
737 // =======================================================================
738 // function : SwapBuffers
739 // purpose  :
740 // =======================================================================
741 void OpenGl_Context::SwapBuffers()
742 {
743 #if defined(HAVE_EGL)
744   if ((EGLSurface )myWindow != EGL_NO_SURFACE)
745   {
746     eglSwapBuffers ((EGLDisplay )myDisplay, (EGLSurface )myWindow);
747   }
748 #elif defined(_WIN32)
749   if ((HDC )myWindowDC != NULL)
750   {
751     ::SwapBuffers ((HDC )myWindowDC);
752     glFlush();
753   }
754 #else
755   if ((Display* )myDisplay != NULL)
756   {
757     glXSwapBuffers ((Display* )myDisplay, (GLXDrawable )myWindow);
758   }
759 #endif
760 }
761
762 #endif // __APPLE__
763
764 // =======================================================================
765 // function : SetSwapInterval
766 // purpose  :
767 // =======================================================================
768 Standard_Boolean OpenGl_Context::SetSwapInterval (const Standard_Integer theInterval)
769 {
770 #if defined(HAVE_EGL)
771   if (::eglSwapInterval ((EGLDisplay )myDisplay, theInterval) == EGL_TRUE)
772   {
773     return Standard_True;
774   }
775 #elif defined(_WIN32)
776   if (myFuncs->wglSwapIntervalEXT != NULL)
777   {
778     myFuncs->wglSwapIntervalEXT (theInterval);
779     return Standard_True;
780   }
781 #elif defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
782   //
783 #elif defined(__APPLE__)
784   if (::CGLSetParameter (CGLGetCurrentContext(), kCGLCPSwapInterval, &theInterval) == kCGLNoError)
785   {
786     return Standard_True;
787   }
788 #else
789   if (theInterval == -1
790    && myFuncs->glXSwapIntervalEXT != NULL)
791   {
792     typedef int (*glXSwapIntervalEXT_t_x)(Display* theDisplay, GLXDrawable theDrawable, int theInterval);
793     glXSwapIntervalEXT_t_x aFuncPtr = (glXSwapIntervalEXT_t_x )myFuncs->glXSwapIntervalEXT;
794     aFuncPtr ((Display* )myDisplay, (GLXDrawable )myWindow, theInterval);
795     return Standard_True;
796   }
797   else if (myFuncs->glXSwapIntervalSGI != NULL)
798   {
799     myFuncs->glXSwapIntervalSGI (theInterval);
800     return Standard_True;
801   }
802 #endif
803   return Standard_False;
804 }
805
806 // =======================================================================
807 // function : findProc
808 // purpose  :
809 // =======================================================================
810 void* OpenGl_Context::findProc (const char* theFuncName)
811 {
812 #if defined(HAVE_EGL)
813   return (void* )eglGetProcAddress (theFuncName);
814 #elif defined(_WIN32)
815   return (void* )wglGetProcAddress (theFuncName);
816 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
817   return (myGlLibHandle != NULL) ? dlsym (myGlLibHandle, theFuncName) : NULL;
818 #else
819   return (void* )glXGetProcAddress ((const GLubyte* )theFuncName);
820 #endif
821 }
822
823 // =======================================================================
824 // function : CheckExtension
825 // purpose  :
826 // =======================================================================
827 Standard_Boolean OpenGl_Context::CheckExtension (const char* theExtName) const
828 {
829   if (theExtName  == NULL)
830   {
831 #ifdef OCCT_DEBUG
832     std::cerr << "CheckExtension called with NULL string!\n";
833 #endif
834     return Standard_False;
835   }
836   else if (caps->contextNoExtensions)
837   {
838     return Standard_False;
839   }
840
841 #if !defined(GL_ES_VERSION_2_0)
842   // available since OpenGL 3.0
843   // and the ONLY way to check extensions with OpenGL 3.1+ core profile
844   if (IsGlGreaterEqual (3, 0)
845    && myFuncs->glGetStringi != NULL)
846   {
847     GLint anExtNb = 0;
848     ::glGetIntegerv (GL_NUM_EXTENSIONS, &anExtNb);
849     const size_t anExtNameLen = strlen (theExtName);
850     for (GLint anIter = 0; anIter < anExtNb; ++anIter)
851     {
852       const char* anExtension = (const char* )myFuncs->glGetStringi (GL_EXTENSIONS, (GLuint )anIter);
853       const size_t aTestExtNameLen = strlen (anExtension);
854       if (aTestExtNameLen == anExtNameLen
855        && strncmp (anExtension, theExtName, anExtNameLen) == 0)
856       {
857         return Standard_True;
858       }
859     }
860     return Standard_False;
861   }
862 #endif
863
864   // use old way with huge string for all extensions
865   const char* anExtString = (const char* )glGetString (GL_EXTENSIONS);
866   if (anExtString == NULL)
867   {
868     Messenger()->Send ("TKOpenGL: glGetString (GL_EXTENSIONS) has returned NULL! No GL context?", Message_Warning);
869     return Standard_False;
870   }
871   return CheckExtension (anExtString, theExtName);
872 }
873
874 // =======================================================================
875 // function : CheckExtension
876 // purpose  :
877 // =======================================================================
878 Standard_Boolean OpenGl_Context::CheckExtension (const char* theExtString,
879                                                  const char* theExtName)
880 {
881   if (theExtString == NULL)
882   {
883     return Standard_False;
884   }
885
886   // Search for theExtName in the extensions string.
887   // Use of strstr() is not sufficient because extension names can be prefixes of other extension names.
888   char* aPtrIter = (char* )theExtString;
889   const char*  aPtrEnd      = aPtrIter + strlen (theExtString);
890   const size_t anExtNameLen = strlen (theExtName);
891   while (aPtrIter < aPtrEnd)
892   {
893     const size_t n = strcspn (aPtrIter, " ");
894     if ((n == anExtNameLen) && (strncmp (aPtrIter, theExtName, anExtNameLen) == 0))
895     {
896       return Standard_True;
897     }
898     aPtrIter += (n + 1);
899   }
900   return Standard_False;
901 }
902
903 #if !defined(__APPLE__) || defined(MACOSX_USE_GLX)
904
905 // =======================================================================
906 // function : Init
907 // purpose  :
908 // =======================================================================
909 Standard_Boolean OpenGl_Context::Init (const Standard_Boolean theIsCoreProfile)
910 {
911   if (myIsInitialized)
912   {
913     return Standard_True;
914   }
915
916 #if defined(HAVE_EGL)
917   myDisplay  = (Aspect_Display )eglGetCurrentDisplay();
918   myGContext = (Aspect_RenderingContext )eglGetCurrentContext();
919   myWindow   = (Aspect_Drawable )eglGetCurrentSurface(EGL_DRAW);
920 #elif defined(_WIN32)
921   myWindowDC = (Aspect_Handle )wglGetCurrentDC();
922   myGContext = (Aspect_RenderingContext )wglGetCurrentContext();
923 #else
924   myDisplay  = (Aspect_Display )glXGetCurrentDisplay();
925   myGContext = (Aspect_RenderingContext )glXGetCurrentContext();
926   myWindow   = (Aspect_Drawable )glXGetCurrentDrawable();
927 #endif
928   if (myGContext == NULL)
929   {
930     return Standard_False;
931   }
932
933   init (theIsCoreProfile);
934   myIsInitialized = Standard_True;
935   return Standard_True;
936 }
937
938 #endif // __APPLE__
939
940 // =======================================================================
941 // function : Init
942 // purpose  :
943 // =======================================================================
944 #if defined(HAVE_EGL)
945 Standard_Boolean OpenGl_Context::Init (const Aspect_Drawable         theEglSurface,
946                                        const Aspect_Display          theEglDisplay,
947                                        const Aspect_RenderingContext theEglContext,
948                                        const Standard_Boolean        theIsCoreProfile)
949 #elif defined(_WIN32)
950 Standard_Boolean OpenGl_Context::Init (const Aspect_Handle           theWindow,
951                                        const Aspect_Handle           theWindowDC,
952                                        const Aspect_RenderingContext theGContext,
953                                        const Standard_Boolean        theIsCoreProfile)
954 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
955
956 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
957 Standard_Boolean OpenGl_Context::Init (EAGLContext*                  theGContext,
958                                        const Standard_Boolean        theIsCoreProfile)
959 #else
960 Standard_Boolean OpenGl_Context::Init (NSOpenGLContext*              theGContext,
961                                        const Standard_Boolean        theIsCoreProfile)
962 #endif
963
964 #else
965 Standard_Boolean OpenGl_Context::Init (const Aspect_Drawable         theWindow,
966                                        const Aspect_Display          theDisplay,
967                                        const Aspect_RenderingContext theGContext,
968                                        const Standard_Boolean        theIsCoreProfile)
969 #endif
970 {
971   Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called only once!");
972 #if defined(HAVE_EGL)
973   myWindow   = theEglSurface;
974   myGContext = theEglContext;
975   myDisplay  = theEglDisplay;
976 #elif defined(_WIN32)
977   myWindow   = theWindow;
978   myGContext = theGContext;
979   myWindowDC = theWindowDC;
980 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
981   myGContext = theGContext;
982 #else
983   myWindow   = theWindow;
984   myGContext = theGContext;
985   myDisplay  = theDisplay;
986 #endif
987   if (myGContext == NULL || !MakeCurrent())
988   {
989     return Standard_False;
990   }
991
992   init (theIsCoreProfile);
993   myIsInitialized = Standard_True;
994   return Standard_True;
995 }
996
997 // =======================================================================
998 // function : ResetErrors
999 // purpose  :
1000 // =======================================================================
1001 bool OpenGl_Context::ResetErrors (const bool theToPrintErrors)
1002 {
1003   int aPrevErr = 0;
1004   int anErr    = ::glGetError();
1005   const bool hasError = anErr != GL_NO_ERROR;
1006   if (!theToPrintErrors)
1007   {
1008     for (; anErr != GL_NO_ERROR && aPrevErr != anErr; aPrevErr = anErr, anErr = ::glGetError())
1009     {
1010       //
1011     }
1012     return hasError;
1013   }
1014
1015   for (; anErr != GL_NO_ERROR && aPrevErr != anErr; aPrevErr = anErr, anErr = ::glGetError())
1016   {
1017     TCollection_ExtendedString anErrId;
1018     switch (anErr)
1019     {
1020       case GL_INVALID_ENUM:      anErrId = "GL_INVALID_ENUM";      break;
1021       case GL_INVALID_VALUE:     anErrId = "GL_INVALID_VALUE";     break;
1022       case GL_INVALID_OPERATION: anErrId = "GL_INVALID_OPERATION"; break;
1023     #ifdef GL_STACK_OVERFLOW
1024       case GL_STACK_OVERFLOW:    anErrId = "GL_STACK_OVERFLOW";    break;
1025       case GL_STACK_UNDERFLOW:   anErrId = "GL_STACK_UNDERFLOW";   break;
1026     #endif
1027       case GL_OUT_OF_MEMORY:     anErrId = "GL_OUT_OF_MEMORY";     break;
1028       case GL_INVALID_FRAMEBUFFER_OPERATION:
1029         anErrId = "GL_INVALID_FRAMEBUFFER_OPERATION";
1030         break;
1031       default:
1032         anErrId = TCollection_ExtendedString("#") + anErr;
1033         break;
1034     }
1035
1036     const TCollection_ExtendedString aMsg = TCollection_ExtendedString ("Unhandled GL error: ") + anErrId;
1037     PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
1038   }
1039   return hasError;
1040 }
1041
1042 // =======================================================================
1043 // function : ReadGlVersion
1044 // purpose  :
1045 // =======================================================================
1046 void OpenGl_Context::ReadGlVersion (Standard_Integer& theGlVerMajor,
1047                                     Standard_Integer& theGlVerMinor)
1048 {
1049   // reset values
1050   theGlVerMajor = 0;
1051   theGlVerMinor = 0;
1052
1053   bool toCheckVer3 = true;
1054 #if defined(__EMSCRIPTEN__)
1055   // WebGL 1.0 prints annoying invalid enumeration warnings to console.
1056   toCheckVer3 = false;
1057   if (EMSCRIPTEN_WEBGL_CONTEXT_HANDLE aWebGlCtx = emscripten_webgl_get_current_context())
1058   {
1059     EmscriptenWebGLContextAttributes anAttribs = {};
1060     if (emscripten_webgl_get_context_attributes (aWebGlCtx, &anAttribs) == EMSCRIPTEN_RESULT_SUCCESS)
1061     {
1062       toCheckVer3 = anAttribs.majorVersion >= 2;
1063     }
1064   }
1065 #endif
1066
1067   // Available since OpenGL 3.0 and OpenGL ES 3.0.
1068   if (toCheckVer3)
1069   {
1070     GLint aMajor = 0, aMinor = 0;
1071     glGetIntegerv (GL_MAJOR_VERSION, &aMajor);
1072     glGetIntegerv (GL_MINOR_VERSION, &aMinor);
1073     // glGetError() sometimes does not report an error here even if
1074     // GL does not know GL_MAJOR_VERSION and GL_MINOR_VERSION constants.
1075     // This happens on some renderers like e.g. Cygwin MESA.
1076     // Thus checking additionally if GL has put anything to
1077     // the output variables.
1078     if (::glGetError() == GL_NO_ERROR && aMajor != 0 && aMinor != 0)
1079     {
1080       theGlVerMajor = aMajor;
1081       theGlVerMinor = aMinor;
1082       return;
1083     }
1084     for (GLenum anErr = ::glGetError(), aPrevErr = GL_NO_ERROR;; aPrevErr = anErr, anErr = ::glGetError())
1085     {
1086       if (anErr == GL_NO_ERROR
1087        || anErr == aPrevErr)
1088       {
1089         break;
1090       }
1091     }
1092   }
1093
1094   // Read version string.
1095   // Notice that only first two numbers split by point '2.1 XXXXX' are significant.
1096   // Following trash (after space) is vendor-specific.
1097   // New drivers also returns micro version of GL like '3.3.0' which has no meaning
1098   // and should be considered as vendor-specific too.
1099   const char* aVerStr = (const char* )glGetString (GL_VERSION);
1100   if (aVerStr == NULL || *aVerStr == '\0')
1101   {
1102     // invalid GL context
1103     return;
1104   }
1105
1106 //#if defined(GL_ES_VERSION_2_0)
1107   // skip "OpenGL ES-** " section
1108   for (; *aVerStr != '\0'; ++aVerStr)
1109   {
1110     if (*aVerStr >= '0' && *aVerStr <= '9')
1111     {
1112       break;
1113     }
1114   }
1115 //#endif
1116
1117   // parse string for major number
1118   char aMajorStr[32];
1119   char aMinorStr[32];
1120   size_t aMajIter = 0;
1121   while (aVerStr[aMajIter] >= '0' && aVerStr[aMajIter] <= '9')
1122   {
1123     ++aMajIter;
1124   }
1125   if (aMajIter == 0 || aMajIter >= sizeof(aMajorStr))
1126   {
1127     return;
1128   }
1129   memcpy (aMajorStr, aVerStr, aMajIter);
1130   aMajorStr[aMajIter] = '\0';
1131
1132   // parse string for minor number
1133   aVerStr += aMajIter + 1;
1134   size_t aMinIter = 0;
1135   while (aVerStr[aMinIter] >= '0' && aVerStr[aMinIter] <= '9')
1136   {
1137     ++aMinIter;
1138   }
1139   if (aMinIter == 0 || aMinIter >= sizeof(aMinorStr))
1140   {
1141     return;
1142   }
1143   memcpy (aMinorStr, aVerStr, aMinIter);
1144   aMinorStr[aMinIter] = '\0';
1145
1146   // read numbers
1147   theGlVerMajor = atoi (aMajorStr);
1148   theGlVerMinor = atoi (aMinorStr);
1149
1150   if (theGlVerMajor <= 0)
1151   {
1152     theGlVerMajor = 0;
1153     theGlVerMinor = 0;
1154   }
1155 }
1156
1157 static Standard_CString THE_DBGMSG_UNKNOWN = "UNKNOWN";
1158 static Standard_CString THE_DBGMSG_SOURCES[] =
1159 {
1160   ".OpenGL",    // GL_DEBUG_SOURCE_API
1161   ".WinSystem", // GL_DEBUG_SOURCE_WINDOW_SYSTEM
1162   ".GLSL",      // GL_DEBUG_SOURCE_SHADER_COMPILER
1163   ".3rdParty",  // GL_DEBUG_SOURCE_THIRD_PARTY
1164   "",           // GL_DEBUG_SOURCE_APPLICATION
1165   ".Other"      // GL_DEBUG_SOURCE_OTHER
1166 };
1167
1168 static Standard_CString THE_DBGMSG_TYPES[] =
1169 {
1170   "Error",           // GL_DEBUG_TYPE_ERROR
1171   "Deprecated",      // GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR
1172   "Undef. behavior", // GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR
1173   "Portability",     // GL_DEBUG_TYPE_PORTABILITY
1174   "Performance",     // GL_DEBUG_TYPE_PERFORMANCE
1175   "Other"            // GL_DEBUG_TYPE_OTHER
1176 };
1177
1178 static Standard_CString THE_DBGMSG_SEV_HIGH   = "High";   // GL_DEBUG_SEVERITY_HIGH
1179 static Standard_CString THE_DBGMSG_SEV_MEDIUM = "Medium"; // GL_DEBUG_SEVERITY_MEDIUM
1180 static Standard_CString THE_DBGMSG_SEV_LOW    = "Low";    // GL_DEBUG_SEVERITY_LOW
1181
1182 //! Callback for GL_ARB_debug_output extension
1183 static void APIENTRY debugCallbackWrap(unsigned int theSource,
1184                                        unsigned int theType,
1185                                        unsigned int theId,
1186                                        unsigned int theSeverity,
1187                                        int          /*theLength*/,
1188                                        const char*  theMessage,
1189                                        const void*  theUserParam)
1190 {
1191   OpenGl_Context* aCtx = (OpenGl_Context* )theUserParam;
1192   aCtx->PushMessage (theSource, theType, theId, theSeverity, theMessage);
1193 }
1194
1195 // =======================================================================
1196 // function : PushMessage
1197 // purpose  :
1198 // =======================================================================
1199 void OpenGl_Context::PushMessage (const unsigned int theSource,
1200                                   const unsigned int theType,
1201                                   const unsigned int theId,
1202                                   const unsigned int theSeverity,
1203                                   const TCollection_ExtendedString& theMessage)
1204 {
1205   if (caps->suppressExtraMsg
1206    && theSource >= GL_DEBUG_SOURCE_API
1207    && theSource <= GL_DEBUG_SOURCE_OTHER
1208    && myFilters[theSource - GL_DEBUG_SOURCE_API].Contains (theId))
1209   {
1210     return;
1211   }
1212
1213   Standard_CString& aSrc = (theSource >= GL_DEBUG_SOURCE_API
1214                         && theSource <= GL_DEBUG_SOURCE_OTHER)
1215                          ? THE_DBGMSG_SOURCES[theSource - GL_DEBUG_SOURCE_API]
1216                          : THE_DBGMSG_UNKNOWN;
1217   Standard_CString& aType = (theType >= GL_DEBUG_TYPE_ERROR
1218                          && theType <= GL_DEBUG_TYPE_OTHER)
1219                           ? THE_DBGMSG_TYPES[theType - GL_DEBUG_TYPE_ERROR]
1220                           : THE_DBGMSG_UNKNOWN;
1221   Standard_CString& aSev = theSeverity == GL_DEBUG_SEVERITY_HIGH
1222                          ? THE_DBGMSG_SEV_HIGH
1223                          : (theSeverity == GL_DEBUG_SEVERITY_MEDIUM
1224                           ? THE_DBGMSG_SEV_MEDIUM
1225                           : THE_DBGMSG_SEV_LOW);
1226   Message_Gravity aGrav = theSeverity == GL_DEBUG_SEVERITY_HIGH
1227                         ? Message_Alarm
1228                         : (theSeverity == GL_DEBUG_SEVERITY_MEDIUM
1229                          ? Message_Warning
1230                          : Message_Info);
1231
1232   TCollection_ExtendedString aMsg;
1233   aMsg += "TKOpenGl"; aMsg += aSrc;
1234   aMsg += " | Type: ";        aMsg += aType;
1235   aMsg += " | ID: ";          aMsg += (Standard_Integer )theId;
1236   aMsg += " | Severity: ";    aMsg += aSev;
1237   aMsg += " | Message:\n  ";
1238   aMsg += theMessage;
1239   Messenger()->Send (aMsg, aGrav);
1240 }
1241
1242 // =======================================================================
1243 // function : ExcludeMessage
1244 // purpose  :
1245 // ======================================================================
1246 Standard_Boolean OpenGl_Context::ExcludeMessage (const unsigned int theSource,
1247                                                  const unsigned int theId)
1248 {
1249   return theSource >= GL_DEBUG_SOURCE_API
1250       && theSource <= GL_DEBUG_SOURCE_OTHER
1251       && myFilters[theSource - GL_DEBUG_SOURCE_API].Add (theId);
1252 }
1253
1254 // =======================================================================
1255 // function : IncludeMessage
1256 // purpose  :
1257 // ======================================================================
1258 Standard_Boolean OpenGl_Context::IncludeMessage (const unsigned int theSource,
1259                                                  const unsigned int theId)
1260 {
1261   return theSource >= GL_DEBUG_SOURCE_API
1262       && theSource <= GL_DEBUG_SOURCE_OTHER
1263       && myFilters[theSource - GL_DEBUG_SOURCE_API].Remove (theId);
1264 }
1265
1266 // =======================================================================
1267 // function : checkWrongVersion
1268 // purpose  :
1269 // ======================================================================
1270 void OpenGl_Context::checkWrongVersion (Standard_Integer theGlVerMajor, Standard_Integer theGlVerMinor,
1271                                         const char* theLastFailedProc)
1272 {
1273   if (!IsGlGreaterEqual (theGlVerMajor, theGlVerMinor))
1274   {
1275     return;
1276   }
1277
1278   PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
1279                TCollection_AsciiString()
1280                + "Error! OpenGL context reports version "
1281                + myGlVerMajor  + "." + myGlVerMinor
1282                + " but does not export required functions for " + theGlVerMajor + "." + theGlVerMinor
1283                + " (" + (theLastFailedProc != NULL ? theLastFailedProc : "") + ")\n"
1284                + "Please report this issue to OpenGL driver vendor '" + myVendor + "'");
1285
1286   // lower internal version
1287   if (theGlVerMinor > 0)
1288   {
1289     myGlVerMajor = theGlVerMajor;
1290     myGlVerMinor = theGlVerMinor - 1;
1291     return;
1292   }
1293 #if defined(GL_ES_VERSION_2_0)
1294   switch (theGlVerMajor)
1295   {
1296     case 3: myGlVerMajor = 2; myGlVerMinor = 0; return;
1297   }
1298 #else
1299   switch (theGlVerMajor)
1300   {
1301     case 2: myGlVerMajor = 1; myGlVerMinor = 5; return;
1302     case 3: myGlVerMajor = 2; myGlVerMinor = 1; return;
1303     case 4: myGlVerMajor = 3; myGlVerMinor = 3; return;
1304   }
1305 #endif
1306 }
1307
1308 // =======================================================================
1309 // function : init
1310 // purpose  :
1311 // =======================================================================
1312 void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
1313 {
1314   // read version
1315   myGlVerMajor = 0;
1316   myGlVerMinor = 0;
1317   myMaxMsaaSamples = 0;
1318   myMaxDrawBuffers = 1;
1319   myMaxColorAttachments = 1;
1320   ReadGlVersion (myGlVerMajor, myGlVerMinor);
1321   myVendor = (const char* )::glGetString (GL_VENDOR);
1322   myVendor.LowerCase();
1323
1324   // standard formats
1325   mySupportedFormats->Clear();
1326   mySupportedFormats->Add (Image_PixMap::ImgGray);
1327   mySupportedFormats->Add (Image_PixMap::ImgAlpha);
1328   mySupportedFormats->Add (Image_PixMap::ImgRGB);
1329   mySupportedFormats->Add (Image_PixMap::ImgRGB32);
1330   mySupportedFormats->Add (Image_PixMap::ImgRGBA);
1331
1332   if (caps->contextMajorVersionUpper != -1)
1333   {
1334     // synthetically restrict OpenGL version for testing
1335     Standard_Integer aCtxVer[2] = { myGlVerMajor, myGlVerMinor };
1336     bool isLowered = false;
1337     if (myGlVerMajor > caps->contextMajorVersionUpper)
1338     {
1339       isLowered = true;
1340       myGlVerMajor = caps->contextMajorVersionUpper;
1341     #if defined(GL_ES_VERSION_2_0)
1342       switch (myGlVerMajor)
1343       {
1344         case 2: myGlVerMinor = 0; break;
1345       }
1346     #else
1347       switch (myGlVerMajor)
1348       {
1349         case 1: myGlVerMinor = 5; break;
1350         case 2: myGlVerMinor = 1; break;
1351         case 3: myGlVerMinor = 3; break;
1352       }
1353     #endif
1354     }
1355     if (caps->contextMinorVersionUpper != -1
1356      && myGlVerMinor > caps->contextMinorVersionUpper)
1357     {
1358       isLowered = true;
1359       myGlVerMinor = caps->contextMinorVersionUpper;
1360     }
1361     if (isLowered)
1362     {
1363       PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
1364                    TCollection_AsciiString ("OpenGL version ") + aCtxVer[0] + "." + aCtxVer[1]
1365                    + " has been lowered to " + myGlVerMajor + "." + myGlVerMinor);
1366     }
1367   }
1368
1369   if (!caps->ffpEnable
1370    && !IsGlGreaterEqual (2, 0))
1371   {
1372     caps->ffpEnable = true;
1373     TCollection_ExtendedString aMsg =
1374       TCollection_ExtendedString("OpenGL driver is too old! Context info:\n")
1375                                + "    Vendor:   " + (const char* )::glGetString (GL_VENDOR)   + "\n"
1376                                + "    Renderer: " + (const char* )::glGetString (GL_RENDERER) + "\n"
1377                                + "    Version:  " + (const char* )::glGetString (GL_VERSION)  + "\n"
1378                                + "  Fallback using deprecated fixed-function pipeline.\n"
1379                                + "  Visualization might work incorrectly.\n"
1380                                  "  Consider upgrading the graphics driver.";
1381     PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, aMsg);
1382   }
1383
1384 #if defined(GL_ES_VERSION_2_0)
1385   (void )theIsCoreProfile;
1386   const bool isCoreProfile = false;
1387 #else
1388
1389   if (myVendor.Search ("nvidia") != -1)
1390   {
1391     // Buffer detailed info: Buffer object 1 (bound to GL_ARRAY_BUFFER_ARB, usage hint is GL_STATIC_DRAW)
1392     // will use VIDEO memory as the source for buffer object operations.
1393     ExcludeMessage (GL_DEBUG_SOURCE_API, 131185);
1394   }
1395   if (IsGlGreaterEqual (3, 0))
1396   {
1397     // retrieve auxiliary function in advance
1398     FindProc ("glGetStringi", myFuncs->glGetStringi);
1399   }
1400
1401   bool isCoreProfile = false;
1402   if (IsGlGreaterEqual (3, 2))
1403   {
1404     isCoreProfile = (theIsCoreProfile == Standard_True);
1405
1406     // detect Core profile
1407     if (!isCoreProfile)
1408     {
1409       GLint aProfile = 0;
1410       ::glGetIntegerv (GL_CONTEXT_PROFILE_MASK, &aProfile);
1411       isCoreProfile = (aProfile & GL_CONTEXT_CORE_PROFILE_BIT) != 0;
1412     }
1413   }
1414 #endif
1415
1416   core11     = NULL;
1417   if (!isCoreProfile)
1418   {
1419     core11 = (OpenGl_GlCore11* )(&(*myFuncs));
1420   }
1421   core11fwd  = (OpenGl_GlCore11Fwd* )(&(*myFuncs));
1422   core15     = NULL;
1423   core15fwd  = NULL;
1424   core20     = NULL;
1425   core20fwd  = NULL;
1426   core32     = NULL;
1427   core32back = NULL;
1428   core33     = NULL;
1429   core33back = NULL;
1430   core41     = NULL;
1431   core41back = NULL;
1432   core42     = NULL;
1433   core42back = NULL;
1434   core43     = NULL;
1435   core43back = NULL;
1436   core44     = NULL;
1437   core44back = NULL;
1438   core45     = NULL;
1439   core45back = NULL;
1440   arbTBO     = NULL;
1441   arbTboRGB32 = Standard_False;
1442   arbIns     = NULL;
1443   arbDbg     = NULL;
1444   arbFBO     = NULL;
1445   arbFBOBlit = NULL;
1446   extGS      = NULL;
1447   myDefaultVao = 0;
1448
1449   //! Make record shorter to retrieve function pointer using variable with same name
1450   const char* aLastFailedProc = NULL;
1451   #define FindProcShort(theFunc) FindProcVerbose(aLastFailedProc, #theFunc, myFuncs->theFunc)
1452
1453 #if defined(GL_ES_VERSION_2_0)
1454
1455   hasTexRGBA8 = IsGlGreaterEqual (3, 0)
1456              || CheckExtension ("GL_OES_rgb8_rgba8");
1457   hasTexSRGB  = IsGlGreaterEqual (3, 0);
1458   hasFboSRGB  = IsGlGreaterEqual (3, 0);
1459   hasSRGBControl = CheckExtension ("GL_EXT_sRGB_write_control");
1460   // NPOT textures has limited support within OpenGL ES 2.0
1461   // which are relaxed by OpenGL ES 3.0 or some extensions
1462   //arbNPTW     = IsGlGreaterEqual (3, 0)
1463   //           || CheckExtension ("GL_OES_texture_npot")
1464   //           || CheckExtension ("GL_NV_texture_npot_2D_mipmap");
1465   arbNPTW     = Standard_True;
1466   arbTexRG    = IsGlGreaterEqual (3, 0)
1467              || CheckExtension ("GL_EXT_texture_rg");
1468   extBgra     = CheckExtension ("GL_EXT_texture_format_BGRA8888");
1469   extAnis = CheckExtension ("GL_EXT_texture_filter_anisotropic");
1470   extPDS  = IsGlGreaterEqual (3, 0)
1471          || CheckExtension ("GL_OES_packed_depth_stencil");
1472 #ifdef __EMSCRIPTEN__
1473   if (!extPDS
1474     && checkEnableWebGlExtension (*this, "GL_WEBGL_depth_texture"))
1475   {
1476     extPDS = true; // WebGL 1.0 extension (in WebGL 2.0 core)
1477   }
1478 #endif
1479
1480   if (extBgra)
1481   {
1482     // no BGR on OpenGL ES - only BGRA as extension
1483     mySupportedFormats->Add (Image_PixMap::ImgBGR32);
1484     mySupportedFormats->Add (Image_PixMap::ImgBGRA);
1485   }
1486
1487   core11fwd = (OpenGl_GlCore11Fwd* )(&(*myFuncs));
1488   if (IsGlGreaterEqual (2, 0))
1489   {
1490     // enable compatible functions
1491     core20    = (OpenGl_GlCore20*    )(&(*myFuncs));
1492     core20fwd = (OpenGl_GlCore20Fwd* )(&(*myFuncs));
1493     core15fwd = (OpenGl_GlCore15Fwd* )(&(*myFuncs));
1494     arbFBO    = (OpenGl_ArbFBO*      )(&(*myFuncs));
1495   }
1496   if (IsGlGreaterEqual (3, 0)
1497    && FindProcShort (glBlitFramebuffer))
1498   {
1499     arbFBOBlit = (OpenGl_ArbFBOBlit* )(&(*myFuncs));
1500   }
1501   if (IsGlGreaterEqual (3, 0)
1502    && FindProcShort (glGenSamplers)
1503    && FindProcShort (glDeleteSamplers)
1504    && FindProcShort (glIsSampler)
1505    && FindProcShort (glBindSampler)
1506    && FindProcShort (glSamplerParameteri)
1507    && FindProcShort (glSamplerParameteriv)
1508    && FindProcShort (glSamplerParameterf)
1509    && FindProcShort (glSamplerParameterfv)
1510    && FindProcShort (glGetSamplerParameteriv)
1511    && FindProcShort (glGetSamplerParameterfv))
1512    //&& FindProcShort (glSamplerParameterIiv) // only on Desktop or with extensions GL_OES_texture_border_clamp/GL_EXT_texture_border_clamp
1513    //&& FindProcShort (glSamplerParameterIuiv)
1514    //&& FindProcShort (glGetSamplerParameterIiv)
1515    //&& FindProcShort (glGetSamplerParameterIuiv))
1516   {
1517     arbSamplerObject = (OpenGl_ArbSamplerObject* )(&(*myFuncs));
1518   }
1519   extFragDepth = !IsGlGreaterEqual(3, 0)
1520                && CheckExtension ("GL_EXT_frag_depth");
1521   if (IsGlGreaterEqual (3, 1)
1522    && FindProcShort (glTexStorage2DMultisample))
1523   {
1524     // MSAA RenderBuffers have been defined in OpenGL ES 3.0,
1525     // but MSAA Textures - only in OpenGL ES 3.1+
1526     ::glGetIntegerv (GL_MAX_SAMPLES, &myMaxMsaaSamples);
1527   }
1528
1529   hasUintIndex = IsGlGreaterEqual (3, 0)
1530               || CheckExtension ("GL_OES_element_index_uint");
1531   hasHighp     = CheckExtension ("GL_OES_fragment_precision_high");
1532   GLint aRange[2] = {0, 0};
1533   GLint aPrec     = 0;
1534   ::glGetShaderPrecisionFormat (GL_FRAGMENT_SHADER, GL_HIGH_FLOAT, aRange, &aPrec);
1535   if (aPrec != 0)
1536   {
1537     hasHighp = Standard_True;
1538   }
1539
1540   arbTexFloat = IsGlGreaterEqual (3, 0)
1541              && FindProcShort (glTexImage3D);
1542   hasTexFloatLinear = arbTexFloat
1543                    && CheckExtension ("GL_OES_texture_float_linear");
1544
1545   const Standard_Boolean hasTexBuffer32  = IsGlGreaterEqual (3, 2) && FindProcShort (glTexBuffer);
1546   const Standard_Boolean hasExtTexBuffer = CheckExtension ("GL_EXT_texture_buffer") && FindProc ("glTexBufferEXT", myFuncs->glTexBuffer);
1547
1548   if (hasTexBuffer32 || hasExtTexBuffer)
1549   {
1550     arbTBO = reinterpret_cast<OpenGl_ArbTBO*> (myFuncs.get());
1551   }
1552
1553   // initialize debug context extension
1554   if (CheckExtension ("GL_KHR_debug"))
1555   {
1556     // this functionality become a part of OpenGL ES 3.2
1557     arbDbg = NULL;
1558     // According to GL_KHR_debug spec, all functions should have KHR suffix.
1559     // However, some implementations can export these functions without suffix.
1560     if (FindProc ("glDebugMessageControlKHR",  myFuncs->glDebugMessageControl)
1561      && FindProc ("glDebugMessageInsertKHR",   myFuncs->glDebugMessageInsert)
1562      && FindProc ("glDebugMessageCallbackKHR", myFuncs->glDebugMessageCallback)
1563      && FindProc ("glGetDebugMessageLogKHR",   myFuncs->glGetDebugMessageLog))
1564     {
1565       arbDbg = (OpenGl_ArbDbg* )(&(*myFuncs));
1566     }
1567
1568     if (arbDbg != NULL
1569      && caps->contextDebug)
1570     {
1571       // setup default callback
1572       myIsGlDebugCtx = Standard_True;
1573       arbDbg->glDebugMessageCallback (debugCallbackWrap, this);
1574       ::glEnable (GL_DEBUG_OUTPUT);
1575       if (caps->contextSyncDebug)
1576       {
1577         // note that some broken implementations (e.g. simulators) might generate error message on this call
1578         ::glEnable (GL_DEBUG_OUTPUT_SYNCHRONOUS);
1579       }
1580     }
1581   }
1582
1583   extDrawBuffers = CheckExtension ("GL_EXT_draw_buffers") && FindProc ("glDrawBuffersEXT", myFuncs->glDrawBuffers);
1584   arbDrawBuffers = CheckExtension ("GL_ARB_draw_buffers") && FindProc ("glDrawBuffersARB", myFuncs->glDrawBuffers);
1585
1586   if (IsGlGreaterEqual (3, 0) && FindProcShort (glDrawBuffers))
1587   {
1588     hasDrawBuffers = OpenGl_FeatureInCore;
1589   }
1590   else if (extDrawBuffers || arbDrawBuffers)
1591   {
1592     hasDrawBuffers = OpenGl_FeatureInExtensions;
1593   }
1594
1595   hasFloatBuffer     = IsGlGreaterEqual (3, 2) ? OpenGl_FeatureInCore :
1596                        CheckExtension ("GL_EXT_color_buffer_float") ? OpenGl_FeatureInExtensions 
1597                                                                     : OpenGl_FeatureNotAvailable;
1598   hasHalfFloatBuffer = IsGlGreaterEqual (3, 2) ? OpenGl_FeatureInCore :
1599                        CheckExtension ("GL_EXT_color_buffer_half_float") ? OpenGl_FeatureInExtensions 
1600                                                                          : OpenGl_FeatureNotAvailable;
1601
1602   oesSampleVariables = CheckExtension ("GL_OES_sample_variables");
1603   oesStdDerivatives  = CheckExtension ("GL_OES_standard_derivatives");
1604   hasSampleVariables = IsGlGreaterEqual (3, 2) ? OpenGl_FeatureInCore :
1605                        oesSampleVariables ? OpenGl_FeatureInExtensions
1606                                           : OpenGl_FeatureNotAvailable;
1607   hasGlslBitwiseOps = IsGlGreaterEqual (3, 0)
1608                     ? OpenGl_FeatureInCore
1609                     : OpenGl_FeatureNotAvailable;
1610   // without hasHighp, dFdx/dFdy precision is considered too low for flat shading (visual artifacts)
1611   hasFlatShading = IsGlGreaterEqual (3, 0)
1612                  ? OpenGl_FeatureInCore
1613                   : (oesStdDerivatives && hasHighp
1614                    ? OpenGl_FeatureInExtensions
1615                    : OpenGl_FeatureNotAvailable);
1616   if (!IsGlGreaterEqual (3, 1)
1617     && myVendor.Search("qualcomm") != -1)
1618   {
1619     // dFdx/dFdy are completely broken on tested Adreno devices with versions below OpenGl ES 3.1
1620     hasFlatShading = OpenGl_FeatureNotAvailable;
1621   }
1622
1623   hasGeometryStage = IsGlGreaterEqual (3, 2)
1624                    ? OpenGl_FeatureInCore
1625                    : (CheckExtension ("GL_EXT_geometry_shader") && CheckExtension ("GL_EXT_shader_io_blocks")
1626                      ? OpenGl_FeatureInExtensions
1627                      : OpenGl_FeatureNotAvailable);
1628 #else
1629
1630   myTexClamp = IsGlGreaterEqual (1, 2) ? GL_CLAMP_TO_EDGE : GL_CLAMP;
1631
1632   hasTexRGBA8 = Standard_True;
1633   hasTexSRGB       = IsGlGreaterEqual (2, 1);
1634   hasFboSRGB       = IsGlGreaterEqual (2, 1);
1635   hasSRGBControl   = hasFboSRGB;
1636   arbDrawBuffers   = CheckExtension ("GL_ARB_draw_buffers");
1637   arbNPTW          = CheckExtension ("GL_ARB_texture_non_power_of_two");
1638   arbTexFloat      = IsGlGreaterEqual (3, 0)
1639                   || CheckExtension ("GL_ARB_texture_float");
1640   hasTexFloatLinear = arbTexFloat;
1641   arbSampleShading = CheckExtension ("GL_ARB_sample_shading");
1642   extBgra          = IsGlGreaterEqual (1, 2)
1643                   || CheckExtension ("GL_EXT_bgra");
1644   extAnis          = CheckExtension ("GL_EXT_texture_filter_anisotropic");
1645   extPDS           = CheckExtension ("GL_EXT_packed_depth_stencil");
1646   atiMem           = CheckExtension ("GL_ATI_meminfo");
1647   nvxMem           = CheckExtension ("GL_NVX_gpu_memory_info");
1648
1649   if (extBgra)
1650   {
1651     mySupportedFormats->Add (Image_PixMap::ImgBGR);
1652     mySupportedFormats->Add (Image_PixMap::ImgBGR32);
1653     mySupportedFormats->Add (Image_PixMap::ImgBGRA);
1654   }
1655
1656   hasDrawBuffers = IsGlGreaterEqual (2, 0) ? OpenGl_FeatureInCore :
1657                    arbDrawBuffers ? OpenGl_FeatureInExtensions 
1658                                   : OpenGl_FeatureNotAvailable;
1659
1660   hasGlslBitwiseOps = IsGlGreaterEqual (3, 0)
1661                     ? OpenGl_FeatureInCore
1662                     : CheckExtension ("GL_EXT_gpu_shader4")
1663                      ? OpenGl_FeatureInExtensions
1664                      : OpenGl_FeatureNotAvailable;
1665
1666   hasFloatBuffer = hasHalfFloatBuffer =  IsGlGreaterEqual (3, 0) ? OpenGl_FeatureInCore :
1667                                          CheckExtension ("GL_ARB_color_buffer_float") ? OpenGl_FeatureInExtensions
1668                                                                                       : OpenGl_FeatureNotAvailable;
1669
1670   hasGeometryStage = IsGlGreaterEqual (3, 2)
1671                    ? OpenGl_FeatureInCore
1672                    : OpenGl_FeatureNotAvailable;
1673
1674   hasSampleVariables = IsGlGreaterEqual (4, 0) ? OpenGl_FeatureInCore :
1675                         arbSampleShading ? OpenGl_FeatureInExtensions
1676                                          : OpenGl_FeatureNotAvailable;
1677
1678   GLint aStereo = GL_FALSE;
1679   glGetIntegerv (GL_STEREO, &aStereo);
1680   myIsStereoBuffers = aStereo == 1;
1681
1682   // get number of maximum clipping planes
1683   glGetIntegerv (GL_MAX_CLIP_PLANES,  &myMaxClipPlanes);
1684 #endif
1685
1686   if (hasDrawBuffers)
1687   {
1688     glGetIntegerv (GL_MAX_DRAW_BUFFERS,      &myMaxDrawBuffers);
1689     glGetIntegerv (GL_MAX_COLOR_ATTACHMENTS, &myMaxColorAttachments);
1690     if (myDrawBuffers.Length() < myMaxDrawBuffers)
1691     {
1692       myDrawBuffers.Resize (0, myMaxDrawBuffers - 1, false);
1693     }
1694   }
1695
1696   glGetIntegerv (GL_MAX_TEXTURE_SIZE, &myMaxTexDim);
1697 #if !defined(GL_ES_VERSION_2_0)
1698   if (IsGlGreaterEqual (1, 3) && core11 != NULL)
1699   {
1700     // this is a maximum of texture units for FFP functionality,
1701     // usually smaller than combined texture units available for GLSL
1702     glGetIntegerv (GL_MAX_TEXTURE_UNITS, &myMaxTexUnitsFFP);
1703     myMaxTexCombined = myMaxTexUnitsFFP;
1704   }
1705 #endif
1706   if (IsGlGreaterEqual (2, 0))
1707   {
1708     glGetIntegerv (GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &myMaxTexCombined);
1709   }
1710   mySpriteTexUnit = myMaxTexCombined >= 2
1711                   ? Graphic3d_TextureUnit_PointSprite
1712                   : Graphic3d_TextureUnit_0;
1713
1714   GLint aMaxVPortSize[2] = {0, 0};
1715   glGetIntegerv (GL_MAX_VIEWPORT_DIMS, aMaxVPortSize);
1716   myMaxDumpSizeX = Min (aMaxVPortSize[0], myMaxTexDim);
1717   myMaxDumpSizeY = Min (aMaxVPortSize[1], myMaxTexDim);
1718   if (myVendor == "intel")
1719   {
1720     // Intel drivers have known bug with empty dump for images with width>=5462
1721     myMaxDumpSizeX = Min (myMaxDumpSizeX, 4096);
1722   }
1723
1724   if (extAnis)
1725   {
1726     glGetIntegerv (GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &myAnisoMax);
1727   }
1728
1729   myClippingState.Init();
1730
1731 #if !defined(GL_ES_VERSION_2_0)
1732
1733   bool has12 = false;
1734   bool has13 = false;
1735   bool has14 = false;
1736   bool has15 = false;
1737   bool has20 = false;
1738   bool has21 = false;
1739   bool has30 = false;
1740   bool has31 = false;
1741   bool has32 = false;
1742   bool has33 = false;
1743   bool has40 = false;
1744   bool has41 = false;
1745   bool has42 = false;
1746   bool has43 = false;
1747   bool has44 = false;
1748   bool has45 = false;
1749
1750   // retrieve platform-dependent extensions
1751 #if defined(HAVE_EGL)
1752   //
1753 #elif defined(_WIN32)
1754   if (FindProcShort (wglGetExtensionsStringARB))
1755   {
1756     const char* aWglExts = myFuncs->wglGetExtensionsStringARB (wglGetCurrentDC());
1757     if (CheckExtension (aWglExts, "WGL_EXT_swap_control"))
1758     {
1759       FindProcShort (wglSwapIntervalEXT);
1760     }
1761     if (CheckExtension (aWglExts, "WGL_ARB_pixel_format"))
1762     {
1763       FindProcShort (wglChoosePixelFormatARB);
1764     }
1765     if (CheckExtension (aWglExts, "WGL_ARB_create_context_profile"))
1766     {
1767       FindProcShort (wglCreateContextAttribsARB);
1768     }
1769     if (CheckExtension (aWglExts, "WGL_NV_DX_interop"))
1770     {
1771       FindProcShort (wglDXSetResourceShareHandleNV);
1772       FindProcShort (wglDXOpenDeviceNV);
1773       FindProcShort (wglDXCloseDeviceNV);
1774       FindProcShort (wglDXRegisterObjectNV);
1775       FindProcShort (wglDXUnregisterObjectNV);
1776       FindProcShort (wglDXObjectAccessNV);
1777       FindProcShort (wglDXLockObjectsNV);
1778       FindProcShort (wglDXUnlockObjectsNV);
1779     }
1780     if (CheckExtension (aWglExts, "WGL_AMD_gpu_association"))
1781     {
1782       FindProcShort (wglGetGPUIDsAMD);
1783       FindProcShort (wglGetGPUInfoAMD);
1784       FindProcShort (wglGetContextGPUIDAMD);
1785     }
1786   }
1787 #elif defined(__APPLE__)
1788     //
1789 #else
1790     const char* aGlxExts = ::glXQueryExtensionsString ((Display* )myDisplay, DefaultScreen ((Display* )myDisplay));
1791     if (CheckExtension (aGlxExts, "GLX_EXT_swap_control"))
1792     {
1793       FindProcShort (glXSwapIntervalEXT);
1794     }
1795     if (CheckExtension (aGlxExts, "GLX_SGI_swap_control"))
1796     {
1797       FindProcShort (glXSwapIntervalSGI);
1798     }
1799     if (CheckExtension (aGlxExts, "GLX_MESA_query_renderer"))
1800     {
1801       FindProcShort (glXQueryRendererIntegerMESA);
1802       FindProcShort (glXQueryCurrentRendererIntegerMESA);
1803       FindProcShort (glXQueryRendererStringMESA);
1804       FindProcShort (glXQueryCurrentRendererStringMESA);
1805     }
1806     //extSwapTear = CheckExtension (aGlxExts, "GLX_EXT_swap_control_tear");
1807 #endif
1808
1809   // load OpenGL 1.2 new functions
1810   has12 = IsGlGreaterEqual (1, 2)
1811        && FindProcShort (glBlendColor)
1812        && FindProcShort (glBlendEquation)
1813        && FindProcShort (glDrawRangeElements)
1814        && FindProcShort (glTexImage3D)
1815        && FindProcShort (glTexSubImage3D)
1816        && FindProcShort (glCopyTexSubImage3D);
1817   if (!has12)
1818   {
1819     checkWrongVersion (1, 2, aLastFailedProc);
1820   }
1821
1822   // load OpenGL 1.3 new functions
1823   has13 = IsGlGreaterEqual (1, 3)
1824        && FindProcShort (glActiveTexture)
1825        && FindProcShort (glSampleCoverage)
1826        && FindProcShort (glCompressedTexImage3D)
1827        && FindProcShort (glCompressedTexImage2D)
1828        && FindProcShort (glCompressedTexImage1D)
1829        && FindProcShort (glCompressedTexSubImage3D)
1830        && FindProcShort (glCompressedTexSubImage2D)
1831        && FindProcShort (glCompressedTexSubImage1D)
1832        && FindProcShort (glGetCompressedTexImage);
1833
1834   if (!isCoreProfile)
1835   {
1836     has13 = has13
1837        && FindProcShort (glClientActiveTexture)
1838        && FindProcShort (glMultiTexCoord1d)
1839        && FindProcShort (glMultiTexCoord1dv)
1840        && FindProcShort (glMultiTexCoord1f)
1841        && FindProcShort (glMultiTexCoord1fv)
1842        && FindProcShort (glMultiTexCoord1i)
1843        && FindProcShort (glMultiTexCoord1iv)
1844        && FindProcShort (glMultiTexCoord1s)
1845        && FindProcShort (glMultiTexCoord1sv)
1846        && FindProcShort (glMultiTexCoord2d)
1847        && FindProcShort (glMultiTexCoord2dv)
1848        && FindProcShort (glMultiTexCoord2f)
1849        && FindProcShort (glMultiTexCoord2fv)
1850        && FindProcShort (glMultiTexCoord2i)
1851        && FindProcShort (glMultiTexCoord2iv)
1852        && FindProcShort (glMultiTexCoord2s)
1853        && FindProcShort (glMultiTexCoord2sv)
1854        && FindProcShort (glMultiTexCoord3d)
1855        && FindProcShort (glMultiTexCoord3dv)
1856        && FindProcShort (glMultiTexCoord3f)
1857        && FindProcShort (glMultiTexCoord3fv)
1858        && FindProcShort (glMultiTexCoord3i)
1859        && FindProcShort (glMultiTexCoord3iv)
1860        && FindProcShort (glMultiTexCoord3s)
1861        && FindProcShort (glMultiTexCoord3sv)
1862        && FindProcShort (glMultiTexCoord4d)
1863        && FindProcShort (glMultiTexCoord4dv)
1864        && FindProcShort (glMultiTexCoord4f)
1865        && FindProcShort (glMultiTexCoord4fv)
1866        && FindProcShort (glMultiTexCoord4i)
1867        && FindProcShort (glMultiTexCoord4iv)
1868        && FindProcShort (glMultiTexCoord4s)
1869        && FindProcShort (glMultiTexCoord4sv)
1870        && FindProcShort (glLoadTransposeMatrixf)
1871        && FindProcShort (glLoadTransposeMatrixd)
1872        && FindProcShort (glMultTransposeMatrixf)
1873        && FindProcShort (glMultTransposeMatrixd);
1874   }
1875   if (!has13)
1876   {
1877     checkWrongVersion (1, 3, aLastFailedProc);
1878   }
1879
1880   // load OpenGL 1.4 new functions
1881   has14 = IsGlGreaterEqual (1, 4)
1882        && FindProcShort (glBlendFuncSeparate)
1883        && FindProcShort (glMultiDrawArrays)
1884        && FindProcShort (glMultiDrawElements)
1885        && FindProcShort (glPointParameterf)
1886        && FindProcShort (glPointParameterfv)
1887        && FindProcShort (glPointParameteri)
1888        && FindProcShort (glPointParameteriv);
1889   if (!has14)
1890   {
1891     checkWrongVersion (1, 4, aLastFailedProc);
1892   }
1893
1894   // load OpenGL 1.5 new functions
1895   has15 = IsGlGreaterEqual (1, 5)
1896        && FindProcShort (glGenQueries)
1897        && FindProcShort (glDeleteQueries)
1898        && FindProcShort (glIsQuery)
1899        && FindProcShort (glBeginQuery)
1900        && FindProcShort (glEndQuery)
1901        && FindProcShort (glGetQueryiv)
1902        && FindProcShort (glGetQueryObjectiv)
1903        && FindProcShort (glGetQueryObjectuiv)
1904        && FindProcShort (glBindBuffer)
1905        && FindProcShort (glDeleteBuffers)
1906        && FindProcShort (glGenBuffers)
1907        && FindProcShort (glIsBuffer)
1908        && FindProcShort (glBufferData)
1909        && FindProcShort (glBufferSubData)
1910        && FindProcShort (glGetBufferSubData)
1911        && FindProcShort (glMapBuffer)
1912        && FindProcShort (glUnmapBuffer)
1913        && FindProcShort (glGetBufferParameteriv)
1914        && FindProcShort (glGetBufferPointerv);
1915   if (has15)
1916   {
1917     if (!isCoreProfile)
1918     {
1919       core15 = (OpenGl_GlCore15* )(&(*myFuncs));
1920     }
1921     core15fwd = (OpenGl_GlCore15Fwd* )(&(*myFuncs));
1922   }
1923   else
1924   {
1925     checkWrongVersion (1, 5, aLastFailedProc);
1926   }
1927
1928   // load OpenGL 2.0 new functions
1929   has20 = IsGlGreaterEqual (2, 0)
1930        && FindProcShort (glBlendEquationSeparate)
1931        && FindProcShort (glDrawBuffers)
1932        && FindProcShort (glStencilOpSeparate)
1933        && FindProcShort (glStencilFuncSeparate)
1934        && FindProcShort (glStencilMaskSeparate)
1935        && FindProcShort (glAttachShader)
1936        && FindProcShort (glBindAttribLocation)
1937        && FindProcShort (glCompileShader)
1938        && FindProcShort (glCreateProgram)
1939        && FindProcShort (glCreateShader)
1940        && FindProcShort (glDeleteProgram)
1941        && FindProcShort (glDeleteShader)
1942        && FindProcShort (glDetachShader)
1943        && FindProcShort (glDisableVertexAttribArray)
1944        && FindProcShort (glEnableVertexAttribArray)
1945        && FindProcShort (glGetActiveAttrib)
1946        && FindProcShort (glGetActiveUniform)
1947        && FindProcShort (glGetAttachedShaders)
1948        && FindProcShort (glGetAttribLocation)
1949        && FindProcShort (glGetProgramiv)
1950        && FindProcShort (glGetProgramInfoLog)
1951        && FindProcShort (glGetShaderiv)
1952        && FindProcShort (glGetShaderInfoLog)
1953        && FindProcShort (glGetShaderSource)
1954        && FindProcShort (glGetUniformLocation)
1955        && FindProcShort (glGetUniformfv)
1956        && FindProcShort (glGetUniformiv)
1957        && FindProcShort (glGetVertexAttribdv)
1958        && FindProcShort (glGetVertexAttribfv)
1959        && FindProcShort (glGetVertexAttribiv)
1960        && FindProcShort (glGetVertexAttribPointerv)
1961        && FindProcShort (glIsProgram)
1962        && FindProcShort (glIsShader)
1963        && FindProcShort (glLinkProgram)
1964        && FindProcShort (glShaderSource)
1965        && FindProcShort (glUseProgram)
1966        && FindProcShort (glUniform1f)
1967        && FindProcShort (glUniform2f)
1968        && FindProcShort (glUniform3f)
1969        && FindProcShort (glUniform4f)
1970        && FindProcShort (glUniform1i)
1971        && FindProcShort (glUniform2i)
1972        && FindProcShort (glUniform3i)
1973        && FindProcShort (glUniform4i)
1974        && FindProcShort (glUniform1fv)
1975        && FindProcShort (glUniform2fv)
1976        && FindProcShort (glUniform3fv)
1977        && FindProcShort (glUniform4fv)
1978        && FindProcShort (glUniform1iv)
1979        && FindProcShort (glUniform2iv)
1980        && FindProcShort (glUniform3iv)
1981        && FindProcShort (glUniform4iv)
1982        && FindProcShort (glUniformMatrix2fv)
1983        && FindProcShort (glUniformMatrix3fv)
1984        && FindProcShort (glUniformMatrix4fv)
1985        && FindProcShort (glValidateProgram)
1986        && FindProcShort (glVertexAttrib1d)
1987        && FindProcShort (glVertexAttrib1dv)
1988        && FindProcShort (glVertexAttrib1f)
1989        && FindProcShort (glVertexAttrib1fv)
1990        && FindProcShort (glVertexAttrib1s)
1991        && FindProcShort (glVertexAttrib1sv)
1992        && FindProcShort (glVertexAttrib2d)
1993        && FindProcShort (glVertexAttrib2dv)
1994        && FindProcShort (glVertexAttrib2f)
1995        && FindProcShort (glVertexAttrib2fv)
1996        && FindProcShort (glVertexAttrib2s)
1997        && FindProcShort (glVertexAttrib2sv)
1998        && FindProcShort (glVertexAttrib3d)
1999        && FindProcShort (glVertexAttrib3dv)
2000        && FindProcShort (glVertexAttrib3f)
2001        && FindProcShort (glVertexAttrib3fv)
2002        && FindProcShort (glVertexAttrib3s)
2003        && FindProcShort (glVertexAttrib3sv)
2004        && FindProcShort (glVertexAttrib4Nbv)
2005        && FindProcShort (glVertexAttrib4Niv)
2006        && FindProcShort (glVertexAttrib4Nsv)
2007        && FindProcShort (glVertexAttrib4Nub)
2008        && FindProcShort (glVertexAttrib4Nubv)
2009        && FindProcShort (glVertexAttrib4Nuiv)
2010        && FindProcShort (glVertexAttrib4Nusv)
2011        && FindProcShort (glVertexAttrib4bv)
2012        && FindProcShort (glVertexAttrib4d)
2013        && FindProcShort (glVertexAttrib4dv)
2014        && FindProcShort (glVertexAttrib4f)
2015        && FindProcShort (glVertexAttrib4fv)
2016        && FindProcShort (glVertexAttrib4iv)
2017        && FindProcShort (glVertexAttrib4s)
2018        && FindProcShort (glVertexAttrib4sv)
2019        && FindProcShort (glVertexAttrib4ubv)
2020        && FindProcShort (glVertexAttrib4uiv)
2021        && FindProcShort (glVertexAttrib4usv)
2022        && FindProcShort (glVertexAttribPointer);
2023   if (has20)
2024   {
2025     const char* aGlslVer = (const char* )::glGetString (GL_SHADING_LANGUAGE_VERSION);
2026     if (aGlslVer == NULL
2027     || *aGlslVer == '\0')
2028     {
2029       // broken context has been detected
2030       PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
2031                    TCollection_AsciiString("Error! OpenGL context reports version ")
2032                    + myGlVerMajor  + "." + myGlVerMinor + " but reports wrong GLSL version");
2033       myGlVerMajor = 1;
2034       myGlVerMinor = 5;
2035     }
2036     else
2037     {
2038       if (!isCoreProfile)
2039       {
2040         core20  = (OpenGl_GlCore20*    )(&(*myFuncs));
2041       }
2042       core20fwd = (OpenGl_GlCore20Fwd* )(&(*myFuncs));
2043     }
2044   }
2045   else
2046   {
2047     checkWrongVersion (2, 0, aLastFailedProc);
2048   }
2049
2050   // load OpenGL 2.1 new functions
2051   has21 = IsGlGreaterEqual (2, 1)
2052        && FindProcShort (glUniformMatrix2x3fv)
2053        && FindProcShort (glUniformMatrix3x2fv)
2054        && FindProcShort (glUniformMatrix2x4fv)
2055        && FindProcShort (glUniformMatrix4x2fv)
2056        && FindProcShort (glUniformMatrix3x4fv)
2057        && FindProcShort (glUniformMatrix4x3fv);
2058   if (!has21)
2059   {
2060     checkWrongVersion (2, 1, aLastFailedProc);
2061   }
2062
2063   // load GL_ARB_framebuffer_object (added to OpenGL 3.0 core)
2064   const bool hasFBO = (IsGlGreaterEqual (3, 0) || CheckExtension ("GL_ARB_framebuffer_object"))
2065        && FindProcShort (glIsRenderbuffer)
2066        && FindProcShort (glBindRenderbuffer)
2067        && FindProcShort (glDeleteRenderbuffers)
2068        && FindProcShort (glGenRenderbuffers)
2069        && FindProcShort (glRenderbufferStorage)
2070        && FindProcShort (glGetRenderbufferParameteriv)
2071        && FindProcShort (glIsFramebuffer)
2072        && FindProcShort (glBindFramebuffer)
2073        && FindProcShort (glDeleteFramebuffers)
2074        && FindProcShort (glGenFramebuffers)
2075        && FindProcShort (glCheckFramebufferStatus)
2076        && FindProcShort (glFramebufferTexture1D)
2077        && FindProcShort (glFramebufferTexture2D)
2078        && FindProcShort (glFramebufferTexture3D)
2079        && FindProcShort (glFramebufferRenderbuffer)
2080        && FindProcShort (glGetFramebufferAttachmentParameteriv)
2081        && FindProcShort (glGenerateMipmap)
2082        && FindProcShort (glBlitFramebuffer)
2083        && FindProcShort (glRenderbufferStorageMultisample)
2084        && FindProcShort (glFramebufferTextureLayer);
2085
2086   // load GL_ARB_vertex_array_object (added to OpenGL 3.0 core)
2087   const bool hasVAO = (IsGlGreaterEqual (3, 0) || CheckExtension ("GL_ARB_vertex_array_object"))
2088        && FindProcShort (glBindVertexArray)
2089        && FindProcShort (glDeleteVertexArrays)
2090        && FindProcShort (glGenVertexArrays)
2091        && FindProcShort (glIsVertexArray);
2092
2093   // load GL_ARB_map_buffer_range (added to OpenGL 3.0 core)
2094   const bool hasMapBufferRange = (IsGlGreaterEqual (3, 0) || CheckExtension ("GL_ARB_map_buffer_range"))
2095        && FindProcShort (glMapBufferRange)
2096        && FindProcShort (glFlushMappedBufferRange);
2097
2098   // load OpenGL 3.0 new functions
2099   has30 = IsGlGreaterEqual (3, 0)
2100        && hasFBO
2101        && hasVAO
2102        && hasMapBufferRange
2103        && FindProcShort (glColorMaski)
2104        && FindProcShort (glGetBooleani_v)
2105        && FindProcShort (glGetIntegeri_v)
2106        && FindProcShort (glEnablei)
2107        && FindProcShort (glDisablei)
2108        && FindProcShort (glIsEnabledi)
2109        && FindProcShort (glBeginTransformFeedback)
2110        && FindProcShort (glEndTransformFeedback)
2111        && FindProcShort (glBindBufferRange)
2112        && FindProcShort (glBindBufferBase)
2113        && FindProcShort (glTransformFeedbackVaryings)
2114        && FindProcShort (glGetTransformFeedbackVarying)
2115        && FindProcShort (glClampColor)
2116        && FindProcShort (glBeginConditionalRender)
2117        && FindProcShort (glEndConditionalRender)
2118        && FindProcShort (glVertexAttribIPointer)
2119        && FindProcShort (glGetVertexAttribIiv)
2120        && FindProcShort (glGetVertexAttribIuiv)
2121        && FindProcShort (glVertexAttribI1i)
2122        && FindProcShort (glVertexAttribI2i)
2123        && FindProcShort (glVertexAttribI3i)
2124        && FindProcShort (glVertexAttribI4i)
2125        && FindProcShort (glVertexAttribI1ui)
2126        && FindProcShort (glVertexAttribI2ui)
2127        && FindProcShort (glVertexAttribI3ui)
2128        && FindProcShort (glVertexAttribI4ui)
2129        && FindProcShort (glVertexAttribI1iv)
2130        && FindProcShort (glVertexAttribI2iv)
2131        && FindProcShort (glVertexAttribI3iv)
2132        && FindProcShort (glVertexAttribI4iv)
2133        && FindProcShort (glVertexAttribI1uiv)
2134        && FindProcShort (glVertexAttribI2uiv)
2135        && FindProcShort (glVertexAttribI3uiv)
2136        && FindProcShort (glVertexAttribI4uiv)
2137        && FindProcShort (glVertexAttribI4bv)
2138        && FindProcShort (glVertexAttribI4sv)
2139        && FindProcShort (glVertexAttribI4ubv)
2140        && FindProcShort (glVertexAttribI4usv)
2141        && FindProcShort (glGetUniformuiv)
2142        && FindProcShort (glBindFragDataLocation)
2143        && FindProcShort (glGetFragDataLocation)
2144        && FindProcShort (glUniform1ui)
2145        && FindProcShort (glUniform2ui)
2146        && FindProcShort (glUniform3ui)
2147        && FindProcShort (glUniform4ui)
2148        && FindProcShort (glUniform1uiv)
2149        && FindProcShort (glUniform2uiv)
2150        && FindProcShort (glUniform3uiv)
2151        && FindProcShort (glUniform4uiv)
2152        && FindProcShort (glTexParameterIiv)
2153        && FindProcShort (glTexParameterIuiv)
2154        && FindProcShort (glGetTexParameterIiv)
2155        && FindProcShort (glGetTexParameterIuiv)
2156        && FindProcShort (glClearBufferiv)
2157        && FindProcShort (glClearBufferuiv)
2158        && FindProcShort (glClearBufferfv)
2159        && FindProcShort (glClearBufferfi)
2160        && FindProcShort (glGetStringi);
2161   if (!has30)
2162   {
2163     checkWrongVersion (3, 0, aLastFailedProc);
2164   }
2165
2166   // load GL_ARB_uniform_buffer_object (added to OpenGL 3.1 core)
2167   const bool hasUBO = (IsGlGreaterEqual (3, 1) || CheckExtension ("GL_ARB_uniform_buffer_object"))
2168        && FindProcShort (glGetUniformIndices)
2169        && FindProcShort (glGetActiveUniformsiv)
2170        && FindProcShort (glGetActiveUniformName)
2171        && FindProcShort (glGetUniformBlockIndex)
2172        && FindProcShort (glGetActiveUniformBlockiv)
2173        && FindProcShort (glGetActiveUniformBlockName)
2174        && FindProcShort (glUniformBlockBinding);
2175
2176   // load GL_ARB_copy_buffer (added to OpenGL 3.1 core)
2177   const bool hasCopyBufSubData = (IsGlGreaterEqual (3, 1) || CheckExtension ("GL_ARB_copy_buffer"))
2178        && FindProcShort (glCopyBufferSubData);
2179
2180   if (has30)
2181   {
2182     // NPOT textures are required by OpenGL 2.0 specifications
2183     // but doesn't hardware accelerated by some ancient OpenGL 2.1 hardware (GeForce FX, RadeOn 9700 etc.)
2184     arbNPTW  = Standard_True;
2185     arbTexRG = Standard_True;
2186   }
2187
2188   // load OpenGL 3.1 new functions
2189   has31 = IsGlGreaterEqual (3, 1)
2190        && hasUBO
2191        && hasCopyBufSubData
2192        && FindProcShort (glDrawArraysInstanced)
2193        && FindProcShort (glDrawElementsInstanced)
2194        && FindProcShort (glTexBuffer)
2195        && FindProcShort (glPrimitiveRestartIndex);
2196   if (has31)
2197   {
2198     arbTBO = (OpenGl_ArbTBO* )(&(*myFuncs));
2199     arbIns = (OpenGl_ArbIns* )(&(*myFuncs));
2200   }
2201   else
2202   {
2203     checkWrongVersion (3, 1, aLastFailedProc);
2204
2205     // initialize TBO extension (ARB)
2206     if (CheckExtension ("GL_ARB_texture_buffer_object")
2207      && FindProc ("glTexBufferARB", myFuncs->glTexBuffer))
2208     {
2209       arbTBO = (OpenGl_ArbTBO* )(&(*myFuncs));
2210     }
2211
2212     // initialize hardware instancing extension (ARB)
2213     if (CheckExtension ("GL_ARB_draw_instanced")
2214      && FindProc ("glDrawArraysInstancedARB",   myFuncs->glDrawArraysInstanced)
2215      && FindProc ("glDrawElementsInstancedARB", myFuncs->glDrawElementsInstanced))
2216     {
2217       arbIns = (OpenGl_ArbIns* )(&(*myFuncs));
2218     }
2219   }
2220
2221   arbTboRGB32 = CheckExtension ("GL_ARB_texture_buffer_object_rgb32");
2222
2223   // load GL_ARB_draw_elements_base_vertex (added to OpenGL 3.2 core)
2224   const bool hasDrawElemsBaseVert = (IsGlGreaterEqual (3, 2) || CheckExtension ("GL_ARB_draw_elements_base_vertex"))
2225        && FindProcShort (glDrawElementsBaseVertex)
2226        && FindProcShort (glDrawRangeElementsBaseVertex)
2227        && FindProcShort (glDrawElementsInstancedBaseVertex)
2228        && FindProcShort (glMultiDrawElementsBaseVertex);
2229
2230   // load GL_ARB_provoking_vertex (added to OpenGL 3.2 core)
2231   const bool hasProvokingVert = (IsGlGreaterEqual (3, 2) || CheckExtension ("GL_ARB_provoking_vertex"))
2232        && FindProcShort (glProvokingVertex);
2233
2234   // load GL_ARB_sync (added to OpenGL 3.2 core)
2235   const bool hasSync = (IsGlGreaterEqual (3, 2) || CheckExtension ("GL_ARB_sync"))
2236        && FindProcShort (glFenceSync)
2237        && FindProcShort (glIsSync)
2238        && FindProcShort (glDeleteSync)
2239        && FindProcShort (glClientWaitSync)
2240        && FindProcShort (glWaitSync)
2241        && FindProcShort (glGetInteger64v)
2242        && FindProcShort (glGetSynciv);
2243
2244   // load GL_ARB_texture_multisample (added to OpenGL 3.2 core)
2245   const bool hasTextureMultisample = (IsGlGreaterEqual (3, 2) || CheckExtension ("GL_ARB_texture_multisample"))
2246        && FindProcShort (glTexImage2DMultisample)
2247        && FindProcShort (glTexImage3DMultisample)
2248        && FindProcShort (glGetMultisamplefv)
2249        && FindProcShort (glSampleMaski);
2250
2251   // load OpenGL 3.2 new functions
2252   has32 = IsGlGreaterEqual (3, 2)
2253        && hasDrawElemsBaseVert
2254        && hasProvokingVert
2255        && hasSync
2256        && hasTextureMultisample
2257        && FindProcShort (glGetInteger64i_v)
2258        && FindProcShort (glGetBufferParameteri64v)
2259        && FindProcShort (glFramebufferTexture);
2260   if (has32)
2261   {
2262     core32 = (OpenGl_GlCore32* )(&(*myFuncs));
2263     if (isCoreProfile)
2264     {
2265       core32->glGenVertexArrays (1, &myDefaultVao);
2266     }
2267     else
2268     {
2269       core32back = (OpenGl_GlCore32Back* )(&(*myFuncs));
2270     }
2271     ::glGetIntegerv (GL_MAX_SAMPLES, &myMaxMsaaSamples);
2272   }
2273   else
2274   {
2275     checkWrongVersion (3, 2, aLastFailedProc);
2276   }
2277
2278   // load GL_ARB_blend_func_extended (added to OpenGL 3.3 core)
2279   const bool hasBlendFuncExtended = (IsGlGreaterEqual (3, 3) || CheckExtension ("GL_ARB_blend_func_extended"))
2280        && FindProcShort (glBindFragDataLocationIndexed)
2281        && FindProcShort (glGetFragDataIndex);
2282
2283   // load GL_ARB_sampler_objects (added to OpenGL 3.3 core)
2284   const bool hasSamplerObjects = (IsGlGreaterEqual (3, 3) || CheckExtension ("GL_ARB_sampler_objects"))
2285        && FindProcShort (glGenSamplers)
2286        && FindProcShort (glDeleteSamplers)
2287        && FindProcShort (glIsSampler)
2288        && FindProcShort (glBindSampler)
2289        && FindProcShort (glSamplerParameteri)
2290        && FindProcShort (glSamplerParameteriv)
2291        && FindProcShort (glSamplerParameterf)
2292        && FindProcShort (glSamplerParameterfv)
2293        && FindProcShort (glSamplerParameterIiv)
2294        && FindProcShort (glSamplerParameterIuiv)
2295        && FindProcShort (glGetSamplerParameteriv)
2296        && FindProcShort (glGetSamplerParameterIiv)
2297        && FindProcShort (glGetSamplerParameterfv)
2298        && FindProcShort (glGetSamplerParameterIuiv);
2299   if (hasSamplerObjects)
2300   {
2301     arbSamplerObject = (OpenGl_ArbSamplerObject* )(&(*myFuncs));
2302   }
2303
2304   // load GL_ARB_timer_query (added to OpenGL 3.3 core)
2305   const bool hasTimerQuery = (IsGlGreaterEqual (3, 3) || CheckExtension ("GL_ARB_timer_query"))
2306        && FindProcShort (glQueryCounter)
2307        && FindProcShort (glGetQueryObjecti64v)
2308        && FindProcShort (glGetQueryObjectui64v);
2309
2310   // load GL_ARB_vertex_type_2_10_10_10_rev (added to OpenGL 3.3 core)
2311   const bool hasVertType21010101rev = (IsGlGreaterEqual (3, 3) || CheckExtension ("GL_ARB_vertex_type_2_10_10_10_rev"))
2312        && FindProcShort (glVertexAttribP1ui)
2313        && FindProcShort (glVertexAttribP1uiv)
2314        && FindProcShort (glVertexAttribP2ui)
2315        && FindProcShort (glVertexAttribP2uiv)
2316        && FindProcShort (glVertexAttribP3ui)
2317        && FindProcShort (glVertexAttribP3uiv)
2318        && FindProcShort (glVertexAttribP4ui)
2319        && FindProcShort (glVertexAttribP4uiv);
2320
2321   if ( hasVertType21010101rev
2322    && !isCoreProfile)
2323   {
2324     // load deprecated functions
2325     const bool hasVertType21010101revExt =
2326           FindProcShort (glVertexP2ui)
2327        && FindProcShort (glVertexP2uiv)
2328        && FindProcShort (glVertexP3ui)
2329        && FindProcShort (glVertexP3uiv)
2330        && FindProcShort (glVertexP4ui)
2331        && FindProcShort (glVertexP4uiv)
2332        && FindProcShort (glTexCoordP1ui)
2333        && FindProcShort (glTexCoordP1uiv)
2334        && FindProcShort (glTexCoordP2ui)
2335        && FindProcShort (glTexCoordP2uiv)
2336        && FindProcShort (glTexCoordP3ui)
2337        && FindProcShort (glTexCoordP3uiv)
2338        && FindProcShort (glTexCoordP4ui)
2339        && FindProcShort (glTexCoordP4uiv)
2340        && FindProcShort (glMultiTexCoordP1ui)
2341        && FindProcShort (glMultiTexCoordP1uiv)
2342        && FindProcShort (glMultiTexCoordP2ui)
2343        && FindProcShort (glMultiTexCoordP2uiv)
2344        && FindProcShort (glMultiTexCoordP3ui)
2345        && FindProcShort (glMultiTexCoordP3uiv)
2346        && FindProcShort (glMultiTexCoordP4ui)
2347        && FindProcShort (glMultiTexCoordP4uiv)
2348        && FindProcShort (glNormalP3ui)
2349        && FindProcShort (glNormalP3uiv)
2350        && FindProcShort (glColorP3ui)
2351        && FindProcShort (glColorP3uiv)
2352        && FindProcShort (glColorP4ui)
2353        && FindProcShort (glColorP4uiv)
2354        && FindProcShort (glSecondaryColorP3ui)
2355        && FindProcShort (glSecondaryColorP3uiv);
2356     (void )hasVertType21010101revExt;
2357   }
2358
2359   // load OpenGL 3.3 extra functions
2360   has33 = IsGlGreaterEqual (3, 3)
2361        && hasBlendFuncExtended
2362        && hasSamplerObjects
2363        && hasTimerQuery
2364        && hasVertType21010101rev
2365        && FindProcShort (glVertexAttribDivisor);
2366   if (has33)
2367   {
2368     core33 = (OpenGl_GlCore33* )(&(*myFuncs));
2369     if (!isCoreProfile)
2370     {
2371       core33back = (OpenGl_GlCore33Back* )(&(*myFuncs));
2372     }
2373   }
2374   else
2375   {
2376     checkWrongVersion (3, 3, aLastFailedProc);
2377   }
2378
2379   // load GL_ARB_draw_indirect (added to OpenGL 4.0 core)
2380   const bool hasDrawIndirect = (IsGlGreaterEqual (4, 0) || CheckExtension ("GL_ARB_draw_indirect"))
2381        && FindProcShort (glDrawArraysIndirect)
2382        && FindProcShort (glDrawElementsIndirect);
2383
2384   // load GL_ARB_gpu_shader_fp64 (added to OpenGL 4.0 core)
2385   const bool hasShaderFP64 = (IsGlGreaterEqual (4, 0) || CheckExtension ("GL_ARB_gpu_shader_fp64"))
2386        && FindProcShort (glUniform1d)
2387        && FindProcShort (glUniform2d)
2388        && FindProcShort (glUniform3d)
2389        && FindProcShort (glUniform4d)
2390        && FindProcShort (glUniform1dv)
2391        && FindProcShort (glUniform2dv)
2392        && FindProcShort (glUniform3dv)
2393        && FindProcShort (glUniform4dv)
2394        && FindProcShort (glUniformMatrix2dv)
2395        && FindProcShort (glUniformMatrix3dv)
2396        && FindProcShort (glUniformMatrix4dv)
2397        && FindProcShort (glUniformMatrix2x3dv)
2398        && FindProcShort (glUniformMatrix2x4dv)
2399        && FindProcShort (glUniformMatrix3x2dv)
2400        && FindProcShort (glUniformMatrix3x4dv)
2401        && FindProcShort (glUniformMatrix4x2dv)
2402        && FindProcShort (glUniformMatrix4x3dv)
2403        && FindProcShort (glGetUniformdv);
2404
2405   // load GL_ARB_shader_subroutine (added to OpenGL 4.0 core)
2406   const bool hasShaderSubroutine = (IsGlGreaterEqual (4, 0) || CheckExtension ("GL_ARB_shader_subroutine"))
2407        && FindProcShort (glGetSubroutineUniformLocation)
2408        && FindProcShort (glGetSubroutineIndex)
2409        && FindProcShort (glGetActiveSubroutineUniformiv)
2410        && FindProcShort (glGetActiveSubroutineUniformName)
2411        && FindProcShort (glGetActiveSubroutineName)
2412        && FindProcShort (glUniformSubroutinesuiv)
2413        && FindProcShort (glGetUniformSubroutineuiv)
2414        && FindProcShort (glGetProgramStageiv);
2415
2416   // load GL_ARB_tessellation_shader (added to OpenGL 4.0 core)
2417   const bool hasTessellationShader = (IsGlGreaterEqual (4, 0) || CheckExtension ("GL_ARB_tessellation_shader"))
2418        && FindProcShort (glPatchParameteri)
2419        && FindProcShort (glPatchParameterfv);
2420
2421   // load GL_ARB_transform_feedback2 (added to OpenGL 4.0 core)
2422   const bool hasTrsfFeedback2 = (IsGlGreaterEqual (4, 0) || CheckExtension ("GL_ARB_transform_feedback2"))
2423        && FindProcShort (glBindTransformFeedback)
2424        && FindProcShort (glDeleteTransformFeedbacks)
2425        && FindProcShort (glGenTransformFeedbacks)
2426        && FindProcShort (glIsTransformFeedback)
2427        && FindProcShort (glPauseTransformFeedback)
2428        && FindProcShort (glResumeTransformFeedback)
2429        && FindProcShort (glDrawTransformFeedback);
2430
2431   // load GL_ARB_transform_feedback3 (added to OpenGL 4.0 core)
2432   const bool hasTrsfFeedback3 = (IsGlGreaterEqual (4, 0) || CheckExtension ("GL_ARB_transform_feedback3"))
2433        && FindProcShort (glDrawTransformFeedbackStream)
2434        && FindProcShort (glBeginQueryIndexed)
2435        && FindProcShort (glEndQueryIndexed)
2436        && FindProcShort (glGetQueryIndexediv);
2437
2438   // load OpenGL 4.0 new functions
2439   has40 = IsGlGreaterEqual (4, 0)
2440       && hasDrawIndirect
2441       && hasShaderFP64
2442       && hasShaderSubroutine
2443       && hasTessellationShader
2444       && hasTrsfFeedback2
2445       && hasTrsfFeedback3
2446       && FindProcShort (glMinSampleShading)
2447       && FindProcShort (glBlendEquationi)
2448       && FindProcShort (glBlendEquationSeparatei)
2449       && FindProcShort (glBlendFunci)
2450       && FindProcShort (glBlendFuncSeparatei);
2451   if (has40)
2452   {
2453     arbTboRGB32 = Standard_True; // in core since OpenGL 4.0
2454   }
2455   else
2456   {
2457     checkWrongVersion (4, 0, aLastFailedProc);
2458   }
2459
2460   // load GL_ARB_ES2_compatibility (added to OpenGL 4.1 core)
2461   const bool hasES2Compatibility = (IsGlGreaterEqual (4, 1) || CheckExtension ("GL_ARB_ES2_compatibility"))
2462        && FindProcShort (glReleaseShaderCompiler)
2463        && FindProcShort (glShaderBinary)
2464        && FindProcShort (glGetShaderPrecisionFormat)
2465        && FindProcShort (glDepthRangef)
2466        && FindProcShort (glClearDepthf);
2467
2468   // load GL_ARB_get_program_binary (added to OpenGL 4.1 core)
2469   const bool hasGetProgramBinary = (IsGlGreaterEqual (4, 1) || CheckExtension ("GL_ARB_get_program_binary"))
2470        && FindProcShort (glGetProgramBinary)
2471        && FindProcShort (glProgramBinary)
2472        && FindProcShort (glProgramParameteri);
2473
2474
2475   // load GL_ARB_separate_shader_objects (added to OpenGL 4.1 core)
2476   const bool hasSeparateShaderObjects = (IsGlGreaterEqual (4, 1) || CheckExtension ("GL_ARB_separate_shader_objects"))
2477        && FindProcShort (glUseProgramStages)
2478        && FindProcShort (glActiveShaderProgram)
2479        && FindProcShort (glCreateShaderProgramv)
2480        && FindProcShort (glBindProgramPipeline)
2481        && FindProcShort (glDeleteProgramPipelines)
2482        && FindProcShort (glGenProgramPipelines)
2483        && FindProcShort (glIsProgramPipeline)
2484        && FindProcShort (glGetProgramPipelineiv)
2485        && FindProcShort (glProgramUniform1i)
2486        && FindProcShort (glProgramUniform1iv)
2487        && FindProcShort (glProgramUniform1f)
2488        && FindProcShort (glProgramUniform1fv)
2489        && FindProcShort (glProgramUniform1d)
2490        && FindProcShort (glProgramUniform1dv)
2491        && FindProcShort (glProgramUniform1ui)
2492        && FindProcShort (glProgramUniform1uiv)
2493        && FindProcShort (glProgramUniform2i)
2494        && FindProcShort (glProgramUniform2iv)
2495        && FindProcShort (glProgramUniform2f)
2496        && FindProcShort (glProgramUniform2fv)
2497        && FindProcShort (glProgramUniform2d)
2498        && FindProcShort (glProgramUniform2dv)
2499        && FindProcShort (glProgramUniform2ui)
2500        && FindProcShort (glProgramUniform2uiv)
2501        && FindProcShort (glProgramUniform3i)
2502        && FindProcShort (glProgramUniform3iv)
2503        && FindProcShort (glProgramUniform3f)
2504        && FindProcShort (glProgramUniform3fv)
2505        && FindProcShort (glProgramUniform3d)
2506        && FindProcShort (glProgramUniform3dv)
2507        && FindProcShort (glProgramUniform3ui)
2508        && FindProcShort (glProgramUniform3uiv)
2509        && FindProcShort (glProgramUniform4i)
2510        && FindProcShort (glProgramUniform4iv)
2511        && FindProcShort (glProgramUniform4f)
2512        && FindProcShort (glProgramUniform4fv)
2513        && FindProcShort (glProgramUniform4d)
2514        && FindProcShort (glProgramUniform4dv)
2515        && FindProcShort (glProgramUniform4ui)
2516        && FindProcShort (glProgramUniform4uiv)
2517        && FindProcShort (glProgramUniformMatrix2fv)
2518        && FindProcShort (glProgramUniformMatrix3fv)
2519        && FindProcShort (glProgramUniformMatrix4fv)
2520        && FindProcShort (glProgramUniformMatrix2dv)
2521        && FindProcShort (glProgramUniformMatrix3dv)
2522        && FindProcShort (glProgramUniformMatrix4dv)
2523        && FindProcShort (glProgramUniformMatrix2x3fv)
2524        && FindProcShort (glProgramUniformMatrix3x2fv)
2525        && FindProcShort (glProgramUniformMatrix2x4fv)
2526        && FindProcShort (glProgramUniformMatrix4x2fv)
2527        && FindProcShort (glProgramUniformMatrix3x4fv)
2528        && FindProcShort (glProgramUniformMatrix4x3fv)
2529        && FindProcShort (glProgramUniformMatrix2x3dv)
2530        && FindProcShort (glProgramUniformMatrix3x2dv)
2531        && FindProcShort (glProgramUniformMatrix2x4dv)
2532        && FindProcShort (glProgramUniformMatrix4x2dv)
2533        && FindProcShort (glProgramUniformMatrix3x4dv)
2534        && FindProcShort (glProgramUniformMatrix4x3dv)
2535        && FindProcShort (glValidateProgramPipeline)
2536        && FindProcShort (glGetProgramPipelineInfoLog);
2537
2538   // load GL_ARB_vertex_attrib_64bit (added to OpenGL 4.1 core)
2539   const bool hasVertAttrib64bit = (IsGlGreaterEqual (4, 1) || CheckExtension ("GL_ARB_vertex_attrib_64bit"))
2540        && FindProcShort (glVertexAttribL1d)
2541        && FindProcShort (glVertexAttribL2d)
2542        && FindProcShort (glVertexAttribL3d)
2543        && FindProcShort (glVertexAttribL4d)
2544        && FindProcShort (glVertexAttribL1dv)
2545        && FindProcShort (glVertexAttribL2dv)
2546        && FindProcShort (glVertexAttribL3dv)
2547        && FindProcShort (glVertexAttribL4dv)
2548        && FindProcShort (glVertexAttribLPointer)
2549        && FindProcShort (glGetVertexAttribLdv);
2550
2551   // load GL_ARB_viewport_array (added to OpenGL 4.1 core)
2552   const bool hasViewportArray = (IsGlGreaterEqual (4, 1) || CheckExtension ("GL_ARB_viewport_array"))
2553        && FindProcShort (glViewportArrayv)
2554        && FindProcShort (glViewportIndexedf)
2555        && FindProcShort (glViewportIndexedfv)
2556        && FindProcShort (glScissorArrayv)
2557        && FindProcShort (glScissorIndexed)
2558        && FindProcShort (glScissorIndexedv)
2559        && FindProcShort (glDepthRangeArrayv)
2560        && FindProcShort (glDepthRangeIndexed)
2561        && FindProcShort (glGetFloati_v)
2562        && FindProcShort (glGetDoublei_v);
2563
2564   has41 = IsGlGreaterEqual (4, 1)
2565        && hasES2Compatibility
2566        && hasGetProgramBinary
2567        && hasSeparateShaderObjects
2568        && hasVertAttrib64bit
2569        && hasViewportArray;
2570   if (has41)
2571   {
2572     core41 = (OpenGl_GlCore41* )(&(*myFuncs));
2573     if (!isCoreProfile)
2574     {
2575       core41back = (OpenGl_GlCore41Back* )(&(*myFuncs));
2576     }
2577   }
2578   else
2579   {
2580     checkWrongVersion (4, 1, aLastFailedProc);
2581   }
2582
2583   // load GL_ARB_base_instance (added to OpenGL 4.2 core)
2584   const bool hasBaseInstance = (IsGlGreaterEqual (4, 2) || CheckExtension ("GL_ARB_base_instance"))
2585        && FindProcShort (glDrawArraysInstancedBaseInstance)
2586        && FindProcShort (glDrawElementsInstancedBaseInstance)
2587        && FindProcShort (glDrawElementsInstancedBaseVertexBaseInstance);
2588
2589   // load GL_ARB_transform_feedback_instanced (added to OpenGL 4.2 core)
2590   const bool hasTrsfFeedbackInstanced = (IsGlGreaterEqual (4, 2) || CheckExtension ("GL_ARB_transform_feedback_instanced"))
2591        && FindProcShort (glDrawTransformFeedbackInstanced)
2592        && FindProcShort (glDrawTransformFeedbackStreamInstanced);
2593
2594   // load GL_ARB_internalformat_query (added to OpenGL 4.2 core)
2595   const bool hasInternalFormatQuery = (IsGlGreaterEqual (4, 2) || CheckExtension ("GL_ARB_internalformat_query"))
2596        && FindProcShort (glGetInternalformativ);
2597
2598   // load GL_ARB_shader_atomic_counters (added to OpenGL 4.2 core)
2599   const bool hasShaderAtomicCounters = (IsGlGreaterEqual (4, 2) || CheckExtension ("GL_ARB_shader_atomic_counters"))
2600        && FindProcShort (glGetActiveAtomicCounterBufferiv);
2601
2602   // load GL_ARB_shader_image_load_store (added to OpenGL 4.2 core)
2603   const bool hasShaderImgLoadStore = (IsGlGreaterEqual (4, 2) || CheckExtension ("GL_ARB_shader_image_load_store"))
2604        && FindProcShort (glBindImageTexture)
2605        && FindProcShort (glMemoryBarrier);
2606
2607   // load GL_ARB_texture_storage (added to OpenGL 4.2 core)
2608   const bool hasTextureStorage = (IsGlGreaterEqual (4, 2) || CheckExtension ("GL_ARB_texture_storage"))
2609        && FindProcShort (glTexStorage1D)
2610        && FindProcShort (glTexStorage2D)
2611        && FindProcShort (glTexStorage3D);
2612
2613   has42 = IsGlGreaterEqual (4, 2)
2614        && hasBaseInstance
2615        && hasTrsfFeedbackInstanced
2616        && hasInternalFormatQuery
2617        && hasShaderAtomicCounters
2618        && hasShaderImgLoadStore
2619        && hasTextureStorage;
2620   if (has42)
2621   {
2622     core42 = (OpenGl_GlCore42* )(&(*myFuncs));
2623     if (!isCoreProfile)
2624     {
2625       core42back = (OpenGl_GlCore42Back* )(&(*myFuncs));
2626     }
2627   }
2628   else
2629   {
2630     checkWrongVersion (4, 2, aLastFailedProc);
2631   }
2632
2633   has43 = IsGlGreaterEqual (4, 3)
2634        && FindProcShort (glClearBufferData)
2635        && FindProcShort (glClearBufferSubData)
2636        && FindProcShort (glDispatchCompute)
2637        && FindProcShort (glDispatchComputeIndirect)
2638        && FindProcShort (glCopyImageSubData)
2639        && FindProcShort (glFramebufferParameteri)
2640        && FindProcShort (glGetFramebufferParameteriv)
2641        && FindProcShort (glGetInternalformati64v)
2642        && FindProcShort (glInvalidateTexSubImage)
2643        && FindProcShort (glInvalidateTexImage)
2644        && FindProcShort (glInvalidateBufferSubData)
2645        && FindProcShort (glInvalidateBufferData)
2646        && FindProcShort (glInvalidateFramebuffer)
2647        && FindProcShort (glInvalidateSubFramebuffer)
2648        && FindProcShort (glMultiDrawArraysIndirect)
2649        && FindProcShort (glMultiDrawElementsIndirect)
2650        && FindProcShort (glGetProgramInterfaceiv)
2651        && FindProcShort (glGetProgramResourceIndex)
2652        && FindProcShort (glGetProgramResourceName)
2653        && FindProcShort (glGetProgramResourceiv)
2654        && FindProcShort (glGetProgramResourceLocation)
2655        && FindProcShort (glGetProgramResourceLocationIndex)
2656        && FindProcShort (glShaderStorageBlockBinding)
2657        && FindProcShort (glTexBufferRange)
2658        && FindProcShort (glTexStorage2DMultisample)
2659        && FindProcShort (glTexStorage3DMultisample)
2660        && FindProcShort (glTextureView)
2661        && FindProcShort (glBindVertexBuffer)
2662        && FindProcShort (glVertexAttribFormat)
2663        && FindProcShort (glVertexAttribIFormat)
2664        && FindProcShort (glVertexAttribLFormat)
2665        && FindProcShort (glVertexAttribBinding)
2666        && FindProcShort (glVertexBindingDivisor)
2667        && FindProcShort (glDebugMessageControl)
2668        && FindProcShort (glDebugMessageInsert)
2669        && FindProcShort (glDebugMessageCallback)
2670        && FindProcShort (glGetDebugMessageLog)
2671        && FindProcShort (glPushDebugGroup)
2672        && FindProcShort (glPopDebugGroup)
2673        && FindProcShort (glObjectLabel)
2674        && FindProcShort (glGetObjectLabel)
2675        && FindProcShort (glObjectPtrLabel)
2676        && FindProcShort (glGetObjectPtrLabel);
2677   if (has43)
2678   {
2679     core43 = (OpenGl_GlCore43* )(&(*myFuncs));
2680     if (!isCoreProfile)
2681     {
2682       core43back = (OpenGl_GlCore43Back* )(&(*myFuncs));
2683     }
2684   }
2685   else
2686   {
2687     checkWrongVersion (4, 3, aLastFailedProc);
2688   }
2689
2690   // load GL_ARB_clear_texture (added to OpenGL 4.4 core)
2691   bool arbTexClear = (IsGlGreaterEqual (4, 4) || CheckExtension ("GL_ARB_clear_texture"))
2692        && FindProcShort (glClearTexImage)
2693        && FindProcShort (glClearTexSubImage);
2694
2695   has44 = IsGlGreaterEqual (4, 4)
2696        && arbTexClear
2697        && FindProcShort (glBufferStorage)
2698        && FindProcShort (glBindBuffersBase)
2699        && FindProcShort (glBindBuffersRange)
2700        && FindProcShort (glBindTextures)
2701        && FindProcShort (glBindSamplers)
2702        && FindProcShort (glBindImageTextures)
2703        && FindProcShort (glBindVertexBuffers);
2704   if (has44)
2705   {
2706     core44 = (OpenGl_GlCore44* )(&(*myFuncs));
2707     if (!isCoreProfile)
2708     {
2709       core44back = (OpenGl_GlCore44Back* )(&(*myFuncs));
2710     }
2711   }
2712   else
2713   {
2714     checkWrongVersion (4, 4, aLastFailedProc);
2715   }
2716
2717   has45 = IsGlGreaterEqual (4, 5)
2718        && FindProcShort (glBindVertexBuffers)
2719        && FindProcShort (glClipControl)
2720        && FindProcShort (glCreateTransformFeedbacks)
2721        && FindProcShort (glTransformFeedbackBufferBase)
2722        && FindProcShort (glTransformFeedbackBufferRange)
2723        && FindProcShort (glGetTransformFeedbackiv)
2724        && FindProcShort (glGetTransformFeedbacki_v)
2725        && FindProcShort (glGetTransformFeedbacki64_v)
2726        && FindProcShort (glCreateBuffers)
2727        && FindProcShort (glNamedBufferStorage)
2728        && FindProcShort (glNamedBufferData)
2729        && FindProcShort (glNamedBufferSubData)
2730        && FindProcShort (glCopyNamedBufferSubData)
2731        && FindProcShort (glClearNamedBufferData)
2732        && FindProcShort (glClearNamedBufferSubData)
2733        && FindProcShort (glMapNamedBuffer)
2734        && FindProcShort (glMapNamedBufferRange)
2735        && FindProcShort (glUnmapNamedBuffer)
2736        && FindProcShort (glFlushMappedNamedBufferRange)
2737        && FindProcShort (glGetNamedBufferParameteriv)
2738        && FindProcShort (glGetNamedBufferParameteri64v)
2739        && FindProcShort (glGetNamedBufferPointerv)
2740        && FindProcShort (glGetNamedBufferSubData)
2741        && FindProcShort (glCreateFramebuffers)
2742        && FindProcShort (glNamedFramebufferRenderbuffer)
2743        && FindProcShort (glNamedFramebufferParameteri)
2744        && FindProcShort (glNamedFramebufferTexture)
2745        && FindProcShort (glNamedFramebufferTextureLayer)
2746        && FindProcShort (glNamedFramebufferDrawBuffer)
2747        && FindProcShort (glNamedFramebufferDrawBuffers)
2748        && FindProcShort (glNamedFramebufferReadBuffer)
2749        && FindProcShort (glInvalidateNamedFramebufferData)
2750        && FindProcShort (glInvalidateNamedFramebufferSubData)
2751        && FindProcShort (glClearNamedFramebufferiv)
2752        && FindProcShort (glClearNamedFramebufferuiv)
2753        && FindProcShort (glClearNamedFramebufferfv)
2754        && FindProcShort (glClearNamedFramebufferfi)
2755        && FindProcShort (glBlitNamedFramebuffer)
2756        && FindProcShort (glCheckNamedFramebufferStatus)
2757        && FindProcShort (glGetNamedFramebufferParameteriv)
2758        && FindProcShort (glGetNamedFramebufferAttachmentParameteriv)
2759        && FindProcShort (glCreateRenderbuffers)
2760        && FindProcShort (glNamedRenderbufferStorage)
2761        && FindProcShort (glNamedRenderbufferStorageMultisample)
2762        && FindProcShort (glGetNamedRenderbufferParameteriv)
2763        && FindProcShort (glCreateTextures)
2764        && FindProcShort (glTextureBuffer)
2765        && FindProcShort (glTextureBufferRange)
2766        && FindProcShort (glTextureStorage1D)
2767        && FindProcShort (glTextureStorage2D)
2768        && FindProcShort (glTextureStorage3D)
2769        && FindProcShort (glTextureStorage2DMultisample)
2770        && FindProcShort (glTextureStorage3DMultisample)
2771        && FindProcShort (glTextureSubImage1D)
2772        && FindProcShort (glTextureSubImage2D)
2773        && FindProcShort (glTextureSubImage3D)
2774        && FindProcShort (glCompressedTextureSubImage1D)
2775        && FindProcShort (glCompressedTextureSubImage2D)
2776        && FindProcShort (glCompressedTextureSubImage3D)
2777        && FindProcShort (glCopyTextureSubImage1D)
2778        && FindProcShort (glCopyTextureSubImage2D)
2779        && FindProcShort (glCopyTextureSubImage3D)
2780        && FindProcShort (glTextureParameterf)
2781        && FindProcShort (glTextureParameterfv)
2782        && FindProcShort (glTextureParameteri)
2783        && FindProcShort (glTextureParameterIiv)
2784        && FindProcShort (glTextureParameterIuiv)
2785        && FindProcShort (glTextureParameteriv)
2786        && FindProcShort (glGenerateTextureMipmap)
2787        && FindProcShort (glBindTextureUnit)
2788        && FindProcShort (glGetTextureImage)
2789        && FindProcShort (glGetCompressedTextureImage)
2790        && FindProcShort (glGetTextureLevelParameterfv)
2791        && FindProcShort (glGetTextureLevelParameteriv)
2792        && FindProcShort (glGetTextureParameterfv)
2793        && FindProcShort (glGetTextureParameterIiv)
2794        && FindProcShort (glGetTextureParameterIuiv)
2795        && FindProcShort (glGetTextureParameteriv)
2796        && FindProcShort (glCreateVertexArrays)
2797        && FindProcShort (glDisableVertexArrayAttrib)
2798        && FindProcShort (glEnableVertexArrayAttrib)
2799        && FindProcShort (glVertexArrayElementBuffer)
2800        && FindProcShort (glVertexArrayVertexBuffer)
2801        && FindProcShort (glVertexArrayVertexBuffers)
2802        && FindProcShort (glVertexArrayAttribBinding)
2803        && FindProcShort (glVertexArrayAttribFormat)
2804        && FindProcShort (glVertexArrayAttribIFormat)
2805        && FindProcShort (glVertexArrayAttribLFormat)
2806        && FindProcShort (glVertexArrayBindingDivisor)
2807        && FindProcShort (glGetVertexArrayiv)
2808        && FindProcShort (glGetVertexArrayIndexediv)
2809        && FindProcShort (glGetVertexArrayIndexed64iv)
2810        && FindProcShort (glCreateSamplers)
2811        && FindProcShort (glCreateProgramPipelines)
2812        && FindProcShort (glCreateQueries)
2813        && FindProcShort (glGetQueryBufferObjecti64v)
2814        && FindProcShort (glGetQueryBufferObjectiv)
2815        && FindProcShort (glGetQueryBufferObjectui64v)
2816        && FindProcShort (glGetQueryBufferObjectuiv)
2817        && FindProcShort (glMemoryBarrierByRegion)
2818        && FindProcShort (glGetTextureSubImage)
2819        && FindProcShort (glGetCompressedTextureSubImage)
2820        && FindProcShort (glGetGraphicsResetStatus)
2821        && FindProcShort (glGetnCompressedTexImage)
2822        && FindProcShort (glGetnTexImage)
2823        && FindProcShort (glGetnUniformdv)
2824        && FindProcShort (glGetnUniformfv)
2825        && FindProcShort (glGetnUniformiv)
2826        && FindProcShort (glGetnUniformuiv)
2827        && FindProcShort (glReadnPixels)
2828        && FindProcShort (glGetnMapdv)
2829        && FindProcShort (glGetnMapfv)
2830        && FindProcShort (glGetnMapiv)
2831        && FindProcShort (glGetnPixelMapfv)
2832        && FindProcShort (glGetnPixelMapuiv)
2833        && FindProcShort (glGetnPixelMapusv)
2834        && FindProcShort (glGetnPolygonStipple)
2835        && FindProcShort (glGetnColorTable)
2836        && FindProcShort (glGetnConvolutionFilter)
2837        && FindProcShort (glGetnSeparableFilter)
2838        && FindProcShort (glGetnHistogram)
2839        && FindProcShort (glGetnMinmax)
2840        && FindProcShort (glTextureBarrier);
2841   if (has45)
2842   {
2843     core45 = (OpenGl_GlCore45* )(&(*myFuncs));
2844     if (!isCoreProfile)
2845     {
2846       core45back = (OpenGl_GlCore45Back* )(&(*myFuncs));
2847     }
2848   }
2849   else
2850   {
2851     checkWrongVersion (4, 5, aLastFailedProc);
2852   }
2853
2854   // initialize debug context extension
2855   if (CheckExtension ("GL_ARB_debug_output"))
2856   {
2857     arbDbg = NULL;
2858     if (has43)
2859     {
2860       arbDbg = (OpenGl_ArbDbg* )(&(*myFuncs));
2861     }
2862     else if (FindProc ("glDebugMessageControlARB",  myFuncs->glDebugMessageControl)
2863           && FindProc ("glDebugMessageInsertARB",   myFuncs->glDebugMessageInsert)
2864           && FindProc ("glDebugMessageCallbackARB", myFuncs->glDebugMessageCallback)
2865           && FindProc ("glGetDebugMessageLogARB",   myFuncs->glGetDebugMessageLog))
2866     {
2867       arbDbg = (OpenGl_ArbDbg* )(&(*myFuncs));
2868     }
2869
2870     if (arbDbg != NULL
2871      && caps->contextDebug)
2872     {
2873       // setup default callback
2874       myIsGlDebugCtx = Standard_True;
2875       arbDbg->glDebugMessageCallback (debugCallbackWrap, this);
2876       if (has43)
2877       {
2878         ::glEnable (GL_DEBUG_OUTPUT);
2879       }
2880       if (caps->contextSyncDebug)
2881       {
2882         ::glEnable (GL_DEBUG_OUTPUT_SYNCHRONOUS);
2883       }
2884     }
2885   }
2886
2887   // initialize FBO extension (ARB)
2888   if (hasFBO)
2889   {
2890     arbFBO     = (OpenGl_ArbFBO*     )(&(*myFuncs));
2891     arbFBOBlit = (OpenGl_ArbFBOBlit* )(&(*myFuncs));
2892     extPDS = Standard_True; // extension for EXT, but part of ARB
2893   }
2894
2895   // initialize GS extension (EXT)
2896   if (CheckExtension ("GL_EXT_geometry_shader4")
2897    && FindProcShort (glProgramParameteriEXT))
2898   {
2899     extGS = (OpenGl_ExtGS* )(&(*myFuncs));
2900   }
2901
2902   // initialize bindless texture extension (ARB)
2903   if (CheckExtension ("GL_ARB_bindless_texture")
2904    && FindProcShort (glGetTextureHandleARB)
2905    && FindProcShort (glGetTextureSamplerHandleARB)
2906    && FindProcShort (glMakeTextureHandleResidentARB)
2907    && FindProcShort (glMakeTextureHandleNonResidentARB)
2908    && FindProcShort (glGetImageHandleARB)
2909    && FindProcShort (glMakeImageHandleResidentARB)
2910    && FindProcShort (glMakeImageHandleNonResidentARB)
2911    && FindProcShort (glUniformHandleui64ARB)
2912    && FindProcShort (glUniformHandleui64vARB)
2913    && FindProcShort (glProgramUniformHandleui64ARB)
2914    && FindProcShort (glProgramUniformHandleui64vARB)
2915    && FindProcShort (glIsTextureHandleResidentARB)
2916    && FindProcShort (glIsImageHandleResidentARB)
2917    && FindProcShort (glVertexAttribL1ui64ARB)
2918    && FindProcShort (glVertexAttribL1ui64vARB)
2919    && FindProcShort (glGetVertexAttribLui64vARB))
2920   {
2921     arbTexBindless = (OpenGl_ArbTexBindless* )(&(*myFuncs));
2922   }
2923
2924   if (has30)
2925   {
2926     // MSAA RenderBuffers have been defined in OpenGL 3.0,
2927     // but MSAA Textures - only in OpenGL 3.2+
2928     if (!has32
2929      && CheckExtension ("GL_ARB_texture_multisample")
2930      && FindProcShort (glTexImage2DMultisample))
2931     {
2932       GLint aNbColorSamples = 0, aNbDepthSamples = 0;
2933       ::glGetIntegerv (GL_MAX_COLOR_TEXTURE_SAMPLES, &aNbColorSamples);
2934       ::glGetIntegerv (GL_MAX_DEPTH_TEXTURE_SAMPLES, &aNbDepthSamples);
2935       myMaxMsaaSamples = Min (aNbColorSamples, aNbDepthSamples);
2936     }
2937     if (!has43
2938      && CheckExtension ("GL_ARB_texture_storage_multisample")
2939      && FindProcShort (glTexStorage2DMultisample))
2940     {
2941       //
2942     }
2943   }
2944
2945   // check whether ray tracing mode is supported
2946   myHasRayTracing = has31
2947                  && arbTboRGB32
2948                  && arbFBOBlit  != NULL;
2949
2950   // check whether textures in ray tracing mode are supported
2951   myHasRayTracingTextures = myHasRayTracing
2952                          && arbTexBindless != NULL;
2953
2954   // check whether adaptive screen sampling in ray tracing mode is supported
2955   myHasRayTracingAdaptiveSampling = myHasRayTracing
2956                                  && has44;
2957   myHasRayTracingAdaptiveSamplingAtomic = myHasRayTracingAdaptiveSampling
2958                                        && CheckExtension ("GL_NV_shader_atomic_float");
2959 #endif
2960
2961   if (arbFBO != NULL
2962    && hasFboSRGB)
2963   {
2964     // Detect if window buffer is considered by OpenGL as sRGB-ready
2965     // (linear RGB color written by shader is automatically converted into sRGB)
2966     // or not (offscreen FBO should be blit into window buffer with gamma correction).
2967     const GLenum aDefWinBuffer =
2968     #if !defined(GL_ES_VERSION_2_0)
2969       GL_BACK_LEFT;
2970     #else
2971       GL_BACK;
2972     #endif
2973     GLint aWinColorEncoding = 0; // GL_LINEAR
2974     arbFBO->glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, aDefWinBuffer, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, &aWinColorEncoding);
2975     ResetErrors (true);
2976     myIsSRgbWindow = aWinColorEncoding == GL_SRGB;
2977
2978     // On desktop OpenGL, pixel formats are almost always sRGB-ready, even when not requested;
2979     // it is safe behavior on desktop where GL_FRAMEBUFFER_SRGB is disabled by default
2980     // (contrary to OpenGL ES, where it is enabled by default).
2981     // NVIDIA drivers, however, always return GL_LINEAR even for sRGB-ready pixel formats on Windows platform,
2982     // while AMD and Intel report GL_SRGB as expected.
2983     // macOS drivers seems to be also report GL_LINEAR even for [NSColorSpace sRGBColorSpace].
2984   #if !defined(GL_ES_VERSION_2_0)
2985   #ifdef __APPLE__
2986     myIsSRgbWindow = true;
2987   #else
2988     if (!myIsSRgbWindow
2989       && myVendor.Search ("nvidia") != -1)
2990     {
2991       myIsSRgbWindow = true;
2992     }
2993   #endif
2994   #endif
2995     if (!myIsSRgbWindow)
2996     {
2997       Message::SendTrace ("OpenGl_Context, warning: window buffer is not sRGB-ready.\n"
2998                           "Check OpenGL window creation parameters for optimal performance.");
2999     }
3000   }
3001
3002   if (arbTexFloat)
3003   {
3004     mySupportedFormats->Add (Image_Format_GrayF);
3005     mySupportedFormats->Add (Image_Format_AlphaF);
3006     mySupportedFormats->Add (Image_Format_RGBF);
3007     mySupportedFormats->Add (Image_Format_RGBAF);
3008     if (arbTexRG)
3009     {
3010       mySupportedFormats->Add (Image_Format_RGF);
3011     }
3012     if (extBgra)
3013     {
3014     #if !defined(GL_ES_VERSION_2_0)
3015       mySupportedFormats->Add (Image_Format_BGRF);
3016     #endif
3017       mySupportedFormats->Add (Image_Format_BGRAF);
3018     }
3019   }
3020
3021 #ifdef __EMSCRIPTEN__
3022   if (checkEnableWebGlExtension (*this, "GL_WEBGL_compressed_texture_s3tc")) // GL_WEBGL_compressed_texture_s3tc_srgb for sRGB formats
3023   {
3024     mySupportedFormats->Add (Image_CompressedFormat_RGB_S3TC_DXT1);
3025     mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT1);
3026     mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT3);
3027     mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT5);
3028   }
3029 #else
3030   if (CheckExtension ("GL_EXT_texture_compression_s3tc")) // GL_EXT_texture_sRGB for sRGB formats
3031   {
3032     mySupportedFormats->Add (Image_CompressedFormat_RGB_S3TC_DXT1);
3033     mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT1);
3034     mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT3);
3035     mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT5);
3036   }
3037   else
3038   {
3039     if (CheckExtension ("GL_EXT_texture_compression_dxt1"))
3040     {
3041       mySupportedFormats->Add (Image_CompressedFormat_RGB_S3TC_DXT1);
3042       mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT1);
3043     }
3044     if (CheckExtension ("GL_ANGLE_texture_compression_dxt3"))
3045     {
3046       mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT3);
3047     }
3048     if (CheckExtension ("GL_ANGLE_texture_compression_dxt5"))
3049     {
3050       mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT5);
3051     }
3052   }
3053 #endif
3054
3055   // check whether PBR shading model is supported
3056   myHasPBR = arbFBO != NULL
3057           && myMaxTexCombined >= 4
3058           && arbTexRG
3059           && arbTexFloat
3060           && (IsGlGreaterEqual (3, 0)
3061         #if !defined(GL_ES_VERSION_2_0)
3062           || (IsGlGreaterEqual (2, 1) && CheckExtension ("GL_EXT_gpu_shader4"))
3063         #endif
3064              );
3065   if (myHasPBR)
3066   {
3067     myPBREnvLUTTexUnit       = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_PbrEnvironmentLUT);
3068     myPBRDiffIBLMapSHTexUnit = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_PbrIblDiffuseSH);
3069     myPBRSpecIBLMapTexUnit   = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_PbrIblSpecular);
3070   }
3071 }
3072
3073 // =======================================================================
3074 // function : MemoryInfo
3075 // purpose  :
3076 // =======================================================================
3077 Standard_Size OpenGl_Context::AvailableMemory() const
3078 {
3079 #if !defined(GL_ES_VERSION_2_0)
3080   if (atiMem)
3081   {
3082     // this is actually information for VBO pool
3083     // however because pools are mostly shared
3084     // it can be used for total GPU memory estimations
3085     GLint aMemInfo[4];
3086     aMemInfo[0] = 0;
3087     glGetIntegerv (GL_VBO_FREE_MEMORY_ATI, aMemInfo);
3088     // returned value is in KiB, however this maybe changed in future
3089     return Standard_Size(aMemInfo[0]) * 1024;
3090   }
3091   else if (nvxMem)
3092   {
3093     // current available dedicated video memory (in KiB), currently unused GPU memory
3094     GLint aMemInfo = 0;
3095     glGetIntegerv (GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &aMemInfo);
3096     return Standard_Size(aMemInfo) * 1024;
3097   }
3098 #endif
3099   return 0;
3100 }
3101
3102 // =======================================================================
3103 // function : MemoryInfo
3104 // purpose  :
3105 // =======================================================================
3106 TCollection_AsciiString OpenGl_Context::MemoryInfo() const
3107 {
3108   TColStd_IndexedDataMapOfStringString aDict;
3109   MemoryInfo (aDict);
3110
3111   TCollection_AsciiString aText;
3112   for (TColStd_IndexedDataMapOfStringString::Iterator anIter (aDict); anIter.More(); anIter.Next())
3113   {
3114     if (!aText.IsEmpty())
3115     {
3116       aText += "\n";
3117     }
3118     aText += TCollection_AsciiString("  ") + anIter.Key() + ": " + anIter.Value();
3119   }
3120   return aText;
3121 }
3122
3123 // =======================================================================
3124 // function : MemoryInfo
3125 // purpose  :
3126 // =======================================================================
3127 void OpenGl_Context::MemoryInfo (TColStd_IndexedDataMapOfStringString& theDict) const
3128 {
3129 #if defined(GL_ES_VERSION_2_0)
3130   (void )theDict;
3131 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
3132   GLint aGlRendId = 0;
3133   CGLGetParameter (CGLGetCurrentContext(), kCGLCPCurrentRendererID, &aGlRendId);
3134
3135   CGLRendererInfoObj  aRendObj = NULL;
3136   CGOpenGLDisplayMask aDispMask = CGDisplayIDToOpenGLDisplayMask (kCGDirectMainDisplay);
3137   GLint aRendNb = 0;
3138   CGLQueryRendererInfo (aDispMask, &aRendObj, &aRendNb);
3139   for (GLint aRendIter = 0; aRendIter < aRendNb; ++aRendIter)
3140   {
3141     GLint aRendId = 0;
3142     if (CGLDescribeRenderer (aRendObj, aRendIter, kCGLRPRendererID, &aRendId) != kCGLNoError
3143      || aRendId != aGlRendId)
3144     {
3145       continue;
3146     }
3147
3148     //kCGLRPVideoMemoryMegabytes   = 131;
3149     //kCGLRPTextureMemoryMegabytes = 132;
3150     GLint aVMem = 0;
3151   #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
3152     if (CGLDescribeRenderer(aRendObj, aRendIter, kCGLRPVideoMemoryMegabytes, &aVMem) == kCGLNoError)
3153     {
3154       addInfo (theDict, "GPU memory",         TCollection_AsciiString() + aVMem + " MiB");
3155     }
3156     if (CGLDescribeRenderer(aRendObj, aRendIter, kCGLRPTextureMemoryMegabytes, &aVMem) == kCGLNoError)
3157     {
3158       addInfo (theDict, "GPU Texture memory", TCollection_AsciiString() + aVMem + " MiB");
3159     }
3160   #else
3161     if (CGLDescribeRenderer(aRendObj, aRendIter, kCGLRPVideoMemory, &aVMem) == kCGLNoError)
3162     {
3163       addInfo (theDict, "GPU memory",         TCollection_AsciiString() + (aVMem / (1024 * 1024)) + " MiB");
3164     }
3165     if (CGLDescribeRenderer(aRendObj, aRendIter, kCGLRPTextureMemory, &aVMem) == kCGLNoError)
3166     {
3167       addInfo (theDict, "GPU Texture memory", TCollection_AsciiString() + (aVMem / (1024 * 1024)) + " MiB");
3168     }
3169   #endif
3170   }
3171 #endif
3172
3173 #if !defined(GL_ES_VERSION_2_0)
3174   if (atiMem)
3175   {
3176     GLint aValues[4];
3177     memset (aValues, 0, sizeof(aValues));
3178     glGetIntegerv (GL_VBO_FREE_MEMORY_ATI, aValues);
3179
3180     // total memory free in the pool
3181     addInfo (theDict, "GPU free memory",    TCollection_AsciiString() + (aValues[0] / 1024) + " MiB");
3182
3183     if (aValues[1] != aValues[0])
3184     {
3185       // largest available free block in the pool
3186       addInfo (theDict, "Largest free block", TCollection_AsciiString() + (aValues[1] / 1024) + " MiB");
3187     }
3188     if (aValues[2] != aValues[0])
3189     {
3190       // total auxiliary memory free
3191       addInfo (theDict, "Free auxiliary memory", TCollection_AsciiString() + (aValues[2] / 1024) + " MiB");
3192     }
3193   }
3194   else if (nvxMem)
3195   {
3196     //current available dedicated video memory (in KiB), currently unused GPU memory
3197     GLint aValue = 0;
3198     glGetIntegerv (GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &aValue);
3199     addInfo (theDict, "GPU free memory", TCollection_AsciiString() + (aValue / 1024) + " MiB");
3200
3201     // dedicated video memory, total size (in KiB) of the GPU memory
3202     GLint aDedicated = 0;
3203     glGetIntegerv (GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, &aDedicated);
3204     addInfo (theDict, "GPU memory", TCollection_AsciiString() + (aDedicated / 1024) + " MiB");
3205
3206     // total available memory, total size (in KiB) of the memory available for allocations
3207     glGetIntegerv (GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, &aValue);
3208     if (aValue != aDedicated)
3209     {
3210       // different only for special configurations
3211       addInfo (theDict, "Total memory", TCollection_AsciiString() + (aValue / 1024) + " MiB");
3212     }
3213   }
3214 #if defined(_WIN32)
3215   else if (myFuncs->wglGetGPUInfoAMD != NULL
3216         && myFuncs->wglGetContextGPUIDAMD != NULL)
3217   {
3218     GLuint aTotalMemMiB = 0;
3219     UINT anAmdId = myFuncs->wglGetContextGPUIDAMD ((HGLRC )myGContext);
3220     if (anAmdId != 0)
3221     {
3222       if (myFuncs->wglGetGPUInfoAMD (anAmdId, WGL_GPU_RAM_AMD, GL_UNSIGNED_INT, sizeof(aTotalMemMiB), &aTotalMemMiB) > 0)
3223       {
3224         addInfo (theDict, "GPU memory", TCollection_AsciiString() + (int )aTotalMemMiB + " MiB");
3225       }
3226     }
3227   }
3228 #endif
3229 #endif
3230
3231 #if !defined(GL_ES_VERSION_2_0) && !defined(__APPLE__) && !defined(_WIN32)
3232   // GLX_RENDERER_VENDOR_ID_MESA
3233   if (myFuncs->glXQueryCurrentRendererIntegerMESA != NULL)
3234   {
3235     unsigned int aVMemMiB = 0;
3236     if (myFuncs->glXQueryCurrentRendererIntegerMESA (GLX_RENDERER_VIDEO_MEMORY_MESA, &aVMemMiB) != False)
3237     {
3238       addInfo (theDict, "GPU memory", TCollection_AsciiString() + int(aVMemMiB) + " MiB");
3239     }
3240   }
3241 #endif
3242 }
3243
3244 // =======================================================================
3245 // function : DiagnosticInfo
3246 // purpose  :
3247 // =======================================================================
3248 void OpenGl_Context::DiagnosticInformation (TColStd_IndexedDataMapOfStringString& theDict,
3249                                             Graphic3d_DiagnosticInfo theFlags) const
3250 {
3251   if ((theFlags & Graphic3d_DiagnosticInfo_NativePlatform) != 0)
3252   {
3253   #if defined(HAVE_EGL)
3254     addInfo (theDict, "EGLVersion",    ::eglQueryString ((EGLDisplay )myDisplay, EGL_VERSION));
3255     addInfo (theDict, "EGLVendor",     ::eglQueryString ((EGLDisplay )myDisplay, EGL_VENDOR));
3256     addInfo (theDict, "EGLClientAPIs", ::eglQueryString ((EGLDisplay )myDisplay, EGL_CLIENT_APIS));
3257     if ((theFlags & Graphic3d_DiagnosticInfo_Extensions) != 0)
3258     {
3259       addInfo (theDict, "EGLExtensions", ::eglQueryString ((EGLDisplay )myDisplay, EGL_EXTENSIONS));
3260     }
3261   #elif defined(_WIN32)
3262     if ((theFlags & Graphic3d_DiagnosticInfo_Extensions) != 0
3263      && myFuncs->wglGetExtensionsStringARB != NULL)
3264     {
3265       const char* aWglExts = myFuncs->wglGetExtensionsStringARB ((HDC )myWindowDC);
3266       addInfo (theDict, "WGLExtensions", aWglExts);
3267     }
3268   #elif defined(__APPLE__)
3269     //
3270   #else
3271     Display* aDisplay = (Display*)myDisplay;
3272     const int aScreen = DefaultScreen(aDisplay);
3273     addInfo (theDict, "GLXDirectRendering", ::glXIsDirect (aDisplay, (GLXContext )myGContext) ? "Yes" : "No");
3274     addInfo (theDict, "GLXVendor",  ::glXQueryServerString (aDisplay, aScreen, GLX_VENDOR));
3275     addInfo (theDict, "GLXVersion", ::glXQueryServerString (aDisplay, aScreen, GLX_VERSION));
3276     if ((theFlags & Graphic3d_DiagnosticInfo_Extensions) != 0)
3277     {
3278       const char* aGlxExts = ::glXQueryExtensionsString (aDisplay, aScreen);
3279       addInfo(theDict, "GLXExtensions", aGlxExts);
3280     }
3281
3282     addInfo (theDict, "GLXClientVendor",  ::glXGetClientString (aDisplay, GLX_VENDOR));
3283     addInfo (theDict, "GLXClientVersion", ::glXGetClientString (aDisplay, GLX_VERSION));
3284     if ((theFlags & Graphic3d_DiagnosticInfo_Extensions) != 0)
3285     {
3286       addInfo (theDict, "GLXClientExtensions", ::glXGetClientString (aDisplay, GLX_EXTENSIONS));
3287     }
3288   #endif
3289   }
3290
3291   if ((theFlags & Graphic3d_DiagnosticInfo_Device) != 0)
3292   {
3293     Standard_Integer aDriverVer[2] = {};
3294     ReadGlVersion (aDriverVer[0], aDriverVer[1]);
3295     addInfo (theDict, "GLvendor",    (const char*)::glGetString (GL_VENDOR));
3296     addInfo (theDict, "GLdevice",    (const char*)::glGetString (GL_RENDERER));
3297   #ifdef __EMSCRIPTEN__
3298     if (checkEnableWebGlExtension (*this, "GL_WEBGL_debug_renderer_info"))
3299     {
3300       if (const char* aVendor = (const char*)::glGetString (0x9245))
3301       {
3302         addInfo (theDict, "GLunmaskedVendor", aVendor);
3303       }
3304       if (const char* aDevice = (const char*)::glGetString (0x9246))
3305       {
3306         addInfo (theDict, "GLunmaskedDevice", aDevice);
3307       }
3308     }
3309   #endif
3310
3311     addInfo (theDict, "GLversion",   (const char*)::glGetString (GL_VERSION));
3312     if (myGlVerMajor != aDriverVer[0]
3313      || myGlVerMinor != aDriverVer[1])
3314     {
3315       addInfo (theDict, "GLversionOcct", TCollection_AsciiString (myGlVerMajor) + "." + TCollection_AsciiString (myGlVerMinor));
3316     }
3317     if (IsGlGreaterEqual (2, 0))
3318     {
3319       addInfo (theDict, "GLSLversion", (const char*)::glGetString (GL_SHADING_LANGUAGE_VERSION));
3320     }
3321     if (myIsGlDebugCtx)
3322     {
3323       addInfo (theDict, "GLdebug", "ON");
3324     }
3325   }
3326
3327   if ((theFlags & Graphic3d_DiagnosticInfo_Limits) != 0)
3328   {
3329     addInfo (theDict, "Max texture size", TCollection_AsciiString(myMaxTexDim));
3330     addInfo (theDict, "Max FBO dump size", TCollection_AsciiString() + myMaxDumpSizeX + "x" + myMaxDumpSizeY);
3331     addInfo (theDict, "Max combined texture units", TCollection_AsciiString(myMaxTexCombined));
3332     addInfo (theDict, "Max MSAA samples", TCollection_AsciiString(myMaxMsaaSamples));
3333   }
3334
3335   if ((theFlags & Graphic3d_DiagnosticInfo_FrameBuffer) != 0)
3336   {
3337     GLint aViewport[4] = {};
3338     ::glGetIntegerv (GL_VIEWPORT, aViewport);
3339     addInfo (theDict, "Viewport", TCollection_AsciiString() + aViewport[2] + "x" + aViewport[3]);
3340   }
3341
3342   if ((theFlags & Graphic3d_DiagnosticInfo_Memory) != 0)
3343   {
3344     MemoryInfo (theDict);
3345   }
3346
3347   if ((theFlags & Graphic3d_DiagnosticInfo_Extensions) != 0)
3348   {
3349   #if !defined(GL_ES_VERSION_2_0)
3350     if (IsGlGreaterEqual (3, 0)
3351      && myFuncs->glGetStringi != NULL)
3352     {
3353       TCollection_AsciiString anExtList;
3354       GLint anExtNb = 0;
3355       ::glGetIntegerv (GL_NUM_EXTENSIONS, &anExtNb);
3356       for (GLint anIter = 0; anIter < anExtNb; ++anIter)
3357       {
3358         const char* anExtension = (const char*)myFuncs->glGetStringi (GL_EXTENSIONS, (GLuint)anIter);
3359         if (!anExtList.IsEmpty())
3360         {
3361           anExtList += " ";
3362         }
3363         anExtList += anExtension;
3364       }
3365       addInfo(theDict, "GLextensions", anExtList);
3366     }
3367     else
3368   #endif
3369     {
3370       addInfo (theDict, "GLextensions", (const char*)::glGetString (GL_EXTENSIONS));
3371     }
3372   }
3373 }
3374
3375 // =======================================================================
3376 // function : GetResource
3377 // purpose  :
3378 // =======================================================================
3379 const Handle(OpenGl_Resource)& OpenGl_Context::GetResource (const TCollection_AsciiString& theKey) const
3380 {
3381   return mySharedResources->IsBound (theKey) ? mySharedResources->Find (theKey) : NULL_GL_RESOURCE;
3382 }
3383
3384 // =======================================================================
3385 // function : ShareResource
3386 // purpose  :
3387 // =======================================================================
3388 Standard_Boolean OpenGl_Context::ShareResource (const TCollection_AsciiString& theKey,
3389                                                 const Handle(OpenGl_Resource)& theResource)
3390 {
3391   if (theKey.IsEmpty() || theResource.IsNull())
3392   {
3393     return Standard_False;
3394   }
3395   return mySharedResources->Bind (theKey, theResource);
3396 }
3397
3398 // =======================================================================
3399 // function : ReleaseResource
3400 // purpose  :
3401 // =======================================================================
3402 void OpenGl_Context::ReleaseResource (const TCollection_AsciiString& theKey,
3403                                       const Standard_Boolean         theToDelay)
3404 {
3405   if (!mySharedResources->IsBound (theKey))
3406   {
3407     return;
3408   }
3409   const Handle(OpenGl_Resource)& aRes = mySharedResources->Find (theKey);
3410   if (aRes->GetRefCount() > 1)
3411   {
3412     return;
3413   }
3414
3415   if (theToDelay)
3416   {
3417     myDelayed->Bind (theKey, 1);
3418   }
3419   else
3420   {
3421     aRes->Release (this);
3422     mySharedResources->UnBind (theKey);
3423   }
3424 }
3425
3426 // =======================================================================
3427 // function : ReleaseDelayed
3428 // purpose  :
3429 // =======================================================================
3430 void OpenGl_Context::ReleaseDelayed()
3431 {
3432   // release queued elements
3433   while (!myUnusedResources->IsEmpty())
3434   {
3435     myUnusedResources->First()->Release (this);
3436     myUnusedResources->RemoveFirst();
3437   }
3438
3439   // release delayed shared resources
3440   NCollection_Vector<TCollection_AsciiString> aDeadList;
3441   for (NCollection_DataMap<TCollection_AsciiString, Standard_Integer>::Iterator anIter (*myDelayed);
3442        anIter.More(); anIter.Next())
3443   {
3444     if (++anIter.ChangeValue() <= 2)
3445     {
3446       continue; // postpone release one more frame to ensure noone use it periodically
3447     }
3448
3449     const TCollection_AsciiString& aKey = anIter.Key();
3450     if (!mySharedResources->IsBound (aKey))
3451     {
3452       // mixed unshared strategy delayed/undelayed was used!
3453       aDeadList.Append (aKey);
3454       continue;
3455     }
3456
3457     const Handle(OpenGl_Resource)& aRes = mySharedResources->ChangeFind (aKey);
3458     if (aRes->GetRefCount() > 1)
3459     {
3460       // should be only 1 instance in mySharedResources
3461       // if not - resource was reused again
3462       aDeadList.Append (aKey);
3463       continue;
3464     }
3465
3466     // release resource if no one requiested it more than 2 redraw calls
3467     aRes->Release (this);
3468     mySharedResources->UnBind (aKey);
3469     aDeadList.Append (aKey);
3470   }
3471
3472   for (Standard_Integer anIter = 0; anIter < aDeadList.Length(); ++anIter)
3473   {
3474     myDelayed->UnBind (aDeadList.Value (anIter));
3475   }
3476 }
3477
3478 // =======================================================================
3479 // function : BindTextures
3480 // purpose  :
3481 // =======================================================================
3482 Handle(OpenGl_TextureSet) OpenGl_Context::BindTextures (const Handle(OpenGl_TextureSet)& theTextures,
3483                                                         const Handle(OpenGl_ShaderProgram)& theProgram)
3484 {
3485   const Standard_Integer aTextureSetBits = !theTextures.IsNull() ? theTextures->TextureSetBits() : 0;
3486   const Standard_Integer aProgramBits    = !theProgram.IsNull() ? theProgram->TextureSetBits() : 0;
3487   Standard_Integer aMissingBits = aProgramBits & ~aTextureSetBits;
3488   if (aMissingBits != 0
3489    && myTextureRgbaBlack.IsNull())
3490   {
3491     // allocate mock textures
3492     myTextureRgbaBlack = new OpenGl_Texture();
3493     myTextureRgbaWhite = new OpenGl_Texture();
3494     Image_PixMap anImage;
3495     anImage.InitZero (Image_Format_RGBA, 2, 2, 0, (Standard_Byte )0);
3496     if (!myTextureRgbaBlack->Init (this, OpenGl_TextureFormat::Create<GLubyte, 4>(), Graphic3d_Vec2i (2, 2), Graphic3d_TOT_2D, &anImage))
3497     {
3498       PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH,
3499                     "Error: unable to create unit mock PBR texture map.");
3500     }
3501     anImage.InitZero (Image_Format_RGBA, 2, 2, 0, (Standard_Byte )255);
3502     if (!myTextureRgbaWhite->Init (this, OpenGl_TextureFormat::Create<GLubyte, 4>(), Graphic3d_Vec2i (2, 2), Graphic3d_TOT_2D, &anImage))
3503     {
3504       PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH,
3505                     "Error: unable to create normal mock PBR texture map.");
3506     }
3507   }
3508
3509   Handle(OpenGl_TextureSet) anOldTextures = myActiveTextures;
3510   if (myActiveTextures != theTextures)
3511   {
3512     Handle(OpenGl_Context) aThisCtx (this);
3513     for (OpenGl_TextureSetPairIterator aSlotIter (myActiveTextures, theTextures); aSlotIter.More(); aSlotIter.Next())
3514     {
3515       const Graphic3d_TextureUnit aTexUnit = aSlotIter.Unit();
3516       const OpenGl_Texture* aTextureOld = aSlotIter.Texture1();
3517       const OpenGl_Texture* aTextureNew = aSlotIter.Texture2();
3518       if (aTextureNew == aTextureOld)
3519       {
3520         continue;
3521       }
3522
3523       if (aTextureNew != NULL
3524        && aTextureNew->IsValid())
3525       {
3526         if (aTexUnit >= myMaxTexCombined)
3527         {
3528           PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
3529                        TCollection_AsciiString("Texture unit ") + aTexUnit + " for " + aTextureNew->ResourceId() + " exceeds hardware limit " + myMaxTexCombined);
3530           continue;
3531         }
3532
3533         aTextureNew->Bind (aThisCtx, aTexUnit);
3534         if (aTextureNew->Sampler()->ToUpdateParameters())
3535         {
3536           if (aTextureNew->Sampler()->IsImmutable())
3537           {
3538             aTextureNew->Sampler()->Init (aThisCtx, *aTextureNew);
3539           }
3540           else
3541           {
3542             OpenGl_Sampler::applySamplerParams (aThisCtx, aTextureNew->Sampler()->Parameters(), aTextureNew->Sampler().get(), aTextureNew->GetTarget(), aTextureNew->MaxMipmapLevel());
3543           }
3544         }
3545       #if !defined(GL_ES_VERSION_2_0)
3546         if (core11 != NULL)
3547         {
3548           OpenGl_Sampler::applyGlobalTextureParams (aThisCtx, *aTextureNew, aTextureNew->Sampler()->Parameters());
3549         }
3550       #endif
3551       }
3552       else if (aTextureOld != NULL
3553             && aTextureOld->IsValid())
3554       {
3555         aTextureOld->Unbind (aThisCtx, aTexUnit);
3556       #if !defined(GL_ES_VERSION_2_0)
3557         if (core11 != NULL)
3558         {
3559           OpenGl_Sampler::resetGlobalTextureParams (aThisCtx, *aTextureOld, aTextureOld->Sampler()->Parameters());
3560         }
3561       #endif
3562       }
3563     }
3564     myActiveTextures = theTextures;
3565   }
3566
3567   if (myActiveMockTextures != aMissingBits)
3568   {
3569     myActiveMockTextures = aMissingBits;
3570     for (Standard_Integer aBitIter = 0; aMissingBits != 0; ++aBitIter)
3571     {
3572       Standard_Integer aUnitMask = 1 << aBitIter;
3573       if ((aUnitMask & aMissingBits) != 0)
3574       {
3575         aMissingBits = aMissingBits & ~aUnitMask;
3576         if (aBitIter == Graphic3d_TextureUnit_Normal)
3577         {
3578           myTextureRgbaBlack->Bind (this, static_cast<Graphic3d_TextureUnit>(aBitIter));
3579         }
3580         else
3581         {
3582           myTextureRgbaWhite->Bind (this, static_cast<Graphic3d_TextureUnit>(aBitIter));
3583         }
3584       }