d02c0bdc49
git-svn-id: http://svn.openscenegraph.org/osg/OpenSceneGraph/trunk@14570 16af8721-9629-0410-8352-f15c8da7e697
879 lines
34 KiB
C++
879 lines
34 KiB
C++
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
|
|
* Copyright (C) 2012 David Callu
|
|
*
|
|
* This library is open source and may be redistributed and/or modified under
|
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
|
* (at your option) any later version. The full license is in LICENSE file
|
|
* included with this distribution, and on the openscenegraph.org website.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* OpenSceneGraph Public License for more details.
|
|
*/
|
|
|
|
#ifndef OSG_BUFFEROBJECT
|
|
#define OSG_BUFFEROBJECT 1
|
|
|
|
#include <osg/GL>
|
|
#include <osg/GL2Extensions>
|
|
#include <osg/Object>
|
|
#include <osg/buffered_value>
|
|
#include <osg/FrameStamp>
|
|
|
|
#include <iosfwd>
|
|
#include <list>
|
|
#include <map>
|
|
|
|
// identify GLES 1.1
|
|
#if (defined(GL_VERSION_ES_CM_1_0) && GL_VERSION_ES_CM_1_0 > 0) || \
|
|
(defined(GL_VERSION_ES_CM_1_1) && GL_VERSION_ES_CM_1_1 > 0)
|
|
|
|
#define OPENGLES_1_1_FOUND 1
|
|
|
|
#endif
|
|
|
|
// for compatibility with gl.h headers that don't support VBO,
|
|
//GL_VERSION_1_5 and GL_ARB_vertex_buffer_object provide these types for OpenGL
|
|
//all ES versions except GL_OES_VERSION_1_0 provide these types for OpenGL ES
|
|
#if !defined(GL_VERSION_1_5) && !defined(GL_ARB_vertex_buffer_object) \
|
|
&& !defined(GL_ES_VERSION_2_0) && !defined(OPENGLES_1_1_FOUND)
|
|
#if defined(_WIN64)
|
|
typedef __int64 GLintptr;
|
|
typedef __int64 GLsizeiptr;
|
|
#elif defined(__ia64__) || defined(__x86_64__) || defined(__ANDROID__)
|
|
typedef long int GLintptr;
|
|
typedef long int GLsizeiptr;
|
|
#else
|
|
typedef int GLintptr;
|
|
typedef int GLsizeiptr;
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef GL_ARB_vertex_buffer_object
|
|
#define GL_ARB_vertex_buffer_object
|
|
|
|
typedef GLintptr GLintptrARB;
|
|
typedef GLsizeiptr GLsizeiptrARB;
|
|
|
|
#define GL_ARRAY_BUFFER_ARB 0x8892
|
|
#define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893
|
|
#define GL_ARRAY_BUFFER_BINDING_ARB 0x8894
|
|
#define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895
|
|
#define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896
|
|
#define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897
|
|
#define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898
|
|
#define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899
|
|
#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A
|
|
#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B
|
|
#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C
|
|
#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D
|
|
#define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E
|
|
#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F
|
|
#define GL_STREAM_DRAW_ARB 0x88E0
|
|
#define GL_STREAM_READ_ARB 0x88E1
|
|
#define GL_STREAM_COPY_ARB 0x88E2
|
|
#define GL_STATIC_DRAW_ARB 0x88E4
|
|
#define GL_STATIC_READ_ARB 0x88E5
|
|
#define GL_STATIC_COPY_ARB 0x88E6
|
|
#define GL_DYNAMIC_DRAW_ARB 0x88E8
|
|
#define GL_DYNAMIC_READ_ARB 0x88E9
|
|
#define GL_DYNAMIC_COPY_ARB 0x88EA
|
|
#define GL_READ_ONLY_ARB 0x88B8
|
|
#define GL_WRITE_ONLY_ARB 0x88B9
|
|
#define GL_READ_WRITE_ARB 0x88BA
|
|
#define GL_BUFFER_SIZE_ARB 0x8764
|
|
#define GL_BUFFER_USAGE_ARB 0x8765
|
|
#define GL_BUFFER_ACCESS_ARB 0x88BB
|
|
#define GL_BUFFER_MAPPED_ARB 0x88BC
|
|
#define GL_BUFFER_MAP_POINTER_ARB 0x88BD
|
|
#endif
|
|
|
|
#ifndef GL_VERSION_1_5
|
|
#define GL_STREAM_DRAW 0x88E0
|
|
#define GL_STREAM_READ 0x88E1
|
|
#define GL_STREAM_COPY 0x88E2
|
|
#define GL_STATIC_DRAW 0x88E4
|
|
#define GL_STATIC_READ 0x88E5
|
|
#define GL_STATIC_COPY 0x88E6
|
|
#define GL_DYNAMIC_DRAW 0x88E8
|
|
#define GL_DYNAMIC_READ 0x88E9
|
|
#define GL_DYNAMIC_COPY 0x88EA
|
|
#endif
|
|
|
|
#ifndef GL_VERSION_2_1
|
|
#define GL_PIXEL_PACK_BUFFER 0x88EB
|
|
#define GL_PIXEL_UNPACK_BUFFER 0x88EC
|
|
#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED
|
|
#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
|
|
#endif
|
|
|
|
|
|
#ifndef GL_ARB_pixel_buffer_object
|
|
#define GL_PIXEL_PACK_BUFFER_ARB 0x88EB
|
|
#define GL_PIXEL_UNPACK_BUFFER_ARB 0x88EC
|
|
#define GL_PIXEL_PACK_BUFFER_BINDING_ARB 0x88ED
|
|
#define GL_PIXEL_UNPACK_BUFFER_BINDING_ARB 0x88EF
|
|
#endif
|
|
|
|
namespace osg
|
|
{
|
|
|
|
class State;
|
|
class BufferData;
|
|
class BufferObject;
|
|
|
|
class BufferObjectProfile
|
|
{
|
|
public:
|
|
BufferObjectProfile():
|
|
_target(0),
|
|
_usage(0),
|
|
_size(0) {}
|
|
|
|
BufferObjectProfile(GLenum target, GLenum usage, unsigned int size):
|
|
_target(target),
|
|
_usage(usage),
|
|
_size(size) {}
|
|
|
|
BufferObjectProfile(const BufferObjectProfile& bpo):
|
|
_target(bpo._target),
|
|
_usage(bpo._usage),
|
|
_size(bpo._size) {}
|
|
|
|
bool operator < (const BufferObjectProfile& rhs) const
|
|
{
|
|
if (_target < rhs._target) return true;
|
|
else if (_target > rhs._target) return false;
|
|
if (_usage < rhs._usage) return true;
|
|
else if (_usage > rhs._usage) return false;
|
|
return _size < rhs._size;
|
|
}
|
|
|
|
bool operator == (const BufferObjectProfile& rhs) const
|
|
{
|
|
return (_target == rhs._target) &&
|
|
(_usage == rhs._usage) &&
|
|
(_size == rhs._size);
|
|
}
|
|
|
|
void setProfile(GLenum target, GLenum usage, unsigned int size)
|
|
{
|
|
_target = target;
|
|
_usage = usage;
|
|
_size = size;
|
|
}
|
|
|
|
BufferObjectProfile& operator = (const BufferObjectProfile& rhs)
|
|
{
|
|
_target = rhs._target;
|
|
_usage = rhs._usage;
|
|
_size = rhs._size;
|
|
return *this;
|
|
}
|
|
|
|
GLenum _target;
|
|
GLenum _usage;
|
|
GLenum _size;
|
|
};
|
|
|
|
// forward declare
|
|
class GLBufferObjectSet;
|
|
class GLBufferObjectManager;
|
|
|
|
class OSG_EXPORT GLBufferObject : public Referenced
|
|
{
|
|
public:
|
|
|
|
GLBufferObject(unsigned int contextID, BufferObject* bufferObject, unsigned int glObjectID=0);
|
|
|
|
void setProfile(const BufferObjectProfile& profile) { _profile = profile; }
|
|
const BufferObjectProfile& getProfile() const { return _profile; }
|
|
|
|
void setBufferObject(BufferObject* bufferObject);
|
|
BufferObject* getBufferObject() { return _bufferObject; }
|
|
|
|
struct BufferEntry
|
|
{
|
|
BufferEntry(): numRead(0), modifiedCount(0),dataSize(0),offset(0),dataSource(0) {}
|
|
|
|
BufferEntry(const BufferEntry& rhs):
|
|
numRead(rhs.numRead),
|
|
modifiedCount(rhs.modifiedCount),
|
|
dataSize(rhs.dataSize),
|
|
offset(rhs.offset),
|
|
dataSource(rhs.dataSource) {}
|
|
|
|
BufferEntry& operator = (const BufferEntry& rhs)
|
|
{
|
|
if (&rhs==this) return *this;
|
|
numRead = rhs.numRead;
|
|
modifiedCount = rhs.modifiedCount;
|
|
dataSize = rhs.dataSize;
|
|
offset = rhs.offset;
|
|
dataSource = rhs.dataSource;
|
|
return *this;
|
|
}
|
|
|
|
unsigned int getNumClients() const;
|
|
|
|
unsigned int numRead;
|
|
unsigned int modifiedCount;
|
|
unsigned int dataSize;
|
|
unsigned int offset;
|
|
BufferData* dataSource;
|
|
};
|
|
|
|
inline unsigned int getContextID() const { return _contextID; }
|
|
|
|
inline GLuint& getGLObjectID() { return _glObjectID; }
|
|
inline GLuint getGLObjectID() const { return _glObjectID; }
|
|
inline GLsizeiptrARB getOffset(unsigned int i) const { return _bufferEntries[i].offset; }
|
|
|
|
inline void bindBuffer();
|
|
|
|
inline void unbindBuffer()
|
|
{
|
|
_extensions->glBindBuffer(_profile._target,0);
|
|
}
|
|
|
|
inline bool isDirty() const { return _dirty; }
|
|
|
|
void dirty() { _dirty = true; }
|
|
|
|
void clear();
|
|
|
|
void compileBuffer();
|
|
|
|
void deleteGLObject();
|
|
|
|
void assign(BufferObject* bufferObject);
|
|
|
|
bool isPBOSupported() const { return _extensions->isPBOSupported; }
|
|
|
|
static GLBufferObject* createGLBufferObject(unsigned int contextID, const BufferObject* bufferObject);
|
|
|
|
static void deleteAllBufferObjects(unsigned int contextID);
|
|
static void discardAllBufferObjects(unsigned int contextID);
|
|
static void flushAllDeletedBufferObjects(unsigned int contextID);
|
|
static void discardAllDeletedBufferObjects(unsigned int contextID);
|
|
static void flushDeletedBufferObjects(unsigned int contextID,double currentTime, double& availbleTime);
|
|
static void releaseGLBufferObject(unsigned int contextID, GLBufferObject* to);
|
|
#if 0
|
|
/** Extensions class which encapsulates the querying of extensions and
|
|
* associated function pointers, and provide convenience wrappers to
|
|
* check for the extensions or use the associated functions.*/
|
|
class OSG_EXPORT Extensions : public osg::Referenced
|
|
{
|
|
public:
|
|
Extensions(unsigned int contextID);
|
|
|
|
Extensions(const Extensions& rhs);
|
|
|
|
void lowestCommonDenominator(const Extensions& rhs);
|
|
|
|
void setupGLExtensions(unsigned int contextID);
|
|
|
|
bool isBufferObjectSupported() const { return _glGenBuffers!=0; }
|
|
bool isPBOSupported() const { return _isPBOSupported; }
|
|
bool isUniformBufferObjectSupported() const { return _isUniformBufferObjectSupported; }
|
|
bool isTBOSupported() const { return _isTBOSupported; }
|
|
|
|
void glGenBuffers (GLsizei n, GLuint *buffers) const;
|
|
void glBindBuffer (GLenum target, GLuint buffer) const;
|
|
void glBufferData (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage) const;
|
|
void glBufferSubData (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data) const;
|
|
void glDeleteBuffers (GLsizei n, const GLuint *buffers) const;
|
|
GLboolean glIsBuffer (GLuint buffer) const;
|
|
void glGetBufferSubData (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data) const;
|
|
GLvoid* glMapBuffer (GLenum target, GLenum access) const;
|
|
GLboolean glUnmapBuffer (GLenum target) const;
|
|
void glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params) const;
|
|
void glGetBufferPointerv (GLenum target, GLenum pname, GLvoid* *params) const;
|
|
void glBindBufferRange (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
|
|
void glBindBufferBase (GLenum target, GLuint index, GLuint buffer);
|
|
void glTexBuffer( GLenum target, GLenum internalFormat, GLuint buffer ) const;
|
|
|
|
protected:
|
|
|
|
typedef void (GL_APIENTRY * GenBuffersProc) (GLsizei n, GLuint *buffers);
|
|
typedef void (GL_APIENTRY * BindBufferProc) (GLenum target, GLuint buffer);
|
|
typedef void (GL_APIENTRY * BufferDataProc) (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage);
|
|
typedef void (GL_APIENTRY * BufferSubDataProc) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data);
|
|
typedef void (GL_APIENTRY * DeleteBuffersProc) (GLsizei n, const GLuint *buffers);
|
|
typedef GLboolean (GL_APIENTRY * IsBufferProc) (GLuint buffer);
|
|
typedef void (GL_APIENTRY * GetBufferSubDataProc) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data);
|
|
typedef GLvoid* (GL_APIENTRY * MapBufferProc) (GLenum target, GLenum access);
|
|
typedef GLboolean (GL_APIENTRY * UnmapBufferProc) (GLenum target);
|
|
typedef void (GL_APIENTRY * GetBufferParameterivProc) (GLenum target, GLenum pname, GLint *params);
|
|
typedef void (GL_APIENTRY * GetBufferPointervProc) (GLenum target, GLenum pname, GLvoid* *params);
|
|
typedef void (GL_APIENTRY * BindBufferRangeProc) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
|
|
typedef void (GL_APIENTRY * BindBufferBaseProc) (GLenum target, GLuint index, GLuint buffer);
|
|
typedef void (GL_APIENTRY *TexBufferProc ) ( GLenum target, GLenum internalFormat, GLuint buffer );
|
|
|
|
|
|
GenBuffersProc _glGenBuffers;
|
|
BindBufferProc _glBindBuffer;
|
|
BufferDataProc _glBufferData;
|
|
BufferSubDataProc _glBufferSubData;
|
|
DeleteBuffersProc _glDeleteBuffers;
|
|
IsBufferProc _glIsBuffer;
|
|
GetBufferSubDataProc _glGetBufferSubData;
|
|
MapBufferProc _glMapBuffer;
|
|
UnmapBufferProc _glUnmapBuffer;
|
|
GetBufferParameterivProc _glGetBufferParameteriv;
|
|
GetBufferPointervProc _glGetBufferPointerv;
|
|
BindBufferRangeProc _glBindBufferRange;
|
|
BindBufferBaseProc _glBindBufferBase;
|
|
TexBufferProc _glTexBuffer;
|
|
|
|
bool _isPBOSupported;
|
|
bool _isUniformBufferObjectSupported;
|
|
bool _isTBOSupported;
|
|
};
|
|
|
|
/** Function to call to get the extension of a specified context.
|
|
* If the Extension object for that context has not yet been created
|
|
* and the 'createIfNotInitalized' flag been set to false then returns NULL.
|
|
* If 'createIfNotInitalized' is true then the Extensions object is
|
|
* automatically created. However, in this case the extension object is
|
|
* only created with the graphics context associated with ContextID..*/
|
|
static Extensions* getExtensions(unsigned int contextID,bool createIfNotInitalized);
|
|
|
|
/** setExtensions allows users to override the extensions across graphics contexts.
|
|
* typically used when you have different extensions supported across graphics pipes
|
|
* but need to ensure that they all use the same low common denominator extensions.*/
|
|
static void setExtensions(unsigned int contextID,Extensions* extensions);
|
|
#endif
|
|
|
|
bool hasAllBufferDataBeenRead() const;
|
|
|
|
void setBufferDataHasBeenRead(const osg::BufferData* bd);
|
|
|
|
protected:
|
|
|
|
virtual ~GLBufferObject();
|
|
|
|
unsigned int computeBufferAlignment(unsigned int pos, unsigned int bufferAlignment) const
|
|
{
|
|
if (bufferAlignment<2) return pos;
|
|
if ((pos%bufferAlignment)==0) return pos;
|
|
return ((pos/bufferAlignment)+1)*bufferAlignment;
|
|
}
|
|
|
|
unsigned int _contextID;
|
|
GLuint _glObjectID;
|
|
|
|
BufferObjectProfile _profile;
|
|
unsigned int _allocatedSize;
|
|
|
|
bool _dirty;
|
|
|
|
typedef std::vector<BufferEntry> BufferEntries;
|
|
BufferEntries _bufferEntries;
|
|
|
|
BufferObject* _bufferObject;
|
|
|
|
public:
|
|
|
|
GLBufferObjectSet* _set;
|
|
GLBufferObject* _previous;
|
|
GLBufferObject* _next;
|
|
unsigned int _frameLastUsed;
|
|
|
|
public:
|
|
GL2Extensions* _extensions;
|
|
|
|
};
|
|
|
|
typedef std::list< ref_ptr<GLBufferObject> > GLBufferObjectList;
|
|
|
|
class OSG_EXPORT GLBufferObjectSet : public Referenced
|
|
{
|
|
public:
|
|
GLBufferObjectSet(GLBufferObjectManager* parent, const BufferObjectProfile& profile);
|
|
|
|
const BufferObjectProfile& getProfile() const { return _profile; }
|
|
|
|
void handlePendingOrphandedGLBufferObjects();
|
|
|
|
void deleteAllGLBufferObjects();
|
|
void discardAllGLBufferObjects();
|
|
void flushAllDeletedGLBufferObjects();
|
|
void discardAllDeletedGLBufferObjects();
|
|
void flushDeletedGLBufferObjects(double currentTime, double& availableTime);
|
|
|
|
GLBufferObject* takeFromOrphans(BufferObject* bufferObject);
|
|
GLBufferObject* takeOrGenerate(BufferObject* bufferObject);
|
|
|
|
void moveToBack(GLBufferObject* to);
|
|
void addToBack(GLBufferObject* to);
|
|
void orphan(GLBufferObject* to);
|
|
void remove(GLBufferObject* to);
|
|
void moveToSet(GLBufferObject* to, GLBufferObjectSet* set);
|
|
|
|
unsigned int size() const { return _profile._size * _numOfGLBufferObjects; }
|
|
|
|
bool makeSpace(unsigned int& size);
|
|
|
|
bool checkConsistency() const;
|
|
|
|
GLBufferObjectManager* getParent() { return _parent; }
|
|
|
|
unsigned int computeNumGLBufferObjectsInList() const;
|
|
unsigned int getNumOfGLBufferObjects() const { return _numOfGLBufferObjects; }
|
|
unsigned int getNumOrphans() const { return static_cast<unsigned int>(_orphanedGLBufferObjects.size()); }
|
|
unsigned int getNumPendingOrphans() const { return static_cast<unsigned int>(_pendingOrphanedGLBufferObjects.size()); }
|
|
|
|
|
|
protected:
|
|
|
|
virtual ~GLBufferObjectSet();
|
|
|
|
OpenThreads::Mutex _mutex;
|
|
|
|
GLBufferObjectManager* _parent;
|
|
unsigned int _contextID;
|
|
BufferObjectProfile _profile;
|
|
unsigned int _numOfGLBufferObjects;
|
|
GLBufferObjectList _orphanedGLBufferObjects;
|
|
GLBufferObjectList _pendingOrphanedGLBufferObjects;
|
|
|
|
GLBufferObject* _head;
|
|
GLBufferObject* _tail;
|
|
};
|
|
|
|
class OSG_EXPORT GLBufferObjectManager : public osg::Referenced
|
|
{
|
|
public:
|
|
GLBufferObjectManager(unsigned int contextID);
|
|
|
|
unsigned int getContextID() const { return _contextID; }
|
|
|
|
|
|
void setNumberActiveGLBufferObjects(unsigned int size) { _numActiveGLBufferObjects = size; }
|
|
unsigned int& getNumberActiveGLBufferObjects() { return _numActiveGLBufferObjects; }
|
|
unsigned int getNumberActiveGLBufferObjects() const { return _numActiveGLBufferObjects; }
|
|
|
|
void setNumberOrphanedGLBufferObjects(unsigned int size) { _numOrphanedGLBufferObjects = size; }
|
|
unsigned int& getNumberOrphanedGLBufferObjects() { return _numOrphanedGLBufferObjects; }
|
|
unsigned int getNumberOrphanedGLBufferObjects() const { return _numOrphanedGLBufferObjects; }
|
|
|
|
void setCurrGLBufferObjectPoolSize(unsigned int size) { _currGLBufferObjectPoolSize = size; }
|
|
unsigned int& getCurrGLBufferObjectPoolSize() { return _currGLBufferObjectPoolSize; }
|
|
unsigned int getCurrGLBufferObjectPoolSize() const { return _currGLBufferObjectPoolSize; }
|
|
|
|
void setMaxGLBufferObjectPoolSize(unsigned int size);
|
|
unsigned int getMaxGLBufferObjectPoolSize() const { return _maxGLBufferObjectPoolSize; }
|
|
|
|
bool hasSpace(unsigned int size) const { return (_currGLBufferObjectPoolSize+size)<=_maxGLBufferObjectPoolSize; }
|
|
bool makeSpace(unsigned int size);
|
|
|
|
GLBufferObject* generateGLBufferObject(const osg::BufferObject* bufferObject);
|
|
|
|
void handlePendingOrphandedGLBufferObjects();
|
|
|
|
void deleteAllGLBufferObjects();
|
|
void discardAllGLBufferObjects();
|
|
void flushAllDeletedGLBufferObjects();
|
|
void discardAllDeletedGLBufferObjects();
|
|
void flushDeletedGLBufferObjects(double currentTime, double& availableTime);
|
|
void releaseGLBufferObject(GLBufferObject* to);
|
|
|
|
GLBufferObjectSet* getGLBufferObjectSet(const BufferObjectProfile& profile);
|
|
|
|
void newFrame(osg::FrameStamp* fs);
|
|
void resetStats();
|
|
void reportStats(std::ostream& out);
|
|
void recomputeStats(std::ostream& out);
|
|
|
|
unsigned int& getFrameNumber() { return _frameNumber; }
|
|
unsigned int& getNumberFrames() { return _numFrames; }
|
|
|
|
unsigned int& getNumberDeleted() { return _numDeleted; }
|
|
double& getDeleteTime() { return _deleteTime; }
|
|
|
|
unsigned int& getNumberGenerated() { return _numGenerated; }
|
|
double& getGenerateTime() { return _generateTime; }
|
|
|
|
unsigned int& getNumberApplied() { return _numApplied; }
|
|
double& getApplyTime() { return _applyTime; }
|
|
|
|
static osg::ref_ptr<GLBufferObjectManager>& getGLBufferObjectManager(unsigned int contextID);
|
|
|
|
protected:
|
|
|
|
typedef std::map< BufferObjectProfile, osg::ref_ptr<GLBufferObjectSet> > GLBufferObjectSetMap;
|
|
unsigned int _contextID;
|
|
unsigned int _numActiveGLBufferObjects;
|
|
unsigned int _numOrphanedGLBufferObjects;
|
|
unsigned int _currGLBufferObjectPoolSize;
|
|
unsigned int _maxGLBufferObjectPoolSize;
|
|
GLBufferObjectSetMap _glBufferObjectSetMap;
|
|
|
|
unsigned int _frameNumber;
|
|
|
|
unsigned int _numFrames;
|
|
unsigned int _numDeleted;
|
|
double _deleteTime;
|
|
|
|
unsigned int _numGenerated;
|
|
double _generateTime;
|
|
|
|
unsigned int _numApplied;
|
|
double _applyTime;
|
|
|
|
};
|
|
|
|
|
|
class OSG_EXPORT BufferObject : public Object
|
|
{
|
|
public:
|
|
|
|
BufferObject();
|
|
|
|
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/
|
|
BufferObject(const BufferObject& bo,const CopyOp& copyop=CopyOp::SHALLOW_COPY);
|
|
|
|
virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const BufferObject*>(obj)!=NULL; }
|
|
virtual const char* libraryName() const { return "osg"; }
|
|
virtual const char* className() const { return "BufferObject"; }
|
|
|
|
void setTarget(GLenum target) { _profile._target = target; }
|
|
GLenum getTarget() const { return _profile._target; }
|
|
|
|
/** Set what type of usage the buffer object will have. Options are:
|
|
* GL_STREAM_DRAW, GL_STREAM_READ, GL_STREAM_COPY,
|
|
* GL_STATIC_DRAW, GL_STATIC_READ, GL_STATIC_COPY,
|
|
* GL_DYNAMIC_DRAW, GL_DYNAMIC_READ, or GL_DYNAMIC_COPY.
|
|
*/
|
|
void setUsage(GLenum usage) { _profile._usage = usage; }
|
|
|
|
/** Get the type of usage the buffer object has been set up for.*/
|
|
GLenum getUsage() const { return _profile._usage; }
|
|
|
|
BufferObjectProfile& getProfile() { return _profile; }
|
|
const BufferObjectProfile& getProfile() const { return _profile; }
|
|
|
|
|
|
/** Set whether the BufferObject should use a GLBufferObject just for copying the BufferData and release it immmediately so that it may be reused.*/
|
|
void setCopyDataAndReleaseGLBufferObject(bool copyAndRelease) { _copyDataAndReleaseGLBufferObject = copyAndRelease; }
|
|
|
|
/** Get whether the BufferObject should use a GLBufferObject just for copying the BufferData and release it immmediately.*/
|
|
bool getCopyDataAndReleaseGLBufferObject() const { return _copyDataAndReleaseGLBufferObject; }
|
|
|
|
|
|
void dirty();
|
|
|
|
/** Resize any per context GLObject buffers to specified size. */
|
|
virtual void resizeGLObjectBuffers(unsigned int maxSize);
|
|
|
|
/** If State is non-zero, this function releases OpenGL objects for
|
|
* the specified graphics context. Otherwise, releases OpenGL objects
|
|
* for all graphics contexts. */
|
|
void releaseGLObjects(State* state=0) const;
|
|
|
|
unsigned int addBufferData(BufferData* bd);
|
|
void removeBufferData(unsigned int index);
|
|
void removeBufferData(BufferData* bd);
|
|
|
|
void setBufferData(unsigned int index, BufferData* bd);
|
|
BufferData* getBufferData(unsigned int index) { return _bufferDataList[index]; }
|
|
const BufferData* getBufferData(unsigned int index) const { return _bufferDataList[index]; }
|
|
|
|
unsigned int getNumBufferData() const { return static_cast<unsigned int>(_bufferDataList.size()); }
|
|
|
|
void setGLBufferObject(unsigned int contextID, GLBufferObject* glbo) { _glBufferObjects[contextID] = glbo; }
|
|
|
|
GLBufferObject* getGLBufferObject(unsigned int contextID) const { return _glBufferObjects[contextID].get(); }
|
|
|
|
GLBufferObject* getOrCreateGLBufferObject(unsigned int contextID) const
|
|
{
|
|
if (!_glBufferObjects[contextID]) _glBufferObjects[contextID] = GLBufferObject::createGLBufferObject(contextID, this);
|
|
return _glBufferObjects[contextID].get();
|
|
}
|
|
|
|
unsigned int computeRequiredBufferSize() const;
|
|
|
|
/** deprecated, provided for backwards compatibility.*/
|
|
static void deleteBufferObject(unsigned int contextID,GLuint globj);
|
|
|
|
protected:
|
|
|
|
~BufferObject();
|
|
|
|
typedef std::vector< BufferData* > BufferDataList;
|
|
typedef osg::buffered_object< osg::ref_ptr<GLBufferObject> > GLBufferObjects;
|
|
|
|
BufferObjectProfile _profile;
|
|
|
|
bool _copyDataAndReleaseGLBufferObject;
|
|
|
|
BufferDataList _bufferDataList;
|
|
|
|
mutable GLBufferObjects _glBufferObjects;
|
|
};
|
|
|
|
class OSG_EXPORT BufferData : public Object
|
|
{
|
|
public:
|
|
|
|
BufferData():
|
|
Object(true),
|
|
_modifiedCount(0),
|
|
_bufferIndex(0),
|
|
_numClients(0) {}
|
|
|
|
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/
|
|
BufferData(const BufferData& bd,const CopyOp& copyop=CopyOp::SHALLOW_COPY):
|
|
osg::Object(bd,copyop),
|
|
_modifiedCount(0),
|
|
_bufferIndex(0),
|
|
_modifiedCallback(bd._modifiedCallback),
|
|
_numClients(0) {}
|
|
|
|
virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const BufferData*>(obj)!=NULL; }
|
|
virtual const char* libraryName() const { return "osg"; }
|
|
virtual const char* className() const { return "BufferData"; }
|
|
|
|
virtual const GLvoid* getDataPointer() const = 0;
|
|
virtual unsigned int getTotalDataSize() const = 0;
|
|
|
|
virtual osg::Array* asArray() { return 0; }
|
|
virtual const osg::Array* asArray() const { return 0; }
|
|
|
|
virtual osg::PrimitiveSet* asPrimitiveSet() { return 0; }
|
|
virtual const osg::PrimitiveSet* asPrimitiveSet() const { return 0; }
|
|
|
|
virtual osg::Image* asImage() { return 0; }
|
|
virtual const osg::Image* asImage() const { return 0; }
|
|
|
|
void setBufferObject(BufferObject* bufferObject);
|
|
BufferObject* getBufferObject() { return _bufferObject.get(); }
|
|
const BufferObject* getBufferObject() const { return _bufferObject.get(); }
|
|
|
|
void setBufferIndex(unsigned int index) { _bufferIndex = index; }
|
|
unsigned int getBufferIndex() const { return _bufferIndex; }
|
|
|
|
GLBufferObject* getGLBufferObject(unsigned int contextID) const { return _bufferObject.valid() ? _bufferObject->getGLBufferObject(contextID) : 0; }
|
|
GLBufferObject* getOrCreateGLBufferObject(unsigned int contextID) const { return _bufferObject.valid() ? _bufferObject->getOrCreateGLBufferObject(contextID) : 0; }
|
|
|
|
struct ModifiedCallback : public virtual osg::Object
|
|
{
|
|
ModifiedCallback() {}
|
|
|
|
ModifiedCallback(const ModifiedCallback&,const CopyOp&) {}
|
|
|
|
META_Object(osg,ModifiedCallback);
|
|
|
|
virtual void modified(BufferData* /*bufferData*/) const {}
|
|
};
|
|
|
|
void setModifiedCallback(ModifiedCallback* md) { _modifiedCallback = md; }
|
|
ModifiedCallback* getModifiedCallback() { return _modifiedCallback.get(); }
|
|
const ModifiedCallback* getModifiedCallback() const { return _modifiedCallback.get(); }
|
|
|
|
/** Dirty the primitive, which increments the modified count, to force buffer objects to update.
|
|
* If a ModifiedCallback is attached to this BufferData then the callback is called prior to the bufferObject's dirty is called. */
|
|
inline void dirty()
|
|
{
|
|
++_modifiedCount;
|
|
if (_modifiedCallback.valid()) _modifiedCallback->modified(this);
|
|
if (_bufferObject.valid()) _bufferObject->dirty();
|
|
}
|
|
|
|
/** Set the modified count value.*/
|
|
inline void setModifiedCount(unsigned int value) { _modifiedCount=value; }
|
|
|
|
/** Get modified count value.*/
|
|
inline unsigned int getModifiedCount() const { return _modifiedCount; }
|
|
|
|
/** Resize any per context GLObject buffers to specified size. */
|
|
virtual void resizeGLObjectBuffers(unsigned int maxSize);
|
|
|
|
/** If State is non-zero, this function releases OpenGL objects for
|
|
* the specified graphics context. Otherwise, releases OpenGL objects
|
|
* for all graphics contexts. */
|
|
void releaseGLObjects(State* state=0) const;
|
|
|
|
unsigned int getNumClients() const { return _numClients; }
|
|
|
|
void addClient(osg::Object * /*client*/) { ++_numClients; }
|
|
|
|
void removeClient(osg::Object * /*client*/) { --_numClients; }
|
|
|
|
protected:
|
|
|
|
virtual ~BufferData();
|
|
|
|
unsigned int _modifiedCount;
|
|
|
|
unsigned int _bufferIndex;
|
|
osg::ref_ptr<BufferObject> _bufferObject;
|
|
osg::ref_ptr<ModifiedCallback> _modifiedCallback;
|
|
|
|
unsigned int _numClients;
|
|
};
|
|
|
|
|
|
class Array;
|
|
class OSG_EXPORT VertexBufferObject : public BufferObject
|
|
{
|
|
public:
|
|
|
|
VertexBufferObject();
|
|
|
|
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/
|
|
VertexBufferObject(const VertexBufferObject& vbo,const CopyOp& copyop=CopyOp::SHALLOW_COPY);
|
|
|
|
META_Object(osg,VertexBufferObject);
|
|
|
|
unsigned int addArray(osg::Array* array);
|
|
void removeArray(osg::Array* array);
|
|
|
|
void setArray(unsigned int i, Array* array);
|
|
Array* getArray(unsigned int i);
|
|
const Array* getArray(unsigned int i) const;
|
|
|
|
protected:
|
|
virtual ~VertexBufferObject();
|
|
};
|
|
|
|
class DrawElements;
|
|
class OSG_EXPORT ElementBufferObject : public BufferObject
|
|
{
|
|
public:
|
|
|
|
ElementBufferObject();
|
|
|
|
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/
|
|
ElementBufferObject(const ElementBufferObject& pbo,const CopyOp& copyop=CopyOp::SHALLOW_COPY);
|
|
|
|
META_Object(osg,ElementBufferObject);
|
|
|
|
unsigned int addDrawElements(osg::DrawElements* PrimitiveSet);
|
|
void removeDrawElements(osg::DrawElements* PrimitiveSet);
|
|
|
|
void setDrawElements(unsigned int i, DrawElements* PrimitiveSet);
|
|
DrawElements* getDrawElements(unsigned int i);
|
|
const DrawElements* getDrawElements(unsigned int i) const;
|
|
|
|
protected:
|
|
|
|
virtual ~ElementBufferObject();
|
|
};
|
|
|
|
class Image;
|
|
class OSG_EXPORT PixelBufferObject : public BufferObject
|
|
{
|
|
public:
|
|
|
|
PixelBufferObject(osg::Image* image=0);
|
|
|
|
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/
|
|
PixelBufferObject(const PixelBufferObject& pbo,const CopyOp& copyop=CopyOp::SHALLOW_COPY);
|
|
|
|
META_Object(osg,PixelBufferObject);
|
|
|
|
void setImage(osg::Image* image);
|
|
|
|
Image* getImage();
|
|
const Image* getImage() const;
|
|
|
|
bool isPBOSupported(unsigned int contextID) const { return _glBufferObjects[contextID]->isPBOSupported(); }
|
|
|
|
protected:
|
|
|
|
virtual ~PixelBufferObject();
|
|
};
|
|
|
|
/**
|
|
* This object represent a general class of pixel buffer objects,
|
|
* which are capable of allocating buffer object (memory)
|
|
* on the GPU. The memory can then be used either for CPU-GPU
|
|
* pixel transfer or directly for GPU-GPU transfer, without CPU intervention.
|
|
**/
|
|
class OSG_EXPORT PixelDataBufferObject : public BufferObject
|
|
{
|
|
public:
|
|
PixelDataBufferObject();
|
|
PixelDataBufferObject(const PixelDataBufferObject& pbo, const CopyOp& copyop=CopyOp::SHALLOW_COPY);
|
|
|
|
META_Object(osg, PixelDataBufferObject);
|
|
|
|
//! Set new size of the buffer object. This will reallocate the memory on the next compile
|
|
inline void setDataSize(unsigned int size) { _profile._size = size; dirty(); }
|
|
|
|
//! Get data size of the used buffer
|
|
inline unsigned int getDataSize() const { return _profile._size; }
|
|
|
|
//! Compile the buffer (reallocate the memory if buffer is dirty)
|
|
virtual void compileBuffer(State& state) const;
|
|
|
|
//! Bind the buffer in read mode, which means that data can be downloaded from the buffer (note: GL_PIXEL_UNPACK_BUFFER_ARB)
|
|
virtual void bindBufferInReadMode(State& state);
|
|
|
|
//! Bind the buffer in write mode, which means following OpenGL instructions will write data into the buffer (note: GL_PIXEL_PACK_BUFFER_ARB)
|
|
virtual void bindBufferInWriteMode(State& state);
|
|
|
|
//! Unbind the buffer
|
|
virtual void unbindBuffer(unsigned int contextID) const;
|
|
|
|
/** Resize any per context GLObject buffers to specified size. */
|
|
virtual void resizeGLObjectBuffers(unsigned int maxSize);
|
|
|
|
enum Mode
|
|
{
|
|
//! A normal mode of this data buffer
|
|
NONE = 0,
|
|
|
|
//! Buffer is in read mode (@see bindBufferInReadMode)
|
|
READ = 1,
|
|
|
|
//! Buffer is in write mode (@see bindBufferInWriteMode)
|
|
WRITE = 2
|
|
};
|
|
|
|
Mode getMode(unsigned int contextID) const { return (Mode)_mode[contextID]; }
|
|
|
|
protected:
|
|
|
|
virtual ~PixelDataBufferObject();
|
|
|
|
typedef osg::buffered_value<unsigned int> ModeList;
|
|
|
|
mutable ModeList _mode;
|
|
|
|
};
|
|
|
|
class OSG_EXPORT UniformBufferObject : public BufferObject
|
|
{
|
|
public:
|
|
UniformBufferObject();
|
|
UniformBufferObject(const UniformBufferObject& ubo, const CopyOp& copyop=CopyOp::SHALLOW_COPY);
|
|
META_Object(osg, UniformBufferObject);
|
|
protected:
|
|
virtual ~UniformBufferObject();
|
|
};
|
|
|
|
class OSG_EXPORT AtomicCounterBufferObject : public BufferObject
|
|
{
|
|
public:
|
|
AtomicCounterBufferObject();
|
|
AtomicCounterBufferObject(const AtomicCounterBufferObject& ubo, const CopyOp& copyop=CopyOp::SHALLOW_COPY);
|
|
META_Object(osg, AtomicCounterBufferObject);
|
|
|
|
protected:
|
|
virtual ~AtomicCounterBufferObject();
|
|
};
|
|
|
|
inline void GLBufferObject::bindBuffer()
|
|
{
|
|
_extensions->glBindBuffer(_profile._target,_glObjectID);
|
|
if (_set) _set->moveToBack(this);
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|