summaryrefslogtreecommitdiffstats
path: root/src/gui/painting/qdrawhelper.cpp
diff options
context:
space:
mode:
authorSamuel Rødal <sroedal@trolltech.com>2009-03-31 18:00:18 (GMT)
committerSamuel Rødal <sroedal@trolltech.com>2009-04-01 13:53:47 (GMT)
commit815eb0e1d05318dfdd3cadb7f45c7e8e80ff4790 (patch)
treed800ec0802598834fc8139562b470bf203534999 /src/gui/painting/qdrawhelper.cpp
parent95d2bd114974ec60cff1cdfbd45f18c2c0e85108 (diff)
downloadQt-815eb0e1d05318dfdd3cadb7f45c7e8e80ff4790.zip
Qt-815eb0e1d05318dfdd3cadb7f45c7e8e80ff4790.tar.gz
Qt-815eb0e1d05318dfdd3cadb7f45c7e8e80ff4790.tar.bz2
Optimize blend functions for short adjacent spans.
When drawing antialiased primitives it's quite common to have several very short (often just one pixel) spans adjacent to each other. This patch makes it possible to fetch several adjacent spans at a time, avoiding the overhead of calling fetch on every single span. Reviewed-by: Gunnar Sletta
Diffstat (limited to 'src/gui/painting/qdrawhelper.cpp')
-rw-r--r--src/gui/painting/qdrawhelper.cpp118
1 files changed, 96 insertions, 22 deletions
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 47dbf1b..7e73304 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -3041,41 +3041,115 @@ static void blend_color_rgb16(int count, const QSpan *spans, void *userData)
blend_color_generic(count, spans, userData);
}
-template <SpanMethod spanMethod>
-Q_STATIC_TEMPLATE_FUNCTION void blend_src_generic(int count, const QSpan *spans, void *userData)
+template <typename T>
+void handleSpans(int count, const QSpan *spans, const QSpanData *data, T &handler)
{
- QSpanData *data = reinterpret_cast<QSpanData *>(userData);
-
- uint buffer[buffer_size];
- uint src_buffer[buffer_size];
- Operator op = getOperator(data, spans, count);
-
uint const_alpha = 256;
if (data->type == QSpanData::Texture)
const_alpha = data->texture.const_alpha;
- while (count--) {
+ int coverage = 0;
+ while (count) {
int x = spans->x;
- int length = spans->len;
- const int coverage = (spans->coverage * const_alpha) >> 8;
+ const int y = spans->y;
+ int right = x + spans->len;
+
+ // compute length of adjacent spans
+ for (int i = 1; i < count && spans[i].y == y && spans[i].x == right; ++i)
+ right += spans[i].len;
+ int length = right - x;
+
while (length) {
int l = qMin(buffer_size, length);
- const uint *src = op.src_fetch(src_buffer, &op, data, spans->y, x, l);
- if (spanMethod == RegularSpans) {
- uint *dest = op.dest_fetch ? op.dest_fetch(buffer, data->rasterBuffer, x, spans->y, l) : buffer;
- op.func(dest, src, l, coverage);
- if (op.dest_store)
- op.dest_store(data->rasterBuffer, x, spans->y, dest, l);
- } else {
- drawBufferSpan(data, src, l, x, spans->y, l, coverage);
- }
- x += l;
length -= l;
+
+ int process_length = l;
+ int process_x = x;
+
+ const uint *src = handler.fetch(process_x, y, process_length);
+ int offset = 0;
+ while (l > 0) {
+ if (x == spans->x) // new span?
+ coverage = (spans->coverage * const_alpha) >> 8;
+
+ int right = spans->x + spans->len;
+ int len = qMin(l, right - x);
+
+ handler.process(x, y, len, coverage, src, offset);
+
+ l -= len;
+ x += len;
+ offset += len;
+
+ if (x == right) { // done with current span?
+ ++spans;
+ --count;
+ }
+ }
+ handler.store(process_x, y, process_length);
}
- ++spans;
}
}
+struct QBlendBase
+{
+ QBlendBase(QSpanData *d, Operator o)
+ : data(d)
+ , op(o)
+ , dest(0)
+ {
+ }
+
+ QSpanData *data;
+ Operator op;
+
+ uint *dest;
+
+ uint buffer[buffer_size];
+ uint src_buffer[buffer_size];
+};
+
+template <SpanMethod spanMethod>
+class BlendSrcGeneric : public QBlendBase
+{
+public:
+ BlendSrcGeneric(QSpanData *d, Operator o)
+ : QBlendBase(d, o)
+ {
+ }
+
+ const uint *fetch(int x, int y, int len)
+ {
+ if (spanMethod == RegularSpans)
+ dest = op.dest_fetch ? op.dest_fetch(buffer, data->rasterBuffer, x, y, len) : buffer;
+
+ return op.src_fetch(src_buffer, &op, data, y, x, len);
+ }
+
+ void process(int x, int y, int len, int coverage, const uint *src, int offset)
+ {
+ if (spanMethod == RegularSpans)
+ op.func(dest + offset, src + offset, len, coverage);
+ else
+ drawBufferSpan(data, src + offset, len, x, y, len, coverage);
+ }
+
+ void store(int x, int y, int len)
+ {
+ if (spanMethod == RegularSpans && op.dest_store) {
+ op.dest_store(data->rasterBuffer, x, y, dest, len);
+ }
+ }
+};
+
+template <SpanMethod spanMethod>
+Q_STATIC_TEMPLATE_FUNCTION void blend_src_generic(int count, const QSpan *spans, void *userData)
+{
+ QSpanData *data = reinterpret_cast<QSpanData *>(userData);
+ BlendSrcGeneric<spanMethod> blend(data, getOperator(data, spans, count));
+ handleSpans(count, spans, data, blend);
+}
+
template <SpanMethod spanMethod>
Q_STATIC_TEMPLATE_FUNCTION void blend_untransformed_generic(int count, const QSpan *spans, void *userData)
{