summaryrefslogtreecommitdiffstats
path: root/doc/src/examples/ahigl.qdoc
diff options
context:
space:
mode:
Diffstat (limited to 'doc/src/examples/ahigl.qdoc')
-rw-r--r--doc/src/examples/ahigl.qdoc572
1 files changed, 572 insertions, 0 deletions
diff --git a/doc/src/examples/ahigl.qdoc b/doc/src/examples/ahigl.qdoc
new file mode 100644
index 0000000..d42df66
--- /dev/null
+++ b/doc/src/examples/ahigl.qdoc
@@ -0,0 +1,572 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example qws/ahigl
+ \title OpenGL for Embedded Systems Example
+
+ \section1 Introduction
+
+ This example demonstrates how you can use OpenGL for Embedded
+ Systems (ES) in your own screen driver and \l{add your graphics
+ driver to Qt for Embedded Linux}. In \l{Qt for Embedded Linux},
+ painting is done in software, normally performed in two steps:
+ First, each client renders its windows onto its window surface in
+ memory using a paint engine. Then the server uses the screen
+ driver to compose the window surface images and copy the
+ composition to the screen. (See the \l{Qt for Embedded Linux
+ Architecture} documentation for details.)
+
+ This example is not for the novice. It assumes the reader is
+ familiar with both OpenGL and the screen driver framework
+ demonstrated in the \l {Accelerated Graphics Driver Example}.
+
+ An OpenGL screen driver for Qt for Embedded Linux can use OpenGL ES
+ in three ways. First, the \l{QWSServer}{Qt for Embedded Linux server}
+ can use the driver to compose multiple window images and then show the
+ composition on the screen. Second, clients can use the driver to
+ accelerate OpenGL painting operations using the QOpenGLPaintEngine
+ class. Finally, clients can use the driver to do OpenGL operations
+ with instances of the QGLWidget class. This example implements all
+ three cases.
+
+ The example uses an implementation of OpenGL ES from
+ \l {http://ati.amd.com}{ATI} for the
+ \l {http://ati.amd.com/products/imageon238x/}{Imageon 2380}. The
+ OpenGL include files gl.h and egl.h must be installed to compile
+ the example, and the OpenGL and EGL libraries must be installed
+ for linking. If your target device is different, you must install
+ the include files and libraries for that device, and you also
+ might need to modify the example source code, if any API signatures
+ in your EGL library differ from the ones used here.
+
+ After compiling and linking the example source, install the
+ screen driver plugin with the command \c {make install}. To
+ start an application that uses the plugin, you can either set the
+ environment variable \l QWS_DISPLAY and then start the
+ application, or just start the application with the \c -display
+ switch, as follows:
+
+ \snippet doc/src/snippets/code/doc_src_examples_ahigl.qdoc 0
+
+ The example driver also implements an animated transition effect
+ for use when showing new windows or reshowing windows that have
+ been minimized. To enable this transition effect, run the
+ application with \c {-display ahigl:effects}.
+
+ \section1 The Class Definitions
+
+ The example comprises three main classes plus some helper classes.
+ The three main classes are the plugin (QAhiGLScreenPlugin), which
+ is defined in qscreenahiglplugin.cpp, the screen driver
+ (QAhiGLScreen), which is defined in qscreenahigl_qws.h, and the
+ window surface (QAhiGLWindowSurface), which is defined in
+ qwindowsurface_ahigl_p.h. The "Ahi" prefix in these class names
+ stands for \e {ATI Handheld Interface}. The example was written
+ for the ATI Imageon 2380, but it can also be used as a template
+ for other ATI handheld devices.
+
+ \section2 The Plugin Class Definition
+
+ The screen driver plugin is class QAhiGLScreenPlugin.
+
+ \snippet examples/qws/ahigl/qscreenahiglplugin.cpp 0
+
+ QAhiGLScreenPlugin is derived from class QScreenDriverPlugin,
+ which in turn is derived from QObject.
+
+ \section2 The Screen Driver Class Definitions
+
+ The screen driver classes are the public class QAhiGLScreen and
+ its private implementation class QAhiGLScreenPrivate. QAhiGLScreen
+ is derived from QGLScreen, which is derived from QScreen. If your
+ screen driver will only do window compositions and display them,
+ then you can derive your screen driver class directly from
+ QScreen. But if your screen driver will do accelerated graphics
+ rendering operations with the QOpenGLPaintEngine, or if it will
+ handle instances of class QGLWidget, then you must derive your
+ screen driver class from QGLScreen.
+
+ \snippet examples/qws/ahigl/qscreenahigl_qws.h 0
+
+ All functions in the public API of class QAhiGLScreen are virtual
+ functions declared in its base classes. hasOpenGL() is declared in
+ QGLScreen. It simply returns true indicating our example screen
+ driver does support OpenGL operations. The other functions in the
+ public API are declared in QScreen. They are called by the
+ \l{QWSServer}{Qt for Embedded Linux server} at the appropriate times.
+
+ Note that class QScreen is a documented class but class QGLScreen
+ is not. This is because the design of class QGLScreen is not yet
+ final.
+
+ The only data member in class QAhiGLScreen is a standard d_ptr,
+ which points to an instance of the driver's private implementation
+ class QAhiGLScreenPrivate. The driver's internal state is stored
+ in the private class. Using the so-called d-pointer pattern allows
+ you to make changes to the driver's internal design without
+ breaking binary compatibility.
+
+ \snippet examples/qws/ahigl/qscreenahigl_qws.cpp 0
+
+ Class QAhiGLScreenPrivate is derived from QObject so that it can
+ use the Qt signal/slot mechanism. QAhiGLScreen is not a QObject,
+ so it can't use the signal/slot mechanism. Signals meant for our
+ screen driver are received by slots in the private implementation
+ class, in this case, windowEvent() and redrawScreen().
+
+ \section2 The Window Surface Class Definitions
+
+ The window surface classes are QAhiGLWindowSurface and its private
+ implementation class QAhiGLWindowSurfacePrivate. We create class
+ QAhiGLWindowSurface so the screen driver can use the OpenGL paint
+ engine and the OpenGL widget, classes QOpenGLPaintEngine and
+ QGLWidget. QAhiGLWindowSurface is derived from the more general
+ OpenGL window surface class, QWSGLWindowSurface, which is derived
+ from QWSWindowSurface.
+
+ \snippet examples/qws/ahigl/qwindowsurface_ahigl_p.h 0
+
+ In addition to implementing the standard functionality required by
+ any new subclass of QWSWindowSurface, QAhiGLWindowSurface also
+ contains the textureId() function used by QAhiGLScreen.
+
+ The same d-pointer pattern is used in this window surface class.
+ The private implementation class is QAhiGLWindowSurfacePrivate. It
+ allows making changes to the state variables of the window surface
+ without breaking binary compatibility.
+
+ \snippet examples/qws/ahigl/qwindowsurface_ahigl.cpp 0
+
+ In this case, our private implementation class has no member
+ functions except for its constructor. It contains only public data
+ members which hold state information for the window surface.
+
+ \section2 The Helper Classes
+
+ The example screen driver maintains a static \l {QMap} {map} of
+ all the \l {QWSWindow} {windows} it is showing on the screen.
+ Each window is mapped to an instance of struct WindowInfo.
+
+ \snippet examples/qws/ahigl/qscreenahigl_qws.cpp 2
+
+ As each new window is created, an instance of struct WindowInfo is
+ allocated and inserted into the window map. WindowInfo uses a
+ GLuint to identify the OpenGL texture it creates for the window.
+ Note that the example driver, in addition to drawing windows using
+ OpenGL, also supports drawing windows in the normal way without
+ OpenGL, but it uses an OpenGL texture for the rendering operations
+ in either case. Top-level windows that are drawn without OpenGL
+ are first rendered in the normal way into a shared memory segment,
+ which is then converted to a OpenGL texture and drawn to the
+ screen.
+
+ To animate the window transition effect, WindowInfo uses an
+ instance of the helper class ShowAnimation. The animation is
+ created by the windowEvent() slot in QAhiGLScreenPrivate, whenever
+ a \l {QWSServer::WindowEvent} {Show} window event is emitted by
+ the \l {QWSServer} {window server}. The server emits this signal
+ when a window is shown the first time and again later, when the
+ window is reshown after having been minimized.
+
+ \snippet examples/qws/ahigl/qscreenahigl_qws.cpp 1
+
+ Class ShowAnimation is derived from the QTimeLine class, which is
+ used for controlling animations. QTimeLine is a QObject, so
+ ShowAnimation can use the Qt signal/slot mechanism. We will see
+ how the timeline's \l {QTimeLine::valueChanged()} {valueChanged()}
+ and \l {QTimeLine::finished()} {finished()} signals are used to
+ control the animation and then destroy the instance of
+ ShowAnimation, when the animation ends. The ShowAnimation
+ constructor needs the pointer to the screen driver's private
+ implementation class so it can set up these signal/slot
+ connections.
+
+ \section1 The Class Implementations
+
+ \section2 The Plugin Class Implementation
+
+ QAhiGLScreenPlugin is a straightforward derivation of
+ QScreenDriverPlugin. It reimplements \l{QScreenDriverPlugin::}{keys()}
+ and \l{QScreenDriverPlugin::}{create()}. They are
+ called as needed by the \l{QWSServer}{Qt for Embedded Linux server.}
+ Recall that the server detects that the ahigl screen driver has
+ been requested, either by including "ahigl" in the value for the
+ environment variable QWS_DISPLAY, or by running your application
+ with a command line like the following.
+
+ \snippet doc/src/snippets/code/doc_src_examples_ahigl.qdoc 1
+
+ The server calls \l {QScreenDriverPlugin::} {keys()}, which
+ returns a \l {QStringList} containing the singleton "ahigl"
+ matching the requested screen driver and telling the server that
+ it can use our example screen driver. The server then calls \l
+ {QScreenDriverPlugin::} {create()}, which creates the instance of
+ QAhiGLScreen.
+
+ \snippet examples/qws/ahigl/qscreenahiglplugin.cpp 1
+
+ In the code snippet above, the macro Q_EXPORT_PLUGIN2 is used to export
+ the plugin class, QAhiGLScreen, for the qahiglscreen plugin.
+ Further information regarding plugins and how to create them
+ can be found at \l{How to Create Qt Plugins}.
+
+ \section2 The Screen Driver Class Implementations
+
+ The plugin creates the singleton instance of QAhiGLScreen. The
+ constructor is passed a \c displayId, which is used in the base
+ class QGLScreen to identify the server that the screen driver is
+ connected to. The constructor also creates its instance of
+ QAhiGLScreenPrivate, which instantiates a QTimer. The timeout()
+ signal of this timer is connected to the redrawScreen() slot so
+ the timer can be used to limit the frequency of actual drawing
+ operations in the hardware.
+
+ The public API of class QAhiGLScreen consists of implementations
+ of virtual functions declared in its base classes. The function
+ hasOpenGL() is declared in base class QGLScreen. The others are
+ declared in base class QScreen.
+
+ The \l {QScreen::}{connect()} function is the first one called by
+ the server after the screen driver is constructed. It initializes
+ the QScreen data members to hardcoded values that describe the ATI
+ screen. A better implementation would query the hardware for the
+ corresponding values in its current state and use those. It asks
+ whether the screen driver was started with the \c effects option
+ and sets the \c doEffects flag accordingly.
+
+ \snippet examples/qws/ahigl/qscreenahigl_qws.cpp 7
+
+ The \l {QScreen::}{initDevice()} function is called by the server
+ after \l {QScreen::}{connect()}. It uses EGL library functions to
+ initialize the ATI hardware. Note that some data structures used
+ in this example are specific to the EGL implementation used, e.g.,
+ the DummyScreen structure.
+
+ \snippet examples/qws/ahigl/qscreenahigl_qws.cpp 8
+
+ Note the signal/slot connection at the bottom of initDevice(). We
+ connect the server's QWSServer::windowEvent() signal to the
+ windowEvent() slot in the screen driver's private implementation
+ class. The windowEvent() slot handles three window events,
+ QWSServer::Create, QWSServer::Destroy, and QWSServer::Show.
+
+ \snippet examples/qws/ahigl/qscreenahigl_qws.cpp 5
+
+ The function manages instances of the helper classes associated
+ with each window. When a QWSServer::Create event occurs, it means
+ a new top-level \l {QWSWindow} {window} has been created. In this
+ case, an instance of helper class WindowInfo is created and
+ inserted into the window map with the pointer to the new \l
+ {QWSWindow} {window} as its key. When a QWSServer::Destroy event
+ occurs, a window is being destroyed, and its mapping is removed
+ from the window map. These two events are straightforward. The
+ tricky bits happen when a QWSServer::Show event occurs. This case
+ occurs when a window is shown for the first time and when it is
+ reshown after having been minimized. If the window transition
+ effect has been enabled, a new instance of the helper class
+ ShowAnimation is created and stored in a QPointer in the window's
+ instance of WindowInfo. The constructor of ShowAnimation
+ automatically \l {QTimeLine::start()} {starts} the animation of
+ the transition effect.
+
+ \snippet examples/qws/ahigl/qscreenahigl_qws.cpp 3
+
+ To ensure that a ShowAnimation is not deleted until its animation
+ ends, the \l {QTimeLine::finished()} {finished()} signal is
+ connected to the \l {QObject::deleteLater()} {deleteLater()} slot.
+ When the animation ends, the finished() signal is emitted and the
+ deleteLater() slot deletes the ShowAnimation. The key here is that
+ the pointer to the ShowAnimation is stored in a QPointer in the
+ WindowInfo class. This QPointer will also be notified when the
+ ShowAnimation is deleted, so the QPointer in WindowInfo can null
+ itself out, if and only if it is still pointing to the instance
+ of ShowAnimation being deleted.
+
+ The \l {QTimeLine::valueForTime()} {valueForTime()} function in
+ QTimeLine is reimplemented in ShowAnimation to return time values
+ that represent a curved path for the window transition effect.
+
+ \snippet examples/qws/ahigl/qscreenahigl_qws.cpp 4
+
+ valueForTime() is called internally, when the time interval it
+ computed during the previous call has elapsed. If it computes a
+ next time value that is different from the one computed
+ previously, the \l {QTimeLine::valueChanged()} {valueChanged()}
+ signal is emitted. The ShowAnimation constructor shown above
+ connects this signal to the redrawScreen() slot in the screen
+ driver's private implementation class. This is how the animation
+ actually happens.
+
+ The screen driver's implementation of \l {QScreen::}
+ {exposeRegion()} is where the main work of the screen driver is
+ meant to be done, i.e., updating the screen. It is called by the
+ \l {QWSServer} {window system} to update a particular window's
+ region of the screen. But note that it doesn't actually update the
+ screen, i.e., it doesn't actually call redrawScreen() directly,
+ but starts the updateTimer, which causes redrawScreen() to be
+ called once for each updateTimer interval. This means that all
+ calls to exposeRegion() during an updateTimer interval are handled
+ by a single call to redrawScreen(). Thus updateTimer can be used
+ to limit the frequency of screen updates.
+
+ \snippet examples/qws/ahigl/qscreenahigl_qws.cpp 13
+
+ The call to the private function invalidateTexture() destroys
+ the window's existing texture (image). This ensures that a new
+ texture will be created for the window, when redrawScreen() is
+ eventually called.
+
+ But there is a caveat to using updateTimer to limit the frequency
+ of screen updates. When the driver's animated transition effect
+ for new windows is enabled and a new window is being shown for the
+ first time or reshown after having been minimized, an instance of
+ ShowAnimation is created to run the animation. The valueChanged()
+ signal of this ShowAnimation is also connected to the
+ redrawScreen() slot, and QTimeLine, the base class of our
+ ShowAnimation, uses its own, internal timer to limit the speed of
+ the animation. This means that in the driver as currently written,
+ if the window transition effect is enabled (i.e. if the plugin is
+ started, with \c {-display ahigl:effects}), then redrawScreen()
+ can be called both when the update timer times out and when the
+ ShowAnimation timer times out, so the screen might get updated
+ more often than the frequency established by the update timer.
+ This may or may not be a bug, depending on your own hardware, if
+ you use this example as a template for your own OpenGL driver.
+
+ The screen driver's private function redrawScreen() constructs
+ the window compositions. It is called only by the function of the
+ same name in the screen driver's private implementation class.
+
+ \snippet examples/qws/ahigl/qscreenahigl_qws.cpp 6
+
+ Recall that this redrawScreen() in the private implementation
+ class is a slot function connected to two signals, the \c
+ timeout() signal of the updateTimer in the private implementation
+ class, and the valueChanged() signal of the helper class
+ ShowAnimation. Thus, the screen is only ever updated when a
+ timeout of one of the two timers occurs. This is important for two
+ reasons. First, the screen is meant to be updated no more than
+ once per updateTimer interval. Second, however, if the animated
+ window transition effect is requested, the screen might be updated
+ more often than that, and this might be a bug if the hardware
+ can't handle more frequent updates.
+
+ The redrawScreen() in QAhiGLScreen begins by using standard
+ OpenGL to fill the screen with the background color.
+
+ \snippet examples/qws/ahigl/qscreenahigl_qws.cpp 10
+
+ Next it iterates over the list of all \l {QWSWindow} {client
+ windows} obtained from the \l {QWSServer} {server}, extracting
+ from each window its instance of QWSWIndowSurface, then using that
+ window surface to create an OpenGL texture, and finally calling
+ the helper function drawWindow() to draw the texture on the
+ screen.
+
+ \snippet examples/qws/ahigl/qscreenahigl_qws.cpp 11
+
+ Note the call to glBindTexture() immediately before the call to
+ drawWindow(). This call binds the identifer \c GL_TEXTURE_2D to
+ the texture we have just created. This makes our texture
+ accessible to functions in the OpenGL libraries. If you miss that
+ point, digging into the internals of drawWindow() won't make much
+ sense.
+
+ Finally, the cursor is added to the window composition, and in the
+ last statement, the whole thing is displayed on the screen.
+
+ \snippet examples/qws/ahigl/qscreenahigl_qws.cpp 12
+
+ The call to \c drawWindow(win,progress), in addition to passing a
+ pointer to the window to be redrawn, also passes the \c progress
+ parameter obtained by calling \l {QTimeLine::currentValue()} on
+ the window's instance of ShowAnimation. Recall that the current
+ value of the timeline is updated internally by a timer local to
+ the timeline, and the redrawScreen() slot is called whenever the
+ current value changes. The progress value will only be used if
+ the animated transition effect has been enabled. These extra calls
+ of redrawScreen() may cause the screen to be updated more often
+ than the rate determined by updateTimer. This must be taken
+ into account, if you set your updateTimer to timeout at the
+ maximum screen update frequency your hardware can handle.
+
+ The drawWindow() function is not shown here and not explained
+ further, but the call to drawWindow() is the entry point to a
+ hierarchy of private helper functions that execute sequences of
+ OpenGL and EGL library calls. The reader is assumed to be familiar
+ enough with the OpenGL and EGL APIs to understand the code in
+ these helper functions on his own. Besides drawWindow(), the list
+ of these helper functions includes drawQuad(), drawQuadWavyFlag(),
+ the two overloadings of drawQuad_helper() (used by drawQuad() and
+ drawQuadWacyFlag()), and setRectCoords().
+
+ Note the two different ways the window's texture can be created in
+ redrawScreen(). If the window surface is an OpenGL window surface
+ (QAhiGLWindowSurface described below), the texture is obtained
+ from the window surface directly by calling its textureId()
+ function. But when the window surface is not an OpenGL one, the
+ static function createTexture() is called with the window
+ surface's \l {QImage} {image} to copy that image into an OpenGL
+ texture. This is done with the EGL functions glTexImage2D() and
+ glTexSubImage2D(). createTexture() is another function that
+ should be understandable for exsperienced OpenGL users, so it is
+ not shown or explained further here.
+
+ The two implementations of \l {QScreen::}{createSurface()} are for
+ instantiating new window surfaces. The overloading with the widget
+ parameter is called in the client.
+
+ \snippet examples/qws/ahigl/qscreenahigl_qws.cpp 14
+
+ If the parameter is an \l {QGLWidget} {OpenGL widget}, or, when it
+ isn't an OpenGL widget but its size is no bigger than 256 x 256,
+ we instantiate our subclass QAhiGLWindowSurface. Otherwise, we
+ instantiate a QWSWindowSurface. The size contraint is a
+ limitation of the OpenGL ES libraries we are using for our ATI
+ device.
+
+ Note the test at the top of the function asking if our application
+ process is the \l {QApplication::GuiServer} {server}. We only
+ create instances of QAhiGLWindowSurface if our client is in the
+ server process. This is because of an implementation restriction
+ required by the OpenGL library used in the example. They only
+ support use of OpenGL in the server process. Hence a client can
+ use the QAhiGLWindowSurface if the client is in the server
+ process.
+
+ The other overloading of createSurface() is called by the
+ server to create a window surface that will hold a copy of a
+ client side window surface.
+
+ \snippet examples/qws/ahigl/qscreenahigl_qws.cpp 15
+
+ This overloading accepts a QString parameter identifying the type
+ of window surface to instantiate. QAhiGLWindowSurface is
+ instantiated if the parameter is \c ahigl. Otherwise, a normal
+ QWSWindowSurface is instantiated. The client's window surface
+ communicates its image data to the server's window surface through
+ shared memory.
+
+ The implementation of \l {QScreen::}{setMode()}, is a stub in this
+ example. It would normally reset the frame buffer's resolution.
+ Its parameters are the \e width, \e height, and the bit \e depth
+ for the frame buffer's new resolution. If you implement setMode()
+ in your screen driver, remember that it must emit a signal to warn
+ other applications to redraw their frame buffers with the new
+ resolution. There is no significance to setMode() not being
+ implemented in this example. It simply wasn't implemented.
+ However, the stub had to be included because QScreen declares
+ setMode() to be pure virtual.
+
+ Before the application exits, the server will call \l {QScreen::}
+ {shutdownDevice()} to release the hardware resources. This is also
+ done using EGL library functions.
+
+ \snippet examples/qws/ahigl/qscreenahigl_qws.cpp 9
+
+ The server will also call \l {QScreen::}{disconnect()}, but this
+ function is only a stub in this example.
+
+ \section2 The window Surface Class Implementations
+
+ QAhiGLScreen creates instances of QAhiGLWindowSurface in its two
+ createSurface() functions, and there are two constructors for
+ QAhiGLWindowSurface that correspond to these two versions of
+ createSurface(). The constructor accepting a \l {QWidget} {widget}
+ parameter is called by the client side version of createSurface(),
+ and the constructor without the \l {QWidget} {widget} parameter is
+ called by the server side version. There will be a window surface
+ constructed on the server side for each one constructed on the
+ client side.
+
+ \snippet examples/qws/ahigl/qwindowsurface_ahigl.cpp 1
+ \codeline
+ \snippet examples/qws/ahigl/qwindowsurface_ahigl.cpp 2
+
+ The constructors create an instance of QAhiGLWindowSurfacePrivate,
+ the private implementation class, which contains all the state
+ variables for QAhiGLWindowSurface. The client side constructor
+ also creates an instance of QWSGLPaintDevice, the OpenGL paint
+ device, for return by \l {QWSWindowSurface::} {paintDevice()}.
+ This ensures that all \l {QPainter}s used on this surface will use
+ an OpenGL enabled QPaintEngine. It is a bit of jiggery pokery,
+ which is required because \l {QWSWindowSurface::} {paintDevice()}
+ is declared pure virtual. Normally, the client side constructor
+ will be called with an \l {QGLWidget}{OpenGL widget}, which has
+ its own \l {QWidget::} {paintEngine()} function that returns the
+ global static OpenGL paint engine, but because the constructor
+ also accepts a normal \l {QWidget}{widget}, it must be able to
+ find the OpenGL paint engine in that case as well, so since \l
+ {QWSWindowSurface::} {paintDevice()} must be implemented anyway,
+ the constructor creates an instance of QWSGLPaintDevice, which can
+ always return the global static pointer to QOpenGLPaintEngine.
+
+ The OpenGL library implementation used for this example only
+ supports one OpenGL context. This context is therefore shared
+ among the single instance of QAhiGLScreen and all instances of
+ QAhiGLWindowSurface. It is passed to both constructors.
+
+ This example uses the OpenGL frame buffer object extension, which
+ allows for accelerating OpenGL painting operations. Using this
+ OpenGL extension, painting operations are performed in a frame
+ buffer object, which QAhiGLScreen later uses to construct window
+ compositions on the screen. Allocation of the frame buffer object
+ is performed in \l {QWindowSurface::} {setGeometry()}. A safer way
+ to use this extension would be to first test to see if the
+ extension is supported by your OpenGL library, and use a different
+ approach if it is not.
+
+ \snippet examples/qws/ahigl/qwindowsurface_ahigl.cpp 3
+
+ Since there can be several instances of the QAhiGLWindowSurface, we need
+ to make sure that the correct framebuffer object is active before painting.
+ This is done by reimplementing \l QWindowSurface::beginPaint():
+
+ \snippet examples/qws/ahigl/qwindowsurface_ahigl.cpp 4
+
+ Finally we need to make sure that whenever a widget grows beyond the size
+ supported by this driver (256 x 256), the surface is deleted and a new
+ standard surface is created instead. This is handled by reimplementing
+ \l QWSWindowSurface::isValid():
+
+ \snippet examples/qws/ahigl/qwindowsurface_ahigl.cpp 5
+*/