Raster paint engine: optimize rect clipping
More aggressively skip processing empty spans. Tested with the qpainter benchmark on armv7; yields small but measurable improvement. Change-Id: Ie0ed0f824a0be7bcc2de3a9aa98ebccb0e8accae Reviewed-by: Lars Knoll <lars.knoll@qt.io> Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
parent
3797704c4f
commit
dd5b829468
|
|
@ -4419,7 +4419,9 @@ static void blend_color_rgb16(int count, const QSpan *spans, void *userData)
|
|||
if (mode == QPainter::CompositionMode_Source) {
|
||||
// inline for performance
|
||||
ushort c = data->solid.color.toRgb16();
|
||||
while (count--) {
|
||||
for (; count--; spans++) {
|
||||
if (!spans->len)
|
||||
continue;
|
||||
ushort *target = ((ushort *)data->rasterBuffer->scanLine(spans->y)) + spans->x;
|
||||
if (spans->coverage == 255) {
|
||||
QT_MEMFILL_USHORT(target, spans->len, c);
|
||||
|
|
@ -4432,13 +4434,14 @@ static void blend_color_rgb16(int count, const QSpan *spans, void *userData)
|
|||
++target;
|
||||
}
|
||||
}
|
||||
++spans;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode == QPainter::CompositionMode_SourceOver) {
|
||||
while (count--) {
|
||||
for (; count--; spans++) {
|
||||
if (!spans->len)
|
||||
continue;
|
||||
uint color = BYTE_MUL(data->solid.color.toArgb32(), spans->coverage);
|
||||
int ialpha = qAlpha(~color);
|
||||
ushort c = qConvertRgb32To16(color);
|
||||
|
|
@ -4470,7 +4473,6 @@ static void blend_color_rgb16(int count, const QSpan *spans, void *userData)
|
|||
// one last pixel beyond a full word
|
||||
*target = c + BYTE_MUL_RGB16(*target, ialpha);
|
||||
}
|
||||
++spans;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -4487,6 +4489,11 @@ void handleSpans(int count, const QSpan *spans, const QSpanData *data, T &handle
|
|||
|
||||
int coverage = 0;
|
||||
while (count) {
|
||||
if (!spans->len) {
|
||||
++spans;
|
||||
--count;
|
||||
continue;
|
||||
}
|
||||
int x = spans->x;
|
||||
const int y = spans->y;
|
||||
int right = x + spans->len;
|
||||
|
|
@ -4639,7 +4646,9 @@ static void blend_untransformed_generic(int count, const QSpan *spans, void *use
|
|||
int xoff = -qRound(-data->dx);
|
||||
int yoff = -qRound(-data->dy);
|
||||
|
||||
while (count--) {
|
||||
for (; count--; spans++) {
|
||||
if (!spans->len)
|
||||
continue;
|
||||
int x = spans->x;
|
||||
int length = spans->len;
|
||||
int sx = xoff + x;
|
||||
|
|
@ -4667,7 +4676,6 @@ static void blend_untransformed_generic(int count, const QSpan *spans, void *use
|
|||
}
|
||||
}
|
||||
}
|
||||
++spans;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4688,7 +4696,9 @@ static void blend_untransformed_generic_rgb64(int count, const QSpan *spans, voi
|
|||
int xoff = -qRound(-data->dx);
|
||||
int yoff = -qRound(-data->dy);
|
||||
|
||||
while (count--) {
|
||||
for (; count--; spans++) {
|
||||
if (!spans->len)
|
||||
continue;
|
||||
int x = spans->x;
|
||||
int length = spans->len;
|
||||
int sx = xoff + x;
|
||||
|
|
@ -4716,7 +4726,6 @@ static void blend_untransformed_generic_rgb64(int count, const QSpan *spans, voi
|
|||
}
|
||||
}
|
||||
}
|
||||
++spans;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4736,7 +4745,9 @@ static void blend_untransformed_argb(int count, const QSpan *spans, void *userDa
|
|||
int xoff = -qRound(-data->dx);
|
||||
int yoff = -qRound(-data->dy);
|
||||
|
||||
while (count--) {
|
||||
for (; count--; spans++) {
|
||||
if (!spans->len)
|
||||
continue;
|
||||
int x = spans->x;
|
||||
int length = spans->len;
|
||||
int sx = xoff + x;
|
||||
|
|
@ -4756,7 +4767,6 @@ static void blend_untransformed_argb(int count, const QSpan *spans, void *userDa
|
|||
op.func(dest, src, length, coverage);
|
||||
}
|
||||
}
|
||||
++spans;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4829,7 +4839,12 @@ static void blend_untransformed_rgb565(int count, const QSpan *spans, void *user
|
|||
int xoff = -qRound(-data->dx);
|
||||
int yoff = -qRound(-data->dy);
|
||||
|
||||
while (count--) {
|
||||
const QSpan *end = spans + count;
|
||||
while (spans < end) {
|
||||
if (!spans->len) {
|
||||
++spans;
|
||||
continue;
|
||||
}
|
||||
const quint8 coverage = (data->texture.const_alpha * spans->coverage) >> 8;
|
||||
if (coverage == 0) {
|
||||
++spans;
|
||||
|
|
|
|||
|
|
@ -4186,7 +4186,7 @@ static void qt_span_fill_clipped(int spanCount, const QSpan *spans, void *userDa
|
|||
Clip spans to \a{clip}-rectangle.
|
||||
Returns number of unclipped spans
|
||||
*/
|
||||
static int qt_intersect_spans(QT_FT_Span *spans, int numSpans,
|
||||
static int qt_intersect_spans(QT_FT_Span *&spans, int numSpans,
|
||||
const QRect &clip)
|
||||
{
|
||||
const short minx = clip.left();
|
||||
|
|
@ -4194,29 +4194,32 @@ static int qt_intersect_spans(QT_FT_Span *spans, int numSpans,
|
|||
const short maxx = clip.right();
|
||||
const short maxy = clip.bottom();
|
||||
|
||||
int n = 0;
|
||||
for (int i = 0; i < numSpans; ++i) {
|
||||
if (spans[i].y > maxy)
|
||||
QT_FT_Span *end = spans + numSpans;
|
||||
while (spans < end) {
|
||||
if (spans->y >= miny)
|
||||
break;
|
||||
if (spans[i].y < miny
|
||||
|| spans[i].x > maxx
|
||||
|| spans[i].x + spans[i].len <= minx) {
|
||||
continue;
|
||||
}
|
||||
if (spans[i].x < minx) {
|
||||
spans[n].len = qMin(spans[i].len - (minx - spans[i].x), maxx - minx + 1);
|
||||
spans[n].x = minx;
|
||||
} else {
|
||||
spans[n].x = spans[i].x;
|
||||
spans[n].len = qMin(spans[i].len, ushort(maxx - spans[n].x + 1));
|
||||
}
|
||||
if (spans[n].len == 0)
|
||||
continue;
|
||||
spans[n].y = spans[i].y;
|
||||
spans[n].coverage = spans[i].coverage;
|
||||
++n;
|
||||
++spans;
|
||||
}
|
||||
return n;
|
||||
|
||||
QT_FT_Span *s = spans;
|
||||
while (s < end) {
|
||||
if (s->y > maxy)
|
||||
break;
|
||||
if (s->x > maxx || s->x + s->len <= minx) {
|
||||
s->len = 0;
|
||||
++s;
|
||||
continue;
|
||||
}
|
||||
if (s->x < minx) {
|
||||
s->len = qMin(s->len - (minx - s->x), maxx - minx + 1);
|
||||
s->x = minx;
|
||||
} else {
|
||||
s->len = qMin(s->len, ushort(maxx - s->x + 1));
|
||||
}
|
||||
++s;
|
||||
}
|
||||
|
||||
return s - spans;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -4229,11 +4232,12 @@ static void qt_span_fill_clipRect(int count, const QSpan *spans,
|
|||
Q_ASSERT(fillData->clip);
|
||||
Q_ASSERT(!fillData->clip->clipRect.isEmpty());
|
||||
|
||||
QSpan *s = const_cast<QSpan *>(spans);
|
||||
// hw: check if this const_cast<> is safe!!!
|
||||
count = qt_intersect_spans(const_cast<QSpan*>(spans), count,
|
||||
count = qt_intersect_spans(s, count,
|
||||
fillData->clip->clipRect);
|
||||
if (count > 0)
|
||||
fillData->unclipped_blend(count, spans, fillData);
|
||||
fillData->unclipped_blend(count, s, fillData);
|
||||
}
|
||||
|
||||
static void qt_span_clip(int count, const QSpan *spans, void *userData)
|
||||
|
|
@ -4844,7 +4848,8 @@ static inline void drawEllipsePoints(int x, int y, int length,
|
|||
if (length == 0)
|
||||
return;
|
||||
|
||||
QT_FT_Span outline[4];
|
||||
QT_FT_Span _outline[4];
|
||||
QT_FT_Span *outline = _outline;
|
||||
const int midx = rect.x() + (rect.width() + 1) / 2;
|
||||
const int midy = rect.y() + (rect.height() + 1) / 2;
|
||||
|
||||
|
|
@ -4876,7 +4881,8 @@ static inline void drawEllipsePoints(int x, int y, int length,
|
|||
outline[3].coverage = 255;
|
||||
|
||||
if (brush_func && outline[0].x + outline[0].len < outline[1].x) {
|
||||
QT_FT_Span fill[2];
|
||||
QT_FT_Span _fill[2];
|
||||
QT_FT_Span *fill = _fill;
|
||||
|
||||
// top fill
|
||||
fill[0].x = outline[0].x + outline[0].len - 1;
|
||||
|
|
|
|||
Loading…
Reference in New Issue