src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp
changeset 7 f7bc934e204c
parent 3 41300fa6a67c
equal deleted inserted replaced
3:41300fa6a67c 7:f7bc934e204c
     1 /****************************************************************************
     1 /****************************************************************************
     2 **
     2 **
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     4 ** All rights reserved.
     4 ** All rights reserved.
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
     6 **
     6 **
     7 ** This file is part of the plugins of the Qt Toolkit.
     7 ** This file is part of the plugins of the Qt Toolkit.
     8 **
     8 **
    66         Matrix_RectsUnsupported = (QTransform::TxRotate|QTransform::TxShear|QTransform::TxProject),
    66         Matrix_RectsUnsupported = (QTransform::TxRotate|QTransform::TxShear|QTransform::TxProject),
    67         Matrix_BlitsUnsupported = (Matrix_NegativeScale|Matrix_RectsUnsupported)
    67         Matrix_BlitsUnsupported = (Matrix_NegativeScale|Matrix_RectsUnsupported)
    68     };
    68     };
    69 
    69 
    70     enum CompositionModeStatus {
    70     enum CompositionModeStatus {
    71         PorterDuff_None = 0x00,
    71         PorterDuff_None = 0x0,
    72         PorterDuff_SupportedBlits = 0x01,
    72         PorterDuff_Supported = 0x1,
    73         PorterDuff_SupportedPrimitives = 0x02,
    73         PorterDuff_PremultiplyColors = 0x2,
    74         PorterDuff_SupportedOpaquePrimitives = 0x04,
    74         PorterDuff_AlwaysBlend = 0x4
    75         PorterDuff_Dirty = 0x10
       
    76     };
    75     };
    77 
    76 
    78     enum ClipType {
    77     enum ClipType {
    79         ClipUnset,
    78         ClipUnset,
    80         NoClip,
    79         NoClip,
    95 
    94 
    96     inline void lock();
    95     inline void lock();
    97     inline void unlock();
    96     inline void unlock();
    98     static inline void unlock(QDirectFBPaintDevice *device);
    97     static inline void unlock(QDirectFBPaintDevice *device);
    99 
    98 
   100     inline bool testCompositionMode(const QPen *pen, const QBrush *brush, const QColor *color = 0) const;
       
   101     inline bool isSimpleBrush(const QBrush &brush) const;
    99     inline bool isSimpleBrush(const QBrush &brush) const;
   102 
   100 
   103     void drawTiledPixmap(const QRectF &dest, const QPixmap &pixmap, const QPointF &pos);
   101     void drawTiledPixmap(const QRectF &dest, const QPixmap &pixmap, const QPointF &pos);
   104     void blit(const QRectF &dest, IDirectFBSurface *surface, const QRectF &src);
   102     void blit(const QRectF &dest, IDirectFBSurface *surface, const QRectF &src);
       
   103 
       
   104     inline bool supportsStretchBlit() const;
   105 
   105 
   106     inline void updateClip();
   106     inline void updateClip();
   107     virtual void systemStateChanged();
   107     virtual void systemStateChanged();
   108 
   108 
   109     static IDirectFBSurface *getSurface(const QImage &img, bool *release);
   109     static IDirectFBSurface *getSurface(const QImage &img, bool *release);
   126     quint8 opacity;
   126     quint8 opacity;
   127 
   127 
   128     ClipType clipType;
   128     ClipType clipType;
   129     QDirectFBPaintDevice *dfbDevice;
   129     QDirectFBPaintDevice *dfbDevice;
   130     uint compositionModeStatus;
   130     uint compositionModeStatus;
       
   131     bool isPremultiplied;
   131 
   132 
   132     bool inClip;
   133     bool inClip;
   133     QRect currentClip;
   134     QRect currentClip;
   134 
   135 
   135     QDirectFBPaintEngine *q;
   136     QDirectFBPaintEngine *q;
   164     }
   165     }
   165 };
   166 };
   166 static QCache<qint64, CachedImage> imageCache(4*1024*1024); // 4 MB
   167 static QCache<qint64, CachedImage> imageCache(4*1024*1024); // 4 MB
   167 #endif
   168 #endif
   168 
   169 
   169 #if defined QT_DIRECTFB_WARN_ON_RASTERFALLBACKS || defined QT_DIRECTFB_DISABLE_RASTERFALLBACKS
   170 #if defined QT_DIRECTFB_WARN_ON_RASTERFALLBACKS || defined QT_DIRECTFB_DISABLE_RASTERFALLBACKS || defined QT_DEBUG
   170 #define VOID_ARG() static_cast<bool>(false)
   171 #define VOID_ARG() static_cast<bool>(false)
   171 enum PaintOperation {
   172 enum PaintOperation {
   172     DRAW_RECTS = 0x0001, DRAW_LINES = 0x0002, DRAW_IMAGE = 0x0004,
   173     DRAW_RECTS = 0x0001, DRAW_LINES = 0x0002, DRAW_IMAGE = 0x0004,
   173     DRAW_PIXMAP = 0x0008, DRAW_TILED_PIXMAP = 0x0010, STROKE_PATH = 0x0020,
   174     DRAW_PIXMAP = 0x0008, DRAW_TILED_PIXMAP = 0x0010, STROKE_PATH = 0x0020,
   174     DRAW_PATH = 0x0040, DRAW_POINTS = 0x0080, DRAW_ELLIPSE = 0x0100,
   175     DRAW_PATH = 0x0040, DRAW_POINTS = 0x0080, DRAW_ELLIPSE = 0x0100,
   175     DRAW_POLYGON = 0x0200, DRAW_TEXT = 0x0400, FILL_PATH = 0x0800,
   176     DRAW_POLYGON = 0x0200, DRAW_TEXT = 0x0400, FILL_PATH = 0x0800,
   176     FILL_RECT = 0x1000, DRAW_COLORSPANS = 0x2000, DRAW_ROUNDED_RECT = 0x4000,
   177     FILL_RECT = 0x1000, DRAW_COLORSPANS = 0x2000, DRAW_ROUNDED_RECT = 0x4000,
   177     ALL = 0xffff
   178     ALL = 0xffff
   178 };
   179 };
   179 #endif
   180 
   180 
   181 #ifdef QT_DEBUG
       
   182 static void initRasterFallbacksMasks(int *warningMask, int *disableMask)
       
   183 {
       
   184     struct {
       
   185         const char *name;
       
   186         PaintOperation operation;
       
   187     } const operations[] = {
       
   188         { "DRAW_RECTS", DRAW_RECTS },
       
   189         { "DRAW_LINES", DRAW_LINES },
       
   190         { "DRAW_IMAGE", DRAW_IMAGE },
       
   191         { "DRAW_PIXMAP", DRAW_PIXMAP },
       
   192         { "DRAW_TILED_PIXMAP", DRAW_TILED_PIXMAP },
       
   193         { "STROKE_PATH", STROKE_PATH },
       
   194         { "DRAW_PATH", DRAW_PATH },
       
   195         { "DRAW_POINTS", DRAW_POINTS },
       
   196         { "DRAW_ELLIPSE", DRAW_ELLIPSE },
       
   197         { "DRAW_POLYGON", DRAW_POLYGON },
       
   198         { "DRAW_TEXT", DRAW_TEXT },
       
   199         { "FILL_PATH", FILL_PATH },
       
   200         { "FILL_RECT", FILL_RECT },
       
   201         { "DRAW_COLORSPANS", DRAW_COLORSPANS },
       
   202         { "DRAW_ROUNDED_RECT", DRAW_ROUNDED_RECT },
       
   203         { "ALL", ALL },
       
   204         { 0, ALL }
       
   205     };
       
   206 
       
   207     QStringList warning = QString::fromLatin1(qgetenv("QT_DIRECTFB_WARN_ON_RASTERFALLBACKS")).toUpper().split(QLatin1Char('|'),
       
   208                                                                                                               QString::SkipEmptyParts);
       
   209     QStringList disable = QString::fromLatin1(qgetenv("QT_DIRECTFB_DISABLE_RASTERFALLBACKS")).toUpper().split(QLatin1Char('|'),
       
   210                                                                                                               QString::SkipEmptyParts);
       
   211     *warningMask = 0;
       
   212     *disableMask = 0;
       
   213     if (!warning.isEmpty() || !disable.isEmpty()) {
       
   214         for (int i=0; operations[i].name; ++i) {
       
   215             const QString name = QString::fromLatin1(operations[i].name);
       
   216             int idx = warning.indexOf(name);
       
   217             if (idx != -1) {
       
   218                 *warningMask |= operations[i].operation;
       
   219                 warning.erase(warning.begin() + idx);
       
   220             }
       
   221             idx = disable.indexOf(name);
       
   222             if (idx != -1) {
       
   223                 *disableMask |= operations[i].operation;
       
   224                 disable.erase(disable.begin() + idx);
       
   225             }
       
   226         }
       
   227     }
       
   228     if (!warning.isEmpty()) {
       
   229         qWarning("QDirectFBPaintEngine QT_DIRECTFB_WARN_ON_RASTERFALLBACKS Unknown operation(s): %s",
       
   230                  qPrintable(warning.join(QLatin1String("|"))));
       
   231     }
       
   232     if (!disable.isEmpty()) {
       
   233         qWarning("QDirectFBPaintEngine QT_DIRECTFB_DISABLE_RASTERFALLBACKS Unknown operation(s): %s",
       
   234                  qPrintable(disable.join(QLatin1String("|"))));
       
   235     }
       
   236 
       
   237 }
       
   238 #endif
       
   239 
       
   240 static inline int rasterFallbacksMask(bool warn)
       
   241 {
   181 #ifdef QT_DIRECTFB_WARN_ON_RASTERFALLBACKS
   242 #ifdef QT_DIRECTFB_WARN_ON_RASTERFALLBACKS
       
   243     if (warn)
       
   244         return QT_DIRECTFB_WARN_ON_RASTERFALLBACKS;
       
   245 #endif
       
   246 #ifdef QT_DIRECTFB_DISABLE_RASTERFALLBACKS
       
   247     if (!warn)
       
   248         return QT_DIRECTFB_DISABLE_RASTERFALLBACKS;
       
   249 #endif
       
   250 #ifndef QT_DEBUG
       
   251     return 0;
       
   252 #else
       
   253     static int warnMask = -1;
       
   254     static int disableMask = -1;
       
   255     if (warnMask == -1)
       
   256         initRasterFallbacksMasks(&warnMask, &disableMask);
       
   257     return warn ? warnMask : disableMask;
       
   258 #endif
       
   259 }
       
   260 #endif
       
   261 
       
   262 #if defined QT_DIRECTFB_WARN_ON_RASTERFALLBACKS || defined QT_DEBUG
   182 template <typename device, typename T1, typename T2, typename T3>
   263 template <typename device, typename T1, typename T2, typename T3>
   183 static void rasterFallbackWarn(const char *msg, const char *func, const device *dev,
   264 static void rasterFallbackWarn(const char *msg, const char *func, const device *dev,
   184                                uint transformationType, bool simplePen,
   265                                uint transformationType, bool simplePen,
   185                                uint clipType, uint compositionModeStatus,
   266                                uint clipType, uint compositionModeStatus,
   186                                const char *nameOne, const T1 &one,
   267                                const char *nameOne, const T1 &one,
   187                                const char *nameTwo, const T2 &two,
   268                                const char *nameTwo, const T2 &two,
   188                                const char *nameThree, const T3 &three);
   269                                const char *nameThree, const T3 &three);
   189 #endif
   270 #endif
   190 
   271 
   191 #if defined QT_DIRECTFB_WARN_ON_RASTERFALLBACKS && defined QT_DIRECTFB_DISABLE_RASTERFALLBACKS
   272 #if defined QT_DEBUG || (defined QT_DIRECTFB_WARN_ON_RASTERFALLBACKS && defined QT_DIRECTFB_DISABLE_RASTERFALLBACKS)
   192 #define RASTERFALLBACK(op, one, two, three)                             \
   273 #define RASTERFALLBACK(op, one, two, three)                             \
   193     if (op & (QT_DIRECTFB_WARN_ON_RASTERFALLBACKS))                     \
   274     {                                                                   \
   194         rasterFallbackWarn("Disabled raster engine operation",          \
   275         const bool disable = op & rasterFallbacksMask(false);           \
   195                            __FUNCTION__, state()->painter->device(),    \
   276         if (op & rasterFallbacksMask(true))                             \
   196                            d_func()->transformationType,                \
   277             rasterFallbackWarn(disable                                  \
   197                            d_func()->simplePen,                         \
   278                                ? "Disabled raster engine operation"     \
   198                            d_func()->clipType,                          \
   279                                : "Falling back to raster engine for",   \
   199                            d_func()->compositionModeStatus,             \
   280                                __FUNCTION__,                            \
   200                            #one, one, #two, two, #three, three);        \
   281                                state()->painter->device(),              \
   201     if (op & (QT_DIRECTFB_DISABLE_RASTERFALLBACKS))                     \
   282                                d_func()->transformationType,            \
   202         return;
   283                                d_func()->simplePen,                     \
       
   284                                d_func()->clipType,                      \
       
   285                                d_func()->compositionModeStatus,         \
       
   286                                #one, one, #two, two, #three, three);    \
       
   287         if (disable)                                                    \
       
   288             return;                                                     \
       
   289     }
   203 #elif defined QT_DIRECTFB_DISABLE_RASTERFALLBACKS
   290 #elif defined QT_DIRECTFB_DISABLE_RASTERFALLBACKS
   204 #define RASTERFALLBACK(op, one, two, three)             \
   291 #define RASTERFALLBACK(op, one, two, three)                             \
   205     if (op & (QT_DIRECTFB_DISABLE_RASTERFALLBACKS))     \
   292     if (op & rasterFallbacksMask(false))                                \
   206         return;
   293         return;
   207 #elif defined QT_DIRECTFB_WARN_ON_RASTERFALLBACKS
   294 #elif defined QT_DIRECTFB_WARN_ON_RASTERFALLBACKS
   208 #define RASTERFALLBACK(op, one, two, three)                             \
   295 #define RASTERFALLBACK(op, one, two, three)                             \
   209     if (op & (QT_DIRECTFB_WARN_ON_RASTERFALLBACKS))                     \
   296     if (op & rasterFallbacksMask(true))                                 \
   210         rasterFallbackWarn("Falling back to raster engine for",         \
   297         rasterFallbackWarn("Falling back to raster engine for",         \
   211                            __FUNCTION__, state()->painter->device(),    \
   298                            __FUNCTION__, state()->painter->device(),    \
   212                            d_func()->transformationType,                \
   299                            d_func()->transformationType,                \
   213                            d_func()->simplePen,                         \
   300                            d_func()->simplePen,                         \
   214                            d_func()->clipType,                          \
   301                            d_func()->clipType,                          \
   283 
   370 
   284     if (!d->surface) {
   371     if (!d->surface) {
   285         qFatal("QDirectFBPaintEngine used on an invalid device: 0x%x",
   372         qFatal("QDirectFBPaintEngine used on an invalid device: 0x%x",
   286                device->devType());
   373                device->devType());
   287     }
   374     }
       
   375     d->isPremultiplied = QDirectFBScreen::isPremultiplied(d->dfbDevice->format());
   288 
   376 
   289     d->prepare(d->dfbDevice);
   377     d->prepare(d->dfbDevice);
   290     gccaps = AllFeatures;
   378     gccaps = AllFeatures;
   291     d->setCompositionMode(state()->composition_mode);
   379     d->setCompositionMode(state()->composition_mode);
   292 
   380 
   409 
   497 
   410     if ((d->transformationType & QDirectFBPaintEnginePrivate::Matrix_RectsUnsupported)
   498     if ((d->transformationType & QDirectFBPaintEnginePrivate::Matrix_RectsUnsupported)
   411         || !d->simplePen
   499         || !d->simplePen
   412         || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip
   500         || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip
   413         || !d->isSimpleBrush(brush)
   501         || !d->isSimpleBrush(brush)
   414         || !d->testCompositionMode(&pen, &brush)) {
   502         || !(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)) {
   415         RASTERFALLBACK(DRAW_RECTS, rectCount, VOID_ARG(), VOID_ARG());
   503         RASTERFALLBACK(DRAW_RECTS, rectCount, VOID_ARG(), VOID_ARG());
   416         d->lock();
   504         d->lock();
   417         QRasterPaintEngine::drawRects(rects, rectCount);
   505         QRasterPaintEngine::drawRects(rects, rectCount);
   418         return;
   506         return;
   419     }
   507     }
   439 
   527 
   440     if ((d->transformationType & QDirectFBPaintEnginePrivate::Matrix_RectsUnsupported)
   528     if ((d->transformationType & QDirectFBPaintEnginePrivate::Matrix_RectsUnsupported)
   441         || !d->simplePen
   529         || !d->simplePen
   442         || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip
   530         || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip
   443         || !d->isSimpleBrush(brush)
   531         || !d->isSimpleBrush(brush)
   444         || !d->testCompositionMode(&pen, &brush)) {
   532         || !(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)) {
   445         RASTERFALLBACK(DRAW_RECTS, rectCount, VOID_ARG(), VOID_ARG());
   533         RASTERFALLBACK(DRAW_RECTS, rectCount, VOID_ARG(), VOID_ARG());
   446         d->lock();
   534         d->lock();
   447         QRasterPaintEngine::drawRects(rects, rectCount);
   535         QRasterPaintEngine::drawRects(rects, rectCount);
   448         return;
   536         return;
   449     }
   537     }
   464     Q_D(QDirectFBPaintEngine);
   552     Q_D(QDirectFBPaintEngine);
   465 
   553 
   466     const QPen &pen = state()->pen;
   554     const QPen &pen = state()->pen;
   467     if (!d->simplePen
   555     if (!d->simplePen
   468         || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip
   556         || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip
   469         || !d->testCompositionMode(&pen, 0)) {
   557         || !(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)) {
   470         RASTERFALLBACK(DRAW_LINES, lineCount, VOID_ARG(), VOID_ARG());
   558         RASTERFALLBACK(DRAW_LINES, lineCount, VOID_ARG(), VOID_ARG());
   471         d->lock();
   559         d->lock();
   472         QRasterPaintEngine::drawLines(lines, lineCount);
   560         QRasterPaintEngine::drawLines(lines, lineCount);
   473         return;
   561         return;
   474     }
   562     }
   484     Q_D(QDirectFBPaintEngine);
   572     Q_D(QDirectFBPaintEngine);
   485 
   573 
   486     const QPen &pen = state()->pen;
   574     const QPen &pen = state()->pen;
   487     if (!d->simplePen
   575     if (!d->simplePen
   488         || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip
   576         || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip
   489         || !d->testCompositionMode(&pen, 0)) {
   577         || !(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)) {
   490         RASTERFALLBACK(DRAW_LINES, lineCount, VOID_ARG(), VOID_ARG());
   578         RASTERFALLBACK(DRAW_LINES, lineCount, VOID_ARG(), VOID_ARG());
   491         d->lock();
   579         d->lock();
   492         QRasterPaintEngine::drawLines(lines, lineCount);
   580         QRasterPaintEngine::drawLines(lines, lineCount);
   493         return;
   581         return;
   494     }
   582     }
   522     images and the cost of caching the image (bytes used) is higher
   610     images and the cost of caching the image (bytes used) is higher
   523     than the max image cache size we fall back to raster engine.
   611     than the max image cache size we fall back to raster engine.
   524     */
   612     */
   525 
   613 
   526 #if !defined QT_NO_DIRECTFB_PREALLOCATED || defined QT_DIRECTFB_IMAGECACHE
   614 #if !defined QT_NO_DIRECTFB_PREALLOCATED || defined QT_DIRECTFB_IMAGECACHE
   527     if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_SupportedBlits)
   615     if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)
   528         || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported)
   616         || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported)
   529         || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip
   617         || (d->clipType == QDirectFBPaintEnginePrivate::ComplexClip)
       
   618         || (!d->supportsStretchBlit() && state()->matrix.mapRect(r).size() != sr.size())
   530 #ifndef QT_DIRECTFB_IMAGECACHE
   619 #ifndef QT_DIRECTFB_IMAGECACHE
   531         || QDirectFBScreen::getSurfacePixelFormat(image.format()) == DSPF_UNKNOWN
   620         || (QDirectFBScreen::getSurfacePixelFormat(image.format()) == DSPF_UNKNOWN)
   532 #elif defined QT_NO_DIRECTFB_PREALLOCATED
   621 #elif defined QT_NO_DIRECTFB_PREALLOCATED
   533         || QDirectFBPaintEnginePrivate::cacheCost(image) > imageCache.maxCost()
   622         || (QDirectFBPaintEnginePrivate::cacheCost(image) > imageCache.maxCost())
   534 #endif
   623 #endif
   535         )
   624         )
   536 #endif
   625 #endif
   537     {
   626     {
   538         RASTERFALLBACK(DRAW_IMAGE, r, image.size(), sr);
   627         RASTERFALLBACK(DRAW_IMAGE, r, image.size(), sr);
   570         QRasterPaintEngine::drawPixmap(r, pixmap, sr);
   659         QRasterPaintEngine::drawPixmap(r, pixmap, sr);
   571     } else {
   660     } else {
   572         QPixmapData *data = pixmap.pixmapData();
   661         QPixmapData *data = pixmap.pixmapData();
   573         Q_ASSERT(data->classId() == QPixmapData::DirectFBClass);
   662         Q_ASSERT(data->classId() == QPixmapData::DirectFBClass);
   574         QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(data);
   663         QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(data);
   575         if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_SupportedBlits)
   664         if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)
   576                || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported)
   665             || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported)
   577                || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip
   666             || (d->clipType == QDirectFBPaintEnginePrivate::ComplexClip)
   578                || (state()->renderHints & QPainter::SmoothPixmapTransform
   667             || (!d->supportsStretchBlit() && state()->matrix.mapRect(r).size() != sr.size())) {
   579                    && state()->matrix.mapRect(r).size() != sr.size())) {
       
   580             RASTERFALLBACK(DRAW_PIXMAP, r, pixmap.size(), sr);
   668             RASTERFALLBACK(DRAW_PIXMAP, r, pixmap.size(), sr);
   581             const QImage *img = dfbData->buffer();
   669             const QImage *img = dfbData->buffer();
   582             d->lock();
   670             d->lock();
   583             QRasterPaintEngine::drawImage(r, *img, sr);
   671             QRasterPaintEngine::drawImage(r, *img, sr);
   584         } else {
   672         } else {
   602     Q_D(QDirectFBPaintEngine);
   690     Q_D(QDirectFBPaintEngine);
   603     if (pixmap.pixmapData()->classId() != QPixmapData::DirectFBClass) {
   691     if (pixmap.pixmapData()->classId() != QPixmapData::DirectFBClass) {
   604         RASTERFALLBACK(DRAW_TILED_PIXMAP, r, pixmap.size(), offset);
   692         RASTERFALLBACK(DRAW_TILED_PIXMAP, r, pixmap.size(), offset);
   605         d->lock();
   693         d->lock();
   606         QRasterPaintEngine::drawTiledPixmap(r, pixmap, offset);
   694         QRasterPaintEngine::drawTiledPixmap(r, pixmap, offset);
   607     } else if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_SupportedBlits)
   695     } else if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)
   608                || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported)
   696                || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported)
   609                || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip
   697                || (d->clipType == QDirectFBPaintEnginePrivate::ComplexClip)
   610                || (state()->renderHints & QPainter::SmoothPixmapTransform && state()->matrix.isScaling())) {
   698                || (!d->supportsStretchBlit() && state()->matrix.isScaling())) {
   611         RASTERFALLBACK(DRAW_TILED_PIXMAP, r, pixmap.size(), offset);
   699         RASTERFALLBACK(DRAW_TILED_PIXMAP, r, pixmap.size(), offset);
   612         QPixmapData *pixmapData = pixmap.pixmapData();
   700         QPixmapData *pixmapData = pixmap.pixmapData();
   613         Q_ASSERT(pixmapData->classId() == QPixmapData::DirectFBClass);
   701         Q_ASSERT(pixmapData->classId() == QPixmapData::DirectFBClass);
   614         QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(pixmapData);
   702         QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(pixmapData);
   615         const QImage *img = dfbData->buffer();
   703         const QImage *img = dfbData->buffer();
   715     if (brush.style() == Qt::NoBrush)
   803     if (brush.style() == Qt::NoBrush)
   716         return;
   804         return;
   717     if (d->clipType != QDirectFBPaintEnginePrivate::ComplexClip) {
   805     if (d->clipType != QDirectFBPaintEnginePrivate::ComplexClip) {
   718         switch (brush.style()) {
   806         switch (brush.style()) {
   719         case Qt::SolidPattern: {
   807         case Qt::SolidPattern: {
   720             if (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_RectsUnsupported
       
   721                 || !d->testCompositionMode(0, &brush)) {
       
   722                 break;
       
   723             }
       
   724             const QColor color = brush.color();
   808             const QColor color = brush.color();
   725             if (!color.isValid())
   809             if (!color.isValid())
   726                 return;
   810                 return;
       
   811 
       
   812             if (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_RectsUnsupported
       
   813                 || !(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)) {
       
   814                 break;
       
   815             }
   727             d->setDFBColor(color);
   816             d->setDFBColor(color);
   728             const QRect r = state()->matrix.mapRect(rect).toRect();
   817             const QRect r = state()->matrix.mapRect(rect).toRect();
   729             CLIPPED_PAINT(d->surface->FillRectangle(d->surface, r.x(), r.y(), r.width(), r.height()));
   818             CLIPPED_PAINT(d->surface->FillRectangle(d->surface, r.x(), r.y(), r.width(), r.height()));
   730             return; }
   819             return; }
   731 
   820 
   732         case Qt::TexturePattern: {
   821         case Qt::TexturePattern: {
   733             if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_SupportedBlits)
   822             if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)
   734                 || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported)
   823                 || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported)
   735                 || (state()->renderHints & QPainter::SmoothPixmapTransform && state()->matrix.isScaling())) {
   824                 || (!d->supportsStretchBlit() && state()->matrix.isScaling())) {
   736                 break;
   825                 break;
   737             }
   826             }
   738 
   827 
   739             const QPixmap texture = brush.texture();
   828             const QPixmap texture = brush.texture();
   740             if (texture.pixmapData()->classId() != QPixmapData::DirectFBClass)
   829             if (texture.pixmapData()->classId() != QPixmapData::DirectFBClass)
   755 {
   844 {
   756     if (!color.isValid())
   845     if (!color.isValid())
   757         return;
   846         return;
   758     Q_D(QDirectFBPaintEngine);
   847     Q_D(QDirectFBPaintEngine);
   759     if ((d->transformationType & QDirectFBPaintEnginePrivate::Matrix_RectsUnsupported)
   848     if ((d->transformationType & QDirectFBPaintEnginePrivate::Matrix_RectsUnsupported)
   760         || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip
   849         || (d->clipType == QDirectFBPaintEnginePrivate::ComplexClip)
   761         || !d->testCompositionMode(0, 0, &color)) {
   850         || !(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)) {
   762         RASTERFALLBACK(FILL_RECT, rect, color, VOID_ARG());
   851         RASTERFALLBACK(FILL_RECT, rect, color, VOID_ARG());
   763         d->lock();
   852         d->lock();
   764         QRasterPaintEngine::fillRect(rect, color);
   853         QRasterPaintEngine::fillRect(rect, color);
   765     } else {
   854     } else {
   766         d->setDFBColor(color);
   855         d->setDFBColor(color);
   800 
   889 
   801 QDirectFBPaintEnginePrivate::QDirectFBPaintEnginePrivate(QDirectFBPaintEngine *p)
   890 QDirectFBPaintEnginePrivate::QDirectFBPaintEnginePrivate(QDirectFBPaintEngine *p)
   802     : surface(0), antialiased(false), simplePen(false),
   891     : surface(0), antialiased(false), simplePen(false),
   803       transformationType(0), opacity(255),
   892       transformationType(0), opacity(255),
   804       clipType(ClipUnset), dfbDevice(0),
   893       clipType(ClipUnset), dfbDevice(0),
   805       compositionModeStatus(0), inClip(false), q(p)
   894       compositionModeStatus(0), isPremultiplied(false), inClip(false), q(p)
   806 {
   895 {
   807     fb = QDirectFBScreen::instance()->dfb();
   896     fb = QDirectFBScreen::instance()->dfb();
   808     surfaceCache = new SurfaceCache;
   897     surfaceCache = new SurfaceCache;
   809 }
   898 }
   810 
   899 
   815 
   904 
   816 bool QDirectFBPaintEnginePrivate::isSimpleBrush(const QBrush &brush) const
   905 bool QDirectFBPaintEnginePrivate::isSimpleBrush(const QBrush &brush) const
   817 {
   906 {
   818     return (brush.style() == Qt::NoBrush) || (brush.style() == Qt::SolidPattern && !antialiased);
   907     return (brush.style() == Qt::NoBrush) || (brush.style() == Qt::SolidPattern && !antialiased);
   819 }
   908 }
   820 
       
   821 bool QDirectFBPaintEnginePrivate::testCompositionMode(const QPen *pen, const QBrush *brush, const QColor *color) const
       
   822 {
       
   823     Q_ASSERT(!pen || pen->style() == Qt::NoPen || pen->style() == Qt::SolidLine);
       
   824     Q_ASSERT(!brush || brush->style() == Qt::NoBrush || brush->style() == Qt::SolidPattern);
       
   825     switch (compositionModeStatus & (QDirectFBPaintEnginePrivate::PorterDuff_SupportedOpaquePrimitives
       
   826                                      |QDirectFBPaintEnginePrivate::PorterDuff_SupportedPrimitives)) {
       
   827     case QDirectFBPaintEnginePrivate::PorterDuff_SupportedPrimitives:
       
   828         return true;
       
   829     case QDirectFBPaintEnginePrivate::PorterDuff_SupportedOpaquePrimitives:
       
   830         if (pen && pen->style() == Qt::SolidLine && pen->color().alpha() != 255)
       
   831             return false;
       
   832         if (brush) {
       
   833             if (brush->style() == Qt::SolidPattern && brush->color().alpha() != 255) {
       
   834                 return false;
       
   835             }
       
   836         } else if (color && color->alpha() != 255) {
       
   837             return false;
       
   838         }
       
   839         return true;
       
   840     case QDirectFBPaintEnginePrivate::PorterDuff_None:
       
   841         return false;
       
   842     default:
       
   843         // ### PorterDuff_SupportedOpaquePrimitives|PorterDuff_SupportedPrimitives can't be combined
       
   844         break;
       
   845     }
       
   846     Q_ASSERT(0);
       
   847     return false;
       
   848 }
       
   849 
       
   850 
   909 
   851 void QDirectFBPaintEnginePrivate::lock()
   910 void QDirectFBPaintEnginePrivate::lock()
   852 {
   911 {
   853     // We will potentially get a new pointer to the buffer after a
   912     // We will potentially get a new pointer to the buffer after a
   854     // lock so we need to call the base implementation of prepare so
   913     // lock so we need to call the base implementation of prepare so
   908     if (!surface)
   967     if (!surface)
   909         return;
   968         return;
   910 
   969 
   911     static const bool forceRasterFallBack = qgetenv("QT_DIRECTFB_FORCE_RASTER").toInt() > 0;
   970     static const bool forceRasterFallBack = qgetenv("QT_DIRECTFB_FORCE_RASTER").toInt() > 0;
   912     if (forceRasterFallBack) {
   971     if (forceRasterFallBack) {
   913         compositionModeStatus = 0;
   972         compositionModeStatus = PorterDuff_None;
   914         return;
   973         return;
   915     }
   974     }
   916 
   975 
   917     compositionModeStatus = PorterDuff_SupportedBlits;
   976     compositionModeStatus = PorterDuff_Supported|PorterDuff_PremultiplyColors|PorterDuff_AlwaysBlend;
   918     switch (mode) {
   977     switch (mode) {
   919     case QPainter::CompositionMode_Clear:
   978     case QPainter::CompositionMode_Clear:
   920         surface->SetPorterDuff(surface, DSPD_CLEAR);
   979         surface->SetPorterDuff(surface, DSPD_CLEAR);
   921         break;
   980         break;
   922     case QPainter::CompositionMode_Source:
   981     case QPainter::CompositionMode_Source:
   923         surface->SetPorterDuff(surface, DSPD_SRC);
   982         surface->SetPorterDuff(surface, DSPD_SRC);
   924         compositionModeStatus |= PorterDuff_SupportedOpaquePrimitives;
   983         compositionModeStatus &= ~PorterDuff_AlwaysBlend;
       
   984         if (!isPremultiplied)
       
   985             compositionModeStatus &= ~PorterDuff_PremultiplyColors;
   925         break;
   986         break;
   926     case QPainter::CompositionMode_SourceOver:
   987     case QPainter::CompositionMode_SourceOver:
   927         compositionModeStatus |= PorterDuff_SupportedPrimitives;
   988         compositionModeStatus &= ~PorterDuff_AlwaysBlend;
   928         surface->SetPorterDuff(surface, DSPD_SRC_OVER);
   989         surface->SetPorterDuff(surface, DSPD_SRC_OVER);
   929         break;
   990         break;
   930     case QPainter::CompositionMode_DestinationOver:
   991     case QPainter::CompositionMode_DestinationOver:
   931         surface->SetPorterDuff(surface, DSPD_DST_OVER);
   992         surface->SetPorterDuff(surface, DSPD_DST_OVER);
   932         break;
   993         break;
   933     case QPainter::CompositionMode_SourceIn:
   994     case QPainter::CompositionMode_SourceIn:
   934         surface->SetPorterDuff(surface, DSPD_SRC_IN);
   995         surface->SetPorterDuff(surface, DSPD_SRC_IN);
       
   996         if (!isPremultiplied)
       
   997             compositionModeStatus &= ~PorterDuff_PremultiplyColors;
   935         break;
   998         break;
   936     case QPainter::CompositionMode_DestinationIn:
   999     case QPainter::CompositionMode_DestinationIn:
   937         surface->SetPorterDuff(surface, DSPD_DST_IN);
  1000         surface->SetPorterDuff(surface, DSPD_DST_IN);
   938         break;
  1001         break;
   939     case QPainter::CompositionMode_SourceOut:
  1002     case QPainter::CompositionMode_SourceOut:
   940         surface->SetPorterDuff(surface, DSPD_SRC_OUT);
  1003         surface->SetPorterDuff(surface, DSPD_SRC_OUT);
   941         break;
  1004         break;
   942     case QPainter::CompositionMode_DestinationOut:
  1005     case QPainter::CompositionMode_DestinationOut:
   943         surface->SetPorterDuff(surface, DSPD_DST_OUT);
  1006         surface->SetPorterDuff(surface, DSPD_DST_OUT);
   944         break;
  1007         break;
       
  1008 #if (Q_DIRECTFB_VERSION >= 0x010209)
       
  1009     case QPainter::CompositionMode_Destination:
       
  1010         surface->SetPorterDuff(surface, DSPD_DST);
       
  1011         break;
       
  1012 #endif
   945 #if (Q_DIRECTFB_VERSION >= 0x010000)
  1013 #if (Q_DIRECTFB_VERSION >= 0x010000)
   946     case QPainter::CompositionMode_SourceAtop:
  1014     case QPainter::CompositionMode_SourceAtop:
   947         surface->SetPorterDuff(surface, DSPD_SRC_ATOP);
  1015         surface->SetPorterDuff(surface, DSPD_SRC_ATOP);
   948         break;
  1016         break;
   949     case QPainter::CompositionMode_DestinationAtop:
  1017     case QPainter::CompositionMode_DestinationAtop:
   955     case QPainter::CompositionMode_Xor:
  1023     case QPainter::CompositionMode_Xor:
   956         surface->SetPorterDuff(surface, DSPD_XOR);
  1024         surface->SetPorterDuff(surface, DSPD_XOR);
   957         break;
  1025         break;
   958 #endif
  1026 #endif
   959     default:
  1027     default:
   960         compositionModeStatus = 0;
  1028         compositionModeStatus = PorterDuff_None;
   961         break;
  1029         break;
   962     }
  1030     }
   963 }
  1031 }
   964 
  1032 
   965 void QDirectFBPaintEnginePrivate::setRenderHints(QPainter::RenderHints hints)
  1033 void QDirectFBPaintEnginePrivate::setRenderHints(QPainter::RenderHints hints)
   977     if (opacity != 255) {
  1045     if (opacity != 255) {
   978         blittingFlags |= DSBLIT_BLEND_COLORALPHA;
  1046         blittingFlags |= DSBLIT_BLEND_COLORALPHA;
   979     }
  1047     }
   980     surface->SetColor(surface, 0xff, 0xff, 0xff, opacity);
  1048     surface->SetColor(surface, 0xff, 0xff, 0xff, opacity);
   981     surface->SetBlittingFlags(surface, blittingFlags);
  1049     surface->SetBlittingFlags(surface, blittingFlags);
   982     if (compositionModeStatus & PorterDuff_Dirty) {
       
   983         setCompositionMode(q->state()->composition_mode);
       
   984     }
       
   985 }
  1050 }
   986 
  1051 
   987 static inline uint ALPHA_MUL(uint x, uint a)
  1052 static inline uint ALPHA_MUL(uint x, uint a)
   988 {
  1053 {
   989     uint t = x * a;
  1054     uint t = x * a;
   992 }
  1057 }
   993 
  1058 
   994 void QDirectFBPaintEnginePrivate::setDFBColor(const QColor &color)
  1059 void QDirectFBPaintEnginePrivate::setDFBColor(const QColor &color)
   995 {
  1060 {
   996     Q_ASSERT(surface);
  1061     Q_ASSERT(surface);
       
  1062     Q_ASSERT(compositionModeStatus & PorterDuff_Supported);
   997     const quint8 alpha = (opacity == 255 ?
  1063     const quint8 alpha = (opacity == 255 ?
   998                           color.alpha() : ALPHA_MUL(color.alpha(), opacity));
  1064                           color.alpha() : ALPHA_MUL(color.alpha(), opacity));
   999     surface->SetColor(surface, color.red(), color.green(), color.blue(), alpha);
  1065     QColor col;
  1000     surface->SetPorterDuff(surface, DSPD_NONE);
  1066     if (compositionModeStatus & PorterDuff_PremultiplyColors) {
  1001     surface->SetDrawingFlags(surface, alpha == 255 ? DSDRAW_NOFX : DSDRAW_BLEND);
  1067         col = QColor(ALPHA_MUL(color.red(), alpha),
  1002     compositionModeStatus |= PorterDuff_Dirty;
  1068                      ALPHA_MUL(color.green(), alpha),
       
  1069                      ALPHA_MUL(color.blue(), alpha),
       
  1070                      alpha);
       
  1071     } else {
       
  1072         col = QColor(color.red(), color.green(), color.blue(), alpha);
       
  1073     }
       
  1074     surface->SetColor(surface, col.red(), col.green(), col.blue(), col.alpha());
       
  1075     surface->SetDrawingFlags(surface, alpha == 255 && !(compositionModeStatus & PorterDuff_AlwaysBlend) ? DSDRAW_NOFX : DSDRAW_BLEND);
  1003 }
  1076 }
  1004 
  1077 
  1005 IDirectFBSurface *QDirectFBPaintEnginePrivate::getSurface(const QImage &img, bool *release)
  1078 IDirectFBSurface *QDirectFBPaintEnginePrivate::getSurface(const QImage &img, bool *release)
  1006 {
  1079 {
  1007 #ifdef QT_NO_DIRECTFB_IMAGECACHE
  1080 #ifdef QT_NO_DIRECTFB_IMAGECACHE
  1047     DFBResult result;
  1120     DFBResult result;
  1048 
  1121 
  1049     if (dr.size() == sr.size()) {
  1122     if (dr.size() == sr.size()) {
  1050         result = surface->Blit(surface, s, &sRect, dr.x(), dr.y());
  1123         result = surface->Blit(surface, s, &sRect, dr.x(), dr.y());
  1051     } else {
  1124     } else {
       
  1125         Q_ASSERT(supportsStretchBlit());
  1052         const DFBRectangle dRect = { dr.x(), dr.y(), dr.width(), dr.height() };
  1126         const DFBRectangle dRect = { dr.x(), dr.y(), dr.width(), dr.height() };
  1053         result = surface->StretchBlit(surface, s, &sRect, &dRect);
  1127         result = surface->StretchBlit(surface, s, &sRect, &dRect);
  1054     }
  1128     }
  1055     if (result != DFB_OK)
  1129     if (result != DFB_OK)
  1056         DirectFBError("QDirectFBPaintEngine::drawPixmap()", result);
  1130         DirectFBError("QDirectFBPaintEngine::drawPixmap()", result);
  1094     QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(data);
  1168     QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(data);
  1095     QDirectFBPaintEnginePrivate::unlock(dfbData);
  1169     QDirectFBPaintEnginePrivate::unlock(dfbData);
  1096     const QSize pixmapSize = dfbData->size();
  1170     const QSize pixmapSize = dfbData->size();
  1097     IDirectFBSurface *sourceSurface = dfbData->directFBSurface();
  1171     IDirectFBSurface *sourceSurface = dfbData->directFBSurface();
  1098     if (transform.isScaling()) {
  1172     if (transform.isScaling()) {
       
  1173         Q_ASSERT(supportsStretchBlit());
  1099         Q_ASSERT(qMin(transform.m11(), transform.m22()) >= 0);
  1174         Q_ASSERT(qMin(transform.m11(), transform.m22()) >= 0);
  1100         offset.rx() *= transform.m11();
  1175         offset.rx() *= transform.m11();
  1101         offset.ry() *= transform.m22();
  1176         offset.ry() *= transform.m22();
  1102 
  1177 
  1103         const QSizeF mappedSize(pixmapSize.width() * transform.m11(), pixmapSize.height() * transform.m22());
  1178         const QSizeF mappedSize(pixmapSize.width() * transform.m11(), pixmapSize.height() * transform.m22());
  1182     } else {
  1257     } else {
  1183         clipType = ComplexClip;
  1258         clipType = ComplexClip;
  1184     }
  1259     }
  1185 }
  1260 }
  1186 
  1261 
       
  1262 bool QDirectFBPaintEnginePrivate::supportsStretchBlit() const
       
  1263 {
       
  1264 #ifdef QT_DIRECTFB_STRETCHBLIT
       
  1265     return !(q->state()->renderHints & QPainter::SmoothPixmapTransform);
       
  1266 #else
       
  1267     return false;
       
  1268 #endif
       
  1269 }
       
  1270 
       
  1271 
  1187 void QDirectFBPaintEnginePrivate::systemStateChanged()
  1272 void QDirectFBPaintEnginePrivate::systemStateChanged()
  1188 {
  1273 {
  1189     QRasterPaintEnginePrivate::systemStateChanged();
  1274     QRasterPaintEnginePrivate::systemStateChanged();
  1190     updateClip();
  1275     updateClip();
  1191 }
  1276 }
  1267         const QRect r = mapRect(transform, rects[i]);
  1352         const QRect r = mapRect(transform, rects[i]);
  1268         surface->DrawRectangle(surface, r.x(), r.y(), r.width(), r.height());
  1353         surface->DrawRectangle(surface, r.x(), r.y(), r.width(), r.height());
  1269     }
  1354     }
  1270 }
  1355 }
  1271 
  1356 
  1272 #ifdef QT_DIRECTFB_WARN_ON_RASTERFALLBACKS
  1357 #if defined QT_DIRECTFB_WARN_ON_RASTERFALLBACKS || defined QT_DEBUG
  1273 template <typename T> inline const T *ptr(const T &t) { return &t; }
  1358 template <typename T> inline const T *ptr(const T &t) { return &t; }
  1274 template <> inline const bool* ptr<bool>(const bool &) { return 0; }
  1359 template <> inline const bool* ptr<bool>(const bool &) { return 0; }
  1275 template <typename device, typename T1, typename T2, typename T3>
  1360 template <typename device, typename T1, typename T2, typename T3>
  1276 static void rasterFallbackWarn(const char *msg, const char *func, const device *dev,
  1361 static void rasterFallbackWarn(const char *msg, const char *func, const device *dev,
  1277                                uint transformationType, bool simplePen,
  1362                                uint transformationType, bool simplePen,