Added documentation for QOpenGLContext and QOpenGLContextGroup.
authorSamuel Rødal <samuel.rodal@nokia.com>
Tue, 21 Feb 2012 11:46:44 +0000 (12:46 +0100)
committerQt by Nokia <qt-info@nokia.com>
Thu, 23 Feb 2012 15:38:45 +0000 (16:38 +0100)
Change-Id: I00e3e3b3fd37b27b31d4705de3c8c34be9211707
Reviewed-by: Casper van Donderen <casper.vandonderen@nokia.com>
Reviewed-by: Gunnar Sletta <gunnar.sletta@nokia.com>
src/gui/kernel/qopenglcontext.cpp

index ba51653..c263a2a 100644 (file)
@@ -74,6 +74,76 @@ QHash<QOpenGLContext *, bool> QOpenGLContextPrivate::makeCurrentTracker;
 QMutex QOpenGLContextPrivate::makeCurrentTrackerMutex;
 #endif
 
+/*!
+    \class QOpenGLContext
+    \brief The QOpenGLContext represents a native OpenGL context, enabling
+           OpenGL rendering on a QSurface.
+
+    QOpenGLContext represents the OpenGL state of an underlying OpenGL context.
+    To set up a context, set its screen and format such that they match those
+    of the surface or surfaces with which the context is meant to be used, if
+    necessary make it share resources with other contexts with
+    setShareContext(), and finally call create(). Use isValid() to check if the
+    context was successfully initialized.
+
+    A context can be made current against a given surface by calling
+    makeCurrent(). When OpenGL rendering is done, call swapBuffers() to swap
+    the front and back buffers of the surface, so that the newly rendered
+    content becomes visible. To be able to support certain platforms,
+    QOpenGLContext requires that you call makeCurrent() again before starting
+    rendering a new frame, after calling swapBuffers().
+
+    If the context is temporarily not needed, such as when the application is
+    not rendering, it can be useful to call destroy() to free resources.
+    However, if you do so you will need to call create() again before the
+    context can be used, and you might need to recreate any OpenGL resources
+    and reinitialize the OpenGL state. You can connect to the
+    aboutToBeDestroyed() signal to clean up any resources that have been
+    allocated with different ownership from the QOpenGLContext itself.
+
+    Once a QOpenGLContext has been made current, you can render to it in a
+    platform independent way by using Qt's OpenGL enablers such as
+    QOpenGLFunctions, QOpenGLBuffer, QOpenGLShaderProgram, and
+    QOpenGLFramebufferObject. It is also possible to use the platform's OpenGL
+    API directly, without using the Qt enablers, although potentially at the
+    cost of portability. The latter is necessary when wanting to use OpenGL 1.x
+    or OpenGL ES 1.x.
+
+    For more information about the OpenGL API, refer to the official
+    \l{OpenGL documentation}.
+
+    \section1 Thread affinity
+
+    QOpenGLContext can be moved to a different thread with moveToThread(). Do
+    not call makeCurrent() from a different thread than the one to which the
+    QOpenGLContext object belongs. A context can only be current in one thread
+    and against one surface at a time, and a thread only has one context
+    current at a time.
+
+    \section1 Context resource sharing
+
+    Resources, such as framebuffer objects, textures, and vertex buffer objects
+    can be shared between contexts.  Use setShareContext() before calling
+    create() to specify that the contexts should share these resources.
+    QOpenGLContext internally keeps track of a QOpenGLContextGroup object which
+    can be accessed with shareGroup(), and which can be used to find all the
+    contexts in a given share group. A share group consists of all contexts that
+    have been succesfully initialized and are sharing with an existing context in
+    the share group. A non-sharing context has a share group consisting of a
+    single context.
+
+    \section1 Default framebuffer
+
+    On certain platforms, a framebuffer other than 0 might be the default frame
+    buffer depending on the current surface. Instead of calling
+    glBindFramebuffer(0), it is recommended that you use
+    glBindFramebuffer(ctx->defaultFramebufferObject()), to ensure that your
+    application is portable between different platforms. However, if you use
+    QOpenGLFunctions::glBindFramebuffer(), this is done automatically for you.
+
+    \sa QOpenGLFunctions, QOpenGLBuffer, QOpenGLShaderProgram, QOpenGLFramebufferObject
+*/
+
 void QOpenGLContextPrivate::setCurrentContext(QOpenGLContext *context)
 {
     QGuiGLThreadContext *threadContext = qwindow_context_storage.localData();
@@ -89,7 +159,8 @@ void QOpenGLContextPrivate::setCurrentContext(QOpenGLContext *context)
 }
 
 /*!
-  Returns the last context which called makeCurrent. This function is thread aware.
+    Returns the last context which called makeCurrent in the current thread,
+    or 0, if no context is current.
 */
 QOpenGLContext* QOpenGLContext::currentContext()
 {
@@ -100,17 +171,31 @@ QOpenGLContext* QOpenGLContext::currentContext()
     return 0;
 }
 
