Generalize fill span optimization

This was added to RGB64 rendering because pixel conversions could be
expensive, but when painting to non-standard imageformats, the same
can also be expensive in the generic 32-bit backend, and thus benefit
from the optimization as well.

Change-Id: I747a398670b1d4dbd844a772e7aafce3c8dbef20
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
This commit is contained in:
Allan Sandfeld Jensen 2018-11-13 13:44:28 +01:00
parent 6e34552638
commit c340b0b279

View File

@ -4280,7 +4280,7 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in
}
++spans;
}
if (!alphaSpans) {
if (!alphaSpans && spanCount > 0) {
// If all spans are opaque we do not need to fetch dest.
// But don't clear passthrough destFetch as they are just as fast and save destStore.
if (op.destFetch != destFetchARGB32P)
@ -4301,23 +4301,62 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in
return op;
}
static void spanfill_from_first(QRasterBuffer *rasterBuffer, QPixelLayout::BPP bpp, int x, int y, int length)
{
switch (bpp) {
case QPixelLayout::BPP64: {
quint64 *dest = reinterpret_cast<quint64 *>(rasterBuffer->scanLine(y)) + x;
qt_memfill_template(dest + 1, dest[0], length - 1);
break;
}
case QPixelLayout::BPP32: {
quint32 *dest = reinterpret_cast<quint32 *>(rasterBuffer->scanLine(y)) + x;
qt_memfill_template(dest + 1, dest[0], length - 1);
break;
}
case QPixelLayout::BPP24: {
quint24 *dest = reinterpret_cast<quint24 *>(rasterBuffer->scanLine(y)) + x;
qt_memfill_template(dest + 1, dest[0], length - 1);
break;
}
case QPixelLayout::BPP16: {
quint16 *dest = reinterpret_cast<quint16 *>(rasterBuffer->scanLine(y)) + x;
qt_memfill_template(dest + 1, dest[0], length - 1);
break;
}
case QPixelLayout::BPP8: {
uchar *dest = rasterBuffer->scanLine(y) + x;
memset(dest + 1, dest[0], length - 1);
break;
}
default:
Q_UNREACHABLE();
}
}
// -------------------- blend methods ---------------------
#if !defined(Q_CC_SUN)
static
#endif
void blend_color_generic(int count, const QSpan *spans, void *userData)
static void blend_color_generic(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
uint buffer[BufferSize];
Operator op = getOperator(data, spans, count);
Operator op = getOperator(data, nullptr, 0);
const uint color = data->solidColor.toArgb32();
bool solidFill = data->rasterBuffer->compositionMode == QPainter::CompositionMode_Source
|| (data->rasterBuffer->compositionMode == QPainter::CompositionMode_SourceOver && qAlpha(color) == 255);
QPixelLayout::BPP bpp = qPixelLayouts[data->rasterBuffer->format].bpp;
while (count--) {
int x = spans->x;
int length = spans->len;
if (solidFill && bpp >= QPixelLayout::BPP8 && spans->coverage == 255 && length) {
// If dest doesn't matter we don't need to bother with blending or converting all the identical pixels
op.destStore(data->rasterBuffer, x, spans->y, &color, 1);
spanfill_from_first(data->rasterBuffer, bpp, x, spans->y, length);
length = 0;
}
while (length) {
int l = qMin(BufferSize, length);
uint *dest = op.destFetch(buffer, data->rasterBuffer, x, spans->y, l);
@ -4335,7 +4374,7 @@ static void blend_color_argb(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
const Operator op = getOperator(data, spans, count);
const Operator op = getOperator(data, nullptr, 0);
const uint color = data->solidColor.toArgb32();
if (op.mode == QPainter::CompositionMode_Source) {
@ -4365,7 +4404,7 @@ static void blend_color_argb(int count, const QSpan *spans, void *userData)
void blend_color_generic_rgb64(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
Operator op = getOperator(data, spans, count);
Operator op = getOperator(data, nullptr, 0);
if (!op.funcSolid64) {
qCDebug(lcQtGuiDrawHelper, "blend_color_generic_rgb64: unsupported 64bit blend attempted, falling back to 32-bit");
return blend_color_generic(count, spans, userData);
@ -4375,19 +4414,16 @@ void blend_color_generic_rgb64(int count, const QSpan *spans, void *userData)
const QRgba64 color = data->solidColor;
bool solidFill = data->rasterBuffer->compositionMode == QPainter::CompositionMode_Source
|| (data->rasterBuffer->compositionMode == QPainter::CompositionMode_SourceOver && color.isOpaque());
bool isBpp32 = qPixelLayouts[data->rasterBuffer->format].bpp == QPixelLayout::BPP32;
QPixelLayout::BPP bpp = qPixelLayouts[data->rasterBuffer->format].bpp;
while (count--) {
int x = spans->x;
int length = spans->len;
if (solidFill && isBpp32 && spans->coverage == 255) {
if (solidFill && bpp >= QPixelLayout::BPP8 && spans->coverage == 255 && length) {
// If dest doesn't matter we don't need to bother with blending or converting all the identical pixels
if (length > 0) {
op.destStore64(data->rasterBuffer, x, spans->y, &color, 1);
uint *dest = (uint*)data->rasterBuffer->scanLine(spans->y) + x;
qt_memfill32(dest + 1, dest[0], length - 1);
length = 0;
}
op.destStore64(data->rasterBuffer, x, spans->y, &color, 1);
spanfill_from_first(data->rasterBuffer, bpp, x, spans->y, length);
length = 0;
}
while (length) {