0024123: Create debug OpenGL context when requested (GL_ARB_debug_output)
authorkgv <kgv@opencascade.com>
Thu, 29 Aug 2013 11:45:45 +0000 (15:45 +0400)
committerbugmaster <bugmaster@opencascade.com>
Thu, 29 Aug 2013 11:46:40 +0000 (15:46 +0400)
Introduce new OpenGl_Caps class for unified graphic driver options access.
New command vgldebug to request debug OpenGL context.
OpenGl_Window  - create debug OpenGL context when requested (WGL-only).
OpenGl_Context - destroy arbTBO, arbIns members.
Workaround namespace collisions with Xlib macros
Eliminate new warning (unused argument in OpenGl_Context::debugCallbackWrap)

20 files changed:
src/InterfaceGraphic/InterfaceGraphic_X11.hxx
src/OpenGl/FILES
src/OpenGl/OpenGl_ArbDbg.hxx [new file with mode: 0644]
src/OpenGl/OpenGl_Caps.cxx [new file with mode: 0644]
src/OpenGl/OpenGl_Caps.hxx [new file with mode: 0644]
src/OpenGl/OpenGl_Context.cxx
src/OpenGl/OpenGl_Context.hxx
src/OpenGl/OpenGl_GraphicDriver.cxx
src/OpenGl/OpenGl_GraphicDriver.hxx
src/OpenGl/OpenGl_GraphicDriver_7.cxx
src/OpenGl/OpenGl_PrimitiveArray.cxx
src/OpenGl/OpenGl_Text.cxx
src/OpenGl/OpenGl_Window.cxx
src/OpenGl/OpenGl_Window.hxx
src/OpenGl/OpenGl_Window_1.mm
src/OpenGl/OpenGl_Workspace.cxx
src/OpenGl/OpenGl_Workspace.hxx
src/ViewerTest/ViewerTest_ObjectCommands.cxx
src/ViewerTest/ViewerTest_OpenGlCommands.cxx
src/ViewerTest/ViewerTest_ViewerCommands.cxx

index 3d39fb6..a597cfd 100755 (executable)
 // purpose or non-infringement. Please see the License for the specific terms
 // and conditions governing the rights and limitations under the License.
 
+#ifndef _WIN32
 #ifndef InterfaceGraphic_X11Header
-# define InterfaceGraphic_X11Header
+#define InterfaceGraphic_X11Header
 
-# ifndef WNT
-#  include <stdio.h>
+#include <stdio.h>
 
-#  include <X11/Xlib.h>
-#  include <X11/Xutil.h>
-#  include <X11/Xatom.h>
-#  include <GL/glx.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <GL/glx.h>
 
-#  if defined (sun) || defined (SUNOS) || defined (__alpha) || defined (DECOSF1) || defined (sgi) || defined (IRIX) || defined (__hpux)|| defined (HPUX) 
-#   ifndef icon_width
-#    include <X11/bitmaps/icon>
-#   endif
+#if defined (sun) || defined (SUNOS) || defined (__alpha) || defined (DECOSF1) || defined (sgi) || defined (IRIX) || defined (__hpux)|| defined (HPUX)
+  #ifndef icon_width
+    #include <X11/bitmaps/icon>
+  #endif
+#endif // SUNOS or DECOSF1 or SOLARIS or HPUX or IRIX
+#if defined(ULTRIX) && !defined(icon_width)
+  #define icon_width  16
+  #define icon_height 16
+  static unsigned char icon_bits[] =
+  {
+    0xff, 0xff, 0xab, 0xaa, 0x55, 0xd5, 0xab, 0xaa, 0x05, 0xd0, 0x0b, 0xa0,
+    0x05, 0xd0, 0x0b, 0xa0, 0x05, 0xd0, 0x0b, 0xa0, 0x05, 0xd0, 0x0b, 0xa0,
+    0x55, 0xd5, 0xab, 0xaa, 0x55, 0xd5, 0xff, 0xff
+  };
+#endif // ULTRIX
 
-#  endif /* SUNOS or DECOSF1 or SOLARIS or HPUX or IRIX */
+// workaround name conflicts with OCCT methods (in class TopoDS_Shape for example)
+#ifdef Convex
+  #undef Convex
+#endif
+#ifdef Status
+  #undef Status
+#endif
 
-#  ifdef ULTRIX
+#define WINDOW     Window
+#define DISPLAY    Display
+#define GLCONTEXT  GLXContext
+#define GLDRAWABLE GLXDrawable
 
-#   ifndef icon_width
-/* le contenu de #include <X11/bitmaps/icon> sur SUN */
-#define icon_width 16
-#define icon_height 16
-static unsigned char icon_bits[] = {
-  0xff, 0xff, 0xab, 0xaa, 0x55, 0xd5, 0xab, 0xaa, 0x05, 0xd0, 0x0b, 0xa0,
-    0x05, 0xd0, 0x0b, 0xa0, 0x05, 0xd0, 0x0b, 0xa0, 0x05, 0xd0, 0x0b, 0xa0,
-    0x55, 0xd5, 0xab, 0xaa, 0x55, 0xd5, 0xff, 0xff};
-#   endif
-
-#  endif /* ULTRIX */
-#  define WINDOW     Window
-#  define DISPLAY    Display
-#  define GLCONTEXT  GLXContext
-#  define GLDRAWABLE GLXDrawable
-
-#  define GET_GL_CONTEXT()       glXGetCurrentContext()
-#  define GET_GLDEV_CONTEXT()    glXGetCurrentDrawable()
-#  define GL_MAKE_CURRENT(a,b,c) glXMakeCurrent(a,b,c)
-
-#  ifndef EXPORT
-#   define EXPORT
-#  endif  /* EXPORT */
-# endif  /* WNT */
-#endif /* InterfaceGraphic_X11Header */
+#define GET_GL_CONTEXT()       glXGetCurrentContext()
+#define GET_GLDEV_CONTEXT()    glXGetCurrentDrawable()
+#define GL_MAKE_CURRENT(a,b,c) glXMakeCurrent(a,b,c)
+
+#ifndef EXPORT
+  #define EXPORT
+#endif  // EXPORT
+
+#endif // InterfaceGraphic_X11Header
+#endif // _WIN32
index ad1f9b7..51d8949 100755 (executable)
@@ -87,6 +87,8 @@ OpenGl_transform_persistence.hxx
 OpenGl_Font.hxx
 OpenGl_Font.cxx
 OpenGl_tgl_funcs.hxx
+OpenGl_Caps.hxx
+OpenGl_Caps.cxx
 Handle_OpenGl_Context.hxx
 OpenGl_Context.hxx
 OpenGl_Context.cxx
@@ -94,6 +96,7 @@ OpenGl_Context_1.mm
 OpenGl_ArbIns.hxx
 OpenGl_ArbTBO.hxx
 OpenGl_ArbVBO.hxx
+OpenGl_ArbDbg.hxx
 OpenGl_ExtFBO.hxx
 OpenGl_ExtGS.hxx
 glext.h
