Mesh: support multiple context in OpenGLMultiBuffer

This commit is contained in:
Zheng, Lei
2019-10-16 15:35:58 +08:00
committed by wmayer
parent ac3ed6aed2
commit 98f0a11ec0
4 changed files with 202 additions and 14 deletions

View File

@@ -184,3 +184,125 @@ void OpenGLBuffer::buffer_delete(void * closure, uint32_t contextid)
GLuint id = (GLuint) ((uintptr_t) closure);
cc_glglue_glDeleteBuffers(glue, 1, &id);
}
// ----------------------------------------------------------------------------
OpenGLMultiBuffer::OpenGLMultiBuffer(GLenum type)
: target(type)
, currentBuf(0)
, currentContext(-1)
, glue(0)
{
SoContextHandler::addContextDestructionCallback(context_destruction_cb, this);
}
OpenGLMultiBuffer::~OpenGLMultiBuffer()
{
SoContextHandler::removeContextDestructionCallback(context_destruction_cb, this);
destroy();
}
void OpenGLMultiBuffer::setCurrentContext(uint32_t ctx)
{
currentContext = ctx;
glue = cc_glglue_instance(currentContext);
currentBuf = &bufs[ctx];
}
bool OpenGLMultiBuffer::create()
{
if (!currentBuf)
return false;
auto &bufferId = *currentBuf;
if (bufferId > 0)
return true;
if (!cc_glglue_has_vertex_buffer_object(glue))
return false;
cc_glglue_glGenBuffers(glue, 1, &bufferId);
return true;
}
bool OpenGLMultiBuffer::isCreated(uint32_t context) const
{
auto it = bufs.find(context);
return (it != bufs.end()) && (it->second > 0);
}
void OpenGLMultiBuffer::destroy()
{
// schedule delete for all allocated GL resources
for (auto &v : bufs) {
if (v.second > 0) {
void * ptr0 = (void*) ((uintptr_t) v.second);
SoGLCacheContextElement::scheduleDeleteCallback(v.first, buffer_delete, ptr0);
}
}
bufs.clear();
currentBuf = 0;
}
void OpenGLMultiBuffer::allocate(const void *data, int count)
{
if (currentBuf && *currentBuf) {
cc_glglue_glBufferData(glue, target, count, data, GL_STATIC_DRAW);
}
}
bool OpenGLMultiBuffer::bind()
{
if (currentBuf && *currentBuf) {
cc_glglue_glBindBuffer(glue, target, *currentBuf);
return true;
}
return false;
}
void OpenGLMultiBuffer::release()
{
if (currentBuf && *currentBuf) {
cc_glglue_glBindBuffer(glue, target, 0);
}
}
GLuint OpenGLMultiBuffer::getBufferId() const
{
return currentBuf ? *currentBuf : 0;
}
int OpenGLMultiBuffer::size() const
{
GLint value = -1;
if (currentBuf && *currentBuf) {
cc_glglue_glGetBufferParameteriv(glue, target, GL_BUFFER_SIZE, &value);
}
return value;
}
void OpenGLMultiBuffer::context_destruction_cb(uint32_t context, void * userdata)
{
OpenGLMultiBuffer * self = static_cast<OpenGLMultiBuffer*>(userdata);
auto it = self->bufs.find(context);
if (it != self->bufs.end() && it->second) {
const cc_glglue * glue = cc_glglue_instance((int) context);
GLuint buffer = it->second;
cc_glglue_glDeleteBuffers(glue, 1, &buffer);
if (self->currentBuf == &it->second)
self->currentBuf = 0;
self->bufs.erase(it);
}
}
void OpenGLMultiBuffer::buffer_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);
}

View File

@@ -24,6 +24,7 @@
#ifndef GUI_GLBUFFER_H
#define GUI_GLBUFFER_H
#include <map>
#include <Inventor/C/glue/gl.h>
namespace Gui {
@@ -59,6 +60,35 @@ private:
const cc_glglue* glue;
};
class GuiExport OpenGLMultiBuffer
{
public:
OpenGLMultiBuffer(GLenum type);
~OpenGLMultiBuffer();
void setCurrentContext(uint32_t ctx);
bool create();
bool isCreated(uint32_t ctx) const;
void destroy();
void allocate(const void *data, int count);
bool bind();
void release();
GLuint getBufferId() const;
int size() const;
private:
static void context_destruction_cb(uint32_t context, void * userdata);
static void buffer_delete(void * closure, uint32_t contextid);
GLenum target;
// map context to buffer id
std::map<uint32_t, GLuint> bufs;
GLuint *currentBuf;
uint32_t currentContext;
const cc_glglue* glue;
};
} // namespace Gui
#endif // GUI_GLBUFFER_H

