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 <eirik.aavitsland@qt.io>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
Allan Sandfeld Jensen 2019-08-15 11:48:11 +02:00
parent 2737b5e36a
commit 21ba294345
2 changed files with 29 additions and 27 deletions

View File

@ -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);
const QRasterPaintEngineState *s = q->state();
if (!s->flags.fast_images || s->intOpacity != 256 || qt_depthForFormat(rasterBuffer->format) < 8)
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->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)

View File

@ -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<QOutlineMapper> outlineMapper;