0025213: Visualization, TKOpenGl - do not use deprecated built-ins in GLSL shaders
authorkgv <kgv@opencascade.com>
Wed, 17 Sep 2014 09:02:32 +0000 (13:02 +0400)
committerbugmaster <bugmaster@opencascade.com>
Thu, 18 Sep 2014 11:24:07 +0000 (15:24 +0400)
Inherit NCollection_Buffer from Standard_Transient, do not use incomplete NCollection_Handle.

OpenGl_Context, add methods ActiveProgram(),BindProgram()
to manage currently active GLSL program.
Add method ::ToUseVbo().

OpenGl_ShaderProgram, setup locations of pre-defined vertex attributes
occVertex, occNormal, occTexCoord, occColor before linkage.
Remove methods OpenGl_ShaderProgram::Bind(), ::BindWithVariables()
and ::Unbind() - OpenGl_Context::BindProgram() should be used instead.

Introduce class OpenGl_VertexBufferCompat, which emulates VBO
behavior on systems without VBO (compatibility with broken OpenGL drivers on Windows).

OpenGl_PrimitiveArray - use OpenGl_VertexBufferCompat when VBO is unavailable,
remove duplicated code. Use OpenGl_VertexBuffer::HasNormalAttribute()
method to activate lighting.

OpenGl_Text - use OpenGl_VertexBufferCompat, eliminate duplicated code.

Changes in OpenGl_VertexBuffer, drop methods BindFixed()/UnbindFixed().
Superseded by new methods BindAllAttributes()/UnbindAllAttributes()
which handle active GLSL program, when it is set.

30 files changed:
src/Graphic3d/Graphic3d_ArrayOfPrimitives.cxx
src/Graphic3d/Graphic3d_BoundBuffer.hxx
src/Graphic3d/Graphic3d_Buffer.hxx
src/Graphic3d/Graphic3d_IndexBuffer.hxx
src/Image/Image_PixMap.cxx
src/Image/Image_PixMapData.hxx
src/NCollection/NCollection_AlignedAllocator.cxx
src/NCollection/NCollection_Buffer.hxx
src/OpenGl/FILES
src/OpenGl/OpenGl_Context.cxx
src/OpenGl/OpenGl_Context.hxx
src/OpenGl/OpenGl_PrimitiveArray.cxx
src/OpenGl/OpenGl_PrimitiveArray.hxx
src/OpenGl/OpenGl_ShaderManager.cxx
src/OpenGl/OpenGl_ShaderManager.hxx
src/OpenGl/OpenGl_ShaderProgram.cxx
src/OpenGl/OpenGl_ShaderProgram.hxx
src/OpenGl/OpenGl_Text.cxx
src/OpenGl/OpenGl_Text.hxx
src/OpenGl/OpenGl_TextFormatter.cxx
src/OpenGl/OpenGl_TextFormatter.hxx
src/OpenGl/OpenGl_VertexBuffer.cxx
src/OpenGl/OpenGl_VertexBuffer.hxx
src/OpenGl/OpenGl_VertexBuffer.lxx [new file with mode: 0644]
src/OpenGl/OpenGl_VertexBufferCompat.cxx [new file with mode: 0644]
src/OpenGl/OpenGl_VertexBufferCompat.hxx [new file with mode: 0644]
src/OpenGl/OpenGl_View_2.cxx
src/OpenGl/OpenGl_Workspace_Raytrace.cxx
src/Shaders/Declarations.glsl
src/Shaders/RaytraceBase.vs

index 5550e3f..f45397a 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 
+IMPLEMENT_STANDARD_HANDLE (Graphic3d_Buffer, NCollection_Buffer)
+IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_Buffer, NCollection_Buffer)
+
+IMPLEMENT_STANDARD_HANDLE (Graphic3d_BoundBuffer, NCollection_Buffer)
+IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_BoundBuffer, NCollection_Buffer)
+
+IMPLEMENT_STANDARD_HANDLE (Graphic3d_IndexBuffer, Graphic3d_Buffer)
+IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_IndexBuffer, Graphic3d_Buffer)
+
 Graphic3d_ArrayOfPrimitives::Graphic3d_ArrayOfPrimitives (const Graphic3d_TypeOfPrimitiveArray theType,
                                                           const Standard_Integer               theMaxVertexs,
                                                           const Standard_Integer               theMaxBounds,
index 7c93703..4c92734 100644 (file)
@@ -63,8 +63,12 @@ public:
   Standard_Integer* Bounds;   //!< pointer to bounds array
   Standard_Integer  NbBounds; //!< number of bounds
 
+public:
+
+  DEFINE_STANDARD_RTTI(Graphic3d_BoundBuffer) // Type definition
+
 };
 
-typedef NCollection_Handle<Graphic3d_BoundBuffer> Handle(Graphic3d_BoundBuffer);
+DEFINE_STANDARD_HANDLE(Graphic3d_BoundBuffer, NCollection_Buffer)
 
 #endif // _Graphic3d_BoundBuffer_HeaderFile
index d16efe6..de4f1ae 100644 (file)
@@ -201,8 +201,12 @@ public:
   Standard_Integer NbElements;   //!< number of the elements
   Standard_Integer NbAttributes; //!< number of vertex attributes
 
+public:
+
+  DEFINE_STANDARD_RTTI(Graphic3d_Buffer) // Type definition
+
 };
 
-typedef NCollection_Handle<Graphic3d_Buffer> Handle(Graphic3d_Buffer);
+DEFINE_STANDARD_HANDLE(Graphic3d_Buffer, NCollection_Buffer)
 
 #endif // _Graphic3d_Buffer_HeaderFile
index ec69dfc..a8d5dd3 100644 (file)
@@ -70,8 +70,12 @@ public:
     }
   }
 
+public:
+
+  DEFINE_STANDARD_RTTI(Graphic3d_IndexBuffer) // Type definition
+
 };
 
-typedef NCollection_Handle<Graphic3d_IndexBuffer> Handle(Graphic3d_IndexBuffer);
+DEFINE_STANDARD_HANDLE(Graphic3d_IndexBuffer, Graphic3d_Buffer)
 
 #endif // _Graphic3d_IndexBuffer_HeaderFile
index e0558e8..61cac86 100644 (file)
@@ -21,6 +21,9 @@
 IMPLEMENT_STANDARD_HANDLE (Image_PixMap, Standard_Transient)
 IMPLEMENT_STANDARD_RTTIEXT(Image_PixMap, Standard_Transient)
 
+IMPLEMENT_STANDARD_HANDLE (Image_PixMapData, NCollection_Buffer)
+IMPLEMENT_STANDARD_RTTIEXT(Image_PixMapData, NCollection_Buffer)
+
 // =======================================================================
 // function : Image_PixMap
 // purpose  :
index 155ee61..2f46f7d 100644 (file)
@@ -124,8 +124,13 @@ public:
   Standard_Size  SizeRowBytes; //!< number of bytes per line (in most cases equal to 3 * sizeX)
   Standard_Size  TopToDown;    //!< image scanlines direction in memory from Top to the Down
 
+
+public:
+
+  DEFINE_STANDARD_RTTI(Image_PixMapData) // Type definition
+
 };
 
-typedef NCollection_Handle<Image_PixMapData> Handle(Image_PixMapData);
+DEFINE_STANDARD_HANDLE(Image_PixMapData, NCollection_Buffer)
 
 #endif // _Image_PixMapData_H__
index 5a9680e..7b4831d 100644 (file)
 // commercial license or contractual agreement.
 
 #include <NCollection_AlignedAllocator.hxx>
+#include <NCollection_Buffer.hxx>
 
 IMPLEMENT_STANDARD_HANDLE  (NCollection_AlignedAllocator, NCollection_BaseAllocator)
 IMPLEMENT_STANDARD_RTTIEXT (NCollection_AlignedAllocator, NCollection_BaseAllocator)
 
+IMPLEMENT_STANDARD_HANDLE  (NCollection_Buffer, Standard_Transient)
+IMPLEMENT_STANDARD_RTTIEXT (NCollection_Buffer, Standard_Transient)
+
 //=======================================================================
 //function : NCollection_AlignedAllocator()
 //purpose  : Constructor
index 61d2cea..2210127 100644 (file)
 #define _NCollection_Buffer_HeaderFile
 
 #include <NCollection_BaseAllocator.hxx>
-#include <NCollection_Handle.hxx>
+#include <Standard_Transient.hxx>
 
 //! Low-level buffer object.
-class NCollection_Buffer
+class NCollection_Buffer : public Standard_Transient
 {
 
 public:
@@ -128,8 +128,12 @@ protected:
   Standard_Size                     mySize;      //!< buffer length in bytes
   Handle(NCollection_BaseAllocator) myAllocator; //!< buffer allocator
 
+public:
+
+  DEFINE_STANDARD_RTTI(NCollection_Buffer) // Type definition
+
 };
 
-typedef NCollection_Handle<NCollection_Buffer> Handle(NCollection_Buffer);
+DEFINE_STANDARD_HANDLE(NCollection_Buffer, Standard_Transient)
 
 #endif // _NCollection_Buffer_HeaderFile
index bf9ffb2..d8ab579 100755 (executable)
@@ -117,8 +117,11 @@ OpenGl_TextureBufferArb.hxx
 OpenGl_TextureBufferArb.cxx
 OpenGl_Vec.hxx
 OpenGl_VertexBuffer.hxx
+OpenGl_VertexBuffer.lxx
 OpenGl_VertexBuffer.cxx
 OpenGl_VertexBufferEditor.hxx
+OpenGl_VertexBufferCompat.hxx
+OpenGl_VertexBufferCompat.cxx
 OpenGl_RenderFilter.hxx
 OpenGl_RenderFilter.cxx
 OpenGl_CappingAlgo.hxx
index c35f712..000304b 100644 (file)
@@ -110,9 +110,9 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps)
   myMaxClipPlanes (6),
   myGlVerMajor (0),
   myGlVerMinor (0),
-  myRenderMode (GL_RENDER),
   myIsInitialized (Standard_False),
   myIsStereoBuffers (Standard_False),
+  myRenderMode (GL_RENDER),
   myDrawBuffer (0)
 {
 #if defined(MAC_OS_X_VERSION_10_3) && !defined(MACOSX_USE_GLX)
@@ -1976,3 +1976,24 @@ void OpenGl_Context::ReleaseDelayed()
     myDelayed->UnBind (aDeadList.Value (anIter));
   }
 }
+
+// =======================================================================
+// function : BindProgram
+// purpose  :
+// =======================================================================
+void OpenGl_Context::BindProgram (const Handle(OpenGl_ShaderProgram)& theProgram)
+{
+  if (theProgram.IsNull()
+  || !theProgram->IsValid())
+  {
+    if (!myActiveProgram.IsNull())
+    {
+      core20fwd->glUseProgram (OpenGl_ShaderProgram::NO_PROGRAM);
+      myActiveProgram.Nullify();
+    }
+    return;
+  }
+
+  myActiveProgram = theProgram;
+  core20fwd->glUseProgram (theProgram->ProgramId());
+}
index 0adac0b..5d8e292 100644 (file)
@@ -22,6 +22,7 @@
 #include <Aspect_RenderingContext.hxx>
 #include <Handle_OpenGl_Context.hxx>
 #include <Handle_OpenGl_ShaderManager.hxx>
+#include <Handle_OpenGl_ShaderProgram.hxx>
 #include <NCollection_DataMap.hxx>
 #include <NCollection_Map.hxx>
 #include <NCollection_Handle.hxx>
@@ -352,6 +353,13 @@ public:
   //! @return value for GL_MAX_CLIP_PLANES
   Standard_EXPORT Standard_Integer MaxClipPlanes() const;
 
+  //! Returns true if VBO is supported and permitted.
+  inline bool ToUseVbo() const
+  {
+    return core15fwd != NULL
+       && !caps->vboDisable;
+  }
+
 public:
 
   //! @return messenger instance
@@ -381,6 +389,8 @@ public:
     return myIsStereoBuffers;
   }
 
+public: //! @name methods to alter or retrieve current state
+
   //! Switch to left stereographic rendering buffer.
   //! This method can be used to keep unchanged choise
   //! of front/back/both buffer rendering.
@@ -402,6 +412,16 @@ public:
   //! OpenGl state variables has a possibility of being out-of-date.
   Standard_EXPORT void FetchState();
 
+  //! @return active GLSL program
+  const Handle(OpenGl_ShaderProgram)& ActiveProgram() const
+  {
+    return myActiveProgram;
+  }
+
+  //! Bind specified program to current context,
+  //! or unbind previous one when NULL specified.
+  Standard_EXPORT void BindProgram (const Handle(OpenGl_ShaderProgram)& theProgram);
+
 private:
 
   //! Wrapper to system function to retrieve GL function pointer by name.
@@ -490,13 +510,17 @@ private: // context info
   Standard_Integer myMaxClipPlanes;   //!< value for GL_MAX_CLIP_PLANES
   Standard_Integer myGlVerMajor;      //!< cached GL version major number
   Standard_Integer myGlVerMinor;      //!< cached GL version minor number
-  Standard_Integer myRenderMode;      //!< value for active rendering mode
   Standard_Boolean myIsInitialized;   //!< flag indicates initialization state
   Standard_Boolean myIsStereoBuffers; //!< context supports stereo buffering
-  Standard_Integer myDrawBuffer;      //!< current draw buffer.
 
   Handle(OpenGl_ShaderManager) myShaderManager; //! support object for managing shader programs
 