diff --git a/src/OpenGl/OpenGl_ArbDbg.hxx b/src/OpenGl/OpenGl_ArbDbg.hxx
new file mode 100644 (file)
index 0000000..0514d98
--- /dev/null
@@ -0,0 +1,36 @@
+// Created on: 2013-08-25
+// Created by: Kirill GAVRILOV
+// Copyright (c) 2013 OPEN CASCADE SAS
+//
+// The content of this file is subject to the Open CASCADE Technology Public
+// License Version 6.5 (the "License"). You may not use the content of this file
+// except in compliance with the License. Please obtain a copy of the License
+// at http://www.opencascade.org and read it completely before using this file.
+//
+// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
+// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+//
+// The Original Code and all software distributed under the License is
+// distributed on an "AS IS" basis, without warranty of any kind, and the
+// Initial Developer hereby disclaims all such warranties, including without
+// limitation, any warranties of merchantability, fitness for a particular
+// purpose or non-infringement. Please see the License for the specific terms
+// and conditions governing the rights and limitations under the License.
+
+#ifndef _OpenGl_ArbDbg_H__
+#define _OpenGl_ArbDbg_H__
+
+#include <OpenGl_GlCore12.hxx>
+
+//! Debug context routines
+struct OpenGl_ArbDbg
+{
+
+  PFNGLDEBUGMESSAGECONTROLARBPROC  glDebugMessageControlARB;
+  PFNGLDEBUGMESSAGEINSERTARBPROC   glDebugMessageInsertARB;
+  PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARB;
+  PFNGLGETDEBUGMESSAGELOGARBPROC   glGetDebugMessageLogARB;
+
+};
+
+#endif // _OpenGl_ArbDbg_H__
diff --git a/src/OpenGl/OpenGl_Caps.cxx b/src/OpenGl/OpenGl_Caps.cxx
new file mode 100644 (file)
index 0000000..86a679e
--- /dev/null
@@ -0,0 +1,54 @@
+// Created on: 2013-08-25
+// Created by: Kirill GAVRILOV
+// Copyright (c) 2013 OPEN CASCADE SAS
+//
+// The content of this file is subject to the Open CASCADE Technology Public
+// License Version 6.5 (the "License"). You may not use the content of this file
+// except in compliance with the License. Please obtain a copy of the License
+// at http://www.opencascade.org and read it completely before using this file.
+//
+// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
+// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+//
+// The Original Code and all software distributed under the License is
+// distributed on an "AS IS" basis, without warranty of any kind, and the
+// Initial Developer hereby disclaims all such warranties, including without
+// limitation, any warranties of merchantability, fitness for a particular
+// purpose or non-infringement. Please see the License for the specific terms
+// and conditions governing the rights and limitations under the License.
+
+#include <OpenGl_Caps.hxx>
+
+IMPLEMENT_STANDARD_HANDLE (OpenGl_Caps, Standard_Transient)
+IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Caps, Standard_Transient)
+
+// =======================================================================
+// function : OpenGl_Caps
+// purpose  :
+// =======================================================================
+OpenGl_Caps::OpenGl_Caps()
+: vboDisable   (Standard_False),
+  contextDebug (Standard_False)
+{
+  //
+}
+
+// =======================================================================
+// function : operator=
+// purpose  :
+// =======================================================================
+OpenGl_Caps& OpenGl_Caps::operator= (const OpenGl_Caps& theCopy)
+{
+  vboDisable   = theCopy.vboDisable;
+  contextDebug = theCopy.contextDebug;
+  return *this;
+}
+
+// =======================================================================
+// function : ~OpenGl_Caps
+// purpose  :
+// =======================================================================
+OpenGl_Caps::~OpenGl_Caps()
+{
+  //
+}
diff --git a/src/OpenGl/OpenGl_Caps.hxx b/src/OpenGl/OpenGl_Caps.hxx
new file mode 100644 (file)
index 0000000..04e5bc2
--- /dev/null
@@ -0,0 +1,64 @@
+// Created on: 2013-08-25
+// Created by: Kirill GAVRILOV
+// Copyright (c) 2013 OPEN CASCADE SAS
+//
+// The content of this file is subject to the Open CASCADE Technology Public
+// License Version 6.5 (the "License"). You may not use the content of this file
+// except in compliance with the License. Please obtain a copy of the License
+// at http://www.opencascade.org and read it completely before using this file.
+//
+// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
+// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+//
+// The Original Code and all software distributed under the License is
+// distributed on an "AS IS" basis, without warranty of any kind, and the
+// Initial Developer hereby disclaims all such warranties, including without
+// limitation, any warranties of merchantability, fitness for a particular
+// purpose or non-infringement. Please see the License for the specific terms
+// and conditions governing the rights and limitations under the License.
+
+#ifndef _OpenGl_Caps_H__
+#define _OpenGl_Caps_H__
+
+#include <Standard_DefineHandle.hxx>
+#include <Standard_Transient.hxx>
+#include <Handle_Standard_Transient.hxx>
+
+//! Class to define graphich driver capabilities.
+//! Notice that these options will be ignored if particular functionality does not provided by GL driver
+class OpenGl_Caps : public Standard_Transient
+{
+
+public: //! @name flags to disable particular functionality
+
+  Standard_Boolean vboDisable;   //!< flag permits VBO usage, will significantly affect performance (OFF by default)
+
+public: //! @name context creation parameters
+
+  Standard_Boolean contextDebug; //!< request debug GL context (requires support in OpenGL driver), useful for debugging of visualization code (OFF by default, currently implemented only fow Windows)
+
+public: //! @name class methods
+
+  //! Default constructor - initialize with most optimal values.
+  Standard_EXPORT OpenGl_Caps();
+
+  //! Destructor.
+  Standard_EXPORT virtual ~OpenGl_Caps();
+
+  //! Copy maker.
+  Standard_EXPORT OpenGl_Caps& operator= (const OpenGl_Caps& theCopy);
+
+private:
+
+  //! Not implemented
+  OpenGl_Caps (const OpenGl_Caps& );
+
+public:
+
+  DEFINE_STANDARD_RTTI(OpenGl_Caps) // Type definition
+
+};
+
+DEFINE_STANDARD_HANDLE(OpenGl_Caps, Standard_Transient)
+
+#endif // _OpenGl_Caps_H__
index bf702ff..b984210 100644 (file)
@@ -17,7 +17,7 @@
 // purpose or non-infringement. Please see the License for the specific terms
 // and conditions governing the rights and limitations under the License.
 
-#if (defined(_WIN32) || defined(__WIN32__))
+#if defined(_WIN32)
   #include <windows.h>
 #endif
 
@@ -26,6 +26,7 @@
 #include <OpenGl_ArbVBO.hxx>
 #include <OpenGl_ArbTBO.hxx>
 #include <OpenGl_ArbIns.hxx>
+#include <OpenGl_ArbDbg.hxx>
 #include <OpenGl_ExtFBO.hxx>
 #include <OpenGl_ExtGS.hxx>
 #include <OpenGl_GlCore20.hxx>
@@ -34,7 +35,7 @@
 
 #include <Standard_ProgramError.hxx>
 
-#if (defined(_WIN32) || defined(__WIN32__))
+#if defined(_WIN32)
   //
 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
   #include <dlfcn.h>
@@ -69,16 +70,18 @@ namespace
 // function : OpenGl_Context
 // purpose  :
 // =======================================================================
