1 // Created on: 2012-01-26
2 // Created by: Kirill GAVRILOV
3 // Copyright (c) 2012 OPEN CASCADE SAS
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
24 #include <OpenGl_Context.hxx>
26 #include <OpenGl_ArbVBO.hxx>
27 #include <OpenGl_ArbTBO.hxx>
28 #include <OpenGl_ArbIns.hxx>
29 #include <OpenGl_ArbDbg.hxx>
30 #include <OpenGl_ExtFBO.hxx>
31 #include <OpenGl_ExtGS.hxx>
32 #include <OpenGl_GlCore20.hxx>
33 #include <OpenGl_ShaderManager.hxx>
35 #include <Message_Messenger.hxx>
37 #include <NCollection_Vector.hxx>
39 #include <Standard_ProgramError.hxx>
43 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
46 #include <GL/glx.h> // glXGetProcAddress()
49 // GL_NVX_gpu_memory_info
50 #ifndef GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX
53 GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX = 0x9047,
54 GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX = 0x9048,
55 GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX = 0x9049,
56 GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX = 0x904A,
57 GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX = 0x904B
61 IMPLEMENT_STANDARD_HANDLE (OpenGl_Context, Standard_Transient)
62 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Context, Standard_Transient)
64 //! Make record shorter to retrieve function pointer using variable with same name
65 #define FindProcShort(theStruct, theFunc) FindProc(#theFunc, theStruct->theFunc)
69 static const Handle(OpenGl_Resource) NULL_GL_RESOURCE;
70 static const GLdouble OpenGl_DefaultPlaneEq[] = {0.0, 0.0, 0.0, 0.0};
73 // =======================================================================
74 // function : OpenGl_Context
76 // =======================================================================
77 OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps)
83 caps (!theCaps.IsNull() ? theCaps : new OpenGl_Caps()),
84 arbNPTW(Standard_False),
91 extBgra(Standard_False),
92 extAnis(Standard_False),
93 extPDS (Standard_False),
94 atiMem (Standard_False),
95 nvxMem (Standard_False),
96 mySharedResources (new OpenGl_ResourcesMap()),
97 myDelayed (new OpenGl_DelayReleaseMap()),
98 myReleaseQueue (new OpenGl_ResourcesQueue()),
100 myGlLibHandle (NULL),
107 myIsFeedback (Standard_False),
108 myIsInitialized (Standard_False)
110 #if defined(MAC_OS_X_VERSION_10_3) && !defined(MACOSX_USE_GLX)
111 // Vendors can not extend functionality on this system
112 // and developers are limited to OpenGL support provided by Mac OS X SDK.
113 // We retrieve function pointers from system library
114 // to generalize extensions support on all platforms.
115 // In this way we also reach binary compatibility benefit between OS releases
116 // if some newest functionality is optionally used.
117 // Notice that GL version / extension availability checks are required
118 // because function pointers may be available but not functionality itself
119 // (depends on renderer).
120 myGlLibHandle = dlopen ("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY);
123 myShaderManager = new OpenGl_ShaderManager (this);
126 // =======================================================================
127 // function : ~OpenGl_Context
129 // =======================================================================
130 OpenGl_Context::~OpenGl_Context()
132 // release clean up queue
135 // release shared resources if any
136 if (((const Handle(Standard_Transient)& )mySharedResources)->GetRefCount() <= 1)
138 myShaderManager.Nullify();
139 for (NCollection_DataMap<TCollection_AsciiString, Handle(OpenGl_Resource)>::Iterator anIter (*mySharedResources);
140 anIter.More(); anIter.Next())
142 anIter.Value()->Release (this);
147 myShaderManager->SetContext (NULL);
149 mySharedResources.Nullify();
153 && caps->contextDebug)
157 glGetPointerv (GL_DEBUG_CALLBACK_USER_PARAM_ARB, &aPtr);
160 arbDbg->glDebugMessageCallbackARB (NULL, NULL);
173 // =======================================================================
174 // function : MaxDegreeOfAnisotropy
176 // =======================================================================
177 Standard_Integer OpenGl_Context::MaxDegreeOfAnisotropy() const
182 // =======================================================================
183 // function : MaxTextureSize
185 // =======================================================================
186 Standard_Integer OpenGl_Context::MaxTextureSize() const
191 // =======================================================================
192 // function : MaxClipPlanes
194 // =======================================================================
195 Standard_Integer OpenGl_Context::MaxClipPlanes() const
197 return myMaxClipPlanes;
200 // =======================================================================
203 // =======================================================================
204 void OpenGl_Context::Share (const Handle(OpenGl_Context)& theShareCtx)
206 if (!theShareCtx.IsNull())
208 mySharedResources = theShareCtx->mySharedResources;
209 myDelayed = theShareCtx->myDelayed;
210 myReleaseQueue = theShareCtx->myReleaseQueue;
211 myShaderManager = theShareCtx->myShaderManager;
215 #if !defined(__APPLE__) || defined(MACOSX_USE_GLX)
217 // =======================================================================
218 // function : IsCurrent
220 // =======================================================================
221 Standard_Boolean OpenGl_Context::IsCurrent() const
224 if (myWindowDC == NULL || myGContext == NULL)
226 return Standard_False;
228 return (( (HDC )myWindowDC == wglGetCurrentDC())
229 && ((HGLRC )myGContext == wglGetCurrentContext()));
231 if (myDisplay == NULL || myWindow == 0 || myGContext == 0)
233 return Standard_False;
236 return ( ((Display* )myDisplay == glXGetCurrentDisplay())
237 && ((GLXContext )myGContext == glXGetCurrentContext())
238 && ((GLXDrawable )myWindow == glXGetCurrentDrawable()));
242 // =======================================================================
243 // function : MakeCurrent
245 // =======================================================================
246 Standard_Boolean OpenGl_Context::MakeCurrent()
249 if (myWindowDC == NULL || myGContext == NULL)
251 Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called before!");
252 return Standard_False;
255 // technically it should be safe to activate already bound GL context
256 // however some drivers (Intel etc.) may FAIL doing this for unknown reason
259 myShaderManager->SetContext (this);
260 return Standard_True;
262 else if (wglMakeCurrent ((HDC )myWindowDC, (HGLRC )myGContext) != TRUE)
264 // notice that glGetError() couldn't be used here!
265 wchar_t* aMsgBuff = NULL;
266 DWORD anErrorCode = GetLastError();
267 FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
268 NULL, anErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (wchar_t* )&aMsgBuff, 0, NULL);
269 TCollection_ExtendedString aMsg ("wglMakeCurrent() has failed. ");
270 if (aMsgBuff != NULL)
272 aMsg += (Standard_ExtString )aMsgBuff;
273 LocalFree (aMsgBuff);
275 PushMessage (GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB, GL_DEBUG_TYPE_ERROR_ARB, (unsigned int )anErrorCode, GL_DEBUG_SEVERITY_HIGH_ARB, aMsg);
276 myIsInitialized = Standard_False;
277 return Standard_False;
280 if (myDisplay == NULL || myWindow == 0 || myGContext == 0)
282 Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called before!");
283 return Standard_False;
286 if (!glXMakeCurrent ((Display* )myDisplay, (GLXDrawable )myWindow, (GLXContext )myGContext))
288 // if there is no current context it might be impossible to use glGetError() correctly
289 PushMessage (GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB, GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB,
290 "glXMakeCurrent() has failed!");
291 myIsInitialized = Standard_False;
292 return Standard_False;
295 myShaderManager->SetContext (this);
296 return Standard_True;
299 // =======================================================================
300 // function : SwapBuffers
302 // =======================================================================
303 void OpenGl_Context::SwapBuffers()
306 if ((HDC )myWindowDC != NULL)
308 ::SwapBuffers ((HDC )myWindowDC);
312 if ((Display* )myDisplay != NULL)
314 glXSwapBuffers ((Display* )myDisplay, (GLXDrawable )myWindow);
321 // =======================================================================
322 // function : findProc
324 // =======================================================================
325 void* OpenGl_Context::findProc (const char* theFuncName)
328 return wglGetProcAddress (theFuncName);
329 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
330 return (myGlLibHandle != NULL) ? dlsym (myGlLibHandle, theFuncName) : NULL;
332 return (void* )glXGetProcAddress ((const GLubyte* )theFuncName);
336 // =======================================================================
337 // function : CheckExtension
339 // =======================================================================
340 Standard_Boolean OpenGl_Context::CheckExtension (const char* theExtName) const
342 if (theExtName == NULL)
344 std::cerr << "CheckExtension called with NULL string!\n";
345 return Standard_False;
348 // available since OpenGL 3.0
349 // and the ONLY way to check extensions with OpenGL 3.1+ core profile
350 /**if (IsGlGreaterEqual (3, 0))
353 glGetIntegerv (GL_NUM_EXTENSIONS, &anExtNb);
354 for (GLint anIter = 0; anIter < anExtNb; ++anIter)
356 const char* anExtension = (const char* )core30->glGetStringi (GL_EXTENSIONS, (GLuint )anIter);
357 if (anExtension[anExtNameLen] == '\0' &&
358 strncmp (anExtension, theExtName, anExtNameLen) == 0)
360 return Standard_True;
363 return Standard_False;
366 // use old way with huge string for all extensions
367 const char* anExtString = (const char* )glGetString (GL_EXTENSIONS);
368 if (anExtString == NULL)
370 Messanger()->Send ("TKOpenGL: glGetString (GL_EXTENSIONS) has returned NULL! No GL context?", Message_Warning);
371 return Standard_False;
373 return CheckExtension (anExtString, theExtName);
376 // =======================================================================
377 // function : CheckExtension
379 // =======================================================================
380 Standard_Boolean OpenGl_Context::CheckExtension (const char* theExtString,
381 const char* theExtName)
383 if (theExtString == NULL)
385 return Standard_False;
388 // Search for theExtName in the extensions string.
389 // Use of strstr() is not sufficient because extension names can be prefixes of other extension names.
390 char* aPtrIter = (char* )theExtString;
391 const char* aPtrEnd = aPtrIter + strlen (theExtString);
392 const size_t anExtNameLen = strlen (theExtName);
393 while (aPtrIter < aPtrEnd)
395 const size_t n = strcspn (aPtrIter, " ");
396 if ((n == anExtNameLen) && (strncmp (aPtrIter, theExtName, anExtNameLen) == 0))
398 return Standard_True;
402 return Standard_False;
405 #if !defined(__APPLE__) || defined(MACOSX_USE_GLX)
407 // =======================================================================
410 // =======================================================================
411 Standard_Boolean OpenGl_Context::Init()
415 return Standard_True;
419 myWindowDC = (Aspect_Handle )wglGetCurrentDC();
420 myGContext = (Aspect_RenderingContext )wglGetCurrentContext();
422 myDisplay = (Aspect_Display )glXGetCurrentDisplay();
423 myGContext = (Aspect_RenderingContext )glXGetCurrentContext();
424 myWindow = (Aspect_Drawable )glXGetCurrentDrawable();
426 if (myGContext == NULL)
428 return Standard_False;
432 myIsInitialized = Standard_True;
433 return Standard_True;
438 // =======================================================================
441 // =======================================================================
443 Standard_Boolean OpenGl_Context::Init (const Aspect_Handle theWindow,
444 const Aspect_Handle theWindowDC,
445 const Aspect_RenderingContext theGContext)
446 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
447 Standard_Boolean OpenGl_Context::Init (const void* theGContext)
449 Standard_Boolean OpenGl_Context::Init (const Aspect_Drawable theWindow,
450 const Aspect_Display theDisplay,
451 const Aspect_RenderingContext theGContext)
454 Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called only once!");
456 myWindow = theWindow;
457 myGContext = theGContext;
458 myWindowDC = theWindowDC;
459 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
460 myGContext = (void* )theGContext;
462 myWindow = theWindow;
463 myGContext = theGContext;
464 myDisplay = theDisplay;
466 if (myGContext == NULL || !MakeCurrent())
468 return Standard_False;
472 myIsInitialized = Standard_True;
473 return Standard_True;
476 // =======================================================================
477 // function : ResetErrors
479 // =======================================================================
480 void OpenGl_Context::ResetErrors()
482 while (glGetError() != GL_NO_ERROR)
488 // =======================================================================
489 // function : readGlVersion
491 // =======================================================================
492 void OpenGl_Context::readGlVersion()
498 // available since OpenGL 3.0
499 GLint aMajor = 0, aMinor = 0;
500 glGetIntegerv (GL_MAJOR_VERSION, &aMajor);
501 glGetIntegerv (GL_MINOR_VERSION, &aMinor);
502 // glGetError() sometimes does not report an error here even if
503 // GL does not know GL_MAJOR_VERSION and GL_MINOR_VERSION constants.
504 // This happens on some rendereres like e.g. Cygwin MESA.
505 // Thus checking additionally if GL has put anything to
506 // the output variables.
507 if (glGetError() == GL_NO_ERROR && aMajor != 0 && aMinor != 0)
509 myGlVerMajor = aMajor;
510 myGlVerMinor = aMinor;
515 // Read version string.
516 // Notice that only first two numbers splitted by point '2.1 XXXXX' are significant.
517 // Following trash (after space) is vendor-specific.
518 // New drivers also returns micro version of GL like '3.3.0' which has no meaning
519 // and should be considered as vendor-specific too.
520 const char* aVerStr = (const char* )glGetString (GL_VERSION);
521 if (aVerStr == NULL || *aVerStr == '\0')
523 // invalid GL context
527 // parse string for major number
531 while (aVerStr[aMajIter] >= '0' && aVerStr[aMajIter] <= '9')
535 if (aMajIter == 0 || aMajIter >= sizeof(aMajorStr))
539 memcpy (aMajorStr, aVerStr, aMajIter);
540 aMajorStr[aMajIter] = '\0';
542 // parse string for minor number
543 aVerStr += aMajIter + 1;
545 while (aVerStr[aMinIter] >= '0' && aVerStr[aMinIter] <= '9')
549 if (aMinIter == 0 || aMinIter >= sizeof(aMinorStr))
553 memcpy (aMinorStr, aVerStr, aMinIter);
554 aMinorStr[aMinIter] = '\0';
557 myGlVerMajor = atoi (aMajorStr);
558 myGlVerMinor = atoi (aMinorStr);
560 if (myGlVerMajor <= 0)
567 static Standard_CString THE_DBGMSG_UNKNOWN = "UNKNOWN";
568 static Standard_CString THE_DBGMSG_SOURCES[] =
570 ".OpenGL", // GL_DEBUG_SOURCE_API_ARB
571 ".WinSystem", // GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB
572 ".GLSL", // GL_DEBUG_SOURCE_SHADER_COMPILER_ARB
573 ".3rdParty", // GL_DEBUG_SOURCE_THIRD_PARTY_ARB
574 "", // GL_DEBUG_SOURCE_APPLICATION_ARB
575 ".Other" // GL_DEBUG_SOURCE_OTHER_ARB
578 static Standard_CString THE_DBGMSG_TYPES[] =
580 "Error", // GL_DEBUG_TYPE_ERROR_ARB
581 "Deprecated", // GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB
582 "Undef. behavior", // GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB
583 "Portability", // GL_DEBUG_TYPE_PORTABILITY_ARB
584 "Performance", // GL_DEBUG_TYPE_PERFORMANCE_ARB
585 "Other" // GL_DEBUG_TYPE_OTHER_ARB
588 static Standard_CString THE_DBGMSG_SEV_HIGH = "High"; // GL_DEBUG_SEVERITY_HIGH_ARB
589 static Standard_CString THE_DBGMSG_SEV_MEDIUM = "Medium"; // GL_DEBUG_SEVERITY_MEDIUM_ARB
590 static Standard_CString THE_DBGMSG_SEV_LOW = "Low"; // GL_DEBUG_SEVERITY_LOW_ARB
592 //! Callback for GL_ARB_debug_output extension
593 static void APIENTRY debugCallbackWrap(unsigned int theSource,
594 unsigned int theType,
596 unsigned int theSeverity,
598 const char* theMessage,
601 OpenGl_Context* aCtx = (OpenGl_Context* )theUserParam;
602 aCtx->PushMessage (theSource, theType, theId, theSeverity, theMessage);
605 // =======================================================================
606 // function : PushMessage
608 // =======================================================================
609 void OpenGl_Context::PushMessage (const unsigned int theSource,
610 const unsigned int theType,
611 const unsigned int theId,
612 const unsigned int theSeverity,
613 const TCollection_ExtendedString& theMessage)
615 //OpenGl_Context* aCtx = (OpenGl_Context* )theUserParam;
616 Standard_CString& aSrc = (theSource >= GL_DEBUG_SOURCE_API_ARB
617 && theSource <= GL_DEBUG_SOURCE_OTHER_ARB)
618 ? THE_DBGMSG_SOURCES[theSource - GL_DEBUG_SOURCE_API_ARB]
619 : THE_DBGMSG_UNKNOWN;
620 Standard_CString& aType = (theType >= GL_DEBUG_TYPE_ERROR_ARB
621 && theType <= GL_DEBUG_TYPE_OTHER_ARB)
622 ? THE_DBGMSG_TYPES[theType - GL_DEBUG_TYPE_ERROR_ARB]
623 : THE_DBGMSG_UNKNOWN;
624 Standard_CString& aSev = theSeverity == GL_DEBUG_SEVERITY_HIGH_ARB
625 ? THE_DBGMSG_SEV_HIGH
626 : (theSeverity == GL_DEBUG_SEVERITY_MEDIUM_ARB
627 ? THE_DBGMSG_SEV_MEDIUM
628 : THE_DBGMSG_SEV_LOW);
629 Message_Gravity aGrav = theSeverity == GL_DEBUG_SEVERITY_HIGH_ARB
631 : (theSeverity == GL_DEBUG_SEVERITY_MEDIUM_ARB
635 TCollection_ExtendedString aMsg;
636 aMsg += "TKOpenGl"; aMsg += aSrc;
637 aMsg += " | Type: "; aMsg += aType;
638 aMsg += " | ID: "; aMsg += (Standard_Integer )theId;
639 aMsg += " | Severity: "; aMsg += aSev;
640 aMsg += " | Message:\n ";
643 Messanger()->Send (aMsg, aGrav);
646 // =======================================================================
649 // =======================================================================
650 void OpenGl_Context::init()
655 arbNPTW = CheckExtension ("GL_ARB_texture_non_power_of_two");
656 extBgra = CheckExtension ("GL_EXT_bgra");
657 extAnis = CheckExtension ("GL_EXT_texture_filter_anisotropic");
658 extPDS = CheckExtension ("GL_EXT_packed_depth_stencil");
659 atiMem = CheckExtension ("GL_ATI_meminfo");
660 nvxMem = CheckExtension ("GL_NVX_gpu_memory_info");
662 // get number of maximum clipping planes
663 glGetIntegerv (GL_MAX_CLIP_PLANES, &myMaxClipPlanes);
664 glGetIntegerv (GL_MAX_TEXTURE_SIZE, &myMaxTexDim);
667 glGetIntegerv (GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &myAnisoMax);
670 myClippingState.Init (myMaxClipPlanes);
672 // initialize debug context extension
673 if (CheckExtension ("GL_ARB_debug_output"))
675 arbDbg = new OpenGl_ArbDbg();
676 memset (arbDbg, 0, sizeof(OpenGl_ArbDbg)); // nullify whole structure
677 if (!FindProcShort (arbDbg, glDebugMessageControlARB)
678 || !FindProcShort (arbDbg, glDebugMessageInsertARB)
679 || !FindProcShort (arbDbg, glDebugMessageCallbackARB)
680 || !FindProcShort (arbDbg, glGetDebugMessageLogARB))
686 && caps->contextDebug)
688 // setup default callback
689 arbDbg->glDebugMessageCallbackARB (debugCallbackWrap, this);
691 glEnable (GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
696 // initialize VBO extension (ARB)
697 if (CheckExtension ("GL_ARB_vertex_buffer_object"))
699 arbVBO = new OpenGl_ArbVBO();
700 memset (arbVBO, 0, sizeof(OpenGl_ArbVBO)); // nullify whole structure
701 if (!FindProcShort (arbVBO, glGenBuffersARB)
702 || !FindProcShort (arbVBO, glBindBufferARB)
703 || !FindProcShort (arbVBO, glBufferDataARB)
704 || !FindProcShort (arbVBO, glDeleteBuffersARB))
711 // initialize TBO extension (ARB)
712 if (CheckExtension ("GL_ARB_texture_buffer_object"))
714 arbTBO = new OpenGl_ArbTBO();
715 memset (arbTBO, 0, sizeof(OpenGl_ArbTBO)); // nullify whole structure
716 if (!FindProcShort (arbTBO, glTexBufferARB))
723 // initialize hardware instancing extension (ARB)
724 if (CheckExtension ("GL_ARB_draw_instanced"))
726 arbIns = new OpenGl_ArbIns();
727 memset (arbIns, 0, sizeof(OpenGl_ArbIns)); // nullify whole structure
728 if (!FindProcShort (arbIns, glDrawArraysInstancedARB)
729 || !FindProcShort (arbIns, glDrawElementsInstancedARB))
736 // initialize FBO extension (EXT)
737 if (CheckExtension ("GL_EXT_framebuffer_object"))
739 extFBO = new OpenGl_ExtFBO();
740 memset (extFBO, 0, sizeof(OpenGl_ExtFBO)); // nullify whole structure
741 if (!FindProcShort (extFBO, glGenFramebuffersEXT)
742 || !FindProcShort (extFBO, glDeleteFramebuffersEXT)
743 || !FindProcShort (extFBO, glBindFramebufferEXT)
744 || !FindProcShort (extFBO, glFramebufferTexture2DEXT)
745 || !FindProcShort (extFBO, glCheckFramebufferStatusEXT)
746 || !FindProcShort (extFBO, glGenRenderbuffersEXT)
747 || !FindProcShort (extFBO, glDeleteRenderbuffersEXT)
748 || !FindProcShort (extFBO, glBindRenderbufferEXT)
749 || !FindProcShort (extFBO, glRenderbufferStorageEXT)
750 || !FindProcShort (extFBO, glFramebufferRenderbufferEXT)
751 || !FindProcShort (extFBO, glGenerateMipmapEXT))
758 // initialize GS extension (EXT)
759 if (CheckExtension ("GL_EXT_geometry_shader4"))
761 extGS = new OpenGl_ExtGS();
762 memset (extGS, 0, sizeof(OpenGl_ExtGS)); // nullify whole structure
763 if (!FindProcShort (extGS, glProgramParameteriEXT))
770 myGlCore20 = new OpenGl_GlCore20();
771 memset (myGlCore20, 0, sizeof(OpenGl_GlCore20)); // nullify whole structure
773 // Check if OpenGL 1.2 core functionality is actually present
774 Standard_Boolean hasGlCore12 = IsGlGreaterEqual (1, 2)
775 && FindProcShort (myGlCore20, glBlendColor)
776 && FindProcShort (myGlCore20, glBlendEquation)
777 && FindProcShort (myGlCore20, glDrawRangeElements)
778 && FindProcShort (myGlCore20, glTexImage3D)
779 && FindProcShort (myGlCore20, glTexSubImage3D)
780 && FindProcShort (myGlCore20, glCopyTexSubImage3D);
782 // Check if OpenGL 1.3 core functionality is actually present
783 Standard_Boolean hasGlCore13 = IsGlGreaterEqual (1, 3)
784 && FindProcShort (myGlCore20, glActiveTexture)
785 && FindProcShort (myGlCore20, glSampleCoverage)
786 && FindProcShort (myGlCore20, glCompressedTexImage3D)
787 && FindProcShort (myGlCore20, glCompressedTexImage2D)
788 && FindProcShort (myGlCore20, glCompressedTexImage1D)
789 && FindProcShort (myGlCore20, glCompressedTexSubImage3D)
790 && FindProcShort (myGlCore20, glCompressedTexSubImage2D)
791 && FindProcShort (myGlCore20, glCompressedTexSubImage1D)
792 && FindProcShort (myGlCore20, glGetCompressedTexImage)
794 && FindProcShort (myGlCore20, glClientActiveTexture)
795 && FindProcShort (myGlCore20, glMultiTexCoord1d)
796 && FindProcShort (myGlCore20, glMultiTexCoord1dv)
797 && FindProcShort (myGlCore20, glMultiTexCoord1f)
798 && FindProcShort (myGlCore20, glMultiTexCoord1fv)
799 && FindProcShort (myGlCore20, glMultiTexCoord1i)
800 && FindProcShort (myGlCore20, glMultiTexCoord1iv)
801 && FindProcShort (myGlCore20, glMultiTexCoord1s)
802 && FindProcShort (myGlCore20, glMultiTexCoord1sv)
803 && FindProcShort (myGlCore20, glMultiTexCoord2d)
804 && FindProcShort (myGlCore20, glMultiTexCoord2dv)
805 && FindProcShort (myGlCore20, glMultiTexCoord2f)
806 && FindProcShort (myGlCore20, glMultiTexCoord2fv)
807 && FindProcShort (myGlCore20, glMultiTexCoord2i)
808 && FindProcShort (myGlCore20, glMultiTexCoord2iv)
809 && FindProcShort (myGlCore20, glMultiTexCoord2s)
810 && FindProcShort (myGlCore20, glMultiTexCoord2sv)
811 && FindProcShort (myGlCore20, glMultiTexCoord3d)
812 && FindProcShort (myGlCore20, glMultiTexCoord3dv)
813 && FindProcShort (myGlCore20, glMultiTexCoord3f)
814 && FindProcShort (myGlCore20, glMultiTexCoord3fv)
815 && FindProcShort (myGlCore20, glMultiTexCoord3i)
816 && FindProcShort (myGlCore20, glMultiTexCoord3iv)
817 && FindProcShort (myGlCore20, glMultiTexCoord3s)
818 && FindProcShort (myGlCore20, glMultiTexCoord3sv)
819 && FindProcShort (myGlCore20, glMultiTexCoord4d)
820 && FindProcShort (myGlCore20, glMultiTexCoord4dv)
821 && FindProcShort (myGlCore20, glMultiTexCoord4f)
822 && FindProcShort (myGlCore20, glMultiTexCoord4fv)
823 && FindProcShort (myGlCore20, glMultiTexCoord4i)
824 && FindProcShort (myGlCore20, glMultiTexCoord4iv)
825 && FindProcShort (myGlCore20, glMultiTexCoord4s)
826 && FindProcShort (myGlCore20, glMultiTexCoord4sv)
827 && FindProcShort (myGlCore20, glLoadTransposeMatrixf)
828 && FindProcShort (myGlCore20, glLoadTransposeMatrixd)
829 && FindProcShort (myGlCore20, glMultTransposeMatrixf)
830 && FindProcShort (myGlCore20, glMultTransposeMatrixd);
832 // Check if OpenGL 1.4 core functionality is actually present
833 Standard_Boolean hasGlCore14 = IsGlGreaterEqual (1, 4)
834 && FindProcShort (myGlCore20, glBlendFuncSeparate)
835 && FindProcShort (myGlCore20, glMultiDrawArrays)
836 && FindProcShort (myGlCore20, glMultiDrawElements)
837 && FindProcShort (myGlCore20, glPointParameterf)
838 && FindProcShort (myGlCore20, glPointParameterfv)
839 && FindProcShort (myGlCore20, glPointParameteri)
840 && FindProcShort (myGlCore20, glPointParameteriv);
842 // Check if OpenGL 1.5 core functionality is actually present
843 Standard_Boolean hasGlCore15 = IsGlGreaterEqual (1, 5)
844 && FindProcShort (myGlCore20, glGenQueries)
845 && FindProcShort (myGlCore20, glDeleteQueries)
846 && FindProcShort (myGlCore20, glIsQuery)
847 && FindProcShort (myGlCore20, glBeginQuery)
848 && FindProcShort (myGlCore20, glEndQuery)
849 && FindProcShort (myGlCore20, glGetQueryiv)
850 && FindProcShort (myGlCore20, glGetQueryObjectiv)
851 && FindProcShort (myGlCore20, glGetQueryObjectuiv)
852 && FindProcShort (myGlCore20, glBindBuffer)
853 && FindProcShort (myGlCore20, glDeleteBuffers)
854 && FindProcShort (myGlCore20, glGenBuffers)
855 && FindProcShort (myGlCore20, glIsBuffer)
856 && FindProcShort (myGlCore20, glBufferData)
857 && FindProcShort (myGlCore20, glBufferSubData)
858 && FindProcShort (myGlCore20, glGetBufferSubData)
859 && FindProcShort (myGlCore20, glMapBuffer)
860 && FindProcShort (myGlCore20, glUnmapBuffer)
861 && FindProcShort (myGlCore20, glGetBufferParameteriv)
862 && FindProcShort (myGlCore20, glGetBufferPointerv);
864 // Check if OpenGL 2.0 core functionality is actually present
865 Standard_Boolean hasGlCore20 = IsGlGreaterEqual (2, 0)
866 && FindProcShort (myGlCore20, glBlendEquationSeparate)
867 && FindProcShort (myGlCore20, glDrawBuffers)
868 && FindProcShort (myGlCore20, glStencilOpSeparate)
869 && FindProcShort (myGlCore20, glStencilFuncSeparate)
870 && FindProcShort (myGlCore20, glStencilMaskSeparate)
871 && FindProcShort (myGlCore20, glAttachShader)
872 && FindProcShort (myGlCore20, glBindAttribLocation)
873 && FindProcShort (myGlCore20, glCompileShader)
874 && FindProcShort (myGlCore20, glCreateProgram)
875 && FindProcShort (myGlCore20, glCreateShader)
876 && FindProcShort (myGlCore20, glDeleteProgram)
877 && FindProcShort (myGlCore20, glDeleteShader)
878 && FindProcShort (myGlCore20, glDetachShader)
879 && FindProcShort (myGlCore20, glDisableVertexAttribArray)
880 && FindProcShort (myGlCore20, glEnableVertexAttribArray)
881 && FindProcShort (myGlCore20, glGetActiveAttrib)
882 && FindProcShort (myGlCore20, glGetActiveUniform)
883 && FindProcShort (myGlCore20, glGetAttachedShaders)
884 && FindProcShort (myGlCore20, glGetAttribLocation)
885 && FindProcShort (myGlCore20, glGetProgramiv)
886 && FindProcShort (myGlCore20, glGetProgramInfoLog)
887 && FindProcShort (myGlCore20, glGetShaderiv)
888 && FindProcShort (myGlCore20, glGetShaderInfoLog)
889 && FindProcShort (myGlCore20, glGetShaderSource)
890 && FindProcShort (myGlCore20, glGetUniformLocation)
891 && FindProcShort (myGlCore20, glGetUniformfv)
892 && FindProcShort (myGlCore20, glGetUniformiv)
893 && FindProcShort (myGlCore20, glGetVertexAttribdv)
894 && FindProcShort (myGlCore20, glGetVertexAttribfv)
895 && FindProcShort (myGlCore20, glGetVertexAttribiv)
896 && FindProcShort (myGlCore20, glGetVertexAttribPointerv)
897 && FindProcShort (myGlCore20, glIsProgram)
898 && FindProcShort (myGlCore20, glIsShader)
899 && FindProcShort (myGlCore20, glLinkProgram)
900 && FindProcShort (myGlCore20, glShaderSource)
901 && FindProcShort (myGlCore20, glUseProgram)
902 && FindProcShort (myGlCore20, glUniform1f)
903 && FindProcShort (myGlCore20, glUniform2f)
904 && FindProcShort (myGlCore20, glUniform3f)
905 && FindProcShort (myGlCore20, glUniform4f)
906 && FindProcShort (myGlCore20, glUniform1i)
907 && FindProcShort (myGlCore20, glUniform2i)
908 && FindProcShort (myGlCore20, glUniform3i)
909 && FindProcShort (myGlCore20, glUniform4i)
910 && FindProcShort (myGlCore20, glUniform1fv)
911 && FindProcShort (myGlCore20, glUniform2fv)
912 && FindProcShort (myGlCore20, glUniform3fv)
913 && FindProcShort (myGlCore20, glUniform4fv)
914 && FindProcShort (myGlCore20, glUniform1iv)
915 && FindProcShort (myGlCore20, glUniform2iv)
916 && FindProcShort (myGlCore20, glUniform3iv)
917 && FindProcShort (myGlCore20, glUniform4iv)
918 && FindProcShort (myGlCore20, glUniformMatrix2fv)
919 && FindProcShort (myGlCore20, glUniformMatrix3fv)
920 && FindProcShort (myGlCore20, glUniformMatrix4fv)
921 && FindProcShort (myGlCore20, glValidateProgram)
922 && FindProcShort (myGlCore20, glVertexAttrib1d)
923 && FindProcShort (myGlCore20, glVertexAttrib1dv)
924 && FindProcShort (myGlCore20, glVertexAttrib1f)
925 && FindProcShort (myGlCore20, glVertexAttrib1fv)
926 && FindProcShort (myGlCore20, glVertexAttrib1s)
927 && FindProcShort (myGlCore20, glVertexAttrib1sv)
928 && FindProcShort (myGlCore20, glVertexAttrib2d)
929 && FindProcShort (myGlCore20, glVertexAttrib2dv)
930 && FindProcShort (myGlCore20, glVertexAttrib2f)
931 && FindProcShort (myGlCore20, glVertexAttrib2fv)
932 && FindProcShort (myGlCore20, glVertexAttrib2s)
933 && FindProcShort (myGlCore20, glVertexAttrib2sv)
934 && FindProcShort (myGlCore20, glVertexAttrib3d)
935 && FindProcShort (myGlCore20, glVertexAttrib3dv)
936 && FindProcShort (myGlCore20, glVertexAttrib3f)
937 && FindProcShort (myGlCore20, glVertexAttrib3fv)
938 && FindProcShort (myGlCore20, glVertexAttrib3s)
939 && FindProcShort (myGlCore20, glVertexAttrib3sv)
940 && FindProcShort (myGlCore20, glVertexAttrib4Nbv)
941 && FindProcShort (myGlCore20, glVertexAttrib4Niv)
942 && FindProcShort (myGlCore20, glVertexAttrib4Nsv)
943 && FindProcShort (myGlCore20, glVertexAttrib4Nub)
944 && FindProcShort (myGlCore20, glVertexAttrib4Nubv)
945 && FindProcShort (myGlCore20, glVertexAttrib4Nuiv)
946 && FindProcShort (myGlCore20, glVertexAttrib4Nusv)
947 && FindProcShort (myGlCore20, glVertexAttrib4bv)
948 && FindProcShort (myGlCore20, glVertexAttrib4d)
949 && FindProcShort (myGlCore20, glVertexAttrib4dv)
950 && FindProcShort (myGlCore20, glVertexAttrib4f)
951 && FindProcShort (myGlCore20, glVertexAttrib4fv)
952 && FindProcShort (myGlCore20, glVertexAttrib4iv)
953 && FindProcShort (myGlCore20, glVertexAttrib4s)
954 && FindProcShort (myGlCore20, glVertexAttrib4sv)
955 && FindProcShort (myGlCore20, glVertexAttrib4ubv)
956 && FindProcShort (myGlCore20, glVertexAttrib4uiv)
957 && FindProcShort (myGlCore20, glVertexAttrib4usv)
958 && FindProcShort (myGlCore20, glVertexAttribPointer);
1007 core20 = myGlCore20;
1010 // =======================================================================
1011 // function : IsFeedback
1013 // =======================================================================
1014 Standard_Boolean OpenGl_Context::IsFeedback() const
1016 return myIsFeedback;
1019 // =======================================================================
1020 // function : SetFeedback
1022 // =======================================================================
1023 void OpenGl_Context::SetFeedback (const Standard_Boolean theFeedbackOn)
1025 myIsFeedback = theFeedbackOn;
1028 // =======================================================================
1029 // function : MemoryInfo
1031 // =======================================================================
1032 Standard_Size OpenGl_Context::AvailableMemory() const
1036 // this is actually information for VBO pool
1037 // however because pools are mostly shared
1038 // it can be used for total GPU memory estimations
1041 glGetIntegerv (GL_VBO_FREE_MEMORY_ATI, aMemInfo);
1042 // returned value is in KiB, however this maybe changed in future
1043 return Standard_Size(aMemInfo[0]) * 1024;
1047 // current available dedicated video memory (in KiB), currently unused GPU memory
1049 glGetIntegerv (GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &aMemInfo);
1050 return Standard_Size(aMemInfo) * 1024;
1055 // =======================================================================
1056 // function : MemoryInfo
1058 // =======================================================================
1059 TCollection_AsciiString OpenGl_Context::MemoryInfo() const
1061 TCollection_AsciiString anInfo;
1065 memset (aValues, 0, sizeof(aValues));
1066 glGetIntegerv (GL_VBO_FREE_MEMORY_ATI, aValues);
1068 // total memory free in the pool
1069 anInfo += TCollection_AsciiString (" GPU free memory: ") + (aValues[0] / 1024) + " MiB\n";
1071 // largest available free block in the pool
1072 anInfo += TCollection_AsciiString (" Largest free block: ") + (aValues[1] / 1024) + " MiB\n";
1073 if (aValues[2] != aValues[0])
1075 // total auxiliary memory free
1076 anInfo += TCollection_AsciiString (" Free memory: ") + (aValues[2] / 1024) + " MiB\n";
1081 //current available dedicated video memory (in KiB), currently unused GPU memory
1083 glGetIntegerv (GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &aValue);
1084 anInfo += TCollection_AsciiString (" GPU free memory: ") + (aValue / 1024) + " MiB\n";
1086 // dedicated video memory, total size (in KiB) of the GPU memory
1087 GLint aDedicated = 0;
1088 glGetIntegerv (GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, &aDedicated);
1089 anInfo += TCollection_AsciiString (" GPU memory: ") + (aDedicated / 1024) + " MiB\n";
1091 // total available memory, total size (in KiB) of the memory available for allocations
1092 glGetIntegerv (GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, &aValue);
1093 if (aValue != aDedicated)
1095 // different only for special configurations
1096 anInfo += TCollection_AsciiString (" Total memory: ") + (aValue / 1024) + " MiB\n";
1103 // =======================================================================
1104 // function : GetResource
1106 // =======================================================================
1107 const Handle(OpenGl_Resource)& OpenGl_Context::GetResource (const TCollection_AsciiString& theKey) const
1109 return mySharedResources->IsBound (theKey) ? mySharedResources->Find (theKey) : NULL_GL_RESOURCE;
1112 // =======================================================================
1113 // function : ShareResource
1115 // =======================================================================
1116 Standard_Boolean OpenGl_Context::ShareResource (const TCollection_AsciiString& theKey,
1117 const Handle(OpenGl_Resource)& theResource)
1119 if (theKey.IsEmpty() || theResource.IsNull())
1121 return Standard_False;
1123 return mySharedResources->Bind (theKey, theResource);
1126 // =======================================================================
1127 // function : ReleaseResource
1129 // =======================================================================
1130 void OpenGl_Context::ReleaseResource (const TCollection_AsciiString& theKey,
1131 const Standard_Boolean theToDelay)
1133 if (!mySharedResources->IsBound (theKey))
1137 const Handle(OpenGl_Resource)& aRes = mySharedResources->Find (theKey);
1138 if (aRes->GetRefCount() > 1)
1145 myDelayed->Bind (theKey, 1);
1149 aRes->Release (this);
1150 mySharedResources->UnBind (theKey);
1154 // =======================================================================
1155 // function : DelayedRelease
1157 // =======================================================================
1158 void OpenGl_Context::DelayedRelease (Handle(OpenGl_Resource)& theResource)
1160 myReleaseQueue->Push (theResource);
1161 theResource.Nullify();
1164 // =======================================================================
1165 // function : ReleaseDelayed
1167 // =======================================================================
1168 void OpenGl_Context::ReleaseDelayed()
1170 // release queued elements
1171 while (!myReleaseQueue->IsEmpty())
1173 myReleaseQueue->Front()->Release (this);
1174 myReleaseQueue->Pop();
1177 // release delayed shared resoruces
1178 NCollection_Vector<TCollection_AsciiString> aDeadList;
1179 for (NCollection_DataMap<TCollection_AsciiString, Standard_Integer>::Iterator anIter (*myDelayed);
1180 anIter.More(); anIter.Next())
1182 if (++anIter.ChangeValue() <= 2)
1184 continue; // postpone release one more frame to ensure noone use it periodically
1187 const TCollection_AsciiString& aKey = anIter.Key();
1188 if (!mySharedResources->IsBound (aKey))
1190 // mixed unshared strategy delayed/undelayed was used!
1191 aDeadList.Append (aKey);
1195 Handle(OpenGl_Resource)& aRes = mySharedResources->ChangeFind (aKey);
1196 if (aRes->GetRefCount() > 1)
1198 // should be only 1 instance in mySharedResources
1199 // if not - resource was reused again
1200 aDeadList.Append (aKey);
1204 // release resource if no one requiested it more than 2 redraw calls
1205 aRes->Release (this);
1206 mySharedResources->UnBind (aKey);
1207 aDeadList.Append (aKey);
1210 for (Standard_Integer anIter = 0; anIter < aDeadList.Length(); ++anIter)
1212 myDelayed->UnBind (aDeadList.Value (anIter));