0032465: Visualization, TKOpenGles - invalid enum on GL_RGBA16F initialization in...
[occt.git] / src / OpenGl / OpenGl_Context.cxx
index fdafc54..8bf742e 100644 (file)
 #include <OpenGl_ExtGS.hxx>
 #include <OpenGl_ArbSamplerObject.hxx>
 #include <OpenGl_ArbTexBindless.hxx>
-#include <OpenGl_GlCore44.hxx>
+#include <OpenGl_GlCore46.hxx>
 #include <OpenGl_FrameBuffer.hxx>
 #include <OpenGl_FrameStats.hxx>
 #include <OpenGl_Sampler.hxx>
 #include <OpenGl_ShaderManager.hxx>
+#include <OpenGl_TextureSetPairIterator.hxx>
 #include <OpenGl_Workspace.hxx>
-#include <OpenGl_AspectFace.hxx>
+#include <OpenGl_Aspects.hxx>
+
 #include <Graphic3d_TransformUtils.hxx>
 #include <Graphic3d_RenderingParams.hxx>
-
+#include <Image_SupportedFormats.hxx>
 #include <Message_Messenger.hxx>
-
 #include <NCollection_Vector.hxx>
-
 #include <Standard_ProgramError.hxx>
+#include <Standard_WarningDisableFunctionCast.hxx>
+
+#if defined(_WIN32) && defined(max)
+  #undef max
+#endif
+#include <limits>
 
 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Context,Standard_Transient)
 
@@ -51,7 +57,9 @@ IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Context,Standard_Transient)
   #endif
 #elif defined(_WIN32)
   //
-#elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
+#elif defined(HAVE_XLIB)
+  #include <GL/glx.h> // glXGetProcAddress()
+#elif defined(__APPLE__)
   #include <dlfcn.h>
   #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
     //
@@ -60,17 +68,14 @@ IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Context,Standard_Transient)
     #include <CoreGraphics/CoreGraphics.h>
   #endif
 #else
-  #include <GL/glx.h> // glXGetProcAddress()
+  //
 #endif
 
-#ifdef HAVE_GL2PS
-  #include <gl2ps.h>
-  #ifdef _MSC_VER
-    #pragma comment (lib, "gl2ps.lib")
-  #endif
+#ifdef __EMSCRIPTEN__
+  #include <emscripten.h>
+  #include <emscripten/html5.h>
 #endif
 
-
 namespace
 {
   static const Handle(OpenGl_Resource) NULL_GL_RESOURCE;
@@ -99,38 +104,52 @@ namespace
 // purpose  :
 // =======================================================================
 OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps)
-: core11     (NULL),
+: core11ffp  (NULL),
   core11fwd  (NULL),
   core15     (NULL),
-  core15fwd  (NULL),
   core20     (NULL),
-  core20fwd  (NULL),
+  core30     (NULL),
   core32     (NULL),
-  core32back (NULL),
   core33     (NULL),
-  core33back (NULL),
   core41     (NULL),
-  core41back (NULL),
   core42     (NULL),
-  core42back (NULL),
   core43     (NULL),
-  core43back (NULL),
   core44     (NULL),
-  core44back (NULL),
+  core45     (NULL),
+  core46     (NULL),
+  core15fwd  (NULL),
+  core20fwd  (NULL),
   caps   (!theCaps.IsNull() ? theCaps : new OpenGl_Caps()),
+  hasGetBufferData (Standard_False),
 #if defined(GL_ES_VERSION_2_0)
+  hasPackRowLength (Standard_False),
+  hasUnpackRowLength (Standard_False),
   hasHighp   (Standard_False),
   hasUintIndex(Standard_False),
   hasTexRGBA8(Standard_False),
 #else
+  hasPackRowLength (Standard_True),
+  hasUnpackRowLength (Standard_True),
   hasHighp   (Standard_True),
   hasUintIndex(Standard_True),
   hasTexRGBA8(Standard_True),
 #endif
+  hasTexFloatLinear (Standard_False),
+  hasTexSRGB (Standard_False),
+  hasFboSRGB (Standard_False),
+  hasSRGBControl (Standard_False),
+  hasFboRenderMipmap (Standard_False),
+#if defined(GL_ES_VERSION_2_0)
+  hasFlatShading (OpenGl_FeatureNotAvailable),
+#else
+  hasFlatShading (OpenGl_FeatureInCore),
+#endif
+  hasGlslBitwiseOps  (OpenGl_FeatureNotAvailable),
   hasDrawBuffers     (OpenGl_FeatureNotAvailable),
   hasFloatBuffer     (OpenGl_FeatureNotAvailable),
   hasHalfFloatBuffer (OpenGl_FeatureNotAvailable),
   hasSampleVariables (OpenGl_FeatureNotAvailable),
+  hasGeometryStage   (OpenGl_FeatureNotAvailable),
   arbDrawBuffers (Standard_False),
   arbNPTW  (Standard_False),
   arbTexRG (Standard_False),
@@ -139,11 +158,13 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps)
   arbTexBindless (NULL),
   arbTBO (NULL),
   arbTboRGB32 (Standard_False),
+  arbClipControl (Standard_False),
   arbIns (NULL),
   arbDbg (NULL),
   arbFBO (NULL),
   arbFBOBlit (NULL),
   arbSampleShading (Standard_False),
+  arbDepthClamp (Standard_False),
   extFragDepth (Standard_False),
   extDrawBuffers (Standard_False),
   extGS  (NULL),
@@ -154,16 +175,23 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps)
   nvxMem (Standard_False),
   oesSampleVariables (Standard_False),
   oesStdDerivatives (Standard_False),
+  myWindow  (0),
+  myDisplay (0),
+  myGContext(0),
   mySharedResources (new OpenGl_ResourcesMap()),
   myDelayed         (new OpenGl_DelayReleaseMap()),
   myUnusedResources (new OpenGl_ResourcesStack()),
   myClippingState (),
   myGlLibHandle (NULL),
   myFuncs (new OpenGl_GlFunctions()),
+  mySupportedFormats (new Image_SupportedFormats()),
   myAnisoMax   (1),
   myTexClamp   (GL_CLAMP_TO_EDGE),
   myMaxTexDim  (1024),
   myMaxTexCombined (1),
+  myMaxTexUnitsFFP (1),
+  myMaxDumpSizeX (1024),
+  myMaxDumpSizeY (1024),
   myMaxClipPlanes (6),
   myMaxMsaaSamples(0),
   myMaxDrawBuffers (1),
@@ -173,28 +201,45 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps)
   myIsInitialized (Standard_False),
   myIsStereoBuffers (Standard_False),
   myIsGlNormalizeEnabled (Standard_False),
+  mySpriteTexUnit (Graphic3d_TextureUnit_PointSprite),
   myHasRayTracing (Standard_False),
   myHasRayTracingTextures (Standard_False),
   myHasRayTracingAdaptiveSampling (Standard_False),
+  myHasRayTracingAdaptiveSamplingAtomic (Standard_False),
+  myHasPBR (Standard_False),
+  myPBREnvLUTTexUnit       (Graphic3d_TextureUnit_PbrEnvironmentLUT),
+  myPBRDiffIBLMapSHTexUnit (Graphic3d_TextureUnit_PbrIblDiffuseSH),
+  myPBRSpecIBLMapTexUnit   (Graphic3d_TextureUnit_PbrIblSpecular),
+  myShadowMapTexUnit       (Graphic3d_TextureUnit_ShadowMap),
+  myDepthPeelingDepthTexUnit (Graphic3d_TextureUnit_DepthPeelingDepth),
+  myDepthPeelingFrontColorTexUnit (Graphic3d_TextureUnit_DepthPeelingFrontColor),
   myFrameStats (new OpenGl_FrameStats()),
+  myActiveMockTextures (0),
+  myActiveHatchType (Aspect_HS_SOLID),
+  myHatchIsEnabled (false),
 #if !defined(GL_ES_VERSION_2_0)
   myPointSpriteOrig (GL_UPPER_LEFT),
   myRenderMode (GL_RENDER),
+  myShadeModel (GL_SMOOTH),
   myPolygonMode (GL_FILL),
 #else
   myPointSpriteOrig (0),
   myRenderMode (0),
+  myShadeModel (0),
   myPolygonMode (0),
 #endif
   myToCullBackFaces (false),
   myReadBuffer (0),
-  myDrawBuffers (1),
+  myDrawBuffers (0, 7),
   myDefaultVao (0),
   myColorMask (true),
-  myIsGlDebugCtx (Standard_False),
+  myAlphaToCoverage (false),
+  myIsGlDebugCtx (false),
+  myIsSRgbWindow (false),
   myResolution (Graphic3d_RenderingParams::THE_DEFAULT_RESOLUTION),
   myResolutionRatio (1.0f),
   myLineWidthScale (1.0f),
+  myLineFeather (1.0f),
   myRenderScale (1.0f),
   myRenderScaleInv (1.0f)
 {
@@ -216,11 +261,7 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps)
   myDisplay  = (Aspect_Display          )EGL_NO_DISPLAY;
   myWindow   = (Aspect_Drawable         )EGL_NO_SURFACE;
   myGContext = (Aspect_RenderingContext )EGL_NO_CONTEXT;
-#elif defined(_WIN32)
-  myWindow   = NULL;
-  myWindowDC = NULL;
-  myGContext = NULL;
-#elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
+#elif defined(__APPLE__) && !defined(HAVE_XLIB)
   // Vendors can not extend functionality on this system
   // and developers are limited to OpenGL support provided by Mac OS X SDK.
   // We retrieve function pointers from system library
@@ -231,16 +272,10 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps)
   // because function pointers may be available but not functionality itself
   // (depends on renderer).
 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
-  myGContext    = NULL;
   myGlLibHandle = dlopen ("/System/Library/Frameworks/OpenGLES.framework/OpenGLES", RTLD_LAZY);
 #else
-  myGContext    = NULL;
   myGlLibHandle = dlopen ("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY);
 #endif
-#else
-  myDisplay =  NULL;
-  myWindow   = 0;
-  myGContext = 0;
 #endif
 
   memset (myFuncs.operator->(), 0, sizeof(OpenGl_GlFunctions));
@@ -267,6 +302,18 @@ OpenGl_Context::~OpenGl_Context()
   myDefaultVao = 0;
 #endif
 
+  // release mock textures
+  if (!myTextureRgbaBlack.IsNull())
+  {
+    myTextureRgbaBlack->Release (this);
+    myTextureRgbaBlack.Nullify();
+  }
+  if (!myTextureRgbaWhite.IsNull())
+  {
+    myTextureRgbaWhite->Release (this);
+    myTextureRgbaWhite.Nullify();
+  }
+
   // release default FBO
   if (!myDefaultFbo.IsNull())
   {
@@ -417,12 +464,8 @@ void OpenGl_Context::SetDrawBuffer (const Standard_Integer theDrawBuffer)
   }
   ::glDrawBuffer (aDrawBuffer);
 
-  myDrawBuffers.Clear();
-
-  if (aDrawBuffer != GL_NONE)
-  {
-    myDrawBuffers.SetValue (0, aDrawBuffer);
-  }
+  myDrawBuffers.Init (GL_NONE);
+  myDrawBuffers.SetValue (0, aDrawBuffer);
 #else
   (void )theDrawBuffer;
 #endif
@@ -436,23 +479,23 @@ void OpenGl_Context::SetDrawBuffers (const Standard_Integer theNb, const Standar
 {
   Standard_ASSERT_RETURN (hasDrawBuffers, "Multiple draw buffers feature is not supported by the context", Standard_ASSERT_DO_NOTHING());
 
-  myDrawBuffers.Clear();
+  if (myDrawBuffers.Length() < theNb)
+  {
+    // should actually never happen here
+    myDrawBuffers.Resize (0, theNb - 1, false);
+  }
+  myDrawBuffers.Init (GL_NONE);
 
   Standard_Boolean useDefaultFbo = Standard_False;
   for (Standard_Integer anI = 0; anI < theNb; ++anI)
   {
-#if !defined(GL_ES_VERSION_2_0)
-    const Standard_Integer aDrawBuffer = !myIsStereoBuffers ? stereoToMonoBuffer (theDrawBuffers[anI]) : theDrawBuffers[anI];
-#else
-    const Standard_Integer aDrawBuffer = theDrawBuffers[anI];
-#endif
-    if (aDrawBuffer < GL_COLOR_ATTACHMENT0 && aDrawBuffer != GL_NONE)
+    if (theDrawBuffers[anI] < GL_COLOR_ATTACHMENT0 && theDrawBuffers[anI] != GL_NONE)
     {
       useDefaultFbo = Standard_True;
     }
-    else if (aDrawBuffer != GL_NONE)
+    else
     {
-      myDrawBuffers.SetValue (anI, aDrawBuffer);
+      myDrawBuffers.SetValue (anI, theDrawBuffers[anI]);
     }
   }
   if (arbFBO != NULL && useDefaultFbo)
@@ -463,6 +506,35 @@ void OpenGl_Context::SetDrawBuffers (const Standard_Integer theNb, const Standar
   myFuncs->glDrawBuffers (theNb, (const GLenum*)theDrawBuffers);
 }
 
+// =======================================================================
+// function : SetFrameBufferSRGB
+// purpose  :
+// =======================================================================
+void OpenGl_Context::SetFrameBufferSRGB (bool theIsFbo, bool theIsFboSRgb)
+{
+  if (!hasFboSRGB)
+  {
+    myIsSRgbActive = false;
+    return;
+  }
+  myIsSRgbActive = ToRenderSRGB()
+               && (theIsFbo || myIsSRgbWindow)
+               && theIsFboSRgb;
+  if (!hasSRGBControl)
+  {
+    return;
+  }
+
+  if (myIsSRgbActive)
+  {
+    core11fwd->glEnable (GL_FRAMEBUFFER_SRGB);
+  }
+  else
+  {
+    core11fwd->glDisable (GL_FRAMEBUFFER_SRGB);
+  }
+}
+
 // =======================================================================
 // function : SetCullBackFaces
 // purpose  :
@@ -494,40 +566,34 @@ void OpenGl_Context::FetchState()
 {
 #if !defined(GL_ES_VERSION_2_0)
   // cache feedback mode state
-  if (core11 != NULL)
+  if (core11ffp != NULL)
   {
     ::glGetIntegerv (GL_RENDER_MODE, &myRenderMode);
+    ::glGetIntegerv (GL_SHADE_MODEL, &myShadeModel);
   }
 
   // cache read buffers state
   ::glGetIntegerv (GL_READ_BUFFER, &myReadBuffer);
 
   // cache draw buffers state
-  myDrawBuffers.Clear();
+  if (myDrawBuffers.Length() < myMaxDrawBuffers)
+  {
+    myDrawBuffers.Resize (0, myMaxDrawBuffers - 1, false);
+  }
+  myDrawBuffers.Init (GL_NONE);
 
+  Standard_Integer aDrawBuffer = GL_NONE;
   if (myMaxDrawBuffers == 1)
   {
-    Standard_Integer aDrawBuffer;
-
     ::glGetIntegerv (GL_DRAW_BUFFER, &aDrawBuffer);
-
-    if (aDrawBuffer != GL_NONE)
-    {
-      myDrawBuffers.SetValue (0, aDrawBuffer);
-    }
+    myDrawBuffers.SetValue (0, aDrawBuffer);
   }
   else
   {
-    Standard_Integer aDrawBuffer;
-
     for (Standard_Integer anI = 0; anI < myMaxDrawBuffers; ++anI)
     {
       ::glGetIntegerv (GL_DRAW_BUFFER0 + anI, &aDrawBuffer);
-
-      if (aDrawBuffer != GL_NONE)
-      {
-        myDrawBuffers.SetValue (anI, aDrawBuffer);
-      }
+      myDrawBuffers.SetValue (anI, aDrawBuffer);
     }
   }
 #endif
@@ -548,7 +614,7 @@ void OpenGl_Context::Share (const Handle(OpenGl_Context)& theShareCtx)
   }
 }
 
-#if !defined(__APPLE__) || defined(MACOSX_USE_GLX)
+#if !defined(__APPLE__) || defined(HAVE_XLIB)
 
 // =======================================================================
 // function : IsCurrent
@@ -558,7 +624,6 @@ Standard_Boolean OpenGl_Context::IsCurrent() const
 {
 #if defined(HAVE_EGL)
   if ((EGLDisplay )myDisplay  == EGL_NO_DISPLAY
-   || (EGLSurface )myWindow   == EGL_NO_SURFACE
    || (EGLContext )myGContext == EGL_NO_CONTEXT)
   {
     return Standard_False;
@@ -568,13 +633,13 @@ Standard_Boolean OpenGl_Context::IsCurrent() const
        && ((EGLContext )myGContext == eglGetCurrentContext())
        && ((EGLSurface )myWindow   == eglGetCurrentSurface (EGL_DRAW)));
 #elif defined(_WIN32)
-  if (myWindowDC == NULL || myGContext == NULL)
+  if (myDisplay == NULL || myGContext == NULL)
   {
     return Standard_False;
   }
-  return (( (HDC )myWindowDC == wglGetCurrentDC())
+  return (( (HDC )myDisplay  == wglGetCurrentDC())
       && ((HGLRC )myGContext == wglGetCurrentContext()));
-#else
+#elif defined(HAVE_XLIB)
   if (myDisplay == NULL || myWindow == 0 || myGContext == 0)
   {
     return Standard_False;
@@ -583,6 +648,8 @@ Standard_Boolean OpenGl_Context::IsCurrent() const
   return (   ((Display* )myDisplay  == glXGetCurrentDisplay())
        &&  ((GLXContext )myGContext == glXGetCurrentContext())
        && ((GLXDrawable )myWindow   == glXGetCurrentDrawable()));
+#else
+  return Standard_False;
 #endif
 }
 
@@ -594,7 +661,6 @@ Standard_Boolean OpenGl_Context::MakeCurrent()
 {
 #if defined(HAVE_EGL)
   if ((EGLDisplay )myDisplay  == EGL_NO_DISPLAY
-   || (EGLSurface )myWindow   == EGL_NO_SURFACE
    || (EGLContext )myGContext == EGL_NO_CONTEXT)
   {
     Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called before!");
@@ -610,7 +676,7 @@ Standard_Boolean OpenGl_Context::MakeCurrent()
     return Standard_False;
   }
 #elif defined(_WIN32)
-  if (myWindowDC == NULL || myGContext == NULL)
+  if (myDisplay == NULL || myGContext == NULL)
   {
     Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called before!");
     return Standard_False;
@@ -623,7 +689,7 @@ Standard_Boolean OpenGl_Context::MakeCurrent()
     myShaderManager->SetContext (this);
     return Standard_True;
   }
-  else if (wglMakeCurrent ((HDC )myWindowDC, (HGLRC )myGContext) != TRUE)
+  else if (wglMakeCurrent ((HDC )myDisplay, (HGLRC )myGContext) != TRUE)
   {
     // notice that glGetError() couldn't be used here!
     wchar_t* aMsgBuff = NULL;
@@ -640,7 +706,7 @@ Standard_Boolean OpenGl_Context::MakeCurrent()
     myIsInitialized = Standard_False;
     return Standard_False;
   }
-#else
+#elif defined(HAVE_XLIB)
   if (myDisplay == NULL || myWindow == 0 || myGContext == 0)
   {
     Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called before!");
@@ -655,6 +721,12 @@ Standard_Boolean OpenGl_Context::MakeCurrent()
     myIsInitialized = Standard_False;
     return Standard_False;
   }
+#else
+  // not implemented
+  if (!myIsInitialized)
+  {
+    throw Standard_ProgramError ("OpenGl_Context::Init() should be called before!");
+  }
 #endif
   myShaderManager->SetContext (this);
   return Standard_True;
@@ -672,16 +744,18 @@ void OpenGl_Context::SwapBuffers()
     eglSwapBuffers ((EGLDisplay )myDisplay, (EGLSurface )myWindow);
   }
 #elif defined(_WIN32)
-  if ((HDC )myWindowDC != NULL)
+  if ((HDC )myDisplay != NULL)
   {
-    ::SwapBuffers ((HDC )myWindowDC);
+    ::SwapBuffers ((HDC )myDisplay);
     glFlush();
   }
-#else
+#elif defined(HAVE_XLIB)
   if ((Display* )myDisplay != NULL)
   {
     glXSwapBuffers ((Display* )myDisplay, (GLXDrawable )myWindow);
   }
+#else
+  //
 #endif
 }
 
@@ -705,13 +779,13 @@ Standard_Boolean OpenGl_Context::SetSwapInterval (const Standard_Integer theInte
     return Standard_True;
   }
 #elif defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
-  //
+  (void )theInterval; // vsync cannot be turned OFF on iOS
 #elif defined(__APPLE__)
   if (::CGLSetParameter (CGLGetCurrentContext(), kCGLCPSwapInterval, &theInterval) == kCGLNoError)
   {
     return Standard_True;
   }
-#else
+#elif defined(HAVE_XLIB)
   if (theInterval == -1
    && myFuncs->glXSwapIntervalEXT != NULL)
   {
@@ -725,6 +799,8 @@ Standard_Boolean OpenGl_Context::SetSwapInterval (const Standard_Integer theInte
     myFuncs->glXSwapIntervalSGI (theInterval);
     return Standard_True;
   }
+#else
+  //
 #endif
   return Standard_False;
 }
@@ -739,10 +815,13 @@ void* OpenGl_Context::findProc (const char* theFuncName)
   return (void* )eglGetProcAddress (theFuncName);
 #elif defined(_WIN32)
   return (void* )wglGetProcAddress (theFuncName);
-#elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
+#elif defined(HAVE_XLIB)
+  return (void* )glXGetProcAddress ((const GLubyte* )theFuncName);
+#elif defined(__APPLE__)
   return (myGlLibHandle != NULL) ? dlsym (myGlLibHandle, theFuncName) : NULL;
 #else
-  return (void* )glXGetProcAddress ((const GLubyte* )theFuncName);
+  (void )theFuncName;
+  return NULL;
 #endif
 }
 
@@ -759,6 +838,10 @@ Standard_Boolean OpenGl_Context::CheckExtension (const char* theExtName) const
 #endif
     return Standard_False;
   }
+  else if (caps->contextNoExtensions)
+  {
+    return Standard_False;
+  }
 
 #if !defined(GL_ES_VERSION_2_0)
   // available since OpenGL 3.0
@@ -790,7 +873,25 @@ Standard_Boolean OpenGl_Context::CheckExtension (const char* theExtName) const
     Messenger()->Send ("TKOpenGL: glGetString (GL_EXTENSIONS) has returned NULL! No GL context?", Message_Warning);
     return Standard_False;
   }
