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

Last change on this file since 1168 was 846, checked in by Dmitry A. Kuminov, 14 years ago

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

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