+private: //! @name fields tracking current state
+
+  Handle(OpenGl_ShaderProgram) myActiveProgram; //!< currently active GLSL program
+  Standard_Integer             myRenderMode;    //!< value for active rendering mode
+  Standard_Integer             myDrawBuffer;    //!< current draw buffer
+
 private:
 
   //! Copying allowed only within Handles
index 0507138..766acf7 100755 (executable)
 #include <OpenGl_ShaderManager.hxx>
 #include <OpenGl_ShaderProgram.hxx>
 #include <OpenGl_Structure.hxx>
+#include <OpenGl_VertexBufferCompat.hxx>
 #include <OpenGl_Workspace.hxx>
 
 namespace
 {
   template<class T>
-  void BindProgramWithMaterial (const Handle(OpenGl_Workspace)& theWS,
-                                const T*                      theAspect)
+  const Handle(OpenGl_ShaderProgram)& bindProgram (const Handle(OpenGl_Workspace)& theWS,
+                                                   const T*                        theAspect)
   {
-    const Handle(OpenGl_Context)& aCtx = theWS->GetGlContext();
+    const Handle(OpenGl_Context)&       aCtx     = theWS->GetGlContext();
     const Handle(OpenGl_ShaderProgram)& aProgram = theAspect->ShaderProgramRes (theWS);
+    aCtx->BindProgram (aProgram);
     if (aProgram.IsNull())
     {
-      OpenGl_ShaderProgram::Unbind (aCtx);
-      return;
+      return aCtx->ActiveProgram();
     }
-    aProgram->BindWithVariables (aCtx);
+
+    aProgram->ApplyVariables (aCtx);
 
     const OpenGl_MaterialState* aMaterialState = aCtx->ShaderManager()->MaterialState (aProgram);
     if (aMaterialState == NULL || aMaterialState->Aspect() != theAspect)
@@ -46,6 +48,28 @@ namespace
     }
 
     aCtx->ShaderManager()->PushState (aProgram);
+    return aProgram;
+  }
+
+  inline const Handle(OpenGl_ShaderProgram)& bindProgram (const Handle(OpenGl_Workspace)& theWorkspace,
+                                                          const OpenGl_AspectFace*        theAspectFace,
+                                                          const OpenGl_AspectLine*        theAspectLine,
+                                                          const OpenGl_AspectMarker*      theAspectMarker,
+                                                          const GLint                     theDrawMode)
+  {
+    if (!theWorkspace->GetGlContext()->IsGlGreaterEqual (2, 0))
+    {
+      return theWorkspace->GetGlContext()->ActiveProgram();
+    }
+    switch (theDrawMode)
+    {
+      case GL_POINTS:
+        return bindProgram (theWorkspace, theAspectMarker);
+      case GL_LINES:
+      case GL_LINE_STRIP:
+        return bindProgram (theWorkspace, theAspectLine);
+    }
+    return bindProgram (theWorkspace, theAspectFace);
   }
 
   //! Convert index data type from size
@@ -91,8 +115,8 @@ namespace
 }
 
 //! Auxiliary template for VBO with interleaved attributes.
-template<int NbAttributes>
-class OpenGl_VertexBufferT : public OpenGl_VertexBuffer
+template<class TheBaseClass, int NbAttributes>
+class OpenGl_VertexBufferT : public TheBaseClass
 {
 
 public:
@@ -125,16 +149,29 @@ public:
     return false;
   }
 
-  virtual void BindFixedPosition (const Handle(OpenGl_Context)& theGlCtx) const
+  virtual bool HasNormalAttribute() const
+  {
+    for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
+    {
+      const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
+      if (anAttrib.Id == Graphic3d_TOA_NORM)
+      {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  virtual void BindPositionAttribute (const Handle(OpenGl_Context)& theGlCtx) const
   {
-    if (!IsValid())
+    if (!TheBaseClass::IsValid())
     {
       return;
     }
 
-    Bind (theGlCtx);
+    TheBaseClass::Bind (theGlCtx);
     GLint aNbComp;
-    const GLubyte* anOffset = NULL;
+    const GLubyte* anOffset = TheBaseClass::myOffset;
     for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
     {
       const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
@@ -145,7 +182,7 @@ public:
       }
       else if (anAttrib.Id == Graphic3d_TOA_POS)
       {
-        bindFixed (theGlCtx, Graphic3d_TOA_POS, aNbComp, aDataType, Stride, anOffset);
+        TheBaseClass::bindAttribute (theGlCtx, Graphic3d_TOA_POS, aNbComp, aDataType, Stride, anOffset);
         break;
       }
 
@@ -153,16 +190,16 @@ public:
     }
   }
 
-  virtual void BindFixed (const Handle(OpenGl_Context)& theGlCtx) const
+  virtual void BindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const
   {
-    if (!IsValid())
+    if (!TheBaseClass::IsValid())
     {
       return;
     }
 
-    Bind (theGlCtx);
+    TheBaseClass::Bind (theGlCtx);
     GLint aNbComp;
-    const GLubyte* anOffset = NULL;
+    const GLubyte* anOffset = TheBaseClass::myOffset;
     for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
     {
       const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
@@ -172,23 +209,23 @@ public:
         continue;
       }
 
-      bindFixed (theGlCtx, anAttrib.Id, aNbComp, aDataType, Stride, anOffset);
+      TheBaseClass::bindAttribute (theGlCtx, anAttrib.Id, aNbComp, aDataType, Stride, anOffset);
       anOffset += Graphic3d_Attribute::Stride (anAttrib.DataType);
     }
   }
 
-  virtual void UnbindFixed (const Handle(OpenGl_Context)& theGlCtx) const
+  virtual void UnbindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const
   {
-    if (!IsValid())
+    if (!TheBaseClass::IsValid())
     {
       return;
     }
-    Unbind (theGlCtx);
+    TheBaseClass::Unbind (theGlCtx);
 
     for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
     {
       const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
-      unbindFixed (theGlCtx, anAttrib.Id);
+      TheBaseClass::unbindAttribute (theGlCtx, anAttrib.Id);
     }
   }
 
@@ -218,398 +255,315 @@ void OpenGl_PrimitiveArray::clearMemoryGL (const Handle(OpenGl_Context)& theGlCt
 }
 
 // =======================================================================
-// function : BuildVBO
+// function : initNormalVbo
 // purpose  :
 // =======================================================================
-Standard_Boolean OpenGl_PrimitiveArray::BuildVBO (const Handle(OpenGl_Workspace)& theWorkspace) const
+Standard_Boolean OpenGl_PrimitiveArray::initNormalVbo (const Handle(OpenGl_Context)& theCtx) const
 {
-  const Handle(OpenGl_Context)& aGlCtx = theWorkspace->GetGlContext();
-  if (myAttribs.IsNull()
-   || myAttribs->IsEmpty()
-   || myAttribs->NbElements < 1)
+  switch (myAttribs->NbAttributes)
   {
-    // vertices should be always defined - others are optional
+    case 1:  myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 1> (*myAttribs); break;
+    case 2:  myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 2> (*myAttribs); break;
+    case 3:  myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 3> (*myAttribs); break;
+    case 4:  myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 4> (*myAttribs); break;
+    case 5:  myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 5> (*myAttribs); break;
+    case 6:  myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 6> (*myAttribs); break;
+    case 7:  myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 7> (*myAttribs); break;
+    case 8:  myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 8> (*myAttribs); break;
+    case 9:  myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 9> (*myAttribs); break;
+    case 10: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 10>(*myAttribs); break;
+  }
+
+  if (!myVboAttribs->init (theCtx, 0, myAttribs->NbElements, myAttribs->Data(), GL_NONE, myAttribs->Stride))
+  {
+    TCollection_ExtendedString aMsg;
+    aMsg += "VBO creation for Primitive Array has failed for ";
+    aMsg += myAttribs->NbElements;
+    aMsg += " vertices. Out of memory?";
+    theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_PERFORMANCE_ARB, 0, GL_DEBUG_SEVERITY_LOW_ARB, aMsg);
+
+    clearMemoryGL (theCtx);
     return Standard_False;
   }
+  else if (myIndices.IsNull())
+  {
+    return Standard_True;
+  }
 
-  switch (myAttribs->NbAttributes)
+  myVboIndices = new OpenGl_IndexBuffer();
+  bool isOk = false;
+  switch (myIndices->Stride)
+  {
+    case 2:
+    {
+      isOk = myVboIndices->Init (theCtx, 1, myIndices->NbElements, reinterpret_cast<const GLushort*> (myIndices->Data()));
+      break;
+    }
+    case 4:
+    {
+      isOk = myVboIndices->Init (theCtx, 1, myIndices->NbElements, reinterpret_cast<const GLuint*> (myIndices->Data()));
+      break;
+    }
+    default:
+    {
+      clearMemoryGL (theCtx);
+      return Standard_False;
+    }
+  }
+  if (!isOk)
   {
-    case 1:  myVboAttribs = new OpenGl_VertexBufferT<1> (*myAttribs); break;
-    case 2:  myVboAttribs = new OpenGl_VertexBufferT<2> (*myAttribs); break;
-    case 3:  myVboAttribs = new OpenGl_VertexBufferT<3> (*myAttribs); break;
-    case 4:  myVboAttribs = new OpenGl_VertexBufferT<4> (*myAttribs); break;
-    case 5:  myVboAttribs = new OpenGl_VertexBufferT<5> (*myAttribs); break;
-    case 6:  myVboAttribs = new OpenGl_VertexBufferT<6> (*myAttribs); break;
-    case 7:  myVboAttribs = new OpenGl_VertexBufferT<7> (*myAttribs); break;
-    case 8:  myVboAttribs = new OpenGl_VertexBufferT<8> (*myAttribs); break;
-    case 9:  myVboAttribs = new OpenGl_VertexBufferT<9> (*myAttribs); break;
-    case 10: myVboAttribs = new OpenGl_VertexBufferT<10>(*myAttribs); break;
-    default: return Standard_False;
+    TCollection_ExtendedString aMsg;
+    aMsg += "VBO creation for Primitive Array has failed for ";
+    aMsg += myIndices->NbElements;
+    aMsg += " indices. Out of memory?";
+    theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_PERFORMANCE_ARB, 0, GL_DEBUG_SEVERITY_LOW_ARB, aMsg);
+    clearMemoryGL (theCtx);
+    return Standard_False;
   }
+  return Standard_True;
+}
 
-  if (!myVboAttribs->init (aGlCtx, 0, myAttribs->NbElements, myAttribs->Data(), GL_NONE, myAttribs->Stride))
+// =======================================================================
+// function : buildVBO
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_PrimitiveArray::buildVBO (const Handle(OpenGl_Context)& theCtx,
+                                                  const Standard_Boolean        theToKeepData) const
+{
+  bool isNormalMode = theCtx->ToUseVbo();
+  if (myAttribs.IsNull()
+   || myAttribs->IsEmpty()
+   || myAttribs->NbElements < 1
+   || myAttribs->NbAttributes < 1
+   || myAttribs->NbAttributes > 10)
   {
-    clearMemoryGL (aGlCtx);
+    // vertices should be always defined - others are optional
     return Standard_False;
   }
 
+  if (isNormalMode
+   && initNormalVbo (theCtx))
+  {
+    if (!theCtx->caps->keepArrayData
+     && !theToKeepData)
+    {
+      myIndices.Nullify();
+      myAttribs.Nullify();
+    }
+    return Standard_True;
+  }
+
+  Handle(OpenGl_VertexBufferCompat) aVboAttribs;
+  switch (myAttribs->NbAttributes)
+  {
+    case 1:  aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 1> (*myAttribs); break;
+    case 2:  aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 2> (*myAttribs); break;
+    case 3:  aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 3> (*myAttribs); break;
+    case 4:  aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 4> (*myAttribs); break;
+    case 5:  aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 5> (*myAttribs); break;
+    case 6:  aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 6> (*myAttribs); break;
+    case 7:  aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 7> (*myAttribs); break;
+    case 8:  aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 8> (*myAttribs); break;
+    case 9:  aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 9> (*myAttribs); break;
+    case 10: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 10>(*myAttribs); break;
+  }
+  aVboAttribs->initLink (myAttribs, 0, myAttribs->NbElements, GL_NONE);
   if (!myIndices.IsNull())
   {
-    myVboIndices = new OpenGl_IndexBuffer();
-    bool isOk = Standard_False;
+    Handle(OpenGl_VertexBufferCompat) aVboIndices = new OpenGl_VertexBufferCompat();
     switch (myIndices->Stride)
     {
       case 2:
       {
-        isOk = myVboIndices->Init (aGlCtx, 1, myIndices->NbElements, reinterpret_cast<const GLushort*> (myIndices->Data()));
+        aVboIndices->initLink (myIndices, 1, myIndices->NbElements, GL_UNSIGNED_SHORT);
         break;
       }
       case 4:
       {
-        isOk = myVboIndices->Init (aGlCtx, 1, myIndices->NbElements, reinterpret_cast<const GLuint*> (myIndices->Data()));
+        aVboIndices->initLink (myIndices, 1, myIndices->NbElements, GL_UNSIGNED_INT);
         break;
       }
-      default: break;
-    }
-    if (!isOk)
-    {
-      clearMemoryGL (aGlCtx);
-      return Standard_False;
+      default:
+      {
+        return Standard_False;
+      }
     }
+    myVboIndices = aVboIndices;
   }
-
-  if (!aGlCtx->caps->keepArrayData)
+  myVboAttribs = aVboAttribs;
+  if (!theCtx->caps->keepArrayData
+   && !theToKeepData)
   {
-    myIndices.Nullify();
-    myAttribs.Nullify();
+    // does not make sense for compatibility mode
+    //myIndices.Nullify();
+    //myAttribs.Nullify();
   }
-  
+
   return Standard_True;
 }
 
 // =======================================================================