View File

@@ -70,8 +70,8 @@ using namespace MeshGui;
class MeshRenderer::Private {
public:
Gui::OpenGLBuffer vertices;
Gui::OpenGLBuffer indices;
Gui::OpenGLMultiBuffer vertices;
Gui::OpenGLMultiBuffer indices;
const SbColor * pcolors;
SoMaterialBindingElement::Binding matbinding;
bool initialized;
@@ -84,6 +84,8 @@ public:
std::vector<float>& vertex, std::vector<int32_t>& index);
void renderFacesGLArray(SoGLRenderAction*);
void renderCoordsGLArray(SoGLRenderAction *);
void update();
bool needUpdate(SoGLRenderAction *);
private:
void renderGLArray(SoGLRenderAction *, GLenum);
@@ -115,13 +117,7 @@ bool MeshRenderer::Private::canRenderGLArray(SoGLRenderAction *action) const
init = true;
}
if (!vboAvailable)
return false;
// if no buffer is created we must pass here in order to create it afterwards
if (!indices.isCreated())
return true;
return indices.getBoundContext() == action->getCacheContext();
return vboAvailable;
}
void MeshRenderer::Private::generateGLArrays(SoGLRenderAction* action,
@@ -135,11 +131,9 @@ void MeshRenderer::Private::generateGLArrays(SoGLRenderAction* action,
vertices.setCurrentContext(action->getCacheContext());
indices.setCurrentContext(action->getCacheContext());
if (!initialized) {
vertices.create();
indices.create();
initialized = true;
}
initialized = true;
vertices.create();
indices.create();
vertices.bind();
vertices.allocate(&(vertex[0]),
@@ -196,6 +190,18 @@ void MeshRenderer::Private::renderCoordsGLArray(SoGLRenderAction *action)
{
renderGLArray(action, GL_POINTS);
}
void MeshRenderer::Private::update()
{
vertices.destroy();
indices.destroy();
}
bool MeshRenderer::Private::needUpdate(SoGLRenderAction *action)
{
return !vertices.isCreated(action->getCacheContext()) ||
!indices.isCreated(action->getCacheContext());
}
#elif defined RENDER_GLARRAYS
class MeshRenderer::Private {
public:
@@ -216,6 +222,13 @@ public:
std::vector<float>& vertex, std::vector<int32_t>& index);
void renderFacesGLArray(SoGLRenderAction *action);
void renderCoordsGLArray(SoGLRenderAction *action);
void update()
{
}
bool needUpdate(SoGLRenderAction *)
{
return false;
}
};
bool MeshRenderer::Private::canRenderGLArray(SoGLRenderAction *) const
@@ -323,6 +336,13 @@ public:
void renderCoordsGLArray(SoGLRenderAction *)
{
}
void update()
{
}
bool needUpdate(SoGLRenderAction *)
{
return false;
}
};
#endif
@@ -336,6 +356,16 @@ MeshRenderer::~MeshRenderer()
delete p;
}
void MeshRenderer::update()
{
p->update();
}
bool MeshRenderer::needUpdate(SoGLRenderAction *action)
{
return p->needUpdate(action);
}
void MeshRenderer::generateGLArrays(SoGLRenderAction* action, SoMaterialBindingElement::Binding matbind,
std::vector<float>& vertex, std::vector<int32_t>& index)
{
@@ -499,6 +529,10 @@ void SoFCIndexedFaceSet::GLRender(SoGLRenderAction *action)
if (useVBO) {
if (updateGLArray.getValue()) {
updateGLArray.setValue(false);
render.update();
generateGLArrays(action);
}
else if (render.needUpdate(action)) {
generateGLArrays(action);
}

View File

@@ -49,6 +49,8 @@ public:
void renderCoordsGLArray(SoGLRenderAction *action);
bool canRenderGLArray(SoGLRenderAction *action) const;
bool matchMaterial(SoState*) const;
void update();
bool needUpdate(SoGLRenderAction *action);
static bool shouldRenderDirectly(bool);
private: