src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp
changeset 19 fcece45ef507
parent 18 2f34d5167611
child 30 5dc02b23752f
equal deleted inserted replaced
18:2f34d5167611 19:fcece45ef507
    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);
   105 
   103 
   128     quint8 opacity;
   126     quint8 opacity;
   129 
   127 
   130     ClipType clipType;
   128     ClipType clipType;
   131     QDirectFBPaintDevice *dfbDevice;
   129     QDirectFBPaintDevice *dfbDevice;
   132     uint compositionModeStatus;
   130     uint compositionModeStatus;
       
   131     bool isPremultiplied;
   133 
   132 
   134     bool inClip;
   133     bool inClip;
   135     QRect currentClip;
   134     QRect currentClip;
   136 
   135 
   137     QDirectFBPaintEngine *q;
   136     QDirectFBPaintEngine *q;
   166     }
   165     }
   167 };
   166 };
   168 static QCache<qint64, CachedImage> imageCache(4*1024*1024); // 4 MB
   167 static QCache<qint64, CachedImage> imageCache(4*1024*1024); // 4 MB
   169 #endif
   168 #endif
   170 
   169 
   171 #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
   172 #define VOID_ARG() static_cast<bool>(false)
   171 #define VOID_ARG() static_cast<bool>(false)
   173 enum PaintOperation {
   172 enum PaintOperation {
   174     DRAW_RECTS = 0x0001, DRAW_LINES = 0x0002, DRAW_IMAGE = 0x0004,
   173     DRAW_RECTS = 0x0001, DRAW_LINES = 0x0002, DRAW_IMAGE = 0x0004,
   175     DRAW_PIXMAP = 0x0008, DRAW_TILED_PIXMAP = 0x0010, STROKE_PATH = 0x0020,
   174     DRAW_PIXMAP = 0x0008, DRAW_TILED_PIXMAP = 0x0010, STROKE_PATH = 0x0020,
   176     DRAW_PATH = 0x0040, DRAW_POINTS = 0x0080, DRAW_ELLIPSE = 0x0100,
   175     DRAW_PATH = 0x0040, DRAW_POINTS = 0x0080, DRAW_ELLIPSE = 0x0100,
   177     DRAW_POLYGON = 0x0200, DRAW_TEXT = 0x0400, FILL_PATH = 0x0800,
   176     DRAW_POLYGON = 0x0200, DRAW_TEXT = 0x0400, FILL_PATH = 0x0800,
   178     FILL_RECT = 0x1000, DRAW_COLORSPANS = 0x2000, DRAW_ROUNDED_RECT = 0x4000,
   177     FILL_RECT = 0x1000, DRAW_COLORSPANS = 0x2000, DRAW_ROUNDED_RECT = 0x4000,
   179     ALL = 0xffff
   178     ALL = 0xffff
   180 };
   179 };
   181 #endif
   180 
   182 
   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 {
   183 #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
   184 template <typename device, typename T1, typename T2, typename T3>
   263 template <typename device, typename T1, typename T2, typename T3>
   185 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,
   186                                uint transformationType, bool simplePen,
   265                                uint transformationType, bool simplePen,
   187                                uint clipType, uint compositionModeStatus,
   266                                uint clipType, uint compositionModeStatus,
   188                                const char *nameOne, const T1 &one,
   267                                const char *nameOne, const T1 &one,
   189                                const char *nameTwo, const T2 &two,
   268                                const char *nameTwo, const T2 &two,
   190                                const char *nameThree, const T3 &three);
   269                                const char *nameThree, const T3 &three);
   191 #endif
   270 #endif
   192 
   271 
   193 #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)
   194 #define RASTERFALLBACK(op, one, two, three)                             \
   273 #define RASTERFALLBACK(op, one, two, three)                             \
   195     if (op & (QT_DIRECTFB_WARN_ON_RASTERFALLBACKS))                     \
   274     {                                                                   \
   196         rasterFallbackWarn("Disabled raster engine operation",          \
   275         const bool disable = op & rasterFallbacksMask(false);           \
   197                            __FUNCTION__, state()->painter->device(),    \
   276         if (op & rasterFallbacksMask(true))                             \
   198                            d_func()->transformationType,                \
   277             rasterFallbackWarn(disable                                  \
   199                            d_func()->simplePen,                         \
   278                                ? "Disabled raster engine operation"     \
   200                            d_func()->clipType,                          \
   279                                : "Falling back to raster engine for",   \
   201                            d_func()->compositionModeStatus,             \
   280                                __FUNCTION__,                            \
   202                            #one, one, #two, two, #three, three);        \
   281                                state()->painter->device(),              \
   203     if (op & (QT_DIRECTFB_DISABLE_RASTERFALLBACKS))                     \
   282                                d_func()->transformationType,            \
   204         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     }
   205 #elif defined QT_DIRECTFB_DISABLE_RASTERFALLBACKS
   290 #elif defined QT_DIRECTFB_DISABLE_RASTERFALLBACKS
   206 #define RASTERFALLBACK(op, one, two, three)             \
   291 #define RASTERFALLBACK(op, one, two, three)                             \
   207     if (op & (QT_DIRECTFB_DISABLE_RASTERFALLBACKS))     \
   292     if (op & rasterFallbacksMask(false))                                \
   208         return;
   293         return;
   209 #elif defined QT_DIRECTFB_WARN_ON_RASTERFALLBACKS
   294 #elif defined QT_DIRECTFB_WARN_ON_RASTERFALLBACKS
   210 #define RASTERFALLBACK(op, one, two, three)                             \
   295 #define RASTERFALLBACK(op, one, two, three)                             \
   211     if (op & (QT_DIRECTFB_WARN_ON_RASTERFALLBACKS))                     \
   296     if (op & rasterFallbacksMask(true))                                 \
   212         rasterFallbackWarn("Falling back to raster engine for",         \
   297         rasterFallbackWarn("Falling back to raster engine for",         \
   213                            __FUNCTION__, state()->painter->device(),    \
   298                            __FUNCTION__, state()->painter->device(),    \
   214                            d_func()->transformationType,                \
   299                            d_func()->transformationType,                \
   215                            d_func()->simplePen,                         \
   300                            d_func()->simplePen,                         \
   216                            d_func()->clipType,                          \
   301                            d_func()->clipType,                          \
   285 
   370 
   286     if (!d->surface) {
   371     if (!d->surface) {
   287         qFatal("QDirectFBPaintEngine used on an invalid device: 0x%x",
   372         qFatal("QDirectFBPaintEngine used on an invalid device: 0x%x",
   288                device->devType());
   373                device->devType());
   289     }
   374     }
       
   375     d->isPremultiplied = QDirectFBScreen::isPremultiplied(d->dfbDevice->format());
   290 
   376 
   291     d->prepare(d->dfbDevice);
   377     d->prepare(d->dfbDevice);
   292     gccaps = AllFeatures;
   378     gccaps = AllFeatures;
   293     d->setCompositionMode(state()->composition_mode);
   379     d->setCompositionMode(state()->composition_mode);
   294 
   380 
   411 
   497 
   412     if ((d->transformationType & QDirectFBPaintEnginePrivate::Matrix_RectsUnsupported)
   498     if ((d->transformationType & QDirectFBPaintEnginePrivate::Matrix_RectsUnsupported)
   413         || !d->simplePen
   499         || !d->simplePen
   414         || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip
   500         || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip
   415         || !d->isSimpleBrush(brush)
   501         || !d->isSimpleBrush(brush)
   416         || !d->testCompositionMode(&pen, &brush)) {
   502         || !(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)) {
   417         RASTERFALLBACK(DRAW_RECTS, rectCount, VOID_ARG(), VOID_ARG());
   503         RASTERFALLBACK(DRAW_RECTS, rectCount, VOID_ARG(), VOID_ARG());
   418         d->lock();
   504         d->lock();
   419         QRasterPaintEngine::drawRects(rects, rectCount);
   505         QRasterPaintEngine::drawRects(rects, rectCount);
   420         return;
   506         return;
   421     }
   507     }
   441 
   527 
   442     if ((d->transformationType & QDirectFBPaintEnginePrivate::Matrix_RectsUnsupported)
   528     if ((d->transformationType & QDirectFBPaintEnginePrivate::Matrix_RectsUnsupported)
   443         || !d->simplePen
   529         || !d->simplePen
   444         || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip
   530         || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip
   445         || !d->isSimpleBrush(brush)
   531         || !d->isSimpleBrush(brush)
   446         || !d->testCompositionMode(&pen, &brush)) {
   532         || !(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)) {
   447         RASTERFALLBACK(DRAW_RECTS, rectCount, VOID_ARG(), VOID_ARG());
   533         RASTERFALLBACK(DRAW_RECTS, rectCount, VOID_ARG(), VOID_ARG());
   448         d->lock();
   534         d->lock();
   449         QRasterPaintEngine::drawRects(rects, rectCount);
   535         QRasterPaintEngine::drawRects(rects, rectCount);
   450         return;
   536         return;
   451     }
   537     }
   466     Q_D(QDirectFBPaintEngine);
   552     Q_D(QDirectFBPaintEngine);
   467 
   553 
   468     const QPen &pen = state()->pen;
   554     const QPen &pen = state()->pen;
   469     if (!d->simplePen
   555     if (!d->simplePen
   470         || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip
   556         || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip
   471         || !d->testCompositionMode(&pen, 0)) {
   557         || !(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)) {
   472         RASTERFALLBACK(DRAW_LINES, lineCount, VOID_ARG(), VOID_ARG());
   558         RASTERFALLBACK(DRAW_LINES, lineCount, VOID_ARG(), VOID_ARG());
   473         d->lock();
   559         d->lock();
   474         QRasterPaintEngine::drawLines(lines, lineCount);
   560         QRasterPaintEngine::drawLines(lines, lineCount);
   475         return;
   561         return;
   476     }
   562     }
   486     Q_D(QDirectFBPaintEngine);
   572     Q_D(QDirectFBPaintEngine);
   487 
   573 
   488     const QPen &pen = state()->pen;
   574     const QPen &pen = state()->pen;
   489     if (!d->simplePen
   575     if (!d->simplePen
   490         || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip
   576         || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip
   491         || !d->testCompositionMode(&pen, 0)) {
   577         || !(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)) {
   492         RASTERFALLBACK(DRAW_LINES, lineCount, VOID_ARG(), VOID_ARG());
   578         RASTERFALLBACK(DRAW_LINES, lineCount, VOID_ARG(), VOID_ARG());
   493         d->lock();
   579         d->lock();
   494         QRasterPaintEngine::drawLines(lines, lineCount);
   580         QRasterPaintEngine::drawLines(lines, lineCount);
   495         return;
   581         return;
   496     }
   582     }
   524     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
   525     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.
   526     */
   612     */
   527 
   613 
   528 #if !defined QT_NO_DIRECTFB_PREALLOCATED || defined QT_DIRECTFB_IMAGECACHE
   614 #if !defined QT_NO_DIRECTFB_PREALLOCATED || defined QT_DIRECTFB_IMAGECACHE
   529     if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_SupportedBlits)
   615     if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)
   530         || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported)
   616         || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported)
   531         || (d->clipType == QDirectFBPaintEnginePrivate::ComplexClip)
   617         || (d->clipType == QDirectFBPaintEnginePrivate::ComplexClip)
   532         || (!d->supportsStretchBlit() && state()->matrix.mapRect(r).size() != sr.size())
   618         || (!d->supportsStretchBlit() && state()->matrix.mapRect(r).size() != sr.size())
   533 #ifndef QT_DIRECTFB_IMAGECACHE
   619 #ifndef QT_DIRECTFB_IMAGECACHE
   534         || (QDirectFBScreen::getSurfacePixelFormat(image.format()) == DSPF_UNKNOWN)
   620         || (QDirectFBScreen::getSurfacePixelFormat(image.format()) == DSPF_UNKNOWN)
   573         QRasterPaintEngine::drawPixmap(r, pixmap, sr);
   659         QRasterPaintEngine::drawPixmap(r, pixmap, sr);
   574     } else {
   660     } else {
   575         QPixmapData *data = pixmap.pixmapData();
   661         QPixmapData *data = pixmap.pixmapData();
   576         Q_ASSERT(data->classId() == QPixmapData::DirectFBClass);
   662         Q_ASSERT(data->classId() == QPixmapData::DirectFBClass);
   577         QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(data);
   663         QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(data);
   578         if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_SupportedBlits)
   664         if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)
   579             || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported)
   665             || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported)
   580             || (d->clipType == QDirectFBPaintEnginePrivate::ComplexClip)
   666             || (d->clipType == QDirectFBPaintEnginePrivate::ComplexClip)
   581             || (!d->supportsStretchBlit() && state()->matrix.mapRect(r).size() != sr.size())) {
   667             || (!d->supportsStretchBlit() && state()->matrix.mapRect(r).size() != sr.size())) {
   582             RASTERFALLBACK(DRAW_PIXMAP, r, pixmap.size(), sr);
   668             RASTERFALLBACK(DRAW_PIXMAP, r, pixmap.size(), sr);
   583             const QImage *img = dfbData->buffer();
   669             const QImage *img = dfbData->buffer();
   604     Q_D(QDirectFBPaintEngine);
   690     Q_D(QDirectFBPaintEngine);
   605     if (pixmap.pixmapData()->classId() != QPixmapData::DirectFBClass) {
   691     if (pixmap.pixmapData()->classId() != QPixmapData::DirectFBClass) {
   606         RASTERFALLBACK(DRAW_TILED_PIXMAP, r, pixmap.size(), offset);
   692         RASTERFALLBACK(DRAW_TILED_PIXMAP, r, pixmap.size(), offset);
   607         d->lock();
   693         d->lock();
   608         QRasterPaintEngine::drawTiledPixmap(r, pixmap, offset);
   694         QRasterPaintEngine::drawTiledPixmap(r, pixmap, offset);
   609     } else if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_SupportedBlits)
   695     } else if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)
   610                || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported)
   696                || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported)
   611                || (d->clipType == QDirectFBPaintEnginePrivate::ComplexClip)
   697                || (d->clipType == QDirectFBPaintEnginePrivate::ComplexClip)
   612                || (!d->supportsStretchBlit() && state()->matrix.isScaling())) {
   698                || (!d->supportsStretchBlit() && state()->matrix.isScaling())) {
   613         RASTERFALLBACK(DRAW_TILED_PIXMAP, r, pixmap.size(), offset);
   699         RASTERFALLBACK(DRAW_TILED_PIXMAP, r, pixmap.size(), offset);
   614         QPixmapData *pixmapData = pixmap.pixmapData();
   700         QPixmapData *pixmapData = pixmap.pixmapData();
   717     if (brush.style() == Qt::NoBrush)
   803     if (brush.style() == Qt::NoBrush)
   718         return;
   804         return;
   719     if (d->clipType != QDirectFBPaintEnginePrivate::ComplexClip) {
   805     if (d->clipType != QDirectFBPaintEnginePrivate::ComplexClip) {
   720         switch (brush.style()) {
   806         switch (brush.style()) {
   721         case Qt::SolidPattern: {
   807         case Qt::SolidPattern: {
   722             if (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_RectsUnsupported
       
   723                 || !d->testCompositionMode(0, &brush)) {
       
   724                 break;
       
   725             }
       
   726             const QColor color = brush.color();
   808             const QColor color = brush.color();
   727             if (!color.isValid())
   809             if (!color.isValid())
   728                 return;
   810                 return;
       
   811 
       
   812             if (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_RectsUnsupported
       
   813                 || !(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)) {
       
   814                 break;
       
   815             }
   729             d->setDFBColor(color);
   816             d->setDFBColor(color);
   730             const QRect r = state()->matrix.mapRect(rect).toRect();
   817             const QRect r = state()->matrix.mapRect(rect).toRect();
   731             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()));
   732             return; }
   819             return; }
   733 
   820 
   734         case Qt::TexturePattern: {
   821         case Qt::TexturePattern: {
   735             if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_SupportedBlits)
   822             if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)
   736                 || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported)
   823                 || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported)
   737                 || (!d->supportsStretchBlit() && state()->matrix.isScaling())) {
   824                 || (!d->supportsStretchBlit() && state()->matrix.isScaling())) {
   738                 break;
   825                 break;
   739             }
   826             }
   740 
   827 
   758     if (!color.isValid())
   845     if (!color.isValid())
   759         return;
   846         return;
   760     Q_D(QDirectFBPaintEngine);
   847     Q_D(QDirectFBPaintEngine);
   761     if ((d->transformationType & QDirectFBPaintEnginePrivate::Matrix_RectsUnsupported)
   848     if ((d->transformationType & QDirectFBPaintEnginePrivate::Matrix_RectsUnsupported)
   762         || (d->clipType == QDirectFBPaintEnginePrivate::ComplexClip)
   849         || (d->clipType == QDirectFBPaintEnginePrivate::ComplexClip)
   763         || !d->testCompositionMode(0, 0, &color)) {
   850         || !(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)) {
   764         RASTERFALLBACK(FILL_RECT, rect, color, VOID_ARG());
   851         RASTERFALLBACK(FILL_RECT, rect, color, VOID_ARG());
   765         d->lock();
   852         d->lock();
   766         QRasterPaintEngine::fillRect(rect, color);
   853         QRasterPaintEngine::fillRect(rect, color);
   767     } else {
   854     } else {
   768         d->setDFBColor(color);
   855         d->setDFBColor(color);
   802 
   889 
   803 QDirectFBPaintEnginePrivate::QDirectFBPaintEnginePrivate(QDirectFBPaintEngine *p)
   890 QDirectFBPaintEnginePrivate::QDirectFBPaintEnginePrivate(QDirectFBPaintEngine *p)
   804     : surface(0), antialiased(false), simplePen(false),
   891     : surface(0), antialiased(false), simplePen(false),
   805       transformationType(0), opacity(255),
   892       transformationType(0), opacity(255),
   806       clipType(ClipUnset), dfbDevice(0),
   893       clipType(ClipUnset), dfbDevice(0),
   807       compositionModeStatus(0), inClip(false), q(p)
   894       compositionModeStatus(0), isPremultiplied(false), inClip(false), q(p)
   808 {
   895 {
   809     fb = QDirectFBScreen::instance()->dfb();
   896     fb = QDirectFBScreen::instance()->dfb();
   810     surfaceCache = new SurfaceCache;
   897     surfaceCache = new SurfaceCache;
   811 }
   898 }
   812 
   899 
   817 
   904 
   818 bool QDirectFBPaintEnginePrivate::isSimpleBrush(const QBrush &brush) const
   905 bool QDirectFBPaintEnginePrivate::isSimpleBrush(const QBrush &brush) const
   819 {
   906 {
   820     return (brush.style() == Qt::NoBrush) || (brush.style() == Qt::SolidPattern && !antialiased);
   907     return (brush.style() == Qt::NoBrush) || (brush.style() == Qt::SolidPattern && !antialiased);
   821 }
   908 }
   822 
       
   823 bool QDirectFBPaintEnginePrivate::testCompositionMode(const QPen *pen, const QBrush *brush, const QColor *color) const
       
   824 {
       
   825     Q_ASSERT(!pen || pen->style() == Qt::NoPen || pen->style() == Qt::SolidLine);
       
   826     Q_ASSERT(!brush || brush->style() == Qt::NoBrush || brush->style() == Qt::SolidPattern);
       
   827     switch (compositionModeStatus & (QDirectFBPaintEnginePrivate::PorterDuff_SupportedOpaquePrimitives
       
   828                                      |QDirectFBPaintEnginePrivate::PorterDuff_SupportedPrimitives)) {
       
   829     case QDirectFBPaintEnginePrivate::PorterDuff_SupportedPrimitives:
       
   830         return true;
       
   831     case QDirectFBPaintEnginePrivate::PorterDuff_SupportedOpaquePrimitives:
       
   832         if (pen && pen->style() == Qt::SolidLine && pen->color().alpha() != 255)
       
   833             return false;
       
   834         if (brush) {
       
   835             if (brush->style() == Qt::SolidPattern && brush->color().alpha() != 255) {
       
   836                 return false;
       
   837             }
       
   838         } else if (color && color->alpha() != 255) {
       
   839             return false;
       
   840         }
       
   841         return true;
       
   842     case QDirectFBPaintEnginePrivate::PorterDuff_None:
       
   843         return false;
       
   844     default:
       
   845         // ### PorterDuff_SupportedOpaquePrimitives|PorterDuff_SupportedPrimitives can't be combined
       
   846         break;
       
   847     }
       
   848     Q_ASSERT(0);
       
   849     return false;
       
   850 }
       
   851 
       
   852 
   909 
   853 void QDirectFBPaintEnginePrivate::lock()
   910 void QDirectFBPaintEnginePrivate::lock()
   854 {
   911 {
   855     // 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
   856     // 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
   910     if (!surface)
   967     if (!surface)
   911         return;
   968         return;
   912 
   969 
   913     static const bool forceRasterFallBack = qgetenv("QT_DIRECTFB_FORCE_RASTER").toInt() > 0;
   970     static const bool forceRasterFallBack = qgetenv("QT_DIRECTFB_FORCE_RASTER").toInt() > 0;
   914     if (forceRasterFallBack) {
   971     if (forceRasterFallBack) {
   915         compositionModeStatus = 0;
   972         compositionModeStatus = PorterDuff_None;
   916         return;
   973         return;
   917     }
   974     }
   918 
   975 
   919     compositionModeStatus = PorterDuff_SupportedBlits;
   976     compositionModeStatus = PorterDuff_Supported|PorterDuff_PremultiplyColors|PorterDuff_AlwaysBlend;
   920     switch (mode) {
   977     switch (mode) {
   921     case QPainter::CompositionMode_Clear:
   978     case QPainter::CompositionMode_Clear:
   922         surface->SetPorterDuff(surface, DSPD_CLEAR);
   979         surface->SetPorterDuff(surface, DSPD_CLEAR);
   923         break;
   980         break;
   924     case QPainter::CompositionMode_Source:
   981     case QPainter::CompositionMode_Source:
   925         surface->SetPorterDuff(surface, DSPD_SRC);
   982         surface->SetPorterDuff(surface, DSPD_SRC);
   926         compositionModeStatus |= PorterDuff_SupportedOpaquePrimitives;
   983         compositionModeStatus &= ~PorterDuff_AlwaysBlend;
       
   984         if (!isPremultiplied)
       
   985             compositionModeStatus &= ~PorterDuff_PremultiplyColors;
   927         break;
   986         break;
   928     case QPainter::CompositionMode_SourceOver:
   987     case QPainter::CompositionMode_SourceOver:
   929         compositionModeStatus |= PorterDuff_SupportedPrimitives;
   988         compositionModeStatus &= ~PorterDuff_AlwaysBlend;
   930         surface->SetPorterDuff(surface, DSPD_SRC_OVER);
   989         surface->SetPorterDuff(surface, DSPD_SRC_OVER);
   931         break;
   990         break;
   932     case QPainter::CompositionMode_DestinationOver:
   991     case QPainter::CompositionMode_DestinationOver:
   933         surface->SetPorterDuff(surface, DSPD_DST_OVER);
   992         surface->SetPorterDuff(surface, DSPD_DST_OVER);
   934         break;
   993         break;
   935     case QPainter::CompositionMode_SourceIn:
   994     case QPainter::CompositionMode_SourceIn:
   936         surface->SetPorterDuff(surface, DSPD_SRC_IN);
   995         surface->SetPorterDuff(surface, DSPD_SRC_IN);
       
   996         if (!isPremultiplied)
       
   997             compositionModeStatus &= ~PorterDuff_PremultiplyColors;
   937         break;
   998         break;
   938     case QPainter::CompositionMode_DestinationIn:
   999     case QPainter::CompositionMode_DestinationIn:
   939         surface->SetPorterDuff(surface, DSPD_DST_IN);
  1000         surface->SetPorterDuff(surface, DSPD_DST_IN);
   940         break;
  1001         break;
   941     case QPainter::CompositionMode_SourceOut:
  1002     case QPainter::CompositionMode_SourceOut:
   942         surface->SetPorterDuff(surface, DSPD_SRC_OUT);
  1003         surface->SetPorterDuff(surface, DSPD_SRC_OUT);
   943         break;
  1004         break;
   944     case QPainter::CompositionMode_DestinationOut:
  1005     case QPainter::CompositionMode_DestinationOut:
   945         surface->SetPorterDuff(surface, DSPD_DST_OUT);
  1006         surface->SetPorterDuff(surface, DSPD_DST_OUT);
   946         break;
  1007         break;
       
  1008 #if (Q_DIRECTFB_VERSION >= 0x010209)
       
  1009     case QPainter::CompositionMode_Destination:
       
  1010         surface->SetPorterDuff(surface, DSPD_DST);
       
  1011         break;
       
  1012 #endif
   947 #if (Q_DIRECTFB_VERSION >= 0x010000)
  1013 #if (Q_DIRECTFB_VERSION >= 0x010000)
   948     case QPainter::CompositionMode_SourceAtop:
  1014     case QPainter::CompositionMode_SourceAtop:
   949         surface->SetPorterDuff(surface, DSPD_SRC_ATOP);
  1015         surface->SetPorterDuff(surface, DSPD_SRC_ATOP);
   950         break;
  1016         break;
   951     case QPainter::CompositionMode_DestinationAtop:
  1017     case QPainter::CompositionMode_DestinationAtop:
   957     case QPainter::CompositionMode_Xor:
  1023     case QPainter::CompositionMode_Xor:
   958         surface->SetPorterDuff(surface, DSPD_XOR);
  1024         surface->SetPorterDuff(surface, DSPD_XOR);
   959         break;
  1025         break;
   960 #endif
  1026 #endif
   961     default:
  1027     default:
   962         compositionModeStatus = 0;
  1028         compositionModeStatus = PorterDuff_None;
   963         break;
  1029         break;
   964     }
  1030     }
   965 }
  1031 }
   966 
  1032 
   967 void QDirectFBPaintEnginePrivate::setRenderHints(QPainter::RenderHints hints)
  1033 void QDirectFBPaintEnginePrivate::setRenderHints(QPainter::RenderHints hints)
   979     if (opacity != 255) {
  1045     if (opacity != 255) {
   980         blittingFlags |= DSBLIT_BLEND_COLORALPHA;
  1046         blittingFlags |= DSBLIT_BLEND_COLORALPHA;
   981     }
  1047     }
   982     surface->SetColor(surface, 0xff, 0xff, 0xff, opacity);
  1048     surface->SetColor(surface, 0xff, 0xff, 0xff, opacity);
   983     surface->SetBlittingFlags(surface, blittingFlags);
  1049     surface->SetBlittingFlags(surface, blittingFlags);
   984     if (compositionModeStatus & PorterDuff_Dirty) {
       
   985         setCompositionMode(q->state()->composition_mode);
       
   986     }
       
   987 }
  1050 }
   988 
  1051 
   989 static inline uint ALPHA_MUL(uint x, uint a)
  1052 static inline uint ALPHA_MUL(uint x, uint a)
   990 {
  1053 {
   991     uint t = x * a;
  1054     uint t = x * a;
   994 }
  1057 }
   995 
  1058 
   996 void QDirectFBPaintEnginePrivate::setDFBColor(const QColor &color)
  1059 void QDirectFBPaintEnginePrivate::setDFBColor(const QColor &color)
   997 {
  1060 {
   998     Q_ASSERT(surface);
  1061     Q_ASSERT(surface);
       
  1062     Q_ASSERT(compositionModeStatus & PorterDuff_Supported);
   999     const quint8 alpha = (opacity == 255 ?
  1063     const quint8 alpha = (opacity == 255 ?
  1000                           color.alpha() : ALPHA_MUL(color.alpha(), opacity));
  1064                           color.alpha() : ALPHA_MUL(color.alpha(), opacity));
  1001     surface->SetColor(surface, color.red(), color.green(), color.blue(), alpha);
  1065     QColor col;
  1002     surface->SetPorterDuff(surface, DSPD_NONE);
  1066     if (compositionModeStatus & PorterDuff_PremultiplyColors) {
  1003     surface->SetDrawingFlags(surface, alpha == 255 ? DSDRAW_NOFX : DSDRAW_BLEND);
  1067         col = QColor(ALPHA_MUL(color.red(), alpha),
  1004     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);
  1005 }
  1076 }
  1006 
  1077 
  1007 IDirectFBSurface *QDirectFBPaintEnginePrivate::getSurface(const QImage &img, bool *release)
  1078 IDirectFBSurface *QDirectFBPaintEnginePrivate::getSurface(const QImage &img, bool *release)
  1008 {
  1079 {
  1009 #ifdef QT_NO_DIRECTFB_IMAGECACHE
  1080 #ifdef QT_NO_DIRECTFB_IMAGECACHE
  1281         const QRect r = mapRect(transform, rects[i]);
  1352         const QRect r = mapRect(transform, rects[i]);
  1282         surface->DrawRectangle(surface, r.x(), r.y(), r.width(), r.height());
  1353         surface->DrawRectangle(surface, r.x(), r.y(), r.width(), r.height());
  1283     }
  1354     }
  1284 }
  1355 }
  1285 
  1356 
  1286 #ifdef QT_DIRECTFB_WARN_ON_RASTERFALLBACKS
  1357 #if defined QT_DIRECTFB_WARN_ON_RASTERFALLBACKS || defined QT_DEBUG
  1287 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; }
  1288 template <> inline const bool* ptr<bool>(const bool &) { return 0; }
  1359 template <> inline const bool* ptr<bool>(const bool &) { return 0; }
  1289 template <typename device, typename T1, typename T2, typename T3>
  1360 template <typename device, typename T1, typename T2, typename T3>
  1290 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,
  1291                                uint transformationType, bool simplePen,
  1362                                uint transformationType, bool simplePen,