From 21ba294345377ad991a9c9bd8d51cd71094411b8 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Thu, 15 Aug 2019 11:48:11 +0200 Subject: Merge memrotate and blit feasability checks Besides reducing duplicate code, this also improves the checks by sharing optimized checks: 1. Fast memrotate will now also trigger with compatible formats (RGB32 over ARGB32) 2. Fast blitting will now also trigger with smooth transforms enabled, if the coordinates are pixel aligned. Change-Id: I576ebb34646d62ed472b1e1772e1b876b8121634 Reviewed-by: Eirik Aavitsland Reviewed-by: Lars Knoll --- src/gui/painting/qpaintengine_raster.cpp | 52 +++++++++++++++++--------------- src/gui/painting/qpaintengine_raster_p.h | 2 +- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 5ab5514dd4..9894da8fe1 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -2214,7 +2214,7 @@ void QRasterPaintEngine::drawImage(const QPointF &p, const QImage &img) const QClipData *clip = d->clip(); QPointF pt(p.x() + s->matrix.dx(), p.y() + s->matrix.dy()); - if (d->canUseImageBlitting(d->rasterBuffer->compositionMode, img)) { + if (d->canUseImageBlitting(d->rasterBuffer->compositionMode, img, pt, img.rect())) { if (!clip) { d->blitImage(pt, img, d->deviceRect); return; @@ -2285,7 +2285,12 @@ namespace { return NoRotation; } - inline bool isPixelAligned(const QRectF &rect) { + inline bool isPixelAligned(const QPointF &pt) + { + return QPointF(pt.toPoint()) == pt; + } + inline bool isPixelAligned(const QRectF &rect) + { return QRectF(rect.toRect()) == rect; } } @@ -2353,17 +2358,12 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe const QClipData *clip = d->clip(); - if (s->matrix.type() > QTransform::TxTranslate + if (s->matrix.type() == QTransform::TxRotate && !stretch_sr && (!clip || clip->hasRectClip) && s->intOpacity == 256 && (d->rasterBuffer->compositionMode == QPainter::CompositionMode_SourceOver - || d->rasterBuffer->compositionMode == QPainter::CompositionMode_Source) - && d->rasterBuffer->format == img.format() - && (d->rasterBuffer->format == QImage::Format_RGB16 - || d->rasterBuffer->format == QImage::Format_RGB32 - || (d->rasterBuffer->format == QImage::Format_ARGB32_Premultiplied - && d->rasterBuffer->compositionMode == QPainter::CompositionMode_Source))) + || d->rasterBuffer->compositionMode == QPainter::CompositionMode_Source)) { RotationType rotationType = qRotationType(s->matrix); const QPixelLayout::BPP plBpp = qPixelLayouts[d->rasterBuffer->format].bpp; @@ -2371,9 +2371,7 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe if (rotationType != NoRotation && qMemRotateFunctions[plBpp][rotationType] && img.rect().contains(sr.toAlignedRect())) { QRectF transformedTargetRect = s->matrix.mapRect(r); - if ((!(s->renderHints & QPainter::SmoothPixmapTransform) && !(s->renderHints & QPainter::Antialiasing)) - || (isPixelAligned(transformedTargetRect) && isPixelAligned(sr))) - { + if (d->canUseImageBlitting(d->rasterBuffer->compositionMode, img, transformedTargetRect.topRight(), sr)) { QRect clippedTransformedTargetRect = transformedTargetRect.toRect().intersected(clip ? clip->clipRect : d->deviceRect); if (clippedTransformedTargetRect.isNull()) return; @@ -2507,8 +2505,8 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe fillPath(path, &d->image_filler_xform); s->matrix = m; } else { - if (d->canUseImageBlitting(d->rasterBuffer->compositionMode, img)) { - QPointF pt(r.x() + s->matrix.dx(), r.y() + s->matrix.dy()); + QPointF pt(r.x() + s->matrix.dx(), r.y() + s->matrix.dy()); + if (d->canUseImageBlitting(d->rasterBuffer->compositionMode, img, pt, sr)) { if (!clip) { d->blitImage(pt, img, d->deviceRect, sr.toRect()); return; @@ -2519,7 +2517,6 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe } else if (d->canUseFastImageBlending(d->rasterBuffer->compositionMode, img)) { SrcOverBlendFunc func = qBlendFunctions[d->rasterBuffer->format][img.format()]; if (func) { - QPointF pt(r.x() + s->matrix.dx(), r.y() + s->matrix.dy()); if (!clip) { d->drawImage(pt, img, func, d->deviceRect, s->intOpacity, sr.toRect()); return; @@ -3754,12 +3751,22 @@ bool QRasterPaintEnginePrivate::canUseFastImageBlending(QPainter::CompositionMod && !image.hasAlphaChannel())); } -bool QRasterPaintEnginePrivate::canUseImageBlitting(QPainter::CompositionMode mode, const QImage &image) const +bool QRasterPaintEnginePrivate::canUseImageBlitting(QPainter::CompositionMode mode, const QImage &image, const QPointF &pt, const QRectF &sr) const { Q_Q(const QRasterPaintEngine); + + if (!(mode == QPainter::CompositionMode_Source + || (mode == QPainter::CompositionMode_SourceOver + && !image.hasAlphaChannel()))) + return false; + const QRasterPaintEngineState *s = q->state(); + Q_ASSERT(s->matrix.type() <= QTransform::TxTranslate || s->matrix.type() == QTransform::TxRotate); - if (!s->flags.fast_images || s->intOpacity != 256 || qt_depthForFormat(rasterBuffer->format) < 8) + if (s->intOpacity != 256 + || image.depth() < 8 + || ((s->renderHints & (QPainter::SmoothPixmapTransform | QPainter::Antialiasing)) + && (!isPixelAligned(pt) || !isPixelAligned(sr)))) return false; QImage::Format dFormat = rasterBuffer->format; @@ -3767,18 +3774,13 @@ bool QRasterPaintEnginePrivate::canUseImageBlitting(QPainter::CompositionMode mo // Formats must match or source format must be a subset of destination format if (dFormat != sFormat && image.pixelFormat().alphaUsage() == QPixelFormat::IgnoresAlpha) { if ((sFormat == QImage::Format_RGB32 && dFormat == QImage::Format_ARGB32) - || (sFormat == QImage::Format_RGBX8888 && dFormat == QImage::Format_RGBA8888)) + || (sFormat == QImage::Format_RGBX8888 && dFormat == QImage::Format_RGBA8888) + || (sFormat == QImage::Format_RGBX64 && dFormat == QImage::Format_RGBA64)) sFormat = dFormat; else sFormat = qt_maybeAlphaVersionWithSameDepth(sFormat); // this returns premul formats } - if (dFormat != sFormat) - return false; - - return s->matrix.type() <= QTransform::TxTranslate - && (mode == QPainter::CompositionMode_Source - || (mode == QPainter::CompositionMode_SourceOver - && !image.hasAlphaChannel())); + return (dFormat == sFormat); } QImage QRasterBuffer::colorizeBitmap(const QImage &image, const QColor &color) diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h index ec4a35087a..089aadc3f7 100644 --- a/src/gui/painting/qpaintengine_raster_p.h +++ b/src/gui/painting/qpaintengine_raster_p.h @@ -306,7 +306,7 @@ public: void recalculateFastImages(); bool canUseFastImageBlending(QPainter::CompositionMode mode, const QImage &image) const; - bool canUseImageBlitting(QPainter::CompositionMode mode, const QImage &image) const; + bool canUseImageBlitting(QPainter::CompositionMode mode, const QImage &image, const QPointF &pt, const QRectF &sr) const; QPaintDevice *device; QScopedPointer outlineMapper; -- cgit v1.2.3