-// function : DrawArray
+// function : drawArray
 // purpose  :
 // =======================================================================
-void OpenGl_PrimitiveArray::DrawArray (Tint theLightingModel,
-                                       const Aspect_InteriorStyle theInteriorStyle,
-                                       Tint theEdgeFlag,
-                                       const TEL_COLOUR* theInteriorColour,
-                                       const TEL_COLOUR* theLineColour,
-                                       const TEL_COLOUR* theEdgeColour,
-                                       const Handle(OpenGl_Workspace)& theWorkspace) const
+void OpenGl_PrimitiveArray::drawArray (const Handle(OpenGl_Workspace)& theWorkspace,
+                                       const Graphic3d_Vec4*           theFaceColors) const
 {
   const Handle(OpenGl_Context)& aGlContext  = theWorkspace->GetGlContext();
-  const Graphic3d_Vec4*         aFaceColors = myBounds.IsNull() ? NULL : myBounds->Colors;
   const bool                    toHilight   = (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) != 0;
   bool                          hasVColors  = false;
-
-  glColor3fv (myDrawMode <= GL_LINE_STRIP ? theLineColour->rgb : theInteriorColour->rgb);
-
-  // Temporarily disable environment mapping
-  if (myDrawMode <= GL_LINE_STRIP)
+  if (myVboAttribs.IsNull())
   {
-    glPushAttrib (GL_ENABLE_BIT);
-    glDisable (GL_TEXTURE_1D);
-    glDisable (GL_TEXTURE_2D);
+    if (myDrawMode == GL_POINTS)
+    {
+      // extreme compatibility mode - without sprites but with markers
+      drawMarkers (theWorkspace);
+    }
+    return;
   }
 
-  if ((myDrawMode >  GL_LINE_STRIP && theInteriorStyle != Aspect_IS_EMPTY) ||
-      (myDrawMode <= GL_LINE_STRIP))
+  myVboAttribs->BindAllAttributes (aGlContext);
+  if (myVboAttribs->HasColorAttribute())
   {
     if (toHilight)
     {
-      aFaceColors = NULL;
+      // disable per-vertex colors
+      OpenGl_VertexBuffer::unbindAttribute (aGlContext, Graphic3d_TOA_COLOR);
     }
-
-    if (theInteriorStyle == Aspect_IS_HIDDENLINE)
+    else
     {
-      theEdgeFlag = 1;
-      aFaceColors = NULL;
+      hasVColors = true;
     }
-
-    // Sometimes the GL_LIGHTING mode is activated here
-    // without glEnable(GL_LIGHTING) call for an unknown reason, so it is necessary
-    // to call glEnable(GL_LIGHTING) to synchronize Light On/Off mechanism*
-    if (theLightingModel == 0 || myDrawMode <= GL_LINE_STRIP)
-      glDisable (GL_LIGHTING);
-    else
-      glEnable (GL_LIGHTING);
-
-    if (!myVboAttribs.IsNull())
+  }
+  if (!myVboIndices.IsNull())
+  {
+    myVboIndices->Bind (aGlContext);
+    GLubyte* anOffset = myVboIndices->GetDataOffset();
+    if (!myBounds.IsNull())
     {
-      myVboAttribs->BindFixed (aGlContext);
-      if (myVboAttribs->HasColorAttribute())
-      {
-        if (toHilight)
-        {
-          // disable per-vertex colors
-          OpenGl_VertexBuffer::unbindFixed (aGlContext, Graphic3d_TOA_COLOR);
-        }
-        else
-        {
-          hasVColors = true;
-        }
-      }
-      if (!myVboIndices.IsNull())
-      {
-        myVboIndices->Bind (aGlContext);
-        if (!myBounds.IsNull())
-        {
-          // draw primitives by vertex count with the indices
-          const size_t aStride  = myVboIndices->GetDataType() == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
-          GLubyte*     anOffset = NULL;
-          for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
-          {
-            const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
-            if (aFaceColors != NULL) glColor3fv (aFaceColors[aGroupIter].GetData());
-            glDrawElements (myDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset);
-            anOffset += aStride * aNbElemsInGroup;
-          }
-        }
-        else
-        {
-          // draw one (or sequential) primitive by the indices
-          glDrawElements (myDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), NULL);
-        }
-        myVboIndices->Unbind (aGlContext);
-      }
-      else if (!myBounds.IsNull())
-      {
-        GLint aFirstElem = 0;
-        for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
-        {
-          const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
-          if (aFaceColors != NULL) glColor3fv (aFaceColors[aGroupIter].GetData());
-          glDrawArrays (myDrawMode, aFirstElem, aNbElemsInGroup);
-          aFirstElem += aNbElemsInGroup;
-        }
-      }
-      else
+      // draw primitives by vertex count with the indices
+      const size_t aStride = myVboIndices->GetDataType() == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
+      for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
       {
-        if (myDrawMode == GL_POINTS)
-        {
-          DrawMarkers (theWorkspace);
-        }
-        else
-        {
-          glDrawArrays (myDrawMode, 0, myVboAttribs->GetElemsNb());
-        }
+        const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
+        if (theFaceColors != NULL) glColor3fv (theFaceColors[aGroupIter].GetData());
+        glDrawElements (myDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset);
+        anOffset += aStride * aNbElemsInGroup;
       }
-
-      // bind with 0
-      myVboAttribs->UnbindFixed (aGlContext);
     }
     else
     {
-      GLint aNbComp;
-      for (Standard_Integer anAttribIter = 0; anAttribIter < myAttribs->NbAttributes; ++anAttribIter)
-      {
-        const Graphic3d_Attribute& anAttrib = myAttribs->Attribute (anAttribIter);
-        if (anAttrib.Id == Graphic3d_TOA_COLOR)
-        {
-          if (toHilight)
-          {
-            continue;
-          }
-          hasVColors = true;
-        }
-        const GLenum  aDataType = toGlDataType (anAttrib.DataType, aNbComp);
-        const GLvoid* aData     = myAttribs->Data (anAttribIter);
-        if (aDataType == GL_NONE)
-        {
-          continue;
-        }
-
-        OpenGl_VertexBuffer::bindFixed (aGlContext, anAttrib.Id, aNbComp, aDataType, myAttribs->Stride, aData);
-      }
-
-      if (!myBounds.IsNull())
-      {
-        GLint aFirstElem = 0;
-        if (!myIndices.IsNull())
-        {
-          const GLenum anIndexType = toGlIndexType (myIndices->Stride);
-          for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
-          {
-            const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
-            if (aFaceColors != NULL) glColor3fv (aFaceColors[aGroupIter].GetData());
-            glDrawElements (myDrawMode, aNbElemsInGroup, anIndexType, myIndices->value (aFirstElem));
-            aFirstElem += aNbElemsInGroup;
-          }
-        }
-        else
-        {
-          for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
-          {
-            const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
-            if (aFaceColors != NULL) glColor3fv (aFaceColors[aGroupIter].GetData());
-            glDrawArrays (myDrawMode, aFirstElem, aNbElemsInGroup);
-            aFirstElem += aNbElemsInGroup;
-          }
-        }
-      }
-      else if (!myIndices.IsNull())
-      {
-        glDrawElements (myDrawMode, myIndices->NbElements, toGlIndexType (myIndices->Stride), myIndices->Data());
-      }
-      else
-      {
-        if (myDrawMode == GL_POINTS)
-        {
-          DrawMarkers (theWorkspace);
-        }
-        else
-        {
-          glDrawArrays (myDrawMode, 0, myAttribs->NbElements);
-        }
-      }
-
-      for (Standard_Integer anAttribIter = 0; anAttribIter < myAttribs->NbAttributes; ++anAttribIter)
-      {
-        const Graphic3d_Attribute& anAttrib = myAttribs->Attribute (anAttribIter);
-        OpenGl_VertexBuffer::unbindFixed (aGlContext, anAttrib.Id);
-      }
+      // draw one (or sequential) primitive by the indices
+      glDrawElements (myDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), anOffset);
     }
+    myVboIndices->Unbind (aGlContext);
   }
-
-  if (hasVColors)
+  else if (!myBounds.IsNull())
   {
-    theWorkspace->NamedStatus |= OPENGL_NS_RESMAT;
+    GLint aFirstElem = 0;
+    for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
+    {
+      const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
+      if (theFaceColors != NULL) glColor3fv (theFaceColors[aGroupIter].GetData());
+      glDrawArrays (myDrawMode, aFirstElem, aNbElemsInGroup);
+      aFirstElem += aNbElemsInGroup;
+    }
   }
-
-  if (theEdgeFlag && myDrawMode > GL_LINE_STRIP)
+  else
   {
-    DrawEdges (theEdgeColour, theWorkspace);
+    if (myDrawMode == GL_POINTS)
+    {
+      drawMarkers (theWorkspace);
+    }
+    else
+    {
+      glDrawArrays (myDrawMode, 0, myVboAttribs->GetElemsNb());
+    }
   }
 
-  if (myDrawMode <= GL_LINE_STRIP)
-    glPopAttrib();
+  // bind with 0
+  myVboAttribs->UnbindAllAttributes (aGlContext);
+
+  if (hasVColors)
+  {
+    theWorkspace->NamedStatus |= OPENGL_NS_RESMAT;
+  }
 }
 
 // =======================================================================
-// function : DrawEdges
+// function : drawEdges
 // purpose  :
 // =======================================================================
