src/gui/embedded/qscreen_qws.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gui/embedded/qscreen_qws.cpp	Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,3340 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qscreen_qws.h"
+
+#include "qcolormap.h"
+#include "qscreendriverfactory_qws.h"
+#include "qwindowsystem_qws.h"
+#include "qwidget.h"
+#include "qcolor.h"
+#include "qpixmap.h"
+#include "qvarlengtharray.h"
+#include "qwsdisplay_qws.h"
+#include "qpainter.h"
+#include <private/qdrawhelper_p.h>
+#include <private/qpaintengine_raster_p.h>
+#include <private/qpixmap_raster_p.h>
+#include <private/qwindowsurface_qws_p.h>
+#include <private/qpainter_p.h>
+#include <private/qwidget_p.h>
+#include <private/qgraphicssystem_qws_p.h>
+
+QT_BEGIN_NAMESPACE
+
+// #define QT_USE_MEMCPY_DUFF
+
+#ifndef QT_NO_QWS_CURSOR
+bool qt_sw_cursor=false;
+Q_GUI_EXPORT QScreenCursor * qt_screencursor = 0;
+#endif
+Q_GUI_EXPORT QScreen * qt_screen = 0;
+
+ClearCacheFunc QScreen::clearCacheFunc = 0;
+
+#ifndef QT_NO_QWS_CURSOR
+/*!
+    \class QScreenCursor
+    \ingroup qws
+
+    \brief The QScreenCursor class is a base class for screen cursors
+    in Qt for Embedded Linux.
+
+    Note that this class is non-portable, and that it is only
+    available in \l{Qt for Embedded Linux}.
+
+    QScreenCursor implements a software cursor, but can be subclassed
+    to support hardware cursors as well. When deriving from the
+    QScreenCursor class it is important to maintain the cursor's
+    image, position, hot spot (the point within the cursor's image
+    that will be the position of the associated mouse events) and
+    visibility as well as informing whether it is hardware accelerated
+    or not.
+
+    Note that there may only be one screen cursor at a time. Use the
+    static instance() function to retrieve a pointer to the current
+    screen cursor. Typically, the cursor is constructed by the QScreen
+    class or one of its descendants when it is initializing the
+    device; the QScreenCursor class should never be instantiated
+    explicitly.
+
+    Use the move() function to change the position of the cursor, and
+    the set() function to alter its image or its hot spot. In
+    addition, you can find out whether the cursor is accelerated or
+    not, using the isAccelerated() function, and the boundingRect()
+    function returns the cursor's bounding rectangle.
+
+    The cursor's appearance can be controlled using the isVisible(),
+    hide() and show() functions; alternatively the QWSServer class
+    provides some means of controlling the cursor's appearance using
+    the QWSServer::isCursorVisible() and QWSServer::setCursorVisible()
+    functions.
+
+    \sa QScreen, QWSServer
+*/
+
+/*!
+    \fn static QScreenCursor* QScreenCursor::instance()
+    \since 4.2
+
+    Returns a pointer to the application's unique screen cursor.
+*/
+
+extern bool qws_sw_cursor;
+
+/*!
+    Constructs a screen cursor
+*/
+QScreenCursor::QScreenCursor()
+{
+    pos = QPoint(qt_screen->deviceWidth()/2, qt_screen->deviceHeight()/2);
+    size = QSize(0,0);
+    enable = true;
+    hwaccel = false;
+    supportsAlpha = true;
+}
+
+/*!
+    Destroys the screen cursor.
+*/
+QScreenCursor::~QScreenCursor()
+{
+}
+
+/*!
+    Hides the cursor from the screen.
+
+    \sa show()
+*/
+void QScreenCursor::hide()
+{
+    if (enable) {
+        enable = false;
+        if (!hwaccel)
+            qt_screen->exposeRegion(boundingRect(), 0);
+    }
+}
+
+/*!
+    Shows the mouse cursor.
+
+    \sa hide()
+*/
+void QScreenCursor::show()
+{
+    if (!enable) {
+        enable = true;
+        if (!hwaccel)
+            qt_screen->exposeRegion(boundingRect(), 0);
+    }
+}
+
+/*!
+    Sets the cursor's image to be the given \a image.
+
+    The \a hotx and \a hoty parameters define the cursor's hot spot,
+    i.e., the point within the cursor's image that will be the
+    position of the associated mouse events.
+
+    \sa move()
+*/
+void QScreenCursor::set(const QImage &image, int hotx, int hoty)
+{
+    const QRect r = boundingRect();
+
+    hotspot = QPoint(hotx, hoty);
+    // These are in almost all cases the fastest formats to blend
+    QImage::Format f;
+    switch (qt_screen->depth()) {
+    case 12:
+        f = QImage::Format_ARGB4444_Premultiplied;
+        break;
+    case 15:
+        f =  QImage::Format_ARGB8555_Premultiplied;
+        break;
+    case 16:
+        f = QImage::Format_ARGB8565_Premultiplied;
+        break;
+    case 18:
+        f = QImage::Format_ARGB6666_Premultiplied;
+        break;
+    default:
+        f =  QImage::Format_ARGB32_Premultiplied;
+    }
+
+    cursor = image.convertToFormat(f);
+
+    size = image.size();
+
+    if (enable && !hwaccel)
+        qt_screen->exposeRegion(r | boundingRect(), 0);
+}
+
+/*!
+    Moves the mouse cursor to the given position, i.e., (\a x, \a y).
+
+    Note that the given position defines the top-left corner of the
+    cursor's image, i.e., not the cursor's hot spot (the position of
+    the associated mouse events).
+
+    \sa set()
+*/
+void QScreenCursor::move(int x, int y)
+{
+    QRegion r = boundingRect();
+    pos = QPoint(x,y);
+    if (enable && !hwaccel) {
+        r |= boundingRect();
+        qt_screen->exposeRegion(r, 0);
+    }
+}
+
+
+/*!
+    \fn void QScreenCursor::initSoftwareCursor ()
+
+    Initializes the screen cursor.
+
+    This function is typically called from the screen driver when
+    initializing the device. Alternatively, the cursor can be set
+    directly using the pointer returned by the static instance()
+    function.
+
+    \sa QScreen::initDevice()
+*/
+void QScreenCursor::initSoftwareCursor()
+{
+    qt_screencursor = new QScreenCursor;
+}
+
+
+#endif // QT_NO_QWS_CURSOR
+
+
+/*!
+    \fn QRect QScreenCursor::boundingRect () const
+
+    Returns the cursor's bounding rectangle.
+*/
+
+/*!
+    \internal
+    \fn bool QScreenCursor::enabled ()
+*/
+
+/*!
+    \fn QImage QScreenCursor::image () const
+
+    Returns the cursor's image.
+*/
+
+
+/*!
+    \fn bool QScreenCursor::isAccelerated () const
+
+    Returns true if the cursor is accelerated; otherwise false.
+*/
+
+/*!
+    \fn bool QScreenCursor::isVisible () const
+
+    Returns true if the cursor is visible; otherwise false.
+*/
+
+/*!
+    \internal
+    \fn bool QScreenCursor::supportsAlphaCursor () const
+*/
+
+/*
+    \variable QScreenCursor::cursor
+
+    \brief the cursor's image.
+
+    \sa image()
+*/
+
+/*
+    \variable QScreenCursor::size
+
+    \brief the cursor's size
+*/
+
+/*
+    \variable QScreenCursor::pos
+
+    \brief the cursor's position, i.e., the position of the top-left
+    corner of the crsor's image
+
+    \sa set(), move()
+*/
+
+/*
+    \variable QScreenCursor::hotspot
+
+    \brief the cursor's hotspot, i.e., the point within the cursor's
+    image that will be the position of the associated mouse events.
+
+    \sa set(), move()
+*/
+
+/*
+    \variable QScreenCursor::enable
+
+    \brief whether the cursor is visible or not
+
+    \sa isVisible()
+*/
+
+/*
+    \variable QScreenCursor::hwaccel
+
+    \brief holds whether the cursor is accelerated or not
+
+    If the cursor is not accelerated, its image will be included by
+    the screen when it composites the window surfaces.
+
+    \sa isAccelerated()
+
+*/
+
+/*
+    \variable QScreenCursor::supportsAlpha
+*/
+
+/*!
+    \internal
+    \macro qt_screencursor
+    \relates QScreenCursor
+
+    A global pointer referring to the unique screen cursor. It is
+    equivalent to the pointer returned by the
+    QScreenCursor::instance() function.
+*/
+
+
+
+class QScreenPrivate
+{
+public:
+    QScreenPrivate(QScreen *parent, QScreen::ClassId id = QScreen::CustomClass);
+    ~QScreenPrivate();
+
+    inline QImage::Format preferredImageFormat() const;
+
+    typedef void (*SolidFillFunc)(QScreen*, const QColor&, const QRegion&);
+    typedef void (*BlitFunc)(QScreen*, const QImage&, const QPoint&, const QRegion&);
+
+    SolidFillFunc solidFill;
+    BlitFunc blit;
+
+    QPoint offset;
+    QList<QScreen*> subScreens;
+    QPixmapDataFactory* pixmapFactory;
+    QGraphicsSystem* graphicsSystem;
+    QWSGraphicsSystem defaultGraphicsSystem; //###
+    QImage::Format pixelFormat;
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+    bool fb_is_littleEndian;
+#endif
+#ifdef QT_QWS_CLIENTBLIT
+    bool supportsBlitInClients;
+#endif
+    int classId;
+    QScreen *q_ptr;
+};
+
+template <typename T>
+static void solidFill_template(QScreen *screen, const QColor &color,
+                               const QRegion &region)
+{
+    T *dest = reinterpret_cast<T*>(screen->base());
+    const T c = qt_colorConvert<T, quint32>(color.rgba(), 0);
+    const int stride = screen->linestep();
+    const QVector<QRect> rects = region.rects();
+
+    for (int i = 0; i < rects.size(); ++i) {
+        const QRect r = rects.at(i);
+        qt_rectfill(dest, c, r.x(), r.y(), r.width(), r.height(), stride);
+    }
+}
+
+#ifdef QT_QWS_DEPTH_GENERIC
+static void solidFill_rgb_32bpp(QScreen *screen, const QColor &color,
+                                const QRegion &region)
+{
+    quint32 *dest = reinterpret_cast<quint32*>(screen->base());
+    const quint32 c = qt_convertToRgb<quint32>(color.rgba());
+
+    const int stride = screen->linestep();
+    const QVector<QRect> rects = region.rects();
+
+    for (int i = 0; i < rects.size(); ++i) {
+        const QRect r = rects.at(i);
+        qt_rectfill(dest, c, r.x(), r.y(), r.width(), r.height(), stride);
+    }
+}
+
+static void solidFill_rgb_16bpp(QScreen *screen, const QColor &color,
+                                const QRegion &region)
+{
+    quint16 *dest = reinterpret_cast<quint16*>(screen->base());
+    const quint16 c = qt_convertToRgb<quint32>(color.rgba());
+
+    const int stride = screen->linestep();
+    const QVector<QRect> rects = region.rects();
+
+    for (int i = 0; i < rects.size(); ++i) {
+        const QRect r = rects.at(i);
+        qt_rectfill(dest, c, r.x(), r.y(), r.width(), r.height(), stride);
+    }
+}
+#endif // QT_QWS_DEPTH_GENERIC
+
+#ifdef QT_QWS_DEPTH_4
+static inline void qt_rectfill_gray4(quint8 *dest, quint8 value,
+                                     int x, int y, int width, int height,
+                                     int stride)
+{
+    const int pixelsPerByte = 2;
+    dest += y * stride + x / pixelsPerByte;
+    const int doAlign = x & 1;
+    const int doTail = (width - doAlign) & 1;
+    const int width8 = (width - doAlign) / pixelsPerByte;
+
+    for (int j = 0; j < height; ++j) {
+        if (doAlign)
+            *dest = (*dest & 0xf0) | (value & 0x0f);
+        if (width8)
+            qt_memfill<quint8>(dest + doAlign, value, width8);
+        if (doTail) {
+            quint8 *d = dest + doAlign + width8;
+            *d = (*d & 0x0f) | (value & 0xf0);
+        }
+        dest += stride;
+    }
+}
+
+static void solidFill_gray4(QScreen *screen, const QColor &color,
+                            const QRegion &region)
+{
+    quint8 *dest = reinterpret_cast<quint8*>(screen->base());
+    const quint8 c = qGray(color.rgba()) >> 4;
+    const quint8 c8 = (c << 4) | c;
+
+    const int stride = screen->linestep();
+    const QVector<QRect> rects = region.rects();
+
+    for (int i = 0; i < rects.size(); ++i) {
+        const QRect r = rects.at(i);
+        qt_rectfill_gray4(dest, c8, r.x(), r.y(), r.width(), r.height(),
+                          stride);
+    }
+}
+#endif // QT_QWS_DEPTH_4
+
+#ifdef QT_QWS_DEPTH_1
+static inline void qt_rectfill_mono(quint8 *dest, quint8 value,
+                                    int x, int y, int width, int height,
+                                    int stride)
+{
+    const int pixelsPerByte = 8;
+    const int alignWidth = qMin(width, (8 - (x & 7)) & 7);
+    const int doAlign = (alignWidth > 0 ? 1 : 0);
+    const int alignStart = pixelsPerByte - 1 - (x & 7);
+    const int alignStop = alignStart - (alignWidth - 1);
+    const quint8 alignMask = ((1 << alignWidth) - 1) << alignStop;
+    const int tailWidth = (width - alignWidth) & 7;
+    const int doTail = (tailWidth > 0 ? 1 : 0);
+    const quint8 tailMask = (1 << (pixelsPerByte - tailWidth)) - 1;
+    const int width8 = (width - alignWidth) / pixelsPerByte;
+
+    dest += y * stride + x / pixelsPerByte;
+    stride -= (doAlign + width8);
+
+    for (int j = 0; j < height; ++j) {
+        if (doAlign) {
+            *dest = (*dest & ~alignMask) | (value & alignMask);
+            ++dest;
+        }
+        if (width8) {
+            qt_memfill<quint8>(dest, value, width8);
+            dest += width8;
+        }
+        if (doTail)
+            *dest = (*dest & tailMask) | (value & ~tailMask);
+        dest += stride;
+    }
+}
+
+static void solidFill_mono(QScreen *screen, const QColor &color,
+                           const QRegion &region)
+{
+    quint8 *dest = reinterpret_cast<quint8*>(screen->base());
+    const quint8 c8 = (qGray(color.rgba()) >> 7) * 0xff;
+
+    const int stride = screen->linestep();
+    const QVector<QRect> rects = region.rects();
+
+    for (int i = 0; i < rects.size(); ++i) {
+        const QRect r = rects.at(i);
+        qt_rectfill_mono(dest, c8, r.x(), r.y(), r.width(), r.height(),
+                         stride);
+    }
+}
+#endif // QT_QWS_DEPTH_1
+
+void qt_solidFill_setup(QScreen *screen, const QColor &color,
+                        const QRegion &region)
+{
+    switch (screen->depth()) {
+#ifdef QT_QWS_DEPTH_32
+    case 32:
+        if (screen->pixelType() == QScreen::NormalPixel)
+            screen->d_ptr->solidFill = solidFill_template<quint32>;
+        else
+            screen->d_ptr->solidFill = solidFill_template<qabgr8888>;
+        break;
+#endif
+#ifdef QT_QWS_DEPTH_24
+    case 24:
+        if (screen->pixelType() == QScreen::NormalPixel)
+            screen->d_ptr->solidFill = solidFill_template<qrgb888>;
+        else
+            screen->d_ptr->solidFill = solidFill_template<quint24>;
+        break;
+#endif
+#ifdef QT_QWS_DEPTH_18
+    case 18:
+        screen->d_ptr->solidFill = solidFill_template<quint18>;
+        break;
+#endif
+#ifdef QT_QWS_DEPTH_16
+    case 16:
+        if (screen->pixelType() == QScreen::NormalPixel)
+            screen->d_ptr->solidFill = solidFill_template<quint16>;
+        else
+            screen->d_ptr->solidFill = solidFill_template<qbgr565>;
+        break;
+#endif
+#ifdef QT_QWS_DEPTH_15
+    case 15:
+        if (screen->pixelType() == QScreen::NormalPixel)
+            screen->d_ptr->solidFill = solidFill_template<qrgb555>;
+        else
+            screen->d_ptr->solidFill = solidFill_template<qbgr555>;
+        break;
+#endif
+#ifdef QT_QWS_DEPTH_12
+    case 12:
+        screen->d_ptr->solidFill = solidFill_template<qrgb444>;
+        break;
+#endif
+#ifdef QT_QWS_DEPTH_8
+    case 8:
+        screen->d_ptr->solidFill = solidFill_template<quint8>;
+        break;
+#endif
+#ifdef QT_QWS_DEPTH_4
+    case 4:
+        screen->d_ptr->solidFill = solidFill_gray4;
+        break;
+#endif
+#ifdef QT_QWS_DEPTH_1
+    case 1:
+        screen->d_ptr->solidFill = solidFill_mono;
+        break;
+#endif
+     default:
+        qFatal("solidFill_setup(): Screen depth %d not supported!",
+               screen->depth());
+        screen->d_ptr->solidFill = 0;
+        break;
+    }
+    screen->d_ptr->solidFill(screen, color, region);
+}
+
+template <typename DST, typename SRC>
+static void blit_template(QScreen *screen, const QImage &image,
+                          const QPoint &topLeft, const QRegion &region)
+{
+    DST *dest = reinterpret_cast<DST*>(screen->base());
+    const int screenStride = screen->linestep();
+    const int imageStride = image.bytesPerLine();
+
+    if (region.numRects() == 1) {
+        const QRect r = region.boundingRect();
+        const SRC *src = reinterpret_cast<const SRC*>(image.scanLine(r.y()))
+                         + r.x();
+        qt_rectconvert<DST, SRC>(dest, src,
+                                 r.x() + topLeft.x(), r.y() + topLeft.y(),
+                                 r.width(), r.height(),
+                                 screenStride, imageStride);
+    } else {
+        const QVector<QRect> rects = region.rects();
+
+        for (int i = 0; i < rects.size(); ++i) {
+            const QRect r = rects.at(i);
+            const SRC *src = reinterpret_cast<const SRC*>(image.scanLine(r.y()))
+                             + r.x();
+            qt_rectconvert<DST, SRC>(dest, src,
+                                     r.x() + topLeft.x(), r.y() + topLeft.y(),
+                                     r.width(), r.height(),
+                                     screenStride, imageStride);
+        }
+    }
+}
+
+#ifdef QT_QWS_DEPTH_32
+static void blit_32(QScreen *screen, const QImage &image,
+                    const QPoint &topLeft, const QRegion &region)
+{
+    switch (image.format()) {
+    case QImage::Format_RGB32:
+    case QImage::Format_ARGB32:
+    case QImage::Format_ARGB32_Premultiplied:
+        blit_template<quint32, quint32>(screen, image, topLeft, region);
+        return;
+#ifdef QT_QWS_DEPTH_16
+    case QImage::Format_RGB16:
+        blit_template<quint32, quint16>(screen, image, topLeft, region);
+        return;
+#endif
+    default:
+        qCritical("blit_32(): Image format %d not supported!", image.format());
+    }
+}
+#endif // QT_QWS_DEPTH_32
+
+#ifdef QT_QWS_DEPTH_24
+static void blit_24(QScreen *screen, const QImage &image,
+                    const QPoint &topLeft, const QRegion &region)
+{
+    switch (image.format()) {
+    case QImage::Format_RGB32:
+    case QImage::Format_ARGB32:
+    case QImage::Format_ARGB32_Premultiplied:
+        blit_template<quint24, quint32>(screen, image, topLeft, region);
+        return;
+    case QImage::Format_RGB888:
+        blit_template<quint24, qrgb888>(screen, image, topLeft, region);
+        return;
+#ifdef QT_QWS_DEPTH_16
+    case QImage::Format_RGB16:
+        blit_template<quint24, quint16>(screen, image, topLeft, region);
+        return;
+#endif
+    default:
+        qCritical("blit_24(): Image format %d not supported!", image.format());
+    }
+}
+
+static void blit_qrgb888(QScreen *screen, const QImage &image,
+                         const QPoint &topLeft, const QRegion &region)
+{
+    switch (image.format()) {
+    case QImage::Format_RGB32:
+    case QImage::Format_ARGB32:
+    case QImage::Format_ARGB32_Premultiplied:
+        blit_template<qrgb888, quint32>(screen, image, topLeft, region);
+        return;
+    case QImage::Format_RGB888:
+        blit_template<qrgb888, qrgb888>(screen, image, topLeft, region);
+        return;
+#ifdef QT_QWS_DEPTH_16
+    case QImage::Format_RGB16:
+        blit_template<qrgb888, quint16>(screen, image, topLeft, region);
+        return;
+#endif
+    default:
+        qCritical("blit_24(): Image format %d not supported!", image.format());
+        break;
+    }
+}
+#endif // QT_QWS_DEPTH_24
+
+#ifdef QT_QWS_DEPTH_18
+static void blit_18(QScreen *screen, const QImage &image,
+                    const QPoint &topLeft, const QRegion &region)
+{
+    switch (image.format()) {
+    case QImage::Format_RGB32:
+    case QImage::Format_ARGB32:
+    case QImage::Format_ARGB32_Premultiplied:
+        blit_template<qrgb666, quint32>(screen, image, topLeft, region);
+        return;
+    case QImage::Format_RGB666:
+        blit_template<qrgb666, qrgb666>(screen, image, topLeft, region);
+        return;
+#ifdef QT_QWS_DEPTH_16
+    case QImage::Format_RGB16:
+        blit_template<qrgb666, quint16>(screen, image, topLeft, region);
+        return;
+#endif
+    default:
+        qCritical("blit_18(): Image format %d not supported!", image.format());
+    }
+}
+#endif // QT_QWS_DEPTH_18
+
+#if (Q_BYTE_ORDER == Q_BIG_ENDIAN) && (defined(QT_QWS_DEPTH_16) || defined(QT_QWS_DEPTH_15))
+class quint16LE
+{
+public:
+    inline quint16LE(quint32 v) {
+        data = ((v & 0xff00) >> 8) | ((v & 0x00ff) << 8);
+    }
+
+    inline quint16LE(int v) {
+        data = ((v & 0xff00) >> 8) | ((v & 0x00ff) << 8);
+    }
+
+    inline quint16LE(quint16 v) {
+        data = ((v & 0xff00) >> 8) | ((v & 0x00ff) << 8);
+    }
+
+    inline quint16LE(qrgb555 v) {
+        data = (( (quint16)v & 0xff00) >> 8) |
+               (( (quint16)v & 0x00ff) << 8);
+    }
+
+    inline bool operator==(const quint16LE &v) const
+    {
+        return data == v.data;
+    }
+
+private:
+    quint16 data;
+};
+#endif
+
+#ifdef QT_QWS_DEPTH_16
+static void blit_16(QScreen *screen, const QImage &image,
+                    const QPoint &topLeft, const QRegion &region)
+{
+    switch (image.format()) {
+    case QImage::Format_RGB32:
+    case QImage::Format_ARGB32:
+    case QImage::Format_ARGB32_Premultiplied:
+        // ### This probably doesn't work but it's a case which should never happen
+        blit_template<quint16, quint32>(screen, image, topLeft, region);
+        return;
+    case QImage::Format_RGB16:
+        blit_template<quint16, quint16>(screen, image, topLeft, region);
+        return;
+    default:
+        qCritical("blit_16(): Image format %d not supported!", image.format());
+    }
+}
+
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+static void blit_16_bigToLittleEndian(QScreen *screen, const QImage &image,
+                                      const QPoint &topLeft,
+                                      const QRegion &region)
+{
+    switch (image.format()) {
+    case QImage::Format_RGB32:
+    case QImage::Format_ARGB32:
+    case QImage::Format_ARGB32_Premultiplied:
+        blit_template<quint16LE, quint32>(screen, image, topLeft, region);
+        return;
+    case QImage::Format_RGB16:
+        blit_template<quint16LE, quint16>(screen, image, topLeft, region);
+        return;
+    default:
+        qCritical("blit_16_bigToLittleEndian(): Image format %d not supported!", image.format());
+    }
+}
+
+#endif // Q_BIG_ENDIAN
+#endif // QT_QWS_DEPTH_16
+
+#ifdef QT_QWS_DEPTH_15
+static void blit_15(QScreen *screen, const QImage &image,
+                    const QPoint &topLeft, const QRegion &region)
+{
+    switch (image.format()) {
+    case QImage::Format_RGB32:
+    case QImage::Format_ARGB32:
+    case QImage::Format_ARGB32_Premultiplied:
+        blit_template<qrgb555, quint32>(screen, image, topLeft, region);
+        return;
+    case QImage::Format_RGB555:
+        blit_template<qrgb555, qrgb555>(screen, image, topLeft, region);
+        return;
+    case QImage::Format_RGB16:
+        blit_template<qrgb555, quint16>(screen, image, topLeft, region);
+        return;
+    default:
+        qCritical("blit_15(): Image format %d not supported!", image.format());
+    }
+}
+
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+static void blit_15_bigToLittleEndian(QScreen *screen, const QImage &image,
+                                      const QPoint &topLeft,
+                                      const QRegion &region)
+{
+    switch (image.format()) {
+    case QImage::Format_RGB555:
+        blit_template<quint16LE, qrgb555>(screen, image, topLeft, region);
+        return;
+    default:
+        qCritical("blit_15_bigToLittleEndian(): Image format %d not supported!", image.format());
+    }
+}
+#endif // Q_BIG_ENDIAN
+#endif // QT_QWS_DEPTH_15
+
+
+#ifdef QT_QWS_DEPTH_12
+static void blit_12(QScreen *screen, const QImage &image,
+                    const QPoint &topLeft, const QRegion &region)
+{
+    switch (image.format()) {
+    case QImage::Format_ARGB4444_Premultiplied:
+        blit_template<qrgb444, qargb4444>(screen, image, topLeft, region);
+        return;
+    case QImage::Format_RGB444:
+        blit_template<qrgb444, qrgb444>(screen, image, topLeft, region);
+        return;
+    default:
+        qCritical("blit_12(): Image format %d not supported!", image.format());
+    }
+}
+#endif // QT_QWS_DEPTH_12
+
+#ifdef QT_QWS_DEPTH_8
+static void blit_8(QScreen *screen, const QImage &image,
+                   const QPoint &topLeft, const QRegion &region)
+{
+    switch (image.format()) {
+    case QImage::Format_RGB32:
+    case QImage::Format_ARGB32:
+    case QImage::Format_ARGB32_Premultiplied:
+        blit_template<quint8, quint32>(screen, image, topLeft, region);
+        return;
+    case QImage::Format_RGB16:
+        blit_template<quint8, quint16>(screen, image, topLeft, region);
+        return;
+    case QImage::Format_ARGB4444_Premultiplied:
+        blit_template<quint8, qargb4444>(screen, image, topLeft, region);
+        return;
+    case QImage::Format_RGB444:
+        blit_template<quint8, qrgb444>(screen, image, topLeft, region);
+        return;
+    default:
+        qCritical("blit_8(): Image format %d not supported!", image.format());
+    }
+}
+#endif // QT_QWS_DEPTH_8
+
+#ifdef QT_QWS_DEPTH_4
+
+struct qgray4 { quint8 dummy; } Q_PACKED;
+
+template <typename SRC>
+Q_STATIC_TEMPLATE_FUNCTION inline quint8 qt_convertToGray4(SRC color);
+
+template <>
+inline quint8 qt_convertToGray4(quint32 color)
+{
+    return qGray(color) >> 4;
+}
+
+template <>
+inline quint8 qt_convertToGray4(quint16 color)
+{
+    const int r = (color & 0xf800) >> 11;
+    const int g = (color & 0x07e0) >> 6; // only keep 5 bit
+    const int b = (color & 0x001f);
+    return (r * 11 + g * 16 + b * 5) >> 6;
+}
+
+template <>
+inline quint8 qt_convertToGray4(qrgb444 color)
+{
+    return qt_convertToGray4(quint32(color));
+}
+
+template <>
+inline quint8 qt_convertToGray4(qargb4444 color)
+{
+    return qt_convertToGray4(quint32(color));
+}
+
+template <typename SRC>
+Q_STATIC_TEMPLATE_FUNCTION inline void qt_rectconvert_gray4(qgray4 *dest4, const SRC *src,
+                                        int x, int y, int width, int height,
+                                        int dstStride, int srcStride)
+{
+    const int pixelsPerByte = 2;
+    quint8 *dest8 = reinterpret_cast<quint8*>(dest4)
+                    + y * dstStride + x / pixelsPerByte;
+    const int doAlign = x & 1;
+    const int doTail = (width - doAlign) & 1;
+    const int width8 = (width - doAlign) / pixelsPerByte;
+    const int count8 = (width8 + 3) / 4;
+
+    srcStride = srcStride / sizeof(SRC) - width;
+    dstStride -= (width8 + doAlign);
+
+    for (int i = 0; i < height; ++i) {
+        if (doAlign) {
+            *dest8 = (*dest8 & 0xf0) | qt_convertToGray4<SRC>(*src++);
+            ++dest8;
+        }
+        if (count8) {
+            int n = count8;
+            switch (width8 & 0x03) // duff's device
+            {
+            case 0: do { *dest8++ = qt_convertToGray4<SRC>(src[0]) << 4
+                                    | qt_convertToGray4<SRC>(src[1]);
+                         src += 2;
+            case 3:      *dest8++ = qt_convertToGray4<SRC>(src[0]) << 4
+                                    | qt_convertToGray4<SRC>(src[1]);
+                         src += 2;
+            case 2:      *dest8++ = qt_convertToGray4<SRC>(src[0]) << 4
+                                    | qt_convertToGray4<SRC>(src[1]);
+                         src += 2;
+            case 1:      *dest8++ = qt_convertToGray4<SRC>(src[0]) << 4
+                                    | qt_convertToGray4<SRC>(src[1]);
+                         src += 2;
+            } while (--n > 0);
+            }
+        }
+
+        if (doTail)
+            *dest8 = qt_convertToGray4<SRC>(*src++) << 4 | (*dest8 & 0x0f);
+
+        dest8 += dstStride;
+        src += srcStride;
+    }
+}
+
+template <>
+void qt_rectconvert(qgray4 *dest, const quint32 *src,
+                    int x, int y, int width, int height,
+                    int dstStride, int srcStride)
+{
+    qt_rectconvert_gray4<quint32>(dest, src, x, y, width, height,
+                                  dstStride, srcStride);
+}
+
+template <>
+void qt_rectconvert(qgray4 *dest, const quint16 *src,
+                    int x, int y, int width, int height,
+                    int dstStride, int srcStride)
+{
+    qt_rectconvert_gray4<quint16>(dest, src, x, y, width, height,
+                                  dstStride, srcStride);
+}
+
+template <>
+void qt_rectconvert(qgray4 *dest, const qrgb444 *src,
+                    int x, int y, int width, int height,
+                    int dstStride, int srcStride)
+{
+    qt_rectconvert_gray4<qrgb444>(dest, src, x, y, width, height,
+                                  dstStride, srcStride);
+}
+
+template <>
+void qt_rectconvert(qgray4 *dest, const qargb4444 *src,
+                    int x, int y, int width, int height,
+                    int dstStride, int srcStride)
+{
+    qt_rectconvert_gray4<qargb4444>(dest, src, x, y, width, height,
+                                    dstStride, srcStride);
+}
+
+static void blit_4(QScreen *screen, const QImage &image,
+                   const QPoint &topLeft, const QRegion &region)
+{
+    switch (image.format()) {
+    case QImage::Format_ARGB32_Premultiplied:
+        blit_template<qgray4, quint32>(screen, image, topLeft, region);
+        return;
+    case QImage::Format_RGB16:
+        blit_template<qgray4, quint16>(screen, image, topLeft, region);
+        return;
+    case QImage::Format_RGB444:
+        blit_template<qgray4, qrgb444>(screen, image, topLeft, region);
+        return;
+    case QImage::Format_ARGB4444_Premultiplied:
+        blit_template<qgray4, qargb4444>(screen, image, topLeft, region);
+        return;
+    default:
+        qCritical("blit_4(): Image format %d not supported!", image.format());
+    }
+}
+#endif // QT_QWS_DEPTH_4
+
+#ifdef QT_QWS_DEPTH_1
+
+struct qmono { quint8 dummy; } Q_PACKED;
+
+template <typename SRC>
+Q_STATIC_TEMPLATE_FUNCTION inline quint8 qt_convertToMono(SRC color);
+
+template <>
+inline quint8 qt_convertToMono(quint32 color)
+{
+    return qGray(color) >> 7;
+}
+
+template <>
+inline quint8 qt_convertToMono(quint16 color)
+{
+    return (qGray(qt_colorConvert<quint32, quint16>(color, 0)) >> 7);
+}
+
+template <>
+inline quint8 qt_convertToMono(qargb4444 color)
+{
+    return (qGray(quint32(color)) >> 7);
+}
+
+template <>
+inline quint8 qt_convertToMono(qrgb444 color)
+{
+    return (qGray(quint32(color)) >> 7);
+}
+
+template <typename SRC>
+inline void qt_rectconvert_mono(qmono *dest, const SRC *src,
+                                       int x, int y, int width, int height,
+                                       int dstStride, int srcStride)
+{
+    const int pixelsPerByte = 8;
+    quint8 *dest8 = reinterpret_cast<quint8*>(dest)
+                    + y * dstStride + x / pixelsPerByte;
+    const int alignWidth = qMin(width, (8 - (x & 7)) & 7);
+    const int doAlign = (alignWidth > 0 ? 1 : 0);
+    const int alignStart = pixelsPerByte - 1 - (x & 7);
+    const int alignStop = alignStart - (alignWidth - 1);
+    const quint8 alignMask = ((1 << alignWidth) - 1) << alignStop;
+    const int tailWidth = (width - alignWidth) & 7;
+    const int doTail = (tailWidth > 0 ? 1 : 0);
+    const quint8 tailMask = (1 << (pixelsPerByte - tailWidth)) - 1;
+    const int width8 = (width - alignWidth) / pixelsPerByte;
+
+    srcStride = srcStride / sizeof(SRC) - (width8 * 8 + alignWidth);
+    dstStride -= (width8 + doAlign);
+
+    for (int j = 0;  j < height; ++j) {
+        if (doAlign) {
+            quint8 d = *dest8 & ~alignMask;
+            for (int i = alignStart; i >= alignStop; --i)
+                d |= qt_convertToMono<SRC>(*src++) << i;
+            *dest8++ = d;
+        }
+        for (int i = 0; i < width8; ++i) {
+            *dest8 = (qt_convertToMono<SRC>(src[0]) << 7)
+                     | (qt_convertToMono<SRC>(src[1]) << 6)
+                     | (qt_convertToMono<SRC>(src[2]) << 5)
+                     | (qt_convertToMono<SRC>(src[3]) << 4)
+                     | (qt_convertToMono<SRC>(src[4]) << 3)
+                     | (qt_convertToMono<SRC>(src[5]) << 2)
+                     | (qt_convertToMono<SRC>(src[6]) << 1)
+                     | (qt_convertToMono<SRC>(src[7]));
+            src += 8;
+            ++dest8;
+        }
+        if (doTail) {
+            quint8 d = *dest8 & tailMask;
+            switch (tailWidth) {
+            case 7: d |= qt_convertToMono<SRC>(src[6]) << 1;
+            case 6: d |= qt_convertToMono<SRC>(src[5]) << 2;
+            case 5: d |= qt_convertToMono<SRC>(src[4]) << 3;
+            case 4: d |= qt_convertToMono<SRC>(src[3]) << 4;
+            case 3: d |= qt_convertToMono<SRC>(src[2]) << 5;
+            case 2: d |= qt_convertToMono<SRC>(src[1]) << 6;
+            case 1: d |= qt_convertToMono<SRC>(src[0]) << 7;
+            }
+            *dest8 = d;
+        }
+
+        dest8 += dstStride;
+        src += srcStride;
+    }
+}
+
+template <>
+void qt_rectconvert(qmono *dest, const quint32 *src,
+                    int x, int y, int width, int height,
+                    int dstStride, int srcStride)
+{
+    qt_rectconvert_mono<quint32>(dest, src, x, y, width, height,
+                                 dstStride, srcStride);
+}
+
+template <>
+void qt_rectconvert(qmono *dest, const quint16 *src,
+                    int x, int y, int width, int height,
+                    int dstStride, int srcStride)
+{
+    qt_rectconvert_mono<quint16>(dest, src, x, y, width, height,
+                                 dstStride, srcStride);
+}
+
+template <>
+void qt_rectconvert(qmono *dest, const qrgb444 *src,
+                    int x, int y, int width, int height,
+                    int dstStride, int srcStride)
+{
+    qt_rectconvert_mono<qrgb444>(dest, src, x, y, width, height,
+                                 dstStride, srcStride);
+}
+
+template <>
+void qt_rectconvert(qmono *dest, const qargb4444 *src,
+                    int x, int y, int width, int height,
+                    int dstStride, int srcStride)
+{
+    qt_rectconvert_mono<qargb4444>(dest, src, x, y, width, height,
+                                   dstStride, srcStride);
+}
+
+static void blit_1(QScreen *screen, const QImage &image,
+                   const QPoint &topLeft, const QRegion &region)
+{
+    switch (image.format()) {
+    case QImage::Format_ARGB32_Premultiplied:
+        blit_template<qmono, quint32>(screen, image, topLeft, region);
+        return;
+    case QImage::Format_RGB16:
+        blit_template<qmono, quint16>(screen, image, topLeft, region);
+        return;
+    case QImage::Format_RGB444:
+        blit_template<qmono, qrgb444>(screen, image, topLeft, region);
+        return;
+    case QImage::Format_ARGB4444_Premultiplied:
+        blit_template<qmono, qargb4444>(screen, image, topLeft, region);
+        return;
+    default:
+        qCritical("blit_1(): Image format %d not supported!", image.format());
+    }
+}
+#endif // QT_QWS_DEPTH_1
+
+#ifdef QT_QWS_DEPTH_GENERIC
+
+static void blit_rgb(QScreen *screen, const QImage &image,
+                     const QPoint &topLeft, const QRegion &region)
+{
+    switch (image.format()) {
+    case QImage::Format_ARGB32_Premultiplied:
+        blit_template<qrgb, quint32>(screen, image, topLeft, region);
+        return;
+    case QImage::Format_RGB16:
+        blit_template<qrgb, quint16>(screen, image, topLeft, region);
+        return;
+    default:
+        qCritical("blit_rgb(): Image format %d not supported!", image.format());
+    }
+}
+
+void qt_set_generic_blit(QScreen *screen, int bpp,
+                         int len_red, int len_green, int len_blue, int len_alpha,
+                         int off_red, int off_green, int off_blue, int off_alpha)
+{
+    qrgb::bpp = bpp / 8;
+    qrgb::len_red = len_red;
+    qrgb::len_green = len_green;
+    qrgb::len_blue = len_blue;
+    qrgb::len_alpha = len_alpha;
+    qrgb::off_red = off_red;
+    qrgb::off_green = off_green;
+    qrgb::off_blue = off_blue;
+    qrgb::off_alpha = off_alpha;
+    screen->d_ptr->blit = blit_rgb;
+    if (bpp == 16)
+        screen->d_ptr->solidFill = solidFill_rgb_16bpp;
+    else if (bpp == 32)
+        screen->d_ptr->solidFill = solidFill_rgb_32bpp;
+}
+
+#endif // QT_QWS_DEPTH_GENERIC
+
+void qt_blit_setup(QScreen *screen, const QImage &image,
+                   const QPoint &topLeft, const QRegion &region)
+{
+    switch (screen->depth()) {
+#ifdef QT_QWS_DEPTH_32
+    case 32:
+        if (screen->pixelType() == QScreen::NormalPixel)
+            screen->d_ptr->blit = blit_32;
+        else
+            screen->d_ptr->blit = blit_template<qabgr8888, quint32>;
+        break;
+#endif
+#ifdef QT_QWS_DEPTH_24
+    case 24:
+        if (screen->pixelType() == QScreen::NormalPixel)
+            screen->d_ptr->blit = blit_qrgb888;
+        else
+            screen->d_ptr->blit = blit_24;
+        break;
+#endif
+#ifdef QT_QWS_DEPTH_18
+    case 18:
+        screen->d_ptr->blit = blit_18;
+        break;
+#endif
+#ifdef QT_QWS_DEPTH_16
+    case 16:
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+        if (screen->d_ptr->fb_is_littleEndian)
+            screen->d_ptr->blit = blit_16_bigToLittleEndian;
+        else
+#endif
+        if (screen->pixelType() == QScreen::NormalPixel)
+            screen->d_ptr->blit = blit_16;
+        else
+            screen->d_ptr->blit = blit_template<qbgr565, quint16>;
+        break;
+#endif
+#ifdef QT_QWS_DEPTH_15
+    case 15:
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+        if (screen->d_ptr->fb_is_littleEndian)
+            screen->d_ptr->blit = blit_15_bigToLittleEndian;
+        else
+#endif // Q_BIG_ENDIAN
+        if (screen->pixelType() == QScreen::NormalPixel)
+            screen->d_ptr->blit = blit_15;
+        else
+            screen->d_ptr->blit = blit_template<qbgr555, qrgb555>;
+        break;
+#endif
+#ifdef QT_QWS_DEPTH_12
+    case 12:
+        screen->d_ptr->blit = blit_12;
+        break;
+#endif
+#ifdef QT_QWS_DEPTH_8
+    case 8:
+        screen->d_ptr->blit = blit_8;
+        break;
+#endif
+#ifdef QT_QWS_DEPTH_4
+    case 4:
+        screen->d_ptr->blit = blit_4;
+        break;
+#endif
+#ifdef QT_QWS_DEPTH_1
+    case 1:
+        screen->d_ptr->blit = blit_1;
+        break;
+#endif
+    default:
+        qFatal("blit_setup(): Screen depth %d not supported!",
+               screen->depth());
+        screen->d_ptr->blit = 0;
+        break;
+    }
+    screen->d_ptr->blit(screen, image, topLeft, region);
+}
+
+QScreenPrivate::QScreenPrivate(QScreen *parent, QScreen::ClassId id)
+    : defaultGraphicsSystem(QWSGraphicsSystem(parent)),
+      pixelFormat(QImage::Format_Invalid),
+#ifdef QT_QWS_CLIENTBLIT
+      supportsBlitInClients(false),
+#endif
+      classId(id), q_ptr(parent)
+{
+    solidFill = qt_solidFill_setup;
+    blit = qt_blit_setup;
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+    fb_is_littleEndian = false;
+#endif
+    pixmapFactory = 0;
+    graphicsSystem = &defaultGraphicsSystem;
+}
+
+QScreenPrivate::~QScreenPrivate()
+{
+}
+
+QImage::Format QScreenPrivate::preferredImageFormat() const
+{
+    if (pixelFormat > QImage::Format_Indexed8)
+        return pixelFormat;
+
+    if (q_ptr->depth() <= 16)
+        return QImage::Format_RGB16;
+    else
+        return QImage::Format_ARGB32_Premultiplied;
+}
+
+/*!
+    \class QScreen
+    \ingroup qws
+
+    \brief The QScreen class is a base class for screen drivers in
+    Qt for Embedded Linux.
+
+    Note that this class is only available in \l{Qt for Embedded Linux}.
+
+    \l{Qt for Embedded Linux} provides ready-made drivers for several screen
+    protocols, see the \l{Qt for Embedded Linux Display Management}{display
+    management} documentation for details. Custom screen drivers can
+    be implemented by subclassing the QScreen class and creating a
+    screen driver plugin (derived from QScreenDriverPlugin). The
+    default implementation of the QScreenDriverFactory class
+    will automatically detect the plugin, and load the driver into the
+    server application at run-time using Qt's \l {How to Create Qt
+    Plugins}{plugin system}.
+
+    When rendering, the default behavior is for each
+    client to render its widgets as well as its decorations into
+    memory, while the server copies the memory content to the device's
+    framebuffer using the screen driver. See the \l{Qt for Embedded Linux
+    Architecture} overview for details (note that it is possible for
+    the clients to manipulate and control the underlying hardware
+    directly as well).
+
+    Starting with Qt 4.2, it is also possible to add an
+    accelerated graphics driver to take advantage of available
+    hardware resources. See the \l{Adding an Accelerated Graphics
+    Driver to Qt for Embedded Linux} documentation for details.
+
+    \tableofcontents
+
+    \section1 Framebuffer Management
+
+    When a \l{Qt for Embedded Linux} application starts running, it
+    calls the screen driver's connect() function to map the
+    framebuffer and the accelerated drivers that the graphics card
+    control registers. The connect() function should then read out the
+    parameters of the framebuffer and use them as required to set this
+    class's protected variables.
+
+    The initDevice() function can be reimplemented to initialize the
+    graphics card. Note, however, that connect() is called \e before
+    the initDevice() function, so, for some hardware configurations,
+    some of the initialization that would normally be done in the
+    initDevice() function might have to be done in the connect()
+    function.
+
+    Likewise, just before a \l{Qt for Embedded Linux} application
+    exits, it calls the screen driver's disconnect() function. The
+    server application will in addition call the shutdownDevice()
+    function before it calls disconnect(). Note that the default
+    implementation of the shutdownDevice() function only hides the
+    mouse cursor.
+
+    QScreen also provides the save() and restore() functions, making
+    it possible to save and restore the state of the graphics
+    card. Note that the default implementations do nothing. Hardware
+    screen drivers should reimplement these functions to save (and
+    restore) its registers, enabling switching between virtual
+    consoles.
+
+    In addition, you can use the base() function to retrieve a pointer
+    to the beginning of the framebuffer, and the region() function to
+    retrieve the framebuffer's region. Use the onCard() function to
+    determine whether the framebuffer is within the graphics card's
+    memory, and the totalSize() function to determine the size of the
+    available graphics card memory (including the screen). Finally,
+    you can use the offset() function to retrieve the offset between
+    the framebuffer's coordinates and the application's coordinate
+    system.
+
+    \section1 Palette Management
+
+    QScreen provides several functions to retrieve information about
+    the color palette: The clut() function returns a pointer to the
+    color lookup table (i.e. its color palette). Use the numCols()
+    function to determine the number of entries in this table, and the
+    alloc() function to retrieve the palette index of the color that
+    is the closest match to a given RGB value.
+
+    To determine if the screen driver supports a given color depth,
+    use the supportsDepth() function that returns true of the
+    specified depth is supported.
+
+    \section1 Drawing on Screen
+
+    When a screen update is required, the \l{Qt for Embedded Linux} server runs
+    through all the top-level windows that intersect with the region
+    that is about to be updated, and ensures that the associated
+    clients have updated their memory buffer. Then the server calls
+    the exposeRegion() function that composes the window surfaces and
+    copies the content of memory to screen by calling the blit() and
+    solidFill() functions.
+
+    The blit() function copies a given region in a given image to a
+    specified point using device coordinates, while the solidFill()
+    function fills the given region of the screen with the specified
+    color. Note that normally there is no need to call either of these
+    functions explicitly.
+
+    In addition, QScreen provides the blank() function that can be
+    reimplemented to prevent any contents from being displayed on the
+    screen, and the setDirty() function that can be reimplemented to
+    indicate that a given rectangle of the screen has been
+    altered. Note that the default implementations of these functions
+    do nothing.
+
+    Reimplement the mapFromDevice() and mapToDevice() functions to
+    map objects from the framebuffer coordinate system to the
+    coordinate space used by the application, and vice versa. Be aware
+    that the default implementations simply return the given objects
+    as they are.
+
+    \section1 Properties
+
+    \table
+    \header \o Property \o Functions
+    \row
+    \o Size
+    \o
+
+    The size of the screen can be retrieved using the screenSize()
+    function. The size is returned in bytes.
+
+    The framebuffer's logical width and height can be retrieved using
+    width() and height(), respectively. These functions return values
+    are given in pixels. Alternatively, the physicalWidth() and
+    physicalHeight() function returns the same metrics in
+    millimeters. QScreen also provides the deviceWidth() and
+    deviceHeight() functions returning the physical width and height
+    of the device in pixels. Note that the latter metrics can differ
+    from the ones used if the display is centered within the
+    framebuffer.
+
+    \row
+    \o Resolution
+    \o
+
+    Reimplement the setMode() function to be able to set the
+    framebuffer to a new resolution (width and height) and bit depth.
+
+    The current depth of the framebuffer can be always be retrieved
+    using the depth() function. Use the pixmapDepth() function to
+    obtain the preferred depth for pixmaps.
+
+    \row
+    \o Pixmap Alignment
+    \o
+
+    Use the pixmapOffsetAlignment() function to retrieve the value to
+    which the start address of pixmaps held in the graphics card's
+    memory, should be aligned.
+
+    Use the pixmapLinestepAlignment() to retrieve the value to which
+    the \e {individual scanlines} of pixmaps should be aligned.
+
+    \row
+    \o Image Display
+    \o
+
+    The isInterlaced() function tells whether the screen is displaying
+    images progressively, and the isTransformed() function whether it
+    is rotated. The transformOrientation() function can be
+    reimplemented to return the current rotation.
+
+    \row
+    \o Scanlines
+    \o
+
+    Use the linestep() function to retrieve the length of each
+    scanline of the framebuffer.
+
+    \row
+    \o Pixel Type
+    \o
+
+    The pixelType() function returns the screen's pixel storage format as
+    described by the PixelType enum.
+
+    \endtable
+
+    \section1 Subclassing and Initial Values
+
+    You need to set the following members when implementing a subclass of QScreen:
+
+    \table
+    \header \o Member \o Initial Value
+    \row \o \l{QScreen::}{data} \o A pointer to the framebuffer if possible;
+    0 otherwise.
+    \row \o \l{QScreen::}{lstep} \o The number of bytes between each scanline
+    in the framebuffer.
+    \row \o \l{QScreen::}{w} \o The logical screen width in pixels.
+    \row \o \l{QScreen::}{h} \o The logical screen height in pixels.
+    \row \o \l{QScreen::}{dw} \o The real screen width in pixels.
+    \row \o \l{QScreen::}{dh} \o The real screen height in pixels.
+    \row \o \l{QScreen::}{d} \o The number of bits per pixel.
+    \row \o \l{QScreen::}{physWidth} \o The screen width in millimeters.
+    \row \o \l{QScreen::}{physHeight} \o The screen height in millimeters.
+    \endtable
+
+    The logical screen values are the same as the real screen values unless the
+    screen is transformed in some way; e.g., rotated.
+
+    See also the \l{Accelerated Graphics Driver Example} for an example that
+    shows how to initialize these values.
+
+    \sa QScreenDriverPlugin, QScreenDriverFactory, {Qt for Embedded Linux Display
+    Management}
+*/
+
+/*!
+    \enum QScreen::PixelType
+
+    This enum describes the pixel storage format of the screen,
+    i.e. the order of the red (R), green (G) and blue (B) components
+    of a pixel.
+
+    \value NormalPixel Red-green-blue (RGB)
+    \value BGRPixel Blue-green-red (BGR)
+
+    \sa pixelType()
+*/
+
+/*!
+    \enum QScreen::ClassId
+
+    This enum defines the class identifiers for the known screen subclasses.
+
+    \value LinuxFBClass QLinuxFBScreen
+    \value TransformedClass QTransformedScreen
+    \value VNCClass QVNCScreen
+    \value MultiClass QMultiScreen
+    \value VFbClass QVFbScreen
+    \value DirectFBClass QDirectFBScreen
+    \value SvgalibClass QSvgalibScreen
+    \value ProxyClass QProxyScreen
+    \value GLClass QGLScreen
+    \value CustomClass Unknown QScreen subclass
+
+    \sa classId()
+*/
+
+/*!
+  \variable QScreen::screenclut
+  \brief the color table
+
+  Initialize this variable in a subclass using a paletted screen mode,
+  and initialize its partner, QScreen::screencols.
+
+  \sa screencols
+*/
+
+/*!
+  \variable QScreen::screencols
+  \brief the number of entries in the color table
+
+  Initialize this variable in a subclass using a paletted screen mode,
+  and initialize its partner, QScreen::screenclut.
+
+  \sa screenclut
+*/
+
+/*!
+  \variable QScreen::data
+  \brief points to the first visible pixel in the frame buffer.
+
+  You must initialize this variable if you are using the default
+  implementation of non-buffered painting Qt::WA_PaintOnScreen,
+  QPixmap::grabWindow() or QDirectPainter::frameBuffer(). If you
+  initialize this variable, you must also initialize QScreen::size and
+  QScreen::mapsize.
+
+  \sa QScreen::size, QScreen::mapsize
+*/
+
+/*!
+  \variable QScreen::w
+  \brief the logical width of the screen.
+
+  This variable \e{must} be initialized by a subclass.
+*/
+
+/*!
+  \variable QScreen::lstep
+  \brief the number of bytes representing a line in the frame buffer.
+
+  i.e., \e{line step}. \c {data[lstep * 2]} is the address of the
+  first visible pixel in the third line of the frame buffer.
+
+  \sa data
+*/
+
+/*!
+  \variable QScreen::h
+  \brief the logical height of the screen.
+
+  This variable \e{must} be initialized by a subclass.
+*/
+
+/*!
+  \variable QScreen::d
+  \brief the pixel depth
+
+  This is the number of significant bits used to set a pixel
+  color. This variable \e{must} be initialized by a subclass.
+*/
+
+/*!
+  \variable QScreen::pixeltype
+  \brief set to BGRPixel
+
+  Set this variable to BGRPixel in a subclass, if the screen pixel
+  format is a BGR type and you have used setPixelFormat() to set the
+  pixel format to the corresponding RGB format. e.g., you have set the
+  pixel format to QImage::Format_RGB555, but your screen really uses
+  BGR, not RGB.
+*/
+
+/*!
+  \variable QScreen::grayscale
+  \brief the gray scale screen mode flag
+
+  Set this variable to true in a subclass, if you are using a
+  grayscale screen mode. e.g., in an 8-bit mode where you don't want
+  to use the palette, but you want to use the grayscales.
+*/
+
+/*!
+  \variable QScreen::dw
+  \brief the device width
+
+  This is the number of pixels in a row of the physical screen.  It
+  \e{must} be initialized by a subclass. Normally, it should be set to
+  the logical width QScreen::w, but it might be different, e.g., if
+  you are doing rotations in software.
+
+  \sa QScreen::w
+*/
+
+/*!
+  \variable QScreen::dh
+  \brief the device height
+
+  This is the number of pixels in a column of the physical screen.  It
+  \e{must} be initialized by a subclass. Normally, it should be set to
+  the logical height QScreen::h, but it might be different, e.g., if
+  you are doing rotations in software.
+
+  \sa QScreen::h
+*/
+
+/*!
+  \variable QScreen::size
+  \brief the number of bytes in the visible region of the frame buffer
+
+  This is the number of bytes in the visible part of the block pointed
+  to by the QScreen::data pointer. You must initialize this variable
+  if you initialize the QScreen::data pointer.
+
+  \sa QScreen::data, QScreen::mapsize
+*/
+
+/*!
+  \variable QScreen::mapsize
+  \brief the total number of bytes in the frame buffer
+
+  This is the total number of bytes in the block pointed to by the
+  QScreen::data pointer. You must initialize this variable if you
+  initialize the QScreen::data pointer.
+
+  \sa QScreen::data, QScreen::size
+*/
+
+/*!
+  \variable QScreen::physWidth
+  \brief the physical width of the screen in millimeters.
+
+  Currently, this variable is used when calculating the screen DPI,
+  which in turn is used when deciding the actual font size Qt is
+  using.
+*/
+
+/*!
+  \variable QScreen::physHeight
+  \brief the physical height of the screen in millimeters.
+
+  Currently, this variable is used when calculating the screen DPI,
+  which in turn is used when deciding the actual font size Qt is
+  using.
+*/
+
+/*!
+    \fn static QScreen* QScreen::instance()
+
+    Returns a pointer to the application's QScreen instance.
+
+    If this screen consists of several subscreens, operations to the
+    returned instance will affect all its subscreens. Use the
+    subscreens() function to retrieve access to a particular
+    subscreen.
+
+    \sa subScreens(), subScreenIndexAt()
+*/
+
+/*!
+    \fn QList<QScreen*> QScreen::subScreens() const
+    \since 4.2
+
+    Returns a list of this screen's subscreens. Use the
+    subScreenIndexAt() function to retrieve the index of a screen at a
+    given position.
+
+    Note that if \e this screen consists of several subscreens,
+    operations to \e this instance will affect all subscreens by
+    default.
+
+    \sa instance(), subScreenIndexAt()
+*/
+
+/*!
+    \fn int QScreen::physicalWidth() const
+    \since 4.2
+
+    Returns the physical width of the screen in millimeters.
+
+    \sa width(), deviceWidth(), physicalHeight()
+*/
+
+/*!
+    \fn int QScreen::physicalHeight() const
+    \since 4.2
+
+    Returns the physical height of the screen in millimeters.
+
+    \sa height(), deviceHeight(), physicalWidth()
+*/
+
+/*!
+    \fn virtual bool QScreen::initDevice() = 0
+
+    This function is called by the \l{Qt for Embedded Linux} server to
+    initialize the framebuffer. Note that a server application will call the
+    connect() function prior to this function.
+
+    Implement this function to make accelerated drivers set up the
+    graphics card. Return true to indicate success and false to indicate
+    failure.
+
+    \sa shutdownDevice(), connect()
+*/
+
+/*!
+    \fn virtual bool QScreen::connect(const QString &displaySpec) = 0
+
+    This function is called by every \l{Qt for Embedded Linux}
+    application on startup, and must be implemented to map in the
+    framebuffer and the accelerated drivers that the graphics card
+    control registers.  Note that coonnect must be called \e before
+    the initDevice() function.
+
+    Ensure that true is returned if a connection to the screen device
+    is made. Otherwise, return false. Upon making the connection, the
+    function should read out the parameters of the framebuffer and use
+    them as required to set this class's protected variables.
+
+    The \a displaySpec argument is passed by the QWS_DISPLAY
+    environment variable or the -display command line parameter, and
+    has the following syntax:
+
+    \snippet doc/src/snippets/code/src_gui_embedded_qscreen_qws.cpp 0
+
+    For example, to use the mach64 driver on fb1 as display 2:
+
+    \snippet doc/src/snippets/code/src_gui_embedded_qscreen_qws.cpp 1
+
+    See \l{Qt for Embedded Linux Display Management} for more details.
+
+    \sa disconnect(), initDevice(), {Running Qt for Embedded Linux Applications}
+*/
+
+/*!
+    \fn QScreen::disconnect()
+
+    This function is called by every \l{Qt for Embedded Linux} application
+    before exiting, and must be implemented to unmap the
+    framebuffer. Note that a server application will call the
+    shutdownDevice() function prior to this function.
+
+    \sa connect(), shutdownDevice(), {Running Qt for Embedded Linux
+    Applications}
+*/
+
+/*!
+    \fn QScreen::setMode(int width, int height, int depth)
+
+    Implement this function to reset the framebuffer's resolution (\a
+    width and \a height) and bit \a depth.
+
+    After the resolution has been set, existing paint engines will be
+    invalid and the framebuffer should be completely redrawn. In a
+    multiple-process situation, all other applications must be
+    notified to reset their mode and update themselves accordingly.
+*/
+
+/*!
+    \fn QScreen::blank(bool on)
+
+    Prevents the screen driver form displaying any content on the
+    screen.
+
+    Note that the default implementation does nothing.
+
+    Reimplement this function to prevent the screen driver from
+    displaying any contents on the screen if \a on is true; otherwise
+    the contents is expected to be shown.
+
+    \sa blit()
+*/
+
+/*!
+    \fn int QScreen::pixmapOffsetAlignment()
+
+    Returns the value (in bits) to which the start address of pixmaps
+    held in the graphics card's memory, should be aligned.
+
+    Note that the default implementation returns 64; reimplement this
+    function to override the return value, e.g., when implementing an
+    accelerated driver (see the \l {Adding an Accelerated Graphics
+    Driver to Qt for Embedded Linux}{Adding an Accelerated Graphics Driver}
+    documentation for details).
+
+    \sa pixmapLinestepAlignment()
+*/
+
+/*!
+    \fn int QScreen::pixmapLinestepAlignment()
+
+    Returns the value (in bits) to which individual scanlines of
+    pixmaps held in the graphics card's memory, should be
+    aligned.
+
+    Note that the default implementation returns 64; reimplement this
+    function to override the return value, e.g., when implementing an
+    accelerated driver (see the \l {Adding an Accelerated Graphics
+    Driver to Qt for Embedded Linux}{Adding an Accelerated Graphics Driver}
+    documentation for details).
+
+    \sa pixmapOffsetAlignment()
+*/
+
+/*!
+    \fn QScreen::width() const
+
+    Returns the logical width of the framebuffer in pixels.
+
+    \sa deviceWidth(), physicalWidth(), height()
+*/
+
+/*!
+    \fn int QScreen::height() const
+
+    Returns the logical height of the framebuffer in pixels.
+
+    \sa deviceHeight(), physicalHeight(), width()
+*/
+
+/*!
+    \fn QScreen::depth() const
+
+    Returns the depth of the framebuffer, in bits per pixel.
+
+    Note that the returned depth is the number of bits each pixel
+    fills rather than the number of significant bits, so 24bpp and
+    32bpp express the same range of colors (8 bits of red, green and
+    blue).
+
+    \sa clut(), pixmapDepth()
+*/
+
+/*!
+    \fn int QScreen::pixmapDepth() const
+
+    Returns the preferred depth for pixmaps, in bits per pixel.
+
+    \sa depth()
+*/
+
+/*!
+    \fn QScreen::linestep() const
+
+    Returns the length of each scanline of the framebuffer in bytes.
+
+    \sa isInterlaced()
+*/
+
+/*!
+    \fn QScreen::deviceWidth() const
+
+    Returns the physical width of the framebuffer device in pixels.
+
+    Note that the returned width can differ from the width which
+    \l{Qt for Embedded Linux} will actually use, that is if the display is
+    centered within the framebuffer.
+
+    \sa width(), physicalWidth(), deviceHeight()
+*/
+
+/*!
+    \fn QScreen::deviceHeight() const
+
+    Returns the full height of the framebuffer device in pixels.
+
+    Note that the returned height can differ from the height which
+    \l{Qt for Embedded Linux} will actually use, that is if the display is
+    centered within the framebuffer.
+
+    \sa height(), physicalHeight(), deviceWidth()
+*/
+
+/*!
+    \fn uchar *QScreen::base() const
+
+    Returns a pointer to the beginning of the framebuffer.
+
+    \sa onCard(), region(), totalSize()
+*/
+
+/*!
+    \fn uchar *QScreen::cache(int)
+
+    \internal
+
+    This function is used to store pixmaps in graphics memory for the
+    use of the accelerated drivers. See QLinuxFbScreen (where the
+    caching is implemented) for more information.
+*/
+
+/*!
+    \fn QScreen::uncache(uchar *)
+
+    \internal
+
+    This function is called on pixmap destruction to remove them from
+    graphics card memory.
+*/
+
+/*!
+    \fn QScreen::screenSize() const
+
+    Returns the size of the screen in bytes.
+
+    The screen size is always located at the beginning of framebuffer
+    memory, i.e. it can also be retrieved using the base() function.
+
+    \sa base(), region()
+*/
+
+/*!
+    \fn QScreen::totalSize() const
+
+    Returns the size of the available graphics card memory (including
+    the screen) in bytes.
+
+    \sa onCard()
+*/
+
+// Unaccelerated screen/driver setup. Can be overridden by accelerated
+// drivers
+
+/*!
+    \fn QScreen::QScreen(int displayId)
+
+    Constructs a new screen driver.
+
+    The \a displayId identifies the \l{Qt for Embedded Linux} server to connect
+    to.
+*/
+
+/*!
+    \fn QScreen::clut()
+
+    Returns a pointer to the screen's color lookup table (i.e. its
+    color palette).
+
+    Note that this function only apply in paletted modes like 8-bit,
+    i.e. in modes where only the palette indexes (and not the actual
+    color values) are stored in memory.
+
+    \sa alloc(), depth(), numCols()
+*/
+
+/*!
+    \fn int QScreen::numCols()
+
+    Returns the number of entries in the screen's color lookup table
+    (i.e. its color palette). A pointer to the color table can be
+    retrieved using the clut() function.
+
+    \sa clut(), alloc()
+*/
+
+/*!
+    \since 4.4
+
+    Constructs a new screen driver.
+
+    The \a display_id identifies the \l{Qt for Embedded Linux}
+    server to connect to. The \a classId specifies the class
+    identifier.
+*/
+QScreen::QScreen(int display_id, ClassId classId)
+    : screencols(0), data(0), entries(0), entryp(0), lowest(0),
+      w(0), lstep(0), h(0), d(1), pixeltype(NormalPixel), grayscale(false),
+      dw(0), dh(0), size(0), mapsize(0), displayId(display_id),
+      physWidth(0), physHeight(0), d_ptr(new QScreenPrivate(this, classId))
+{
+    clearCacheFunc = 0;
+}
+
+QScreen::QScreen(int display_id)
+    : screencols(0), data(0), entries(0), entryp(0), lowest(0),
+      w(0), lstep(0), h(0), d(1), pixeltype(NormalPixel), grayscale(false),
+      dw(0), dh(0), size(0), mapsize(0), displayId(display_id),
+      physWidth(0), physHeight(0), d_ptr(new QScreenPrivate(this))
+{
+    clearCacheFunc = 0;
+}
+
+/*!
+    Destroys this screen driver.
+*/
+
+QScreen::~QScreen()
+{
+    delete d_ptr;
+}
+
+/*!
+    This function is called by the \l{Qt for Embedded Linux} server before it
+    calls the disconnect() function when exiting.
+
+    Note that the default implementation only hides the mouse cursor;
+    reimplement this function to do the necessary graphics card
+    specific cleanup.
+
+    \sa initDevice(), disconnect()
+*/
+
+void QScreen::shutdownDevice()
+{
+#ifndef QT_NO_QWS_CURSOR
+    if (qt_screencursor)
+        qt_screencursor->hide();
+#endif
+}
+
+extern bool qws_accel; //in qapplication_qws.cpp
+
+/*!
+    \fn PixelType QScreen::pixelType() const
+
+    Returns the pixel storage format of the screen.
+*/
+
+/*!
+  Returns the pixel format of the screen, or \c QImage::Format_Invalid
+  if the pixel format is not a supported image format.
+
+*/
+QImage::Format QScreen::pixelFormat() const
+{
+    return d_ptr->pixelFormat;
+}
+
+/*!
+  Sets the screen's pixel format to \a format.
+ */
+void QScreen::setPixelFormat(QImage::Format format)
+{
+    d_ptr->pixelFormat = format;
+}
+
+
+/*!
+    \fn int QScreen::alloc(unsigned int red, unsigned int green, unsigned int blue)
+
+    Returns the index in the screen's palette which is the closest
+    match to the given RGB value (\a red, \a green, \a blue).
+
+    Note that this function only apply in paletted modes like 8-bit,
+    i.e. in modes where only the palette indexes (and not the actual
+    color values) are stored in memory.
+
+    \sa clut(), numCols()
+*/
+
+int QScreen::alloc(unsigned int r,unsigned int g,unsigned int b)
+{
+    int ret = 0;
+    if (d == 8) {
+        if (grayscale)
+            return qGray(r, g, b);
+
+        // First we look to see if we match a default color
+        const int pos = (r + 25) / 51 * 36 + (g + 25) / 51 * 6 + (b + 25) / 51;
+        if (pos < screencols && screenclut[pos] == qRgb(r, g, b)) {
+            return pos;
+        }
+
+        // search for nearest color
+        unsigned int mindiff = 0xffffffff;
+        unsigned int diff;
+        int dr,dg,db;
+
+        for (int loopc = 0; loopc < screencols; ++loopc) {
+            dr = qRed(screenclut[loopc]) - r;
+            dg = qGreen(screenclut[loopc]) - g;
+            db = qBlue(screenclut[loopc]) - b;
+            diff = dr*dr + dg*dg + db*db;
+
+            if (diff < mindiff) {
+                ret = loopc;
+                if (!diff)
+                    break;
+                mindiff = diff;
+            }
+        }
+    } else if (d == 4) {
+        ret = qGray(r, g, b) >> 4;
+    } else if (d == 1) {
+        ret = qGray(r, g, b) >= 128;
+    } else {
+        qFatal("cannot alloc %dbpp color", d);
+    }
+
+    return ret;
+}
+
+/*!
+    Saves the current state of the graphics card.
+
+    For example, hardware screen drivers should reimplement the save()
+    and restore() functions to save and restore its registers,
+    enabling swintching between virtual consoles.
+
+    Note that the default implementation does nothing.
+
+    \sa restore()
+*/
+
+void QScreen::save()
+{
+}
+
+/*!
+    Restores the previously saved state of the graphics card.
+
+    For example, hardware screen drivers should reimplement the save()
+    and restore() functions to save and restore its registers,
+    enabling swintching between virtual consoles.
+
+    Note that the default implementation does nothing.
+
+    \sa save()
+*/
+
+void QScreen::restore()
+{
+}
+
+void QScreen::blank(bool)
+{
+}
+
+/*!
+    \internal
+*/
+
+void QScreen::set(unsigned int, unsigned int, unsigned int, unsigned int)
+{
+}
+
+/*!
+    \fn bool QScreen::supportsDepth(int depth) const
+
+    Returns true if the screen supports the specified color \a depth;
+    otherwise returns false.
+
+    \sa clut()
+*/
+
+bool QScreen::supportsDepth(int d) const
+{
+    if (false) {
+        //Just to simplify the ifdeffery
+#ifdef QT_QWS_DEPTH_1
+    } else if(d==1) {
+        return true;
+#endif
+#ifdef QT_QWS_DEPTH_4
+    } else if(d==4) {
+        return true;
+#endif
+#ifdef QT_QWS_DEPTH_8
+    } else if(d==8) {
+        return true;
+#endif
+#ifdef QT_QWS_DEPTH_16
+    } else if(d==16) {
+        return true;
+#endif
+#ifdef QT_QWS_DEPTH_15
+    } else if (d == 15) {
+        return true;
+#endif
+#ifdef QT_QWS_DEPTH_18
+    } else if(d==18 || d==19) {
+        return true;
+#endif
+#ifdef QT_QWS_DEPTH_24
+    } else if(d==24) {
+        return true;
+#endif
+#ifdef QT_QWS_DEPTH_32
+    } else if(d==32) {
+        return true;
+#endif
+    }
+    return false;
+}
+
+/*!
+    \fn bool QScreen::onCard(const unsigned char *buffer) const
+
+    Returns true if the specified \a buffer is within the graphics
+    card's memory; otherwise returns false (i.e. if it's in main RAM).
+
+    \sa base(), totalSize()
+*/
+
+bool QScreen::onCard(const unsigned char * p) const
+{
+    long t=(unsigned long)p;
+    long bmin=(unsigned long)data;
+    if (t < bmin)
+        return false;
+    if(t >= bmin+mapsize)
+        return false;
+    return true;
+}
+
+/*!
+    \fn bool QScreen::onCard(const unsigned char * buffer, ulong& offset) const
+    \overload
+
+    If the specified \a buffer is within the graphics card's memory,
+    this function stores the offset from the start of graphics card
+    memory (in bytes), in the location specified by the \a offset
+    parameter.
+*/
+
+bool QScreen::onCard(const unsigned char * p, ulong& offset) const
+{
+    long t=(unsigned long)p;
+    long bmin=(unsigned long)data;
+    if (t < bmin)
+        return false;
+    long o = t - bmin;
+    if (o >= mapsize)
+        return false;
+    offset = o;
+    return true;
+}
+
+/*
+#if !defined(QT_NO_QWS_REPEATER)
+    { "Repeater", qt_get_screen_repeater, 0 },
+#endif
+#if defined(QT_QWS_EE)
+    { "EE", qt_get_screen_ee, 0 },
+#endif
+
+*/
+
+/*
+Given a display_id (number of the \l{Qt for Embedded Linux} server to connect to)
+and a spec (e.g. Mach64:/dev/fb0) return a QScreen-descendant.
+The QScreenDriverFactory is queried for a suitable driver and, if found,
+asked to create a driver.
+People writing new graphics drivers should either hook their own
+QScreen-descendant into QScreenDriverFactory or use the QScreenDriverPlugin
+to make a dynamically loadable driver.
+*/
+
+Q_GUI_EXPORT QScreen* qt_get_screen(int display_id, const char *spec)
+{
+    QString displaySpec = QString::fromAscii(spec);
+    QString driver = displaySpec;
+    int colon = displaySpec.indexOf(QLatin1Char(':'));
+    if (colon >= 0)
+        driver.truncate(colon);
+    driver = driver.trimmed();
+
+    bool foundDriver = false;
+    QString driverName = driver;
+
+    QStringList driverList;
+    if (!driver.isEmpty())
+        driverList << driver;
+    else
+        driverList = QScreenDriverFactory::keys();
+
+    for (int i = 0; i < driverList.size(); ++i) {
+        const QString driverName = driverList.at(i);
+        qt_screen = QScreenDriverFactory::create(driverName, display_id);
+        if (qt_screen) {
+            foundDriver = true;
+            if (qt_screen->connect(displaySpec)) {
+                return qt_screen;
+            } else {
+                delete qt_screen;
+                qt_screen = 0;
+            }
+        }
+    }
+
+    if (driver.isNull())
+        qFatal("No suitable driver found");
+    else if (foundDriver)
+        qFatal("%s: driver cannot connect", driver.toLatin1().constData());
+    else
+        qFatal("%s: driver not found", driver.toLatin1().constData());
+
+    return 0;
+}
+
+#ifndef QT_NO_QWS_CURSOR
+static void blendCursor(QImage *dest, const QImage &cursor, const QPoint &offset)
+{
+    QRasterBuffer rb;
+    rb.prepare(dest);
+
+    QSpanData spanData;
+    spanData.init(&rb, 0);
+    spanData.type = QSpanData::Texture;
+    spanData.initTexture(&cursor, 256);
+    spanData.dx = -offset.x();
+    spanData.dy = -offset.y();
+    if (!spanData.blend)
+        return;
+
+    const QRect rect = QRect(offset, cursor.size())
+                       & QRect(QPoint(0, 0), dest->size());
+    const int w = rect.width();
+    const int h = rect.height();
+
+    QVarLengthArray<QT_FT_Span, 32> spans(h);
+    for (int i = 0; i < h; ++i) {
+        spans[i].x = rect.x();
+        spans[i].len = w;
+        spans[i].y = rect.y() + i;
+        spans[i].coverage = 255;
+    }
+    spanData.blend(h, spans.constData(), &spanData);
+}
+#endif // QT_NO_QWS_CURSOR
+
+/*!
+    \fn void QScreen::exposeRegion(QRegion region, int windowIndex)
+
+    This function is called by the \l{Qt for Embedded Linux} server whenever a
+    screen update is required. \a region is the area on the screen
+    that must be updated, and \a windowIndex is the index into
+    QWSServer::clientWindows() of the window that required the
+    update. QWSWindow::state() gives more information about the cause.
+
+    The default implementation composes the
+    affected windows and paints the given \a region on screen by
+    calling the blit() and solidFill() functions
+
+    This function can be reimplemented to perform composition in
+    hardware, or to perform transition effects.
+    For simpler hardware acceleration, or to interface with
+    this is typically done by reimplementing the blit() and
+    solidFill() functions instead.
+
+    Note that there is no need to call this function explicitly.
+
+    \sa blit(), solidFill(), blank()
+*/
+void QScreen::exposeRegion(QRegion r, int windowIndex)
+{
+    r &= region();
+    if (r.isEmpty())
+        return;
+
+    int changing = windowIndex;
+    // when we have just lowered a window, we have to expose all the windows below where the
+    // window used to be.
+    if (changing && qwsServer->clientWindows().at(changing)->state() == QWSWindow::Lowering)
+        changing = 0;
+#ifdef QTOPIA_PERFTEST
+    static enum { PerfTestUnknown, PerfTestOn, PerfTestOff } perfTestState = PerfTestUnknown;
+    if(PerfTestUnknown == perfTestState) {
+        if(::getenv("QTOPIA_PERFTEST"))
+            perfTestState = PerfTestOn;
+        else
+            perfTestState = PerfTestOff;
+    }
+    if(PerfTestOn == perfTestState) {
+        QWSWindow *changed = qwsServer->clientWindows().at(changing);
+        if(!changed->client()->identity().isEmpty())
+            qDebug() << "Performance  :  expose_region  :"
+                     << changed->client()->identity()
+                     << r.boundingRect() << ": "
+                     << qPrintable( QTime::currentTime().toString( "h:mm:ss.zzz" ) );
+    }
+#endif
+
+    const QRect bounds = r.boundingRect();
+    QRegion blendRegion;
+    QImage *blendBuffer = 0;
+
+#ifndef QT_NO_QWS_CURSOR
+    if (qt_screencursor && !qt_screencursor->isAccelerated()) {
+        blendRegion = r & qt_screencursor->boundingRect();
+    }
+#endif
+    compose(0, r, blendRegion, &blendBuffer, changing);
+
+    if (blendBuffer && !blendBuffer->isNull()) {
+        const QPoint offset = blendRegion.boundingRect().topLeft();
+#ifndef QT_NO_QWS_CURSOR
+        if (qt_screencursor && !qt_screencursor->isAccelerated()) {
+            const QRect cursorRect = qt_screencursor->boundingRect();
+            if (blendRegion.intersects(cursorRect)) {
+                blendCursor(blendBuffer, qt_screencursor->image(),
+                            cursorRect.topLeft() - offset);
+            }
+        }
+#endif // QT_NO_QWS_CURSOR
+        blit(*blendBuffer, offset, blendRegion);
+        delete blendBuffer;
+    }
+
+    if (r.numRects() == 1) {
+        setDirty(r.boundingRect());
+    } else {
+        const QVector<QRect> rects = r.rects();
+        for (int i = 0; i < rects.size(); ++i)
+            setDirty(rects.at(i));
+    }
+}
+
+/*!
+    \fn void QScreen::blit(const QImage &image, const QPoint &topLeft, const QRegion &region)
+
+    Copies the given \a region in the given \a image to the point
+    specified by \a topLeft using device coordinates.
+
+    This function is called from the exposeRegion() function; it is
+    not intended to be called explicitly.
+
+    Reimplement this function to make use of \l{Adding an Accelerated
+    Graphics Driver to Qt for Embedded Linux}{accelerated hardware}. Note that
+    this function must be reimplemented if the framebuffer format is
+    not supported by \l{Qt for Embedded Linux} (See the
+    \l{Qt for Embedded Linux Display Management}{Display Management}
+    documentation for more details).
+
+    \sa exposeRegion(), solidFill(), blank()
+*/
+void QScreen::blit(const QImage &img, const QPoint &topLeft, const QRegion &reg)
+{
+    const QRect bound = (region() & QRect(topLeft, img.size())).boundingRect();
+    QWSDisplay::grab();
+    d_ptr->blit(this, img, topLeft - offset(),
+            (reg & bound).translated(-topLeft));
+    QWSDisplay::ungrab();
+}
+
+#ifdef QT_QWS_CLIENTBLIT
+/*!
+  Returns true if this screen driver supports calling QScreen::blit() and
+  QScreen::setDirty() directly from non-server applications, otherwise returns
+  false.
+
+  If available, this is used to optimize the performance of non-occluded, opaque
+  client windows by removing the server round trip when they are updated.
+
+  \sa setSupportsBlitInClients()
+ */
+bool QScreen::supportsBlitInClients() const
+{
+    return d_ptr->supportsBlitInClients;
+}
+
+/*!
+  If \a supported, the screen driver is marked as supporting blitting directly
+  from non-server applications.
+
+  \sa supportsBlitInClients()
+ */
+void QScreen::setSupportsBlitInClients(bool supported)
+{
+    d_ptr->supportsBlitInClients = supported;
+}
+#endif
+
+/*!
+    \internal
+*/
+
+void QScreen::blit(QWSWindow *win, const QRegion &clip)
+{
+    QWSWindowSurface *surface = win->windowSurface();
+    if (!surface)
+        return;
+
+    const QImage &img = surface->image();
+    if (img.isNull())
+        return;
+
+    const QRegion rgn = clip & win->paintedRegion();
+    if (rgn.isEmpty())
+        return;
+
+    surface->lock();
+    blit(img, win->requestedRegion().boundingRect().topLeft(), rgn);
+    surface->unlock();
+}
+
+struct fill_data {
+    quint32 color;
+    uchar *data;
+    int lineStep;
+    int x;
+    int y;
+    int w;
+    int h;
+};
+
+/*!
+    Fills the given \a region of the screen with the specified \a
+    color.
+
+    This function is called from the exposeRegion() function; it is
+    not intended to be called explicitly.
+
+    Reimplement this function to make use of \l{Adding an Accelerated
+    Graphics Driver to Qt for Embedded Linux}{accelerated hardware}. Note that
+    this function must be reimplemented if the framebuffer format is
+    not supported by \l{Qt for Embedded Linux} (See the
+    \l{Qt for Embedded Linux Display Management}{Display Management}
+    documentation for more details).
+
+    \sa exposeRegion(), blit(), blank()
+*/
+// the base class implementation works in device coordinates, so that transformed drivers can use it
+void QScreen::solidFill(const QColor &color, const QRegion &region)
+{
+    QWSDisplay::grab();
+    d_ptr->solidFill(this, color,
+                     region.translated(-offset()) & QRect(0, 0, dw, dh));
+    QWSDisplay::ungrab();
+}
+
+/*!
+    \since 4.2
+
+    Creates and returns a new window surface matching the given \a
+    key.
+
+    The server application will call this function whenever it needs
+    to create a server side representation of a window, e.g. when
+    copying the content of memory to the screen using the screen
+    driver.
+
+    Note that this function must be reimplemented when adding an
+    accelerated graphics driver. See the
+    \l{Adding an Accelerated Graphics Driver to Qt for Embedded Linux}
+    {Adding an Accelerated Graphics Driver} documentation for details.
+
+    \sa {Qt for Embedded Linux Architecture}
+*/
+QWSWindowSurface* QScreen::createSurface(const QString &key) const
+{
+#ifndef QT_NO_PAINTONSCREEN
+    if (key == QLatin1String("OnScreen"))
+        return new QWSOnScreenSurface;
+    else
+#endif
+    if (key == QLatin1String("mem"))
+        return new QWSLocalMemSurface;
+#ifndef QT_NO_QWS_MULTIPROCESS
+    else if (key == QLatin1String("shm"))
+        return new QWSSharedMemSurface;
+#endif
+#ifndef QT_NO_PAINT_DEBUG
+    else if (key == QLatin1String("Yellow"))
+        return new QWSYellowSurface;
+#endif
+#ifndef QT_NO_DIRECTPAINTER
+    else if (key == QLatin1String("DirectPainter"))
+        return new QWSDirectPainterSurface;
+#endif
+
+    return 0;
+}
+
+#ifndef QT_NO_PAINTONSCREEN
+bool QScreen::isWidgetPaintOnScreen(const QWidget *w)
+{
+    static int doOnScreen = -1;
+    if (doOnScreen == -1) {
+        const QByteArray env = qgetenv("QT_ONSCREEN_PAINT");
+        if (env == "force")
+            doOnScreen = 2;
+        else
+            doOnScreen = (env.toInt() > 0 ? 1 : 0);
+    }
+
+    if (doOnScreen == 2) // force
+        return true;
+
+    if (doOnScreen == 0 && !w->testAttribute(Qt::WA_PaintOnScreen))
+        return false;
+
+    return w->d_func()->isOpaque;
+}
+#endif
+
+/*!
+    \overload
+
+    Creates and returns a new window surface for the given \a widget.
+*/
+QWSWindowSurface* QScreen::createSurface(QWidget *widget) const
+{
+#ifndef QT_NO_PAINTONSCREEN
+    if (isWidgetPaintOnScreen(widget) && base())
+        return new QWSOnScreenSurface(widget);
+    else
+#endif
+    if (QApplication::type() == QApplication::GuiServer)
+        return new QWSLocalMemSurface(widget);
+#ifndef QT_NO_QWS_MULTIPROCESS
+    else
+        return new QWSSharedMemSurface(widget);
+#endif
+
+    return 0;
+}
+
+void QScreen::compose(int level, const QRegion &exposed, QRegion &blend,
+                      QImage **blendbuffer, int changing_level)
+{
+    QRect exposed_bounds = exposed.boundingRect();
+    QWSWindow *win = 0;
+    do {
+        win = qwsServer->clientWindows().value(level); // null is background
+        ++level;
+    } while (win && !win->paintedRegion().boundingRect().intersects(exposed_bounds));
+
+    QWSWindowSurface *surface = (win ? win->windowSurface() : 0);
+    bool above_changing = level <= changing_level; // 0 is topmost
+
+    QRegion exposedBelow = exposed;
+    bool opaque = true;
+
+    if (win) {
+        opaque = win->isOpaque() || !surface->isBuffered();
+        if (opaque) {
+            exposedBelow -= win->paintedRegion();
+            if (above_changing || !surface->isBuffered())
+                blend -= exposed & win->paintedRegion();
+        } else {
+            blend += exposed & win->paintedRegion();
+        }
+    }
+    if (win && !exposedBelow.isEmpty()) {
+        compose(level, exposedBelow, blend, blendbuffer, changing_level);
+    } else {
+        QSize blendSize = blend.boundingRect().size();
+        if (!blendSize.isNull()) {
+            *blendbuffer = new QImage(blendSize, d_ptr->preferredImageFormat());
+        }
+    }
+
+    const QRegion blitRegion = exposed - blend;
+    if (!win)
+        paintBackground(blitRegion);
+    else if (!above_changing && surface->isBuffered())
+        blit(win, blitRegion);
+
+    QRegion blendRegion = exposed & blend;
+
+    if (win)
+        blendRegion &= win->paintedRegion();
+    if (!blendRegion.isEmpty()) {
+
+        QPoint off = blend.boundingRect().topLeft();
+
+        QRasterBuffer rb;
+        rb.prepare(*blendbuffer);
+        QSpanData spanData;
+        spanData.init(&rb, 0);
+        if (!win) {
+            const QImage::Format format = (*blendbuffer)->format();
+            switch (format) {
+            case QImage::Format_ARGB32_Premultiplied:
+            case QImage::Format_ARGB32:
+            case QImage::Format_ARGB8565_Premultiplied:
+            case QImage::Format_ARGB8555_Premultiplied:
+            case QImage::Format_ARGB6666_Premultiplied:
+            case QImage::Format_ARGB4444_Premultiplied:
+                spanData.rasterBuffer->compositionMode = QPainter::CompositionMode_Source;
+                break;
+            default:
+                break;
+            }
+            spanData.setup(qwsServer->backgroundBrush(), 256, QPainter::CompositionMode_SourceOver);
+            spanData.dx = off.x();
+            spanData.dy = off.y();
+        } else if (!surface->isBuffered()) {
+                return;
+        } else {
+            const QImage &img = surface->image();
+            QPoint winoff = off - win->requestedRegion().boundingRect().topLeft();
+            // convert win->opacity() from scale [0..255] to [0..256]
+            int const_alpha = win->opacity();
+            const_alpha += (const_alpha >> 7);
+            spanData.type = QSpanData::Texture;
+            spanData.initTexture(&img, const_alpha);
+            spanData.dx = winoff.x();
+            spanData.dy = winoff.y();
+        }
+        if (!spanData.blend)
+            return;
+
+        if (surface)
+            surface->lock();
+        const QVector<QRect> rects = blendRegion.rects();
+        const int nspans = 256;
+        QT_FT_Span spans[nspans];
+        for (int i = 0; i < rects.size(); ++i) {
+            int y = rects.at(i).y() - off.y();
+            int ye = y + rects.at(i).height();
+            int x = rects.at(i).x() - off.x();
+            int len = rects.at(i).width();
+            while (y < ye) {
+                int n = qMin(nspans, ye - y);
+                int i = 0;
+                while (i < n) {
+                    spans[i].x = x;
+                    spans[i].len = len;
+                    spans[i].y = y + i;
+                    spans[i].coverage = 255;
+                    ++i;
+                }
+                spanData.blend(n, spans, &spanData);
+                y += n;
+            }
+        }
+        if (surface)
+            surface->unlock();
+    }
+}
+
+void QScreen::paintBackground(const QRegion &r)
+{
+    const QBrush &bg = qwsServer->backgroundBrush();
+    Qt::BrushStyle bs = bg.style();
+    if (bs == Qt::NoBrush || r.isEmpty())
+        return;
+
+    if (bs == Qt::SolidPattern) {
+        solidFill(bg.color(), r);
+    } else {
+        const QRect br = r.boundingRect();
+        QImage img(br.size(), d_ptr->preferredImageFormat());
+        QPoint off = br.topLeft();
+        QRasterBuffer rb;
+        rb.prepare(&img);
+        QSpanData spanData;
+        spanData.init(&rb, 0);
+        spanData.setup(bg, 256, QPainter::CompositionMode_Source);
+        spanData.dx = off.x();
+        spanData.dy = off.y();
+        Q_ASSERT(spanData.blend);
+
+        const QVector<QRect> rects = r.rects();
+        const int nspans = 256;
+        QT_FT_Span spans[nspans];
+        for (int i = 0; i < rects.size(); ++i) {
+            int y = rects.at(i).y() - off.y();
+            int ye = y + rects.at(i).height();
+            int x = rects.at(i).x() - off.x();
+            int len = rects.at(i).width();
+            while (y < ye) {
+                int n = qMin(nspans, ye - y);
+                int i = 0;
+                while (i < n) {
+                    spans[i].x = x;
+                    spans[i].len = len;
+                    spans[i].y = y + i;
+                    spans[i].coverage = 255;
+                    ++i;
+                }
+                spanData.blend(n, spans, &spanData);
+                y += n;
+            }
+        }
+        blit(img, br.topLeft(), r);
+    }
+}
+
+/*!
+    \fn virtual int QScreen::sharedRamSize(void *)
+
+    \internal
+*/
+
+/*!
+    \fn QScreen::setDirty(const QRect& rectangle)
+
+    Marks the given \a rectangle as dirty.
+
+    Note that the default implementation does nothing; reimplement
+    this function to indicate that the given \a rectangle has been
+    altered.
+*/
+
+void QScreen::setDirty(const QRect&)
+{
+}
+
+/*!
+    \fn QScreen::isTransformed() const
+
+    Returns true if the screen is transformed (for instance, rotated
+    90 degrees); otherwise returns false.
+
+    \sa transformOrientation(), isInterlaced()
+*/
+
+bool QScreen::isTransformed() const
+{
+    return false;
+}
+
+/*!
+    \fn QScreen::isInterlaced() const
+
+    Returns true if the display is interlaced (i.e. is displaying
+    images progressively like a television screen); otherwise returns
+    false.
+
+    If the display is interlaced, the drawing is altered to look
+    better.
+
+    \sa isTransformed(), linestep()
+*/
+
+bool QScreen::isInterlaced() const
+{
+    return false;//qws_screen_is_interlaced;;
+}
+
+/*!
+    \fn QScreen::mapToDevice(const QSize &size) const
+
+    Maps the given \a size from the coordinate space used by the
+    application to the framebuffer coordinate system. Note that the
+    default implementation simply returns the given \a size as it is.
+
+    Reimplement this function to use the given device's coordinate
+    system when mapping.
+
+    \sa mapFromDevice()
+*/
+
+QSize QScreen::mapToDevice(const QSize &s) const
+{
+    return s;
+}
+
+/*!
+    \fn QScreen::mapFromDevice(const QSize &size) const
+
+    Maps the given \a size from the framebuffer coordinate system to
+    the coordinate space used by the application. Note that the
+    default implementation simply returns the given \a size as it is.
+
+    Reimplement this function to use the given device's coordinate
+    system when mapping.
+
+    \sa mapToDevice()
+*/
+
+QSize QScreen::mapFromDevice(const QSize &s) const
+{
+    return s;
+}
+
+/*!
+    \fn QScreen::mapToDevice(const QPoint &point, const QSize &screenSize) const
+    \overload
+
+    Maps the given \a point from the coordinate space used by the
+    application to the framebuffer coordinate system, passing the
+    device's \a screenSize as argument. Note that the default
+    implementation returns the given \a point as it is.
+*/
+
+QPoint QScreen::mapToDevice(const QPoint &p, const QSize &) const
+{
+    return p;
+}
+
+/*!
+    \fn QScreen::mapFromDevice(const QPoint &point, const QSize &screenSize) const
+    \overload
+
+    Maps the given \a point from the framebuffer coordinate system to
+    the coordinate space used by the application, passing the device's
+    \a screenSize as argument. Note that the default implementation
+    simply returns the given \a point as it is.
+*/
+
+QPoint QScreen::mapFromDevice(const QPoint &p, const QSize &) const
+{
+    return p;
+}
+
+/*!
+    \fn QScreen::mapToDevice(const QRect &rectangle, const QSize &screenSize) const
+    \overload
+
+    Maps the given \a rectangle from the coordinate space used by the
+    application to the framebuffer coordinate system, passing the
+    device's \a screenSize as argument. Note that the default
+    implementation returns the given \a rectangle as it is.
+*/
+
+QRect QScreen::mapToDevice(const QRect &r, const QSize &) const
+{
+    return r;
+}
+
+/*!
+    \fn QScreen::mapFromDevice(const QRect &rectangle, const QSize &screenSize) const
+    \overload
+
+    Maps the given \a rectangle from the framebuffer coordinate system to
+    the coordinate space used by the application, passing the device's
+    \a screenSize as argument. Note that the default implementation
+    simply returns the given \a rectangle as it is.
+*/
+
+QRect QScreen::mapFromDevice(const QRect &r, const QSize &) const
+{
+    return r;
+}
+
+/*!
+    \fn QScreen::mapToDevice(const QImage &image) const
+    \overload
+
+    Maps the given \a image from the coordinate space used by the
+    application to the framebuffer coordinate system. Note that the
+    default implementation returns the given \a image as it is.
+*/
+
+QImage QScreen::mapToDevice(const QImage &i) const
+{
+    return i;
+}
+
+/*!
+    \fn QScreen::mapFromDevice(const QImage &image) const
+    \overload
+
+    Maps the given \a image from the framebuffer coordinate system to
+    the coordinate space used by the application. Note that the
+    default implementation simply returns the given \a image as it is.
+*/
+
+QImage QScreen::mapFromDevice(const QImage &i) const
+{
+    return i;
+}
+
+/*!
+    \fn QScreen::mapToDevice(const QRegion &region, const QSize &screenSize) const
+    \overload
+
+    Maps the given \a region from the coordinate space used by the
+    application to the framebuffer coordinate system, passing the
+    device's \a screenSize as argument. Note that the default
+    implementation returns the given \a region as it is.
+*/
+
+QRegion QScreen::mapToDevice(const QRegion &r, const QSize &) const
+{
+    return r;
+}
+
+/*!
+    \fn QScreen::mapFromDevice(const QRegion &region, const QSize &screenSize) const
+    \overload
+
+    Maps the given \a region from the framebuffer coordinate system to
+    the coordinate space used by the application, passing the device's
+    \a screenSize as argument. Note that the default implementation
+    simply returns the given \a region as it is.
+*/
+
+QRegion QScreen::mapFromDevice(const QRegion &r, const QSize &) const
+{
+    return r;
+}
+
+/*!
+    \fn QScreen::transformOrientation() const
+
+    Returns the current rotation as an integer value.
+
+    Note that the default implementation returns 0; reimplement this
+    function to override this value.
+
+    \sa isTransformed()
+*/
+
+int QScreen::transformOrientation() const
+{
+    return 0;
+}
+
+int QScreen::pixmapDepth() const
+{
+    return depth();
+}
+
+/*!
+    \internal
+*/
+int QScreen::memoryNeeded(const QString&)
+{
+    return 0;
+}
+
+/*!
+    \internal
+*/
+void QScreen::haltUpdates()
+{
+}
+
+/*!
+    \internal
+*/
+void QScreen::resumeUpdates()
+{
+}
+
+/*!
+    \fn QRegion QScreen::region() const
+    \since 4.2
+
+    Returns the region covered by this screen driver.
+
+    \sa base(), screenSize()
+*/
+
+/*!
+    \internal
+*/
+void QScreen::setOffset(const QPoint &p)
+{
+    d_ptr->offset = p;
+}
+
+/*!
+    \since 4.2
+
+    Returns the logical offset of the screen, i.e., the offset between
+    (0,0) in screen coordinates and the application coordinate system.
+*/
+QPoint QScreen::offset() const
+{
+    return d_ptr->offset;
+}
+
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+void QScreen::setFrameBufferLittleEndian(bool littleEndian)
+{
+    d_ptr->fb_is_littleEndian = littleEndian;
+}
+
+bool QScreen::frameBufferLittleEndian() const
+{
+    return d_ptr->fb_is_littleEndian;
+}
+#endif
+
+/*!
+    \fn int QScreen::subScreenIndexAt(const QPoint &position) const
+    \since 4.2
+
+    Returns the index of the subscreen at the given \a position;
+    returns -1 if no screen is found.
+
+    The index identifies the subscreen in the list of pointers
+    returned by the subScreens() function.
+
+    \sa instance(), subScreens()
+*/
+int QScreen::subScreenIndexAt(const QPoint &p) const
+{
+    const QList<QScreen*> screens = subScreens();
+    const int n = screens.count();
+    for (int i = 0; i < n; ++i) {
+        if (screens.at(i)->region().contains(p))
+            return i;
+    }
+
+    return -1;
+}
+
+#if 0
+#ifdef QT_LOADABLE_MODULES
+
+// ### needs update after driver init changes
+
+static QScreen * qt_dodriver(char * driver,char * a,unsigned char * b)
+
+{
+    char buf[200];
+    strcpy(buf,"/etc/qws/drivers/");
+    qstrcpy(buf+17,driver);
+    qDebug("Attempting driver %s",driver);
+
+    void * handle;
+    handle=dlopen(buf,RTLD_LAZY);
+    if(handle==0) {
+        qFatal("Module load error");
+    }
+    QScreen *(*qt_get_screen_func)(char *,unsigned char *);
+    qt_get_screen_func=dlsym(handle,"qt_get_screen");
+    if(qt_get_screen_func==0) {
+        qFatal("Couldn't get symbol");
+    }
+    QScreen * ret=qt_get_screen_func(a,b);
+    return ret;
+}
+
+static QScreen * qt_do_entry(char * entry)
+{
+    unsigned char config[256];
+
+    FILE * f=fopen(entry,"r");
+    if(!f) {
+        return 0;
+    }
+
+    int r=fread(config,256,1,f);
+    if(r<1)
+        return 0;
+
+    fclose(f);
+
+    unsigned short vendorid=*((unsigned short int *)config);
+    unsigned short deviceid=*(((unsigned short int *)config)+1);
+    if(config[0xb]!=3)
+        return 0;
+
+    if(vendorid==0x1002) {
+        if(deviceid==0x4c4d) {
+            qDebug("Compaq Armada/IBM Thinkpad's Mach64 card");
+            return qt_dodriver("mach64.so",entry,config);
+        } else if(deviceid==0x4742) {
+            qDebug("Desktop Rage Pro Mach64 card");
+            return qt_dodriver("mach64.so",entry,config);
+        } else {
+            qDebug("Unrecognised ATI card id %x",deviceid);
+            return 0;
+        }
+    } else {
+        qDebug("Unrecognised vendor");
+    }
+    return 0;
+}
+
+extern bool qws_accel;
+
+/// ** NOT SUPPPORTED **
+
+QScreen * qt_probe_bus()
+{
+    if(!qws_accel) {
+        return qt_dodriver("unaccel.so",0,0);
+    }
+
+    DIR * dirptr=opendir("/proc/bus/pci");
+    if(!dirptr)
+        return qt_dodriver("unaccel.so",0,0);
+    DIR * dirptr2;
+    dirent * cards;
+
+    dirent * busses=readdir(dirptr);
+
+    while(busses) {
+        if(busses->d_name[0]!='.') {
+            char buf[100];
+            strcpy(buf,"/proc/bus/pci/");
+            qstrcpy(buf+14,busses->d_name);
+            int p=strlen(buf);
+            dirptr2=opendir(buf);
+            if(dirptr2) {
+                cards=readdir(dirptr2);
+                while(cards) {
+                    if(cards->d_name[0]!='.') {
+                        buf[p]='/';
+                        qstrcpy(buf+p+1,cards->d_name);
+                        QScreen * ret=qt_do_entry(buf);
+                        if(ret)
+                            return ret;
+                    }
+                    cards=readdir(dirptr2);
+                }
+                closedir(dirptr2);
+            }
+        }
+        busses=readdir(dirptr);
+    }
+    closedir(dirptr);
+
+    return qt_dodriver("unaccel.so",0,0);
+}
+
+#else
+
+char *qt_qws_hardcoded_slot = "/proc/bus/pci/01/00.0";
+
+const unsigned char* qt_probe_bus()
+{
+    const char * slot;
+    slot=::getenv("QWS_CARD_SLOT");
+    if(!slot)
+        slot=qt_qws_hardcoded_slot;
+    if (slot) {
+        static unsigned char config[256];
+        FILE * f=fopen(slot,"r");
+        if(!f) {
+            qDebug("Open failure for %s",slot);
+            slot=0;
+        } else {
+            int r=fread((char*)config,256,1,f);
+            fclose(f);
+            if(r<1) {
+                qDebug("Read failure");
+                return 0;
+            } else {
+                return config;
+            }
+        }
+    }
+    return 0;
+}
+
+#endif
+
+#endif // 0
+
+/*!
+    \internal
+    \since 4.4
+*/
+void QScreen::setPixmapDataFactory(QPixmapDataFactory *factory)
+{
+    static bool shownWarning = false;
+    if (!shownWarning) {
+        qWarning("QScreen::setPixmapDataFactory() is deprecated - use setGraphicsSystem() instead");
+        shownWarning = true;
+    }
+
+    d_ptr->pixmapFactory = factory;
+}
+
+/*!
+    \internal
+    \since 4.4
+*/
+QPixmapDataFactory* QScreen::pixmapDataFactory() const
+{
+    return d_ptr->pixmapFactory;
+}
+
+/*!
+    \internal
+    \since 4.5
+*/
+void QScreen::setGraphicsSystem(QGraphicsSystem* system)
+{
+    d_ptr->graphicsSystem = system;
+}
+
+/*!
+    \internal
+    \since 4.5
+*/
+QGraphicsSystem* QScreen::graphicsSystem() const
+{
+    return d_ptr->graphicsSystem;
+}
+
+/*!
+    \since 4.4
+
+    Returns the class identifier for the screen object.
+*/
+QScreen::ClassId QScreen::classId() const
+{
+    return static_cast<ClassId>(d_ptr->classId);
+}
+
+QT_END_NAMESPACE