-  return CheckExtension (anExtString, theExtName);
+  if (!CheckExtension (anExtString, theExtName))
+  {
+    return Standard_False;
+  }
+
+#ifdef __EMSCRIPTEN__
+  //! Check if WebGL extension is available and activate it
+  //! (usage of extension without activation will generate errors).
+  if (EMSCRIPTEN_WEBGL_CONTEXT_HANDLE aWebGlCtx = emscripten_webgl_get_current_context())
+  {
+    if (emscripten_webgl_enable_extension (aWebGlCtx, theExtName))
+    {
+      return Standard_True;
+    }
+  }
+  return Standard_False;
+#else
+  return Standard_True;
+#endif
 }
 
 // =======================================================================
@@ -822,7 +923,7 @@ Standard_Boolean OpenGl_Context::CheckExtension (const char* theExtString,
   return Standard_False;
 }
 
-#if !defined(__APPLE__) || defined(MACOSX_USE_GLX)
+#if !defined(__APPLE__) || defined(HAVE_XLIB)
 
 // =======================================================================
 // function : Init
@@ -840,12 +941,14 @@ Standard_Boolean OpenGl_Context::Init (const Standard_Boolean theIsCoreProfile)
   myGContext = (Aspect_RenderingContext )eglGetCurrentContext();
   myWindow   = (Aspect_Drawable )eglGetCurrentSurface(EGL_DRAW);
 #elif defined(_WIN32)
-  myWindowDC = (Aspect_Handle )wglGetCurrentDC();
+  myDisplay  = (Aspect_Handle )wglGetCurrentDC();
   myGContext = (Aspect_RenderingContext )wglGetCurrentContext();
-#else
+#elif defined(HAVE_XLIB)
   myDisplay  = (Aspect_Display )glXGetCurrentDisplay();
   myGContext = (Aspect_RenderingContext )glXGetCurrentContext();
   myWindow   = (Aspect_Drawable )glXGetCurrentDrawable();
