diff options
Diffstat (limited to 'src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp')
-rw-r--r-- | src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp | 86 |
1 files changed, 63 insertions, 23 deletions
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp index 4869eba55e..ceed7aeb59 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp @@ -55,6 +55,7 @@ #include <private/qpixmap_raster_p.h> #include <private/qimagepixmapcleanuphooks_p.h> + QT_BEGIN_NAMESPACE class SurfaceCache; @@ -67,6 +68,15 @@ public: Matrix_BlitsUnsupported = (Matrix_NegativeScale|Matrix_RectsUnsupported) }; + inline static uint getTransformationType(const QTransform &transform) + { + int ret = transform.type(); + if (qMin(transform.m11(), transform.m22()) < 0) { + ret |= QDirectFBPaintEnginePrivate::Matrix_NegativeScale; + } + return ret; + } + enum CompositionModeStatus { PorterDuff_None = 0x0, PorterDuff_Supported = 0x1, @@ -98,7 +108,7 @@ public: inline bool isSimpleBrush(const QBrush &brush) const; - void drawTiledPixmap(const QRectF &dest, const QPixmap &pixmap, const QPointF &pos); + void drawTiledPixmap(const QRectF &dest, const QPixmap &pixmap, const QPointF &pos, const QTransform &pixmapTransform); void blit(const QRectF &dest, IDirectFBSurface *surface, const QRectF &src); inline bool supportsStretchBlit() const; @@ -112,7 +122,11 @@ public: static inline int cacheCost(const QImage &img) { return img.width() * img.height() * img.depth() / 8; } #endif - void prepareForBlit(bool alpha); + enum BlitFlag { + HasAlpha = 0x1, + Premultiplied = 0x2 + }; + void prepareForBlit(uint blitFlags); IDirectFBSurface *surface; @@ -616,7 +630,12 @@ void QDirectFBPaintEngine::drawImage(const QRectF &r, const QImage &image, #if !defined QT_NO_DIRECTFB_PREALLOCATED || defined QT_DIRECTFB_IMAGECACHE bool release; IDirectFBSurface *imgSurface = d->getSurface(image, &release); - d->prepareForBlit(QDirectFBScreen::hasAlphaChannel(imgSurface)); + uint blitFlags = 0; + if (image.hasAlphaChannel()) + blitFlags |= QDirectFBPaintEnginePrivate::HasAlpha; + if (QDirectFBScreen::isPremultiplied(image.format())) + blitFlags |= QDirectFBPaintEnginePrivate::Premultiplied; + d->prepareForBlit(blitFlags); CLIPPED_PAINT(d->blit(r, imgSurface, sr)); if (release) { #if (Q_DIRECTFB_VERSION >= 0x010000) @@ -655,8 +674,14 @@ void QDirectFBPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pixmap, QRasterPaintEngine::drawImage(r, *img, sr); } else { QDirectFBPaintEnginePrivate::unlock(dfbData); - d->prepareForBlit(pixmap.hasAlphaChannel()); IDirectFBSurface *s = dfbData->directFBSurface(); + uint blitFlags = 0; + if (pixmap.hasAlphaChannel()) + blitFlags |= QDirectFBPaintEnginePrivate::HasAlpha; + if (QDirectFBScreen::isPremultiplied(dfbData->pixelFormat())) + blitFlags |= QDirectFBPaintEnginePrivate::Premultiplied; + + d->prepareForBlit(blitFlags); CLIPPED_PAINT(d->blit(r, s, sr)); } } @@ -691,7 +716,8 @@ void QDirectFBPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap pix(data); QRasterPaintEngine::drawTiledPixmap(r, pix, offset); } else { - CLIPPED_PAINT(d->drawTiledPixmap(r, pixmap, offset)); + QTransform transform(state()->matrix); + CLIPPED_PAINT(d->drawTiledPixmap(r, pixmap, offset, transform)); } } @@ -811,9 +837,14 @@ void QDirectFBPaintEngine::fillRect(const QRectF &rect, const QBrush &brush) return; } case Qt::TexturePattern: { + const QPointF &brushOrigin = state()->brushOrigin; + const QTransform stateTransform = state()->matrix; + QTransform transform(stateTransform); + transform.translate(brushOrigin.x(), brushOrigin.y()); + transform = brush.transform() * transform; if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported) - || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported) - || (!d->supportsStretchBlit() && state()->matrix.isScaling())) { + || (QDirectFBPaintEnginePrivate::getTransformationType(transform) & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported) + || (!d->supportsStretchBlit() && transform.isScaling())) { break; } @@ -821,7 +852,7 @@ void QDirectFBPaintEngine::fillRect(const QRectF &rect, const QBrush &brush) if (texture.pixmapData()->classId() != QPixmapData::DirectFBClass) break; - CLIPPED_PAINT(d->drawTiledPixmap(rect, texture, rect.topLeft() - state()->brushOrigin)); + CLIPPED_PAINT(d->drawTiledPixmap(stateTransform.mapRect(rect), texture, rect.topLeft() - brushOrigin, transform)); return; } default: break; @@ -932,10 +963,7 @@ void QDirectFBPaintEnginePrivate::unlock(QDirectFBPaintDevice *device) void QDirectFBPaintEnginePrivate::setTransform(const QTransform &transform) { - transformationType = transform.type(); - if (qMin(transform.m11(), transform.m22()) < 0) { - transformationType |= QDirectFBPaintEnginePrivate::Matrix_NegativeScale; - } + transformationType = getTransformationType(transform); setPen(q->state()->pen); } @@ -978,7 +1006,7 @@ void QDirectFBPaintEnginePrivate::setCompositionMode(QPainter::CompositionMode m break; case QPainter::CompositionMode_SourceOver: compositionModeStatus &= ~PorterDuff_AlwaysBlend; - surface->SetPorterDuff(surface, DSPD_NONE); + surface->SetPorterDuff(surface, DSPD_SRC_OVER); break; case QPainter::CompositionMode_DestinationOver: surface->SetPorterDuff(surface, DSPD_DST_OVER); @@ -1031,13 +1059,18 @@ void QDirectFBPaintEnginePrivate::setRenderHints(QPainter::RenderHints hints) } } -void QDirectFBPaintEnginePrivate::prepareForBlit(bool alpha) +void QDirectFBPaintEnginePrivate::prepareForBlit(uint flags) { - DFBSurfaceBlittingFlags blittingFlags = alpha ? DSBLIT_BLEND_ALPHACHANNEL : DSBLIT_NOFX; + DFBSurfaceBlittingFlags blittingFlags = DSBLIT_NOFX; + if (flags & Premultiplied) + blittingFlags |= DSBLIT_SRC_PREMULTIPLY; + if (flags & HasAlpha) + blittingFlags |= DSBLIT_BLEND_ALPHACHANNEL; if (opacity != 255) { blittingFlags |= DSBLIT_BLEND_COLORALPHA; + surface->SetColor(surface, 0xff, 0xff, 0xff, opacity); } - surface->SetColor(surface, 0xff, 0xff, 0xff, opacity); + surface->SetBlittingFlags(surface, blittingFlags); } @@ -1132,10 +1165,12 @@ static inline qreal fixCoord(qreal rect_pos, qreal pixmapSize, qreal offset) return pos; } -void QDirectFBPaintEnginePrivate::drawTiledPixmap(const QRectF &dest, const QPixmap &pixmap, const QPointF &off) +void QDirectFBPaintEnginePrivate::drawTiledPixmap(const QRectF &dest, const QPixmap &pixmap, + const QPointF &off, const QTransform &pixmapTransform) { - Q_ASSERT(!(transformationType & Matrix_BlitsUnsupported)); const QTransform &transform = q->state()->matrix; + Q_ASSERT(!(getTransformationType(transform) & Matrix_BlitsUnsupported) && + !(getTransformationType(pixmapTransform) & Matrix_BlitsUnsupported)); const QRect destinationRect = transform.mapRect(dest).toRect().normalized(); QRect newClip = destinationRect; if (!currentClip.isEmpty()) @@ -1152,22 +1187,27 @@ void QDirectFBPaintEnginePrivate::drawTiledPixmap(const QRectF &dest, const QPix }; surface->SetClip(surface, &clip); - QPointF offset = off; + QPointF offset = pixmapTransform.inverted().map(off); Q_ASSERT(transform.type() <= QTransform::TxScale); - prepareForBlit(pixmap.hasAlphaChannel()); QPixmapData *data = pixmap.pixmapData(); Q_ASSERT(data->classId() == QPixmapData::DirectFBClass); QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(data); + IDirectFBSurface *sourceSurface = dfbData->directFBSurface(); + uint blitFlags = 0; + if (dfbData->hasAlphaChannel()) + blitFlags |= HasAlpha; + if (QDirectFBScreen::isPremultiplied(dfbData->pixelFormat())) + blitFlags |= Premultiplied; + prepareForBlit(blitFlags); QDirectFBPaintEnginePrivate::unlock(dfbData); const QSize pixmapSize = dfbData->size(); - IDirectFBSurface *sourceSurface = dfbData->directFBSurface(); - if (transform.isScaling()) { + if (transform.isScaling() || pixmapTransform.isScaling()) { Q_ASSERT(supportsStretchBlit()); Q_ASSERT(qMin(transform.m11(), transform.m22()) >= 0); offset.rx() *= transform.m11(); offset.ry() *= transform.m22(); - const QSizeF mappedSize(pixmapSize.width() * transform.m11(), pixmapSize.height() * transform.m22()); + const QSizeF mappedSize(pixmapSize.width() * pixmapTransform.m11(), pixmapSize.height() * pixmapTransform.m22()); qreal y = fixCoord(destinationRect.y(), mappedSize.height(), offset.y()); const qreal startX = fixCoord(destinationRect.x(), mappedSize.width(), offset.x()); while (y <= destinationRect.bottom()) { |