+/*!
+    Returns true if the two contexts are sharing OpenGL resources.
+*/
 bool QOpenGLContext::areSharing(QOpenGLContext *first, QOpenGLContext *second)
 {
     return first->shareGroup() == second->shareGroup();
 }
 
+/*!
+    Returns the underlying platform context.
+
+    \internal
+*/
 QPlatformOpenGLContext *QOpenGLContext::handle() const
 {
     Q_D(const QOpenGLContext);
     return d->platformGLContext;
 }
 
+/*!
+    Returns the underlying platform context with which this context is sharing.
+
+    \internal
+*/
+
 QPlatformOpenGLContext *QOpenGLContext::shareHandle() const
 {
     Q_D(const QOpenGLContext);
@@ -120,7 +205,11 @@ QPlatformOpenGLContext *QOpenGLContext::shareHandle() const
 }
 
 /*!
-  Creates a new GL context instance, you need to call create() before it can be used.
+    Creates a new OpenGL context instance.
+
+    Before it can be used you need to set the proper format and call create().
+
+    \sa create(), makeCurrent()
 */
 QOpenGLContext::QOpenGLContext(QObject *parent)
     : QObject(*new QOpenGLContextPrivate(), parent)
@@ -130,7 +219,8 @@ QOpenGLContext::QOpenGLContext(QObject *parent)
 }
 
 /*!
-  Sets the format the GL context should be compatible with. You need to call create() before it takes effect.
+    Sets the \a format the OpenGL context should be compatible with. You need
+    to call create() before it takes effect.
 */
 void QOpenGLContext::setFormat(const QSurfaceFormat &format)
 {
@@ -139,7 +229,8 @@ void QOpenGLContext::setFormat(const QSurfaceFormat &format)
 }
 
 /*!
-  Sets the context to share textures, shaders, and other GL resources with. You need to call create() before it takes effect.
+    Sets the context to share textures, shaders, and other OpenGL resources
+    with. You need to call create() before it takes effect.
 */
 void QOpenGLContext::setShareContext(QOpenGLContext *shareContext)
 {
@@ -148,7 +239,8 @@ void QOpenGLContext::setShareContext(QOpenGLContext *shareContext)
 }
 
 /*!
-  Sets the screen the GL context should be valid for. You need to call create() before it takes effect.
+    Sets the \a screen the GL context should be valid for. You need to call
+    create() before it takes effect.
 */
 void QOpenGLContext::setScreen(QScreen *screen)
 {
@@ -159,9 +251,15 @@ void QOpenGLContext::setScreen(QScreen *screen)
 }
 
 /*!
-  Attempts to create the GL context with the desired parameters.
+    Attempts to create the OpenGL context with the current configuration.
+
+    The current configuration includes the format, the share context, and the
+    screen.
 
-  Returns true if the native context was successfully created and is ready to be used.
+    Returns true if the native context was successfully created and is ready to
+    be used with makeCurrent(), swapBuffers(), etc.
+
+    \sa makeCurrent(), destroy()
 */
 bool QOpenGLContext::create()
 {
@@ -179,6 +277,22 @@ bool QOpenGLContext::create()
     return d->platformGLContext;
 }
 
