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