Merge pull request #541 from wwmayer/vbo_cleanup

Vbo cleanup
This commit is contained in:
wwmayer 2017-02-20 21:04:33 +01:00 committed by GitHub
commit ced83be2da

View File

@ -29,6 +29,7 @@
#ifndef _PreComp_ #ifndef _PreComp_
#include <float.h> #include <float.h>
#include <algorithm> #include <algorithm>
#include <map>
#include <Inventor/SoPickedPoint.h> #include <Inventor/SoPickedPoint.h>
#include <Inventor/SoPrimitiveVertex.h> #include <Inventor/SoPrimitiveVertex.h>
#include <Inventor/actions/SoCallbackAction.h> #include <Inventor/actions/SoCallbackAction.h>
@ -44,6 +45,7 @@
#include <Inventor/elements/SoCoordinateElement.h> #include <Inventor/elements/SoCoordinateElement.h>
#include <Inventor/elements/SoGLCoordinateElement.h> #include <Inventor/elements/SoGLCoordinateElement.h>
#include <Inventor/elements/SoGLCacheContextElement.h> #include <Inventor/elements/SoGLCacheContextElement.h>
#include <Inventor/elements/SoGLVBOElement.h>
#include <Inventor/elements/SoLineWidthElement.h> #include <Inventor/elements/SoLineWidthElement.h>
#include <Inventor/elements/SoPointSizeElement.h> #include <Inventor/elements/SoPointSizeElement.h>
#include <Inventor/errors/SoDebugError.h> #include <Inventor/errors/SoDebugError.h>
@ -51,6 +53,7 @@
#include <Inventor/details/SoFaceDetail.h> #include <Inventor/details/SoFaceDetail.h>
#include <Inventor/details/SoLineDetail.h> #include <Inventor/details/SoLineDetail.h>
#include <Inventor/misc/SoState.h> #include <Inventor/misc/SoState.h>
#include <Inventor/misc/SoContextHandler.h>
#endif #endif
#include "SoBrepFaceSet.h" #include "SoBrepFaceSet.h"
@ -75,70 +78,80 @@
// Should come after glext.h to avoid warnings // Should come after glext.h to avoid warnings
#include <Inventor/C/glue/gl.h> #include <Inventor/C/glue/gl.h>
#if QT_VERSION < 0x50000
#include <QGLContext>
#else
#include <QOpenGLContext>
#endif
using namespace PartGui; using namespace PartGui;
#if QT_VERSION < 0x50000
#define _PROC(addr) QString::fromLatin1(addr)
#else
#define _PROC(addr) QByteArray(addr)
#endif
SO_NODE_SOURCE(SoBrepFaceSet); SO_NODE_SOURCE(SoBrepFaceSet);
#define PRIVATE(p) ((p)->pimpl) #define PRIVATE(p) ((p)->pimpl)
class SoBrepFaceSet::VBO { class SoBrepFaceSet::VBO {
public: public:
struct Buffer {
uint32_t myvbo[2];
};
static SbBool vboAvailable; static SbBool vboAvailable;
SbBool updateVbo; SbBool updateVbo;
uint32_t myvbo[2];
SbBool vboLoaded; SbBool vboLoaded;
uint32_t indice_array; uint32_t indice_array;
std::map<uint32_t, Buffer> vbomap;
VBO() { VBO()
{
SoContextHandler::addContextDestructionCallback(context_destruction_cb, this);
//SoBase::staticDataLock();
static bool init = false; static bool init = false;
if (!init) { if (!init) {
std::string ext = (const char*)(glGetString(GL_EXTENSIONS)); std::string ext = (const char*)(glGetString(GL_EXTENSIONS));
vboAvailable = (ext.find("GL_ARB_vertex_buffer_object") != std::string::npos); vboAvailable = (ext.find("GL_ARB_vertex_buffer_object") != std::string::npos);
init = true; init = true;
} }
//SoBase::staticDataUnlock();
#ifdef FC_OS_WIN32
#if QT_VERSION < 0x50000
const QGLContext* gl = QGLContext::currentContext();
#else
QOpenGLContext* gl = QOpenGLContext::currentContext();
#endif
PFNGLGENBUFFERSPROC glGenBuffersARB = (PFNGLGENBUFFERSPROC)gl->getProcAddress(_PROC("glGenBuffersARB"));
#endif
updateVbo = false; updateVbo = false;
vboLoaded = false; vboLoaded = false;
indice_array = 0; indice_array = 0;
if (vboAvailable) { }
glGenBuffersARB(2, &myvbo[0]); ~VBO()
{
SoContextHandler::removeContextDestructionCallback(context_destruction_cb, this);
// schedule delete for all allocated GL resources
std::map<uint32_t, Buffer>::iterator it;
for (it = vbomap.begin(); it != vbomap.end(); ++it) {
void * ptr0 = (void*) ((uintptr_t) it->second.myvbo[0]);
SoGLCacheContextElement::scheduleDeleteCallback(it->first, VBO::vbo_delete, ptr0);
void * ptr1 = (void*) ((uintptr_t) it->second.myvbo[1]);
SoGLCacheContextElement::scheduleDeleteCallback(it->first, VBO::vbo_delete, ptr1);
} }
} }
~VBO() {
static void context_destruction_cb(uint32_t context, void * userdata)
{
Buffer buffer;
VBO * self = static_cast<VBO*>(userdata);
std::map<uint32_t, Buffer>::iterator it = self->vbomap.find(context);
if (it != self->vbomap.end()) {
#ifdef FC_OS_WIN32 #ifdef FC_OS_WIN32
#if QT_VERSION < 0x50000 const cc_glglue * glue = cc_glglue_instance((int) context);
const QGLContext* gl = QGLContext::currentContext(); PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC)cc_glglue_getprocaddress(glue, "glDeleteBuffersARB");
#else
QOpenGLContext* gl = QOpenGLContext::currentContext();
#endif #endif
if (!gl) //cc_glglue_glDeleteBuffers(glue, buffer.size(), buffer.data());
return; buffer = it->second;
PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC)gl->getProcAddress(_PROC("glDeleteBuffersARB")); glDeleteBuffersARB(2, buffer.myvbo);
#endif self->vbomap.erase(it);
glDeleteBuffersARB(2, &myvbo[0]); }
}
static void vbo_delete(void * closure, uint32_t contextid)
{
const cc_glglue * glue = cc_glglue_instance((int) contextid);
GLuint id = (GLuint) ((uintptr_t) closure);
cc_glglue_glDeleteBuffers(glue, 1, &id);
} }
}; };
@ -196,10 +209,12 @@ void SoBrepFaceSet::doAction(SoAction* action)
for (int i=0; i<num;i++) for (int i=0; i<num;i++)
v[i] = i; v[i] = i;
this->selectionIndex.finishEditing(); this->selectionIndex.finishEditing();
PRIVATE(this)->updateVbo = true;
return; return;
} }
else if (selaction->getType() == Gui::SoSelectionElementAction::None) { else if (selaction->getType() == Gui::SoSelectionElementAction::None) {
this->selectionIndex.setNum(0); this->selectionIndex.setNum(0);
PRIVATE(this)->updateVbo = true;
return; return;
} }
@ -469,6 +484,10 @@ void SoBrepFaceSet::GLRender(SoGLRenderAction *action)
if (hasVBO) { if (hasVBO) {
// get the VBO status of the viewer // get the VBO status of the viewer
Gui::SoGLVBOActivatedElement::get(state, hasVBO); Gui::SoGLVBOActivatedElement::get(state, hasVBO);
//
//if (SoGLVBOElement::shouldCreateVBO(state, numindices)) {
// this->startVertexArray(action, coords, normals, false, false);
//}
} }
renderShape(action, hasVBO, static_cast<const SoGLCoordinateElement*>(coords), cindices, numindices, renderShape(action, hasVBO, static_cast<const SoGLCoordinateElement*>(coords), cindices, numindices,
pindices, numparts, normals, nindices, &mb, mindices, &tb, tindices, nbind, mbind, doTextures?1:0); pindices, numparts, normals, nindices, &mb, mindices, &tb, tindices, nbind, mbind, doTextures?1:0);
@ -972,6 +991,21 @@ void SoBrepFaceSet::renderShape(SoGLRenderAction * action,
uint32_t RGBA,R,G,B,A; uint32_t RGBA,R,G,B,A;
float Rf,Gf,Bf,Af; float Rf,Gf,Bf,Af;
VBO::Buffer buf;
uint32_t contextId = action->getCacheContext();
std::map<uint32_t, VBO::Buffer>::iterator it = PRIVATE(this)->vbomap.find(contextId);
if (it == PRIVATE(this)->vbomap.end()) {
#ifdef FC_OS_WIN32
const cc_glglue * glue = cc_glglue_instance(action->getCacheContext());
PFNGLGENBUFFERSPROC glGenBuffersARB = (PFNGLGENBUFFERSPROC)cc_glglue_getprocaddress(glue, "glGenBuffersARB");
#endif
glGenBuffersARB(2, buf.myvbo);
PRIVATE(this)->vbomap[contextId] = buf;
}
else {
buf = it->second;
}
// vbo loaded is defining if we must pre-load data into the VBO. When the variable is set to 0 // vbo loaded is defining if we must pre-load data into the VBO. When the variable is set to 0
// it means that the VBO has not been initialized // it means that the VBO has not been initialized
// updateVbo is tracking the need to update the content of the VBO which act as a buffer within // updateVbo is tracking the need to update the content of the VBO which act as a buffer within
@ -988,8 +1022,8 @@ void SoBrepFaceSet::renderShape(SoGLRenderAction * action,
PFNGLBINDBUFFERARBPROC glBindBufferARB = (PFNGLBINDBUFFERARBPROC) cc_glglue_getprocaddress(glue, "glBindBufferARB"); PFNGLBINDBUFFERARBPROC glBindBufferARB = (PFNGLBINDBUFFERARBPROC) cc_glglue_getprocaddress(glue, "glBindBufferARB");
PFNGLMAPBUFFERARBPROC glMapBufferARB = (PFNGLMAPBUFFERARBPROC) cc_glglue_getprocaddress(glue, "glMapBufferARB"); PFNGLMAPBUFFERARBPROC glMapBufferARB = (PFNGLMAPBUFFERARBPROC) cc_glglue_getprocaddress(glue, "glMapBufferARB");
#endif #endif
glBindBufferARB(GL_ARRAY_BUFFER_ARB, PRIVATE(this)->myvbo[0]); glBindBufferARB(GL_ARRAY_BUFFER_ARB, buf.myvbo[0]);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, PRIVATE(this)->myvbo[1]); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buf.myvbo[1]);
vertex_array=(float*)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); vertex_array=(float*)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
index_array=(GLuint *)glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); index_array=(GLuint *)glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
@ -1198,10 +1232,10 @@ void SoBrepFaceSet::renderShape(SoGLRenderAction * action,
PFNGLBUFFERDATAARBPROC glBufferDataARB = (PFNGLBUFFERDATAARBPROC)cc_glglue_getprocaddress(glue, "glBufferDataARB"); PFNGLBUFFERDATAARBPROC glBufferDataARB = (PFNGLBUFFERDATAARBPROC)cc_glglue_getprocaddress(glue, "glBufferDataARB");
#endif #endif
glBindBufferARB(GL_ARRAY_BUFFER_ARB, PRIVATE(this)->myvbo[0]); glBindBufferARB(GL_ARRAY_BUFFER_ARB, buf.myvbo[0]);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(float) * indice , vertex_array, GL_DYNAMIC_DRAW_ARB); glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(float) * indice , vertex_array, GL_DYNAMIC_DRAW_ARB);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, PRIVATE(this)->myvbo[1]); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buf.myvbo[1]);
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, sizeof(GLuint) * PRIVATE(this)->indice_array , &index_array[0], GL_DYNAMIC_DRAW_ARB); glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, sizeof(GLuint) * PRIVATE(this)->indice_array , &index_array[0], GL_DYNAMIC_DRAW_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
@ -1228,8 +1262,8 @@ void SoBrepFaceSet::renderShape(SoGLRenderAction * action,
PFNGLBINDBUFFERARBPROC glBindBufferARB = (PFNGLBINDBUFFERARBPROC)cc_glglue_getprocaddress(glue, "glBindBufferARB"); PFNGLBINDBUFFERARBPROC glBindBufferARB = (PFNGLBINDBUFFERARBPROC)cc_glglue_getprocaddress(glue, "glBindBufferARB");
#endif #endif
glBindBufferARB(GL_ARRAY_BUFFER_ARB, PRIVATE(this)->myvbo[0]); glBindBufferARB(GL_ARRAY_BUFFER_ARB, buf.myvbo[0]);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, PRIVATE(this)->myvbo[1]); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buf.myvbo[1]);
glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_COLOR_ARRAY);