-void OpenGl_PrimitiveArray::DrawEdges (const TEL_COLOUR*               theEdgeColour,
+void OpenGl_PrimitiveArray::drawEdges (const TEL_COLOUR*               theEdgeColour,
                                        const Handle(OpenGl_Workspace)& theWorkspace) const
 {
+  if (myVboAttribs.IsNull())
+  {
+    return;
+  }
+
   glDisable (GL_LIGHTING);
 
   const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
   const OpenGl_AspectLine* anAspectLineOld = NULL;
-  if (myDrawMode > GL_LINE_STRIP)
-  {
-    anAspectLineOld = theWorkspace->SetAspectLine (theWorkspace->AspectFace (Standard_True)->AspectEdge());
-    const OpenGl_AspectLine* anAspect = theWorkspace->AspectLine (Standard_True);
 
-    glPushAttrib (GL_POLYGON_BIT);
-    glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
+  anAspectLineOld = theWorkspace->SetAspectLine (theWorkspace->AspectFace (Standard_True)->AspectEdge());
+  const OpenGl_AspectLine* anAspect = theWorkspace->AspectLine (Standard_True);
 
-    if (aGlContext->IsGlGreaterEqual (2, 0))
-    {
-      BindProgramWithMaterial (theWorkspace, anAspect);
-    }
+  glPushAttrib (GL_POLYGON_BIT);
+  glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
+
+  if (aGlContext->IsGlGreaterEqual (2, 0))
+  {
+    bindProgram (theWorkspace, anAspect);
   }
 
   /// OCC22236 NOTE: draw edges for all situations:
   /// 1) draw elements with GL_LINE style as edges from myPArray->bufferVBO[VBOEdges] indices array
   /// 2) draw elements from vertex array, when bounds defines count of primitive's vertices.
   /// 3) draw primitive's edges by vertexes if no edges and bounds array is specified
-  if (!myVboAttribs.IsNull())
+  myVboAttribs->BindPositionAttribute (aGlContext);
+  glColor3fv (theEdgeColour->rgb);
+  if (!myVboIndices.IsNull())
   {
-    myVboAttribs->BindFixedPosition (aGlContext);
-    glColor3fv (theEdgeColour->rgb);
-    if (!myVboIndices.IsNull())
-    {
-      myVboIndices->Bind (aGlContext);
+    myVboIndices->Bind (aGlContext);
+    GLubyte* anOffset = myVboIndices->GetDataOffset();
 
-      // draw primitives by vertex count with the indices
-      if (!myBounds.IsNull())
-      {
-        const size_t aStride  = myVboIndices->GetDataType() == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
-        GLubyte*     anOffset = NULL;
-        for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
-        {
-          const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
-          glDrawElements (myDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset);
-          anOffset += aStride * aNbElemsInGroup;
-        }
-      }
-      // draw one (or sequential) primitive by the indices
-      else
-      {
-        glDrawElements (myDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), NULL);
-      }
-      myVboIndices->Unbind (aGlContext);
-    }
-    else if (!myBounds.IsNull())
+    // draw primitives by vertex count with the indices
+    if (!myBounds.IsNull())
     {
-      GLint aFirstElem = 0;
+      const size_t aStride = myVboIndices->GetDataType() == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
       for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
       {
         const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
-        glDrawArrays (myDrawMode, aFirstElem, aNbElemsInGroup);
-        aFirstElem += aNbElemsInGroup;
+        glDrawElements (myDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset);
+        anOffset += aStride * aNbElemsInGroup;
       }
     }
+    // draw one (or sequential) primitive by the indices
     else
     {
-      glDrawArrays (myDrawMode, 0, myAttribs->NbElements);
+      glDrawElements (myDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), anOffset);
     }
-
-    // unbind buffers
-    myVboAttribs->UnbindFixed (aGlContext, GL_VERTEX_ARRAY);
+    myVboIndices->Unbind (aGlContext);
   }
-  else
+  else if (!myBounds.IsNull())
   {
-    GLint aNbComp;
-    for (Standard_Integer anAttribIter = 0; anAttribIter < myAttribs->NbAttributes; ++anAttribIter)
-    {
-      const Graphic3d_Attribute& anAttrib = myAttribs->Attribute (anAttribIter);
-      if (anAttrib.Id == Graphic3d_TOA_POS)
-      {
-        const GLenum  aDataType = toGlDataType (anAttrib.DataType, aNbComp);
-        const GLvoid* aData     = myAttribs->Data (anAttribIter);
-        OpenGl_VertexBuffer::bindFixed (aGlContext, anAttrib.Id, aNbComp, aDataType, myAttribs->Stride, aData);
-        break;
-      }
-    }
-
-    glColor3fv (theEdgeColour->rgb);
-    if (!myBounds.IsNull())
-    {
-      if (!myIndices.IsNull())
-      {
-        const GLenum anIndexType = toGlIndexType (myIndices->Stride);
-        GLint aFirstElem = 0;
-        for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
-        {
-          const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
-          glDrawElements (myDrawMode, aNbElemsInGroup, anIndexType, myIndices->value (aFirstElem));
-          aFirstElem += aNbElemsInGroup;
-        }
-      }
-      else
-      {
-        GLint aFirstElem = 0;
-        for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
-        {
-          const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
-          glDrawArrays (myDrawMode, aFirstElem, aNbElemsInGroup);
-          aFirstElem += aNbElemsInGroup;
-        }
-      }
-    }
-    else if (!myIndices.IsNull())
-    {
-      glDrawElements (myDrawMode, myIndices->NbElements, toGlIndexType (myIndices->Stride), myIndices->Data());
-    }
-    else
+    GLint aFirstElem = 0;
+    for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
     {
-      glDrawArrays (myDrawMode, 0, myAttribs->NbElements);
+      const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
+      glDrawArrays (myDrawMode, aFirstElem, aNbElemsInGroup);
+      aFirstElem += aNbElemsInGroup;
     }
   }
+  else
+  {
+    glDrawArrays (myDrawMode, 0, myAttribs->NbElements);
+  }
+
+  // unbind buffers
+  myVboAttribs->UnbindAttribute (aGlContext, Graphic3d_TOA_POS);
 
   if (myDrawMode > GL_LINE_STRIP)
   {
@@ -620,10 +574,10 @@ void OpenGl_PrimitiveArray::DrawEdges (const TEL_COLOUR*               theEdgeCo
 }
 
 // =======================================================================
-// function : DrawMarkers
+// function : drawMarkers
 // purpose  :
 // =======================================================================
-void OpenGl_PrimitiveArray::DrawMarkers (const Handle(OpenGl_Workspace)& theWorkspace) const
+void OpenGl_PrimitiveArray::drawMarkers (const Handle(OpenGl_Workspace)& theWorkspace) const
 {
   const OpenGl_AspectMarker* anAspectMarker     = theWorkspace->AspectMarker (Standard_True);
   const Handle(OpenGl_Context)&     aCtx        = theWorkspace->GetGlContext();
@@ -815,27 +769,16 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace
 
   // create VBOs on first render call
   const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
-  if (!myIsVboInit
-   && !aCtx->caps->vboDisable
-   && aCtx->core15 != NULL
-   && (myDrawMode != GL_POINTS || anAspectMarker->SpriteRes (theWorkspace).IsNull() || !anAspectMarker->SpriteRes (theWorkspace)->IsDisplayList()))
+  if (!myIsVboInit)
   {
-    if (!BuildVBO (theWorkspace))
-    {
-      TCollection_ExtendedString aMsg;
-      aMsg += "VBO creation for Primitive Array has failed for ";
-      aMsg += myAttribs->NbElements;
-      aMsg += " vertices. Out of memory?";
-      aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_PERFORMANCE_ARB, 0, GL_DEBUG_SEVERITY_LOW_ARB, aMsg);
-    }
+    // compatibility - keep data to draw markers using display lists
+    const Standard_Boolean toKeepData = myDrawMode == GL_POINTS
+                                    && !anAspectMarker->SpriteRes (theWorkspace).IsNull()
+                                    &&  anAspectMarker->SpriteRes (theWorkspace)->IsDisplayList();
+    buildVBO (aCtx, toKeepData);
     myIsVboInit = Standard_True;
   }
 
-  if (myDrawMode <= GL_LINE_STRIP)
-  {
-    glDisable (GL_LIGHTING);
-  }
-
   Tint aFrontLightingModel = anAspectFace->IntFront().color_mask;
   const TEL_COLOUR* anInteriorColor = &anAspectFace->IntFront().matcol;
   const TEL_COLOUR* anEdgeColor = &anAspectFace->AspectEdge()->Color();
@@ -848,34 +791,53 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace
     aFrontLightingModel = 0;
   }
 
-  if (aCtx->IsGlGreaterEqual (2, 0))
+  // Temporarily disable environment mapping
+  if (myDrawMode <= GL_LINE_STRIP)
+  {
+    glPushAttrib (GL_ENABLE_BIT);
+    glDisable (GL_TEXTURE_1D);
+    glDisable (GL_TEXTURE_2D);
+  }
+  // manage FFP lighting
+  if (aFrontLightingModel == 0
+  ||  myVboAttribs.IsNull()
+  || !myVboAttribs->HasNormalAttribute())
   {
-    switch (myDrawMode)
+    glDisable (GL_LIGHTING);
+  }
+  else
+  {
+    glEnable (GL_LIGHTING);
+  }
+
+  bindProgram (theWorkspace,
+               anAspectFace, anAspectLine, anAspectMarker,
+               myDrawMode);
+
+  if ((myDrawMode >  GL_LINE_STRIP && anAspectFace->InteriorStyle() != Aspect_IS_EMPTY) ||
+      (myDrawMode <= GL_LINE_STRIP))
+  {
+    const bool            toHilight   = (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) != 0;
+    const Graphic3d_Vec4* aFaceColors = !myBounds.IsNull() && !toHilight && anAspectFace->InteriorStyle() != Aspect_IS_HIDDENLINE
+                                      ?  myBounds->Colors
+                                      :  NULL;
+    glColor3fv (myDrawMode <= GL_LINE_STRIP ? aLineColor->rgb : anInteriorColor->rgb);
+
+    drawArray (theWorkspace, aFaceColors);
+  }
+
+  if (myDrawMode > GL_LINE_STRIP)
+  {
+    if (anAspectFace->Edge()
+     || anAspectFace->InteriorStyle() == Aspect_IS_HIDDENLINE)
     {
-      case GL_POINTS:
-      {
-        BindProgramWithMaterial (theWorkspace, anAspectMarker);
-        break;
-      }
-      case GL_LINES:
-      case GL_LINE_STRIP:
-      {
-        BindProgramWithMaterial (theWorkspace, anAspectLine);
-        break;
-      }
-      default: // polygonal array
-      {
-        BindProgramWithMaterial (theWorkspace, anAspectFace);
-        break;
-      }
+      drawEdges (anEdgeColor, theWorkspace);
     }
   }
 
-  DrawArray (aFrontLightingModel,
-             anAspectFace->InteriorStyle(),
-             anAspectFace->Edge(),
-             anInteriorColor,
-             aLineColor,
-             anEdgeColor,
-             theWorkspace);
+  if (myDrawMode <= GL_LINE_STRIP)
+  {
+    glPopAttrib();
+  }
+  aCtx->BindProgram (NULL);
 }
index 025d91d..c7d300e 100644 (file)
@@ -28,7 +28,9 @@
 #include <OpenGl_Element.hxx>
 
 class OpenGl_GraphicDriver;
+class Handle(OpenGl_ShaderProgram);
 
+//! Class for rendering of arbitrary primitive array.
 class OpenGl_PrimitiveArray : public OpenGl_Element
 {
 public:
@@ -69,24 +71,25 @@ public:
 
 private:
 
+  //! Initialize normal (OpenGL-provided) VBO
+  Standard_Boolean initNormalVbo (const Handle(OpenGl_Context)& theCtx) const;
+
   //! VBO initialization procedures
-  Standard_Boolean BuildVBO (const Handle(OpenGl_Workspace)& theWorkspace) const;
+  //! @param theCtx        bound GL context
+  //! @param theToKeepData when true, myAttribs will not be nullified after VBO creation
+  Standard_Boolean buildVBO (const Handle(OpenGl_Context)& theCtx,
+                             const Standard_Boolean        theToKeepData) const;
   void clearMemoryGL (const Handle(OpenGl_Context)& theGlCtx) const;
 
   //! Main procedure to draw array
-  void DrawArray (Tint theLightingModel,
-                  const Aspect_InteriorStyle theInteriorStyle,
-                  Tint theEdgeFlag,
-                  const TEL_COLOUR* theInteriorColour,
-                  const TEL_COLOUR* theLineColour,
-                  const TEL_COLOUR* theEdgeColour,
-                  const Handle(OpenGl_Workspace)& theWorkspace) const;
+  void drawArray (const Handle(OpenGl_Workspace)& theWorkspace,
+                  const Graphic3d_Vec4*           theFaceColors) const;
 
   //! Auxiliary procedures
-  void DrawEdges (const TEL_COLOUR*               theEdgeColour,
+  void drawEdges (const TEL_COLOUR*               theEdgeColour,
                   const Handle(OpenGl_Workspace)& theWorkspace) const;
 
-  void DrawMarkers (const Handle(OpenGl_Workspace)& theWorkspace) const;
+  void drawMarkers (const Handle(OpenGl_Workspace)& theWorkspace) const;
 
 protected:
 
@@ -95,7 +98,7 @@ protected:
 
 protected:
 
-  mutable Handle(OpenGl_IndexBuffer)    myVboIndices;
+  mutable Handle(OpenGl_VertexBuffer)   myVboIndices;
   mutable Handle(OpenGl_VertexBuffer)   myVboAttribs;
 
   mutable Handle(Graphic3d_IndexBuffer) myIndices;
index 5eb2a13..4f0e1de 100755 (executable)
@@ -34,7 +34,6 @@ IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderManager, Standard_Transient)
 // =======================================================================
 OpenGl_ShaderManager::OpenGl_ShaderManager (OpenGl_Context* theContext)
 : myContext  (theContext),
-  myIsPP     (Standard_False),
   myLastView (NULL)
 {
   //
index 4ea5d32..1da56c2 100755 (executable)
@@ -187,7 +187,6 @@ protected:
 
 private:
 
-  Standard_Boolean         myIsPP;         //!< Is any program object bound (programmable pipeline)?
   const OpenGl_View*       myLastView;     //!< Pointer to the last view shader manager used with.
 };
 
index 2068089..4931090 100755 (executable)
@@ -16,6 +16,7 @@
 #include <OSD_File.hxx>
 #include <OSD_Protection.hxx>
 
+#include <Graphic3d_Buffer.hxx>
 #include <Standard_Assert.hxx>
 #include <Standard_Atomic.hxx>
 #include <TCollection_ExtendedString.hxx>
@@ -262,6 +263,12 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&
     }
   }
 
