[844] | 1 | /****************************************************************************
|
---|
| 2 | **
|
---|
| 3 | ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
---|
| 4 | ** All rights reserved.
|
---|
| 5 | ** Contact: Nokia Corporation ([email protected])
|
---|
| 6 | **
|
---|
| 7 | ** This file is part of the QtOpenGL module of the Qt Toolkit.
|
---|
| 8 | **
|
---|
| 9 | ** $QT_BEGIN_LICENSE:LGPL$
|
---|
| 10 | ** Commercial Usage
|
---|
| 11 | ** Licensees holding valid Qt Commercial licenses may use this file in
|
---|
| 12 | ** accordance with the Qt Commercial License Agreement provided with the
|
---|
| 13 | ** Software or, alternatively, in accordance with the terms contained in
|
---|
| 14 | ** a written agreement between you and Nokia.
|
---|
| 15 | **
|
---|
| 16 | ** GNU Lesser General Public License Usage
|
---|
| 17 | ** Alternatively, this file may be used under the terms of the GNU Lesser
|
---|
| 18 | ** General Public License version 2.1 as published by the Free Software
|
---|
| 19 | ** Foundation and appearing in the file LICENSE.LGPL included in the
|
---|
| 20 | ** packaging of this file. Please review the following information to
|
---|
| 21 | ** ensure the GNU Lesser General Public License version 2.1 requirements
|
---|
| 22 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
---|
| 23 | **
|
---|
| 24 | ** In addition, as a special exception, Nokia gives you certain additional
|
---|
| 25 | ** rights. These rights are described in the Nokia Qt LGPL Exception
|
---|
| 26 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
---|
| 27 | **
|
---|
| 28 | ** GNU General Public License Usage
|
---|
| 29 | ** Alternatively, this file may be used under the terms of the GNU
|
---|
| 30 | ** General Public License version 3.0 as published by the Free Software
|
---|
| 31 | ** Foundation and appearing in the file LICENSE.GPL included in the
|
---|
| 32 | ** packaging of this file. Please review the following information to
|
---|
| 33 | ** ensure the GNU General Public License version 3.0 requirements will be
|
---|
| 34 | ** met: http://www.gnu.org/copyleft/gpl.html.
|
---|
| 35 | **
|
---|
| 36 | ** If you have questions regarding the use of this file, please contact
|
---|
| 37 | ** Nokia at [email protected].
|
---|
| 38 | ** $QT_END_LICENSE$
|
---|
| 39 | **
|
---|
| 40 | ****************************************************************************/
|
---|
| 41 |
|
---|
| 42 | #include <QtOpenGL/qgl.h>
|
---|
| 43 | #include <QtOpenGL/private/qgl_p.h>
|
---|
| 44 | #include <QtOpenGL/private/qglextensions_p.h>
|
---|
| 45 | #include <QtCore/qatomic.h>
|
---|
| 46 | #include "qglbuffer.h"
|
---|
| 47 |
|
---|
| 48 | QT_BEGIN_NAMESPACE
|
---|
| 49 |
|
---|
| 50 | /*!
|
---|
| 51 | \class QGLBuffer
|
---|
| 52 | \brief The QGLBuffer class provides functions for creating and managing GL buffer objects.
|
---|
| 53 | \since 4.7
|
---|
| 54 | \ingroup painting-3D
|
---|
| 55 |
|
---|
| 56 | Buffer objects are created in the GL server so that the
|
---|
| 57 | client application can avoid uploading vertices, indices,
|
---|
| 58 | texture image data, etc every time they are needed.
|
---|
| 59 |
|
---|
| 60 | QGLBuffer objects can be copied around as a reference to the
|
---|
| 61 | underlying GL buffer object:
|
---|
| 62 |
|
---|
| 63 | \code
|
---|
| 64 | QGLBuffer buffer1(QGLBuffer::IndexBuffer);
|
---|
| 65 | buffer1.create();
|
---|
| 66 |
|
---|
| 67 | QGLBuffer buffer2 = buffer1;
|
---|
| 68 | \endcode
|
---|
| 69 |
|
---|
| 70 | QGLBuffer performs a shallow copy when objects are copied in this
|
---|
| 71 | manner, but does not implement copy-on-write semantics. The original
|
---|
| 72 | object will be affected whenever the copy is modified.
|
---|
| 73 | */
|
---|
| 74 |
|
---|
| 75 | /*!
|
---|
| 76 | \enum QGLBuffer::Type
|
---|
| 77 | This enum defines the type of GL buffer object to create with QGLBuffer.
|
---|
| 78 |
|
---|
| 79 | \value VertexBuffer Vertex buffer object for use when specifying
|
---|
| 80 | vertex arrays.
|
---|
| 81 | \value IndexBuffer Index buffer object for use with \c{glDrawElements()}.
|
---|
| 82 | \value PixelPackBuffer Pixel pack buffer object for reading pixel
|
---|
| 83 | data from the GL server (for example, with \c{glReadPixels()}).
|
---|
| 84 | Not supported under OpenGL/ES.
|
---|
| 85 | \value PixelUnpackBuffer Pixel unpack buffer object for writing pixel
|
---|
| 86 | data to the GL server (for example, with \c{glTexImage2D()}).
|
---|
| 87 | Not supported under OpenGL/ES.
|
---|
| 88 | */
|
---|
| 89 |
|
---|
| 90 | /*!
|
---|
| 91 | \enum QGLBuffer::UsagePattern
|
---|
| 92 | This enum defines the usage pattern of a QGLBuffer object.
|
---|
| 93 |
|
---|
| 94 | \value StreamDraw The data will be set once and used a few times
|
---|
| 95 | for drawing operations. Under OpenGL/ES 1.1 this is identical
|
---|
| 96 | to StaticDraw.
|
---|
| 97 | \value StreamRead The data will be set once and used a few times
|
---|
| 98 | for reading data back from the GL server. Not supported
|
---|
| 99 | under OpenGL/ES.
|
---|
| 100 | \value StreamCopy The data will be set once and used a few times
|
---|
| 101 | for reading data back from the GL server for use in further
|
---|
| 102 | drawing operations. Not supported under OpenGL/ES.
|
---|
| 103 | \value StaticDraw The data will be set once and used many times
|
---|
| 104 | for drawing operations.
|
---|
| 105 | \value StaticRead The data will be set once and used many times
|
---|
| 106 | for reading data back from the GL server. Not supported
|
---|
| 107 | under OpenGL/ES.
|
---|
| 108 | \value StaticCopy The data will be set once and used many times
|
---|
| 109 | for reading data back from the GL server for use in further
|
---|
| 110 | drawing operations. Not supported under OpenGL/ES.
|
---|
| 111 | \value DynamicDraw The data will be modified repeatedly and used
|
---|
| 112 | many times for drawing operations.
|
---|
| 113 | \value DynamicRead The data will be modified repeatedly and used
|
---|
| 114 | many times for reading data back from the GL server.
|
---|
| 115 | Not supported under OpenGL/ES.
|
---|
| 116 | \value DynamicCopy The data will be modified repeatedly and used
|
---|
| 117 | many times for reading data back from the GL server for
|
---|
| 118 | use in further drawing operations. Not supported under OpenGL/ES.
|
---|
| 119 | */
|
---|
| 120 |
|
---|
| 121 | /*!
|
---|
| 122 | \enum QGLBuffer::Access
|
---|
| 123 | This enum defines the access mode for QGLBuffer::map().
|
---|
| 124 |
|
---|
| 125 | \value ReadOnly The buffer will be mapped for reading only.
|
---|
| 126 | \value WriteOnly The buffer will be mapped for writing only.
|
---|
| 127 | \value ReadWrite The buffer will be mapped for reading and writing.
|
---|
| 128 | */
|
---|
| 129 |
|
---|
| 130 | class QGLBufferPrivate
|
---|
| 131 | {
|
---|
| 132 | public:
|
---|
| 133 | QGLBufferPrivate(QGLBuffer::Type t)
|
---|
| 134 | : ref(1),
|
---|
| 135 | type(t),
|
---|
| 136 | guard(0),
|
---|
| 137 | usagePattern(QGLBuffer::StaticDraw),
|
---|
| 138 | actualUsagePattern(QGLBuffer::StaticDraw)
|
---|
| 139 | {
|
---|
| 140 | }
|
---|
| 141 |
|
---|
| 142 | QAtomicInt ref;
|
---|
| 143 | QGLBuffer::Type type;
|
---|
| 144 | QGLSharedResourceGuard guard;
|
---|
| 145 | QGLBuffer::UsagePattern usagePattern;
|
---|
| 146 | QGLBuffer::UsagePattern actualUsagePattern;
|
---|
| 147 | };
|
---|
| 148 |
|
---|
| 149 | /*!
|
---|
| 150 | Constructs a new buffer object of type QGLBuffer::VertexBuffer.
|
---|
| 151 |
|
---|
| 152 | Note: this constructor just creates the QGLBuffer instance. The actual
|
---|
| 153 | buffer object in the GL server is not created until create() is called.
|
---|
| 154 |
|
---|
| 155 | \sa create()
|
---|
| 156 | */
|
---|
| 157 | QGLBuffer::QGLBuffer()
|
---|
| 158 | : d_ptr(new QGLBufferPrivate(QGLBuffer::VertexBuffer))
|
---|
| 159 | {
|
---|
| 160 | }
|
---|
| 161 |
|
---|
| 162 | /*!
|
---|
| 163 | Constructs a new buffer object of \a type.
|
---|
| 164 |
|
---|
| 165 | Note: this constructor just creates the QGLBuffer instance. The actual
|
---|
| 166 | buffer object in the GL server is not created until create() is called.
|
---|
| 167 |
|
---|
| 168 | \sa create()
|
---|
| 169 | */
|
---|
| 170 | QGLBuffer::QGLBuffer(QGLBuffer::Type type)
|
---|
| 171 | : d_ptr(new QGLBufferPrivate(type))
|
---|
| 172 | {
|
---|
| 173 | }
|
---|
| 174 |
|
---|
| 175 | /*!
|
---|
| 176 | Constructs a shallow copy of \a other.
|
---|
| 177 |
|
---|
| 178 | Note: QGLBuffer does not implement copy-on-write semantics,
|
---|
| 179 | so \a other will be affected whenever the copy is modified.
|
---|
| 180 | */
|
---|
| 181 | QGLBuffer::QGLBuffer(const QGLBuffer &other)
|
---|
| 182 | : d_ptr(other.d_ptr)
|
---|
| 183 | {
|
---|
| 184 | d_ptr->ref.ref();
|
---|
| 185 | }
|
---|
| 186 |
|
---|
| 187 | #define ctx d->guard.context()
|
---|
| 188 |
|
---|
| 189 | /*!
|
---|
| 190 | Destroys this buffer object, including the storage being
|
---|
| 191 | used in the GL server.
|
---|
| 192 | */
|
---|
| 193 | QGLBuffer::~QGLBuffer()
|
---|
| 194 | {
|
---|
| 195 | if (!d_ptr->ref.deref()) {
|
---|
| 196 | destroy();
|
---|
| 197 | delete d_ptr;
|
---|
| 198 | }
|
---|
| 199 | }
|
---|
| 200 |
|
---|
| 201 | /*!
|
---|
| 202 | Assigns a shallow copy of \a other to this object.
|
---|
| 203 |
|
---|
| 204 | Note: QGLBuffer does not implement copy-on-write semantics,
|
---|
| 205 | so \a other will be affected whenever the copy is modified.
|
---|
| 206 | */
|
---|
| 207 | QGLBuffer &QGLBuffer::operator=(const QGLBuffer &other)
|
---|
| 208 | {
|
---|
| 209 | if (d_ptr != other.d_ptr) {
|
---|
| 210 | other.d_ptr->ref.ref();
|
---|
| 211 | if (!d_ptr->ref.deref())
|
---|
| 212 | destroy();
|
---|
| 213 | d_ptr = other.d_ptr;
|
---|
| 214 | }
|
---|
| 215 | return *this;
|
---|
| 216 | }
|
---|
| 217 |
|
---|
| 218 | /*!
|
---|
| 219 | Returns the type of buffer represented by this object.
|
---|
| 220 | */
|
---|
| 221 | QGLBuffer::Type QGLBuffer::type() const
|
---|
| 222 | {
|
---|
| 223 | Q_D(const QGLBuffer);
|
---|
| 224 | return d->type;
|
---|
| 225 | }
|
---|
| 226 |
|
---|
| 227 | /*!
|
---|
| 228 | Returns the usage pattern for this buffer object.
|
---|
| 229 | The default value is StaticDraw.
|
---|
| 230 |
|
---|
| 231 | \sa setUsagePattern()
|
---|
| 232 | */
|
---|
| 233 | QGLBuffer::UsagePattern QGLBuffer::usagePattern() const
|
---|
| 234 | {
|
---|
| 235 | Q_D(const QGLBuffer);
|
---|
| 236 | return d->usagePattern;
|
---|
| 237 | }
|
---|
| 238 |
|
---|
| 239 | /*!
|
---|
| 240 | Sets the usage pattern for this buffer object to \a value.
|
---|
| 241 | This function must be called before allocate() or write().
|
---|
| 242 |
|
---|
| 243 | \sa usagePattern(), allocate(), write()
|
---|
| 244 | */
|
---|
| 245 | void QGLBuffer::setUsagePattern(QGLBuffer::UsagePattern value)
|
---|
| 246 | {
|
---|
| 247 | Q_D(QGLBuffer);
|
---|
| 248 | #if defined(QT_OPENGL_ES_1)
|
---|
| 249 | // OpenGL/ES 1.1 does not support GL_STREAM_DRAW, so use GL_STATIC_DRAW.
|
---|
| 250 | // OpenGL/ES 2.0 does support GL_STREAM_DRAW.
|
---|
| 251 | d->usagePattern = value;
|
---|
| 252 | if (value == StreamDraw)
|
---|
| 253 | d->actualUsagePattern = StaticDraw;
|
---|
| 254 | else
|
---|
| 255 | d->actualUsagePattern = value;
|
---|
| 256 | #else
|
---|
| 257 | d->usagePattern = d->actualUsagePattern = value;
|
---|
| 258 | #endif
|
---|
| 259 | }
|
---|
| 260 |
|
---|
| 261 | #undef ctx
|
---|
| 262 |
|
---|
| 263 | /*!
|
---|
| 264 | Creates the buffer object in the GL server. Returns true if
|
---|
| 265 | the object was created; false otherwise.
|
---|
| 266 |
|
---|
| 267 | This function must be called with a current QGLContext.
|
---|
| 268 | The buffer will be bound to and can only be used in
|
---|
| 269 | that context (or any other context that is shared with it).
|
---|
| 270 |
|
---|
| 271 | This function will return false if the GL implementation
|
---|
| 272 | does not support buffers, or there is no current QGLContext.
|
---|
| 273 |
|
---|
| 274 | \sa isCreated(), allocate(), write(), destroy()
|
---|
| 275 | */
|
---|
| 276 | bool QGLBuffer::create()
|
---|
| 277 | {
|
---|
| 278 | Q_D(QGLBuffer);
|
---|
| 279 | if (d->guard.id())
|
---|
| 280 | return true;
|
---|
| 281 | const QGLContext *ctx = QGLContext::currentContext();
|
---|
| 282 | if (ctx) {
|
---|
| 283 | if (!qt_resolve_buffer_extensions(const_cast<QGLContext *>(ctx)))
|
---|
| 284 | return false;
|
---|
| 285 | GLuint bufferId = 0;
|
---|
| 286 | glGenBuffers(1, &bufferId);
|
---|
| 287 | if (bufferId) {
|
---|
| 288 | d->guard.setContext(ctx);
|
---|
| 289 | d->guard.setId(bufferId);
|
---|
| 290 | return true;
|
---|
| 291 | }
|
---|
| 292 | }
|
---|
| 293 | return false;
|
---|
| 294 | }
|
---|
| 295 |
|
---|
| 296 | #define ctx d->guard.context()
|
---|
| 297 |
|
---|
| 298 | /*!
|
---|
| 299 | Returns true if this buffer has been created; false otherwise.
|
---|
| 300 |
|
---|
| 301 | \sa create(), destroy()
|
---|
| 302 | */
|
---|
| 303 | bool QGLBuffer::isCreated() const
|
---|
| 304 | {
|
---|
| 305 | Q_D(const QGLBuffer);
|
---|
| 306 | return d->guard.id() != 0;
|
---|
| 307 | }
|
---|
| 308 |
|
---|
| 309 | /*!
|
---|
| 310 | Destroys this buffer object, including the storage being
|
---|
| 311 | used in the GL server. All references to the buffer will
|
---|
| 312 | become invalid.
|
---|
| 313 | */
|
---|
| 314 | void QGLBuffer::destroy()
|
---|
| 315 | {
|
---|
| 316 | Q_D(QGLBuffer);
|
---|
| 317 | GLuint bufferId = d->guard.id();
|
---|
| 318 | if (bufferId) {
|
---|
| 319 | // Switch to the original creating context to destroy it.
|
---|
| 320 | QGLShareContextScope scope(d->guard.context());
|
---|
| 321 | glDeleteBuffers(1, &bufferId);
|
---|
| 322 | }
|
---|
| 323 | d->guard.setId(0);
|
---|
| 324 | d->guard.setContext(0);
|
---|
| 325 | }
|
---|
| 326 |
|
---|
| 327 | /*!
|
---|
| 328 | Reads the \a count bytes in this buffer starting at \a offset
|
---|
| 329 | into \a data. Returns true on success; false if reading from
|
---|
| 330 | the buffer is not supported. Buffer reading is not supported
|
---|
| 331 | under OpenGL/ES.
|
---|
| 332 |
|
---|
| 333 | It is assumed that this buffer has been bound to the current context.
|
---|
| 334 |
|
---|
| 335 | \sa write(), bind()
|
---|
| 336 | */
|
---|
| 337 | bool QGLBuffer::read(int offset, void *data, int count)
|
---|
| 338 | {
|
---|
| 339 | #if !defined(QT_OPENGL_ES)
|
---|
| 340 | Q_D(QGLBuffer);
|
---|
| 341 | if (!glGetBufferSubData || !d->guard.id())
|
---|
| 342 | return false;
|
---|
| 343 | while (glGetError() != GL_NO_ERROR) ; // Clear error state.
|
---|
| 344 | glGetBufferSubData(d->type, offset, count, data);
|
---|
| 345 | return glGetError() == GL_NO_ERROR;
|
---|
| 346 | #else
|
---|
| 347 | Q_UNUSED(offset);
|
---|
| 348 | Q_UNUSED(data);
|
---|
| 349 | Q_UNUSED(count);
|
---|
| 350 | return false;
|
---|
| 351 | #endif
|
---|
| 352 | }
|
---|
| 353 |
|
---|
| 354 | /*!
|
---|
| 355 | Replaces the \a count bytes of this buffer starting at \a offset
|
---|
| 356 | with the contents of \a data. Any other bytes in the buffer
|
---|
| 357 | will be left unmodified.
|
---|
| 358 |
|
---|
| 359 | It is assumed that create() has been called on this buffer and that
|
---|
| 360 | it has been bound to the current context.
|
---|
| 361 |
|
---|
| 362 | \sa create(), read(), allocate()
|
---|
| 363 | */
|
---|
| 364 | void QGLBuffer::write(int offset, const void *data, int count)
|
---|
| 365 | {
|
---|
| 366 | #ifndef QT_NO_DEBUG
|
---|
| 367 | if (!isCreated())
|
---|
| 368 | qWarning("QGLBuffer::allocate(): buffer not created");
|
---|
| 369 | #endif
|
---|
| 370 | Q_D(QGLBuffer);
|
---|
| 371 | if (d->guard.id())
|
---|
| 372 | glBufferSubData(d->type, offset, count, data);
|
---|
| 373 | }
|
---|
| 374 |
|
---|
| 375 | /*!
|
---|
| 376 | Allocates \a count bytes of space to the buffer, initialized to
|
---|
| 377 | the contents of \a data. Any previous contents will be removed.
|
---|
| 378 |
|
---|
| 379 | It is assumed that create() has been called on this buffer and that
|
---|
| 380 | it has been bound to the current context.
|
---|
| 381 |
|
---|
| 382 | \sa create(), read(), write()
|
---|
| 383 | */
|
---|
| 384 | void QGLBuffer::allocate(const void *data, int count)
|
---|
| 385 | {
|
---|
| 386 | #ifndef QT_NO_DEBUG
|
---|
| 387 | if (!isCreated())
|
---|
| 388 | qWarning("QGLBuffer::allocate(): buffer not created");
|
---|
| 389 | #endif
|
---|
| 390 | Q_D(QGLBuffer);
|
---|
| 391 | if (d->guard.id())
|
---|
| 392 | glBufferData(d->type, count, data, d->actualUsagePattern);
|
---|
| 393 | }
|
---|
| 394 |
|
---|
| 395 | /*!
|
---|
| 396 | \fn void QGLBuffer::allocate(int count)
|
---|
| 397 | \overload
|
---|
| 398 |
|
---|
| 399 | Allocates \a count bytes of space to the buffer. Any previous
|
---|
| 400 | contents will be removed.
|
---|
| 401 |
|
---|
| 402 | It is assumed that create() has been called on this buffer and that
|
---|
| 403 | it has been bound to the current context.
|
---|
| 404 |
|
---|
| 405 | \sa create(), write()
|
---|
| 406 | */
|
---|
| 407 |
|
---|
| 408 | /*!
|
---|
| 409 | Binds the buffer associated with this object to the current
|
---|
| 410 | GL context. Returns false if binding was not possible, usually because
|
---|
| 411 | type() is not supported on this GL implementation.
|
---|
| 412 |
|
---|
| 413 | The buffer must be bound to the same QGLContext current when create()
|
---|
| 414 | was called, or to another QGLContext that is sharing with it.
|
---|
| 415 | Otherwise, false will be returned from this function.
|
---|
| 416 |
|
---|
| 417 | \sa release(), create()
|
---|
| 418 | */
|
---|
| 419 | bool QGLBuffer::bind()
|
---|
| 420 | {
|
---|
| 421 | #ifndef QT_NO_DEBUG
|
---|
| 422 | if (!isCreated())
|
---|
| 423 | qWarning("QGLBuffer::bind(): buffer not created");
|
---|
| 424 | #endif
|
---|
| 425 | Q_D(const QGLBuffer);
|
---|
| 426 | GLuint bufferId = d->guard.id();
|
---|
| 427 | if (bufferId) {
|
---|
| 428 | if (!QGLContext::areSharing(QGLContext::currentContext(),
|
---|
| 429 | d->guard.context())) {
|
---|
| 430 | #ifndef QT_NO_DEBUG
|
---|
| 431 | qWarning("QGLBuffer::bind: buffer is not valid in the current context");
|
---|
| 432 | #endif
|
---|
| 433 | return false;
|
---|
| 434 | }
|
---|
| 435 | glBindBuffer(d->type, bufferId);
|
---|
| 436 | return true;
|
---|
| 437 | } else {
|
---|
| 438 | return false;
|
---|
| 439 | }
|
---|
| 440 | }
|
---|
| 441 |
|
---|
| 442 | /*!
|
---|
| 443 | Releases the buffer associated with this object from the
|
---|
| 444 | current GL context.
|
---|
| 445 |
|
---|
| 446 | This function must be called with the same QGLContext current
|
---|
| 447 | as when bind() was called on the buffer.
|
---|
| 448 |
|
---|
| 449 | \sa bind()
|
---|
| 450 | */
|
---|
| 451 | void QGLBuffer::release()
|
---|
| 452 | {
|
---|
| 453 | #ifndef QT_NO_DEBUG
|
---|
| 454 | if (!isCreated())
|
---|
| 455 | qWarning("QGLBuffer::release(): buffer not created");
|
---|
| 456 | #endif
|
---|
| 457 | Q_D(const QGLBuffer);
|
---|
| 458 | if (d->guard.id())
|
---|
| 459 | glBindBuffer(d->type, 0);
|
---|
| 460 | }
|
---|
| 461 |
|
---|
| 462 | #undef ctx
|
---|
| 463 |
|
---|
| 464 | /*!
|
---|
| 465 | Releases the buffer associated with \a type in the current
|
---|
| 466 | QGLContext.
|
---|
| 467 |
|
---|
| 468 | This function is a direct call to \c{glBindBuffer(type, 0)}
|
---|
| 469 | for use when the caller does not know which QGLBuffer has
|
---|
| 470 | been bound to the context but wants to make sure that it
|
---|
| 471 | is released.
|
---|
| 472 |
|
---|
| 473 | \code
|
---|
| 474 | QGLBuffer::release(QGLBuffer::VertexBuffer);
|
---|
| 475 | \endcode
|
---|
| 476 | */
|
---|
| 477 | void QGLBuffer::release(QGLBuffer::Type type)
|
---|
| 478 | {
|
---|
| 479 | const QGLContext *ctx = QGLContext::currentContext();
|
---|
| 480 | if (ctx && qt_resolve_buffer_extensions(const_cast<QGLContext *>(ctx)))
|
---|
| 481 | glBindBuffer(GLenum(type), 0);
|
---|
| 482 | }
|
---|
| 483 |
|
---|
| 484 | #define ctx d->guard.context()
|
---|
| 485 |
|
---|
| 486 | /*!
|
---|
| 487 | Returns the GL identifier associated with this buffer; zero if
|
---|
| 488 | the buffer has not been created.
|
---|
| 489 |
|
---|
| 490 | \sa isCreated()
|
---|
| 491 | */
|
---|
| 492 | GLuint QGLBuffer::bufferId() const
|
---|
| 493 | {
|
---|
| 494 | Q_D(const QGLBuffer);
|
---|
| 495 | return d->guard.id();
|
---|
| 496 | }
|
---|
| 497 |
|
---|
| 498 | #ifndef GL_BUFFER_SIZE
|
---|
| 499 | #define GL_BUFFER_SIZE 0x8764
|
---|
| 500 | #endif
|
---|
| 501 |
|
---|
| 502 | /*!
|
---|
| 503 | Returns the size of the data in this buffer, for reading operations.
|
---|
| 504 | Returns -1 if fetching the buffer size is not supported, or the
|
---|
| 505 | buffer has not been created.
|
---|
| 506 |
|
---|
| 507 | It is assumed that this buffer has been bound to the current context.
|
---|
| 508 |
|
---|
| 509 | \sa isCreated(), bind()
|
---|
| 510 | */
|
---|
| 511 | int QGLBuffer::size() const
|
---|
| 512 | {
|
---|
| 513 | Q_D(const QGLBuffer);
|
---|
| 514 | if (!d->guard.id())
|
---|
| 515 | return -1;
|
---|
| 516 | GLint value = -1;
|
---|
| 517 | glGetBufferParameteriv(d->type, GL_BUFFER_SIZE, &value);
|
---|
| 518 | return value;
|
---|
| 519 | }
|
---|
| 520 |
|
---|
| 521 | /*!
|
---|
| 522 | Maps the contents of this buffer into the application's memory
|
---|
| 523 | space and returns a pointer to it. Returns null if memory
|
---|
| 524 | mapping is not possible. The \a access parameter indicates the
|
---|
| 525 | type of access to be performed.
|
---|
| 526 |
|
---|
| 527 | It is assumed that create() has been called on this buffer and that
|
---|
| 528 | it has been bound to the current context.
|
---|
| 529 |
|
---|
| 530 | This function is only supported under OpenGL/ES if the
|
---|
| 531 | \c{GL_OES_mapbuffer} extension is present.
|
---|
| 532 |
|
---|
| 533 | \sa unmap(), create(), bind()
|
---|
| 534 | */
|
---|
| 535 | void *QGLBuffer::map(QGLBuffer::Access access)
|
---|
| 536 | {
|
---|
| 537 | Q_D(QGLBuffer);
|
---|
| 538 | #ifndef QT_NO_DEBUG
|
---|
| 539 | if (!isCreated())
|
---|
| 540 | qWarning("QGLBuffer::map(): buffer not created");
|
---|
| 541 | #endif
|
---|
| 542 | if (!d->guard.id())
|
---|
| 543 | return 0;
|
---|
| 544 | if (!glMapBufferARB)
|
---|
| 545 | return 0;
|
---|
| 546 | return glMapBufferARB(d->type, access);
|
---|
| 547 | }
|
---|
| 548 |
|
---|
| 549 | /*!
|
---|
| 550 | Unmaps the buffer after it was mapped into the application's
|
---|
| 551 | memory space with a previous call to map(). Returns true if
|
---|
| 552 | the unmap succeeded; false otherwise.
|
---|
| 553 |
|
---|
| 554 | It is assumed that this buffer has been bound to the current context,
|
---|
| 555 | and that it was previously mapped with map().
|
---|
| 556 |
|
---|
| 557 | This function is only supported under OpenGL/ES if the
|
---|
| 558 | \c{GL_OES_mapbuffer} extension is present.
|
---|
| 559 |
|
---|
| 560 | \sa map()
|
---|
| 561 | */
|
---|
| 562 | bool QGLBuffer::unmap()
|
---|
| 563 | {
|
---|
| 564 | Q_D(QGLBuffer);
|
---|
| 565 | #ifndef QT_NO_DEBUG
|
---|
| 566 | if (!isCreated())
|
---|
| 567 | qWarning("QGLBuffer::unmap(): buffer not created");
|
---|
| 568 | #endif
|
---|
| 569 | if (!d->guard.id())
|
---|
| 570 | return false;
|
---|
| 571 | if (!glUnmapBufferARB)
|
---|
| 572 | return false;
|
---|
| 573 | return glUnmapBufferARB(d->type) == GL_TRUE;
|
---|
| 574 | }
|
---|
| 575 |
|
---|
| 576 | QT_END_NAMESPACE
|
---|