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