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