| 1 | /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield |
|---|
| 2 | * |
|---|
| 3 | * This library is open source and may be redistributed and/or modified under |
|---|
| 4 | * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or |
|---|
| 5 | * (at your option) any later version. The full license is in LICENSE file |
|---|
| 6 | * included with this distribution, and on the openscenegraph.org website. |
|---|
| 7 | * |
|---|
| 8 | * This library is distributed in the hope that it will be useful, |
|---|
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 11 | * OpenSceneGraph Public License for more details. |
|---|
| 12 | */ |
|---|
| 13 | |
|---|
| 14 | #ifndef OSG_BUFFEROBJECT |
|---|
| 15 | #define OSG_BUFFEROBJECT 1 |
|---|
| 16 | |
|---|
| 17 | #include <osg/GL> |
|---|
| 18 | #include <osg/Object> |
|---|
| 19 | #include <osg/buffered_value> |
|---|
| 20 | #include <osg/FrameStamp> |
|---|
| 21 | |
|---|
| 22 | #include <iosfwd> |
|---|
| 23 | #include <list> |
|---|
| 24 | #include <map> |
|---|
| 25 | |
|---|
| 26 | // identify GLES 1.1 |
|---|
| 27 | #if (defined(GL_VERSION_ES_CM_1_0) && GL_VERSION_ES_CM_1_0 > 0) || \ |
|---|
| 28 | (defined(GL_VERSION_ES_CM_1_1) && GL_VERSION_ES_CM_1_1 > 0) |
|---|
| 29 | |
|---|
| 30 | #define OPENGLES_1_1_FOUND 1 |
|---|
| 31 | |
|---|
| 32 | #endif |
|---|
| 33 | |
|---|
| 34 | // for compatibility with gl.h headers that don't support VBO, |
|---|
| 35 | //GL_VERSION_1_5 and GL_ARB_vertex_buffer_object provide these types for OpenGL |
|---|
| 36 | //all ES versions except GL_OES_VERSION_1_0 provide these types for OpenGL ES |
|---|
| 37 | #if !defined(GL_VERSION_1_5) && !defined(GL_ARB_vertex_buffer_object) \ |
|---|
| 38 | && !defined(GL_ES_VERSION_2_0) && !defined(OPENGLES_1_1_FOUND) |
|---|
| 39 | #if defined(_WIN64) |
|---|
| 40 | typedef __int64 GLintptr; |
|---|
| 41 | typedef __int64 GLsizeiptr; |
|---|
| 42 | #elif defined(__ia64__) || defined(__x86_64__) || defined(ANDROID) |
|---|
| 43 | typedef long int GLintptr; |
|---|
| 44 | typedef long int GLsizeiptr; |
|---|
| 45 | #else |
|---|
| 46 | typedef int GLintptr; |
|---|
| 47 | typedef int GLsizeiptr; |
|---|
| 48 | #endif |
|---|
| 49 | #endif |
|---|
| 50 | |
|---|
| 51 | #ifndef GL_ARB_vertex_buffer_object |
|---|
| 52 | #define GL_ARB_vertex_buffer_object |
|---|
| 53 | |
|---|
| 54 | typedef GLintptr GLintptrARB; |
|---|
| 55 | typedef GLsizeiptr GLsizeiptrARB; |
|---|
| 56 | |
|---|
| 57 | #define GL_ARRAY_BUFFER_ARB 0x8892 |
|---|
| 58 | #define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893 |
|---|
| 59 | #define GL_ARRAY_BUFFER_BINDING_ARB 0x8894 |
|---|
| 60 | #define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895 |
|---|
| 61 | #define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896 |
|---|
| 62 | #define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897 |
|---|
| 63 | #define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898 |
|---|
| 64 | #define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899 |
|---|
| 65 | #define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A |
|---|
| 66 | #define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B |
|---|
| 67 | #define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C |
|---|
| 68 | #define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D |
|---|
| 69 | #define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E |
|---|
| 70 | #define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F |
|---|
| 71 | #define GL_STREAM_DRAW_ARB 0x88E0 |
|---|
| 72 | #define GL_STREAM_READ_ARB 0x88E1 |
|---|
| 73 | #define GL_STREAM_COPY_ARB 0x88E2 |
|---|
| 74 | #define GL_STATIC_DRAW_ARB 0x88E4 |
|---|
| 75 | #define GL_STATIC_READ_ARB 0x88E5 |
|---|
| 76 | #define GL_STATIC_COPY_ARB 0x88E6 |
|---|
| 77 | #define GL_DYNAMIC_DRAW_ARB 0x88E8 |
|---|
| 78 | #define GL_DYNAMIC_READ_ARB 0x88E9 |
|---|
| 79 | #define GL_DYNAMIC_COPY_ARB 0x88EA |
|---|
| 80 | #define GL_READ_ONLY_ARB 0x88B8 |
|---|
| 81 | #define GL_WRITE_ONLY_ARB 0x88B9 |
|---|
| 82 | #define GL_READ_WRITE_ARB 0x88BA |
|---|
| 83 | #define GL_BUFFER_SIZE_ARB 0x8764 |
|---|
| 84 | #define GL_BUFFER_USAGE_ARB 0x8765 |
|---|
| 85 | #define GL_BUFFER_ACCESS_ARB 0x88BB |
|---|
| 86 | #define GL_BUFFER_MAPPED_ARB 0x88BC |
|---|
| 87 | #define GL_BUFFER_MAP_POINTER_ARB 0x88BD |
|---|
| 88 | #endif |
|---|
| 89 | |
|---|
| 90 | #ifndef GL_VERSION_1_5 |
|---|
| 91 | #define GL_STREAM_DRAW 0x88E0 |
|---|
| 92 | #define GL_STREAM_READ 0x88E1 |
|---|
| 93 | #define GL_STREAM_COPY 0x88E2 |
|---|
| 94 | #define GL_STATIC_DRAW 0x88E4 |
|---|
| 95 | #define GL_STATIC_READ 0x88E5 |
|---|
| 96 | #define GL_STATIC_COPY 0x88E6 |
|---|
| 97 | #define GL_DYNAMIC_DRAW 0x88E8 |
|---|
| 98 | #define GL_DYNAMIC_READ 0x88E9 |
|---|
| 99 | #define GL_DYNAMIC_COPY 0x88EA |
|---|
| 100 | #endif |
|---|
| 101 | |
|---|
| 102 | #ifndef GL_VERSION_2_1 |
|---|
| 103 | #define GL_PIXEL_PACK_BUFFER 0x88EB |
|---|
| 104 | #define GL_PIXEL_UNPACK_BUFFER 0x88EC |
|---|
| 105 | #define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED |
|---|
| 106 | #define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF |
|---|
| 107 | #endif |
|---|
| 108 | |
|---|
| 109 | |
|---|
| 110 | #ifndef GL_ARB_pixel_buffer_object |
|---|
| 111 | #define GL_PIXEL_PACK_BUFFER_ARB 0x88EB |
|---|
| 112 | #define GL_PIXEL_UNPACK_BUFFER_ARB 0x88EC |
|---|
| 113 | #define GL_PIXEL_PACK_BUFFER_BINDING_ARB 0x88ED |
|---|
| 114 | #define GL_PIXEL_UNPACK_BUFFER_BINDING_ARB 0x88EF |
|---|
| 115 | #endif |
|---|
| 116 | |
|---|
| 117 | namespace osg |
|---|
| 118 | { |
|---|
| 119 | |
|---|
| 120 | class State; |
|---|
| 121 | class BufferData; |
|---|
| 122 | class BufferObject; |
|---|
| 123 | |
|---|
| 124 | class BufferObjectProfile |
|---|
| 125 | { |
|---|
| 126 | public: |
|---|
| 127 | BufferObjectProfile(): |
|---|
| 128 | _target(0), |
|---|
| 129 | _usage(0), |
|---|
| 130 | _size(0) {} |
|---|
| 131 | |
|---|
| 132 | BufferObjectProfile(GLenum target, GLenum usage, unsigned int size): |
|---|
| 133 | _target(target), |
|---|
| 134 | _usage(usage), |
|---|
| 135 | _size(size) {} |
|---|
| 136 | |
|---|
| 137 | BufferObjectProfile(const BufferObjectProfile& bpo): |
|---|
| 138 | _target(bpo._target), |
|---|
| 139 | _usage(bpo._usage), |
|---|
| 140 | _size(bpo._size) {} |
|---|
| 141 | |
|---|
| 142 | bool operator < (const BufferObjectProfile& rhs) const |
|---|
| 143 | { |
|---|
| 144 | if (_target < rhs._target) return true; |
|---|
| 145 | else if (_target > rhs._target) return false; |
|---|
| 146 | if (_usage < rhs._usage) return true; |
|---|
| 147 | else if (_usage > rhs._usage) return false; |
|---|
| 148 | return _size < rhs._size; |
|---|
| 149 | } |
|---|
| 150 | |
|---|
| 151 | bool operator == (const BufferObjectProfile& rhs) const |
|---|
| 152 | { |
|---|
| 153 | return (_target == rhs._target) && |
|---|
| 154 | (_usage == rhs._usage) && |
|---|
| 155 | (_size == rhs._size); |
|---|
| 156 | } |
|---|
| 157 | |
|---|
| 158 | void setProfile(GLenum target, GLenum usage, unsigned int size) |
|---|
| 159 | { |
|---|
| 160 | _target = target; |
|---|
| 161 | _usage = usage; |
|---|
| 162 | _size = size; |
|---|
| 163 | } |
|---|
| 164 | |
|---|
| 165 | BufferObjectProfile& operator = (const BufferObjectProfile& rhs) |
|---|
| 166 | { |
|---|
| 167 | _target = rhs._target; |
|---|
| 168 | _usage = rhs._usage; |
|---|
| 169 | _size = rhs._size; |
|---|
| 170 | return *this; |
|---|
| 171 | } |
|---|
| 172 | |
|---|
| 173 | GLenum _target; |
|---|
| 174 | GLenum _usage; |
|---|
| 175 | GLenum _size; |
|---|
| 176 | }; |
|---|
| 177 | |
|---|
| 178 | // forward declare |
|---|
| 179 | class GLBufferObjectSet; |
|---|
| 180 | class GLBufferObjectManager; |
|---|
| 181 | |
|---|
| 182 | class OSG_EXPORT GLBufferObject : public Referenced |
|---|
| 183 | { |
|---|
| 184 | public: |
|---|
| 185 | |
|---|
| 186 | GLBufferObject(unsigned int contextID, BufferObject* bufferObject, unsigned int glObjectID=0); |
|---|
| 187 | |
|---|
| 188 | void setProfile(const BufferObjectProfile& profile) { _profile = profile; } |
|---|
| 189 | const BufferObjectProfile& getProfile() const { return _profile; } |
|---|
| 190 | |
|---|
| 191 | void setBufferObject(BufferObject* bufferObject); |
|---|
| 192 | BufferObject* getBufferObject() { return _bufferObject; } |
|---|
| 193 | |
|---|
| 194 | struct BufferEntry |
|---|
| 195 | { |
|---|
| 196 | BufferEntry(): modifiedCount(0),dataSize(0),offset(0),dataSource(0) {} |
|---|
| 197 | |
|---|
| 198 | BufferEntry(const BufferEntry& rhs): |
|---|
| 199 | modifiedCount(rhs.modifiedCount), |
|---|
| 200 | dataSize(rhs.dataSize), |
|---|
| 201 | offset(rhs.offset), |
|---|
| 202 | dataSource(rhs.dataSource) {} |
|---|
| 203 | |
|---|
| 204 | BufferEntry& operator = (const BufferEntry& rhs) |
|---|
| 205 | { |
|---|
| 206 | if (&rhs==this) return *this; |
|---|
| 207 | modifiedCount = rhs.modifiedCount; |
|---|
| 208 | dataSize = rhs.dataSize; |
|---|
| 209 | offset = rhs.offset; |
|---|
| 210 | dataSource = rhs.dataSource; |
|---|
| 211 | return *this; |
|---|
| 212 | } |
|---|
| 213 | |
|---|
| 214 | unsigned int modifiedCount; |
|---|
| 215 | unsigned int dataSize; |
|---|
| 216 | unsigned int offset; |
|---|
| 217 | BufferData* dataSource; |
|---|
| 218 | }; |
|---|
| 219 | |
|---|
| 220 | inline unsigned int getContextID() const { return _contextID; } |
|---|
| 221 | |
|---|
| 222 | inline GLuint& getGLObjectID() { return _glObjectID; } |
|---|
| 223 | inline GLuint getGLObjectID() const { return _glObjectID; } |
|---|
| 224 | inline GLsizeiptrARB getOffset(unsigned int i) const { return _bufferEntries[i].offset; } |
|---|
| 225 | |
|---|
| 226 | inline void bindBuffer(); |
|---|
| 227 | |
|---|
| 228 | inline void unbindBuffer() |
|---|
| 229 | { |
|---|
| 230 | _extensions->glBindBuffer(_profile._target,0); |
|---|
| 231 | } |
|---|
| 232 | |
|---|
| 233 | inline bool isDirty() const { return _dirty; } |
|---|
| 234 | |
|---|
| 235 | void dirty() { _dirty = true; } |
|---|
| 236 | |
|---|
| 237 | void clear(); |
|---|
| 238 | |
|---|
| 239 | void compileBuffer(); |
|---|
| 240 | |
|---|
| 241 | void deleteGLObject(); |
|---|
| 242 | |
|---|
| 243 | void assign(BufferObject* bufferObject); |
|---|
| 244 | |
|---|
| 245 | bool isPBOSupported() const { return _extensions->isPBOSupported(); } |
|---|
| 246 | |
|---|
| 247 | static GLBufferObject* createGLBufferObject(unsigned int contextID, const BufferObject* bufferObject); |
|---|
| 248 | |
|---|
| 249 | static void deleteAllBufferObjects(unsigned int contextID); |
|---|
| 250 | static void discardAllBufferObjects(unsigned int contextID); |
|---|
| 251 | static void flushAllDeletedBufferObjects(unsigned int contextID); |
|---|
| 252 | static void discardAllDeletedBufferObjects(unsigned int contextID); |
|---|
| 253 | static void flushDeletedBufferObjects(unsigned int contextID,double currentTime, double& availbleTime); |
|---|
| 254 | static void releaseGLBufferObject(unsigned int contextID, GLBufferObject* to); |
|---|
| 255 | |
|---|
| 256 | /** Extensions class which encapsulates the querying of extensions and |
|---|
| 257 | * associated function pointers, and provide convenience wrappers to |
|---|
| 258 | * check for the extensions or use the associated functions.*/ |
|---|
| 259 | class OSG_EXPORT Extensions : public osg::Referenced |
|---|
| 260 | { |
|---|
| 261 | public: |
|---|
| 262 | Extensions(unsigned int contextID); |
|---|
| 263 | |
|---|
| 264 | Extensions(const Extensions& rhs); |
|---|
| 265 | |
|---|
| 266 | void lowestCommonDenominator(const Extensions& rhs); |
|---|
| 267 | |
|---|
| 268 | void setupGLExtensions(unsigned int contextID); |
|---|
| 269 | |
|---|
| 270 | bool isBufferObjectSupported() const { return _glGenBuffers!=0; } |
|---|
| 271 | bool isPBOSupported() const { return _isPBOSupported; } |
|---|
| 272 | bool isUniformBufferObjectSupported() const { return _isUniformBufferObjectSupported; } |
|---|
| 273 | |
|---|
| 274 | void glGenBuffers (GLsizei n, GLuint *buffers) const; |
|---|
| 275 | void glBindBuffer (GLenum target, GLuint buffer) const; |
|---|
| 276 | void glBufferData (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage) const; |
|---|
| 277 | void glBufferSubData (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data) const; |
|---|
| 278 | void glDeleteBuffers (GLsizei n, const GLuint *buffers) const; |
|---|
| 279 | GLboolean glIsBuffer (GLuint buffer) const; |
|---|
| 280 | void glGetBufferSubData (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data) const; |
|---|
| 281 | GLvoid* glMapBuffer (GLenum target, GLenum access) const; |
|---|
| 282 | GLboolean glUnmapBuffer (GLenum target) const; |
|---|
| 283 | void glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params) const; |
|---|
| 284 | void glGetBufferPointerv (GLenum target, GLenum pname, GLvoid* *params) const; |
|---|
| 285 | void glBindBufferRange (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); |
|---|
| 286 | void glBindBufferBase (GLenum target, GLuint index, GLuint buffer); |
|---|
| 287 | |
|---|
| 288 | protected: |
|---|
| 289 | |
|---|
| 290 | typedef void (GL_APIENTRY * GenBuffersProc) (GLsizei n, GLuint *buffers); |
|---|
| 291 | typedef void (GL_APIENTRY * BindBufferProc) (GLenum target, GLuint buffer); |
|---|
| 292 | typedef void (GL_APIENTRY * BufferDataProc) (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage); |
|---|
| 293 | typedef void (GL_APIENTRY * BufferSubDataProc) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data); |
|---|
| 294 | typedef void (GL_APIENTRY * DeleteBuffersProc) (GLsizei n, const GLuint *buffers); |
|---|
| 295 | typedef GLboolean (GL_APIENTRY * IsBufferProc) (GLuint buffer); |
|---|
| 296 | typedef void (GL_APIENTRY * GetBufferSubDataProc) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data); |
|---|
| 297 | typedef GLvoid* (GL_APIENTRY * MapBufferProc) (GLenum target, GLenum access); |
|---|
| 298 | typedef GLboolean (GL_APIENTRY * UnmapBufferProc) (GLenum target); |
|---|
| 299 | typedef void (GL_APIENTRY * GetBufferParameterivProc) (GLenum target, GLenum pname, GLint *params); |
|---|
| 300 | typedef void (GL_APIENTRY * GetBufferPointervProc) (GLenum target, GLenum pname, GLvoid* *params); |
|---|
| 301 | typedef void (GL_APIENTRY * BindBufferRangeProc) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); |
|---|
| 302 | typedef void (GL_APIENTRY * BindBufferBaseProc) (GLenum target, GLuint index, GLuint buffer); |
|---|
| 303 | |
|---|
| 304 | |
|---|
| 305 | GenBuffersProc _glGenBuffers; |
|---|
| 306 | BindBufferProc _glBindBuffer; |
|---|
| 307 | BufferDataProc _glBufferData; |
|---|
| 308 | BufferSubDataProc _glBufferSubData; |
|---|
| 309 | DeleteBuffersProc _glDeleteBuffers; |
|---|
| 310 | IsBufferProc _glIsBuffer; |
|---|
| 311 | GetBufferSubDataProc _glGetBufferSubData; |
|---|
| 312 | MapBufferProc _glMapBuffer; |
|---|
| 313 | UnmapBufferProc _glUnmapBuffer; |
|---|
| 314 | GetBufferParameterivProc _glGetBufferParameteriv; |
|---|
| 315 | GetBufferPointervProc _glGetBufferPointerv; |
|---|
| 316 | BindBufferRangeProc _glBindBufferRange; |
|---|
| 317 | BindBufferBaseProc _glBindBufferBase; |
|---|
| 318 | |
|---|
| 319 | bool _isPBOSupported; |
|---|
| 320 | bool _isUniformBufferObjectSupported; |
|---|
| 321 | }; |
|---|
| 322 | |
|---|
| 323 | /** Function to call to get the extension of a specified context. |
|---|
| 324 | * If the Extension object for that context has not yet been created |
|---|
| 325 | * and the 'createIfNotInitalized' flag been set to false then returns NULL. |
|---|
| 326 | * If 'createIfNotInitalized' is true then the Extensions object is |
|---|
| 327 | * automatically created. However, in this case the extension object is |
|---|
| 328 | * only created with the graphics context associated with ContextID..*/ |
|---|
| 329 | static Extensions* getExtensions(unsigned int contextID,bool createIfNotInitalized); |
|---|
| 330 | |
|---|
| 331 | /** setExtensions allows users to override the extensions across graphics contexts. |
|---|
| 332 | * typically used when you have different extensions supported across graphics pipes |
|---|
| 333 | * but need to ensure that they all use the same low common denominator extensions.*/ |
|---|
| 334 | static void setExtensions(unsigned int contextID,Extensions* extensions); |
|---|
| 335 | |
|---|
| 336 | protected: |
|---|
| 337 | |
|---|
| 338 | virtual ~GLBufferObject(); |
|---|
| 339 | |
|---|
| 340 | unsigned int computeBufferAlignment(unsigned int pos, unsigned int bufferAlignment) const |
|---|
| 341 | { |
|---|
| 342 | if (bufferAlignment<2) return pos; |
|---|
| 343 | if ((pos%bufferAlignment)==0) return pos; |
|---|
| 344 | return ((pos/bufferAlignment)+1)*bufferAlignment; |
|---|
| 345 | } |
|---|
| 346 | |
|---|
| 347 | unsigned int _contextID; |
|---|
| 348 | GLuint _glObjectID; |
|---|
| 349 | |
|---|
| 350 | BufferObjectProfile _profile; |
|---|
| 351 | unsigned int _allocatedSize; |
|---|
| 352 | |
|---|
| 353 | bool _dirty; |
|---|
| 354 | |
|---|
| 355 | typedef std::vector<BufferEntry> BufferEntries; |
|---|
| 356 | BufferEntries _bufferEntries; |
|---|
| 357 | |
|---|
| 358 | BufferObject* _bufferObject; |
|---|
| 359 | |
|---|
| 360 | public: |
|---|
| 361 | |
|---|
| 362 | GLBufferObjectSet* _set; |
|---|
| 363 | GLBufferObject* _previous; |
|---|
| 364 | GLBufferObject* _next; |
|---|
| 365 | unsigned int _frameLastUsed; |
|---|
| 366 | |
|---|
| 367 | public: |
|---|
| 368 | Extensions* _extensions; |
|---|
| 369 | |
|---|
| 370 | }; |
|---|
| 371 | |
|---|
| 372 | typedef std::list< ref_ptr<GLBufferObject> > GLBufferObjectList; |
|---|
| 373 | |
|---|
| 374 | class OSG_EXPORT GLBufferObjectSet : public Referenced |
|---|
| 375 | { |
|---|
| 376 | public: |
|---|
| 377 | GLBufferObjectSet(GLBufferObjectManager* parent, const BufferObjectProfile& profile); |
|---|
| 378 | |
|---|
| 379 | const BufferObjectProfile& getProfile() const { return _profile; } |
|---|
| 380 | |
|---|
| 381 | void handlePendingOrphandedGLBufferObjects(); |
|---|
| 382 | |
|---|
| 383 | void deleteAllGLBufferObjects(); |
|---|
| 384 | void discardAllGLBufferObjects(); |
|---|
| 385 | void flushAllDeletedGLBufferObjects(); |
|---|
| 386 | void discardAllDeletedGLBufferObjects(); |
|---|
| 387 | void flushDeletedGLBufferObjects(double currentTime, double& availableTime); |
|---|
| 388 | |
|---|
| 389 | GLBufferObject* takeFromOrphans(BufferObject* bufferObject); |
|---|
| 390 | GLBufferObject* takeOrGenerate(BufferObject* bufferObject); |
|---|
| 391 | |
|---|
| 392 | void moveToBack(GLBufferObject* to); |
|---|
| 393 | void addToBack(GLBufferObject* to); |
|---|
| 394 | void orphan(GLBufferObject* to); |
|---|
| 395 | void remove(GLBufferObject* to); |
|---|
| 396 | void moveToSet(GLBufferObject* to, GLBufferObjectSet* set); |
|---|
| 397 | |
|---|
| 398 | unsigned int size() const { return _profile._size * _numOfGLBufferObjects; } |
|---|
| 399 | |
|---|
| 400 | bool makeSpace(unsigned int& size); |
|---|
| 401 | |
|---|
| 402 | bool checkConsistency() const; |
|---|
| 403 | |
|---|
| 404 | GLBufferObjectManager* getParent() { return _parent; } |
|---|
| 405 | |
|---|
| 406 | unsigned int computeNumGLBufferObjectsInList() const; |
|---|
| 407 | unsigned int getNumOfGLBufferObjects() const { return _numOfGLBufferObjects; } |
|---|
| 408 | unsigned int getNumOrphans() const { return _orphanedGLBufferObjects.size(); } |
|---|
| 409 | unsigned int getNumPendingOrphans() const { return _pendingOrphanedGLBufferObjects.size(); } |
|---|
| 410 | |
|---|
| 411 | |
|---|
| 412 | protected: |
|---|
| 413 | |
|---|
| 414 | virtual ~GLBufferObjectSet(); |
|---|
| 415 | |
|---|
| 416 | OpenThreads::Mutex _mutex; |
|---|
| 417 | |
|---|
| 418 | GLBufferObjectManager* _parent; |
|---|
| 419 | unsigned int _contextID; |
|---|
| 420 | BufferObjectProfile _profile; |
|---|
| 421 | unsigned int _numOfGLBufferObjects; |
|---|
| 422 | GLBufferObjectList _orphanedGLBufferObjects; |
|---|
| 423 | GLBufferObjectList _pendingOrphanedGLBufferObjects; |
|---|
| 424 | |
|---|
| 425 | GLBufferObject* _head; |
|---|
| 426 | GLBufferObject* _tail; |
|---|
| 427 | }; |
|---|
| 428 | |
|---|
| 429 | class OSG_EXPORT GLBufferObjectManager : public osg::Referenced |
|---|
| 430 | { |
|---|
| 431 | public: |
|---|
| 432 | GLBufferObjectManager(unsigned int contextID); |
|---|
| 433 | |
|---|
| 434 | unsigned int getContextID() const { return _contextID; } |
|---|
| 435 | |
|---|
| 436 | |
|---|
| 437 | void setNumberActiveGLBufferObjects(unsigned int size) { _numActiveGLBufferObjects = size; } |
|---|
| 438 | unsigned int& getNumberActiveGLBufferObjects() { return _numActiveGLBufferObjects; } |
|---|
| 439 | unsigned int getNumberActiveGLBufferObjects() const { return _numActiveGLBufferObjects; } |
|---|
| 440 | |
|---|
| 441 | void setNumberOrphanedGLBufferObjects(unsigned int size) { _numOrphanedGLBufferObjects = size; } |
|---|
| 442 | unsigned int& getNumberOrphanedGLBufferObjects() { return _numOrphanedGLBufferObjects; } |
|---|
| 443 | unsigned int getNumberOrphanedGLBufferObjects() const { return _numOrphanedGLBufferObjects; } |
|---|
| 444 | |
|---|
| 445 | void setCurrGLBufferObjectPoolSize(unsigned int size) { _currGLBufferObjectPoolSize = size; } |
|---|
| 446 | unsigned int& getCurrGLBufferObjectPoolSize() { return _currGLBufferObjectPoolSize; } |
|---|
| 447 | unsigned int getCurrGLBufferObjectPoolSize() const { return _currGLBufferObjectPoolSize; } |
|---|
| 448 | |
|---|
| 449 | void setMaxGLBufferObjectPoolSize(unsigned int size); |
|---|
| 450 | unsigned int getMaxGLBufferObjectPoolSize() const { return _maxGLBufferObjectPoolSize; } |
|---|
| 451 | |
|---|
| 452 | bool hasSpace(unsigned int size) const { return (_currGLBufferObjectPoolSize+size)<=_maxGLBufferObjectPoolSize; } |
|---|
| 453 | bool makeSpace(unsigned int size); |
|---|
| 454 | |
|---|
| 455 | GLBufferObject* generateGLBufferObject(const osg::BufferObject* bufferObject); |
|---|
| 456 | |
|---|
| 457 | void handlePendingOrphandedGLBufferObjects(); |
|---|
| 458 | |
|---|
| 459 | void deleteAllGLBufferObjects(); |
|---|
| 460 | void discardAllGLBufferObjects(); |
|---|
| 461 | void flushAllDeletedGLBufferObjects(); |
|---|
| 462 | void discardAllDeletedGLBufferObjects(); |
|---|
| 463 | void flushDeletedGLBufferObjects(double currentTime, double& availableTime); |
|---|
| 464 | void releaseGLBufferObject(GLBufferObject* to); |
|---|
| 465 | |
|---|
| 466 | GLBufferObjectSet* getGLBufferObjectSet(const BufferObjectProfile& profile); |
|---|
| 467 | |
|---|
| 468 | void newFrame(osg::FrameStamp* fs); |
|---|
| 469 | void resetStats(); |
|---|
| 470 | void reportStats(std::ostream& out); |
|---|
| 471 | void recomputeStats(std::ostream& out); |
|---|
| 472 | |
|---|
| 473 | unsigned int& getFrameNumber() { return _frameNumber; } |
|---|
| 474 | unsigned int& getNumberFrames() { return _numFrames; } |
|---|
| 475 | |
|---|
| 476 | unsigned int& getNumberDeleted() { return _numDeleted; } |
|---|
| 477 | double& getDeleteTime() { return _deleteTime; } |
|---|
| 478 | |
|---|
| 479 | unsigned int& getNumberGenerated() { return _numGenerated; } |
|---|
| 480 | double& getGenerateTime() { return _generateTime; } |
|---|
| 481 | |
|---|
| 482 | unsigned int& getNumberApplied() { return _numApplied; } |
|---|
| 483 | double& getApplyTime() { return _applyTime; } |
|---|
| 484 | |
|---|
| 485 | static osg::ref_ptr<GLBufferObjectManager>& getGLBufferObjectManager(unsigned int contextID); |
|---|
| 486 | |
|---|
| 487 | protected: |
|---|
| 488 | |
|---|
| 489 | typedef std::map< BufferObjectProfile, osg::ref_ptr<GLBufferObjectSet> > GLBufferObjectSetMap; |
|---|
| 490 | unsigned int _contextID; |
|---|
| 491 | unsigned int _numActiveGLBufferObjects; |
|---|
| 492 | unsigned int _numOrphanedGLBufferObjects; |
|---|
| 493 | unsigned int _currGLBufferObjectPoolSize; |
|---|
| 494 | unsigned int _maxGLBufferObjectPoolSize; |
|---|
| 495 | GLBufferObjectSetMap _glBufferObjectSetMap; |
|---|
| 496 | |
|---|
| 497 | unsigned int _frameNumber; |
|---|
| 498 | |
|---|
| 499 | unsigned int _numFrames; |
|---|
| 500 | unsigned int _numDeleted; |
|---|
| 501 | double _deleteTime; |
|---|
| 502 | |
|---|
| 503 | unsigned int _numGenerated; |
|---|
| 504 | double _generateTime; |
|---|
| 505 | |
|---|
| 506 | unsigned int _numApplied; |
|---|
| 507 | double _applyTime; |
|---|
| 508 | |
|---|
| 509 | }; |
|---|
| 510 | |
|---|
| 511 | |
|---|
| 512 | class OSG_EXPORT BufferObject : public Object |
|---|
| 513 | { |
|---|
| 514 | public: |
|---|
| 515 | |
|---|
| 516 | BufferObject(); |
|---|
| 517 | |
|---|
| 518 | /** Copy constructor using CopyOp to manage deep vs shallow copy.*/ |
|---|
| 519 | BufferObject(const BufferObject& bo,const CopyOp& copyop=CopyOp::SHALLOW_COPY); |
|---|
| 520 | |
|---|
| 521 | virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const BufferObject*>(obj)!=NULL; } |
|---|
| 522 | virtual const char* libraryName() const { return "osg"; } |
|---|
| 523 | virtual const char* className() const { return "BufferObject"; } |
|---|
| 524 | |
|---|
| 525 | void setTarget(GLenum target) { _profile._target = target; } |
|---|
| 526 | GLenum getTarget() const { return _profile._target; } |
|---|
| 527 | |
|---|
| 528 | /** Set what type of usage the buffer object will have. Options are: |
|---|
| 529 | * GL_STREAM_DRAW, GL_STREAM_READ, GL_STREAM_COPY, |
|---|
| 530 | * GL_STATIC_DRAW, GL_STATIC_READ, GL_STATIC_COPY, |
|---|
| 531 | * GL_DYNAMIC_DRAW, GL_DYNAMIC_READ, or GL_DYNAMIC_COPY. |
|---|
| 532 | */ |
|---|
| 533 | void setUsage(GLenum usage) { _profile._usage = usage; } |
|---|
| 534 | |
|---|
| 535 | /** Get the type of usage the buffer object has been set up for.*/ |
|---|
| 536 | GLenum getUsage() const { return _profile._usage; } |
|---|
| 537 | |
|---|
| 538 | BufferObjectProfile& getProfile() { return _profile; } |
|---|
| 539 | const BufferObjectProfile& getProfile() const { return _profile; } |
|---|
| 540 | |
|---|
| 541 | |
|---|
| 542 | /** Set whether the BufferObject should use a GLBufferObject just for copying the BufferData and release it immmediately so that it may be reused.*/ |
|---|
| 543 | void setCopyDataAndReleaseGLBufferObject(bool copyAndRelease) { _copyDataAndReleaseGLBufferObject = copyAndRelease; } |
|---|
| 544 | |
|---|
| 545 | /** Get whether the BufferObject should use a GLBufferObject just for copying the BufferData and release it immmediately.*/ |
|---|
| 546 | bool getCopyDataAndReleaseGLBufferObject() const { return _copyDataAndReleaseGLBufferObject; } |
|---|
| 547 | |
|---|
| 548 | |
|---|
| 549 | void dirty(); |
|---|
| 550 | |
|---|
| 551 | /** Resize any per context GLObject buffers to specified size. */ |
|---|
| 552 | virtual void resizeGLObjectBuffers(unsigned int maxSize); |
|---|
| 553 | |
|---|
| 554 | /** If State is non-zero, this function releases OpenGL objects for |
|---|
| 555 | * the specified graphics context. Otherwise, releases OpenGL objects |
|---|
| 556 | * for all graphics contexts. */ |
|---|
| 557 | void releaseGLObjects(State* state=0) const; |
|---|
| 558 | |
|---|
| 559 | unsigned int addBufferData(BufferData* bd); |
|---|
| 560 | void removeBufferData(unsigned int index); |
|---|
| 561 | void removeBufferData(BufferData* bd); |
|---|
| 562 | |
|---|
| 563 | void setBufferData(unsigned int index, BufferData* bd); |
|---|
| 564 | BufferData* getBufferData(unsigned int index) { return _bufferDataList[index]; } |
|---|
| 565 | const BufferData* getBufferData(unsigned int index) const { return _bufferDataList[index]; } |
|---|
| 566 | |
|---|
| 567 | unsigned int getNumBufferData() const { return _bufferDataList.size(); } |
|---|
| 568 | |
|---|
| 569 | void setGLBufferObject(unsigned int contextID, GLBufferObject* glbo) { _glBufferObjects[contextID] = glbo; } |
|---|
| 570 | |
|---|
| 571 | GLBufferObject* getGLBufferObject(unsigned int contextID) const { return _glBufferObjects[contextID].get(); } |
|---|
| 572 | |
|---|
| 573 | GLBufferObject* getOrCreateGLBufferObject(unsigned int contextID) const |
|---|
| 574 | { |
|---|
| 575 | if (!_glBufferObjects[contextID]) _glBufferObjects[contextID] = GLBufferObject::createGLBufferObject(contextID, this); |
|---|
| 576 | return _glBufferObjects[contextID].get(); |
|---|
| 577 | } |
|---|
| 578 | |
|---|
| 579 | unsigned int computeRequiredBufferSize() const; |
|---|
| 580 | |
|---|
| 581 | /** deprecated, provided for backwards compatibility.*/ |
|---|
| 582 | static void deleteBufferObject(unsigned int contextID,GLuint globj); |
|---|
| 583 | |
|---|
| 584 | protected: |
|---|
| 585 | |
|---|
| 586 | ~BufferObject(); |
|---|
| 587 | |
|---|
| 588 | typedef std::vector< BufferData* > BufferDataList; |
|---|
| 589 | typedef osg::buffered_object< osg::ref_ptr<GLBufferObject> > GLBufferObjects; |
|---|
| 590 | |
|---|
| 591 | BufferObjectProfile _profile; |
|---|
| 592 | |
|---|
| 593 | bool _copyDataAndReleaseGLBufferObject; |
|---|
| 594 | |
|---|
| 595 | BufferDataList _bufferDataList; |
|---|
| 596 | |
|---|
| 597 | mutable GLBufferObjects _glBufferObjects; |
|---|
| 598 | }; |
|---|
| 599 | |
|---|
| 600 | class OSG_EXPORT BufferData : public Object |
|---|
| 601 | { |
|---|
| 602 | public: |
|---|
| 603 | |
|---|
| 604 | BufferData(): |
|---|
| 605 | Object(true), |
|---|
| 606 | _modifiedCount(0), |
|---|
| 607 | _bufferIndex(0) {} |
|---|
| 608 | |
|---|
| 609 | /** Copy constructor using CopyOp to manage deep vs shallow copy.*/ |
|---|
| 610 | BufferData(const BufferData& bd,const CopyOp& copyop=CopyOp::SHALLOW_COPY): |
|---|
| 611 | osg::Object(bd,copyop), |
|---|
| 612 | _modifiedCount(0), |
|---|
| 613 | _bufferIndex(0), |
|---|
| 614 | _modifiedCallback(bd._modifiedCallback) {} |
|---|
| 615 | |
|---|
| 616 | virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const BufferData*>(obj)!=NULL; } |
|---|
| 617 | virtual const char* libraryName() const { return "osg"; } |
|---|
| 618 | virtual const char* className() const { return "BufferData"; } |
|---|
| 619 | |
|---|
| 620 | virtual const GLvoid* getDataPointer() const = 0; |
|---|
| 621 | virtual unsigned int getTotalDataSize() const = 0; |
|---|
| 622 | |
|---|
| 623 | virtual osg::Array* asArray() { return 0; } |
|---|
| 624 | virtual const osg::Array* asArray() const { return 0; } |
|---|
| 625 | |
|---|
| 626 | virtual osg::PrimitiveSet* asPrimitiveSet() { return 0; } |
|---|
| 627 | virtual const osg::PrimitiveSet* asPrimitiveSet() const { return 0; } |
|---|
| 628 | |
|---|
| 629 | virtual osg::Image* asImage() { return 0; } |
|---|
| 630 | virtual const osg::Image* asImage() const { return 0; } |
|---|
| 631 | |
|---|
| 632 | void setBufferObject(BufferObject* bufferObject); |
|---|
| 633 | BufferObject* getBufferObject() { return _bufferObject.get(); } |
|---|
| 634 | const BufferObject* getBufferObject() const { return _bufferObject.get(); } |
|---|
| 635 | |
|---|
| 636 | void setBufferIndex(unsigned int index) { _bufferIndex = index; } |
|---|
| 637 | unsigned int getBufferIndex() const { return _bufferIndex; } |
|---|
| 638 | |
|---|
| 639 | GLBufferObject* getGLBufferObject(unsigned int contextID) const { return _bufferObject.valid() ? _bufferObject->getGLBufferObject(contextID) : 0; } |
|---|
| 640 | GLBufferObject* getOrCreateGLBufferObject(unsigned int contextID) const { return _bufferObject.valid() ? _bufferObject->getOrCreateGLBufferObject(contextID) : 0; } |
|---|
| 641 | |
|---|
| 642 | struct ModifiedCallback : public virtual osg::Object |
|---|
| 643 | { |
|---|
| 644 | ModifiedCallback() {} |
|---|
| 645 | |
|---|
| 646 | ModifiedCallback(const ModifiedCallback&,const CopyOp&) {} |
|---|
| 647 | |
|---|
| 648 | META_Object(osg,ModifiedCallback); |
|---|
| 649 | |
|---|
| 650 | virtual void modified(BufferData* /*bufferData*/) const {} |
|---|
| 651 | }; |
|---|
| 652 | |
|---|
| 653 | void setModifiedCallback(ModifiedCallback* md) { _modifiedCallback = md; } |
|---|
| 654 | ModifiedCallback* getModifiedCallback() { return _modifiedCallback.get(); } |
|---|
| 655 | const ModifiedCallback* getModifiedCallback() const { return _modifiedCallback.get(); } |
|---|
| 656 | |
|---|
| 657 | /** Dirty the primitive, which increments the modified count, to force buffer objects to update. |
|---|
| 658 | * If a ModifiedCallback is attached to this BufferData then the callback is called prior to the bufferObject's dirty is called. */ |
|---|
| 659 | inline void dirty() |
|---|
| 660 | { |
|---|
| 661 | ++_modifiedCount; |
|---|
| 662 | if (_modifiedCallback.valid()) _modifiedCallback->modified(this); |
|---|
| 663 | if (_bufferObject.valid()) _bufferObject->dirty(); |
|---|
| 664 | } |
|---|
| 665 | |
|---|
| 666 | /** Set the modified count value.*/ |
|---|
| 667 | inline void setModifiedCount(unsigned int value) { _modifiedCount=value; } |
|---|
| 668 | |
|---|
| 669 | /** Get modified count value.*/ |
|---|
| 670 | inline unsigned int getModifiedCount() const { return _modifiedCount; } |
|---|
| 671 | |
|---|
| 672 | /** Resize any per context GLObject buffers to specified size. */ |
|---|
| 673 | virtual void resizeGLObjectBuffers(unsigned int maxSize); |
|---|
| 674 | |
|---|
| 675 | /** If State is non-zero, this function releases OpenGL objects for |
|---|
| 676 | * the specified graphics context. Otherwise, releases OpenGL objects |
|---|
| 677 | * for all graphics contexts. */ |
|---|
| 678 | void releaseGLObjects(State* state=0) const; |
|---|
| 679 | |
|---|
| 680 | protected: |
|---|
| 681 | |
|---|
| 682 | virtual ~BufferData(); |
|---|
| 683 | |
|---|
| 684 | unsigned int _modifiedCount; |
|---|
| 685 | |
|---|
| 686 | unsigned int _bufferIndex; |
|---|
| 687 | osg::ref_ptr<BufferObject> _bufferObject; |
|---|
| 688 | osg::ref_ptr<ModifiedCallback> _modifiedCallback; |
|---|
| 689 | }; |
|---|
| 690 | |
|---|
| 691 | |
|---|
| 692 | class Array; |
|---|
| 693 | class OSG_EXPORT VertexBufferObject : public BufferObject |
|---|
| 694 | { |
|---|
| 695 | public: |
|---|
| 696 | |
|---|
| 697 | VertexBufferObject(); |
|---|
| 698 | |
|---|
| 699 | /** Copy constructor using CopyOp to manage deep vs shallow copy.*/ |
|---|
| 700 | VertexBufferObject(const VertexBufferObject& vbo,const CopyOp& copyop=CopyOp::SHALLOW_COPY); |
|---|
| 701 | |
|---|
| 702 | META_Object(osg,VertexBufferObject); |
|---|
| 703 | |
|---|
| 704 | unsigned int addArray(osg::Array* array); |
|---|
| 705 | void removeArray(osg::Array* array); |
|---|
| 706 | |
|---|
| 707 | void setArray(unsigned int i, Array* array); |
|---|
| 708 | Array* getArray(unsigned int i); |
|---|
| 709 | const Array* getArray(unsigned int i) const; |
|---|
| 710 | |
|---|
| 711 | protected: |
|---|
| 712 | virtual ~VertexBufferObject(); |
|---|
| 713 | }; |
|---|
| 714 | |
|---|
| 715 | class DrawElements; |
|---|
| 716 | class OSG_EXPORT ElementBufferObject : public BufferObject |
|---|
| 717 | { |
|---|
| 718 | public: |
|---|
| 719 | |
|---|
| 720 | ElementBufferObject(); |
|---|
| 721 | |
|---|
| 722 | /** Copy constructor using CopyOp to manage deep vs shallow copy.*/ |
|---|
| 723 | ElementBufferObject(const ElementBufferObject& pbo,const CopyOp& copyop=CopyOp::SHALLOW_COPY); |
|---|
| 724 | |
|---|
| 725 | META_Object(osg,ElementBufferObject); |
|---|
| 726 | |
|---|
| 727 | unsigned int addDrawElements(osg::DrawElements* PrimitiveSet); |
|---|
| 728 | void removeDrawElements(osg::DrawElements* PrimitiveSet); |
|---|
| 729 | |
|---|
| 730 | void setDrawElements(unsigned int i, DrawElements* PrimitiveSet); |
|---|
| 731 | DrawElements* getDrawElements(unsigned int i); |
|---|
| 732 | const DrawElements* getDrawElements(unsigned int i) const; |
|---|
| 733 | |
|---|
| 734 | protected: |
|---|
| 735 | |
|---|
| 736 | virtual ~ElementBufferObject(); |
|---|
| 737 | }; |
|---|
| 738 | |
|---|
| 739 | class Image; |
|---|
| 740 | class OSG_EXPORT PixelBufferObject : public BufferObject |
|---|
| 741 | { |
|---|
| 742 | public: |
|---|
| 743 | |
|---|
| 744 | PixelBufferObject(osg::Image* image=0); |
|---|
| 745 | |
|---|
| 746 | /** Copy constructor using CopyOp to manage deep vs shallow copy.*/ |
|---|
| 747 | PixelBufferObject(const PixelBufferObject& pbo,const CopyOp& copyop=CopyOp::SHALLOW_COPY); |
|---|
| 748 | |
|---|
| 749 | META_Object(osg,PixelBufferObject); |
|---|
| 750 | |
|---|
| 751 | void setImage(osg::Image* image); |
|---|
| 752 | |
|---|
| 753 | Image* getImage(); |
|---|
| 754 | const Image* getImage() const; |
|---|
| 755 | |
|---|
| 756 | bool isPBOSupported(unsigned int contextID) const { return _glBufferObjects[contextID]->isPBOSupported(); } |
|---|
| 757 | |
|---|
| 758 | protected: |
|---|
| 759 | |
|---|
| 760 | virtual ~PixelBufferObject(); |
|---|
| 761 | }; |
|---|
| 762 | |
|---|
| 763 | /** |
|---|
| 764 | * This object represent a general class of pixel buffer objects, |
|---|
| 765 | * which are capable of allocating buffer object (memory) |
|---|
| 766 | * on the GPU. The memory can then be used either for CPU-GPU |
|---|
| 767 | * pixel transfer or directly for GPU-GPU transfer, without CPU intervention. |
|---|
| 768 | **/ |
|---|
| 769 | class OSG_EXPORT PixelDataBufferObject : public BufferObject |
|---|
| 770 | { |
|---|
| 771 | public: |
|---|
| 772 | PixelDataBufferObject(); |
|---|
| 773 | PixelDataBufferObject(const PixelDataBufferObject& pbo, const CopyOp& copyop=CopyOp::SHALLOW_COPY); |
|---|
| 774 | |
|---|
| 775 | META_Object(osg, PixelDataBufferObject); |
|---|
| 776 | |
|---|
| 777 | //! Set new size of the buffer object. This will reallocate the memory on the next compile |
|---|
| 778 | inline void setDataSize(unsigned int size) { _profile._size = size; dirty(); } |
|---|
| 779 | |
|---|
| 780 | //! Get data size of the used buffer |
|---|
| 781 | inline unsigned int getDataSize() const { return _profile._size; } |
|---|
| 782 | |
|---|
| 783 | //! Compile the buffer (reallocate the memory if buffer is dirty) |
|---|
| 784 | virtual void compileBuffer(State& state) const; |
|---|
| 785 | |
|---|
| 786 | //! Bind the buffer in read mode, which means that data can be downloaded from the buffer (note: GL_PIXEL_UNPACK_BUFFER_ARB) |
|---|
| 787 | virtual void bindBufferInReadMode(State& state); |
|---|
| 788 | |
|---|
| 789 | //! Bind the buffer in write mode, which means following OpenGL instructions will write data into the buffer (note: GL_PIXEL_PACK_BUFFER_ARB) |
|---|
| 790 | virtual void bindBufferInWriteMode(State& state); |
|---|
| 791 | |
|---|
| 792 | //! Unbind the buffer |
|---|
| 793 | virtual void unbindBuffer(unsigned int contextID) const; |
|---|
| 794 | |
|---|
| 795 | /** Resize any per context GLObject buffers to specified size. */ |
|---|
| 796 | virtual void resizeGLObjectBuffers(unsigned int maxSize); |
|---|
| 797 | |
|---|
| 798 | enum Mode |
|---|
| 799 | { |
|---|
| 800 | //! A normal mode of this data buffer |
|---|
| 801 | NONE = 0, |
|---|
| 802 | |
|---|
| 803 | //! Buffer is in read mode (@see bindBufferInReadMode) |
|---|
| 804 | READ = 1, |
|---|
| 805 | |
|---|
| 806 | //! Buffer is in write mode (@see bindBufferInWriteMode) |
|---|
| 807 | WRITE = 2 |
|---|
| 808 | }; |
|---|
| 809 | |
|---|
| 810 | Mode getMode(unsigned int contextID) const { return (Mode)_mode[contextID]; } |
|---|
| 811 | |
|---|
| 812 | protected: |
|---|
| 813 | |
|---|
| 814 | virtual ~PixelDataBufferObject(); |
|---|
| 815 | |
|---|
| 816 | typedef osg::buffered_value<unsigned int> ModeList; |
|---|
| 817 | |
|---|
| 818 | mutable ModeList _mode; |
|---|
| 819 | |
|---|
| 820 | }; |
|---|
| 821 | |
|---|
| 822 | class OSG_EXPORT UniformBufferObject : public BufferObject |
|---|
| 823 | { |
|---|
| 824 | public: |
|---|
| 825 | UniformBufferObject(); |
|---|
| 826 | UniformBufferObject(const UniformBufferObject& ubo, const CopyOp& copyop=CopyOp::SHALLOW_COPY); |
|---|
| 827 | META_Object(osg, UniformBufferObject); |
|---|
| 828 | protected: |
|---|
| 829 | virtual ~UniformBufferObject(); |
|---|
| 830 | }; |
|---|
| 831 | |
|---|
| 832 | inline void GLBufferObject::bindBuffer() |
|---|
| 833 | { |
|---|
| 834 | _extensions->glBindBuffer(_profile._target,_glObjectID); |
|---|
| 835 | if (_set) _set->moveToBack(this); |
|---|
| 836 | } |
|---|
| 837 | |
|---|
| 838 | } |
|---|
| 839 | |
|---|
| 840 | #endif |
|---|