+  // bind locations for pre-defined Vertex Attributes
+  SetAttributeName (theCtx, Graphic3d_TOA_POS,   "occVertex");
+  SetAttributeName (theCtx, Graphic3d_TOA_NORM,  "occNormal");
+  SetAttributeName (theCtx, Graphic3d_TOA_UV,    "occTexCoord");
+  SetAttributeName (theCtx, Graphic3d_TOA_COLOR, "occColor");
+
   if (!Link (theCtx))
   {
     TCollection_AsciiString aLog;
@@ -414,21 +421,6 @@ Standard_Boolean OpenGl_ShaderProgram::FetchInfoLog (const Handle(OpenGl_Context
 }
 
 // =======================================================================
-// function : Bind
-// purpose  : Sets the program object as part of current rendering state
-// =======================================================================
-void OpenGl_ShaderProgram::Bind (const Handle(OpenGl_Context)& theCtx) const
-{
-  if (myProgramID == NO_PROGRAM)
-  {
-    return;
-  }
-
-  theCtx->core20->glUseProgram (myProgramID);
-  theCtx->ShaderManager()->myIsPP = Standard_True;
-}
-
-// =======================================================================
 // function : ApplyVariables
 // purpose  : Fetches uniform variables from proxy shader program
 // =======================================================================
@@ -449,29 +441,6 @@ Standard_Boolean OpenGl_ShaderProgram::ApplyVariables(const Handle(OpenGl_Contex
 }
 
 // =======================================================================
-// function : BindWithVariables
-// purpose  : Binds the program object and applies variables
-// =======================================================================
-Standard_Boolean OpenGl_ShaderProgram::BindWithVariables (const Handle(OpenGl_Context)& theCtx)
-{
-  Bind (theCtx);
-  return ApplyVariables (theCtx);
-}
-
-// =======================================================================
-// function : Unbind
-// purpose  : Reverts to fixed-function graphics pipeline (FFP)
-// =======================================================================
-void OpenGl_ShaderProgram::Unbind (const Handle(OpenGl_Context)& theCtx)
-{
-  if (theCtx->ShaderManager()->myIsPP)
-  {
-    theCtx->core20->glUseProgram (NO_PROGRAM);
-    theCtx->ShaderManager()->myIsPP = Standard_False;
-  }
-}
-
-// =======================================================================
 // function : ActiveState
 // purpose  : Returns index of last modification for specified state type
 // =======================================================================
index e1fa54f..9b5163f 100755 (executable)
@@ -181,21 +181,18 @@ public:
   //! Fetches uniform variables from proxy shader program.
   Standard_EXPORT Standard_Boolean ApplyVariables (const Handle(OpenGl_Context)& theCtx);
 
-  //! Sets the program object as part of current rendering state.
-  Standard_EXPORT void Bind (const Handle(OpenGl_Context)& theCtx) const;
-
-  //! Binds the program object and applies variables from proxy shader program.
-  Standard_EXPORT Standard_Boolean BindWithVariables (const Handle(OpenGl_Context)& theCtx);
-
-  //! Reverts to fixed-function graphics pipeline (FFP).
-  Standard_EXPORT static void Unbind (const Handle(OpenGl_Context)& theCtx);
-
   //! @return true if current object was initialized
   inline bool IsValid() const
   {
     return myProgramID != NO_PROGRAM;
   }
 
+  //! @return program ID
+  inline GLuint ProgramId() const
+  {
+    return myProgramID;
+  }
+
 private:
 
   //! Returns index of last modification of variables of specified state type.
index 1d8da41..75e19ab 100755 (executable)
@@ -285,8 +285,6 @@ void OpenGl_Text::releaseVbos (OpenGl_Context* theCtx)
   myTextures.Clear();
   myVertsVbo.Clear();
   myTCrdsVbo.Clear();
-  myVertsArray.Clear();
-  myTCrdsArray.Clear();
 }
 
 // =======================================================================
@@ -384,11 +382,11 @@ void OpenGl_Text::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
 
   if (aCtx->IsGlGreaterEqual (2, 0))
   {
-    Handle(OpenGl_ShaderProgram) aProgram = aTextAspect->ShaderProgramRes (theWorkspace);
-
+    const Handle(OpenGl_ShaderProgram)& aProgram = aTextAspect->ShaderProgramRes (theWorkspace);
+    aCtx->BindProgram (aProgram);
     if (!aProgram.IsNull())
     {
-      aProgram->BindWithVariables (aCtx);
+      aProgram->ApplyVariables (aCtx);
 
       const OpenGl_MaterialState* aMaterialState = aCtx->ShaderManager()->MaterialState (aProgram);
 
@@ -397,10 +395,6 @@ void OpenGl_Text::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
 
       aCtx->ShaderManager()->PushState (aProgram);
     }
-    else
-    {
-      OpenGl_ShaderProgram::Unbind (aCtx);
-    }
   }
 
   // use highlight color or colors from aspect
@@ -513,45 +507,28 @@ void OpenGl_Text::drawText (const Handle(OpenGl_PrinterContext)& ,
   }
 #endif
 
-  if (myVertsVbo.Length() == myTextures.Length())
+  if (myVertsVbo.Length() != myTextures.Length()
+   || myTextures.IsEmpty())
   {
-    for (Standard_Integer anIter = 0; anIter < myTextures.Length(); ++anIter)
-    {
-      const GLuint aTexId = myTextures.Value (anIter);
-      const Handle(OpenGl_VertexBuffer)& aVerts = myVertsVbo.Value (anIter);
-      const Handle(OpenGl_VertexBuffer)& aTCrds = myTCrdsVbo.Value (anIter);
-      aVerts->BindFixed (theCtx, GL_VERTEX_ARRAY);
-      aTCrds->BindFixed (theCtx, GL_TEXTURE_COORD_ARRAY);
-      glBindTexture (GL_TEXTURE_2D, aTexId);
-
-      glDrawArrays (GL_TRIANGLES, 0, GLsizei(aVerts->GetElemsNb()));
-
-      glBindTexture (GL_TEXTURE_2D, 0);
-      aTCrds->UnbindFixed (theCtx, GL_TEXTURE_COORD_ARRAY);
-      aVerts->UnbindFixed (theCtx, GL_VERTEX_ARRAY);
-    }
+    return;
   }
-  else if (myVertsArray.Length() == myTextures.Length())
+
+  for (Standard_Integer anIter = 0; anIter < myTextures.Length(); ++anIter)
   {
-    glEnableClientState (GL_VERTEX_ARRAY);
-    glEnableClientState (GL_TEXTURE_COORD_ARRAY);
-    for (Standard_Integer anIter = 0; anIter < myTextures.Length(); ++anIter)
-    {
-      const GLuint aTexId = myTextures.Value (anIter);
-      const Handle(OpenGl_Vec2Array)& aVerts = myVertsArray.Value (anIter);
-      const Handle(OpenGl_Vec2Array)& aTCrds = myTCrdsArray.Value (anIter);
+    const GLuint aTexId = myTextures.Value (anIter);
+    glBindTexture (GL_TEXTURE_2D, aTexId);
 
-      glVertexPointer   (2, GL_FLOAT, 0, (GLfloat* )&aVerts->First());
-      glTexCoordPointer (2, GL_FLOAT, 0, (GLfloat* )&aTCrds->First());
-      glBindTexture (GL_TEXTURE_2D, aTexId);
+    const Handle(OpenGl_VertexBuffer)& aVerts = myVertsVbo.Value (anIter);
+    const Handle(OpenGl_VertexBuffer)& aTCrds = myTCrdsVbo.Value (anIter);
+    aVerts->BindAttribute (theCtx, Graphic3d_TOA_POS);
+    aTCrds->BindAttribute (theCtx, Graphic3d_TOA_UV);
 
-      glDrawArrays (GL_TRIANGLES, 0, aVerts->Length());
+    glDrawArrays (GL_TRIANGLES, 0, GLsizei(aVerts->GetElemsNb()));
 
-      glBindTexture (GL_TEXTURE_2D, 0);
-    }
-    glDisableClientState (GL_TEXTURE_COORD_ARRAY);
-    glDisableClientState (GL_VERTEX_ARRAY);
+    aVerts->UnbindAttribute (theCtx, Graphic3d_TOA_UV);
+    aVerts->UnbindAttribute (theCtx, Graphic3d_TOA_POS);
   }
+  glBindTexture (GL_TEXTURE_2D, 0);
 }
 
 // =======================================================================
@@ -654,14 +631,7 @@ void OpenGl_Text::render (const Handle(OpenGl_PrinterContext)& thePrintCtx,
     aFormatter.Append (theCtx, myString, *myFont.operator->());
     aFormatter.Format();
 
-    if (!theCtx->caps->vboDisable && theCtx->core15 != NULL)
-    {
-      aFormatter.Result (theCtx, myTextures, myVertsVbo, myTCrdsVbo);
-    }
-    else
-    {
-      aFormatter.Result (theCtx, myTextures, myVertsArray, myTCrdsArray);
-    }
+    aFormatter.Result (theCtx, myTextures, myVertsVbo, myTCrdsVbo);
     aFormatter.BndBox (myBndBox);
   }
 
index 1824586..31a79aa 100755 (executable)
@@ -133,8 +133,6 @@ protected:
   mutable NCollection_Vector<GLuint>                      myTextures;   //!< textures' IDs
   mutable NCollection_Vector<Handle(OpenGl_VertexBuffer)> myVertsVbo;   //!< VBOs of vertices
   mutable NCollection_Vector<Handle(OpenGl_VertexBuffer)> myTCrdsVbo;   //!< VBOs of texture coordinates
-  mutable NCollection_Vector<Handle(OpenGl_Vec2Array)>    myVertsArray; //!< arrays of vertices (for compatibility mode)
-  mutable NCollection_Vector<Handle(OpenGl_Vec2Array)>    myTCrdsArray; //!< arrays of vertices (for compatibility mode)
   mutable Font_FTFont::Rect                               myBndBox;
 
 protected:
index dbef616..f715f9d 100755 (executable)
@@ -15,7 +15,7 @@
 
 #include <OpenGl_TextFormatter.hxx>
 
-#include <OpenGl_VertexBuffer.hxx>
+#include <OpenGl_VertexBufferCompat.hxx>
 
 #include <cmath>
 
@@ -220,10 +220,20 @@ void OpenGl_TextFormatter::Result (const Handle(OpenGl_Context)&
     theVertsPerTexture.Clear();
     theTCrdsPerTexture.Clear();
 
+    const bool isNormalMode = theCtx->ToUseVbo();
+    Handle(OpenGl_VertexBuffer) aVertsVbo, aTcrdsVbo;
     while (theVertsPerTexture.Length() < theTextures.Length())
     {
-      Handle(OpenGl_VertexBuffer) aVertsVbo = new OpenGl_VertexBuffer();
-      Handle(OpenGl_VertexBuffer) aTcrdsVbo = new OpenGl_VertexBuffer();
+      if (isNormalMode)
+      {
+        aVertsVbo = new OpenGl_VertexBuffer();
+        aTcrdsVbo = new OpenGl_VertexBuffer();
+      }
+      else
+      {
+        aVertsVbo = new OpenGl_VertexBufferCompat();
+        aTcrdsVbo = new OpenGl_VertexBufferCompat();
+      }
       theVertsPerTexture.Append (aVertsVbo);
       theTCrdsPerTexture.Append (aTcrdsVbo);
       aVertsVbo->Create (theCtx);
@@ -263,42 +273,6 @@ void OpenGl_TextFormatter::Result (const Handle(OpenGl_Context)&
 }
 
 // =======================================================================
-// function : Result
-// purpose  :
-// =======================================================================
-void OpenGl_TextFormatter::Result (const Handle(OpenGl_Context)&                 /*theCtx*/,
-                                   NCollection_Vector<GLuint>&                   theTextures,
-                                   NCollection_Vector<Handle(OpenGl_Vec2Array)>& theVertsPerTexture,
-                                   NCollection_Vector<Handle(OpenGl_Vec2Array)>& theTCrdsPerTexture) const
-{
-  NCollection_Vector< NCollection_Handle <NCollection_Vector <OpenGl_Vec2> > > aVertsPerTexture;
-  NCollection_Vector< NCollection_Handle <NCollection_Vector <OpenGl_Vec2> > > aTCrdsPerTexture;
-  Result (theTextures, aVertsPerTexture, aTCrdsPerTexture);
-
-  theVertsPerTexture.Clear();
-  theTCrdsPerTexture.Clear();
-
-  for (Standard_Integer aTextureIter = 0; aTextureIter < theTextures.Length(); ++aTextureIter)
-  {
-    const NCollection_Vector<OpenGl_Vec2>& aVerts = *aVertsPerTexture.Value (aTextureIter);
-    const NCollection_Vector<OpenGl_Vec2>& aTCrds = *aTCrdsPerTexture.Value (aTextureIter);
-    Handle(OpenGl_Vec2Array) aVertsArray = new OpenGl_Vec2Array (1, aVerts.Length());
-    Handle(OpenGl_Vec2Array) aTCrdsArray = new OpenGl_Vec2Array (1, aVerts.Length());
-    theVertsPerTexture.Append (aVertsArray);
-    theTCrdsPerTexture.Append (aTCrdsArray);
-
-    for (Standard_Integer aVertIter = 0; aVertIter < aVerts.Length(); ++aVertIter)
-    {
-      aVertsArray->ChangeValue (aVertIter + 1) = aVerts.Value (aVertIter);
-    }
-    for (Standard_Integer aVertIter = 0; aVertIter < aVerts.Length(); ++aVertIter)
-    {
-      aTCrdsArray->ChangeValue (aVertIter + 1) = aTCrds.Value (aVertIter);
-    }
-  }
-}
-
-// =======================================================================
 // function : Append
 // purpose  :
 // =======================================================================
index 39d8ed2..adca108 100755 (executable)
@@ -24,9 +24,6 @@
 
 #include <NCollection_String.hxx>
 
-typedef NCollection_Array1<OpenGl_Vec2> OpenGl_Vec2Array;
-typedef NCollection_Handle<OpenGl_Vec2Array> Handle(OpenGl_Vec2Array);
-
 //! This class intended to prepare formatted text.
 class OpenGl_TextFormatter : public Standard_Transient
 {
@@ -63,12 +60,6 @@ public:
                                NCollection_Vector<Handle(OpenGl_VertexBuffer)>& theVertsPerTexture,
                                NCollection_Vector<Handle(OpenGl_VertexBuffer)>& theTCrdsPerTexture) const;
 
-  //! Retrieve formatting results.
-  Standard_EXPORT void Result (const Handle(OpenGl_Context)&                 theCtx,
-                               NCollection_Vector<GLuint>&                   theTextures,
-                               NCollection_Vector<Handle(OpenGl_Vec2Array)>& theVertsPerTexture,
-                               NCollection_Vector<Handle(OpenGl_Vec2Array)>& theTCrdsPerTexture) const;
-
   //! @return width of formatted text.
   inline Standard_ShortReal ResultWidth() const
   {
index 8f66090..9f06b96 100644 (file)
@@ -26,6 +26,7 @@ IMPLEMENT_STANDARD_RTTIEXT(OpenGl_VertexBuffer, OpenGl_Resource)
 // =======================================================================
 OpenGl_VertexBuffer::OpenGl_VertexBuffer()
 : OpenGl_Resource(),
+  myOffset (NULL),
   myBufferId (NO_BUFFER),
   myComponentsNb (4),
   myElemsNb (0),
@@ -84,6 +85,7 @@ void OpenGl_VertexBuffer::Release (OpenGl_Context* theGlCtx)
   {
     theGlCtx->core15->glDeleteBuffers (1, &myBufferId);
   }
+  myOffset   = NULL;
   myBufferId = NO_BUFFER;
 }
 
@@ -171,7 +173,7 @@ void OpenGl_VertexBuffer::BindVertexAttrib (const Handle(OpenGl_Context)& theGlC
   }
   Bind (theGlCtx);
   theGlCtx->core20->glEnableVertexAttribArray (theAttribLoc);
-  theGlCtx->core20->glVertexAttribPointer (theAttribLoc, GLint (myComponentsNb), myDataType, GL_FALSE, 0, NULL);
+  theGlCtx->core20->glVertexAttribPointer (theAttribLoc, GLint (myComponentsNb), myDataType, GL_FALSE, 0, myOffset);
 }
 
 // =======================================================================
@@ -190,98 +192,46 @@ void OpenGl_VertexBuffer::UnbindVertexAttrib (const Handle(OpenGl_Context)& theG
 }
 
 // =======================================================================
-// function : BindFixed
+// function : BindAllAttributes
 // purpose  :
 // =======================================================================
-void OpenGl_VertexBuffer::BindFixed (const Handle(OpenGl_Context)& theGlCtx,
-                                     const GLenum                  theMode) const
+void OpenGl_VertexBuffer::BindAllAttributes (const Handle(OpenGl_Context)& ) const
 {
-  if (!IsValid())
-  {
-    return;
-  }
-
-  Bind (theGlCtx);
-  glEnableClientState (theMode);
-  switch (theMode)
-  {
-    case GL_VERTEX_ARRAY:
-    {
-      glVertexPointer (static_cast<GLint> (myComponentsNb), myDataType, 0, NULL);
-      break;
-    }
-    case GL_NORMAL_ARRAY:
-    {
-      glNormalPointer (myDataType, 0, NULL);
-      break;
-    }
-    case GL_TEXTURE_COORD_ARRAY:
-    {
-      glTexCoordPointer (static_cast<GLint> (myComponentsNb), myDataType, 0, NULL);
-      break;
-    }
-    case GL_COLOR_ARRAY:
-    {
-      glColorPointer (static_cast<GLint> (myComponentsNb), myDataType, 0, NULL);
-      glColorMaterial (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
-      glEnable (GL_COLOR_MATERIAL);
-      break;
-    }
-    default: break;
-  }
-}
-
-// =======================================================================
-// function : UnbindFixed
-// purpose  :
-// =======================================================================
-void OpenGl_VertexBuffer::UnbindFixed (const Handle(OpenGl_Context)& theGlCtx,
-                                       const GLenum                  theMode) const
-{
-  if (!IsValid())
-  {
-    return;
-  }
-  Unbind (theGlCtx);
-  glDisableClientState (theMode);
-  if (theMode == GL_COLOR_ARRAY)
-  {
-    glDisable (GL_COLOR_MATERIAL);
-  }
+  //
 }
 
 // =======================================================================
-// function : BindFixed
+// function : BindPositionAttribute
 // purpose  :
 // =======================================================================
-void OpenGl_VertexBuffer::BindFixed (const Handle(OpenGl_Context)& ) const
+void OpenGl_VertexBuffer::BindPositionAttribute (const Handle(OpenGl_Context)& ) const
 {
   //
 }
 
 // =======================================================================
-// function : BindFixedPosition
+// function : UnbindAllAttributes
 // purpose  :
 // =======================================================================
-void OpenGl_VertexBuffer::BindFixedPosition (const Handle(OpenGl_Context)& ) const
+void OpenGl_VertexBuffer::UnbindAllAttributes (const Handle(OpenGl_Context)& ) const
 {
   //
 }
 
 // =======================================================================
-// function : UnbindFixed
+// function : HasColorAttribute
 // purpose  :
 // =======================================================================
-void OpenGl_VertexBuffer::UnbindFixed (const Handle(OpenGl_Context)& ) const
+bool OpenGl_VertexBuffer::HasColorAttribute() const
 {
-    //
+  return false;
 }
 
 // =======================================================================
-// function : HasColorAttribute
+// function : HasNormalAttribute
 // purpose  :
 // =======================================================================
-bool OpenGl_VertexBuffer::HasColorAttribute() const
+bool OpenGl_VertexBuffer::HasNormalAttribute() const
 {
   return false;
 }
index 3a04cc4..d029c00 100644 (file)
@@ -18,6 +18,7 @@
 #include <OpenGl_GlCore20.hxx>
 #include <OpenGl_Resource.hxx>
 #include <OpenGl_Context.hxx>
+#include <OpenGl_ShaderProgram.hxx>
 
 #include <Graphic3d_IndexBuffer.hxx>
 
@@ -65,18 +66,24 @@ public:
     return myDataType;
   }
 
+  //! @return offset to data, NULL by default
+  inline GLubyte* GetDataOffset() const
+  {
+    return myOffset;
+  }
+
   //! Creates VBO name (id) if not yet generated.
   //! Data should be initialized by another method.
-  Standard_EXPORT bool Create (const Handle(OpenGl_Context)& theGlCtx);
+  Standard_EXPORT virtual bool Create (const Handle(OpenGl_Context)& theGlCtx);
 
   //! Destroy object - will release GPU memory if any.
   Standard_EXPORT virtual void Release (OpenGl_Context* theGlCtx);
 
   //! Bind this VBO.
-  Standard_EXPORT void Bind (const Handle(OpenGl_Context)& theGlCtx) const;
+  Standard_EXPORT virtual void Bind (const Handle(OpenGl_Context)& theGlCtx) const;
 
   //! Unbind this VBO.
-  Standard_EXPORT void Unbind (const Handle(OpenGl_Context)& theGlCtx) const;
+  Standard_EXPORT virtual void Unbind (const Handle(OpenGl_Context)& theGlCtx) const;
 
   //! Notice that VBO will be unbound after this call.
   //! @param theComponentsNb - specifies the number of components per generic vertex attribute; must be 1, 2, 3, or 4;
@@ -190,17 +197,31 @@ public:
   Standard_EXPORT void UnbindVertexAttrib (const Handle(OpenGl_Context)& theGlCtx,
                                            const GLuint                  theAttribLoc) const;
 
-  //! Bind this VBO as fixed pipeline attribute.
+  //! Bind this VBO and enable specified attribute in OpenGl_Context::ActiveProgram() or FFP.
   //! @param theGlCtx - handle to bound GL context;
   //! @param theMode  - array mode (GL_VERTEX_ARRAY, GL_NORMAL_ARRAY, GL_COLOR_ARRAY, GL_INDEX_ARRAY, GL_TEXTURE_COORD_ARRAY).
-  Standard_EXPORT void BindFixed (const Handle(OpenGl_Context)& theGlCtx,
-                                  const GLenum                  theMode) const;
+  void BindAttribute (const Handle(OpenGl_Context)&   theCtx,
+                      const Graphic3d_TypeOfAttribute theMode) const
+  {
+    if (IsValid())
+    {
+      Bind (theCtx);
+      bindAttribute (theCtx, theMode, static_cast<GLint> (myComponentsNb), myDataType, 0, myOffset);
+    }
+  }
 
-  //! Unbind this VBO as fixed pipeline attribute.
-  //! @param theGlCtx - handle to bound GL context;
-  //! @param theMode  - array mode.
-  Standard_EXPORT void UnbindFixed (const Handle(OpenGl_Context)& theGlCtx,
-                                    const GLenum                  theMode) const;
+  //! Unbind this VBO and disable specified attribute in OpenGl_Context::ActiveProgram() or FFP.
+  //! @param theCtx handle to bound GL context
+  //! @param theMode  array mode
+  void UnbindAttribute (const Handle(OpenGl_Context)&   theCtx,
+                        const Graphic3d_TypeOfAttribute theMode) const
+  {
+    if (IsValid())
+    {
+      Unbind (theCtx);
+      unbindAttribute (theCtx, theMode);
+    }
+  }
 
 public: //! @name advanced methods
 
@@ -222,12 +243,12 @@ public: //! @name advanced methods
   }
 
   //! Initialize buffer with new data.
-  Standard_EXPORT bool init (const Handle(OpenGl_Context)& theGlCtx,
-                             const GLuint   theComponentsNb,
-                             const GLsizei  theElemsNb,
-                             const void*    theData,
-                             const GLenum   theDataType,
-                             const GLsizei  theStride);
+  Standard_EXPORT virtual bool init (const Handle(OpenGl_Context)& theGlCtx,
+                                     const GLuint   theComponentsNb,
+                                     const GLsizei  theElemsNb,
+                                     const void*    theData,
+                                     const GLenum   theDataType,
+                                     const GLsizei  theStride);
 
   //! Initialize buffer with new data.
   bool init (const Handle(OpenGl_Context)& theGlCtx,
@@ -240,11 +261,27 @@ public: //! @name advanced methods
   }
 
   //! Update part of the buffer with new data.
-  Standard_EXPORT bool subData (const Handle(OpenGl_Context)& theGlCtx,
-                                const GLsizei  theElemFrom,
-                                const GLsizei  theElemsNb,
-                                const void*    theData,
-                                const GLenum   theDataType);
+  Standard_EXPORT virtual bool subData (const Handle(OpenGl_Context)& theGlCtx,
+                                        const GLsizei  theElemFrom,
+                                        const GLsizei  theElemsNb,
+                                        const void*    theData,
+                                        const GLenum   theDataType);
+
+  //! Setup array pointer - either for active GLSL program OpenGl_Context::ActiveProgram()
+  //! or for FFP using bindFixed() when no program bound.
+  static void bindAttribute (const Handle(OpenGl_Context)&   theGlCtx,
+                             const Graphic3d_TypeOfAttribute theMode,
+                             const GLint                     theNbComp,
+                             const GLenum                    theDataType,
+                             const GLsizei                   theStride,
+                             const GLvoid*                   theOffset);
+
+  //! Disable GLSL array pointer - either for active GLSL program OpenGl_Context::ActiveProgram()
+  //! or for FFP using unbindFixed() when no program bound.
+  static void unbindAttribute (const Handle(OpenGl_Context)&   theGlCtx,
+                               const Graphic3d_TypeOfAttribute theMode);
+
+private:
 
   //! Setup FFP array pointer.
   static void bindFixed (const Handle(OpenGl_Context)&   theGlCtx,
@@ -252,85 +289,37 @@ public: //! @name advanced methods
                          const GLint                     theNbComp,
                          const GLenum                    theDataType,
                          const GLsizei                   theStride,
-                         const GLvoid*                   theOffset)
-  {
-    switch (theMode)
-    {
-      case Graphic3d_TOA_POS:
-      {
-        theGlCtx->core11->glEnableClientState (GL_VERTEX_ARRAY);
-        theGlCtx->core11->glVertexPointer (theNbComp, theDataType, theStride, theOffset);
-        break;
-      }
-      case Graphic3d_TOA_NORM:
-      {
-        theGlCtx->core11->glEnableClientState (GL_NORMAL_ARRAY);
-        theGlCtx->core11->glNormalPointer (theDataType, theStride, theOffset);
-        break;
-      }
-      case Graphic3d_TOA_UV:
-      {
-        theGlCtx->core11->glEnableClientState (GL_TEXTURE_COORD_ARRAY);
-        theGlCtx->core11->glTexCoordPointer (theNbComp, theDataType, theStride, theOffset);
-        break;
-      }
-      case Graphic3d_TOA_COLOR:
-      {
-        theGlCtx->core11->glEnableClientState (GL_COLOR_ARRAY);
-        theGlCtx->core11->glColorPointer (theNbComp, theDataType, theStride, theOffset);
-        theGlCtx->core11->glColorMaterial (GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
-        theGlCtx->core11fwd->glEnable (GL_COLOR_MATERIAL);
-        break;
-      }
-      case Graphic3d_TOA_CUSTOM:
-      {
-        break;
-      }
-    }
-  }
+                         const GLvoid*                   theOffset);
 
   //! Disable FFP array pointer.
   static void unbindFixed (const Handle(OpenGl_Context)&   theGlCtx,
-                           const Graphic3d_TypeOfAttribute theMode)
-  {
-    switch (theMode)
-    {
-      case Graphic3d_TOA_POS:    theGlCtx->core11->glDisableClientState (GL_VERTEX_ARRAY);        break;
-      case Graphic3d_TOA_NORM:   theGlCtx->core11->glDisableClientState (GL_NORMAL_ARRAY);        break;
-      case Graphic3d_TOA_UV:     theGlCtx->core11->glDisableClientState (GL_TEXTURE_COORD_ARRAY); break;
-      case Graphic3d_TOA_COLOR:
-      {
-        theGlCtx->core11->glDisableClientState (GL_COLOR_ARRAY);
-        theGlCtx->core11fwd->glDisable (GL_COLOR_MATERIAL);
-        break;
-      }
-      case Graphic3d_TOA_CUSTOM:
-      {
-        break;
-      }
-    }
-  }
+                           const Graphic3d_TypeOfAttribute theMode);
 
 public: //! @name methods for interleaved attributes array
 
