diff options
author | Lars Knoll <lars.knoll@qt.io> | 2017-11-17 13:23:30 +0100 |
---|---|---|
committer | Eirik Aavitsland <eirik.aavitsland@qt.io> | 2019-06-11 09:25:55 +0000 |
commit | dd5b829468b4818f00a3c3a7df7f104dfa869bd1 (patch) | |
tree | addcacdba23e9c6625e9a965aaeefaa4e86e0aec /src/gui/painting | |
parent | 3797704c4ff0d91f544efa791973eced07c3ef02 (diff) |
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>
Diffstat (limited to 'src/gui/painting')
-rw-r--r-- | src/gui/painting/qdrawhelper.cpp | 37 | ||||
-rw-r--r-- | src/gui/painting/qpaintengine_raster.cpp | 50 |
2 files changed, 54 insertions, 33 deletions
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index ca3590e280..1f7ab5006c 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -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; diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index ab22a71134..76c5842f58 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -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) { + ++spans; + } + + 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 (spans[i].x < minx) { - spans[n].len = qMin(spans[i].len - (minx - spans[i].x), maxx - minx + 1); - spans[n].x = minx; + if (s->x < minx) { + s->len = qMin(s->len - (minx - s->x), maxx - minx + 1); + s->x = minx; } else { - spans[n].x = spans[i].x; - spans[n].len = qMin(spans[i].len, ushort(maxx - spans[n].x + 1)); + s->len = qMin(s->len, ushort(maxx - s->x + 1)); } - if (spans[n].len == 0) - continue; - spans[n].y = spans[i].y; - spans[n].coverage = spans[i].coverage; - ++n; + ++s; } - return n; + + 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; |