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