+#else
+  //
 #endif
   if (myGContext == NULL)
   {
@@ -863,49 +966,15 @@ Standard_Boolean OpenGl_Context::Init (const Standard_Boolean theIsCoreProfile)
 // function : Init
 // purpose  :
 // =======================================================================
-#if defined(HAVE_EGL)
-Standard_Boolean OpenGl_Context::Init (const Aspect_Drawable         theEglSurface,
-                                       const Aspect_Display          theEglDisplay,
-                                       const Aspect_RenderingContext theEglContext,
-                                       const Standard_Boolean        theIsCoreProfile)
-#elif defined(_WIN32)
-Standard_Boolean OpenGl_Context::Init (const Aspect_Handle           theWindow,
-                                       const Aspect_Handle           theWindowDC,
-                                       const Aspect_RenderingContext theGContext,
-                                       const Standard_Boolean        theIsCoreProfile)
-#elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
-
-#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
-Standard_Boolean OpenGl_Context::Init (EAGLContext*                  theGContext,
-                                       const Standard_Boolean        theIsCoreProfile)
-#else
-Standard_Boolean OpenGl_Context::Init (NSOpenGLContext*              theGContext,
-                                       const Standard_Boolean        theIsCoreProfile)
-#endif
-
-#else
-Standard_Boolean OpenGl_Context::Init (const Aspect_Drawable         theWindow,
+Standard_Boolean OpenGl_Context::Init (const Aspect_Drawable         theSurface,
                                        const Aspect_Display          theDisplay,
-                                       const Aspect_RenderingContext theGContext,
+                                       const Aspect_RenderingContext theContext,
                                        const Standard_Boolean        theIsCoreProfile)
-#endif
 {
   Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called only once!");
-#if defined(HAVE_EGL)
-  myWindow   = theEglSurface;
-  myGContext = theEglContext;
-  myDisplay  = theEglDisplay;
-#elif defined(_WIN32)
-  myWindow   = theWindow;
-  myGContext = theGContext;
-  myWindowDC = theWindowDC;
-#elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
-  myGContext = theGContext;
-#else
-  myWindow   = theWindow;
-  myGContext = theGContext;
+  myWindow   = theSurface;
   myDisplay  = theDisplay;
-#endif
+  myGContext = theContext;
   if (myGContext == NULL || !MakeCurrent())
   {
     return Standard_False;
@@ -916,6 +985,62 @@ Standard_Boolean OpenGl_Context::Init (const Aspect_Drawable         theWindow,
   return Standard_True;
 }
 
+// =======================================================================
+// function : FormatGlEnumHex
+// purpose  :
+// =======================================================================
+TCollection_AsciiString OpenGl_Context::FormatGlEnumHex (int theGlEnum)
+{
+  char aBuff[16];
+  Sprintf (aBuff, theGlEnum < (int )std::numeric_limits<uint16_t>::max()
+                ? "0x%04X"
+                : "0x%08X", theGlEnum);
+  return aBuff;
+}
+
+// =======================================================================
+// function : FormatSize
+// purpose  :
+// =======================================================================
+TCollection_AsciiString OpenGl_Context::FormatSize (Standard_Size theSize)
+{
+  char aBuff[32];
+  Sprintf (aBuff, "%" PRIu64, (uint64_t )theSize);
+  return aBuff;
+}
+
+// =======================================================================
+// function : FormatPointer
+// purpose  :
+// =======================================================================
+TCollection_AsciiString OpenGl_Context::FormatPointer (const void* thePtr)
+{
+  char aBuff[32];
+  Sprintf (aBuff, "0x%" PRIXPTR, (uintptr_t )thePtr);
+  return aBuff;
+}
+
+// =======================================================================
+// function : FormatGlError
+// purpose  :
+// =======================================================================
+TCollection_AsciiString OpenGl_Context::FormatGlError (int theGlError)
+{
+  switch (theGlError)
+  {
+    case GL_INVALID_ENUM:      return "GL_INVALID_ENUM";
+    case GL_INVALID_VALUE:     return "GL_INVALID_VALUE";
+    case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION";
+  #ifdef GL_STACK_OVERFLOW
+    case GL_STACK_OVERFLOW:    return "GL_STACK_OVERFLOW";
+    case GL_STACK_UNDERFLOW:   return "GL_STACK_UNDERFLOW";
+  #endif
+    case GL_OUT_OF_MEMORY:     return "GL_OUT_OF_MEMORY";
+    case GL_INVALID_FRAMEBUFFER_OPERATION: return "GL_INVALID_FRAMEBUFFER_OPERATION";
+  }
+  return FormatGlEnumHex (theGlError);
+}
+
 // =======================================================================
 // function : ResetErrors
 // purpose  :
@@ -936,29 +1061,40 @@ bool OpenGl_Context::ResetErrors (const bool theToPrintErrors)
 
   for (; anErr != GL_NO_ERROR && aPrevErr != anErr; aPrevErr = anErr, anErr = ::glGetError())
   {
-    TCollection_ExtendedString anErrId;
+    const TCollection_ExtendedString aMsg = TCollection_ExtendedString ("Unhandled GL error: ") + FormatGlError (anErr);
+    PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
+  }
+  return hasError;
+}
+
+// =======================================================================
+// function : debugPrintError
+// purpose  :
+// =======================================================================
+bool OpenGl_GlFunctions::debugPrintError (const char* theName) const
+{
+  const int anErr = ::glGetError();
+  if (anErr != GL_NO_ERROR)
+  {
+    Message::SendFail() << theName << "(), unhandled GL error: " << OpenGl_Context::FormatGlError (anErr);
+    // there is no glSetError(), just emulate non-clear state
     switch (anErr)
     {
-      case GL_INVALID_ENUM:      anErrId = "GL_INVALID_ENUM";      break;
-      case GL_INVALID_VALUE:     anErrId = "GL_INVALID_VALUE";     break;
-      case GL_INVALID_OPERATION: anErrId = "GL_INVALID_OPERATION"; break;
-    #ifdef GL_STACK_OVERFLOW
-      case GL_STACK_OVERFLOW:    anErrId = "GL_STACK_OVERFLOW";    break;
-      case GL_STACK_UNDERFLOW:   anErrId = "GL_STACK_UNDERFLOW";   break;
-    #endif
-      case GL_OUT_OF_MEMORY:     anErrId = "GL_OUT_OF_MEMORY";     break;
-      case GL_INVALID_FRAMEBUFFER_OPERATION:
-        anErrId = "GL_INVALID_FRAMEBUFFER_OPERATION";
+      case GL_INVALID_VALUE:
+      {
+        ::glLineWidth(-1.0f);
+        ::glLineWidth( 1.0f);
         break;
+      }
       default:
-        anErrId = TCollection_ExtendedString("#") + anErr;
+      case GL_INVALID_ENUM:
+      {
+        ::glEnable (0xFFFF);
         break;
+      }
     }
-
-    const TCollection_ExtendedString aMsg = TCollection_ExtendedString ("Unhandled GL error: ") + anErrId;
-    PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
   }
-  return hasError;
+  return anErr != GL_NO_ERROR;
 }
 
 // =======================================================================
@@ -972,32 +1108,47 @@ void OpenGl_Context::ReadGlVersion (Standard_Integer& theGlVerMajor,
   theGlVerMajor = 0;
   theGlVerMinor = 0;
 
-#ifdef GL_MAJOR_VERSION
-  // available since OpenGL 3.0 and OpenGL 3.0 ES
-  GLint aMajor = 0, aMinor = 0;
-  glGetIntegerv (GL_MAJOR_VERSION, &aMajor);
-  glGetIntegerv (GL_MINOR_VERSION, &aMinor);
-  // glGetError() sometimes does not report an error here even if
-  // GL does not know GL_MAJOR_VERSION and GL_MINOR_VERSION constants.
-  // This happens on some renderers like e.g. Cygwin MESA.
-  // Thus checking additionally if GL has put anything to
-  // the output variables.
-  if (::glGetError() == GL_NO_ERROR && aMajor != 0 && aMinor != 0)
-  {
-    theGlVerMajor = aMajor;
-    theGlVerMinor = aMinor;
-    return;
-  }
-  for (GLenum anErr = ::glGetError(), aPrevErr = GL_NO_ERROR;; aPrevErr = anErr, anErr = ::glGetError())
+  bool toCheckVer3 = true;
+#if defined(__EMSCRIPTEN__)
+  // WebGL 1.0 prints annoying invalid enumeration warnings to console.
+  toCheckVer3 = false;
+  if (EMSCRIPTEN_WEBGL_CONTEXT_HANDLE aWebGlCtx = emscripten_webgl_get_current_context())
   {
-    if (anErr == GL_NO_ERROR
-     || anErr == aPrevErr)
+    EmscriptenWebGLContextAttributes anAttribs = {};
+    if (emscripten_webgl_get_context_attributes (aWebGlCtx, &anAttribs) == EMSCRIPTEN_RESULT_SUCCESS)
     {
-      break;
+      toCheckVer3 = anAttribs.majorVersion >= 2;
     }
   }
 #endif
 
+  // Available since OpenGL 3.0 and OpenGL ES 3.0.
+  if (toCheckVer3)
+  {
+    GLint aMajor = 0, aMinor = 0;
+    glGetIntegerv (GL_MAJOR_VERSION, &aMajor);
+    glGetIntegerv (GL_MINOR_VERSION, &aMinor);
+    // glGetError() sometimes does not report an error here even if
+    // GL does not know GL_MAJOR_VERSION and GL_MINOR_VERSION constants.
+    // This happens on some renderers like e.g. Cygwin MESA.
+    // Thus checking additionally if GL has put anything to
+    // the output variables.
+    if (::glGetError() == GL_NO_ERROR && aMajor != 0 && aMinor != 0)
+    {
+      theGlVerMajor = aMajor;
+      theGlVerMinor = aMinor;
+      return;
+    }
+    for (GLenum anErr = ::glGetError(), aPrevErr = GL_NO_ERROR;; aPrevErr = anErr, anErr = ::glGetError())
+    {
+      if (anErr == GL_NO_ERROR
+       || anErr == aPrevErr)
+      {
+        break;
+      }
+    }
+  }
+
   // Read version string.
   // Notice that only first two numbers split by point '2.1 XXXXX' are significant.
   // Following trash (after space) is vendor-specific.
@@ -1053,6 +1204,20 @@ void OpenGl_Context::ReadGlVersion (Standard_Integer& theGlVerMajor,
   // read numbers
   theGlVerMajor = atoi (aMajorStr);
   theGlVerMinor = atoi (aMinorStr);
+#if defined(__EMSCRIPTEN__)
+  if (theGlVerMajor >= 3)
+  {
+    if (!toCheckVer3
+     || ::strstr (aVerStr, "WebGL 1.0") != NULL)
+    {
+      Message::SendWarning() << "Warning! OpenGL context reports version " << theGlVerMajor << "." << theGlVerMinor
+                             << " but WebGL 2.0 was unavailable\n"
+                             << "Fallback to OpenGL ES 2.0 will be used instead of reported version";
+      theGlVerMajor = 2;
+      theGlVerMinor = 0;
+    }
+  }
+#endif
 
   if (theGlVerMajor <= 0)
   {
@@ -1174,24 +1339,42 @@ Standard_Boolean OpenGl_Context::IncludeMessage (const unsigned int theSource,
 // function : checkWrongVersion
 // purpose  :
 // ======================================================================
-void OpenGl_Context::checkWrongVersion (const Standard_Integer theGlVerMajor,
-                                        const Standard_Integer theGlVerMinor)
+void OpenGl_Context::checkWrongVersion (Standard_Integer theGlVerMajor, Standard_Integer theGlVerMinor,
+                                        const char* theLastFailedProc)
 {
   if (!IsGlGreaterEqual (theGlVerMajor, theGlVerMinor))
   {
     return;
   }
 
-  TCollection_ExtendedString aMsg = TCollection_ExtendedString()
-    + "Error! OpenGL context reports version "
-    + myGlVerMajor  + "." + myGlVerMinor
-    + " but does not export required functions for "
-    + theGlVerMajor + "." + theGlVerMinor;
-  PushMessage (GL_DEBUG_SOURCE_APPLICATION,
-               GL_DEBUG_TYPE_ERROR,
-               0,
-               GL_DEBUG_SEVERITY_HIGH,
-               aMsg);
+  PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
+               TCollection_AsciiString()
+               + "Error! OpenGL context reports version "
+               + myGlVerMajor  + "." + myGlVerMinor
+               + " but does not export required functions for " + theGlVerMajor + "." + theGlVerMinor
+               + " (" + (theLastFailedProc != NULL ? theLastFailedProc : "") + ")\n"
+               + "Please report this issue to OpenGL driver vendor '" + myVendor + "'");
+
+  // lower internal version
+  if (theGlVerMinor > 0)
+  {
+    myGlVerMajor = theGlVerMajor;
+    myGlVerMinor = theGlVerMinor - 1;
+    return;
+  }
+#if defined(GL_ES_VERSION_2_0)
+  switch (theGlVerMajor)
+  {
+    case 3: myGlVerMajor = 2; myGlVerMinor = 0; return;
+  }
+#else
+  switch (theGlVerMajor)
+  {
+    case 2: myGlVerMajor = 1; myGlVerMinor = 5; return;
+    case 3: myGlVerMajor = 2; myGlVerMinor = 1; return;
+    case 4: myGlVerMajor = 3; myGlVerMinor = 3; return;
+  }
+#endif
 }
 
 // =======================================================================
@@ -1206,8 +1389,49 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
   myMaxMsaaSamples = 0;
   myMaxDrawBuffers = 1;
   myMaxColorAttachments = 1;
+  myDefaultVao = 0;
   ReadGlVersion (myGlVerMajor, myGlVerMinor);
   myVendor = (const char* )::glGetString (GL_VENDOR);
+  myVendor.LowerCase();
+  mySupportedFormats->Clear();
+
+  if (caps->contextMajorVersionUpper != -1)
+  {
+    // synthetically restrict OpenGL version for testing
+    Standard_Integer aCtxVer[2] = { myGlVerMajor, myGlVerMinor };
+    bool isLowered = false;
+    if (myGlVerMajor > caps->contextMajorVersionUpper)
+    {
+      isLowered = true;
+      myGlVerMajor = caps->contextMajorVersionUpper;
+    #if defined(GL_ES_VERSION_2_0)
+      switch (myGlVerMajor)
+      {
+        case 2: myGlVerMinor = 0; break;
+      }
+    #else
+      switch (myGlVerMajor)
+      {
+        case 1: myGlVerMinor = 5; break;
+        case 2: myGlVerMinor = 1; break;
+        case 3: myGlVerMinor = 3; break;
+      }
+    #endif
+    }
+    if (caps->contextMinorVersionUpper != -1
+     && myGlVerMinor > caps->contextMinorVersionUpper)
+    {
+      isLowered = true;
+      myGlVerMinor = caps->contextMinorVersionUpper;
+    }
+    if (isLowered)
+    {
+      PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
+                   TCollection_AsciiString ("OpenGL version ") + aCtxVer[0] + "." + aCtxVer[1]
+                   + " has been lowered to " + myGlVerMajor + "." + myGlVerMinor);
+    }
+  }
+
   if (!caps->ffpEnable
    && !IsGlGreaterEqual (2, 0))
   {
@@ -1228,7 +1452,7 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
   const bool isCoreProfile = false;
 #else
 
-  if (myVendor.Search ("NVIDIA") != -1)
+  if (myVendor.Search ("nvidia") != -1)
   {
     // Buffer detailed info: Buffer object 1 (bound to GL_ARRAY_BUFFER_ARB, usage hint is GL_STATIC_DRAW)
     // will use VIDEO memory as the source for buffer object operations.
@@ -1255,1247 +1479,150 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
   }
 #endif
 
-  core11     = NULL;
-  if (!isCoreProfile)
-  {
-    core11 = (OpenGl_GlCore11* )(&(*myFuncs));
-  }
-  core11fwd  = (OpenGl_GlCore11Fwd* )(&(*myFuncs));
-  core15     = NULL;
-  core15fwd  = NULL;
-  core20     = NULL;
-  core20fwd  = NULL;
-  core32     = NULL;
-  core32back = NULL;
-  core33     = NULL;
-  core33back = NULL;
-  core41     = NULL;
-  core41back = NULL;
-  core42     = NULL;
-  core42back = NULL;
-  core43     = NULL;
-  core43back = NULL;
-  core44     = NULL;
-  core44back = NULL;
-  arbTBO     = NULL;
-  arbTboRGB32 = Standard_False;
-  arbIns     = NULL;
-  arbDbg     = NULL;
-  arbFBO     = NULL;
-  arbFBOBlit = NULL;
-  extGS      = NULL;
-  myDefaultVao = 0;
+  myFuncs->load (*this, isCoreProfile);
 
-  //! Make record shorter to retrieve function pointer using variable with same name
-  #define FindProcShort(theFunc) FindProc(#theFunc, myFuncs->theFunc)
+  // setup shader generator
+  myShaderManager->SetGapiVersion (myGlVerMajor, myGlVerMinor);
+  myShaderManager->SetEmulateDepthClamp (!arbDepthClamp);
 
+  bool toReverseDFdxSign = false;
+#if defined(GL_ES_VERSION_2_0)
+  // workaround Adreno driver bug computing reversed normal using dFdx/dFdy
+  toReverseDFdxSign = myVendor.Search("qualcomm") != -1;
+#endif
+  myShaderManager->SetFlatShading (hasFlatShading != OpenGl_FeatureNotAvailable, toReverseDFdxSign);
 #if defined(GL_ES_VERSION_2_0)
+  myShaderManager->SetUseRedAlpha (false);
+#else
+  myShaderManager->SetUseRedAlpha (core11ffp == NULL);
+#endif
+  #define checkGlslExtensionShort(theName) myShaderManager->EnableGlslExtension (Graphic3d_GlslExtension_ ## theName, CheckExtension (#theName))
+#if defined(GL_ES_VERSION_2_0)
+  checkGlslExtensionShort(GL_OES_standard_derivatives);
+  checkGlslExtensionShort(GL_EXT_shader_texture_lod);
+  checkGlslExtensionShort(GL_EXT_frag_depth);
+#else
+  checkGlslExtensionShort(GL_EXT_gpu_shader4);
+#endif
 
-  hasTexRGBA8 = IsGlGreaterEqual (3, 0)
-             || CheckExtension ("GL_OES_rgb8_rgba8");
-  // NPOT textures has limited support within OpenGL ES 2.0
-  // which are relaxed by OpenGL ES 3.0 or some extensions
-  //arbNPTW     = IsGlGreaterEqual (3, 0)
-  //           || CheckExtension ("GL_OES_texture_npot")
-  //           || CheckExtension ("GL_NV_texture_npot_2D_mipmap");
-  arbNPTW     = Standard_True;
-  arbTexRG    = IsGlGreaterEqual (3, 0)
-             || CheckExtension ("GL_EXT_texture_rg");
-  extBgra     = CheckExtension ("GL_EXT_texture_format_BGRA8888");
-  extAnis = CheckExtension ("GL_EXT_texture_filter_anisotropic");
-  extPDS  = IsGlGreaterEqual (3, 0)
-         || CheckExtension ("GL_OES_packed_depth_stencil");
-
-  core11fwd = (OpenGl_GlCore11Fwd* )(&(*myFuncs));
-  if (IsGlGreaterEqual (2, 0))
+  // initialize debug context extension
+  if (arbDbg != NULL
+   && caps->contextDebug)
   {
-    // enable compatible functions
-    core20    = (OpenGl_GlCore20*    )(&(*myFuncs));
-    core20fwd = (OpenGl_GlCore20Fwd* )(&(*myFuncs));
-    core15fwd = (OpenGl_GlCore15Fwd* )(&(*myFuncs));
-    arbFBO    = (OpenGl_ArbFBO*      )(&(*myFuncs));
+    // setup default callback
+    myIsGlDebugCtx = Standard_True;
+    arbDbg->glDebugMessageCallback (debugCallbackWrap, this);
+  #if defined(GL_ES_VERSION_2_0)
+    ::glEnable (GL_DEBUG_OUTPUT);
+  #else
+    if (core43 != NULL)
+    {
+      ::glEnable (GL_DEBUG_OUTPUT);
+    }
+  #endif
+    if (caps->contextSyncDebug)
+    {
+      // note that some broken implementations (e.g. simulators) might generate error message on this call
+      ::glEnable (GL_DEBUG_OUTPUT_SYNCHRONOUS);
+    }
   }
-  if (IsGlGreaterEqual (3, 0)
-   && FindProcShort (glBlitFramebuffer))
+
+  if (hasDrawBuffers)
   {
-    arbFBOBlit = (OpenGl_ArbFBOBlit* )(&(*myFuncs));
+    glGetIntegerv (GL_MAX_DRAW_BUFFERS,      &myMaxDrawBuffers);
+    glGetIntegerv (GL_MAX_COLOR_ATTACHMENTS, &myMaxColorAttachments);
+    if (myDrawBuffers.Length() < myMaxDrawBuffers)
+    {
+      myDrawBuffers.Resize (0, myMaxDrawBuffers - 1, false);
+    }
   }
-  if (IsGlGreaterEqual (3, 0)
-   && FindProcShort (glGenSamplers)
-   && FindProcShort (glDeleteSamplers)
-   && FindProcShort (glIsSampler)
-   && FindProcShort (glBindSampler)
-   && FindProcShort (glSamplerParameteri)
-   && FindProcShort (glSamplerParameteriv)
-   && FindProcShort (glSamplerParameterf)
-   && FindProcShort (glSamplerParameterfv)
-   && FindProcShort (glGetSamplerParameteriv)
-   && FindProcShort (glGetSamplerParameterfv))
-   //&& FindProcShort (glSamplerParameterIiv) // only on Desktop or with extensions GL_OES_texture_border_clamp/GL_EXT_texture_border_clamp
-   //&& FindProcShort (glSamplerParameterIuiv)
-   //&& FindProcShort (glGetSamplerParameterIiv)
-   //&& FindProcShort (glGetSamplerParameterIuiv))
-  {
-    arbSamplerObject = (OpenGl_ArbSamplerObject* )(&(*myFuncs));
-  }
-  extFragDepth = !IsGlGreaterEqual(3, 0)
-               && CheckExtension ("GL_EXT_frag_depth");
-  if (IsGlGreaterEqual (3, 1)
-   && FindProc ("glTexStorage2DMultisample", myFuncs->glTexStorage2DMultisample))
+
+  glGetIntegerv (GL_MAX_TEXTURE_SIZE, &myMaxTexDim);
+#if !defined(GL_ES_VERSION_2_0)
+  if (IsGlGreaterEqual (1, 3) && core11ffp != NULL)
   {
-    // MSAA RenderBuffers have been defined in OpenGL ES 3.0,
-    // but MSAA Textures - only in OpenGL ES 3.1+
-    ::glGetIntegerv (GL_MAX_SAMPLES, &myMaxMsaaSamples);
+    // this is a maximum of texture units for FFP functionality,
+    // usually smaller than combined texture units available for GLSL
+    glGetIntegerv (GL_MAX_TEXTURE_UNITS, &myMaxTexUnitsFFP);
+    myMaxTexCombined = myMaxTexUnitsFFP;
   }
-
-  hasUintIndex = IsGlGreaterEqual (3, 0)
-              || CheckExtension ("GL_OES_element_index_uint");
-  hasHighp     = CheckExtension ("GL_OES_fragment_precision_high");
-  GLint aRange[2] = {0, 0};
-  GLint aPrec     = 0;
-  ::glGetShaderPrecisionFormat (GL_FRAGMENT_SHADER, GL_HIGH_FLOAT, aRange, &aPrec);
-  if (aPrec != 0)
+#endif
+  if (IsGlGreaterEqual (2, 0))
   {
-    hasHighp = Standard_True;
+    glGetIntegerv (GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &myMaxTexCombined);
   }
+  mySpriteTexUnit = myMaxTexCombined >= 2
+                  ? Graphic3d_TextureUnit_PointSprite
+                  : Graphic3d_TextureUnit_0;
 
-  arbTexFloat = IsGlGreaterEqual (3, 0)
-             && FindProc ("glTexImage3D", myFuncs->glTexImage3D);
-
-  const Standard_Boolean hasTexBuffer32  = IsGlGreaterEqual (3, 2) && FindProc ("glTexBuffer", myFuncs->glTexBuffer);
-  const Standard_Boolean hasExtTexBuffer = CheckExtension ("GL_EXT_texture_buffer") && FindProc ("glTexBufferEXT", myFuncs->glTexBuffer);
-
-  if (hasTexBuffer32 || hasExtTexBuffer)
+  GLint aMaxVPortSize[2] = {0, 0};
+  glGetIntegerv (GL_MAX_VIEWPORT_DIMS, aMaxVPortSize);
+  myMaxDumpSizeX = Min (aMaxVPortSize[0], myMaxTexDim);
+  myMaxDumpSizeY = Min (aMaxVPortSize[1], myMaxTexDim);
+  if (myVendor == "intel")
   {
-    arbTBO = reinterpret_cast<OpenGl_ArbTBO*> (myFuncs.get());
+    // Intel drivers have known bug with empty dump for images with width>=5462
+    myMaxDumpSizeX = Min (myMaxDumpSizeX, 4096);
   }
 
-  // initialize debug context extension
-  if (CheckExtension ("GL_KHR_debug"))
+  if (extAnis)
   {
-    // this functionality become a part of OpenGL ES 3.2
-    arbDbg = NULL;
-    // According to GL_KHR_debug spec, all functions should have KHR suffix.
-    // However, some implementations can export these functions without suffix.
-    if (FindProc ("glDebugMessageControlKHR",  myFuncs->glDebugMessageControl)
-     && FindProc ("glDebugMessageInsertKHR",   myFuncs->glDebugMessageInsert)
-     && FindProc ("glDebugMessageCallbackKHR", myFuncs->glDebugMessageCallback)
-     && FindProc ("glGetDebugMessageLogKHR",   myFuncs->glGetDebugMessageLog))
-    {
-      arbDbg = (OpenGl_ArbDbg* )(&(*myFuncs));
-    }
+    glGetIntegerv (GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &myAnisoMax);
+  }
 
-    if (arbDbg != NULL
-     && caps->contextDebug)
-    {
-      // setup default callback
-      myIsGlDebugCtx = Standard_True;
-      arbDbg->glDebugMessageCallback (debugCallbackWrap, this);
-      ::glEnable (GL_DEBUG_OUTPUT);
-      if (caps->contextSyncDebug)
-      {
-        // note that some broken implementations (e.g. simulators) might generate error message on this call
-        ::glEnable (GL_DEBUG_OUTPUT_SYNCHRONOUS);
-      }
-    }
-  }
+  myClippingState.Init();
 
-  extDrawBuffers = CheckExtension ("GL_EXT_draw_buffers") && FindProc ("glDrawBuffersEXT", myFuncs->glDrawBuffers);
-  arbDrawBuffers = CheckExtension ("GL_ARB_draw_buffers") && FindProc ("glDrawBuffersARB", myFuncs->glDrawBuffers);
-
-  if (IsGlGreaterEqual (3, 0) && FindProc ("glDrawBuffers", myFuncs->glDrawBuffers))
-  {
-    hasDrawBuffers = OpenGl_FeatureInCore;
-  }
-  else if (extDrawBuffers || arbDrawBuffers)
+#if defined(GL_ES_VERSION_2_0)
+  if (IsGlGreaterEqual (3, 1)
+   && myFuncs->glTexStorage2DMultisample != NULL)
   {
-    hasDrawBuffers = OpenGl_FeatureInExtensions;
+    // MSAA RenderBuffers have been defined in OpenGL ES 3.0,
+    // but MSAA Textures - only in OpenGL ES 3.1+
+    ::glGetIntegerv (GL_MAX_SAMPLES, &myMaxMsaaSamples);
   }
-
-  hasFloatBuffer     = IsGlGreaterEqual (3, 2) ? OpenGl_FeatureInCore :
-                       CheckExtension ("GL_EXT_color_buffer_float") ? OpenGl_FeatureInExtensions 
-                                                                    : OpenGl_FeatureNotAvailable;
-  hasHalfFloatBuffer = IsGlGreaterEqual (3, 2) ? OpenGl_FeatureInCore :
-                       CheckExtension ("GL_EXT_color_buffer_half_float") ? OpenGl_FeatureInExtensions 
-                                                                         : OpenGl_FeatureNotAvailable;
-
-  oesSampleVariables = CheckExtension ("GL_OES_sample_variables");
-  oesStdDerivatives  = CheckExtension ("GL_OES_standard_derivatives");
-  hasSampleVariables = IsGlGreaterEqual (3, 2) ? OpenGl_FeatureInCore :
-                       oesSampleVariables ? OpenGl_FeatureInExtensions
-                                          : OpenGl_FeatureNotAvailable;
 #else
-
-  myTexClamp = IsGlGreaterEqual (1, 2) ? GL_CLAMP_TO_EDGE : GL_CLAMP;
-
-  hasTexRGBA8 = Standard_True;
-  arbDrawBuffers   = CheckExtension ("GL_ARB_draw_buffers");
-  arbNPTW          = CheckExtension ("GL_ARB_texture_non_power_of_two");
-  arbTexFloat      = IsGlGreaterEqual (3, 0)
-                  || CheckExtension ("GL_ARB_texture_float");
-  arbSampleShading = CheckExtension ("GL_ARB_sample_shading");
-  extBgra          = CheckExtension ("GL_EXT_bgra");
-  extAnis          = CheckExtension ("GL_EXT_texture_filter_anisotropic");
-  extPDS           = CheckExtension ("GL_EXT_packed_depth_stencil");
-  atiMem           = CheckExtension ("GL_ATI_meminfo");
-  nvxMem           = CheckExtension ("GL_NVX_gpu_memory_info");
-
-  hasDrawBuffers = IsGlGreaterEqual (2, 0) ? OpenGl_FeatureInCore :
-                   arbDrawBuffers ? OpenGl_FeatureInExtensions 
-                                  : OpenGl_FeatureNotAvailable;
-
-  hasFloatBuffer = hasHalfFloatBuffer =  IsGlGreaterEqual (3, 0) ? OpenGl_FeatureInCore :
-                                         CheckExtension ("GL_ARB_color_buffer_float") ? OpenGl_FeatureInExtensions
-                                                                                      : OpenGl_FeatureNotAvailable;
-
-  hasSampleVariables = IsGlGreaterEqual (4, 0) ? OpenGl_FeatureInCore :
-                        arbSampleShading ? OpenGl_FeatureInExtensions
-                                         : OpenGl_FeatureNotAvailable;
-
-  GLint aStereo = GL_FALSE;
-  glGetIntegerv (GL_STEREO, &aStereo);
-  myIsStereoBuffers = aStereo == 1;
-
-  // get number of maximum clipping planes
-  glGetIntegerv (GL_MAX_CLIP_PLANES,  &myMaxClipPlanes);
-#endif
-
-  if (hasDrawBuffers)
-  {
-    glGetIntegerv (GL_MAX_DRAW_BUFFERS,      &myMaxDrawBuffers);
-    glGetIntegerv (GL_MAX_COLOR_ATTACHMENTS, &myMaxColorAttachments);
-  }
-
-  glGetIntegerv (GL_MAX_TEXTURE_SIZE, &myMaxTexDim);
-  if (IsGlGreaterEqual (1, 5))
-  {
-    glGetIntegerv (GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &myMaxTexCombined);
-  }
-
-  if (extAnis)
+  if (core30 != NULL)
   {
-    glGetIntegerv (GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &myAnisoMax);
-  }
-
-  myClippingState.Init (myMaxClipPlanes);
-
-#if !defined(GL_ES_VERSION_2_0)
-
-  bool has12 = false;
-  bool has13 = false;
-  bool has14 = false;
-  bool has15 = false;
-  bool has20 = false;
-  bool has21 = false;
-  bool has30 = false;
-  bool has31 = false;
-  bool has32 = false;
-  bool has33 = false;
-  bool has40 = false;
-  bool has41 = false;
-  bool has42 = false;
-  bool has43 = false;
-  bool has44 = false;
-
-  // retrieve platform-dependent extensions
-#if defined(HAVE_EGL)
-  //
-#elif defined(_WIN32)
-  if (FindProcShort (wglGetExtensionsStringARB))
-  {
-    const char* aWglExts = myFuncs->wglGetExtensionsStringARB (wglGetCurrentDC());
-    if (CheckExtension (aWglExts, "WGL_EXT_swap_control"))
+    // MSAA RenderBuffers have been defined in OpenGL 3.0,
+    // but MSAA Textures - only in OpenGL 3.2+
+    if (core32 != NULL)
     {
-      FindProcShort (wglSwapIntervalEXT);
+      ::glGetIntegerv (GL_MAX_SAMPLES, &myMaxMsaaSamples);
     }
-    if (CheckExtension (aWglExts, "WGL_ARB_pixel_format"))
+    else if (CheckExtension ("GL_ARB_texture_multisample")
+          && myFuncs->glTexImage2DMultisample != NULL)
     {
-      FindProcShort (wglChoosePixelFormatARB);
-    }
-    if (CheckExtension (aWglExts, "WGL_ARB_create_context_profile"))
-    {
-      FindProcShort (wglCreateContextAttribsARB);
-    }
-    if (CheckExtension (aWglExts, "WGL_NV_DX_interop"))
-    {
-      FindProcShort (wglDXSetResourceShareHandleNV);
-      FindProcShort (wglDXOpenDeviceNV);
-      FindProcShort (wglDXCloseDeviceNV);
-      FindProcShort (wglDXRegisterObjectNV);
-      FindProcShort (wglDXUnregisterObjectNV);
-      FindProcShort (wglDXObjectAccessNV);
-      FindProcShort (wglDXLockObjectsNV);
-      FindProcShort (wglDXUnlockObjectsNV);
-    }
-    if (CheckExtension (aWglExts, "WGL_AMD_gpu_association"))
-    {
-      FindProcShort (wglGetGPUIDsAMD);
-      FindProcShort (wglGetGPUInfoAMD);
-      FindProcShort (wglGetContextGPUIDAMD);
+      GLint aNbColorSamples = 0, aNbDepthSamples = 0;
+      ::glGetIntegerv (GL_MAX_COLOR_TEXTURE_SAMPLES, &aNbColorSamples);
+      ::glGetIntegerv (GL_MAX_DEPTH_TEXTURE_SAMPLES, &aNbDepthSamples);
+      myMaxMsaaSamples = Min (aNbColorSamples, aNbDepthSamples);
     }
   }
-#elif defined(__APPLE__)
-    //
-#else
-    const char* aGlxExts = ::glXQueryExtensionsString ((Display* )myDisplay, DefaultScreen ((Display* )myDisplay));
-    if (CheckExtension (aGlxExts, "GLX_EXT_swap_control"))
-    {
-      FindProcShort (glXSwapIntervalEXT);
-    }
-    if (CheckExtension (aGlxExts, "GLX_SGI_swap_control"))
-    {
-      FindProcShort (glXSwapIntervalSGI);
-    }
-    if (CheckExtension (aGlxExts, "GLX_MESA_query_renderer"))
-    {
-      FindProcShort (glXQueryRendererIntegerMESA);
-      FindProcShort (glXQueryCurrentRendererIntegerMESA);
-      FindProcShort (glXQueryRendererStringMESA);
-      FindProcShort (glXQueryCurrentRendererStringMESA);
-    }
-    //extSwapTear = CheckExtension (aGlxExts, "GLX_EXT_swap_control_tear");
 #endif
 
-  // load OpenGL 1.2 new functions
-  has12 = IsGlGreaterEqual (1, 2)
-       && FindProcShort (glBlendColor)
-       && FindProcShort (glBlendEquation)
-       && FindProcShort (glDrawRangeElements)
-       && FindProcShort (glTexImage3D)
-       && FindProcShort (glTexSubImage3D)
-       && FindProcShort (glCopyTexSubImage3D);
-
-  // load OpenGL 1.3 new functions
-  has13 = IsGlGreaterEqual (1, 3)
-       && FindProcShort (glActiveTexture)
-       && FindProcShort (glSampleCoverage)
-       && FindProcShort (glCompressedTexImage3D)
-       && FindProcShort (glCompressedTexImage2D)
-       && FindProcShort (glCompressedTexImage1D)
-       && FindProcShort (glCompressedTexSubImage3D)
-       && FindProcShort (glCompressedTexSubImage2D)
-       && FindProcShort (glCompressedTexSubImage1D)
-       && FindProcShort (glGetCompressedTexImage);
-
-  if (!isCoreProfile)
-  {
-    has13 = has13
-       && FindProcShort (glClientActiveTexture)
-       && FindProcShort (glMultiTexCoord1d)
-       && FindProcShort (glMultiTexCoord1dv)
-       && FindProcShort (glMultiTexCoord1f)
-       && FindProcShort (glMultiTexCoord1fv)
-       && FindProcShort (glMultiTexCoord1i)
-       && FindProcShort (glMultiTexCoord1iv)
-       && FindProcShort (glMultiTexCoord1s)
-       && FindProcShort (glMultiTexCoord1sv)
-       && FindProcShort (glMultiTexCoord2d)
-       && FindProcShort (glMultiTexCoord2dv)
-       && FindProcShort (glMultiTexCoord2f)
-       && FindProcShort (glMultiTexCoord2fv)
-       && FindProcShort (glMultiTexCoord2i)
-       && FindProcShort (glMultiTexCoord2iv)
-       && FindProcShort (glMultiTexCoord2s)
-       && FindProcShort (glMultiTexCoord2sv)
-       && FindProcShort (glMultiTexCoord3d)
-       && FindProcShort (glMultiTexCoord3dv)
-       && FindProcShort (glMultiTexCoord3f)
-       && FindProcShort (glMultiTexCoord3fv)
-       && FindProcShort (glMultiTexCoord3i)
-       && FindProcShort (glMultiTexCoord3iv)
-       && FindProcShort (glMultiTexCoord3s)
-       && FindProcShort (glMultiTexCoord3sv)
-       && FindProcShort (glMultiTexCoord4d)
-       && FindProcShort (glMultiTexCoord4dv)
-       && FindProcShort (glMultiTexCoord4f)
-       && FindProcShort (glMultiTexCoord4fv)
-       && FindProcShort (glMultiTexCoord4i)
-       && FindProcShort (glMultiTexCoord4iv)
-       && FindProcShort (glMultiTexCoord4s)
-       && FindProcShort (glMultiTexCoord4sv)
-       && FindProcShort (glLoadTransposeMatrixf)
-       && FindProcShort (glLoadTransposeMatrixd)
-       && FindProcShort (glMultTransposeMatrixf)
-       && FindProcShort (glMultTransposeMatrixd);
-  }
-
-  // load OpenGL 1.4 new functions
-  has14 = IsGlGreaterEqual (1, 4)
-       && FindProcShort (glBlendFuncSeparate)
-       && FindProcShort (glMultiDrawArrays)
-       && FindProcShort (glMultiDrawElements)
-       && FindProcShort (glPointParameterf)
-       && FindProcShort (glPointParameterfv)
-       && FindProcShort (glPointParameteri)
-       && FindProcShort (glPointParameteriv);
-
-  // load OpenGL 1.5 new functions
-  has15 = IsGlGreaterEqual (1, 5)
-       && FindProcShort (glGenQueries)
-       && FindProcShort (glDeleteQueries)
-       && FindProcShort (glIsQuery)
-       && FindProcShort (glBeginQuery)
-       && FindProcShort (glEndQuery)
-       && FindProcShort (glGetQueryiv)
-       && FindProcShort (glGetQueryObjectiv)
-       && FindProcShort (glGetQueryObjectuiv)
-       && FindProcShort (glBindBuffer)
-       && FindProcShort (glDeleteBuffers)
-       && FindProcShort (glGenBuffers)
-       && FindProcShort (glIsBuffer)
-       && FindProcShort (glBufferData)
-       && FindProcShort (glBufferSubData)
-       && FindProcShort (glGetBufferSubData)
-       && FindProcShort (glMapBuffer)
-       && FindProcShort (glUnmapBuffer)
-       && FindProcShort (glGetBufferParameteriv)
-       && FindProcShort (glGetBufferPointerv);
-
-  // load OpenGL 2.0 new functions
-  has20 = IsGlGreaterEqual (2, 0)
-       && FindProcShort (glBlendEquationSeparate)
-       && FindProcShort (glDrawBuffers)
-       && FindProcShort (glStencilOpSeparate)
-       && FindProcShort (glStencilFuncSeparate)
-       && FindProcShort (glStencilMaskSeparate)
-       && FindProcShort (glAttachShader)
-       && FindProcShort (glBindAttribLocation)
-       && FindProcShort (glCompileShader)
-       && FindProcShort (glCreateProgram)
-       && FindProcShort (glCreateShader)
-       && FindProcShort (glDeleteProgram)
-       && FindProcShort (glDeleteShader)
-       && FindProcShort (glDetachShader)
-       && FindProcShort (glDisableVertexAttribArray)
-       && FindProcShort (glEnableVertexAttribArray)
-       && FindProcShort (glGetActiveAttrib)
-       && FindProcShort (glGetActiveUniform)
-       && FindProcShort (glGetAttachedShaders)
-       && FindProcShort (glGetAttribLocation)
-       && FindProcShort (glGetProgramiv)
-       && FindProcShort (glGetProgramInfoLog)
-       && FindProcShort (glGetShaderiv)
-       && FindProcShort (glGetShaderInfoLog)
-       && FindProcShort (glGetShaderSource)
-       && FindProcShort (glGetUniformLocation)
-       && FindProcShort (glGetUniformfv)
-       && FindProcShort (glGetUniformiv)
-       && FindProcShort (glGetVertexAttribdv)
-       && FindProcShort (glGetVertexAttribfv)
-       && FindProcShort (glGetVertexAttribiv)
-       && FindProcShort (glGetVertexAttribPointerv)
-       && FindProcShort (glIsProgram)
-       && FindProcShort (glIsShader)
-       && FindProcShort (glLinkProgram)
-       && FindProcShort (glShaderSource)
-       && FindProcShort (glUseProgram)
-       && FindProcShort (glUniform1f)
-       && FindProcShort (glUniform2f)
-       && FindProcShort (glUniform3f)
-       && FindProcShort (glUniform4f)
-       && FindProcShort (glUniform1i)
-       && FindProcShort (glUniform2i)
-       && FindProcShort (glUniform3i)
-       && FindProcShort (glUniform4i)
-       && FindProcShort (glUniform1fv)
-       && FindProcShort (glUniform2fv)
-       && FindProcShort (glUniform3fv)
-       && FindProcShort (glUniform4fv)
-       && FindProcShort (glUniform1iv)
-       && FindProcShort (glUniform2iv)
-       && FindProcShort (glUniform3iv)
-       && FindProcShort (glUniform4iv)
-       && FindProcShort (glUniformMatrix2fv)
-       && FindProcShort (glUniformMatrix3fv)
-       && FindProcShort (glUniformMatrix4fv)
-       && FindProcShort (glValidateProgram)
-       && FindProcShort (glVertexAttrib1d)
-       && FindProcShort (glVertexAttrib1dv)
-       && FindProcShort (glVertexAttrib1f)
-       && FindProcShort (glVertexAttrib1fv)
-       && FindProcShort (glVertexAttrib1s)
-       && FindProcShort (glVertexAttrib1sv)
-       && FindProcShort (glVertexAttrib2d)
-       && FindProcShort (glVertexAttrib2dv)
-       && FindProcShort (glVertexAttrib2f)
-       && FindProcShort (glVertexAttrib2fv)
-       && FindProcShort (glVertexAttrib2s)
-       && FindProcShort (glVertexAttrib2sv)
-       && FindProcShort (glVertexAttrib3d)
-       && FindProcShort (glVertexAttrib3dv)
-       && FindProcShort (glVertexAttrib3f)
-       && FindProcShort (glVertexAttrib3fv)
-       && FindProcShort (glVertexAttrib3s)
-       && FindProcShort (glVertexAttrib3sv)
-       && FindProcShort (glVertexAttrib4Nbv)
-       && FindProcShort (glVertexAttrib4Niv)
-       && FindProcShort (glVertexAttrib4Nsv)
-       && FindProcShort (glVertexAttrib4Nub)
-       && FindProcShort (glVertexAttrib4Nubv)
-       && FindProcShort (glVertexAttrib4Nuiv)
-       && FindProcShort (glVertexAttrib4Nusv)
-       && FindProcShort (glVertexAttrib4bv)
-       && FindProcShort (glVertexAttrib4d)
-       && FindProcShort (glVertexAttrib4dv)
-       && FindProcShort (glVertexAttrib4f)
-       && FindProcShort (glVertexAttrib4fv)
-       && FindProcShort (glVertexAttrib4iv)
-       && FindProcShort (glVertexAttrib4s)
-       && FindProcShort (glVertexAttrib4sv)
-       && FindProcShort (glVertexAttrib4ubv)
-       && FindProcShort (glVertexAttrib4uiv)
-       && FindProcShort (glVertexAttrib4usv)
-       && FindProcShort (glVertexAttribPointer);
-
-  // load OpenGL 2.1 new functions
-  has21 = IsGlGreaterEqual (2, 1)
-       && FindProcShort (glUniformMatrix2x3fv)
-       && FindProcShort (glUniformMatrix3x2fv)
-       && FindProcShort (glUniformMatrix2x4fv)
-       && FindProcShort (glUniformMatrix4x2fv)
-       && FindProcShort (glUniformMatrix3x4fv)
-       && FindProcShort (glUniformMatrix4x3fv);
-
-  // load GL_ARB_framebuffer_object (added to OpenGL 3.0 core)
-  const bool hasFBO = (IsGlGreaterEqual (3, 0) || CheckExtension ("GL_ARB_framebuffer_object"))
-       && FindProcShort (glIsRenderbuffer)
-       && FindProcShort (glBindRenderbuffer)
-       && FindProcShort (glDeleteRenderbuffers)
-       && FindProcShort (glGenRenderbuffers)
-       && FindProcShort (glRenderbufferStorage)
-       && FindProcShort (glGetRenderbufferParameteriv)
-       && FindProcShort (glIsFramebuffer)
-       && FindProcShort (glBindFramebuffer)
-       && FindProcShort (glDeleteFramebuffers)
-       && FindProcShort (glGenFramebuffers)
-       && FindProcShort (glCheckFramebufferStatus)
-       && FindProcShort (glFramebufferTexture1D)
-       && FindProcShort (glFramebufferTexture2D)
-       && FindProcShort (glFramebufferTexture3D)
-       && FindProcShort (glFramebufferRenderbuffer)
-       && FindProcShort (glGetFramebufferAttachmentParameteriv)
-       && FindProcShort (glGenerateMipmap)
-       && FindProcShort (glBlitFramebuffer)
-       && FindProcShort (glRenderbufferStorageMultisample)
-       && FindProcShort (glFramebufferTextureLayer);
-
-  // load GL_ARB_vertex_array_object (added to OpenGL 3.0 core)
-  const bool hasVAO = (IsGlGreaterEqual (3, 0) || CheckExtension ("GL_ARB_vertex_array_object"))
-       && FindProcShort (glBindVertexArray)
-       && FindProcShort (glDeleteVertexArrays)
-       && FindProcShort (glGenVertexArrays)
-       && FindProcShort (glIsVertexArray);
-
-  // load GL_ARB_map_buffer_range (added to OpenGL 3.0 core)
-  const bool hasMapBufferRange = (IsGlGreaterEqual (3, 0) || CheckExtension ("GL_ARB_map_buffer_range"))
-       && FindProcShort (glMapBufferRange)
-       && FindProcShort (glFlushMappedBufferRange);
-
-  // load OpenGL 3.0 new functions
-  has30 = IsGlGreaterEqual (3, 0)
-       && hasFBO
-       && hasVAO
-       && hasMapBufferRange
-       && FindProcShort (glColorMaski)
-       && FindProcShort (glGetBooleani_v)
-       && FindProcShort (glGetIntegeri_v)
-       && FindProcShort (glEnablei)
-       && FindProcShort (glDisablei)
-       && FindProcShort (glIsEnabledi)
-       && FindProcShort (glBeginTransformFeedback)
-       && FindProcShort (glEndTransformFeedback)
-       && FindProcShort (glBindBufferRange)
-       && FindProcShort (glBindBufferBase)
-       && FindProcShort (glTransformFeedbackVaryings)
-       && FindProcShort (glGetTransformFeedbackVarying)
-       && FindProcShort (glClampColor)
-       && FindProcShort (glBeginConditionalRender)
-       && FindProcShort (glEndConditionalRender)
-       && FindProcShort (glVertexAttribIPointer)
-       && FindProcShort (glGetVertexAttribIiv)
-       && FindProcShort (glGetVertexAttribIuiv)
-       && FindProcShort (glVertexAttribI1i)
-       && FindProcShort (glVertexAttribI2i)
-       && FindProcShort (glVertexAttribI3i)
-       && FindProcShort (glVertexAttribI4i)
-       && FindProcShort (glVertexAttribI1ui)
-       && FindProcShort (glVertexAttribI2ui)
-       && FindProcShort (glVertexAttribI3ui)
-       && FindProcShort (glVertexAttribI4ui)
-       && FindProcShort (glVertexAttribI1iv)
-       && FindProcShort (glVertexAttribI2iv)
-       && FindProcShort (glVertexAttribI3iv)
-       && FindProcShort (glVertexAttribI4iv)
-       && FindProcShort (glVertexAttribI1uiv)
-       && FindProcShort (glVertexAttribI2uiv)
-       && FindProcShort (glVertexAttribI3uiv)
-       && FindProcShort (glVertexAttribI4uiv)
-       && FindProcShort (glVertexAttribI4bv)
-       && FindProcShort (glVertexAttribI4sv)
-       && FindProcShort (glVertexAttribI4ubv)
-       && FindProcShort (glVertexAttribI4usv)
-       && FindProcShort (glGetUniformuiv)
-       && FindProcShort (glBindFragDataLocation)
-       && FindProcShort (glGetFragDataLocation)
-       && FindProcShort (glUniform1ui)
-       && FindProcShort (glUniform2ui)
-       && FindProcShort (glUniform3ui)
-       && FindProcShort (glUniform4ui)
-       && FindProcShort (glUniform1uiv)
-       && FindProcShort (glUniform2uiv)
-       && FindProcShort (glUniform3uiv)
-       && FindProcShort (glUniform4uiv)
-       && FindProcShort (glTexParameterIiv)
-       && FindProcShort (glTexParameterIuiv)
-       && FindProcShort (glGetTexParameterIiv)
-       && FindProcShort (glGetTexParameterIuiv)
-       && FindProcShort (glClearBufferiv)
-       && FindProcShort (glClearBufferuiv)
-       && FindProcShort (glClearBufferfv)
-       && FindProcShort (glClearBufferfi)
-       && FindProcShort (glGetStringi);
-
-  // load GL_ARB_uniform_buffer_object (added to OpenGL 3.1 core)
-  const bool hasUBO = (IsGlGreaterEqual (3, 1) || CheckExtension ("GL_ARB_uniform_buffer_object"))
-       && FindProcShort (glGetUniformIndices)
-       && FindProcShort (glGetActiveUniformsiv)
-       && FindProcShort (glGetActiveUniformName)
-       && FindProcShort (glGetUniformBlockIndex)
-       && FindProcShort (glGetActiveUniformBlockiv)
-       && FindProcShort (glGetActiveUniformBlockName)
-       && FindProcShort (glUniformBlockBinding);
-
-  // load GL_ARB_copy_buffer (added to OpenGL 3.1 core)
-  const bool hasCopyBufSubData = (IsGlGreaterEqual (3, 1) || CheckExtension ("GL_ARB_copy_buffer"))
-       && FindProcShort (glCopyBufferSubData);
-
-  if (has30)
-  {
-    // NPOT textures are required by OpenGL 2.0 specifications
-    // but doesn't hardware accelerated by some ancient OpenGL 2.1 hardware (GeForce FX, RadeOn 9700 etc.)
-    arbNPTW  = Standard_True;
-    arbTexRG = Standard_True;
-  }
-
-  // load OpenGL 3.1 new functions
-  has31 = IsGlGreaterEqual (3, 1)
-       && hasUBO
-       && hasCopyBufSubData
-       && FindProcShort (glDrawArraysInstanced)
-       && FindProcShort (glDrawElementsInstanced)
-       && FindProcShort (glTexBuffer)
-       && FindProcShort (glPrimitiveRestartIndex);
-
-  // load GL_ARB_draw_elements_base_vertex (added to OpenGL 3.2 core)
-  const bool hasDrawElemsBaseVert = (IsGlGreaterEqual (3, 2) || CheckExtension ("GL_ARB_draw_elements_base_vertex"))
-       && FindProcShort (glDrawElementsBaseVertex)
-       && FindProcShort (glDrawRangeElementsBaseVertex)
-       && FindProcShort (glDrawElementsInstancedBaseVertex)
-       && FindProcShort (glMultiDrawElementsBaseVertex);
-
-  // load GL_ARB_provoking_vertex (added to OpenGL 3.2 core)
-  const bool hasProvokingVert = (IsGlGreaterEqual (3, 2) || CheckExtension ("GL_ARB_provoking_vertex"))
-       && FindProcShort (glProvokingVertex);
-
-  // load GL_ARB_sync (added to OpenGL 3.2 core)
-  const bool hasSync = (IsGlGreaterEqual (3, 2) || CheckExtension ("GL_ARB_sync"))
-       && FindProcShort (glFenceSync)
-       && FindProcShort (glIsSync)
-       && FindProcShort (glDeleteSync)
-       && FindProcShort (glClientWaitSync)
-       && FindProcShort (glWaitSync)
-       && FindProcShort (glGetInteger64v)
-       && FindProcShort (glGetSynciv);
-
-  // load GL_ARB_texture_multisample (added to OpenGL 3.2 core)
-  const bool hasTextureMultisample = (IsGlGreaterEqual (3, 2) || CheckExtension ("GL_ARB_texture_multisample"))
-       && FindProcShort (glTexImage2DMultisample)
-       && FindProcShort (glTexImage3DMultisample)
-       && FindProcShort (glGetMultisamplefv)
-       && FindProcShort (glSampleMaski);
-
-  // load OpenGL 3.2 new functions
-  has32 = IsGlGreaterEqual (3, 2)
-       && hasDrawElemsBaseVert
-       && hasProvokingVert
-       && hasSync
-       && hasTextureMultisample
-       && FindProcShort (glGetInteger64i_v)
-       && FindProcShort (glGetBufferParameteri64v)
-       && FindProcShort (glFramebufferTexture);
-
-  // load GL_ARB_blend_func_extended (added to OpenGL 3.3 core)
-  const bool hasBlendFuncExtended = (IsGlGreaterEqual (3, 3) || CheckExtension ("GL_ARB_blend_func_extended"))
-       && FindProcShort (glBindFragDataLocationIndexed)
-       && FindProcShort (glGetFragDataIndex);
-
-  // load GL_ARB_sampler_objects (added to OpenGL 3.3 core)
-  const bool hasSamplerObjects = (IsGlGreaterEqual (3, 3) || CheckExtension ("GL_ARB_sampler_objects"))
-       && FindProcShort (glGenSamplers)
-       && FindProcShort (glDeleteSamplers)
-       && FindProcShort (glIsSampler)
-       && FindProcShort (glBindSampler)
-       && FindProcShort (glSamplerParameteri)
-       && FindProcShort (glSamplerParameteriv)
-       && FindProcShort (glSamplerParameterf)
-       && FindProcShort (glSamplerParameterfv)
-       && FindProcShort (glSamplerParameterIiv)
-       && FindProcShort (glSamplerParameterIuiv)
-       && FindProcShort (glGetSamplerParameteriv)
-       && FindProcShort (glGetSamplerParameterIiv)
-       && FindProcShort (glGetSamplerParameterfv)
-       && FindProcShort (glGetSamplerParameterIuiv);
-  if (hasSamplerObjects)
-  {
-    arbSamplerObject = (OpenGl_ArbSamplerObject* )(&(*myFuncs));
-  }
-
-  // load GL_ARB_timer_query (added to OpenGL 3.3 core)
-  const bool hasTimerQuery = (IsGlGreaterEqual (3, 3) || CheckExtension ("GL_ARB_timer_query"))
-       && FindProcShort (glQueryCounter)
-       && FindProcShort (glGetQueryObjecti64v)
-       && FindProcShort (glGetQueryObjectui64v);
-
-  // load GL_ARB_vertex_type_2_10_10_10_rev (added to OpenGL 3.3 core)
-  const bool hasVertType21010101rev = (IsGlGreaterEqual (3, 3) || CheckExtension ("GL_ARB_vertex_type_2_10_10_10_rev"))
-       && FindProcShort (glVertexAttribP1ui)
-       && FindProcShort (glVertexAttribP1uiv)
-       && FindProcShort (glVertexAttribP2ui)
-       && FindProcShort (glVertexAttribP2uiv)
-       && FindProcShort (glVertexAttribP3ui)
-       && FindProcShort (glVertexAttribP3uiv)
-       && FindProcShort (glVertexAttribP4ui)
-       && FindProcShort (glVertexAttribP4uiv);
-
-  if ( hasVertType21010101rev
-   && !isCoreProfile)
-  {
-    // load deprecated functions
-    const bool hasVertType21010101revExt =
-          FindProcShort (glVertexP2ui)
-       && FindProcShort (glVertexP2uiv)
-       && FindProcShort (glVertexP3ui)
-       && FindProcShort (glVertexP3uiv)
-       && FindProcShort (glVertexP4ui)
-       && FindProcShort (glVertexP4uiv)
-       && FindProcShort (glTexCoordP1ui)
-       && FindProcShort (glTexCoordP1uiv)
-       && FindProcShort (glTexCoordP2ui)
-       && FindProcShort (glTexCoordP2uiv)
-       && FindProcShort (glTexCoordP3ui)
-       && FindProcShort (glTexCoordP3uiv)
-       && FindProcShort (glTexCoordP4ui)
-       && FindProcShort (glTexCoordP4uiv)
-       && FindProcShort (glMultiTexCoordP1ui)
-       && FindProcShort (glMultiTexCoordP1uiv)
-       && FindProcShort (glMultiTexCoordP2ui)
-       && FindProcShort (glMultiTexCoordP2uiv)
-       && FindProcShort (glMultiTexCoordP3ui)
-       && FindProcShort (glMultiTexCoordP3uiv)
-       && FindProcShort (glMultiTexCoordP4ui)
-       && FindProcShort (glMultiTexCoordP4uiv)
-       && FindProcShort (glNormalP3ui)
-       && FindProcShort (glNormalP3uiv)
-       && FindProcShort (glColorP3ui)
-       && FindProcShort (glColorP3uiv)
-       && FindProcShort (glColorP4ui)
-       && FindProcShort (glColorP4uiv)
-       && FindProcShort (glSecondaryColorP3ui)
-       && FindProcShort (glSecondaryColorP3uiv);
-    (void )hasVertType21010101revExt;
-  }
-
-  // load OpenGL 3.3 extra functions
-  has33 = IsGlGreaterEqual (3, 3)
-       && hasBlendFuncExtended
-       && hasSamplerObjects
-       && hasTimerQuery
-       && hasVertType21010101rev
-       && FindProcShort (glVertexAttribDivisor);
-
-  // load GL_ARB_draw_indirect (added to OpenGL 4.0 core)
-  const bool hasDrawIndirect = (IsGlGreaterEqual (4, 0) || CheckExtension ("GL_ARB_draw_indirect"))
-       && FindProcShort (glDrawArraysIndirect)
-       && FindProcShort (glDrawElementsIndirect);
-
-  // load GL_ARB_gpu_shader_fp64 (added to OpenGL 4.0 core)
-  const bool hasShaderFP64 = (IsGlGreaterEqual (4, 0) || CheckExtension ("GL_ARB_gpu_shader_fp64"))
-       && FindProcShort (glUniform1d)
-       && FindProcShort (glUniform2d)
-       && FindProcShort (glUniform3d)
-       && FindProcShort (glUniform4d)
-       && FindProcShort (glUniform1dv)
-       && FindProcShort (glUniform2dv)
-       && FindProcShort (glUniform3dv)
-       && FindProcShort (glUniform4dv)
-       && FindProcShort (glUniformMatrix2dv)
-       && FindProcShort (glUniformMatrix3dv)
-       && FindProcShort (glUniformMatrix4dv)
-       && FindProcShort (glUniformMatrix2x3dv)
-       && FindProcShort (glUniformMatrix2x4dv)
-       && FindProcShort (glUniformMatrix3x2dv)
-       && FindProcShort (glUniformMatrix3x4dv)
-       && FindProcShort (glUniformMatrix4x2dv)
-       && FindProcShort (glUniformMatrix4x3dv)
-       && FindProcShort (glGetUniformdv);
-
-  // load GL_ARB_shader_subroutine (added to OpenGL 4.0 core)
-  const bool hasShaderSubroutine = (IsGlGreaterEqual (4, 0) || CheckExtension ("GL_ARB_shader_subroutine"))
-       && FindProcShort (glGetSubroutineUniformLocation)
-       && FindProcShort (glGetSubroutineIndex)
-       && FindProcShort (glGetActiveSubroutineUniformiv)
-       && FindProcShort (glGetActiveSubroutineUniformName)
-       && FindProcShort (glGetActiveSubroutineName)
-       && FindProcShort (glUniformSubroutinesuiv)
-       && FindProcShort (glGetUniformSubroutineuiv)
-       && FindProcShort (glGetProgramStageiv);
-
-  // load GL_ARB_tessellation_shader (added to OpenGL 4.0 core)
-  const bool hasTessellationShader = (IsGlGreaterEqual (4, 0) || CheckExtension ("GL_ARB_tessellation_shader"))
-       && FindProcShort (glPatchParameteri)
-       && FindProcShort (glPatchParameterfv);
-
-  // load GL_ARB_transform_feedback2 (added to OpenGL 4.0 core)
-  const bool hasTrsfFeedback2 = (IsGlGreaterEqual (4, 0) || CheckExtension ("GL_ARB_transform_feedback2"))
-       && FindProcShort (glBindTransformFeedback)
-       && FindProcShort (glDeleteTransformFeedbacks)
-       && FindProcShort (glGenTransformFeedbacks)
-       && FindProcShort (glIsTransformFeedback)
-       && FindProcShort (glPauseTransformFeedback)
-       && FindProcShort (glResumeTransformFeedback)
-       && FindProcShort (glDrawTransformFeedback);
-
-  // load GL_ARB_transform_feedback3 (added to OpenGL 4.0 core)
-  const bool hasTrsfFeedback3 = (IsGlGreaterEqual (4, 0) || CheckExtension ("GL_ARB_transform_feedback3"))
-       && FindProcShort (glDrawTransformFeedbackStream)
-       && FindProcShort (glBeginQueryIndexed)
-       && FindProcShort (glEndQueryIndexed)
-       && FindProcShort (glGetQueryIndexediv);
-
-  // load OpenGL 4.0 new functions
-  has40 = IsGlGreaterEqual (4, 0)
-      && hasDrawIndirect
-      && hasShaderFP64
-      && hasShaderSubroutine
-      && hasTessellationShader
-      && hasTrsfFeedback2
-      && hasTrsfFeedback3
-      && FindProcShort (glMinSampleShading)
-      && FindProcShort (glBlendEquationi)
-      && FindProcShort (glBlendEquationSeparatei)
-      && FindProcShort (glBlendFunci)
-      && FindProcShort (glBlendFuncSeparatei);
-
-  // load GL_ARB_ES2_compatibility (added to OpenGL 4.1 core)
-  const bool hasES2Compatibility = (IsGlGreaterEqual (4, 1) || CheckExtension ("GL_ARB_ES2_compatibility"))
-       && FindProcShort (glReleaseShaderCompiler)
-       && FindProcShort (glShaderBinary)
-       && FindProcShort (glGetShaderPrecisionFormat)
-       && FindProcShort (glDepthRangef)
-       && FindProcShort (glClearDepthf);
-
-  // load GL_ARB_get_program_binary (added to OpenGL 4.1 core)
-  const bool hasGetProgramBinary = (IsGlGreaterEqual (4, 1) || CheckExtension ("GL_ARB_get_program_binary"))
-       && FindProcShort (glGetProgramBinary)
-       && FindProcShort (glProgramBinary)
-       && FindProcShort (glProgramParameteri);
-
-
-  // load GL_ARB_separate_shader_objects (added to OpenGL 4.1 core)
-  const bool hasSeparateShaderObjects = (IsGlGreaterEqual (4, 1) || CheckExtension ("GL_ARB_separate_shader_objects"))
-       && FindProcShort (glUseProgramStages)
-       && FindProcShort (glActiveShaderProgram)
-       && FindProcShort (glCreateShaderProgramv)
-       && FindProcShort (glBindProgramPipeline)
-       && FindProcShort (glDeleteProgramPipelines)
-       && FindProcShort (glGenProgramPipelines)
-       && FindProcShort (glIsProgramPipeline)
-       && FindProcShort (glGetProgramPipelineiv)
-       && FindProcShort (glProgramUniform1i)
-       && FindProcShort (glProgramUniform1iv)
-       && FindProcShort (glProgramUniform1f)
-       && FindProcShort (glProgramUniform1fv)
-       && FindProcShort (glProgramUniform1d)
-       && FindProcShort (glProgramUniform1dv)
-       && FindProcShort (glProgramUniform1ui)
-       && FindProcShort (glProgramUniform1uiv)
-       && FindProcShort (glProgramUniform2i)
-       && FindProcShort (glProgramUniform2iv)
-       && FindProcShort (glProgramUniform2f)
-       && FindProcShort (glProgramUniform2fv)
-       && FindProcShort (glProgramUniform2d)
-       && FindProcShort (glProgramUniform2dv)
-       && FindProcShort (glProgramUniform2ui)
-       && FindProcShort (glProgramUniform2uiv)
-       && FindProcShort (glProgramUniform3i)
-       && FindProcShort (glProgramUniform3iv)
-       && FindProcShort (glProgramUniform3f)
-       && FindProcShort (glProgramUniform3fv)
-       && FindProcShort (glProgramUniform3d)
-       && FindProcShort (glProgramUniform3dv)
-       && FindProcShort (glProgramUniform3ui)
-       && FindProcShort (glProgramUniform3uiv)
-       && FindProcShort (glProgramUniform4i)
-       && FindProcShort (glProgramUniform4iv)
-       && FindProcShort (glProgramUniform4f)
-       && FindProcShort (glProgramUniform4fv)
-       && FindProcShort (glProgramUniform4d)
-       && FindProcShort (glProgramUniform4dv)
-       && FindProcShort (glProgramUniform4ui)
-       && FindProcShort (glProgramUniform4uiv)
-       && FindProcShort (glProgramUniformMatrix2fv)
-       && FindProcShort (glProgramUniformMatrix3fv)
-       && FindProcShort (glProgramUniformMatrix4fv)
-       && FindProcShort (glProgramUniformMatrix2dv)
-       && FindProcShort (glProgramUniformMatrix3dv)
-       && FindProcShort (glProgramUniformMatrix4dv)
-       && FindProcShort (glProgramUniformMatrix2x3fv)
-       && FindProcShort (glProgramUniformMatrix3x2fv)
-       && FindProcShort (glProgramUniformMatrix2x4fv)
-       && FindProcShort (glProgramUniformMatrix4x2fv)
-       && FindProcShort (glProgramUniformMatrix3x4fv)
-       && FindProcShort (glProgramUniformMatrix4x3fv)
-       && FindProcShort (glProgramUniformMatrix2x3dv)
-       && FindProcShort (glProgramUniformMatrix3x2dv)
-       && FindProcShort (glProgramUniformMatrix2x4dv)
-       && FindProcShort (glProgramUniformMatrix4x2dv)
-       && FindProcShort (glProgramUniformMatrix3x4dv)
-       && FindProcShort (glProgramUniformMatrix4x3dv)
-       && FindProcShort (glValidateProgramPipeline)
-       && FindProcShort (glGetProgramPipelineInfoLog);
-
-  // load GL_ARB_vertex_attrib_64bit (added to OpenGL 4.1 core)
-  const bool hasVertAttrib64bit = (IsGlGreaterEqual (4, 1) || CheckExtension ("GL_ARB_vertex_attrib_64bit"))
-       && FindProcShort (glVertexAttribL1d)
-       && FindProcShort (glVertexAttribL2d)
-       && FindProcShort (glVertexAttribL3d)
-       && FindProcShort (glVertexAttribL4d)
-       && FindProcShort (glVertexAttribL1dv)
-       && FindProcShort (glVertexAttribL2dv)
-       && FindProcShort (glVertexAttribL3dv)
-       && FindProcShort (glVertexAttribL4dv)
-       && FindProcShort (glVertexAttribLPointer)
-       && FindProcShort (glGetVertexAttribLdv);
-
-  // load GL_ARB_viewport_array (added to OpenGL 4.1 core)
-  const bool hasViewportArray = (IsGlGreaterEqual (4, 1) || CheckExtension ("GL_ARB_viewport_array"))
-       && FindProcShort (glViewportArrayv)
-       && FindProcShort (glViewportIndexedf)
-       && FindProcShort (glViewportIndexedfv)
-       && FindProcShort (glScissorArrayv)
-       && FindProcShort (glScissorIndexed)
-       && FindProcShort (glScissorIndexedv)
-       && FindProcShort (glDepthRangeArrayv)
-       && FindProcShort (glDepthRangeIndexed)
-       && FindProcShort (glGetFloati_v)
-       && FindProcShort (glGetDoublei_v);
-
-  has41 = IsGlGreaterEqual (4, 1)
-       && hasES2Compatibility
-       && hasGetProgramBinary
-       && hasSeparateShaderObjects
-       && hasVertAttrib64bit
-       && hasViewportArray;
-
-  // load GL_ARB_base_instance (added to OpenGL 4.2 core)
-  const bool hasBaseInstance = (IsGlGreaterEqual (4, 2) || CheckExtension ("GL_ARB_base_instance"))
-       && FindProcShort (glDrawArraysInstancedBaseInstance)
-       && FindProcShort (glDrawElementsInstancedBaseInstance)
-       && FindProcShort (glDrawElementsInstancedBaseVertexBaseInstance);
-
-  // load GL_ARB_transform_feedback_instanced (added to OpenGL 4.2 core)
-  const bool hasTrsfFeedbackInstanced = (IsGlGreaterEqual (4, 2) || CheckExtension ("GL_ARB_transform_feedback_instanced"))
-       && FindProcShort (glDrawTransformFeedbackInstanced)
-       && FindProcShort (glDrawTransformFeedbackStreamInstanced);
-
-  // load GL_ARB_internalformat_query (added to OpenGL 4.2 core)
-  const bool hasInternalFormatQuery = (IsGlGreaterEqual (4, 2) || CheckExtension ("GL_ARB_internalformat_query"))
-       && FindProcShort (glGetInternalformativ);
-
-  // load GL_ARB_shader_atomic_counters (added to OpenGL 4.2 core)
-  const bool hasShaderAtomicCounters = (IsGlGreaterEqual (4, 2) || CheckExtension ("GL_ARB_shader_atomic_counters"))
-       && FindProcShort (glGetActiveAtomicCounterBufferiv);
-
-  // load GL_ARB_shader_image_load_store (added to OpenGL 4.2 core)
-  const bool hasShaderImgLoadStore = (IsGlGreaterEqual (4, 2) || CheckExtension ("GL_ARB_shader_image_load_store"))
-       && FindProcShort (glBindImageTexture)
-       && FindProcShort (glMemoryBarrier);
-
-  // load GL_ARB_texture_storage (added to OpenGL 4.2 core)
-  const bool hasTextureStorage = (IsGlGreaterEqual (4, 2) || CheckExtension ("GL_ARB_texture_storage"))
-       && FindProcShort (glTexStorage1D)
-       && FindProcShort (glTexStorage2D)
-       && FindProcShort (glTexStorage3D);
-
-  has42 = IsGlGreaterEqual (4, 2)
-       && hasBaseInstance
-       && hasTrsfFeedbackInstanced
-       && hasInternalFormatQuery
-       && hasShaderAtomicCounters
-       && hasShaderImgLoadStore
-       && hasTextureStorage;
-
-  has43 = IsGlGreaterEqual (4, 3)
-       && FindProcShort (glClearBufferData)
-       && FindProcShort (glClearBufferSubData)
-       && FindProcShort (glDispatchCompute)
-       && FindProcShort (glDispatchComputeIndirect)
-       && FindProcShort (glCopyImageSubData)
-       && FindProcShort (glFramebufferParameteri)
-       && FindProcShort (glGetFramebufferParameteriv)
-       && FindProcShort (glGetInternalformati64v)
-       && FindProcShort (glInvalidateTexSubImage)
-       && FindProcShort (glInvalidateTexImage)
-       && FindProcShort (glInvalidateBufferSubData)
-       && FindProcShort (glInvalidateBufferData)
-       && FindProcShort (glInvalidateFramebuffer)
-       && FindProcShort (glInvalidateSubFramebuffer)
-       && FindProcShort (glMultiDrawArraysIndirect)
-       && FindProcShort (glMultiDrawElementsIndirect)
-       && FindProcShort (glGetProgramInterfaceiv)
-       && FindProcShort (glGetProgramResourceIndex)
-       && FindProcShort (glGetProgramResourceName)
-       && FindProcShort (glGetProgramResourceiv)
-       && FindProcShort (glGetProgramResourceLocation)
-       && FindProcShort (glGetProgramResourceLocationIndex)
-       && FindProcShort (glShaderStorageBlockBinding)
-       && FindProcShort (glTexBufferRange)
-       && FindProcShort (glTexStorage2DMultisample)
-       && FindProcShort (glTexStorage3DMultisample)
-       && FindProcShort (glTextureView)
-       && FindProcShort (glBindVertexBuffer)
-       && FindProcShort (glVertexAttribFormat)
-       && FindProcShort (glVertexAttribIFormat)
-       && FindProcShort (glVertexAttribLFormat)
-       && FindProcShort (glVertexAttribBinding)
-       && FindProcShort (glVertexBindingDivisor)
-       && FindProcShort (glDebugMessageControl)
-       && FindProcShort (glDebugMessageInsert)
-       && FindProcShort (glDebugMessageCallback)
-       && FindProcShort (glGetDebugMessageLog)
-       && FindProcShort (glPushDebugGroup)
-       && FindProcShort (glPopDebugGroup)
-       && FindProcShort (glObjectLabel)
-       && FindProcShort (glGetObjectLabel)
-       && FindProcShort (glObjectPtrLabel)
-       && FindProcShort (glGetObjectPtrLabel);
-
-  // load GL_ARB_clear_texture (added to OpenGL 4.4 core)
-  bool arbTexClear = (IsGlGreaterEqual (4, 4) || CheckExtension ("GL_ARB_clear_texture"))
-       && FindProcShort (glClearTexImage)
-       && FindProcShort (glClearTexSubImage);
-
-  has44 = IsGlGreaterEqual (4, 4)
-       && arbTexClear
-       && FindProcShort (glBufferStorage)
-       && FindProcShort (glBindBuffersBase)
-       && FindProcShort (glBindBuffersRange)
-       && FindProcShort (glBindTextures)
-       && FindProcShort (glBindSamplers)
-       && FindProcShort (glBindImageTextures)
-       && FindProcShort (glBindVertexBuffers);
-
-  // initialize debug context extension
-  if (CheckExtension ("GL_ARB_debug_output"))
-  {
-    arbDbg = NULL;
-    if (has43)
-    {
-      arbDbg = (OpenGl_ArbDbg* )(&(*myFuncs));
-    }
-    else if (FindProc ("glDebugMessageControlARB",  myFuncs->glDebugMessageControl)
-          && FindProc ("glDebugMessageInsertARB",   myFuncs->glDebugMessageInsert)
-          && FindProc ("glDebugMessageCallbackARB", myFuncs->glDebugMessageCallback)
-          && FindProc ("glGetDebugMessageLogARB",   myFuncs->glGetDebugMessageLog))
-    {
-      arbDbg = (OpenGl_ArbDbg* )(&(*myFuncs));
-    }
-
-    if (arbDbg != NULL
-     && caps->contextDebug)
-    {
-      // setup default callback
-      myIsGlDebugCtx = Standard_True;
-      arbDbg->glDebugMessageCallback (debugCallbackWrap, this);
-      if (has43)
-      {
-        ::glEnable (GL_DEBUG_OUTPUT);
-      }
-      if (caps->contextSyncDebug)
-      {
-        ::glEnable (GL_DEBUG_OUTPUT_SYNCHRONOUS);
-      }
-    }
-  }
-
-  // initialize TBO extension (ARB)
-  if (!has31
-   && CheckExtension ("GL_ARB_texture_buffer_object")
-   && FindProc ("glTexBufferARB", myFuncs->glTexBuffer))
-  {
-    arbTBO = (OpenGl_ArbTBO* )(&(*myFuncs));
-  }
-  arbTboRGB32 = CheckExtension ("GL_ARB_texture_buffer_object_rgb32");
-
-  // initialize hardware instancing extension (ARB)
-  if (!has31
-   && CheckExtension ("GL_ARB_draw_instanced")
-   && FindProc ("glDrawArraysInstancedARB",   myFuncs->glDrawArraysInstanced)
-   && FindProc ("glDrawElementsInstancedARB", myFuncs->glDrawElementsInstanced))
-  {
-    arbIns = (OpenGl_ArbIns* )(&(*myFuncs));
-  }
-
-  // initialize FBO extension (ARB)
-  if (hasFBO)
-  {
-    arbFBO     = (OpenGl_ArbFBO*     )(&(*myFuncs));
-    arbFBOBlit = (OpenGl_ArbFBOBlit* )(&(*myFuncs));
-    extPDS = Standard_True; // extension for EXT, but part of ARB
-  }
-
-  // initialize GS extension (EXT)
-  if (CheckExtension ("GL_EXT_geometry_shader4")
-   && FindProcShort (glProgramParameteriEXT))
-  {
-    extGS = (OpenGl_ExtGS* )(&(*myFuncs));
-  }
-
-  // initialize bindless texture extension (ARB)
-  if (CheckExtension ("GL_ARB_bindless_texture")
-   && FindProcShort (glGetTextureHandleARB)
-   && FindProcShort (glGetTextureSamplerHandleARB)
-   && FindProcShort (glMakeTextureHandleResidentARB)
-   && FindProcShort (glMakeTextureHandleNonResidentARB)
-   && FindProcShort (glGetImageHandleARB)
-   && FindProcShort (glMakeImageHandleResidentARB)
-   && FindProcShort (glMakeImageHandleNonResidentARB)
-   && FindProcShort (glUniformHandleui64ARB)
-   && FindProcShort (glUniformHandleui64vARB)
-   && FindProcShort (glProgramUniformHandleui64ARB)
-   && FindProcShort (glProgramUniformHandleui64vARB)
-   && FindProcShort (glIsTextureHandleResidentARB)
-   && FindProcShort (glIsImageHandleResidentARB)
-   && FindProcShort (glVertexAttribL1ui64ARB)
-   && FindProcShort (glVertexAttribL1ui64vARB)
-   && FindProcShort (glGetVertexAttribLui64vARB))
-  {
-    arbTexBindless = (OpenGl_ArbTexBindless* )(&(*myFuncs));
-  }
-
-  if (!has12)
-  {
-    checkWrongVersion (1, 2);
-    myGlVerMajor = 1;
-    myGlVerMinor = 1;
-    return;
-  }
-  else if (!has13)
-  {
-    checkWrongVersion (1, 3);
-    myGlVerMajor = 1;
-    myGlVerMinor = 2;
-    return;
-  }
-  else if (!has14)
-  {
-    checkWrongVersion (1, 4);
-    myGlVerMajor = 1;
-    myGlVerMinor = 3;
-    return;
-  }
-  else if (!has15)
-  {
-    checkWrongVersion (1, 5);
-    myGlVerMajor = 1;
-    myGlVerMinor = 4;
-    return;
-  }
-  if (!isCoreProfile)
-  {
-    core15 = (OpenGl_GlCore15* )(&(*myFuncs));
-  }
-  core15fwd = (OpenGl_GlCore15Fwd* )(&(*myFuncs));
-
-  if (!has20)
-  {
-    checkWrongVersion (2, 0);
-    myGlVerMajor = 1;
-    myGlVerMinor = 5;
-    return;
-  }
-
-  const char* aGlslVer = (const char* )::glGetString (GL_SHADING_LANGUAGE_VERSION);
-  if (aGlslVer == NULL
-  || *aGlslVer == '\0')
-  {
-    // broken context has been detected
-    TCollection_ExtendedString aMsg = TCollection_ExtendedString()
-      + "Error! OpenGL context reports version "
-      + myGlVerMajor  + "." + myGlVerMinor
-      + " but reports wrong GLSL version";
-    PushMessage (GL_DEBUG_SOURCE_APPLICATION,
-                 GL_DEBUG_TYPE_ERROR,
-                 0,
-                 GL_DEBUG_SEVERITY_HIGH,
-                 aMsg);
-    myGlVerMajor = 1;
-    myGlVerMinor = 5;
-    return;
-  }
-
-  if (!isCoreProfile)
-  {
-    core20  = (OpenGl_GlCore20*    )(&(*myFuncs));
-  }
-  core20fwd = (OpenGl_GlCore20Fwd* )(&(*myFuncs));
-
-  if (!has21)
+#if !defined(GL_ES_VERSION_2_0)
+  if (core32 != NULL && isCoreProfile)
   {
-    checkWrongVersion (2, 1);
-    myGlVerMajor = 2;
-    myGlVerMinor = 0;
-    return;
+    core32->glGenVertexArrays (1, &myDefaultVao);
   }
 
-  if (!has30)
-  {
-    checkWrongVersion (3, 0);
-    myGlVerMajor = 2;
-    myGlVerMinor = 1;
-    return;
-  }
+  myTexClamp = IsGlGreaterEqual (1, 2) ? GL_CLAMP_TO_EDGE : GL_CLAMP;
 
-  // MSAA RenderBuffers have been defined in OpenGL 3.0,
-  // but MSAA Textures - only in OpenGL 3.2+
-  if (!has32
-   && CheckExtension ("GL_ARB_texture_multisample")
-   && FindProcShort (glTexImage2DMultisample))
-  {
-    GLint aNbColorSamples = 0, aNbDepthSamples = 0;
-    ::glGetIntegerv (GL_MAX_COLOR_TEXTURE_SAMPLES, &aNbColorSamples);
-    ::glGetIntegerv (GL_MAX_DEPTH_TEXTURE_SAMPLES, &aNbDepthSamples);
-    myMaxMsaaSamples = Min (aNbColorSamples, aNbDepthSamples);
-  }
-  if (!has43
-   && CheckExtension ("GL_ARB_texture_storage_multisample")
-   && FindProcShort (glTexStorage2DMultisample))
-  {
-    //
-  }
+  GLint aStereo = GL_FALSE;
+  glGetIntegerv (GL_STEREO, &aStereo);
+  myIsStereoBuffers = aStereo == 1;
 
-  if (!has31)
-  {
-    checkWrongVersion (3, 1);
-    myGlVerMajor = 3;
-    myGlVerMinor = 0;
-    return;
-  }
-  arbTBO = (OpenGl_ArbTBO* )(&(*myFuncs));
-  arbIns = (OpenGl_ArbIns* )(&(*myFuncs));
+  // get number of maximum clipping planes
+  glGetIntegerv (GL_MAX_CLIP_PLANES, &myMaxClipPlanes);
+#endif
 
+#if defined(GL_ES_VERSION_2_0)
+  // check whether ray tracing mode is supported
+  myHasRayTracing = IsGlGreaterEqual (3, 2);
+  myHasRayTracingTextures = myHasRayTracingAdaptiveSampling = myHasRayTracingAdaptiveSamplingAtomic = false;
+#else
   // check whether ray tracing mode is supported
-  myHasRayTracing = has31
+  myHasRayTracing = IsGlGreaterEqual (3, 1)
                  && arbTboRGB32
                  && arbFBOBlit  != NULL;
 
@@ -2505,101 +1632,158 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
 
   // check whether adaptive screen sampling in ray tracing mode is supported
   myHasRayTracingAdaptiveSampling = myHasRayTracing
-                                 && has44
-                                 && CheckExtension ("GL_NV_shader_atomic_float");
+                                 && core44 != NULL;
+  myHasRayTracingAdaptiveSamplingAtomic = myHasRayTracingAdaptiveSampling
+                                       && CheckExtension ("GL_NV_shader_atomic_float");
+#endif
 
-  if (!has32)
-  {
-    checkWrongVersion (3, 2);
-    myGlVerMajor = 3;
-    myGlVerMinor = 1;
-    return;
-  }
-  core32 = (OpenGl_GlCore32* )(&(*myFuncs));
-  if (isCoreProfile)
-  {
-    core32->glGenVertexArrays (1, &myDefaultVao);
-  }
-  else
-  {
-    core32back = (OpenGl_GlCore32Back* )(&(*myFuncs));
+  if (arbFBO != NULL
+   && hasFboSRGB)
+  {
+    // Detect if window buffer is considered by OpenGL as sRGB-ready
+    // (linear RGB color written by shader is automatically converted into sRGB)
+    // or not (offscreen FBO should be blit into window buffer with gamma correction).
+    const GLenum aDefWinBuffer =
+    #if !defined(GL_ES_VERSION_2_0)
+      GL_BACK_LEFT;
+    #else
+      GL_BACK;
+    #endif
+    GLint aWinColorEncoding = 0; // GL_LINEAR
+    arbFBO->glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, aDefWinBuffer, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, &aWinColorEncoding);
+    ResetErrors (true);
+    myIsSRgbWindow = aWinColorEncoding == GL_SRGB;
+
+    // On desktop OpenGL, pixel formats are almost always sRGB-ready, even when not requested;
+    // it is safe behavior on desktop where GL_FRAMEBUFFER_SRGB is disabled by default
+    // (contrary to OpenGL ES, where it is enabled by default).
+    // NVIDIA drivers, however, always return GL_LINEAR even for sRGB-ready pixel formats on Windows platform,
+    // while AMD and Intel report GL_SRGB as expected.
+    // macOS drivers seems to be also report GL_LINEAR even for [NSColorSpace sRGBColorSpace].
+  #if !defined(GL_ES_VERSION_2_0)
+  #ifdef __APPLE__
+    myIsSRgbWindow = true;
+  #else
+    if (!myIsSRgbWindow
+      && myVendor.Search ("nvidia") != -1)
+    {
+      myIsSRgbWindow = true;
+    }
+  #endif
+  #endif
+    if (!myIsSRgbWindow)
+    {
+      Message::SendTrace ("OpenGl_Context, warning: window buffer is not sRGB-ready.\n"
+                          "Check OpenGL window creation parameters for optimal performance.");
+    }
   }
-  ::glGetIntegerv (GL_MAX_SAMPLES, &myMaxMsaaSamples);
 
-  if (!has33)
-  {
-    checkWrongVersion (3, 3);
-    myGlVerMajor = 3;
-    myGlVerMinor = 2;
-    return;
-  }
-  core33 = (OpenGl_GlCore33* )(&(*myFuncs));
-  if (!isCoreProfile)
+  // standard formats
+  mySupportedFormats->Add (Image_Format_Gray);
+  mySupportedFormats->Add (Image_Format_Alpha);
+  mySupportedFormats->Add (Image_Format_RGB);
+  mySupportedFormats->Add (Image_Format_RGB32);
+  mySupportedFormats->Add (Image_Format_RGBA);
+  if (extBgra)
   {
-    core33back = (OpenGl_GlCore33Back* )(&(*myFuncs));
+  #if !defined(GL_ES_VERSION_2_0)
+    // no BGR on OpenGL ES - only BGRA as extension
+    mySupportedFormats->Add (Image_Format_BGR);
+  #endif
+    mySupportedFormats->Add (Image_Format_BGR32);
+    mySupportedFormats->Add (Image_Format_BGRA);
   }
-
-  if (!has40)
+  if (arbTexFloat)
   {
-    checkWrongVersion (4, 0);
-    myGlVerMajor = 3;
-    myGlVerMinor = 3;
-    return;
+    mySupportedFormats->Add (Image_Format_GrayF);
+    mySupportedFormats->Add (Image_Format_AlphaF);
+    mySupportedFormats->Add (Image_Format_RGBF);
+    mySupportedFormats->Add (Image_Format_RGBAF);
+    if (hasHalfFloatBuffer != OpenGl_FeatureNotAvailable)
+    {
+      mySupportedFormats->Add (Image_Format_RGBAF_half);
+    }
+    if (arbTexRG)
+    {
+      mySupportedFormats->Add (Image_Format_RGF);
+      if (hasHalfFloatBuffer != OpenGl_FeatureNotAvailable)
+      {
+        mySupportedFormats->Add (Image_Format_RGF_half);
+      }
+    }
+    if (extBgra)
+    {
+    #if !defined(GL_ES_VERSION_2_0)
+      mySupportedFormats->Add (Image_Format_BGRF);
+    #endif
+      mySupportedFormats->Add (Image_Format_BGRAF);
+    }
   }
-  arbTboRGB32 = Standard_True; // in core since OpenGL 4.0
 
-  if (!has41)
+#ifdef __EMSCRIPTEN__
+  if (CheckExtension ("GL_WEBGL_compressed_texture_s3tc")) // GL_WEBGL_compressed_texture_s3tc_srgb for sRGB formats
   {
-    checkWrongVersion (4, 1);
-    myGlVerMajor = 4;
-    myGlVerMinor = 0;
-    return;
+    mySupportedFormats->Add (Image_CompressedFormat_RGB_S3TC_DXT1);
+    mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT1);
+    mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT3);
+    mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT5);
   }
-  core41 = (OpenGl_GlCore41* )(&(*myFuncs));
-  if (!isCoreProfile)
+  if (!extPDS
+    && CheckExtension ("GL_WEBGL_depth_texture"))
   {
-    core41back = (OpenGl_GlCore41Back* )(&(*myFuncs));
+    extPDS = true; // WebGL 1.0 extension (in WebGL 2.0 core)
   }
-
-  if(!has42)
+#else
+  if (CheckExtension ("GL_EXT_texture_compression_s3tc")) // GL_EXT_texture_sRGB for sRGB formats
   {
-    checkWrongVersion (4, 2);
-    myGlVerMajor = 4;
-    myGlVerMinor = 1;
-    return;
+    mySupportedFormats->Add (Image_CompressedFormat_RGB_S3TC_DXT1);
+    mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT1);
+    mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT3);
+    mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT5);
   }
