src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the plugins of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qdirectfbscreen.h"
       
    43 #include "qdirectfbwindowsurface.h"
       
    44 #include "qdirectfbpixmap.h"
       
    45 #include "qdirectfbmouse.h"
       
    46 #include "qdirectfbkeyboard.h"
       
    47 #include <QtGui/qwsdisplay_qws.h>
       
    48 #include <QtGui/qcolor.h>
       
    49 #include <QtGui/qapplication.h>
       
    50 #include <QtGui/qwindowsystem_qws.h>
       
    51 #include <QtGui/private/qgraphicssystem_qws_p.h>
       
    52 #include <QtGui/private/qwssignalhandler_p.h>
       
    53 #include <QtCore/qvarlengtharray.h>
       
    54 #include <QtCore/qvector.h>
       
    55 #include <QtCore/qrect.h>
       
    56 
       
    57 #ifndef QT_NO_QWS_DIRECTFB
       
    58 
       
    59 QT_BEGIN_NAMESPACE
       
    60 
       
    61 class QDirectFBScreenPrivate : public QObject, public QWSGraphicsSystem
       
    62 {
       
    63     Q_OBJECT
       
    64 public:
       
    65     QDirectFBScreenPrivate(QDirectFBScreen *qptr);
       
    66     ~QDirectFBScreenPrivate();
       
    67 
       
    68     void setFlipFlags(const QStringList &args);
       
    69     QPixmapData *createPixmapData(QPixmapData::PixelType type) const;
       
    70 public slots:
       
    71 #ifdef QT_DIRECTFB_WM
       
    72     void onWindowEvent(QWSWindow *window, QWSServer::WindowEvent event);
       
    73 #endif
       
    74 public:
       
    75     IDirectFB *dfb;
       
    76     DFBSurfaceFlipFlags flipFlags;
       
    77     QDirectFBScreen::DirectFBFlags directFBFlags;
       
    78     QImage::Format alphaPixmapFormat;
       
    79     IDirectFBScreen *dfbScreen;
       
    80 #ifdef QT_NO_DIRECTFB_WM
       
    81     IDirectFBSurface *primarySurface;
       
    82     QColor backgroundColor;
       
    83 #endif
       
    84 #ifndef QT_NO_DIRECTFB_LAYER
       
    85     IDirectFBDisplayLayer *dfbLayer;
       
    86 #endif
       
    87     QSet<IDirectFBSurface*> allocatedSurfaces;
       
    88 
       
    89 #ifndef QT_NO_DIRECTFB_MOUSE
       
    90     QDirectFBMouseHandler *mouse;
       
    91 #endif
       
    92 #ifndef QT_NO_DIRECTFB_KEYBOARD
       
    93     QDirectFBKeyboardHandler *keyboard;
       
    94 #endif
       
    95 #if defined QT_DIRECTFB_IMAGEPROVIDER && defined QT_DIRECTFB_IMAGEPROVIDER_KEEPALIVE
       
    96     IDirectFBImageProvider *imageProvider;
       
    97 #endif
       
    98     IDirectFBSurface *cursorSurface;
       
    99     qint64 cursorImageKey;
       
   100 
       
   101     QDirectFBScreen *q;
       
   102     static QDirectFBScreen *instance;
       
   103 };
       
   104 
       
   105 QDirectFBScreen *QDirectFBScreenPrivate::instance = 0;
       
   106 
       
   107 QDirectFBScreenPrivate::QDirectFBScreenPrivate(QDirectFBScreen *qptr)
       
   108     : QWSGraphicsSystem(qptr), dfb(0), flipFlags(DSFLIP_NONE),
       
   109       directFBFlags(QDirectFBScreen::NoFlags), alphaPixmapFormat(QImage::Format_Invalid),
       
   110       dfbScreen(0)
       
   111 #ifdef QT_NO_DIRECTFB_WM
       
   112     , primarySurface(0)
       
   113 #endif
       
   114 #ifndef QT_NO_DIRECTFB_LAYER
       
   115     , dfbLayer(0)
       
   116 #endif
       
   117 #ifndef QT_NO_DIRECTFB_MOUSE
       
   118     , mouse(0)
       
   119 #endif
       
   120 #ifndef QT_NO_DIRECTFB_KEYBOARD
       
   121     , keyboard(0)
       
   122 #endif
       
   123 #if defined QT_DIRECTFB_IMAGEPROVIDER && defined QT_DIRECTFB_IMAGEPROVIDER_KEEPALIVE
       
   124     , imageProvider(0)
       
   125 #endif
       
   126     , cursorSurface(0)
       
   127     , cursorImageKey(0)
       
   128     , q(qptr)
       
   129 {
       
   130 #ifndef QT_NO_QWS_SIGNALHANDLER
       
   131     QWSSignalHandler::instance()->addObject(this);
       
   132 #endif
       
   133 #ifdef QT_DIRECTFB_WM
       
   134     connect(QWSServer::instance(), SIGNAL(windowEvent(QWSWindow*, QWSServer::WindowEvent)),
       
   135             this, SLOT(onWindowEvent(QWSWindow*, QWSServer::WindowEvent)));
       
   136 #endif
       
   137 }
       
   138 
       
   139 QDirectFBScreenPrivate::~QDirectFBScreenPrivate()
       
   140 {
       
   141 #ifndef QT_NO_DIRECTFB_MOUSE
       
   142     delete mouse;
       
   143 #endif
       
   144 #ifndef QT_NO_DIRECTFB_KEYBOARD
       
   145     delete keyboard;
       
   146 #endif
       
   147 #if defined QT_DIRECTFB_IMAGEPROVIDER_KEEPALIVE
       
   148     if (imageProvider)
       
   149         imageProvider->Release(imageProvider);
       
   150 #endif
       
   151 
       
   152     for (QSet<IDirectFBSurface*>::const_iterator it = allocatedSurfaces.begin(); it != allocatedSurfaces.end(); ++it) {
       
   153         (*it)->Release(*it);
       
   154     }
       
   155 
       
   156 #ifdef QT_NO_DIRECTFB_WM
       
   157     if (primarySurface)
       
   158         primarySurface->Release(primarySurface);
       
   159 #endif
       
   160 
       
   161 #ifndef QT_NO_DIRECTFB_LAYER
       
   162     if (dfbLayer)
       
   163         dfbLayer->Release(dfbLayer);
       
   164 #endif
       
   165 
       
   166     if (dfbScreen)
       
   167         dfbScreen->Release(dfbScreen);
       
   168 
       
   169     if (dfb)
       
   170         dfb->Release(dfb);
       
   171 }
       
   172 
       
   173 IDirectFBSurface *QDirectFBScreen::createDFBSurface(const QImage &image, QImage::Format format, SurfaceCreationOptions options, DFBResult *resultPtr)
       
   174 {
       
   175     if (image.isNull()) // assert?
       
   176         return 0;
       
   177 
       
   178     if (QDirectFBScreen::getSurfacePixelFormat(format) == DSPF_UNKNOWN) {
       
   179         format = QDirectFBPixmapData::hasAlphaChannel(image) ? d_ptr->alphaPixmapFormat : pixelFormat();
       
   180     }
       
   181     if (image.format() != format) {
       
   182         return createDFBSurface(image.convertToFormat(format), format, options | NoPreallocated, resultPtr);
       
   183     }
       
   184 
       
   185     DFBSurfaceDescription description;
       
   186     memset(&description, 0, sizeof(DFBSurfaceDescription));
       
   187     description.width = image.width();
       
   188     description.height = image.height();
       
   189     description.flags = DSDESC_WIDTH|DSDESC_HEIGHT|DSDESC_PIXELFORMAT;
       
   190     initSurfaceDescriptionPixelFormat(&description, format);
       
   191     bool doMemCopy = true;
       
   192 #ifdef QT_DIRECTFB_PREALLOCATED
       
   193     if (!(options & NoPreallocated)) {
       
   194         doMemCopy = false;
       
   195         description.flags |= DSDESC_PREALLOCATED;
       
   196         description.preallocated[0].data = const_cast<uchar*>(image.bits());
       
   197         description.preallocated[0].pitch = image.bytesPerLine();
       
   198         description.preallocated[1].data = 0;
       
   199         description.preallocated[1].pitch = 0;
       
   200     }
       
   201 #endif
       
   202     DFBResult result;
       
   203     IDirectFBSurface *surface = createDFBSurface(description, options, &result);
       
   204     if (resultPtr)
       
   205         *resultPtr = result;
       
   206     if (!surface) {
       
   207         DirectFBError("Couldn't create surface createDFBSurface(QImage, QImage::Format, SurfaceCreationOptions)", result);
       
   208         return 0;
       
   209     }
       
   210     if (doMemCopy) {
       
   211         int bplDFB;
       
   212         uchar *mem = QDirectFBScreen::lockSurface(surface, DSLF_WRITE, &bplDFB);
       
   213         if (mem) {
       
   214             const int height = image.height();
       
   215             const int bplQt = image.bytesPerLine();
       
   216             if (bplQt == bplDFB && bplQt == (image.width() * image.depth() / 8)) {
       
   217                 memcpy(mem, image.bits(), image.numBytes());
       
   218             } else {
       
   219                 for (int i=0; i<height; ++i) {
       
   220                     memcpy(mem, image.scanLine(i), bplQt);
       
   221                     mem += bplDFB;
       
   222                 }
       
   223             }
       
   224             surface->Unlock(surface);
       
   225         }
       
   226     }
       
   227 #ifdef QT_DIRECTFB_PALETTE
       
   228     if (image.numColors() != 0 && surface)
       
   229         QDirectFBScreen::setSurfaceColorTable(surface, image);
       
   230 #endif
       
   231     return surface;
       
   232 }
       
   233 
       
   234 IDirectFBSurface *QDirectFBScreen::copyDFBSurface(IDirectFBSurface *src,
       
   235                                                   QImage::Format format,
       
   236                                                   SurfaceCreationOptions options,
       
   237                                                   DFBResult *result)
       
   238 {
       
   239     Q_ASSERT(src);
       
   240     QSize size;
       
   241     src->GetSize(src, &size.rwidth(), &size.rheight());
       
   242     IDirectFBSurface *surface = createDFBSurface(size, format, options, result);
       
   243     DFBSurfaceBlittingFlags flags = QDirectFBScreen::hasAlphaChannel(surface)
       
   244                                     ? DSBLIT_BLEND_ALPHACHANNEL
       
   245                                     : DSBLIT_NOFX;
       
   246     if (flags & DSBLIT_BLEND_ALPHACHANNEL)
       
   247         surface->Clear(surface, 0, 0, 0, 0);
       
   248 
       
   249     surface->SetBlittingFlags(surface, flags);
       
   250     surface->Blit(surface, src, 0, 0, 0);
       
   251 #if (Q_DIRECTFB_VERSION >= 0x010000)
       
   252     surface->ReleaseSource(surface);
       
   253 #endif
       
   254     return surface;
       
   255 }
       
   256 
       
   257 IDirectFBSurface *QDirectFBScreen::createDFBSurface(const QSize &size,
       
   258                                                     QImage::Format format,
       
   259                                                     SurfaceCreationOptions options,
       
   260                                                     DFBResult *result)
       
   261 {
       
   262     DFBSurfaceDescription desc;
       
   263     memset(&desc, 0, sizeof(DFBSurfaceDescription));
       
   264     desc.flags |= DSDESC_WIDTH|DSDESC_HEIGHT;
       
   265     if (!QDirectFBScreen::initSurfaceDescriptionPixelFormat(&desc, format))
       
   266         return 0;
       
   267     desc.width = size.width();
       
   268     desc.height = size.height();
       
   269     return createDFBSurface(desc, options, result);
       
   270 }
       
   271 
       
   272 IDirectFBSurface *QDirectFBScreen::createDFBSurface(DFBSurfaceDescription desc, SurfaceCreationOptions options, DFBResult *resultPtr)
       
   273 {
       
   274     DFBResult tmp;
       
   275     DFBResult &result = (resultPtr ? *resultPtr : tmp);
       
   276     result = DFB_OK;
       
   277     IDirectFBSurface *newSurface = 0;
       
   278 
       
   279     if (!d_ptr->dfb) {
       
   280         qWarning("QDirectFBScreen::createDFBSurface() - not connected");
       
   281         return 0;
       
   282     }
       
   283 
       
   284     if (d_ptr->directFBFlags & VideoOnly
       
   285         && !(desc.flags & DSDESC_PREALLOCATED)
       
   286         && (!(desc.flags & DSDESC_CAPS) || !(desc.caps & DSCAPS_SYSTEMONLY))) {
       
   287         // Add the video only capability. This means the surface will be created in video ram
       
   288         if (!(desc.flags & DSDESC_CAPS)) {
       
   289             desc.caps = DSCAPS_VIDEOONLY;
       
   290             desc.flags |= DSDESC_CAPS;
       
   291         } else {
       
   292             desc.caps |= DSCAPS_VIDEOONLY;
       
   293         }
       
   294         result = d_ptr->dfb->CreateSurface(d_ptr->dfb, &desc, &newSurface);
       
   295         if (result != DFB_OK
       
   296 #ifdef QT_NO_DEBUG
       
   297             && (desc.flags & DSDESC_CAPS) && (desc.caps & DSCAPS_PRIMARY)
       
   298 #endif
       
   299             ) {
       
   300             qWarning("QDirectFBScreen::createDFBSurface() Failed to create surface in video memory!\n"
       
   301                      "   Flags %0x Caps %0x width %d height %d pixelformat %0x %d preallocated %p %d\n%s",
       
   302                      desc.flags, desc.caps, desc.width, desc.height,
       
   303                      desc.pixelformat, DFB_PIXELFORMAT_INDEX(desc.pixelformat),
       
   304                      desc.preallocated[0].data, desc.preallocated[0].pitch,
       
   305                      DirectFBErrorString(result));
       
   306         }
       
   307         desc.caps &= ~DSCAPS_VIDEOONLY;
       
   308     }
       
   309 
       
   310     if (d_ptr->directFBFlags & SystemOnly)
       
   311         desc.caps |= DSCAPS_SYSTEMONLY;
       
   312 
       
   313     if (!newSurface)
       
   314         result = d_ptr->dfb->CreateSurface(d_ptr->dfb, &desc, &newSurface);
       
   315 
       
   316     if (result != DFB_OK) {
       
   317         qWarning("QDirectFBScreen::createDFBSurface() Failed!\n"
       
   318                  "   Flags %0x Caps %0x width %d height %d pixelformat %0x %d preallocated %p %d\n%s",
       
   319                  desc.flags, desc.caps, desc.width, desc.height,
       
   320                  desc.pixelformat, DFB_PIXELFORMAT_INDEX(desc.pixelformat),
       
   321                  desc.preallocated[0].data, desc.preallocated[0].pitch,
       
   322                  DirectFBErrorString(result));
       
   323         return 0;
       
   324     }
       
   325 
       
   326     Q_ASSERT(newSurface);
       
   327 
       
   328     if (options & TrackSurface) {
       
   329         d_ptr->allocatedSurfaces.insert(newSurface);
       
   330     }
       
   331 
       
   332     return newSurface;
       
   333 }
       
   334 
       
   335 #ifdef QT_DIRECTFB_SUBSURFACE
       
   336 IDirectFBSurface *QDirectFBScreen::getSubSurface(IDirectFBSurface *surface,
       
   337                                                  const QRect &rect,
       
   338                                                  SurfaceCreationOptions options,
       
   339                                                  DFBResult *resultPtr)
       
   340 {
       
   341     Q_ASSERT(!(options & NoPreallocated));
       
   342     Q_ASSERT(surface);
       
   343     DFBResult res;
       
   344     DFBResult &result = (resultPtr ? *resultPtr : res);
       
   345     IDirectFBSurface *subSurface = 0;
       
   346     if (rect.isNull()) {
       
   347         result = surface->GetSubSurface(surface, 0, &subSurface);
       
   348     } else {
       
   349         const DFBRectangle subRect = { rect.x(), rect.y(), rect.width(), rect.height() };
       
   350         result = surface->GetSubSurface(surface, &subRect, &subSurface);
       
   351     }
       
   352     if (result != DFB_OK) {
       
   353         DirectFBError("Can't get sub surface", result);
       
   354     } else if (options & TrackSurface) {
       
   355         d_ptr->allocatedSurfaces.insert(subSurface);
       
   356     }
       
   357     return subSurface;
       
   358 }
       
   359 #endif
       
   360 
       
   361 
       
   362 void QDirectFBScreen::releaseDFBSurface(IDirectFBSurface *surface)
       
   363 {
       
   364     Q_ASSERT(QDirectFBScreen::instance());
       
   365     Q_ASSERT(surface);
       
   366     surface->Release(surface);
       
   367     if (!d_ptr->allocatedSurfaces.remove(surface))
       
   368         qWarning("QDirectFBScreen::releaseDFBSurface() - %p not in list", surface);
       
   369 
       
   370     //qDebug("Released surface at %p. New count = %d", surface, d_ptr->allocatedSurfaces.count());
       
   371 }
       
   372 
       
   373 QDirectFBScreen::DirectFBFlags QDirectFBScreen::directFBFlags() const
       
   374 {
       
   375     return d_ptr->directFBFlags;
       
   376 }
       
   377 
       
   378 IDirectFB *QDirectFBScreen::dfb()
       
   379 {
       
   380     return d_ptr->dfb;
       
   381 }
       
   382 
       
   383 #ifdef QT_NO_DIRECTFB_WM
       
   384 IDirectFBSurface *QDirectFBScreen::primarySurface()
       
   385 {
       
   386     return d_ptr->primarySurface;
       
   387 }
       
   388 #endif
       
   389 
       
   390 #ifndef QT_NO_DIRECTFB_LAYER
       
   391 IDirectFBDisplayLayer *QDirectFBScreen::dfbDisplayLayer()
       
   392 {
       
   393     return d_ptr->dfbLayer;
       
   394 }
       
   395 #endif
       
   396 
       
   397 DFBSurfacePixelFormat QDirectFBScreen::getSurfacePixelFormat(QImage::Format format)
       
   398 {
       
   399     switch (format) {
       
   400 #ifndef QT_NO_DIRECTFB_PALETTE
       
   401     case QImage::Format_Indexed8:
       
   402         return DSPF_LUT8;
       
   403 #endif
       
   404     case QImage::Format_RGB888:
       
   405         return DSPF_RGB24;
       
   406     case QImage::Format_ARGB4444_Premultiplied:
       
   407         return DSPF_ARGB4444;
       
   408 #if (Q_DIRECTFB_VERSION >= 0x010100)
       
   409     case QImage::Format_RGB444:
       
   410         return DSPF_RGB444;
       
   411     case QImage::Format_RGB555:
       
   412         return DSPF_RGB555;
       
   413 #endif
       
   414     case QImage::Format_RGB16:
       
   415         return DSPF_RGB16;
       
   416 #if (Q_DIRECTFB_VERSION >= 0x010000)
       
   417     case QImage::Format_ARGB6666_Premultiplied:
       
   418         return DSPF_ARGB6666;
       
   419     case QImage::Format_RGB666:
       
   420         return DSPF_RGB18;
       
   421 #endif
       
   422     case QImage::Format_RGB32:
       
   423         return DSPF_RGB32;
       
   424     case QImage::Format_ARGB32_Premultiplied:
       
   425     case QImage::Format_ARGB32:
       
   426         return DSPF_ARGB;
       
   427     default:
       
   428         return DSPF_UNKNOWN;
       
   429     };
       
   430 }
       
   431 
       
   432 QImage::Format QDirectFBScreen::getImageFormat(IDirectFBSurface *surface)
       
   433 {
       
   434     DFBSurfacePixelFormat format;
       
   435     surface->GetPixelFormat(surface, &format);
       
   436 
       
   437     switch (format) {
       
   438     case DSPF_LUT8:
       
   439         return QImage::Format_Indexed8;
       
   440     case DSPF_RGB24:
       
   441         return QImage::Format_RGB888;
       
   442     case DSPF_ARGB4444:
       
   443         return QImage::Format_ARGB4444_Premultiplied;
       
   444 #if (Q_DIRECTFB_VERSION >= 0x010100)
       
   445     case DSPF_RGB444:
       
   446         return QImage::Format_RGB444;
       
   447     case DSPF_RGB555:
       
   448 #endif
       
   449     case DSPF_ARGB1555:
       
   450         return QImage::Format_RGB555;
       
   451     case DSPF_RGB16:
       
   452         return QImage::Format_RGB16;
       
   453 #if (Q_DIRECTFB_VERSION >= 0x010000)
       
   454     case DSPF_ARGB6666:
       
   455         return QImage::Format_ARGB6666_Premultiplied;
       
   456     case DSPF_RGB18:
       
   457         return QImage::Format_RGB666;
       
   458 #endif
       
   459     case DSPF_RGB32:
       
   460         return QImage::Format_RGB32;
       
   461     case DSPF_ARGB: {
       
   462         DFBSurfaceCapabilities caps;
       
   463         const DFBResult result = surface->GetCapabilities(surface, &caps);
       
   464         Q_ASSERT(result == DFB_OK);
       
   465         Q_UNUSED(result);
       
   466         return (caps & DSCAPS_PREMULTIPLIED
       
   467                 ? QImage::Format_ARGB32_Premultiplied
       
   468                 : QImage::Format_ARGB32); }
       
   469     default:
       
   470         break;
       
   471     }
       
   472     return QImage::Format_Invalid;
       
   473 }
       
   474 
       
   475 DFBSurfaceDescription QDirectFBScreen::getSurfaceDescription(const uint *buffer,
       
   476                                                              int length)
       
   477 {
       
   478     DFBSurfaceDescription description;
       
   479     memset(&description, 0, sizeof(DFBSurfaceDescription));
       
   480 
       
   481     description.flags = DSDESC_CAPS|DSDESC_WIDTH|DSDESC_HEIGHT|DSDESC_PIXELFORMAT|DSDESC_PREALLOCATED;
       
   482     description.caps = DSCAPS_PREMULTIPLIED;
       
   483     description.width = length;
       
   484     description.height = 1;
       
   485     description.pixelformat = DSPF_ARGB;
       
   486     description.preallocated[0].data = (void*)buffer;
       
   487     description.preallocated[0].pitch = length * sizeof(uint);
       
   488     description.preallocated[1].data = 0;
       
   489     description.preallocated[1].pitch = 0;
       
   490     return description;
       
   491 }
       
   492 
       
   493 #ifndef QT_NO_DIRECTFB_PALETTE
       
   494 void QDirectFBScreen::setSurfaceColorTable(IDirectFBSurface *surface,
       
   495                                            const QImage &image)
       
   496 {
       
   497     if (!surface)
       
   498         return;
       
   499 
       
   500     const int numColors = image.numColors();
       
   501     if (numColors == 0)
       
   502         return;
       
   503 
       
   504     QVarLengthArray<DFBColor, 256> colors(numColors);
       
   505     for (int i = 0; i < numColors; ++i) {
       
   506         QRgb c = image.color(i);
       
   507         colors[i].a = qAlpha(c);
       
   508         colors[i].r = qRed(c);
       
   509         colors[i].g = qGreen(c);
       
   510         colors[i].b = qBlue(c);
       
   511     }
       
   512 
       
   513     IDirectFBPalette *palette;
       
   514     DFBResult result;
       
   515     result = surface->GetPalette(surface, &palette);
       
   516     if (result != DFB_OK) {
       
   517         DirectFBError("QDirectFBScreen::setSurfaceColorTable GetPalette",
       
   518                       result);
       
   519         return;
       
   520     }
       
   521     result = palette->SetEntries(palette, colors.data(), numColors, 0);
       
   522     if (result != DFB_OK) {
       
   523         DirectFBError("QDirectFBScreen::setSurfaceColorTable SetEntries",
       
   524                       result);
       
   525     }
       
   526     palette->Release(palette);
       
   527 }
       
   528 
       
   529 #endif // QT_NO_DIRECTFB_PALETTE
       
   530 
       
   531 #if defined QT_DIRECTFB_CURSOR
       
   532 class Q_GUI_EXPORT QDirectFBScreenCursor : public QScreenCursor
       
   533 {
       
   534 public:
       
   535     QDirectFBScreenCursor();
       
   536     virtual void set(const QImage &image, int hotx, int hoty);
       
   537     virtual void move(int x, int y);
       
   538     virtual void show();
       
   539     virtual void hide();
       
   540 private:
       
   541 #ifdef QT_DIRECTFB_WINDOW_AS_CURSOR
       
   542     ~QDirectFBScreenCursor();
       
   543     bool createWindow();
       
   544     IDirectFBWindow *window;
       
   545 #endif
       
   546     IDirectFBDisplayLayer *layer;
       
   547 };
       
   548 
       
   549 QDirectFBScreenCursor::QDirectFBScreenCursor()
       
   550 {
       
   551     IDirectFB *fb = QDirectFBScreen::instance()->dfb();
       
   552     if (!fb)
       
   553         qFatal("QDirectFBScreenCursor: DirectFB not initialized");
       
   554 
       
   555     layer = QDirectFBScreen::instance()->dfbDisplayLayer();
       
   556     Q_ASSERT(layer);
       
   557 
       
   558     enable = false;
       
   559     hwaccel = true;
       
   560     supportsAlpha = true;
       
   561 #ifdef QT_DIRECTFB_WINDOW_AS_CURSOR
       
   562     window = 0;
       
   563     DFBResult result = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE);
       
   564     if (result != DFB_OK) {
       
   565         DirectFBError("QDirectFBScreenCursor::hide: "
       
   566                       "Unable to set cooperative level", result);
       
   567     }
       
   568     result = layer->SetCursorOpacity(layer, 0);
       
   569     if (result != DFB_OK) {
       
   570         DirectFBError("QDirectFBScreenCursor::hide: "
       
   571                       "Unable to set cursor opacity", result);
       
   572     }
       
   573 
       
   574     result = layer->SetCooperativeLevel(layer, DLSCL_SHARED);
       
   575     if (result != DFB_OK) {
       
   576         DirectFBError("QDirectFBScreenCursor::hide: "
       
   577                       "Unable to set cooperative level", result);
       
   578     }
       
   579 #endif
       
   580 }
       
   581 
       
   582 #ifdef QT_DIRECTFB_WINDOW_AS_CURSOR
       
   583 QDirectFBScreenCursor::~QDirectFBScreenCursor()
       
   584 {
       
   585     if (window) {
       
   586         window->Release(window);
       
   587         window = 0;
       
   588     }
       
   589 }
       
   590 
       
   591 bool QDirectFBScreenCursor::createWindow()
       
   592 {
       
   593     Q_ASSERT(!window);
       
   594     Q_ASSERT(!cursor.isNull());
       
   595     DFBWindowDescription description;
       
   596     memset(&description, 0, sizeof(DFBWindowDescription));
       
   597     description.flags = DWDESC_POSX|DWDESC_POSY|DWDESC_WIDTH|DWDESC_HEIGHT|DWDESC_CAPS|DWDESC_PIXELFORMAT|DWDESC_SURFACE_CAPS;
       
   598     description.width = cursor.width();
       
   599     description.height = cursor.height();
       
   600     description.posx = pos.x() - hotspot.x();
       
   601     description.posy = pos.y() - hotspot.y();
       
   602 #if (Q_DIRECTFB_VERSION >= 0x010100)
       
   603     description.flags |= DWDESC_OPTIONS;
       
   604     description.options = DWOP_GHOST|DWOP_ALPHACHANNEL;
       
   605 #endif
       
   606     description.caps = DWCAPS_NODECORATION|DWCAPS_DOUBLEBUFFER;
       
   607     const QImage::Format format = QDirectFBScreen::instance()->alphaPixmapFormat();
       
   608     description.pixelformat = QDirectFBScreen::getSurfacePixelFormat(format);
       
   609     if (QDirectFBScreen::isPremultiplied(format))
       
   610         description.surface_caps = DSCAPS_PREMULTIPLIED;
       
   611 
       
   612     DFBResult result = layer->CreateWindow(layer, &description, &window);
       
   613     if (result != DFB_OK) {
       
   614         DirectFBError("QDirectFBScreenCursor::createWindow: Unable to create window", result);
       
   615         return false;
       
   616     }
       
   617     result = window->SetOpacity(window, 255);
       
   618     if (result != DFB_OK) {
       
   619         DirectFBError("QDirectFBScreenCursor::createWindow: Unable to set opacity ", result);
       
   620         return false;
       
   621     }
       
   622 
       
   623     result = window->SetStackingClass(window, DWSC_UPPER);
       
   624     if (result != DFB_OK) {
       
   625         DirectFBError("QDirectFBScreenCursor::createWindow: Unable to set stacking class ", result);
       
   626         return false;
       
   627     }
       
   628 
       
   629     result = window->RaiseToTop(window);
       
   630     if (result != DFB_OK) {
       
   631         DirectFBError("QDirectFBScreenCursor::createWindow: Unable to raise window ", result);
       
   632         return false;
       
   633     }
       
   634 
       
   635     return true;
       
   636 }
       
   637 #endif
       
   638 
       
   639 void QDirectFBScreenCursor::move(int x, int y)
       
   640 {
       
   641     pos = QPoint(x, y);
       
   642 #ifdef QT_DIRECTFB_WINDOW_AS_CURSOR
       
   643     if (window) {
       
   644         const QPoint p = pos - hotspot;
       
   645         DFBResult result = window->MoveTo(window, p.x(), p.y());
       
   646         if (result != DFB_OK) {
       
   647             DirectFBError("QDirectFBScreenCursor::move: Unable to move window", result);
       
   648         }
       
   649     }
       
   650 #else
       
   651     layer->WarpCursor(layer, x, y);
       
   652 #endif
       
   653 }
       
   654 
       
   655 void QDirectFBScreenCursor::hide()
       
   656 {
       
   657     if (enable) {
       
   658         enable = false;
       
   659         DFBResult result;
       
   660 #ifndef QT_DIRECTFB_WINDOW_AS_CURSOR
       
   661         result = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE);
       
   662         if (result != DFB_OK) {
       
   663             DirectFBError("QDirectFBScreenCursor::hide: "
       
   664                           "Unable to set cooperative level", result);
       
   665         }
       
   666         result = layer->SetCursorOpacity(layer, 0);
       
   667         if (result != DFB_OK) {
       
   668             DirectFBError("QDirectFBScreenCursor::hide: "
       
   669                           "Unable to set cursor opacity", result);
       
   670         }
       
   671         result = layer->SetCooperativeLevel(layer, DLSCL_SHARED);
       
   672         if (result != DFB_OK) {
       
   673             DirectFBError("QDirectFBScreenCursor::hide: "
       
   674                           "Unable to set cooperative level", result);
       
   675         }
       
   676 #else
       
   677         if (window) {
       
   678             result = window->SetOpacity(window, 0);
       
   679             if (result != DFB_OK) {
       
   680                 DirectFBError("QDirectFBScreenCursor::hide: "
       
   681                               "Unable to set window opacity", result);
       
   682             }
       
   683         }
       
   684 #endif
       
   685     }
       
   686 }
       
   687 
       
   688 void QDirectFBScreenCursor::show()
       
   689 {
       
   690     if (!enable) {
       
   691         enable = true;
       
   692         DFBResult result;
       
   693         result = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE);
       
   694         if (result != DFB_OK) {
       
   695             DirectFBError("QDirectFBScreenCursor::show: "
       
   696                           "Unable to set cooperative level", result);
       
   697         }
       
   698         result = layer->SetCursorOpacity(layer,
       
   699 #ifdef QT_DIRECTFB_WINDOW_AS_CURSOR
       
   700                                          0
       
   701 #else
       
   702                                          255
       
   703 #endif
       
   704             );
       
   705         if (result != DFB_OK) {
       
   706             DirectFBError("QDirectFBScreenCursor::show: "
       
   707                           "Unable to set cursor shape", result);
       
   708         }
       
   709         result = layer->SetCooperativeLevel(layer, DLSCL_SHARED);
       
   710         if (result != DFB_OK) {
       
   711             DirectFBError("QDirectFBScreenCursor::show: "
       
   712                           "Unable to set cooperative level", result);
       
   713         }
       
   714 #ifdef QT_DIRECTFB_WINDOW_AS_CURSOR
       
   715         if (window) {
       
   716             DFBResult result = window->SetOpacity(window, 255);
       
   717             if (result != DFB_OK) {
       
   718                 DirectFBError("QDirectFBScreenCursor::show: "
       
   719                               "Unable to set window opacity", result);
       
   720             }
       
   721         }
       
   722 #endif
       
   723     }
       
   724 }
       
   725 
       
   726 void QDirectFBScreenCursor::set(const QImage &image, int hotx, int hoty)
       
   727 {
       
   728     QDirectFBScreen *screen = QDirectFBScreen::instance();
       
   729     if (!screen)
       
   730         return;
       
   731 
       
   732     if (image.isNull()) {
       
   733         cursor = QImage();
       
   734         hide();
       
   735     } else {
       
   736         cursor = image.convertToFormat(screen->alphaPixmapFormat());
       
   737         size = cursor.size();
       
   738         hotspot = QPoint(hotx, hoty);
       
   739         DFBResult result = DFB_OK;
       
   740         IDirectFBSurface *surface = screen->createDFBSurface(cursor, screen->alphaPixmapFormat(),
       
   741                                                              QDirectFBScreen::DontTrackSurface, &result);
       
   742         if (!surface) {
       
   743             DirectFBError("QDirectFBScreenCursor::set: Unable to create surface", result);
       
   744             return;
       
   745         }
       
   746 #ifndef QT_DIRECTFB_WINDOW_AS_CURSOR
       
   747         result = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE);
       
   748         if (result != DFB_OK) {
       
   749             DirectFBError("QDirectFBScreenCursor::show: "
       
   750                           "Unable to set cooperative level", result);
       
   751         }
       
   752         result = layer->SetCursorShape(layer, surface, hotx, hoty);
       
   753         if (result != DFB_OK) {
       
   754             DirectFBError("QDirectFBScreenCursor::show: "
       
   755                           "Unable to set cursor shape", result);
       
   756         }
       
   757         result = layer->SetCooperativeLevel(layer, DLSCL_SHARED);
       
   758         if (result != DFB_OK) {
       
   759             DirectFBError("QDirectFBScreenCursor::show: "
       
   760                           "Unable to set cooperative level", result);
       
   761         }
       
   762 #else
       
   763         if (window || createWindow()) {
       
   764             QSize windowSize;
       
   765             result = window->GetSize(window, &windowSize.rwidth(), &windowSize.rheight());
       
   766             if (result != DFB_OK) {
       
   767                 DirectFBError("QDirectFBScreenCursor::set: "
       
   768                               "Unable to get window size", result);
       
   769             }
       
   770             result = window->Resize(window, size.width(), size.height());
       
   771             if (result != DFB_OK) {
       
   772                 DirectFBError("QDirectFBScreenCursor::set: Unable to resize window", result);
       
   773             }
       
   774 
       
   775             IDirectFBSurface *windowSurface;
       
   776             result = window->GetSurface(window, &windowSurface);
       
   777             if (result != DFB_OK) {
       
   778                 DirectFBError("QDirectFBScreenCursor::set: Unable to get window surface", result);
       
   779             } else {
       
   780                 result = windowSurface->Clear(windowSurface, 0, 0, 0, 0);
       
   781                 if (result != DFB_OK) {
       
   782                     DirectFBError("QDirectFBScreenCursor::set: Unable to clear surface", result);
       
   783                 }
       
   784 
       
   785                 result = windowSurface->Blit(windowSurface, surface, 0, 0, 0);
       
   786                 if (result != DFB_OK) {
       
   787                     DirectFBError("QDirectFBScreenCursor::set: Unable to blit to surface", result);
       
   788                 }
       
   789             }
       
   790             result = windowSurface->Flip(windowSurface, 0, DSFLIP_NONE);
       
   791             if (result != DFB_OK) {
       
   792                 DirectFBError("QDirectFBScreenCursor::set: Unable to flip window", result);
       
   793             }
       
   794 
       
   795             windowSurface->Release(windowSurface);
       
   796         }
       
   797 #endif
       
   798         surface->Release(surface);
       
   799         show();
       
   800     }
       
   801 
       
   802 }
       
   803 #endif // QT_DIRECTFB_CURSOR
       
   804 
       
   805 QDirectFBScreen::QDirectFBScreen(int display_id)
       
   806     : QScreen(display_id, DirectFBClass), d_ptr(new QDirectFBScreenPrivate(this))
       
   807 {
       
   808     QDirectFBScreenPrivate::instance = this;
       
   809 }
       
   810 
       
   811 QDirectFBScreen::~QDirectFBScreen()
       
   812 {
       
   813     if (QDirectFBScreenPrivate::instance == this)
       
   814         QDirectFBScreenPrivate::instance = 0;
       
   815     delete d_ptr;
       
   816 }
       
   817 
       
   818 QDirectFBScreen *QDirectFBScreen::instance()
       
   819 {
       
   820     return QDirectFBScreenPrivate::instance;
       
   821 }
       
   822 
       
   823 int QDirectFBScreen::depth(DFBSurfacePixelFormat format)
       
   824 {
       
   825     switch (format) {
       
   826     case DSPF_A1:
       
   827         return 1;
       
   828     case DSPF_A8:
       
   829     case DSPF_RGB332:
       
   830     case DSPF_LUT8:
       
   831     case DSPF_ALUT44:
       
   832         return 8;
       
   833     case DSPF_I420:
       
   834     case DSPF_YV12:
       
   835     case DSPF_NV12:
       
   836     case DSPF_NV21:
       
   837 #if (Q_DIRECTFB_VERSION >= 0x010100)
       
   838     case DSPF_RGB444:
       
   839 #endif
       
   840         return 12;
       
   841 #if (Q_DIRECTFB_VERSION >= 0x010100)
       
   842     case DSPF_RGB555:
       
   843         return 15;
       
   844 #endif
       
   845     case DSPF_ARGB1555:
       
   846     case DSPF_RGB16:
       
   847     case DSPF_YUY2:
       
   848     case DSPF_UYVY:
       
   849     case DSPF_NV16:
       
   850     case DSPF_ARGB2554:
       
   851     case DSPF_ARGB4444:
       
   852         return 16;
       
   853     case DSPF_RGB24:
       
   854         return 24;
       
   855     case DSPF_RGB32:
       
   856     case DSPF_ARGB:
       
   857     case DSPF_AiRGB:
       
   858         return 32;
       
   859     case DSPF_UNKNOWN:
       
   860     default:
       
   861         return 0;
       
   862     };
       
   863     return 0;
       
   864 }
       
   865 
       
   866 int QDirectFBScreen::depth(QImage::Format format)
       
   867 {
       
   868     int depth = 0;
       
   869     switch(format) {
       
   870     case QImage::Format_Invalid:
       
   871     case QImage::NImageFormats:
       
   872         Q_ASSERT(false);
       
   873     case QImage::Format_Mono:
       
   874     case QImage::Format_MonoLSB:
       
   875         depth = 1;
       
   876         break;
       
   877     case QImage::Format_Indexed8:
       
   878         depth = 8;
       
   879         break;
       
   880     case QImage::Format_RGB32:
       
   881     case QImage::Format_ARGB32:
       
   882     case QImage::Format_ARGB32_Premultiplied:
       
   883         depth = 32;
       
   884         break;
       
   885     case QImage::Format_RGB555:
       
   886     case QImage::Format_RGB16:
       
   887     case QImage::Format_RGB444:
       
   888     case QImage::Format_ARGB4444_Premultiplied:
       
   889         depth = 16;
       
   890         break;
       
   891     case QImage::Format_RGB666:
       
   892     case QImage::Format_ARGB6666_Premultiplied:
       
   893     case QImage::Format_ARGB8565_Premultiplied:
       
   894     case QImage::Format_ARGB8555_Premultiplied:
       
   895     case QImage::Format_RGB888:
       
   896         depth = 24;
       
   897         break;
       
   898     }
       
   899     return depth;
       
   900 }
       
   901 
       
   902 void QDirectFBScreenPrivate::setFlipFlags(const QStringList &args)
       
   903 {
       
   904     QRegExp flipRegexp(QLatin1String("^flip=([\\w,]*)$"));
       
   905     int index = args.indexOf(flipRegexp);
       
   906     if (index >= 0) {
       
   907         const QStringList flips = flipRegexp.cap(1).split(QLatin1Char(','),
       
   908                                                           QString::SkipEmptyParts);
       
   909         flipFlags = DSFLIP_NONE;
       
   910         foreach(const QString &flip, flips) {
       
   911             if (flip == QLatin1String("wait"))
       
   912                 flipFlags |= DSFLIP_WAIT;
       
   913             else if (flip == QLatin1String("blit"))
       
   914                 flipFlags |= DSFLIP_BLIT;
       
   915             else if (flip == QLatin1String("onsync"))
       
   916                 flipFlags |= DSFLIP_ONSYNC;
       
   917             else if (flip == QLatin1String("pipeline"))
       
   918                 flipFlags |= DSFLIP_PIPELINE;
       
   919             else
       
   920                 qWarning("QDirectFBScreen: Unknown flip argument: %s",
       
   921                          qPrintable(flip));
       
   922         }
       
   923     } else {
       
   924         flipFlags = DSFLIP_BLIT;
       
   925     }
       
   926 }
       
   927 
       
   928 #ifdef QT_DIRECTFB_WM
       
   929 void QDirectFBScreenPrivate::onWindowEvent(QWSWindow *window, QWSServer::WindowEvent event)
       
   930 {
       
   931     if (event == QWSServer::Raise) {
       
   932         QWSWindowSurface *windowSurface = window->windowSurface();
       
   933         if (windowSurface && windowSurface->key() == QLatin1String("directfb")) {
       
   934             static_cast<QDirectFBWindowSurface*>(windowSurface)->raise();
       
   935         }
       
   936     }
       
   937 }
       
   938 #endif
       
   939 
       
   940 QPixmapData *QDirectFBScreenPrivate::createPixmapData(QPixmapData::PixelType type) const
       
   941 {
       
   942     if (type == QPixmapData::BitmapType)
       
   943         return QWSGraphicsSystem::createPixmapData(type);
       
   944 
       
   945     return new QDirectFBPixmapData(q, type);
       
   946 }
       
   947 
       
   948 #if (Q_DIRECTFB_VERSION >= 0x000923)
       
   949 #ifdef QT_NO_DEBUG
       
   950 struct FlagDescription;
       
   951 static const FlagDescription *accelerationDescriptions = 0;
       
   952 static const FlagDescription *blitDescriptions = 0;
       
   953 static const FlagDescription *drawDescriptions = 0;
       
   954 #else
       
   955 struct FlagDescription {
       
   956     const char *name;
       
   957     uint flag;
       
   958 };
       
   959 
       
   960 static const FlagDescription accelerationDescriptions[] = {
       
   961     { " DFXL_NONE ", DFXL_NONE },
       
   962     { " DFXL_FILLRECTANGLE", DFXL_FILLRECTANGLE },
       
   963     { " DFXL_DRAWRECTANGLE", DFXL_DRAWRECTANGLE },
       
   964     { " DFXL_DRAWLINE", DFXL_DRAWLINE },
       
   965     { " DFXL_FILLTRIANGLE", DFXL_FILLTRIANGLE },
       
   966     { " DFXL_BLIT", DFXL_BLIT },
       
   967     { " DFXL_STRETCHBLIT", DFXL_STRETCHBLIT },
       
   968     { " DFXL_TEXTRIANGLES", DFXL_TEXTRIANGLES },
       
   969     { " DFXL_DRAWSTRING", DFXL_DRAWSTRING },
       
   970     { 0, 0 }
       
   971 };
       
   972 
       
   973 static const FlagDescription blitDescriptions[] = {
       
   974     { " DSBLIT_NOFX", DSBLIT_NOFX },
       
   975     { " DSBLIT_BLEND_ALPHACHANNEL", DSBLIT_BLEND_ALPHACHANNEL },
       
   976     { " DSBLIT_BLEND_COLORALPHA", DSBLIT_BLEND_COLORALPHA },
       
   977     { " DSBLIT_COLORIZE", DSBLIT_COLORIZE },
       
   978     { " DSBLIT_SRC_COLORKEY", DSBLIT_SRC_COLORKEY },
       
   979     { " DSBLIT_DST_COLORKEY", DSBLIT_DST_COLORKEY },
       
   980     { " DSBLIT_SRC_PREMULTIPLY", DSBLIT_SRC_PREMULTIPLY },
       
   981     { " DSBLIT_DST_PREMULTIPLY", DSBLIT_DST_PREMULTIPLY },
       
   982     { " DSBLIT_DEMULTIPLY", DSBLIT_DEMULTIPLY },
       
   983     { " DSBLIT_DEINTERLACE", DSBLIT_DEINTERLACE },
       
   984 #if (Q_DIRECTFB_VERSION >= 0x000923)
       
   985     { " DSBLIT_SRC_PREMULTCOLOR", DSBLIT_SRC_PREMULTCOLOR },
       
   986     { " DSBLIT_XOR", DSBLIT_XOR },
       
   987 #endif
       
   988 #if (Q_DIRECTFB_VERSION >= 0x010000)
       
   989     { " DSBLIT_INDEX_TRANSLATION", DSBLIT_INDEX_TRANSLATION },
       
   990 #endif
       
   991     { 0, 0 }
       
   992 };
       
   993 
       
   994 static const FlagDescription drawDescriptions[] = {
       
   995     { " DSDRAW_NOFX", DSDRAW_NOFX },
       
   996     { " DSDRAW_BLEND", DSDRAW_BLEND },
       
   997     { " DSDRAW_DST_COLORKEY", DSDRAW_DST_COLORKEY },
       
   998     { " DSDRAW_SRC_PREMULTIPLY", DSDRAW_SRC_PREMULTIPLY },
       
   999     { " DSDRAW_DST_PREMULTIPLY", DSDRAW_DST_PREMULTIPLY },
       
  1000     { " DSDRAW_DEMULTIPLY", DSDRAW_DEMULTIPLY },
       
  1001     { " DSDRAW_XOR", DSDRAW_XOR },
       
  1002     { 0, 0 }
       
  1003 };
       
  1004 #endif
       
  1005 
       
  1006 static const QByteArray flagDescriptions(uint mask, const FlagDescription *flags)
       
  1007 {
       
  1008 #ifdef QT_NO_DEBUG
       
  1009     Q_UNUSED(mask);
       
  1010     Q_UNUSED(flags);
       
  1011     return QByteArray("");
       
  1012 #else
       
  1013     if (!mask)
       
  1014         return flags[0].name;
       
  1015 
       
  1016     QStringList list;
       
  1017     for (int i=1; flags[i].name; ++i) {
       
  1018         if (mask & flags[i].flag) {
       
  1019             list.append(QString::fromLatin1(flags[i].name));
       
  1020         }
       
  1021     }
       
  1022     Q_ASSERT(!list.isEmpty());
       
  1023     return (QLatin1Char(' ') + list.join(QLatin1String("|"))).toLatin1();
       
  1024 #endif
       
  1025 }
       
  1026 static void printDirectFBInfo(IDirectFB *fb, IDirectFBSurface *primarySurface)
       
  1027 {
       
  1028     DFBResult result;
       
  1029     DFBGraphicsDeviceDescription dev;
       
  1030 
       
  1031     result = fb->GetDeviceDescription(fb, &dev);
       
  1032     if (result != DFB_OK) {
       
  1033         DirectFBError("Error reading graphics device description", result);
       
  1034         return;
       
  1035     }
       
  1036 
       
  1037     DFBSurfacePixelFormat pixelFormat;
       
  1038     primarySurface->GetPixelFormat(primarySurface, &pixelFormat);
       
  1039 
       
  1040     qDebug("Device: %s (%s), Driver: %s v%i.%i (%s) Pixelformat: %d (%d)\n"
       
  1041            "acceleration: 0x%x%s\nblit: 0x%x%s\ndraw: 0x%0x%s\nvideo: %iKB\n",
       
  1042            dev.name, dev.vendor, dev.driver.name, dev.driver.major,
       
  1043            dev.driver.minor, dev.driver.vendor, DFB_PIXELFORMAT_INDEX(pixelFormat),
       
  1044            QDirectFBScreen::getImageFormat(primarySurface), dev.acceleration_mask,
       
  1045            flagDescriptions(dev.acceleration_mask, accelerationDescriptions).constData(),
       
  1046            dev.blitting_flags, flagDescriptions(dev.blitting_flags, blitDescriptions).constData(),
       
  1047            dev.drawing_flags, flagDescriptions(dev.drawing_flags, drawDescriptions).constData(),
       
  1048            (dev.video_memory >> 10));
       
  1049 }
       
  1050 #endif
       
  1051 
       
  1052 static inline bool setIntOption(const QStringList &arguments, const QString &variable, int *value)
       
  1053 {
       
  1054     Q_ASSERT(value);
       
  1055     QRegExp rx(QString::fromLatin1("%1=?(\\d+)").arg(variable));
       
  1056     rx.setCaseSensitivity(Qt::CaseInsensitive);
       
  1057     if (arguments.indexOf(rx) != -1) {
       
  1058         *value = rx.cap(1).toInt();
       
  1059         return true;
       
  1060     }
       
  1061     return false;
       
  1062 }
       
  1063 
       
  1064 static inline QColor colorFromName(const QString &name)
       
  1065 {
       
  1066     QRegExp rx("#([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])");
       
  1067     rx.setCaseSensitivity(Qt::CaseInsensitive);
       
  1068     if (rx.exactMatch(name)) {
       
  1069         Q_ASSERT(rx.numCaptures() == 4);
       
  1070         int ints[4];
       
  1071         int i;
       
  1072         for (i=0; i<4; ++i) {
       
  1073             bool ok;
       
  1074             ints[i] = rx.cap(i + 1).toUInt(&ok, 16);
       
  1075             if (!ok || ints[i] > 255)
       
  1076                 break;
       
  1077         }
       
  1078         if (i == 4)
       
  1079             return QColor(ints[0], ints[1], ints[2], ints[3]);
       
  1080     }
       
  1081     return QColor(name);
       
  1082 }
       
  1083 
       
  1084 bool QDirectFBScreen::connect(const QString &displaySpec)
       
  1085 {
       
  1086     DFBResult result = DFB_OK;
       
  1087 
       
  1088     {   // pass command line arguments to DirectFB
       
  1089         const QStringList args = QCoreApplication::arguments();
       
  1090         int argc = args.size();
       
  1091         char **argv = new char*[argc];
       
  1092 
       
  1093         for (int i = 0; i < argc; ++i)
       
  1094             argv[i] = qstrdup(args.at(i).toLocal8Bit().constData());
       
  1095 
       
  1096         result = DirectFBInit(&argc, &argv);
       
  1097         if (result != DFB_OK) {
       
  1098             DirectFBError("QDirectFBScreen: error initializing DirectFB",
       
  1099                           result);
       
  1100         }
       
  1101         delete[] argv;
       
  1102     }
       
  1103 
       
  1104     const QStringList displayArgs = displaySpec.split(QLatin1Char(':'),
       
  1105                                                       QString::SkipEmptyParts);
       
  1106 
       
  1107     d_ptr->setFlipFlags(displayArgs);
       
  1108 
       
  1109     result = DirectFBCreate(&d_ptr->dfb);
       
  1110     if (result != DFB_OK) {
       
  1111         DirectFBError("QDirectFBScreen: error creating DirectFB interface",
       
  1112                       result);
       
  1113         return false;
       
  1114     }
       
  1115 
       
  1116     if (displayArgs.contains(QLatin1String("videoonly"), Qt::CaseInsensitive))
       
  1117         d_ptr->directFBFlags |= VideoOnly;
       
  1118 
       
  1119     if (displayArgs.contains(QLatin1String("systemonly"), Qt::CaseInsensitive)) {
       
  1120         if (d_ptr->directFBFlags & VideoOnly) {
       
  1121             qWarning("QDirectFBScreen: error. videoonly and systemonly are mutually exclusive");
       
  1122         } else {
       
  1123             d_ptr->directFBFlags |= SystemOnly;
       
  1124         }
       
  1125     }
       
  1126 
       
  1127     if (displayArgs.contains(QLatin1String("boundingrectflip"), Qt::CaseInsensitive)) {
       
  1128         d_ptr->directFBFlags |= BoundingRectFlip;
       
  1129     }
       
  1130 
       
  1131 #ifdef QT_DIRECTFB_IMAGECACHE
       
  1132     int imageCacheSize = 4 * 1024 * 1024; // 4 MB
       
  1133     setIntOption(displayArgs, QLatin1String("imagecachesize"), &imageCacheSize);
       
  1134     QDirectFBPaintEngine::initImageCache(imageCacheSize);
       
  1135 #endif
       
  1136 
       
  1137 #ifndef QT_NO_DIRECTFB_WM
       
  1138     if (displayArgs.contains(QLatin1String("fullscreen")))
       
  1139 #endif
       
  1140         d_ptr->dfb->SetCooperativeLevel(d_ptr->dfb, DFSCL_FULLSCREEN);
       
  1141 
       
  1142     DFBSurfaceDescription description;
       
  1143     memset(&description, 0, sizeof(DFBSurfaceDescription));
       
  1144     IDirectFBSurface *surface;
       
  1145 
       
  1146 #ifdef QT_NO_DIRECTFB_WM
       
  1147     description.flags = DSDESC_CAPS;
       
  1148     if (::setIntOption(displayArgs, QLatin1String("width"), &description.width))
       
  1149         description.flags |= DSDESC_WIDTH;
       
  1150     if (::setIntOption(displayArgs, QLatin1String("height"), &description.height))
       
  1151         description.flags |= DSDESC_HEIGHT;
       
  1152 
       
  1153     description.caps = DSCAPS_PRIMARY|DSCAPS_DOUBLE;
       
  1154     struct {
       
  1155         const char *name;
       
  1156         const DFBSurfaceCapabilities cap;
       
  1157     } const capabilities[] = {
       
  1158         { "static_alloc", DSCAPS_STATIC_ALLOC },
       
  1159         { "triplebuffer", DSCAPS_TRIPLE },
       
  1160         { "interlaced", DSCAPS_INTERLACED },
       
  1161         { "separated", DSCAPS_SEPARATED },
       
  1162 //        { "depthbuffer", DSCAPS_DEPTH }, // only makes sense with TextureTriangles which are not supported
       
  1163         { 0, DSCAPS_NONE }
       
  1164     };
       
  1165     for (int i=0; capabilities[i].name; ++i) {
       
  1166         if (displayArgs.contains(QString::fromLatin1(capabilities[i].name), Qt::CaseInsensitive))
       
  1167             description.caps |= capabilities[i].cap;
       
  1168     }
       
  1169 
       
  1170     if (displayArgs.contains(QLatin1String("forcepremultiplied"), Qt::CaseInsensitive)) {
       
  1171         description.caps |= DSCAPS_PREMULTIPLIED;
       
  1172     }
       
  1173 
       
  1174     // We don't track the primary surface as it's released in disconnect
       
  1175     d_ptr->primarySurface = createDFBSurface(description, DontTrackSurface, &result);
       
  1176     if (!d_ptr->primarySurface) {
       
  1177         DirectFBError("QDirectFBScreen: error creating primary surface",
       
  1178                       result);
       
  1179         return false;
       
  1180     }
       
  1181 
       
  1182     surface = d_ptr->primarySurface;
       
  1183 #else
       
  1184     description.flags = DSDESC_WIDTH|DSDESC_HEIGHT;
       
  1185     description.width = description.height = 1;
       
  1186     surface = createDFBSurface(description, DontTrackSurface, &result);
       
  1187     if (!surface) {
       
  1188         DirectFBError("QDirectFBScreen: error creating surface", result);
       
  1189         return false;
       
  1190     }
       
  1191 #endif
       
  1192     // Work out what format we're going to use for surfaces with an alpha channel
       
  1193     QImage::Format pixelFormat = QDirectFBScreen::getImageFormat(surface);
       
  1194     d_ptr->alphaPixmapFormat = pixelFormat;
       
  1195 
       
  1196     switch (pixelFormat) {
       
  1197     case QImage::Format_RGB666:
       
  1198         d_ptr->alphaPixmapFormat = QImage::Format_ARGB6666_Premultiplied;
       
  1199         break;
       
  1200     case QImage::Format_RGB444:
       
  1201         d_ptr->alphaPixmapFormat = QImage::Format_ARGB4444_Premultiplied;
       
  1202         break;
       
  1203     case QImage::Format_RGB32:
       
  1204         pixelFormat = d_ptr->alphaPixmapFormat = QImage::Format_ARGB32_Premultiplied;
       
  1205         // ### Format_RGB32 doesn't work so well with Qt. Force ARGB32 for windows/pixmaps
       
  1206         break;
       
  1207     case QImage::Format_Indexed8:
       
  1208         qWarning("QDirectFBScreen::connect(). Qt/DirectFB does not work with the LUT8  pixelformat.");
       
  1209         return false;
       
  1210     case QImage::NImageFormats:
       
  1211     case QImage::Format_Invalid:
       
  1212     case QImage::Format_Mono:
       
  1213     case QImage::Format_MonoLSB:
       
  1214     case QImage::Format_RGB888:
       
  1215     case QImage::Format_RGB16:
       
  1216     case QImage::Format_RGB555:
       
  1217         d_ptr->alphaPixmapFormat = QImage::Format_ARGB32_Premultiplied;
       
  1218         break;
       
  1219     case QImage::Format_ARGB32:
       
  1220     case QImage::Format_ARGB32_Premultiplied:
       
  1221     case QImage::Format_ARGB4444_Premultiplied:
       
  1222     case QImage::Format_ARGB8555_Premultiplied:
       
  1223     case QImage::Format_ARGB8565_Premultiplied:
       
  1224     case QImage::Format_ARGB6666_Premultiplied:
       
  1225         // works already
       
  1226         break;
       
  1227     }
       
  1228     setPixelFormat(pixelFormat);
       
  1229     QScreen::d = QDirectFBScreen::depth(pixelFormat);
       
  1230     data = 0;
       
  1231     lstep = 0;
       
  1232     size = 0;
       
  1233 
       
  1234     if (result != DFB_OK) {
       
  1235         DirectFBError("QDirectFBScreen::connect: "
       
  1236                       "Unable to get screen!", result);
       
  1237         return false;
       
  1238     }
       
  1239     const QString qws_size = QString::fromLatin1(qgetenv("QWS_SIZE"));
       
  1240     if (!qws_size.isEmpty()) {
       
  1241         QRegExp rx(QLatin1String("(\\d+)x(\\d+)"));
       
  1242         if (!rx.exactMatch(qws_size)) {
       
  1243             qWarning("QDirectFBScreen::connect: Can't parse QWS_SIZE=\"%s\"", qPrintable(qws_size));
       
  1244         } else {
       
  1245             int *ints[2] = { &w, &h };
       
  1246             for (int i=0; i<2; ++i) {
       
  1247                 *ints[i] = rx.cap(i + 1).toInt();
       
  1248                 if (*ints[i] <= 0) {
       
  1249                     qWarning("QDirectFBScreen::connect: %s is not a positive integer",
       
  1250                              qPrintable(rx.cap(i + 1)));
       
  1251                     w = h = 0;
       
  1252                     break;
       
  1253                 }
       
  1254             }
       
  1255         }
       
  1256     }
       
  1257 
       
  1258     setIntOption(displayArgs, QLatin1String("width"), &w);
       
  1259     setIntOption(displayArgs, QLatin1String("height"), &h);
       
  1260 
       
  1261 #ifndef QT_NO_DIRECTFB_LAYER
       
  1262     result = d_ptr->dfb->GetDisplayLayer(d_ptr->dfb, DLID_PRIMARY,
       
  1263                                          &d_ptr->dfbLayer);
       
  1264     if (result != DFB_OK) {
       
  1265         DirectFBError("QDirectFBScreen::connect: "
       
  1266                       "Unable to get primary display layer!", result);
       
  1267         return false;
       
  1268     }
       
  1269     result = d_ptr->dfbLayer->GetScreen(d_ptr->dfbLayer, &d_ptr->dfbScreen);
       
  1270 #else
       
  1271     result = d_ptr->dfb->GetScreen(d_ptr->dfb, 0, &d_ptr->dfbScreen);
       
  1272 #endif
       
  1273 
       
  1274     if (w <= 0 || h <= 0) {
       
  1275 #ifdef QT_NO_DIRECTFB_WM
       
  1276         result = d_ptr->primarySurface->GetSize(d_ptr->primarySurface, &w, &h);
       
  1277 #elif (Q_DIRECTFB_VERSION >= 0x010000)
       
  1278         result = d_ptr->dfbScreen->GetSize(d_ptr->dfbScreen, &w, &h);
       
  1279 #else
       
  1280         qWarning("QDirectFBScreen::connect: DirectFB versions prior to 1.0 do not offer a way\n"
       
  1281                  "query the size of the primary surface in windowed mode. You have to specify\n"
       
  1282                  "the size of the display using QWS_SIZE=[0-9]x[0-9] or\n"
       
  1283                  "QWS_DISPLAY=directfb:width=[0-9]:height=[0-9]");
       
  1284         return false;
       
  1285 #endif
       
  1286         if (result != DFB_OK) {
       
  1287             DirectFBError("QDirectFBScreen::connect: "
       
  1288                           "Unable to get screen size!", result);
       
  1289             return false;
       
  1290         }
       
  1291     }
       
  1292 
       
  1293 
       
  1294     dw = w;
       
  1295     dh = h;
       
  1296 
       
  1297     Q_ASSERT(dw != 0 && dh != 0);
       
  1298 
       
  1299     physWidth = physHeight = -1;
       
  1300     setIntOption(displayArgs, QLatin1String("mmWidth"), &physWidth);
       
  1301     setIntOption(displayArgs, QLatin1String("mmHeight"), &physHeight);
       
  1302     const int dpi = 72;
       
  1303     if (physWidth < 0)
       
  1304         physWidth = qRound(dw * 25.4 / dpi);
       
  1305     if (physHeight < 0)
       
  1306         physHeight = qRound(dh * 25.4 / dpi);
       
  1307 
       
  1308     setGraphicsSystem(d_ptr);
       
  1309 
       
  1310 #if (Q_DIRECTFB_VERSION >= 0x000923)
       
  1311     if (displayArgs.contains(QLatin1String("debug"), Qt::CaseInsensitive))
       
  1312         printDirectFBInfo(d_ptr->dfb, surface);
       
  1313 #endif
       
  1314 #ifdef QT_DIRECTFB_WM
       
  1315     surface->Release(surface);
       
  1316     QColor backgroundColor;
       
  1317 #else
       
  1318     QColor &backgroundColor = d_ptr->backgroundColor;
       
  1319 #endif
       
  1320 
       
  1321     QRegExp backgroundColorRegExp(QLatin1String("bgcolor=(.+)"));
       
  1322     backgroundColorRegExp.setCaseSensitivity(Qt::CaseInsensitive);
       
  1323     if (displayArgs.indexOf(backgroundColorRegExp) != -1) {
       
  1324         backgroundColor = colorFromName(backgroundColorRegExp.cap(1));
       
  1325     }
       
  1326 #ifdef QT_NO_DIRECTFB_WM
       
  1327     if (!backgroundColor.isValid())
       
  1328         backgroundColor = Qt::green;
       
  1329     d_ptr->primarySurface->Clear(d_ptr->primarySurface, backgroundColor.red(),
       
  1330                                  backgroundColor.green(), backgroundColor.blue(),
       
  1331                                  backgroundColor.alpha());
       
  1332     d_ptr->primarySurface->Flip(d_ptr->primarySurface, 0, d_ptr->flipFlags);
       
  1333 #else
       
  1334     if (backgroundColor.isValid()) {
       
  1335         DFBResult result = d_ptr->dfbLayer->SetCooperativeLevel(d_ptr->dfbLayer, DLSCL_ADMINISTRATIVE);
       
  1336         if (result != DFB_OK) {
       
  1337             DirectFBError("QDirectFBScreen::connect "
       
  1338                           "Unable to set cooperative level", result);
       
  1339         }
       
  1340         result = d_ptr->dfbLayer->SetBackgroundColor(d_ptr->dfbLayer, backgroundColor.red(), backgroundColor.green(),
       
  1341                                                      backgroundColor.blue(), backgroundColor.alpha());
       
  1342         if (result != DFB_OK) {
       
  1343             DirectFBError("QDirectFBScreenCursor::connect: "
       
  1344                           "Unable to set background color", result);
       
  1345         }
       
  1346 
       
  1347         result = d_ptr->dfbLayer->SetBackgroundMode(d_ptr->dfbLayer, DLBM_COLOR);
       
  1348         if (result != DFB_OK) {
       
  1349             DirectFBError("QDirectFBScreenCursor::connect: "
       
  1350                           "Unable to set background mode", result);
       
  1351         }
       
  1352 
       
  1353         result = d_ptr->dfbLayer->SetCooperativeLevel(d_ptr->dfbLayer, DLSCL_SHARED);
       
  1354         if (result != DFB_OK) {
       
  1355             DirectFBError("QDirectFBScreen::connect "
       
  1356                           "Unable to set cooperative level", result);
       
  1357         }
       
  1358 
       
  1359     }
       
  1360 #endif
       
  1361 
       
  1362     return true;
       
  1363 }
       
  1364 
       
  1365 void QDirectFBScreen::disconnect()
       
  1366 {
       
  1367 #if defined QT_DIRECTFB_IMAGEPROVIDER_KEEPALIVE
       
  1368     if (d_ptr->imageProvider)
       
  1369         d_ptr->imageProvider->Release(d_ptr->imageProvider);
       
  1370 #endif
       
  1371 #ifdef QT_NO_DIRECTFB_WM
       
  1372     d_ptr->primarySurface->Release(d_ptr->primarySurface);
       
  1373     d_ptr->primarySurface = 0;
       
  1374 #endif
       
  1375 
       
  1376     foreach (IDirectFBSurface *surf, d_ptr->allocatedSurfaces)
       
  1377         surf->Release(surf);
       
  1378     d_ptr->allocatedSurfaces.clear();
       
  1379 
       
  1380 #ifndef QT_NO_DIRECTFB_LAYER
       
  1381     d_ptr->dfbLayer->Release(d_ptr->dfbLayer);
       
  1382     d_ptr->dfbLayer = 0;
       
  1383 #endif
       
  1384 
       
  1385     d_ptr->dfbScreen->Release(d_ptr->dfbScreen);
       
  1386     d_ptr->dfbScreen = 0;
       
  1387 
       
  1388     d_ptr->dfb->Release(d_ptr->dfb);
       
  1389     d_ptr->dfb = 0;
       
  1390 }
       
  1391 
       
  1392 bool QDirectFBScreen::initDevice()
       
  1393 {
       
  1394 #ifndef QT_NO_DIRECTFB_MOUSE
       
  1395     if (qgetenv("QWS_MOUSE_PROTO").isEmpty()) {
       
  1396         QWSServer::instance()->setDefaultMouse("None");
       
  1397         d_ptr->mouse = new QDirectFBMouseHandler;
       
  1398     }
       
  1399 #endif
       
  1400 #ifndef QT_NO_DIRECTFB_KEYBOARD
       
  1401     if (qgetenv("QWS_KEYBOARD").isEmpty()) {
       
  1402         QWSServer::instance()->setDefaultKeyboard("None");
       
  1403         d_ptr->keyboard = new QDirectFBKeyboardHandler(QString());
       
  1404     }
       
  1405 #endif
       
  1406 
       
  1407 #ifdef QT_DIRECTFB_CURSOR
       
  1408     qt_screencursor = new QDirectFBScreenCursor;
       
  1409 #elif !defined QT_NO_QWS_CURSOR
       
  1410     QScreenCursor::initSoftwareCursor();
       
  1411 #endif
       
  1412     return true;
       
  1413 }
       
  1414 
       
  1415 void QDirectFBScreen::shutdownDevice()
       
  1416 {
       
  1417 #ifndef QT_NO_DIRECTFB_MOUSE
       
  1418     delete d_ptr->mouse;
       
  1419     d_ptr->mouse = 0;
       
  1420 #endif
       
  1421 #ifndef QT_NO_DIRECTFB_KEYBOARD
       
  1422     delete d_ptr->keyboard;
       
  1423     d_ptr->keyboard = 0;
       
  1424 #endif
       
  1425 
       
  1426 #ifndef QT_NO_QWS_CURSOR
       
  1427     delete qt_screencursor;
       
  1428     qt_screencursor = 0;
       
  1429 #endif
       
  1430 }
       
  1431 
       
  1432 void QDirectFBScreen::setMode(int width, int height, int depth)
       
  1433 {
       
  1434     d_ptr->dfb->SetVideoMode(d_ptr->dfb, width, height, depth);
       
  1435 }
       
  1436 
       
  1437 void QDirectFBScreen::blank(bool on)
       
  1438 {
       
  1439     d_ptr->dfbScreen->SetPowerMode(d_ptr->dfbScreen,
       
  1440                                    (on ? DSPM_ON : DSPM_SUSPEND));
       
  1441 }
       
  1442 
       
  1443 QWSWindowSurface *QDirectFBScreen::createSurface(QWidget *widget) const
       
  1444 {
       
  1445 #ifdef QT_NO_DIRECTFB_WM
       
  1446     if (QApplication::type() == QApplication::GuiServer) {
       
  1447         return new QDirectFBWindowSurface(d_ptr->flipFlags, const_cast<QDirectFBScreen*>(this), widget);
       
  1448     } else {
       
  1449         return QScreen::createSurface(widget);
       
  1450     }
       
  1451 #else
       
  1452     return new QDirectFBWindowSurface(d_ptr->flipFlags, const_cast<QDirectFBScreen*>(this), widget);
       
  1453 #endif
       
  1454 }
       
  1455 
       
  1456 QWSWindowSurface *QDirectFBScreen::createSurface(const QString &key) const
       
  1457 {
       
  1458     if (key == QLatin1String("directfb")) {
       
  1459         return new QDirectFBWindowSurface(d_ptr->flipFlags, const_cast<QDirectFBScreen*>(this));
       
  1460     }
       
  1461     return QScreen::createSurface(key);
       
  1462 }
       
  1463 
       
  1464 #if defined QT_NO_DIRECTFB_WM
       
  1465 struct PaintCommand {
       
  1466     PaintCommand() : dfbSurface(0), windowOpacity(255), blittingFlags(DSBLIT_NOFX) {}
       
  1467     IDirectFBSurface *dfbSurface;
       
  1468     QImage image;
       
  1469     QPoint windowPosition;
       
  1470     QRegion source;
       
  1471     quint8 windowOpacity;
       
  1472     DFBSurfaceBlittingFlags blittingFlags;
       
  1473 };
       
  1474 
       
  1475 static inline void initParameters(DFBRectangle &source, const QRect &sourceGlobal, const QPoint &pos)
       
  1476 {
       
  1477     source.x = sourceGlobal.x() - pos.x();
       
  1478     source.y = sourceGlobal.y() - pos.y();
       
  1479     source.w = sourceGlobal.width();
       
  1480     source.h = sourceGlobal.height();
       
  1481 }
       
  1482 #endif
       
  1483 
       
  1484 void QDirectFBScreen::exposeRegion(QRegion r, int)
       
  1485 {
       
  1486     Q_UNUSED(r);
       
  1487 #if defined QT_NO_DIRECTFB_WM
       
  1488 
       
  1489     r &= region();
       
  1490     if (r.isEmpty()) {
       
  1491         return;
       
  1492     }
       
  1493     r = r.boundingRect();
       
  1494 
       
  1495     IDirectFBSurface *primary = d_ptr->primarySurface;
       
  1496     const QList<QWSWindow*> windows = QWSServer::instance()->clientWindows();
       
  1497     QVarLengthArray<PaintCommand, 4> commands(windows.size());
       
  1498     QRegion region = r;
       
  1499     int idx = 0;
       
  1500     for (int i=0; i<windows.size(); ++i) {
       
  1501         QWSWindowSurface *surface = windows.at(i)->windowSurface();
       
  1502         if (!surface)
       
  1503             continue;
       
  1504 
       
  1505         const QRect windowGeometry = surface->geometry();
       
  1506         const QRegion intersection = region & windowGeometry;
       
  1507         if (intersection.isEmpty()) {
       
  1508             continue;
       
  1509         }
       
  1510 
       
  1511         PaintCommand &cmd = commands[idx];
       
  1512 
       
  1513         if (surface->key() == QLatin1String("directfb")) {
       
  1514             const QDirectFBWindowSurface *ws = static_cast<QDirectFBWindowSurface*>(surface);
       
  1515             cmd.dfbSurface = ws->directFBSurface();
       
  1516 
       
  1517             if (!cmd.dfbSurface) {
       
  1518                 continue;
       
  1519             }
       
  1520         } else {
       
  1521             cmd.image = surface->image();
       
  1522             if (cmd.image.isNull()) {
       
  1523                 continue;
       
  1524             }
       
  1525         }
       
  1526         ++idx;
       
  1527 
       
  1528         cmd.windowPosition = windowGeometry.topLeft();
       
  1529         cmd.source = intersection;
       
  1530         if (windows.at(i)->isOpaque()) {
       
  1531             region -= intersection;
       
  1532             if (region.isEmpty())
       
  1533                 break;
       
  1534         } else {
       
  1535             cmd.windowOpacity = windows.at(i)->opacity();
       
  1536             cmd.blittingFlags = cmd.windowOpacity == 255
       
  1537                                 ? DSBLIT_BLEND_ALPHACHANNEL
       
  1538                                 : (DSBLIT_BLEND_ALPHACHANNEL|DSBLIT_BLEND_COLORALPHA);
       
  1539         }
       
  1540     }
       
  1541     if (!region.isEmpty()) {
       
  1542         solidFill(d_ptr->backgroundColor, region);
       
  1543     }
       
  1544 
       
  1545     while (idx > 0) {
       
  1546         const PaintCommand &cmd = commands[--idx];
       
  1547         Q_ASSERT(cmd.dfbSurface || !cmd.image.isNull());
       
  1548         IDirectFBSurface *surface;
       
  1549         if (cmd.dfbSurface) {
       
  1550             surface = cmd.dfbSurface;
       
  1551         } else {
       
  1552             Q_ASSERT(!cmd.image.isNull());
       
  1553             DFBResult result;
       
  1554             surface = createDFBSurface(cmd.image, cmd.image.format(), DontTrackSurface, &result);
       
  1555             Q_ASSERT((result != DFB_OK) == !surface);
       
  1556             if (result != DFB_OK) {
       
  1557                 DirectFBError("QDirectFBScreen::exposeRegion: Can't create surface from image", result);
       
  1558                 continue;
       
  1559             }
       
  1560         }
       
  1561 
       
  1562         primary->SetBlittingFlags(primary, cmd.blittingFlags);
       
  1563         if (cmd.blittingFlags & DSBLIT_BLEND_COLORALPHA) {
       
  1564             primary->SetColor(primary, 0xff, 0xff, 0xff, cmd.windowOpacity);
       
  1565         }
       
  1566         const QRegion &region = cmd.source;
       
  1567         const int rectCount = region.numRects();
       
  1568         DFBRectangle source;
       
  1569         if (rectCount == 1) {
       
  1570             ::initParameters(source, region.boundingRect(), cmd.windowPosition);
       
  1571             primary->Blit(primary, surface, &source, cmd.windowPosition.x() + source.x, cmd.windowPosition.y() + source.y);
       
  1572         } else {
       
  1573             const QVector<QRect> rects = region.rects();
       
  1574             for (int i=0; i<rectCount; ++i) {
       
  1575                 ::initParameters(source, rects.at(i), cmd.windowPosition);
       
  1576                 primary->Blit(primary, surface, &source, cmd.windowPosition.x() + source.x, cmd.windowPosition.y() + source.y);
       
  1577             }
       
  1578         }
       
  1579         if (surface != cmd.dfbSurface) {
       
  1580             surface->Release(surface);
       
  1581         }
       
  1582     }
       
  1583 
       
  1584     primary->SetColor(primary, 0xff, 0xff, 0xff, 0xff);
       
  1585 
       
  1586 #if defined QT_NO_DIRECTFB_CURSOR and !defined QT_NO_QWS_CURSOR
       
  1587     if (QScreenCursor *cursor = QScreenCursor::instance()) {
       
  1588         const QRect cursorRectangle = cursor->boundingRect();
       
  1589         if (cursor->isVisible() && !cursor->isAccelerated() && r.intersects(cursorRectangle)) {
       
  1590             const QImage image = cursor->image();
       
  1591             if (image.cacheKey() != d_ptr->cursorImageKey) {
       
  1592                 if (d_ptr->cursorSurface) {
       
  1593                     releaseDFBSurface(d_ptr->cursorSurface);
       
  1594                 }
       
  1595                 d_ptr->cursorSurface = createDFBSurface(image, image.format(), QDirectFBScreen::TrackSurface);
       
  1596                 d_ptr->cursorImageKey = image.cacheKey();
       
  1597             }
       
  1598 
       
  1599             Q_ASSERT(d_ptr->cursorSurface);
       
  1600             primary->SetBlittingFlags(primary, DSBLIT_BLEND_ALPHACHANNEL);
       
  1601             primary->Blit(primary, d_ptr->cursorSurface, 0, cursorRectangle.x(), cursorRectangle.y());
       
  1602         }
       
  1603     }
       
  1604 #endif
       
  1605     flipSurface(primary, d_ptr->flipFlags, r, QPoint());
       
  1606     primary->SetBlittingFlags(primary, DSBLIT_NOFX);
       
  1607 #endif
       
  1608 }
       
  1609 
       
  1610 void QDirectFBScreen::solidFill(const QColor &color, const QRegion &region)
       
  1611 {
       
  1612 #ifdef QT_DIRECTFB_WM
       
  1613     Q_UNUSED(color);
       
  1614     Q_UNUSED(region);
       
  1615 #else
       
  1616     if (region.isEmpty())
       
  1617         return;
       
  1618 
       
  1619     d_ptr->primarySurface->SetColor(d_ptr->primarySurface,
       
  1620                                     color.red(), color.green(), color.blue(),
       
  1621                                     color.alpha());
       
  1622     const int n = region.numRects();
       
  1623     if (n == 1) {
       
  1624         const QRect r = region.boundingRect();
       
  1625         d_ptr->primarySurface->FillRectangle(d_ptr->primarySurface, r.x(), r.y(), r.width(), r.height());
       
  1626     } else {
       
  1627         const QVector<QRect> rects = region.rects();
       
  1628         QVarLengthArray<DFBRectangle, 32> rectArray(n);
       
  1629         for (int i=0; i<n; ++i) {
       
  1630             const QRect &r = rects.at(i);
       
  1631             rectArray[i].x = r.x();
       
  1632             rectArray[i].y = r.y();
       
  1633             rectArray[i].w = r.width();
       
  1634             rectArray[i].h = r.height();
       
  1635         }
       
  1636         d_ptr->primarySurface->FillRectangles(d_ptr->primarySurface, rectArray.constData(), n);
       
  1637     }
       
  1638 #endif
       
  1639 }
       
  1640 
       
  1641 QImage::Format QDirectFBScreen::alphaPixmapFormat() const
       
  1642 {
       
  1643     return d_ptr->alphaPixmapFormat;
       
  1644 }
       
  1645 
       
  1646 bool QDirectFBScreen::initSurfaceDescriptionPixelFormat(DFBSurfaceDescription *description,
       
  1647                                                         QImage::Format format)
       
  1648 {
       
  1649     const DFBSurfacePixelFormat pixelformat = QDirectFBScreen::getSurfacePixelFormat(format);
       
  1650     if (pixelformat == DSPF_UNKNOWN)
       
  1651         return false;
       
  1652     description->flags |= DSDESC_PIXELFORMAT;
       
  1653     description->pixelformat = pixelformat;
       
  1654     if (QDirectFBScreen::isPremultiplied(format)) {
       
  1655         if (!(description->flags & DSDESC_CAPS)) {
       
  1656             description->caps = DSCAPS_PREMULTIPLIED;
       
  1657             description->flags |= DSDESC_CAPS;
       
  1658         } else {
       
  1659             description->caps |= DSCAPS_PREMULTIPLIED;
       
  1660         }
       
  1661     }
       
  1662     return true;
       
  1663 }
       
  1664 
       
  1665 uchar *QDirectFBScreen::lockSurface(IDirectFBSurface *surface, DFBSurfaceLockFlags flags, int *bpl)
       
  1666 {
       
  1667     void *mem;
       
  1668     const DFBResult result = surface->Lock(surface, flags, &mem, bpl);
       
  1669     if (result != DFB_OK) {
       
  1670         DirectFBError("QDirectFBScreen::lockSurface()", result);
       
  1671     }
       
  1672 
       
  1673     return reinterpret_cast<uchar*>(mem);
       
  1674 }
       
  1675 
       
  1676 
       
  1677 void QDirectFBScreen::flipSurface(IDirectFBSurface *surface, DFBSurfaceFlipFlags flipFlags,
       
  1678                                   const QRegion &region, const QPoint &offset)
       
  1679 {
       
  1680     if (!(flipFlags & DSFLIP_BLIT)) {
       
  1681         surface->Flip(surface, 0, flipFlags);
       
  1682     } else {
       
  1683         if (!(d_ptr->directFBFlags & BoundingRectFlip) && region.numRects() > 1) {
       
  1684             const QVector<QRect> rects = region.rects();
       
  1685             const DFBSurfaceFlipFlags nonWaitFlags = flipFlags & ~DSFLIP_WAIT;
       
  1686             for (int i=0; i<rects.size(); ++i) {
       
  1687                 const QRect &r = rects.at(i);
       
  1688                 const DFBRegion dfbReg = { r.x() + offset.x(), r.y() + offset.y(),
       
  1689                                            r.right() + offset.x(),
       
  1690                                            r.bottom() + offset.y() };
       
  1691                 surface->Flip(surface, &dfbReg, i + 1 < rects.size() ? nonWaitFlags : flipFlags);
       
  1692             }
       
  1693         } else {
       
  1694             const QRect r = region.boundingRect();
       
  1695             const DFBRegion dfbReg = { r.x() + offset.x(), r.y() + offset.y(),
       
  1696                                        r.right() + offset.x(),
       
  1697                                        r.bottom() + offset.y() };
       
  1698             surface->Flip(surface, &dfbReg, flipFlags);
       
  1699         }
       
  1700     }
       
  1701 }
       
  1702 
       
  1703 #if defined QT_DIRECTFB_IMAGEPROVIDER_KEEPALIVE
       
  1704 void QDirectFBScreen::setDirectFBImageProvider(IDirectFBImageProvider *provider)
       
  1705 {
       
  1706     Q_ASSERT(provider);
       
  1707     if (d_ptr->imageProvider)
       
  1708         d_ptr->imageProvider->Release(d_ptr->imageProvider);
       
  1709     d_ptr->imageProvider = provider;
       
  1710 }
       
  1711 #endif
       
  1712 
       
  1713 void QDirectFBScreen::waitIdle()
       
  1714 {
       
  1715     d_ptr->dfb->WaitIdle(d_ptr->dfb);
       
  1716 }
       
  1717 
       
  1718 #ifdef QT_DIRECTFB_WM
       
  1719 IDirectFBWindow *QDirectFBScreen::windowForWidget(const QWidget *widget) const
       
  1720 {
       
  1721     if (widget) {
       
  1722         const QWSWindowSurface *surface = static_cast<const QWSWindowSurface*>(widget->windowSurface());
       
  1723         if (surface && surface->key() == QLatin1String("directfb")) {
       
  1724             return static_cast<const QDirectFBWindowSurface*>(surface)->directFBWindow();
       
  1725         }
       
  1726     }
       
  1727     return 0;
       
  1728 }
       
  1729 #endif
       
  1730 
       
  1731 IDirectFBSurface * QDirectFBScreen::surfaceForWidget(const QWidget *widget, QRect *rect) const
       
  1732 {
       
  1733     Q_ASSERT(widget);
       
  1734     if (!widget->isVisible() || widget->size().isNull())
       
  1735         return 0;
       
  1736 
       
  1737     const QWSWindowSurface *surface = static_cast<const QWSWindowSurface*>(widget->windowSurface());
       
  1738     if (surface && surface->key() == QLatin1String("directfb")) {
       
  1739         return static_cast<const QDirectFBWindowSurface*>(surface)->surfaceForWidget(widget, rect);
       
  1740     }
       
  1741     return 0;
       
  1742 }
       
  1743 
       
  1744 #ifdef QT_DIRECTFB_SUBSURFACE
       
  1745 IDirectFBSurface *QDirectFBScreen::subSurfaceForWidget(const QWidget *widget, const QRect &area) const
       
  1746 {
       
  1747     Q_ASSERT(widget);
       
  1748     QRect rect;
       
  1749     IDirectFBSurface *surface = surfaceForWidget(widget, &rect);
       
  1750     IDirectFBSurface *subSurface = 0;
       
  1751     if (surface) {
       
  1752         if (!area.isNull())
       
  1753             rect &= area.translated(widget->mapTo(widget->window(), QPoint(0, 0)));
       
  1754         if (!rect.isNull()) {
       
  1755             const DFBRectangle subRect = { rect.x(), rect.y(), rect.width(), rect.height() };
       
  1756             const DFBResult result = surface->GetSubSurface(surface, &subRect, &subSurface);
       
  1757             if (result != DFB_OK) {
       
  1758                 DirectFBError("QDirectFBScreen::subSurface(): Can't get sub surface", result);
       
  1759             }
       
  1760         }
       
  1761     }
       
  1762     return subSurface;
       
  1763 }
       
  1764 #endif
       
  1765 
       
  1766 #ifndef QT_DIRECTFB_PLUGIN
       
  1767 Q_GUI_EXPORT IDirectFBSurface *qt_directfb_surface_for_widget(const QWidget *widget, QRect *rect)
       
  1768 {
       
  1769     return QDirectFBScreen::instance() ? QDirectFBScreen::instance()->surfaceForWidget(widget, rect) : 0;
       
  1770 }
       
  1771 #ifdef QT_DIRECTFB_SUBSURFACE
       
  1772 Q_GUI_EXPORT IDirectFBSurface *qt_directfb_subsurface_for_widget(const QWidget *widget, const QRect &area)
       
  1773 {
       
  1774     return QDirectFBScreen::instance() ? QDirectFBScreen::instance()->subSurfaceForWidget(widget, area) : 0;
       
  1775 }
       
  1776 #endif
       
  1777 #ifdef QT_DIRECTFB_WM
       
  1778 Q_GUI_EXPORT IDirectFBWindow *qt_directfb_window_for_widget(const QWidget *widget)
       
  1779 {
       
  1780     return QDirectFBScreen::instance() ? QDirectFBScreen::instance()->windowForWidget(widget) : 0;
       
  1781 }
       
  1782 
       
  1783 #endif
       
  1784 #endif
       
  1785 
       
  1786 QT_END_NAMESPACE
       
  1787 
       
  1788 #include "qdirectfbscreen.moc"
       
  1789 #endif // QT_NO_QWS_DIRECTFB
       
  1790