util/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp
changeset 7 f7bc934e204c
equal deleted inserted replaced
3:41300fa6a67c 7:f7bc934e204c
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the 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.byteCount());
       
   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.colorCount() != 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.colorCount();
       
   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|DSFLIP_ONSYNC;
       
   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(QLatin1String("#([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.captureCount() == 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     } else if (displayArgs.contains(QLatin1String("nopartialflip"), Qt::CaseInsensitive)) {
       
  1130         d_ptr->directFBFlags |= NoPartialFlip;
       
  1131     }
       
  1132 
       
  1133 #ifdef QT_DIRECTFB_IMAGECACHE
       
  1134     int imageCacheSize = 4 * 1024 * 1024; // 4 MB
       
  1135     setIntOption(displayArgs, QLatin1String("imagecachesize"), &imageCacheSize);
       
  1136     QDirectFBPaintEngine::initImageCache(imageCacheSize);
       
  1137 #endif
       
  1138 
       
  1139 #ifndef QT_NO_DIRECTFB_WM
       
  1140     if (displayArgs.contains(QLatin1String("fullscreen")))
       
  1141 #endif
       
  1142         d_ptr->dfb->SetCooperativeLevel(d_ptr->dfb, DFSCL_FULLSCREEN);
       
  1143 
       
  1144     const bool forcePremultiplied = displayArgs.contains(QLatin1String("forcepremultiplied"), Qt::CaseInsensitive);
       
  1145 
       
  1146     DFBSurfaceDescription description;
       
  1147     memset(&description, 0, sizeof(DFBSurfaceDescription));
       
  1148     IDirectFBSurface *surface;
       
  1149 
       
  1150 #ifdef QT_NO_DIRECTFB_WM
       
  1151     description.flags = DSDESC_CAPS;
       
  1152     if (::setIntOption(displayArgs, QLatin1String("width"), &description.width))
       
  1153         description.flags |= DSDESC_WIDTH;
       
  1154     if (::setIntOption(displayArgs, QLatin1String("height"), &description.height))
       
  1155         description.flags |= DSDESC_HEIGHT;
       
  1156 
       
  1157     description.caps = DSCAPS_PRIMARY|DSCAPS_DOUBLE;
       
  1158     struct {
       
  1159         const char *name;
       
  1160         const DFBSurfaceCapabilities cap;
       
  1161     } const capabilities[] = {
       
  1162         { "static_alloc", DSCAPS_STATIC_ALLOC },
       
  1163         { "triplebuffer", DSCAPS_TRIPLE },
       
  1164         { "interlaced", DSCAPS_INTERLACED },
       
  1165         { "separated", DSCAPS_SEPARATED },
       
  1166 //        { "depthbuffer", DSCAPS_DEPTH }, // only makes sense with TextureTriangles which are not supported
       
  1167         { 0, DSCAPS_NONE }
       
  1168     };
       
  1169     for (int i=0; capabilities[i].name; ++i) {
       
  1170         if (displayArgs.contains(QString::fromLatin1(capabilities[i].name), Qt::CaseInsensitive))
       
  1171             description.caps |= capabilities[i].cap;
       
  1172     }
       
  1173 
       
  1174     if (forcePremultiplied) {
       
  1175         description.caps |= DSCAPS_PREMULTIPLIED;
       
  1176     }
       
  1177 
       
  1178     // We don't track the primary surface as it's released in disconnect
       
  1179     d_ptr->primarySurface = createDFBSurface(description, DontTrackSurface, &result);
       
  1180     if (!d_ptr->primarySurface) {
       
  1181         DirectFBError("QDirectFBScreen: error creating primary surface",
       
  1182                       result);
       
  1183         return false;
       
  1184     }
       
  1185 
       
  1186     surface = d_ptr->primarySurface;
       
  1187 #else
       
  1188     description.flags = DSDESC_WIDTH|DSDESC_HEIGHT;
       
  1189     description.width = description.height = 1;
       
  1190     surface = createDFBSurface(description, DontTrackSurface, &result);
       
  1191     if (!surface) {
       
  1192         DirectFBError("QDirectFBScreen: error creating surface", result);
       
  1193         return false;
       
  1194     }
       
  1195 #endif
       
  1196     // Work out what format we're going to use for surfaces with an alpha channel
       
  1197     QImage::Format pixelFormat = QDirectFBScreen::getImageFormat(surface);
       
  1198     d_ptr->alphaPixmapFormat = pixelFormat;
       
  1199 
       
  1200     switch (pixelFormat) {
       
  1201     case QImage::Format_RGB666:
       
  1202         d_ptr->alphaPixmapFormat = QImage::Format_ARGB6666_Premultiplied;
       
  1203         break;
       
  1204     case QImage::Format_RGB444:
       
  1205         d_ptr->alphaPixmapFormat = QImage::Format_ARGB4444_Premultiplied;
       
  1206         break;
       
  1207     case QImage::Format_RGB32:
       
  1208         pixelFormat = d_ptr->alphaPixmapFormat = QImage::Format_ARGB32_Premultiplied;
       
  1209         // ### Format_RGB32 doesn't work so well with Qt. Force ARGB32 for windows/pixmaps
       
  1210         break;
       
  1211     case QImage::Format_Indexed8:
       
  1212         qWarning("QDirectFBScreen::connect(). Qt/DirectFB does not work with the LUT8  pixelformat.");
       
  1213         return false;
       
  1214     case QImage::NImageFormats:
       
  1215     case QImage::Format_Invalid:
       
  1216     case QImage::Format_Mono:
       
  1217     case QImage::Format_MonoLSB:
       
  1218     case QImage::Format_RGB888:
       
  1219     case QImage::Format_RGB16:
       
  1220     case QImage::Format_RGB555:
       
  1221         d_ptr->alphaPixmapFormat = QImage::Format_ARGB32_Premultiplied;
       
  1222         break;
       
  1223     case QImage::Format_ARGB32:
       
  1224         if (forcePremultiplied)
       
  1225             d_ptr->alphaPixmapFormat = pixelFormat = QImage::Format_ARGB32_Premultiplied;
       
  1226     case QImage::Format_ARGB32_Premultiplied:
       
  1227     case QImage::Format_ARGB4444_Premultiplied:
       
  1228     case QImage::Format_ARGB8555_Premultiplied:
       
  1229     case QImage::Format_ARGB8565_Premultiplied:
       
  1230     case QImage::Format_ARGB6666_Premultiplied:
       
  1231         // works already
       
  1232         break;
       
  1233     }
       
  1234     setPixelFormat(pixelFormat);
       
  1235     QScreen::d = QDirectFBScreen::depth(pixelFormat);
       
  1236     data = 0;
       
  1237     lstep = 0;
       
  1238     size = 0;
       
  1239 
       
  1240     if (result != DFB_OK) {
       
  1241         DirectFBError("QDirectFBScreen::connect: "
       
  1242                       "Unable to get screen!", result);
       
  1243         return false;
       
  1244     }
       
  1245     const QString qws_size = QString::fromLatin1(qgetenv("QWS_SIZE"));
       
  1246     if (!qws_size.isEmpty()) {
       
  1247         QRegExp rx(QLatin1String("(\\d+)x(\\d+)"));
       
  1248         if (!rx.exactMatch(qws_size)) {
       
  1249             qWarning("QDirectFBScreen::connect: Can't parse QWS_SIZE=\"%s\"", qPrintable(qws_size));
       
  1250         } else {
       
  1251             int *ints[2] = { &w, &h };
       
  1252             for (int i=0; i<2; ++i) {
       
  1253                 *ints[i] = rx.cap(i + 1).toInt();
       
  1254                 if (*ints[i] <= 0) {
       
  1255                     qWarning("QDirectFBScreen::connect: %s is not a positive integer",
       
  1256                              qPrintable(rx.cap(i + 1)));
       
  1257                     w = h = 0;
       
  1258                     break;
       
  1259                 }
       
  1260             }
       
  1261         }
       
  1262     }
       
  1263 
       
  1264     setIntOption(displayArgs, QLatin1String("width"), &w);
       
  1265     setIntOption(displayArgs, QLatin1String("height"), &h);
       
  1266 
       
  1267 #ifndef QT_NO_DIRECTFB_LAYER
       
  1268     int layerId = DLID_PRIMARY;
       
  1269     setIntOption(displayArgs, QLatin1String("layerid"), &layerId);
       
  1270 
       
  1271     result = d_ptr->dfb->GetDisplayLayer(d_ptr->dfb, static_cast<DFBDisplayLayerID>(layerId),
       
  1272                                          &d_ptr->dfbLayer);
       
  1273     if (result != DFB_OK) {
       
  1274         DirectFBError("QDirectFBScreen::connect: "
       
  1275                       "Unable to get display layer!", result);
       
  1276         return false;
       
  1277     }
       
  1278     result = d_ptr->dfbLayer->GetScreen(d_ptr->dfbLayer, &d_ptr->dfbScreen);
       
  1279 #else
       
  1280     result = d_ptr->dfb->GetScreen(d_ptr->dfb, 0, &d_ptr->dfbScreen);
       
  1281 #endif
       
  1282 
       
  1283     if (w <= 0 || h <= 0) {
       
  1284 #ifdef QT_NO_DIRECTFB_WM
       
  1285         result = d_ptr->primarySurface->GetSize(d_ptr->primarySurface, &w, &h);
       
  1286 #elif (Q_DIRECTFB_VERSION >= 0x010000)
       
  1287         IDirectFBSurface *layerSurface;
       
  1288         if (d_ptr->dfbLayer->GetSurface(d_ptr->dfbLayer, &layerSurface) != DFB_OK) {
       
  1289             result = layerSurface->GetSize(layerSurface, &w, &h);
       
  1290             layerSurface->Release(layerSurface);
       
  1291         }
       
  1292         if (w <= 0 || h <= 0) {
       
  1293             result = d_ptr->dfbScreen->GetSize(d_ptr->dfbScreen, &w, &h);
       
  1294         }
       
  1295 #else
       
  1296         qWarning("QDirectFBScreen::connect: DirectFB versions prior to 1.0 do not offer a way\n"
       
  1297                  "query the size of the primary surface in windowed mode. You have to specify\n"
       
  1298                  "the size of the display using QWS_SIZE=[0-9]x[0-9] or\n"
       
  1299                  "QWS_DISPLAY=directfb:width=[0-9]:height=[0-9]");
       
  1300         return false;
       
  1301 #endif
       
  1302         if (result != DFB_OK) {
       
  1303             DirectFBError("QDirectFBScreen::connect: "
       
  1304                           "Unable to get screen size!", result);
       
  1305             return false;
       
  1306         }
       
  1307     }
       
  1308 
       
  1309 
       
  1310     dw = w;
       
  1311     dh = h;
       
  1312 
       
  1313     Q_ASSERT(dw != 0 && dh != 0);
       
  1314 
       
  1315     physWidth = physHeight = -1;
       
  1316     setIntOption(displayArgs, QLatin1String("mmWidth"), &physWidth);
       
  1317     setIntOption(displayArgs, QLatin1String("mmHeight"), &physHeight);
       
  1318     const int dpi = 72;
       
  1319     if (physWidth < 0)
       
  1320         physWidth = qRound(dw * 25.4 / dpi);
       
  1321     if (physHeight < 0)
       
  1322         physHeight = qRound(dh * 25.4 / dpi);
       
  1323 
       
  1324     setGraphicsSystem(d_ptr);
       
  1325 
       
  1326 #if (Q_DIRECTFB_VERSION >= 0x000923)
       
  1327     if (displayArgs.contains(QLatin1String("debug"), Qt::CaseInsensitive))
       
  1328         printDirectFBInfo(d_ptr->dfb, surface);
       
  1329 #endif
       
  1330 #ifdef QT_DIRECTFB_WM
       
  1331     surface->Release(surface);
       
  1332     QColor backgroundColor;
       
  1333 #else
       
  1334     QColor &backgroundColor = d_ptr->backgroundColor;
       
  1335 #endif
       
  1336 
       
  1337     QRegExp backgroundColorRegExp(QLatin1String("bgcolor=(.+)"));
       
  1338     backgroundColorRegExp.setCaseSensitivity(Qt::CaseInsensitive);
       
  1339     if (displayArgs.indexOf(backgroundColorRegExp) != -1) {
       
  1340         backgroundColor = colorFromName(backgroundColorRegExp.cap(1));
       
  1341     }
       
  1342 #ifdef QT_NO_DIRECTFB_WM
       
  1343     if (!backgroundColor.isValid())
       
  1344         backgroundColor = Qt::green;
       
  1345     d_ptr->primarySurface->Clear(d_ptr->primarySurface, backgroundColor.red(),
       
  1346                                  backgroundColor.green(), backgroundColor.blue(),
       
  1347                                  backgroundColor.alpha());
       
  1348     d_ptr->primarySurface->Flip(d_ptr->primarySurface, 0, d_ptr->flipFlags);
       
  1349 #else
       
  1350     if (backgroundColor.isValid()) {
       
  1351         DFBResult result = d_ptr->dfbLayer->SetCooperativeLevel(d_ptr->dfbLayer, DLSCL_ADMINISTRATIVE);
       
  1352         if (result != DFB_OK) {
       
  1353             DirectFBError("QDirectFBScreen::connect "
       
  1354                           "Unable to set cooperative level", result);
       
  1355         }
       
  1356         result = d_ptr->dfbLayer->SetBackgroundColor(d_ptr->dfbLayer, backgroundColor.red(), backgroundColor.green(),
       
  1357                                                      backgroundColor.blue(), backgroundColor.alpha());
       
  1358         if (result != DFB_OK) {
       
  1359             DirectFBError("QDirectFBScreenCursor::connect: "
       
  1360                           "Unable to set background color", result);
       
  1361         }
       
  1362 
       
  1363         result = d_ptr->dfbLayer->SetBackgroundMode(d_ptr->dfbLayer, DLBM_COLOR);
       
  1364         if (result != DFB_OK) {
       
  1365             DirectFBError("QDirectFBScreenCursor::connect: "
       
  1366                           "Unable to set background mode", result);
       
  1367         }
       
  1368 
       
  1369         result = d_ptr->dfbLayer->SetCooperativeLevel(d_ptr->dfbLayer, DLSCL_SHARED);
       
  1370         if (result != DFB_OK) {
       
  1371             DirectFBError("QDirectFBScreen::connect "
       
  1372                           "Unable to set cooperative level", result);
       
  1373         }
       
  1374 
       
  1375     }
       
  1376 #endif
       
  1377 
       
  1378     return true;
       
  1379 }
       
  1380 
       
  1381 void QDirectFBScreen::disconnect()
       
  1382 {
       
  1383 #if defined QT_DIRECTFB_IMAGEPROVIDER_KEEPALIVE
       
  1384     if (d_ptr->imageProvider)
       
  1385         d_ptr->imageProvider->Release(d_ptr->imageProvider);
       
  1386 #endif
       
  1387 #ifdef QT_NO_DIRECTFB_WM
       
  1388     d_ptr->primarySurface->Release(d_ptr->primarySurface);
       
  1389     d_ptr->primarySurface = 0;
       
  1390 #endif
       
  1391 
       
  1392     foreach (IDirectFBSurface *surf, d_ptr->allocatedSurfaces)
       
  1393         surf->Release(surf);
       
  1394     d_ptr->allocatedSurfaces.clear();
       
  1395 
       
  1396 #ifndef QT_NO_DIRECTFB_LAYER
       
  1397     d_ptr->dfbLayer->Release(d_ptr->dfbLayer);
       
  1398     d_ptr->dfbLayer = 0;
       
  1399 #endif
       
  1400 
       
  1401     d_ptr->dfbScreen->Release(d_ptr->dfbScreen);
       
  1402     d_ptr->dfbScreen = 0;
       
  1403 
       
  1404     d_ptr->dfb->Release(d_ptr->dfb);
       
  1405     d_ptr->dfb = 0;
       
  1406 }
       
  1407 
       
  1408 bool QDirectFBScreen::initDevice()
       
  1409 {
       
  1410 #ifndef QT_NO_DIRECTFB_MOUSE
       
  1411     if (qgetenv("QWS_MOUSE_PROTO").isEmpty()) {
       
  1412         QWSServer::instance()->setDefaultMouse("None");
       
  1413         d_ptr->mouse = new QDirectFBMouseHandler;
       
  1414     }
       
  1415 #endif
       
  1416 #ifndef QT_NO_DIRECTFB_KEYBOARD
       
  1417     if (qgetenv("QWS_KEYBOARD").isEmpty()) {
       
  1418         QWSServer::instance()->setDefaultKeyboard("None");
       
  1419         d_ptr->keyboard = new QDirectFBKeyboardHandler(QString());
       
  1420     }
       
  1421 #endif
       
  1422 
       
  1423 #ifdef QT_DIRECTFB_CURSOR
       
  1424     qt_screencursor = new QDirectFBScreenCursor;
       
  1425 #elif !defined QT_NO_QWS_CURSOR
       
  1426     QScreenCursor::initSoftwareCursor();
       
  1427 #endif
       
  1428     return true;
       
  1429 }
       
  1430 
       
  1431 void QDirectFBScreen::shutdownDevice()
       
  1432 {
       
  1433 #ifndef QT_NO_DIRECTFB_MOUSE
       
  1434     delete d_ptr->mouse;
       
  1435     d_ptr->mouse = 0;
       
  1436 #endif
       
  1437 #ifndef QT_NO_DIRECTFB_KEYBOARD
       
  1438     delete d_ptr->keyboard;
       
  1439     d_ptr->keyboard = 0;
       
  1440 #endif
       
  1441 
       
  1442 #ifndef QT_NO_QWS_CURSOR
       
  1443     delete qt_screencursor;
       
  1444     qt_screencursor = 0;
       
  1445 #endif
       
  1446 }
       
  1447 
       
  1448 void QDirectFBScreen::setMode(int width, int height, int depth)
       
  1449 {
       
  1450     d_ptr->dfb->SetVideoMode(d_ptr->dfb, width, height, depth);
       
  1451 }
       
  1452 
       
  1453 void QDirectFBScreen::blank(bool on)
       
  1454 {
       
  1455     d_ptr->dfbScreen->SetPowerMode(d_ptr->dfbScreen,
       
  1456                                    (on ? DSPM_ON : DSPM_SUSPEND));
       
  1457 }
       
  1458 
       
  1459 QWSWindowSurface *QDirectFBScreen::createSurface(QWidget *widget) const
       
  1460 {
       
  1461 #ifdef QT_NO_DIRECTFB_WM
       
  1462     if (QApplication::type() == QApplication::GuiServer) {
       
  1463         return new QDirectFBWindowSurface(d_ptr->flipFlags, const_cast<QDirectFBScreen*>(this), widget);
       
  1464     } else {
       
  1465         return QScreen::createSurface(widget);
       
  1466     }
       
  1467 #else
       
  1468     return new QDirectFBWindowSurface(d_ptr->flipFlags, const_cast<QDirectFBScreen*>(this), widget);
       
  1469 #endif
       
  1470 }
       
  1471 
       
  1472 QWSWindowSurface *QDirectFBScreen::createSurface(const QString &key) const
       
  1473 {
       
  1474     if (key == QLatin1String("directfb")) {
       
  1475         return new QDirectFBWindowSurface(d_ptr->flipFlags, const_cast<QDirectFBScreen*>(this));
       
  1476     }
       
  1477     return QScreen::createSurface(key);
       
  1478 }
       
  1479 
       
  1480 #if defined QT_NO_DIRECTFB_WM
       
  1481 struct PaintCommand {
       
  1482     PaintCommand() : dfbSurface(0), windowOpacity(255), blittingFlags(DSBLIT_NOFX) {}
       
  1483     IDirectFBSurface *dfbSurface;
       
  1484     QImage image;
       
  1485     QPoint windowPosition;
       
  1486     QRegion source;
       
  1487     quint8 windowOpacity;
       
  1488     DFBSurfaceBlittingFlags blittingFlags;
       
  1489 };
       
  1490 
       
  1491 static inline void initParameters(DFBRectangle &source, const QRect &sourceGlobal, const QPoint &pos)
       
  1492 {
       
  1493     source.x = sourceGlobal.x() - pos.x();
       
  1494     source.y = sourceGlobal.y() - pos.y();
       
  1495     source.w = sourceGlobal.width();
       
  1496     source.h = sourceGlobal.height();
       
  1497 }
       
  1498 #endif
       
  1499 
       
  1500 void QDirectFBScreen::exposeRegion(QRegion r, int)
       
  1501 {
       
  1502     Q_UNUSED(r);
       
  1503 #if defined QT_NO_DIRECTFB_WM
       
  1504 
       
  1505     r &= region();
       
  1506     if (r.isEmpty()) {
       
  1507         return;
       
  1508     }
       
  1509     r = r.boundingRect();
       
  1510 
       
  1511     IDirectFBSurface *primary = d_ptr->primarySurface;
       
  1512     const QList<QWSWindow*> windows = QWSServer::instance()->clientWindows();
       
  1513     QVarLengthArray<PaintCommand, 4> commands(windows.size());
       
  1514     QRegion region = r;
       
  1515     int idx = 0;
       
  1516     for (int i=0; i<windows.size(); ++i) {
       
  1517         QWSWindowSurface *surface = windows.at(i)->windowSurface();
       
  1518         if (!surface)
       
  1519             continue;
       
  1520 
       
  1521         const QRect windowGeometry = surface->geometry();
       
  1522         const QRegion intersection = region & windowGeometry;
       
  1523         if (intersection.isEmpty()) {
       
  1524             continue;
       
  1525         }
       
  1526 
       
  1527         PaintCommand &cmd = commands[idx];
       
  1528 
       
  1529         if (surface->key() == QLatin1String("directfb")) {
       
  1530             const QDirectFBWindowSurface *ws = static_cast<QDirectFBWindowSurface*>(surface);
       
  1531             cmd.dfbSurface = ws->directFBSurface();
       
  1532 
       
  1533             if (!cmd.dfbSurface) {
       
  1534                 continue;
       
  1535             }
       
  1536         } else {
       
  1537             cmd.image = surface->image();
       
  1538             if (cmd.image.isNull()) {
       
  1539                 continue;
       
  1540             }
       
  1541         }
       
  1542         ++idx;
       
  1543 
       
  1544         cmd.windowPosition = windowGeometry.topLeft();
       
  1545         cmd.source = intersection;
       
  1546         if (windows.at(i)->isOpaque()) {
       
  1547             region -= intersection;
       
  1548             if (region.isEmpty())
       
  1549                 break;
       
  1550         } else {
       
  1551             cmd.windowOpacity = windows.at(i)->opacity();
       
  1552             cmd.blittingFlags = cmd.windowOpacity == 255
       
  1553                                 ? DSBLIT_BLEND_ALPHACHANNEL
       
  1554                                 : (DSBLIT_BLEND_ALPHACHANNEL|DSBLIT_BLEND_COLORALPHA);
       
  1555         }
       
  1556     }
       
  1557     if (!region.isEmpty()) {
       
  1558         solidFill(d_ptr->backgroundColor, region);
       
  1559     }
       
  1560 
       
  1561     while (idx > 0) {
       
  1562         const PaintCommand &cmd = commands[--idx];
       
  1563         Q_ASSERT(cmd.dfbSurface || !cmd.image.isNull());
       
  1564         IDirectFBSurface *surface;
       
  1565         if (cmd.dfbSurface) {
       
  1566             surface = cmd.dfbSurface;
       
  1567         } else {
       
  1568             Q_ASSERT(!cmd.image.isNull());
       
  1569             DFBResult result;
       
  1570             surface = createDFBSurface(cmd.image, cmd.image.format(), DontTrackSurface, &result);
       
  1571             Q_ASSERT((result != DFB_OK) == !surface);
       
  1572             if (result != DFB_OK) {
       
  1573                 DirectFBError("QDirectFBScreen::exposeRegion: Can't create surface from image", result);
       
  1574                 continue;
       
  1575             }
       
  1576         }
       
  1577 
       
  1578         primary->SetBlittingFlags(primary, cmd.blittingFlags);
       
  1579         if (cmd.blittingFlags & DSBLIT_BLEND_COLORALPHA) {
       
  1580             primary->SetColor(primary, 0xff, 0xff, 0xff, cmd.windowOpacity);
       
  1581         }
       
  1582         const QRegion &region = cmd.source;
       
  1583         const int rectCount = region.rectCount();
       
  1584         DFBRectangle source;
       
  1585         if (rectCount == 1) {
       
  1586             ::initParameters(source, region.boundingRect(), cmd.windowPosition);
       
  1587             primary->Blit(primary, surface, &source, cmd.windowPosition.x() + source.x, cmd.windowPosition.y() + source.y);
       
  1588         } else {
       
  1589             const QVector<QRect> rects = region.rects();
       
  1590             for (int i=0; i<rectCount; ++i) {
       
  1591                 ::initParameters(source, rects.at(i), cmd.windowPosition);
       
  1592                 primary->Blit(primary, surface, &source, cmd.windowPosition.x() + source.x, cmd.windowPosition.y() + source.y);
       
  1593             }
       
  1594         }
       
  1595         if (surface != cmd.dfbSurface) {
       
  1596             surface->Release(surface);
       
  1597         }
       
  1598     }
       
  1599 
       
  1600     primary->SetColor(primary, 0xff, 0xff, 0xff, 0xff);
       
  1601 
       
  1602 #if defined QT_NO_DIRECTFB_CURSOR and !defined QT_NO_QWS_CURSOR
       
  1603     if (QScreenCursor *cursor = QScreenCursor::instance()) {
       
  1604         const QRect cursorRectangle = cursor->boundingRect();
       
  1605         if (cursor->isVisible() && !cursor->isAccelerated() && r.intersects(cursorRectangle)) {
       
  1606             const QImage image = cursor->image();
       
  1607             if (image.cacheKey() != d_ptr->cursorImageKey) {
       
  1608                 if (d_ptr->cursorSurface) {
       
  1609                     releaseDFBSurface(d_ptr->cursorSurface);
       
  1610                 }
       
  1611                 d_ptr->cursorSurface = createDFBSurface(image, image.format(), QDirectFBScreen::TrackSurface);
       
  1612                 d_ptr->cursorImageKey = image.cacheKey();
       
  1613             }
       
  1614 
       
  1615             Q_ASSERT(d_ptr->cursorSurface);
       
  1616             primary->SetBlittingFlags(primary, DSBLIT_BLEND_ALPHACHANNEL);
       
  1617             primary->Blit(primary, d_ptr->cursorSurface, 0, cursorRectangle.x(), cursorRectangle.y());
       
  1618         }
       
  1619     }
       
  1620 #endif
       
  1621     flipSurface(primary, d_ptr->flipFlags, r, QPoint());
       
  1622     primary->SetBlittingFlags(primary, DSBLIT_NOFX);
       
  1623 #endif
       
  1624 }
       
  1625 
       
  1626 void QDirectFBScreen::solidFill(const QColor &color, const QRegion &region)
       
  1627 {
       
  1628 #ifdef QT_DIRECTFB_WM
       
  1629     Q_UNUSED(color);
       
  1630     Q_UNUSED(region);
       
  1631 #else
       
  1632     if (region.isEmpty())
       
  1633         return;
       
  1634 
       
  1635     d_ptr->primarySurface->SetColor(d_ptr->primarySurface,
       
  1636                                     color.red(), color.green(), color.blue(),
       
  1637                                     color.alpha());
       
  1638     const int n = region.rectCount();
       
  1639     if (n == 1) {
       
  1640         const QRect r = region.boundingRect();
       
  1641         d_ptr->primarySurface->FillRectangle(d_ptr->primarySurface, r.x(), r.y(), r.width(), r.height());
       
  1642     } else {
       
  1643         const QVector<QRect> rects = region.rects();
       
  1644         QVarLengthArray<DFBRectangle, 32> rectArray(n);
       
  1645         for (int i=0; i<n; ++i) {
       
  1646             const QRect &r = rects.at(i);
       
  1647             rectArray[i].x = r.x();
       
  1648             rectArray[i].y = r.y();
       
  1649             rectArray[i].w = r.width();
       
  1650             rectArray[i].h = r.height();
       
  1651         }
       
  1652         d_ptr->primarySurface->FillRectangles(d_ptr->primarySurface, rectArray.constData(), n);
       
  1653     }
       
  1654 #endif
       
  1655 }
       
  1656 
       
  1657 QImage::Format QDirectFBScreen::alphaPixmapFormat() const
       
  1658 {
       
  1659     return d_ptr->alphaPixmapFormat;
       
  1660 }
       
  1661 
       
  1662 bool QDirectFBScreen::initSurfaceDescriptionPixelFormat(DFBSurfaceDescription *description,
       
  1663                                                         QImage::Format format)
       
  1664 {
       
  1665     const DFBSurfacePixelFormat pixelformat = QDirectFBScreen::getSurfacePixelFormat(format);
       
  1666     if (pixelformat == DSPF_UNKNOWN)
       
  1667         return false;
       
  1668     description->flags |= DSDESC_PIXELFORMAT;
       
  1669     description->pixelformat = pixelformat;
       
  1670     if (QDirectFBScreen::isPremultiplied(format)) {
       
  1671         if (!(description->flags & DSDESC_CAPS)) {
       
  1672             description->caps = DSCAPS_PREMULTIPLIED;
       
  1673             description->flags |= DSDESC_CAPS;
       
  1674         } else {
       
  1675             description->caps |= DSCAPS_PREMULTIPLIED;
       
  1676         }
       
  1677     }
       
  1678     return true;
       
  1679 }
       
  1680 
       
  1681 uchar *QDirectFBScreen::lockSurface(IDirectFBSurface *surface, DFBSurfaceLockFlags flags, int *bpl)
       
  1682 {
       
  1683     void *mem = 0;
       
  1684     const DFBResult result = surface->Lock(surface, flags, &mem, bpl);
       
  1685     if (result != DFB_OK) {
       
  1686         DirectFBError("QDirectFBScreen::lockSurface()", result);
       
  1687     }
       
  1688 
       
  1689     return reinterpret_cast<uchar*>(mem);
       
  1690 }
       
  1691 
       
  1692 static inline bool isFullUpdate(IDirectFBSurface *surface, const QRegion &region, const QPoint &offset)
       
  1693 {
       
  1694     if (offset == QPoint(0, 0) && region.rectCount() == 1) {
       
  1695 	QSize size;
       
  1696 	surface->GetSize(surface, &size.rwidth(), &size.rheight());
       
  1697 	if (region.boundingRect().size() == size)
       
  1698 	    return true;
       
  1699     }
       
  1700     return false;
       
  1701 }
       
  1702 
       
  1703 void QDirectFBScreen::flipSurface(IDirectFBSurface *surface, DFBSurfaceFlipFlags flipFlags,
       
  1704                                   const QRegion &region, const QPoint &offset)
       
  1705 {
       
  1706     if (d_ptr->directFBFlags & NoPartialFlip
       
  1707         || (!(flipFlags & DSFLIP_BLIT) && QT_PREPEND_NAMESPACE(isFullUpdate(surface, region, offset)))) {
       
  1708         surface->Flip(surface, 0, flipFlags);
       
  1709     } else {
       
  1710         if (!(d_ptr->directFBFlags & BoundingRectFlip) && region.rectCount() > 1) {
       
  1711             const QVector<QRect> rects = region.rects();
       
  1712             const DFBSurfaceFlipFlags nonWaitFlags = flipFlags & ~DSFLIP_WAIT;
       
  1713             for (int i=0; i<rects.size(); ++i) {
       
  1714                 const QRect &r = rects.at(i);
       
  1715                 const DFBRegion dfbReg = { r.x() + offset.x(), r.y() + offset.y(),
       
  1716                                            r.right() + offset.x(),
       
  1717                                            r.bottom() + offset.y() };
       
  1718                 surface->Flip(surface, &dfbReg, i + 1 < rects.size() ? nonWaitFlags : flipFlags);
       
  1719             }
       
  1720         } else {
       
  1721             const QRect r = region.boundingRect();
       
  1722             const DFBRegion dfbReg = { r.x() + offset.x(), r.y() + offset.y(),
       
  1723                                        r.right() + offset.x(),
       
  1724                                        r.bottom() + offset.y() };
       
  1725             surface->Flip(surface, &dfbReg, flipFlags);
       
  1726         }
       
  1727     }
       
  1728 }
       
  1729 
       
  1730 #if defined QT_DIRECTFB_IMAGEPROVIDER_KEEPALIVE
       
  1731 void QDirectFBScreen::setDirectFBImageProvider(IDirectFBImageProvider *provider)
       
  1732 {
       
  1733     Q_ASSERT(provider);
       
  1734     if (d_ptr->imageProvider)
       
  1735         d_ptr->imageProvider->Release(d_ptr->imageProvider);
       
  1736     d_ptr->imageProvider = provider;
       
  1737 }
       
  1738 #endif
       
  1739 
       
  1740 void QDirectFBScreen::waitIdle()
       
  1741 {
       
  1742     d_ptr->dfb->WaitIdle(d_ptr->dfb);
       
  1743 }
       
  1744 
       
  1745 #ifdef QT_DIRECTFB_WM
       
  1746 IDirectFBWindow *QDirectFBScreen::windowForWidget(const QWidget *widget) const
       
  1747 {
       
  1748     if (widget) {
       
  1749         const QWSWindowSurface *surface = static_cast<const QWSWindowSurface*>(widget->windowSurface());
       
  1750         if (surface && surface->key() == QLatin1String("directfb")) {
       
  1751             return static_cast<const QDirectFBWindowSurface*>(surface)->directFBWindow();
       
  1752         }
       
  1753     }
       
  1754     return 0;
       
  1755 }
       
  1756 #endif
       
  1757 
       
  1758 IDirectFBSurface * QDirectFBScreen::surfaceForWidget(const QWidget *widget, QRect *rect) const
       
  1759 {
       
  1760     Q_ASSERT(widget);
       
  1761     if (!widget->isVisible() || widget->size().isNull())
       
  1762         return 0;
       
  1763 
       
  1764     const QWSWindowSurface *surface = static_cast<const QWSWindowSurface*>(widget->windowSurface());
       
  1765     if (surface && surface->key() == QLatin1String("directfb")) {
       
  1766         return static_cast<const QDirectFBWindowSurface*>(surface)->surfaceForWidget(widget, rect);
       
  1767     }
       
  1768     return 0;
       
  1769 }
       
  1770 
       
  1771 #ifdef QT_DIRECTFB_SUBSURFACE
       
  1772 IDirectFBSurface *QDirectFBScreen::subSurfaceForWidget(const QWidget *widget, const QRect &area) const
       
  1773 {
       
  1774     Q_ASSERT(widget);
       
  1775     QRect rect;
       
  1776     IDirectFBSurface *surface = surfaceForWidget(widget, &rect);
       
  1777     IDirectFBSurface *subSurface = 0;
       
  1778     if (surface) {
       
  1779         if (!area.isNull())
       
  1780             rect &= area.translated(widget->mapTo(widget->window(), QPoint(0, 0)));
       
  1781         if (!rect.isNull()) {
       
  1782             const DFBRectangle subRect = { rect.x(), rect.y(), rect.width(), rect.height() };
       
  1783             const DFBResult result = surface->GetSubSurface(surface, &subRect, &subSurface);
       
  1784             if (result != DFB_OK) {
       
  1785                 DirectFBError("QDirectFBScreen::subSurface(): Can't get sub surface", result);
       
  1786             }
       
  1787         }
       
  1788     }
       
  1789     return subSurface;
       
  1790 }
       
  1791 #endif
       
  1792 
       
  1793 #ifndef QT_DIRECTFB_PLUGIN
       
  1794 Q_GUI_EXPORT IDirectFBSurface *qt_directfb_surface_for_widget(const QWidget *widget, QRect *rect)
       
  1795 {
       
  1796     return QDirectFBScreen::instance() ? QDirectFBScreen::instance()->surfaceForWidget(widget, rect) : 0;
       
  1797 }
       
  1798 #ifdef QT_DIRECTFB_SUBSURFACE
       
  1799 Q_GUI_EXPORT IDirectFBSurface *qt_directfb_subsurface_for_widget(const QWidget *widget, const QRect &area)
       
  1800 {
       
  1801     return QDirectFBScreen::instance() ? QDirectFBScreen::instance()->subSurfaceForWidget(widget, area) : 0;
       
  1802 }
       
  1803 #endif
       
  1804 #ifdef QT_DIRECTFB_WM
       
  1805 Q_GUI_EXPORT IDirectFBWindow *qt_directfb_window_for_widget(const QWidget *widget)
       
  1806 {
       
  1807     return QDirectFBScreen::instance() ? QDirectFBScreen::instance()->windowForWidget(widget) : 0;
       
  1808 }
       
  1809 
       
  1810 #endif
       
  1811 #endif
       
  1812 
       
  1813 QT_END_NAMESPACE
       
  1814 
       
  1815 #include "qdirectfbscreen.moc"
       
  1816 #endif // QT_NO_QWS_DIRECTFB
       
  1817