Skip to content

Commit

Permalink
Optimize blits of any compatible formats
Browse files Browse the repository at this point in the history
The fast image blending is only used for SourceOver composition, but
several of our embedded backends make heavy use of Source composition
which doesn't have a short-cut. This patch adds a blitting short cut
that works in those cases.

Task-number: QTBUG-69724
Change-Id: Icc61a67cc27bc83863153d69cae60dd986d26f69
Reviewed-by: Lars Knoll <[email protected]>
  • Loading branch information
Allan Sandfeld Jensen committed Aug 3, 2018
1 parent d2d59e7 commit cdf154e
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 2 deletions.
119 changes: 117 additions & 2 deletions src/gui/painting/qpaintengine_raster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1056,6 +1056,77 @@ void QRasterPaintEnginePrivate::drawImage(const QPointF &pt,
alpha);
}

void QRasterPaintEnginePrivate::blitImage(const QPointF &pt,
const QImage &img,
const QRect &clip,
const QRect &sr)
{
if (!clip.isValid())
return;

Q_ASSERT(img.depth() >= 8);

qsizetype srcBPL = img.bytesPerLine();
const uchar *srcBits = img.bits();
int srcSize = img.depth() >> 3; // This is the part that is incompatible with lower than 8-bit..
int iw = img.width();
int ih = img.height();

if (!sr.isEmpty()) {
iw = sr.width();
ih = sr.height();
// Adjust the image according to the source offset...
srcBits += ((sr.y() * srcBPL) + sr.x() * srcSize);
}

// adapt the x parameters
int x = qRound(pt.x());
int cx1 = clip.x();
int cx2 = clip.x() + clip.width();
if (x < cx1) {
int d = cx1 - x;
srcBits += srcSize * d;
iw -= d;
x = cx1;
}
if (x + iw > cx2) {
int d = x + iw - cx2;
iw -= d;
}
if (iw <= 0)
return;

// adapt the y paremeters...
int cy1 = clip.y();
int cy2 = clip.y() + clip.height();
int y = qRound(pt.y());
if (y < cy1) {
int d = cy1 - y;
srcBits += srcBPL * d;
ih -= d;
y = cy1;
}
if (y + ih > cy2) {
int d = y + ih - cy2;
ih -= d;
}
if (ih <= 0)
return;

// blit..
int dstSize = rasterBuffer->bytesPerPixel();
qsizetype dstBPL = rasterBuffer->bytesPerLine();
const uint *src = (const uint *) srcBits;
uint *dst = reinterpret_cast<uint *>(rasterBuffer->buffer() + x * dstSize + y * dstBPL);

const int len = iw * (qt_depthForFormat(rasterBuffer->format) >> 3);
for (int y = 0; y < ih; ++y) {
memcpy(dst, src, len);
dst = (quint32 *)(((uchar *) dst) + dstBPL);
src = (const quint32 *)(((const uchar *) src) + srcBPL);
}
}


void QRasterPaintEnginePrivate::systemStateChanged()
{
Expand Down Expand Up @@ -2160,7 +2231,15 @@ 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->canUseFastImageBlending(d->rasterBuffer->compositionMode, img)) {
if (d->canUseImageBlitting(d->rasterBuffer->compositionMode, img)) {
if (!clip) {
d->blitImage(pt, img, d->deviceRect);
return;
} else if (clip->hasRectClip) {
d->blitImage(pt, img, clip->clipRect);
return;
}
} else if (d->canUseFastImageBlending(d->rasterBuffer->compositionMode, img)) {
SrcOverBlendFunc func = qBlendFunctions[d->rasterBuffer->format][img.format()];
if (func) {
if (!clip) {
Expand Down Expand Up @@ -2445,7 +2524,16 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe
fillPath(path, &d->image_filler_xform);
s->matrix = m;
} else {
if (d->canUseFastImageBlending(d->rasterBuffer->compositionMode, img)) {
if (d->canUseImageBlitting(d->rasterBuffer->compositionMode, img)) {
QPointF pt(r.x() + s->matrix.dx(), r.y() + s->matrix.dy());
if (!clip) {
d->blitImage(pt, img, d->deviceRect, sr.toRect());
return;
} else if (clip->hasRectClip) {
d->blitImage(pt, img, clip->clipRect, sr.toRect());
return;
}
} 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());
Expand Down Expand Up @@ -3665,6 +3753,33 @@ bool QRasterPaintEnginePrivate::canUseFastImageBlending(QPainter::CompositionMod
&& !image.hasAlphaChannel()));
}

bool QRasterPaintEnginePrivate::canUseImageBlitting(QPainter::CompositionMode mode, const QImage &image) const
{
Q_Q(const QRasterPaintEngine);
const QRasterPaintEngineState *s = q->state();

if (!s->flags.fast_images || s->intOpacity != 256 || qt_depthForFormat(rasterBuffer->format) < 8)
return false;

QImage::Format dFormat = rasterBuffer->format;
QImage::Format sFormat = image.format();
// 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 = 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()));
}

QImage QRasterBuffer::colorizeBitmap(const QImage &image, const QColor &color)
{
Q_ASSERT(image.depth() == 1);
Expand Down
3 changes: 3 additions & 0 deletions src/gui/painting/qpaintengine_raster_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,8 @@ class QRasterPaintEnginePrivate : public QPaintEngineExPrivate

void drawImage(const QPointF &pt, const QImage &img, SrcOverBlendFunc func,
const QRect &clip, int alpha, const QRect &sr = QRect());
void blitImage(const QPointF &pt, const QImage &img,
const QRect &clip, const QRect &sr = QRect());

QTransform brushMatrix() const {
Q_Q(const QRasterPaintEngine);
Expand All @@ -313,6 +315,7 @@ class QRasterPaintEnginePrivate : public QPaintEngineExPrivate

void recalculateFastImages();
bool canUseFastImageBlending(QPainter::CompositionMode mode, const QImage &image) const;
bool canUseImageBlitting(QPainter::CompositionMode mode, const QImage &image) const;

QPaintDevice *device;
QScopedPointer<QOutlineMapper> outlineMapper;
Expand Down

0 comments on commit cdf154e

Please sign in to comment.