Added osg::MultiDrawArrays which wraps up glMultiDrawArrays extension.

This commit is contained in:
Robert Osfield
2016-01-22 09:47:49 +00:00
parent 2791d280ae
commit 5cb486f7c5
5 changed files with 200 additions and 4 deletions

View File

@@ -609,6 +609,10 @@ class OSG_EXPORT GLExtensions : public osg::Referenced
GLboolean (GL_APIENTRY * glIsVertexArray) (GLuint handle);
void (GL_APIENTRY * glBindVertexArray) (GLuint handle);
// MultiDrawArrays
void (GL_APIENTRY * glMultiDrawArrays) (GLenum mode, const GLint * first, const GLsizei * count, GLsizei primcount);
};

View File

@@ -29,6 +29,8 @@
#include <vector>
#define OSG_HAS_MULTIDRAWARRAYS
namespace osg {
typedef MixinVector<GLsizei> VectorGLsizei;
@@ -174,7 +176,8 @@ class OSG_EXPORT PrimitiveSet : public BufferData
DrawArrayLengthsPrimitiveType,
DrawElementsUBytePrimitiveType,
DrawElementsUShortPrimitiveType,
DrawElementsUIntPrimitiveType
DrawElementsUIntPrimitiveType,
MultiDrawArraysPrimitiveType
};
enum Mode
@@ -587,6 +590,57 @@ class OSG_EXPORT DrawElementsUInt : public DrawElements, public VectorGLuint
virtual ~DrawElementsUInt();
};
#ifdef OSG_HAS_MULTIDRAWARRAYS
class OSG_EXPORT MultiDrawArrays : public osg::PrimitiveSet
{
public:
MultiDrawArrays(GLenum mode=0):
osg::PrimitiveSet(Type(MultiDrawArraysPrimitiveType), mode) {}
MultiDrawArrays(const MultiDrawArrays& dal,const CopyOp& copyop=CopyOp::SHALLOW_COPY):
osg::PrimitiveSet(dal,copyop),
_firsts(dal._firsts),
_counts(dal._counts) {}
virtual osg::Object* cloneType() const { return new MultiDrawArrays(); }
virtual osg::Object* clone(const osg::CopyOp& copyop) const { return new MultiDrawArrays(*this,copyop); }
virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const MultiDrawArrays*>(obj)!=NULL; }
virtual const char* libraryName() const { return "osg"; }
virtual const char* className() const { return "MultiDrawArrays"; }
virtual void draw(osg::State& state, bool useVertexBufferObjects) const;
virtual void accept(PrimitiveFunctor& functor) const;
virtual void accept(PrimitiveIndexFunctor& functor) const;
virtual unsigned int getNumIndices() const;
virtual unsigned int index(unsigned int pos) const;
virtual void offsetIndices(int offset);
virtual unsigned int getNumPrimitives() const;
typedef std::vector<GLint> Firsts;
void setFirsts(const Firsts& firsts) { _firsts = firsts; }
Firsts& getFirsts() { return _firsts; }
const Firsts& getFirsts() const { return _firsts; }
typedef std::vector<GLsizei> Counts;
void setCounts(const Counts& firsts) { _counts = firsts; }
Counts& getCounts() { return _counts; }
const Counts& getCounts() const { return _counts; }
void add(GLint first, GLsizei count);
protected:
Firsts _firsts;
Counts _counts;
};
#endif
}
#endif

View File

@@ -1034,7 +1034,7 @@ GLExtensions::GLExtensions(unsigned int contextID)
glGenerateMipmap != 0 &&
glGetRenderbufferParameteriv != 0 &&
( OSG_GLES1_FEATURES || isGLExtensionOrVersionSupported(contextID, "GL_EXT_framebuffer_object",3.0f) );
isPackedDepthStencilSupported = OSG_GL3_FEATURES ||
(isGLExtensionSupported(contextID, "GL_EXT_packed_depth_stencil")) ||
@@ -1077,7 +1077,9 @@ GLExtensions::GLExtensions(unsigned int contextID)
osg::setGLExtensionFuncPtr(glBindVertexArray,"glBindVertexArray");
osg::setGLExtensionFuncPtr(glDeleteVertexArrays,"glDeleteVertexArrays");
osg::setGLExtensionFuncPtr(glIsVertexArray,"glIsVertexArray");
// MultiDrawArrays
setGLExtensionFuncPtr(glMultiDrawArrays, "glMultiDrawArrays", "glMultiDrawArraysEXT");
}

View File

