source: trunk/doc/src/examples/svgalib.qdoc@ 769

Last change on this file since 769 was 769, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.3 sources from branches/vendor/nokia/qt.

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