| 102 | | |
| 103 | | class OSG_EXPORT BufferObject : public Object |
| 104 | | { |
| 105 | | public: |
| 106 | | |
| 107 | | BufferObject(); |
| 108 | | |
| 109 | | /** Copy constructor using CopyOp to manage deep vs shallow copy.*/ |
| 110 | | BufferObject(const BufferObject& bo,const CopyOp& copyop=CopyOp::SHALLOW_COPY); |
| 111 | | |
| 112 | | virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const BufferObject*>(obj)!=NULL; } |
| 113 | | virtual const char* libraryName() const { return "osg"; } |
| 114 | | virtual const char* className() const { return "BufferObject"; } |
| 115 | | |
| 116 | | /** Set what type of usage the buffer object will have. Options are: |
| 117 | | * GL_STREAM_DRAW, GL_STREAM_READ, GL_STREAM_COPY, |
| 118 | | * GL_STATIC_DRAW, GL_STATIC_READ, GL_STATIC_COPY, |
| 119 | | * GL_DYNAMIC_DRAW, GL_DYNAMIC_READ, or GL_DYNAMIC_COPY. |
| 120 | | */ |
| 121 | | void setUsage(GLenum usage) { _usage = usage; } |
| 122 | | |
| 123 | | /** Get the type of usage the buffer object has been set up for.*/ |
| 124 | | GLenum getUsage() const { return _usage; } |
| | 102 | class BufferData; |
| | 103 | class BufferObject; |
| | 104 | |
| | 105 | class OSG_EXPORT GLBufferObject : public Referenced |
| | 106 | { |
| | 107 | public: |
| | 108 | |
| | 109 | GLBufferObject(unsigned int contextID, BufferObject* bufferObject=0); |
| | 110 | |
| | 111 | void setBufferObject(BufferObject* bufferObject); |
| | 112 | BufferObject* getBufferObject() { return _bufferObject; } |
| 128 | | BufferEntry(): dataSize(0),offset(0) {} |
| 129 | | BufferEntry(const BufferEntry& be): modifiedCount(be.modifiedCount),dataSize(be.dataSize),offset(be.offset) {} |
| 130 | | |
| 131 | | BufferEntry& operator = (const BufferEntry& be) { modifiedCount=be.modifiedCount; dataSize=be.dataSize; offset=be.offset; return *this; } |
| 132 | | |
| 133 | | mutable buffered_value<unsigned int> modifiedCount; |
| 134 | | mutable unsigned int dataSize; |
| 135 | | mutable unsigned int offset; |
| | 116 | BufferEntry(): modifiedCount(0),dataSize(0),offset(0),dataSource(0) {} |
| | 117 | |
| | 118 | BufferEntry(const BufferEntry& rhs): |
| | 119 | modifiedCount(rhs.modifiedCount), |
| | 120 | dataSize(rhs.dataSize), |
| | 121 | offset(rhs.offset), |
| | 122 | dataSource(rhs.dataSource) {} |
| | 123 | |
| | 124 | BufferEntry& operator = (const BufferEntry& rhs) |
| | 125 | { |
| | 126 | if (&rhs==this) return *this; |
| | 127 | modifiedCount = rhs.modifiedCount; |
| | 128 | dataSize = rhs.dataSize; |
| | 129 | offset = rhs.offset; |
| | 130 | dataSource = rhs.dataSource; |
| | 131 | return *this; |
| | 132 | } |
| | 133 | |
| | 134 | unsigned int modifiedCount; |
| | 135 | GLsizeiptrARB dataSize; |
| | 136 | GLsizeiptrARB offset; |
| | 137 | BufferData* dataSource; |
| 155 | | inline void dirty() { _compiledList.setAllElementsTo(0); } |
| 156 | | |
| 157 | | bool isDirty(unsigned int contextID) const { return _compiledList[contextID]==0; } |
| 158 | | |
| 159 | | virtual void compileBuffer(State& state) const = 0; |
| 160 | | |
| 161 | | /** Resize any per context GLObject buffers to specified size. */ |
| 162 | | virtual void resizeGLObjectBuffers(unsigned int maxSize); |
| 163 | | |
| 164 | | /** If State is non-zero, this function releases OpenGL objects for |
| 165 | | * the specified graphics context. Otherwise, releases OpenGL objects |
| 166 | | * for all graphics contexts. */ |
| 167 | | void releaseGLObjects(State* state=0) const; |
| | 156 | inline bool isDirty() const { return _dirty; } |
| | 157 | |
| | 158 | void dirty() { _dirty = true; } |
| | 159 | |
| | 160 | void clear(); |
| | 161 | |
| | 162 | void compileBuffer(); |
| | 163 | |
| | 164 | void deleteGLObject(); |
| | 165 | |
| | 166 | void assign(BufferObject* bufferObject); |
| | 167 | |
| | 168 | bool isPBOSupported() const { return _extensions->isPBOSupported(); } |
| | 169 | |
| | 170 | static GLBufferObject* createGLBufferObject(unsigned int contextID, const BufferObject* bufferObject); |
| 270 | | }; |
| | 273 | |
| | 274 | typedef std::vector<BufferEntry> BufferEntries; |
| | 275 | BufferEntries _bufferEntries; |
| | 276 | |
| | 277 | BufferObject* _bufferObject; |
| | 278 | |
| | 279 | public: |
| | 280 | Extensions* _extensions; |
| | 281 | |
| | 282 | }; |
| | 283 | |
| | 284 | class OSG_EXPORT BufferObject : public Object |
| | 285 | { |
| | 286 | public: |
| | 287 | |
| | 288 | BufferObject(); |
| | 289 | |
| | 290 | /** Copy constructor using CopyOp to manage deep vs shallow copy.*/ |
| | 291 | BufferObject(const BufferObject& bo,const CopyOp& copyop=CopyOp::SHALLOW_COPY); |
| | 292 | |
| | 293 | virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const BufferObject*>(obj)!=NULL; } |
| | 294 | virtual const char* libraryName() const { return "osg"; } |
| | 295 | virtual const char* className() const { return "BufferObject"; } |
| | 296 | |
| | 297 | void setTarget(GLenum target) { _target = target; } |
| | 298 | GLenum getTarget() const { return _target; } |
| | 299 | |
| | 300 | /** Set what type of usage the buffer object will have. Options are: |
| | 301 | * GL_STREAM_DRAW, GL_STREAM_READ, GL_STREAM_COPY, |
| | 302 | * GL_STATIC_DRAW, GL_STATIC_READ, GL_STATIC_COPY, |
| | 303 | * GL_DYNAMIC_DRAW, GL_DYNAMIC_READ, or GL_DYNAMIC_COPY. |
| | 304 | */ |
| | 305 | void setUsage(GLenum usage) { _usage = usage; } |
| | 306 | |
| | 307 | /** Get the type of usage the buffer object has been set up for.*/ |
| | 308 | GLenum getUsage() const { return _usage; } |
| | 309 | |
| | 310 | void dirty(); |
| | 311 | |
| | 312 | /** Resize any per context GLObject buffers to specified size. */ |
| | 313 | virtual void resizeGLObjectBuffers(unsigned int maxSize); |
| | 314 | |
| | 315 | /** If State is non-zero, this function releases OpenGL objects for |
| | 316 | * the specified graphics context. Otherwise, releases OpenGL objects |
| | 317 | * for all graphics contexts. */ |
| | 318 | void releaseGLObjects(State* state=0) const; |
| | 319 | |
| | 320 | unsigned int addBufferData(BufferData* bd); |
| | 321 | void removeBufferData(unsigned int index); |
| | 322 | void removeBufferData(BufferData* bd); |
| | 323 | |
| | 324 | void setBufferData(unsigned int index, BufferData* bd); |
| | 325 | BufferData* getBufferData(unsigned int index) { return _bufferDataList[index]; } |
| | 326 | const BufferData* getBufferData(unsigned int index) const { return _bufferDataList[index]; } |
| | 327 | |
| | 328 | unsigned int getNumBufferData() const { return _bufferDataList.size(); } |
| | 329 | |
| | 330 | GLBufferObject* getGLBufferObject(unsigned int contextID) const { return _glBufferObjects[contextID].get(); } |
| | 331 | |
| | 332 | GLBufferObject* getOrCreateGLBufferObject(unsigned int contextID) const |
| | 333 | { |
| | 334 | if (!_glBufferObjects[contextID]) _glBufferObjects[contextID] = GLBufferObject::createGLBufferObject(contextID, this); |
| | 335 | return _glBufferObjects[contextID].get(); |
| | 336 | } |
| | 337 | |
| | 338 | protected: |
| | 339 | |
| | 340 | ~BufferObject(); |
| | 341 | |
| | 342 | typedef std::vector< BufferData* > BufferDataList; |
| | 343 | typedef osg::buffered_object< osg::ref_ptr<GLBufferObject> > GLBufferObjects; |
| | 344 | |
| | 345 | GLenum _target; |
| | 346 | GLenum _usage; |
| | 347 | BufferDataList _bufferDataList; |
| | 348 | |
| | 349 | mutable GLBufferObjects _glBufferObjects; |
| | 350 | }; |
| | 351 | |
| | 352 | class BufferData : public Object |
| | 353 | { |
| | 354 | public: |
| | 355 | |
| | 356 | BufferData(): |
| | 357 | Object(true), |
| | 358 | _modifiedCount(0), |
| | 359 | _bufferIndex(0) {} |
| | 360 | |
| | 361 | /** Copy constructor using CopyOp to manage deep vs shallow copy.*/ |
| | 362 | BufferData(const BufferData& bd,const CopyOp& copyop=CopyOp::SHALLOW_COPY): |
| | 363 | osg::Object(bd,copyop), |
| | 364 | _modifiedCount(0), |
| | 365 | _bufferIndex(0) {} |
| | 366 | |
| | 367 | virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const BufferData*>(obj)!=NULL; } |
| | 368 | virtual const char* libraryName() const { return "osg"; } |
| | 369 | virtual const char* className() const { return "BufferData"; } |
| | 370 | |
| | 371 | virtual const GLvoid* getDataPointer() const = 0; |
| | 372 | virtual unsigned int getTotalDataSize() const = 0; |
| | 373 | |
| | 374 | void setBufferObject(BufferObject* bufferObject); |
| | 375 | BufferObject* getBufferObject() { return _bufferObject.get(); } |
| | 376 | const BufferObject* getBufferObject() const { return _bufferObject.get(); } |
| | 377 | |
| | 378 | void setBufferIndex(unsigned int index) { _bufferIndex = index; } |
| | 379 | unsigned int getBufferIndex() const { return _bufferIndex; } |
| | 380 | |
| | 381 | GLBufferObject* getGLBufferObject(unsigned int contextID) const { return _bufferObject.valid() ? _bufferObject->getGLBufferObject(contextID) : 0; } |
| | 382 | GLBufferObject* getOrCreateGLBufferObject(unsigned int contextID) const { return _bufferObject.valid() ? _bufferObject->getOrCreateGLBufferObject(contextID) : 0; } |
| | 383 | |
| | 384 | /** Dirty the primitive, which increments the modified count, to force buffer objects to update. */ |
| | 385 | inline void dirty() { ++_modifiedCount; if (_bufferObject.valid()) _bufferObject->dirty(); } |
| | 386 | |
| | 387 | /** Set the modified count value.*/ |
| | 388 | inline void setModifiedCount(unsigned int value) { _modifiedCount=value; } |
| | 389 | |
| | 390 | /** Get modified count value.*/ |
| | 391 | inline unsigned int getModifiedCount() const { return _modifiedCount; } |
| | 392 | |
| | 393 | protected: |
| | 394 | |
| | 395 | virtual ~BufferData(); |
| | 396 | |
| | 397 | unsigned int _modifiedCount; |
| | 398 | |
| | 399 | unsigned int _bufferIndex; |
| | 400 | osg::ref_ptr<BufferObject> _bufferObject; |
| | 401 | }; |
| | 402 | |