You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
828 lines
32 KiB
828 lines
32 KiB
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield |
|
* |
|
* 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/Object> |
|
#include <osg/buffered_value> |
|
#include <osg/FrameStamp> |
|
|
|
#include <iosfwd> |
|
#include <list> |
|
#include <map> |
|
|
|
#ifndef GL_ARB_vertex_buffer_object |
|
|
|
#define GL_ARB_vertex_buffer_object |
|
|
|
// for compatibility with gl.h headers that don't support VBO, |
|
#if defined(_WIN64) |
|
typedef __int64 GLintptrARB; |
|
typedef __int64 GLsizeiptrARB; |
|
#elif defined(__ia64__) || defined(__x86_64__) |
|
typedef long int GLintptrARB; |
|
typedef long int GLsizeiptrARB; |
|
#else |
|
typedef int GLintptrARB; |
|
typedef int GLsizeiptrARB; |
|
#endif |
|
|
|
#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 |
|
#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 |
|
|
|
#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(): modifiedCount(0),dataSize(0),offset(0),dataSource(0) {} |
|
|
|
BufferEntry(const BufferEntry& rhs): |
|
modifiedCount(rhs.modifiedCount), |
|
dataSize(rhs.dataSize), |
|
offset(rhs.offset), |
|
dataSource(rhs.dataSource) {} |
|
|
|
BufferEntry& operator = (const BufferEntry& rhs) |
|
{ |
|
if (&rhs==this) return *this; |
|
modifiedCount = rhs.modifiedCount; |
|
dataSize = rhs.dataSize; |
|
offset = rhs.offset; |
|
dataSource = rhs.dataSource; |
|
return *this; |
|
} |
|
|
|
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); |
|
|
|
/** 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; } |
|
|
|
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); |
|
|
|
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); |
|
|
|
|
|
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; |
|
|
|
bool _isPBOSupported; |
|
bool _isUniformBufferObjectSupported; |
|
}; |
|
|
|
/** 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); |
|
|
|
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: |
|
Extensions* _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 _orphanedGLBufferObjects.size(); } |
|
unsigned int getNumPendingOrphans() const { return _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 _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) {} |
|
|
|
/** 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) {} |
|
|
|
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; |
|
|
|
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; |
|
|
|
protected: |
|
|
|
virtual ~BufferData(); |
|
|
|
unsigned int _modifiedCount; |
|
|
|
unsigned int _bufferIndex; |
|
osg::ref_ptr<BufferObject> _bufferObject; |
|
osg::ref_ptr<ModifiedCallback> _modifiedCallback; |
|
}; |
|
|
|
|
|
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(); |
|
}; |
|
|
|
inline void GLBufferObject::bindBuffer() |
|
{ |
|
_extensions->glBindBuffer(_profile._target,_glObjectID); |
|
if (_set) _set->moveToBack(this); |
|
} |
|
|
|
} |
|
|
|
#endif
|
|
|