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