+/*!
+    Destroy the underlying platform context associated with this context.
+
+    If any other context is directly or indirectly sharing resources with this
+    context, the shared resources, which includes vertex buffer objects, shader
+    objects, textures, and framebuffer objects, are not freed. However,
+    destroying the underlying platform context frees any state associated with
+    the context.
+
+    After destroy() has been called, you must call create() if you wish to
+    use the context again.
+
+    \note This implicitly calls doneCurrent() if the context is current.
+
+    \sa create()
+*/
 void QOpenGLContext::destroy()
 {
     Q_D(QOpenGLContext);
@@ -199,15 +313,20 @@ void QOpenGLContext::destroy()
     \fn void QOpenGLContext::aboutToBeDestroyed()
 
     This signal is emitted before the underlying native OpenGL context is
-    destroyed, such that users may clean up OpenGL resources that might otherwise
-    be left dangling in the case of shared OpenGL contexts.
+    destroyed, such that users may clean up OpenGL resources that might
+    otherwise be left dangling in the case of shared OpenGL contexts.
 
-    If you wish to make the context current in order to do clean-up, make sure to
-    only connect to the signal using a direct connection.
+    If you wish to make the context current in order to do clean-up, make sure
+    to only connect to the signal using a direct connection.
 */
 
 /*!
-  If this is the current context for the thread, doneCurrent is called
+    Destroys the QOpenGLContext object.
+
+    This implicitly calls destroy(), so if this is the current context for the
+    thread, doneCurrent() is also called.
+
+    \sa destroy()
 */
 QOpenGLContext::~QOpenGLContext()
 {
@@ -219,7 +338,9 @@ QOpenGLContext::~QOpenGLContext()
 }
 
 /*!
-  Returns if this context is valid, i.e. has been successfully created.
+    Returns if this context is valid, i.e. has been successfully created.
+
+    \sa create()
 */
 bool QOpenGLContext::isValid() const
 {
@@ -228,11 +349,13 @@ bool QOpenGLContext::isValid() const
 }
 
 /*!
-  Get the QOpenGLFunctions instance for this context.
+    Get the QOpenGLFunctions instance for this context.
 
-  The context or a sharing context must be current.
-*/
+    QOpenGLContext offers this as a convenient way to access QOpenGLFunctions
+    without having to manage it manually.
 
+    The context or a sharing context must be current.
+*/
 QOpenGLFunctions *QOpenGLContext::functions() const
 {
     Q_D(const QOpenGLContext);
@@ -242,15 +365,17 @@ QOpenGLFunctions *QOpenGLContext::functions() const
 }
 
 /*!
-  Call this to get the default framebuffer object for the current surface.
+    Call this to get the default framebuffer object for the current surface.
 
-  On some platforms the default framebuffer object depends on the surface being rendered to,
-  and might be different from 0. Thus, instead of calling glBindFramebuffer(0), you should
-  call glBindFramebuffer(ctx->defaultFramebufferObject()) if you want your application to
-  work across different Qt platforms.
+    On some platforms the default framebuffer object depends on the surface
+    being rendered to, and might be different from 0. Thus, instead of calling
+    glBindFramebuffer(0), you should call
+    glBindFramebuffer(ctx->defaultFramebufferObject()) if you want your
+    application to work across different Qt platforms.
 
-  If you use the glBindFramebuffer() in QOpenGLFunctions you do not have to worry about this,
-  as it automatically binds the current context's defaultFramebufferObject() when 0 is passed.
+    If you use the glBindFramebuffer() in QOpenGLFunctions you do not have to
+    worry about this, as it automatically binds the current context's
+    defaultFramebufferObject() when 0 is passed.
 */
 GLuint QOpenGLContext::defaultFramebufferObject() const
 {
@@ -265,12 +390,18 @@ GLuint QOpenGLContext::defaultFramebufferObject() const
 }
 
 /*!
-  If surface is 0 this is equivalent to calling doneCurrent().
+    Makes the context current in the current thread, against the given
+    \a surface.
+
+    If \a surface is 0 this is equivalent to calling doneCurrent().
 
-  Do not call this function from a different thread than the one the QOpenGLContext instance lives in. If
-  you wish to use QOpenGLContext from a different thread you should first call make sure it's not current
-  in the current thread, by calling doneCurrent() if necessary. Then call moveToThread(otherThread)
-  before using it in the other thread.
+    Do not call this function from a different thread than the one the
+    QOpenGLContext instance lives in. If you wish to use QOpenGLContext from a
+    different thread you should first call make sure it's not current in the
+    current thread, by calling doneCurrent() if necessary. Then call
+    moveToThread(otherThread) before using it in the other thread.
+
+    \sa functions(), doneCurrent()
 */
 bool QOpenGLContext::makeCurrent(QSurface *surface)
 {
@@ -313,6 +444,10 @@ bool QOpenGLContext::makeCurrent(QSurface *surface)
 
 /*!
     Convenience function for calling makeCurrent with a 0 surface.
+
+    This results in no context being current in the current thread.
+
+    \sa makeCurrent(), currentContext()
 */
 void QOpenGLContext::doneCurrent()
 {
@@ -330,7 +465,9 @@ void QOpenGLContext::doneCurrent()
 }
 
 /*!
-    Returns the surface the context is current for.
+    Returns the surface the context has been made current with.
+
+    This is the surface passed as an argument to makeCurrent().
 */
 QSurface *QOpenGLContext::surface() const
 {
@@ -391,6 +528,11 @@ void QOpenGLContext::swapBuffers(QSurface *surface)
     d->platformGLContext->swapBuffers(surfaceHandle);
 }
 
+/*!
+    Resolves the function pointer to an OpenGL extension function, identified by \a procName
+
+    Returns 0 if no such function can be found.
+*/
 QFunctionPointer QOpenGLContext::getProcAddress(const QByteArray &procName)
 {
     Q_D(QOpenGLContext);
@@ -399,6 +541,11 @@ QFunctionPointer QOpenGLContext::getProcAddress(const QByteArray &procName)
     return d->platformGLContext->getProcAddress(procName);
 }
 
+/*!
+    Returns the format of the underlying platform context, if create() has been called.
+
+    Otherwise, returns the requested format.
+*/
 QSurfaceFormat QOpenGLContext::format() const
 {
     Q_D(const QOpenGLContext);
@@ -407,27 +554,41 @@ QSurfaceFormat QOpenGLContext::format() const
     return d->platformGLContext->format();
 }
 
+/*!
+    Returns the share group this context belongs to.
+*/
 QOpenGLContextGroup *QOpenGLContext::shareGroup() const
 {
     Q_D(const QOpenGLContext);
     return d->shareGroup;
 }
 
+/*!
+    Returns the share context this context was created with.
+
+    If the underlying platform was not able to support the requested
+    sharing, this will return 0.
+*/
 QOpenGLContext *QOpenGLContext::shareContext() const
 {
     Q_D(const QOpenGLContext);
     return d->shareContext;
 }
 
+/*!
+    Returns the screen the context was created for.
+*/
 QScreen *QOpenGLContext::screen() const
 {
     Q_D(const QOpenGLContext);
     return d->screen;
 }
 
-/*
-  internal: Needs to have a pointer to qGLContext. But since this is in QtGui we cant
-  have any type information.
+/*!
+    internal: Needs to have a pointer to qGLContext. But since this is in QtGui we cant
+    have any type information.
+
+    \internal
 */
 void *QOpenGLContext::qGLContextHandle() const
 {
@@ -435,6 +596,9 @@ void *QOpenGLContext::qGLContextHandle() const
     return d->qGLContextHandle;
 }
 
+/*!
+    \internal
+*/
 void QOpenGLContext::setQGLContextHandle(void *handle,void (*qGLContextDeleteFunction)(void *))
 {
     Q_D(QOpenGLContext);
@@ -442,6 +606,9 @@ void QOpenGLContext::setQGLContextHandle(void *handle,void (*qGLContextDeleteFun
     d->qGLContextDeleteFunction = qGLContextDeleteFunction;
 }
 
+/*!
+    \internal
+*/
 void QOpenGLContext::deleteQGLContext()
 {
     Q_D(QOpenGLContext);
@@ -452,23 +619,45 @@ void QOpenGLContext::deleteQGLContext()
     }
 }
 
+/*!
+    \class QOpenGLContextGroup
+    \brief The QOpenGLContextGroup represents a group of contexts sharing
+    OpenGL resources.
+
+    QOpenGLContextGroup is automatically created and managed by QOpenGLContext
+    instances.  Its purpose is to identify all the contexts that are sharing
+    resources.
+
+    \sa QOpenGLContext::shareGroup()
+*/
 QOpenGLContextGroup::QOpenGLContextGroup()
     : QObject(*new QOpenGLContextGroupPrivate())
 {
 }
 
+/*!
+    \internal
+*/
 QOpenGLContextGroup::~QOpenGLContextGroup()
 {
     Q_D(QOpenGLContextGroup);
     d->cleanup();
 }
 
+/*!
+    Returns all the QOpenGLContext objects in this share group.
+*/
 QList<QOpenGLContext *> QOpenGLContextGroup::shares() const
 {
     Q_D(const QOpenGLContextGroup);
     return d->m_shares;
 }
 
+/*!
+    Returns the QOpenGLContextGroup corresponding to the current context.
+
+    \sa QOpenGLContext::currentContext()
+*/
 QOpenGLContextGroup *QOpenGLContextGroup::currentContextGroup()
 {
     QOpenGLContext *current = QOpenGLContext::currentContext();
@@ -544,9 +733,10 @@ void QOpenGLContextGroupPrivate::deletePendingResources(QOpenGLContext *ctx)
     \class QOpenGLSharedResource
     \internal
     \since 5.0
-    \brief The QOpenGLSharedResource class is used to keep track of resources that
-    are shared between OpenGL contexts (like textures, framebuffer objects, shader
-    programs, etc), and clean them up in a safe way when they're no longer needed.
+    \brief The QOpenGLSharedResource class is used to keep track of resources
+    that are shared between OpenGL contexts (like textures, framebuffer
+    objects, shader programs, etc), and clean them up in a safe way when
+    they're no longer needed.
 
     The QOpenGLSharedResource instance should never be deleted, instead free()
     should be called when it's no longer needed. Thus it will be put on a queue
@@ -556,11 +746,11 @@ void QOpenGLContextGroupPrivate::deletePendingResources(QOpenGLContext *ctx)
     The sub-class needs to implement two pure virtual functions. The first,
     freeResource() must be implemented to actually do the freeing, for example
     call glDeleteTextures() on a texture id. Qt makes sure a valid context in
-    the resource's share group is current at the time. The other, invalidateResource(),
-    is called by Qt in the circumstance when the last context in the share group is
-    destroyed before free() has been called. The implementation of invalidateResource()
-    should set any identifiers to 0 or set a flag to prevent them from being used
-    later on.
+    the resource's share group is current at the time. The other,
+    invalidateResource(), is called by Qt in the circumstance when the last
+    context in the share group is destroyed before free() has been called. The
+    implementation of invalidateResource() should set any identifiers to 0 or
+    set a flag to prevent them from being used later on.
 */
 QOpenGLSharedResource::QOpenGLSharedResource(QOpenGLContextGroup *group)
     : m_group(group)
@@ -616,9 +806,9 @@ void QOpenGLSharedResourceGuard::freeResource(QOpenGLContext *context)
     \since 5.0
     \brief The QOpenGLMultiGroupSharedResource keeps track of a shared resource
     that might be needed from multiple contexts, like a glyph cache or gradient
-    cache. One instance of the object is created for each group when
-    necessary. The shared resource instance should have a constructor that
-    takes a QOpenGLContext *. To get an instance for a given context one calls
+    cache. One instance of the object is created for each group when necessary.
+    The shared resource instance should have a constructor that takes a
+    QOpenGLContext *. To get an instance for a given context one calls
     T *QOpenGLMultiGroupSharedResource::value<T>(context), where T is a sub-class
     of QOpenGLSharedResource.