-  //! Bind all vertex attributes. Default implementation does nothing.
-  Standard_EXPORT virtual void BindFixed   (const Handle(OpenGl_Context)& theGlCtx) const;
+  //! @return true if buffer contains per-vertex color attribute
+  Standard_EXPORT virtual bool HasColorAttribute() const;
+
+  //! @return true if buffer contains per-vertex normal attribute
+  Standard_EXPORT virtual bool HasNormalAttribute() const;
 
-  //! Bind all vertex position attribute only. Default implementation does nothing.
-  Standard_EXPORT virtual void BindFixedPosition (const Handle(OpenGl_Context)& theGlCtx) const;
+  //! Bind all vertex attributes to active program OpenGl_Context::ActiveProgram() or for FFP.
+  //! Default implementation does nothing.
+  Standard_EXPORT virtual void BindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const;
 
-  //! Unbind all vertex attributes. Default implementation does nothing.
-  Standard_EXPORT virtual void UnbindFixed (const Handle(OpenGl_Context)& theGlCtx) const;
+  //! Bind vertex position attribute only. Default implementation does nothing.
+  Standard_EXPORT virtual void BindPositionAttribute (const Handle(OpenGl_Context)& theGlCtx) const;
 
-  //! @return true if buffer contains per-vertex color attribute
-  Standard_EXPORT virtual bool HasColorAttribute() const;
+  //! Unbind all vertex attributes. Default implementation does nothing.
+  Standard_EXPORT virtual void UnbindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const;
 
 protected:
 
