0023226: Extend OpenGl_Context to store map of shared GPU resources
[occt.git] / src / OpenGl / OpenGl_VertexBuffer.cxx
diff --git a/src/OpenGl/OpenGl_VertexBuffer.cxx b/src/OpenGl/OpenGl_VertexBuffer.cxx
new file mode 100644 (file)
index 0000000..436e67d
--- /dev/null
@@ -0,0 +1,290 @@
+// Created by: Kirill GAVRILOV
+// Copyright (c) 2012 OPEN CASCADE SAS
+//
+// The content of this file is subject to the Open CASCADE Technology Public
+// License Version 6.5 (the "License"). You may not use the content of this file
+// except in compliance with the License. Please obtain a copy of the License
+// at http://www.opencascade.org and read it completely before using this file.
+//
+// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
+// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+//
+// The Original Code and all software distributed under the License is
+// distributed on an "AS IS" basis, without warranty of any kind, and the
+// Initial Developer hereby disclaims all such warranties, including without
+// limitation, any warranties of merchantability, fitness for a particular
+// purpose or non-infringement. Please see the License for the specific terms
+// and conditions governing the rights and limitations under the License.
+
+#include <OpenGl_VertexBuffer.hxx>
+
+#include <OpenGl_Context.hxx>
+#include <Standard_Assert.hxx>
+
+IMPLEMENT_STANDARD_HANDLE (OpenGl_VertexBuffer, OpenGl_Resource)
+IMPLEMENT_STANDARD_RTTIEXT(OpenGl_VertexBuffer, OpenGl_Resource)
+
+// =======================================================================
+// function : OpenGl_VertexBuffer
+// purpose  :
+// =======================================================================
+OpenGl_VertexBuffer::OpenGl_VertexBuffer()
+: OpenGl_Resource(),
+  myBufferId (NO_BUFFER),
+  myComponentsNb (4),
+  myElemsNb (0),
+  myDataType (GL_FLOAT)
+{
+  //
+}
+
+// =======================================================================
+// function : ~OpenGl_VertexBuffer
+// purpose  :
+// =======================================================================
+OpenGl_VertexBuffer::~OpenGl_VertexBuffer()
+{
+  Release (NULL);
+}
+
+// =======================================================================
+// function : GetTarget
+// purpose  :
+// =======================================================================
+GLenum OpenGl_VertexBuffer::GetTarget() const
+{
+  return GL_ARRAY_BUFFER;
+}
+
+// =======================================================================
+// function : Create
+// purpose  :
+// =======================================================================
+bool OpenGl_VertexBuffer::Create (const Handle(OpenGl_Context)& theGlCtx)
+{
+  if (myBufferId == NO_BUFFER)
+  {
+    theGlCtx->core15->glGenBuffers (1, &myBufferId);
+  }
+  return myBufferId != NO_BUFFER;
+}
+
+// =======================================================================
+// function : Release
+// purpose  :
+// =======================================================================
+void OpenGl_VertexBuffer::Release (const OpenGl_Context* theGlCtx)
+{
+  if (myBufferId == NO_BUFFER)
+  {
+    return;
+  }
+
+  // application can not handle this case by exception - this is bug in code
+  Standard_ASSERT_RETURN (theGlCtx != NULL,
+    "OpenGl_VertexBuffer destroyed without GL context! Possible GPU memory leakage...",);
+
+  theGlCtx->core15->glDeleteBuffers (1, &myBufferId);
+  myBufferId = NO_BUFFER;
+}
+
+// =======================================================================
+// function : Bind
+// purpose  :
+// =======================================================================
+void OpenGl_VertexBuffer::Bind (const Handle(OpenGl_Context)& theGlCtx) const
+{
+  theGlCtx->core15->glBindBuffer (GetTarget(), myBufferId);
+}
+
+// =======================================================================
+// function : Unbind
+// purpose  :
+// =======================================================================
+void OpenGl_VertexBuffer::Unbind (const Handle(OpenGl_Context)& theGlCtx) const
+{
+  theGlCtx->core15->glBindBuffer (GetTarget(), NO_BUFFER);
+}
+
+// =======================================================================
+// function : Init
+// purpose  :
+// =======================================================================
+bool OpenGl_VertexBuffer::Init (const Handle(OpenGl_Context)& theGlCtx,
+                                const GLuint   theComponentsNb,
+                                const GLsizei  theElemsNb,
+                                const GLfloat* theData)
+{
+  if (!Create (theGlCtx))
+  {
+    return false;
+  }
+
+  Bind (theGlCtx);
+  myDataType     = GL_FLOAT;
+  myComponentsNb = theComponentsNb;
+  myElemsNb      = theElemsNb;
+  theGlCtx->core15->glBufferData (GetTarget(), GLsizeiptr(myElemsNb) * GLsizeiptr(myComponentsNb) * sizeof(GLfloat), theData, GL_STATIC_DRAW);
+  bool isDone = (glGetError() == GL_NO_ERROR); // GL_OUT_OF_MEMORY
+  Unbind (theGlCtx);
+  return isDone;
+}
+
+// =======================================================================
+// function : SubData
+// purpose  :
+// =======================================================================
+bool OpenGl_VertexBuffer::SubData (const Handle(OpenGl_Context)& theGlCtx,
+                                   const GLsizei  theElemFrom,
+                                   const GLsizei  theElemsNb,
+                                   const GLfloat* theData)
+{
+  if (!IsValid() || myDataType != GL_FLOAT ||
+      theElemFrom < 0 || ((theElemFrom + theElemsNb) > myElemsNb))
+  {
+    return false;
+  }
+
+  Bind (theGlCtx);
+  theGlCtx->core15->glBufferSubData (GetTarget(),
+                                     GLintptr(theElemFrom)  * GLintptr(myComponentsNb)   * sizeof(GLfloat), // offset in bytes
+                                     GLsizeiptr(theElemsNb) * GLsizeiptr(myComponentsNb) * sizeof(GLfloat), // size   in bytes
+                                     theData);
+  bool isDone = (glGetError() == GL_NO_ERROR); // some dummy error
+  Unbind (theGlCtx);
+  return isDone;
+}
+
+// =======================================================================
+// function : Init
+// purpose  :
+// =======================================================================
+bool OpenGl_VertexBuffer::Init (const Handle(OpenGl_Context)& theGlCtx,
+                                const GLuint  theComponentsNb,
+                                const GLsizei theElemsNb,
+                                const GLuint* theData)
+{
+  if (!Create (theGlCtx))
+  {
+    return false;
+  }
+
+  Bind (theGlCtx);
+  myDataType     = GL_UNSIGNED_INT;  
+  myComponentsNb = theComponentsNb;
+  myElemsNb      = theElemsNb;
+  theGlCtx->core15->glBufferData (GetTarget(), GLsizeiptr(myElemsNb) * GLsizeiptr(myComponentsNb) * sizeof(GLuint), theData, GL_STATIC_DRAW);
+  bool isDone = (glGetError() == GL_NO_ERROR); // GL_OUT_OF_MEMORY
+  Unbind (theGlCtx);
+  return isDone;
+}
+
+// =======================================================================
+// function : Init
+// purpose  :
+// =======================================================================
+bool OpenGl_VertexBuffer::Init (const Handle(OpenGl_Context)& theGlCtx,
+                                const GLuint   theComponentsNb,
+                                const GLsizei  theElemsNb,
+                                const GLubyte* theData)
+{
+  if (!Create (theGlCtx))
+  {
+    return false;
+  }
+
+  Bind (theGlCtx);
+  myDataType     = GL_UNSIGNED_BYTE;
+  myComponentsNb = theComponentsNb;
+  myElemsNb      = theElemsNb;
+  theGlCtx->core15->glBufferData (GetTarget(), GLsizeiptr(myElemsNb) * GLsizeiptr(myComponentsNb) * sizeof(GLubyte), theData, GL_STATIC_DRAW);
+  bool isDone = (glGetError() == GL_NO_ERROR); // GL_OUT_OF_MEMORY
+  Unbind (theGlCtx);
+  return isDone;
+}
+
+// =======================================================================
+// function : BindVertexAttrib
+// purpose  :
+// =======================================================================
+void OpenGl_VertexBuffer::BindVertexAttrib (const Handle(OpenGl_Context)& theGlCtx,
+                                            const GLuint                  theAttribLoc) const
+{
+  if (!IsValid() || theAttribLoc == GLuint (-1))
+  {
+    return;
+  }
+  Bind (theGlCtx);
+  theGlCtx->core20->glEnableVertexAttribArray (theAttribLoc);
+  theGlCtx->core20->glVertexAttribPointer (theAttribLoc, GLint (myComponentsNb), myDataType, GL_FALSE, 0, NULL);
+}
+
+// =======================================================================
+// function : UnbindVertexAttrib
+// purpose  :
+// =======================================================================
+void OpenGl_VertexBuffer::UnbindVertexAttrib (const Handle(OpenGl_Context)& theGlCtx,
+                                              const GLuint                  theAttribLoc) const
+{
+  if (!IsValid() || theAttribLoc == GLuint (-1))
+  {
+    return;
+  }
+  theGlCtx->core20->glDisableVertexAttribArray (theAttribLoc);
+  Unbind (theGlCtx);
+}
+
+// =======================================================================
+// function : BindFixed
+// purpose  :
+// =======================================================================
+void OpenGl_VertexBuffer::BindFixed (const Handle(OpenGl_Context)& theGlCtx,
+                                     const GLenum                  theMode) 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);
+      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);
+}