Update copyright headers
[qt:qt.git] / doc / src / examples / svgalib.qdoc
1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the documentation of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:FDL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Free Documentation License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Free
19 ** Documentation License version 1.3 as published by the Free Software
20 ** Foundation and appearing in the file included in the packaging of
21 ** this file.  Please review the following information to ensure
22 ** the GNU Free Documentation License version 1.3 requirements
23 ** will be met: http://www.gnu.org/copyleft/fdl.html.
24 ** $QT_END_LICENSE$
25 **
26 ****************************************************************************/
27
28 /*!
29     \example qws/svgalib
30     \title Accelerated Graphics Driver Example
31
32     \brief The Accelerated Graphics Driver example shows how you can write
33     your own accelerated graphics driver and \l {add your graphics
34     driver to Qt for Embedded Linux}.
35     
36     In \l{Qt for Embedded Linux},
37     painting is a pure software implementation and is normally performed
38     in two steps:
39     The clients render each window onto a corresponding surface
40     (stored in memory) using a paint engine, and then the server uses
41     the graphics driver to compose the surface images and copy them to
42     the screen. (See the \l{Qt for Embedded Linux Architecture} documentation
43     for details.)
44
45     The rendering can be accelerated in two ways: Either by
46     accelerating the copying of pixels to the screen, or by
47     accelerating the explicit painting operations. The first is done
48     in the graphics driver implementation, the latter is performed by
49     the paint engine implementation. Typically, both the pixel copying
50     and the painting operations are accelerated using the following
51     approach:
52
53     \list 1
54         \o \l {Step 1: Creating a Custom Graphics Driver}
55         {Creating a Custom Graphics Driver}
56
57         \o \l {Step 2: Implementing a Custom Raster Paint Engine}
58         {Implementing a Custom Paint Engine}
59
60         \o \l {Step 3: Making the Widgets Aware of the Custom Paint
61         Engine}{Making the Widgets Aware of the Custom Paint Engine}
62
63     \endlist
64
65     After compiling the example code, install the graphics driver
66     plugin with the command \c {make install}. To start an application
67     using the graphics driver, you can either set the environment
68     variable \l QWS_DISPLAY and then run the application, or you can
69     just run the application using the \c -display switch:
70
71     \snippet doc/src/snippets/code/doc_src_examples_svgalib.qdoc 0
72
73     \table
74     \header \o SVGAlib
75     \row \o
76
77     Instead of interfacing the graphics hardware directly, this
78     example relies on \l {http://www.svgalib.org}{SVGAlib} being
79     installed on your system.  \l {http://www.svgalib.org}{SVGAlib} is
80     a small graphics library which provides acceleration for many
81     common graphics cards used on desktop computers. It should work on
82     most workstations and has a small and simple API.
83
84     \endtable
85
86     \section1 Step 1: Creating a Custom Graphics Driver
87
88     The custom graphics driver is created by deriving from the QScreen
89     class. QScreen is the base class for implementing screen/graphics
90     drivers in Qt for Embedded Linux.
91
92     \snippet examples/qws/svgalib/svgalibscreen.h 0
93     \codeline
94     \snippet examples/qws/svgalib/svgalibscreen.h 1
95
96     The \l {QScreen::}{connect()}, \l {QScreen::}{disconnect()}, \l
97     {QScreen::}{initDevice()} and \l {QScreen::}{shutdownDevice()}
98     functions are declared as pure virtual functions in QScreen and
99     must be implemented. They are used to configure the hardware, or
100     query its configuration: \l {QScreen::}{connect()} and \l
101     {QScreen::}{disconnect()} are called by both the server and client
102     processes, while the \l {QScreen::}{initDevice()} and \l
103     {QScreen::}{shutdownDevice()} functions are only called by the
104     server process.
105
106     QScreen's \l {QScreen::}{setMode()} and \l {QScreen::}{blank()}
107     functions are also pure virtual, but our driver's implementations
108     are trivial. The last two functions (\l {QScreen::}{blit()} and \l
109     {QScreen::}{solidFill()}) are the ones involved in putting pixels
110     on the screen, i.e., we reimplement these functions to perform the
111     pixel copying acceleration.
112
113     Finally, the \c context variable is a pointer to a \l
114     {http://www.svgalib.org}{SVGAlib} specific type. Note that the
115     details of using the \l {http://www.svgalib.org}{SVGAlib} library
116     is beyond the scope of this example.
117
118     \section2 SvgalibScreen Class Implementation
119
120     The \l {QScreen::}{connect()} function is the first function that
121     is called after the constructor returns. It queries \l
122     {http://www.svgalib.org}{SVGAlib} about the graphics mode and
123     initializes the variables.
124
125     \snippet examples/qws/svgalib/svgalibscreen.cpp 0
126
127     It is important that the \l {QScreen::}{connect()} function
128     initializes the \c data, \c lstep, \c w, \c h, \c dw, \c dh, \c d,
129     \c physWidth and \c physHeight variables (inherited from QScreen)
130     to ensure that the driver is in a state consistent with the driver
131     configuration.
132
133     In this particular example we do not have any information of the
134     real physical size of the screen, so we set these values with the
135     assumption of a screen with 72 DPI.
136
137     \snippet examples/qws/svgalib/svgalibscreen.cpp 1
138
139     When the \l {QScreen::}{connect()} function returns, the server
140     process calls the \l {QScreen::}{initDevice()} function which is
141     expected to do the necessary hardware initialization, leaving the
142     hardware in a state consistent with the driver configuration.
143
144     Note that we have chosen to use the software cursor. If you want
145     to use a hardware cursor, you should create a subclass of
146     QScreenCursor, create an instance of it, and make the global
147     variable \c qt_screencursor point to this instance.
148
149     \snippet examples/qws/svgalib/svgalibscreen.cpp 2
150     \codeline
151     \snippet examples/qws/svgalib/svgalibscreen.cpp 3
152
153     Before exiting, the server process will call the \l
154     {QScreen::}{shutdownDevice()} function to do the necessary
155     hardware cleanup. Again, it is important that the function leaves
156     the hardware in a state consistent with the driver
157     configuration. When \l {QScreen::}{shutdownDevice()} returns, the
158     \l {QScreen::}{disconnect()} function is called. Our
159     implementation of the latter function is trivial.
160
161     Note that, provided that the \c QScreen::data variable points to a
162     valid linear framebuffer, the graphics driver is fully functional
163     as a simple screen driver at this point. The rest of this example
164     will show where to take advantage of the accelerated capabilities
165     available on the hardware.
166
167     Whenever an area on the screen needs to be updated, the server will
168     call the \l {QScreen::}{exposeRegion()} function that paints the 
169     given region on screen. The default implementation will do the 
170     necessary composing of the top-level windows and call \l 
171     {QScreen::}{solidFill()} and \l {QScreen::}{blit()} whenever it is 
172     required. We do not want to change this behavior in the driver so
173     we do not reimplement \l {QScreen::}{exposeRegion()}. 
174
175     To control how the pixels are put onto the screen we need to
176     reimplement the \l {QScreen::}{solidFill()} and \l 
177     {QScreen::}{blit()} functions.
178
179     \snippet examples/qws/svgalib/svgalibscreen.cpp 4
180     \codeline
181     \snippet examples/qws/svgalib/svgalibscreen.cpp 5
182
183     \section1 Step 2: Implementing a Custom Raster Paint Engine
184
185     \l{Qt for Embedded Linux} uses QRasterPaintEngine (a raster-based
186     implementation of QPaintEngine) to implement the painting
187     operations.
188
189     Acceleration of the painting operations is done by deriving from
190     QRasterPaintEngine class. This is a powerful mechanism for
191     accelerating graphic primitives while getting software fallbacks
192     for all the primitives you do not accelerate.
193
194     \snippet examples/qws/svgalib/svgalibpaintengine.h 0
195
196     In this example, we will only accelerate one of the \l
197     {QRasterPaintEngine::}{drawRects()} functions, i.e., only
198     non-rotated, aliased and opaque rectangles will be rendered using
199     accelerated painting. All other primitives are rendered using the
200     base class's unaccelerated implementation.
201
202     The paint engine's state is stored in the private member
203     variables, and we reimplement the \l
204     {QPaintEngine::}{updateState()} function to ensure that our
205     custom paint engine's state is updated properly whenever it is
206     required. The private \c setClip() and \c updateClip() functions
207     are only helper function used to simplify the \l
208     {QPaintEngine::}{updateState()} implementation.
209
210     We also reimplement QRasterPaintEngine's \l
211     {QRasterPaintEngine::}{begin()} and \l
212     {QRasterPaintEngine::}{end()} functions to initialize the paint
213     engine and to do the cleanup when we are done rendering,
214     respectively.
215
216     \table
217     \header \o Private Header Files
218     \row
219     \o
220
221     Note the \c include statement used by this class. The files
222     prefixed with \c private/ are private headers file within
223     \l{Qt for Embedded Linux}. Private header files are not part of
224     the standard installation and are only present while
225     compiling Qt. To be able to compile using
226     private header files you need to use a \c qmake binary within a
227     compiled \l{Qt for Embedded Linux} package.
228
229     \warning Private header files may change without notice between
230     releases.
231
232     \endtable
233
234     The \l {QRasterPaintEngine::}{begin()} function initializes the
235     internal state of the paint engine. Note that it also calls the
236     base class implementation to initialize the parts inherited from
237     QRasterPaintEngine:
238
239     \snippet examples/qws/svgalib/svgalibpaintengine.cpp 0
240     \codeline
241     \snippet examples/qws/svgalib/svgalibpaintengine.cpp 1
242
243     The implementation of the \l {QRasterPaintEngine::}{end()}
244     function removes the clipping constraints that might have been set
245     in \l {http://www.svgalib.org}{SVGAlib}, before calling the
246     corresponding base class implementation.
247
248     \snippet examples/qws/svgalib/svgalibpaintengine.cpp 2
249
250     The \l {QPaintEngine::}{updateState()} function updates our
251     custom paint engine's state. The QPaintEngineState class provides
252     information about the active paint engine's current state.
253
254     Note that we only accept and save the current matrix if it doesn't
255     do any shearing. The pen is accepted if it is opaque and only one
256     pixel wide. The rest of the engine's properties are updated
257     following the same pattern. Again it is important that the
258     QPaintEngine::updateState() function is called to update the
259     parts inherited from the base class.
260
261     \snippet examples/qws/svgalib/svgalibpaintengine.cpp 3
262     \codeline
263     \snippet examples/qws/svgalib/svgalibpaintengine.cpp 4
264
265     The \c setClip() helper function is called from our custom
266     implementation of \l {QPaintEngine::}{updateState()}, and
267     enables clipping to the given region. An empty region means that
268     clipping is disabled.
269
270     Our custom update function also makes use of the \c updateClip()
271     helper function that checks if the clip is "simple", i.e., that it
272     can be represented by only one rectangle, and updates the clip
273     region in \l {http://www.svgalib.org}{SVGAlib}.
274
275     \snippet examples/qws/svgalib/svgalibpaintengine.cpp 5
276
277     Finally, we accelerated that drawing of non-rotated, aliased and
278     opaque rectangles in our reimplementation of the \l
279     {QRasterPaintEngine::}{drawRects()} function. The
280     QRasterPaintEngine fallback is used whenever the rectangle is not
281     simple enough.
282
283     \section1 Step 3: Making the Widgets Aware of the Custom Paint Engine
284
285     To activate the custom paint engine, we also need to implement a
286     corresponding paint device and window surface and make some minor
287     adjustments of the graphics driver.
288
289     \list
290         \o \l {Implementing a Custom Paint Device}
291         \o \l {Implementing a Custom Window Surface}
292         \o \l {Adjusting the Graphics Driver}
293     \endlist
294
295     \section2 Implementing a Custom Paint Device
296
297     The custom paint device can be derived from the
298     QCustomRasterPaintDevice class. Reimplement its \l
299     {QCustomRasterPaintDevice::}{paintEngine()} and \l
300     {QCustomRasterPaintDevice::}{memory()} functions to activate the
301     accelerated paint engine:
302
303     \snippet examples/qws/svgalib/svgalibpaintdevice.h 0
304
305     The \l {QCustomRasterPaintDevice::}{paintEngine()} function should
306     return an instance of the \c SvgalibPaintEngine class. The \l
307     {QCustomRasterPaintDevice::}{memory()} function should return a
308     pointer to the buffer which should be used when drawing the
309     widget.
310
311     Our example driver is rendering directly to the screen without any
312     buffering, i.e., our custom pain device's \l
313     {QCustomRasterPaintDevice::}{memory()} function returns a pointer
314     to the framebuffer. For this reason, we must also reimplement the
315     \l {QPaintDevice::}{metric()} function to reflect the metrics of
316     framebuffer.
317
318     \section2 Implementing a Custom Window Surface
319
320     The custom window surface can be derived from the QWSWindowSurface
321     class. QWSWindowSurface manages the memory used when drawing a
322     window.
323
324     \snippet examples/qws/svgalib/svgalibsurface.h 0
325
326     We can implement most of the pure virtual functions inherited from
327     QWSWindowSurface as trivial inline functions, except the scroll()
328     function that actually makes use of some hardware acceleration:
329
330     \snippet examples/qws/svgalib/svgalibsurface.cpp 0
331
332     \section2 Adjusting the Graphics Driver
333
334     Finally, we enable the graphics driver to recognize an instance of
335     our custom window surface:
336
337     \snippet examples/qws/svgalib/svgalibscreen.cpp 7
338     \codeline
339     \snippet examples/qws/svgalib/svgalibscreen.cpp 8
340
341     The \l {QScreen::}{createSurface()} functions are factory
342     functions that determines what kind of surface a top-level window
343     is using. In our example we only use the custom surface if the
344     given window has the Qt::WA_PaintOnScreen attribute or the
345     QT_ONSCREEN_PAINT environment variable is set.
346 */
347