Qtopia Core 4.2 Screen Drivers

by Håvard Wall

QScreen is a class that is specific to Qtopia Core (previously called Qt/Embedded). It is the base class for Qtopia Core's built-in and custom screen drivers. In this article, we will review the changes that were made to QScreen in Qtopia Core 4.2 and show how to take full advantage of hardware acceleration.

Multihead Support

QScreen now features two virtual functions that can be reimplemented by subclasses to support multiple screens:

    QList<QScreen *> subScreens() const;
    QRegion region() const;

Qtopia Core 4.2 also include a "Multi" screen driver, which creates other QScreen instances and forwards all function calls to the appropriate QScreen. Here's an example of how to run a Qtopia Core application on three different screens simultaneously:

app -qws -display "Multi: QVFb:0 QVFb:offset=640,0:1 VNC"
Using -display, we tell Qtopia Core to create two instances of the Qt virtual buffer driver ("QVFb") and one instance of the VNC driver. The second QVFb instance is given an offset of (640, 0), so that it doesn't overlap the first instance.

The coordinates passed to your reimplementations of QScreen's virtual functions are always specified in global coordinates. In most cases, your existing custom drivers will work with no change, but if you perform some kind of lookup in a data structure that assumes the screen's origin is (0, 0), you will need to subtract QScreen::offset() to convert the global coordinates into screen coordinates.

Window Surface Abstraction

Qtopia Core 4.2 introduces "window surfaces" as a mechanism to control the memory used when painting a QWidget. This provides a way to accelerate painting beyond what is possible by reimplementing QScreen's solidFill() and blit() functions. To support window surfaces, these factory functions were added to QScreen:

    QWSWindowSurface *createSurface(QWidget *widget) const;
    QWSWindowSurface *createSurface(const QString &key) const;

QWSWindowSurface is the abstraction of the area a top-level QWidget (i.e., a window) is drawn onto. By default, if you are creating a window in the QWS server, this will be a chunk of local memory. If you are creating a window in a client process, it will be a chunk of shared memory. And if you set the Qt::WA_PaintOnScreen attribute on the window, it will be an area inside the framebuffer. This default behavior can be overridden by reimplementing the createSurface() functions in a subclass.

If you're writing a driver for a device with little memory and no framebuffer, you probably want to avoid drawing into memory at all and rather use an I/O controller to send drawing commands directly to the video card. To achieve this, you would subclass QWSWindowSurface to avoid the memory allocation and reimplement the paintDevice() function to return a QCustomRasterPaintDevice subclass. The paint device's paintEngine() function would return an instance of an accelerated paint engine.

Writing an Accelerated Paint Engine

Writing an accelerated paint engine consists of subclassing QRasterPaintEngine and reimplementing the following two virtual functions, which are new in Qtopia Core 4.2:

    void drawColorSpans(const QSpan *spans, int count,
                        uint color);
    void drawBufferSpan(const uint *buffer, int bufferSize,
                        int x, int y, int length,
                        uint constantAlpha);

These functions are only called if the paint device's memory() function is reimplemented to return 0. The drawColorSpans() function is called to draw one or more spans with the given color on the screen. The drawBufferSpan() function is called to draw a buffer of pixels from memory.

Be aware that both QWSWindowSurface and the accelerated paint engine technique described above are included in Qtopia Core 4.2 as "preliminary APIs", meaning that they may change in a later release.

This document is licensed under the Creative Commons Attribution-Share Alike 2.5 license.

Copyright © 2006 Trolltech Trademarks