doc/src/examples/svgalib.qdoc
branchRCL_3
changeset 7 3f74d0d4af4c
equal deleted inserted replaced
6:dee5afe5301f 7:3f74d0d4af4c
       
     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 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    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 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    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