-  GLuint  myBufferId;     //!< VBO name (index)
-  GLuint  myComponentsNb; //!< Number of components per generic vertex attribute, must be 1, 2, 3, or 4
-  GLsizei myElemsNb;      //!< Number of vertex attributes / number of vertices
-  GLenum  myDataType;     //!< Data type (GL_FLOAT, GL_UNSIGNED_INT, GL_UNSIGNED_BYTE etc.)
+  GLubyte* myOffset;       //!< offset to data
+  GLuint   myBufferId;     //!< VBO name (index)
+  GLuint   myComponentsNb; //!< Number of components per generic vertex attribute, must be 1, 2, 3, or 4
+  GLsizei  myElemsNb;      //!< Number of vertex attributes / number of vertices
+  GLenum   myDataType;     //!< Data type (GL_FLOAT, GL_UNSIGNED_INT, GL_UNSIGNED_BYTE etc.)
 
 public:
 
@@ -340,4 +329,6 @@ public:
 
 DEFINE_STANDARD_HANDLE(OpenGl_VertexBuffer, OpenGl_Resource)
 
+#include <OpenGl_VertexBuffer.lxx>
+
 #endif // _OpenGl_VertexBuffer_H__
diff --git a/src/OpenGl/OpenGl_VertexBuffer.lxx b/src/OpenGl/OpenGl_VertexBuffer.lxx
new file mode 100644 (file)
index 0000000..866e573
--- /dev/null
@@ -0,0 +1,121 @@
+// Created by: Kirill GAVRILOV
+// Copyright (c) 2014 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.
+
+// =======================================================================
+// function : bindAttribute
+// purpose  :
+// =======================================================================
+inline void OpenGl_VertexBuffer::bindAttribute (const Handle(OpenGl_Context)&   theCtx,
+                                                const Graphic3d_TypeOfAttribute theAttribute,
+                                                const GLint                     theNbComp,
+                                                const GLenum                    theDataType,
+                                                const GLsizei                   theStride,
+                                                const GLvoid*                   theOffset)
+{
+  if (theCtx->ActiveProgram().IsNull())
+  {
+    bindFixed (theCtx, theAttribute, theNbComp, theDataType, theStride, theOffset);
+    return;
+  }
+
+  theCtx->core20fwd->glEnableVertexAttribArray (theAttribute);
+  theCtx->core20fwd->glVertexAttribPointer (theAttribute, theNbComp, theDataType, GL_FALSE, theStride, theOffset);
+}
+
+// =======================================================================
+// function : bindFixed
+// purpose  :
+// =======================================================================
+inline void OpenGl_VertexBuffer::bindFixed (const Handle(OpenGl_Context)&   theCtx,
+                                            const Graphic3d_TypeOfAttribute theMode,
+                                            const GLint                     theNbComp,
+                                            const GLenum                    theDataType,
+                                            const GLsizei                   theStride,
+                                            const GLvoid*                   theOffset)
+{
+  switch (theMode)
+  {
+    case Graphic3d_TOA_POS:
+    {
+      theCtx->core11->glEnableClientState (GL_VERTEX_ARRAY);
+      theCtx->core11->glVertexPointer (theNbComp, theDataType, theStride, theOffset);
+      return;
+    }
+    case Graphic3d_TOA_NORM:
+    {
+      theCtx->core11->glEnableClientState (GL_NORMAL_ARRAY);
+      theCtx->core11->glNormalPointer (theDataType, theStride, theOffset);
+      return;
+    }
+    case Graphic3d_TOA_UV:
+    {
+      theCtx->core11->glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+      theCtx->core11->glTexCoordPointer (theNbComp, theDataType, theStride, theOffset);
+      return;
+    }
+    case Graphic3d_TOA_COLOR:
+    {
+      theCtx->core11->glEnableClientState (GL_COLOR_ARRAY);
+      theCtx->core11->glColorPointer (theNbComp, theDataType, theStride, theOffset);
+      theCtx->core11->glColorMaterial (GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
+      theCtx->core11fwd->glEnable (GL_COLOR_MATERIAL);
+      return;
+    }
+    case Graphic3d_TOA_CUSTOM:
+    {
+      return;
+    }
+  }
+}
+
+// =======================================================================
+// function : unbindAttribute
+// purpose  :
+// =======================================================================
+inline void OpenGl_VertexBuffer::unbindAttribute (const Handle(OpenGl_Context)&   theCtx,
+                                                  const Graphic3d_TypeOfAttribute theAttribute)
+{
+  if (theCtx->ActiveProgram().IsNull())
+  {
+    unbindFixed (theCtx, theAttribute);
+    return;
+  }
+
+  theCtx->core20fwd->glDisableVertexAttribArray (theAttribute);
+}
+
+// =======================================================================
+// function : unbindAttribute
+// purpose  :
+// =======================================================================
+inline void OpenGl_VertexBuffer::unbindFixed (const Handle(OpenGl_Context)&   theCtx,
+                                              const Graphic3d_TypeOfAttribute theMode)
+{
+  switch (theMode)
+  {
+    case Graphic3d_TOA_POS:   theCtx->core11->glDisableClientState (GL_VERTEX_ARRAY);        return;
+    case Graphic3d_TOA_NORM:  theCtx->core11->glDisableClientState (GL_NORMAL_ARRAY);        return;
+    case Graphic3d_TOA_UV:    theCtx->core11->glDisableClientState (GL_TEXTURE_COORD_ARRAY); return;
+    case Graphic3d_TOA_COLOR:
+    {
+      theCtx->core11->glDisableClientState (GL_COLOR_ARRAY);
+      theCtx->core11fwd->glDisable (GL_COLOR_MATERIAL);
+      return;
+    }
+    case Graphic3d_TOA_CUSTOM:
+    {
+      return;
+    }
+  }
+}
diff --git a/src/OpenGl/OpenGl_VertexBufferCompat.cxx b/src/OpenGl/OpenGl_VertexBufferCompat.cxx
new file mode 100644 (file)
index 0000000..5d8c194
--- /dev/null
@@ -0,0 +1,225 @@
+// Created by: Kirill GAVRILOV
+// Copyright (c) 2013-2014 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.
+
+#include <OpenGl_VertexBufferCompat.hxx>
+
+#include <NCollection_AlignedAllocator.hxx>
+
+IMPLEMENT_STANDARD_HANDLE (OpenGl_VertexBufferCompat, OpenGl_VertexBuffer)
+IMPLEMENT_STANDARD_RTTIEXT(OpenGl_VertexBufferCompat, OpenGl_VertexBuffer)
+
+// =======================================================================
+// function : OpenGl_VertexBufferCompat
+// purpose  :
+// =======================================================================
+OpenGl_VertexBufferCompat::OpenGl_VertexBufferCompat()
+{
+  //
+}
+
+// =======================================================================
+// function : ~OpenGl_VertexBufferCompat
+// purpose  :
+// =======================================================================
+OpenGl_VertexBufferCompat::~OpenGl_VertexBufferCompat()
+{
+  Release (NULL);
+}
+
+// =======================================================================
+// function : Create
+// purpose  :
+// =======================================================================
+bool OpenGl_VertexBufferCompat::Create (const Handle(OpenGl_Context)& )
+{
+  if (myBufferId == NO_BUFFER)
+  {
+    myBufferId = (GLuint )-1; // dummy identifier...
+    Handle(NCollection_AlignedAllocator) anAlloc = new NCollection_AlignedAllocator (16);
+    myData = new NCollection_Buffer (anAlloc);
+  }
+  return myBufferId != NO_BUFFER;
+}
+
+// =======================================================================
+// function : Release
+// purpose  :
+// =======================================================================
+void OpenGl_VertexBufferCompat::Release (OpenGl_Context* )
+{
+  if (myBufferId == NO_BUFFER)
+  {
+    return;
+  }
+
+  myOffset   = NULL;
+  myBufferId = NO_BUFFER;
+  myData.Nullify();
+}
+
+// =======================================================================
+// function : Bind
+// purpose  :
+// =======================================================================
+void OpenGl_VertexBufferCompat::Bind (const Handle(OpenGl_Context)& ) const
+{
+  //
+}
+
+// =======================================================================
+// function : Unbind
+// purpose  :
+// =======================================================================
+void OpenGl_VertexBufferCompat::Unbind (const Handle(OpenGl_Context)& ) const
+{
+  //
+}
+
+//! Convert GL type to Graphic3d enumeration
+static inline bool toGraphic3dDataType (const GLuint          theNbComponents,
+                                        const GLenum          theGlType,
+                                        Graphic3d_TypeOfData& theType)
+{
+  switch (theGlType)
+  {
+    case GL_UNSIGNED_BYTE:
+    {
+      if (theNbComponents == 4)
+      {
+        theType = Graphic3d_TOD_VEC4UB;
+        return true;
+      }
+      return false;
+    }
+    case GL_UNSIGNED_SHORT:
+    {
+      if (theNbComponents == 1)
+      {
+        theType = Graphic3d_TOD_USHORT;
+        return true;
+      }
+      return false;
+    }
+    case GL_UNSIGNED_INT:
+    {
+      if (theNbComponents == 1)
+      {
+        theType = Graphic3d_TOD_UINT;
+        return true;
+      }
+      return false;
+    }
+    case GL_FLOAT:
+    {
+      switch (theNbComponents)
+      {
+        case 2: theType = Graphic3d_TOD_VEC2; return true;
+        case 3: theType = Graphic3d_TOD_VEC3; return true;
+        case 4: theType = Graphic3d_TOD_VEC4; return true;
+      }
+      return false;
+    }
+  }
+  return false;
+}
+
+// =======================================================================
+// function : initLink
+// purpose  :
+// =======================================================================
+bool OpenGl_VertexBufferCompat::initLink (const Handle(NCollection_Buffer)& theData,
+                                          const GLuint   theComponentsNb,
+                                          const GLsizei  theElemsNb,
+                                          const GLenum   theDataType)
+{
+  if (theData.IsNull())
+  {
+    myOffset = NULL;
+    return false;
+  }
+
+  if (myBufferId == NO_BUFFER)
+  {
+    myBufferId = (GLuint )-1; // dummy identifier...
+  }
+  myData         = theData;
+  myDataType     = theDataType;
+  myComponentsNb = theComponentsNb;
+  myElemsNb      = theElemsNb;
+  myOffset       = myData->ChangeData();
+  return true;
+}
+
+// =======================================================================
+// function : init
+// purpose  :
+// =======================================================================
+bool OpenGl_VertexBufferCompat::init (const Handle(OpenGl_Context)& theCtx,
+                                      const GLuint   theComponentsNb,
+                                      const GLsizei  theElemsNb,
+                                      const void*    theData,
+                                      const GLenum   theDataType,
+                                      const GLsizei  theStride)
+{
+  if (!Create (theCtx))
+  {
+    myOffset = NULL;
+    return false;
+  }
+
+  myDataType     = theDataType;
+  myComponentsNb = theComponentsNb;
+  myElemsNb      = theElemsNb;
+
+  const size_t aNbBytes = size_t(myElemsNb) * theStride;
+  if (!myData->Allocate (aNbBytes))
+  {
+    myOffset = NULL;
+    return false;
+  }
+
+  myOffset = myData->ChangeData();
+  if (theData != NULL)
+  {
+    memcpy (myData->ChangeData(), theData, aNbBytes);
+  }
+  return true;
+}
+
+// =======================================================================
+// function : subData
+// purpose  :
+// =======================================================================
+bool OpenGl_VertexBufferCompat::subData (const Handle(OpenGl_Context)& ,
+                                         const GLsizei  theElemFrom,
+                                         const GLsizei  theElemsNb,
+                                         const void*    theData,
+                                         const GLenum   theDataType)
+{
+  if (!IsValid() || myDataType != theDataType ||
+      theElemFrom < 0 || ((theElemFrom + theElemsNb) > myElemsNb))
+  {
+    return false;
+  }
+  else if (theData == NULL)
+  {
+    return true;
+  }
+
+  const size_t aDataSize = sizeOfGlType (theDataType);
+  const size_t anOffset  = size_t(theElemFrom) * size_t(myComponentsNb) * aDataSize;
+  const size_t aNbBytes  = size_t(theElemsNb)  * size_t(myComponentsNb) * aDataSize;
+  memcpy (myData->ChangeData() + anOffset, theData, aNbBytes);
+  return true;
+}
diff --git a/src/OpenGl/OpenGl_VertexBufferCompat.hxx b/src/OpenGl/OpenGl_VertexBufferCompat.hxx
new file mode 100644 (file)
index 0000000..48793f7
--- /dev/null
@@ -0,0 +1,94 @@
+// Created by: Kirill GAVRILOV
+// Copyright (c) 2014 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 _OpenGl_VertexBufferCompat_HeaderFile
+#define _OpenGl_VertexBufferCompat_HeaderFile
+
+#include <OpenGl_VertexBuffer.hxx>
+
+//! Compatibility layer for old OpenGL without VBO.
+//! Make sure to pass pointer from GetDataOffset() instead of NULL.
+//! Method GetDataOffset() returns pointer to real data in this class
+//! (while base class OpenGl_VertexBuffer always return NULL).
+//!
+//! Methods Bind()/Unbind() do nothing (do not affect OpenGL state)
+//! and ::GetTarget() is never used.
+//! For this reason there is no analog for OpenGl_IndexBuffer.
+//! Just pass GetDataOffset() to glDrawElements() directly as last argument.
+//!
+//! Class overrides methods init() and subData() to copy data into own memory buffer.
+//! Extra method initLink() might be used to pass existing buffer through handle without copying the data.
+//!
+//! Method Create() creates dummy identifier for this object which should NOT be passed to OpenGL functions.
+class OpenGl_VertexBufferCompat : public OpenGl_VertexBuffer
+{
+
+public:
+
+  //! Create uninitialized VBO.
+  Standard_EXPORT OpenGl_VertexBufferCompat();
+
+  //! Destroy object.
+  Standard_EXPORT virtual ~OpenGl_VertexBufferCompat();
+
+  //! Creates VBO name (id) if not yet generated.
+  //! Data should be initialized by another method.
+  Standard_EXPORT bool Create (const Handle(OpenGl_Context)& theGlCtx);
+
+  //! Destroy object - will release memory if any.
+  Standard_EXPORT virtual void Release (OpenGl_Context* theGlCtx) Standard_OVERRIDE;
+
+  //! Bind this VBO.
+  Standard_EXPORT virtual void Bind (const Handle(OpenGl_Context)& theGlCtx) const Standard_OVERRIDE;
+
+  //! Unbind this VBO.
+  Standard_EXPORT virtual void Unbind (const Handle(OpenGl_Context)& theGlCtx) const Standard_OVERRIDE;
+
+public: //! @name advanced methods
+
+  //! Initialize buffer with existing data.
+  //! Data will NOT be copied by this method!
+  Standard_EXPORT bool initLink (const Handle(NCollection_Buffer)& theData,
+                                 const GLuint   theComponentsNb,
+                                 const GLsizei  theElemsNb,
+                                 const GLenum   theDataType);
+
+  //! Initialize buffer with new data (data will be copied).
+  Standard_EXPORT virtual bool init (const Handle(OpenGl_Context)& theGlCtx,
+                                     const GLuint   theComponentsNb,
+                                     const GLsizei  theElemsNb,
+                                     const void*    theData,
+                                     const GLenum   theDataType,
+                                     const GLsizei  theStride) Standard_OVERRIDE;
+
+  //! Update part of the buffer with new data.
+  Standard_EXPORT virtual bool subData (const Handle(OpenGl_Context)& theGlCtx,
+                                        const GLsizei  theElemFrom,
+                                        const GLsizei  theElemsNb,
+                                        const void*    theData,
+                                        const GLenum   theDataType) Standard_OVERRIDE;
+
+protected:
+
+  Handle(NCollection_Buffer) myData; //!< buffer data
+
+public:
+
+  DEFINE_STANDARD_RTTI(OpenGl_VertexBufferCompat) // Type definition
+
+};
+
+DEFINE_STANDARD_HANDLE(OpenGl_VertexBufferCompat, OpenGl_VertexBuffer)
+
+#endif // _OpenGl_VertexBufferCompat_HeaderFile
index 3bd7bd5..74cb064 100644 (file)
@@ -600,7 +600,7 @@ void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext,
     // We need to disable (unbind) all shaders programs to ensure
     // that all objects without specified aspect will be drawn
     // correctly (such as background)
-    OpenGl_ShaderProgram::Unbind (aContext);
+    aContext->BindProgram (NULL);
   }
 
   // Render trihedron
