// Created on: 2012-01-26 // Created by: Kirill GAVRILOV // Copyright (c) 2012-2014 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // // This library is free software; you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License version 2.1 as published // by the Free Software Foundation, with special exception defined in the file // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT // distribution for complete text of the license and disclaimer of any warranty. // // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. #if defined(_WIN32) #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Context,Standard_Transient) #if defined(HAVE_EGL) #include #ifdef _MSC_VER #pragma comment(lib, "libEGL.lib") #endif #elif defined(_WIN32) // #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX) #include #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE // #else #include #include #endif #else #include // glXGetProcAddress() #endif #ifdef __EMSCRIPTEN__ #include //! Check if WebGL extension is available and activate it //! (usage of extension without activation will generate errors). static bool checkEnableWebGlExtension (const OpenGl_Context& theCtx, const char* theExtName) { if (!theCtx.CheckExtension (theExtName)) { return false; } if (EMSCRIPTEN_WEBGL_CONTEXT_HANDLE aWebGlCtx = emscripten_webgl_get_current_context()) { if (emscripten_webgl_enable_extension (aWebGlCtx, theExtName)) { return true; } } return false; } #endif namespace { static const Handle(OpenGl_Resource) NULL_GL_RESOURCE; static const OpenGl_Mat4 THE_IDENTITY_MATRIX; //! Add key-value pair to the dictionary. static void addInfo (TColStd_IndexedDataMapOfStringString& theDict, const TCollection_AsciiString& theKey, const TCollection_AsciiString& theValue) { theDict.ChangeFromIndex (theDict.Add (theKey, theValue)) = theValue; } //! Add key-value pair to the dictionary. static void addInfo (TColStd_IndexedDataMapOfStringString& theDict, const TCollection_AsciiString& theKey, const char* theValue) { TCollection_AsciiString aValue (theValue != NULL ? theValue : ""); theDict.ChangeFromIndex (theDict.Add (theKey, aValue)) = aValue; } } // ======================================================================= // function : OpenGl_Context // purpose : // ======================================================================= OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps) : core11 (NULL), core11fwd (NULL), core15 (NULL), core15fwd (NULL), core20 (NULL), core20fwd (NULL), core32 (NULL), core32back (NULL), core33 (NULL), core33back (NULL), core41 (NULL), core41back (NULL), core42 (NULL), core42back (NULL), core43 (NULL), core43back (NULL), core44 (NULL), core44back (NULL), core45 (NULL), core45back (NULL), caps (!theCaps.IsNull() ? theCaps : new OpenGl_Caps()), #if defined(GL_ES_VERSION_2_0) hasHighp (Standard_False), hasUintIndex(Standard_False), hasTexRGBA8(Standard_False), #else hasHighp (Standard_True), hasUintIndex(Standard_True), hasTexRGBA8(Standard_True), #endif hasTexFloatLinear (Standard_False), hasTexSRGB (Standard_False), hasFboSRGB (Standard_False), hasSRGBControl (Standard_False), #if defined(GL_ES_VERSION_2_0) hasFlatShading (OpenGl_FeatureNotAvailable), #else hasFlatShading (OpenGl_FeatureInCore), #endif hasGlslBitwiseOps (OpenGl_FeatureNotAvailable), hasDrawBuffers (OpenGl_FeatureNotAvailable), hasFloatBuffer (OpenGl_FeatureNotAvailable), hasHalfFloatBuffer (OpenGl_FeatureNotAvailable), hasSampleVariables (OpenGl_FeatureNotAvailable), hasGeometryStage (OpenGl_FeatureNotAvailable), arbDrawBuffers (Standard_False), arbNPTW (Standard_False), arbTexRG (Standard_False), arbTexFloat (Standard_False), arbSamplerObject (NULL), arbTexBindless (NULL), arbTBO (NULL), arbTboRGB32 (Standard_False), arbIns (NULL), arbDbg (NULL), arbFBO (NULL), arbFBOBlit (NULL), arbSampleShading (Standard_False), extFragDepth (Standard_False), extDrawBuffers (Standard_False), extGS (NULL), extBgra(Standard_False), extAnis(Standard_False), extPDS (Standard_False), atiMem (Standard_False), nvxMem (Standard_False), oesSampleVariables (Standard_False), oesStdDerivatives (Standard_False), mySharedResources (new OpenGl_ResourcesMap()), myDelayed (new OpenGl_DelayReleaseMap()), myUnusedResources (new OpenGl_ResourcesStack()), myClippingState (), myGlLibHandle (NULL), myFuncs (new OpenGl_GlFunctions()), myAnisoMax (1), myTexClamp (GL_CLAMP_TO_EDGE), myMaxTexDim (1024), myMaxTexCombined (1), myMaxTexUnitsFFP (1), myMaxDumpSizeX (1024), myMaxDumpSizeY (1024), myMaxClipPlanes (6), myMaxMsaaSamples(0), myMaxDrawBuffers (1), myMaxColorAttachments (1), myGlVerMajor (0), myGlVerMinor (0), myIsInitialized (Standard_False), myIsStereoBuffers (Standard_False), myIsGlNormalizeEnabled (Standard_False), mySpriteTexUnit (Graphic3d_TextureUnit_PointSprite), myHasRayTracing (Standard_False), myHasRayTracingTextures (Standard_False), myHasRayTracingAdaptiveSampling (Standard_False), myHasRayTracingAdaptiveSamplingAtomic (Standard_False), myHasPBR (Standard_False), myPBREnvLUTTexUnit (Graphic3d_TextureUnit_PbrEnvironmentLUT), myPBRDiffIBLMapSHTexUnit (Graphic3d_TextureUnit_PbrIblDiffuseSH), myPBRSpecIBLMapTexUnit (Graphic3d_TextureUnit_PbrIblSpecular), myFrameStats (new OpenGl_FrameStats()), myActiveMockTextures (0), #if !defined(GL_ES_VERSION_2_0) myPointSpriteOrig (GL_UPPER_LEFT), myRenderMode (GL_RENDER), myPolygonMode (GL_FILL), #else myPointSpriteOrig (0), myRenderMode (0), myPolygonMode (0), #endif myToCullBackFaces (false), myReadBuffer (0), myDrawBuffers (0, 7), myDefaultVao (0), myColorMask (true), myAlphaToCoverage (false), myIsGlDebugCtx (false), myIsSRgbWindow (false), myResolution (Graphic3d_RenderingParams::THE_DEFAULT_RESOLUTION), myResolutionRatio (1.0f), myLineWidthScale (1.0f), myLineFeather (1.0f), myRenderScale (1.0f), myRenderScaleInv (1.0f) { myViewport[0] = 0; myViewport[1] = 0; myViewport[2] = 0; myViewport[3] = 0; myViewportVirt[0] = 0; myViewportVirt[1] = 0; myViewportVirt[2] = 0; myViewportVirt[3] = 0; myPolygonOffset.Mode = Aspect_POM_Off; myPolygonOffset.Factor = 0.0f; myPolygonOffset.Units = 0.0f; // system-dependent fields #if defined(HAVE_EGL) myDisplay = (Aspect_Display )EGL_NO_DISPLAY; myWindow = (Aspect_Drawable )EGL_NO_SURFACE; myGContext = (Aspect_RenderingContext )EGL_NO_CONTEXT; #elif defined(_WIN32) myWindow = NULL; myWindowDC = NULL; myGContext = NULL; #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX) // Vendors can not extend functionality on this system // and developers are limited to OpenGL support provided by Mac OS X SDK. // We retrieve function pointers from system library // to generalize extensions support on all platforms. // In this way we also reach binary compatibility benefit between OS releases // if some newest functionality is optionally used. // Notice that GL version / extension availability checks are required // because function pointers may be available but not functionality itself // (depends on renderer). #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE myGContext = NULL; myGlLibHandle = dlopen ("/System/Library/Frameworks/OpenGLES.framework/OpenGLES", RTLD_LAZY); #else myGContext = NULL; myGlLibHandle = dlopen ("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY); #endif #else myDisplay = NULL; myWindow = 0; myGContext = 0; #endif memset (myFuncs.operator->(), 0, sizeof(OpenGl_GlFunctions)); myShaderManager = new OpenGl_ShaderManager (this); } // ======================================================================= // function : ~OpenGl_Context // purpose : // ======================================================================= OpenGl_Context::~OpenGl_Context() { // release clean up queue ReleaseDelayed(); #if !defined(GL_ES_VERSION_2_0) // release default VAO if (myDefaultVao != 0 && IsValid() && core32 != NULL) { core32->glDeleteVertexArrays (1, &myDefaultVao); } myDefaultVao = 0; #endif // release mock textures if (!myTextureRgbaBlack.IsNull()) { myTextureRgbaBlack->Release (this); myTextureRgbaBlack.Nullify(); } if (!myTextureRgbaWhite.IsNull()) { myTextureRgbaWhite->Release (this); myTextureRgbaWhite.Nullify(); } // release default FBO if (!myDefaultFbo.IsNull()) { myDefaultFbo->Release (this); myDefaultFbo.Nullify(); } // release shared resources if any if (mySharedResources->GetRefCount() <= 1) { myShaderManager.Nullify(); for (NCollection_DataMap::Iterator anIter (*mySharedResources); anIter.More(); anIter.Next()) { anIter.Value()->Release (this); } // release delayed resources added during deletion of shared resources while (!myUnusedResources->IsEmpty()) { myUnusedResources->First()->Release (this); myUnusedResources->RemoveFirst(); } } else if (myShaderManager->IsSameContext (this)) { myShaderManager->SetContext (NULL); } mySharedResources.Nullify(); myDelayed.Nullify(); if (arbDbg != NULL && myIsGlDebugCtx && IsValid()) { // reset callback #if !defined(GL_ES_VERSION_2_0) void* aPtr = NULL; glGetPointerv (GL_DEBUG_CALLBACK_USER_PARAM, &aPtr); if (aPtr == this) #endif { arbDbg->glDebugMessageCallback (NULL, NULL); } myIsGlDebugCtx = Standard_False; } } // ======================================================================= // function : forcedRelease // purpose : // ======================================================================= void OpenGl_Context::forcedRelease() { ReleaseDelayed(); for (NCollection_DataMap::Iterator anIter (*mySharedResources); anIter.More(); anIter.Next()) { anIter.Value()->Release (this); } mySharedResources->Clear(); myShaderManager->clear(); myShaderManager->SetContext (NULL); // release delayed resources added during deletion of shared resources while (!myUnusedResources->IsEmpty()) { myUnusedResources->First()->Release (this); myUnusedResources->RemoveFirst(); } } // ======================================================================= // function : ResizeViewport // purpose : // ======================================================================= void OpenGl_Context::ResizeViewport (const Standard_Integer* theRect) { core11fwd->glViewport (theRect[0], theRect[1], theRect[2], theRect[3]); myViewport[0] = theRect[0]; myViewport[1] = theRect[1]; myViewport[2] = theRect[2]; myViewport[3] = theRect[3]; if (HasRenderScale()) { myViewportVirt[0] = Standard_Integer(theRect[0] * myRenderScaleInv); myViewportVirt[1] = Standard_Integer(theRect[1] * myRenderScaleInv); myViewportVirt[2] = Standard_Integer(theRect[2] * myRenderScaleInv); myViewportVirt[3] = Standard_Integer(theRect[3] * myRenderScaleInv); } else { myViewportVirt[0] = theRect[0]; myViewportVirt[1] = theRect[1]; myViewportVirt[2] = theRect[2]; myViewportVirt[3] = theRect[3]; } } #if !defined(GL_ES_VERSION_2_0) inline Standard_Integer stereoToMonoBuffer (const Standard_Integer theBuffer) { switch (theBuffer) { case GL_BACK_LEFT: case GL_BACK_RIGHT: return GL_BACK; case GL_FRONT_LEFT: case GL_FRONT_RIGHT: return GL_FRONT; default: return theBuffer; } } #endif // ======================================================================= // function : SetReadBuffer // purpose : // ======================================================================= void OpenGl_Context::SetReadBuffer (const Standard_Integer theReadBuffer) { #if !defined(GL_ES_VERSION_2_0) myReadBuffer = !myIsStereoBuffers ? stereoToMonoBuffer (theReadBuffer) : theReadBuffer; if (myReadBuffer < GL_COLOR_ATTACHMENT0 && arbFBO != NULL) { arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); } ::glReadBuffer (myReadBuffer); #else (void )theReadBuffer; #endif } // ======================================================================= // function : SetDrawBuffer // purpose : // ======================================================================= void OpenGl_Context::SetDrawBuffer (const Standard_Integer theDrawBuffer) { #if !defined(GL_ES_VERSION_2_0) const Standard_Integer aDrawBuffer = !myIsStereoBuffers ? stereoToMonoBuffer (theDrawBuffer) : theDrawBuffer; if (aDrawBuffer < GL_COLOR_ATTACHMENT0 && arbFBO != NULL) { arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); } ::glDrawBuffer (aDrawBuffer); myDrawBuffers.Init (GL_NONE); myDrawBuffers.SetValue (0, aDrawBuffer); #else (void )theDrawBuffer; #endif } // ======================================================================= // function : SetDrawBuffers // purpose : // ======================================================================= void OpenGl_Context::SetDrawBuffers (const Standard_Integer theNb, const Standard_Integer* theDrawBuffers) { Standard_ASSERT_RETURN (hasDrawBuffers, "Multiple draw buffers feature is not supported by the context", Standard_ASSERT_DO_NOTHING()); if (myDrawBuffers.Length() < theNb) { // should actually never happen here myDrawBuffers.Resize (0, theNb - 1, false); } myDrawBuffers.Init (GL_NONE); Standard_Boolean useDefaultFbo = Standard_False; for (Standard_Integer anI = 0; anI < theNb; ++anI) { if (theDrawBuffers[anI] < GL_COLOR_ATTACHMENT0 && theDrawBuffers[anI] != GL_NONE) { useDefaultFbo = Standard_True; } else { myDrawBuffers.SetValue (anI, theDrawBuffers[anI]); } } if (arbFBO != NULL && useDefaultFbo) { arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); } myFuncs->glDrawBuffers (theNb, (const GLenum*)theDrawBuffers); } // ======================================================================= // function : SetFrameBufferSRGB // purpose : // ======================================================================= void OpenGl_Context::SetFrameBufferSRGB (bool theIsFbo) { if (!hasFboSRGB) { myIsSRgbActive = false; return; } myIsSRgbActive = ToRenderSRGB() && (theIsFbo || myIsSRgbWindow); if (!hasSRGBControl) { return; } if (myIsSRgbActive) { core11fwd->glEnable (GL_FRAMEBUFFER_SRGB); } else { core11fwd->glDisable (GL_FRAMEBUFFER_SRGB); } } // ======================================================================= // function : SetCullBackFaces // purpose : // ======================================================================= void OpenGl_Context::SetCullBackFaces (bool theToEnable) { if (myToCullBackFaces == theToEnable) { return; } myToCullBackFaces = theToEnable; if (theToEnable) { //glCullFace (GL_BACK); GL_BACK by default core11fwd->glEnable (GL_CULL_FACE); } else { core11fwd->glDisable (GL_CULL_FACE); } } // ======================================================================= // function : FetchState // purpose : // ======================================================================= void OpenGl_Context::FetchState() { #if !defined(GL_ES_VERSION_2_0) // cache feedback mode state if (core11 != NULL) { ::glGetIntegerv (GL_RENDER_MODE, &myRenderMode); } // cache read buffers state ::glGetIntegerv (GL_READ_BUFFER, &myReadBuffer); // cache draw buffers state if (myDrawBuffers.Length() < myMaxDrawBuffers) { myDrawBuffers.Resize (0, myMaxDrawBuffers - 1, false); } myDrawBuffers.Init (GL_NONE); Standard_Integer aDrawBuffer = GL_NONE; if (myMaxDrawBuffers == 1) { ::glGetIntegerv (GL_DRAW_BUFFER, &aDrawBuffer); myDrawBuffers.SetValue (0, aDrawBuffer); } else { for (Standard_Integer anI = 0; anI < myMaxDrawBuffers; ++anI) { ::glGetIntegerv (GL_DRAW_BUFFER0 + anI, &aDrawBuffer); myDrawBuffers.SetValue (anI, aDrawBuffer); } } #endif } // ======================================================================= // function : Share // purpose : // ======================================================================= void OpenGl_Context::Share (const Handle(OpenGl_Context)& theShareCtx) { if (!theShareCtx.IsNull()) { mySharedResources = theShareCtx->mySharedResources; myDelayed = theShareCtx->myDelayed; myUnusedResources = theShareCtx->myUnusedResources; myShaderManager = theShareCtx->myShaderManager; } } #if !defined(__APPLE__) || defined(MACOSX_USE_GLX) // ======================================================================= // function : IsCurrent // purpose : // ======================================================================= Standard_Boolean OpenGl_Context::IsCurrent() const { #if defined(HAVE_EGL) if ((EGLDisplay )myDisplay == EGL_NO_DISPLAY || (EGLContext )myGContext == EGL_NO_CONTEXT) { return Standard_False; } return (((EGLDisplay )myDisplay == eglGetCurrentDisplay()) && ((EGLContext )myGContext == eglGetCurrentContext()) && ((EGLSurface )myWindow == eglGetCurrentSurface (EGL_DRAW))); #elif defined(_WIN32) if (myWindowDC == NULL || myGContext == NULL) { return Standard_False; } return (( (HDC )myWindowDC == wglGetCurrentDC()) && ((HGLRC )myGContext == wglGetCurrentContext())); #else if (myDisplay == NULL || myWindow == 0 || myGContext == 0) { return Standard_False; } return ( ((Display* )myDisplay == glXGetCurrentDisplay()) && ((GLXContext )myGContext == glXGetCurrentContext()) && ((GLXDrawable )myWindow == glXGetCurrentDrawable())); #endif } // ======================================================================= // function : MakeCurrent // purpose : // ======================================================================= Standard_Boolean OpenGl_Context::MakeCurrent() { #if defined(HAVE_EGL) if ((EGLDisplay )myDisplay == EGL_NO_DISPLAY || (EGLContext )myGContext == EGL_NO_CONTEXT) { Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called before!"); return Standard_False; } if (eglMakeCurrent ((EGLDisplay )myDisplay, (EGLSurface )myWindow, (EGLSurface )myWindow, (EGLContext )myGContext) != EGL_TRUE) { // if there is no current context it might be impossible to use glGetError() correctly PushMessage (GL_DEBUG_SOURCE_WINDOW_SYSTEM, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, "eglMakeCurrent() has failed!"); myIsInitialized = Standard_False; return Standard_False; } #elif defined(_WIN32) if (myWindowDC == NULL || myGContext == NULL) { Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called before!"); return Standard_False; } // technically it should be safe to activate already bound GL context // however some drivers (Intel etc.) may FAIL doing this for unknown reason if (IsCurrent()) { myShaderManager->SetContext (this); return Standard_True; } else if (wglMakeCurrent ((HDC )myWindowDC, (HGLRC )myGContext) != TRUE) { // notice that glGetError() couldn't be used here! wchar_t* aMsgBuff = NULL; DWORD anErrorCode = GetLastError(); FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, anErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (wchar_t* )&aMsgBuff, 0, NULL); TCollection_ExtendedString aMsg ("wglMakeCurrent() has failed. "); if (aMsgBuff != NULL) { aMsg += (Standard_ExtString )aMsgBuff; LocalFree (aMsgBuff); } PushMessage (GL_DEBUG_SOURCE_WINDOW_SYSTEM, GL_DEBUG_TYPE_ERROR, (unsigned int )anErrorCode, GL_DEBUG_SEVERITY_HIGH, aMsg); myIsInitialized = Standard_False; return Standard_False; } #else if (myDisplay == NULL || myWindow == 0 || myGContext == 0) { Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called before!"); return Standard_False; } if (!glXMakeCurrent ((Display* )myDisplay, (GLXDrawable )myWindow, (GLXContext )myGContext)) { // if there is no current context it might be impossible to use glGetError() correctly PushMessage (GL_DEBUG_SOURCE_WINDOW_SYSTEM, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, "glXMakeCurrent() has failed!"); myIsInitialized = Standard_False; return Standard_False; } #endif myShaderManager->SetContext (this); return Standard_True; } // ======================================================================= // function : SwapBuffers // purpose : // ======================================================================= void OpenGl_Context::SwapBuffers() { #if defined(HAVE_EGL) if ((EGLSurface )myWindow != EGL_NO_SURFACE) { eglSwapBuffers ((EGLDisplay )myDisplay, (EGLSurface )myWindow); } #elif defined(_WIN32) if ((HDC )myWindowDC != NULL) { ::SwapBuffers ((HDC )myWindowDC); glFlush(); } #else if ((Display* )myDisplay != NULL) { glXSwapBuffers ((Display* )myDisplay, (GLXDrawable )myWindow); } #endif } #endif // __APPLE__ // ======================================================================= // function : SetSwapInterval // purpose : // ======================================================================= Standard_Boolean OpenGl_Context::SetSwapInterval (const Standard_Integer theInterval) { #if defined(HAVE_EGL) if (::eglSwapInterval ((EGLDisplay )myDisplay, theInterval) == EGL_TRUE) { return Standard_True; } #elif defined(_WIN32) if (myFuncs->wglSwapIntervalEXT != NULL) { myFuncs->wglSwapIntervalEXT (theInterval); return Standard_True; } #elif defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE // #elif defined(__APPLE__) if (::CGLSetParameter (CGLGetCurrentContext(), kCGLCPSwapInterval, &theInterval) == kCGLNoError) { return Standard_True; } #else if (theInterval == -1 && myFuncs->glXSwapIntervalEXT != NULL) { typedef int (*glXSwapIntervalEXT_t_x)(Display* theDisplay, GLXDrawable theDrawable, int theInterval); glXSwapIntervalEXT_t_x aFuncPtr = (glXSwapIntervalEXT_t_x )myFuncs->glXSwapIntervalEXT; aFuncPtr ((Display* )myDisplay, (GLXDrawable )myWindow, theInterval); return Standard_True; } else if (myFuncs->glXSwapIntervalSGI != NULL) { myFuncs->glXSwapIntervalSGI (theInterval); return Standard_True; } #endif return Standard_False; } // ======================================================================= // function : findProc // purpose : // ======================================================================= void* OpenGl_Context::findProc (const char* theFuncName) { #if defined(HAVE_EGL) return (void* )eglGetProcAddress (theFuncName); #elif defined(_WIN32) return (void* )wglGetProcAddress (theFuncName); #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX) return (myGlLibHandle != NULL) ? dlsym (myGlLibHandle, theFuncName) : NULL; #else return (void* )glXGetProcAddress ((const GLubyte* )theFuncName); #endif } // ======================================================================= // function : CheckExtension // purpose : // ======================================================================= Standard_Boolean OpenGl_Context::CheckExtension (const char* theExtName) const { if (theExtName == NULL) { #ifdef OCCT_DEBUG std::cerr << "CheckExtension called with NULL string!\n"; #endif return Standard_False; } else if (caps->contextNoExtensions) { return Standard_False; } #if !defined(GL_ES_VERSION_2_0) // available since OpenGL 3.0 // and the ONLY way to check extensions with OpenGL 3.1+ core profile if (IsGlGreaterEqual (3, 0) && myFuncs->glGetStringi != NULL) { GLint anExtNb = 0; ::glGetIntegerv (GL_NUM_EXTENSIONS, &anExtNb); const size_t anExtNameLen = strlen (theExtName); for (GLint anIter = 0; anIter < anExtNb; ++anIter) { const char* anExtension = (const char* )myFuncs->glGetStringi (GL_EXTENSIONS, (GLuint )anIter); const size_t aTestExtNameLen = strlen (anExtension); if (aTestExtNameLen == anExtNameLen && strncmp (anExtension, theExtName, anExtNameLen) == 0) { return Standard_True; } } return Standard_False; } #endif // use old way with huge string for all extensions const char* anExtString = (const char* )glGetString (GL_EXTENSIONS); if (anExtString == NULL) { Messenger()->Send ("TKOpenGL: glGetString (GL_EXTENSIONS) has returned NULL! No GL context?", Message_Warning); return Standard_False; } return CheckExtension (anExtString, theExtName); } // ======================================================================= // function : CheckExtension // purpose : // ======================================================================= Standard_Boolean OpenGl_Context::CheckExtension (const char* theExtString, const char* theExtName) { if (theExtString == NULL) { return Standard_False; } // Search for theExtName in the extensions string. // Use of strstr() is not sufficient because extension names can be prefixes of other extension names. char* aPtrIter = (char* )theExtString; const char* aPtrEnd = aPtrIter + strlen (theExtString); const size_t anExtNameLen = strlen (theExtName); while (aPtrIter < aPtrEnd) { const size_t n = strcspn (aPtrIter, " "); if ((n == anExtNameLen) && (strncmp (aPtrIter, theExtName, anExtNameLen) == 0)) { return Standard_True; } aPtrIter += (n + 1); } return Standard_False; } #if !defined(__APPLE__) || defined(MACOSX_USE_GLX) // ======================================================================= // function : Init // purpose : // ======================================================================= Standard_Boolean OpenGl_Context::Init (const Standard_Boolean theIsCoreProfile) { if (myIsInitialized) { return Standard_True; } #if defined(HAVE_EGL) myDisplay = (Aspect_Display )eglGetCurrentDisplay(); myGContext = (Aspect_RenderingContext )eglGetCurrentContext(); myWindow = (Aspect_Drawable )eglGetCurrentSurface(EGL_DRAW); #elif defined(_WIN32) myWindowDC = (Aspect_Handle )wglGetCurrentDC(); myGContext = (Aspect_RenderingContext )wglGetCurrentContext(); #else myDisplay = (Aspect_Display )glXGetCurrentDisplay(); myGContext = (Aspect_RenderingContext )glXGetCurrentContext(); myWindow = (Aspect_Drawable )glXGetCurrentDrawable(); #endif if (myGContext == NULL) { return Standard_False; } init (theIsCoreProfile); myIsInitialized = Standard_True; return Standard_True; } #endif // __APPLE__ // ======================================================================= // function : Init // purpose : // ======================================================================= #if defined(HAVE_EGL) Standard_Boolean OpenGl_Context::Init (const Aspect_Drawable theEglSurface, const Aspect_Display theEglDisplay, const Aspect_RenderingContext theEglContext, const Standard_Boolean theIsCoreProfile) #elif defined(_WIN32) Standard_Boolean OpenGl_Context::Init (const Aspect_Handle theWindow, const Aspect_Handle theWindowDC, const Aspect_RenderingContext theGContext, const Standard_Boolean theIsCoreProfile) #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX) #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE Standard_Boolean OpenGl_Context::Init (EAGLContext* theGContext, const Standard_Boolean theIsCoreProfile) #else Standard_Boolean OpenGl_Context::Init (NSOpenGLContext* theGContext, const Standard_Boolean theIsCoreProfile) #endif #else Standard_Boolean OpenGl_Context::Init (const Aspect_Drawable theWindow, const Aspect_Display theDisplay, const Aspect_RenderingContext theGContext, const Standard_Boolean theIsCoreProfile) #endif { Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called only once!"); #if defined(HAVE_EGL) myWindow = theEglSurface; myGContext = theEglContext; myDisplay = theEglDisplay; #elif defined(_WIN32) myWindow = theWindow; myGContext = theGContext; myWindowDC = theWindowDC; #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX) myGContext = theGContext; #else myWindow = theWindow; myGContext = theGContext; myDisplay = theDisplay; #endif if (myGContext == NULL || !MakeCurrent()) { return Standard_False; } init (theIsCoreProfile); myIsInitialized = Standard_True; return Standard_True; } // ======================================================================= // function : ResetErrors // purpose : // ======================================================================= bool OpenGl_Context::ResetErrors (const bool theToPrintErrors) { int aPrevErr = 0; int anErr = ::glGetError(); const bool hasError = anErr != GL_NO_ERROR; if (!theToPrintErrors) { for (; anErr != GL_NO_ERROR && aPrevErr != anErr; aPrevErr = anErr, anErr = ::glGetError()) { // } return hasError; } for (; anErr != GL_NO_ERROR && aPrevErr != anErr; aPrevErr = anErr, anErr = ::glGetError()) { TCollection_ExtendedString anErrId; switch (anErr) { case GL_INVALID_ENUM: anErrId = "GL_INVALID_ENUM"; break; case GL_INVALID_VALUE: anErrId = "GL_INVALID_VALUE"; break; case GL_INVALID_OPERATION: anErrId = "GL_INVALID_OPERATION"; break; #ifdef GL_STACK_OVERFLOW case GL_STACK_OVERFLOW: anErrId = "GL_STACK_OVERFLOW"; break; case GL_STACK_UNDERFLOW: anErrId = "GL_STACK_UNDERFLOW"; break; #endif case GL_OUT_OF_MEMORY: anErrId = "GL_OUT_OF_MEMORY"; break; case GL_INVALID_FRAMEBUFFER_OPERATION: anErrId = "GL_INVALID_FRAMEBUFFER_OPERATION"; break; default: anErrId = TCollection_ExtendedString("#") + anErr; break; } const TCollection_ExtendedString aMsg = TCollection_ExtendedString ("Unhandled GL error: ") + anErrId; PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER, 0, GL_DEBUG_SEVERITY_LOW, aMsg); } return hasError; } // ======================================================================= // function : ReadGlVersion // purpose : // ======================================================================= void OpenGl_Context::ReadGlVersion (Standard_Integer& theGlVerMajor, Standard_Integer& theGlVerMinor) { // reset values theGlVerMajor = 0; theGlVerMinor = 0; #ifdef GL_MAJOR_VERSION // available since OpenGL 3.0 and OpenGL 3.0 ES GLint aMajor = 0, aMinor = 0; glGetIntegerv (GL_MAJOR_VERSION, &aMajor); glGetIntegerv (GL_MINOR_VERSION, &aMinor); // glGetError() sometimes does not report an error here even if // GL does not know GL_MAJOR_VERSION and GL_MINOR_VERSION constants. // This happens on some renderers like e.g. Cygwin MESA. // Thus checking additionally if GL has put anything to // the output variables. if (::glGetError() == GL_NO_ERROR && aMajor != 0 && aMinor != 0) { theGlVerMajor = aMajor; theGlVerMinor = aMinor; return; } for (GLenum anErr = ::glGetError(), aPrevErr = GL_NO_ERROR;; aPrevErr = anErr, anErr = ::glGetError()) { if (anErr == GL_NO_ERROR || anErr == aPrevErr) { break; } } #endif // Read version string. // Notice that only first two numbers split by point '2.1 XXXXX' are significant. // Following trash (after space) is vendor-specific. // New drivers also returns micro version of GL like '3.3.0' which has no meaning // and should be considered as vendor-specific too. const char* aVerStr = (const char* )glGetString (GL_VERSION); if (aVerStr == NULL || *aVerStr == '\0') { // invalid GL context return; } //#if defined(GL_ES_VERSION_2_0) // skip "OpenGL ES-** " section for (; *aVerStr != '\0'; ++aVerStr) { if (*aVerStr >= '0' && *aVerStr <= '9') { break; } } //#endif // parse string for major number char aMajorStr[32]; char aMinorStr[32]; size_t aMajIter = 0; while (aVerStr[aMajIter] >= '0' && aVerStr[aMajIter] <= '9') { ++aMajIter; } if (aMajIter == 0 || aMajIter >= sizeof(aMajorStr)) { return; } memcpy (aMajorStr, aVerStr, aMajIter); aMajorStr[aMajIter] = '\0'; // parse string for minor number aVerStr += aMajIter + 1; size_t aMinIter = 0; while (aVerStr[aMinIter] >= '0' && aVerStr[aMinIter] <= '9') { ++aMinIter; } if (aMinIter == 0 || aMinIter >= sizeof(aMinorStr)) { return; } memcpy (aMinorStr, aVerStr, aMinIter); aMinorStr[aMinIter] = '\0'; // read numbers theGlVerMajor = atoi (aMajorStr); theGlVerMinor = atoi (aMinorStr); if (theGlVerMajor <= 0) { theGlVerMajor = 0; theGlVerMinor = 0; } } static Standard_CString THE_DBGMSG_UNKNOWN = "UNKNOWN"; static Standard_CString THE_DBGMSG_SOURCES[] = { ".OpenGL", // GL_DEBUG_SOURCE_API ".WinSystem", // GL_DEBUG_SOURCE_WINDOW_SYSTEM ".GLSL", // GL_DEBUG_SOURCE_SHADER_COMPILER ".3rdParty", // GL_DEBUG_SOURCE_THIRD_PARTY "", // GL_DEBUG_SOURCE_APPLICATION ".Other" // GL_DEBUG_SOURCE_OTHER }; static Standard_CString THE_DBGMSG_TYPES[] = { "Error", // GL_DEBUG_TYPE_ERROR "Deprecated", // GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR "Undef. behavior", // GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR "Portability", // GL_DEBUG_TYPE_PORTABILITY "Performance", // GL_DEBUG_TYPE_PERFORMANCE "Other" // GL_DEBUG_TYPE_OTHER }; static Standard_CString THE_DBGMSG_SEV_HIGH = "High"; // GL_DEBUG_SEVERITY_HIGH static Standard_CString THE_DBGMSG_SEV_MEDIUM = "Medium"; // GL_DEBUG_SEVERITY_MEDIUM static Standard_CString THE_DBGMSG_SEV_LOW = "Low"; // GL_DEBUG_SEVERITY_LOW //! Callback for GL_ARB_debug_output extension static void APIENTRY debugCallbackWrap(unsigned int theSource, unsigned int theType, unsigned int theId, unsigned int theSeverity, int /*theLength*/, const char* theMessage, const void* theUserParam) { OpenGl_Context* aCtx = (OpenGl_Context* )theUserParam; aCtx->PushMessage (theSource, theType, theId, theSeverity, theMessage); } // ======================================================================= // function : PushMessage // purpose : // ======================================================================= void OpenGl_Context::PushMessage (const unsigned int theSource, const unsigned int theType, const unsigned int theId, const unsigned int theSeverity, const TCollection_ExtendedString& theMessage) { if (caps->suppressExtraMsg && theSource >= GL_DEBUG_SOURCE_API && theSource <= GL_DEBUG_SOURCE_OTHER && myFilters[theSource - GL_DEBUG_SOURCE_API].Contains (theId)) { return; } Standard_CString& aSrc = (theSource >= GL_DEBUG_SOURCE_API && theSource <= GL_DEBUG_SOURCE_OTHER) ? THE_DBGMSG_SOURCES[theSource - GL_DEBUG_SOURCE_API] : THE_DBGMSG_UNKNOWN; Standard_CString& aType = (theType >= GL_DEBUG_TYPE_ERROR && theType <= GL_DEBUG_TYPE_OTHER) ? THE_DBGMSG_TYPES[theType - GL_DEBUG_TYPE_ERROR] : THE_DBGMSG_UNKNOWN; Standard_CString& aSev = theSeverity == GL_DEBUG_SEVERITY_HIGH ? THE_DBGMSG_SEV_HIGH : (theSeverity == GL_DEBUG_SEVERITY_MEDIUM ? THE_DBGMSG_SEV_MEDIUM : THE_DBGMSG_SEV_LOW); Message_Gravity aGrav = theSeverity == GL_DEBUG_SEVERITY_HIGH ? Message_Alarm : (theSeverity == GL_DEBUG_SEVERITY_MEDIUM ? Message_Warning : Message_Info); TCollection_ExtendedString aMsg; aMsg += "TKOpenGl"; aMsg += aSrc; aMsg += " | Type: "; aMsg += aType; aMsg += " | ID: "; aMsg += (Standard_Integer )theId; aMsg += " | Severity: "; aMsg += aSev; aMsg += " | Message:\n "; aMsg += theMessage; Messenger()->Send (aMsg, aGrav); } // ======================================================================= // function : ExcludeMessage // purpose : // ====================================================================== Standard_Boolean OpenGl_Context::ExcludeMessage (const unsigned int theSource, const unsigned int theId) { return theSource >= GL_DEBUG_SOURCE_API && theSource <= GL_DEBUG_SOURCE_OTHER && myFilters[theSource - GL_DEBUG_SOURCE_API].Add (theId); } // ======================================================================= // function : IncludeMessage // purpose : // ====================================================================== Standard_Boolean OpenGl_Context::IncludeMessage (const unsigned int theSource, const unsigned int theId) { return theSource >= GL_DEBUG_SOURCE_API && theSource <= GL_DEBUG_SOURCE_OTHER && myFilters[theSource - GL_DEBUG_SOURCE_API].Remove (theId); } // ======================================================================= // function : checkWrongVersion // purpose : // ====================================================================== void OpenGl_Context::checkWrongVersion (Standard_Integer theGlVerMajor, Standard_Integer theGlVerMinor, const char* theLastFailedProc) { if (!IsGlGreaterEqual (theGlVerMajor, theGlVerMinor)) { return; } PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, TCollection_AsciiString() + "Error! OpenGL context reports version " + myGlVerMajor + "." + myGlVerMinor + " but does not export required functions for " + theGlVerMajor + "." + theGlVerMinor + " (" + (theLastFailedProc != NULL ? theLastFailedProc : "") + ")\n" + "Please report this issue to OpenGL driver vendor '" + myVendor + "'"); // lower internal version if (theGlVerMinor > 0) { myGlVerMajor = theGlVerMajor; myGlVerMinor = theGlVerMinor - 1; return; } #if defined(GL_ES_VERSION_2_0) switch (theGlVerMajor) { case 3: myGlVerMajor = 2; myGlVerMinor = 0; return; } #else switch (theGlVerMajor) { case 2: myGlVerMajor = 1; myGlVerMinor = 5; return; case 3: myGlVerMajor = 2; myGlVerMinor = 1; return; case 4: myGlVerMajor = 3; myGlVerMinor = 3; return; } #endif } // ======================================================================= // function : init // purpose : // ======================================================================= void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile) { // read version myGlVerMajor = 0; myGlVerMinor = 0; myMaxMsaaSamples = 0; myMaxDrawBuffers = 1; myMaxColorAttachments = 1; ReadGlVersion (myGlVerMajor, myGlVerMinor); myVendor = (const char* )::glGetString (GL_VENDOR); myVendor.LowerCase(); if (caps->contextMajorVersionUpper != -1) { // synthetically restrict OpenGL version for testing Standard_Integer aCtxVer[2] = { myGlVerMajor, myGlVerMinor }; bool isLowered = false; if (myGlVerMajor > caps->contextMajorVersionUpper) { isLowered = true; myGlVerMajor = caps->contextMajorVersionUpper; #if defined(GL_ES_VERSION_2_0) switch (myGlVerMajor) { case 2: myGlVerMinor = 0; break; } #else switch (myGlVerMajor) { case 1: myGlVerMinor = 5; break; case 2: myGlVerMinor = 1; break; case 3: myGlVerMinor = 3; break; } #endif } if (caps->contextMinorVersionUpper != -1 && myGlVerMinor > caps->contextMinorVersionUpper) { isLowered = true; myGlVerMinor = caps->contextMinorVersionUpper; } if (isLowered) { PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM, TCollection_AsciiString ("OpenGL version ") + aCtxVer[0] + "." + aCtxVer[1] + " has been lowered to " + myGlVerMajor + "." + myGlVerMinor); } } if (!caps->ffpEnable && !IsGlGreaterEqual (2, 0)) { caps->ffpEnable = true; TCollection_ExtendedString aMsg = TCollection_ExtendedString("OpenGL driver is too old! Context info:\n") + " Vendor: " + (const char* )::glGetString (GL_VENDOR) + "\n" + " Renderer: " + (const char* )::glGetString (GL_RENDERER) + "\n" + " Version: " + (const char* )::glGetString (GL_VERSION) + "\n" + " Fallback using deprecated fixed-function pipeline.\n" + " Visualization might work incorrectly.\n" " Consider upgrading the graphics driver."; PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, aMsg); } #if defined(GL_ES_VERSION_2_0) (void )theIsCoreProfile; const bool isCoreProfile = false; #else if (myVendor.Search ("nvidia") != -1) { // Buffer detailed info: Buffer object 1 (bound to GL_ARRAY_BUFFER_ARB, usage hint is GL_STATIC_DRAW) // will use VIDEO memory as the source for buffer object operations. ExcludeMessage (GL_DEBUG_SOURCE_API, 131185); } if (IsGlGreaterEqual (3, 0)) { // retrieve auxiliary function in advance FindProc ("glGetStringi", myFuncs->glGetStringi); } bool isCoreProfile = false; if (IsGlGreaterEqual (3, 2)) { isCoreProfile = (theIsCoreProfile == Standard_True); // detect Core profile if (!isCoreProfile) { GLint aProfile = 0; ::glGetIntegerv (GL_CONTEXT_PROFILE_MASK, &aProfile); isCoreProfile = (aProfile & GL_CONTEXT_CORE_PROFILE_BIT) != 0; } } #endif core11 = NULL; if (!isCoreProfile) { core11 = (OpenGl_GlCore11* )(&(*myFuncs)); } core11fwd = (OpenGl_GlCore11Fwd* )(&(*myFuncs)); core15 = NULL; core15fwd = NULL; core20 = NULL; core20fwd = NULL; core32 = NULL; core32back = NULL; core33 = NULL; core33back = NULL; core41 = NULL; core41back = NULL; core42 = NULL; core42back = NULL; core43 = NULL; core43back = NULL; core44 = NULL; core44back = NULL; core45 = NULL; core45back = NULL; arbTBO = NULL; arbTboRGB32 = Standard_False; arbIns = NULL; arbDbg = NULL; arbFBO = NULL; arbFBOBlit = NULL; extGS = NULL; myDefaultVao = 0; //! Make record shorter to retrieve function pointer using variable with same name const char* aLastFailedProc = NULL; #define FindProcShort(theFunc) FindProcVerbose(aLastFailedProc, #theFunc, myFuncs->theFunc) #if defined(GL_ES_VERSION_2_0) hasTexRGBA8 = IsGlGreaterEqual (3, 0) || CheckExtension ("GL_OES_rgb8_rgba8"); hasTexSRGB = IsGlGreaterEqual (3, 0); hasFboSRGB = IsGlGreaterEqual (3, 0); hasSRGBControl = CheckExtension ("GL_EXT_sRGB_write_control"); // NPOT textures has limited support within OpenGL ES 2.0 // which are relaxed by OpenGL ES 3.0 or some extensions //arbNPTW = IsGlGreaterEqual (3, 0) // || CheckExtension ("GL_OES_texture_npot") // || CheckExtension ("GL_NV_texture_npot_2D_mipmap"); arbNPTW = Standard_True; arbTexRG = IsGlGreaterEqual (3, 0) || CheckExtension ("GL_EXT_texture_rg"); extBgra = CheckExtension ("GL_EXT_texture_format_BGRA8888"); extAnis = CheckExtension ("GL_EXT_texture_filter_anisotropic"); extPDS = IsGlGreaterEqual (3, 0) || CheckExtension ("GL_OES_packed_depth_stencil"); #ifdef __EMSCRIPTEN__ if (!extPDS && checkEnableWebGlExtension (*this, "GL_WEBGL_depth_texture")) { extPDS = true; // WebGL 1.0 extension (in WebGL 2.0 core) } #endif core11fwd = (OpenGl_GlCore11Fwd* )(&(*myFuncs)); if (IsGlGreaterEqual (2, 0)) { // enable compatible functions core20 = (OpenGl_GlCore20* )(&(*myFuncs)); core20fwd = (OpenGl_GlCore20Fwd* )(&(*myFuncs)); core15fwd = (OpenGl_GlCore15Fwd* )(&(*myFuncs)); arbFBO = (OpenGl_ArbFBO* )(&(*myFuncs)); } if (IsGlGreaterEqual (3, 0) && FindProcShort (glBlitFramebuffer)) { arbFBOBlit = (OpenGl_ArbFBOBlit* )(&(*myFuncs)); } if (IsGlGreaterEqual (3, 0) && FindProcShort (glGenSamplers) && FindProcShort (glDeleteSamplers) && FindProcShort (glIsSampler) && FindProcShort (glBindSampler) && FindProcShort (glSamplerParameteri) && FindProcShort (glSamplerParameteriv) && FindProcShort (glSamplerParameterf) && FindProcShort (glSamplerParameterfv) && FindProcShort (glGetSamplerParameteriv) && FindProcShort (glGetSamplerParameterfv)) //&& FindProcShort (glSamplerParameterIiv) // only on Desktop or with extensions GL_OES_texture_border_clamp/GL_EXT_texture_border_clamp //&& FindProcShort (glSamplerParameterIuiv) //&& FindProcShort (glGetSamplerParameterIiv) //&& FindProcShort (glGetSamplerParameterIuiv)) { arbSamplerObject = (OpenGl_ArbSamplerObject* )(&(*myFuncs)); } extFragDepth = !IsGlGreaterEqual(3, 0) && CheckExtension ("GL_EXT_frag_depth"); if (IsGlGreaterEqual (3, 1) && FindProcShort (glTexStorage2DMultisample)) { // MSAA RenderBuffers have been defined in OpenGL ES 3.0, // but MSAA Textures - only in OpenGL ES 3.1+ ::glGetIntegerv (GL_MAX_SAMPLES, &myMaxMsaaSamples); } hasUintIndex = IsGlGreaterEqual (3, 0) || CheckExtension ("GL_OES_element_index_uint"); hasHighp = CheckExtension ("GL_OES_fragment_precision_high"); GLint aRange[2] = {0, 0}; GLint aPrec = 0; ::glGetShaderPrecisionFormat (GL_FRAGMENT_SHADER, GL_HIGH_FLOAT, aRange, &aPrec); if (aPrec != 0) { hasHighp = Standard_True; } arbTexFloat = IsGlGreaterEqual (3, 0) && FindProcShort (glTexImage3D); hasTexFloatLinear = arbTexFloat && CheckExtension ("GL_OES_texture_float_linear"); const Standard_Boolean hasTexBuffer32 = IsGlGreaterEqual (3, 2) && FindProcShort (glTexBuffer); const Standard_Boolean hasExtTexBuffer = CheckExtension ("GL_EXT_texture_buffer") && FindProc ("glTexBufferEXT", myFuncs->glTexBuffer); if (hasTexBuffer32 || hasExtTexBuffer) { arbTBO = reinterpret_cast (myFuncs.get()); } // initialize debug context extension if (CheckExtension ("GL_KHR_debug")) { // this functionality become a part of OpenGL ES 3.2 arbDbg = NULL; // According to GL_KHR_debug spec, all functions should have KHR suffix. // However, some implementations can export these functions without suffix. if (FindProc ("glDebugMessageControlKHR", myFuncs->glDebugMessageControl) && FindProc ("glDebugMessageInsertKHR", myFuncs->glDebugMessageInsert) && FindProc ("glDebugMessageCallbackKHR", myFuncs->glDebugMessageCallback) && FindProc ("glGetDebugMessageLogKHR", myFuncs->glGetDebugMessageLog)) { arbDbg = (OpenGl_ArbDbg* )(&(*myFuncs)); } if (arbDbg != NULL && caps->contextDebug) { // setup default callback myIsGlDebugCtx = Standard_True; arbDbg->glDebugMessageCallback (debugCallbackWrap, this); ::glEnable (GL_DEBUG_OUTPUT); if (caps->contextSyncDebug) { // note that some broken implementations (e.g. simulators) might generate error message on this call ::glEnable (GL_DEBUG_OUTPUT_SYNCHRONOUS); } } } extDrawBuffers = CheckExtension ("GL_EXT_draw_buffers") && FindProc ("glDrawBuffersEXT", myFuncs->glDrawBuffers); arbDrawBuffers = CheckExtension ("GL_ARB_draw_buffers") && FindProc ("glDrawBuffersARB", myFuncs->glDrawBuffers); if (IsGlGreaterEqual (3, 0) && FindProcShort (glDrawBuffers)) { hasDrawBuffers = OpenGl_FeatureInCore; } else if (extDrawBuffers || arbDrawBuffers) { hasDrawBuffers = OpenGl_FeatureInExtensions; } hasFloatBuffer = IsGlGreaterEqual (3, 2) ? OpenGl_FeatureInCore : CheckExtension ("GL_EXT_color_buffer_float") ? OpenGl_FeatureInExtensions : OpenGl_FeatureNotAvailable; hasHalfFloatBuffer = IsGlGreaterEqual (3, 2) ? OpenGl_FeatureInCore : CheckExtension ("GL_EXT_color_buffer_half_float") ? OpenGl_FeatureInExtensions : OpenGl_FeatureNotAvailable; oesSampleVariables = CheckExtension ("GL_OES_sample_variables"); oesStdDerivatives = CheckExtension ("GL_OES_standard_derivatives"); hasSampleVariables = IsGlGreaterEqual (3, 2) ? OpenGl_FeatureInCore : oesSampleVariables ? OpenGl_FeatureInExtensions : OpenGl_FeatureNotAvailable; hasGlslBitwiseOps = IsGlGreaterEqual (3, 0) ? OpenGl_FeatureInCore : OpenGl_FeatureNotAvailable; // without hasHighp, dFdx/dFdy precision is considered too low for flat shading (visual artifacts) hasFlatShading = IsGlGreaterEqual (3, 0) ? OpenGl_FeatureInCore : (oesStdDerivatives && hasHighp ? OpenGl_FeatureInExtensions : OpenGl_FeatureNotAvailable); if (!IsGlGreaterEqual (3, 1) && myVendor.Search("qualcomm") != -1) { // dFdx/dFdy are completely broken on tested Adreno devices with versions below OpenGl ES 3.1 hasFlatShading = OpenGl_FeatureNotAvailable; } hasGeometryStage = IsGlGreaterEqual (3, 2) ? OpenGl_FeatureInCore : (CheckExtension ("GL_EXT_geometry_shader") && CheckExtension ("GL_EXT_shader_io_blocks") ? OpenGl_FeatureInExtensions : OpenGl_FeatureNotAvailable); #else myTexClamp = IsGlGreaterEqual (1, 2) ? GL_CLAMP_TO_EDGE : GL_CLAMP; hasTexRGBA8 = Standard_True; hasTexSRGB = IsGlGreaterEqual (2, 0); hasFboSRGB = IsGlGreaterEqual (2, 1); hasSRGBControl = hasFboSRGB; arbDrawBuffers = CheckExtension ("GL_ARB_draw_buffers"); arbNPTW = CheckExtension ("GL_ARB_texture_non_power_of_two"); arbTexFloat = IsGlGreaterEqual (3, 0) || CheckExtension ("GL_ARB_texture_float"); hasTexFloatLinear = arbTexFloat; arbSampleShading = CheckExtension ("GL_ARB_sample_shading"); extBgra = CheckExtension ("GL_EXT_bgra"); extAnis = CheckExtension ("GL_EXT_texture_filter_anisotropic"); extPDS = CheckExtension ("GL_EXT_packed_depth_stencil"); atiMem = CheckExtension ("GL_ATI_meminfo"); nvxMem = CheckExtension ("GL_NVX_gpu_memory_info"); hasDrawBuffers = IsGlGreaterEqual (2, 0) ? OpenGl_FeatureInCore : arbDrawBuffers ? OpenGl_FeatureInExtensions : OpenGl_FeatureNotAvailable; hasGlslBitwiseOps = IsGlGreaterEqual (3, 0) ? OpenGl_FeatureInCore : CheckExtension ("GL_EXT_gpu_shader4") ? OpenGl_FeatureInExtensions : OpenGl_FeatureNotAvailable; hasFloatBuffer = hasHalfFloatBuffer = IsGlGreaterEqual (3, 0) ? OpenGl_FeatureInCore : CheckExtension ("GL_ARB_color_buffer_float") ? OpenGl_FeatureInExtensions : OpenGl_FeatureNotAvailable; hasGeometryStage = IsGlGreaterEqual (3, 2) ? OpenGl_FeatureInCore : OpenGl_FeatureNotAvailable; hasSampleVariables = IsGlGreaterEqual (4, 0) ? OpenGl_FeatureInCore : arbSampleShading ? OpenGl_FeatureInExtensions : OpenGl_FeatureNotAvailable; GLint aStereo = GL_FALSE; glGetIntegerv (GL_STEREO, &aStereo); myIsStereoBuffers = aStereo == 1; // get number of maximum clipping planes glGetIntegerv (GL_MAX_CLIP_PLANES, &myMaxClipPlanes); #endif if (hasDrawBuffers) { glGetIntegerv (GL_MAX_DRAW_BUFFERS, &myMaxDrawBuffers); glGetIntegerv (GL_MAX_COLOR_ATTACHMENTS, &myMaxColorAttachments); if (myDrawBuffers.Length() < myMaxDrawBuffers) { myDrawBuffers.Resize (0, myMaxDrawBuffers - 1, false); } } glGetIntegerv (GL_MAX_TEXTURE_SIZE, &myMaxTexDim); #if !defined(GL_ES_VERSION_2_0) if (IsGlGreaterEqual (1, 3) && core11 != NULL) { // this is a maximum of texture units for FFP functionality, // usually smaller than combined texture units available for GLSL glGetIntegerv (GL_MAX_TEXTURE_UNITS, &myMaxTexUnitsFFP); myMaxTexCombined = myMaxTexUnitsFFP; } #endif if (IsGlGreaterEqual (2, 0)) { glGetIntegerv (GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &myMaxTexCombined); } mySpriteTexUnit = myMaxTexCombined >= 2 ? Graphic3d_TextureUnit_PointSprite : Graphic3d_TextureUnit_0; GLint aMaxVPortSize[2] = {0, 0}; glGetIntegerv (GL_MAX_VIEWPORT_DIMS, aMaxVPortSize); myMaxDumpSizeX = Min (aMaxVPortSize[0], myMaxTexDim); myMaxDumpSizeY = Min (aMaxVPortSize[1], myMaxTexDim); if (myVendor == "intel") { // Intel drivers have known bug with empty dump for images with width>=5462 myMaxDumpSizeX = Min (myMaxDumpSizeX, 4096); } if (extAnis) { glGetIntegerv (GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &myAnisoMax); } myClippingState.Init(); #if !defined(GL_ES_VERSION_2_0) bool has12 = false; bool has13 = false; bool has14 = false; bool has15 = false; bool has20 = false; bool has21 = false; bool has30 = false; bool has31 = false; bool has32 = false; bool has33 = false; bool has40 = false; bool has41 = false; bool has42 = false; bool has43 = false; bool has44 = false; bool has45 = false; // retrieve platform-dependent extensions #if defined(HAVE_EGL) // #elif defined(_WIN32) if (FindProcShort (wglGetExtensionsStringARB)) { const char* aWglExts = myFuncs->wglGetExtensionsStringARB (wglGetCurrentDC()); if (CheckExtension (aWglExts, "WGL_EXT_swap_control")) { FindProcShort (wglSwapIntervalEXT); } if (CheckExtension (aWglExts, "WGL_ARB_pixel_format")) { FindProcShort (wglChoosePixelFormatARB); } if (CheckExtension (aWglExts, "WGL_ARB_create_context_profile")) { FindProcShort (wglCreateContextAttribsARB); } if (CheckExtension (aWglExts, "WGL_NV_DX_interop")) { FindProcShort (wglDXSetResourceShareHandleNV); FindProcShort (wglDXOpenDeviceNV); FindProcShort (wglDXCloseDeviceNV); FindProcShort (wglDXRegisterObjectNV); FindProcShort (wglDXUnregisterObjectNV); FindProcShort (wglDXObjectAccessNV); FindProcShort (wglDXLockObjectsNV); FindProcShort (wglDXUnlockObjectsNV); } if (CheckExtension (aWglExts, "WGL_AMD_gpu_association")) { FindProcShort (wglGetGPUIDsAMD); FindProcShort (wglGetGPUInfoAMD); FindProcShort (wglGetContextGPUIDAMD); } } #elif defined(__APPLE__) // #else const char* aGlxExts = ::glXQueryExtensionsString ((Display* )myDisplay, DefaultScreen ((Display* )myDisplay)); if (CheckExtension (aGlxExts, "GLX_EXT_swap_control")) { FindProcShort (glXSwapIntervalEXT); } if (CheckExtension (aGlxExts, "GLX_SGI_swap_control")) { FindProcShort (glXSwapIntervalSGI); } if (CheckExtension (aGlxExts, "GLX_MESA_query_renderer")) { FindProcShort (glXQueryRendererIntegerMESA); FindProcShort (glXQueryCurrentRendererIntegerMESA); FindProcShort (glXQueryRendererStringMESA); FindProcShort (glXQueryCurrentRendererStringMESA); } //extSwapTear = CheckExtension (aGlxExts, "GLX_EXT_swap_control_tear"); #endif // load OpenGL 1.2 new functions has12 = IsGlGreaterEqual (1, 2) && FindProcShort (glBlendColor) && FindProcShort (glBlendEquation) && FindProcShort (glDrawRangeElements) && FindProcShort (glTexImage3D) && FindProcShort (glTexSubImage3D) && FindProcShort (glCopyTexSubImage3D); if (!has12) { checkWrongVersion (1, 2, aLastFailedProc); } // load OpenGL 1.3 new functions has13 = IsGlGreaterEqual (1, 3) && FindProcShort (glActiveTexture) && FindProcShort (glSampleCoverage) && FindProcShort (glCompressedTexImage3D) && FindProcShort (glCompressedTexImage2D) && FindProcShort (glCompressedTexImage1D) && FindProcShort (glCompressedTexSubImage3D) && FindProcShort (glCompressedTexSubImage2D) && FindProcShort (glCompressedTexSubImage1D) && FindProcShort (glGetCompressedTexImage); if (!isCoreProfile) { has13 = has13 && FindProcShort (glClientActiveTexture) && FindProcShort (glMultiTexCoord1d) && FindProcShort (glMultiTexCoord1dv) && FindProcShort (glMultiTexCoord1f) && FindProcShort (glMultiTexCoord1fv) && FindProcShort (glMultiTexCoord1i) && FindProcShort (glMultiTexCoord1iv) && FindProcShort (glMultiTexCoord1s) && FindProcShort (glMultiTexCoord1sv) && FindProcShort (glMultiTexCoord2d) && FindProcShort (glMultiTexCoord2dv) && FindProcShort (glMultiTexCoord2f) && FindProcShort (glMultiTexCoord2fv) && FindProcShort (glMultiTexCoord2i) && FindProcShort (glMultiTexCoord2iv) && FindProcShort (glMultiTexCoord2s) && FindProcShort (glMultiTexCoord2sv) && FindProcShort (glMultiTexCoord3d) && FindProcShort (glMultiTexCoord3dv) && FindProcShort (glMultiTexCoord3f) && FindProcShort (glMultiTexCoord3fv) && FindProcShort (glMultiTexCoord3i) && FindProcShort (glMultiTexCoord3iv) && FindProcShort (glMultiTexCoord3s) && FindProcShort (glMultiTexCoord3sv) && FindProcShort (glMultiTexCoord4d) && FindProcShort (glMultiTexCoord4dv) && FindProcShort (glMultiTexCoord4f) && FindProcShort (glMultiTexCoord4fv) && FindProcShort (glMultiTexCoord4i) && FindProcShort (glMultiTexCoord4iv) && FindProcShort (glMultiTexCoord4s) && FindProcShort (glMultiTexCoord4sv) && FindProcShort (glLoadTransposeMatrixf) && FindProcShort (glLoadTransposeMatrixd) && FindProcShort (glMultTransposeMatrixf) && FindProcShort (glMultTransposeMatrixd); } if (!has13) { checkWrongVersion (1, 3, aLastFailedProc); } // load OpenGL 1.4 new functions has14 = IsGlGreaterEqual (1, 4) && FindProcShort (glBlendFuncSeparate) && FindProcShort (glMultiDrawArrays) && FindProcShort (glMultiDrawElements) && FindProcShort (glPointParameterf) && FindProcShort (glPointParameterfv) && FindProcShort (glPointParameteri) && FindProcShort (glPointParameteriv); if (!has14) { checkWrongVersion (1, 4, aLastFailedProc); } // load OpenGL 1.5 new functions has15 = IsGlGreaterEqual (1, 5) && FindProcShort (glGenQueries) && FindProcShort (glDeleteQueries) && FindProcShort (glIsQuery) && FindProcShort (glBeginQuery) && FindProcShort (glEndQuery) && FindProcShort (glGetQueryiv) && FindProcShort (glGetQueryObjectiv) && FindProcShort (glGetQueryObjectuiv) && FindProcShort (glBindBuffer) && FindProcShort (glDeleteBuffers) && FindProcShort (glGenBuffers) && FindProcShort (glIsBuffer) && FindProcShort (glBufferData) && FindProcShort (glBufferSubData) && FindProcShort (glGetBufferSubData) && FindProcShort (glMapBuffer) && FindProcShort (glUnmapBuffer) && FindProcShort (glGetBufferParameteriv) && FindProcShort (glGetBufferPointerv); if (has15) { if (!isCoreProfile) { core15 = (OpenGl_GlCore15* )(&(*myFuncs)); } core15fwd = (OpenGl_GlCore15Fwd* )(&(*myFuncs)); } else { checkWrongVersion (1, 5, aLastFailedProc); } // load OpenGL 2.0 new functions has20 = IsGlGreaterEqual (2, 0) && FindProcShort (glBlendEquationSeparate) && FindProcShort (glDrawBuffers) && FindProcShort (glStencilOpSeparate) && FindProcShort (glStencilFuncSeparate) && FindProcShort (glStencilMaskSeparate) && FindProcShort (glAttachShader) && FindProcShort (glBindAttribLocation) && FindProcShort (glCompileShader) && FindProcShort (glCreateProgram) && FindProcShort (glCreateShader) && FindProcShort (glDeleteProgram) && FindProcShort (glDeleteShader) && FindProcShort (glDetachShader) && FindProcShort (glDisableVertexAttribArray) && FindProcShort (glEnableVertexAttribArray) && FindProcShort (glGetActiveAttrib) && FindProcShort (glGetActiveUniform) && FindProcShort (glGetAttachedShaders) && FindProcShort (glGetAttribLocation) && FindProcShort (glGetProgramiv) && FindProcShort (glGetProgramInfoLog) && FindProcShort (glGetShaderiv) && FindProcShort (glGetShaderInfoLog) && FindProcShort (glGetShaderSource) && FindProcShort (glGetUniformLocation) && FindProcShort (glGetUniformfv) && FindProcShort (glGetUniformiv) && FindProcShort (glGetVertexAttribdv) && FindProcShort (glGetVertexAttribfv) && FindProcShort (glGetVertexAttribiv) && FindProcShort (glGetVertexAttribPointerv) && FindProcShort (glIsProgram) && FindProcShort (glIsShader) && FindProcShort (glLinkProgram) && FindProcShort (glShaderSource) && FindProcShort (glUseProgram) && FindProcShort (glUniform1f) && FindProcShort (glUniform2f) && FindProcShort (glUniform3f) && FindProcShort (glUniform4f) && FindProcShort (glUniform1i) && FindProcShort (glUniform2i) && FindProcShort (glUniform3i) && FindProcShort (glUniform4i) && FindProcShort (glUniform1fv) && FindProcShort (glUniform2fv) && FindProcShort (glUniform3fv) && FindProcShort (glUniform4fv) && FindProcShort (glUniform1iv) && FindProcShort (glUniform2iv) && FindProcShort (glUniform3iv) && FindProcShort (glUniform4iv) && FindProcShort (glUniformMatrix2fv) && FindProcShort (glUniformMatrix3fv) && FindProcShort (glUniformMatrix4fv) && FindProcShort (glValidateProgram) && FindProcShort (glVertexAttrib1d) && FindProcShort (glVertexAttrib1dv) && FindProcShort (glVertexAttrib1f) && FindProcShort (glVertexAttrib1fv) && FindProcShort (glVertexAttrib1s) && FindProcShort (glVertexAttrib1sv) && FindProcShort (glVertexAttrib2d) && FindProcShort (glVertexAttrib2dv) && FindProcShort (glVertexAttrib2f) && FindProcShort (glVertexAttrib2fv) && FindProcShort (glVertexAttrib2s) && FindProcShort (glVertexAttrib2sv) && FindProcShort (glVertexAttrib3d) && FindProcShort (glVertexAttrib3dv) && FindProcShort (glVertexAttrib3f) && FindProcShort (glVertexAttrib3fv) && FindProcShort (glVertexAttrib3s) && FindProcShort (glVertexAttrib3sv) && FindProcShort (glVertexAttrib4Nbv) && FindProcShort (glVertexAttrib4Niv) && FindProcShort (glVertexAttrib4Nsv) && FindProcShort (glVertexAttrib4Nub) && FindProcShort (glVertexAttrib4Nubv) && FindProcShort (glVertexAttrib4Nuiv) && FindProcShort (glVertexAttrib4Nusv) && FindProcShort (glVertexAttrib4bv) && FindProcShort (glVertexAttrib4d) && FindProcShort (glVertexAttrib4dv) && FindProcShort (glVertexAttrib4f) && FindProcShort (glVertexAttrib4fv) && FindProcShort (glVertexAttrib4iv) && FindProcShort (glVertexAttrib4s) && FindProcShort (glVertexAttrib4sv) && FindProcShort (glVertexAttrib4ubv) && FindProcShort (glVertexAttrib4uiv) && FindProcShort (glVertexAttrib4usv) && FindProcShort (glVertexAttribPointer); if (has20) { const char* aGlslVer = (const char* )::glGetString (GL_SHADING_LANGUAGE_VERSION); if (aGlslVer == NULL || *aGlslVer == '\0') { // broken context has been detected PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, TCollection_AsciiString("Error! OpenGL context reports version ") + myGlVerMajor + "." + myGlVerMinor + " but reports wrong GLSL version"); myGlVerMajor = 1; myGlVerMinor = 5; } else { if (!isCoreProfile) { core20 = (OpenGl_GlCore20* )(&(*myFuncs)); } core20fwd = (OpenGl_GlCore20Fwd* )(&(*myFuncs)); } } else { checkWrongVersion (2, 0, aLastFailedProc); } // load OpenGL 2.1 new functions has21 = IsGlGreaterEqual (2, 1) && FindProcShort (glUniformMatrix2x3fv) && FindProcShort (glUniformMatrix3x2fv) && FindProcShort (glUniformMatrix2x4fv) && FindProcShort (glUniformMatrix4x2fv) && FindProcShort (glUniformMatrix3x4fv) && FindProcShort (glUniformMatrix4x3fv); if (!has21) { checkWrongVersion (2, 1, aLastFailedProc); } // load GL_ARB_framebuffer_object (added to OpenGL 3.0 core) const bool hasFBO = (IsGlGreaterEqual (3, 0) || CheckExtension ("GL_ARB_framebuffer_object")) && FindProcShort (glIsRenderbuffer) && FindProcShort (glBindRenderbuffer) && FindProcShort (glDeleteRenderbuffers) && FindProcShort (glGenRenderbuffers) && FindProcShort (glRenderbufferStorage) && FindProcShort (glGetRenderbufferParameteriv) && FindProcShort (glIsFramebuffer) && FindProcShort (glBindFramebuffer) && FindProcShort (glDeleteFramebuffers) && FindProcShort (glGenFramebuffers) && FindProcShort (glCheckFramebufferStatus) && FindProcShort (glFramebufferTexture1D) && FindProcShort (glFramebufferTexture2D) && FindProcShort (glFramebufferTexture3D) && FindProcShort (glFramebufferRenderbuffer) && FindProcShort (glGetFramebufferAttachmentParameteriv) && FindProcShort (glGenerateMipmap) && FindProcShort (glBlitFramebuffer) && FindProcShort (glRenderbufferStorageMultisample) && FindProcShort (glFramebufferTextureLayer); // load GL_ARB_vertex_array_object (added to OpenGL 3.0 core) const bool hasVAO = (IsGlGreaterEqual (3, 0) || CheckExtension ("GL_ARB_vertex_array_object")) && FindProcShort (glBindVertexArray) && FindProcShort (glDeleteVertexArrays) && FindProcShort (glGenVertexArrays) && FindProcShort (glIsVertexArray); // load GL_ARB_map_buffer_range (added to OpenGL 3.0 core) const bool hasMapBufferRange = (IsGlGreaterEqual (3, 0) || CheckExtension ("GL_ARB_map_buffer_range")) && FindProcShort (glMapBufferRange) && FindProcShort (glFlushMappedBufferRange); // load OpenGL 3.0 new functions has30 = IsGlGreaterEqual (3, 0) && hasFBO && hasVAO && hasMapBufferRange && FindProcShort (glColorMaski) && FindProcShort (glGetBooleani_v) && FindProcShort (glGetIntegeri_v) && FindProcShort (glEnablei) && FindProcShort (glDisablei) && FindProcShort (glIsEnabledi) && FindProcShort (glBeginTransformFeedback) && FindProcShort (glEndTransformFeedback) && FindProcShort (glBindBufferRange) && FindProcShort (glBindBufferBase) && FindProcShort (glTransformFeedbackVaryings) && FindProcShort (glGetTransformFeedbackVarying) && FindProcShort (glClampColor) && FindProcShort (glBeginConditionalRender) && FindProcShort (glEndConditionalRender) && FindProcShort (glVertexAttribIPointer) && FindProcShort (glGetVertexAttribIiv) && FindProcShort (glGetVertexAttribIuiv) && FindProcShort (glVertexAttribI1i) && FindProcShort (glVertexAttribI2i) && FindProcShort (glVertexAttribI3i) && FindProcShort (glVertexAttribI4i) && FindProcShort (glVertexAttribI1ui) && FindProcShort (glVertexAttribI2ui) && FindProcShort (glVertexAttribI3ui) && FindProcShort (glVertexAttribI4ui) && FindProcShort (glVertexAttribI1iv) && FindProcShort (glVertexAttribI2iv) && FindProcShort (glVertexAttribI3iv) && FindProcShort (glVertexAttribI4iv) && FindProcShort (glVertexAttribI1uiv) && FindProcShort (glVertexAttribI2uiv) && FindProcShort (glVertexAttribI3uiv) && FindProcShort (glVertexAttribI4uiv) && FindProcShort (glVertexAttribI4bv) && FindProcShort (glVertexAttribI4sv) && FindProcShort (glVertexAttribI4ubv) && FindProcShort (glVertexAttribI4usv) && FindProcShort (glGetUniformuiv) && FindProcShort (glBindFragDataLocation) && FindProcShort (glGetFragDataLocation) && FindProcShort (glUniform1ui) && FindProcShort (glUniform2ui) && FindProcShort (glUniform3ui) && FindProcShort (glUniform4ui) && FindProcShort (glUniform1uiv) && FindProcShort (glUniform2uiv) && FindProcShort (glUniform3uiv) && FindProcShort (glUniform4uiv) && FindProcShort (glTexParameterIiv) && FindProcShort (glTexParameterIuiv) && FindProcShort (glGetTexParameterIiv) && FindProcShort (glGetTexParameterIuiv) && FindProcShort (glClearBufferiv) && FindProcShort (glClearBufferuiv) && FindProcShort (glClearBufferfv) && FindProcShort (glClearBufferfi) && FindProcShort (glGetStringi); if (!has30) { checkWrongVersion (3, 0, aLastFailedProc); } // load GL_ARB_uniform_buffer_object (added to OpenGL 3.1 core) const bool hasUBO = (IsGlGreaterEqual (3, 1) || CheckExtension ("GL_ARB_uniform_buffer_object")) && FindProcShort (glGetUniformIndices) && FindProcShort (glGetActiveUniformsiv) && FindProcShort (glGetActiveUniformName) && FindProcShort (glGetUniformBlockIndex) && FindProcShort (glGetActiveUniformBlockiv) && FindProcShort (glGetActiveUniformBlockName) && FindProcShort (glUniformBlockBinding); // load GL_ARB_copy_buffer (added to OpenGL 3.1 core) const bool hasCopyBufSubData = (IsGlGreaterEqual (3, 1) || CheckExtension ("GL_ARB_copy_buffer")) && FindProcShort (glCopyBufferSubData); if (has30) { // NPOT textures are required by OpenGL 2.0 specifications // but doesn't hardware accelerated by some ancient OpenGL 2.1 hardware (GeForce FX, RadeOn 9700 etc.) arbNPTW = Standard_True; arbTexRG = Standard_True; } // load OpenGL 3.1 new functions has31 = IsGlGreaterEqual (3, 1) && hasUBO && hasCopyBufSubData && FindProcShort (glDrawArraysInstanced) && FindProcShort (glDrawElementsInstanced) && FindProcShort (glTexBuffer) && FindProcShort (glPrimitiveRestartIndex); if (has31) { arbTBO = (OpenGl_ArbTBO* )(&(*myFuncs)); arbIns = (OpenGl_ArbIns* )(&(*myFuncs)); } else { checkWrongVersion (3, 1, aLastFailedProc); // initialize TBO extension (ARB) if (CheckExtension ("GL_ARB_texture_buffer_object") && FindProc ("glTexBufferARB", myFuncs->glTexBuffer)) { arbTBO = (OpenGl_ArbTBO* )(&(*myFuncs)); } // initialize hardware instancing extension (ARB) if (CheckExtension ("GL_ARB_draw_instanced") && FindProc ("glDrawArraysInstancedARB", myFuncs->glDrawArraysInstanced) && FindProc ("glDrawElementsInstancedARB", myFuncs->glDrawElementsInstanced)) { arbIns = (OpenGl_ArbIns* )(&(*myFuncs)); } } arbTboRGB32 = CheckExtension ("GL_ARB_texture_buffer_object_rgb32"); // load GL_ARB_draw_elements_base_vertex (added to OpenGL 3.2 core) const bool hasDrawElemsBaseVert = (IsGlGreaterEqual (3, 2) || CheckExtension ("GL_ARB_draw_elements_base_vertex")) && FindProcShort (glDrawElementsBaseVertex) && FindProcShort (glDrawRangeElementsBaseVertex) && FindProcShort (glDrawElementsInstancedBaseVertex) && FindProcShort (glMultiDrawElementsBaseVertex); // load GL_ARB_provoking_vertex (added to OpenGL 3.2 core) const bool hasProvokingVert = (IsGlGreaterEqual (3, 2) || CheckExtension ("GL_ARB_provoking_vertex")) && FindProcShort (glProvokingVertex); // load GL_ARB_sync (added to OpenGL 3.2 core) const bool hasSync = (IsGlGreaterEqual (3, 2) || CheckExtension ("GL_ARB_sync")) && FindProcShort (glFenceSync) && FindProcShort (glIsSync) && FindProcShort (glDeleteSync) && FindProcShort (glClientWaitSync) && FindProcShort (glWaitSync) && FindProcShort (glGetInteger64v) && FindProcShort (glGetSynciv); // load GL_ARB_texture_multisample (added to OpenGL 3.2 core) const bool hasTextureMultisample = (IsGlGreaterEqual (3, 2) || CheckExtension ("GL_ARB_texture_multisample")) && FindProcShort (glTexImage2DMultisample) && FindProcShort (glTexImage3DMultisample) && FindProcShort (glGetMultisamplefv) && FindProcShort (glSampleMaski); // load OpenGL 3.2 new functions has32 = IsGlGreaterEqual (3, 2) && hasDrawElemsBaseVert && hasProvokingVert && hasSync && hasTextureMultisample && FindProcShort (glGetInteger64i_v) && FindProcShort (glGetBufferParameteri64v) && FindProcShort (glFramebufferTexture); if (has32) { core32 = (OpenGl_GlCore32* )(&(*myFuncs)); if (isCoreProfile) { core32->glGenVertexArrays (1, &myDefaultVao); } else { core32back = (OpenGl_GlCore32Back* )(&(*myFuncs)); } ::glGetIntegerv (GL_MAX_SAMPLES, &myMaxMsaaSamples); } else { checkWrongVersion (3, 2, aLastFailedProc); } // load GL_ARB_blend_func_extended (added to OpenGL 3.3 core) const bool hasBlendFuncExtended = (IsGlGreaterEqual (3, 3) || CheckExtension ("GL_ARB_blend_func_extended")) && FindProcShort (glBindFragDataLocationIndexed) && FindProcShort (glGetFragDataIndex); // load GL_ARB_sampler_objects (added to OpenGL 3.3 core) const bool hasSamplerObjects = (IsGlGreaterEqual (3, 3) || CheckExtension ("GL_ARB_sampler_objects")) && FindProcShort (glGenSamplers) && FindProcShort (glDeleteSamplers) && FindProcShort (glIsSampler) && FindProcShort (glBindSampler) && FindProcShort (glSamplerParameteri) && FindProcShort (glSamplerParameteriv) && FindProcShort (glSamplerParameterf) && FindProcShort (glSamplerParameterfv) && FindProcShort (glSamplerParameterIiv) && FindProcShort (glSamplerParameterIuiv) && FindProcShort (glGetSamplerParameteriv) && FindProcShort (glGetSamplerParameterIiv) && FindProcShort (glGetSamplerParameterfv) && FindProcShort (glGetSamplerParameterIuiv); if (hasSamplerObjects) { arbSamplerObject = (OpenGl_ArbSamplerObject* )(&(*myFuncs)); } // load GL_ARB_timer_query (added to OpenGL 3.3 core) const bool hasTimerQuery = (IsGlGreaterEqual (3, 3) || CheckExtension ("GL_ARB_timer_query")) && FindProcShort (glQueryCounter) && FindProcShort (glGetQueryObjecti64v) && FindProcShort (glGetQueryObjectui64v); // load GL_ARB_vertex_type_2_10_10_10_rev (added to OpenGL 3.3 core) const bool hasVertType21010101rev = (IsGlGreaterEqual (3, 3) || CheckExtension ("GL_ARB_vertex_type_2_10_10_10_rev")) && FindProcShort (glVertexAttribP1ui) && FindProcShort (glVertexAttribP1uiv) && FindProcShort (glVertexAttribP2ui) && FindProcShort (glVertexAttribP2uiv) && FindProcShort (glVertexAttribP3ui) && FindProcShort (glVertexAttribP3uiv) && FindProcShort (glVertexAttribP4ui) && FindProcShort (glVertexAttribP4uiv); if ( hasVertType21010101rev && !isCoreProfile) { // load deprecated functions const bool hasVertType21010101revExt = FindProcShort (glVertexP2ui) && FindProcShort (glVertexP2uiv) && FindProcShort (glVertexP3ui) && FindProcShort (glVertexP3uiv) && FindProcShort (glVertexP4ui) && FindProcShort (glVertexP4uiv) && FindProcShort (glTexCoordP1ui) && FindProcShort (glTexCoordP1uiv) && FindProcShort (glTexCoordP2ui) && FindProcShort (glTexCoordP2uiv) && FindProcShort (glTexCoordP3ui) && FindProcShort (glTexCoordP3uiv) && FindProcShort (glTexCoordP4ui) && FindProcShort (glTexCoordP4uiv) && FindProcShort (glMultiTexCoordP1ui) && FindProcShort (glMultiTexCoordP1uiv) && FindProcShort (glMultiTexCoordP2ui) && FindProcShort (glMultiTexCoordP2uiv) && FindProcShort (glMultiTexCoordP3ui) && FindProcShort (glMultiTexCoordP3uiv) && FindProcShort (glMultiTexCoordP4ui) && FindProcShort (glMultiTexCoordP4uiv) && FindProcShort (glNormalP3ui) && FindProcShort (glNormalP3uiv) && FindProcShort (glColorP3ui) && FindProcShort (glColorP3uiv) && FindProcShort (glColorP4ui) && FindProcShort (glColorP4uiv) && FindProcShort (glSecondaryColorP3ui) && FindProcShort (glSecondaryColorP3uiv); (void )hasVertType21010101revExt; } // load OpenGL 3.3 extra functions has33 = IsGlGreaterEqual (3, 3) && hasBlendFuncExtended && hasSamplerObjects && hasTimerQuery && hasVertType21010101rev && FindProcShort (glVertexAttribDivisor); if (has33) { core33 = (OpenGl_GlCore33* )(&(*myFuncs)); if (!isCoreProfile) { core33back = (OpenGl_GlCore33Back* )(&(*myFuncs)); } } else { checkWrongVersion (3, 3, aLastFailedProc); } // load GL_ARB_draw_indirect (added to OpenGL 4.0 core) const bool hasDrawIndirect = (IsGlGreaterEqual (4, 0) || CheckExtension ("GL_ARB_draw_indirect")) && FindProcShort (glDrawArraysIndirect) && FindProcShort (glDrawElementsIndirect); // load GL_ARB_gpu_shader_fp64 (added to OpenGL 4.0 core) const bool hasShaderFP64 = (IsGlGreaterEqual (4, 0) || CheckExtension ("GL_ARB_gpu_shader_fp64")) && FindProcShort (glUniform1d) && FindProcShort (glUniform2d) && FindProcShort (glUniform3d) && FindProcShort (glUniform4d) && FindProcShort (glUniform1dv) && FindProcShort (glUniform2dv) && FindProcShort (glUniform3dv) && FindProcShort (glUniform4dv) && FindProcShort (glUniformMatrix2dv) && FindProcShort (glUniformMatrix3dv) && FindProcShort (glUniformMatrix4dv) && FindProcShort (glUniformMatrix2x3dv) && FindProcShort (glUniformMatrix2x4dv) && FindProcShort (glUniformMatrix3x2dv) && FindProcShort (glUniformMatrix3x4dv) && FindProcShort (glUniformMatrix4x2dv) && FindProcShort (glUniformMatrix4x3dv) && FindProcShort (glGetUniformdv); // load GL_ARB_shader_subroutine (added to OpenGL 4.0 core) const bool hasShaderSubroutine = (IsGlGreaterEqual (4, 0) || CheckExtension ("GL_ARB_shader_subroutine")) && FindProcShort (glGetSubroutineUniformLocation) && FindProcShort (glGetSubroutineIndex) && FindProcShort (glGetActiveSubroutineUniformiv) && FindProcShort (glGetActiveSubroutineUniformName) && FindProcShort (glGetActiveSubroutineName) && FindProcShort (glUniformSubroutinesuiv) && FindProcShort (glGetUniformSubroutineuiv) && FindProcShort (glGetProgramStageiv); // load GL_ARB_tessellation_shader (added to OpenGL 4.0 core) const bool hasTessellationShader = (IsGlGreaterEqual (4, 0) || CheckExtension ("GL_ARB_tessellation_shader")) && FindProcShort (glPatchParameteri) && FindProcShort (glPatchParameterfv); // load GL_ARB_transform_feedback2 (added to OpenGL 4.0 core) const bool hasTrsfFeedback2 = (IsGlGreaterEqual (4, 0) || CheckExtension ("GL_ARB_transform_feedback2")) && FindProcShort (glBindTransformFeedback) && FindProcShort (glDeleteTransformFeedbacks) && FindProcShort (glGenTransformFeedbacks) && FindProcShort (glIsTransformFeedback) && FindProcShort (glPauseTransformFeedback) && FindProcShort (glResumeTransformFeedback) && FindProcShort (glDrawTransformFeedback); // load GL_ARB_transform_feedback3 (added to OpenGL 4.0 core) const bool hasTrsfFeedback3 = (IsGlGreaterEqual (4, 0) || CheckExtension ("GL_ARB_transform_feedback3")) && FindProcShort (glDrawTransformFeedbackStream) && FindProcShort (glBeginQueryIndexed) && FindProcShort (glEndQueryIndexed) && FindProcShort (glGetQueryIndexediv); // load OpenGL 4.0 new functions has40 = IsGlGreaterEqual (4, 0) && hasDrawIndirect && hasShaderFP64 && hasShaderSubroutine && hasTessellationShader && hasTrsfFeedback2 && hasTrsfFeedback3 && FindProcShort (glMinSampleShading) && FindProcShort (glBlendEquationi) && FindProcShort (glBlendEquationSeparatei) && FindProcShort (glBlendFunci) && FindProcShort (glBlendFuncSeparatei); if (has40) { arbTboRGB32 = Standard_True; // in core since OpenGL 4.0 } else { checkWrongVersion (4, 0, aLastFailedProc); } // load GL_ARB_ES2_compatibility (added to OpenGL 4.1 core) const bool hasES2Compatibility = (IsGlGreaterEqual (4, 1) || CheckExtension ("GL_ARB_ES2_compatibility")) && FindProcShort (glReleaseShaderCompiler) && FindProcShort (glShaderBinary) && FindProcShort (glGetShaderPrecisionFormat) && FindProcShort (glDepthRangef) && FindProcShort (glClearDepthf); // load GL_ARB_get_program_binary (added to OpenGL 4.1 core) const bool hasGetProgramBinary = (IsGlGreaterEqual (4, 1) || CheckExtension ("GL_ARB_get_program_binary")) && FindProcShort (glGetProgramBinary) && FindProcShort (glProgramBinary) && FindProcShort (glProgramParameteri); // load GL_ARB_separate_shader_objects (added to OpenGL 4.1 core) const bool hasSeparateShaderObjects = (IsGlGreaterEqual (4, 1) || CheckExtension ("GL_ARB_separate_shader_objects")) && FindProcShort (glUseProgramStages) && FindProcShort (glActiveShaderProgram) && FindProcShort (glCreateShaderProgramv) && FindProcShort (glBindProgramPipeline) && FindProcShort (glDeleteProgramPipelines) && FindProcShort (glGenProgramPipelines) && FindProcShort (glIsProgramPipeline) && FindProcShort (glGetProgramPipelineiv) && FindProcShort (glProgramUniform1i) && FindProcShort (glProgramUniform1iv) && FindProcShort (glProgramUniform1f) && FindProcShort (glProgramUniform1fv) && FindProcShort (glProgramUniform1d) && FindProcShort (glProgramUniform1dv) && FindProcShort (glProgramUniform1ui) && FindProcShort (glProgramUniform1uiv) && FindProcShort (glProgramUniform2i) && FindProcShort (glProgramUniform2iv) && FindProcShort (glProgramUniform2f) && FindProcShort (glProgramUniform2fv) && FindProcShort (glProgramUniform2d) && FindProcShort (glProgramUniform2dv) && FindProcShort (glProgramUniform2ui) && FindProcShort (glProgramUniform2uiv) && FindProcShort (glProgramUniform3i) && FindProcShort (glProgramUniform3iv) && FindProcShort (glProgramUniform3f) && FindProcShort (glProgramUniform3fv) && FindProcShort (glProgramUniform3d) && FindProcShort (glProgramUniform3dv) && FindProcShort (glProgramUniform3ui) && FindProcShort (glProgramUniform3uiv) && FindProcShort (glProgramUniform4i) && FindProcShort (glProgramUniform4iv) && FindProcShort (glProgramUniform4f) && FindProcShort (glProgramUniform4fv) && FindProcShort (glProgramUniform4d) && FindProcShort (glProgramUniform4dv) && FindProcShort (glProgramUniform4ui) && FindProcShort (glProgramUniform4uiv) && FindProcShort (glProgramUniformMatrix2fv) && FindProcShort (glProgramUniformMatrix3fv) && FindProcShort (glProgramUniformMatrix4fv) && FindProcShort (glProgramUniformMatrix2dv) && FindProcShort (glProgramUniformMatrix3dv) && FindProcShort (glProgramUniformMatrix4dv) && FindProcShort (glProgramUniformMatrix2x3fv) && FindProcShort (glProgramUniformMatrix3x2fv) && FindProcShort (glProgramUniformMatrix2x4fv) && FindProcShort (glProgramUniformMatrix4x2fv) && FindProcShort (glProgramUniformMatrix3x4fv) && FindProcShort (glProgramUniformMatrix4x3fv) && FindProcShort (glProgramUniformMatrix2x3dv) && FindProcShort (glProgramUniformMatrix3x2dv) && FindProcShort (glProgramUniformMatrix2x4dv) && FindProcShort (glProgramUniformMatrix4x2dv) && FindProcShort (glProgramUniformMatrix3x4dv) && FindProcShort (glProgramUniformMatrix4x3dv) && FindProcShort (glValidateProgramPipeline) && FindProcShort (glGetProgramPipelineInfoLog); // load GL_ARB_vertex_attrib_64bit (added to OpenGL 4.1 core) const bool hasVertAttrib64bit = (IsGlGreaterEqual (4, 1) || CheckExtension ("GL_ARB_vertex_attrib_64bit")) && FindProcShort (glVertexAttribL1d) && FindProcShort (glVertexAttribL2d) && FindProcShort (glVertexAttribL3d) && FindProcShort (glVertexAttribL4d) && FindProcShort (glVertexAttribL1dv) && FindProcShort (glVertexAttribL2dv) && FindProcShort (glVertexAttribL3dv) && FindProcShort (glVertexAttribL4dv) && FindProcShort (glVertexAttribLPointer) && FindProcShort (glGetVertexAttribLdv); // load GL_ARB_viewport_array (added to OpenGL 4.1 core) const bool hasViewportArray = (IsGlGreaterEqual (4, 1) || CheckExtension ("GL_ARB_viewport_array")) && FindProcShort (glViewportArrayv) && FindProcShort (glViewportIndexedf) && FindProcShort (glViewportIndexedfv) && FindProcShort (glScissorArrayv) && FindProcShort (glScissorIndexed) && FindProcShort (glScissorIndexedv) && FindProcShort (glDepthRangeArrayv) && FindProcShort (glDepthRangeIndexed) && FindProcShort (glGetFloati_v) && FindProcShort (glGetDoublei_v); has41 = IsGlGreaterEqual (4, 1) && hasES2Compatibility && hasGetProgramBinary && hasSeparateShaderObjects && hasVertAttrib64bit && hasViewportArray; if (has41) { core41 = (OpenGl_GlCore41* )(&(*myFuncs)); if (!isCoreProfile) { core41back = (OpenGl_GlCore41Back* )(&(*myFuncs)); } } else { checkWrongVersion (4, 1, aLastFailedProc); } // load GL_ARB_base_instance (added to OpenGL 4.2 core) const bool hasBaseInstance = (IsGlGreaterEqual (4, 2) || CheckExtension ("GL_ARB_base_instance")) && FindProcShort (glDrawArraysInstancedBaseInstance) && FindProcShort (glDrawElementsInstancedBaseInstance) && FindProcShort (glDrawElementsInstancedBaseVertexBaseInstance); // load GL_ARB_transform_feedback_instanced (added to OpenGL 4.2 core) const bool hasTrsfFeedbackInstanced = (IsGlGreaterEqual (4, 2) || CheckExtension ("GL_ARB_transform_feedback_instanced")) && FindProcShort (glDrawTransformFeedbackInstanced) && FindProcShort (glDrawTransformFeedbackStreamInstanced); // load GL_ARB_internalformat_query (added to OpenGL 4.2 core) const bool hasInternalFormatQuery = (IsGlGreaterEqual (4, 2) || CheckExtension ("GL_ARB_internalformat_query")) && FindProcShort (glGetInternalformativ); // load GL_ARB_shader_atomic_counters (added to OpenGL 4.2 core) const bool hasShaderAtomicCounters = (IsGlGreaterEqual (4, 2) || CheckExtension ("GL_ARB_shader_atomic_counters")) && FindProcShort (glGetActiveAtomicCounterBufferiv); // load GL_ARB_shader_image_load_store (added to OpenGL 4.2 core) const bool hasShaderImgLoadStore = (IsGlGreaterEqual (4, 2) || CheckExtension ("GL_ARB_shader_image_load_store")) && FindProcShort (glBindImageTexture) && FindProcShort (glMemoryBarrier); // load GL_ARB_texture_storage (added to OpenGL 4.2 core) const bool hasTextureStorage = (IsGlGreaterEqual (4, 2) || CheckExtension ("GL_ARB_texture_storage")) && FindProcShort (glTexStorage1D) && FindProcShort (glTexStorage2D) && FindProcShort (glTexStorage3D); has42 = IsGlGreaterEqual (4, 2) && hasBaseInstance && hasTrsfFeedbackInstanced && hasInternalFormatQuery && hasShaderAtomicCounters && hasShaderImgLoadStore && hasTextureStorage; if (has42) { core42 = (OpenGl_GlCore42* )(&(*myFuncs)); if (!isCoreProfile) { core42back = (OpenGl_GlCore42Back* )(&(*myFuncs)); } } else { checkWrongVersion (4, 2, aLastFailedProc); } has43 = IsGlGreaterEqual (4, 3) && FindProcShort (glClearBufferData) && FindProcShort (glClearBufferSubData) && FindProcShort (glDispatchCompute) && FindProcShort (glDispatchComputeIndirect) && FindProcShort (glCopyImageSubData) && FindProcShort (glFramebufferParameteri) && FindProcShort (glGetFramebufferParameteriv) && FindProcShort (glGetInternalformati64v) && FindProcShort (glInvalidateTexSubImage) && FindProcShort (glInvalidateTexImage) && FindProcShort (glInvalidateBufferSubData) && FindProcShort (glInvalidateBufferData) && FindProcShort (glInvalidateFramebuffer) && FindProcShort (glInvalidateSubFramebuffer) && FindProcShort (glMultiDrawArraysIndirect) && FindProcShort (glMultiDrawElementsIndirect) && FindProcShort (glGetProgramInterfaceiv) && FindProcShort (glGetProgramResourceIndex) && FindProcShort (glGetProgramResourceName) && FindProcShort (glGetProgramResourceiv) && FindProcShort (glGetProgramResourceLocation) && FindProcShort (glGetProgramResourceLocationIndex) && FindProcShort (glShaderStorageBlockBinding) && FindProcShort (glTexBufferRange) && FindProcShort (glTexStorage2DMultisample) && FindProcShort (glTexStorage3DMultisample) && FindProcShort (glTextureView) && FindProcShort (glBindVertexBuffer) && FindProcShort (glVertexAttribFormat) && FindProcShort (glVertexAttribIFormat) && FindProcShort (glVertexAttribLFormat) && FindProcShort (glVertexAttribBinding) && FindProcShort (glVertexBindingDivisor) && FindProcShort (glDebugMessageControl) && FindProcShort (glDebugMessageInsert) && FindProcShort (glDebugMessageCallback) && FindProcShort (glGetDebugMessageLog) && FindProcShort (glPushDebugGroup) && FindProcShort (glPopDebugGroup) && FindProcShort (glObjectLabel) && FindProcShort (glGetObjectLabel) && FindProcShort (glObjectPtrLabel) && FindProcShort (glGetObjectPtrLabel); if (has43) { core43 = (OpenGl_GlCore43* )(&(*myFuncs)); if (!isCoreProfile) { core43back = (OpenGl_GlCore43Back* )(&(*myFuncs)); } } else { checkWrongVersion (4, 3, aLastFailedProc); } // load GL_ARB_clear_texture (added to OpenGL 4.4 core) bool arbTexClear = (IsGlGreaterEqual (4, 4) || CheckExtension ("GL_ARB_clear_texture")) && FindProcShort (glClearTexImage) && FindProcShort (glClearTexSubImage); has44 = IsGlGreaterEqual (4, 4) && arbTexClear && FindProcShort (glBufferStorage) && FindProcShort (glBindBuffersBase) && FindProcShort (glBindBuffersRange) && FindProcShort (glBindTextures) && FindProcShort (glBindSamplers) && FindProcShort (glBindImageTextures) && FindProcShort (glBindVertexBuffers); if (has44) { core44 = (OpenGl_GlCore44* )(&(*myFuncs)); if (!isCoreProfile) { core44back = (OpenGl_GlCore44Back* )(&(*myFuncs)); } } else { checkWrongVersion (4, 4, aLastFailedProc); } has45 = IsGlGreaterEqual (4, 5) && FindProcShort (glBindVertexBuffers) && FindProcShort (glClipControl) && FindProcShort (glCreateTransformFeedbacks) && FindProcShort (glTransformFeedbackBufferBase) && FindProcShort (glTransformFeedbackBufferRange) && FindProcShort (glGetTransformFeedbackiv) && FindProcShort (glGetTransformFeedbacki_v) && FindProcShort (glGetTransformFeedbacki64_v) && FindProcShort (glCreateBuffers) && FindProcShort (glNamedBufferStorage) && FindProcShort (glNamedBufferData) && FindProcShort (glNamedBufferSubData) && FindProcShort (glCopyNamedBufferSubData) && FindProcShort (glClearNamedBufferData) && FindProcShort (glClearNamedBufferSubData) && FindProcShort (glMapNamedBuffer) && FindProcShort (glMapNamedBufferRange) && FindProcShort (glUnmapNamedBuffer) && FindProcShort (glFlushMappedNamedBufferRange) && FindProcShort (glGetNamedBufferParameteriv) && FindProcShort (glGetNamedBufferParameteri64v) && FindProcShort (glGetNamedBufferPointerv) && FindProcShort (glGetNamedBufferSubData) && FindProcShort (glCreateFramebuffers) && FindProcShort (glNamedFramebufferRenderbuffer) && FindProcShort (glNamedFramebufferParameteri) && FindProcShort (glNamedFramebufferTexture) && FindProcShort (glNamedFramebufferTextureLayer) && FindProcShort (glNamedFramebufferDrawBuffer) && FindProcShort (glNamedFramebufferDrawBuffers) && FindProcShort (glNamedFramebufferReadBuffer) && FindProcShort (glInvalidateNamedFramebufferData) && FindProcShort (glInvalidateNamedFramebufferSubData) && FindProcShort (glClearNamedFramebufferiv) && FindProcShort (glClearNamedFramebufferuiv) && FindProcShort (glClearNamedFramebufferfv) && FindProcShort (glClearNamedFramebufferfi) && FindProcShort (glBlitNamedFramebuffer) && FindProcShort (glCheckNamedFramebufferStatus) && FindProcShort (glGetNamedFramebufferParameteriv) && FindProcShort (glGetNamedFramebufferAttachmentParameteriv) && FindProcShort (glCreateRenderbuffers) && FindProcShort (glNamedRenderbufferStorage) && FindProcShort (glNamedRenderbufferStorageMultisample) && FindProcShort (glGetNamedRenderbufferParameteriv) && FindProcShort (glCreateTextures) && FindProcShort (glTextureBuffer) && FindProcShort (glTextureBufferRange) && FindProcShort (glTextureStorage1D) && FindProcShort (glTextureStorage2D) && FindProcShort (glTextureStorage3D) && FindProcShort (glTextureStorage2DMultisample) && FindProcShort (glTextureStorage3DMultisample) && FindProcShort (glTextureSubImage1D) && FindProcShort (glTextureSubImage2D) && FindProcShort (glTextureSubImage3D) && FindProcShort (glCompressedTextureSubImage1D) && FindProcShort (glCompressedTextureSubImage2D) && FindProcShort (glCompressedTextureSubImage3D) && FindProcShort (glCopyTextureSubImage1D) && FindProcShort (glCopyTextureSubImage2D) && FindProcShort (glCopyTextureSubImage3D) && FindProcShort (glTextureParameterf) && FindProcShort (glTextureParameterfv) && FindProcShort (glTextureParameteri) && FindProcShort (glTextureParameterIiv) && FindProcShort (glTextureParameterIuiv) && FindProcShort (glTextureParameteriv) && FindProcShort (glGenerateTextureMipmap) && FindProcShort (glBindTextureUnit) && FindProcShort (glGetTextureImage) && FindProcShort (glGetCompressedTextureImage) && FindProcShort (glGetTextureLevelParameterfv) && FindProcShort (glGetTextureLevelParameteriv) && FindProcShort (glGetTextureParameterfv) && FindProcShort (glGetTextureParameterIiv) && FindProcShort (glGetTextureParameterIuiv) && FindProcShort (glGetTextureParameteriv) && FindProcShort (glCreateVertexArrays) && FindProcShort (glDisableVertexArrayAttrib) && FindProcShort (glEnableVertexArrayAttrib) && FindProcShort (glVertexArrayElementBuffer) && FindProcShort (glVertexArrayVertexBuffer) && FindProcShort (glVertexArrayVertexBuffers) && FindProcShort (glVertexArrayAttribBinding) && FindProcShort (glVertexArrayAttribFormat) && FindProcShort (glVertexArrayAttribIFormat) && FindProcShort (glVertexArrayAttribLFormat) && FindProcShort (glVertexArrayBindingDivisor) && FindProcShort (glGetVertexArrayiv) && FindProcShort (glGetVertexArrayIndexediv) && FindProcShort (glGetVertexArrayIndexed64iv) && FindProcShort (glCreateSamplers) && FindProcShort (glCreateProgramPipelines) && FindProcShort (glCreateQueries) && FindProcShort (glGetQueryBufferObjecti64v) && FindProcShort (glGetQueryBufferObjectiv) && FindProcShort (glGetQueryBufferObjectui64v) && FindProcShort (glGetQueryBufferObjectuiv) && FindProcShort (glMemoryBarrierByRegion) && FindProcShort (glGetTextureSubImage) && FindProcShort (glGetCompressedTextureSubImage) && FindProcShort (glGetGraphicsResetStatus) && FindProcShort (glGetnCompressedTexImage) && FindProcShort (glGetnTexImage) && FindProcShort (glGetnUniformdv) && FindProcShort (glGetnUniformfv) && FindProcShort (glGetnUniformiv) && FindProcShort (glGetnUniformuiv) && FindProcShort (glReadnPixels) && FindProcShort (glGetnMapdv) && FindProcShort (glGetnMapfv) && FindProcShort (glGetnMapiv) && FindProcShort (glGetnPixelMapfv) && FindProcShort (glGetnPixelMapuiv) && FindProcShort (glGetnPixelMapusv) && FindProcShort (glGetnPolygonStipple) && FindProcShort (glGetnColorTable) && FindProcShort (glGetnConvolutionFilter) && FindProcShort (glGetnSeparableFilter) && FindProcShort (glGetnHistogram) && FindProcShort (glGetnMinmax) && FindProcShort (glTextureBarrier); if (has45) { core45 = (OpenGl_GlCore45* )(&(*myFuncs)); if (!isCoreProfile) { core45back = (OpenGl_GlCore45Back* )(&(*myFuncs)); } } else { checkWrongVersion (4, 5, aLastFailedProc); } // initialize debug context extension if (CheckExtension ("GL_ARB_debug_output")) { arbDbg = NULL; if (has43) { arbDbg = (OpenGl_ArbDbg* )(&(*myFuncs)); } else if (FindProc ("glDebugMessageControlARB", myFuncs->glDebugMessageControl) && FindProc ("glDebugMessageInsertARB", myFuncs->glDebugMessageInsert) && FindProc ("glDebugMessageCallbackARB", myFuncs->glDebugMessageCallback) && FindProc ("glGetDebugMessageLogARB", myFuncs->glGetDebugMessageLog)) { arbDbg = (OpenGl_ArbDbg* )(&(*myFuncs)); } if (arbDbg != NULL && caps->contextDebug) { // setup default callback myIsGlDebugCtx = Standard_True; arbDbg->glDebugMessageCallback (debugCallbackWrap, this); if (has43) { ::glEnable (GL_DEBUG_OUTPUT); } if (caps->contextSyncDebug) { ::glEnable (GL_DEBUG_OUTPUT_SYNCHRONOUS); } } } // initialize FBO extension (ARB) if (hasFBO) { arbFBO = (OpenGl_ArbFBO* )(&(*myFuncs)); arbFBOBlit = (OpenGl_ArbFBOBlit* )(&(*myFuncs)); extPDS = Standard_True; // extension for EXT, but part of ARB } // initialize GS extension (EXT) if (CheckExtension ("GL_EXT_geometry_shader4") && FindProcShort (glProgramParameteriEXT)) { extGS = (OpenGl_ExtGS* )(&(*myFuncs)); } // initialize bindless texture extension (ARB) if (CheckExtension ("GL_ARB_bindless_texture") && FindProcShort (glGetTextureHandleARB) && FindProcShort (glGetTextureSamplerHandleARB) && FindProcShort (glMakeTextureHandleResidentARB) && FindProcShort (glMakeTextureHandleNonResidentARB) && FindProcShort (glGetImageHandleARB) && FindProcShort (glMakeImageHandleResidentARB) && FindProcShort (glMakeImageHandleNonResidentARB) && FindProcShort (glUniformHandleui64ARB) && FindProcShort (glUniformHandleui64vARB) && FindProcShort (glProgramUniformHandleui64ARB) && FindProcShort (glProgramUniformHandleui64vARB) && FindProcShort (glIsTextureHandleResidentARB) && FindProcShort (glIsImageHandleResidentARB) && FindProcShort (glVertexAttribL1ui64ARB) && FindProcShort (glVertexAttribL1ui64vARB) && FindProcShort (glGetVertexAttribLui64vARB)) { arbTexBindless = (OpenGl_ArbTexBindless* )(&(*myFuncs)); } if (has30) { // MSAA RenderBuffers have been defined in OpenGL 3.0, // but MSAA Textures - only in OpenGL 3.2+ if (!has32 && CheckExtension ("GL_ARB_texture_multisample") && FindProcShort (glTexImage2DMultisample)) { GLint aNbColorSamples = 0, aNbDepthSamples = 0; ::glGetIntegerv (GL_MAX_COLOR_TEXTURE_SAMPLES, &aNbColorSamples); ::glGetIntegerv (GL_MAX_DEPTH_TEXTURE_SAMPLES, &aNbDepthSamples); myMaxMsaaSamples = Min (aNbColorSamples, aNbDepthSamples); } if (!has43 && CheckExtension ("GL_ARB_texture_storage_multisample") && FindProcShort (glTexStorage2DMultisample)) { // } } // check whether ray tracing mode is supported myHasRayTracing = has31 && arbTboRGB32 && arbFBOBlit != NULL; // check whether textures in ray tracing mode are supported myHasRayTracingTextures = myHasRayTracing && arbTexBindless != NULL; // check whether adaptive screen sampling in ray tracing mode is supported myHasRayTracingAdaptiveSampling = myHasRayTracing && has44; myHasRayTracingAdaptiveSamplingAtomic = myHasRayTracingAdaptiveSampling && CheckExtension ("GL_NV_shader_atomic_float"); #endif if (arbFBO != NULL && hasFboSRGB) { // Detect if window buffer is considered by OpenGL as sRGB-ready // (linear RGB color written by shader is automatically converted into sRGB) // or not (offscreen FBO should be blit into window buffer with gamma correction). const GLenum aDefWinBuffer = #if !defined(GL_ES_VERSION_2_0) GL_BACK_LEFT; #else GL_BACK; #endif GLint aWinColorEncoding = 0; // GL_LINEAR arbFBO->glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, aDefWinBuffer, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, &aWinColorEncoding); ResetErrors (true); myIsSRgbWindow = aWinColorEncoding == GL_SRGB; // On desktop OpenGL, pixel formats are almost always sRGB-ready, even when not requested; // it is safe behavior on desktop where GL_FRAMEBUFFER_SRGB is disabled by default // (contrary to OpenGL ES, where it is enabled by default). // NVIDIA drivers, however, always return GL_LINEAR even for sRGB-ready pixel formats on Windows platform, // while AMD and Intel report GL_SRGB as expected. // macOS drivers seems to be also report GL_LINEAR even for [NSColorSpace sRGBColorSpace]. #if !defined(GL_ES_VERSION_2_0) #ifdef __APPLE__ myIsSRgbWindow = true; #else if (!myIsSRgbWindow && myVendor.Search ("nvidia") != -1) { myIsSRgbWindow = true; } #endif #endif if (!myIsSRgbWindow) { Message::DefaultMessenger()->Send ("OpenGl_Context, warning: window buffer is not sRGB-ready.\n" "Check OpenGL window creation parameters for optimal performance.", Message_Trace); } } // check whether PBR shading model is supported myHasPBR = arbFBO != NULL && myMaxTexCombined >= 4 && arbTexRG && arbTexFloat && (IsGlGreaterEqual (3, 0) #if !defined(GL_ES_VERSION_2_0) || (IsGlGreaterEqual (2, 1) && CheckExtension ("GL_EXT_gpu_shader4")) #endif ); if (myHasPBR) { myPBREnvLUTTexUnit = static_cast(myMaxTexCombined + Graphic3d_TextureUnit_PbrEnvironmentLUT); myPBRDiffIBLMapSHTexUnit = static_cast(myMaxTexCombined + Graphic3d_TextureUnit_PbrIblDiffuseSH); myPBRSpecIBLMapTexUnit = static_cast(myMaxTexCombined + Graphic3d_TextureUnit_PbrIblSpecular); } } // ======================================================================= // function : MemoryInfo // purpose : // ======================================================================= Standard_Size OpenGl_Context::AvailableMemory() const { #if !defined(GL_ES_VERSION_2_0) if (atiMem) { // this is actually information for VBO pool // however because pools are mostly shared // it can be used for total GPU memory estimations GLint aMemInfo[4]; aMemInfo[0] = 0; glGetIntegerv (GL_VBO_FREE_MEMORY_ATI, aMemInfo); // returned value is in KiB, however this maybe changed in future return Standard_Size(aMemInfo[0]) * 1024; } else if (nvxMem) { // current available dedicated video memory (in KiB), currently unused GPU memory GLint aMemInfo = 0; glGetIntegerv (GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &aMemInfo); return Standard_Size(aMemInfo) * 1024; } #endif return 0; } // ======================================================================= // function : MemoryInfo // purpose : // ======================================================================= TCollection_AsciiString OpenGl_Context::MemoryInfo() const { TColStd_IndexedDataMapOfStringString aDict; MemoryInfo (aDict); TCollection_AsciiString aText; for (TColStd_IndexedDataMapOfStringString::Iterator anIter (aDict); anIter.More(); anIter.Next()) { if (!aText.IsEmpty()) { aText += "\n"; } aText += TCollection_AsciiString(" ") + anIter.Key() + ": " + anIter.Value(); } return aText; } // ======================================================================= // function : MemoryInfo // purpose : // ======================================================================= void OpenGl_Context::MemoryInfo (TColStd_IndexedDataMapOfStringString& theDict) const { #if defined(GL_ES_VERSION_2_0) (void )theDict; #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX) GLint aGlRendId = 0; CGLGetParameter (CGLGetCurrentContext(), kCGLCPCurrentRendererID, &aGlRendId); CGLRendererInfoObj aRendObj = NULL; CGOpenGLDisplayMask aDispMask = CGDisplayIDToOpenGLDisplayMask (kCGDirectMainDisplay); GLint aRendNb = 0; CGLQueryRendererInfo (aDispMask, &aRendObj, &aRendNb); for (GLint aRendIter = 0; aRendIter < aRendNb; ++aRendIter) { GLint aRendId = 0; if (CGLDescribeRenderer (aRendObj, aRendIter, kCGLRPRendererID, &aRendId) != kCGLNoError || aRendId != aGlRendId) { continue; } //kCGLRPVideoMemoryMegabytes = 131; //kCGLRPTextureMemoryMegabytes = 132; GLint aVMem = 0; #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 if (CGLDescribeRenderer(aRendObj, aRendIter, kCGLRPVideoMemoryMegabytes, &aVMem) == kCGLNoError) { addInfo (theDict, "GPU memory", TCollection_AsciiString() + aVMem + " MiB"); } if (CGLDescribeRenderer(aRendObj, aRendIter, kCGLRPTextureMemoryMegabytes, &aVMem) == kCGLNoError) { addInfo (theDict, "GPU Texture memory", TCollection_AsciiString() + aVMem + " MiB"); } #else if (CGLDescribeRenderer(aRendObj, aRendIter, kCGLRPVideoMemory, &aVMem) == kCGLNoError) { addInfo (theDict, "GPU memory", TCollection_AsciiString() + (aVMem / (1024 * 1024)) + " MiB"); } if (CGLDescribeRenderer(aRendObj, aRendIter, kCGLRPTextureMemory, &aVMem) == kCGLNoError) { addInfo (theDict, "GPU Texture memory", TCollection_AsciiString() + (aVMem / (1024 * 1024)) + " MiB"); } #endif } #endif #if !defined(GL_ES_VERSION_2_0) if (atiMem) { GLint aValues[4]; memset (aValues, 0, sizeof(aValues)); glGetIntegerv (GL_VBO_FREE_MEMORY_ATI, aValues); // total memory free in the pool addInfo (theDict, "GPU free memory", TCollection_AsciiString() + (aValues[0] / 1024) + " MiB"); if (aValues[1] != aValues[0]) { // largest available free block in the pool addInfo (theDict, "Largest free block", TCollection_AsciiString() + (aValues[1] / 1024) + " MiB"); } if (aValues[2] != aValues[0]) { // total auxiliary memory free addInfo (theDict, "Free auxiliary memory", TCollection_AsciiString() + (aValues[2] / 1024) + " MiB"); } } else if (nvxMem) { //current available dedicated video memory (in KiB), currently unused GPU memory GLint aValue = 0; glGetIntegerv (GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &aValue); addInfo (theDict, "GPU free memory", TCollection_AsciiString() + (aValue / 1024) + " MiB"); // dedicated video memory, total size (in KiB) of the GPU memory GLint aDedicated = 0; glGetIntegerv (GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, &aDedicated); addInfo (theDict, "GPU memory", TCollection_AsciiString() + (aDedicated / 1024) + " MiB"); // total available memory, total size (in KiB) of the memory available for allocations glGetIntegerv (GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, &aValue); if (aValue != aDedicated) { // different only for special configurations addInfo (theDict, "Total memory", TCollection_AsciiString() + (aValue / 1024) + " MiB"); } } #if defined(_WIN32) else if (myFuncs->wglGetGPUInfoAMD != NULL && myFuncs->wglGetContextGPUIDAMD != NULL) { GLuint aTotalMemMiB = 0; UINT anAmdId = myFuncs->wglGetContextGPUIDAMD ((HGLRC )myGContext); if (anAmdId != 0) { if (myFuncs->wglGetGPUInfoAMD (anAmdId, WGL_GPU_RAM_AMD, GL_UNSIGNED_INT, sizeof(aTotalMemMiB), &aTotalMemMiB) > 0) { addInfo (theDict, "GPU memory", TCollection_AsciiString() + (int )aTotalMemMiB + " MiB"); } } } #endif #endif #if !defined(GL_ES_VERSION_2_0) && !defined(__APPLE__) && !defined(_WIN32) // GLX_RENDERER_VENDOR_ID_MESA if (myFuncs->glXQueryCurrentRendererIntegerMESA != NULL) { unsigned int aVMemMiB = 0; if (myFuncs->glXQueryCurrentRendererIntegerMESA (GLX_RENDERER_VIDEO_MEMORY_MESA, &aVMemMiB) != False) { addInfo (theDict, "GPU memory", TCollection_AsciiString() + int(aVMemMiB) + " MiB"); } } #endif } // ======================================================================= // function : DiagnosticInfo // purpose : // ======================================================================= void OpenGl_Context::DiagnosticInformation (TColStd_IndexedDataMapOfStringString& theDict, Graphic3d_DiagnosticInfo theFlags) const { if ((theFlags & Graphic3d_DiagnosticInfo_NativePlatform) != 0) { #if defined(HAVE_EGL) addInfo (theDict, "EGLVersion", ::eglQueryString ((EGLDisplay )myDisplay, EGL_VERSION)); addInfo (theDict, "EGLVendor", ::eglQueryString ((EGLDisplay )myDisplay, EGL_VENDOR)); addInfo (theDict, "EGLClientAPIs", ::eglQueryString ((EGLDisplay )myDisplay, EGL_CLIENT_APIS)); if ((theFlags & Graphic3d_DiagnosticInfo_Extensions) != 0) { addInfo (theDict, "EGLExtensions", ::eglQueryString ((EGLDisplay )myDisplay, EGL_EXTENSIONS)); } #elif defined(_WIN32) if ((theFlags & Graphic3d_DiagnosticInfo_Extensions) != 0 && myFuncs->wglGetExtensionsStringARB != NULL) { const char* aWglExts = myFuncs->wglGetExtensionsStringARB ((HDC )myWindowDC); addInfo (theDict, "WGLExtensions", aWglExts); } #elif defined(__APPLE__) // #else Display* aDisplay = (Display*)myDisplay; const int aScreen = DefaultScreen(aDisplay); addInfo (theDict, "GLXDirectRendering", ::glXIsDirect (aDisplay, (GLXContext )myGContext) ? "Yes" : "No"); addInfo (theDict, "GLXVendor", ::glXQueryServerString (aDisplay, aScreen, GLX_VENDOR)); addInfo (theDict, "GLXVersion", ::glXQueryServerString (aDisplay, aScreen, GLX_VERSION)); if ((theFlags & Graphic3d_DiagnosticInfo_Extensions) != 0) { const char* aGlxExts = ::glXQueryExtensionsString (aDisplay, aScreen); addInfo(theDict, "GLXExtensions", aGlxExts); } addInfo (theDict, "GLXClientVendor", ::glXGetClientString (aDisplay, GLX_VENDOR)); addInfo (theDict, "GLXClientVersion", ::glXGetClientString (aDisplay, GLX_VERSION)); if ((theFlags & Graphic3d_DiagnosticInfo_Extensions) != 0) { addInfo (theDict, "GLXClientExtensions", ::glXGetClientString (aDisplay, GLX_EXTENSIONS)); } #endif } if ((theFlags & Graphic3d_DiagnosticInfo_Device) != 0) { Standard_Integer aDriverVer[2] = {}; ReadGlVersion (aDriverVer[0], aDriverVer[1]); addInfo (theDict, "GLvendor", (const char*)::glGetString (GL_VENDOR)); addInfo (theDict, "GLdevice", (const char*)::glGetString (GL_RENDERER)); #ifdef __EMSCRIPTEN__ if (checkEnableWebGlExtension (*this, "GL_WEBGL_debug_renderer_info")) { if (const char* aVendor = (const char*)::glGetString (0x9245)) { addInfo (theDict, "GLunmaskedVendor", aVendor); } if (const char* aDevice = (const char*)::glGetString (0x9246)) { addInfo (theDict, "GLunmaskedDevice", aDevice); } } #endif addInfo (theDict, "GLversion", (const char*)::glGetString (GL_VERSION)); if (myGlVerMajor != aDriverVer[0] || myGlVerMinor != aDriverVer[1]) { addInfo (theDict, "GLversionOcct", TCollection_AsciiString (myGlVerMajor) + "." + TCollection_AsciiString (myGlVerMinor)); } if (IsGlGreaterEqual (2, 0)) { addInfo (theDict, "GLSLversion", (const char*)::glGetString (GL_SHADING_LANGUAGE_VERSION)); } if (myIsGlDebugCtx) { addInfo (theDict, "GLdebug", "ON"); } } if ((theFlags & Graphic3d_DiagnosticInfo_Limits) != 0) { addInfo (theDict, "Max texture size", TCollection_AsciiString(myMaxTexDim)); addInfo (theDict, "Max FBO dump size", TCollection_AsciiString() + myMaxDumpSizeX + "x" + myMaxDumpSizeY); addInfo (theDict, "Max combined texture units", TCollection_AsciiString(myMaxTexCombined)); addInfo (theDict, "Max MSAA samples", TCollection_AsciiString(myMaxMsaaSamples)); } if ((theFlags & Graphic3d_DiagnosticInfo_FrameBuffer) != 0) { GLint aViewport[4] = {}; ::glGetIntegerv (GL_VIEWPORT, aViewport); addInfo (theDict, "Viewport", TCollection_AsciiString() + aViewport[2] + "x" + aViewport[3]); } if ((theFlags & Graphic3d_DiagnosticInfo_Memory) != 0) { MemoryInfo (theDict); } if ((theFlags & Graphic3d_DiagnosticInfo_Extensions) != 0) { #if !defined(GL_ES_VERSION_2_0) if (IsGlGreaterEqual (3, 0) && myFuncs->glGetStringi != NULL) { TCollection_AsciiString anExtList; GLint anExtNb = 0; ::glGetIntegerv (GL_NUM_EXTENSIONS, &anExtNb); for (GLint anIter = 0; anIter < anExtNb; ++anIter) { const char* anExtension = (const char*)myFuncs->glGetStringi (GL_EXTENSIONS, (GLuint)anIter); if (!anExtList.IsEmpty()) { anExtList += " "; } anExtList += anExtension; } addInfo(theDict, "GLextensions", anExtList); } else #endif { addInfo (theDict, "GLextensions", (const char*)::glGetString (GL_EXTENSIONS)); } } } // ======================================================================= // function : GetResource // purpose : // ======================================================================= const Handle(OpenGl_Resource)& OpenGl_Context::GetResource (const TCollection_AsciiString& theKey) const { return mySharedResources->IsBound (theKey) ? mySharedResources->Find (theKey) : NULL_GL_RESOURCE; } // ======================================================================= // function : ShareResource // purpose : // ======================================================================= Standard_Boolean OpenGl_Context::ShareResource (const TCollection_AsciiString& theKey, const Handle(OpenGl_Resource)& theResource) { if (theKey.IsEmpty() || theResource.IsNull()) { return Standard_False; } return mySharedResources->Bind (theKey, theResource); } // ======================================================================= // function : ReleaseResource // purpose : // ======================================================================= void OpenGl_Context::ReleaseResource (const TCollection_AsciiString& theKey, const Standard_Boolean theToDelay) { if (!mySharedResources->IsBound (theKey)) { return; } const Handle(OpenGl_Resource)& aRes = mySharedResources->Find (theKey); if (aRes->GetRefCount() > 1) { return; } if (theToDelay) { myDelayed->Bind (theKey, 1); } else { aRes->Release (this); mySharedResources->UnBind (theKey); } } // ======================================================================= // function : ReleaseDelayed // purpose : // ======================================================================= void OpenGl_Context::ReleaseDelayed() { // release queued elements while (!myUnusedResources->IsEmpty()) { myUnusedResources->First()->Release (this); myUnusedResources->RemoveFirst(); } // release delayed shared resources NCollection_Vector aDeadList; for (NCollection_DataMap::Iterator anIter (*myDelayed); anIter.More(); anIter.Next()) { if (++anIter.ChangeValue() <= 2) { continue; // postpone release one more frame to ensure noone use it periodically } const TCollection_AsciiString& aKey = anIter.Key(); if (!mySharedResources->IsBound (aKey)) { // mixed unshared strategy delayed/undelayed was used! aDeadList.Append (aKey); continue; } const Handle(OpenGl_Resource)& aRes = mySharedResources->ChangeFind (aKey); if (aRes->GetRefCount() > 1) { // should be only 1 instance in mySharedResources // if not - resource was reused again aDeadList.Append (aKey); continue; } // release resource if no one requiested it more than 2 redraw calls aRes->Release (this); mySharedResources->UnBind (aKey); aDeadList.Append (aKey); } for (Standard_Integer anIter = 0; anIter < aDeadList.Length(); ++anIter) { myDelayed->UnBind (aDeadList.Value (anIter)); } } // ======================================================================= // function : BindTextures // purpose : // ======================================================================= Handle(OpenGl_TextureSet) OpenGl_Context::BindTextures (const Handle(OpenGl_TextureSet)& theTextures, const Handle(OpenGl_ShaderProgram)& theProgram) { const Standard_Integer aTextureSetBits = !theTextures.IsNull() ? theTextures->TextureSetBits() : 0; const Standard_Integer aProgramBits = !theProgram.IsNull() ? theProgram->TextureSetBits() : 0; Standard_Integer aMissingBits = aProgramBits & ~aTextureSetBits; if (aMissingBits != 0 && myTextureRgbaBlack.IsNull()) { // allocate mock textures myTextureRgbaBlack = new OpenGl_Texture(); myTextureRgbaWhite = new OpenGl_Texture(); Image_PixMap anImage; anImage.InitZero (Image_Format_RGBA, 2, 2, 0, (Standard_Byte )0); if (!myTextureRgbaBlack->Init (this, OpenGl_TextureFormat::Create(), Graphic3d_Vec2i (2, 2), Graphic3d_TOT_2D, &anImage)) { PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, "Error: unable to create unit mock PBR texture map."); } anImage.InitZero (Image_Format_RGBA, 2, 2, 0, (Standard_Byte )255); if (!myTextureRgbaWhite->Init (this, OpenGl_TextureFormat::Create(), Graphic3d_Vec2i (2, 2), Graphic3d_TOT_2D, &anImage)) { PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, "Error: unable to create normal mock PBR texture map."); } } Handle(OpenGl_TextureSet) anOldTextures = myActiveTextures; if (myActiveTextures != theTextures) { Handle(OpenGl_Context) aThisCtx (this); OpenGl_TextureSet::Iterator aTextureIterOld (myActiveTextures), aTextureIterNew (theTextures); for (;;) { if (!aTextureIterNew.More()) { for (; aTextureIterOld.More(); aTextureIterOld.Next()) { if (const Handle(OpenGl_Texture)& aTextureOld = aTextureIterOld.Value()) { aTextureOld->Unbind (aThisCtx, aTextureIterOld.Unit()); #if !defined(GL_ES_VERSION_2_0) if (core11 != NULL) { OpenGl_Sampler::resetGlobalTextureParams (aThisCtx, *aTextureOld, aTextureOld->Sampler()->Parameters()); } #endif } } break; } const Handle(OpenGl_Texture)& aTextureNew = aTextureIterNew.Value(); if (aTextureIterOld.More()) { const Handle(OpenGl_Texture)& aTextureOld = aTextureIterOld.Value(); if (aTextureNew == aTextureOld && aTextureIterNew.Unit() == aTextureIterOld.Unit()) { aTextureIterNew.Next(); aTextureIterOld.Next(); continue; } else if (aTextureNew.IsNull() || !aTextureNew->IsValid()) { if (!aTextureOld.IsNull()) { aTextureOld->Unbind (aThisCtx, aTextureIterOld.Unit()); #if !defined(GL_ES_VERSION_2_0) if (core11 != NULL) { OpenGl_Sampler::resetGlobalTextureParams (aThisCtx, *aTextureOld, aTextureOld->Sampler()->Parameters()); } #endif } aTextureIterNew.Next(); aTextureIterOld.Next(); continue; } aTextureIterOld.Next(); } if (aTextureNew.IsNull()) { aTextureIterNew.Next(); continue; } const Graphic3d_TextureUnit aTexUnit = aTextureIterNew.Unit(); if (aTexUnit >= myMaxTexCombined) { PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, TCollection_AsciiString("Texture unit ") + aTexUnit + " for " + aTextureNew->ResourceId() + " exceeds hardware limit " + myMaxTexCombined); aTextureIterNew.Next(); continue; } aTextureNew->Bind (aThisCtx, aTexUnit); if (aTextureNew->Sampler()->ToUpdateParameters()) { if (aTextureNew->Sampler()->IsImmutable()) { aTextureNew->Sampler()->Init (aThisCtx, *aTextureNew); } else { OpenGl_Sampler::applySamplerParams (aThisCtx, aTextureNew->Sampler()->Parameters(), aTextureNew->Sampler().get(), aTextureNew->GetTarget(), aTextureNew->HasMipmaps()); } } #if !defined(GL_ES_VERSION_2_0) if (core11 != NULL) { OpenGl_Sampler::applyGlobalTextureParams (aThisCtx, *aTextureNew, aTextureNew->Sampler()->Parameters()); } #endif aTextureIterNew.Next(); } myActiveTextures = theTextures; } if (myActiveMockTextures != aMissingBits) { myActiveMockTextures = aMissingBits; for (Standard_Integer aBitIter = 0; aMissingBits != 0; ++aBitIter) { Standard_Integer aUnitMask = 1 << aBitIter; if ((aUnitMask & aMissingBits) != 0) { aMissingBits = aMissingBits & ~aUnitMask; if (aBitIter == Graphic3d_TextureUnit_Normal) { myTextureRgbaBlack->Bind (this, static_cast(aBitIter)); } else { myTextureRgbaWhite->Bind (this, static_cast(aBitIter)); } } } } return anOldTextures; } // ======================================================================= // function : BindProgram // purpose : // ======================================================================= Standard_Boolean OpenGl_Context::BindProgram (const Handle(OpenGl_ShaderProgram)& theProgram) { if (core20fwd == NULL) { return Standard_False; } else if (myActiveProgram == theProgram) { return Standard_True; } if (theProgram.IsNull() || !theProgram->IsValid()) { if (!myActiveProgram.IsNull()) { core20fwd->glUseProgram (OpenGl_ShaderProgram::NO_PROGRAM); myActiveProgram.Nullify(); } return Standard_False; } myActiveProgram = theProgram; core20fwd->glUseProgram (theProgram->ProgramId()); return Standard_True; } // ======================================================================= // function : BindDefaultVao // purpose : // ======================================================================= void OpenGl_Context::BindDefaultVao() { #if !defined(GL_ES_VERSION_2_0) if (myDefaultVao == 0 || core32 == NULL) { return; } core32->glBindVertexArray (myDefaultVao); #endif } // ======================================================================= // function : SetDefaultFrameBuffer // purpose : // ======================================================================= Handle(OpenGl_FrameBuffer) OpenGl_Context::SetDefaultFrameBuffer (const Handle(OpenGl_FrameBuffer)& theFbo) { Handle(OpenGl_FrameBuffer) aFbo = myDefaultFbo; myDefaultFbo = theFbo; return aFbo; } // ======================================================================= // function : SetShadingMaterial // purpose : // ======================================================================= void OpenGl_Context::SetShadingMaterial (const OpenGl_Aspects* theAspect, const Handle(Graphic3d_PresentationAttributes)& theHighlight) { const Handle(Graphic3d_Aspects)& anAspect = (!theHighlight.IsNull() && !theHighlight->BasicFillAreaAspect().IsNull()) ? (const Handle(Graphic3d_Aspects)& )theHighlight->BasicFillAreaAspect() : theAspect->Aspect(); const bool toDistinguish = anAspect->Distinguish(); const bool toMapTexture = anAspect->ToMapTexture(); const Graphic3d_MaterialAspect& aMatFrontSrc = anAspect->FrontMaterial(); const Graphic3d_MaterialAspect& aMatBackSrc = toDistinguish ? anAspect->BackMaterial() : aMatFrontSrc; const Quantity_Color& aFrontIntColor = anAspect->InteriorColor(); const Quantity_Color& aBackIntColor = toDistinguish ? anAspect->BackInteriorColor() : aFrontIntColor; myMatFront.Init (*this, aMatFrontSrc, aFrontIntColor); if (toDistinguish) { myMatBack.Init (*this, aMatBackSrc, aBackIntColor); } else { myMatBack = myMatFront; } if (!theHighlight.IsNull() && theHighlight->BasicFillAreaAspect().IsNull()) { myMatFront.SetColor (theHighlight->ColorRGBA()); myMatBack .SetColor (theHighlight->ColorRGBA()); } Standard_ShortReal anAlphaFront = 1.0f; Standard_ShortReal anAlphaBack = 1.0f; if (CheckIsTransparent (theAspect, theHighlight, anAlphaFront, anAlphaBack)) { myMatFront.Common.Diffuse.a() = anAlphaFront; myMatBack .Common.Diffuse.a() = anAlphaBack; myMatFront.Pbr.BaseColor.a() = anAlphaFront; myMatBack .Pbr.BaseColor.a() = anAlphaBack; } // do not update material properties in case of zero reflection mode, // because GL lighting will be disabled by OpenGl_PrimitiveArray::DrawArray() anyway. const OpenGl_MaterialState& aMatState = myShaderManager->MaterialState(); float anAlphaCutoff = anAspect->AlphaMode() == Graphic3d_AlphaMode_Mask ? anAspect->AlphaCutoff() : ShortRealLast(); if (anAspect->ToDrawEdges()) { if (anAspect->InteriorStyle() == Aspect_IS_EMPTY || (anAspect->InteriorStyle() == Aspect_IS_SOLID && anAspect->EdgeColorRGBA().Alpha() < 1.0f)) { anAlphaCutoff = 0.285f; } } if (theAspect->ShadingModel() == Graphic3d_TOSM_UNLIT) { if (anAlphaCutoff == aMatState.AlphaCutoff()) { return; } } else if (myMatFront == aMatState.FrontMaterial() && myMatBack == aMatState.BackMaterial() && toDistinguish == aMatState.ToDistinguish() && toMapTexture == aMatState.ToMapTexture() && anAlphaCutoff == aMatState.AlphaCutoff()) { return; } myShaderManager->UpdateMaterialStateTo (myMatFront, myMatBack, anAlphaCutoff, toDistinguish, toMapTexture); } // ======================================================================= // function : CheckIsTransparent // purpose : // ======================================================================= Standard_Boolean OpenGl_Context::CheckIsTransparent (const OpenGl_Aspects* theAspect, const Handle(Graphic3d_PresentationAttributes)& theHighlight, Standard_ShortReal& theAlphaFront, Standard_ShortReal& theAlphaBack) { const Handle(Graphic3d_Aspects)& anAspect = (!theHighlight.IsNull() && !theHighlight->BasicFillAreaAspect().IsNull()) ? (const Handle(Graphic3d_Aspects)& )theHighlight->BasicFillAreaAspect() : theAspect->Aspect(); const bool toDistinguish = anAspect->Distinguish(); const Graphic3d_MaterialAspect& aMatFrontSrc = anAspect->FrontMaterial(); const Graphic3d_MaterialAspect& aMatBackSrc = toDistinguish ? anAspect->BackMaterial() : aMatFrontSrc; // handling transparency if (!theHighlight.IsNull() && theHighlight->BasicFillAreaAspect().IsNull()) { theAlphaFront = theHighlight->ColorRGBA().Alpha(); theAlphaBack = theHighlight->ColorRGBA().Alpha(); } else { theAlphaFront = aMatFrontSrc.Alpha(); theAlphaBack = aMatBackSrc .Alpha(); } if (anAspect->AlphaMode() == Graphic3d_AlphaMode_BlendAuto) { return theAlphaFront < 1.0f || theAlphaBack < 1.0f; } return anAspect->AlphaMode() == Graphic3d_AlphaMode_Blend; } // ======================================================================= // function : SetColor4fv // purpose : // ======================================================================= void OpenGl_Context::SetColor4fv (const OpenGl_Vec4& theColor) { if (!myActiveProgram.IsNull()) { if (const OpenGl_ShaderUniformLocation& aLoc = myActiveProgram->GetStateLocation (OpenGl_OCCT_COLOR)) { myActiveProgram->SetUniform (this, aLoc, Vec4FromQuantityColor (theColor)); } } #if !defined(GL_ES_VERSION_2_0) else if (core11 != NULL) { core11->glColor4fv (theColor.GetData()); } #endif } // ======================================================================= // function : SetTypeOfLine // purpose : // ======================================================================= void OpenGl_Context::SetTypeOfLine (const Aspect_TypeOfLine theType, const Standard_ShortReal theFactor) { SetLineStipple (theFactor, Graphic3d_Aspects::DefaultLinePatternForType (theType)); } // ======================================================================= // function : SetLineStipple // purpose : // ======================================================================= void OpenGl_Context::SetLineStipple (const Standard_ShortReal theFactor, const uint16_t thePattern) { if (!myActiveProgram.IsNull()) { if (const OpenGl_ShaderUniformLocation aPatternLoc = myActiveProgram->GetStateLocation (OpenGl_OCCT_LINE_STIPPLE_PATTERN)) { if (hasGlslBitwiseOps != OpenGl_FeatureNotAvailable) { myActiveProgram->SetUniform (this, aPatternLoc, (Standard_Integer )thePattern); } else { Standard_Integer aPatArr[16] = {}; for (unsigned int aBit = 0; aBit < 16; ++aBit) { aPatArr[aBit] = ((unsigned int)(thePattern) & (1U << aBit)) != 0 ? 1 : 0; } myActiveProgram->SetUniform (this, aPatternLoc, 16, aPatArr); } myActiveProgram->SetUniform (this, myActiveProgram->GetStateLocation (OpenGl_OCCT_LINE_STIPPLE_FACTOR), theFactor); } return; } #if !defined(GL_ES_VERSION_2_0) if (thePattern != 0xFFFF) { if (core11 != NULL) { core11fwd->glEnable (GL_LINE_STIPPLE); core11->glLineStipple (static_cast (theFactor), static_cast (thePattern)); } } else { if (core11 != NULL) { core11fwd->glDisable (GL_LINE_STIPPLE); } } #endif } // ======================================================================= // function : SetLineWidth // purpose : // ======================================================================= void OpenGl_Context::SetLineWidth (const Standard_ShortReal theWidth) { if (core11 != NULL) { // glLineWidth() is still defined within Core Profile, but has no effect with values != 1.0f core11fwd->glLineWidth (theWidth * myLineWidthScale); } } // ======================================================================= // function : SetTextureMatrix // purpose : // ======================================================================= void OpenGl_Context::SetTextureMatrix (const Handle(Graphic3d_TextureParams)& theParams) { if (theParams.IsNull()) { return; } else if (!myActiveProgram.IsNull()) { const GLint aUniLoc = myActiveProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_TRSF2D); if (aUniLoc == OpenGl_ShaderProgram::INVALID_LOCATION) { return; } // pack transformation parameters OpenGl_Vec4 aTrsf[2] = { OpenGl_Vec4 (-theParams->Translation().x(), -theParams->Translation().y(), theParams->Scale().x(), theParams->Scale().y()), OpenGl_Vec4 (static_cast (std::sin (-theParams->Rotation() * M_PI / 180.0)), static_cast (std::cos (-theParams->Rotation() * M_PI / 180.0)), 0.0f, 0.0f) }; myActiveProgram->SetUniform (this, aUniLoc, 2, aTrsf); return; } #if !defined(GL_ES_VERSION_2_0) if (core11 != NULL) { GLint aMatrixMode = GL_TEXTURE; ::glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode); core11->glMatrixMode (GL_TEXTURE); OpenGl_Mat4 aTextureMat; const Graphic3d_Vec2& aScale = theParams->Scale(); const Graphic3d_Vec2& aTrans = theParams->Translation(); Graphic3d_TransformUtils::Scale (aTextureMat, aScale.x(), aScale.y(), 1.0f); Graphic3d_TransformUtils::Translate (aTextureMat, -aTrans.x(), -aTrans.y(), 0.0f); Graphic3d_TransformUtils::Rotate (aTextureMat, -theParams->Rotation(), 0.0f, 0.0f, 1.0f); core11->glLoadMatrixf (aTextureMat); core11->glMatrixMode (aMatrixMode); } #endif } // ======================================================================= // function : SetPointSize // purpose : // ======================================================================= void OpenGl_Context::SetPointSize (const Standard_ShortReal theSize) { if (!myActiveProgram.IsNull()) { myActiveProgram->SetUniform (this, myActiveProgram->GetStateLocation (OpenGl_OCCT_POINT_SIZE), theSize); #if !defined(GL_ES_VERSION_2_0) //myContext->core11fwd->glEnable (GL_VERTEX_PROGRAM_POINT_SIZE); #endif } #if !defined(GL_ES_VERSION_2_0) //else { core11fwd->glPointSize (theSize); if (core20fwd != NULL) { //myContext->core11fwd->glDisable (GL_VERTEX_PROGRAM_POINT_SIZE); } } #endif } // ======================================================================= // function : SetPointSpriteOrigin // purpose : // ======================================================================= void OpenGl_Context::SetPointSpriteOrigin() { #if !defined(GL_ES_VERSION_2_0) if (core15fwd == NULL) { return; } const int aNewState = !myActiveProgram.IsNull() ? GL_UPPER_LEFT : GL_LOWER_LEFT; if (myPointSpriteOrig != aNewState) { myPointSpriteOrig = aNewState; core15fwd->glPointParameteri (GL_POINT_SPRITE_COORD_ORIGIN, aNewState); } #endif } // ======================================================================= // function : SetGlNormalizeEnabled // purpose : // ======================================================================= Standard_Boolean OpenGl_Context::SetGlNormalizeEnabled (Standard_Boolean isEnabled) { if (isEnabled == myIsGlNormalizeEnabled) { return myIsGlNormalizeEnabled; } Standard_Boolean anOldGlNormalize = myIsGlNormalizeEnabled; myIsGlNormalizeEnabled = isEnabled; #if !defined(GL_ES_VERSION_2_0) if (core11 != NULL) { if (isEnabled) { ::glEnable (GL_NORMALIZE); } else { ::glDisable (GL_NORMALIZE); } } #endif return anOldGlNormalize; } // ======================================================================= // function : SetPolygonMode // purpose : // ======================================================================= Standard_Integer OpenGl_Context::SetPolygonMode (const Standard_Integer theMode) { if (myPolygonMode == theMode) { return myPolygonMode; } const Standard_Integer anOldPolygonMode = myPolygonMode; myPolygonMode = theMode; #if !defined(GL_ES_VERSION_2_0) ::glPolygonMode (GL_FRONT_AND_BACK, (GLenum)theMode); #endif return anOldPolygonMode; } // ======================================================================= // function : SetPolygonHatchEnabled // purpose : // ======================================================================= bool OpenGl_Context::SetPolygonHatchEnabled (const bool theIsEnabled) { if (myHatchStyles.IsNull()) { return false; } else if (myHatchStyles->IsEnabled() == theIsEnabled) { return theIsEnabled; } return myHatchStyles->SetEnabled (this, theIsEnabled); } // ======================================================================= // function : SetPolygonHatchStyle // purpose : // ======================================================================= Standard_Integer OpenGl_Context::SetPolygonHatchStyle (const Handle(Graphic3d_HatchStyle)& theStyle) { if (theStyle.IsNull()) { return 0; } if (myHatchStyles.IsNull()) { if (!GetResource ("OpenGl_LineAttributes", myHatchStyles)) { // share and register for release once the resource is no longer used myHatchStyles = new OpenGl_LineAttributes(); ShareResource ("OpenGl_LineAttributes", myHatchStyles); } } if (myHatchStyles->TypeOfHatch() == theStyle->HatchType()) { return theStyle->HatchType(); } return myHatchStyles->SetTypeOfHatch (this, theStyle); } // ======================================================================= // function : SetPolygonOffset // purpose : // ======================================================================= void OpenGl_Context::SetPolygonOffset (const Graphic3d_PolygonOffset& theOffset) { const bool toFillOld = (myPolygonOffset.Mode & Aspect_POM_Fill) == Aspect_POM_Fill; const bool toFillNew = (theOffset.Mode & Aspect_POM_Fill) == Aspect_POM_Fill; if (toFillNew != toFillOld) { if (toFillNew) { glEnable (GL_POLYGON_OFFSET_FILL); } else { glDisable (GL_POLYGON_OFFSET_FILL); } } #if !defined(GL_ES_VERSION_2_0) const bool toLineOld = (myPolygonOffset.Mode & Aspect_POM_Line) == Aspect_POM_Line; const bool toLineNew = (theOffset.Mode & Aspect_POM_Line) == Aspect_POM_Line; if (toLineNew != toLineOld) { if (toLineNew) { glEnable (GL_POLYGON_OFFSET_LINE); } else { glDisable (GL_POLYGON_OFFSET_LINE); } } const bool toPointOld = (myPolygonOffset.Mode & Aspect_POM_Point) == Aspect_POM_Point; const bool toPointNew = (theOffset.Mode & Aspect_POM_Point) == Aspect_POM_Point; if (toPointNew != toPointOld) { if (toPointNew) { glEnable (GL_POLYGON_OFFSET_POINT); } else { glDisable (GL_POLYGON_OFFSET_POINT); } } #endif if (myPolygonOffset.Factor != theOffset.Factor || myPolygonOffset.Units != theOffset.Units) { glPolygonOffset (theOffset.Factor, theOffset.Units); } myPolygonOffset = theOffset; } // ======================================================================= // function : ApplyModelWorldMatrix // purpose : // ======================================================================= void OpenGl_Context::ApplyModelWorldMatrix() { if (myShaderManager->ModelWorldState().ModelWorldMatrix() != ModelWorldState.Current()) { myShaderManager->UpdateModelWorldStateTo (ModelWorldState.Current()); } } // ======================================================================= // function : ApplyWorldViewMatrix // purpose : // ======================================================================= void OpenGl_Context::ApplyWorldViewMatrix() { if (myShaderManager->ModelWorldState().ModelWorldMatrix() != THE_IDENTITY_MATRIX) { myShaderManager->UpdateModelWorldStateTo (THE_IDENTITY_MATRIX); } if (myShaderManager->WorldViewState().WorldViewMatrix() != WorldViewState.Current()) { myShaderManager->UpdateWorldViewStateTo (WorldViewState.Current()); } } // ======================================================================= // function : ApplyModelViewMatrix // purpose : // ======================================================================= void OpenGl_Context::ApplyModelViewMatrix() { if (myShaderManager->ModelWorldState().ModelWorldMatrix() != ModelWorldState.Current()) { myShaderManager->UpdateModelWorldStateTo (ModelWorldState.Current()); } if (myShaderManager->WorldViewState().WorldViewMatrix() != WorldViewState.Current()) { myShaderManager->UpdateWorldViewStateTo (WorldViewState.Current()); } } // ======================================================================= // function : ApplyProjectionMatrix // purpose : // ======================================================================= void OpenGl_Context::ApplyProjectionMatrix() { if (myShaderManager->ProjectionState().ProjectionMatrix() != ProjectionState.Current()) { myShaderManager->UpdateProjectionStateTo (ProjectionState.Current()); } } // ======================================================================= // function : EnableFeatures // purpose : // ======================================================================= void OpenGl_Context::EnableFeatures() const { // } // ======================================================================= // function : DisableFeatures // purpose : // ======================================================================= void OpenGl_Context::DisableFeatures() const { // Disable stuff that's likely to slow down glDrawPixels. glDisable(GL_DITHER); glDisable(GL_BLEND); glDisable(GL_DEPTH_TEST); glDisable(GL_STENCIL_TEST); #if !defined(GL_ES_VERSION_2_0) if (core11 == NULL) { return; } glDisable(GL_TEXTURE_1D); glDisable(GL_TEXTURE_2D); glDisable(GL_LIGHTING); glDisable(GL_ALPHA_TEST); glDisable(GL_FOG); glDisable(GL_LOGIC_OP); glPixelTransferi(GL_MAP_COLOR, GL_FALSE); glPixelTransferi(GL_RED_SCALE, 1); glPixelTransferi(GL_RED_BIAS, 0); glPixelTransferi(GL_GREEN_SCALE, 1); glPixelTransferi(GL_GREEN_BIAS, 0); glPixelTransferi(GL_BLUE_SCALE, 1); glPixelTransferi(GL_BLUE_BIAS, 0); glPixelTransferi(GL_ALPHA_SCALE, 1); glPixelTransferi(GL_ALPHA_BIAS, 0); if ((myGlVerMajor >= 1) && (myGlVerMinor >= 2)) { if (CheckExtension ("GL_CONVOLUTION_1D_EXT")) glDisable(GL_CONVOLUTION_1D_EXT); if (CheckExtension ("GL_CONVOLUTION_2D_EXT")) glDisable(GL_CONVOLUTION_2D_EXT); if (CheckExtension ("GL_SEPARABLE_2D_EXT")) glDisable(GL_SEPARABLE_2D_EXT); if (CheckExtension ("GL_SEPARABLE_2D_EXT")) glDisable(GL_HISTOGRAM_EXT); if (CheckExtension ("GL_MINMAX_EXT")) glDisable(GL_MINMAX_EXT); if (CheckExtension ("GL_TEXTURE_3D_EXT")) glDisable(GL_TEXTURE_3D_EXT); } #endif } // ======================================================================= // function : SetColorMask // purpose : // ======================================================================= bool OpenGl_Context::SetColorMask (bool theToWriteColor) { const GLboolean toWrite = theToWriteColor ? GL_TRUE : GL_FALSE; glColorMask (toWrite, toWrite, toWrite, toWrite); const bool anOldValue = myColorMask; myColorMask = theToWriteColor; return anOldValue; } // ======================================================================= // function : SetSampleAlphaToCoverage // purpose : // ======================================================================= bool OpenGl_Context::SetSampleAlphaToCoverage (bool theToEnable) { bool toEnable = myAllowAlphaToCov && theToEnable; if (myAlphaToCoverage == toEnable) { return myAlphaToCoverage; } if (core15fwd != NULL) { if (toEnable) { //core15fwd->core15fwd->glSampleCoverage (1.0f, GL_FALSE); core15fwd->glEnable (GL_SAMPLE_ALPHA_TO_COVERAGE); } else { core15fwd->glDisable (GL_SAMPLE_ALPHA_TO_COVERAGE); } } const bool anOldValue = myAlphaToCoverage; myAlphaToCoverage = toEnable; return anOldValue; } // ======================================================================= // function : DumpJson // purpose : // ======================================================================= void OpenGl_Context::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const { OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myAnisoMax) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myTexClamp) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMaxTexDim) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMaxTexCombined) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMaxDumpSizeX) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMaxDumpSizeY) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMaxClipPlanes) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMaxMsaaSamples) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMaxDrawBuffers) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMaxColorAttachments) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myGlVerMajor) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myGlVerMinor) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsInitialized) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsStereoBuffers) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsGlNormalizeEnabled) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myHasRayTracing) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myHasRayTracingTextures) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myHasRayTracingAdaptiveSampling) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myHasRayTracingAdaptiveSamplingAtomic) for (int i = 0; i < 4; i++) { OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myViewport[i]) } for (int i = 0; i < 4; i++) { OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myViewportVirt[i]) } OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myPointSpriteOrig) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myRenderMode) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myPolygonMode) OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myPolygonOffset) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myToCullBackFaces) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myReadBuffer) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myDefaultVao) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myColorMask) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myAllowAlphaToCov) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myAlphaToCoverage) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsGlDebugCtx) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myResolution) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myResolutionRatio) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myLineWidthScale) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myLineFeather) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myRenderScale) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myRenderScaleInv) OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &ModelWorldState) OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &WorldViewState) OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &ProjectionState) } // ======================================================================= // function : DumpJsonOpenGlState // purpose : // ======================================================================= void OpenGl_Context::DumpJsonOpenGlState (Standard_OStream& theOStream, Standard_Integer) { GLboolean isEnableBlend = glIsEnabled (GL_BLEND); GLboolean isEnableCullFace = glIsEnabled (GL_CULL_FACE); GLboolean isEnableDepthTest = glIsEnabled (GL_DEPTH_TEST); OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, isEnableBlend) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, isEnableCullFace) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, isEnableDepthTest) }