1 // Created on: 2012-01-26
2 // Created by: Kirill GAVRILOV
3 // Copyright (c) 2012-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and / or modify it
8 // under the terms of the GNU Lesser General Public version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
20 #include <OpenGl_Context.hxx>
22 #include <OpenGl_ArbVBO.hxx>
23 #include <OpenGl_ArbTBO.hxx>
24 #include <OpenGl_ArbIns.hxx>
25 #include <OpenGl_ArbDbg.hxx>
26 #include <OpenGl_ExtFBO.hxx>
27 #include <OpenGl_ExtGS.hxx>
28 #include <OpenGl_GlCore20.hxx>
29 #include <OpenGl_ShaderManager.hxx>
31 #include <Message_Messenger.hxx>
33 #include <NCollection_Vector.hxx>
35 #include <Standard_ProgramError.hxx>
39 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
42 #include <GL/glx.h> // glXGetProcAddress()
45 // GL_NVX_gpu_memory_info
46 #ifndef GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX
49 GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX = 0x9047,
50 GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX = 0x9048,
51 GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX = 0x9049,
52 GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX = 0x904A,
53 GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX = 0x904B
57 IMPLEMENT_STANDARD_HANDLE (OpenGl_Context, Standard_Transient)
58 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Context, Standard_Transient)
60 //! Make record shorter to retrieve function pointer using variable with same name
61 #define FindProcShort(theStruct, theFunc) FindProc(#theFunc, theStruct->theFunc)
65 static const Handle(OpenGl_Resource) NULL_GL_RESOURCE;
66 static const GLdouble OpenGl_DefaultPlaneEq[] = {0.0, 0.0, 0.0, 0.0};
69 // =======================================================================
70 // function : OpenGl_Context
72 // =======================================================================
73 OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps)
79 caps (!theCaps.IsNull() ? theCaps : new OpenGl_Caps()),
80 arbNPTW(Standard_False),
87 extBgra(Standard_False),
88 extAnis(Standard_False),
89 extPDS (Standard_False),
90 atiMem (Standard_False),
91 nvxMem (Standard_False),
92 mySharedResources (new OpenGl_ResourcesMap()),
93 myDelayed (new OpenGl_DelayReleaseMap()),
94 myReleaseQueue (new OpenGl_ResourcesQueue()),
103 myRenderMode (GL_RENDER),
104 myIsInitialized (Standard_False),
105 myIsStereoBuffers (Standard_False),
108 #if defined(MAC_OS_X_VERSION_10_3) && !defined(MACOSX_USE_GLX)
109 // Vendors can not extend functionality on this system
110 // and developers are limited to OpenGL support provided by Mac OS X SDK.
111 // We retrieve function pointers from system library
112 // to generalize extensions support on all platforms.
113 // In this way we also reach binary compatibility benefit between OS releases
114 // if some newest functionality is optionally used.
115 // Notice that GL version / extension availability checks are required
116 // because function pointers may be available but not functionality itself
117 // (depends on renderer).
118 myGlLibHandle = dlopen ("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY);
121 myShaderManager = new OpenGl_ShaderManager (this);
124 // =======================================================================
125 // function : ~OpenGl_Context
127 // =======================================================================
128 OpenGl_Context::~OpenGl_Context()
130 // release clean up queue
133 // release shared resources if any
134 if (((const Handle(Standard_Transient)& )mySharedResources)->GetRefCount() <= 1)
136 myShaderManager.Nullify();
137 for (NCollection_DataMap<TCollection_AsciiString, Handle(OpenGl_Resource)>::Iterator anIter (*mySharedResources);
138 anIter.More(); anIter.Next())
140 anIter.Value()->Release (this);
145 myShaderManager->SetContext (NULL);
147 mySharedResources.Nullify();
151 && caps->contextDebug)
155 glGetPointerv (GL_DEBUG_CALLBACK_USER_PARAM_ARB, &aPtr);
158 arbDbg->glDebugMessageCallbackARB (NULL, NULL);
171 // =======================================================================
172 // function : MaxDegreeOfAnisotropy
174 // =======================================================================
175 Standard_Integer OpenGl_Context::MaxDegreeOfAnisotropy() const
180 // =======================================================================
181 // function : MaxTextureSize
183 // =======================================================================
184 Standard_Integer OpenGl_Context::MaxTextureSize() const
189 // =======================================================================
190 // function : MaxClipPlanes
192 // =======================================================================
193 Standard_Integer OpenGl_Context::MaxClipPlanes() const
195 return myMaxClipPlanes;
198 // =======================================================================
199 // function : SetDrawBufferLeft
201 // =======================================================================
202 void OpenGl_Context::SetDrawBufferLeft()
204 switch (myDrawBuffer)
208 glDrawBuffer (GL_BACK_LEFT);
209 myDrawBuffer = GL_BACK_LEFT;
212 case GL_FRONT_RIGHT :
214 glDrawBuffer (GL_FRONT_LEFT);
215 myDrawBuffer = GL_FRONT_LEFT;
218 case GL_FRONT_AND_BACK :
220 glDrawBuffer (GL_LEFT);
221 myDrawBuffer = GL_LEFT;
226 // =======================================================================
227 // function : SetDrawBufferRight
229 // =======================================================================
230 void OpenGl_Context::SetDrawBufferRight()
232 switch (myDrawBuffer)
236 glDrawBuffer (GL_BACK_RIGHT);
237 myDrawBuffer = GL_BACK_RIGHT;
242 glDrawBuffer (GL_FRONT_RIGHT);
243 myDrawBuffer = GL_FRONT_RIGHT;
246 case GL_FRONT_AND_BACK :
248 glDrawBuffer (GL_RIGHT);
249 myDrawBuffer = GL_RIGHT;
254 // =======================================================================
255 // function : SetDrawBufferMono
257 // =======================================================================
258 void OpenGl_Context::SetDrawBufferMono()
260 switch (myDrawBuffer)
264 glDrawBuffer (GL_BACK);
265 myDrawBuffer = GL_BACK;
269 case GL_FRONT_RIGHT :
270 glDrawBuffer (GL_FRONT);
271 myDrawBuffer = GL_FRONT;
276 glDrawBuffer (GL_FRONT_AND_BACK);
277 myDrawBuffer = GL_FRONT_AND_BACK;
282 // =======================================================================
283 // function : FetchState
285 // =======================================================================
286 void OpenGl_Context::FetchState()
288 // cache feedback mode state
289 glGetIntegerv (GL_RENDER_MODE, &myRenderMode);
291 // cache draw buffer state
292 glGetIntegerv (GL_DRAW_BUFFER, &myDrawBuffer);
295 // =======================================================================
298 // =======================================================================
299 void OpenGl_Context::Share (const Handle(OpenGl_Context)& theShareCtx)
301 if (!theShareCtx.IsNull())
303 mySharedResources = theShareCtx->mySharedResources;
304 myDelayed = theShareCtx->myDelayed;
305 myReleaseQueue = theShareCtx->myReleaseQueue;
306 myShaderManager = theShareCtx->myShaderManager;
310 #if !defined(__APPLE__) || defined(MACOSX_USE_GLX)
312 // =======================================================================
313 // function : IsCurrent
315 // =======================================================================
316 Standard_Boolean OpenGl_Context::IsCurrent() const
319 if (myWindowDC == NULL || myGContext == NULL)
321 return Standard_False;
323 return (( (HDC )myWindowDC == wglGetCurrentDC())
324 && ((HGLRC )myGContext == wglGetCurrentContext()));
326 if (myDisplay == NULL || myWindow == 0 || myGContext == 0)
328 return Standard_False;
331 return ( ((Display* )myDisplay == glXGetCurrentDisplay())
332 && ((GLXContext )myGContext == glXGetCurrentContext())
333 && ((GLXDrawable )myWindow == glXGetCurrentDrawable()));
337 // =======================================================================
338 // function : MakeCurrent
340 // =======================================================================
341 Standard_Boolean OpenGl_Context::MakeCurrent()
344 if (myWindowDC == NULL || myGContext == NULL)
346 Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called before!");
347 return Standard_False;
350 // technically it should be safe to activate already bound GL context
351 // however some drivers (Intel etc.) may FAIL doing this for unknown reason
354 myShaderManager->SetContext (this);
355 return Standard_True;
357 else if (wglMakeCurrent ((HDC )myWindowDC, (HGLRC )myGContext) != TRUE)
359 // notice that glGetError() couldn't be used here!
360 wchar_t* aMsgBuff = NULL;
361 DWORD anErrorCode = GetLastError();
362 FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
363 NULL, anErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (wchar_t* )&aMsgBuff, 0, NULL);
364 TCollection_ExtendedString aMsg ("wglMakeCurrent() has failed. ");
365 if (aMsgBuff != NULL)
367 aMsg += (Standard_ExtString )aMsgBuff;
368 LocalFree (aMsgBuff);
370 PushMessage (GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB, GL_DEBUG_TYPE_ERROR_ARB, (unsigned int )anErrorCode, GL_DEBUG_SEVERITY_HIGH_ARB, aMsg);
371 myIsInitialized = Standard_False;
372 return Standard_False;
375 if (myDisplay == NULL || myWindow == 0 || myGContext == 0)
377 Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called before!");
378 return Standard_False;
381 if (!glXMakeCurrent ((Display* )myDisplay, (GLXDrawable )myWindow, (GLXContext )myGContext))
383 // if there is no current context it might be impossible to use glGetError() correctly
384 PushMessage (GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB, GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB,
385 "glXMakeCurrent() has failed!");
386 myIsInitialized = Standard_False;
387 return Standard_False;
390 myShaderManager->SetContext (this);
391 return Standard_True;
394 // =======================================================================
395 // function : SwapBuffers
397 // =======================================================================
398 void OpenGl_Context::SwapBuffers()
401 if ((HDC )myWindowDC != NULL)
403 ::SwapBuffers ((HDC )myWindowDC);
407 if ((Display* )myDisplay != NULL)
409 glXSwapBuffers ((Display* )myDisplay, (GLXDrawable )myWindow);
416 // =======================================================================
417 // function : findProc
419 // =======================================================================
420 void* OpenGl_Context::findProc (const char* theFuncName)
423 return wglGetProcAddress (theFuncName);
424 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
425 return (myGlLibHandle != NULL) ? dlsym (myGlLibHandle, theFuncName) : NULL;
427 return (void* )glXGetProcAddress ((const GLubyte* )theFuncName);
431 // =======================================================================
432 // function : CheckExtension
434 // =======================================================================
435 Standard_Boolean OpenGl_Context::CheckExtension (const char* theExtName) const
437 if (theExtName == NULL)
439 std::cerr << "CheckExtension called with NULL string!\n";
440 return Standard_False;
443 // available since OpenGL 3.0
444 // and the ONLY way to check extensions with OpenGL 3.1+ core profile
445 /**if (IsGlGreaterEqual (3, 0))
448 glGetIntegerv (GL_NUM_EXTENSIONS, &anExtNb);
449 for (GLint anIter = 0; anIter < anExtNb; ++anIter)
451 const char* anExtension = (const char* )core30->glGetStringi (GL_EXTENSIONS, (GLuint )anIter);
452 if (anExtension[anExtNameLen] == '\0' &&
453 strncmp (anExtension, theExtName, anExtNameLen) == 0)
455 return Standard_True;
458 return Standard_False;
461 // use old way with huge string for all extensions
462 const char* anExtString = (const char* )glGetString (GL_EXTENSIONS);
463 if (anExtString == NULL)
465 Messenger()->Send ("TKOpenGL: glGetString (GL_EXTENSIONS) has returned NULL! No GL context?", Message_Warning);
466 return Standard_False;
468 return CheckExtension (anExtString, theExtName);
471 // =======================================================================
472 // function : CheckExtension
474 // =======================================================================
475 Standard_Boolean OpenGl_Context::CheckExtension (const char* theExtString,
476 const char* theExtName)
478 if (theExtString == NULL)
480 return Standard_False;
483 // Search for theExtName in the extensions string.
484 // Use of strstr() is not sufficient because extension names can be prefixes of other extension names.
485 char* aPtrIter = (char* )theExtString;
486 const char* aPtrEnd = aPtrIter + strlen (theExtString);
487 const size_t anExtNameLen = strlen (theExtName);
488 while (aPtrIter < aPtrEnd)
490 const size_t n = strcspn (aPtrIter, " ");
491 if ((n == anExtNameLen) && (strncmp (aPtrIter, theExtName, anExtNameLen) == 0))
493 return Standard_True;
497 return Standard_False;
500 #if !defined(__APPLE__) || defined(MACOSX_USE_GLX)
502 // =======================================================================
505 // =======================================================================
506 Standard_Boolean OpenGl_Context::Init()
510 return Standard_True;
514 myWindowDC = (Aspect_Handle )wglGetCurrentDC();
515 myGContext = (Aspect_RenderingContext )wglGetCurrentContext();
517 myDisplay = (Aspect_Display )glXGetCurrentDisplay();
518 myGContext = (Aspect_RenderingContext )glXGetCurrentContext();
519 myWindow = (Aspect_Drawable )glXGetCurrentDrawable();
521 if (myGContext == NULL)
523 return Standard_False;
527 myIsInitialized = Standard_True;
528 return Standard_True;
533 // =======================================================================
536 // =======================================================================
538 Standard_Boolean OpenGl_Context::Init (const Aspect_Handle theWindow,
539 const Aspect_Handle theWindowDC,
540 const Aspect_RenderingContext theGContext)
541 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
542 Standard_Boolean OpenGl_Context::Init (const void* theGContext)
544 Standard_Boolean OpenGl_Context::Init (const Aspect_Drawable theWindow,
545 const Aspect_Display theDisplay,
546 const Aspect_RenderingContext theGContext)
549 Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called only once!");
551 myWindow = theWindow;
552 myGContext = theGContext;
553 myWindowDC = theWindowDC;
554 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
555 myGContext = (void* )theGContext;
557 myWindow = theWindow;
558 myGContext = theGContext;
559 myDisplay = theDisplay;
561 if (myGContext == NULL || !MakeCurrent())
563 return Standard_False;
567 myIsInitialized = Standard_True;
568 return Standard_True;
571 // =======================================================================
572 // function : ResetErrors
574 // =======================================================================
575 void OpenGl_Context::ResetErrors()
577 while (glGetError() != GL_NO_ERROR)
583 // =======================================================================
584 // function : readGlVersion
586 // =======================================================================
587 void OpenGl_Context::readGlVersion()
593 // available since OpenGL 3.0
594 GLint aMajor = 0, aMinor = 0;
595 glGetIntegerv (GL_MAJOR_VERSION, &aMajor);
596 glGetIntegerv (GL_MINOR_VERSION, &aMinor);
597 // glGetError() sometimes does not report an error here even if
598 // GL does not know GL_MAJOR_VERSION and GL_MINOR_VERSION constants.
599 // This happens on some rendereres like e.g. Cygwin MESA.
600 // Thus checking additionally if GL has put anything to
601 // the output variables.
602 if (glGetError() == GL_NO_ERROR && aMajor != 0 && aMinor != 0)
604 myGlVerMajor = aMajor;
605 myGlVerMinor = aMinor;
610 // Read version string.
611 // Notice that only first two numbers splitted by point '2.1 XXXXX' are significant.
612 // Following trash (after space) is vendor-specific.
613 // New drivers also returns micro version of GL like '3.3.0' which has no meaning
614 // and should be considered as vendor-specific too.
615 const char* aVerStr = (const char* )glGetString (GL_VERSION);
616 if (aVerStr == NULL || *aVerStr == '\0')
618 // invalid GL context
622 // parse string for major number
626 while (aVerStr[aMajIter] >= '0' && aVerStr[aMajIter] <= '9')
630 if (aMajIter == 0 || aMajIter >= sizeof(aMajorStr))
634 memcpy (aMajorStr, aVerStr, aMajIter);
635 aMajorStr[aMajIter] = '\0';
637 // parse string for minor number
638 aVerStr += aMajIter + 1;
640 while (aVerStr[aMinIter] >= '0' && aVerStr[aMinIter] <= '9')
644 if (aMinIter == 0 || aMinIter >= sizeof(aMinorStr))
648 memcpy (aMinorStr, aVerStr, aMinIter);
649 aMinorStr[aMinIter] = '\0';
652 myGlVerMajor = atoi (aMajorStr);
653 myGlVerMinor = atoi (aMinorStr);
655 if (myGlVerMajor <= 0)
662 static Standard_CString THE_DBGMSG_UNKNOWN = "UNKNOWN";
663 static Standard_CString THE_DBGMSG_SOURCES[] =
665 ".OpenGL", // GL_DEBUG_SOURCE_API_ARB
666 ".WinSystem", // GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB
667 ".GLSL", // GL_DEBUG_SOURCE_SHADER_COMPILER_ARB
668 ".3rdParty", // GL_DEBUG_SOURCE_THIRD_PARTY_ARB
669 "", // GL_DEBUG_SOURCE_APPLICATION_ARB
670 ".Other" // GL_DEBUG_SOURCE_OTHER_ARB
673 static Standard_CString THE_DBGMSG_TYPES[] =
675 "Error", // GL_DEBUG_TYPE_ERROR_ARB
676 "Deprecated", // GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB
677 "Undef. behavior", // GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB
678 "Portability", // GL_DEBUG_TYPE_PORTABILITY_ARB
679 "Performance", // GL_DEBUG_TYPE_PERFORMANCE_ARB
680 "Other" // GL_DEBUG_TYPE_OTHER_ARB
683 static Standard_CString THE_DBGMSG_SEV_HIGH = "High"; // GL_DEBUG_SEVERITY_HIGH_ARB
684 static Standard_CString THE_DBGMSG_SEV_MEDIUM = "Medium"; // GL_DEBUG_SEVERITY_MEDIUM_ARB
685 static Standard_CString THE_DBGMSG_SEV_LOW = "Low"; // GL_DEBUG_SEVERITY_LOW_ARB
687 //! Callback for GL_ARB_debug_output extension
688 static void APIENTRY debugCallbackWrap(unsigned int theSource,
689 unsigned int theType,
691 unsigned int theSeverity,
693 const char* theMessage,
694 const void* theUserParam)
696 OpenGl_Context* aCtx = (OpenGl_Context* )theUserParam;
697 aCtx->PushMessage (theSource, theType, theId, theSeverity, theMessage);
700 // =======================================================================
701 // function : PushMessage
703 // =======================================================================
704 void OpenGl_Context::PushMessage (const unsigned int theSource,
705 const unsigned int theType,
706 const unsigned int theId,
707 const unsigned int theSeverity,
708 const TCollection_ExtendedString& theMessage)
710 //OpenGl_Context* aCtx = (OpenGl_Context* )theUserParam;
711 Standard_CString& aSrc = (theSource >= GL_DEBUG_SOURCE_API_ARB
712 && theSource <= GL_DEBUG_SOURCE_OTHER_ARB)
713 ? THE_DBGMSG_SOURCES[theSource - GL_DEBUG_SOURCE_API_ARB]
714 : THE_DBGMSG_UNKNOWN;
715 Standard_CString& aType = (theType >= GL_DEBUG_TYPE_ERROR_ARB
716 && theType <= GL_DEBUG_TYPE_OTHER_ARB)
717 ? THE_DBGMSG_TYPES[theType - GL_DEBUG_TYPE_ERROR_ARB]
718 : THE_DBGMSG_UNKNOWN;
719 Standard_CString& aSev = theSeverity == GL_DEBUG_SEVERITY_HIGH_ARB
720 ? THE_DBGMSG_SEV_HIGH
721 : (theSeverity == GL_DEBUG_SEVERITY_MEDIUM_ARB
722 ? THE_DBGMSG_SEV_MEDIUM
723 : THE_DBGMSG_SEV_LOW);
724 Message_Gravity aGrav = theSeverity == GL_DEBUG_SEVERITY_HIGH_ARB
726 : (theSeverity == GL_DEBUG_SEVERITY_MEDIUM_ARB
730 TCollection_ExtendedString aMsg;
731 aMsg += "TKOpenGl"; aMsg += aSrc;
732 aMsg += " | Type: "; aMsg += aType;
733 aMsg += " | ID: "; aMsg += (Standard_Integer )theId;
734 aMsg += " | Severity: "; aMsg += aSev;
735 aMsg += " | Message:\n ";
738 Messenger()->Send (aMsg, aGrav);
741 // =======================================================================
744 // =======================================================================
745 void OpenGl_Context::init()
750 arbNPTW = CheckExtension ("GL_ARB_texture_non_power_of_two");
751 extBgra = CheckExtension ("GL_EXT_bgra");
752 extAnis = CheckExtension ("GL_EXT_texture_filter_anisotropic");
753 extPDS = CheckExtension ("GL_EXT_packed_depth_stencil");
754 atiMem = CheckExtension ("GL_ATI_meminfo");
755 nvxMem = CheckExtension ("GL_NVX_gpu_memory_info");
757 // get number of maximum clipping planes
758 glGetIntegerv (GL_MAX_CLIP_PLANES, &myMaxClipPlanes);
759 glGetIntegerv (GL_MAX_TEXTURE_SIZE, &myMaxTexDim);
762 glGetIntegerv (GL_STEREO, &aStereo);
763 myIsStereoBuffers = aStereo == 1;
767 glGetIntegerv (GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &myAnisoMax);
770 myClippingState.Init (myMaxClipPlanes);
772 // initialize debug context extension
773 if (CheckExtension ("GL_ARB_debug_output"))
775 arbDbg = new OpenGl_ArbDbg();
776 memset (arbDbg, 0, sizeof(OpenGl_ArbDbg)); // nullify whole structure
777 if (!FindProcShort (arbDbg, glDebugMessageControlARB)
778 || !FindProcShort (arbDbg, glDebugMessageInsertARB)
779 || !FindProcShort (arbDbg, glDebugMessageCallbackARB)
780 || !FindProcShort (arbDbg, glGetDebugMessageLogARB))
786 && caps->contextDebug)
788 // setup default callback
789 arbDbg->glDebugMessageCallbackARB (debugCallbackWrap, this);
791 glEnable (GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
796 // initialize VBO extension (ARB)
797 if (CheckExtension ("GL_ARB_vertex_buffer_object"))
799 arbVBO = new OpenGl_ArbVBO();
800 memset (arbVBO, 0, sizeof(OpenGl_ArbVBO)); // nullify whole structure
801 if (!FindProcShort (arbVBO, glGenBuffersARB)
802 || !FindProcShort (arbVBO, glBindBufferARB)
803 || !FindProcShort (arbVBO, glBufferDataARB)
804 || !FindProcShort (arbVBO, glDeleteBuffersARB))
811 // initialize TBO extension (ARB)
812 if (CheckExtension ("GL_ARB_texture_buffer_object"))
814 arbTBO = new OpenGl_ArbTBO();
815 memset (arbTBO, 0, sizeof(OpenGl_ArbTBO)); // nullify whole structure
816 if (!FindProcShort (arbTBO, glTexBufferARB))
823 // initialize hardware instancing extension (ARB)
824 if (CheckExtension ("GL_ARB_draw_instanced"))
826 arbIns = new OpenGl_ArbIns();
827 memset (arbIns, 0, sizeof(OpenGl_ArbIns)); // nullify whole structure
828 if (!FindProcShort (arbIns, glDrawArraysInstancedARB)
829 || !FindProcShort (arbIns, glDrawElementsInstancedARB))
836 // initialize FBO extension (EXT)
837 if (CheckExtension ("GL_EXT_framebuffer_object"))
839 extFBO = new OpenGl_ExtFBO();
840 memset (extFBO, 0, sizeof(OpenGl_ExtFBO)); // nullify whole structure
841 if (!FindProcShort (extFBO, glGenFramebuffersEXT)
842 || !FindProcShort (extFBO, glDeleteFramebuffersEXT)
843 || !FindProcShort (extFBO, glBindFramebufferEXT)
844 || !FindProcShort (extFBO, glFramebufferTexture2DEXT)
845 || !FindProcShort (extFBO, glCheckFramebufferStatusEXT)
846 || !FindProcShort (extFBO, glGenRenderbuffersEXT)
847 || !FindProcShort (extFBO, glDeleteRenderbuffersEXT)
848 || !FindProcShort (extFBO, glBindRenderbufferEXT)
849 || !FindProcShort (extFBO, glRenderbufferStorageEXT)
850 || !FindProcShort (extFBO, glFramebufferRenderbufferEXT)
851 || !FindProcShort (extFBO, glGenerateMipmapEXT))
858 // initialize GS extension (EXT)
859 if (CheckExtension ("GL_EXT_geometry_shader4"))
861 extGS = new OpenGl_ExtGS();
862 memset (extGS, 0, sizeof(OpenGl_ExtGS)); // nullify whole structure
863 if (!FindProcShort (extGS, glProgramParameteriEXT))
870 myGlCore20 = new OpenGl_GlCore20();
871 memset (myGlCore20, 0, sizeof(OpenGl_GlCore20)); // nullify whole structure
873 // Check if OpenGL 1.2 core functionality is actually present
874 Standard_Boolean hasGlCore12 = IsGlGreaterEqual (1, 2)
875 && FindProcShort (myGlCore20, glBlendColor)
876 && FindProcShort (myGlCore20, glBlendEquation)
877 && FindProcShort (myGlCore20, glDrawRangeElements)
878 && FindProcShort (myGlCore20, glTexImage3D)
879 && FindProcShort (myGlCore20, glTexSubImage3D)
880 && FindProcShort (myGlCore20, glCopyTexSubImage3D);
882 // Check if OpenGL 1.3 core functionality is actually present
883 Standard_Boolean hasGlCore13 = IsGlGreaterEqual (1, 3)
884 && FindProcShort (myGlCore20, glActiveTexture)
885 && FindProcShort (myGlCore20, glSampleCoverage)
886 && FindProcShort (myGlCore20, glCompressedTexImage3D)
887 && FindProcShort (myGlCore20, glCompressedTexImage2D)
888 && FindProcShort (myGlCore20, glCompressedTexImage1D)
889 && FindProcShort (myGlCore20, glCompressedTexSubImage3D)
890 && FindProcShort (myGlCore20, glCompressedTexSubImage2D)
891 && FindProcShort (myGlCore20, glCompressedTexSubImage1D)
892 && FindProcShort (myGlCore20, glGetCompressedTexImage)
894 && FindProcShort (myGlCore20, glClientActiveTexture)
895 && FindProcShort (myGlCore20, glMultiTexCoord1d)
896 && FindProcShort (myGlCore20, glMultiTexCoord1dv)
897 && FindProcShort (myGlCore20, glMultiTexCoord1f)
898 && FindProcShort (myGlCore20, glMultiTexCoord1fv)
899 && FindProcShort (myGlCore20, glMultiTexCoord1i)
900 && FindProcShort (myGlCore20, glMultiTexCoord1iv)
901 && FindProcShort (myGlCore20, glMultiTexCoord1s)
902 && FindProcShort (myGlCore20, glMultiTexCoord1sv)
903 && FindProcShort (myGlCore20, glMultiTexCoord2d)
904 && FindProcShort (myGlCore20, glMultiTexCoord2dv)
905 && FindProcShort (myGlCore20, glMultiTexCoord2f)
906 && FindProcShort (myGlCore20, glMultiTexCoord2fv)
907 && FindProcShort (myGlCore20, glMultiTexCoord2i)
908 && FindProcShort (myGlCore20, glMultiTexCoord2iv)
909 && FindProcShort (myGlCore20, glMultiTexCoord2s)
910 && FindProcShort (myGlCore20, glMultiTexCoord2sv)
911 && FindProcShort (myGlCore20, glMultiTexCoord3d)
912 && FindProcShort (myGlCore20, glMultiTexCoord3dv)
913 && FindProcShort (myGlCore20, glMultiTexCoord3f)
914 && FindProcShort (myGlCore20, glMultiTexCoord3fv)
915 && FindProcShort (myGlCore20, glMultiTexCoord3i)
916 && FindProcShort (myGlCore20, glMultiTexCoord3iv)
917 && FindProcShort (myGlCore20, glMultiTexCoord3s)
918 && FindProcShort (myGlCore20, glMultiTexCoord3sv)
919 && FindProcShort (myGlCore20, glMultiTexCoord4d)
920 && FindProcShort (myGlCore20, glMultiTexCoord4dv)
921 && FindProcShort (myGlCore20, glMultiTexCoord4f)
922 && FindProcShort (myGlCore20, glMultiTexCoord4fv)
923 && FindProcShort (myGlCore20, glMultiTexCoord4i)
924 && FindProcShort (myGlCore20, glMultiTexCoord4iv)
925 && FindProcShort (myGlCore20, glMultiTexCoord4s)
926 && FindProcShort (myGlCore20, glMultiTexCoord4sv)
927 && FindProcShort (myGlCore20, glLoadTransposeMatrixf)
928 && FindProcShort (myGlCore20, glLoadTransposeMatrixd)
929 && FindProcShort (myGlCore20, glMultTransposeMatrixf)
930 && FindProcShort (myGlCore20, glMultTransposeMatrixd);
932 // Check if OpenGL 1.4 core functionality is actually present
933 Standard_Boolean hasGlCore14 = IsGlGreaterEqual (1, 4)
934 && FindProcShort (myGlCore20, glBlendFuncSeparate)
935 && FindProcShort (myGlCore20, glMultiDrawArrays)
936 && FindProcShort (myGlCore20, glMultiDrawElements)
937 && FindProcShort (myGlCore20, glPointParameterf)
938 && FindProcShort (myGlCore20, glPointParameterfv)
939 && FindProcShort (myGlCore20, glPointParameteri)
940 && FindProcShort (myGlCore20, glPointParameteriv);
942 // Check if OpenGL 1.5 core functionality is actually present
943 Standard_Boolean hasGlCore15 = IsGlGreaterEqual (1, 5)
944 && FindProcShort (myGlCore20, glGenQueries)
945 && FindProcShort (myGlCore20, glDeleteQueries)
946 && FindProcShort (myGlCore20, glIsQuery)
947 && FindProcShort (myGlCore20, glBeginQuery)
948 && FindProcShort (myGlCore20, glEndQuery)
949 && FindProcShort (myGlCore20, glGetQueryiv)
950 && FindProcShort (myGlCore20, glGetQueryObjectiv)
951 && FindProcShort (myGlCore20, glGetQueryObjectuiv)
952 && FindProcShort (myGlCore20, glBindBuffer)
953 && FindProcShort (myGlCore20, glDeleteBuffers)
954 && FindProcShort (myGlCore20, glGenBuffers)
955 && FindProcShort (myGlCore20, glIsBuffer)
956 && FindProcShort (myGlCore20, glBufferData)
957 && FindProcShort (myGlCore20, glBufferSubData)
958 && FindProcShort (myGlCore20, glGetBufferSubData)
959 && FindProcShort (myGlCore20, glMapBuffer)
960 && FindProcShort (myGlCore20, glUnmapBuffer)
961 && FindProcShort (myGlCore20, glGetBufferParameteriv)
962 && FindProcShort (myGlCore20, glGetBufferPointerv);
964 // Check if OpenGL 2.0 core functionality is actually present
965 Standard_Boolean hasGlCore20 = IsGlGreaterEqual (2, 0)
966 && FindProcShort (myGlCore20, glBlendEquationSeparate)
967 && FindProcShort (myGlCore20, glDrawBuffers)
968 && FindProcShort (myGlCore20, glStencilOpSeparate)
969 && FindProcShort (myGlCore20, glStencilFuncSeparate)
970 && FindProcShort (myGlCore20, glStencilMaskSeparate)
971 && FindProcShort (myGlCore20, glAttachShader)
972 && FindProcShort (myGlCore20, glBindAttribLocation)
973 && FindProcShort (myGlCore20, glCompileShader)
974 && FindProcShort (myGlCore20, glCreateProgram)
975 && FindProcShort (myGlCore20, glCreateShader)
976 && FindProcShort (myGlCore20, glDeleteProgram)
977 && FindProcShort (myGlCore20, glDeleteShader)
978 && FindProcShort (myGlCore20, glDetachShader)
979 && FindProcShort (myGlCore20, glDisableVertexAttribArray)
980 && FindProcShort (myGlCore20, glEnableVertexAttribArray)
981 && FindProcShort (myGlCore20, glGetActiveAttrib)
982 && FindProcShort (myGlCore20, glGetActiveUniform)
983 && FindProcShort (myGlCore20, glGetAttachedShaders)
984 && FindProcShort (myGlCore20, glGetAttribLocation)
985 && FindProcShort (myGlCore20, glGetProgramiv)
986 && FindProcShort (myGlCore20, glGetProgramInfoLog)
987 && FindProcShort (myGlCore20, glGetShaderiv)
988 && FindProcShort (myGlCore20, glGetShaderInfoLog)
989 && FindProcShort (myGlCore20, glGetShaderSource)
990 && FindProcShort (myGlCore20, glGetUniformLocation)
991 && FindProcShort (myGlCore20, glGetUniformfv)
992 && FindProcShort (myGlCore20, glGetUniformiv)
993 && FindProcShort (myGlCore20, glGetVertexAttribdv)
994 && FindProcShort (myGlCore20, glGetVertexAttribfv)
995 && FindProcShort (myGlCore20, glGetVertexAttribiv)
996 && FindProcShort (myGlCore20, glGetVertexAttribPointerv)
997 && FindProcShort (myGlCore20, glIsProgram)
998 && FindProcShort (myGlCore20, glIsShader)
999 && FindProcShort (myGlCore20, glLinkProgram)
1000 && FindProcShort (myGlCore20, glShaderSource)
1001 && FindProcShort (myGlCore20, glUseProgram)
1002 && FindProcShort (myGlCore20, glUniform1f)
1003 && FindProcShort (myGlCore20, glUniform2f)
1004 && FindProcShort (myGlCore20, glUniform3f)
1005 && FindProcShort (myGlCore20, glUniform4f)
1006 && FindProcShort (myGlCore20, glUniform1i)
1007 && FindProcShort (myGlCore20, glUniform2i)
1008 && FindProcShort (myGlCore20, glUniform3i)
1009 && FindProcShort (myGlCore20, glUniform4i)
1010 && FindProcShort (myGlCore20, glUniform1fv)
1011 && FindProcShort (myGlCore20, glUniform2fv)
1012 && FindProcShort (myGlCore20, glUniform3fv)
1013 && FindProcShort (myGlCore20, glUniform4fv)
1014 && FindProcShort (myGlCore20, glUniform1iv)
1015 && FindProcShort (myGlCore20, glUniform2iv)
1016 && FindProcShort (myGlCore20, glUniform3iv)
1017 && FindProcShort (myGlCore20, glUniform4iv)
1018 && FindProcShort (myGlCore20, glUniformMatrix2fv)
1019 && FindProcShort (myGlCore20, glUniformMatrix3fv)
1020 && FindProcShort (myGlCore20, glUniformMatrix4fv)
1021 && FindProcShort (myGlCore20, glValidateProgram)
1022 && FindProcShort (myGlCore20, glVertexAttrib1d)
1023 && FindProcShort (myGlCore20, glVertexAttrib1dv)
1024 && FindProcShort (myGlCore20, glVertexAttrib1f)
1025 && FindProcShort (myGlCore20, glVertexAttrib1fv)
1026 && FindProcShort (myGlCore20, glVertexAttrib1s)
1027 && FindProcShort (myGlCore20, glVertexAttrib1sv)
1028 && FindProcShort (myGlCore20, glVertexAttrib2d)
1029 && FindProcShort (myGlCore20, glVertexAttrib2dv)
1030 && FindProcShort (myGlCore20, glVertexAttrib2f)
1031 && FindProcShort (myGlCore20, glVertexAttrib2fv)
1032 && FindProcShort (myGlCore20, glVertexAttrib2s)
1033 && FindProcShort (myGlCore20, glVertexAttrib2sv)
1034 && FindProcShort (myGlCore20, glVertexAttrib3d)
1035 && FindProcShort (myGlCore20, glVertexAttrib3dv)
1036 && FindProcShort (myGlCore20, glVertexAttrib3f)
1037 && FindProcShort (myGlCore20, glVertexAttrib3fv)
1038 && FindProcShort (myGlCore20, glVertexAttrib3s)
1039 && FindProcShort (myGlCore20, glVertexAttrib3sv)
1040 && FindProcShort (myGlCore20, glVertexAttrib4Nbv)
1041 && FindProcShort (myGlCore20, glVertexAttrib4Niv)
1042 && FindProcShort (myGlCore20, glVertexAttrib4Nsv)
1043 && FindProcShort (myGlCore20, glVertexAttrib4Nub)
1044 && FindProcShort (myGlCore20, glVertexAttrib4Nubv)
1045 && FindProcShort (myGlCore20, glVertexAttrib4Nuiv)
1046 && FindProcShort (myGlCore20, glVertexAttrib4Nusv)
1047 && FindProcShort (myGlCore20, glVertexAttrib4bv)
1048 && FindProcShort (myGlCore20, glVertexAttrib4d)
1049 && FindProcShort (myGlCore20, glVertexAttrib4dv)
1050 && FindProcShort (myGlCore20, glVertexAttrib4f)
1051 && FindProcShort (myGlCore20, glVertexAttrib4fv)
1052 && FindProcShort (myGlCore20, glVertexAttrib4iv)
1053 && FindProcShort (myGlCore20, glVertexAttrib4s)
1054 && FindProcShort (myGlCore20, glVertexAttrib4sv)
1055 && FindProcShort (myGlCore20, glVertexAttrib4ubv)
1056 && FindProcShort (myGlCore20, glVertexAttrib4uiv)
1057 && FindProcShort (myGlCore20, glVertexAttrib4usv)
1058 && FindProcShort (myGlCore20, glVertexAttribPointer);
1068 core12 = myGlCore20;
1078 core13 = myGlCore20;
1088 core14 = myGlCore20;
1098 core15 = myGlCore20;
1107 core20 = myGlCore20;
1111 // =======================================================================
1112 // function : MemoryInfo
1114 // =======================================================================
1115 Standard_Size OpenGl_Context::AvailableMemory() const
1119 // this is actually information for VBO pool
1120 // however because pools are mostly shared
1121 // it can be used for total GPU memory estimations
1124 glGetIntegerv (GL_VBO_FREE_MEMORY_ATI, aMemInfo);
1125 // returned value is in KiB, however this maybe changed in future
1126 return Standard_Size(aMemInfo[0]) * 1024;
1130 // current available dedicated video memory (in KiB), currently unused GPU memory
1132 glGetIntegerv (GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &aMemInfo);
1133 return Standard_Size(aMemInfo) * 1024;
1138 // =======================================================================
1139 // function : MemoryInfo
1141 // =======================================================================
1142 TCollection_AsciiString OpenGl_Context::MemoryInfo() const
1144 TCollection_AsciiString anInfo;
1148 memset (aValues, 0, sizeof(aValues));
1149 glGetIntegerv (GL_VBO_FREE_MEMORY_ATI, aValues);
1151 // total memory free in the pool
1152 anInfo += TCollection_AsciiString (" GPU free memory: ") + (aValues[0] / 1024) + " MiB\n";
1154 // largest available free block in the pool
1155 anInfo += TCollection_AsciiString (" Largest free block: ") + (aValues[1] / 1024) + " MiB\n";
1156 if (aValues[2] != aValues[0])
1158 // total auxiliary memory free
1159 anInfo += TCollection_AsciiString (" Free memory: ") + (aValues[2] / 1024) + " MiB\n";
1164 //current available dedicated video memory (in KiB), currently unused GPU memory
1166 glGetIntegerv (GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &aValue);
1167 anInfo += TCollection_AsciiString (" GPU free memory: ") + (aValue / 1024) + " MiB\n";
1169 // dedicated video memory, total size (in KiB) of the GPU memory
1170 GLint aDedicated = 0;
1171 glGetIntegerv (GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, &aDedicated);
1172 anInfo += TCollection_AsciiString (" GPU memory: ") + (aDedicated / 1024) + " MiB\n";
1174 // total available memory, total size (in KiB) of the memory available for allocations
1175 glGetIntegerv (GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, &aValue);
1176 if (aValue != aDedicated)
1178 // different only for special configurations
1179 anInfo += TCollection_AsciiString (" Total memory: ") + (aValue / 1024) + " MiB\n";
1186 // =======================================================================
1187 // function : GetResource
1189 // =======================================================================
1190 const Handle(OpenGl_Resource)& OpenGl_Context::GetResource (const TCollection_AsciiString& theKey) const
1192 return mySharedResources->IsBound (theKey) ? mySharedResources->Find (theKey) : NULL_GL_RESOURCE;
1195 // =======================================================================
1196 // function : ShareResource
1198 // =======================================================================
1199 Standard_Boolean OpenGl_Context::ShareResource (const TCollection_AsciiString& theKey,
1200 const Handle(OpenGl_Resource)& theResource)
1202 if (theKey.IsEmpty() || theResource.IsNull())
1204 return Standard_False;
1206 return mySharedResources->Bind (theKey, theResource);
1209 // =======================================================================
1210 // function : ReleaseResource
1212 // =======================================================================
1213 void OpenGl_Context::ReleaseResource (const TCollection_AsciiString& theKey,
1214 const Standard_Boolean theToDelay)
1216 if (!mySharedResources->IsBound (theKey))
1220 const Handle(OpenGl_Resource)& aRes = mySharedResources->Find (theKey);
1221 if (aRes->GetRefCount() > 1)
1228 myDelayed->Bind (theKey, 1);
1232 aRes->Release (this);
1233 mySharedResources->UnBind (theKey);
1237 // =======================================================================
1238 // function : DelayedRelease
1240 // =======================================================================
1241 void OpenGl_Context::DelayedRelease (Handle(OpenGl_Resource)& theResource)
1243 myReleaseQueue->Push (theResource);
1244 theResource.Nullify();
1247 // =======================================================================
1248 // function : ReleaseDelayed
1250 // =======================================================================
1251 void OpenGl_Context::ReleaseDelayed()
1253 // release queued elements
1254 while (!myReleaseQueue->IsEmpty())
1256 myReleaseQueue->Front()->Release (this);
1257 myReleaseQueue->Pop();
1260 // release delayed shared resoruces
1261 NCollection_Vector<TCollection_AsciiString> aDeadList;
1262 for (NCollection_DataMap<TCollection_AsciiString, Standard_Integer>::Iterator anIter (*myDelayed);
1263 anIter.More(); anIter.Next())
1265 if (++anIter.ChangeValue() <= 2)
1267 continue; // postpone release one more frame to ensure noone use it periodically
1270 const TCollection_AsciiString& aKey = anIter.Key();
1271 if (!mySharedResources->IsBound (aKey))
1273 // mixed unshared strategy delayed/undelayed was used!
1274 aDeadList.Append (aKey);
1278 Handle(OpenGl_Resource)& aRes = mySharedResources->ChangeFind (aKey);
1279 if (aRes->GetRefCount() > 1)
1281 // should be only 1 instance in mySharedResources
1282 // if not - resource was reused again
1283 aDeadList.Append (aKey);
1287 // release resource if no one requiested it more than 2 redraw calls
1288 aRes->Release (this);
1289 mySharedResources->UnBind (aKey);
1290 aDeadList.Append (aKey);
1293 for (Standard_Integer anIter = 0; anIter < aDeadList.Length(); ++anIter)
1295 myDelayed->UnBind (aDeadList.Value (anIter));