0031196: Visualization, TKOpenGl - enable Ray-Tracing using OpenGL ES 3.2
[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   // initialize debug context extension
1514   if (arbDbg != NULL
1515    && caps->contextDebug)
1516   {
1517     // setup default callback
1518     myIsGlDebugCtx = Standard_True;
1519     arbDbg->glDebugMessageCallback (debugCallbackWrap, this);
1520   #if defined(GL_ES_VERSION_2_0)
1521     ::glEnable (GL_DEBUG_OUTPUT);
1522   #else
1523     if (core43 != NULL)
1524     {
1525       ::glEnable (GL_DEBUG_OUTPUT);
1526     }
1527   #endif
1528     if (caps->contextSyncDebug)
1529     {
1530       // note that some broken implementations (e.g. simulators) might generate error message on this call
1531       ::glEnable (GL_DEBUG_OUTPUT_SYNCHRONOUS);
1532     }
1533   }
1534
1535   if (hasDrawBuffers)
1536   {
1537     glGetIntegerv (GL_MAX_DRAW_BUFFERS,      &myMaxDrawBuffers);
1538     glGetIntegerv (GL_MAX_COLOR_ATTACHMENTS, &myMaxColorAttachments);
1539     if (myDrawBuffers.Length() < myMaxDrawBuffers)
1540     {
1541       myDrawBuffers.Resize (0, myMaxDrawBuffers - 1, false);
1542     }
1543   }
1544
1545   glGetIntegerv (GL_MAX_TEXTURE_SIZE, &myMaxTexDim);
1546 #if !defined(GL_ES_VERSION_2_0)
1547   if (IsGlGreaterEqual (1, 3) && core11 != NULL)
1548   {
1549     // this is a maximum of texture units for FFP functionality,
1550     // usually smaller than combined texture units available for GLSL
1551     glGetIntegerv (GL_MAX_TEXTURE_UNITS, &myMaxTexUnitsFFP);
1552     myMaxTexCombined = myMaxTexUnitsFFP;
1553   }
1554 #endif
1555   if (IsGlGreaterEqual (2, 0))
1556   {
1557     glGetIntegerv (GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &myMaxTexCombined);
1558   }
1559   mySpriteTexUnit = myMaxTexCombined >= 2
1560                   ? Graphic3d_TextureUnit_PointSprite
1561                   : Graphic3d_TextureUnit_0;
1562
1563   GLint aMaxVPortSize[2] = {0, 0};
1564   glGetIntegerv (GL_MAX_VIEWPORT_DIMS, aMaxVPortSize);
1565   myMaxDumpSizeX = Min (aMaxVPortSize[0], myMaxTexDim);
1566   myMaxDumpSizeY = Min (aMaxVPortSize[1], myMaxTexDim);
1567   if (myVendor == "intel")
1568   {
1569     // Intel drivers have known bug with empty dump for images with width>=5462
1570     myMaxDumpSizeX = Min (myMaxDumpSizeX, 4096);
1571   }
1572
1573   if (extAnis)
1574   {
1575     glGetIntegerv (GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &myAnisoMax);
1576   }
1577
1578   myClippingState.Init();
1579
1580 #if defined(GL_ES_VERSION_2_0)
1581   if (IsGlGreaterEqual (3, 1)
1582    && myFuncs->glTexStorage2DMultisample != NULL)
1583   {
1584     // MSAA RenderBuffers have been defined in OpenGL ES 3.0,
1585     // but MSAA Textures - only in OpenGL ES 3.1+
1586     ::glGetIntegerv (GL_MAX_SAMPLES, &myMaxMsaaSamples);
1587   }
1588 #else
1589   if (core30fwd != NULL)
1590   {
1591     // MSAA RenderBuffers have been defined in OpenGL 3.0,
1592     // but MSAA Textures - only in OpenGL 3.2+
1593     if (core32 != NULL)
1594     {
1595       ::glGetIntegerv (GL_MAX_SAMPLES, &myMaxMsaaSamples);
1596     }
1597     else if (CheckExtension ("GL_ARB_texture_multisample")
1598           && myFuncs->glTexImage2DMultisample != NULL)
1599     {
1600       GLint aNbColorSamples = 0, aNbDepthSamples = 0;
1601       ::glGetIntegerv (GL_MAX_COLOR_TEXTURE_SAMPLES, &aNbColorSamples);
1602       ::glGetIntegerv (GL_MAX_DEPTH_TEXTURE_SAMPLES, &aNbDepthSamples);
1603       myMaxMsaaSamples = Min (aNbColorSamples, aNbDepthSamples);
1604     }
1605   }
1606 #endif
1607
1608 #if !defined(GL_ES_VERSION_2_0)
1609   if (core32 != NULL && isCoreProfile)
1610   {
1611     core32->glGenVertexArrays (1, &myDefaultVao);
1612   }
1613
1614   myTexClamp = IsGlGreaterEqual (1, 2) ? GL_CLAMP_TO_EDGE : GL_CLAMP;
1615
1616   GLint aStereo = GL_FALSE;
1617   glGetIntegerv (GL_STEREO, &aStereo);
1618   myIsStereoBuffers = aStereo == 1;
1619
1620   // get number of maximum clipping planes
1621   glGetIntegerv (GL_MAX_CLIP_PLANES, &myMaxClipPlanes);
1622 #endif
1623
1624 #if defined(GL_ES_VERSION_2_0)
1625   // check whether ray tracing mode is supported
1626   myHasRayTracing = IsGlGreaterEqual (3, 2);
1627   myHasRayTracingTextures = myHasRayTracingAdaptiveSampling = myHasRayTracingAdaptiveSamplingAtomic = false;
1628 #else
1629   // check whether ray tracing mode is supported
1630   myHasRayTracing = IsGlGreaterEqual (3, 1)
1631                  && arbTboRGB32
1632                  && arbFBOBlit  != NULL;
1633
1634   // check whether textures in ray tracing mode are supported
1635   myHasRayTracingTextures = myHasRayTracing
1636                          && arbTexBindless != NULL;
1637
1638   // check whether adaptive screen sampling in ray tracing mode is supported
1639   myHasRayTracingAdaptiveSampling = myHasRayTracing
1640                                  && core44 != NULL;
1641   myHasRayTracingAdaptiveSamplingAtomic = myHasRayTracingAdaptiveSampling
1642                                        && CheckExtension ("GL_NV_shader_atomic_float");
1643 #endif
1644
1645   if (arbFBO != NULL
1646    && hasFboSRGB)
1647   {
1648     // Detect if window buffer is considered by OpenGL as sRGB-ready
1649     // (linear RGB color written by shader is automatically converted into sRGB)
1650     // or not (offscreen FBO should be blit into window buffer with gamma correction).
1651     const GLenum aDefWinBuffer =
1652     #if !defined(GL_ES_VERSION_2_0)
1653       GL_BACK_LEFT;
1654     #else
1655       GL_BACK;
1656     #endif
1657     GLint aWinColorEncoding = 0; // GL_LINEAR
1658     arbFBO->glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, aDefWinBuffer, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, &aWinColorEncoding);
1659     ResetErrors (true);
1660     myIsSRgbWindow = aWinColorEncoding == GL_SRGB;
1661
1662     // On desktop OpenGL, pixel formats are almost always sRGB-ready, even when not requested;
1663     // it is safe behavior on desktop where GL_FRAMEBUFFER_SRGB is disabled by default
1664     // (contrary to OpenGL ES, where it is enabled by default).
1665     // NVIDIA drivers, however, always return GL_LINEAR even for sRGB-ready pixel formats on Windows platform,
1666     // while AMD and Intel report GL_SRGB as expected.
1667     // macOS drivers seems to be also report GL_LINEAR even for [NSColorSpace sRGBColorSpace].
1668   #if !defined(GL_ES_VERSION_2_0)
1669   #ifdef __APPLE__
1670     myIsSRgbWindow = true;
1671   #else
1672     if (!myIsSRgbWindow
1673       && myVendor.Search ("nvidia") != -1)
1674     {
1675       myIsSRgbWindow = true;
1676     }
1677   #endif
1678   #endif
1679     if (!myIsSRgbWindow)
1680     {
1681       Message::SendTrace ("OpenGl_Context, warning: window buffer is not sRGB-ready.\n"
1682                           "Check OpenGL window creation parameters for optimal performance.");
1683     }
1684   }
1685
1686   // standard formats
1687   mySupportedFormats->Add (Image_Format_Gray);
1688   mySupportedFormats->Add (Image_Format_Alpha);
1689   mySupportedFormats->Add (Image_Format_RGB);
1690   mySupportedFormats->Add (Image_Format_RGB32);
1691   mySupportedFormats->Add (Image_Format_RGBA);
1692   if (extBgra)
1693   {
1694   #if !defined(GL_ES_VERSION_2_0)
1695     // no BGR on OpenGL ES - only BGRA as extension
1696     mySupportedFormats->Add (Image_Format_BGR);
1697   #endif
1698     mySupportedFormats->Add (Image_Format_BGR32);
1699     mySupportedFormats->Add (Image_Format_BGRA);
1700   }
1701   if (arbTexFloat)
1702   {
1703     mySupportedFormats->Add (Image_Format_GrayF);
1704     mySupportedFormats->Add (Image_Format_AlphaF);
1705     mySupportedFormats->Add (Image_Format_RGBF);
1706     mySupportedFormats->Add (Image_Format_RGBAF);
1707     if (hasHalfFloatBuffer)
1708     {
1709       mySupportedFormats->Add (Image_Format_RGBAF_half);
1710     }
1711     if (arbTexRG)
1712     {
1713       mySupportedFormats->Add (Image_Format_RGF);
1714       if (hasHalfFloatBuffer)
1715       {
1716         mySupportedFormats->Add (Image_Format_RGF_half);
1717       }
1718     }
1719     if (extBgra)
1720     {
1721     #if !defined(GL_ES_VERSION_2_0)
1722       mySupportedFormats->Add (Image_Format_BGRF);
1723     #endif
1724       mySupportedFormats->Add (Image_Format_BGRAF);
1725     }
1726   }
1727
1728 #ifdef __EMSCRIPTEN__
1729   if (checkEnableWebGlExtension (*this, "GL_WEBGL_compressed_texture_s3tc")) // GL_WEBGL_compressed_texture_s3tc_srgb for sRGB formats
1730   {
1731     mySupportedFormats->Add (Image_CompressedFormat_RGB_S3TC_DXT1);
1732     mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT1);
1733     mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT3);
1734     mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT5);
1735   }
1736   if (!extPDS
1737     && checkEnableWebGlExtension (*this, "GL_WEBGL_depth_texture"))
1738   {
1739     extPDS = true; // WebGL 1.0 extension (in WebGL 2.0 core)
1740   }
1741 #else
1742   if (CheckExtension ("GL_EXT_texture_compression_s3tc")) // GL_EXT_texture_sRGB for sRGB formats
1743   {
1744     mySupportedFormats->Add (Image_CompressedFormat_RGB_S3TC_DXT1);
1745     mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT1);
1746     mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT3);
1747     mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT5);
1748   }
1749   else
1750   {
1751     if (CheckExtension ("GL_EXT_texture_compression_dxt1"))
1752     {
1753       mySupportedFormats->Add (Image_CompressedFormat_RGB_S3TC_DXT1);
1754       mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT1);
1755     }
1756     if (CheckExtension ("GL_ANGLE_texture_compression_dxt3"))
1757     {
1758       mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT3);
1759     }
1760     if (CheckExtension ("GL_ANGLE_texture_compression_dxt5"))
1761     {
1762       mySupportedFormats->Add (Image_CompressedFormat_RGBA_S3TC_DXT5);
1763     }
1764   }
1765 #endif
1766
1767   // check whether PBR shading model is supported
1768   myHasPBR = arbFBO != NULL
1769           && myMaxTexCombined >= 4
1770           && arbTexFloat
1771           && (IsGlGreaterEqual (3, 0)
1772         #if defined(GL_ES_VERSION_2_0)
1773            || hasHighp
1774         // || CheckExtension ("GL_EXT_shader_texture_lod") fallback is used when extension is unavailable
1775         #else
1776           || (IsGlGreaterEqual (2, 1) && CheckExtension ("GL_EXT_gpu_shader4"))
1777         #endif
1778              );
1779
1780   myDepthPeelingDepthTexUnit      = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_DepthPeelingDepth);      // -6
1781   myDepthPeelingFrontColorTexUnit = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_DepthPeelingFrontColor); // -5
1782   myShadowMapTexUnit              = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_ShadowMap);              // -4
1783   myPBREnvLUTTexUnit              = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_PbrEnvironmentLUT);      // -3
1784   myPBRDiffIBLMapSHTexUnit        = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_PbrIblDiffuseSH);        // -2
1785   myPBRSpecIBLMapTexUnit          = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_PbrIblSpecular);         // -1
1786   if (!myHasPBR)
1787   {
1788     myDepthPeelingDepthTexUnit      = static_cast<Graphic3d_TextureUnit>(myDepthPeelingDepthTexUnit + 3);
1789     myDepthPeelingFrontColorTexUnit = static_cast<Graphic3d_TextureUnit>(myDepthPeelingFrontColorTexUnit + 3);
1790     myShadowMapTexUnit              = static_cast<Graphic3d_TextureUnit>(myShadowMapTexUnit + 3);
1791   }
1792 }
1793
1794 // =======================================================================
1795 // function : MemoryInfo
1796 // purpose  :
1797 // =======================================================================
1798 Standard_Size OpenGl_Context::AvailableMemory() const
1799 {
1800 #if !defined(GL_ES_VERSION_2_0)
1801   if (atiMem)
1802   {
1803     // this is actually information for VBO pool
1804     // however because pools are mostly shared
1805     // it can be used for total GPU memory estimations
1806     GLint aMemInfo[4];
1807     aMemInfo[0] = 0;
1808     glGetIntegerv (GL_VBO_FREE_MEMORY_ATI, aMemInfo);
1809     // returned value is in KiB, however this maybe changed in future
1810     return Standard_Size(aMemInfo[0]) * 1024;
1811   }
1812   else if (nvxMem)
1813   {
1814     // current available dedicated video memory (in KiB), currently unused GPU memory
1815     GLint aMemInfo = 0;
1816     glGetIntegerv (GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &aMemInfo);
1817     return Standard_Size(aMemInfo) * 1024;
1818   }
1819 #endif
1820   return 0;
1821 }
1822
1823 // =======================================================================
1824 // function : MemoryInfo
1825 // purpose  :
1826 // =======================================================================
1827 TCollection_AsciiString OpenGl_Context::MemoryInfo() const
1828 {
1829   TColStd_IndexedDataMapOfStringString aDict;
1830   MemoryInfo (aDict);
1831
1832   TCollection_AsciiString aText;
1833   for (TColStd_IndexedDataMapOfStringString::Iterator anIter (aDict); anIter.More(); anIter.Next())
1834   {
1835     if (!aText.IsEmpty())
1836     {
1837       aText += "\n";
1838     }
1839     aText += TCollection_AsciiString("  ") + anIter.Key() + ": " + anIter.Value();
1840   }
1841   return aText;
1842 }
1843
1844 // =======================================================================
1845 // function : MemoryInfo
1846 // purpose  :
1847 // =======================================================================
1848 void OpenGl_Context::MemoryInfo (TColStd_IndexedDataMapOfStringString& theDict) const
1849 {
1850 #if defined(GL_ES_VERSION_2_0)
1851   (void )theDict;
1852 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1853   GLint aGlRendId = 0;
1854   CGLGetParameter (CGLGetCurrentContext(), kCGLCPCurrentRendererID, &aGlRendId);
1855
1856   CGLRendererInfoObj  aRendObj = NULL;
1857   CGOpenGLDisplayMask aDispMask = CGDisplayIDToOpenGLDisplayMask (kCGDirectMainDisplay);
1858   GLint aRendNb = 0;
1859   CGLQueryRendererInfo (aDispMask, &aRendObj, &aRendNb);
1860   for (GLint aRendIter = 0; aRendIter < aRendNb; ++aRendIter)
1861   {
1862     GLint aRendId = 0;
1863     if (CGLDescribeRenderer (aRendObj, aRendIter, kCGLRPRendererID, &aRendId) != kCGLNoError
1864      || aRendId != aGlRendId)
1865     {
1866       continue;
1867     }
1868
1869     //kCGLRPVideoMemoryMegabytes   = 131;
1870     //kCGLRPTextureMemoryMegabytes = 132;
1871     GLint aVMem = 0;
1872   #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
1873     if (CGLDescribeRenderer(aRendObj, aRendIter, kCGLRPVideoMemoryMegabytes, &aVMem) == kCGLNoError)
1874     {
1875       addInfo (theDict, "GPU memory",         TCollection_AsciiString() + aVMem + " MiB");
1876     }
1877     if (CGLDescribeRenderer(aRendObj, aRendIter, kCGLRPTextureMemoryMegabytes, &aVMem) == kCGLNoError)
1878     {
1879       addInfo (theDict, "GPU Texture memory", TCollection_AsciiString() + aVMem + " MiB");
1880     }
1881   #else
1882     if (CGLDescribeRenderer(aRendObj, aRendIter, kCGLRPVideoMemory, &aVMem) == kCGLNoError)
1883     {
1884       addInfo (theDict, "GPU memory",         TCollection_AsciiString() + (aVMem / (1024 * 1024)) + " MiB");
1885     }
1886     if (CGLDescribeRenderer(aRendObj, aRendIter, kCGLRPTextureMemory, &aVMem) == kCGLNoError)
1887     {
1888       addInfo (theDict, "GPU Texture memory", TCollection_AsciiString() + (aVMem / (1024 * 1024)) + " MiB");
1889     }
1890   #endif
1891   }
1892 #endif
1893
1894 #if !defined(GL_ES_VERSION_2_0)
1895   if (atiMem)
1896   {
1897     GLint aValues[4];
1898     memset (aValues, 0, sizeof(aValues));
1899     glGetIntegerv (GL_VBO_FREE_MEMORY_ATI, aValues);
1900
1901     // total memory free in the pool
1902     addInfo (theDict, "GPU free memory",    TCollection_AsciiString() + (aValues[0] / 1024) + " MiB");
1903
1904     if (aValues[1] != aValues[0])
1905     {
1906       // largest available free block in the pool
1907       addInfo (theDict, "Largest free block", TCollection_AsciiString() + (aValues[1] / 1024) + " MiB");
1908     }
1909     if (aValues[2] != aValues[0])
1910     {
1911       // total auxiliary memory free
1912       addInfo (theDict, "Free auxiliary memory", TCollection_AsciiString() + (aValues[2] / 1024) + " MiB");
1913     }
1914   }
1915   else if (nvxMem)
1916   {
1917     //current available dedicated video memory (in KiB), currently unused GPU memory
1918     GLint aValue = 0;
1919     glGetIntegerv (GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &aValue);
1920     addInfo (theDict, "GPU free memory", TCollection_AsciiString() + (aValue / 1024) + " MiB");
1921
1922     // dedicated video memory, total size (in KiB) of the GPU memory
1923     GLint aDedicated = 0;
1924     glGetIntegerv (GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, &aDedicated);
1925     addInfo (theDict, "GPU memory", TCollection_AsciiString() + (aDedicated / 1024) + " MiB");
1926
1927     // total available memory, total size (in KiB) of the memory available for allocations
1928     glGetIntegerv (GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, &aValue);
1929     if (aValue != aDedicated)
1930     {
1931       // different only for special configurations
1932       addInfo (theDict, "Total memory", TCollection_AsciiString() + (aValue / 1024) + " MiB");
1933     }
1934   }
1935 #if defined(_WIN32)
1936   else if (myFuncs->wglGetGPUInfoAMD != NULL
1937         && myFuncs->wglGetContextGPUIDAMD != NULL)
1938   {
1939     GLuint aTotalMemMiB = 0;
1940     UINT anAmdId = myFuncs->wglGetContextGPUIDAMD ((HGLRC )myGContext);
1941     if (anAmdId != 0)
1942     {
1943       if (myFuncs->wglGetGPUInfoAMD (anAmdId, WGL_GPU_RAM_AMD, GL_UNSIGNED_INT, sizeof(aTotalMemMiB), &aTotalMemMiB) > 0)
1944       {
1945         addInfo (theDict, "GPU memory", TCollection_AsciiString() + (int )aTotalMemMiB + " MiB");
1946       }
1947     }
1948   }
1949 #endif
1950 #endif
1951
1952 #if !defined(GL_ES_VERSION_2_0) && !defined(__APPLE__) && !defined(_WIN32)
1953   // GLX_RENDERER_VENDOR_ID_MESA
1954   if (myFuncs->glXQueryCurrentRendererIntegerMESA != NULL)
1955   {
1956     unsigned int aVMemMiB = 0;
1957     if (myFuncs->glXQueryCurrentRendererIntegerMESA (GLX_RENDERER_VIDEO_MEMORY_MESA, &aVMemMiB) != False)
1958     {
1959       addInfo (theDict, "GPU memory", TCollection_AsciiString() + int(aVMemMiB) + " MiB");
1960     }
1961   }
1962 #endif
1963 }
1964
1965 // =======================================================================
1966 // function : DiagnosticInfo
1967 // purpose  :
1968 // =======================================================================
1969 void OpenGl_Context::DiagnosticInformation (TColStd_IndexedDataMapOfStringString& theDict,
1970                                             Graphic3d_DiagnosticInfo theFlags) const
1971 {
1972   if ((theFlags & Graphic3d_DiagnosticInfo_NativePlatform) != 0)
1973   {
1974   #if defined(HAVE_EGL)
1975     addInfo (theDict, "EGLVersion",    ::eglQueryString ((EGLDisplay )myDisplay, EGL_VERSION));
1976     addInfo (theDict, "EGLVendor",     ::eglQueryString ((EGLDisplay )myDisplay, EGL_VENDOR));
1977     addInfo (theDict, "EGLClientAPIs", ::eglQueryString ((EGLDisplay )myDisplay, EGL_CLIENT_APIS));
1978     if ((theFlags & Graphic3d_DiagnosticInfo_Extensions) != 0)
1979     {
1980       addInfo (theDict, "EGLExtensions", ::eglQueryString ((EGLDisplay )myDisplay, EGL_EXTENSIONS));
1981     }
1982   #elif defined(_WIN32)
1983     if ((theFlags & Graphic3d_DiagnosticInfo_Extensions) != 0
1984      && myFuncs->wglGetExtensionsStringARB != NULL)
1985     {
1986       const char* aWglExts = myFuncs->wglGetExtensionsStringARB ((HDC )myWindowDC);
1987       addInfo (theDict, "WGLExtensions", aWglExts);
1988     }
1989   #elif defined(__APPLE__)
1990     //
1991   #else
1992     Display* aDisplay = (Display*)myDisplay;
1993     const int aScreen = DefaultScreen(aDisplay);
1994     addInfo (theDict, "GLXDirectRendering", ::glXIsDirect (aDisplay, (GLXContext )myGContext) ? "Yes" : "No");
1995     addInfo (theDict, "GLXVendor",  ::glXQueryServerString (aDisplay, aScreen, GLX_VENDOR));
1996     addInfo (theDict, "GLXVersion", ::glXQueryServerString (aDisplay, aScreen, GLX_VERSION));
1997     if ((theFlags & Graphic3d_DiagnosticInfo_Extensions) != 0)
1998     {
1999       const char* aGlxExts = ::glXQueryExtensionsString (aDisplay, aScreen);
2000       addInfo(theDict, "GLXExtensions", aGlxExts);
2001     }
2002
2003     addInfo (theDict, "GLXClientVendor",  ::glXGetClientString (aDisplay, GLX_VENDOR));
2004     addInfo (theDict, "GLXClientVersion", ::glXGetClientString (aDisplay, GLX_VERSION));
2005     if ((theFlags & Graphic3d_DiagnosticInfo_Extensions) != 0)
2006     {
2007       addInfo (theDict, "GLXClientExtensions", ::glXGetClientString (aDisplay, GLX_EXTENSIONS));
2008     }
2009   #endif
2010   }
2011
2012   if ((theFlags & Graphic3d_DiagnosticInfo_Device) != 0)
2013   {
2014     Standard_Integer aDriverVer[2] = {};
2015     ReadGlVersion (aDriverVer[0], aDriverVer[1]);
2016     addInfo (theDict, "GLvendor",    (const char*)::glGetString (GL_VENDOR));
2017     addInfo (theDict, "GLdevice",    (const char*)::glGetString (GL_RENDERER));
2018   #ifdef __EMSCRIPTEN__
2019     if (checkEnableWebGlExtension (*this, "GL_WEBGL_debug_renderer_info"))
2020     {
2021       if (const char* aVendor = (const char*)::glGetString (0x9245))
2022       {
2023         addInfo (theDict, "GLunmaskedVendor", aVendor);
2024       }
2025       if (const char* aDevice = (const char*)::glGetString (0x9246))
2026       {
2027         addInfo (theDict, "GLunmaskedDevice", aDevice);
2028       }
2029     }
2030   #endif
2031
2032     addInfo (theDict, "GLversion",   (const char*)::glGetString (GL_VERSION));
2033     if (myGlVerMajor != aDriverVer[0]
2034      || myGlVerMinor != aDriverVer[1])
2035     {
2036       addInfo (theDict, "GLversionOcct", TCollection_AsciiString (myGlVerMajor) + "." + TCollection_AsciiString (myGlVerMinor));
2037     }
2038     if (IsGlGreaterEqual (2, 0))
2039     {
2040       addInfo (theDict, "GLSLversion", (const char*)::glGetString (GL_SHADING_LANGUAGE_VERSION));
2041     }
2042     if (myIsGlDebugCtx)
2043     {
2044       addInfo (theDict, "GLdebug", "ON");
2045     }
2046   }
2047
2048   if ((theFlags & Graphic3d_DiagnosticInfo_Limits) != 0)
2049   {
2050     addInfo (theDict, "Max texture size", TCollection_AsciiString(myMaxTexDim));
2051     addInfo (theDict, "Max FBO dump size", TCollection_AsciiString() + myMaxDumpSizeX + "x" + myMaxDumpSizeY);
2052     addInfo (theDict, "Max combined texture units", TCollection_AsciiString(myMaxTexCombined));
2053     addInfo (theDict, "Max MSAA samples", TCollection_AsciiString(myMaxMsaaSamples));
2054   }
2055
2056   if ((theFlags & Graphic3d_DiagnosticInfo_FrameBuffer) != 0)
2057   {
2058     GLint aViewport[4] = {};
2059     ::glGetIntegerv (GL_VIEWPORT, aViewport);
2060     addInfo (theDict, "Viewport", TCollection_AsciiString() + aViewport[2] + "x" + aViewport[3]);
2061   }
2062
2063   if ((theFlags & Graphic3d_DiagnosticInfo_Memory) != 0)
2064   {
2065     MemoryInfo (theDict);
2066   }
2067
2068   if ((theFlags & Graphic3d_DiagnosticInfo_Extensions) != 0)
2069   {
2070   #if !defined(GL_ES_VERSION_2_0)
2071     if (IsGlGreaterEqual (3, 0)
2072      && myFuncs->glGetStringi != NULL)
2073     {
2074       TCollection_AsciiString anExtList;
2075       GLint anExtNb = 0;
2076       ::glGetIntegerv (GL_NUM_EXTENSIONS, &anExtNb);
2077       for (GLint anIter = 0; anIter < anExtNb; ++anIter)
2078       {
2079         const char* anExtension = (const char*)myFuncs->glGetStringi (GL_EXTENSIONS, (GLuint)anIter);
2080         if (!anExtList.IsEmpty())
2081         {
2082           anExtList += " ";
2083         }
2084         anExtList += anExtension;
2085       }
2086       addInfo(theDict, "GLextensions", anExtList);
2087     }
2088     else
2089   #endif
2090     {
2091       addInfo (theDict, "GLextensions", (const char*)::glGetString (GL_EXTENSIONS));
2092     }
2093   }
2094 }
2095
2096 // =======================================================================
2097 // function : GetResource
2098 // purpose  :
2099 // =======================================================================
2100 const Handle(OpenGl_Resource)& OpenGl_Context::GetResource (const TCollection_AsciiString& theKey) const
2101 {
2102   return mySharedResources->IsBound (theKey) ? mySharedResources->Find (theKey) : NULL_GL_RESOURCE;
2103 }
2104
2105 // =======================================================================
2106 // function : ShareResource
2107 // purpose  :
2108 // =======================================================================
2109 Standard_Boolean OpenGl_Context::ShareResource (const TCollection_AsciiString& theKey,
2110                                                 const Handle(OpenGl_Resource)& theResource)
2111 {
2112   if (theKey.IsEmpty() || theResource.IsNull())
2113   {
2114     return Standard_False;
2115   }
2116   return mySharedResources->Bind (theKey, theResource);
2117 }
2118
2119 // =======================================================================
2120 // function : ReleaseResource
2121 // purpose  :
2122 // =======================================================================
2123 void OpenGl_Context::ReleaseResource (const TCollection_AsciiString& theKey,
2124                                       const Standard_Boolean         theToDelay)
2125 {
2126   if (!mySharedResources->IsBound (theKey))
2127   {
2128     return;
2129   }
2130   const Handle(OpenGl_Resource)& aRes = mySharedResources->Find (theKey);
2131   if (aRes->GetRefCount() > 1)
2132   {
2133     return;
2134   }
2135
2136   if (theToDelay)
2137   {
2138     myDelayed->Bind (theKey, 1);
2139   }
2140   else
2141   {
2142     aRes->Release (this);
2143     mySharedResources->UnBind (theKey);
2144   }
2145 }
2146
2147 // =======================================================================
2148 // function : ReleaseDelayed
2149 // purpose  :
2150 // =======================================================================
2151 void OpenGl_Context::ReleaseDelayed()
2152 {
2153   // release queued elements
2154   while (!myUnusedResources->IsEmpty())
2155   {
2156     myUnusedResources->First()->Release (this);
2157     myUnusedResources->RemoveFirst();
2158   }
2159
2160   // release delayed shared resources
2161   NCollection_Vector<TCollection_AsciiString> aDeadList;
2162   for (NCollection_DataMap<TCollection_AsciiString, Standard_Integer>::Iterator anIter (*myDelayed);
2163        anIter.More(); anIter.Next())
2164   {
2165     if (++anIter.ChangeValue() <= 2)
2166     {
2167       continue; // postpone release one more frame to ensure noone use it periodically
2168     }
2169
2170     const TCollection_AsciiString& aKey = anIter.Key();
2171     if (!mySharedResources->IsBound (aKey))
2172     {
2173       // mixed unshared strategy delayed/undelayed was used!
2174       aDeadList.Append (aKey);
2175       continue;
2176     }
2177
2178     const Handle(OpenGl_Resource)& aRes = mySharedResources->ChangeFind (aKey);
2179     if (aRes->GetRefCount() > 1)
2180     {
2181       // should be only 1 instance in mySharedResources
2182       // if not - resource was reused again
2183       aDeadList.Append (aKey);
2184       continue;
2185     }
2186
2187     // release resource if no one requiested it more than 2 redraw calls
2188     aRes->Release (this);
2189     mySharedResources->UnBind (aKey);
2190     aDeadList.Append (aKey);
2191   }
2192
2193   for (Standard_Integer anIter = 0; anIter < aDeadList.Length(); ++anIter)
2194   {
2195     myDelayed->UnBind (aDeadList.Value (anIter));
2196   }
2197 }
2198
2199 // =======================================================================
2200 // function : BindTextures
2201 // purpose  :
2202 // =======================================================================
2203 Handle(OpenGl_TextureSet) OpenGl_Context::BindTextures (const Handle(OpenGl_TextureSet)& theTextures,
2204                                                         const Handle(OpenGl_ShaderProgram)& theProgram)
2205 {
2206   const Standard_Integer aTextureSetBits = !theTextures.IsNull() ? theTextures->TextureSetBits() : 0;
2207   const Standard_Integer aProgramBits    = !theProgram.IsNull() ? theProgram->TextureSetBits() : 0;
2208   Standard_Integer aMissingBits = aProgramBits & ~aTextureSetBits;
2209   if (aMissingBits != 0
2210    && myTextureRgbaBlack.IsNull())
2211   {
2212     // allocate mock textures
2213     myTextureRgbaBlack = new OpenGl_Texture();
2214     myTextureRgbaWhite = new OpenGl_Texture();
2215     Image_PixMap anImage;
2216     anImage.InitZero (Image_Format_RGBA, 2, 2, 0, (Standard_Byte )0);
2217     if (!myTextureRgbaBlack->Init (this, OpenGl_TextureFormat::Create<GLubyte, 4>(), Graphic3d_Vec2i (2, 2), Graphic3d_TOT_2D, &anImage))
2218     {
2219       PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH,
2220                     "Error: unable to create unit mock PBR texture map.");
2221     }
2222     anImage.InitZero (Image_Format_RGBA, 2, 2, 0, (Standard_Byte )255);
2223     if (!myTextureRgbaWhite->Init (this, OpenGl_TextureFormat::Create<GLubyte, 4>(), Graphic3d_Vec2i (2, 2), Graphic3d_TOT_2D, &anImage))
2224     {
2225       PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH,
2226                     "Error: unable to create normal mock PBR texture map.");
2227     }
2228   }
2229
2230   Handle(OpenGl_TextureSet) anOldTextures = myActiveTextures;
2231   if (myActiveTextures != theTextures)
2232   {
2233     Handle(OpenGl_Context) aThisCtx (this);
2234     for (OpenGl_TextureSetPairIterator aSlotIter (myActiveTextures, theTextures); aSlotIter.More(); aSlotIter.Next())
2235     {
2236       const Graphic3d_TextureUnit aTexUnit = aSlotIter.Unit();
2237       const OpenGl_Texture* aTextureOld = aSlotIter.Texture1();
2238       const OpenGl_Texture* aTextureNew = aSlotIter.Texture2();
2239       if (aTextureNew == aTextureOld)
2240       {
2241         continue;
2242       }
2243
2244       if (aTextureNew != NULL
2245        && aTextureNew->IsValid())
2246       {
2247         if (aTexUnit >= myMaxTexCombined)
2248         {
2249           PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
2250                        TCollection_AsciiString("Texture unit ") + aTexUnit + " for " + aTextureNew->ResourceId() + " exceeds hardware limit " + myMaxTexCombined);
2251           continue;
2252         }
2253
2254         aTextureNew->Bind (aThisCtx, aTexUnit);
2255         if (aTextureNew->Sampler()->ToUpdateParameters())
2256         {
2257           if (aTextureNew->Sampler()->IsImmutable())
2258           {
2259             aTextureNew->Sampler()->Init (aThisCtx, *aTextureNew);
2260           }
2261           else
2262           {
2263             OpenGl_Sampler::applySamplerParams (aThisCtx, aTextureNew->Sampler()->Parameters(), aTextureNew->Sampler().get(), aTextureNew->GetTarget(), aTextureNew->MaxMipmapLevel());
2264           }
2265         }
2266       #if !defined(GL_ES_VERSION_2_0)
2267         if (core11 != NULL)
2268         {
2269           OpenGl_Sampler::applyGlobalTextureParams (aThisCtx, *aTextureNew, aTextureNew->Sampler()->Parameters());
2270         }
2271       #endif
2272       }
2273       else if (aTextureOld != NULL
2274             && aTextureOld->IsValid())
2275       {
2276         aTextureOld->Unbind (aThisCtx, aTexUnit);
2277       #if !defined(GL_ES_VERSION_2_0)
2278         if (core11 != NULL)
2279         {
2280           OpenGl_Sampler::resetGlobalTextureParams (aThisCtx, *aTextureOld, aTextureOld->Sampler()->Parameters());
2281         }
2282       #endif
2283       }
2284     }
2285     myActiveTextures = theTextures;
2286   }
2287
2288   if (myActiveMockTextures != aMissingBits)
2289   {
2290     myActiveMockTextures = aMissingBits;
2291     for (Standard_Integer aBitIter = 0; aMissingBits != 0; ++aBitIter)
2292     {
2293       Standard_Integer aUnitMask = 1 << aBitIter;
2294       if ((aUnitMask & aMissingBits) != 0)
2295       {
2296         aMissingBits = aMissingBits & ~aUnitMask;
2297         if (aBitIter == Graphic3d_TextureUnit_Normal)
2298         {
2299           myTextureRgbaBlack->Bind (this, static_cast<Graphic3d_TextureUnit>(aBitIter));
2300         }
2301         else
2302         {
2303           myTextureRgbaWhite->Bind (this, static_cast<Graphic3d_TextureUnit>(aBitIter));
2304         }
2305       }
2306     }
2307   }
2308
2309   return anOldTextures;
2310 }
2311
2312 // =======================================================================
2313 // function : BindProgram
2314 // purpose  :
2315 // =======================================================================
2316 Standard_Boolean OpenGl_Context::BindProgram (const Handle(OpenGl_ShaderProgram)& theProgram)
2317 {
2318   if (core20fwd == NULL)
2319   {
2320     return Standard_False;
2321   }
2322   else if (myActiveProgram == theProgram)
2323   {
2324     return Standard_True;
2325   }
2326
2327   if (theProgram.IsNull()
2328   || !theProgram->IsValid())
2329   {
2330     if (!myActiveProgram.IsNull())
2331     {
2332       core20fwd->glUseProgram (OpenGl_ShaderProgram::NO_PROGRAM);
2333       myActiveProgram.Nullify();
2334     }
2335     return Standard_False;
2336   }
2337
2338   myActiveProgram = theProgram;
2339   core20fwd->glUseProgram (theProgram->ProgramId());
2340   return Standard_True;
2341 }
2342
2343 // =======================================================================
2344 // function : BindDefaultVao
2345 // purpose  :
2346 // =======================================================================
2347 void OpenGl_Context::BindDefaultVao()
2348 {
2349 #if !defined(GL_ES_VERSION_2_0)
2350   if (myDefaultVao == 0
2351    || core32 == NULL)
2352   {
2353     return;
2354   }
2355
2356   core32->glBindVertexArray (myDefaultVao);
2357 #endif
2358 }
2359
2360 // =======================================================================
2361 // function : SetDefaultFrameBuffer
2362 // purpose  :
2363 // =======================================================================
2364 Handle(OpenGl_FrameBuffer) OpenGl_Context::SetDefaultFrameBuffer (const Handle(OpenGl_FrameBuffer)& theFbo)
2365 {
2366   Handle(OpenGl_FrameBuffer) aFbo = myDefaultFbo;
2367   myDefaultFbo = theFbo;
2368   return aFbo;
2369 }
2370
2371 // =======================================================================
2372 // function : SetShadingMaterial
2373 // purpose  :
2374 // =======================================================================
2375 void OpenGl_Context::SetShadingMaterial (const OpenGl_Aspects* theAspect,
2376                                          const Handle(Graphic3d_PresentationAttributes)& theHighlight)
2377 {
2378   const Handle(Graphic3d_Aspects)& anAspect = (!theHighlight.IsNull() && !theHighlight->BasicFillAreaAspect().IsNull())
2379                                             ?  (const Handle(Graphic3d_Aspects)& )theHighlight->BasicFillAreaAspect()
2380                                             :  theAspect->Aspect();
2381
2382   const bool toDistinguish = anAspect->Distinguish();
2383   const bool toMapTexture  = anAspect->ToMapTexture();
2384   const Graphic3d_MaterialAspect& aMatFrontSrc = anAspect->FrontMaterial();
2385   const Graphic3d_MaterialAspect& aMatBackSrc  = toDistinguish
2386                                                ? anAspect->BackMaterial()
2387                                                : aMatFrontSrc;
2388   const Quantity_Color& aFrontIntColor = anAspect->InteriorColor();
2389   const Quantity_Color& aBackIntColor  = toDistinguish
2390                                        ? anAspect->BackInteriorColor()
2391                                        : aFrontIntColor;
2392
2393   myMatFront.Init (*this, aMatFrontSrc, aFrontIntColor);
2394   if (toDistinguish)
2395   {
2396     myMatBack.Init (*this, aMatBackSrc, aBackIntColor);
2397   }
2398   else
2399   {
2400     myMatBack = myMatFront;
2401   }
2402
2403   if (!theHighlight.IsNull()
2404     && theHighlight->BasicFillAreaAspect().IsNull())
2405   {
2406     myMatFront.SetColor (theHighlight->ColorRGBA());
2407     myMatBack .SetColor (theHighlight->ColorRGBA());
2408   }
2409
2410   Standard_ShortReal anAlphaFront = 1.0f;
2411   Standard_ShortReal anAlphaBack  = 1.0f;
2412   if (CheckIsTransparent (theAspect, theHighlight, anAlphaFront, anAlphaBack))
2413   {
2414     myMatFront.Common.Diffuse.a() = anAlphaFront;
2415     myMatBack .Common.Diffuse.a() = anAlphaBack;
2416
2417     myMatFront.Pbr.BaseColor.a() = anAlphaFront;
2418     myMatBack .Pbr.BaseColor.a() = anAlphaBack;
2419   }
2420
2421   // do not update material properties in case of zero reflection mode,
2422   // because GL lighting will be disabled by OpenGl_PrimitiveArray::DrawArray() anyway.
2423   const OpenGl_MaterialState& aMatState = myShaderManager->MaterialState();
2424   float anAlphaCutoff = anAspect->AlphaMode() == Graphic3d_AlphaMode_Mask
2425                       ? anAspect->AlphaCutoff()
2426                       : ShortRealLast();
2427   if (anAspect->ToDrawEdges())
2428   {
2429     if (anAspect->InteriorStyle() == Aspect_IS_EMPTY
2430      || (anAspect->InteriorStyle() == Aspect_IS_SOLID
2431       && anAspect->EdgeColorRGBA().Alpha() < 1.0f))
2432     {
2433       anAlphaCutoff = 0.285f;
2434     }
2435   }
2436   if (theAspect->ShadingModel() == Graphic3d_TOSM_UNLIT)
2437   {
2438     if (anAlphaCutoff == aMatState.AlphaCutoff())
2439     {
2440       return;
2441     }
2442   }
2443   else if (myMatFront    == aMatState.FrontMaterial()
2444         && myMatBack     == aMatState.BackMaterial()
2445         && toDistinguish == aMatState.ToDistinguish()
2446         && toMapTexture  == aMatState.ToMapTexture()
2447         && anAlphaCutoff == aMatState.AlphaCutoff())
2448   {
2449     return;
2450   }
2451
2452   myShaderManager->UpdateMaterialStateTo (myMatFront, myMatBack, anAlphaCutoff, toDistinguish, toMapTexture);
2453 }
2454
2455 // =======================================================================
2456 // function : CheckIsTransparent
2457 // purpose  :
2458 // =======================================================================
2459 Standard_Boolean OpenGl_Context::CheckIsTransparent (const OpenGl_Aspects* theAspect,
2460                                                      const Handle(Graphic3d_PresentationAttributes)& theHighlight,
2461                                                      Standard_ShortReal& theAlphaFront,
2462                                                      Standard_ShortReal& theAlphaBack)
2463 {
2464   const Handle(Graphic3d_Aspects)& anAspect = (!theHighlight.IsNull() && !theHighlight->BasicFillAreaAspect().IsNull())
2465                                             ?  (const Handle(Graphic3d_Aspects)& )theHighlight->BasicFillAreaAspect()
2466                                             :  theAspect->Aspect();
2467
2468   const bool toDistinguish = anAspect->Distinguish();
2469   const Graphic3d_MaterialAspect& aMatFrontSrc = anAspect->FrontMaterial();
2470   const Graphic3d_MaterialAspect& aMatBackSrc  = toDistinguish
2471                                                ? anAspect->BackMaterial()
2472                                                : aMatFrontSrc;
2473
2474   // handling transparency
2475   if (!theHighlight.IsNull()
2476     && theHighlight->BasicFillAreaAspect().IsNull())
2477   {
2478     theAlphaFront = theHighlight->ColorRGBA().Alpha();
2479     theAlphaBack  = theHighlight->ColorRGBA().Alpha();
2480   }
2481   else
2482   {
2483     theAlphaFront = aMatFrontSrc.Alpha();
2484     theAlphaBack  = aMatBackSrc .Alpha();
2485   }
2486
2487   if (anAspect->AlphaMode() == Graphic3d_AlphaMode_BlendAuto)
2488   {
2489     return theAlphaFront < 1.0f
2490         || theAlphaBack  < 1.0f;
2491   }
2492   return anAspect->AlphaMode() == Graphic3d_AlphaMode_Blend;
2493 }
2494
2495 // =======================================================================
2496 // function : SetColor4fv
2497 // purpose  :
2498 // =======================================================================
2499 void OpenGl_Context::SetColor4fv (const OpenGl_Vec4& theColor)
2500 {
2501   if (!myActiveProgram.IsNull())
2502   {
2503     if (const OpenGl_ShaderUniformLocation& aLoc = myActiveProgram->GetStateLocation (OpenGl_OCCT_COLOR))
2504     {
2505       myActiveProgram->SetUniform (this, aLoc, Vec4FromQuantityColor (theColor));
2506     }
2507   }
2508 #if !defined(GL_ES_VERSION_2_0)
2509   else if (core11 != NULL)
2510   {
2511     core11->glColor4fv (theColor.GetData());
2512   }
2513 #endif
2514 }
2515
2516 // =======================================================================
2517 // function : SetTypeOfLine
2518 // purpose  :
2519 // =======================================================================
2520 void OpenGl_Context::SetTypeOfLine (const Aspect_TypeOfLine  theType,
2521                                     const Standard_ShortReal theFactor)
2522 {
2523   SetLineStipple (theFactor, Graphic3d_Aspects::DefaultLinePatternForType (theType));
2524 }
2525
2526 // =======================================================================
2527 // function : SetLineStipple
2528 // purpose  :
2529 // =======================================================================
2530 void OpenGl_Context::SetLineStipple (const Standard_ShortReal theFactor,
2531                                      const uint16_t thePattern)
2532 {
2533   if (!myActiveProgram.IsNull())
2534   {
2535     if (const OpenGl_ShaderUniformLocation aPatternLoc = myActiveProgram->GetStateLocation (OpenGl_OCCT_LINE_STIPPLE_PATTERN))
2536     {
2537       if (hasGlslBitwiseOps != OpenGl_FeatureNotAvailable)
2538       {
2539         myActiveProgram->SetUniform (this, aPatternLoc, (Standard_Integer )thePattern);
2540       }
2541       else
2542       {
2543         Standard_Integer aPatArr[16] = {};
2544         for (unsigned int aBit = 0; aBit < 16; ++aBit)
2545         {
2546           aPatArr[aBit] = ((unsigned int)(thePattern) & (1U << aBit)) != 0 ? 1 : 0;
2547         }
2548         myActiveProgram->SetUniform (this, aPatternLoc, 16, aPatArr);
2549       }
2550       myActiveProgram->SetUniform (this, myActiveProgram->GetStateLocation (OpenGl_OCCT_LINE_STIPPLE_FACTOR), theFactor);
2551     }
2552     return;
2553   }
2554
2555 #if !defined(GL_ES_VERSION_2_0)
2556   if (thePattern != 0xFFFF)
2557   {
2558     if (core11 != NULL)
2559     {
2560       core11fwd->glEnable (GL_LINE_STIPPLE);
2561
2562       core11->glLineStipple (static_cast<GLint>    (theFactor),
2563                              static_cast<GLushort> (thePattern));
2564     }
2565   }
2566   else
2567   {
2568     if (core11 != NULL)
2569     {
2570       core11fwd->glDisable (GL_LINE_STIPPLE);
2571     }
2572   }
2573 #endif
2574 }
2575
2576 // =======================================================================
2577 // function : SetLineWidth
2578 // purpose  :
2579 // =======================================================================
2580 void OpenGl_Context::SetLineWidth (const Standard_ShortReal theWidth)
2581 {
2582   if (core11 != NULL)
2583   {
2584     // glLineWidth() is still defined within Core Profile, but has no effect with values != 1.0f
2585     core11fwd->glLineWidth (theWidth * myLineWidthScale);
2586   }
2587 }
2588
2589 // =======================================================================
2590 // function : SetTextureMatrix
2591 // purpose  :
2592 // =======================================================================
2593 void OpenGl_Context::SetTextureMatrix (const Handle(Graphic3d_TextureParams)& theParams,
2594                                        const Standard_Boolean theIsTopDown)
2595 {
2596   if (theParams.IsNull())
2597   {
2598     return;
2599   }
2600
2601   const Graphic3d_Vec2& aScale = theParams->Scale();
2602   const Graphic3d_Vec2& aTrans = theParams->Translation();
2603   if (!myActiveProgram.IsNull())
2604   {
2605     const GLint aUniLoc = myActiveProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_TRSF2D);
2606     if (aUniLoc == OpenGl_ShaderProgram::INVALID_LOCATION)
2607     {
2608       return;
2609     }
2610
2611     // pack transformation parameters
2612     OpenGl_Vec4 aTrsf[2] =
2613     {
2614       OpenGl_Vec4 (-aTrans.x(), -aTrans.y(), aScale.x(), aScale.y()),
2615       OpenGl_Vec4 (static_cast<float> (std::sin (-theParams->Rotation() * M_PI / 180.0)),
2616                    static_cast<float> (std::cos (-theParams->Rotation() * M_PI / 180.0)),
2617                    0.0f, 0.0f)
2618     };
2619     if (caps->isTopDownTextureUV != theIsTopDown)
2620     {
2621       // flip V
2622       aTrsf[0].y() = -aTrans.y() + 1.0f / aScale.y();
2623       aTrsf[0].w() = -aScale.y();
2624     }
2625     myActiveProgram->SetUniform (this, aUniLoc, 2, aTrsf);
2626     return;
2627   }
2628
2629 #if !defined(GL_ES_VERSION_2_0)
2630   if (core11 != NULL)
2631   {
2632     GLint aMatrixMode = GL_TEXTURE;
2633     ::glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode);
2634
2635     core11->glMatrixMode (GL_TEXTURE);
2636     OpenGl_Mat4 aTextureMat;
2637     if (caps->isTopDownTextureUV != theIsTopDown)
2638     {
2639       // flip V
2640       Graphic3d_TransformUtils::Scale     (aTextureMat,  aScale.x(), -aScale.y(), 1.0f);
2641       Graphic3d_TransformUtils::Translate (aTextureMat, -aTrans.x(), -aTrans.y() + 1.0f / aScale.y(), 0.0f);
2642     }
2643     else
2644     {
2645       Graphic3d_TransformUtils::Scale     (aTextureMat,  aScale.x(),  aScale.y(), 1.0f);
2646       Graphic3d_TransformUtils::Translate (aTextureMat, -aTrans.x(), -aTrans.y(), 0.0f);
2647     }
2648     Graphic3d_TransformUtils::Rotate (aTextureMat, -theParams->Rotation(), 0.0f, 0.0f, 1.0f);
2649     core11->glLoadMatrixf (aTextureMat);
2650     core11->glMatrixMode (aMatrixMode);
2651   }
2652 #endif
2653 }
2654
2655 // =======================================================================
2656 // function : SetPointSize
2657 // purpose  :
2658 // =======================================================================
2659 void OpenGl_Context::SetPointSize (const Standard_ShortReal theSize)
2660 {
2661   if (!myActiveProgram.IsNull())
2662   {
2663     myActiveProgram->SetUniform (this, myActiveProgram->GetStateLocation (OpenGl_OCCT_POINT_SIZE), theSize);
2664   #if !defined(GL_ES_VERSION_2_0)
2665     //myContext->core11fwd->glEnable (GL_VERTEX_PROGRAM_POINT_SIZE);
2666   #endif
2667   }
2668 #if !defined(GL_ES_VERSION_2_0)
2669   //else
2670   {
2671     core11fwd->glPointSize (theSize);
2672     if (core20fwd != NULL)
2673     {
2674       //myContext->core11fwd->glDisable (GL_VERTEX_PROGRAM_POINT_SIZE);
2675     }
2676   }
2677 #endif
2678 }
2679
2680 // =======================================================================
2681 // function : SetPointSpriteOrigin
2682 // purpose  :
2683 // =======================================================================
2684 void OpenGl_Context::SetPointSpriteOrigin()
2685 {
2686 #if !defined(GL_ES_VERSION_2_0)
2687   if (core15fwd == NULL)
2688   {
2689     return;
2690   }
2691
2692   const int aNewState = !myActiveProgram.IsNull() ? GL_UPPER_LEFT : GL_LOWER_LEFT;
2693   if (myPointSpriteOrig != aNewState)
2694   {
2695     myPointSpriteOrig = aNewState;
2696     core15fwd->glPointParameteri (GL_POINT_SPRITE_COORD_ORIGIN, aNewState);
2697   }
2698 #endif
2699 }
2700
2701 // =======================================================================
2702 // function : SetGlNormalizeEnabled
2703 // purpose  :
2704 // =======================================================================
2705 Standard_Boolean OpenGl_Context::SetGlNormalizeEnabled (Standard_Boolean isEnabled)
2706 {
2707   if (isEnabled == myIsGlNormalizeEnabled)
2708   {
2709     return myIsGlNormalizeEnabled;
2710   }
2711
2712   Standard_Boolean anOldGlNormalize = myIsGlNormalizeEnabled;
2713
2714   myIsGlNormalizeEnabled = isEnabled;
2715
2716 #if !defined(GL_ES_VERSION_2_0)
2717   if (core11 != NULL)
2718   {
2719     if (isEnabled)
2720     {
2721       ::glEnable  (GL_NORMALIZE);
2722     }
2723     else
2724     {
2725       ::glDisable (GL_NORMALIZE);
2726     }
2727   }
2728 #endif
2729
2730   return anOldGlNormalize;
2731 }
2732
2733 // =======================================================================
2734 // function : SetShadeModel
2735 // purpose  :
2736 // =======================================================================
2737 void OpenGl_Context::SetShadeModel (Graphic3d_TypeOfShadingModel theModel)
2738 {
2739 #if !defined(GL_ES_VERSION_2_0)
2740   if (core11 != NULL)
2741   {
2742     const Standard_Integer aModel = theModel == Graphic3d_TOSM_FACET
2743                                  || theModel == Graphic3d_TOSM_PBR_FACET ? GL_FLAT : GL_SMOOTH;
2744     if (myShadeModel == aModel)
2745     {
2746       return;
2747     }
2748     myShadeModel = aModel;
2749     core11->glShadeModel (aModel);
2750   }
2751 #else
2752   (void )theModel;
2753 #endif
2754 }
2755
2756 // =======================================================================
2757 // function : SetPolygonMode
2758 // purpose  :
2759 // =======================================================================
2760 Standard_Integer OpenGl_Context::SetPolygonMode (const Standard_Integer theMode)
2761 {
2762   if (myPolygonMode == theMode)
2763   {
2764     return myPolygonMode;
2765   }
2766
2767   const Standard_Integer anOldPolygonMode = myPolygonMode;
2768
2769   myPolygonMode = theMode;
2770
2771 #if !defined(GL_ES_VERSION_2_0)
2772   ::glPolygonMode (GL_FRONT_AND_BACK, (GLenum)theMode);
2773 #endif
2774
2775   return anOldPolygonMode;
2776 }
2777
2778 // =======================================================================
2779 // function : SetPolygonHatchEnabled
2780 // purpose  :
2781 // =======================================================================
2782 bool OpenGl_Context::SetPolygonHatchEnabled (const bool theIsEnabled)
2783 {
2784   if (core11 == NULL)
2785   {
2786     return false;
2787   }
2788   else if (myHatchIsEnabled == theIsEnabled)
2789   {
2790     return theIsEnabled;
2791   }
2792
2793   const bool anOldIsEnabled = myHatchIsEnabled;
2794 #if !defined(GL_ES_VERSION_2_0)
2795   if (theIsEnabled
2796    && myActiveHatchType != Aspect_HS_SOLID)
2797   {
2798     core11fwd->glEnable (GL_POLYGON_STIPPLE);
2799   }
2800   else
2801   {
2802     core11fwd->glDisable (GL_POLYGON_STIPPLE);
2803   }
2804 #endif
2805   myHatchIsEnabled = theIsEnabled;
2806   return anOldIsEnabled;
2807 }
2808
2809 // =======================================================================
2810 // function : SetPolygonHatchStyle
2811 // purpose  :
2812 // =======================================================================
2813 Standard_Integer OpenGl_Context::SetPolygonHatchStyle (const Handle(Graphic3d_HatchStyle)& theStyle)
2814 {
2815   const Standard_Integer aNewStyle = !theStyle.IsNull() ? theStyle->HatchType() : Aspect_HS_SOLID;
2816   if (myActiveHatchType == aNewStyle
2817    || core11 == NULL)
2818   {
2819     return myActiveHatchType;
2820   }
2821
2822 #if !defined(GL_ES_VERSION_2_0)
2823   if (aNewStyle == Aspect_HS_SOLID)
2824   {
2825     if (myHatchIsEnabled)
2826     {
2827       core11fwd->glDisable (GL_POLYGON_STIPPLE);
2828     }
2829     return myActiveHatchType;
2830   }
2831
2832   if (myHatchStyles.IsNull()
2833   && !GetResource ("OpenGl_LineAttributes", myHatchStyles))
2834   {
2835     // share and register for release once the resource is no longer used
2836     myHatchStyles = new OpenGl_LineAttributes();
2837     ShareResource ("OpenGl_LineAttributes", myHatchStyles);
2838   }
2839
2840   const Standard_Integer anOldType = myActiveHatchType;
2841   myActiveHatchType = aNewStyle;
2842   myHatchStyles->SetTypeOfHatch (this, theStyle);
2843   if (myHatchIsEnabled
2844    && anOldType == Aspect_HS_SOLID)
2845   {
2846     core11fwd->glEnable (GL_POLYGON_STIPPLE);
2847   }
2848   return anOldType;
2849 #else
2850   return myActiveHatchType;
2851 #endif
2852 }
2853
2854 // =======================================================================
2855 // function : SetPolygonOffset
2856 // purpose  :
2857 // =======================================================================
2858 void OpenGl_Context::SetPolygonOffset (const Graphic3d_PolygonOffset& theOffset)
2859 {
2860   const bool toFillOld = (myPolygonOffset.Mode & Aspect_POM_Fill) == Aspect_POM_Fill;
2861   const bool toFillNew = (theOffset.Mode       & Aspect_POM_Fill) == Aspect_POM_Fill;
2862   if (toFillNew != toFillOld)
2863   {
2864     if (toFillNew)
2865     {
2866       glEnable (GL_POLYGON_OFFSET_FILL);
2867     }
2868     else
2869     {
2870       glDisable (GL_POLYGON_OFFSET_FILL);
2871     }
2872   }
2873
2874 #if !defined(GL_ES_VERSION_2_0)
2875   const bool toLineOld = (myPolygonOffset.Mode & Aspect_POM_Line) == Aspect_POM_Line;
2876   const bool toLineNew = (theOffset.Mode       & Aspect_POM_Line) == Aspect_POM_Line;
2877   if (toLineNew != toLineOld)
2878   {
2879     if (toLineNew)
2880     {
2881       glEnable (GL_POLYGON_OFFSET_LINE);
2882     }
2883     else
2884     {
2885       glDisable (GL_POLYGON_OFFSET_LINE);
2886     }
2887   }
2888
2889   const bool toPointOld = (myPolygonOffset.Mode & Aspect_POM_Point) == Aspect_POM_Point;
2890   const bool toPointNew = (theOffset.Mode       & Aspect_POM_Point) == Aspect_POM_Point;
2891   if (toPointNew != toPointOld)
2892   {
2893     if (toPointNew)
2894     {
2895       glEnable (GL_POLYGON_OFFSET_POINT);
2896     }
2897     else
2898     {
2899       glDisable (GL_POLYGON_OFFSET_POINT);
2900     }
2901   }
2902 #endif
2903
2904   if (myPolygonOffset.Factor != theOffset.Factor
2905    || myPolygonOffset.Units  != theOffset.Units)
2906   {
2907     glPolygonOffset (theOffset.Factor, theOffset.Units);
2908   }
2909   myPolygonOffset = theOffset;
2910 }
2911
2912 // =======================================================================
2913 // function : SetCamera
2914 // purpose  :
2915 // =======================================================================
2916 void OpenGl_Context::SetCamera (const Handle(Graphic3d_Camera)& theCamera)
2917 {
2918   myCamera = theCamera;
2919   if (!theCamera.IsNull())
2920   {
2921     ProjectionState.SetCurrent (theCamera->ProjectionMatrixF());
2922     WorldViewState .SetCurrent (theCamera->OrientationMatrixF());
2923     ApplyProjectionMatrix();
2924     ApplyWorldViewMatrix();
2925   }
2926 }
2927
2928 // =======================================================================
2929 // function : ApplyModelWorldMatrix
2930 // purpose  :
2931 // =======================================================================
2932 void OpenGl_Context::ApplyModelWorldMatrix()
2933 {
2934   if (myShaderManager->ModelWorldState().ModelWorldMatrix() != ModelWorldState.Current())
2935   {
2936     myShaderManager->UpdateModelWorldStateTo (ModelWorldState.Current());
2937   }
2938 }
2939
2940 // =======================================================================
2941 // function : ApplyWorldViewMatrix
2942 // purpose  :
2943 // =======================================================================
2944 void OpenGl_Context::ApplyWorldViewMatrix()
2945 {
2946   if (myShaderManager->ModelWorldState().ModelWorldMatrix() != THE_IDENTITY_MATRIX)
2947   {
2948     myShaderManager->UpdateModelWorldStateTo (THE_IDENTITY_MATRIX);
2949   }
2950   if (myShaderManager->WorldViewState().WorldViewMatrix() != WorldViewState.Current())
2951   {
2952     myShaderManager->UpdateWorldViewStateTo (WorldViewState.Current());
2953   }
2954 }
2955
2956 // =======================================================================
2957 // function : ApplyModelViewMatrix
2958 // purpose  :
2959 // =======================================================================
2960 void OpenGl_Context::ApplyModelViewMatrix()
2961 {
2962   if (myShaderManager->ModelWorldState().ModelWorldMatrix() != ModelWorldState.Current())
2963   {
2964     myShaderManager->UpdateModelWorldStateTo (ModelWorldState.Current());
2965   }
2966   if (myShaderManager->WorldViewState().WorldViewMatrix() != WorldViewState.Current())
2967   {
2968     myShaderManager->UpdateWorldViewStateTo  (WorldViewState.Current());
2969   }
2970 }
2971
2972 // =======================================================================
2973 // function : ApplyProjectionMatrix
2974 // purpose  :
2975 // =======================================================================
2976 void OpenGl_Context::ApplyProjectionMatrix()
2977 {
2978   if (myShaderManager->ProjectionState().ProjectionMatrix() != ProjectionState.Current())
2979   {
2980     myShaderManager->UpdateProjectionStateTo (ProjectionState.Current());
2981   }
2982 }
2983
2984 // =======================================================================
2985 // function : EnableFeatures
2986 // purpose  :
2987 // =======================================================================
2988 void OpenGl_Context::EnableFeatures() const
2989 {
2990   //
2991 }
2992
2993 // =======================================================================
2994 // function : DisableFeatures
2995 // purpose  :
2996 // =======================================================================
2997 void OpenGl_Context::DisableFeatures() const
2998 {
2999   // Disable stuff that's likely to slow down glDrawPixels.
3000   glDisable(GL_DITHER);
3001   glDisable(GL_BLEND);
3002   glDisable(GL_DEPTH_TEST);
3003   glDisable(GL_STENCIL_TEST);
3004
3005 #if !defined(GL_ES_VERSION_2_0)
3006   if (core11 == NULL)
3007   {
3008     return;
3009   }
3010
3011   glDisable(GL_TEXTURE_1D);
3012   glDisable(GL_TEXTURE_2D);
3013
3014   glDisable(GL_LIGHTING);
3015   glDisable(GL_ALPHA_TEST);
3016   glDisable(GL_FOG);
3017   glDisable(GL_LOGIC_OP);
3018
3019   glPixelTransferi(GL_MAP_COLOR, GL_FALSE);
3020   glPixelTransferi(GL_RED_SCALE, 1);
3021   glPixelTransferi(GL_RED_BIAS, 0);
3022   glPixelTransferi(GL_GREEN_SCALE, 1);
3023   glPixelTransferi(GL_GREEN_BIAS, 0);
3024   glPixelTransferi(GL_BLUE_SCALE, 1);
3025   glPixelTransferi(GL_BLUE_BIAS, 0);
3026   glPixelTransferi(GL_ALPHA_SCALE, 1);
3027   glPixelTransferi(GL_ALPHA_BIAS, 0);
3028
3029   if ((myGlVerMajor >= 1) && (myGlVerMinor >= 2))
3030   {
3031     if (CheckExtension ("GL_CONVOLUTION_1D_EXT"))
3032       glDisable(GL_CONVOLUTION_1D_EXT);
3033
3034     if (CheckExtension ("GL_CONVOLUTION_2D_EXT"))
3035       glDisable(GL_CONVOLUTION_2D_EXT);
3036
3037     if (CheckExtension ("GL_SEPARABLE_2D_EXT"))
3038       glDisable(GL_SEPARABLE_2D_EXT);
3039
3040     if (CheckExtension ("GL_SEPARABLE_2D_EXT"))
3041       glDisable(GL_HISTOGRAM_EXT);
3042
3043     if (CheckExtension ("GL_MINMAX_EXT"))
3044       glDisable(GL_MINMAX_EXT);
3045
3046     if (CheckExtension ("GL_TEXTURE_3D_EXT"))
3047       glDisable(GL_TEXTURE_3D_EXT);
3048   }
3049 #endif
3050 }
3051
3052 // =======================================================================
3053 // function : SetColorMaskRGBA
3054 // purpose  :
3055 // =======================================================================
3056 void OpenGl_Context::SetColorMaskRGBA (const NCollection_Vec4<bool>& theVal)
3057 {
3058   glColorMask (theVal.r() ? GL_TRUE : GL_FALSE,
3059                theVal.g() ? GL_TRUE : GL_FALSE,
3060                theVal.b() ? GL_TRUE : GL_FALSE,
3061                theVal.a() ? GL_TRUE : GL_FALSE);
3062   myColorMask = theVal;
3063 }
3064
3065 // =======================================================================
3066 // function : SetColorMask
3067 // purpose  :
3068 // =======================================================================
3069 bool OpenGl_Context::SetColorMask (bool theToWriteColor)
3070 {
3071   const bool anOldValue = myColorMask.r();
3072   myColorMask.SetValues (theToWriteColor, theToWriteColor, theToWriteColor, caps->buffersOpaqueAlpha ? false : theToWriteColor);
3073   const GLboolean toWrite = theToWriteColor ? GL_TRUE : GL_FALSE;
3074   glColorMask (toWrite, toWrite, toWrite, myColorMask.a() ? GL_TRUE : GL_FALSE);
3075   return anOldValue;
3076 }
3077
3078 // =======================================================================
3079 // function : SetSampleAlphaToCoverage
3080 // purpose  :
3081 // =======================================================================
3082 bool OpenGl_Context::SetSampleAlphaToCoverage (bool theToEnable)
3083 {
3084   bool toEnable = myAllowAlphaToCov && theToEnable;
3085   if (myAlphaToCoverage == toEnable)
3086   {
3087     return myAlphaToCoverage;
3088   }
3089
3090   if (core15fwd != NULL)
3091   {
3092     if (toEnable)
3093     {
3094       //core15fwd->core15fwd->glSampleCoverage (1.0f, GL_FALSE);
3095       core15fwd->glEnable (GL_SAMPLE_ALPHA_TO_COVERAGE);
3096     }
3097     else
3098     {
3099       core15fwd->glDisable (GL_SAMPLE_ALPHA_TO_COVERAGE);
3100     }
3101   }
3102
3103   const bool anOldValue = myAlphaToCoverage;
3104   myAlphaToCoverage = toEnable;
3105   return anOldValue;
3106 }
3107
3108 // =======================================================================
3109 // function : GetBufferSubData
3110 // purpose  :
3111 // =======================================================================
3112 bool OpenGl_Context::GetBufferSubData (GLenum theTarget, GLintptr theOffset, GLsizeiptr theSize, void* theData)
3113 {
3114   if (!hasGetBufferData)
3115   {
3116     return false;
3117   }
3118 #ifdef __EMSCRIPTEN__
3119   EM_ASM_(
3120   {
3121     Module.ctx.getBufferSubData($0, $1, HEAPU8.subarray($2, $2 + $3));
3122   }, theTarget, theOffset, theData, theSize);
3123   return true;
3124 #elif defined(GL_ES_VERSION_2_0)
3125   if (void* aData = core30fwd->glMapBufferRange (theTarget, theOffset, theSize, GL_MAP_READ_BIT))
3126   {
3127     memcpy (theData, aData, theSize);
3128     core30fwd->glUnmapBuffer (theTarget);
3129     return true;
3130   }
3131   return false;
3132 #else
3133   core15fwd->glGetBufferSubData (theTarget, theOffset, theSize, theData);
3134   return true;
3135 #endif
3136 }
3137
3138 // =======================================================================
3139 // function : DumpJson
3140 // purpose  :
3141 // =======================================================================
3142 void OpenGl_Context::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
3143 {
3144   OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
3145
3146   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myAnisoMax)
3147   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myTexClamp)
3148   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMaxTexDim)
3149   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMaxTexCombined)
3150   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMaxDumpSizeX)
3151   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMaxDumpSizeY)
3152   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMaxClipPlanes)
3153   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMaxMsaaSamples)
3154   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMaxDrawBuffers)
3155   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMaxColorAttachments)
3156   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myGlVerMajor)
3157   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myGlVerMinor)
3158   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsInitialized)
3159   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsStereoBuffers)
3160   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsGlNormalizeEnabled)
3161
3162   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myHasRayTracing)
3163   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myHasRayTracingTextures)
3164   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myHasRayTracingAdaptiveSampling)
3165   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myHasRayTracingAdaptiveSamplingAtomic)
3166
3167   for (int i = 0; i < 4; i++)
3168   {
3169     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myViewport[i])
3170   }
3171
3172   for (int i = 0; i < 4; i++)
3173   {
3174     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myViewportVirt[i])
3175   }
3176
3177   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myPointSpriteOrig)
3178   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myRenderMode)
3179   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myPolygonMode)
3180   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myPolygonOffset)
3181   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myToCullBackFaces)
3182   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myReadBuffer)
3183
3184   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myDefaultVao)
3185   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myColorMask)
3186   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myAllowAlphaToCov)
3187   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myAlphaToCoverage)
3188   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsGlDebugCtx)
3189
3190   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myResolution)
3191   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myResolutionRatio)
3192
3193   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myLineWidthScale)
3194   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myLineFeather)
3195   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myRenderScale)
3196   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myRenderScaleInv)
3197   
3198   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &ModelWorldState)
3199   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &WorldViewState)
3200   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &ProjectionState)
3201 }
3202
3203 // =======================================================================
3204 // function : DumpJsonOpenGlState
3205 // purpose  :
3206 // =======================================================================
3207 void OpenGl_Context::DumpJsonOpenGlState (Standard_OStream& theOStream, Standard_Integer)
3208 {
3209   GLboolean isEnableBlend = glIsEnabled (GL_BLEND);
3210   GLboolean isEnableCullFace = glIsEnabled (GL_CULL_FACE);
3211   GLboolean isEnableDepthTest = glIsEnabled (GL_DEPTH_TEST);
3212   
3213   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, isEnableBlend)
3214   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, isEnableCullFace)
3215   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, isEnableDepthTest)
3216 }
3217