@@ -17,6 +17,10 @@
using namespace osg;
////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// PrimitiveSet
//
unsigned int PrimitiveSet::getNumPrimitives() const
{
switch(_mode)
@@ -36,6 +40,10 @@ unsigned int PrimitiveSet::getNumPrimitives() const
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// DrawArray
//
void DrawArrays::draw(State& state, bool) const
{
#if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE)
@@ -72,6 +80,10 @@ void DrawArrays::accept(PrimitiveIndexFunctor& functor) const
functor.drawArrays(_mode,_first,_count);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// DrawArrayLengths
//
unsigned int DrawArrayLengths::getNumPrimitives() const
{
switch(_mode)
@@ -159,6 +171,10 @@ unsigned int DrawArrayLengths::getNumIndices() const
return count;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// DrawElementsUByte
//
DrawElementsUByte::~DrawElementsUByte()
{
releaseGLObjects();
@@ -215,6 +231,10 @@ void DrawElementsUByte::offsetIndices(int offset)
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// DrawElementsUShort
//
DrawElementsUShort::~DrawElementsUShort()
{
releaseGLObjects();
@@ -270,7 +290,10 @@ void DrawElementsUShort::offsetIndices(int offset)
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// DrawElementsUInt
//
DrawElementsUInt::~DrawElementsUInt()
{
releaseGLObjects();
@@ -325,3 +348,101 @@ void DrawElementsUInt::offsetIndices(int offset)
*itr += offset;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// MultiDrawArrays
//
#ifdef OSG_HAS_MULTIDRAWARRAYS
void MultiDrawArrays::draw(osg::State& state, bool) const
{
// OSG_NOTICE<<"osg::MultiDrawArrays::draw"<<std::endl;
GLExtensions* ext = state.get<GLExtensions>();
if (ext->glMultiDrawArrays)
{
GLsizei primcount = std::min(_firsts.size(), _counts.size());
ext->glMultiDrawArrays(_mode, &_firsts.front(), &_counts.front(), primcount);
}
}
void MultiDrawArrays::accept(PrimitiveFunctor& functor) const
{
unsigned int primcount = std::min(_firsts.size(), _counts.size());
for(unsigned int i=0; i<primcount; ++i)
{
functor.drawArrays(_mode, _firsts[i], _counts[i]);
}
}
void MultiDrawArrays::accept(PrimitiveIndexFunctor& functor) const
{
unsigned int primcount = std::min(_firsts.size(), _counts.size());
for(unsigned int i=0; i<primcount; ++i)
{
functor.drawArrays(_mode, _firsts[i], _counts[i]);
}
}
unsigned int MultiDrawArrays::getNumIndices() const
{
unsigned int total=0;
for(Counts::const_iterator itr = _counts.begin(); itr!=_counts.end(); ++itr)
{
total += *itr;
}
return total;
}
unsigned int MultiDrawArrays::index(unsigned int pos) const
{
unsigned int i;
for(i=0; i<_counts.size(); ++i)
{
unsigned int count = _counts[i];
if (pos<count) break;
pos -= count;
}
if (i>=_firsts.size()) return 0;
return _firsts[i] + pos;
}
void MultiDrawArrays::offsetIndices(int offset)
{
for(Firsts::iterator itr = _firsts.begin(); itr!=_firsts.end(); ++itr)
{
*itr += offset;
}
}
unsigned int MultiDrawArrays::getNumPrimitives() const
{
switch(_mode)
{
case(POINTS): return getNumIndices();
case(LINES): return getNumIndices()/2;
case(TRIANGLES): return getNumIndices()/3;
case(QUADS): return getNumIndices()/4;
case(LINE_STRIP):
case(LINE_LOOP):
case(TRIANGLE_STRIP):
case(TRIANGLE_FAN):
case(QUAD_STRIP):
case(PATCHES):
case(POLYGON):
{
unsigned int primcount = std::min(_firsts.size(), _counts.size());
return primcount;
}
}
return 0;
}
void MultiDrawArrays::add(GLint first, GLsizei count)
{
_firsts.push_back(first);
_counts.push_back(count);
}
#endif

View File

@@ -149,3 +149,18 @@ REGISTER_OBJECT_WRAPPER( DrawElements,
DRAW_ELEMENTS_WRAPPER( DrawElementsUByte, RW_UCHAR )
DRAW_ELEMENTS_WRAPPER( DrawElementsUShort, RW_USHORT )
DRAW_ELEMENTS_WRAPPER( DrawElementsUInt, RW_UINT )
#ifdef OSG_HAS_MULTIDRAWARRAYS
namespace MultiDrawArrayWrapper {
REGISTER_OBJECT_WRAPPER( MultiDrawArrays,
new osg::MultiDrawArrays,
osg::MultiDrawArrays,
"osg::Object osg::PrimitiveSet osg::MultiDrawArrays" )
{
ADD_VECTOR_SERIALIZER( Firsts, osg::MultiDrawArrays::Firsts, osgDB::BaseSerializer::RW_INT, 8 );
ADD_VECTOR_SERIALIZER( Counts, osg::MultiDrawArrays::Counts, osgDB::BaseSerializer::RW_INT, 8 );
}
}
#endif