-OpenGl_Context::OpenGl_Context()
+OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps)
 : core12 (NULL),
   core13 (NULL),
   core14 (NULL),
   core15 (NULL),
   core20 (NULL),
+  caps   (!theCaps.IsNull() ? theCaps : new OpenGl_Caps()),
   arbNPTW(Standard_False),
   arbVBO (NULL),
   arbTBO (NULL),
   arbIns (NULL),
+  arbDbg (NULL),
   extFBO (NULL),
   extGS  (NULL),
   extBgra(Standard_False),
@@ -134,6 +137,9 @@ OpenGl_Context::~OpenGl_Context()
 
   delete myGlCore20;
   delete arbVBO;
+  delete arbTBO;
+  delete arbIns;
+  delete arbDbg;
   delete extFBO;
   delete extGS;
 }
@@ -178,7 +184,7 @@ void OpenGl_Context::Share (const Handle(OpenGl_Context)& theShareCtx)
 // =======================================================================
 Standard_Boolean OpenGl_Context::IsCurrent() const
 {
-#if (defined(_WIN32) || defined(__WIN32__))
+#if defined(_WIN32)
   if (myWindowDC == NULL || myGContext == NULL)
   {
     return Standard_False;
@@ -203,7 +209,7 @@ Standard_Boolean OpenGl_Context::IsCurrent() const
 // =======================================================================
 Standard_Boolean OpenGl_Context::MakeCurrent()
 {
-#if (defined(_WIN32) || defined(__WIN32__))
+#if defined(_WIN32)
   if (myWindowDC == NULL || myGContext == NULL)
   {
     Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called before!");
@@ -257,7 +263,7 @@ Standard_Boolean OpenGl_Context::MakeCurrent()
 // =======================================================================
 void OpenGl_Context::SwapBuffers()
 {
-#if (defined(_WIN32) || defined(__WIN32__))
+#if defined(_WIN32)
   if ((HDC )myWindowDC != NULL)
   {
     ::SwapBuffers ((HDC )myWindowDC);
@@ -279,7 +285,7 @@ void OpenGl_Context::SwapBuffers()
 // =======================================================================
 void* OpenGl_Context::findProc (const char* theFuncName)
 {
-#if (defined(_WIN32) || defined(__WIN32__))
+#if defined(_WIN32)
   return wglGetProcAddress (theFuncName);
 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
   return (myGlLibHandle != NULL) ? dlsym (myGlLibHandle, theFuncName) : NULL;
@@ -299,7 +305,6 @@ Standard_Boolean OpenGl_Context::CheckExtension (const char* theExtName) const
     std::cerr << "CheckExtension called with NULL string!\n";
     return Standard_False;
   }
-  const size_t anExtNameLen = strlen (theExtName);
 
   // available since OpenGL 3.0
   // and the ONLY way to check extensions with OpenGL 3.1+ core profile
@@ -326,11 +331,26 @@ Standard_Boolean OpenGl_Context::CheckExtension (const char* theExtName) const
     std::cerr << "glGetString (GL_EXTENSIONS) returns NULL! No GL context?\n";
     return Standard_False;
   }
+  return CheckExtension (anExtString, theExtName);
+}
+
+// =======================================================================
+// function : CheckExtension
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_Context::CheckExtension (const char* theExtString,
+                                                 const char* theExtName)
+{
+  if (theExtString == NULL)
+  {
+    return Standard_False;
+  }
 
   // Search for theExtName in the extensions string.
   // Use of strstr() is not sufficient because extension names can be prefixes of other extension names.
-  char* aPtrIter = (char* )anExtString;
-  const char* aPtrEnd = aPtrIter + strlen (anExtString);
+  char* aPtrIter = (char* )theExtString;
+  const char*  aPtrEnd      = aPtrIter + strlen (theExtString);
+  const size_t anExtNameLen = strlen (theExtName);
   while (aPtrIter < aPtrEnd)
   {
     const size_t n = strcspn (aPtrIter, " ");
@@ -356,7 +376,7 @@ Standard_Boolean OpenGl_Context::Init()
     return Standard_True;
   }
 
-#if (defined(_WIN32) || defined(__WIN32__))
+#if defined(_WIN32)
   myWindowDC = (Aspect_Handle )wglGetCurrentDC();
   myGContext = (Aspect_RenderingContext )wglGetCurrentContext();
 #else
@@ -380,7 +400,7 @@ Standard_Boolean OpenGl_Context::Init()
 // function : Init
 // purpose  :
 // =======================================================================
-#if (defined(_WIN32) || defined(__WIN32__))
+#if defined(_WIN32)
 Standard_Boolean OpenGl_Context::Init (const Aspect_Handle           theWindow,
                                        const Aspect_Handle           theWindowDC,
                                        const Aspect_RenderingContext theGContext)
@@ -393,7 +413,7 @@ Standard_Boolean OpenGl_Context::Init (const Aspect_Drawable         theWindow,
 #endif
 {
   Standard_ProgramError_Raise_if (myIsInitialized, "OpenGl_Context::Init() should be called only once!");
-#if (defined(_WIN32) || defined(__WIN32__))
+#if defined(_WIN32)
   myWindow   = theWindow;
   myGContext = theGContext;
   myWindowDC = theWindowDC;
@@ -505,6 +525,60 @@ void OpenGl_Context::readGlVersion()
   }
 }
 
+static Standard_CString THE_DBGMSG_UNKNOWN = "UNKNOWN";
+static Standard_CString THE_DBGMSG_SOURCES[] =
+{
+  "OpenGL",          // GL_DEBUG_SOURCE_API_ARB
+  "Window System",   // GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB
+  "Shader Compiler", // GL_DEBUG_SOURCE_SHADER_COMPILER_ARB
+  "Third Party",     // GL_DEBUG_SOURCE_THIRD_PARTY_ARB
+  "Application",     // GL_DEBUG_SOURCE_APPLICATION_ARB
+  "Other"            // GL_DEBUG_SOURCE_OTHER_ARB
+};
+
+static Standard_CString THE_DBGMSG_TYPES[] =
+{
+  "Error",              // GL_DEBUG_TYPE_ERROR_ARB
+  "Deprecated",         // GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB
+  "Undefined behavior", // GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB
+  "Portability",        // GL_DEBUG_TYPE_PORTABILITY_ARB
+  "Performance",        // GL_DEBUG_TYPE_PERFORMANCE_ARB
+  "Other"               // GL_DEBUG_TYPE_OTHER_ARB
+};
+
+static Standard_CString THE_DBGMSG_SEV_HIGH   = "High";   // GL_DEBUG_SEVERITY_HIGH_ARB
+static Standard_CString THE_DBGMSG_SEV_MEDIUM = "Medium"; // GL_DEBUG_SEVERITY_MEDIUM_ARB
+static Standard_CString THE_DBGMSG_SEV_LOW    = "Low";    // GL_DEBUG_SEVERITY_LOW_ARB
+
+static void APIENTRY debugCallbackWrap(unsigned int theSource,
+                                       unsigned int theType,
+                                       unsigned int theId,
+                                       unsigned int theSeverity,
+                                       int          /*theLength*/,
+                                       const char*  theMessage,
+                                       void*        /*theUserParam*/)
+{
+  //OpenGl_Context* aCtx = (OpenGl_Context* )theUserParam;
+  Standard_CString& aSrc = (theSource >= GL_DEBUG_SOURCE_API_ARB
+                         && theSource <= GL_DEBUG_SOURCE_OTHER_ARB)
+                         ? THE_DBGMSG_SOURCES[theSource - GL_DEBUG_SOURCE_API_ARB]
+                         : THE_DBGMSG_UNKNOWN;
+  Standard_CString& aType = (theType >= GL_DEBUG_TYPE_ERROR_ARB
+                          && theType <= GL_DEBUG_TYPE_OTHER_ARB)
+                          ? THE_DBGMSG_TYPES[theType - GL_DEBUG_TYPE_ERROR_ARB]
+                          : THE_DBGMSG_UNKNOWN;
+  Standard_CString& aSev = theSeverity == GL_DEBUG_SEVERITY_HIGH_ARB
+                         ? THE_DBGMSG_SEV_HIGH
+                         : (theSeverity == GL_DEBUG_SEVERITY_MEDIUM_ARB
+                          ? THE_DBGMSG_SEV_MEDIUM
+                          : THE_DBGMSG_SEV_LOW);
+  std::cerr << "Source:"  << aSrc
+            << " | Type:" << aType
+            << " | ID:"   << theId
+            << " | Severity:" << aSev
+            << " | Message:\n  " << theMessage << "\n";
+}
+
 // =======================================================================
 // function : init
 // purpose  :
@@ -526,6 +600,28 @@ void OpenGl_Context::init()
     glGetIntegerv (GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &myAnisoMax);
   }
 
+  // initialize debug context extension
+  if (CheckExtension ("GL_ARB_debug_output"))
+  {
+    arbDbg = new OpenGl_ArbDbg();
+    memset (arbDbg, 0, sizeof(OpenGl_ArbDbg)); // nullify whole structure
+    if (!FindProcShort (arbDbg, glDebugMessageControlARB)
+     || !FindProcShort (arbDbg, glDebugMessageInsertARB)
+     || !FindProcShort (arbDbg, glDebugMessageCallbackARB)
+     || !FindProcShort (arbDbg, glGetDebugMessageLogARB))
+    {
+      delete arbDbg;
+      arbDbg = NULL;
+    }
+    if (arbDbg != NULL
+     && caps->contextDebug)
+    {
+      // setup default callback
+      arbDbg->glDebugMessageCallbackARB (debugCallbackWrap, this);
+      glEnable (GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
+    }
+  }
+
   // initialize VBO extension (ARB)
   if (CheckExtension ("GL_ARB_vertex_buffer_object"))
   {
index a35b36e..ecdc69c 100644 (file)
@@ -28,6 +28,7 @@
 #include <NCollection_DataMap.hxx>
 #include <NCollection_Handle.hxx>
 #include <NCollection_Queue.hxx>
+#include <OpenGl_Caps.hxx>
 #include <OpenGl_Resource.hxx>
 #include <Standard_Transient.hxx>
 #include <TCollection_AsciiString.hxx>
@@ -42,6 +43,7 @@ struct OpenGl_GlCore20;
 struct OpenGl_ArbVBO;
 struct OpenGl_ArbTBO;
 struct OpenGl_ArbIns;
+struct OpenGl_ArbDbg;
 struct OpenGl_ExtFBO;
 struct OpenGl_ExtGS;
 
@@ -102,7 +104,7 @@ public:
 public:
 
   //! Empty constructor. You should call Init() to perform initialization with bound GL context.
-  Standard_EXPORT OpenGl_Context();
+  Standard_EXPORT OpenGl_Context (const Handle(OpenGl_Caps)& theCaps = NULL);
 
   //! Destructor.
   Standard_EXPORT virtual ~OpenGl_Context();
@@ -115,7 +117,7 @@ public:
   //! GL context should be active!
   Standard_EXPORT Standard_Boolean Init();
 
-#if (defined(_WIN32) || defined(__WIN32__))
+#if defined(_WIN32)
   Standard_EXPORT Standard_Boolean Init (const Aspect_Handle           theWindow,
                                          const Aspect_Handle           theWindowDC,
                                          const Aspect_RenderingContext theGContext);
@@ -130,6 +132,10 @@ public:
   //! Check if theExtName extension is supported by active GL context.
   Standard_EXPORT Standard_Boolean CheckExtension (const char* theExtName) const;
 
+  //! Check if theExtName extension is in extensions string.
+  Standard_EXPORT static Standard_Boolean CheckExtension (const char* theExtString,
+                                                          const char* theExtName);
+
   //! Auxiliary template to retrieve GL function pointer.
   //! Pointer to function retrieved from library is statically casted
   //! to requested type - there no way to check real signature of exported function.
@@ -257,12 +263,15 @@ public: // core profiles
   OpenGl_GlCore15* core15;
   OpenGl_GlCore20* core20;
 
+  Handle(OpenGl_Caps) caps; //!< context options
+
 public: // extensions
 
   Standard_Boolean arbNPTW; //!< GL_ARB_texture_non_power_of_two
   OpenGl_ArbVBO*   arbVBO;  //!< GL_ARB_vertex_buffer_object
   OpenGl_ArbTBO*   arbTBO;  //!< GL_ARB_texture_buffer_object
   OpenGl_ArbIns*   arbIns;  //!< GL_ARB_draw_instanced
+  OpenGl_ArbDbg*   arbDbg;  //!< GL_ARB_debug_output
   OpenGl_ExtFBO*   extFBO;  //!< GL_EXT_framebuffer_object
   OpenGl_ExtGS*    extGS;   //!< GL_EXT_geometry_shader4
   Standard_Boolean extBgra; //!< GL_EXT_bgra
@@ -272,7 +281,7 @@ public: // extensions
 
 private: // system-dependent fields
 
-#if (defined(_WIN32) || defined(__WIN32__))
+#if defined(_WIN32)
   Aspect_Handle           myWindow;   //!< window handle (owner of GL context) : HWND
   Aspect_Handle           myWindowDC; //!< Device Descriptor handle : HDC
   Aspect_RenderingContext myGContext; //!< Rendering Context handle : HGLRC
index 74e8d3b..be8fcd7 100755 (executable)
@@ -35,9 +35,6 @@ IMPLEMENT_STANDARD_RTTIEXT(OpenGl_GraphicDriver,Graphic3d_GraphicDriver)
 
 namespace
 {
-  // Global switch - shared by whole TKOpenGl module. To be removed.
-  static Standard_Boolean TheToUseVbo = Standard_True;
-
   static const Handle(OpenGl_Context) TheNullGlCtx;
 };
 
@@ -67,6 +64,7 @@ extern "C" {
 // =======================================================================
 OpenGl_GraphicDriver::OpenGl_GraphicDriver (const Standard_CString theShrName)
 : Graphic3d_GraphicDriver (theShrName),
+  myCaps           (new OpenGl_Caps()),
   myMapOfView      (1, NCollection_BaseAllocator::CommonBaseAllocator()),
   myMapOfWS        (1, NCollection_BaseAllocator::CommonBaseAllocator()),
   myMapOfStructure (1, NCollection_BaseAllocator::CommonBaseAllocator()),
@@ -95,21 +93,12 @@ Standard_ShortReal OpenGl_GraphicDriver::DefaultTextHeight() const
 }
 
 // =======================================================================
-// function : ToUseVBO
-// purpose  :
-// =======================================================================
-Standard_Boolean OpenGl_GraphicDriver::ToUseVBO()
-{
-  return TheToUseVbo;
-}
-
-// =======================================================================
 // function : EnableVBO
 // purpose  :
 // =======================================================================
 void OpenGl_GraphicDriver::EnableVBO (const Standard_Boolean theToTurnOn)
 {
-  TheToUseVbo = theToTurnOn;
+  myCaps->vboDisable = !theToTurnOn;
 }
 
 // =======================================================================
index e909f50..0f076b3 100644 (file)
@@ -86,7 +86,7 @@ class OpenGl_GraphicDriver : public Graphic3d_GraphicDriver
 public:
 
   //! Constructor
-  Standard_EXPORT OpenGl_GraphicDriver (const Standard_CString theShrName);
+  Standard_EXPORT OpenGl_GraphicDriver (const Standard_CString theShrName = "TKOpenGl");
 
   Standard_EXPORT Standard_Boolean Begin (const Handle(Aspect_DisplayConnection)& theDisplayConnection);
   Standard_EXPORT void End ();
@@ -296,8 +296,17 @@ public:
 
 public:
 
-  //! Returns true if VBO usage does not forbidden.
-  Standard_EXPORT static Standard_Boolean ToUseVBO();
+  //! @return the visualization options
+  inline const OpenGl_Caps& Options() const
+  {
+    return *myCaps.operator->();
+  }
+
+  //! @return the visualization options
+  inline OpenGl_Caps& ChangeOptions()
+  {
+    return *myCaps.operator->();
+  }
 
   //! VBO usage can be forbidden by this method even if it is supported by GL driver.
   //! Notice that disabling of VBO will cause rendering performance degradation.
@@ -327,6 +336,7 @@ public:
 
 private:
 
+  Handle(OpenGl_Caps)                                             myCaps;
   NCollection_DataMap<Standard_Integer, Handle(OpenGl_View)>      myMapOfView;
   NCollection_DataMap<Standard_Integer, Handle(OpenGl_Workspace)> myMapOfWS;
   NCollection_DataMap<Standard_Integer, OpenGl_Structure*>        myMapOfStructure;
index 39cbeed..4e91e47 100755 (executable)
@@ -501,7 +501,7 @@ Standard_Boolean OpenGl_GraphicDriver::View (Graphic3d_CView& theCView)
   if (aWS.IsNull())
   {
     Handle(OpenGl_Context) aShareCtx = GetSharedContext();
-    aWS = new OpenGl_Workspace (openglDisplay, theCView.DefWindow, theCView.GContext, aShareCtx);
+    aWS = new OpenGl_Workspace (openglDisplay, theCView.DefWindow, theCView.GContext, myCaps, aShareCtx);
     openglDisplay->SetWindow (theCView.DefWindow.XWindow, aWS);
   }
 
index 02a14a6..fdc0f02 100755 (executable)
@@ -597,7 +597,8 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace
   }
 
   // create VBOs on first render call
-  if (!myIsVboInit && OpenGl_GraphicDriver::ToUseVBO() && theWorkspace->GetGlContext()->core15 != NULL)
+  const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
+  if (!myIsVboInit && !aCtx->caps->vboDisable && aCtx->core15 != NULL)
   {
     BuildVBO (theWorkspace);
     myIsVboInit = Standard_True;
index 04dcf0e..6280229 100644 (file)
@@ -635,7 +635,7 @@ void OpenGl_Text::render (const Handle(OpenGl_PrinterContext)& thePrintCtx,
     aFormatter.Append (theCtx, myString, *myFont.operator->());
     aFormatter.Format();
 
-    if (OpenGl_GraphicDriver::ToUseVBO() && theCtx->core15 != NULL)
+    if (!theCtx->caps->vboDisable && theCtx->core15 != NULL)
     {
       aFormatter.Result (theCtx, myTextures, myVertsVbo, myTCrdsVbo);
     }
index a05ec82..415d26a 100644 (file)
@@ -38,7 +38,30 @@ namespace
 {
   static const TEL_COLOUR THE_DEFAULT_BG_COLOR = { { 0.F, 0.F, 0.F, 1.F } };
 
-#if (defined(_WIN32) || defined(__WIN32__))
+#if defined(_WIN32)
+
+  // WGL_ARB_create_context_profile
+#ifndef WGL_CONTEXT_MAJOR_VERSION_ARB
+  #define WGL_CONTEXT_MAJOR_VERSION_ARB           0x2091
+  #define WGL_CONTEXT_MINOR_VERSION_ARB           0x2092
+  #define WGL_CONTEXT_LAYER_PLANE_ARB             0x2093
+  #define WGL_CONTEXT_FLAGS_ARB                   0x2094
+  #define WGL_CONTEXT_PROFILE_MASK_ARB            0x9126
+
+  // WGL_CONTEXT_FLAGS bits
+  #define WGL_CONTEXT_DEBUG_BIT_ARB               0x0001
+  #define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB  0x0002
+
+  // WGL_CONTEXT_PROFILE_MASK_ARB bits
+  #define WGL_CONTEXT_CORE_PROFILE_BIT_ARB          0x00000001
+  #define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+#endif // WGL_CONTEXT_MAJOR_VERSION_ARB
+
+  static LRESULT CALLBACK wndProcDummy (HWND theWin, UINT theMsg, WPARAM theParamW, LPARAM theParamL)
+  {
+    return DefWindowProcW (theWin, theMsg, theParamW, theParamL);
+  }
+
   static int find_pixel_format (HDC                    theDevCtx,
                                 PIXELFORMATDESCRIPTOR& thePixelFrmt,
                                 const Standard_Boolean theIsDoubleBuff)
@@ -139,11 +162,12 @@ namespace
 OpenGl_Window::OpenGl_Window (const Handle(OpenGl_Display)& theDisplay,
                               const CALL_DEF_WINDOW&        theCWindow,
                               Aspect_RenderingContext       theGContext,
+                              const Handle(OpenGl_Caps)&    theCaps,
                               const Handle(OpenGl_Context)& theShareCtx)
 : myDisplay (theDisplay),
-  myGlContext (new OpenGl_Context()),
+  myGlContext (new OpenGl_Context (theCaps)),
   myOwnGContext (theGContext == 0),
-#if (defined(_WIN32) || defined(__WIN32__))
+#if defined(_WIN32)
   mySysPalInUse (FALSE),
 #endif
   myWidth ((Standard_Integer )theCWindow.dx),
@@ -156,7 +180,7 @@ OpenGl_Window::OpenGl_Window (const Handle(OpenGl_Display)& theDisplay,
   myBgColor.rgb[1] = theCWindow.Background.g;
   myBgColor.rgb[2] = theCWindow.Background.b;
 
-#if (defined(_WIN32) || defined(__WIN32__))
+#if defined(_WIN32)
   HWND  aWindow   = (HWND )theCWindow.XWindow;
   HDC   aWindowDC = GetDC (aWindow);
   HGLRC aGContext = (HGLRC )theGContext;
@@ -201,9 +225,92 @@ OpenGl_Window::OpenGl_Window (const Handle(OpenGl_Display)& theDisplay,
     return;
   }
 
+  HGLRC aSlaveCtx = !theShareCtx.IsNull() ? (HGLRC )theShareCtx->myGContext : NULL;
   if (aGContext == NULL)
   {
-    aGContext = wglCreateContext (aWindowDC);
+    // create temporary context to retrieve advanced context creation procedures
+    HMODULE aModule = GetModuleHandleW(NULL);
+    WNDCLASSW aClass; memset (&aClass, 0, sizeof(aClass));
+    aClass.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
+    aClass.lpfnWndProc   = wndProcDummy;
+    aClass.hInstance     = aModule;
+    aClass.lpszClassName = L"OpenGl_WindowTmp";
+    HWND  aWinTmp     = NULL;
+    HDC   aDevCtxTmp  = NULL;
+    HGLRC aRendCtxTmp = NULL;
+    if (!theCaps->contextDebug
+     || RegisterClassW (&aClass) == 0)
+    {
+      aClass.lpszClassName = NULL;
+    }
+    if (aClass.lpszClassName != NULL)
+    {
+      aWinTmp = CreateWindowExW(WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE | WS_EX_NOACTIVATE,
+                                aClass.lpszClassName, L"OpenGl_WindowTmp",
+                                WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_DISABLED,
+                                2, 2, 4, 4,
+                                NULL, NULL, aModule, NULL);
+    }
+    if (aWinTmp != NULL)
+    {
+      aDevCtxTmp = GetDC (aWinTmp);
+      SetPixelFormat (aDevCtxTmp, aPixelFrmtId, &aPixelFrmt);
+      aRendCtxTmp = wglCreateContext (aDevCtxTmp);
+    }
+    if (aRendCtxTmp != NULL)
+    {
+      wglMakeCurrent (aDevCtxTmp, aRendCtxTmp);
+
+      typedef const char* (WINAPI *wglGetExtensionsStringARB_t)(HDC theDeviceContext);
+      typedef HGLRC (WINAPI *wglCreateContextAttribsARB_t)(HDC        theDevCtx,
+                                                           HGLRC      theShareContext,
+                                                           const int* theAttribs);
+      wglGetExtensionsStringARB_t  aGetExtensions = (wglGetExtensionsStringARB_t  )wglGetProcAddress ("wglGetExtensionsStringARB");
+      wglCreateContextAttribsARB_t aCreateCtxProc = (wglCreateContextAttribsARB_t )wglGetProcAddress ("wglCreateContextAttribsARB");
+      const char* aWglExts = aGetExtensions (wglGetCurrentDC());
+      if (aCreateCtxProc != NULL
+       && OpenGl_Context::CheckExtension (aWglExts, "WGL_ARB_create_context_profile"))
+      {
+        // Beware! NVIDIA drivers reject context creation when WGL_CONTEXT_PROFILE_MASK_ARB are specified
+        // but not WGL_CONTEXT_MAJOR_VERSION_ARB/WGL_CONTEXT_MINOR_VERSION_ARB.
+        int aCtxAttribs[] =
+        {
+          //WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
+          //WGL_CONTEXT_MINOR_VERSION_ARB, 2,
+          //WGL_CONTEXT_PROFILE_MASK_ARB,  WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, //WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
+          WGL_CONTEXT_FLAGS_ARB,         theCaps->contextDebug ? WGL_CONTEXT_DEBUG_BIT_ARB : 0,
+          0, 0
+        };
+
+        aGContext = aCreateCtxProc (aWindowDC, aSlaveCtx, aCtxAttribs);
+        if (aGContext != NULL)
+        {
+          aSlaveCtx = NULL;
+        }
+      }
+    }
+
+    if (aRendCtxTmp != NULL)
+    {
+      wglDeleteContext (aRendCtxTmp);
+    }
+    if (aDevCtxTmp != NULL)
+    {
+      ReleaseDC (aWinTmp, aDevCtxTmp);
+    }
+    if (aWinTmp != NULL)
+    {
+      DestroyWindow (aWinTmp);
+    }
+    if (aClass.lpszClassName != NULL)
+    {
+      UnregisterClassW (aClass.lpszClassName, aModule);
+    }
+
+    if (aGContext == NULL)
+    {
+      aGContext = wglCreateContext (aWindowDC);
+    }
     if (aGContext == NULL)
     {
       ReleaseDC (aWindow, aWindowDC);
@@ -216,7 +323,7 @@ OpenGl_Window::OpenGl_Window (const Handle(OpenGl_Display)& theDisplay,
   }
 
   // all GL context within one OpenGl_GraphicDriver should be shared!
-  if (!theShareCtx.IsNull() && wglShareLists ((HGLRC )theShareCtx->myGContext, aGContext) != TRUE)
+  if (aSlaveCtx != NULL && wglShareLists (aSlaveCtx, aGContext) != TRUE)
   {
     TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: wglShareLists failed. Error code: ");
     aMsg += (int )GetLastError();
@@ -409,7 +516,7 @@ OpenGl_Window::OpenGl_Window (const Handle(OpenGl_Display)& theDisplay,
 // =======================================================================
 OpenGl_Window::~OpenGl_Window()
 {
-#if (defined(_WIN32) || defined(__WIN32__))
+#if defined(_WIN32)
   HWND  aWindow   = (HWND  )myGlContext->myWindow;
   HDC   aWindowDC = (HDC   )myGlContext->myWindowDC;
   HGLRC aGContext = (HGLRC )myGlContext->myGContext;
@@ -468,7 +575,7 @@ void OpenGl_Window::Resize (const CALL_DEF_WINDOW& theCWindow)
   myWidth  = (Standard_Integer )theCWindow.dx;
   myHeight = (Standard_Integer )theCWindow.dy;
 
-#if (!defined(_WIN32) && !defined(__WIN32__))
+#if !defined(_WIN32)
   XResizeWindow (aDisp, myGlContext->myWindow, (unsigned int )myWidth, (unsigned int )myHeight);
   XSync (aDisp, False);
 #endif
@@ -525,7 +632,7 @@ void OpenGl_Window::Init()
   if (!Activate())
     return;
 
-#if (defined(_WIN32) || defined(__WIN32__))
+#if defined(_WIN32)
   RECT cr;
   GetClientRect ((HWND )myGlContext->myWindow, &cr);
   myWidth  = cr.right - cr.left;
index 9cd61e7..aeb60e5 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <OpenGl_GlCore11.hxx>
 #include <InterfaceGraphic_Aspect.hxx>
+#include <OpenGl_Caps.hxx>
 
 #include <Handle_OpenGl_Context.hxx>
 #include <Handle_OpenGl_Display.hxx>
@@ -39,6 +40,7 @@ public:
   OpenGl_Window (const Handle(OpenGl_Display)& theDisplay,
                  const CALL_DEF_WINDOW&        theCWindow,
                  Aspect_RenderingContext       theGContext,
+                 const Handle(OpenGl_Caps)&    theCaps,
                  const Handle(OpenGl_Context)& theShareCtx);
 
   //! Destructor
index dce08ac..2b7e2f6 100644 (file)
@@ -52,9 +52,10 @@ namespace
 OpenGl_Window::OpenGl_Window (const Handle(OpenGl_Display)& theDisplay,
                               const CALL_DEF_WINDOW&        theCWindow,
                               Aspect_RenderingContext       theGContext,
+                              const Handle(OpenGl_Caps)&    theCaps,
                               const Handle(OpenGl_Context)& theShareCtx)
 : myDisplay (theDisplay),
-  myGlContext (new OpenGl_Context()),
+  myGlContext (new OpenGl_Context (theCaps)),
   myOwnGContext (theGContext == 0),
   myWidth ((Standard_Integer )theCWindow.dx),
   myHeight ((Standard_Integer )theCWindow.dy),
index 10ec9d5..2250790 100644 (file)
@@ -32,7 +32,7 @@
 
 #include <Graphic3d_TextureParams.hxx>
 
-#if (defined(_WIN32) || defined(__WIN32__)) && defined(HAVE_VIDEOCAPTURE)
+#if defined(_WIN32) && defined(HAVE_VIDEOCAPTURE)
   #include <OpenGl_AVIWriter.hxx>
 #endif
 
@@ -70,8 +70,9 @@ namespace
 OpenGl_Workspace::OpenGl_Workspace (const Handle(OpenGl_Display)& theDisplay,
                                     const CALL_DEF_WINDOW&        theCWindow,
                                     Aspect_RenderingContext       theGContext,
+                                    const Handle(OpenGl_Caps)&    theCaps,
                                     const Handle(OpenGl_Context)& theShareCtx)
-: OpenGl_Window (theDisplay, theCWindow, theGContext, theShareCtx),
+: OpenGl_Window (theDisplay, theCWindow, theGContext, theCaps, theShareCtx),
   NamedStatus (0),
   HighlightColor (&myDefaultHighlightColor),
   //
index b0c06d0..351127a 100644 (file)
@@ -70,6 +70,7 @@ public:
   OpenGl_Workspace (const Handle(OpenGl_Display)& theDisplay,
                     const CALL_DEF_WINDOW&        theCWindow,
                     Aspect_RenderingContext       theGContext,
+                    const Handle(OpenGl_Caps)&    theCaps,
                     const Handle(OpenGl_Context)& theShareCtx);
 
   //! Destructor
index 444a365..e1c8505 100755 (executable)
@@ -2759,7 +2759,7 @@ static int VDrawSphere (Draw_Interpretor& /*di*/, Standard_Integer argc, const c
   else if (argc < 3)
   {
     std::cout << "Use: " << argv[0]
-              << " shapeName Fineness [X=0.0 Y=0.0 Z=0.0] [Radius=100.0] [ToEnableVBO=1] [NumberOfViewerUpdate=1] [ToShowEdges=0]\n";
+              << " shapeName Fineness [X=0.0 Y=0.0 Z=0.0] [Radius=100.0] [ToShowEdges=0]\n";
     return 1;
   }
 
index 6244fb3..a30169d 100644 (file)
@@ -419,8 +419,6 @@ static int VImmediateFront (Draw_Interpretor& /*theDI*/,
 
   if (theArgNb < 2)
   {
-    //theDI << "VBO: " << aDriver->ToUseVBO() << "\n";
-    //return 0;
     std::cerr << "Wrong number of arguments.\n";
     return 1;
   }
@@ -449,11 +447,15 @@ static int VGlInfo (Draw_Interpretor& theDI,
 
   if (theArgNb <= 1)
   {
+    Standard_CString aDebugInfo = OpenGl_Context::CheckExtension ((const char* )glGetString (GL_EXTENSIONS),
+                                                                  "GL_ARB_debug_output")
+                                ? "  GLdebug     =  ON\n" : "";
     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";
+          << "  GLSLversion = '" << (const char* )glGetString(GL_SHADING_LANGUAGE_VERSION) << "'\n"
+          << aDebugInfo;
     return 0;
   }
 
index eacdc3d..b1705d7 100755 (executable)
 # include <config.h>
 #endif
 
-#ifdef WNT
-#include <windows.h>
-#endif
-
+#include <OpenGl_GlCore20.hxx>
 #include <AIS_Shape.hxx>
 #include <AIS_Drawer.hxx>
 #include <AIS_InteractiveObject.hxx>
@@ -36,7 +33,6 @@
 #include <AIS_ListIteratorOfListOfInteractive.hxx>
 #include <DBRep.hxx>
 #include <Graphic3d_AspectMarker3d.hxx>
-#include <Graphic3d_GraphicDriver.hxx>
 #include <Graphic3d_ExportFormat.hxx>
 #include <Graphic3d_NameOfTextureEnv.hxx>
 #include <Graphic3d_TextureEnv.hxx>
@@ -60,6 +56,7 @@
 #include <Draw_Appli.hxx>
 #include <Aspect_PrintAlgo.hxx>
 #include <Image_AlienPixMap.hxx>
+#include <OpenGl_GraphicDriver.hxx>
 #include <OSD_Timer.hxx>
 #include <TColStd_SequenceOfInteger.hxx>
 #include <TColStd_HSequenceOfReal.hxx>
@@ -79,7 +76,7 @@
 #include <Visual3d_Layer.hxx>
 #include <cstdlib>
 
-#if defined(_WIN32) || defined(__WIN32__)
+#if defined(_WIN32)
   #include <WNT_WClass.hxx>
   #include <WNT_Window.hxx>
 
@@ -109,7 +106,7 @@ Standard_EXPORT int ViewerMainLoop(Standard_Integer , const char** argv);
 extern const Handle(NIS_InteractiveContext)& TheNISContext();
 extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
 
-#if defined(_WIN32) || defined(__WIN32__)
+#if defined(_WIN32)
 static Handle(WNT_Window)& VT_GetWindow() {
   static Handle(WNT_Window) WNTWin;
   return WNTWin;
@@ -144,11 +141,11 @@ static void SetDisplayConnection (const Handle(Aspect_DisplayConnection)& theDis
   GetDisplayConnection() = theDisplayConnection;
 }
 
-#if defined(_WIN32) || defined(__WIN32__) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
+#if defined(_WIN32) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
 Aspect_Handle GetWindowHandle(const Handle(Aspect_Window)& theWindow)
 {
   Aspect_Handle aWindowHandle = NULL;
-#if defined(_WIN32) || defined(__WIN32__)
+#if defined(_WIN32)
   const Handle (WNT_Window) aWindow = Handle(WNT_Window)::DownCast (theWindow);
   if (!aWindow.IsNull())
     return aWindow->HWindow();
@@ -164,9 +161,9 @@ Aspect_Handle GetWindowHandle(const Handle(Aspect_Window)& theWindow)
 static Standard_Boolean MyHLRIsOn = Standard_False;
 
 NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)> ViewerTest_myViews;
-static NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)> ViewerTest_myContexts;
+static NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>  ViewerTest_myContexts;
 static NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)> ViewerTest_myDrivers;
-
+static OpenGl_Caps ViewerTest_myDefaultCaps;
 
 #define ZCLIPWIDTH 1.
 
@@ -209,7 +206,7 @@ static LRESULT WINAPI AdvViewerWindowProc(
 const Handle(MMgt_TShared)& ViewerTest::WClass()
 {
   static Handle(MMgt_TShared) theWClass;
-#if defined(_WIN32) || defined(__WIN32__)
+#if defined(_WIN32)
   if (theWClass.IsNull())
   {
     theWClass = new WNT_WClass ("GW3D_Class", AdvViewerWindowProc,
@@ -409,7 +406,7 @@ Handle(AIS_InteractiveContext) FindContextByView (const Handle(V3d_View)& theVie
 void SetWindowTitle (const Handle(Aspect_Window)& theWindow,
                      Standard_CString theTitle)
 {
-#if defined(_WIN32) || defined(__WIN32__)
+#if defined(_WIN32)
   SetWindowText ((HWND)Handle(WNT_Window)::DownCast(theWindow)->HWindow(),
     theTitle);
 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
@@ -488,15 +485,13 @@ TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft
   // window fit in the small screens (actual for remote desktops, see #23003).
   // The position corresponds to the window's client area, thus some
   // gap is added for window frame to be visible.
-
   Standard_Integer aPxLeft   = 20;
   Standard_Integer aPxTop    = 40;
   Standard_Integer aPxWidth  = 409;
   Standard_Integer aPxHeight = 409;
   Standard_Boolean toCreateViewer = Standard_False;
 
-
-  Handle(Graphic3d_GraphicDriver) aGraphicDriver;
+  Handle(OpenGl_GraphicDriver) aGraphicDriver;
   ViewerTest_Names aViewNames(theViewName);
   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName ()))
     aViewNames.SetViewName (aViewNames.GetViewerName() + "/" + CreateName<Handle(V3d_View)>(ViewerTest_myViews, "View"));
@@ -514,7 +509,7 @@ TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft
   if (!ViewerTest_myDrivers.IsBound1 (aViewNames.GetDriverName()))
   {
     // Get connection string
-  #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
+  #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
     TCollection_AsciiString aDisplayName(theDisplayName);
     if (aDisplayName.IsEmpty())
       SetDisplayConnection (new Aspect_DisplayConnection ());
@@ -524,13 +519,15 @@ TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft
   #else
     SetDisplayConnection (new Aspect_DisplayConnection ());
   #endif
-    aGraphicDriver = Graphic3d::InitGraphicDriver (GetDisplayConnection());
+    aGraphicDriver = new OpenGl_GraphicDriver();
+    aGraphicDriver->ChangeOptions() = ViewerTest_myDefaultCaps;
+    aGraphicDriver->Begin (GetDisplayConnection());
     ViewerTest_myDrivers.Bind (aViewNames.GetDriverName(), aGraphicDriver);
     toCreateViewer = Standard_True;
   }
   else
   {
-    aGraphicDriver = ViewerTest_myDrivers.Find1(aViewNames.GetDriverName());
+    aGraphicDriver = Handle(OpenGl_GraphicDriver)::DownCast (ViewerTest_myDrivers.Find1 (aViewNames.GetDriverName()));
   }
 
   //Dispose the window if input parameters are default
@@ -3776,41 +3773,74 @@ static int VFps (Draw_Interpretor& theDI,
   return 0;
 }
 
+//==============================================================================
+//function : VGlDebug
+//purpose  :
+//==============================================================================
+
+static int VGlDebug (Draw_Interpretor& theDI,
+                     Standard_Integer  theArgNb,
+                     const char**      theArgVec)
+{
+  if (theArgNb < 2)
+  {
+    Handle(V3d_View) aView = ViewerTest::CurrentView();
+    if (aView.IsNull())
+    {
+      std::cerr << "No active view. Please call vinit.\n";
+      return 0;
+    }
+
+    Standard_Boolean isActive = OpenGl_Context::CheckExtension ((const char* )glGetString (GL_EXTENSIONS),
+                                                                "GL_ARB_debug_output");
+    std::cout << "Active graphic driver: debug " << (isActive ? "ON" : "OFF") << "\n";
+    theDI << (isActive ? "1" : "0");
+    return 0;
+  }
+
+  ViewerTest_myDefaultCaps.contextDebug = Draw::Atoi (theArgVec[1]) != 0;
+  return 0;
+}
 
 //==============================================================================
 //function : VVbo
 //purpose  :
 //==============================================================================
 
-static int VVbo (Draw_Interpretor& /*theDI*/,
+static int VVbo (Draw_Interpretor& theDI,
                  Standard_Integer  theArgNb,
                  const char**      theArgVec)
 {
-  // get the context
-  Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
-  if (aContextAIS.IsNull())
+  const Standard_Boolean toSet    = (theArgNb > 1);
+  const Standard_Boolean toUseVbo = toSet ? (Draw::Atoi (theArgVec[1]) == 0) : 1;
+  if (toSet)
   {
-    std::cerr << "No active view. Please call vinit.\n";
-    return 1;
+    ViewerTest_myDefaultCaps.vboDisable = toUseVbo;
   }
 
-  Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
-
-  if (aDriver.IsNull())
+  // get the context
+  Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
+  if (aContextAIS.IsNull())
   {
-    std::cerr << "Graphic driver not available.\n";
+    if (!toSet)
+    {
+      std::cerr << "No active view!\n";
+    }
     return 1;
   }
-
-  if (theArgNb < 2)
+  Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContextAIS->CurrentViewer()->Driver());
+  if (!aDriver.IsNull())
   {
-    //theDI << "VBO: " << aDriver->ToUseVBO() << "\n";
-    //return 0;
-    std::cerr << "Wrong number of arguments.\n";
-    return 1;
+    if (!toSet)
+    {
+      theDI << (aDriver->Options().vboDisable ? "0" : "1") << "\n";
+    }
+    else
+    {
+      aDriver->ChangeOptions().vboDisable = toUseVbo;
+    }
   }
 
-  aDriver->EnableVBO (Draw::Atoi(theArgVec[1]) != 0);
   return 0;
 }
 
@@ -3832,7 +3862,6 @@ static int VMemGpu (Draw_Interpretor& theDI,
   }
 
   Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
-
   if (aDriver.IsNull())
   {
     std::cerr << "Graphic driver not available.\n";
@@ -4860,8 +4889,13 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
   theCommands.Add ("vfps",
     "vfps [framesNb=100] : estimate average frame rate for active view",
     __FILE__, VFps, group);
+  theCommands.Add ("vgldebug",
+    "vgldebug [{0|1}] : request debug GL context, should be called before vinit\n"
+    "                : this function is implemented only for Windows\n"
+    "                : GL_ARB_debug_output extension should be exported by OpenGL driver!",
+    __FILE__, VGlDebug, group);
   theCommands.Add ("vvbo",
-    "vvbo {0|1} : turn VBO usage On/Off; affects only newly displayed objects",
+    "vvbo [{0|1}] : turn VBO usage On/Off; affects only newly displayed objects",
     __FILE__, VVbo, group);
   theCommands.Add ("vmemgpu",
     "vmemgpu [f]: print system-dependent GPU memory information if available;"