-  core42 = (OpenGl_GlCore42* )(&(*myFuncs));
-  if (!isCoreProfile)
+  else
   {
-    core42back = (OpenGl_GlCore42Back* )(&(*myFuncs));
+    if (CheckExtension ("GL_EXT_texture_compression_dxt1"))
+    {
+      mySupportedFormats->Add (Image_CompressedFormat_RGB_S3TC_DXT1);
+      mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT1);
+    }
+    if (CheckExtension ("GL_ANGLE_texture_compression_dxt3"))
+    {
+      mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT3);
+    }
+    if (CheckExtension ("GL_ANGLE_texture_compression_dxt5"))
+    {
+      mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT5);
+    }
   }
+#endif
 
-  if (!has43)
-  {
-    checkWrongVersion (4, 3);
-    myGlVerMajor = 4;
-    myGlVerMinor = 2;
-    return;
-  }
-  core43 = (OpenGl_GlCore43* )(&(*myFuncs));
-  if (!isCoreProfile)
-  {
-    core43back = (OpenGl_GlCore43Back* )(&(*myFuncs));
-  }
+  // check whether PBR shading model is supported
+  myHasPBR = arbFBO != NULL
+          && myMaxTexCombined >= 4
+          && arbTexFloat
+          && (IsGlGreaterEqual (3, 0)
+        #if defined(GL_ES_VERSION_2_0)
+           || hasHighp
+        // || CheckExtension ("GL_EXT_shader_texture_lod") fallback is used when extension is unavailable
+        #else
+          || (IsGlGreaterEqual (2, 1) && CheckExtension ("GL_EXT_gpu_shader4"))
+        #endif
+             );
 
