summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTrond Kjernåsen <trond.kjernasen@nokia.com>2010-09-09 10:27:46 (GMT)
committerTrond Kjernåsen <trond.kjernasen@nokia.com>2010-09-09 10:29:56 (GMT)
commitc0c5f52efeb62d05c2c6a379a46fccb1166ce73d (patch)
tree95fa750655518d5820c83b9be0fb7ec85fb037ce /src
parent48b5fa29f5da3c241bc64520bd56ccd5713c4586 (diff)
downloadQt-c0c5f52efeb62d05c2c6a379a46fccb1166ce73d.zip
Qt-c0c5f52efeb62d05c2c6a379a46fccb1166ce73d.tar.gz
Qt-c0c5f52efeb62d05c2c6a379a46fccb1166ce73d.tar.bz2
Doc update regarding threaded painting with QPainter in the QGL module.
Reviewed-by: Gunnar
Diffstat (limited to 'src')
-rw-r--r--src/opengl/qgl.cpp92
-rw-r--r--src/opengl/qglframebufferobject.cpp7
-rw-r--r--src/opengl/qglpixelbuffer.cpp8
3 files changed, 98 insertions, 9 deletions
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
index 5a50716..e4967a6 100644
--- a/src/opengl/qgl.cpp
+++ b/src/opengl/qgl.cpp
@@ -3610,16 +3610,90 @@ void QGLContextPrivate::setCurrentContext(QGLContext *context)
\section1 Threading
- It is possible to render into a QGLWidget from another thread, but
- it requires that all access to the GL context is safe guarded. The
- Qt GUI thread will try to use the context in resizeEvent and
- paintEvent, so in order for threaded rendering using a GL widget
- to work, these functions need to be intercepted in the GUI thread
- and handled accordingly in the application. Under X11, set the
- Qt::AA_X11InitThreads application attribute, before you create the
- QApplication object, to make the X11 library and GLX calls thread
- safe.
+ As of Qt version 4.8, support for doing threaded GL rendering has
+ been improved. There are three scenarios that we currently support:
+ \list
+ \o 1. Buffer swapping in a thread.
+
+ Swapping buffers in a double buffered context may be a
+ synchronous, locking call that may be a costly operation in some
+ GL implementations. Especially so on embedded devices. It's not
+ optimal to have the CPU idling while the GPU is doing a buffer
+ swap. In those cases it is possible to do the rendering in the
+ main thread and do the actual buffer swap in a separate
+ thread. This can be done with the following steps:
+
+ 1. Call doneCurrent() in the main thread when the rendering is
+ finished.
+
+ 2. Notify the swapping thread that it can grab the context.
+
+ 3. Make the rendering context current in the swapping thread with
+ makeCurrent() and then call swapBuffers().
+
+ 4. Call doneCurrent() in the swapping thread and notify the main
+ thread that swapping is done.
+
+ Doing this will free up the main thread so that it can continue
+ with, for example, handling UI events or network requests. Even if
+ there is a context swap involved, it may be preferable compared to
+ having the main thread wait while the GPU finishes the swap
+ operation. Note that this is highly implementation dependent.
+
+ \o 2. Texture uploading in a thread.
+
+ Doing texture uploads in a thread may be very useful for
+ applications handling large amounts of images that needs to be
+ displayed, like for instance a photo gallery application. This is
+ supported in Qt through the existing bindTexture() API. A simple
+ way of doing this is to create two sharing QGLWidgets. One is made
+ current in the main GUI thread, while the other is made current in
+ the texture upload thread. The widget in the uploading thread is
+ never shown, it is only used for sharing textures with the main
+ thread. For each texture that is bound via bindTexture(), notify
+ the main thread so that it can start using the texture.
+
+ \o 3. Using QPainter to draw into a QGLWidget in a thread.
+
+ In Qt 4.8, it is possible to draw into a QGLWidget using a
+ QPainter in a separate thread. Note that this is also possible for
+ QGLPixelBuffers and QGLFramebufferObjects. Since this is only
+ supported in the GL 2 paint engine, OpenGL 2.0 or OpenGL ES 2.0 is
+ required.
+
+ QGLWidgets can only be created in the main GUI thread. This means
+ a call to doneCurrent() is necessary to release the GL context
+ from the main thread, before the widget can be drawn into by
+ another thread. Also, the main GUI thread will dispatch resize and
+ paint events to a QGLWidget when the widget is resized, or parts
+ of it becomes exposed or needs redrawing. It is therefore
+ necessary to handle those events because the default
+ implementations inside QGLWidget will try to make the QGLWidget's
+ context current, which again will interfere with any threads
+ rendering into the widget. Reimplement QGLWidget::paintEvent() and
+ QGLWidget::resizeEvent() to notify the rendering thread that a
+ resize or update is necessary, and be careful not to call the base
+ class implementation. If you are rendering an animation, it might
+ not be necessary to handle the paint event at all since the
+ rendering thread is doing regular updates. Then it would be enough
+ to reimplement QGLWidget::paintEvent() to do nothing.
+
+ \endlist
+
+ As a general rule when doing threaded rendering: be aware that
+ binding and releasing contexts in different threads have to be
+ synchronized by the user. A GL rendering context can only be
+ current in one thread at any time. If you try to open a QPainter
+ on a QGLWidget and the widget's rendering context is current in
+ another thread, it will fail.
+
+ Note that under X11 it is necessary to set the
+ Qt::AA_X11InitThreads application attribute to make the X11
+ library and GLX calls thread safe, otherwise the above scenarios
+ will fail.
+ In addition to this, rendering using raw GL calls in a separate
+ thread is supported.
\e{OpenGL is a trademark of Silicon Graphics, Inc. in the United States and other
countries.}
diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp
index 876e97a..660201b 100644
--- a/src/opengl/qglframebufferobject.cpp
+++ b/src/opengl/qglframebufferobject.cpp
@@ -616,6 +616,13 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz,
as a texture, you first need to copy from it to a regular framebuffer
object using QGLContext::blitFramebuffer().
+ \section Threading
+
+ As of Qt 4.8, it's possible to draw into a QGLFramebufferObject
+ using a QPainter in a separate thread. Note that OpenGL 2.0 or
+ OpenGL ES 2.0 is required for this to work. Also, under X11, it's
+ necessary to set the Qt::AA_X11InitThreads application attribute.
+
\sa {Framebuffer Object Example}
*/
diff --git a/src/opengl/qglpixelbuffer.cpp b/src/opengl/qglpixelbuffer.cpp
index 3d9cd21..da2974c 100644
--- a/src/opengl/qglpixelbuffer.cpp
+++ b/src/opengl/qglpixelbuffer.cpp
@@ -70,6 +70,14 @@
extension.
\endlist
+
+ \section Threading
+
+ As of Qt 4.8, it's possible to render into a QGLPixelBuffer using
+ a QPainter in a separate thread. Note that OpenGL 2.0 or OpenGL ES
+ 2.0 is required for this to work. Also, under X11, it's necessary
+ to set the Qt::AA_X11InitThreads application attribute.
+
Pbuffers are provided by the OpenGL \c pbuffer extension; call
hasOpenGLPbuffer() to find out if the system provides pbuffers.