0024271: Provide Boolean operations for NCollection_Map
[occt.git] / src / OpenGl / OpenGl_Context.cxx
CommitLineData
b311480e 1// Created on: 2012-01-26
2// Created by: Kirill GAVRILOV
4fe56619 3// Copyright (c) 2012 OPEN CASCADE SAS
b311480e 4//
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.
9//
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.
12//
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.
19
58655684 20#if defined(_WIN32)
5f8b738e 21 #include <windows.h>
22#endif
23
2166f0fa
SK
24#include <OpenGl_Context.hxx>
25
5f8b738e 26#include <OpenGl_ArbVBO.hxx>
5e27df78 27#include <OpenGl_ArbTBO.hxx>
28#include <OpenGl_ArbIns.hxx>
58655684 29#include <OpenGl_ArbDbg.hxx>
5f8b738e 30#include <OpenGl_ExtFBO.hxx>
37eb4787 31#include <OpenGl_ExtGS.hxx>
5f8b738e 32#include <OpenGl_GlCore20.hxx>
33
cbf18624 34#include <Message_Messenger.hxx>
a174a3c5 35#include <NCollection_Vector.hxx>
36
2bd4c032 37#include <Standard_ProgramError.hxx>
38
58655684 39#if defined(_WIN32)
5f8b738e 40 //
41#elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
42 #include <dlfcn.h>
43#else
44 #include <GL/glx.h> // glXGetProcAddress()
45#endif
46
f0430952 47// GL_NVX_gpu_memory_info
48#ifndef GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX
49 enum
50 {
51 GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX = 0x9047,
52 GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX = 0x9048,
53 GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX = 0x9049,
54 GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX = 0x904A,
55 GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX = 0x904B
56 };
57#endif
58
2166f0fa
SK
59IMPLEMENT_STANDARD_HANDLE (OpenGl_Context, Standard_Transient)
60IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Context, Standard_Transient)
61
5f8b738e 62//! Make record shorter to retrieve function pointer using variable with same name
63#define FindProcShort(theStruct, theFunc) FindProc(#theFunc, theStruct->theFunc)
2166f0fa 64
5e27df78 65namespace
66{
67 static const Handle(OpenGl_Resource) NULL_GL_RESOURCE;
4269bd1b 68 static const GLdouble OpenGl_DefaultPlaneEq[] = {0.0, 0.0, 0.0, 0.0};
5e27df78 69};
70
2166f0fa
SK
71// =======================================================================
72// function : OpenGl_Context
73// purpose :
74// =======================================================================
58655684 75OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps)
5f8b738e 76: core12 (NULL),
77 core13 (NULL),
78 core14 (NULL),
79 core15 (NULL),
80 core20 (NULL),
58655684 81 caps (!theCaps.IsNull() ? theCaps : new OpenGl_Caps()),
bf75be98 82 arbNPTW(Standard_False),
5f8b738e 83 arbVBO (NULL),
5e27df78 84 arbTBO (NULL),
85 arbIns (NULL),
58655684 86 arbDbg (NULL),
5f8b738e 87 extFBO (NULL),
37eb4787 88 extGS (NULL),
bf75be98 89 extBgra(Standard_False),
90 extAnis(Standard_False),
b859a34d 91 extPDS(Standard_False),
f0430952 92 atiMem (Standard_False),
93 nvxMem (Standard_False),
5e27df78 94 mySharedResources (new OpenGl_ResourcesMap()),
a174a3c5 95 myDelayed (new OpenGl_DelayReleaseMap()),
96 myReleaseQueue (new OpenGl_ResourcesQueue()),
4269bd1b 97 myClippingState (),
5f8b738e 98 myGlLibHandle (NULL),
99 myGlCore20 (NULL),
2f6cb3ac 100 myAnisoMax (1),
eafb234b 101 myMaxTexDim (1024),
4269bd1b 102 myMaxClipPlanes (6),
5f8b738e 103 myGlVerMajor (0),
104 myGlVerMinor (0),
664cae74 105 myIsFeedback (Standard_False),
5f8b738e 106 myIsInitialized (Standard_False)
2166f0fa 107{
5f8b738e 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);
119#endif
2166f0fa
SK
120}
121
122// =======================================================================
123// function : ~OpenGl_Context
124// purpose :
125// =======================================================================
126OpenGl_Context::~OpenGl_Context()
127{
5e27df78 128 // release clean up queue
129 ReleaseDelayed();
130
131 // release shared resources if any
132 if (((const Handle(Standard_Transient)& )mySharedResources)->GetRefCount() <= 1)
133 {
134 for (NCollection_DataMap<TCollection_AsciiString, Handle(OpenGl_Resource)>::Iterator anIter (*mySharedResources);
135 anIter.More(); anIter.Next())
136 {
137 anIter.Value()->Release (this);
138 }
139 }
140 mySharedResources.Nullify();
a174a3c5 141 myDelayed.Nullify();
5e27df78 142
cbf18624 143 if (arbDbg != NULL
144 && caps->contextDebug)
145 {
146 // reset callback
147 void* aPtr = NULL;
148 glGetPointerv (GL_DEBUG_CALLBACK_USER_PARAM_ARB, &aPtr);
149 if (aPtr == this)
150 {
151 arbDbg->glDebugMessageCallbackARB (NULL, NULL);
152 }
153 }
154
5f8b738e 155 delete myGlCore20;
156 delete arbVBO;
58655684 157 delete arbTBO;
158 delete arbIns;
159 delete arbDbg;
5f8b738e 160 delete extFBO;
37eb4787 161 delete extGS;
5f8b738e 162}
163
bf75be98 164// =======================================================================
165// function : MaxDegreeOfAnisotropy
166// purpose :
167// =======================================================================
168Standard_Integer OpenGl_Context::MaxDegreeOfAnisotropy() const
169{
170 return myAnisoMax;
171}
172
173// =======================================================================
174// function : MaxTextureSize
175// purpose :
176// =======================================================================
177Standard_Integer OpenGl_Context::MaxTextureSize() const
178{
179 return myMaxTexDim;
180}
181
4269bd1b 182// =======================================================================
183// function : MaxClipPlanes
184// purpose :
185// =======================================================================
186Standard_Integer OpenGl_Context::MaxClipPlanes() const
187{
188 return myMaxClipPlanes;
189}
190
5e27df78 191// =======================================================================
192// function : Share
193// purpose :
194// =======================================================================
195void OpenGl_Context::Share (const Handle(OpenGl_Context)& theShareCtx)
196{
197 if (!theShareCtx.IsNull())
198 {
199 mySharedResources = theShareCtx->mySharedResources;
a174a3c5 200 myDelayed = theShareCtx->myDelayed;
5e27df78 201 myReleaseQueue = theShareCtx->myReleaseQueue;
202 }
203}
204
4fe56619 205#if !defined(__APPLE__) || defined(MACOSX_USE_GLX)
206
86fa64d9 207// =======================================================================
208// function : IsCurrent
209// purpose :
210// =======================================================================
211Standard_Boolean OpenGl_Context::IsCurrent() const
212{
58655684 213#if defined(_WIN32)
86fa64d9 214 if (myWindowDC == NULL || myGContext == NULL)
215 {
216 return Standard_False;
217 }
218 return (( (HDC )myWindowDC == wglGetCurrentDC())
219 && ((HGLRC )myGContext == wglGetCurrentContext()));
220#else
221 if (myDisplay == NULL || myWindow == 0 || myGContext == 0)
222 {
223 return Standard_False;
224 }
225
226 return ( ((Display* )myDisplay == glXGetCurrentDisplay())
227 && ((GLXContext )myGContext == glXGetCurrentContext())
228 && ((GLXDrawable )myWindow == glXGetCurrentDrawable()));
229#endif
230}
231
2bd4c032 232// =======================================================================
233// function : MakeCurrent
234// purpose :
235// =======================================================================
236Standard_Boolean OpenGl_Context::MakeCurrent()
237{
58655684 238#if defined(_WIN32)
86fa64d9 239 if (myWindowDC == NULL || myGContext == NULL)
2bd4c032 240 {
86fa64d9 241 Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called before!");
242 return Standard_False;
243 }
244
245 // technically it should be safe to activate already bound GL context
246 // however some drivers (Intel etc.) may FAIL doing this for unknown reason
247 if (IsCurrent())
248 {
249 return Standard_True;
250 }
251 else if (wglMakeCurrent ((HDC )myWindowDC, (HGLRC )myGContext) != TRUE)
252 {
253 // notice that glGetError() couldn't be used here!
254 wchar_t* aMsgBuff = NULL;
255 DWORD anErrorCode = GetLastError();
256 FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
257 NULL, anErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (wchar_t* )&aMsgBuff, 0, NULL);
cbf18624 258 TCollection_ExtendedString aMsg ("wglMakeCurrent() has failed. ");
86fa64d9 259 if (aMsgBuff != NULL)
260 {
cbf18624 261 aMsg += (Standard_ExtString )aMsgBuff;
86fa64d9 262 LocalFree (aMsgBuff);
263 }
cbf18624 264 PushMessage (GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB, GL_DEBUG_TYPE_ERROR_ARB, (unsigned int )anErrorCode, GL_DEBUG_SEVERITY_HIGH_ARB, aMsg);
2bd4c032 265 return Standard_False;
266 }
267#else
86fa64d9 268 if (myDisplay == NULL || myWindow == 0 || myGContext == 0)
269 {
270 Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called before!");
271 return Standard_False;
272 }
273
274 if (!glXMakeCurrent ((Display* )myDisplay, (GLXDrawable )myWindow, (GLXContext )myGContext))
2bd4c032 275 {
276 // if there is no current context it might be impossible to use glGetError() correctly
cbf18624 277 PushMessage (GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB, GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB,
278 "glXMakeCurrent() has failed!");
2bd4c032 279 return Standard_False;
280 }
281#endif
282 return Standard_True;
283}
284
5e27df78 285// =======================================================================
286// function : SwapBuffers
287// purpose :
288// =======================================================================
289void OpenGl_Context::SwapBuffers()
290{
58655684 291#if defined(_WIN32)
5e27df78 292 if ((HDC )myWindowDC != NULL)
293 {
294 ::SwapBuffers ((HDC )myWindowDC);
295 glFlush();
296 }
297#else
298 if ((Display* )myDisplay != NULL)
299 {
300 glXSwapBuffers ((Display* )myDisplay, (GLXDrawable )myWindow);
301 }
302#endif
303}
304
4fe56619 305#endif // __APPLE__
306
5f8b738e 307// =======================================================================
308// function : findProc
309// purpose :
310// =======================================================================
311void* OpenGl_Context::findProc (const char* theFuncName)
312{
58655684 313#if defined(_WIN32)
5f8b738e 314 return wglGetProcAddress (theFuncName);
315#elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
316 return (myGlLibHandle != NULL) ? dlsym (myGlLibHandle, theFuncName) : NULL;
317#else
318 return (void* )glXGetProcAddress ((const GLubyte* )theFuncName);
319#endif
2166f0fa
SK
320}
321
322// =======================================================================
323// function : CheckExtension
324// purpose :
325// =======================================================================
2bd4c032 326Standard_Boolean OpenGl_Context::CheckExtension (const char* theExtName) const
2166f0fa 327{
5f8b738e 328 if (theExtName == NULL)
329 {
330 std::cerr << "CheckExtension called with NULL string!\n";
331 return Standard_False;
332 }
5f8b738e 333
334 // available since OpenGL 3.0
335 // and the ONLY way to check extensions with OpenGL 3.1+ core profile
2bd4c032 336 /**if (IsGlGreaterEqual (3, 0))
5f8b738e 337 {
338 GLint anExtNb = 0;
339 glGetIntegerv (GL_NUM_EXTENSIONS, &anExtNb);
340 for (GLint anIter = 0; anIter < anExtNb; ++anIter)
341 {
342 const char* anExtension = (const char* )core30->glGetStringi (GL_EXTENSIONS, (GLuint )anIter);
343 if (anExtension[anExtNameLen] == '\0' &&
344 strncmp (anExtension, theExtName, anExtNameLen) == 0)
345 {
346 return Standard_True;
347 }
348 }
349 return Standard_False;
350 }*/
351
352 // use old way with huge string for all extensions
353 const char* anExtString = (const char* )glGetString (GL_EXTENSIONS);
354 if (anExtString == NULL)
355 {
cbf18624 356 Messanger()->Send ("TKOpenGL: glGetString (GL_EXTENSIONS) has returned NULL! No GL context?", Message_Warning);
2166f0fa
SK
357 return Standard_False;
358 }
58655684 359 return CheckExtension (anExtString, theExtName);
360}
361
362// =======================================================================
363// function : CheckExtension
364// purpose :
365// =======================================================================
366Standard_Boolean OpenGl_Context::CheckExtension (const char* theExtString,
367 const char* theExtName)
368{
369 if (theExtString == NULL)
370 {
371 return Standard_False;
372 }
2166f0fa
SK
373
374 // Search for theExtName in the extensions string.
375 // Use of strstr() is not sufficient because extension names can be prefixes of other extension names.
58655684 376 char* aPtrIter = (char* )theExtString;
377 const char* aPtrEnd = aPtrIter + strlen (theExtString);
378 const size_t anExtNameLen = strlen (theExtName);
2166f0fa
SK
379 while (aPtrIter < aPtrEnd)
380 {
6a7d83c4 381 const size_t n = strcspn (aPtrIter, " ");
5f8b738e 382 if ((n == anExtNameLen) && (strncmp (aPtrIter, theExtName, anExtNameLen) == 0))
383 {
2166f0fa 384 return Standard_True;
5f8b738e 385 }
2166f0fa
SK
386 aPtrIter += (n + 1);
387 }
388 return Standard_False;
389}
390
4fe56619 391#if !defined(__APPLE__) || defined(MACOSX_USE_GLX)
392
2166f0fa
SK
393// =======================================================================
394// function : Init
395// purpose :
396// =======================================================================
f0430952 397Standard_Boolean OpenGl_Context::Init()
2166f0fa 398{
2bd4c032 399 if (myIsInitialized)
5f8b738e 400 {
f0430952 401 return Standard_True;
5f8b738e 402 }
2bd4c032 403
58655684 404#if defined(_WIN32)
2bd4c032 405 myWindowDC = (Aspect_Handle )wglGetCurrentDC();
406 myGContext = (Aspect_RenderingContext )wglGetCurrentContext();
407#else
408 myDisplay = (Aspect_Display )glXGetCurrentDisplay();
409 myGContext = (Aspect_RenderingContext )glXGetCurrentContext();
410 myWindow = (Aspect_Drawable )glXGetCurrentDrawable();
411#endif
f0430952 412 if (myGContext == NULL)
413 {
414 return Standard_False;
415 }
2bd4c032 416
417 init();
418 myIsInitialized = Standard_True;
f0430952 419 return Standard_True;
2bd4c032 420}
421
4fe56619 422#endif // __APPLE__
423
2bd4c032 424// =======================================================================
425// function : Init
426// purpose :
427// =======================================================================
58655684 428#if defined(_WIN32)
f0430952 429Standard_Boolean OpenGl_Context::Init (const Aspect_Handle theWindow,
430 const Aspect_Handle theWindowDC,
431 const Aspect_RenderingContext theGContext)
4fe56619 432#elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
433Standard_Boolean OpenGl_Context::Init (const void* theGContext)
2bd4c032 434#else
f0430952 435Standard_Boolean OpenGl_Context::Init (const Aspect_Drawable theWindow,
436 const Aspect_Display theDisplay,
437 const Aspect_RenderingContext theGContext)
2bd4c032 438#endif
439{
440 Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called only once!");
58655684 441#if defined(_WIN32)
2bd4c032 442 myWindow = theWindow;
443 myGContext = theGContext;
2bd4c032 444 myWindowDC = theWindowDC;
4fe56619 445#elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
446 myGContext = (void* )theGContext;
2bd4c032 447#else
4fe56619 448 myWindow = theWindow;
449 myGContext = theGContext;
2bd4c032 450 myDisplay = theDisplay;
451#endif
86fa64d9 452 if (myGContext == NULL || !MakeCurrent())
f0430952 453 {
454 return Standard_False;
455 }
2bd4c032 456
457 init();
458 myIsInitialized = Standard_True;
f0430952 459 return Standard_True;
5f8b738e 460}
461
462// =======================================================================
463// function : ResetErrors
464// purpose :
465// =======================================================================
466void OpenGl_Context::ResetErrors()
467{
468 while (glGetError() != GL_NO_ERROR)
469 {
470 //
471 }
472}
473
474// =======================================================================
475// function : readGlVersion
476// purpose :
477// =======================================================================
478void OpenGl_Context::readGlVersion()
479{
480 // reset values
481 myGlVerMajor = 0;
482 myGlVerMinor = 0;
483
484 // available since OpenGL 3.0
86325709 485 GLint aMajor = 0, aMinor = 0;
5f8b738e 486 glGetIntegerv (GL_MAJOR_VERSION, &aMajor);
487 glGetIntegerv (GL_MINOR_VERSION, &aMinor);
86325709 488 // glGetError() sometimes does not report an error here even if
489 // GL does not know GL_MAJOR_VERSION and GL_MINOR_VERSION constants.
490 // This happens on some rendereres like e.g. Cygwin MESA.
491 // Thus checking additionally if GL has put anything to
492 // the output variables.
493 if (glGetError() == GL_NO_ERROR && aMajor != 0 && aMinor != 0)
5f8b738e 494 {
495 myGlVerMajor = aMajor;
496 myGlVerMinor = aMinor;
497 return;
498 }
499 ResetErrors();
500
501 // Read version string.
502 // Notice that only first two numbers splitted by point '2.1 XXXXX' are significant.
503 // Following trash (after space) is vendor-specific.
504 // New drivers also returns micro version of GL like '3.3.0' which has no meaning
505 // and should be considered as vendor-specific too.
506 const char* aVerStr = (const char* )glGetString (GL_VERSION);
507 if (aVerStr == NULL || *aVerStr == '\0')
508 {
509 // invalid GL context
510 return;
511 }
512
513 // parse string for major number
514 char aMajorStr[32];
515 char aMinorStr[32];
516 size_t aMajIter = 0;
517 while (aVerStr[aMajIter] >= '0' && aVerStr[aMajIter] <= '9')
518 {
519 ++aMajIter;
520 }
521 if (aMajIter == 0 || aMajIter >= sizeof(aMajorStr))
522 {
523 return;
524 }
525 memcpy (aMajorStr, aVerStr, aMajIter);
526 aMajorStr[aMajIter] = '\0';
527
528 // parse string for minor number
86325709 529 aVerStr += aMajIter + 1;
530 size_t aMinIter = 0;
5f8b738e 531 while (aVerStr[aMinIter] >= '0' && aVerStr[aMinIter] <= '9')
532 {
533 ++aMinIter;
534 }
86325709 535 if (aMinIter == 0 || aMinIter >= sizeof(aMinorStr))
5f8b738e 536 {
537 return;
538 }
86325709 539 memcpy (aMinorStr, aVerStr, aMinIter);
540 aMinorStr[aMinIter] = '\0';
5f8b738e 541
542 // read numbers
543 myGlVerMajor = atoi (aMajorStr);
544 myGlVerMinor = atoi (aMinorStr);
545
546 if (myGlVerMajor <= 0)
547 {
548 myGlVerMajor = 0;
549 myGlVerMinor = 0;
550 }
551}
552
58655684 553static Standard_CString THE_DBGMSG_UNKNOWN = "UNKNOWN";
554static Standard_CString THE_DBGMSG_SOURCES[] =
555{
cbf18624 556 ".OpenGL", // GL_DEBUG_SOURCE_API_ARB
557 ".WinSystem", // GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB
558 ".GLSL", // GL_DEBUG_SOURCE_SHADER_COMPILER_ARB
559 ".3rdParty", // GL_DEBUG_SOURCE_THIRD_PARTY_ARB
560 "", // GL_DEBUG_SOURCE_APPLICATION_ARB
561 ".Other" // GL_DEBUG_SOURCE_OTHER_ARB
58655684 562};
563
564static Standard_CString THE_DBGMSG_TYPES[] =
565{
cbf18624 566 "Error", // GL_DEBUG_TYPE_ERROR_ARB
567 "Deprecated", // GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB
568 "Undef. behavior", // GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB
569 "Portability", // GL_DEBUG_TYPE_PORTABILITY_ARB
570 "Performance", // GL_DEBUG_TYPE_PERFORMANCE_ARB
571 "Other" // GL_DEBUG_TYPE_OTHER_ARB
58655684 572};
573
574static Standard_CString THE_DBGMSG_SEV_HIGH = "High"; // GL_DEBUG_SEVERITY_HIGH_ARB
575static Standard_CString THE_DBGMSG_SEV_MEDIUM = "Medium"; // GL_DEBUG_SEVERITY_MEDIUM_ARB
576static Standard_CString THE_DBGMSG_SEV_LOW = "Low"; // GL_DEBUG_SEVERITY_LOW_ARB
577
cbf18624 578//! Callback for GL_ARB_debug_output extension
58655684 579static void APIENTRY debugCallbackWrap(unsigned int theSource,
580 unsigned int theType,
581 unsigned int theId,
582 unsigned int theSeverity,
583 int /*theLength*/,
584 const char* theMessage,
cbf18624 585 void* theUserParam)
586{
587 OpenGl_Context* aCtx = (OpenGl_Context* )theUserParam;
588 aCtx->PushMessage (theSource, theType, theId, theSeverity, theMessage);
589}
590
591// =======================================================================
592// function : PushMessage
593// purpose :
594// =======================================================================
595void OpenGl_Context::PushMessage (const unsigned int theSource,
596 const unsigned int theType,
597 const unsigned int theId,
598 const unsigned int theSeverity,
599 const TCollection_ExtendedString& theMessage)
58655684 600{
601 //OpenGl_Context* aCtx = (OpenGl_Context* )theUserParam;
602 Standard_CString& aSrc = (theSource >= GL_DEBUG_SOURCE_API_ARB
603 && theSource <= GL_DEBUG_SOURCE_OTHER_ARB)
604 ? THE_DBGMSG_SOURCES[theSource - GL_DEBUG_SOURCE_API_ARB]
605 : THE_DBGMSG_UNKNOWN;
606 Standard_CString& aType = (theType >= GL_DEBUG_TYPE_ERROR_ARB
607 && theType <= GL_DEBUG_TYPE_OTHER_ARB)
608 ? THE_DBGMSG_TYPES[theType - GL_DEBUG_TYPE_ERROR_ARB]
609 : THE_DBGMSG_UNKNOWN;
610 Standard_CString& aSev = theSeverity == GL_DEBUG_SEVERITY_HIGH_ARB
611 ? THE_DBGMSG_SEV_HIGH
612 : (theSeverity == GL_DEBUG_SEVERITY_MEDIUM_ARB
613 ? THE_DBGMSG_SEV_MEDIUM
614 : THE_DBGMSG_SEV_LOW);
cbf18624 615 Message_Gravity aGrav = theSeverity == GL_DEBUG_SEVERITY_HIGH_ARB
616 ? Message_Alarm
617 : (theSeverity == GL_DEBUG_SEVERITY_MEDIUM_ARB
618 ? Message_Warning
619 : Message_Info);
620
621 TCollection_ExtendedString aMsg;
622 aMsg += "TKOpenGl"; aMsg += aSrc;
623 aMsg += " | Type: "; aMsg += aType;
624 aMsg += " | ID: "; aMsg += (Standard_Integer )theId;
625 aMsg += " | Severity: "; aMsg += aSev;
626 aMsg += " | Message:\n ";
627 aMsg += theMessage;
628
629 Messanger()->Send (aMsg, aGrav);
58655684 630}
631
5f8b738e 632// =======================================================================
633// function : init
634// purpose :
635// =======================================================================
636void OpenGl_Context::init()
637{
638 // read version
639 readGlVersion();
640
bf75be98 641 arbNPTW = CheckExtension ("GL_ARB_texture_non_power_of_two");
642 extBgra = CheckExtension ("GL_EXT_bgra");
643 extAnis = CheckExtension ("GL_EXT_texture_filter_anisotropic");
b859a34d 644 extPDS = CheckExtension ("GL_EXT_packed_depth_stencil");
bf75be98 645 atiMem = CheckExtension ("GL_ATI_meminfo");
646 nvxMem = CheckExtension ("GL_NVX_gpu_memory_info");
647
4269bd1b 648 // get number of maximum clipping planes
649 glGetIntegerv (GL_MAX_CLIP_PLANES, &myMaxClipPlanes);
bf75be98 650 glGetIntegerv (GL_MAX_TEXTURE_SIZE, &myMaxTexDim);
651 if (extAnis)
652 {
653 glGetIntegerv (GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &myAnisoMax);
654 }
f0430952 655
4269bd1b 656 myClippingState.Init (myMaxClipPlanes);
657
58655684 658 // initialize debug context extension
659 if (CheckExtension ("GL_ARB_debug_output"))
660 {
661 arbDbg = new OpenGl_ArbDbg();
662 memset (arbDbg, 0, sizeof(OpenGl_ArbDbg)); // nullify whole structure
663 if (!FindProcShort (arbDbg, glDebugMessageControlARB)
664 || !FindProcShort (arbDbg, glDebugMessageInsertARB)
665 || !FindProcShort (arbDbg, glDebugMessageCallbackARB)
666 || !FindProcShort (arbDbg, glGetDebugMessageLogARB))
667 {
668 delete arbDbg;
669 arbDbg = NULL;
670 }
671 if (arbDbg != NULL
672 && caps->contextDebug)
673 {
674 // setup default callback
675 arbDbg->glDebugMessageCallbackARB (debugCallbackWrap, this);
fcdbe201 676 #ifdef DEB
58655684 677 glEnable (GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
fcdbe201 678 #endif
58655684 679 }
680 }
681
5f8b738e 682 // initialize VBO extension (ARB)
683 if (CheckExtension ("GL_ARB_vertex_buffer_object"))
2166f0fa
SK
684 {
685 arbVBO = new OpenGl_ArbVBO();
5f8b738e 686 memset (arbVBO, 0, sizeof(OpenGl_ArbVBO)); // nullify whole structure
687 if (!FindProcShort (arbVBO, glGenBuffersARB)
688 || !FindProcShort (arbVBO, glBindBufferARB)
689 || !FindProcShort (arbVBO, glBufferDataARB)
690 || !FindProcShort (arbVBO, glDeleteBuffersARB))
2166f0fa
SK
691 {
692 delete arbVBO;
693 arbVBO = NULL;
694 }
695 }
696
5e27df78 697 // initialize TBO extension (ARB)
698 if (CheckExtension ("GL_ARB_texture_buffer_object"))
699 {
700 arbTBO = new OpenGl_ArbTBO();
701 memset (arbTBO, 0, sizeof(OpenGl_ArbTBO)); // nullify whole structure
702 if (!FindProcShort (arbTBO, glTexBufferARB))
703 {
704 delete arbTBO;
705 arbTBO = NULL;
706 }
707 }
708
709 // initialize hardware instancing extension (ARB)
710 if (CheckExtension ("GL_ARB_draw_instanced"))
711 {
712 arbIns = new OpenGl_ArbIns();
713 memset (arbIns, 0, sizeof(OpenGl_ArbIns)); // nullify whole structure
714 if (!FindProcShort (arbIns, glDrawArraysInstancedARB)
715 || !FindProcShort (arbIns, glDrawElementsInstancedARB))
716 {
717 delete arbIns;
718 arbIns = NULL;
719 }
720 }
721
5f8b738e 722 // initialize FBO extension (EXT)
723 if (CheckExtension ("GL_EXT_framebuffer_object"))
2166f0fa
SK
724 {
725 extFBO = new OpenGl_ExtFBO();
5f8b738e 726 memset (extFBO, 0, sizeof(OpenGl_ExtFBO)); // nullify whole structure
727 if (!FindProcShort (extFBO, glGenFramebuffersEXT)
728 || !FindProcShort (extFBO, glDeleteFramebuffersEXT)
729 || !FindProcShort (extFBO, glBindFramebufferEXT)
730 || !FindProcShort (extFBO, glFramebufferTexture2DEXT)
731 || !FindProcShort (extFBO, glCheckFramebufferStatusEXT)
732 || !FindProcShort (extFBO, glGenRenderbuffersEXT)
733 || !FindProcShort (extFBO, glDeleteRenderbuffersEXT)
734 || !FindProcShort (extFBO, glBindRenderbufferEXT)
735 || !FindProcShort (extFBO, glRenderbufferStorageEXT)
1a7dfdb7 736 || !FindProcShort (extFBO, glFramebufferRenderbufferEXT)
737 || !FindProcShort (extFBO, glGenerateMipmapEXT))
2166f0fa
SK
738 {
739 delete extFBO;
740 extFBO = NULL;
741 }
742 }
5f8b738e 743
37eb4787 744 // initialize GS extension (EXT)
745 if (CheckExtension ("GL_EXT_geometry_shader4"))
746 {
747 extGS = new OpenGl_ExtGS();
748 memset (extGS, 0, sizeof(OpenGl_ExtGS)); // nullify whole structure
749 if (!FindProcShort (extGS, glProgramParameteriEXT))
750 {
751 delete extGS;
752 extGS = NULL;
753 }
754 }
755
5f8b738e 756 myGlCore20 = new OpenGl_GlCore20();
757 memset (myGlCore20, 0, sizeof(OpenGl_GlCore20)); // nullify whole structure
758
86325709 759 // Check if OpenGL 1.2 core functionality is actually present
760 Standard_Boolean hasGlCore12 = IsGlGreaterEqual (1, 2)
761 && FindProcShort (myGlCore20, glBlendColor)
762 && FindProcShort (myGlCore20, glBlendEquation)
763 && FindProcShort (myGlCore20, glDrawRangeElements)
764 && FindProcShort (myGlCore20, glTexImage3D)
765 && FindProcShort (myGlCore20, glTexSubImage3D)
766 && FindProcShort (myGlCore20, glCopyTexSubImage3D);
767
768 // Check if OpenGL 1.3 core functionality is actually present
769 Standard_Boolean hasGlCore13 = IsGlGreaterEqual (1, 3)
770 && FindProcShort (myGlCore20, glActiveTexture)
771 && FindProcShort (myGlCore20, glSampleCoverage)
772 && FindProcShort (myGlCore20, glCompressedTexImage3D)
773 && FindProcShort (myGlCore20, glCompressedTexImage2D)
774 && FindProcShort (myGlCore20, glCompressedTexImage1D)
775 && FindProcShort (myGlCore20, glCompressedTexSubImage3D)
776 && FindProcShort (myGlCore20, glCompressedTexSubImage2D)
777 && FindProcShort (myGlCore20, glCompressedTexSubImage1D)
778 && FindProcShort (myGlCore20, glGetCompressedTexImage)
779 // deprecated
780 && FindProcShort (myGlCore20, glClientActiveTexture)
781 && FindProcShort (myGlCore20, glMultiTexCoord1d)
782 && FindProcShort (myGlCore20, glMultiTexCoord1dv)
783 && FindProcShort (myGlCore20, glMultiTexCoord1f)
784 && FindProcShort (myGlCore20, glMultiTexCoord1fv)
785 && FindProcShort (myGlCore20, glMultiTexCoord1i)
786 && FindProcShort (myGlCore20, glMultiTexCoord1iv)
787 && FindProcShort (myGlCore20, glMultiTexCoord1s)
788 && FindProcShort (myGlCore20, glMultiTexCoord1sv)
789 && FindProcShort (myGlCore20, glMultiTexCoord2d)
790 && FindProcShort (myGlCore20, glMultiTexCoord2dv)
791 && FindProcShort (myGlCore20, glMultiTexCoord2f)
792 && FindProcShort (myGlCore20, glMultiTexCoord2fv)
793 && FindProcShort (myGlCore20, glMultiTexCoord2i)
794 && FindProcShort (myGlCore20, glMultiTexCoord2iv)
795 && FindProcShort (myGlCore20, glMultiTexCoord2s)
796 && FindProcShort (myGlCore20, glMultiTexCoord2sv)
797 && FindProcShort (myGlCore20, glMultiTexCoord3d)
798 && FindProcShort (myGlCore20, glMultiTexCoord3dv)
799 && FindProcShort (myGlCore20, glMultiTexCoord3f)
800 && FindProcShort (myGlCore20, glMultiTexCoord3fv)
801 && FindProcShort (myGlCore20, glMultiTexCoord3i)
802 && FindProcShort (myGlCore20, glMultiTexCoord3iv)
803 && FindProcShort (myGlCore20, glMultiTexCoord3s)
804 && FindProcShort (myGlCore20, glMultiTexCoord3sv)
805 && FindProcShort (myGlCore20, glMultiTexCoord4d)
806 && FindProcShort (myGlCore20, glMultiTexCoord4dv)
807 && FindProcShort (myGlCore20, glMultiTexCoord4f)
808 && FindProcShort (myGlCore20, glMultiTexCoord4fv)
809 && FindProcShort (myGlCore20, glMultiTexCoord4i)
810 && FindProcShort (myGlCore20, glMultiTexCoord4iv)
811 && FindProcShort (myGlCore20, glMultiTexCoord4s)
812 && FindProcShort (myGlCore20, glMultiTexCoord4sv)
813 && FindProcShort (myGlCore20, glLoadTransposeMatrixf)
814 && FindProcShort (myGlCore20, glLoadTransposeMatrixd)
815 && FindProcShort (myGlCore20, glMultTransposeMatrixf)
816 && FindProcShort (myGlCore20, glMultTransposeMatrixd);
817
818 // Check if OpenGL 1.4 core functionality is actually present
819 Standard_Boolean hasGlCore14 = IsGlGreaterEqual (1, 4)
820 && FindProcShort (myGlCore20, glBlendFuncSeparate)
821 && FindProcShort (myGlCore20, glMultiDrawArrays)
822 && FindProcShort (myGlCore20, glMultiDrawElements)
823 && FindProcShort (myGlCore20, glPointParameterf)
824 && FindProcShort (myGlCore20, glPointParameterfv)
825 && FindProcShort (myGlCore20, glPointParameteri)
826 && FindProcShort (myGlCore20, glPointParameteriv);
827
828 // Check if OpenGL 1.5 core functionality is actually present
829 Standard_Boolean hasGlCore15 = IsGlGreaterEqual (1, 5)
830 && FindProcShort (myGlCore20, glGenQueries)
831 && FindProcShort (myGlCore20, glDeleteQueries)
832 && FindProcShort (myGlCore20, glIsQuery)
833 && FindProcShort (myGlCore20, glBeginQuery)
834 && FindProcShort (myGlCore20, glEndQuery)
835 && FindProcShort (myGlCore20, glGetQueryiv)
836 && FindProcShort (myGlCore20, glGetQueryObjectiv)
837 && FindProcShort (myGlCore20, glGetQueryObjectuiv)
838 && FindProcShort (myGlCore20, glBindBuffer)
839 && FindProcShort (myGlCore20, glDeleteBuffers)
840 && FindProcShort (myGlCore20, glGenBuffers)
841 && FindProcShort (myGlCore20, glIsBuffer)
842 && FindProcShort (myGlCore20, glBufferData)
843 && FindProcShort (myGlCore20, glBufferSubData)
844 && FindProcShort (myGlCore20, glGetBufferSubData)
845 && FindProcShort (myGlCore20, glMapBuffer)
846 && FindProcShort (myGlCore20, glUnmapBuffer)
847 && FindProcShort (myGlCore20, glGetBufferParameteriv)
848 && FindProcShort (myGlCore20, glGetBufferPointerv);
849
850 // Check if OpenGL 2.0 core functionality is actually present
851 Standard_Boolean hasGlCore20 = IsGlGreaterEqual (2, 0)
852 && FindProcShort (myGlCore20, glBlendEquationSeparate)
853 && FindProcShort (myGlCore20, glDrawBuffers)
854 && FindProcShort (myGlCore20, glStencilOpSeparate)
855 && FindProcShort (myGlCore20, glStencilFuncSeparate)
856 && FindProcShort (myGlCore20, glStencilMaskSeparate)
857 && FindProcShort (myGlCore20, glAttachShader)
858 && FindProcShort (myGlCore20, glBindAttribLocation)
859 && FindProcShort (myGlCore20, glCompileShader)
860 && FindProcShort (myGlCore20, glCreateProgram)
861 && FindProcShort (myGlCore20, glCreateShader)
862 && FindProcShort (myGlCore20, glDeleteProgram)
863 && FindProcShort (myGlCore20, glDeleteShader)
864 && FindProcShort (myGlCore20, glDetachShader)
865 && FindProcShort (myGlCore20, glDisableVertexAttribArray)
866 && FindProcShort (myGlCore20, glEnableVertexAttribArray)
867 && FindProcShort (myGlCore20, glGetActiveAttrib)
868 && FindProcShort (myGlCore20, glGetActiveUniform)
869 && FindProcShort (myGlCore20, glGetAttachedShaders)
870 && FindProcShort (myGlCore20, glGetAttribLocation)
871 && FindProcShort (myGlCore20, glGetProgramiv)
872 && FindProcShort (myGlCore20, glGetProgramInfoLog)
873 && FindProcShort (myGlCore20, glGetShaderiv)
874 && FindProcShort (myGlCore20, glGetShaderInfoLog)
875 && FindProcShort (myGlCore20, glGetShaderSource)
876 && FindProcShort (myGlCore20, glGetUniformLocation)
877 && FindProcShort (myGlCore20, glGetUniformfv)
878 && FindProcShort (myGlCore20, glGetUniformiv)
879 && FindProcShort (myGlCore20, glGetVertexAttribdv)
880 && FindProcShort (myGlCore20, glGetVertexAttribfv)
881 && FindProcShort (myGlCore20, glGetVertexAttribiv)
882 && FindProcShort (myGlCore20, glGetVertexAttribPointerv)
883 && FindProcShort (myGlCore20, glIsProgram)
884 && FindProcShort (myGlCore20, glIsShader)
885 && FindProcShort (myGlCore20, glLinkProgram)
886 && FindProcShort (myGlCore20, glShaderSource)
887 && FindProcShort (myGlCore20, glUseProgram)
888 && FindProcShort (myGlCore20, glUniform1f)
889 && FindProcShort (myGlCore20, glUniform2f)
890 && FindProcShort (myGlCore20, glUniform3f)
891 && FindProcShort (myGlCore20, glUniform4f)
892 && FindProcShort (myGlCore20, glUniform1i)
893 && FindProcShort (myGlCore20, glUniform2i)
894 && FindProcShort (myGlCore20, glUniform3i)
895 && FindProcShort (myGlCore20, glUniform4i)
896 && FindProcShort (myGlCore20, glUniform1fv)
897 && FindProcShort (myGlCore20, glUniform2fv)
898 && FindProcShort (myGlCore20, glUniform3fv)
899 && FindProcShort (myGlCore20, glUniform4fv)
900 && FindProcShort (myGlCore20, glUniform1iv)
901 && FindProcShort (myGlCore20, glUniform2iv)
902 && FindProcShort (myGlCore20, glUniform3iv)
903 && FindProcShort (myGlCore20, glUniform4iv)
904 && FindProcShort (myGlCore20, glUniformMatrix2fv)
905 && FindProcShort (myGlCore20, glUniformMatrix3fv)
906 && FindProcShort (myGlCore20, glUniformMatrix4fv)
907 && FindProcShort (myGlCore20, glValidateProgram)
908 && FindProcShort (myGlCore20, glVertexAttrib1d)
909 && FindProcShort (myGlCore20, glVertexAttrib1dv)
910 && FindProcShort (myGlCore20, glVertexAttrib1f)
911 && FindProcShort (myGlCore20, glVertexAttrib1fv)
912 && FindProcShort (myGlCore20, glVertexAttrib1s)
913 && FindProcShort (myGlCore20, glVertexAttrib1sv)
914 && FindProcShort (myGlCore20, glVertexAttrib2d)
915 && FindProcShort (myGlCore20, glVertexAttrib2dv)
916 && FindProcShort (myGlCore20, glVertexAttrib2f)
917 && FindProcShort (myGlCore20, glVertexAttrib2fv)
918 && FindProcShort (myGlCore20, glVertexAttrib2s)
919 && FindProcShort (myGlCore20, glVertexAttrib2sv)
920 && FindProcShort (myGlCore20, glVertexAttrib3d)
921 && FindProcShort (myGlCore20, glVertexAttrib3dv)
922 && FindProcShort (myGlCore20, glVertexAttrib3f)
923 && FindProcShort (myGlCore20, glVertexAttrib3fv)
924 && FindProcShort (myGlCore20, glVertexAttrib3s)
925 && FindProcShort (myGlCore20, glVertexAttrib3sv)
926 && FindProcShort (myGlCore20, glVertexAttrib4Nbv)
927 && FindProcShort (myGlCore20, glVertexAttrib4Niv)
928 && FindProcShort (myGlCore20, glVertexAttrib4Nsv)
929 && FindProcShort (myGlCore20, glVertexAttrib4Nub)
930 && FindProcShort (myGlCore20, glVertexAttrib4Nubv)
931 && FindProcShort (myGlCore20, glVertexAttrib4Nuiv)
932 && FindProcShort (myGlCore20, glVertexAttrib4Nusv)
933 && FindProcShort (myGlCore20, glVertexAttrib4bv)
934 && FindProcShort (myGlCore20, glVertexAttrib4d)
935 && FindProcShort (myGlCore20, glVertexAttrib4dv)
936 && FindProcShort (myGlCore20, glVertexAttrib4f)
937 && FindProcShort (myGlCore20, glVertexAttrib4fv)
938 && FindProcShort (myGlCore20, glVertexAttrib4iv)
939 && FindProcShort (myGlCore20, glVertexAttrib4s)
940 && FindProcShort (myGlCore20, glVertexAttrib4sv)
941 && FindProcShort (myGlCore20, glVertexAttrib4ubv)
942 && FindProcShort (myGlCore20, glVertexAttrib4uiv)
943 && FindProcShort (myGlCore20, glVertexAttrib4usv)
944 && FindProcShort (myGlCore20, glVertexAttribPointer);
945
946 if (!hasGlCore12)
947 {
948 myGlVerMajor = 1;
949 myGlVerMinor = 1;
950 return;
5f8b738e 951 }
86325709 952 else
5f8b738e 953 {
86325709 954 core12 = myGlCore20;
5f8b738e 955 }
86325709 956 if (!hasGlCore13)
5f8b738e 957 {
86325709 958 myGlVerMajor = 1;
959 myGlVerMinor = 2;
960 return;
5f8b738e 961 }
86325709 962 else
963 {
964 core13 = myGlCore20;
5f8b738e 965 }
86325709 966 if(!hasGlCore14)
967 {
968 myGlVerMajor = 1;
969 myGlVerMinor = 3;
970 return;
5f8b738e 971 }
86325709 972 else
5f8b738e 973 {
5f8b738e 974 core14 = myGlCore20;
86325709 975 }
976 if(!hasGlCore15)
977 {
978 myGlVerMajor = 1;
979 myGlVerMinor = 4;
980 return;
981 }
982 else
983 {
5f8b738e 984 core15 = myGlCore20;
86325709 985 }
986 if(!hasGlCore20)
987 {
988 myGlVerMajor = 1;
989 myGlVerMinor = 5;
990 }
991 else
992 {
5f8b738e 993 core20 = myGlCore20;
994 }
2166f0fa 995}
664cae74 996// =======================================================================
997// function : IsFeedback
998// purpose :
999// =======================================================================
1000Standard_Boolean OpenGl_Context::IsFeedback() const
1001{
1002 return myIsFeedback;
1003}
1004
1005// =======================================================================
1006// function : SetFeedback
1007// purpose :
1008// =======================================================================
1009void OpenGl_Context::SetFeedback (const Standard_Boolean theFeedbackOn)
1010{
1011 myIsFeedback = theFeedbackOn;
1012}
f0430952 1013
1014// =======================================================================
1015// function : MemoryInfo
1016// purpose :
1017// =======================================================================
1018Standard_Size OpenGl_Context::AvailableMemory() const
1019{
1020 if (atiMem)
1021 {
1022 // this is actually information for VBO pool
1023 // however because pools are mostly shared
1024 // it can be used for total GPU memory estimations
1025 GLint aMemInfo[4];
1026 aMemInfo[0] = 0;
1027 glGetIntegerv (GL_VBO_FREE_MEMORY_ATI, aMemInfo);
1028 // returned value is in KiB, however this maybe changed in future
1029 return Standard_Size(aMemInfo[0]) * 1024;
1030 }
1031 else if (nvxMem)
1032 {
1033 // current available dedicated video memory (in KiB), currently unused GPU memory
1034 GLint aMemInfo = 0;
1035 glGetIntegerv (GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &aMemInfo);
1036 return Standard_Size(aMemInfo) * 1024;
1037 }
1038 return 0;
1039}
1040
1041// =======================================================================
1042// function : MemoryInfo
1043// purpose :
1044// =======================================================================
1045TCollection_AsciiString OpenGl_Context::MemoryInfo() const
1046{
1047 TCollection_AsciiString anInfo;
1048 if (atiMem)
1049 {
1050 GLint aValues[4];
1051 memset (aValues, 0, sizeof(aValues));
1052 glGetIntegerv (GL_VBO_FREE_MEMORY_ATI, aValues);
1053
1054 // total memory free in the pool
1055 anInfo += TCollection_AsciiString (" GPU free memory: ") + (aValues[0] / 1024) + " MiB\n";
1056
1057 // largest available free block in the pool
1058 anInfo += TCollection_AsciiString (" Largest free block: ") + (aValues[1] / 1024) + " MiB\n";
1059 if (aValues[2] != aValues[0])
1060 {
1061 // total auxiliary memory free
1062 anInfo += TCollection_AsciiString (" Free memory: ") + (aValues[2] / 1024) + " MiB\n";
1063 }
1064 }
1065 else if (nvxMem)
1066 {
1067 //current available dedicated video memory (in KiB), currently unused GPU memory
1068 GLint aValue = 0;
1069 glGetIntegerv (GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &aValue);
1070 anInfo += TCollection_AsciiString (" GPU free memory: ") + (aValue / 1024) + " MiB\n";
1071
1072 // dedicated video memory, total size (in KiB) of the GPU memory
1073 GLint aDedicated = 0;
1074 glGetIntegerv (GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, &aDedicated);
1075 anInfo += TCollection_AsciiString (" GPU memory: ") + (aDedicated / 1024) + " MiB\n";
1076
1077 // total available memory, total size (in KiB) of the memory available for allocations
1078 glGetIntegerv (GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, &aValue);
1079 if (aValue != aDedicated)
1080 {
1081 // different only for special configurations
1082 anInfo += TCollection_AsciiString (" Total memory: ") + (aValue / 1024) + " MiB\n";
1083 }
1084 }
1085 return anInfo;
1086}
5e27df78 1087
1088
1089// =======================================================================
1090// function : GetResource
1091// purpose :
1092// =======================================================================
1093const Handle(OpenGl_Resource)& OpenGl_Context::GetResource (const TCollection_AsciiString& theKey) const
1094{
1095 return mySharedResources->IsBound (theKey) ? mySharedResources->Find (theKey) : NULL_GL_RESOURCE;
1096}
1097
1098// =======================================================================
1099// function : ShareResource
1100// purpose :
1101// =======================================================================
1102Standard_Boolean OpenGl_Context::ShareResource (const TCollection_AsciiString& theKey,
1103 const Handle(OpenGl_Resource)& theResource)
1104{
1105 if (theKey.IsEmpty() || theResource.IsNull())
1106 {
1107 return Standard_False;
1108 }
1109 return mySharedResources->Bind (theKey, theResource);
1110}
1111
1112// =======================================================================
1113// function : ReleaseResource
1114// purpose :
1115// =======================================================================
a174a3c5 1116void OpenGl_Context::ReleaseResource (const TCollection_AsciiString& theKey,
1117 const Standard_Boolean theToDelay)
5e27df78 1118{
1119 if (!mySharedResources->IsBound (theKey))
1120 {
1121 return;
1122 }
1123 const Handle(OpenGl_Resource)& aRes = mySharedResources->Find (theKey);
1124 if (aRes->GetRefCount() > 1)
1125 {
1126 return;
1127 }
1128
a174a3c5 1129 if (theToDelay)
1130 {
1131 myDelayed->Bind (theKey, 1);
1132 }
1133 else
1134 {
1135 aRes->Release (this);
1136 mySharedResources->UnBind (theKey);
1137 }
5e27df78 1138}
1139
1140// =======================================================================
1141// function : DelayedRelease
1142// purpose :
1143// =======================================================================
1144void OpenGl_Context::DelayedRelease (Handle(OpenGl_Resource)& theResource)
1145{
1146 myReleaseQueue->Push (theResource);
1147 theResource.Nullify();
1148}
1149
1150// =======================================================================
1151// function : ReleaseDelayed
1152// purpose :
1153// =======================================================================
1154void OpenGl_Context::ReleaseDelayed()
1155{
a174a3c5 1156 // release queued elements
5e27df78 1157 while (!myReleaseQueue->IsEmpty())
1158 {
1159 myReleaseQueue->Front()->Release (this);
1160 myReleaseQueue->Pop();
1161 }
a174a3c5 1162
1163 // release delayed shared resoruces
1164 NCollection_Vector<TCollection_AsciiString> aDeadList;
1165 for (NCollection_DataMap<TCollection_AsciiString, Standard_Integer>::Iterator anIter (*myDelayed);
1166 anIter.More(); anIter.Next())
1167 {
1168 if (++anIter.ChangeValue() <= 2)
1169 {
1170 continue; // postpone release one more frame to ensure noone use it periodically
1171 }
1172
1173 const TCollection_AsciiString& aKey = anIter.Key();
1174 if (!mySharedResources->IsBound (aKey))
1175 {
1176 // mixed unshared strategy delayed/undelayed was used!
1177 aDeadList.Append (aKey);
1178 continue;
1179 }
1180
1181 Handle(OpenGl_Resource)& aRes = mySharedResources->ChangeFind (aKey);
1182 if (aRes->GetRefCount() > 1)
1183 {
1184 // should be only 1 instance in mySharedResources
1185 // if not - resource was reused again
1186 aDeadList.Append (aKey);
1187 continue;
1188 }
1189
1190 // release resource if no one requiested it more than 2 redraw calls
1191 aRes->Release (this);
1192 mySharedResources->UnBind (aKey);
1193 aDeadList.Append (aKey);
1194 }
1195
1196 for (Standard_Integer anIter = 0; anIter < aDeadList.Length(); ++anIter)
1197 {
1198 myDelayed->UnBind (aDeadList.Value (anIter));
1199 }
5e27df78 1200}