-  if (!has44)
+  myDepthPeelingDepthTexUnit      = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_DepthPeelingDepth);      // -6
+  myDepthPeelingFrontColorTexUnit = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_DepthPeelingFrontColor); // -5
+  myShadowMapTexUnit              = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_ShadowMap);              // -4
+  myPBREnvLUTTexUnit              = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_PbrEnvironmentLUT);      // -3
+  myPBRDiffIBLMapSHTexUnit        = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_PbrIblDiffuseSH);        // -2
+  myPBRSpecIBLMapTexUnit          = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_PbrIblSpecular);         // -1
+  if (!myHasPBR)
   {
-    checkWrongVersion (4, 4);
-    myGlVerMajor = 4;
-    myGlVerMinor = 3;
-    return;
+    myDepthPeelingDepthTexUnit      = static_cast<Graphic3d_TextureUnit>(myDepthPeelingDepthTexUnit + 3);
+    myDepthPeelingFrontColorTexUnit = static_cast<Graphic3d_TextureUnit>(myDepthPeelingFrontColorTexUnit + 3);
+    myShadowMapTexUnit              = static_cast<Graphic3d_TextureUnit>(myShadowMapTexUnit + 3);
   }
-  core44 = (OpenGl_GlCore44* )(&(*myFuncs));
-  if (!isCoreProfile)
-  {
-    core44back = (OpenGl_GlCore44Back* )(&(*myFuncs));
-  }
-#endif
 }
 
 // =======================================================================