index 3c408ce..fa896d5 100644 (file)
@@ -947,7 +947,7 @@ Standard_Boolean OpenGl_Workspace::UpdateRaytraceEnvironmentMap()
 
     if (!aProgram.IsNull())
     {
-      aProgram->Bind (myGlContext);
+      myGlContext->BindProgram (aProgram);
 
       if (!myView->TextureEnv().IsNull() && myView->SurfaceDetail() != Visual3d_TOD_NONE)
       {
@@ -965,10 +965,8 @@ Standard_Boolean OpenGl_Workspace::UpdateRaytraceEnvironmentMap()
     }
   }
 
-  OpenGl_ShaderProgram::Unbind (myGlContext);
-
+  myGlContext->BindProgram (NULL);
   myViewModificationStatus = myView->ModificationState();
-
   return Standard_True;
 }
 
@@ -1192,6 +1190,8 @@ Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView&
         return Standard_False;
       }
 
+      myRaytraceProgram->SetAttributeName (myGlContext, Graphic3d_TOA_POS, "occVertex");
+      myPostFSAAProgram->SetAttributeName (myGlContext, Graphic3d_TOA_POS, "occVertex");
       if (!myRaytraceProgram->Link (myGlContext)
        || !myPostFSAAProgram->Link (myGlContext))
       {
@@ -1286,6 +1286,7 @@ Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView&
         return SafeFailBack ("Failed to attach ray-trace shader objects");
       }
 
+      myRaytraceProgram->SetAttributeName (myGlContext, Graphic3d_TOA_POS, "occVertex");
       if (!myRaytraceProgram->Link (myGlContext))
       {
         TCollection_AsciiString aLinkLog;
@@ -1342,6 +1343,7 @@ Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView&
         return SafeFailBack ("Failed to attach FSAA shader objects");
       }
 
+      myPostFSAAProgram->SetAttributeName (myGlContext, Graphic3d_TOA_POS, "occVertex");
       if (!myPostFSAAProgram->Link (myGlContext))
       {
         TCollection_AsciiString aLinkLog;
@@ -1365,7 +1367,7 @@ Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView&
       Handle(OpenGl_ShaderProgram)& aShaderProgram =
         (anIndex == 0) ? myRaytraceProgram : myPostFSAAProgram;
 
-      aShaderProgram->Bind (myGlContext);
+      myGlContext->BindProgram (aShaderProgram);
 
       aShaderProgram->SetSampler (myGlContext,
         "uSceneMinPointTexture", OpenGl_RT_SceneMinPointTexture);
@@ -1406,7 +1408,7 @@ Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView&
       }
 
       myUniformLocations[anIndex][OpenGl_RT_aPosition] =
-        aShaderProgram->GetAttributeLocation (myGlContext, "aPosition");
+        aShaderProgram->GetAttributeLocation (myGlContext, "occVertex");
 
       myUniformLocations[anIndex][OpenGl_RT_uOriginLB] =
         aShaderProgram->GetUniformLocation (myGlContext, "uOriginLB");
@@ -1453,7 +1455,7 @@ Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView&
         aShaderProgram->GetUniformLocation (myGlContext, "uEnvironmentEnable");
     }
 
-    OpenGl_ShaderProgram::Unbind (myGlContext);
+    myGlContext->BindProgram (NULL);
   }
 
   if (myComputeInitStatus != OpenGl_RT_NONE)
@@ -1956,7 +1958,7 @@ Standard_Boolean OpenGl_Workspace::RunRaytraceShaders (const Graphic3d_CView& th
     glDisable (GL_BLEND);
   }
 
-  myRaytraceProgram->Bind (myGlContext);
+  myGlContext->BindProgram (myRaytraceProgram);
 
   Standard_Integer aLightSourceBufferSize =
     static_cast<Standard_Integer> (myRaytraceGeometry.Sources.size());
@@ -1992,20 +1994,16 @@ Standard_Boolean OpenGl_Workspace::RunRaytraceShaders (const Graphic3d_CView& th
   myRaytraceProgram->SetUniform (myGlContext,
     myUniformLocations[0][OpenGl_RT_uReflEnabled], theCView.RenderParams.IsReflectionEnabled ? 1 : 0);
 
-  myGlContext->core20fwd->glEnableVertexAttribArray (
-    myUniformLocations[0][OpenGl_RT_aPosition]);
+  myGlContext->core20fwd->glEnableVertexAttribArray (Graphic3d_TOA_POS);
   {
-    myGlContext->core20fwd->glVertexAttribPointer (
-      myUniformLocations[0][OpenGl_RT_aPosition], 3, GL_FLOAT, GL_FALSE, 0, NULL);
-
+    myGlContext->core20fwd->glVertexAttribPointer (Graphic3d_TOA_POS, 3, GL_FLOAT, GL_FALSE, 0, NULL);
     myGlContext->core15fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
   }
-  myGlContext->core20fwd->glDisableVertexAttribArray (
-    myUniformLocations[0][OpenGl_RT_aPosition]);
+  myGlContext->core20fwd->glDisableVertexAttribArray (Graphic3d_TOA_POS);
   
   if (!theCView.RenderParams.IsAntialiasingEnabled)
   {
-    myRaytraceProgram->Unbind (myGlContext);
+    myGlContext->BindProgram (NULL);
 
     myOpenGlFBO->ColorTexture()->Unbind        (myGlContext, GL_TEXTURE0 + OpenGl_RT_OpenGlColorTexture);
     myOpenGlFBO->DepthStencilTexture()->Unbind (myGlContext, GL_TEXTURE0 + OpenGl_RT_OpenGlDepthTexture);
@@ -2029,7 +2027,7 @@ Standard_Boolean OpenGl_Workspace::RunRaytraceShaders (const Graphic3d_CView& th
 
   myRaytraceFBO1->ColorTexture()->Bind (myGlContext, GL_TEXTURE0 + OpenGl_RT_FSAAInputTexture);
 
-  myPostFSAAProgram->Bind (myGlContext);
+  myGlContext->BindProgram (myPostFSAAProgram);
 
   myPostFSAAProgram->SetUniform (myGlContext,
     myUniformLocations[1][OpenGl_RT_uOriginLB], theOrigins[0]);
@@ -2065,11 +2063,8 @@ Standard_Boolean OpenGl_Workspace::RunRaytraceShaders (const Graphic3d_CView& th
   const Standard_ShortReal aMaxOffset = 0.559017f;
   const Standard_ShortReal aMinOffset = 0.186339f;
 
-  myGlContext->core20fwd->glEnableVertexAttribArray (
-    myUniformLocations[1][OpenGl_RT_aPosition]);
-  
-  myGlContext->core20fwd->glVertexAttribPointer (
-    myUniformLocations[1][OpenGl_RT_aPosition], 3, GL_FLOAT, GL_FALSE, 0, NULL);
+  myGlContext->core20fwd->glEnableVertexAttribArray (Graphic3d_TOA_POS);
+  myGlContext->core20fwd->glVertexAttribPointer (Graphic3d_TOA_POS, 3, GL_FLOAT, GL_FALSE, 0, NULL);
 
   // Perform multi-pass adaptive FSAA using ping-pong technique
   // rotated grid AA always uses 4 samples
@@ -2119,10 +2114,9 @@ Standard_Boolean OpenGl_Workspace::RunRaytraceShaders (const Graphic3d_CView& th
     }
   }
 
-  myGlContext->core20fwd->glDisableVertexAttribArray (
-    myUniformLocations[1][OpenGl_RT_aPosition]);
+  myGlContext->core20fwd->glDisableVertexAttribArray (Graphic3d_TOA_POS);
 
-  myPostFSAAProgram->Unbind (myGlContext);
+  myGlContext->BindProgram (NULL);
   myRaytraceFBO1->ColorTexture()->Unbind     (myGlContext, GL_TEXTURE0 + OpenGl_RT_FSAAInputTexture);
   myOpenGlFBO->ColorTexture()->Unbind        (myGlContext, GL_TEXTURE0 + OpenGl_RT_OpenGlColorTexture);
   myOpenGlFBO->DepthStencilTexture()->Unbind (myGlContext, GL_TEXTURE0 + OpenGl_RT_OpenGlDepthTexture);
index 0653b4c..a23cf64 100644 (file)
 // vertex attributes from compatibility profile. In the next
 // release old functionality will be removed from shader API.
 #ifdef VERTEX_SHADER
-  #define occColor    gl_Color          //!< Vertex color
-  #define occNormal   gl_Normal         //!< Normal  coordinates
-  #define occVertex   gl_Vertex         //!< Vertex  coordinates
-  #define occTexCoord gl_MultiTexCoord0 //!< Texture coordinates
+  attribute vec4 occVertex;
+  attribute vec3 occNormal;
+  attribute vec4 occTexCoord;
+  attribute vec4 occColor;
 #endif
 
 // Matrix state
index 6ff4d01..8b16abe 100644 (file)
@@ -1,12 +1,12 @@
-in vec4 aPosition;
+in vec4 occVertex;
 
 //! Normalized pixel coordinates.
 out vec2 vPixel;
 
 void main (void)
 {
-  vPixel = vec2 ((aPosition.x + 1.f) * 0.5f,
-                 (aPosition.y + 1.f) * 0.5f);
-                 
-  gl_Position = aPosition;
-}
\ No newline at end of file
+  vPixel = vec2 ((occVertex.x + 1.f) * 0.5f,
+                 (occVertex.y + 1.f) * 0.5f);
+
+  gl_Position = occVertex;
+}