src/opengl/qglbuffer.cpp
changeset 30 5dc02b23752f
child 33 3e2da88830cd
equal deleted inserted replaced
29:b72c6db6890b 30:5dc02b23752f
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtOpenGL module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    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 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    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 "qglbuffer.h"
       
    46 
       
    47 QT_BEGIN_NAMESPACE
       
    48 
       
    49 /*!
       
    50     \class QGLBuffer
       
    51     \brief The QGLBuffer class provides functions for creating and managing GL buffer objects.
       
    52     \since 4.7
       
    53     \ingroup painting-3D
       
    54 
       
    55     Buffer objects are created in the GL server so that the
       
    56     client application can avoid uploading vertices, indices,
       
    57     texture image data, etc every time they are needed.
       
    58 */
       
    59 
       
    60 /*!
       
    61     \enum QGLBuffer::Type
       
    62     This enum defines the type of GL buffer object to create with QGLBuffer.
       
    63 
       
    64     \value VertexBuffer Vertex buffer object for use when specifying
       
    65            vertex arrays.
       
    66     \value IndexBuffer Index buffer object for use with \c{glDrawElements()}.
       
    67     \value PixelPackBuffer Pixel pack buffer object for reading pixel
       
    68            data from the GL server (for example, with \c{glReadPixels()}).
       
    69            Not supported under OpenGL/ES.
       
    70     \value PixelUnpackBuffer Pixel unpack buffer object for writing pixel
       
    71            data to the GL server (for example, with \c{glTexImage2D()}).
       
    72            Not supported under OpenGL/ES.
       
    73 */
       
    74 
       
    75 /*!
       
    76     \enum QGLBuffer::UsagePattern
       
    77     This enum defines the usage pattern of a QGLBuffer object.
       
    78 
       
    79     \value StreamDraw The data will be set once and used a few times
       
    80            for drawing operations.  Under OpenGL/ES 1.1 this is identical
       
    81            to StaticDraw.
       
    82     \value StreamRead The data will be set once and used a few times
       
    83            for reading data back from the GL server.  Not supported
       
    84            under OpenGL/ES.
       
    85     \value StreamCopy The data will be set once and used a few times
       
    86            for reading data back from the GL server for use in further
       
    87            drawing operations.  Not supported under OpenGL/ES.
       
    88     \value StaticDraw The data will be set once and used many times
       
    89            for drawing operations.
       
    90     \value StaticRead The data will be set once and used many times
       
    91            for reading data back from the GL server.  Not supported
       
    92            under OpenGL/ES.
       
    93     \value StaticCopy The data will be set once and used many times
       
    94            for reading data back from the GL server for use in further
       
    95            drawing operations.  Not supported under OpenGL/ES.
       
    96     \value DynamicDraw The data will be modified repeatedly and used
       
    97            many times for drawing operations.
       
    98     \value DynamicRead The data will be modified repeatedly and used
       
    99            many times for reading data back from the GL server.
       
   100            Not supported under OpenGL/ES.
       
   101     \value DynamicCopy The data will be modified repeatedly and used
       
   102            many times for reading data back from the GL server for
       
   103            use in further drawing operations.  Not supported under OpenGL/ES.
       
   104 */
       
   105 
       
   106 /*!
       
   107     \enum QGLBuffer::Access
       
   108     This enum defines the access mode for QGLBuffer::map().
       
   109 
       
   110     \value ReadOnly The buffer will be mapped for reading only.
       
   111     \value WriteOnly The buffer will be mapped for writing only.
       
   112     \value ReadWrite The buffer will be mapped for reading and writing.
       
   113 */
       
   114 
       
   115 class QGLBufferPrivate
       
   116 {
       
   117 public:
       
   118     QGLBufferPrivate(QGLBuffer::Type t)
       
   119         : type(t),
       
   120           guard(0),
       
   121           usagePattern(QGLBuffer::StaticDraw),
       
   122           actualUsagePattern(QGLBuffer::StaticDraw)
       
   123     {
       
   124     }
       
   125 
       
   126     QGLBuffer::Type type;
       
   127     QGLSharedResourceGuard guard;
       
   128     QGLBuffer::UsagePattern usagePattern;
       
   129     QGLBuffer::UsagePattern actualUsagePattern;
       
   130 };
       
   131 
       
   132 /*!
       
   133     Constructs a new buffer object of \a type.
       
   134 
       
   135     Note: this constructor just creates the QGLBuffer instance.  The actual
       
   136     buffer object in the GL server is not created until create() is called.
       
   137 
       
   138     \sa create()
       
   139 */
       
   140 QGLBuffer::QGLBuffer(QGLBuffer::Type type)
       
   141     : d_ptr(new QGLBufferPrivate(type))
       
   142 {
       
   143 }
       
   144 
       
   145 #define ctx d->guard.context()
       
   146 
       
   147 /*!
       
   148     Destroys this buffer object, including the storage being
       
   149     used in the GL server.
       
   150 */
       
   151 QGLBuffer::~QGLBuffer()
       
   152 {
       
   153     Q_D(QGLBuffer);
       
   154     GLuint bufferId = d->guard.id();
       
   155     if (bufferId) {
       
   156         // Switch to the original creating context to destroy it.
       
   157         QGLShareContextScope scope(d->guard.context());
       
   158         glDeleteBuffers(1, &bufferId);
       
   159     }
       
   160 }
       
   161 
       
   162 /*!
       
   163     Returns the type of buffer represented by this object.
       
   164 */
       
   165 QGLBuffer::Type QGLBuffer::type() const
       
   166 {
       
   167     Q_D(const QGLBuffer);
       
   168     return d->type;
       
   169 }
       
   170 
       
   171 /*!
       
   172     Returns the usage pattern for this buffer object.
       
   173     The default value is StaticDraw.
       
   174 
       
   175     \sa setUsagePattern()
       
   176 */
       
   177 QGLBuffer::UsagePattern QGLBuffer::usagePattern() const
       
   178 {
       
   179     Q_D(const QGLBuffer);
       
   180     return d->usagePattern;
       
   181 }
       
   182 
       
   183 /*!
       
   184     Sets the usage pattern for this buffer object to \a value.
       
   185     This function must be called before allocate() or write().
       
   186 
       
   187     \sa usagePattern(), allocate(), write()
       
   188 */
       
   189 void QGLBuffer::setUsagePattern(QGLBuffer::UsagePattern value)
       
   190 {
       
   191     Q_D(QGLBuffer);
       
   192 #if defined(QT_OPENGL_ES_1)
       
   193     // OpenGL/ES 1.1 does not support GL_STREAM_DRAW, so use GL_STATIC_DRAW.
       
   194     // OpenGL/ES 2.0 does support GL_STREAM_DRAW.
       
   195     d->usagePattern = value;
       
   196     if (value == StreamDraw)
       
   197         d->actualUsagePattern = StaticDraw;
       
   198     else
       
   199         d->actualUsagePattern = value;
       
   200 #else
       
   201     d->usagePattern = d->actualUsagePattern = value;
       
   202 #endif
       
   203 }
       
   204 
       
   205 #undef ctx
       
   206 
       
   207 /*!
       
   208     Creates the buffer object in the GL server.  Returns true if
       
   209     the object was created; false otherwise.
       
   210 
       
   211     This function must be called with a current QGLContext.
       
   212     The buffer will be bound to and can only be used in
       
   213     that context (or any other context that is shared with it).
       
   214 
       
   215     This function will return false if the GL implementation
       
   216     does not support buffers, or there is no current QGLContext.
       
   217 
       
   218     \sa isCreated(), allocate(), write()
       
   219 */
       
   220 bool QGLBuffer::create()
       
   221 {
       
   222     Q_D(QGLBuffer);
       
   223     if (d->guard.id())
       
   224         return true;
       
   225     const QGLContext *ctx = QGLContext::currentContext();
       
   226     if (ctx) {
       
   227         if (!qt_resolve_buffer_extensions(const_cast<QGLContext *>(ctx)))
       
   228             return false;
       
   229         GLuint bufferId = 0;
       
   230         glGenBuffers(1, &bufferId);
       
   231         if (bufferId) {
       
   232             d->guard.setContext(ctx);
       
   233             d->guard.setId(bufferId);
       
   234             return true;
       
   235         }
       
   236     }
       
   237     return false;
       
   238 }
       
   239 
       
   240 #define ctx d->guard.context()
       
   241 
       
   242 /*!
       
   243     Returns true if this buffer has been created; false otherwise.
       
   244 
       
   245     \sa create()
       
   246 */
       
   247 bool QGLBuffer::isCreated() const
       
   248 {
       
   249     Q_D(const QGLBuffer);
       
   250     return d->guard.id() != 0;
       
   251 }
       
   252 
       
   253 /*!
       
   254     Reads the \a count bytes in this buffer starting at \a offset
       
   255     into \a data.  Returns true on success; false if reading from
       
   256     the buffer is not supported.  Buffer reading is not supported
       
   257     under OpenGL/ES.
       
   258 
       
   259     It is assumed that this buffer has been bound to the current context.
       
   260 
       
   261     \sa write(), bind()
       
   262 */
       
   263 bool QGLBuffer::read(int offset, void *data, int count)
       
   264 {
       
   265 #if !defined(QT_OPENGL_ES)
       
   266     Q_D(QGLBuffer);
       
   267     if (!glGetBufferSubData || !d->guard.id())
       
   268         return false;
       
   269     while (glGetError() != GL_NO_ERROR) ; // Clear error state.
       
   270     glGetBufferSubData(d->type, offset, count, data);
       
   271     return glGetError() == GL_NO_ERROR;
       
   272 #else
       
   273     Q_UNUSED(offset);
       
   274     Q_UNUSED(data);
       
   275     Q_UNUSED(count);
       
   276     return false;
       
   277 #endif
       
   278 }
       
   279 
       
   280 /*!
       
   281     Replaces the \a count bytes of this buffer starting at \a offset
       
   282     with the contents of \a data.  Any other bytes in the buffer
       
   283     will be left unmodified.
       
   284 
       
   285     It is assumed that create() has been called on this buffer and that
       
   286     it has been bound to the current context.
       
   287 
       
   288     \sa create(), read(), allocate()
       
   289 */
       
   290 void QGLBuffer::write(int offset, const void *data, int count)
       
   291 {
       
   292 #ifndef QT_NO_DEBUG
       
   293     if (!isCreated())
       
   294         qWarning("QGLBuffer::allocate(): buffer not created");
       
   295 #endif
       
   296     Q_D(QGLBuffer);
       
   297     if (d->guard.id())
       
   298         glBufferSubData(d->type, offset, count, data);
       
   299 }
       
   300 
       
   301 /*!
       
   302     Allocates \a count bytes of space to the buffer, initialized to
       
   303     the contents of \a data.  Any previous contents will be removed.
       
   304 
       
   305     It is assumed that create() has been called on this buffer and that
       
   306     it has been bound to the current context.
       
   307 
       
   308     \sa create(), read(), write()
       
   309 */
       
   310 void QGLBuffer::allocate(const void *data, int count)
       
   311 {
       
   312 #ifndef QT_NO_DEBUG
       
   313     if (!isCreated())
       
   314         qWarning("QGLBuffer::allocate(): buffer not created");
       
   315 #endif
       
   316     Q_D(QGLBuffer);
       
   317     if (d->guard.id())
       
   318         glBufferData(d->type, count, data, d->actualUsagePattern);
       
   319 }
       
   320 
       
   321 /*!
       
   322     \fn void QGLBuffer::allocate(int count)
       
   323     \overload
       
   324 
       
   325     Allocates \a count bytes of space to the buffer.  Any previous
       
   326     contents will be removed.
       
   327 
       
   328     It is assumed that create() has been called on this buffer and that
       
   329     it has been bound to the current context.
       
   330 
       
   331     \sa create(), write()
       
   332 */
       
   333 
       
   334 /*!
       
   335     Binds the buffer associated with this object to the current
       
   336     GL context.  Returns false if binding was not possible, usually because
       
   337     type() is not supported on this GL implementation.
       
   338 
       
   339     The buffer must be bound to the same QGLContext current when create()
       
   340     was called, or to another QGLContext that is sharing with it.
       
   341     Otherwise, false will be returned from this function.
       
   342 
       
   343     \sa release(), create()
       
   344 */
       
   345 bool QGLBuffer::bind() const
       
   346 {
       
   347 #ifndef QT_NO_DEBUG
       
   348     if (!isCreated())
       
   349         qWarning("QGLBuffer::bind(): buffer not created");
       
   350 #endif
       
   351     Q_D(const QGLBuffer);
       
   352     GLuint bufferId = d->guard.id();
       
   353     if (bufferId) {
       
   354         if (!QGLContext::areSharing(QGLContext::currentContext(),
       
   355                                     d->guard.context())) {
       
   356 #ifndef QT_NO_DEBUG
       
   357             qWarning("QGLBuffer::bind: buffer is not valid in the current context");
       
   358 #endif
       
   359             return false;
       
   360         }
       
   361         glBindBuffer(d->type, bufferId);
       
   362         return true;
       
   363     } else {
       
   364         return false;
       
   365     }
       
   366 }
       
   367 
       
   368 /*!
       
   369     Releases the buffer associated with this object from the
       
   370     current GL context.
       
   371 
       
   372     This function must be called with the same QGLContext current
       
   373     as when bind() was called on the buffer.
       
   374 
       
   375     \sa bind()
       
   376 */
       
   377 void QGLBuffer::release() const
       
   378 {
       
   379 #ifndef QT_NO_DEBUG
       
   380     if (!isCreated())
       
   381         qWarning("QGLBuffer::release(): buffer not created");
       
   382 #endif
       
   383     Q_D(const QGLBuffer);
       
   384     if (d->guard.id())
       
   385         glBindBuffer(d->type, 0);
       
   386 }
       
   387 
       
   388 #undef ctx
       
   389 
       
   390 /*!
       
   391     Releases the buffer associated with \a type in the current
       
   392     QGLContext.
       
   393 
       
   394     This function is a direct call to \c{glBindBuffer(type, 0)}
       
   395     for use when the caller does not know which QGLBuffer has
       
   396     been bound to the context but wants to make sure that it
       
   397     is released.
       
   398 
       
   399     \code
       
   400     QGLBuffer::release(QGLBuffer::VertexBuffer);
       
   401     \endcode
       
   402 */
       
   403 void QGLBuffer::release(QGLBuffer::Type type)
       
   404 {
       
   405     const QGLContext *ctx = QGLContext::currentContext();
       
   406     if (ctx && qt_resolve_buffer_extensions(const_cast<QGLContext *>(ctx)))
       
   407         glBindBuffer(GLenum(type), 0);
       
   408 }
       
   409 
       
   410 #define ctx d->guard.context()
       
   411 
       
   412 /*!
       
   413     Returns the GL identifier associated with this buffer; zero if
       
   414     the buffer has not been created.
       
   415 
       
   416     \sa isCreated()
       
   417 */
       
   418 GLuint QGLBuffer::bufferId() const
       
   419 {
       
   420     Q_D(const QGLBuffer);
       
   421     return d->guard.id();
       
   422 }
       
   423 
       
   424 #ifndef GL_BUFFER_SIZE
       
   425 #define GL_BUFFER_SIZE 0x8764
       
   426 #endif
       
   427 
       
   428 /*!
       
   429     Returns the size of the data in this buffer, for reading operations.
       
   430     Returns -1 if fetching the buffer size is not supported, or the
       
   431     buffer has not been created.
       
   432 
       
   433     It is assumed that this buffer has been bound to the current context.
       
   434 
       
   435     \sa isCreated(), bind()
       
   436 */
       
   437 int QGLBuffer::size() const
       
   438 {
       
   439     Q_D(const QGLBuffer);
       
   440     if (!d->guard.id())
       
   441         return -1;
       
   442     GLint value = -1;
       
   443     glGetBufferParameteriv(d->type, GL_BUFFER_SIZE, &value);
       
   444     return value;
       
   445 }
       
   446 
       
   447 /*!
       
   448     Maps the contents of this buffer into the application's memory
       
   449     space and returns a pointer to it.  Returns null if memory
       
   450     mapping is not possible.  The \a access parameter indicates the
       
   451     type of access to be performed.
       
   452 
       
   453     It is assumed that create() has been called on this buffer and that
       
   454     it has been bound to the current context.
       
   455 
       
   456     This function is only supported under OpenGL/ES if the
       
   457     \c{GL_OES_mapbuffer} extension is present.
       
   458 
       
   459     \sa unmap(), create(), bind()
       
   460 */
       
   461 void *QGLBuffer::map(QGLBuffer::Access access)
       
   462 {
       
   463     Q_D(QGLBuffer);
       
   464 #ifndef QT_NO_DEBUG
       
   465     if (!isCreated())
       
   466         qWarning("QGLBuffer::map(): buffer not created");
       
   467 #endif
       
   468     if (!d->guard.id())
       
   469         return 0;
       
   470     if (!glMapBufferARB)
       
   471         return 0;
       
   472     return glMapBufferARB(d->type, access);
       
   473 }
       
   474 
       
   475 /*!
       
   476     Unmaps the buffer after it was mapped into the application's
       
   477     memory space with a previous call to map().  Returns true if
       
   478     the unmap succeeded; false otherwise.
       
   479 
       
   480     It is assumed that this buffer has been bound to the current context,
       
   481     and that it was previously mapped with map().
       
   482 
       
   483     This function is only supported under OpenGL/ES if the
       
   484     \c{GL_OES_mapbuffer} extension is present.
       
   485 
       
   486     \sa map()
       
   487 */
       
   488 bool QGLBuffer::unmap()
       
   489 {
       
   490     Q_D(QGLBuffer);
       
   491 #ifndef QT_NO_DEBUG
       
   492     if (!isCreated())
       
   493         qWarning("QGLBuffer::unmap(): buffer not created");
       
   494 #endif
       
   495     if (!d->guard.id())
       
   496         return false;
       
   497     if (!glUnmapBufferARB)
       
   498         return false;
       
   499     return glUnmapBufferARB(d->type) == GL_TRUE;
       
   500 }
       
   501 
       
   502 QT_END_NAMESPACE