doc/src/examples/svgalib.qdoc
changeset 0 1918ee327afb
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     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 ** 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     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