Optimize blits of any compatible formats
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 <lars.knoll@qt.io>
This commit is contained in:
parent
d2d59e77d5
commit
cdf154e65a
@ -1056,6 +1056,77 @@ void QRasterPaintEnginePrivate::drawImage(const QPointF &pt,
|
|||||||
alpha);
|
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()
|
void QRasterPaintEnginePrivate::systemStateChanged()
|
||||||
{
|
{
|
||||||
@ -2160,7 +2231,15 @@ void QRasterPaintEngine::drawImage(const QPointF &p, const QImage &img)
|
|||||||
const QClipData *clip = d->clip();
|
const QClipData *clip = d->clip();
|
||||||
QPointF pt(p.x() + s->matrix.dx(), p.y() + s->matrix.dy());
|
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()];
|
SrcOverBlendFunc func = qBlendFunctions[d->rasterBuffer->format][img.format()];
|
||||||
if (func) {
|
if (func) {
|
||||||
if (!clip) {
|
if (!clip) {
|
||||||
@ -2445,7 +2524,16 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe
|
|||||||
fillPath(path, &d->image_filler_xform);
|
fillPath(path, &d->image_filler_xform);
|
||||||
s->matrix = m;
|
s->matrix = m;
|
||||||
} else {
|
} 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()];
|
SrcOverBlendFunc func = qBlendFunctions[d->rasterBuffer->format][img.format()];
|
||||||
if (func) {
|
if (func) {
|
||||||
QPointF pt(r.x() + s->matrix.dx(), r.y() + s->matrix.dy());
|
QPointF pt(r.x() + s->matrix.dx(), r.y() + s->matrix.dy());
|
||||||
@ -3665,6 +3753,33 @@ bool QRasterPaintEnginePrivate::canUseFastImageBlending(QPainter::CompositionMod
|
|||||||
&& !image.hasAlphaChannel()));
|
&& !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)
|
QImage QRasterBuffer::colorizeBitmap(const QImage &image, const QColor &color)
|
||||||
{
|
{
|
||||||
Q_ASSERT(image.depth() == 1);
|
Q_ASSERT(image.depth() == 1);
|
||||||
|
@ -291,6 +291,8 @@ public:
|
|||||||
|
|
||||||
void drawImage(const QPointF &pt, const QImage &img, SrcOverBlendFunc func,
|
void drawImage(const QPointF &pt, const QImage &img, SrcOverBlendFunc func,
|
||||||
const QRect &clip, int alpha, const QRect &sr = QRect());
|
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 {
|
QTransform brushMatrix() const {
|
||||||
Q_Q(const QRasterPaintEngine);
|
Q_Q(const QRasterPaintEngine);
|
||||||
@ -313,6 +315,7 @@ public:
|
|||||||
|
|
||||||
void recalculateFastImages();
|
void recalculateFastImages();
|
||||||
bool canUseFastImageBlending(QPainter::CompositionMode mode, const QImage &image) const;
|
bool canUseFastImageBlending(QPainter::CompositionMode mode, const QImage &image) const;
|
||||||
|
bool canUseImageBlitting(QPainter::CompositionMode mode, const QImage &image) const;
|
||||||
|
|
||||||
QPaintDevice *device;
|
QPaintDevice *device;
|
||||||
QScopedPointer<QOutlineMapper> outlineMapper;
|
QScopedPointer<QOutlineMapper> outlineMapper;
|
||||||
|
Loading…
Reference in New Issue
Block a user