1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-10 18:51:21 +03:00
occt/src/OpenGl/OpenGl_VertexBuffer.cxx
kgv 871fa1038d 0024406: Visualization - crash on re-usage of the same primitive array
Redesign Graphic3d_ArrayOfPrimitives
Store vertices data in buffer objects managed using smart-pointers
- no more low-level memory corruption by memory releasing after VBO creation.
Remove broken hasEdgeInfos.

Interleave vertex attributes (position, color, normal, uv) in single buffer.
Remove from Graphic3d_ArrayOfPrimitives methods ::Orientate().
Remove structures Graphic3d_PrimitiveArray, CALL_DEF_PARRAY.
Add support for 2D vertex arrays.

Graphic3d_Group - remove array or primitive arrays.
Introduce more universal method Graphic3d_Group::AddPrimitiveArray().

Fix warning
2014-04-17 18:01:51 +04:00

288 lines
9.3 KiB
C++

// 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_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...",);
if (theGlCtx->IsValid())
{
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 void* theData,
const GLenum theDataType,
const GLsizei theStride)
{
if (!Create (theGlCtx))
{
return false;
}
Bind (theGlCtx);
myDataType = theDataType;
myComponentsNb = theComponentsNb;
myElemsNb = theElemsNb;
theGlCtx->core15->glBufferData (GetTarget(), GLsizeiptr(myElemsNb) * theStride, 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 void* theData,
const GLenum theDataType)
{
if (!IsValid() || myDataType != theDataType ||
theElemFrom < 0 || ((theElemFrom + theElemsNb) > myElemsNb))
{
return false;
}
Bind (theGlCtx);
const size_t aDataSize = sizeOfGlType (theDataType);
theGlCtx->core15->glBufferSubData (GetTarget(),
GLintptr(theElemFrom) * GLintptr (myComponentsNb) * aDataSize, // offset in bytes
GLsizeiptr(theElemsNb) * GLsizeiptr(myComponentsNb) * aDataSize, // size in bytes
theData);
bool isDone = (glGetError() == GL_NO_ERROR); // some dummy error
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);
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
// purpose :
// =======================================================================
void OpenGl_VertexBuffer::BindFixed (const Handle(OpenGl_Context)& ) const
{
//
}
// =======================================================================
// function : BindFixedPosition
// purpose :
// =======================================================================
void OpenGl_VertexBuffer::BindFixedPosition (const Handle(OpenGl_Context)& ) const
{
//
}
// =======================================================================
// function : UnbindFixed
// purpose :
// =======================================================================
void OpenGl_VertexBuffer::UnbindFixed (const Handle(OpenGl_Context)& ) const
{
//
}
// =======================================================================
// function : HasColorAttribute
// purpose :
// =======================================================================
bool OpenGl_VertexBuffer::HasColorAttribute() const
{
return false;
}