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