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