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