@@ -2660,7 +1844,7 @@ void OpenGl_Context::MemoryInfo (TColStd_IndexedDataMapOfStringString& theDict)
 {
 #if defined(GL_ES_VERSION_2_0)
   (void )theDict;
-#elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
+#elif defined(__APPLE__) && !defined(HAVE_XLIB)
   GLint aGlRendId = 0;
   CGLGetParameter (CGLGetCurrentContext(), kCGLCPCurrentRendererID, &aGlRendId);
 
@@ -2794,12 +1978,10 @@ void OpenGl_Context::DiagnosticInformation (TColStd_IndexedDataMapOfStringString
     if ((theFlags & Graphic3d_DiagnosticInfo_Extensions) != 0
      && myFuncs->wglGetExtensionsStringARB != NULL)
     {
-      const char* aWglExts = myFuncs->wglGetExtensionsStringARB ((HDC )myWindowDC);
+      const char* aWglExts = myFuncs->wglGetExtensionsStringARB ((HDC )myDisplay);
       addInfo (theDict, "WGLExtensions", aWglExts);
     }
-  #elif defined(__APPLE__)
-    //
-  #else
+  #elif defined(HAVE_XLIB)
     Display* aDisplay = (Display*)myDisplay;
     const int aScreen = DefaultScreen(aDisplay);
     addInfo (theDict, "GLXDirectRendering", ::glXIsDirect (aDisplay, (GLXContext )myGContext) ? "Yes" : "No");
@@ -2817,14 +1999,37 @@ void OpenGl_Context::DiagnosticInformation (TColStd_IndexedDataMapOfStringString
     {
       addInfo (theDict, "GLXClientExtensions", ::glXGetClientString (aDisplay, GLX_EXTENSIONS));
     }
+  #else
+    //
   #endif
   }
 
   if ((theFlags & Graphic3d_DiagnosticInfo_Device) != 0)
   {
+    Standard_Integer aDriverVer[2] = {};
+    ReadGlVersion (aDriverVer[0], aDriverVer[1]);
     addInfo (theDict, "GLvendor",    (const char*)::glGetString (GL_VENDOR));
     addInfo (theDict, "GLdevice",    (const char*)::glGetString (GL_RENDERER));
+  #ifdef __EMSCRIPTEN__
+    if (CheckExtension ("GL_WEBGL_debug_renderer_info"))
+    {
+      if (const char* aVendor = (const char*)::glGetString (0x9245))
+      {
+        addInfo (theDict, "GLunmaskedVendor", aVendor);
+      }
+      if (const char* aDevice = (const char*)::glGetString (0x9246))
+      {
+        addInfo (theDict, "GLunmaskedDevice", aDevice);
+      }
+    }
+  #endif
+
     addInfo (theDict, "GLversion",   (const char*)::glGetString (GL_VERSION));
+    if (myGlVerMajor != aDriverVer[0]
+     || myGlVerMinor != aDriverVer[1])
+    {
+      addInfo (theDict, "GLversionOcct", TCollection_AsciiString (myGlVerMajor) + "." + TCollection_AsciiString (myGlVerMinor));
+    }
     if (IsGlGreaterEqual (2, 0))
     {
       addInfo (theDict, "GLSLversion", (const char*)::glGetString (GL_SHADING_LANGUAGE_VERSION));
@@ -2838,6 +2043,7 @@ void OpenGl_Context::DiagnosticInformation (TColStd_IndexedDataMapOfStringString
   if ((theFlags & Graphic3d_DiagnosticInfo_Limits) != 0)
   {
     addInfo (theDict, "Max texture size", TCollection_AsciiString(myMaxTexDim));
+    addInfo (theDict, "Max FBO dump size", TCollection_AsciiString() + myMaxDumpSizeX + "x" + myMaxDumpSizeY);
     addInfo (theDict, "Max combined texture units", TCollection_AsciiString(myMaxTexCombined));
     addInfo (theDict, "Max MSAA samples", TCollection_AsciiString(myMaxMsaaSamples));
   }
@@ -2953,7 +2159,7 @@ void OpenGl_Context::ReleaseDelayed()
   {
     if (++anIter.ChangeValue() <= 2)
     {
-      continue; // postpone release one more frame to ensure noone use it periodically
+      continue; // postpone release one more frame to ensure no one uses it periodically
     }
 
     const TCollection_AsciiString& aKey = anIter.Key();
@@ -2973,7 +2179,7 @@ void OpenGl_Context::ReleaseDelayed()
       continue;
     }
 
-    // release resource if no one requiested it more than 2 redraw calls
+    // release resource if no one requested it more than 2 redraw calls
     aRes->Release (this);
     mySharedResources->UnBind (aKey);
     aDeadList.Append (aKey);
@@ -2989,104 +2195,112 @@ void OpenGl_Context::ReleaseDelayed()
 // function : BindTextures
 // purpose  :
 // =======================================================================
-Handle(OpenGl_TextureSet) OpenGl_Context::BindTextures (const Handle(OpenGl_TextureSet)& theTextures)
+Handle(OpenGl_TextureSet) OpenGl_Context::BindTextures (const Handle(OpenGl_TextureSet)& theTextures,
+                                                        const Handle(OpenGl_ShaderProgram)& theProgram)
 {
-  if (myActiveTextures == theTextures)
+  const Standard_Integer aTextureSetBits = !theTextures.IsNull() ? theTextures->TextureSetBits() : 0;
+  const Standard_Integer aProgramBits    = !theProgram.IsNull() ? theProgram->TextureSetBits() : 0;
+  Standard_Integer aMissingBits = aProgramBits & ~aTextureSetBits;
+  if (aMissingBits != 0
+   && myTextureRgbaBlack.IsNull())
   {
-    return myActiveTextures;
-  }
-
-  Handle(OpenGl_Context) aThisCtx (this);
-  OpenGl_TextureSet::Iterator aTextureIterOld (myActiveTextures), aTextureIterNew (theTextures);
-  for (;;)
-  {
-    if (!aTextureIterNew.More())
+    // allocate mock textures
+    myTextureRgbaBlack = new OpenGl_Texture();
+    myTextureRgbaWhite = new OpenGl_Texture();
+    Image_PixMap anImage;
+    anImage.InitZero (Image_Format_RGBA, 2, 2, 0, (Standard_Byte )0);
+    if (!myTextureRgbaBlack->Init (this, OpenGl_TextureFormat::Create<GLubyte, 4>(), Graphic3d_Vec2i (2, 2), Graphic3d_TOT_2D, &anImage))
     {
-      for (; aTextureIterOld.More(); aTextureIterOld.Next())
-      {
-        if (const Handle(OpenGl_Texture)& aTextureOld = aTextureIterOld.Value())
-        {
-        #if !defined(GL_ES_VERSION_2_0)
-          if (core11 != NULL)
-          {
-            OpenGl_Sampler::resetGlobalTextureParams (aThisCtx, *aTextureOld, aTextureOld->Sampler()->Parameters());
-          }
-        #endif
-          aTextureOld->Unbind (aThisCtx);
-        }
-      }
-      break;
+      PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH,
+                    "Error: unable to create unit mock PBR texture map.");
+    }
+    anImage.InitZero (Image_Format_RGBA, 2, 2, 0, (Standard_Byte )255);
+    if (!myTextureRgbaWhite->Init (this, OpenGl_TextureFormat::Create<GLubyte, 4>(), Graphic3d_Vec2i (2, 2), Graphic3d_TOT_2D, &anImage))
+    {
+      PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH,
+                    "Error: unable to create normal mock PBR texture map.");
     }
+  }
 
-    const Handle(OpenGl_Texture)& aTextureNew = aTextureIterNew.Value();
-    if (aTextureIterOld.More())
+  Handle(OpenGl_TextureSet) anOldTextures = myActiveTextures;
+  if (myActiveTextures != theTextures)
+  {
+    Handle(OpenGl_Context) aThisCtx (this);
+    for (OpenGl_TextureSetPairIterator aSlotIter (myActiveTextures, theTextures); aSlotIter.More(); aSlotIter.Next())
     {
-      const Handle(OpenGl_Texture)& aTextureOld = aTextureIterOld.Value();
+      const Graphic3d_TextureUnit aTexUnit = aSlotIter.Unit();
+      const OpenGl_Texture* aTextureOld = aSlotIter.Texture1();
+      const OpenGl_Texture* aTextureNew = aSlotIter.Texture2();
       if (aTextureNew == aTextureOld)
       {
-        aTextureIterNew.Next();
-        aTextureIterOld.Next();
         continue;
       }
-      else if (aTextureNew.IsNull()
-           || !aTextureNew->IsValid())
+
+      if (aTextureNew != NULL
+       && aTextureNew->IsValid())
       {
-        if (!aTextureOld.IsNull())
+        if (aTexUnit >= myMaxTexCombined)
+        {
+          PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
+                       TCollection_AsciiString("Texture unit ") + aTexUnit + " for " + aTextureNew->ResourceId() + " exceeds hardware limit " + myMaxTexCombined);
+          continue;
+        }
+
+        aTextureNew->Bind (aThisCtx, aTexUnit);
+        if (aTextureNew->Sampler()->ToUpdateParameters())
         {
-        #if !defined(GL_ES_VERSION_2_0)
-          if (core11 != NULL)
+          if (aTextureNew->Sampler()->IsImmutable())
           {
-            OpenGl_Sampler::resetGlobalTextureParams (aThisCtx, *aTextureOld, aTextureOld->Sampler()->Parameters());
+            aTextureNew->Sampler()->Init (aThisCtx, *aTextureNew);
+          }
+          else
+          {
+            OpenGl_Sampler::applySamplerParams (aThisCtx, aTextureNew->Sampler()->Parameters(), aTextureNew->Sampler().get(), aTextureNew->GetTarget(), aTextureNew->MaxMipmapLevel());
           }
-        #endif
-          aTextureOld->Unbind (aThisCtx);
         }
-
-        aTextureIterNew.Next();
-        aTextureIterOld.Next();
-        continue;
+      #if !defined(GL_ES_VERSION_2_0)
+        if (core11ffp != NULL)
+        {
+          OpenGl_Sampler::applyGlobalTextureParams (aThisCtx, *aTextureNew, aTextureNew->Sampler()->Parameters());
+        }
+      #endif
+      }
+      else if (aTextureOld != NULL
+            && aTextureOld->IsValid())
+      {
+        aTextureOld->Unbind (aThisCtx, aTexUnit);
+      #if !defined(GL_ES_VERSION_2_0)
+        if (core11ffp != NULL)
+        {
+          OpenGl_Sampler::resetGlobalTextureParams (aThisCtx, *aTextureOld, aTextureOld->Sampler()->Parameters());
+        }
+      #endif
       }
-
-      aTextureIterOld.Next();
-    }
-    if (aTextureNew.IsNull())
-    {
-      aTextureIterNew.Next();
-      continue;
-    }
-
-    const Graphic3d_TextureUnit aTexUnit = aTextureNew->Sampler()->Parameters()->TextureUnit();
-    if (aTexUnit >= myMaxTexCombined)
-    {
-      PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
-                   TCollection_AsciiString("Texture unit ") + aTexUnit + " for " + aTextureNew->ResourceId() + " exceeds hardware limit " + myMaxTexCombined);
-      aTextureIterNew.Next();
-      continue;
     }
+    myActiveTextures = theTextures;
+  }
 
-    aTextureNew->Bind (aThisCtx);
-    if (aTextureNew->Sampler()->ToUpdateParameters())
+  if (myActiveMockTextures != aMissingBits)
+  {
+    myActiveMockTextures = aMissingBits;
+    for (Standard_Integer aBitIter = 0; aMissingBits != 0; ++aBitIter)
     {
-      if (aTextureNew->Sampler()->IsImmutable())
-      {
-        aTextureNew->Sampler()->Init (aThisCtx, *aTextureNew);
-      }
-      else
+      Standard_Integer aUnitMask = 1 << aBitIter;
+      if ((aUnitMask & aMissingBits) != 0)
       {
-        OpenGl_Sampler::applySamplerParams (aThisCtx, aTextureNew->Sampler()->Parameters(), aTextureNew->Sampler().get(), aTextureNew->GetTarget(), aTextureNew->HasMipmaps());
+        aMissingBits = aMissingBits & ~aUnitMask;
+        if (aBitIter == Graphic3d_TextureUnit_Normal)
+        {
+          myTextureRgbaBlack->Bind (this, static_cast<Graphic3d_TextureUnit>(aBitIter));
+        }
+        else
+        {
+          myTextureRgbaWhite->Bind (this, static_cast<Graphic3d_TextureUnit>(aBitIter));
+        }
       }
     }
-  #if !defined(GL_ES_VERSION_2_0)
-    if (core11 != NULL)
-    {
-      OpenGl_Sampler::applyGlobalTextureParams (aThisCtx, *aTextureNew, aTextureNew->Sampler()->Parameters());
-    }
-  #endif
-    aTextureIterNew.Next();
   }
 
-  Handle(OpenGl_TextureSet) anOldTextures = myActiveTextures;
-  myActiveTextures = theTextures;
   return anOldTextures;
 }
 
@@ -3153,12 +2367,12 @@ Handle(OpenGl_FrameBuffer) OpenGl_Context::SetDefaultFrameBuffer (const Handle(O
 // function : SetShadingMaterial
 // purpose  :
 // =======================================================================
-void OpenGl_Context::SetShadingMaterial (const OpenGl_AspectFace* theAspect,
+void OpenGl_Context::SetShadingMaterial (const OpenGl_Aspects* theAspect,
                                          const Handle(Graphic3d_PresentationAttributes)& theHighlight)
 {
-  const Handle(Graphic3d_AspectFillArea3d)& anAspect = (!theHighlight.IsNull() && !theHighlight->BasicFillAreaAspect().IsNull())
-                                                      ?  theHighlight->BasicFillAreaAspect()
-                                                      :  theAspect->Aspect();
+  const Handle(Graphic3d_Aspects)& anAspect = (!theHighlight.IsNull() && !theHighlight->BasicFillAreaAspect().IsNull())
+                                            ?  (const Handle(Graphic3d_Aspects)& )theHighlight->BasicFillAreaAspect()
+                                            :  theAspect->Aspect();
 
   const bool toDistinguish = anAspect->Distinguish();
   const bool toMapTexture  = anAspect->ToMapTexture();
@@ -3171,61 +2385,70 @@ void OpenGl_Context::SetShadingMaterial (const OpenGl_AspectFace* theAspect,
                                        ? anAspect->BackInteriorColor()
                                        : aFrontIntColor;
 
-  myMatFront.Init (aMatFrontSrc, aFrontIntColor);
-  if (toDistinguish)
-  {
-    myMatBack.Init (aMatBackSrc, aBackIntColor);
-  }
-  else
-  {
-    myMatBack = myMatFront;
-  }
-
+  myMaterial.Init (*this, aMatFrontSrc, aFrontIntColor, aMatBackSrc, aBackIntColor);
   if (!theHighlight.IsNull()
     && theHighlight->BasicFillAreaAspect().IsNull())
   {
-    myMatFront.SetColor (theHighlight->ColorRGBA());
-    myMatBack .SetColor (theHighlight->ColorRGBA());
+    myMaterial.SetColor (theHighlight->ColorRGBA().GetRGB());
+    myMaterial.SetColor (theHighlight->ColorRGBA().GetRGB());
   }
 
-  Standard_ShortReal anAlphaFront = 1.0f;
-  Standard_ShortReal anAlphaBack  = 1.0f;
+  float anAlphaFront = 1.0f, anAlphaBack = 1.0f;
   if (CheckIsTransparent (theAspect, theHighlight, anAlphaFront, anAlphaBack))
   {
-    myMatFront.Diffuse.a() = anAlphaFront;
-    myMatBack .Diffuse.a() = anAlphaBack;
+    myMaterial.Common[0].Diffuse.a() = anAlphaFront;
+    myMaterial.Common[1].Diffuse.a() = anAlphaBack;
+
+    myMaterial.Pbr[0].BaseColor.a() = anAlphaFront;
+    myMaterial.Pbr[1].BaseColor.a() = anAlphaBack;
   }
 
   // do not update material properties in case of zero reflection mode,
   // because GL lighting will be disabled by OpenGl_PrimitiveArray::DrawArray() anyway.
-  if (theAspect->IsNoLighting())
+  const OpenGl_MaterialState& aMatState = myShaderManager->MaterialState();
+  float anAlphaCutoff = (anAspect->AlphaMode() == Graphic3d_AlphaMode_Mask
+                      || anAspect->AlphaMode() == Graphic3d_AlphaMode_MaskBlend)
+                      ? anAspect->AlphaCutoff()
+                      : ShortRealLast();
+  if (anAspect->ToDrawEdges())
   {
-    return;
+    if (anAspect->InteriorStyle() == Aspect_IS_EMPTY
+     || (anAspect->InteriorStyle() == Aspect_IS_SOLID
+      && anAspect->EdgeColorRGBA().Alpha() < 1.0f))
+    {
+      anAlphaCutoff = 0.285f;
+    }
   }
-
-  if (myMatFront    == myShaderManager->MaterialState().FrontMaterial()
-   && myMatBack     == myShaderManager->MaterialState().BackMaterial()
-   && toDistinguish == myShaderManager->MaterialState().ToDistinguish()
-   && toMapTexture  == myShaderManager->MaterialState().ToMapTexture())
+  if (theAspect->ShadingModel() == Graphic3d_TOSM_UNLIT)
+  {
+    if (anAlphaCutoff == aMatState.AlphaCutoff())
+    {
+      return;
+    }
+  }
+  else if (myMaterial.IsEqual (aMatState.Material())
+        && toDistinguish == aMatState.ToDistinguish()
+        && toMapTexture  == aMatState.ToMapTexture()
+        && anAlphaCutoff == aMatState.AlphaCutoff())
   {
     return;
   }
 
-  myShaderManager->UpdateMaterialStateTo (myMatFront, myMatBack, toDistinguish, toMapTexture);
+  myShaderManager->UpdateMaterialStateTo (myMaterial, anAlphaCutoff, toDistinguish, toMapTexture);
 }
 
 // =======================================================================
 // function : CheckIsTransparent
 // purpose  :
 // =======================================================================
-Standard_Boolean OpenGl_Context::CheckIsTransparent (const OpenGl_AspectFace* theAspect,
+Standard_Boolean OpenGl_Context::CheckIsTransparent (const OpenGl_Aspects* theAspect,
                                                      const Handle(Graphic3d_PresentationAttributes)& theHighlight,
                                                      Standard_ShortReal& theAlphaFront,
                                                      Standard_ShortReal& theAlphaBack)
 {
-  const Handle(Graphic3d_AspectFillArea3d)& anAspect = (!theHighlight.IsNull() && !theHighlight->BasicFillAreaAspect().IsNull())
-                                                      ?  theHighlight->BasicFillAreaAspect()
-                                                      :  theAspect->Aspect();
+  const Handle(Graphic3d_Aspects)& anAspect = (!theHighlight.IsNull() && !theHighlight->BasicFillAreaAspect().IsNull())
+                                            ?  (const Handle(Graphic3d_Aspects)& )theHighlight->BasicFillAreaAspect()
+                                            :  theAspect->Aspect();
 
   const bool toDistinguish = anAspect->Distinguish();
   const Graphic3d_MaterialAspect& aMatFrontSrc = anAspect->FrontMaterial();
@@ -3246,9 +2469,13 @@ Standard_Boolean OpenGl_Context::CheckIsTransparent (const OpenGl_AspectFace* th
     theAlphaBack  = aMatBackSrc .Alpha();
   }
 
-  const bool isTransparent = theAlphaFront < 1.0f
-                          || theAlphaBack  < 1.0f;
-  return isTransparent;
+  if (anAspect->AlphaMode() == Graphic3d_AlphaMode_BlendAuto)
+  {
+    return theAlphaFront < 1.0f
+        || theAlphaBack  < 1.0f;
+  }
+  // Graphic3d_AlphaMode_Mask and Graphic3d_AlphaMode_MaskBlend are not considered transparent here
+  return anAspect->AlphaMode() == Graphic3d_AlphaMode_Blend;
 }
 
 // =======================================================================
@@ -3259,12 +2486,15 @@ void OpenGl_Context::SetColor4fv (const OpenGl_Vec4& theColor)
 {
   if (!myActiveProgram.IsNull())
   {
-    myActiveProgram->SetUniform (this, myActiveProgram->GetStateLocation (OpenGl_OCCT_COLOR), theColor);
+    if (const OpenGl_ShaderUniformLocation& aLoc = myActiveProgram->GetStateLocation (OpenGl_OCCT_COLOR))
+    {
+      myActiveProgram->SetUniform (this, aLoc, Vec4FromQuantityColor (theColor));
+    }
   }
 #if !defined(GL_ES_VERSION_2_0)
-  else if (core11 != NULL)
+  else if (core11ffp != NULL)
   {
-    core11->glColor4fv (theColor.GetData());
+    core11ffp->glColor4fv (theColor.GetData());
   }
 #endif
 }
@@ -3276,75 +2506,55 @@ void OpenGl_Context::SetColor4fv (const OpenGl_Vec4& theColor)
 void OpenGl_Context::SetTypeOfLine (const Aspect_TypeOfLine  theType,
                                     const Standard_ShortReal theFactor)
 {
-  Standard_Integer aPattern = 0xFFFF;
-  switch (theType)
-  {
-    case Aspect_TOL_DASH:
-    {
-      aPattern = 0xFFC0;
-      break;
-    }
-    case Aspect_TOL_DOT:
-    {
-      aPattern = 0xCCCC;
-      break;
-    }
-    case Aspect_TOL_DOTDASH:
-    {
-      aPattern = 0xFF18;
-      break;
-    }
-    case Aspect_TOL_EMPTY:
-    case Aspect_TOL_SOLID:
-    {
-      aPattern = 0xFFFF;
-      break;
-    }
-    case Aspect_TOL_USERDEFINED:
-    {
-      aPattern = 0xFF24;
-      break;
-    }
-  }
+  SetLineStipple (theFactor, Graphic3d_Aspects::DefaultLinePatternForType (theType));
+}
 
+// =======================================================================
+// function : SetLineStipple
+// purpose  :
+// =======================================================================
+void OpenGl_Context::SetLineStipple (const Standard_ShortReal theFactor,
+                                     const uint16_t thePattern)
+{
   if (!myActiveProgram.IsNull())
   {
-    myActiveProgram->SetUniform (this, "uPattern", aPattern);
-    myActiveProgram->SetUniform (this, "uFactor",  theFactor);
+    if (const OpenGl_ShaderUniformLocation aPatternLoc = myActiveProgram->GetStateLocation (OpenGl_OCCT_LINE_STIPPLE_PATTERN))
+    {
+      if (hasGlslBitwiseOps != OpenGl_FeatureNotAvailable)
+      {
+        myActiveProgram->SetUniform (this, aPatternLoc, (Standard_Integer )thePattern);
+      }
+      else
+      {
+        Standard_Integer aPatArr[16] = {};
+        for (unsigned int aBit = 0; aBit < 16; ++aBit)
+        {
+          aPatArr[aBit] = ((unsigned int)(thePattern) & (1U << aBit)) != 0 ? 1 : 0;
+        }
+        myActiveProgram->SetUniform (this, aPatternLoc, 16, aPatArr);
+      }
+      myActiveProgram->SetUniform (this, myActiveProgram->GetStateLocation (OpenGl_OCCT_LINE_STIPPLE_FACTOR), theFactor);
+    }
     return;
   }
 
 #if !defined(GL_ES_VERSION_2_0)
-  if (aPattern != 0xFFFF)
+  if (thePattern != 0xFFFF)
   {
-  #ifdef HAVE_GL2PS
-    if (IsFeedback())
-    {
-      gl2psEnable (GL2PS_LINE_STIPPLE);
-    }
-  #endif
-
-    if (core11 != NULL)
+    if (core11ffp != NULL)
     {
       core11fwd->glEnable (GL_LINE_STIPPLE);
 
-      core11->glLineStipple (static_cast<GLint>    (theFactor),
-                             static_cast<GLushort> (aPattern));
+      core11ffp->glLineStipple (static_cast<GLint>    (theFactor),
+                                static_cast<GLushort> (thePattern));
     }
   }
   else
   {
-    if (core11 != NULL)
+    if (core11ffp != NULL)
     {
       core11fwd->glDisable (GL_LINE_STIPPLE);
     }
-
-  #ifdef HAVE_GL2PS
-    if (IsFeedback())
-    {
-      gl2psDisable (GL2PS_LINE_STIPPLE);
-    }
-  #endif
   }
 #endif
 }
@@ -3355,30 +2565,30 @@ void OpenGl_Context::SetTypeOfLine (const Aspect_TypeOfLine  theType,
 // =======================================================================
 void OpenGl_Context::SetLineWidth (const Standard_ShortReal theWidth)
 {
-  if (core11 != NULL)
+#if !defined(GL_ES_VERSION_2_0)
+  if (core11ffp != NULL)
+#endif
   {
     // glLineWidth() is still defined within Core Profile, but has no effect with values != 1.0f
     core11fwd->glLineWidth (theWidth * myLineWidthScale);
   }
-#ifdef HAVE_GL2PS
-  if (IsFeedback())
-  {
-    gl2psLineWidth (theWidth);
-  }
-#endif
 }
 
 // =======================================================================
 // function : SetTextureMatrix
 // purpose  :
 // =======================================================================
-void OpenGl_Context::SetTextureMatrix (const Handle(Graphic3d_TextureParams)& theParams)
+void OpenGl_Context::SetTextureMatrix (const Handle(Graphic3d_TextureParams)& theParams,
+                                       const Standard_Boolean theIsTopDown)
 {
   if (theParams.IsNull())
   {
     return;
   }
-  else if (!myActiveProgram.IsNull())
+
+  const Graphic3d_Vec2& aScale = theParams->Scale();
+  const Graphic3d_Vec2& aTrans = theParams->Translation();
+  if (!myActiveProgram.IsNull())
   {
     const GLint aUniLoc = myActiveProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_TRSF2D);
     if (aUniLoc == OpenGl_ShaderProgram::INVALID_LOCATION)
@@ -3387,31 +2597,45 @@ void OpenGl_Context::SetTextureMatrix (const Handle(Graphic3d_TextureParams)& th
     }
 
     // pack transformation parameters
-    OpenGl_Vec4 aTrsf[2];
-    aTrsf[0].x()  = -theParams->Translation().x();
-    aTrsf[0].y()  = -theParams->Translation().y();
-    aTrsf[0].zw() = theParams->Scale();
-    aTrsf[1].x()  = std::sin (-theParams->Rotation() * static_cast<float> (M_PI / 180.0));
-    aTrsf[1].y()  = std::cos (-theParams->Rotation() * static_cast<float> (M_PI / 180.0));
+    OpenGl_Vec4 aTrsf[2] =
+    {
+      OpenGl_Vec4 (-aTrans.x(), -aTrans.y(), aScale.x(), aScale.y()),
+      OpenGl_Vec4 (static_cast<float> (std::sin (-theParams->Rotation() * M_PI / 180.0)),
+                   static_cast<float> (std::cos (-theParams->Rotation() * M_PI / 180.0)),
+                   0.0f, 0.0f)
+    };
+    if (caps->isTopDownTextureUV != theIsTopDown)
+    {
+      // flip V
+      aTrsf[0].y() = -aTrans.y() + 1.0f / aScale.y();
+      aTrsf[0].w() = -aScale.y();
+    }
     myActiveProgram->SetUniform (this, aUniLoc, 2, aTrsf);
     return;
   }
 
 #if !defined(GL_ES_VERSION_2_0)
-  if (core11 != NULL)
+  if (core11ffp != NULL)
   {
     GLint aMatrixMode = GL_TEXTURE;
     ::glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode);
 
-    core11->glMatrixMode (GL_TEXTURE);
+    core11ffp->glMatrixMode (GL_TEXTURE);
     OpenGl_Mat4 aTextureMat;
-    const Graphic3d_Vec2& aScale = theParams->Scale();
-    const Graphic3d_Vec2& aTrans = theParams->Translation();
-    Graphic3d_TransformUtils::Scale     (aTextureMat,  aScale.x(),  aScale.y(), 1.0f);
-    Graphic3d_TransformUtils::Translate (aTextureMat, -aTrans.x(), -aTrans.y(), 0.0f);
-    Graphic3d_TransformUtils::Rotate    (aTextureMat, -theParams->Rotation(), 0.0f, 0.0f, 1.0f);
-    core11->glLoadMatrixf (aTextureMat);
-    core11->glMatrixMode (aMatrixMode);
+    if (caps->isTopDownTextureUV != theIsTopDown)
+    {
+      // flip V
+      Graphic3d_TransformUtils::Scale     (aTextureMat,  aScale.x(), -aScale.y(), 1.0f);
+      Graphic3d_TransformUtils::Translate (aTextureMat, -aTrans.x(), -aTrans.y() + 1.0f / aScale.y(), 0.0f);
+    }
+    else
+    {
+      Graphic3d_TransformUtils::Scale     (aTextureMat,  aScale.x(),  aScale.y(), 1.0f);
+      Graphic3d_TransformUtils::Translate (aTextureMat, -aTrans.x(), -aTrans.y(), 0.0f);
+    }
+    Graphic3d_TransformUtils::Rotate (aTextureMat, -theParams->Rotation(), 0.0f, 0.0f, 1.0f);
+    core11ffp->glLoadMatrixf (aTextureMat.GetData());
+    core11ffp->glMatrixMode (aMatrixMode);
   }
 #endif
 }
@@ -3474,19 +2698,17 @@ Standard_Boolean OpenGl_Context::SetGlNormalizeEnabled (Standard_Boolean isEnabl
   }
 
   Standard_Boolean anOldGlNormalize = myIsGlNormalizeEnabled;
-
   myIsGlNormalizeEnabled = isEnabled;
-
 #if !defined(GL_ES_VERSION_2_0)
-  if (core11 != NULL)
+  if (core11ffp != NULL)
   {
     if (isEnabled)
     {
-      ::glEnable  (GL_NORMALIZE);
+      core11fwd->glEnable  (GL_NORMALIZE);
     }
     else
     {
-      ::glDisable (GL_NORMALIZE);
+      core11fwd->glDisable (GL_NORMALIZE);
     }
   }
 #endif
@@ -3494,6 +2716,29 @@ Standard_Boolean OpenGl_Context::SetGlNormalizeEnabled (Standard_Boolean isEnabl
   return anOldGlNormalize;
 }
 
+// =======================================================================
+// function : SetShadeModel
+// purpose  :
+// =======================================================================
+void OpenGl_Context::SetShadeModel (Graphic3d_TypeOfShadingModel theModel)
+{
+#if !defined(GL_ES_VERSION_2_0)
+  if (core11ffp != NULL)
+  {
+    const Standard_Integer aModel = theModel == Graphic3d_TOSM_FACET
+                                 || theModel == Graphic3d_TOSM_PBR_FACET ? GL_FLAT : GL_SMOOTH;
+    if (myShadeModel == aModel)
+    {
+      return;
+    }
+    myShadeModel = aModel;
+    core11ffp->glShadeModel (aModel);
+  }
+#else
+  (void )theModel;
+#endif
+}
+
 // =======================================================================
 // function : SetPolygonMode
 // purpose  :
@@ -3522,16 +2767,29 @@ Standard_Integer OpenGl_Context::SetPolygonMode (const Standard_Integer theMode)
 // =======================================================================
 bool OpenGl_Context::SetPolygonHatchEnabled (const bool theIsEnabled)
 {
-  if (myHatchStyles.IsNull())
+  if (core11ffp == NULL)
   {
     return false;
   }
-  else if (myHatchStyles->IsEnabled() == theIsEnabled)
+  else if (myHatchIsEnabled == theIsEnabled)
   {
     return theIsEnabled;
   }
 
-  return myHatchStyles->SetEnabled (this, theIsEnabled);
+  const bool anOldIsEnabled = myHatchIsEnabled;
+#if !defined(GL_ES_VERSION_2_0)
+  if (theIsEnabled
+   && myActiveHatchType != Aspect_HS_SOLID)
+  {
+    core11fwd->glEnable (GL_POLYGON_STIPPLE);
+  }
+  else
+  {
+    core11fwd->glDisable (GL_POLYGON_STIPPLE);
+  }
+#endif
+  myHatchIsEnabled = theIsEnabled;
+  return anOldIsEnabled;
 }
 
 // =======================================================================
@@ -3540,26 +2798,43 @@ bool OpenGl_Context::SetPolygonHatchEnabled (const bool theIsEnabled)
 // =======================================================================
 Standard_Integer OpenGl_Context::SetPolygonHatchStyle (const Handle(Graphic3d_HatchStyle)& theStyle)
 {
-  if (theStyle.IsNull())
+  const Standard_Integer aNewStyle = !theStyle.IsNull() ? theStyle->HatchType() : Aspect_HS_SOLID;
+  if (myActiveHatchType == aNewStyle
+   || core11ffp == NULL)
   {
-    return 0;
+    return myActiveHatchType;
   }
 
-  if (myHatchStyles.IsNull())
+#if !defined(GL_ES_VERSION_2_0)
+  if (aNewStyle == Aspect_HS_SOLID)
   {
-    if (!GetResource ("OpenGl_LineAttributes", myHatchStyles))
+    if (myHatchIsEnabled)
     {
-      // share and register for release once the resource is no longer used
-      myHatchStyles = new OpenGl_LineAttributes();
-      ShareResource ("OpenGl_LineAttributes", myHatchStyles);
+      core11fwd->glDisable (GL_POLYGON_STIPPLE);
     }
+    return myActiveHatchType;
   }
-  if (myHatchStyles->TypeOfHatch() == theStyle->HatchType())
+
+  if (myHatchStyles.IsNull()
+  && !GetResource ("OpenGl_LineAttributes", myHatchStyles))
   {
-    return theStyle->HatchType();
+    // share and register for release once the resource is no longer used
+    myHatchStyles = new OpenGl_LineAttributes();
+    ShareResource ("OpenGl_LineAttributes", myHatchStyles);
   }
 
-  return myHatchStyles->SetTypeOfHatch (this, theStyle);
+  const Standard_Integer anOldType = myActiveHatchType;
+  myActiveHatchType = aNewStyle;
+  myHatchStyles->SetTypeOfHatch (this, theStyle);
+  if (myHatchIsEnabled
+   && anOldType == Aspect_HS_SOLID)
+  {
+    core11fwd->glEnable (GL_POLYGON_STIPPLE);
+  }
+  return anOldType;
+#else
+  return myActiveHatchType;
+#endif
 }
 
 // =======================================================================
@@ -3574,11 +2849,11 @@ void OpenGl_Context::SetPolygonOffset (const Graphic3d_PolygonOffset& theOffset)
   {
     if (toFillNew)
     {
-      glEnable (GL_POLYGON_OFFSET_FILL);
+      core11fwd->glEnable (GL_POLYGON_OFFSET_FILL);
     }
     else
     {
-      glDisable (GL_POLYGON_OFFSET_FILL);
+      core11fwd->glDisable (GL_POLYGON_OFFSET_FILL);
     }
   }
 
@@ -3589,11 +2864,11 @@ void OpenGl_Context::SetPolygonOffset (const Graphic3d_PolygonOffset& theOffset)
   {
     if (toLineNew)
     {
-      glEnable (GL_POLYGON_OFFSET_LINE);
+      core11fwd->glEnable (GL_POLYGON_OFFSET_LINE);
     }
     else
     {
-      glDisable (GL_POLYGON_OFFSET_LINE);
+      core11fwd->glDisable (GL_POLYGON_OFFSET_LINE);
     }
   }
 
@@ -3603,11 +2878,11 @@ void OpenGl_Context::SetPolygonOffset (const Graphic3d_PolygonOffset& theOffset)
   {
     if (toPointNew)
     {
-      glEnable (GL_POLYGON_OFFSET_POINT);
+      core11fwd->glEnable (GL_POLYGON_OFFSET_POINT);
     }
     else
     {
-      glDisable (GL_POLYGON_OFFSET_POINT);
+      core11fwd->glDisable (GL_POLYGON_OFFSET_POINT);
     }
   }
 #endif
@@ -3615,11 +2890,27 @@ void OpenGl_Context::SetPolygonOffset (const Graphic3d_PolygonOffset& theOffset)
   if (myPolygonOffset.Factor != theOffset.Factor
    || myPolygonOffset.Units  != theOffset.Units)
   {
-    glPolygonOffset (theOffset.Factor, theOffset.Units);
+    core11fwd->glPolygonOffset (theOffset.Factor, theOffset.Units);
   }
   myPolygonOffset = theOffset;
 }
 
+// =======================================================================
+// function : SetCamera
+// purpose  :
+// =======================================================================
+void OpenGl_Context::SetCamera (const Handle(Graphic3d_Camera)& theCamera)
+{
+  myCamera = theCamera;
+  if (!theCamera.IsNull())
+  {
+    ProjectionState.SetCurrent (theCamera->ProjectionMatrixF());
+    WorldViewState .SetCurrent (theCamera->OrientationMatrixF());
+    ApplyProjectionMatrix();
+    ApplyWorldViewMatrix();
+  }
+}
+
 // =======================================================================
 // function : ApplyModelWorldMatrix
 // purpose  :
@@ -3692,24 +2983,24 @@ void OpenGl_Context::EnableFeatures() const
 void OpenGl_Context::DisableFeatures() const
 {
   // Disable stuff that's likely to slow down glDrawPixels.
-  glDisable(GL_DITHER);
-  glDisable(GL_BLEND);
-  glDisable(GL_DEPTH_TEST);
-  glDisable(GL_STENCIL_TEST);
+  core11fwd->glDisable(GL_DITHER);
+  core11fwd->glDisable(GL_BLEND);
+  core11fwd->glDisable(GL_DEPTH_TEST);
+  core11fwd->glDisable(GL_STENCIL_TEST);
 
 #if !defined(GL_ES_VERSION_2_0)
-  if (core11 == NULL)
+  if (core11ffp == NULL)
   {
     return;
   }
 
-  glDisable(GL_TEXTURE_1D);
-  glDisable(GL_TEXTURE_2D);
+  core11fwd->glDisable(GL_TEXTURE_1D);
+  core11fwd->glDisable(GL_TEXTURE_2D);
 
-  glDisable(GL_LIGHTING);
-  glDisable(GL_ALPHA_TEST);
-  glDisable(GL_FOG);
-  glDisable(GL_LOGIC_OP);
+  core11fwd->glDisable(GL_LIGHTING);
+  core11fwd->glDisable(GL_ALPHA_TEST);
+  core11fwd->glDisable(GL_FOG);
+  core11fwd->glDisable(GL_LOGIC_OP);
 
   glPixelTransferi(GL_MAP_COLOR, GL_FALSE);
   glPixelTransferi(GL_RED_SCALE, 1);
@@ -3724,36 +3015,189 @@ void OpenGl_Context::DisableFeatures() const
   if ((myGlVerMajor >= 1) && (myGlVerMinor >= 2))
   {
     if (CheckExtension ("GL_CONVOLUTION_1D_EXT"))
-      glDisable(GL_CONVOLUTION_1D_EXT);
+      core11fwd->glDisable(GL_CONVOLUTION_1D_EXT);
 
     if (CheckExtension ("GL_CONVOLUTION_2D_EXT"))
-      glDisable(GL_CONVOLUTION_2D_EXT);
+      core11fwd->glDisable(GL_CONVOLUTION_2D_EXT);
 
     if (CheckExtension ("GL_SEPARABLE_2D_EXT"))
-      glDisable(GL_SEPARABLE_2D_EXT);
+      core11fwd->glDisable(GL_SEPARABLE_2D_EXT);
 
     if (CheckExtension ("GL_SEPARABLE_2D_EXT"))
-      glDisable(GL_HISTOGRAM_EXT);
+      core11fwd->glDisable(GL_HISTOGRAM_EXT);
 
     if (CheckExtension ("GL_MINMAX_EXT"))
-      glDisable(GL_MINMAX_EXT);
+      core11fwd->glDisable(GL_MINMAX_EXT);
 
     if (CheckExtension ("GL_TEXTURE_3D_EXT"))
-      glDisable(GL_TEXTURE_3D_EXT);
+      core11fwd->glDisable(GL_TEXTURE_3D_EXT);
   }
 #endif
 }
 
+// =======================================================================
+// function : SetColorMaskRGBA
+// purpose  :
+// =======================================================================
+void OpenGl_Context::SetColorMaskRGBA (const NCollection_Vec4<bool>& theVal)
+{
+  core11fwd->glColorMask (theVal.r() ? GL_TRUE : GL_FALSE,
+               theVal.g() ? GL_TRUE : GL_FALSE,
+               theVal.b() ? GL_TRUE : GL_FALSE,
+               theVal.a() ? GL_TRUE : GL_FALSE);
+  myColorMask = theVal;
+}
+
 // =======================================================================
 // function : SetColorMask
 // purpose  :
 // =======================================================================
 bool OpenGl_Context::SetColorMask (bool theToWriteColor)
 {
+  const bool anOldValue = myColorMask.r();
+  myColorMask.SetValues (theToWriteColor, theToWriteColor, theToWriteColor, caps->buffersOpaqueAlpha ? false : theToWriteColor);
   const GLboolean toWrite = theToWriteColor ? GL_TRUE : GL_FALSE;
-  glColorMask (toWrite, toWrite, toWrite, toWrite);
+  core11fwd->glColorMask (toWrite, toWrite, toWrite, myColorMask.a() ? GL_TRUE : GL_FALSE);
+  return anOldValue;
+}
 
-  const bool anOldValue = myColorMask;
-  myColorMask = theToWriteColor;
+// =======================================================================
+// function : SetSampleAlphaToCoverage
+// purpose  :
+// =======================================================================
+bool OpenGl_Context::SetSampleAlphaToCoverage (bool theToEnable)
+{
+  bool toEnable = myAllowAlphaToCov && theToEnable;
+  if (myAlphaToCoverage == toEnable)
+  {
+    return myAlphaToCoverage;
+  }
+
+  if (core15fwd != NULL)
+  {
+    if (toEnable)
+    {
+      //core15fwd->core15fwd->glSampleCoverage (1.0f, GL_FALSE);
+      core15fwd->glEnable (GL_SAMPLE_ALPHA_TO_COVERAGE);
+    }
+    else
+    {
+      core15fwd->glDisable (GL_SAMPLE_ALPHA_TO_COVERAGE);
+    }
+  }
+
+  const bool anOldValue = myAlphaToCoverage;
+  myAlphaToCoverage = toEnable;
   return anOldValue;
 }
+
+// =======================================================================
+// function : GetBufferSubData
+// purpose  :
+// =======================================================================
+bool OpenGl_Context::GetBufferSubData (GLenum theTarget, GLintptr theOffset, GLsizeiptr theSize, void* theData)
+{
+  if (!hasGetBufferData)
+  {
+    return false;
+  }
+#ifdef __EMSCRIPTEN__
+  EM_ASM_(
+  {
+    Module.ctx.getBufferSubData($0, $1, HEAPU8.subarray($2, $2 + $3));
+  }, theTarget, theOffset, theData, theSize);
+  return true;
+#elif defined(GL_ES_VERSION_2_0)
+  if (void* aData = core30->glMapBufferRange (theTarget, theOffset, theSize, GL_MAP_READ_BIT))
+  {
+    memcpy (theData, aData, theSize);
+    core30->glUnmapBuffer (theTarget);
+    return true;
+  }
+  return false;
+#else
+  core15fwd->glGetBufferSubData (theTarget, theOffset, theSize, theData);
+  return true;
+#endif
+}
+
+// =======================================================================
+// function : DumpJson
+// purpose  :
+// =======================================================================
+void OpenGl_Context::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
+{
+  OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
+
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myAnisoMax)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myTexClamp)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMaxTexDim)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMaxTexCombined)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMaxDumpSizeX)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMaxDumpSizeY)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMaxClipPlanes)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMaxMsaaSamples)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMaxDrawBuffers)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMaxColorAttachments)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myGlVerMajor)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myGlVerMinor)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsInitialized)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsStereoBuffers)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsGlNormalizeEnabled)
+
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myHasRayTracing)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myHasRayTracingTextures)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myHasRayTracingAdaptiveSampling)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myHasRayTracingAdaptiveSamplingAtomic)
+
+  for (int i = 0; i < 4; i++)
+  {
+    OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myViewport[i])
+  }
+
+  for (int i = 0; i < 4; i++)
+  {
+    OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myViewportVirt[i])
+  }
+
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myPointSpriteOrig)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myRenderMode)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myPolygonMode)
+  OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myPolygonOffset)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myToCullBackFaces)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myReadBuffer)
+
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myDefaultVao)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myColorMask)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myAllowAlphaToCov)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myAlphaToCoverage)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsGlDebugCtx)
+
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myResolution)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myResolutionRatio)
+
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myLineWidthScale)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myLineFeather)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myRenderScale)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myRenderScaleInv)
+  
+  OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &ModelWorldState)
+  OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &WorldViewState)
+  OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &ProjectionState)
+}
+
+// =======================================================================
+// function : DumpJsonOpenGlState
+// purpose  :
+// =======================================================================
+void OpenGl_Context::DumpJsonOpenGlState (Standard_OStream& theOStream, Standard_Integer)
+{
+  GLboolean isEnableBlend = glIsEnabled (GL_BLEND);
+  GLboolean isEnableCullFace = glIsEnabled (GL_CULL_FACE);
+  GLboolean isEnableDepthTest = glIsEnabled (GL_DEPTH_TEST);
+  
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, isEnableBlend)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, isEnableCullFace)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, isEnableDepthTest)
+}
+