0032308: Configuration - make Xlib dependency optional
[occt.git] / src / OpenGl / OpenGl_Context.cxx
1 // Created on: 2012-01-26
2 // Created by: Kirill GAVRILOV
3 // Copyright (c) 2012-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #if defined(_WIN32)
17   #include <windows.h>
18 #endif
19
20 #include <OpenGl_Context.hxx>
21
22 #include <OpenGl_ArbTBO.hxx>
23 #include <OpenGl_ArbIns.hxx>
24 #include <OpenGl_ArbDbg.hxx>
25 #include <OpenGl_ArbFBO.hxx>
26 #include <OpenGl_ExtGS.hxx>
27 #include <OpenGl_ArbSamplerObject.hxx>
28 #include <OpenGl_ArbTexBindless.hxx>
29 #include <OpenGl_GlCore46.hxx>
30 #include <OpenGl_FrameBuffer.hxx>
31 #include <OpenGl_FrameStats.hxx>
32 #include <OpenGl_Sampler.hxx>
33 #include <OpenGl_ShaderManager.hxx>
34 #include <OpenGl_TextureSetPairIterator.hxx>
35 #include <OpenGl_Workspace.hxx>
36 #include <OpenGl_Aspects.hxx>
37
38 #include <Graphic3d_TransformUtils.hxx>
39 #include <Graphic3d_RenderingParams.hxx>
40 #include <Image_SupportedFormats.hxx>
41 #include <Message_Messenger.hxx>
42 #include <NCollection_Vector.hxx>
43 #include <Standard_ProgramError.hxx>
44 #include <Standard_WarningDisableFunctionCast.hxx>
45
46 #if defined(_WIN32) && defined(max)
47   #undef max
48 #endif
49 #include <limits>
50
51 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Context,Standard_Transient)
52
53 #if defined(HAVE_EGL)
54   #include <EGL/egl.h>
55   #ifdef _MSC_VER
56     #pragma comment(lib, "libEGL.lib")
57   #endif
58 #elif defined(_WIN32)
59   //
60 #elif defined(HAVE_XLIB)
61   #include <GL/glx.h> // glXGetProcAddress()
62 #elif defined(__APPLE__)
63   #include <dlfcn.h>
64   #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
65     //
66   #else
67     #include <OpenGL/OpenGL.h>
68     #include <CoreGraphics/CoreGraphics.h>
69   #endif
70 #else
71   //
72 #endif
73
74 #ifdef __EMSCRIPTEN__
75   #include <emscripten.h>
76   #include <emscripten/html5.h>
77
78   //! Check if WebGL extension is available and activate it
79   //! (usage of extension without activation will generate errors).
80   static bool checkEnableWebGlExtension (const OpenGl_Context& theCtx,
81                                          const char* theExtName)
82   {
83     if (!theCtx.CheckExtension (theExtName))
84     {
85       return false;
86     }
87     if (EMSCRIPTEN_WEBGL_CONTEXT_HANDLE aWebGlCtx = emscripten_webgl_get_current_context())
88     {
89       if (emscripten_webgl_enable_extension (aWebGlCtx, theExtName))
90       {
91         return true;
92       }
93     }
94     return false;
95   }
96 #endif
97
98 namespace
99 {
100   static const Handle(OpenGl_Resource) NULL_GL_RESOURCE;
101   static const OpenGl_Mat4 THE_IDENTITY_MATRIX;
102
103   //! Add key-value pair to the dictionary.
104   static void addInfo (TColStd_IndexedDataMapOfStringString& theDict,
105                        const TCollection_AsciiString& theKey,
106                        const TCollection_AsciiString& theValue)
107   {
108     theDict.ChangeFromIndex (theDict.Add (theKey, theValue)) = theValue;
109   }
110
111   //! Add key-value pair to the dictionary.
112   static void addInfo (TColStd_IndexedDataMapOfStringString& theDict,
113                        const TCollection_AsciiString& theKey,
114                        const char* theValue)
115   {
116     TCollection_AsciiString aValue (theValue != NULL ? theValue : "");
117     theDict.ChangeFromIndex (theDict.Add (theKey, aValue)) = aValue;
118   }
119 }
120
121 // =======================================================================
122 // function : OpenGl_Context
123 // purpose  :
124 // =======================================================================
125 OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps)
126 : core11ffp  (NULL),
127   core11fwd  (NULL),
128   core15     (NULL),
129   core20     (NULL),
130   core30     (NULL),
131   core32     (NULL),
132   core33     (NULL),
133   core41     (NULL),
134   core42     (NULL),
135   core43     (NULL),
136   core44     (NULL),
137   core45     (NULL),
138   core46     (NULL),
139   core15fwd  (NULL),
140   core20fwd  (NULL),
141   caps   (!theCaps.IsNull() ? theCaps : new OpenGl_Caps()),
142   hasGetBufferData (Standard_False),
143 #if defined(GL_ES_VERSION_2_0)
144   hasPackRowLength (Standard_False),
145   hasUnpackRowLength (Standard_False),
146   hasHighp   (Standard_False),
147   hasUintIndex(Standard_False),
148   hasTexRGBA8(Standard_False),
149 #else
150   hasPackRowLength (Standard_True),
151   hasUnpackRowLength (Standard_True),
152   hasHighp   (Standard_True),
153   hasUintIndex(Standard_True),
154   hasTexRGBA8(Standard_True),
155 #endif
156   hasTexFloatLinear (Standard_False),
157   hasTexSRGB (Standard_False),
158   hasFboSRGB (Standard_False),
159   hasSRGBControl (Standard_False),
160   hasFboRenderMipmap (Standard_False),
161 #if defined(GL_ES_VERSION_2_0)
162   hasFlatShading (OpenGl_FeatureNotAvailable),
163 #else
164   hasFlatShading (OpenGl_FeatureInCore),
165 #endif
166   hasGlslBitwiseOps  (OpenGl_FeatureNotAvailable),
167   hasDrawBuffers     (OpenGl_FeatureNotAvailable),
168   hasFloatBuffer     (OpenGl_FeatureNotAvailable),
169   hasHalfFloatBuffer (OpenGl_FeatureNotAvailable),
170   hasSampleVariables (OpenGl_FeatureNotAvailable),
171   hasGeometryStage   (OpenGl_FeatureNotAvailable),
172   arbDrawBuffers (Standard_False),
173   arbNPTW  (Standard_False),
174   arbTexRG (Standard_False),
175   arbTexFloat (Standard_False),
176   arbSamplerObject (NULL),
177   arbTexBindless (NULL),
178   arbTBO (NULL),
179   arbTboRGB32 (Standard_False),
180   arbClipControl (Standard_False),
181   arbIns (NULL),
182   arbDbg (NULL),
183   arbFBO (NULL),
184   arbFBOBlit (NULL),
185   arbSampleShading (Standard_False),
186   arbDepthClamp (Standard_False),
187   extFragDepth (Standard_False),
188   extDrawBuffers (Standard_False),
189   extGS  (NULL),
190   extBgra(Standard_False),
191   extAnis(Standard_False),
192   extPDS (Standard_False),
193   atiMem (Standard_False),
194   nvxMem (Standard_False),
195   oesSampleVariables (Standard_False),
196   oesStdDerivatives (Standard_False),
197   myWindow  (0),
198   myDisplay (0),
199   myGContext(0),
200   mySharedResources (new OpenGl_ResourcesMap()),
201   myDelayed         (new OpenGl_DelayReleaseMap()),
202   myUnusedResources (new OpenGl_ResourcesStack()),
203   myClippingState (),
204   myGlLibHandle (NULL),
205   myFuncs (new OpenGl_GlFunctions()),
206   mySupportedFormats (new Image_SupportedFormats()),
207   myAnisoMax   (1),
208   myTexClamp   (GL_CLAMP_TO_EDGE),
209   myMaxTexDim  (1024),
210   myMaxTexCombined (1),
211   myMaxTexUnitsFFP (1),
212   myMaxDumpSizeX (1024),
213   myMaxDumpSizeY (1024),
214   myMaxClipPlanes (6),
215   myMaxMsaaSamples(0),
216   myMaxDrawBuffers (1),
217   myMaxColorAttachments (1),
218   myGlVerMajor (0),
219   myGlVerMinor (0),
220   myIsInitialized (Standard_False),
221   myIsStereoBuffers (Standard_False),
222   myIsGlNormalizeEnabled (Standard_False),
223   mySpriteTexUnit (Graphic3d_TextureUnit_PointSprite),
224   myHasRayTracing (Standard_False),
225   myHasRayTracingTextures (Standard_False),
226   myHasRayTracingAdaptiveSampling (Standard_False),
227   myHasRayTracingAdaptiveSamplingAtomic (Standard_False),
228   myHasPBR (Standard_False),
229   myPBREnvLUTTexUnit       (Graphic3d_TextureUnit_PbrEnvironmentLUT),
230   myPBRDiffIBLMapSHTexUnit (Graphic3d_TextureUnit_PbrIblDiffuseSH),
231   myPBRSpecIBLMapTexUnit   (Graphic3d_TextureUnit_PbrIblSpecular),
232   myShadowMapTexUnit       (Graphic3d_TextureUnit_ShadowMap),
233   myDepthPeelingDepthTexUnit (Graphic3d_TextureUnit_DepthPeelingDepth),
234   myDepthPeelingFrontColorTexUnit (Graphic3d_TextureUnit_DepthPeelingFrontColor),
235   myFrameStats (new OpenGl_FrameStats()),
236   myActiveMockTextures (0),
237   myActiveHatchType (Aspect_HS_SOLID),
238   myHatchIsEnabled (false),
239 #if !defined(GL_ES_VERSION_2_0)
240   myPointSpriteOrig (GL_UPPER_LEFT),
241   myRenderMode (GL_RENDER),
242   myShadeModel (GL_SMOOTH),
243   myPolygonMode (GL_FILL),
244 #else
245   myPointSpriteOrig (0),
246   myRenderMode (0),
247   myShadeModel (0),
248   myPolygonMode (0),
249 #endif
250   myToCullBackFaces (false),
251   myReadBuffer (0),
252   myDrawBuffers (0, 7),
253   myDefaultVao (0),
254   myColorMask (true),
255   myAlphaToCoverage (false),
256   myIsGlDebugCtx (false),
257   myIsSRgbWindow (false),
258   myResolution (Graphic3d_RenderingParams::THE_DEFAULT_RESOLUTION),
259   myResolutionRatio (1.0f),
260   myLineWidthScale (1.0f),
261   myLineFeather (1.0f),
262   myRenderScale (1.0f),
263   myRenderScaleInv (1.0f)
264 {
265   myViewport[0] = 0;
266   myViewport[1] = 0;
267   myViewport[2] = 0;
268   myViewport[3] = 0;
269   myViewportVirt[0] = 0;
270   myViewportVirt[1] = 0;
271   myViewportVirt[2] = 0;
272   myViewportVirt[3] = 0;
273
274   myPolygonOffset.Mode   = Aspect_POM_Off;
275   myPolygonOffset.Factor = 0.0f;
276   myPolygonOffset.Units  = 0.0f;
277
278   // system-dependent fields
279 #if defined(HAVE_EGL)
280   myDisplay  = (Aspect_Display          )EGL_NO_DISPLAY;
281   myWindow   = (Aspect_Drawable         )EGL_NO_SURFACE;
282   myGContext = (Aspect_RenderingContext )EGL_NO_CONTEXT;
283 #elif defined(__APPLE__) && !defined(HAVE_XLIB)
284   // Vendors can not extend functionality on this system
285   // and developers are limited to OpenGL support provided by Mac OS X SDK.
286   // We retrieve function pointers from system library
287   // to generalize extensions support on all platforms.
288   // In this way we also reach binary compatibility benefit between OS releases
289   // if some newest functionality is optionally used.
290   // Notice that GL version / extension availability checks are required
291   // because function pointers may be available but not functionality itself
292   // (depends on renderer).
293 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
294   myGlLibHandle = dlopen ("/System/Library/Frameworks/OpenGLES.framework/OpenGLES", RTLD_LAZY);
295 #else
296   myGlLibHandle = dlopen ("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY);
297 #endif
298 #endif
299
300   memset (myFuncs.operator->(), 0, sizeof(OpenGl_GlFunctions));
301   myShaderManager = new OpenGl_ShaderManager (this);
302 }
303
304 // =======================================================================
305 // function : ~OpenGl_Context
306 // purpose  :
307 // =======================================================================
308 OpenGl_Context::~OpenGl_Context()
309 {
310   // release clean up queue
311   ReleaseDelayed();
312
313 #if !defined(GL_ES_VERSION_2_0)
314   // release default VAO
315   if (myDefaultVao != 0
316    && IsValid()
317    && core32 != NULL)
318   {
319     core32->glDeleteVertexArrays (1, &myDefaultVao);
320   }
321   myDefaultVao = 0;
322 #endif
323
324   // release mock textures
325   if (!myTextureRgbaBlack.IsNull())
326   {
327     myTextureRgbaBlack->Release (this);
328     myTextureRgbaBlack.Nullify();
329   }
330   if (!myTextureRgbaWhite.IsNull())
331   {
332     myTextureRgbaWhite->Release (this);
333     myTextureRgbaWhite.Nullify();
334   }
335
336   // release default FBO
337   if (!myDefaultFbo.IsNull())
338   {
339     myDefaultFbo->Release (this);
340     myDefaultFbo.Nullify();
341   }
342
343   // release shared resources if any
344   if (mySharedResources->GetRefCount() <= 1)
345   {
346     myShaderManager.Nullify();
347     for (NCollection_DataMap<TCollection_AsciiString, Handle(OpenGl_Resource)>::Iterator anIter (*mySharedResources);
348          anIter.More(); anIter.Next())
349     {
350       anIter.Value()->Release (this);
351     }
352
353     // release delayed resources added during deletion of shared resources
354     while (!myUnusedResources->IsEmpty())
355     {
356       myUnusedResources->First()->Release (this);
357       myUnusedResources->RemoveFirst();
358     }
359   }
360   else if (myShaderManager->IsSameContext (this))
361   {
362     myShaderManager->SetContext (NULL);
363   }
364   mySharedResources.Nullify();
365   myDelayed.Nullify();
366
367   if (arbDbg != NULL
368    && myIsGlDebugCtx
369    && IsValid())
370   {
371     // reset callback
372   #if !defined(GL_ES_VERSION_2_0)
373     void* aPtr = NULL;
374     glGetPointerv (GL_DEBUG_CALLBACK_USER_PARAM, &aPtr);
375     if (aPtr == this)
376   #endif
377     {
378       arbDbg->glDebugMessageCallback (NULL, NULL);
379     }
380     myIsGlDebugCtx = Standard_False;
381   }
382 }
383
384 // =======================================================================
385 // function : forcedRelease
386 // purpose  :
387 // =======================================================================
388 void OpenGl_Context::forcedRelease()
389 {
390   ReleaseDelayed();
391   for (NCollection_DataMap<TCollection_AsciiString, Handle(OpenGl_Resource)>::Iterator anIter (*mySharedResources);
392        anIter.More(); anIter.Next())
393   {
394     anIter.Value()->Release (this);
395   }
396   mySharedResources->Clear();
397   myShaderManager->clear();
398   myShaderManager->SetContext (NULL);
399
400   // release delayed resources added during deletion of shared resources
401   while (!myUnusedResources->IsEmpty())
402   {
403     myUnusedResources->First()->Release (this);
404     myUnusedResources->RemoveFirst();
405   }
406 }
407
408 // =======================================================================
409 // function : ResizeViewport
410 // purpose  :
411 // =======================================================================
412 void OpenGl_Context::ResizeViewport (const Standard_Integer* theRect)
413 {
414   core11fwd->glViewport (theRect[0], theRect[1], theRect[2], theRect[3]);
415   myViewport[0] = theRect[0];
416   myViewport[1] = theRect[1];
417   myViewport[2] = theRect[2];
418   myViewport[3] = theRect[3];
419   if (HasRenderScale())
420   {
421     myViewportVirt[0] = Standard_Integer(theRect[0] * myRenderScaleInv);
422     myViewportVirt[1] = Standard_Integer(theRect[1] * myRenderScaleInv);
423     myViewportVirt[2] = Standard_Integer(theRect[2] * myRenderScaleInv);
424     myViewportVirt[3] = Standard_Integer(theRect[3] * myRenderScaleInv);
425   }
426   else
427   {
428     myViewportVirt[0] = theRect[0];
429     myViewportVirt[1] = theRect[1];
430     myViewportVirt[2] = theRect[2];
431     myViewportVirt[3] = theRect[3];
432   }
433 }
434
435 #if !defined(GL_ES_VERSION_2_0)
436 inline Standard_Integer stereoToMonoBuffer (const Standard_Integer theBuffer)
437 {
438   switch (theBuffer)
439   {
440     case GL_BACK_LEFT:
441     case GL_BACK_RIGHT:
442       return GL_BACK;
443     case GL_FRONT_LEFT:
444     case GL_FRONT_RIGHT:
445       return GL_FRONT;
446     default:
447       return theBuffer;
448   }
449 }
450 #endif
451
452 // =======================================================================
453 // function : SetReadBuffer
454 // purpose  :
455 // =======================================================================
456 void OpenGl_Context::SetReadBuffer (const Standard_Integer theReadBuffer)
457 {
458 #if !defined(GL_ES_VERSION_2_0)
459   myReadBuffer = !myIsStereoBuffers ? stereoToMonoBuffer (theReadBuffer) : theReadBuffer;
460   if (myReadBuffer < GL_COLOR_ATTACHMENT0
461    && arbFBO != NULL)
462   {
463     arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
464   }
465   ::glReadBuffer (myReadBuffer);
466 #else
467   (void )theReadBuffer;
468 #endif
469 }
470
471 // =======================================================================
472 // function : SetDrawBuffer
473 // purpose  :
474 // =======================================================================
475 void OpenGl_Context::SetDrawBuffer (const Standard_Integer theDrawBuffer)
476 {
477 #if !defined(GL_ES_VERSION_2_0)
478   const Standard_Integer aDrawBuffer = !myIsStereoBuffers ? stereoToMonoBuffer (theDrawBuffer) : theDrawBuffer;
479   if (aDrawBuffer < GL_COLOR_ATTACHMENT0
480    && arbFBO != NULL)
481   {
482     arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
483   }
484   ::glDrawBuffer (aDrawBuffer);
485
486   myDrawBuffers.Init (GL_NONE);
487   myDrawBuffers.SetValue (0, aDrawBuffer);
488 #else
489   (void )theDrawBuffer;
490 #endif
491 }
492
493 // =======================================================================
494 // function : SetDrawBuffers
495 // purpose  :
496 // =======================================================================
497 void OpenGl_Context::SetDrawBuffers (const Standard_Integer theNb, const Standard_Integer* theDrawBuffers)
498 {
499   Standard_ASSERT_RETURN (hasDrawBuffers, "Multiple draw buffers feature is not supported by the context", Standard_ASSERT_DO_NOTHING());
500
501   if (myDrawBuffers.Length() < theNb)
502   {
503     // should actually never happen here
504     myDrawBuffers.Resize (0, theNb - 1, false);
505   }
506   myDrawBuffers.Init (GL_NONE);
507
508   Standard_Boolean useDefaultFbo = Standard_False;
509   for (Standard_Integer anI = 0; anI < theNb; ++anI)
510   {
511     if (theDrawBuffers[anI] < GL_COLOR_ATTACHMENT0 && theDrawBuffers[anI] != GL_NONE)
512     {
513       useDefaultFbo = Standard_True;
514     }
515     else
516     {
517       myDrawBuffers.SetValue (anI, theDrawBuffers[anI]);
518     }
519   }
520   if (arbFBO != NULL && useDefaultFbo)
521   {
522     arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
523   }
524
525   myFuncs->glDrawBuffers (theNb, (const GLenum*)theDrawBuffers);
526 }
527
528 // =======================================================================
529 // function : SetFrameBufferSRGB
530 // purpose  :
531 // =======================================================================
532 void OpenGl_Context::SetFrameBufferSRGB (bool theIsFbo, bool theIsFboSRgb)
533 {
534   if (!hasFboSRGB)
535   {
536     myIsSRgbActive = false;
537     return;
538   }
539   myIsSRgbActive = ToRenderSRGB()
540                && (theIsFbo || myIsSRgbWindow)
541                && theIsFboSRgb;
542   if (!hasSRGBControl)
543   {
544     return;
545   }
546
547   if (myIsSRgbActive)
548   {
549     core11fwd->glEnable (GL_FRAMEBUFFER_SRGB);
550   }
551   else
552   {
553     core11fwd->glDisable (GL_FRAMEBUFFER_SRGB);
554   }
555 }
556
557 // =======================================================================
558 // function : SetCullBackFaces
559 // purpose  :
560 // =======================================================================
561 void OpenGl_Context::SetCullBackFaces (bool theToEnable)
562 {
563   if (myToCullBackFaces == theToEnable)
564   {
565     return;
566   }
567
568   myToCullBackFaces = theToEnable;
569   if (theToEnable)
570   {
571     //glCullFace (GL_BACK); GL_BACK by default
572     core11fwd->glEnable (GL_CULL_FACE);
573   }
574   else
575   {
576     core11fwd->glDisable (GL_CULL_FACE);
577   }
578 }
579
580 // =======================================================================
581 // function : FetchState
582 // purpose  :
583 // =======================================================================
584 void OpenGl_Context::FetchState()
585 {
586 #if !defined(GL_ES_VERSION_2_0)
587   // cache feedback mode state
588   if (core11ffp != NULL)
589   {
590     ::glGetIntegerv (GL_RENDER_MODE, &myRenderMode);
591     ::glGetIntegerv (GL_SHADE_MODEL, &myShadeModel);
592   }
593
594   // cache read buffers state
595   ::glGetIntegerv (GL_READ_BUFFER, &myReadBuffer);
596
597   // cache draw buffers state
598   if (myDrawBuffers.Length() < myMaxDrawBuffers)
599   {
600     myDrawBuffers.Resize (0, myMaxDrawBuffers - 1, false);
601   }
602   myDrawBuffers.Init (GL_NONE);
603
604   Standard_Integer aDrawBuffer = GL_NONE;
605   if (myMaxDrawBuffers == 1)
606   {
607     ::glGetIntegerv (GL_DRAW_BUFFER, &aDrawBuffer);
608     myDrawBuffers.SetValue (0, aDrawBuffer);
609   }
610   else
611   {
612     for (Standard_Integer anI = 0; anI < myMaxDrawBuffers; ++anI)
613     {
614       ::glGetIntegerv (GL_DRAW_BUFFER0 + anI, &aDrawBuffer);
615       myDrawBuffers.SetValue (anI, aDrawBuffer);
616     }
617   }
618 #endif
619 }
620
621 // =======================================================================
622 // function : Share
623 // purpose  :
624 // =======================================================================
625 void OpenGl_Context::Share (const Handle(OpenGl_Context)& theShareCtx)
626 {
627   if (!theShareCtx.IsNull())
628   {
629     mySharedResources = theShareCtx->mySharedResources;
630     myDelayed         = theShareCtx->myDelayed;
631     myUnusedResources = theShareCtx->myUnusedResources;
632     myShaderManager   = theShareCtx->myShaderManager;
633   }
634 }
635
636 #if !defined(__APPLE__) || defined(HAVE_XLIB)
637
638 // =======================================================================
639 // function : IsCurrent
640 // purpose  :
641 // =======================================================================
642 Standard_Boolean OpenGl_Context::IsCurrent() const
643 {
644 #if defined(HAVE_EGL)
645   if ((EGLDisplay )myDisplay  == EGL_NO_DISPLAY
646    || (EGLContext )myGContext == EGL_NO_CONTEXT)
647   {
648     return Standard_False;
649   }
650
651   return (((EGLDisplay )myDisplay  == eglGetCurrentDisplay())
652        && ((EGLContext )myGContext == eglGetCurrentContext())
653        && ((EGLSurface )myWindow   == eglGetCurrentSurface (EGL_DRAW)));
654 #elif defined(_WIN32)
655   if (myDisplay == NULL || myGContext == NULL)
656   {
657     return Standard_False;
658   }
659   return (( (HDC )myDisplay  == wglGetCurrentDC())
660       && ((HGLRC )myGContext == wglGetCurrentContext()));
661 #elif defined(HAVE_XLIB)
662   if (myDisplay == NULL || myWindow == 0 || myGContext == 0)
663   {
664     return Standard_False;
665   }
666
667   return (   ((Display* )myDisplay  == glXGetCurrentDisplay())
668        &&  ((GLXContext )myGContext == glXGetCurrentContext())
669        && ((GLXDrawable )myWindow   == glXGetCurrentDrawable()));
670 #else
671   return Standard_False;
672 #endif
673 }
674
675 // =======================================================================
676 // function : MakeCurrent
677 // purpose  :
678 // =======================================================================
679 Standard_Boolean OpenGl_Context::MakeCurrent()
680 {
681 #if defined(HAVE_EGL)
682   if ((EGLDisplay )myDisplay  == EGL_NO_DISPLAY
683    || (EGLContext )myGContext == EGL_NO_CONTEXT)
684   {
685     Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called before!");
686     return Standard_False;
687   }
688
689   if (eglMakeCurrent ((EGLDisplay )myDisplay, (EGLSurface )myWindow, (EGLSurface )myWindow, (EGLContext )myGContext) != EGL_TRUE)
690   {
691     // if there is no current context it might be impossible to use glGetError() correctly
692     PushMessage (GL_DEBUG_SOURCE_WINDOW_SYSTEM, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
693                  "eglMakeCurrent() has failed!");
694     myIsInitialized = Standard_False;
695     return Standard_False;
696   }
697 #elif defined(_WIN32)
698   if (myDisplay == NULL || myGContext == NULL)
699   {
700     Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called before!");
701     return Standard_False;
702   }
703
704   // technically it should be safe to activate already bound GL context
705   // however some drivers (Intel etc.) may FAIL doing this for unknown reason
706   if (IsCurrent())
707   {
708     myShaderManager->SetContext (this);
709     return Standard_True;
710   }
711   else if (wglMakeCurrent ((HDC )myDisplay, (HGLRC )myGContext) != TRUE)
712   {
713     // notice that glGetError() couldn't be used here!
714     wchar_t* aMsgBuff = NULL;
715     DWORD anErrorCode = GetLastError();
716     FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
717                     NULL, anErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (wchar_t* )&aMsgBuff, 0, NULL);
718     TCollection_ExtendedString aMsg ("wglMakeCurrent() has failed. ");
719     if (aMsgBuff != NULL)
720     {
721       aMsg += (Standard_ExtString )aMsgBuff;
722       LocalFree (aMsgBuff);
723     }
724     PushMessage (GL_DEBUG_SOURCE_WINDOW_SYSTEM, GL_DEBUG_TYPE_ERROR, (unsigned int )anErrorCode, GL_DEBUG_SEVERITY_HIGH, aMsg);
725     myIsInitialized = Standard_False;
726     return Standard_False;
727   }
728 #elif defined(HAVE_XLIB)
729   if (myDisplay == NULL || myWindow == 0 || myGContext == 0)
730   {
731     Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called before!");
732     return Standard_False;
733   }
734
735   if (!glXMakeCurrent ((Display* )myDisplay, (GLXDrawable )myWindow, (GLXContext )myGContext))
736   {
737     // if there is no current context it might be impossible to use glGetError() correctly
738     PushMessage (GL_DEBUG_SOURCE_WINDOW_SYSTEM, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
739                  "glXMakeCurrent() has failed!");
740     myIsInitialized = Standard_False;
741     return Standard_False;
742   }
743 #else
744   // not implemented
745   if (!myIsInitialized)
746   {
747     throw Standard_ProgramError ("OpenGl_Context::Init() should be called before!");
748   }
749 #endif
750   myShaderManager->SetContext (this);
751   return Standard_True;
752 }
753
754 // =======================================================================
755 // function : SwapBuffers
756 // purpose  :
757 // =======================================================================
758 void OpenGl_Context::SwapBuffers()
759 {
760 #if defined(HAVE_EGL)
761   if ((EGLSurface )myWindow != EGL_NO_SURFACE)
762   {
763     eglSwapBuffers ((EGLDisplay )myDisplay, (EGLSurface )myWindow);
764   }
765 #elif defined(_WIN32)
766   if ((HDC )myDisplay != NULL)
767   {
768     ::SwapBuffers ((HDC )myDisplay);
769     glFlush();
770   }
771 #elif defined(HAVE_XLIB)
772   if ((Display* )myDisplay != NULL)
773   {
774     glXSwapBuffers ((Display* )myDisplay, (GLXDrawable )myWindow);
775   }
776 #else
777   //
778 #endif
779 }
780
781 #endif // __APPLE__
782
783 // =======================================================================
784 // function : SetSwapInterval
785 // purpose  :
786 // =======================================================================
787 Standard_Boolean OpenGl_Context::SetSwapInterval (const Standard_Integer theInterval)
788 {
789 #if defined(HAVE_EGL)
790   if (::eglSwapInterval ((EGLDisplay )myDisplay, theInterval) == EGL_TRUE)
791   {
792     return Standard_True;
793   }
794 #elif defined(_WIN32)
795   if (myFuncs->wglSwapIntervalEXT != NULL)
796   {
797     myFuncs->wglSwapIntervalEXT (theInterval);
798     return Standard_True;
799   }
800 #elif defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
801   (void )theInterval; // vsync cannot be turned OFF on iOS
802 #elif defined(__APPLE__)
803   if (::CGLSetParameter (CGLGetCurrentContext(), kCGLCPSwapInterval, &theInterval) == kCGLNoError)
804   {
805     return Standard_True;
806   }
807 #elif defined(HAVE_XLIB)
808   if (theInterval == -1
809    && myFuncs->glXSwapIntervalEXT != NULL)
810   {
811     typedef int (*glXSwapIntervalEXT_t_x)(Display* theDisplay, GLXDrawable theDrawable, int theInterval);
812     glXSwapIntervalEXT_t_x aFuncPtr = (glXSwapIntervalEXT_t_x )myFuncs->glXSwapIntervalEXT;
813     aFuncPtr ((Display* )myDisplay, (GLXDrawable )myWindow, theInterval);
814     return Standard_True;
815   }
816   else if (myFuncs->glXSwapIntervalSGI != NULL)
817   {
818     myFuncs->glXSwapIntervalSGI (theInterval);
819     return Standard_True;
820   }
821 #else
822   //
823 #endif
824   return Standard_False;
825 }
826
827 // =======================================================================
828 // function : findProc
829 // purpose  :
830 // =======================================================================
831 void* OpenGl_Context::findProc (const char* theFuncName)
832 {
833 #if defined(HAVE_EGL)
834   return (void* )eglGetProcAddress (theFuncName);
835 #elif defined(_WIN32)
836   return (void* )wglGetProcAddress (theFuncName);
837 #elif defined(HAVE_XLIB)
838   return (void* )glXGetProcAddress ((const GLubyte* )theFuncName);
839 #elif defined(__APPLE__)
840   return (myGlLibHandle != NULL) ? dlsym (myGlLibHandle, theFuncName) : NULL;
841 #else
842   (void )theFuncName;
843   return NULL;
844 #endif
845 }
846
847 // =======================================================================
848 // function : CheckExtension
849 // purpose  :
850 // =======================================================================
851 Standard_Boolean OpenGl_Context::CheckExtension (const char* theExtName) const
852 {
853   if (theExtName  == NULL)
854   {
855 #ifdef OCCT_DEBUG
856     std::cerr << "CheckExtension called with NULL string!\n";
857 #endif
858     return Standard_False;
859   }
860   else if (caps->contextNoExtensions)
861   {
862     return Standard_False;
863   }
864
865 #if !defined(GL_ES_VERSION_2_0)
866   // available since OpenGL 3.0
867   // and the ONLY way to check extensions with OpenGL 3.1+ core profile
868   if (IsGlGreaterEqual (3, 0)
869    && myFuncs->glGetStringi != NULL)
870   {
871     GLint anExtNb = 0;
872     ::glGetIntegerv (GL_NUM_EXTENSIONS, &anExtNb);
873     const size_t anExtNameLen = strlen (theExtName);
874     for (GLint anIter = 0; anIter < anExtNb; ++anIter)
875     {
876       const char* anExtension = (const char* )myFuncs->glGetStringi (GL_EXTENSIONS, (GLuint )anIter);
877       const size_t aTestExtNameLen = strlen (anExtension);
878       if (aTestExtNameLen == anExtNameLen
879        && strncmp (anExtension, theExtName, anExtNameLen) == 0)
880       {
881         return Standard_True;
882       }
883     }
884     return Standard_False;
885   }
886 #endif
887
888   // use old way with huge string for all extensions
889   const char* anExtString = (const char* )glGetString (GL_EXTENSIONS);
890   if (anExtString == NULL)
891   {
892     Messenger()->Send ("TKOpenGL: glGetString (GL_EXTENSIONS) has returned NULL! No GL context?", Message_Warning);
893     return Standard_False;
894   }
895   return CheckExtension (anExtString, theExtName);
896 }
897
898 // =======================================================================
899 // function : CheckExtension
900 // purpose  :
901 // =======================================================================
902 Standard_Boolean OpenGl_Context::CheckExtension (const char* theExtString,
903                                                  const char* theExtName)
904 {
905   if (theExtString == NULL)
906   {
907     return Standard_False;
908   }
909
910   // Search for theExtName in the extensions string.
911   // Use of strstr() is not sufficient because extension names can be prefixes of other extension names.
912   char* aPtrIter = (char* )theExtString;
913   const char*  aPtrEnd      = aPtrIter + strlen (theExtString);
914   const size_t anExtNameLen = strlen (theExtName);
915   while (aPtrIter < aPtrEnd)
916   {
917     const size_t n = strcspn (aPtrIter, " ");
918     if ((n == anExtNameLen) && (strncmp (aPtrIter, theExtName, anExtNameLen) == 0))
919     {
920       return Standard_True;
921     }
922     aPtrIter += (n + 1);
923   }
924   return Standard_False;
925 }
926
927 #if !defined(__APPLE__) || defined(HAVE_XLIB)
928
929 // =======================================================================
930 // function : Init
931 // purpose  :
932 // =======================================================================
933 Standard_Boolean OpenGl_Context::Init (const Standard_Boolean theIsCoreProfile)
934 {
935   if (myIsInitialized)
936   {
937     return Standard_True;
938   }
939
940 #if defined(HAVE_EGL)
941   myDisplay  = (Aspect_Display )eglGetCurrentDisplay();
942   myGContext = (Aspect_RenderingContext )eglGetCurrentContext();
943   myWindow   = (Aspect_Drawable )eglGetCurrentSurface(EGL_DRAW);
944 #elif defined(_WIN32)
945   myDisplay  = (Aspect_Handle )wglGetCurrentDC();
946   myGContext = (Aspect_RenderingContext )wglGetCurrentContext();
947 #elif defined(HAVE_XLIB)
948   myDisplay  = (Aspect_Display )glXGetCurrentDisplay();
949   myGContext = (Aspect_RenderingContext )glXGetCurrentContext();
950   myWindow   = (Aspect_Drawable )glXGetCurrentDrawable();
951 #else
952   //
953 #endif
954   if (myGContext == NULL)
955   {
956     return Standard_False;
957   }
958
959   init (theIsCoreProfile);
960   myIsInitialized = Standard_True;
961   return Standard_True;
962 }
963
964 #endif // __APPLE__
965
966 // =======================================================================
967 // function : Init
968 // purpose  :
969 // =======================================================================
970 Standard_Boolean OpenGl_Context::Init (const Aspect_Drawable         theSurface,
971                                        const Aspect_Display          theDisplay,
972                                        const Aspect_RenderingContext theContext,
973                                        const Standard_Boolean        theIsCoreProfile)
974 {
975   Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called only once!");
976   myWindow   = theSurface;
977   myDisplay  = theDisplay;
978   myGContext = theContext;
979   if (myGContext == NULL || !MakeCurrent())
980   {
981     return Standard_False;
982   }
983
984   init (theIsCoreProfile);
985   myIsInitialized = Standard_True;
986   return Standard_True;
987 }
988
989 // =======================================================================
990 // function : FormatGlEnumHex
991 // purpose  :
992 // =======================================================================
993 TCollection_AsciiString OpenGl_Context::FormatGlEnumHex (int theGlEnum)
994 {
995   char aBuff[16];
996   Sprintf (aBuff, theGlEnum < (int )std::numeric_limits<uint16_t>::max()
997                 ? "0x%04X"
998                 : "0x%08X", theGlEnum);
999   return aBuff;
1000 }
1001
1002 // =======================================================================
1003 // function : FormatSize
1004 // purpose  :
1005 // =======================================================================
1006 TCollection_AsciiString OpenGl_Context::FormatSize (Standard_Size theSize)
1007 {
1008   char aBuff[32];
1009   Sprintf (aBuff, "%" PRIu64, (uint64_t )theSize);
1010   return aBuff;
1011 }
1012
1013 // =======================================================================
1014 // function : FormatPointer
1015 // purpose  :
1016 // =======================================================================
1017 TCollection_AsciiString OpenGl_Context::FormatPointer (const void* thePtr)
1018 {
1019   char aBuff[32];
1020   Sprintf (aBuff, "0x%" PRIXPTR, (uintptr_t )thePtr);
1021   return aBuff;
1022 }
1023
1024 // =======================================================================
1025 // function : FormatGlError
1026 // purpose  :
1027 // =======================================================================
1028 TCollection_AsciiString OpenGl_Context::FormatGlError (int theGlError)
1029 {
1030   switch (theGlError)
1031   {
1032     case GL_INVALID_ENUM:      return "GL_INVALID_ENUM";
1033     case GL_INVALID_VALUE:     return "GL_INVALID_VALUE";
1034     case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION";
1035   #ifdef GL_STACK_OVERFLOW
1036     case GL_STACK_OVERFLOW:    return "GL_STACK_OVERFLOW";
1037     case GL_STACK_UNDERFLOW:   return "GL_STACK_UNDERFLOW";
1038   #endif
1039     case GL_OUT_OF_MEMORY:     return "GL_OUT_OF_MEMORY";
1040     case GL_INVALID_FRAMEBUFFER_OPERATION: return "GL_INVALID_FRAMEBUFFER_OPERATION";
1041   }
1042   return FormatGlEnumHex (theGlError);
1043 }
1044
1045 // =======================================================================
1046 // function : ResetErrors
1047 // purpose  :
1048 // =======================================================================
1049 bool OpenGl_Context::ResetErrors (const bool theToPrintErrors)
1050 {
1051   int aPrevErr = 0;
1052   int anErr    = ::glGetError();
1053   const bool hasError = anErr != GL_NO_ERROR;
1054   if (!theToPrintErrors)
1055   {
1056     for (; anErr != GL_NO_ERROR && aPrevErr != anErr; aPrevErr = anErr, anErr = ::glGetError())
1057     {
1058       //
1059     }
1060     return hasError;
1061   }
1062
1063   for (; anErr != GL_NO_ERROR && aPrevErr != anErr; aPrevErr = anErr, anErr = ::glGetError())
1064   {
1065     const TCollection_ExtendedString aMsg = TCollection_ExtendedString ("Unhandled GL error: ") + FormatGlError (anErr);
1066     PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
1067   }
1068   return hasError;
1069 }
1070
1071 // =======================================================================
1072 // function : debugPrintError
1073 // purpose  :
1074 // =======================================================================
1075 bool OpenGl_GlFunctions::debugPrintError (const char* theName) const
1076 {
1077   const int anErr = ::glGetError();
1078   if (anErr != GL_NO_ERROR)
1079   {
1080     Message::SendFail() << theName << "(), unhandled GL error: " << OpenGl_Context::FormatGlError (anErr);
1081     // there is no glSetError(), just emulate non-clear state
1082     switch (anErr)
1083     {
1084       case GL_INVALID_VALUE:
1085       {
1086         ::glLineWidth(-1.0f);
1087         ::glLineWidth( 1.0f);
1088         break;
1089       }
1090       default:
1091       case GL_INVALID_ENUM:
1092       {
1093         ::glEnable (0xFFFF);
1094         break;
1095       }
1096     }
1097   }
1098   return anErr != GL_NO_ERROR;
1099 }
1100
1101 // =======================================================================
1102 // function : ReadGlVersion
1103 // purpose  :
1104 // =======================================================================
1105 void OpenGl_Context::ReadGlVersion (Standard_Integer& theGlVerMajor,
1106                                     Standard_Integer& theGlVerMinor)
1107 {
1108   // reset values
1109   theGlVerMajor = 0;
1110   theGlVerMinor = 0;
1111
1112   bool toCheckVer3 = true;
1113 #if defined(__EMSCRIPTEN__)
1114   // WebGL 1.0 prints annoying invalid enumeration warnings to console.
1115   toCheckVer3 = false;
1116   if (EMSCRIPTEN_WEBGL_CONTEXT_HANDLE aWebGlCtx = emscripten_webgl_get_current_context())
1117   {
1118     EmscriptenWebGLContextAttributes anAttribs = {};
1119     if (emscripten_webgl_get_context_attributes (aWebGlCtx, &anAttribs) == EMSCRIPTEN_RESULT_SUCCESS)
1120     {
1121       toCheckVer3 = anAttribs.majorVersion >= 2;
1122     }
1123   }
1124 #endif
1125
1126   // Available since OpenGL 3.0 and OpenGL ES 3.0.
1127   if (toCheckVer3)
1128   {
1129     GLint aMajor = 0, aMinor = 0;
1130     glGetIntegerv (GL_MAJOR_VERSION, &aMajor);
1131     glGetIntegerv (GL_MINOR_VERSION, &aMinor);
1132     // glGetError() sometimes does not report an error here even if
1133     // GL does not know GL_MAJOR_VERSION and GL_MINOR_VERSION constants.
1134     // This happens on some renderers like e.g. Cygwin MESA.
1135     // Thus checking additionally if GL has put anything to
1136     // the output variables.
1137     if (::glGetError() == GL_NO_ERROR && aMajor != 0 && aMinor != 0)
1138     {
1139       theGlVerMajor = aMajor;
1140       theGlVerMinor = aMinor;
1141       return;
1142     }
1143     for (GLenum anErr = ::glGetError(), aPrevErr = GL_NO_ERROR;; aPrevErr = anErr, anErr = ::glGetError())
1144     {
1145       if (anErr == GL_NO_ERROR
1146        || anErr == aPrevErr)
1147       {
1148         break;
1149       }
1150     }
1151   }
1152
1153   // Read version string.
1154   // Notice that only first two numbers split by point '2.1 XXXXX' are significant.
1155   // Following trash (after space) is vendor-specific.
1156   // New drivers also returns micro version of GL like '3.3.0' which has no meaning
1157   // and should be considered as vendor-specific too.
1158   const char* aVerStr = (const char* )glGetString (GL_VERSION);
1159   if (aVerStr == NULL || *aVerStr == '\0')
1160   {
1161     // invalid GL context
1162     return;
1163   }
1164
1165 //#if defined(GL_ES_VERSION_2_0)
1166   // skip "OpenGL ES-** " section
1167   for (; *aVerStr != '\0'; ++aVerStr)
1168   {
1169     if (*aVerStr >= '0' && *aVerStr <= '9')
1170     {
1171       break;
1172     }
1173   }
1174 //#endif
1175
1176   // parse string for major number
1177   char aMajorStr[32];
1178   char aMinorStr[32];
1179   size_t aMajIter = 0;
1180   while (aVerStr[aMajIter] >= '0' && aVerStr[aMajIter] <= '9')
1181   {
1182     ++aMajIter;
1183   }
1184   if (aMajIter == 0 || aMajIter >= sizeof(aMajorStr))
1185   {
1186     return;
1187   }
1188   memcpy (aMajorStr, aVerStr, aMajIter);
1189   aMajorStr[aMajIter] = '\0';
1190
1191   // parse string for minor number
1192   aVerStr += aMajIter + 1;
1193   size_t aMinIter = 0;
1194   while (aVerStr[aMinIter] >= '0' && aVerStr[aMinIter] <= '9')
1195   {
1196     ++aMinIter;
1197   }
1198   if (aMinIter == 0 || aMinIter >= sizeof(aMinorStr))
1199   {
1200     return;
1201   }
1202   memcpy (aMinorStr, aVerStr, aMinIter);
1203   aMinorStr[aMinIter] = '\0';
1204
1205   // read numbers
1206   theGlVerMajor = atoi (aMajorStr);
1207   theGlVerMinor = atoi (aMinorStr);
1208 #if defined(__EMSCRIPTEN__)
1209   if (theGlVerMajor >= 3)
1210   {
1211     if (!toCheckVer3
1212      || ::strstr (aVerStr, "WebGL 1.0") != NULL)
1213     {
1214       Message::SendWarning() << "Warning! OpenGL context reports version " << theGlVerMajor << "." << theGlVerMinor
1215                              << " but WebGL 2.0 was unavailable\n"
1216                              << "Fallback to OpenGL ES 2.0 will be used instead of reported version";
1217       theGlVerMajor = 2;
1218       theGlVerMinor = 0;
1219     }
1220   }
1221 #endif
1222
1223   if (theGlVerMajor <= 0)
1224   {
1225     theGlVerMajor = 0;
1226     theGlVerMinor = 0;
1227   }
1228 }
1229
1230 static Standard_CString THE_DBGMSG_UNKNOWN = "UNKNOWN";
1231 static Standard_CString THE_DBGMSG_SOURCES[] =
1232 {
1233   ".OpenGL",    // GL_DEBUG_SOURCE_API
1234   ".WinSystem", // GL_DEBUG_SOURCE_WINDOW_SYSTEM
1235   ".GLSL",      // GL_DEBUG_SOURCE_SHADER_COMPILER
1236   ".3rdParty",  // GL_DEBUG_SOURCE_THIRD_PARTY
1237   "",           // GL_DEBUG_SOURCE_APPLICATION
1238   ".Other"      // GL_DEBUG_SOURCE_OTHER
1239 };
1240
1241 static Standard_CString THE_DBGMSG_TYPES[] =
1242 {
1243   "Error",           // GL_DEBUG_TYPE_ERROR
1244   "Deprecated",      // GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR
1245   "Undef. behavior", // GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR
1246   "Portability",     // GL_DEBUG_TYPE_PORTABILITY
1247   "Performance",     // GL_DEBUG_TYPE_PERFORMANCE
1248   "Other"            // GL_DEBUG_TYPE_OTHER
1249 };
1250
1251 static Standard_CString THE_DBGMSG_SEV_HIGH   = "High";   // GL_DEBUG_SEVERITY_HIGH
1252 static Standard_CString THE_DBGMSG_SEV_MEDIUM = "Medium"; // GL_DEBUG_SEVERITY_MEDIUM
1253 static Standard_CString THE_DBGMSG_SEV_LOW    = "Low";    // GL_DEBUG_SEVERITY_LOW
1254
1255 //! Callback for GL_ARB_debug_output extension
1256 static void APIENTRY debugCallbackWrap(unsigned int theSource,
1257                                        unsigned int theType,
1258                                        unsigned int theId,
1259                                        unsigned int theSeverity,
1260                                        int          /*theLength*/,
1261                                        const char*  theMessage,
1262                                        const void*  theUserParam)
1263 {
1264   OpenGl_Context* aCtx = (OpenGl_Context* )theUserParam;
1265   aCtx->PushMessage (theSource, theType, theId, theSeverity, theMessage);
1266 }
1267
1268 // =======================================================================
1269 // function : PushMessage
1270 // purpose  :
1271 // =======================================================================
1272 void OpenGl_Context::PushMessage (const unsigned int theSource,
1273                                   const unsigned int theType,
1274                                   const unsigned int theId,
1275                                   const unsigned int theSeverity,
1276                                   const TCollection_ExtendedString& theMessage)
1277 {
1278   if (caps->suppressExtraMsg
1279    && theSource >= GL_DEBUG_SOURCE_API
1280    && theSource <= GL_DEBUG_SOURCE_OTHER
1281    && myFilters[theSource - GL_DEBUG_SOURCE_API].Contains (theId))
1282   {
1283     return;
1284   }
1285
1286   Standard_CString& aSrc = (theSource >= GL_DEBUG_SOURCE_API
1287                         && theSource <= GL_DEBUG_SOURCE_OTHER)
1288                          ? THE_DBGMSG_SOURCES[theSource - GL_DEBUG_SOURCE_API]
1289                          : THE_DBGMSG_UNKNOWN;
1290   Standard_CString& aType = (theType >= GL_DEBUG_TYPE_ERROR
1291                          && theType <= GL_DEBUG_TYPE_OTHER)
1292                           ? THE_DBGMSG_TYPES[theType - GL_DEBUG_TYPE_ERROR]
1293                           : THE_DBGMSG_UNKNOWN;
1294   Standard_CString& aSev = theSeverity == GL_DEBUG_SEVERITY_HIGH
1295                          ? THE_DBGMSG_SEV_HIGH
1296                          : (theSeverity == GL_DEBUG_SEVERITY_MEDIUM
1297                           ? THE_DBGMSG_SEV_MEDIUM
1298                           : THE_DBGMSG_SEV_LOW);
1299   Message_Gravity aGrav = theSeverity == GL_DEBUG_SEVERITY_HIGH
1300                         ? Message_Alarm
1301                         : (theSeverity == GL_DEBUG_SEVERITY_MEDIUM
1302                          ? Message_Warning
1303                          : Message_Info);
1304
1305   TCollection_ExtendedString aMsg;
1306   aMsg += "TKOpenGl"; aMsg += aSrc;
1307   aMsg += " | Type: ";        aMsg += aType;
1308   aMsg += " | ID: ";          aMsg += (Standard_Integer )theId;
1309   aMsg += " | Severity: ";    aMsg += aSev;
1310   aMsg += " | Message:\n  ";
1311   aMsg += theMessage;
1312   Messenger()->Send (aMsg, aGrav);
1313 }
1314
1315 // =======================================================================
1316 // function : ExcludeMessage
1317 // purpose  :
1318 // ======================================================================
1319 Standard_Boolean OpenGl_Context::ExcludeMessage (const unsigned int theSource,
1320                                                  const unsigned int theId)
1321 {
1322   return theSource >= GL_DEBUG_SOURCE_API
1323       && theSource <= GL_DEBUG_SOURCE_OTHER
1324       && myFilters[theSource - GL_DEBUG_SOURCE_API].Add (theId);
1325 }
1326
1327 // =======================================================================
1328 // function : IncludeMessage
1329 // purpose  :
1330 // ======================================================================
1331 Standard_Boolean OpenGl_Context::IncludeMessage (const unsigned int theSource,
1332                                                  const unsigned int theId)
1333 {
1334   return theSource >= GL_DEBUG_SOURCE_API
1335       && theSource <= GL_DEBUG_SOURCE_OTHER
1336       && myFilters[theSource - GL_DEBUG_SOURCE_API].Remove (theId);
1337 }
1338
1339 // =======================================================================
1340 // function : checkWrongVersion
1341 // purpose  :
1342 // ======================================================================
1343 void OpenGl_Context::checkWrongVersion (Standard_Integer theGlVerMajor, Standard_Integer theGlVerMinor,
1344                                         const char* theLastFailedProc)
1345 {
1346   if (!IsGlGreaterEqual (theGlVerMajor, theGlVerMinor))
1347   {
1348     return;
1349   }
1350
1351   PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
1352                TCollection_AsciiString()
1353                + "Error! OpenGL context reports version "
1354                + myGlVerMajor  + "." + myGlVerMinor
1355                + " but does not export required functions for " + theGlVerMajor + "." + theGlVerMinor
1356                + " (" + (theLastFailedProc != NULL ? theLastFailedProc : "") + ")\n"
1357                + "Please report this issue to OpenGL driver vendor '" + myVendor + "'");
1358
1359   // lower internal version
1360   if (theGlVerMinor > 0)
1361   {
1362     myGlVerMajor = theGlVerMajor;
1363     myGlVerMinor = theGlVerMinor - 1;
1364     return;
1365   }
1366 #if defined(GL_ES_VERSION_2_0)
1367   switch (theGlVerMajor)
1368   {
1369     case 3: myGlVerMajor = 2; myGlVerMinor = 0; return;
1370   }
1371 #else
1372   switch (theGlVerMajor)
1373   {
1374     case 2: myGlVerMajor = 1; myGlVerMinor = 5; return;
1375     case 3: myGlVerMajor = 2; myGlVerMinor = 1; return;
1376     case 4: myGlVerMajor = 3; myGlVerMinor = 3; return;
1377   }
1378 #endif
1379 }
1380
1381 // =======================================================================
1382 // function : init
1383 // purpose  :
1384 // =======================================================================
1385 void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
1386 {
1387   // read version
1388   myGlVerMajor = 0;
1389   myGlVerMinor = 0;
1390   myMaxMsaaSamples = 0;
1391   myMaxDrawBuffers = 1;
1392   myMaxColorAttachments = 1;
1393   myDefaultVao = 0;
1394   ReadGlVersion (myGlVerMajor, myGlVerMinor);
1395   myVendor = (const char* )::glGetString (GL_VENDOR);
1396   myVendor.LowerCase();
1397   mySupportedFormats->Clear();
1398
1399   if (caps->contextMajorVersionUpper != -1)
1400   {
1401     // synthetically restrict OpenGL version for testing
1402     Standard_Integer aCtxVer[2] = { myGlVerMajor, myGlVerMinor };
1403     bool isLowered = false;
1404     if (myGlVerMajor > caps->contextMajorVersionUpper)
1405     {
1406       isLowered = true;
1407       myGlVerMajor = caps->contextMajorVersionUpper;
1408     #if defined(GL_ES_VERSION_2_0)
1409       switch (myGlVerMajor)
1410       {
1411         case 2: myGlVerMinor = 0; break;
1412       }
1413     #else
1414       switch (myGlVerMajor)
1415       {
1416         case 1: myGlVerMinor = 5; break;
1417         case 2: myGlVerMinor = 1; break;
1418         case 3: myGlVerMinor = 3; break;
1419       }
1420     #endif
1421     }
1422     if (caps->contextMinorVersionUpper != -1
1423      && myGlVerMinor > caps->contextMinorVersionUpper)
1424     {
1425       isLowered = true;
1426       myGlVerMinor = caps->contextMinorVersionUpper;
1427     }
1428     if (isLowered)
1429     {
1430       PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
1431                    TCollection_AsciiString ("OpenGL version ") + aCtxVer[0] + "." + aCtxVer[1]
1432                    + " has been lowered to " + myGlVerMajor + "." + myGlVerMinor);
1433     }
1434   }
1435
1436   if (!caps->ffpEnable
1437    && !IsGlGreaterEqual (2, 0))
1438   {
1439     caps->ffpEnable = true;
1440     TCollection_ExtendedString aMsg =
1441       TCollection_ExtendedString("OpenGL driver is too old! Context info:\n")
1442                                + "    Vendor:   " + (const char* )::glGetString (GL_VENDOR)   + "\n"
1443                                + "    Renderer: " + (const char* )::glGetString (GL_RENDERER) + "\n"
1444                                + "    Version:  " + (const char* )::glGetString (GL_VERSION)  + "\n"
1445                                + "  Fallback using deprecated fixed-function pipeline.\n"
1446                                + "  Visualization might work incorrectly.\n"
1447                                  "  Consider upgrading the graphics driver.";
1448     PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, aMsg);
1449   }
1450
1451 #if defined(GL_ES_VERSION_2_0)
1452   (void )theIsCoreProfile;
1453   const bool isCoreProfile = false;
1454 #else
1455
1456   if (myVendor.Search ("nvidia") != -1)
1457   {
1458     // Buffer detailed info: Buffer object 1 (bound to GL_ARRAY_BUFFER_ARB, usage hint is GL_STATIC_DRAW)
1459     // will use VIDEO memory as the source for buffer object operations.
1460     ExcludeMessage (GL_DEBUG_SOURCE_API, 131185);
1461   }
1462   if (IsGlGreaterEqual (3, 0))
1463   {
1464     // retrieve auxiliary function in advance
1465     FindProc ("glGetStringi", myFuncs->glGetStringi);
1466   }
1467
1468   bool isCoreProfile = false;
1469   if (IsGlGreaterEqual (3, 2))
1470   {
1471     isCoreProfile = (theIsCoreProfile == Standard_True);
1472
1473     // detect Core profile
1474     if (!isCoreProfile)
1475     {
1476       GLint aProfile = 0;
1477       ::glGetIntegerv (GL_CONTEXT_PROFILE_MASK, &aProfile);
1478       isCoreProfile = (aProfile & GL_CONTEXT_CORE_PROFILE_BIT) != 0;
1479     }
1480   }
1481 #endif
1482
1483   myFuncs->load (*this, isCoreProfile);
1484
1485   // setup shader generator
1486   myShaderManager->SetGapiVersion (myGlVerMajor, myGlVerMinor);
1487   myShaderManager->SetEmulateDepthClamp (!arbDepthClamp);
1488
1489   bool toReverseDFdxSign = false;
1490 #if defined(GL_ES_VERSION_2_0)
1491   // workaround Adreno driver bug computing reversed normal using dFdx/dFdy
1492   toReverseDFdxSign = myVendor.Search("qualcomm") != -1;
1493 #endif
1494   myShaderManager->SetFlatShading (hasFlatShading != OpenGl_FeatureNotAvailable, toReverseDFdxSign);
1495 #if defined(GL_ES_VERSION_2_0)
1496   myShaderManager->SetUseRedAlpha (false);
1497 #else
1498   myShaderManager->SetUseRedAlpha (core11ffp == NULL);
1499 #endif
1500   #define checkGlslExtensionShort(theName) myShaderManager->EnableGlslExtension (Graphic3d_GlslExtension_ ## theName, CheckExtension (#theName))
1501 #if defined(GL_ES_VERSION_2_0)
1502   checkGlslExtensionShort(GL_OES_standard_derivatives);
1503   checkGlslExtensionShort(GL_EXT_shader_texture_lod);
1504   checkGlslExtensionShort(GL_EXT_frag_depth);
1505 #else
1506   checkGlslExtensionShort(GL_EXT_gpu_shader4);
1507 #endif
1508
1509   // initialize debug context extension
1510   if (arbDbg != NULL
1511    && caps->contextDebug)
1512   {
1513     // setup default callback
1514     myIsGlDebugCtx = Standard_True;
1515     arbDbg->glDebugMessageCallback (debugCallbackWrap, this);
1516   #if defined(GL_ES_VERSION_2_0)
1517     ::glEnable (GL_DEBUG_OUTPUT);
1518   #else
1519     if (core43 != NULL)
1520     {
1521       ::glEnable (GL_DEBUG_OUTPUT);
1522     }
1523   #endif
1524     if (caps->contextSyncDebug)
1525     {
1526       // note that some broken implementations (e.g. simulators) might generate error message on this call
1527       ::glEnable (GL_DEBUG_OUTPUT_SYNCHRONOUS);
1528     }
1529   }
1530
1531   if (hasDrawBuffers)
1532   {
1533     glGetIntegerv (GL_MAX_DRAW_BUFFERS,      &myMaxDrawBuffers);
1534     glGetIntegerv (GL_MAX_COLOR_ATTACHMENTS, &myMaxColorAttachments);
1535     if (myDrawBuffers.Length() < myMaxDrawBuffers)
1536     {
1537       myDrawBuffers.Resize (0, myMaxDrawBuffers - 1, false);
1538     }
1539   }
1540
1541   glGetIntegerv (GL_MAX_TEXTURE_SIZE, &myMaxTexDim);
1542 #if !defined(GL_ES_VERSION_2_0)
1543   if (IsGlGreaterEqual (1, 3) && core11ffp != NULL)
1544   {
1545     // this is a maximum of texture units for FFP functionality,
1546     // usually smaller than combined texture units available for GLSL
1547     glGetIntegerv (GL_MAX_TEXTURE_UNITS, &myMaxTexUnitsFFP);
1548     myMaxTexCombined = myMaxTexUnitsFFP;
1549   }
1550 #endif
1551   if (IsGlGreaterEqual (2, 0))
1552   {
1553     glGetIntegerv (GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &myMaxTexCombined);
1554   }
1555   mySpriteTexUnit = myMaxTexCombined >= 2
1556                   ? Graphic3d_TextureUnit_PointSprite
1557                   : Graphic3d_TextureUnit_0;
1558
1559   GLint aMaxVPortSize[2] = {0, 0};
1560   glGetIntegerv (GL_MAX_VIEWPORT_DIMS, aMaxVPortSize);
1561   myMaxDumpSizeX = Min (aMaxVPortSize[0], myMaxTexDim);
1562   myMaxDumpSizeY = Min (aMaxVPortSize[1], myMaxTexDim);
1563   if (myVendor == "intel")
1564   {
1565     // Intel drivers have known bug with empty dump for images with width>=5462
1566     myMaxDumpSizeX = Min (myMaxDumpSizeX, 4096);
1567   }
1568
1569   if (extAnis)
1570   {
1571     glGetIntegerv (GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &myAnisoMax);
1572   }
1573
1574   myClippingState.Init();
1575
1576 #if defined(GL_ES_VERSION_2_0)
1577   if (IsGlGreaterEqual (3, 1)
1578    && myFuncs->glTexStorage2DMultisample != NULL)
1579   {
1580     // MSAA RenderBuffers have been defined in OpenGL ES 3.0,
1581     // but MSAA Textures - only in OpenGL ES 3.1+
1582     ::glGetIntegerv (GL_MAX_SAMPLES, &myMaxMsaaSamples);
1583   }
1584 #else
1585   if (core30 != NULL)
1586   {
1587     // MSAA RenderBuffers have been defined in OpenGL 3.0,
1588     // but MSAA Textures - only in OpenGL 3.2+
1589     if (core32 != NULL)
1590     {
1591       ::glGetIntegerv (GL_MAX_SAMPLES, &myMaxMsaaSamples);
1592     }
1593     else if (CheckExtension ("GL_ARB_texture_multisample")
1594           && myFuncs->glTexImage2DMultisample != NULL)
1595     {
1596       GLint aNbColorSamples = 0, aNbDepthSamples = 0;
1597       ::glGetIntegerv (GL_MAX_COLOR_TEXTURE_SAMPLES, &aNbColorSamples);
1598       ::glGetIntegerv (GL_MAX_DEPTH_TEXTURE_SAMPLES, &aNbDepthSamples);
1599       myMaxMsaaSamples = Min (aNbColorSamples, aNbDepthSamples);
1600     }
1601   }
1602 #endif
1603
1604 #if !defined(GL_ES_VERSION_2_0)
1605   if (core32 != NULL && isCoreProfile)
1606   {
1607     core32->glGenVertexArrays (1, &myDefaultVao);
1608   }
1609
1610   myTexClamp = IsGlGreaterEqual (1, 2) ? GL_CLAMP_TO_EDGE : GL_CLAMP;
1611
1612   GLint aStereo = GL_FALSE;
1613   glGetIntegerv (GL_STEREO, &aStereo);
1614   myIsStereoBuffers = aStereo == 1;
1615
1616   // get number of maximum clipping planes
1617   glGetIntegerv (GL_MAX_CLIP_PLANES, &myMaxClipPlanes);
1618 #endif
1619
1620 #if defined(GL_ES_VERSION_2_0)
1621   // check whether ray tracing mode is supported
1622   myHasRayTracing = IsGlGreaterEqual (3, 2);
1623   myHasRayTracingTextures = myHasRayTracingAdaptiveSampling = myHasRayTracingAdaptiveSamplingAtomic = false;
1624 #else
1625   // check whether ray tracing mode is supported
1626   myHasRayTracing = IsGlGreaterEqual (3, 1)
1627                  && arbTboRGB32
1628                  && arbFBOBlit  != NULL;
1629
1630   // check whether textures in ray tracing mode are supported
1631   myHasRayTracingTextures = myHasRayTracing
1632                          && arbTexBindless != NULL;
1633
1634   // check whether adaptive screen sampling in ray tracing mode is supported
1635   myHasRayTracingAdaptiveSampling = myHasRayTracing
1636                                  && core44 != NULL;
1637   myHasRayTracingAdaptiveSamplingAtomic = myHasRayTracingAdaptiveSampling
1638                                        && CheckExtension ("GL_NV_shader_atomic_float");
1639 #endif
1640
1641   if (arbFBO != NULL
1642    && hasFboSRGB)
1643   {
1644     // Detect if window buffer is considered by OpenGL as sRGB-ready
1645     // (linear RGB color written by shader is automatically converted into sRGB)
1646     // or not (offscreen FBO should be blit into window buffer with gamma correction).
1647     const GLenum aDefWinBuffer =
1648     #if !defined(GL_ES_VERSION_2_0)
1649       GL_BACK_LEFT;
1650     #else
1651       GL_BACK;
1652     #endif
1653     GLint aWinColorEncoding = 0; // GL_LINEAR
1654     arbFBO->glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, aDefWinBuffer, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, &aWinColorEncoding);
1655     ResetErrors (true);
1656     myIsSRgbWindow = aWinColorEncoding == GL_SRGB;
1657
1658     // On desktop OpenGL, pixel formats are almost always sRGB-ready, even when not requested;
1659     // it is safe behavior on desktop where GL_FRAMEBUFFER_SRGB is disabled by default
1660     // (contrary to OpenGL ES, where it is enabled by default).
1661     // NVIDIA drivers, however, always return GL_LINEAR even for sRGB-ready pixel formats on Windows platform,
1662     // while AMD and Intel report GL_SRGB as expected.
1663     // macOS drivers seems to be also report GL_LINEAR even for [NSColorSpace sRGBColorSpace].
1664   #if !defined(GL_ES_VERSION_2_0)
1665   #ifdef __APPLE__
1666     myIsSRgbWindow = true;
1667   #else
1668     if (!myIsSRgbWindow
1669       && myVendor.Search ("nvidia") != -1)
1670     {
1671       myIsSRgbWindow = true;
1672     }
1673   #endif
1674   #endif
1675     if (!myIsSRgbWindow)
1676     {
1677       Message::SendTrace ("OpenGl_Context, warning: window buffer is not sRGB-ready.\n"
1678                           "Check OpenGL window creation parameters for optimal performance.");
1679     }
1680   }
1681
1682   // standard formats
1683   mySupportedFormats->Add (Image_Format_Gray);
1684   mySupportedFormats->Add (Image_Format_Alpha);
1685   mySupportedFormats->Add (Image_Format_RGB);
1686   mySupportedFormats->Add (Image_Format_RGB32);
1687   mySupportedFormats->Add (Image_Format_RGBA);
1688   if (extBgra)
1689   {
1690   #if !defined(GL_ES_VERSION_2_0)
1691     // no BGR on OpenGL ES - only BGRA as extension
1692     mySupportedFormats->Add (Image_Format_BGR);
1693   #endif
1694     mySupportedFormats->Add (Image_Format_BGR32);
1695     mySupportedFormats->Add (Image_Format_BGRA);
1696   }
1697   if (arbTexFloat)
1698   {
1699     mySupportedFormats->Add (Image_Format_GrayF);
1700     mySupportedFormats->Add (Image_Format_AlphaF);
1701     mySupportedFormats->Add (Image_Format_RGBF);
1702     mySupportedFormats->Add (Image_Format_RGBAF);
1703     if (hasHalfFloatBuffer)
1704     {
1705       mySupportedFormats->Add (Image_Format_RGBAF_half);
1706     }
1707     if (arbTexRG)
1708     {
1709       mySupportedFormats->Add (Image_Format_RGF);
1710       if (hasHalfFloatBuffer)
1711       {
1712         mySupportedFormats->Add (Image_Format_RGF_half);
1713       }
1714     }
1715     if (extBgra)
1716     {
1717     #if !defined(GL_ES_VERSION_2_0)
1718       mySupportedFormats->Add (Image_Format_BGRF);
1719     #endif
1720       mySupportedFormats->Add (Image_Format_BGRAF);
1721     }
1722   }
1723
1724 #ifdef __EMSCRIPTEN__
1725   if (checkEnableWebGlExtension (*this, "GL_WEBGL_compressed_texture_s3tc")) // GL_WEBGL_compressed_texture_s3tc_srgb for sRGB formats
1726   {
1727     mySupportedFormats->Add (Image_CompressedFormat_RGB_S3TC_DXT1);
1728     mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT1);
1729     mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT3);
1730     mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT5);
1731   }
1732   if (!extPDS
1733     && checkEnableWebGlExtension (*this, "GL_WEBGL_depth_texture"))
1734   {
1735     extPDS = true; // WebGL 1.0 extension (in WebGL 2.0 core)
1736   }
1737 #else
1738   if (CheckExtension ("GL_EXT_texture_compression_s3tc")) // GL_EXT_texture_sRGB for sRGB formats
1739   {
1740     mySupportedFormats->Add (Image_CompressedFormat_RGB_S3TC_DXT1);
1741     mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT1);
1742     mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT3);
1743     mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT5);
1744   }
1745   else
1746   {
1747     if (CheckExtension ("GL_EXT_texture_compression_dxt1"))
1748     {
1749       mySupportedFormats->Add (Image_CompressedFormat_RGB_S3TC_DXT1);
1750       mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT1);
1751     }
1752     if (CheckExtension ("GL_ANGLE_texture_compression_dxt3"))
1753     {
1754       mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT3);
1755     }
1756     if (CheckExtension ("GL_ANGLE_texture_compression_dxt5"))
1757     {
1758       mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT5);
1759     }
1760   }
1761 #endif
1762
1763   // check whether PBR shading model is supported
1764   myHasPBR = arbFBO != NULL
1765           && myMaxTexCombined >= 4
1766           && arbTexFloat
1767           && (IsGlGreaterEqual (3, 0)
1768         #if defined(GL_ES_VERSION_2_0)
1769            || hasHighp
1770         // || CheckExtension ("GL_EXT_shader_texture_lod") fallback is used when extension is unavailable
1771         #else
1772           || (IsGlGreaterEqual (2, 1) && CheckExtension ("GL_EXT_gpu_shader4"))
1773         #endif
1774              );
1775
1776   myDepthPeelingDepthTexUnit      = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_DepthPeelingDepth);      // -6
1777   myDepthPeelingFrontColorTexUnit = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_DepthPeelingFrontColor); // -5
1778   myShadowMapTexUnit              = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_ShadowMap);              // -4
1779   myPBREnvLUTTexUnit              = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_PbrEnvironmentLUT);      // -3
1780   myPBRDiffIBLMapSHTexUnit        = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_PbrIblDiffuseSH);        // -2
1781   myPBRSpecIBLMapTexUnit          = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_PbrIblSpecular);         // -1
1782   if (!myHasPBR)
1783   {
1784     myDepthPeelingDepthTexUnit      = static_cast<Graphic3d_TextureUnit>(myDepthPeelingDepthTexUnit + 3);
1785     myDepthPeelingFrontColorTexUnit = static_cast<Graphic3d_TextureUnit>(myDepthPeelingFrontColorTexUnit + 3);
1786     myShadowMapTexUnit              = static_cast<Graphic3d_TextureUnit>(myShadowMapTexUnit + 3);
1787   }
1788 }
1789
1790 // =======================================================================
1791 // function : MemoryInfo
1792 // purpose  :
1793 // =======================================================================
1794 Standard_Size OpenGl_Context::AvailableMemory() const
1795 {
1796 #if !defined(GL_ES_VERSION_2_0)
1797   if (atiMem)
1798   {
1799     // this is actually information for VBO pool
1800     // however because pools are mostly shared
1801     // it can be used for total GPU memory estimations
1802     GLint aMemInfo[4];
1803     aMemInfo[0] = 0;
1804     glGetIntegerv (GL_VBO_FREE_MEMORY_ATI, aMemInfo);
1805     // returned value is in KiB, however this maybe changed in future
1806     return Standard_Size(aMemInfo[0]) * 1024;
1807   }
1808   else if (nvxMem)
1809   {
1810     // current available dedicated video memory (in KiB), currently unused GPU memory
1811     GLint aMemInfo = 0;
1812     glGetIntegerv (GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &aMemInfo);
1813     return Standard_Size(aMemInfo) * 1024;
1814   }
1815 #endif
1816   return 0;
1817 }
1818
1819 // =======================================================================
1820 // function : MemoryInfo
1821 // purpose  :
1822 // =======================================================================
1823 TCollection_AsciiString OpenGl_Context::MemoryInfo() const
1824 {
1825   TColStd_IndexedDataMapOfStringString aDict;
1826   MemoryInfo (aDict);
1827
1828   TCollection_AsciiString aText;
1829   for (TColStd_IndexedDataMapOfStringString::Iterator anIter (aDict); anIter.More(); anIter.Next())
1830   {
1831     if (!aText.IsEmpty())
1832     {
1833       aText += "\n";
1834     }
1835     aText += TCollection_AsciiString("  ") + anIter.Key() + ": " + anIter.Value();
1836   }
1837   return aText;
1838 }
1839
1840 // =======================================================================
1841 // function : MemoryInfo
1842 // purpose  :
1843 // =======================================================================
1844 void OpenGl_Context::MemoryInfo (TColStd_IndexedDataMapOfStringString& theDict) const
1845 {
1846 #if defined(GL_ES_VERSION_2_0)
1847   (void )theDict;
1848 #elif defined(__APPLE__) && !defined(HAVE_XLIB)
1849   GLint aGlRendId = 0;
1850   CGLGetParameter (CGLGetCurrentContext(), kCGLCPCurrentRendererID, &aGlRendId);
1851
1852   CGLRendererInfoObj  aRendObj = NULL;
1853   CGOpenGLDisplayMask aDispMask = CGDisplayIDToOpenGLDisplayMask (kCGDirectMainDisplay);
1854   GLint aRendNb = 0;
1855   CGLQueryRendererInfo (aDispMask, &aRendObj, &aRendNb);
1856   for (GLint aRendIter = 0; aRendIter < aRendNb; ++aRendIter)
1857   {
1858     GLint aRendId = 0;
1859     if (CGLDescribeRenderer (aRendObj, aRendIter, kCGLRPRendererID, &aRendId) != kCGLNoError
1860      || aRendId != aGlRendId)
1861     {
1862       continue;
1863     }
1864
1865     //kCGLRPVideoMemoryMegabytes   = 131;
1866     //kCGLRPTextureMemoryMegabytes = 132;
1867     GLint aVMem = 0;
1868   #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
1869     if (CGLDescribeRenderer(aRendObj, aRendIter, kCGLRPVideoMemoryMegabytes, &aVMem) == kCGLNoError)
1870     {
1871       addInfo (theDict, "GPU memory",         TCollection_AsciiString() + aVMem + " MiB");
1872     }
1873     if (CGLDescribeRenderer(aRendObj, aRendIter, kCGLRPTextureMemoryMegabytes, &aVMem) == kCGLNoError)
1874     {
1875       addInfo (theDict, "GPU Texture memory", TCollection_AsciiString() + aVMem + " MiB");
1876     }
1877   #else
1878     if (CGLDescribeRenderer(aRendObj, aRendIter, kCGLRPVideoMemory, &aVMem) == kCGLNoError)
1879     {
1880       addInfo (theDict, "GPU memory",         TCollection_AsciiString() + (aVMem / (1024 * 1024)) + " MiB");
1881     }
1882     if (CGLDescribeRenderer(aRendObj, aRendIter, kCGLRPTextureMemory, &aVMem) == kCGLNoError)
1883     {
1884       addInfo (theDict, "GPU Texture memory", TCollection_AsciiString() + (aVMem / (1024 * 1024)) + " MiB");
1885     }
1886   #endif
1887   }
1888 #endif
1889
1890 #if !defined(GL_ES_VERSION_2_0)
1891   if (atiMem)
1892   {
1893     GLint aValues[4];
1894     memset (aValues, 0, sizeof(aValues));
1895     glGetIntegerv (GL_VBO_FREE_MEMORY_ATI, aValues);
1896
1897     // total memory free in the pool
1898     addInfo (theDict, "GPU free memory",    TCollection_AsciiString() + (aValues[0] / 1024) + " MiB");
1899
1900     if (aValues[1] != aValues[0])
1901     {
1902       // largest available free block in the pool
1903       addInfo (theDict, "Largest free block", TCollection_AsciiString() + (aValues[1] / 1024) + " MiB");
1904     }
1905     if (aValues[2] != aValues[0])
1906     {
1907       // total auxiliary memory free
1908       addInfo (theDict, "Free auxiliary memory", TCollection_AsciiString() + (aValues[2] / 1024) + " MiB");
1909     }
1910   }
1911   else if (nvxMem)
1912   {
1913     //current available dedicated video memory (in KiB), currently unused GPU memory
1914     GLint aValue = 0;
1915     glGetIntegerv (GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &aValue);
1916     addInfo (theDict, "GPU free memory", TCollection_AsciiString() + (aValue / 1024) + " MiB");
1917
1918     // dedicated video memory, total size (in KiB) of the GPU memory
1919     GLint aDedicated = 0;
1920     glGetIntegerv (GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, &aDedicated);
1921     addInfo (theDict, "GPU memory", TCollection_AsciiString() + (aDedicated / 1024) + " MiB");
1922
1923     // total available memory, total size (in KiB) of the memory available for allocations
1924     glGetIntegerv (GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, &aValue);
1925     if (aValue != aDedicated)
1926     {
1927       // different only for special configurations
1928       addInfo (theDict, "Total memory", TCollection_AsciiString() + (aValue / 1024) + " MiB");
1929     }
1930   }
1931 #if defined(_WIN32)
1932   else if (myFuncs->wglGetGPUInfoAMD != NULL
1933         && myFuncs->wglGetContextGPUIDAMD != NULL)
1934   {
1935     GLuint aTotalMemMiB = 0;
1936     UINT anAmdId = myFuncs->wglGetContextGPUIDAMD ((HGLRC )myGContext);
1937     if (anAmdId != 0)
1938     {
1939       if (myFuncs->wglGetGPUInfoAMD (anAmdId, WGL_GPU_RAM_AMD, GL_UNSIGNED_INT, sizeof(aTotalMemMiB), &aTotalMemMiB) > 0)
1940       {
1941         addInfo (theDict, "GPU memory", TCollection_AsciiString() + (int )aTotalMemMiB + " MiB");
1942       }
1943     }
1944   }
1945 #endif
1946 #endif
1947
1948 #if !defined(GL_ES_VERSION_2_0) && !defined(__APPLE__) && !defined(_WIN32)
1949   // GLX_RENDERER_VENDOR_ID_MESA
1950   if (myFuncs->glXQueryCurrentRendererIntegerMESA != NULL)
1951   {
1952     unsigned int aVMemMiB = 0;
1953     if (myFuncs->glXQueryCurrentRendererIntegerMESA (GLX_RENDERER_VIDEO_MEMORY_MESA, &aVMemMiB) != False)
1954     {
1955       addInfo (theDict, "GPU memory", TCollection_AsciiString() + int(aVMemMiB) + " MiB");
1956     }
1957   }
1958 #endif
1959 }
1960
1961 // =======================================================================
1962 // function : DiagnosticInfo
1963 // purpose  :
1964 // =======================================================================
1965 void OpenGl_Context::DiagnosticInformation (TColStd_IndexedDataMapOfStringString& theDict,
1966                                             Graphic3d_DiagnosticInfo theFlags) const
1967 {
1968   if ((theFlags & Graphic3d_DiagnosticInfo_NativePlatform) != 0)
1969   {
1970   #if defined(HAVE_EGL)
1971     addInfo (theDict, "EGLVersion",    ::eglQueryString ((EGLDisplay )myDisplay, EGL_VERSION));
1972     addInfo (theDict, "EGLVendor",     ::eglQueryString ((EGLDisplay )myDisplay, EGL_VENDOR));
1973     addInfo (theDict, "EGLClientAPIs", ::eglQueryString ((EGLDisplay )myDisplay, EGL_CLIENT_APIS));
1974     if ((theFlags & Graphic3d_DiagnosticInfo_Extensions) != 0)
1975     {
1976       addInfo (theDict, "EGLExtensions", ::eglQueryString ((EGLDisplay )myDisplay, EGL_EXTENSIONS));
1977     }
1978   #elif defined(_WIN32)
1979     if ((theFlags & Graphic3d_DiagnosticInfo_Extensions) != 0
1980      && myFuncs->wglGetExtensionsStringARB != NULL)
1981     {
1982       const char* aWglExts = myFuncs->wglGetExtensionsStringARB ((HDC )myDisplay);
1983       addInfo (theDict, "WGLExtensions", aWglExts);
1984     }
1985   #elif defined(HAVE_XLIB)
1986     Display* aDisplay = (Display*)myDisplay;
1987     const int aScreen = DefaultScreen(aDisplay);
1988     addInfo (theDict, "GLXDirectRendering", ::glXIsDirect (aDisplay, (GLXContext )myGContext) ? "Yes" : "No");
1989     addInfo (theDict, "GLXVendor",  ::glXQueryServerString (aDisplay, aScreen, GLX_VENDOR));
1990     addInfo (theDict, "GLXVersion", ::glXQueryServerString (aDisplay, aScreen, GLX_VERSION));
1991     if ((theFlags & Graphic3d_DiagnosticInfo_Extensions) != 0)
1992     {
1993       const char* aGlxExts = ::glXQueryExtensionsString (aDisplay, aScreen);
1994       addInfo(theDict, "GLXExtensions", aGlxExts);
1995     }
1996
1997     addInfo (theDict, "GLXClientVendor",  ::glXGetClientString (aDisplay, GLX_VENDOR));
1998     addInfo (theDict, "GLXClientVersion", ::glXGetClientString (aDisplay, GLX_VERSION));
1999     if ((theFlags & Graphic3d_DiagnosticInfo_Extensions) != 0)
2000     {
2001       addInfo (theDict, "GLXClientExtensions", ::glXGetClientString (aDisplay, GLX_EXTENSIONS));
2002     }
2003   #else
2004     //
2005   #endif
2006   }
2007
2008   if ((theFlags & Graphic3d_DiagnosticInfo_Device) != 0)
2009   {
2010     Standard_Integer aDriverVer[2] = {};
2011     ReadGlVersion (aDriverVer[0], aDriverVer[1]);
2012     addInfo (theDict, "GLvendor",    (const char*)::glGetString (GL_VENDOR));
2013     addInfo (theDict, "GLdevice",    (const char*)::glGetString (GL_RENDERER));
2014   #ifdef __EMSCRIPTEN__
2015     if (checkEnableWebGlExtension (*this, "GL_WEBGL_debug_renderer_info"))
2016     {
2017       if (const char* aVendor = (const char*)::glGetString (0x9245))
2018       {
2019         addInfo (theDict, "GLunmaskedVendor", aVendor);
2020       }
2021       if (const char* aDevice = (const char*)::glGetString (0x9246))
2022       {
2023         addInfo (theDict, "GLunmaskedDevice", aDevice);
2024       }
2025     }
2026   #endif
2027
2028     addInfo (theDict, "GLversion",   (const char*)::glGetString (GL_VERSION));
2029     if (myGlVerMajor != aDriverVer[0]
2030      || myGlVerMinor != aDriverVer[1])
2031     {
2032       addInfo (theDict, "GLversionOcct", TCollection_AsciiString (myGlVerMajor) + "." + TCollection_AsciiString (myGlVerMinor));
2033     }
2034     if (IsGlGreaterEqual (2, 0))
2035     {
2036       addInfo (theDict, "GLSLversion", (const char*)::glGetString (GL_SHADING_LANGUAGE_VERSION));
2037     }
2038     if (myIsGlDebugCtx)
2039     {
2040       addInfo (theDict, "GLdebug", "ON");
2041     }
2042   }
2043
2044   if ((theFlags & Graphic3d_DiagnosticInfo_Limits) != 0)
2045   {
2046     addInfo (theDict, "Max texture size", TCollection_AsciiString(myMaxTexDim));
2047     addInfo (theDict, "Max FBO dump size", TCollection_AsciiString() + myMaxDumpSizeX + "x" + myMaxDumpSizeY);
2048     addInfo (theDict, "Max combined texture units", TCollection_AsciiString(myMaxTexCombined));
2049     addInfo (theDict, "Max MSAA samples", TCollection_AsciiString(myMaxMsaaSamples));
2050   }
2051
2052   if ((theFlags & Graphic3d_DiagnosticInfo_FrameBuffer) != 0)
2053   {
2054     GLint aViewport[4] = {};
2055     ::glGetIntegerv (GL_VIEWPORT, aViewport);
2056     addInfo (theDict, "Viewport", TCollection_AsciiString() + aViewport[2] + "x" + aViewport[3]);
2057   }
2058
2059   if ((theFlags & Graphic3d_DiagnosticInfo_Memory) != 0)
2060   {
2061     MemoryInfo (theDict);
2062   }
2063
2064   if ((theFlags & Graphic3d_DiagnosticInfo_Extensions) != 0)
2065   {
2066   #if !defined(GL_ES_VERSION_2_0)
2067     if (IsGlGreaterEqual (3, 0)
2068      && myFuncs->glGetStringi != NULL)
2069     {
2070       TCollection_AsciiString anExtList;
2071       GLint anExtNb = 0;
2072       ::glGetIntegerv (GL_NUM_EXTENSIONS, &anExtNb);
2073       for (GLint anIter = 0; anIter < anExtNb; ++anIter)
2074       {
2075         const char* anExtension = (const char*)myFuncs->glGetStringi (GL_EXTENSIONS, (GLuint)anIter);
2076         if (!anExtList.IsEmpty())
2077         {
2078           anExtList += " ";
2079         }
2080         anExtList += anExtension;
2081       }
2082       addInfo(theDict, "GLextensions", anExtList);
2083     }
2084     else
2085   #endif
2086     {
2087       addInfo (theDict, "GLextensions", (const char*)::glGetString (GL_EXTENSIONS));
2088     }
2089   }
2090 }
2091
2092 // =======================================================================
2093 // function : GetResource
2094 // purpose  :
2095 // =======================================================================
2096 const Handle(OpenGl_Resource)& OpenGl_Context::GetResource (const TCollection_AsciiString& theKey) const
2097 {
2098   return mySharedResources->IsBound (theKey) ? mySharedResources->Find (theKey) : NULL_GL_RESOURCE;
2099 }
2100
2101 // =======================================================================
2102 // function : ShareResource
2103 // purpose  :
2104 // =======================================================================
2105 Standard_Boolean OpenGl_Context::ShareResource (const TCollection_AsciiString& theKey,
2106                                                 const Handle(OpenGl_Resource)& theResource)
2107 {
2108   if (theKey.IsEmpty() || theResource.IsNull())
2109   {
2110     return Standard_False;
2111   }
2112   return mySharedResources->Bind (theKey, theResource);
2113 }
2114
2115 // =======================================================================
2116 // function : ReleaseResource
2117 // purpose  :
2118 // =======================================================================
2119 void OpenGl_Context::ReleaseResource (const TCollection_AsciiString& theKey,
2120                                       const Standard_Boolean         theToDelay)
2121 {
2122   if (!mySharedResources->IsBound (theKey))
2123   {
2124     return;
2125   }
2126   const Handle(OpenGl_Resource)& aRes = mySharedResources->Find (theKey);
2127   if (aRes->GetRefCount() > 1)
2128   {
2129     return;
2130   }
2131
2132   if (theToDelay)
2133   {
2134     myDelayed->Bind (theKey, 1);
2135   }
2136   else
2137   {
2138     aRes->Release (this);
2139     mySharedResources->UnBind (theKey);
2140   }
2141 }
2142
2143 // =======================================================================
2144 // function : ReleaseDelayed
2145 // purpose  :
2146 // =======================================================================
2147 void OpenGl_Context::ReleaseDelayed()
2148 {
2149   // release queued elements
2150   while (!myUnusedResources->IsEmpty())
2151   {
2152     myUnusedResources->First()->Release (this);
2153     myUnusedResources->RemoveFirst();
2154   }
2155
2156   // release delayed shared resources
2157   NCollection_Vector<TCollection_AsciiString> aDeadList;
2158   for (NCollection_DataMap<TCollection_AsciiString, Standard_Integer>::Iterator anIter (*myDelayed);
2159        anIter.More(); anIter.Next())
2160   {
2161     if (++anIter.ChangeValue() <= 2)
2162     {
2163       continue; // postpone release one more frame to ensure no one uses it periodically
2164     }
2165
2166     const TCollection_AsciiString& aKey = anIter.Key();
2167     if (!mySharedResources->IsBound (aKey))
2168     {
2169       // mixed unshared strategy delayed/undelayed was used!
2170       aDeadList.Append (aKey);
2171       continue;
2172     }
2173
2174     const Handle(OpenGl_Resource)& aRes = mySharedResources->ChangeFind (aKey);
2175     if (aRes->GetRefCount() > 1)
2176     {
2177       // should be only 1 instance in mySharedResources
2178       // if not - resource was reused again
2179       aDeadList.Append (aKey);
2180       continue;
2181     }
2182
2183     // release resource if no one requested it more than 2 redraw calls
2184     aRes->Release (this);
2185     mySharedResources->UnBind (aKey);
2186     aDeadList.Append (aKey);
2187   }
2188
2189   for (Standard_Integer anIter = 0; anIter < aDeadList.Length(); ++anIter)
2190   {
2191     myDelayed->UnBind (aDeadList.Value (anIter));
2192   }
2193 }
2194
2195 // =======================================================================
2196 // function : BindTextures
2197 // purpose  :
2198 // =======================================================================
2199 Handle(OpenGl_TextureSet) OpenGl_Context::BindTextures (const Handle(OpenGl_TextureSet)& theTextures,
2200                                                         const Handle(OpenGl_ShaderProgram)& theProgram)
2201 {
2202   const Standard_Integer aTextureSetBits = !theTextures.IsNull() ? theTextures->TextureSetBits() : 0;
2203   const Standard_Integer aProgramBits    = !theProgram.IsNull() ? theProgram->TextureSetBits() : 0;
2204   Standard_Integer aMissingBits = aProgramBits & ~aTextureSetBits;
2205   if (aMissingBits != 0
2206    && myTextureRgbaBlack.IsNull())
2207   {
2208     // allocate mock textures
2209     myTextureRgbaBlack = new OpenGl_Texture();
2210     myTextureRgbaWhite = new OpenGl_Texture();
2211     Image_PixMap anImage;
2212     anImage.InitZero (Image_Format_RGBA, 2, 2, 0, (Standard_Byte )0);
2213     if (!myTextureRgbaBlack->Init (this, OpenGl_TextureFormat::Create<GLubyte, 4>(), Graphic3d_Vec2i (2, 2), Graphic3d_TOT_2D, &anImage))
2214     {
2215       PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH,
2216                     "Error: unable to create unit mock PBR texture map.");
2217     }
2218     anImage.InitZero (Image_Format_RGBA, 2, 2, 0, (Standard_Byte )255);
2219     if (!myTextureRgbaWhite->Init (this, OpenGl_TextureFormat::Create<GLubyte, 4>(), Graphic3d_Vec2i (2, 2), Graphic3d_TOT_2D, &anImage))
2220     {
2221       PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH,
2222                     "Error: unable to create normal mock PBR texture map.");
2223     }
2224   }
2225
2226   Handle(OpenGl_TextureSet) anOldTextures = myActiveTextures;
2227   if (myActiveTextures != theTextures)
2228   {
2229     Handle(OpenGl_Context) aThisCtx (this);
2230     for (OpenGl_TextureSetPairIterator aSlotIter (myActiveTextures, theTextures); aSlotIter.More(); aSlotIter.Next())
2231     {
2232       const Graphic3d_TextureUnit aTexUnit = aSlotIter.Unit();
2233       const OpenGl_Texture* aTextureOld = aSlotIter.Texture1();
2234       const OpenGl_Texture* aTextureNew = aSlotIter.Texture2();
2235       if (aTextureNew == aTextureOld)
2236       {
2237         continue;
2238       }
2239
2240       if (aTextureNew != NULL
2241        && aTextureNew->IsValid())
2242       {
2243         if (aTexUnit >= myMaxTexCombined)
2244         {
2245           PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
2246                        TCollection_AsciiString("Texture unit ") + aTexUnit + " for " + aTextureNew->ResourceId() + " exceeds hardware limit " + myMaxTexCombined);
2247           continue;
2248         }
2249
2250         aTextureNew->Bind (aThisCtx, aTexUnit);
2251         if (aTextureNew->Sampler()->ToUpdateParameters())
2252         {
2253           if (aTextureNew->Sampler()->IsImmutable())
2254           {
2255             aTextureNew->Sampler()->Init (aThisCtx, *aTextureNew);
2256           }
2257           else
2258           {
2259             OpenGl_Sampler::applySamplerParams (aThisCtx, aTextureNew->Sampler()->Parameters(), aTextureNew->Sampler().get(), aTextureNew->GetTarget(), aTextureNew->MaxMipmapLevel());
2260           }
2261         }
2262       #if !defined(GL_ES_VERSION_2_0)
2263         if (core11ffp != NULL)
2264         {
2265           OpenGl_Sampler::applyGlobalTextureParams (aThisCtx, *aTextureNew, aTextureNew->Sampler()->Parameters());
2266         }
2267       #endif
2268       }
2269       else if (aTextureOld != NULL
2270             && aTextureOld->IsValid())
2271       {
2272         aTextureOld->Unbind (aThisCtx, aTexUnit);
2273       #if !defined(GL_ES_VERSION_2_0)
2274         if (core11ffp != NULL)
2275         {
2276           OpenGl_Sampler::resetGlobalTextureParams (aThisCtx, *aTextureOld, aTextureOld->Sampler()->Parameters());
2277         }
2278       #endif
2279       }
2280     }
2281     myActiveTextures = theTextures;
2282   }
2283
2284   if (myActiveMockTextures != aMissingBits)
2285   {
2286     myActiveMockTextures = aMissingBits;
2287     for (Standard_Integer aBitIter = 0; aMissingBits != 0; ++aBitIter)
2288     {
2289       Standard_Integer aUnitMask = 1 << aBitIter;
2290       if ((aUnitMask & aMissingBits) != 0)
2291       {
2292         aMissingBits = aMissingBits & ~aUnitMask;
2293         if (aBitIter == Graphic3d_TextureUnit_Normal)
2294         {
2295           myTextureRgbaBlack->Bind (this, static_cast<Graphic3d_TextureUnit>(aBitIter));
2296         }
2297         else
2298         {
2299           myTextureRgbaWhite->Bind (this, static_cast<Graphic3d_TextureUnit>(aBitIter));
2300         }
2301       }
2302     }
2303   }
2304
2305   return anOldTextures;
2306 }
2307
2308 // =======================================================================
2309 // function : BindProgram
2310 // purpose  :
2311 // =======================================================================
2312 Standard_Boolean OpenGl_Context::BindProgram (const Handle(OpenGl_ShaderProgram)& theProgram)
2313 {
2314   if (core20fwd == NULL)
2315   {
2316     return Standard_False;
2317   }
2318   else if (myActiveProgram == theProgram)
2319   {
2320     return Standard_True;
2321   }
2322
2323   if (theProgram.IsNull()
2324   || !theProgram->IsValid())
2325   {
2326     if (!myActiveProgram.IsNull())
2327     {
2328       core20fwd->glUseProgram (OpenGl_ShaderProgram::NO_PROGRAM);
2329       myActiveProgram.Nullify();
2330     }
2331     return Standard_False;
2332   }
2333
2334   myActiveProgram = theProgram;
2335   core20fwd->glUseProgram (theProgram->ProgramId());
2336   return Standard_True;
2337 }
2338
2339 // =======================================================================
2340 // function : BindDefaultVao
2341 // purpose  :
2342 // =======================================================================
2343 void OpenGl_Context::BindDefaultVao()
2344 {
2345 #if !defined(GL_ES_VERSION_2_0)
2346   if (myDefaultVao == 0
2347    || core32 == NULL)
2348   {
2349     return;
2350   }
2351
2352   core32->glBindVertexArray (myDefaultVao);
2353 #endif
2354 }
2355
2356 // =======================================================================
2357 // function : SetDefaultFrameBuffer
2358 // purpose  :
2359 // =======================================================================
2360 Handle(OpenGl_FrameBuffer) OpenGl_Context::SetDefaultFrameBuffer (const Handle(OpenGl_FrameBuffer)& theFbo)
2361 {
2362   Handle(OpenGl_FrameBuffer) aFbo = myDefaultFbo;
2363   myDefaultFbo = theFbo;
2364   return aFbo;
2365 }
2366
2367 // =======================================================================
2368 // function : SetShadingMaterial
2369 // purpose  :
2370 // =======================================================================
2371 void OpenGl_Context::SetShadingMaterial (const OpenGl_Aspects* theAspect,
2372                                          const Handle(Graphic3d_PresentationAttributes)& theHighlight)
2373 {
2374   const Handle(Graphic3d_Aspects)& anAspect = (!theHighlight.IsNull() && !theHighlight->BasicFillAreaAspect().IsNull())
2375                                             ?  (const Handle(Graphic3d_Aspects)& )theHighlight->BasicFillAreaAspect()
2376                                             :  theAspect->Aspect();
2377
2378   const bool toDistinguish = anAspect->Distinguish();
2379   const bool toMapTexture  = anAspect->ToMapTexture();
2380   const Graphic3d_MaterialAspect& aMatFrontSrc = anAspect->FrontMaterial();
2381   const Graphic3d_MaterialAspect& aMatBackSrc  = toDistinguish
2382                                                ? anAspect->BackMaterial()
2383                                                : aMatFrontSrc;
2384   const Quantity_Color& aFrontIntColor = anAspect->InteriorColor();
2385   const Quantity_Color& aBackIntColor  = toDistinguish
2386                                        ? anAspect->BackInteriorColor()
2387                                        : aFrontIntColor;
2388
2389   myMaterial.Init (*this, aMatFrontSrc, aFrontIntColor, aMatBackSrc, aBackIntColor);
2390   if (!theHighlight.IsNull()
2391     && theHighlight->BasicFillAreaAspect().IsNull())
2392   {
2393     myMaterial.SetColor (theHighlight->ColorRGBA().GetRGB());
2394     myMaterial.SetColor (theHighlight->ColorRGBA().GetRGB());
2395   }
2396
2397   float anAlphaFront = 1.0f, anAlphaBack = 1.0f;
2398   if (CheckIsTransparent (theAspect, theHighlight, anAlphaFront, anAlphaBack))
2399   {
2400     myMaterial.Common[0].Diffuse.a() = anAlphaFront;
2401     myMaterial.Common[1].Diffuse.a() = anAlphaBack;
2402
2403     myMaterial.Pbr[0].BaseColor.a() = anAlphaFront;
2404     myMaterial.Pbr[1].BaseColor.a() = anAlphaBack;
2405   }
2406
2407   // do not update material properties in case of zero reflection mode,
2408   // because GL lighting will be disabled by OpenGl_PrimitiveArray::DrawArray() anyway.
2409   const OpenGl_MaterialState& aMatState = myShaderManager->MaterialState();
2410   float anAlphaCutoff = (anAspect->AlphaMode() == Graphic3d_AlphaMode_Mask
2411                       || anAspect->AlphaMode() == Graphic3d_AlphaMode_MaskBlend)
2412                       ? anAspect->AlphaCutoff()
2413                       : ShortRealLast();
2414   if (anAspect->ToDrawEdges())
2415   {
2416     if (anAspect->InteriorStyle() == Aspect_IS_EMPTY
2417      || (anAspect->InteriorStyle() == Aspect_IS_SOLID
2418       && anAspect->EdgeColorRGBA().Alpha() < 1.0f))
2419     {
2420       anAlphaCutoff = 0.285f;
2421     }
2422   }
2423   if (theAspect->ShadingModel() == Graphic3d_TOSM_UNLIT)
2424   {
2425     if (anAlphaCutoff == aMatState.AlphaCutoff())
2426     {
2427       return;
2428     }
2429   }
2430   else if (myMaterial.IsEqual (aMatState.Material())
2431         && toDistinguish == aMatState.ToDistinguish()
2432         && toMapTexture  == aMatState.ToMapTexture()
2433         && anAlphaCutoff == aMatState.AlphaCutoff())
2434   {
2435     return;
2436   }
2437
2438   myShaderManager->UpdateMaterialStateTo (myMaterial, anAlphaCutoff, toDistinguish, toMapTexture);
2439 }
2440
2441 // =======================================================================
2442 // function : CheckIsTransparent
2443 // purpose  :
2444 // =======================================================================
2445 Standard_Boolean OpenGl_Context::CheckIsTransparent (const OpenGl_Aspects* theAspect,
2446                                                      const Handle(Graphic3d_PresentationAttributes)& theHighlight,
2447                                                      Standard_ShortReal& theAlphaFront,
2448                                                      Standard_ShortReal& theAlphaBack)
2449 {
2450   const Handle(Graphic3d_Aspects)& anAspect = (!theHighlight.IsNull() && !theHighlight->BasicFillAreaAspect().IsNull())
2451                                             ?  (const Handle(Graphic3d_Aspects)& )theHighlight->BasicFillAreaAspect()
2452                                             :  theAspect->Aspect();
2453
2454   const bool toDistinguish = anAspect->Distinguish();
2455   const Graphic3d_MaterialAspect& aMatFrontSrc = anAspect->FrontMaterial();
2456   const Graphic3d_MaterialAspect& aMatBackSrc  = toDistinguish
2457                                                ? anAspect->BackMaterial()
2458                                                : aMatFrontSrc;
2459
2460   // handling transparency
2461   if (!theHighlight.IsNull()
2462     && theHighlight->BasicFillAreaAspect().IsNull())
2463   {
2464     theAlphaFront = theHighlight->ColorRGBA().Alpha();
2465     theAlphaBack  = theHighlight->ColorRGBA().Alpha();
2466   }
2467   else
2468   {
2469     theAlphaFront = aMatFrontSrc.Alpha();
2470     theAlphaBack  = aMatBackSrc .Alpha();
2471   }
2472
2473   if (anAspect->AlphaMode() == Graphic3d_AlphaMode_BlendAuto)
2474   {
2475     return theAlphaFront < 1.0f
2476         || theAlphaBack  < 1.0f;
2477   }
2478   // Graphic3d_AlphaMode_Mask and Graphic3d_AlphaMode_MaskBlend are not considered transparent here
2479   return anAspect->AlphaMode() == Graphic3d_AlphaMode_Blend;
2480 }
2481
2482 // =======================================================================
2483 // function : SetColor4fv
2484 // purpose  :
2485 // =======================================================================
2486 void OpenGl_Context::SetColor4fv (const OpenGl_Vec4& theColor)
2487 {
2488   if (!myActiveProgram.IsNull())
2489   {
2490     if (const OpenGl_ShaderUniformLocation& aLoc = myActiveProgram->GetStateLocation (OpenGl_OCCT_COLOR))
2491     {
2492       myActiveProgram->SetUniform (this, aLoc, Vec4FromQuantityColor (theColor));
2493     }
2494   }
2495 #if !defined(GL_ES_VERSION_2_0)
2496   else if (core11ffp != NULL)
2497   {
2498     core11ffp->glColor4fv (theColor.GetData());
2499   }
2500 #endif
2501 }
2502
2503 // =======================================================================
2504 // function : SetTypeOfLine
2505 // purpose  :
2506 // =======================================================================
2507 void OpenGl_Context::SetTypeOfLine (const Aspect_TypeOfLine  theType,
2508                                     const Standard_ShortReal theFactor)
2509 {
2510   SetLineStipple (theFactor, Graphic3d_Aspects::DefaultLinePatternForType (theType));
2511 }
2512
2513 // =======================================================================
2514 // function : SetLineStipple
2515 // purpose  :
2516 // =======================================================================
2517 void OpenGl_Context::SetLineStipple (const Standard_ShortReal theFactor,
2518                                      const uint16_t thePattern)
2519 {
2520   if (!myActiveProgram.IsNull())
2521   {
2522     if (const OpenGl_ShaderUniformLocation aPatternLoc = myActiveProgram->GetStateLocation (OpenGl_OCCT_LINE_STIPPLE_PATTERN))
2523     {
2524       if (hasGlslBitwiseOps != OpenGl_FeatureNotAvailable)
2525       {
2526         myActiveProgram->SetUniform (this, aPatternLoc, (Standard_Integer )thePattern);
2527       }
2528       else
2529       {
2530         Standard_Integer aPatArr[16] = {};
2531         for (unsigned int aBit = 0; aBit < 16; ++aBit)
2532         {
2533           aPatArr[aBit] = ((unsigned int)(thePattern) & (1U << aBit)) != 0 ? 1 : 0;
2534         }
2535         myActiveProgram->SetUniform (this, aPatternLoc, 16, aPatArr);
2536       }
2537       myActiveProgram->SetUniform (this, myActiveProgram->GetStateLocation (OpenGl_OCCT_LINE_STIPPLE_FACTOR), theFactor);
2538     }
2539     return;
2540   }
2541
2542 #if !defined(GL_ES_VERSION_2_0)
2543   if (thePattern != 0xFFFF)
2544   {
2545     if (core11ffp != NULL)
2546     {
2547       core11fwd->glEnable (GL_LINE_STIPPLE);
2548
2549       core11ffp->glLineStipple (static_cast<GLint>    (theFactor),
2550                                 static_cast<GLushort> (thePattern));
2551     }
2552   }
2553   else
2554   {
2555     if (core11ffp != NULL)
2556     {
2557       core11fwd->glDisable (GL_LINE_STIPPLE);
2558     }
2559   }
2560 #endif
2561 }
2562
2563 // =======================================================================
2564 // function : SetLineWidth
2565 // purpose  :
2566 // =======================================================================
2567 void OpenGl_Context::SetLineWidth (const Standard_ShortReal theWidth)
2568 {
2569 #if !defined(GL_ES_VERSION_2_0)
2570   if (core11ffp != NULL)
2571 #endif
2572   {
2573     // glLineWidth() is still defined within Core Profile, but has no effect with values != 1.0f
2574     core11fwd->glLineWidth (theWidth * myLineWidthScale);
2575   }
2576 }
2577
2578 // =======================================================================
2579 // function : SetTextureMatrix
2580 // purpose  :
2581 // =======================================================================
2582 void OpenGl_Context::SetTextureMatrix (const Handle(Graphic3d_TextureParams)& theParams,
2583                                        const Standard_Boolean theIsTopDown)
2584 {
2585   if (theParams.IsNull())
2586   {
2587     return;
2588   }
2589
2590   const Graphic3d_Vec2& aScale = theParams->Scale();
2591   const Graphic3d_Vec2& aTrans = theParams->Translation();
2592   if (!myActiveProgram.IsNull())
2593   {
2594     const GLint aUniLoc = myActiveProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_TRSF2D);
2595     if (aUniLoc == OpenGl_ShaderProgram::INVALID_LOCATION)
2596     {
2597       return;
2598     }
2599
2600     // pack transformation parameters
2601     OpenGl_Vec4 aTrsf[2] =
2602     {
2603       OpenGl_Vec4 (-aTrans.x(), -aTrans.y(), aScale.x(), aScale.y()),
2604       OpenGl_Vec4 (static_cast<float> (std::sin (-theParams->Rotation() * M_PI / 180.0)),
2605                    static_cast<float> (std::cos (-theParams->Rotation() * M_PI / 180.0)),
2606                    0.0f, 0.0f)
2607     };
2608     if (caps->isTopDownTextureUV != theIsTopDown)
2609     {
2610       // flip V
2611       aTrsf[0].y() = -aTrans.y() + 1.0f / aScale.y();
2612       aTrsf[0].w() = -aScale.y();
2613     }
2614     myActiveProgram->SetUniform (this, aUniLoc, 2, aTrsf);
2615     return;
2616   }
2617
2618 #if !defined(GL_ES_VERSION_2_0)
2619   if (core11ffp != NULL)
2620   {
2621     GLint aMatrixMode = GL_TEXTURE;
2622     ::glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode);
2623
2624     core11ffp->glMatrixMode (GL_TEXTURE);
2625     OpenGl_Mat4 aTextureMat;
2626     if (caps->isTopDownTextureUV != theIsTopDown)
2627     {
2628       // flip V
2629       Graphic3d_TransformUtils::Scale     (aTextureMat,  aScale.x(), -aScale.y(), 1.0f);
2630       Graphic3d_TransformUtils::Translate (aTextureMat, -aTrans.x(), -aTrans.y() + 1.0f / aScale.y(), 0.0f);
2631     }
2632     else
2633     {
2634       Graphic3d_TransformUtils::Scale     (aTextureMat,  aScale.x(),  aScale.y(), 1.0f);
2635       Graphic3d_TransformUtils::Translate (aTextureMat, -aTrans.x(), -aTrans.y(), 0.0f);
2636     }
2637     Graphic3d_TransformUtils::Rotate (aTextureMat, -theParams->Rotation(), 0.0f, 0.0f, 1.0f);
2638     core11ffp->glLoadMatrixf (aTextureMat.GetData());
2639     core11ffp->glMatrixMode (aMatrixMode);
2640   }
2641 #endif
2642 }
2643
2644 // =======================================================================
2645 // function : SetPointSize
2646 // purpose  :
2647 // =======================================================================
2648 void OpenGl_Context::SetPointSize (const Standard_ShortReal theSize)
2649 {
2650   if (!myActiveProgram.IsNull())
2651   {
2652     myActiveProgram->SetUniform (this, myActiveProgram->GetStateLocation (OpenGl_OCCT_POINT_SIZE), theSize);
2653   #if !defined(GL_ES_VERSION_2_0)
2654     //myContext->core11fwd->glEnable (GL_VERTEX_PROGRAM_POINT_SIZE);
2655   #endif
2656   }
2657 #if !defined(GL_ES_VERSION_2_0)
2658   //else
2659   {
2660     core11fwd->glPointSize (theSize);
2661     if (core20fwd != NULL)
2662     {
2663       //myContext->core11fwd->glDisable (GL_VERTEX_PROGRAM_POINT_SIZE);
2664     }
2665   }
2666 #endif
2667 }
2668
2669 // =======================================================================
2670 // function : SetPointSpriteOrigin
2671 // purpose  :
2672 // =======================================================================
2673 void OpenGl_Context::SetPointSpriteOrigin()
2674 {
2675 #if !defined(GL_ES_VERSION_2_0)
2676   if (core15fwd == NULL)
2677   {
2678     return;
2679   }
2680
2681   const int aNewState = !myActiveProgram.IsNull() ? GL_UPPER_LEFT : GL_LOWER_LEFT;
2682   if (myPointSpriteOrig != aNewState)
2683   {
2684     myPointSpriteOrig = aNewState;
2685     core15fwd->glPointParameteri (GL_POINT_SPRITE_COORD_ORIGIN, aNewState);
2686   }
2687 #endif
2688 }
2689
2690 // =======================================================================
2691 // function : SetGlNormalizeEnabled
2692 // purpose  :
2693 // =======================================================================
2694 Standard_Boolean OpenGl_Context::SetGlNormalizeEnabled (Standard_Boolean isEnabled)
2695 {
2696   if (isEnabled == myIsGlNormalizeEnabled)
2697   {
2698     return myIsGlNormalizeEnabled;
2699   }
2700
2701   Standard_Boolean anOldGlNormalize = myIsGlNormalizeEnabled;
2702   myIsGlNormalizeEnabled = isEnabled;
2703 #if !defined(GL_ES_VERSION_2_0)
2704   if (core11ffp != NULL)
2705   {
2706     if (isEnabled)
2707     {
2708       core11fwd->glEnable  (GL_NORMALIZE);
2709     }
2710     else
2711     {
2712       core11fwd->glDisable (GL_NORMALIZE);
2713     }
2714   }
2715 #endif
2716
2717   return anOldGlNormalize;
2718 }
2719
2720 // =======================================================================
2721 // function : SetShadeModel
2722 // purpose  :
2723 // =======================================================================
2724 void OpenGl_Context::SetShadeModel (Graphic3d_TypeOfShadingModel theModel)
2725 {
2726 #if !defined(GL_ES_VERSION_2_0)
2727   if (core11ffp != NULL)
2728   {
2729     const Standard_Integer aModel = theModel == Graphic3d_TOSM_FACET
2730                                  || theModel == Graphic3d_TOSM_PBR_FACET ? GL_FLAT : GL_SMOOTH;
2731     if (myShadeModel == aModel)
2732     {
2733       return;
2734     }
2735     myShadeModel = aModel;
2736     core11ffp->glShadeModel (aModel);
2737   }
2738 #else
2739   (void )theModel;
2740 #endif
2741 }
2742
2743 // =======================================================================
2744 // function : SetPolygonMode
2745 // purpose  :
2746 // =======================================================================
2747 Standard_Integer OpenGl_Context::SetPolygonMode (const Standard_Integer theMode)
2748 {
2749   if (myPolygonMode == theMode)
2750   {
2751     return myPolygonMode;
2752   }
2753
2754   const Standard_Integer anOldPolygonMode = myPolygonMode;
2755
2756   myPolygonMode = theMode;
2757
2758 #if !defined(GL_ES_VERSION_2_0)
2759   ::glPolygonMode (GL_FRONT_AND_BACK, (GLenum)theMode);
2760 #endif
2761
2762   return anOldPolygonMode;
2763 }
2764
2765 // =======================================================================
2766 // function : SetPolygonHatchEnabled
2767 // purpose  :
2768 // =======================================================================
2769 bool OpenGl_Context::SetPolygonHatchEnabled (const bool theIsEnabled)
2770 {
2771   if (core11ffp == NULL)
2772   {
2773     return false;
2774   }
2775   else if (myHatchIsEnabled == theIsEnabled)
2776   {
2777     return theIsEnabled;
2778   }
2779
2780   const bool anOldIsEnabled = myHatchIsEnabled;
2781 #if !defined(GL_ES_VERSION_2_0)
2782   if (theIsEnabled
2783    && myActiveHatchType != Aspect_HS_SOLID)
2784   {
2785     core11fwd->glEnable (GL_POLYGON_STIPPLE);
2786   }
2787   else
2788   {
2789     core11fwd->glDisable (GL_POLYGON_STIPPLE);
2790   }
2791 #endif
2792   myHatchIsEnabled = theIsEnabled;
2793   return anOldIsEnabled;
2794 }
2795
2796 // =======================================================================
2797 // function : SetPolygonHatchStyle
2798 // purpose  :
2799 // =======================================================================
2800 Standard_Integer OpenGl_Context::SetPolygonHatchStyle (const Handle(Graphic3d_HatchStyle)& theStyle)
2801 {
2802   const Standard_Integer aNewStyle = !theStyle.IsNull() ? theStyle->HatchType() : Aspect_HS_SOLID;
2803   if (myActiveHatchType == aNewStyle
2804    || core11ffp == NULL)
2805   {
2806     return myActiveHatchType;
2807   }
2808
2809 #if !defined(GL_ES_VERSION_2_0)
2810   if (aNewStyle == Aspect_HS_SOLID)
2811   {
2812     if (myHatchIsEnabled)
2813     {
2814       core11fwd->glDisable (GL_POLYGON_STIPPLE);
2815     }
2816     return myActiveHatchType;
2817   }
2818
2819   if (myHatchStyles.IsNull()
2820   && !GetResource ("OpenGl_LineAttributes", myHatchStyles))
2821   {
2822     // share and register for release once the resource is no longer used
2823     myHatchStyles = new OpenGl_LineAttributes();
2824     ShareResource ("OpenGl_LineAttributes", myHatchStyles);
2825   }
2826
2827   const Standard_Integer anOldType = myActiveHatchType;
2828   myActiveHatchType = aNewStyle;
2829   myHatchStyles->SetTypeOfHatch (this, theStyle);
2830   if (myHatchIsEnabled
2831    && anOldType == Aspect_HS_SOLID)
2832   {
2833     core11fwd->glEnable (GL_POLYGON_STIPPLE);
2834   }
2835   return anOldType;
2836 #else
2837   return myActiveHatchType;
2838 #endif
2839 }
2840
2841 // =======================================================================
2842 // function : SetPolygonOffset
2843 // purpose  :
2844 // =======================================================================
2845 void OpenGl_Context::SetPolygonOffset (const Graphic3d_PolygonOffset& theOffset)
2846 {
2847   const bool toFillOld = (myPolygonOffset.Mode & Aspect_POM_Fill) == Aspect_POM_Fill;
2848   const bool toFillNew = (theOffset.Mode       & Aspect_POM_Fill) == Aspect_POM_Fill;
2849   if (toFillNew != toFillOld)
2850   {
2851     if (toFillNew)
2852     {
2853       core11fwd->glEnable (GL_POLYGON_OFFSET_FILL);
2854     }
2855     else
2856     {
2857       core11fwd->glDisable (GL_POLYGON_OFFSET_FILL);
2858     }
2859   }
2860
2861 #if !defined(GL_ES_VERSION_2_0)
2862   const bool toLineOld = (myPolygonOffset.Mode & Aspect_POM_Line) == Aspect_POM_Line;
2863   const bool toLineNew = (theOffset.Mode       & Aspect_POM_Line) == Aspect_POM_Line;
2864   if (toLineNew != toLineOld)
2865   {
2866     if (toLineNew)
2867     {
2868       core11fwd->glEnable (GL_POLYGON_OFFSET_LINE);
2869     }
2870     else
2871     {
2872       core11fwd->glDisable (GL_POLYGON_OFFSET_LINE);
2873     }
2874   }
2875
2876   const bool toPointOld = (myPolygonOffset.Mode & Aspect_POM_Point) == Aspect_POM_Point;
2877   const bool toPointNew = (theOffset.Mode       & Aspect_POM_Point) == Aspect_POM_Point;
2878   if (toPointNew != toPointOld)
2879   {
2880     if (toPointNew)
2881     {
2882       core11fwd->glEnable (GL_POLYGON_OFFSET_POINT);
2883     }
2884     else
2885     {
2886       core11fwd->glDisable (GL_POLYGON_OFFSET_POINT);
2887     }
2888   }
2889 #endif
2890
2891   if (myPolygonOffset.Factor != theOffset.Factor
2892    || myPolygonOffset.Units  != theOffset.Units)
2893   {
2894     core11fwd->glPolygonOffset (theOffset.Factor, theOffset.Units);
2895   }
2896   myPolygonOffset = theOffset;
2897 }
2898
2899 // =======================================================================
2900 // function : SetCamera
2901 // purpose  :
2902 // =======================================================================
2903 void OpenGl_Context::SetCamera (const Handle(Graphic3d_Camera)& theCamera)
2904 {
2905   myCamera = theCamera;
2906   if (!theCamera.IsNull())
2907   {
2908     ProjectionState.SetCurrent (theCamera->ProjectionMatrixF());
2909     WorldViewState .SetCurrent (theCamera->OrientationMatrixF());
2910     ApplyProjectionMatrix();
2911     ApplyWorldViewMatrix();
2912   }
2913 }
2914
2915 // =======================================================================
2916 // function : ApplyModelWorldMatrix
2917 // purpose  :
2918 // =======================================================================
2919 void OpenGl_Context::ApplyModelWorldMatrix()
2920 {
2921   if (myShaderManager->ModelWorldState().ModelWorldMatrix() != ModelWorldState.Current())
2922   {
2923     myShaderManager->UpdateModelWorldStateTo (ModelWorldState.Current());
2924   }
2925 }
2926
2927 // =======================================================================
2928 // function : ApplyWorldViewMatrix
2929 // purpose  :
2930 // =======================================================================
2931 void OpenGl_Context::ApplyWorldViewMatrix()
2932 {
2933   if (myShaderManager->ModelWorldState().ModelWorldMatrix() != THE_IDENTITY_MATRIX)
2934   {
2935     myShaderManager->UpdateModelWorldStateTo (THE_IDENTITY_MATRIX);
2936   }
2937   if (myShaderManager->WorldViewState().WorldViewMatrix() != WorldViewState.Current())
2938   {
2939     myShaderManager->UpdateWorldViewStateTo (WorldViewState.Current());
2940   }
2941 }
2942
2943 // =======================================================================
2944 // function : ApplyModelViewMatrix
2945 // purpose  :
2946 // =======================================================================
2947 void OpenGl_Context::ApplyModelViewMatrix()
2948 {
2949   if (myShaderManager->ModelWorldState().ModelWorldMatrix() != ModelWorldState.Current())
2950   {
2951     myShaderManager->UpdateModelWorldStateTo (ModelWorldState.Current());
2952   }
2953   if (myShaderManager->WorldViewState().WorldViewMatrix() != WorldViewState.Current())
2954   {
2955     myShaderManager->UpdateWorldViewStateTo  (WorldViewState.Current());
2956   }
2957 }
2958
2959 // =======================================================================
2960 // function : ApplyProjectionMatrix
2961 // purpose  :
2962 // =======================================================================
2963 void OpenGl_Context::ApplyProjectionMatrix()
2964 {
2965   if (myShaderManager->ProjectionState().ProjectionMatrix() != ProjectionState.Current())
2966   {
2967     myShaderManager->UpdateProjectionStateTo (ProjectionState.Current());
2968   }
2969 }
2970
2971 // =======================================================================
2972 // function : EnableFeatures
2973 // purpose  :
2974 // =======================================================================
2975 void OpenGl_Context::EnableFeatures() const
2976 {
2977   //
2978 }
2979
2980 // =======================================================================
2981 // function : DisableFeatures
2982 // purpose  :
2983 // =======================================================================
2984 void OpenGl_Context::DisableFeatures() const
2985 {
2986   // Disable stuff that's likely to slow down glDrawPixels.
2987   core11fwd->glDisable(GL_DITHER);
2988   core11fwd->glDisable(GL_BLEND);
2989   core11fwd->glDisable(GL_DEPTH_TEST);
2990   core11fwd->glDisable(GL_STENCIL_TEST);
2991
2992 #if !defined(GL_ES_VERSION_2_0)
2993   if (core11ffp == NULL)
2994   {
2995     return;
2996   }
2997
2998   core11fwd->glDisable(GL_TEXTURE_1D);
2999   core11fwd->glDisable(GL_TEXTURE_2D);
3000
3001   core11fwd->glDisable(GL_LIGHTING);
3002   core11fwd->glDisable(GL_ALPHA_TEST);
3003   core11fwd->glDisable(GL_FOG);
3004   core11fwd->glDisable(GL_LOGIC_OP);
3005
3006   glPixelTransferi(GL_MAP_COLOR, GL_FALSE);
3007   glPixelTransferi(GL_RED_SCALE, 1);
3008   glPixelTransferi(GL_RED_BIAS, 0);
3009   glPixelTransferi(GL_GREEN_SCALE, 1);
3010   glPixelTransferi(GL_GREEN_BIAS, 0);
3011   glPixelTransferi(GL_BLUE_SCALE, 1);
3012   glPixelTransferi(GL_BLUE_BIAS, 0);
3013   glPixelTransferi(GL_ALPHA_SCALE, 1);
3014   glPixelTransferi(GL_ALPHA_BIAS, 0);
3015
3016   if ((myGlVerMajor >= 1) && (myGlVerMinor >= 2))
3017   {
3018     if (CheckExtension ("GL_CONVOLUTION_1D_EXT"))
3019       core11fwd->glDisable(GL_CONVOLUTION_1D_EXT);
3020
3021     if (CheckExtension ("GL_CONVOLUTION_2D_EXT"))
3022       core11fwd->glDisable(GL_CONVOLUTION_2D_EXT);
3023
3024     if (CheckExtension ("GL_SEPARABLE_2D_EXT"))
3025       core11fwd->glDisable(GL_SEPARABLE_2D_EXT);
3026
3027     if (CheckExtension ("GL_SEPARABLE_2D_EXT"))
3028       core11fwd->glDisable(GL_HISTOGRAM_EXT);
3029
3030     if (CheckExtension ("GL_MINMAX_EXT"))
3031       core11fwd->glDisable(GL_MINMAX_EXT);
3032
3033     if (CheckExtension ("GL_TEXTURE_3D_EXT"))
3034       core11fwd->glDisable(GL_TEXTURE_3D_EXT);
3035   }
3036 #endif
3037 }
3038
3039 // =======================================================================
3040 // function : SetColorMaskRGBA
3041 // purpose  :
3042 // =======================================================================
3043 void OpenGl_Context::SetColorMaskRGBA (const NCollection_Vec4<bool>& theVal)
3044 {
3045   core11fwd->glColorMask (theVal.r() ? GL_TRUE : GL_FALSE,
3046                theVal.g() ? GL_TRUE : GL_FALSE,
3047                theVal.b() ? GL_TRUE : GL_FALSE,
3048                theVal.a() ? GL_TRUE : GL_FALSE);
3049   myColorMask = theVal;
3050 }
3051
3052 // =======================================================================
3053 // function : SetColorMask
3054 // purpose  :
3055 // =======================================================================
3056 bool OpenGl_Context::SetColorMask (bool theToWriteColor)
3057 {
3058   const bool anOldValue = myColorMask.r();
3059   myColorMask.SetValues (theToWriteColor, theToWriteColor, theToWriteColor, caps->buffersOpaqueAlpha ? false : theToWriteColor);
3060   const GLboolean toWrite = theToWriteColor ? GL_TRUE : GL_FALSE;
3061   core11fwd->glColorMask (toWrite, toWrite, toWrite, myColorMask.a() ? GL_TRUE : GL_FALSE);
3062   return anOldValue;
3063 }
3064
3065 // =======================================================================
3066 // function : SetSampleAlphaToCoverage
3067 // purpose  :
3068 // =======================================================================
3069 bool OpenGl_Context::SetSampleAlphaToCoverage (bool theToEnable)
3070 {
3071   bool toEnable = myAllowAlphaToCov && theToEnable;
3072   if (myAlphaToCoverage == toEnable)
3073   {
3074     return myAlphaToCoverage;
3075   }
3076
3077   if (core15fwd != NULL)
3078   {
3079     if (toEnable)
3080     {
3081       //core15fwd->core15fwd->glSampleCoverage (1.0f, GL_FALSE);
3082       core15fwd->glEnable (GL_SAMPLE_ALPHA_TO_COVERAGE);
3083     }
3084     else
3085     {
3086       core15fwd->glDisable (GL_SAMPLE_ALPHA_TO_COVERAGE);
3087     }
3088   }
3089
3090   const bool anOldValue = myAlphaToCoverage;
3091   myAlphaToCoverage = toEnable;
3092   return anOldValue;
3093 }
3094
3095 // =======================================================================
3096 // function : GetBufferSubData
3097 // purpose  :
3098 // =======================================================================
3099 bool OpenGl_Context::GetBufferSubData (GLenum theTarget, GLintptr theOffset, GLsizeiptr theSize, void* theData)
3100 {
3101   if (!hasGetBufferData)
3102   {
3103     return false;
3104   }
3105 #ifdef __EMSCRIPTEN__
3106   EM_ASM_(
3107   {
3108     Module.ctx.getBufferSubData($0, $1, HEAPU8.subarray($2, $2 + $3));
3109   }, theTarget, theOffset, theData, theSize);
3110   return true;
3111 #elif defined(GL_ES_VERSION_2_0)
3112   if (void* aData = core30->glMapBufferRange (theTarget, theOffset, theSize, GL_MAP_READ_BIT))
3113   {
3114     memcpy (theData, aData, theSize);
3115     core30->glUnmapBuffer (theTarget);
3116     return true;
3117   }
3118   return false;
3119 #else
3120   core15fwd->glGetBufferSubData (theTarget, theOffset, theSize, theData);
3121   return true;
3122 #endif
3123 }
3124
3125 // =======================================================================
3126 // function : DumpJson
3127 // purpose  :
3128 // =======================================================================
3129 void OpenGl_Context::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
3130 {
3131   OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
3132
3133   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myAnisoMax)
3134   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myTexClamp)
3135   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMaxTexDim)
3136   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMaxTexCombined)
3137   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMaxDumpSizeX)
3138   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMaxDumpSizeY)
3139   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMaxClipPlanes)
3140   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMaxMsaaSamples)
3141   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMaxDrawBuffers)
3142   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMaxColorAttachments)
3143   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myGlVerMajor)
3144   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myGlVerMinor)
3145   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsInitialized)
3146   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsStereoBuffers)
3147   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsGlNormalizeEnabled)
3148
3149   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myHasRayTracing)
3150   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myHasRayTracingTextures)
3151   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myHasRayTracingAdaptiveSampling)
3152   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myHasRayTracingAdaptiveSamplingAtomic)
3153
3154   for (int i = 0; i < 4; i++)
3155   {
3156     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myViewport[i])
3157   }
3158
3159   for (int i = 0; i < 4; i++)
3160   {
3161     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myViewportVirt[i])
3162   }
3163
3164   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myPointSpriteOrig)
3165   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myRenderMode)
3166   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myPolygonMode)
3167   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myPolygonOffset)
3168   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myToCullBackFaces)
3169   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myReadBuffer)
3170
3171   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myDefaultVao)
3172   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myColorMask)
3173   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myAllowAlphaToCov)
3174   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myAlphaToCoverage)
3175   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsGlDebugCtx)
3176
3177   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myResolution)
3178   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myResolutionRatio)
3179
3180   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myLineWidthScale)
3181   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myLineFeather)
3182   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myRenderScale)
3183   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myRenderScaleInv)
3184   
3185   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &ModelWorldState)
3186   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &WorldViewState)
3187   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &ProjectionState)
3188 }
3189
3190 // =======================================================================
3191 // function : DumpJsonOpenGlState
3192 // purpose  :
3193 // =======================================================================
3194 void OpenGl_Context::DumpJsonOpenGlState (Standard_OStream& theOStream, Standard_Integer)
3195 {
3196   GLboolean isEnableBlend = glIsEnabled (GL_BLEND);
3197   GLboolean isEnableCullFace = glIsEnabled (GL_CULL_FACE);
3198   GLboolean isEnableDepthTest = glIsEnabled (GL_DEPTH_TEST);
3199   
3200   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, isEnableBlend)
3201   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, isEnableCullFace)
3202   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, isEnableDepthTest)
3203 }
3204