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

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

trunk: Merged in qt 4.6.1 sources.

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