From 26d9c83516ab1bc077697ea795be29fa5b049c24 Mon Sep 17 00:00:00 2001 From: kgv Date: Wed, 31 Aug 2016 21:06:54 +0300 Subject: [PATCH] 0027813: Visualization - add method V3d_View::DiagnosticInformation() similar to vglinfo command New method V3d_View::DiagnosticInformation() has been introduced providing the access to low-level OpenGL context information for diagnostic automated reports or displaying in application About System. --- src/Graphic3d/FILES | 1 + src/Graphic3d/Graphic3d_CView.hxx | 12 + src/Graphic3d/Graphic3d_DiagnosticInfo.hxx | 32 +++ src/OpenGl/OpenGl_Context.cxx | 225 +++++++++++++++++- src/OpenGl/OpenGl_Context.hxx | 17 +- src/OpenGl/OpenGl_GlFunctions.hxx | 31 +++ src/OpenGl/OpenGl_View.cxx | 22 ++ src/OpenGl/OpenGl_View.hxx | 10 + src/TColStd/FILES | 1 + .../TColStd_IndexedDataMapOfStringString.hxx | 22 ++ src/TCollection/TCollection_AsciiString.cxx | 28 +++ src/TCollection/TCollection_AsciiString.hxx | 4 + src/TCollection/TCollection_HAsciiString.cxx | 14 +- src/V3d/V3d_View.cxx | 10 + src/V3d/V3d_View.hxx | 11 + src/ViewerTest/ViewerTest_OpenGlCommands.cxx | 87 +++++-- 16 files changed, 480 insertions(+), 47 deletions(-) create mode 100644 src/Graphic3d/Graphic3d_DiagnosticInfo.hxx create mode 100644 src/TColStd/TColStd_IndexedDataMapOfStringString.hxx diff --git a/src/Graphic3d/FILES b/src/Graphic3d/FILES index 3b2fe4241e..59ed3159f2 100755 --- a/src/Graphic3d/FILES +++ b/src/Graphic3d/FILES @@ -49,6 +49,7 @@ Graphic3d_CView.cxx Graphic3d_CView.hxx Graphic3d_DataStructureManager.cxx Graphic3d_DataStructureManager.hxx +Graphic3d_DiagnosticInfo.hxx Graphic3d_ExportFormat.hxx Graphic3d_GraduatedTrihedron.hxx Graphic3d_GraphicDriver.cxx diff --git a/src/Graphic3d/Graphic3d_CView.hxx b/src/Graphic3d/Graphic3d_CView.hxx index b9e768fae6..3a04dfbe52 100644 --- a/src/Graphic3d/Graphic3d_CView.hxx +++ b/src/Graphic3d/Graphic3d_CView.hxx @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -46,6 +47,7 @@ #include #include #include +#include class Graphic3d_CView; class Graphic3d_GraphicDriver; @@ -459,6 +461,16 @@ public: //! Sets list of clip planes for the view. virtual void SetClipPlanes (const Graphic3d_SequenceOfHClipPlane& thePlanes) = 0; + //! Fill in the dictionary with diagnostic info. + //! Should be called within rendering thread. + //! + //! This API should be used only for user output or for creating automated reports. + //! The format of returned information (e.g. key-value layout) + //! is NOT part of this API and can be changed at any time. + //! Thus application should not parse returned information to weed out specific parameters. + virtual void DiagnosticInformation (TColStd_IndexedDataMapOfStringString& theDict, + Graphic3d_DiagnosticInfo theFlags) const = 0; + private: //! Adds the structure to display lists of the view. diff --git a/src/Graphic3d/Graphic3d_DiagnosticInfo.hxx b/src/Graphic3d/Graphic3d_DiagnosticInfo.hxx new file mode 100644 index 0000000000..86557904d0 --- /dev/null +++ b/src/Graphic3d/Graphic3d_DiagnosticInfo.hxx @@ -0,0 +1,32 @@ +// Copyright (c) 2016 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Graphic3d_DiagnosticInfo_HeaderFile +#define _Graphic3d_DiagnosticInfo_HeaderFile + +//! Diagnostic info categories bit flags. +enum Graphic3d_DiagnosticInfo +{ + Graphic3d_DiagnosticInfo_Device = 0x001, //!< device / vendor / version information + Graphic3d_DiagnosticInfo_FrameBuffer = 0x002, //!< framebuffer information + Graphic3d_DiagnosticInfo_Limits = 0x004, //!< hardware limits + Graphic3d_DiagnosticInfo_Memory = 0x008, //!< memory counters + Graphic3d_DiagnosticInfo_NativePlatform = 0x010, //!< native platform API information (e.g. WGL / GLX / EGL) + Graphic3d_DiagnosticInfo_Extensions = 0x020, //!< vendor extension list (usually very long) + // groups + Graphic3d_DiagnosticInfo_Short = Graphic3d_DiagnosticInfo_Device | Graphic3d_DiagnosticInfo_FrameBuffer | Graphic3d_DiagnosticInfo_Limits, //!< minimal information + Graphic3d_DiagnosticInfo_Basic = Graphic3d_DiagnosticInfo_Short | Graphic3d_DiagnosticInfo_NativePlatform | Graphic3d_DiagnosticInfo_Memory, //!< basic information, without extension list + Graphic3d_DiagnosticInfo_Complete = Graphic3d_DiagnosticInfo_Basic | Graphic3d_DiagnosticInfo_Extensions //!< complete information, including extension list +}; + +#endif // _Graphic3d_DiagnosticInfo_HeaderFile diff --git a/src/OpenGl/OpenGl_Context.cxx b/src/OpenGl/OpenGl_Context.cxx index 42d5e6204b..848282c5d1 100644 --- a/src/OpenGl/OpenGl_Context.cxx +++ b/src/OpenGl/OpenGl_Context.cxx @@ -54,6 +54,7 @@ IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Context,Standard_Transient) // #else #include + #include #endif #else #include // glXGetProcAddress() @@ -71,6 +72,23 @@ namespace { static const Handle(OpenGl_Resource) NULL_GL_RESOURCE; static const OpenGl_Mat4 THE_IDENTITY_MATRIX; + + //! Add key-value pair to the dictionary. + static void addInfo (TColStd_IndexedDataMapOfStringString& theDict, + const TCollection_AsciiString& theKey, + const TCollection_AsciiString& theValue) + { + theDict.ChangeFromIndex (theDict.Add (theKey, theValue)) = theValue; + } + + //! Add key-value pair to the dictionary. + static void addInfo (TColStd_IndexedDataMapOfStringString& theDict, + const TCollection_AsciiString& theKey, + const char* theValue) + { + TCollection_AsciiString aValue (theValue != NULL ? theValue : ""); + theDict.ChangeFromIndex (theDict.Add (theKey, aValue)) = aValue; + } } // ======================================================================= @@ -1337,6 +1355,13 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile) { FindProcShort (glXSwapIntervalSGI); } + if (CheckExtension (aGlxExts, "GLX_MESA_query_renderer")) + { + FindProcShort (glXQueryRendererIntegerMESA); + FindProcShort (glXQueryCurrentRendererIntegerMESA); + FindProcShort (glXQueryRendererStringMESA); + FindProcShort (glXQueryCurrentRendererStringMESA); + } //extSwapTear = CheckExtension (aGlxExts, "GLX_EXT_swap_control_tear"); #endif @@ -2407,7 +2432,71 @@ Standard_Size OpenGl_Context::AvailableMemory() const // ======================================================================= TCollection_AsciiString OpenGl_Context::MemoryInfo() const { - TCollection_AsciiString anInfo; + TColStd_IndexedDataMapOfStringString aDict; + MemoryInfo (aDict); + + TCollection_AsciiString aText; + for (TColStd_IndexedDataMapOfStringString::Iterator anIter (aDict); anIter.More(); anIter.Next()) + { + if (!aText.IsEmpty()) + { + aText += "\n"; + } + aText += TCollection_AsciiString(" ") + anIter.Key() + ": " + anIter.Value(); + } + return aText; +} + +// ======================================================================= +// function : MemoryInfo +// purpose : +// ======================================================================= +void OpenGl_Context::MemoryInfo (TColStd_IndexedDataMapOfStringString& theDict) const +{ +#if defined(GL_ES_VERSION_2_0) + (void )theDict; +#elif defined(__APPLE__) && !defined(MACOSX_USE_GLX) + GLint aGlRendId = 0; + CGLGetParameter (CGLGetCurrentContext(), kCGLCPCurrentRendererID, &aGlRendId); + + CGLRendererInfoObj aRendObj = NULL; + CGOpenGLDisplayMask aDispMask = CGDisplayIDToOpenGLDisplayMask (kCGDirectMainDisplay); + GLint aRendNb = 0; + CGLQueryRendererInfo (aDispMask, &aRendObj, &aRendNb); + for (GLint aRendIter = 0; aRendIter < aRendNb; ++aRendIter) + { + GLint aRendId = 0; + if (CGLDescribeRenderer (aRendObj, aRendIter, kCGLRPRendererID, &aRendId) != kCGLNoError + || aRendId != aGlRendId) + { + continue; + } + + //kCGLRPVideoMemoryMegabytes = 131; + //kCGLRPTextureMemoryMegabytes = 132; + GLint aVMem = 0; + #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 + if (CGLDescribeRenderer(aRendObj, aRendIter, kCGLRPVideoMemoryMegabytes, &aVMem) == kCGLNoError) + { + addInfo (theDict, "GPU memory", TCollection_AsciiString() + aVMem + " MiB"); + } + if (CGLDescribeRenderer(aRendObj, aRendIter, kCGLRPTextureMemoryMegabytes, &aVMem) == kCGLNoError) + { + addInfo (theDict, "GPU Texture memory", TCollection_AsciiString() + aVMem + " MiB"); + } + #else + if (CGLDescribeRenderer(aRendObj, aRendIter, kCGLRPVideoMemory, &aVMem) == kCGLNoError) + { + addInfo (theDict, "GPU memory", TCollection_AsciiString() + (aVMem / (1024 * 1024)) + " MiB"); + } + if (CGLDescribeRenderer(aRendObj, aRendIter, kCGLRPTextureMemory, &aVMem) == kCGLNoError) + { + addInfo (theDict, "GPU Texture memory", TCollection_AsciiString() + (aVMem / (1024 * 1024)) + " MiB"); + } + #endif + } +#endif + #if !defined(GL_ES_VERSION_2_0) if (atiMem) { @@ -2416,14 +2505,17 @@ TCollection_AsciiString OpenGl_Context::MemoryInfo() const glGetIntegerv (GL_VBO_FREE_MEMORY_ATI, aValues); // total memory free in the pool - anInfo += TCollection_AsciiString (" GPU free memory: ") + (aValues[0] / 1024) + " MiB\n"; + addInfo (theDict, "GPU free memory", TCollection_AsciiString() + (aValues[0] / 1024) + " MiB"); - // largest available free block in the pool - anInfo += TCollection_AsciiString (" Largest free block: ") + (aValues[1] / 1024) + " MiB\n"; + if (aValues[1] != aValues[0]) + { + // largest available free block in the pool + addInfo (theDict, "Largest free block", TCollection_AsciiString() + (aValues[1] / 1024) + " MiB"); + } if (aValues[2] != aValues[0]) { // total auxiliary memory free - anInfo += TCollection_AsciiString (" Free memory: ") + (aValues[2] / 1024) + " MiB\n"; + addInfo (theDict, "Free auxiliary memory", TCollection_AsciiString() + (aValues[2] / 1024) + " MiB"); } } else if (nvxMem) @@ -2431,25 +2523,140 @@ TCollection_AsciiString OpenGl_Context::MemoryInfo() const //current available dedicated video memory (in KiB), currently unused GPU memory GLint aValue = 0; glGetIntegerv (GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &aValue); - anInfo += TCollection_AsciiString (" GPU free memory: ") + (aValue / 1024) + " MiB\n"; + addInfo (theDict, "GPU free memory", TCollection_AsciiString() + (aValue / 1024) + " MiB"); // dedicated video memory, total size (in KiB) of the GPU memory GLint aDedicated = 0; glGetIntegerv (GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, &aDedicated); - anInfo += TCollection_AsciiString (" GPU memory: ") + (aDedicated / 1024) + " MiB\n"; + addInfo (theDict, "GPU memory", TCollection_AsciiString() + (aDedicated / 1024) + " MiB"); // total available memory, total size (in KiB) of the memory available for allocations glGetIntegerv (GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, &aValue); if (aValue != aDedicated) { // different only for special configurations - anInfo += TCollection_AsciiString (" Total memory: ") + (aValue / 1024) + " MiB\n"; + addInfo (theDict, "Total memory", TCollection_AsciiString() + (aValue / 1024) + " MiB"); + } + } +#endif + +#if !defined(GL_ES_VERSION_2_0) && !defined(__APPLE__) && !defined(_WIN32) + // GLX_RENDERER_VENDOR_ID_MESA + if (myFuncs->glXQueryCurrentRendererIntegerMESA != NULL) + { + unsigned int aVMemMiB = 0; + if (myFuncs->glXQueryCurrentRendererIntegerMESA (GLX_RENDERER_VIDEO_MEMORY_MESA, &aVMemMiB) != False) + { + addInfo (theDict, "GPU memory", TCollection_AsciiString() + int(aVMemMiB) + " MiB"); } } #endif - return anInfo; } +// ======================================================================= +// function : DiagnosticInfo +// purpose : +// ======================================================================= +void OpenGl_Context::DiagnosticInformation (TColStd_IndexedDataMapOfStringString& theDict, + Graphic3d_DiagnosticInfo theFlags) const +{ + if ((theFlags & Graphic3d_DiagnosticInfo_NativePlatform) != 0) + { + #if defined(HAVE_EGL) + addInfo (theDict, "EGLVersion", ::eglQueryString ((Aspect_Display)myDisplay, EGL_VERSION)); + addInfo (theDict, "EGLVendor", ::eglQueryString ((Aspect_Display)myDisplay, EGL_VENDOR)); + addInfo (theDict, "EGLClientAPIs", ::eglQueryString ((Aspect_Display)myDisplay, EGL_CLIENT_APIS)); + if ((theFlags & Graphic3d_DiagnosticInfo_Extensions) != 0) + { + addInfo (theDict, "EGLExtensions", ::eglQueryString ((Aspect_Display)myDisplay, EGL_EXTENSIONS)); + } + #elif defined(_WIN32) + if ((theFlags & Graphic3d_DiagnosticInfo_Extensions) != 0 + && myFuncs->wglGetExtensionsStringARB != NULL) + { + const char* aWglExts = myFuncs->wglGetExtensionsStringARB ((HDC )myWindowDC); + addInfo (theDict, "WGLExtensions", aWglExts); + } + #elif defined(__APPLE__) + // + #else + Display* aDisplay = (Display*)myDisplay; + const int aScreen = DefaultScreen(aDisplay); + addInfo (theDict, "GLXDirectRendering", ::glXIsDirect (aDisplay, (GLXContext )myGContext) ? "Yes" : "No"); + addInfo (theDict, "GLXVendor", ::glXQueryServerString (aDisplay, aScreen, GLX_VENDOR)); + addInfo (theDict, "GLXVersion", ::glXQueryServerString (aDisplay, aScreen, GLX_VERSION)); + if ((theFlags & Graphic3d_DiagnosticInfo_Extensions) != 0) + { + const char* aGlxExts = ::glXQueryExtensionsString (aDisplay, aScreen); + addInfo(theDict, "GLXExtensions", aGlxExts); + } + + addInfo (theDict, "GLXClientVendor", ::glXGetClientString (aDisplay, GLX_VENDOR)); + addInfo (theDict, "GLXClientVersion", ::glXGetClientString (aDisplay, GLX_VERSION)); + if ((theFlags & Graphic3d_DiagnosticInfo_Extensions) != 0) + { + addInfo (theDict, "GLXClientExtensions", ::glXGetClientString (aDisplay, GLX_EXTENSIONS)); + } + #endif + } + + if ((theFlags & Graphic3d_DiagnosticInfo_Device) != 0) + { + addInfo (theDict, "GLvendor", (const char*)::glGetString (GL_VENDOR)); + addInfo (theDict, "GLdevice", (const char*)::glGetString (GL_RENDERER)); + addInfo (theDict, "GLversion", (const char*)::glGetString (GL_VERSION)); + addInfo (theDict, "GLSLversion", (const char*)::glGetString (GL_SHADING_LANGUAGE_VERSION)); + if (myIsGlDebugCtx) + { + addInfo (theDict, "GLdebug", "ON"); + } + } + + if ((theFlags & Graphic3d_DiagnosticInfo_Limits) != 0) + { + addInfo (theDict, "Max texture size", TCollection_AsciiString(myMaxTexDim)); + addInfo (theDict, "Max MSAA samples", TCollection_AsciiString(myMaxMsaaSamples)); + } + + if ((theFlags & Graphic3d_DiagnosticInfo_FrameBuffer) != 0) + { + GLint aViewport[4] = {}; + ::glGetIntegerv (GL_VIEWPORT, aViewport); + addInfo (theDict, "Viewport", TCollection_AsciiString() + aViewport[2] + "x" + aViewport[3]); + } + + if ((theFlags & Graphic3d_DiagnosticInfo_Memory) != 0) + { + MemoryInfo (theDict); + } + + if ((theFlags & Graphic3d_DiagnosticInfo_Extensions) != 0) + { + #if !defined(GL_ES_VERSION_2_0) + if (IsGlGreaterEqual (3, 0) + && myFuncs->glGetStringi != NULL) + { + TCollection_AsciiString anExtList; + GLint anExtNb = 0; + ::glGetIntegerv (GL_NUM_EXTENSIONS, &anExtNb); + for (GLint anIter = 0; anIter < anExtNb; ++anIter) + { + const char* anExtension = (const char*)myFuncs->glGetStringi (GL_EXTENSIONS, (GLuint)anIter); + if (!anExtList.IsEmpty()) + { + anExtList += " "; + } + anExtList += anExtension; + } + addInfo(theDict, "GLextensions", anExtList); + } + else + #endif + { + addInfo (theDict, "GLextensions", (const char*)::glGetString (GL_EXTENSIONS)); + } + } +} // ======================================================================= // function : GetResource diff --git a/src/OpenGl/OpenGl_Context.hxx b/src/OpenGl/OpenGl_Context.hxx index 6a53922816..dd7a83a30d 100644 --- a/src/OpenGl/OpenGl_Context.hxx +++ b/src/OpenGl/OpenGl_Context.hxx @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -33,7 +34,7 @@ #include #include #include -#include +#include #include #include #include @@ -307,6 +308,12 @@ public: || (myGlVerMajor == theVerMajor && myGlVerMinor >= theVerMinor); } + //! Return cached GL version major number. + Standard_Integer VersionMajor() const { return myGlVerMajor; } + + //! Return cached GL version minor number. + Standard_Integer VersionMinor() const { return myGlVerMinor; } + //! Access entire map of loaded OpenGL functions. const OpenGl_GlFunctions* Functions() const { return myFuncs.operator->(); } @@ -360,6 +367,14 @@ public: //! and contains more vendor-specific values than AvailableMemory(). Standard_EXPORT TCollection_AsciiString MemoryInfo() const; + //! This function retrieves information from GL about GPU memory. + Standard_EXPORT void MemoryInfo (TColStd_IndexedDataMapOfStringString& theDict) const; + + //! Fill in the dictionary with OpenGL info. + //! Should be called with bound context. + Standard_EXPORT void DiagnosticInformation (TColStd_IndexedDataMapOfStringString& theDict, + Graphic3d_DiagnosticInfo theFlags) const; + //! Access shared resource by its name. //! @param theKey - unique identifier; //! @return handle to shared resource or NULL. diff --git a/src/OpenGl/OpenGl_GlFunctions.hxx b/src/OpenGl/OpenGl_GlFunctions.hxx index 6c364f05d7..34da9ac7e2 100644 --- a/src/OpenGl/OpenGl_GlFunctions.hxx +++ b/src/OpenGl/OpenGl_GlFunctions.hxx @@ -1644,6 +1644,37 @@ public: //! @name glX extensions typedef int (*glXSwapIntervalSGI_t)(int theInterval); glXSwapIntervalSGI_t glXSwapIntervalSGI; + + // GLX_MESA_query_renderer +#ifndef GLX_RENDERER_VENDOR_ID_MESA + // for glXQueryRendererIntegerMESA() and glXQueryCurrentRendererIntegerMESA() + #define GLX_RENDERER_VENDOR_ID_MESA 0x8183 + #define GLX_RENDERER_DEVICE_ID_MESA 0x8184 + #define GLX_RENDERER_VERSION_MESA 0x8185 + #define GLX_RENDERER_ACCELERATED_MESA 0x8186 + #define GLX_RENDERER_VIDEO_MEMORY_MESA 0x8187 + #define GLX_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_MESA 0x8188 + #define GLX_RENDERER_PREFERRED_PROFILE_MESA 0x8189 + #define GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA 0x818A + #define GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA 0x818B + #define GLX_RENDERER_OPENGL_ES_PROFILE_VERSION_MESA 0x818C + #define GLX_RENDERER_OPENGL_ES2_PROFILE_VERSION_MESA 0x818D + + #define GLX_RENDERER_ID_MESA 0x818E +#endif // GLX_RENDERER_VENDOR_ID_MESA + + typedef Bool (*glXQueryRendererIntegerMESA_t)(Display* theDisplay, int theScreen, + int theRenderer, int theAttribute, + unsigned int* theValue); + typedef Bool (*glXQueryCurrentRendererIntegerMESA_t)(int theAttribute, unsigned int* theValue); + typedef const char* (*glXQueryRendererStringMESA_t)(Display* theDisplay, int theScreen, + int theRenderer, int theAttribute); + typedef const char* (*glXQueryCurrentRendererStringMESA_t)(int theAttribute); + + glXQueryRendererIntegerMESA_t glXQueryRendererIntegerMESA; + glXQueryCurrentRendererIntegerMESA_t glXQueryCurrentRendererIntegerMESA; + glXQueryRendererStringMESA_t glXQueryRendererStringMESA; + glXQueryCurrentRendererStringMESA_t glXQueryCurrentRendererStringMESA; #endif #endif // OpenGL ES vs. desktop diff --git a/src/OpenGl/OpenGl_View.cxx b/src/OpenGl/OpenGl_View.cxx index 4c23086713..92028a4a43 100644 --- a/src/OpenGl/OpenGl_View.cxx +++ b/src/OpenGl/OpenGl_View.cxx @@ -818,3 +818,25 @@ void OpenGl_View::changePriority (const Handle(Graphic3d_CStructure)& theStructu const OpenGl_Structure* aStruct = reinterpret_cast (theStructure.operator->()); myZLayers.ChangePriority (aStruct, aLayerId, theNewPriority); } + +//======================================================================= +//function : DiagnosticInformation +//purpose : +//======================================================================= +void OpenGl_View::DiagnosticInformation (TColStd_IndexedDataMapOfStringString& theDict, + Graphic3d_DiagnosticInfo theFlags) const +{ + Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); + if (!myWorkspace->Activate() + || aCtx.IsNull()) + { + return; + } + + aCtx->DiagnosticInformation (theDict, theFlags); + if ((theFlags & Graphic3d_DiagnosticInfo_FrameBuffer) != 0) + { + TCollection_AsciiString aResRatio (myRenderParams.ResolutionRatio()); + theDict.ChangeFromIndex (theDict.Add ("ResolutionRatio", aResRatio)) = aResRatio; + } +} diff --git a/src/OpenGl/OpenGl_View.hxx b/src/OpenGl/OpenGl_View.hxx index 7cdfdd4963..49d415297b 100644 --- a/src/OpenGl/OpenGl_View.hxx +++ b/src/OpenGl/OpenGl_View.hxx @@ -314,6 +314,16 @@ public: //! Sets list of clip planes for the view. virtual void SetClipPlanes (const Graphic3d_SequenceOfHClipPlane& thePlanes) Standard_OVERRIDE { myClipPlanes = thePlanes; } + //! Fill in the dictionary with diagnostic info. + //! Should be called within rendering thread. + //! + //! This API should be used only for user output or for creating automated reports. + //! The format of returned information (e.g. key-value layout) + //! is NOT part of this API and can be changed at any time. + //! Thus application should not parse returned information to weed out specific parameters. + Standard_EXPORT virtual void DiagnosticInformation (TColStd_IndexedDataMapOfStringString& theDict, + Graphic3d_DiagnosticInfo theFlags) const Standard_OVERRIDE; + public: //! Returns background color. diff --git a/src/TColStd/FILES b/src/TColStd/FILES index 615b0d07db..911ffe6399 100755 --- a/src/TColStd/FILES +++ b/src/TColStd/FILES @@ -50,6 +50,7 @@ TColStd_HSequenceOfHExtendedString.hxx TColStd_HSequenceOfInteger.hxx TColStd_HSequenceOfReal.hxx TColStd_HSequenceOfTransient.hxx +TColStd_IndexedDataMapOfStringString.hxx TColStd_IndexedDataMapOfTransientTransient.hxx TColStd_IndexedMapOfInteger.hxx TColStd_IndexedMapOfReal.hxx diff --git a/src/TColStd/TColStd_IndexedDataMapOfStringString.hxx b/src/TColStd/TColStd_IndexedDataMapOfStringString.hxx new file mode 100644 index 0000000000..7468a0f9d8 --- /dev/null +++ b/src/TColStd/TColStd_IndexedDataMapOfStringString.hxx @@ -0,0 +1,22 @@ +// Copyright (c) 2016 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef TColStd_IndexedDataMapOfStringString_HeaderFile +#define TColStd_IndexedDataMapOfStringString_HeaderFile + +#include +#include + +typedef NCollection_IndexedDataMap TColStd_IndexedDataMapOfStringString; + +#endif // TColStd_IndexedDataMapOfStringString_HeaderFile diff --git a/src/TCollection/TCollection_AsciiString.cxx b/src/TCollection/TCollection_AsciiString.cxx index 51edd9211b..43a86707ab 100644 --- a/src/TCollection/TCollection_AsciiString.cxx +++ b/src/TCollection/TCollection_AsciiString.cxx @@ -570,6 +570,34 @@ Standard_Boolean TCollection_AsciiString::IsEqual return ( strncmp( other.mystring, mystring, mylength ) == 0 ); } +// ---------------------------------------------------------------------------- +// IsSameString +// ---------------------------------------------------------------------------- +Standard_Boolean TCollection_AsciiString::IsSameString (const TCollection_AsciiString& theString1, + const TCollection_AsciiString& theString2, + const Standard_Boolean theIsCaseSensitive) +{ + const Standard_Integer aSize1 = theString1.Length(); + if (aSize1 != theString2.Length()) + { + return Standard_False; + } + + if (theIsCaseSensitive) + { + return (strncmp (theString1.ToCString(), theString2.ToCString(), aSize1) == 0); + } + + for (Standard_Integer aCharIter = 1; aCharIter <= aSize1; ++aCharIter) + { + if (toupper (theString1.Value (aCharIter)) != toupper (theString2.Value (aCharIter))) + { + return Standard_False; + } + } + return Standard_True; +} + // ---------------------------------------------------------------------------- // IsEmpty // ---------------------------------------------------------------------------- diff --git a/src/TCollection/TCollection_AsciiString.hxx b/src/TCollection/TCollection_AsciiString.hxx index daf31bb35a..89c6c45352 100644 --- a/src/TCollection/TCollection_AsciiString.hxx +++ b/src/TCollection/TCollection_AsciiString.hxx @@ -659,6 +659,10 @@ friend Standard_EXPORT Standard_IStream& operator >> (Standard_IStream& astream, //! (Just for HashCode for AsciiString) static Standard_Boolean IsEqual (const TCollection_AsciiString& string1, const Standard_CString string2); + //! Returns True if the strings contain same characters. + Standard_EXPORT static Standard_Boolean IsSameString (const TCollection_AsciiString& theString1, + const TCollection_AsciiString& theString2, + const Standard_Boolean theIsCaseSensitive); friend class TCollection_HAsciiString; diff --git a/src/TCollection/TCollection_HAsciiString.cxx b/src/TCollection/TCollection_HAsciiString.cxx index 9945fcb598..90e203f78b 100644 --- a/src/TCollection/TCollection_HAsciiString.cxx +++ b/src/TCollection/TCollection_HAsciiString.cxx @@ -320,19 +320,7 @@ Standard_Boolean TCollection_HAsciiString::IsSameString const Standard_Boolean CaseSensitive) const { if(S.IsNull()) Standard_NullObject::Raise("TCollection_HAsciiString::IsSameString"); - - const Standard_Integer size1 = Length(); - if ( size1 != S->Length() ) return Standard_False; - if ( CaseSensitive ) { - return ( strncmp( myString.ToCString(), S->ToCString(), size1 ) == 0 ); - } - else { - for ( Standard_Integer i = 1 ; i <= size1; i++) { - if ( toupper( Value(i) ) != toupper( S->Value(i) ) ) - return Standard_False; - } - return Standard_True ; - } + return TCollection_AsciiString::IsSameString (myString, S->myString, CaseSensitive); } //------------------------------------------------------------------------ diff --git a/src/V3d/V3d_View.cxx b/src/V3d/V3d_View.cxx index b44dd5af38..668d78e71f 100644 --- a/src/V3d/V3d_View.cxx +++ b/src/V3d/V3d_View.cxx @@ -3330,3 +3330,13 @@ void V3d_View::SetFrustumCulling (const Standard_Boolean theToClip) { myView->SetCullingEnabled (theToClip); } + +// ======================================================================= +// function : DiagnosticInformation +// purpose : +// ======================================================================= +void V3d_View::DiagnosticInformation (TColStd_IndexedDataMapOfStringString& theDict, + Graphic3d_DiagnosticInfo theFlags) const +{ + myView->DiagnosticInformation (theDict, theFlags); +} diff --git a/src/V3d/V3d_View.hxx b/src/V3d/V3d_View.hxx index 0b75aaeaff..49195ca5cb 100644 --- a/src/V3d/V3d_View.hxx +++ b/src/V3d/V3d_View.hxx @@ -931,6 +931,17 @@ friend //! has been Iconified . Standard_EXPORT void V3d_Viewer::SetViewOff (const Handle(V3d_View)& View); + //! Fill in the dictionary with diagnostic info. + //! Should be called within rendering thread. + //! + //! This API should be used only for user output or for creating automated reports. + //! The format of returned information (e.g. key-value layout) + //! is NOT part of this API and can be changed at any time. + //! Thus application should not parse returned information to weed out specific parameters. + //! @param theDict destination map for information + //! @param theFlags defines the information to be retrieved + Standard_EXPORT void DiagnosticInformation (TColStd_IndexedDataMapOfStringString& theDict, + Graphic3d_DiagnosticInfo theFlags) const; DEFINE_STANDARD_RTTIEXT(V3d_View,MMgt_TShared) diff --git a/src/ViewerTest/ViewerTest_OpenGlCommands.cxx b/src/ViewerTest/ViewerTest_OpenGlCommands.cxx index 51d3911d6a..13cea1470a 100644 --- a/src/ViewerTest/ViewerTest_OpenGlCommands.cxx +++ b/src/ViewerTest/ViewerTest_OpenGlCommands.cxx @@ -401,6 +401,20 @@ static int VImmediateFront (Draw_Interpretor& /*theDI*/, return 0; } +//! Search the info from the key. +inline TCollection_AsciiString searchInfo (const TColStd_IndexedDataMapOfStringString& theDict, + const TCollection_AsciiString& theKey) +{ + for (TColStd_IndexedDataMapOfStringString::Iterator anIter (theDict); anIter.More(); anIter.Next()) + { + if (TCollection_AsciiString::IsSameString (anIter.Key(), theKey, Standard_False)) + { + return anIter.Value(); + } + } + return TCollection_AsciiString(); +} + //============================================================================== //function : VGlInfo //purpose : @@ -418,53 +432,76 @@ static int VGlInfo (Draw_Interpretor& theDI, return 1; } - if (theArgNb <= 1) + Standard_Integer anArgIter = 1; + Graphic3d_DiagnosticInfo anInfoLevel = Graphic3d_DiagnosticInfo_Basic; + if (theArgNb == 2) { - Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aView->Viewer()->Driver()); - if (aDriver.IsNull()) + TCollection_AsciiString aName (theArgVec[1]); + aName.LowerCase(); + if (aName == "-short") { - std::cerr << "Error: view does not use OpenGL.\n"; - return 1; + ++anArgIter; + anInfoLevel = Graphic3d_DiagnosticInfo_Short; } - Handle(OpenGl_Context) aCtx = aDriver->GetSharedContext(); - Standard_CString aDebugInfo = !aCtx.IsNull() && aCtx->IsDebugContext() - ? " GLdebug = ON\n" - : ""; + else if (aName == "-basic") + { + ++anArgIter; + anInfoLevel = Graphic3d_DiagnosticInfo_Basic; + } + else if (aName == "-complete" + || aName == "-full") + { + ++anArgIter; + anInfoLevel = Graphic3d_DiagnosticInfo_Complete; + } + } + + TColStd_IndexedDataMapOfStringString aDict; + if (anArgIter >= theArgNb) + { + aView->DiagnosticInformation (aDict, anInfoLevel); + TCollection_AsciiString aText; + for (TColStd_IndexedDataMapOfStringString::Iterator aValueIter (aDict); aValueIter.More(); aValueIter.Next()) + { + if (!aText.IsEmpty()) + { + aText += "\n"; + } + aText += TCollection_AsciiString(" ") + aValueIter.Key() + ": " + aValueIter.Value(); + } + theDI << "OpenGL info:\n" - << " GLvendor = '" << (const char* )glGetString(GL_VENDOR) << "'\n" - << " GLdevice = '" << (const char* )glGetString(GL_RENDERER) << "'\n" - << " GLversion = '" << (const char* )glGetString(GL_VERSION) << "'\n" - << " GLSLversion = '" << (const char* )glGetString(GL_SHADING_LANGUAGE_VERSION) << "'\n" - << aDebugInfo; + << aText; return 0; } const Standard_Boolean isList = theArgNb >= 3; - for (Standard_Integer anIter = 1; anIter < theArgNb; ++anIter) + aView->DiagnosticInformation (aDict, Graphic3d_DiagnosticInfo_Complete); + for (; anArgIter < theArgNb; ++anArgIter) { - TCollection_AsciiString aName (theArgVec[anIter]); + TCollection_AsciiString aName (theArgVec[anArgIter]); aName.UpperCase(); - const char* aValue = NULL; + TCollection_AsciiString aValue; if (aName.Search ("VENDOR") != -1) { - aValue = (const char* )glGetString (GL_VENDOR); + aValue = searchInfo (aDict, "GLvendor"); } else if (aName.Search ("RENDERER") != -1) { - aValue = (const char* )glGetString (GL_RENDERER); + aValue = searchInfo (aDict, "GLdevice"); } else if (aName.Search ("SHADING_LANGUAGE_VERSION") != -1 || aName.Search ("GLSL") != -1) { - aValue = (const char* )glGetString (GL_SHADING_LANGUAGE_VERSION); + aValue = searchInfo (aDict, "GLSLversion"); } else if (aName.Search ("VERSION") != -1) { - aValue = (const char* )glGetString (GL_VERSION); + aValue = searchInfo (aDict, "GLversion"); } else if (aName.Search ("EXTENSIONS") != -1) { - aValue = (const char* )glGetString (GL_EXTENSIONS); + aValue = searchInfo (aDict, "GLextensions"); } else { @@ -630,8 +667,10 @@ void ViewerTest::OpenGlCommands(Draw_Interpretor& theCommands) "vimmediatefront : render immediate mode to front buffer or to back buffer", __FILE__, VImmediateFront, aGroup); theCommands.Add("vglinfo", - "vglinfo [GL_VENDOR] [GL_RENDERER] [GL_VERSION] [GL_SHADING_LANGUAGE_VERSION] [GL_EXTENSIONS]" - " : prints GL info", + "vglinfo [-short|-basic|-complete]" + "\n\t\t: [GL_VENDOR] [GL_RENDERER] [GL_VERSION]" + "\n\t\t: [GL_SHADING_LANGUAGE_VERSION] [GL_EXTENSIONS]" + "\n\t\t: print OpenGL info", __FILE__, VGlInfo, aGroup); theCommands.Add("vshaderprog", " 'vshaderprog [name] pathToVertexShader pathToFragmentShader'"