summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@digia.com>2014-01-15 15:02:09 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-01-16 03:00:45 +0100
commit407eee51e6ce261b51ecacdcb9a4e2ff6364699a (patch)
tree2dcec72442f176422a7a2bb9f8bd8919c6157ea7 /src
parent93a895a41a55e286e8393c5f8566ce6332b49277 (diff)
Optimize INV_PREMUL
Our inverse premultiply is rather unoptimized. It's major weakness is using three divide operation which are the slowest integer operations. This patch reduces the three divisions to just one but using an approximation that is accurate for all uchar values. The patch also adds a general short-cut for alpha==255. Together these improvements makes it 2 to 16 times faster depending on how many 0 and 255 alpha values are encountered. Change-Id: I96d7098a1bc320793b0d0526637acd1fdb5a43eb Reviewed-by: Gunnar Sletta <gunnar.sletta@jollamobile.com>
Diffstat (limited to 'src')
-rw-r--r--src/gui/painting/qdrawhelper.cpp2
-rw-r--r--src/gui/painting/qdrawhelper_p.h16
2 files changed, 11 insertions, 7 deletions
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 141688b826..8aef64c780 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -274,7 +274,7 @@ static const uint *QT_FASTCALL convertFromARGB32PM(uint *buffer, const uint *src
if (!layout->premultiplied) {
for (int i = 0; i < count; ++i)
- buffer[i] = qAlpha(src[i]) == 255 ? src[i] : INV_PREMUL(src[i]);
+ buffer[i] = INV_PREMUL(src[i]);
src = buffer;
}
for (int i = 0; i < count; ++i) {
diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h
index 6af4aa4943..4b11a8e92b 100644
--- a/src/gui/painting/qdrawhelper_p.h
+++ b/src/gui/painting/qdrawhelper_p.h
@@ -691,12 +691,16 @@ static Q_ALWAYS_INLINE uint BYTE_MUL_RGB16_32(uint x, uint a) {
return t;
}
-#define INV_PREMUL(p) \
- (qAlpha(p) == 0 ? 0 : \
- ((qAlpha(p) << 24) \
- | (((255*qRed(p))/ qAlpha(p)) << 16) \
- | (((255*qGreen(p)) / qAlpha(p)) << 8) \
- | ((255*qBlue(p)) / qAlpha(p))))
+static Q_ALWAYS_INLINE uint INV_PREMUL(uint p) {
+ const uint alpha = qAlpha(p);
+ if (alpha == 255)
+ return p;
+ if (alpha == 0)
+ return 0;
+ // (p*(0x00ff00ff/alpha)) >> 16 == (p*255)/alpha for all p and alpha <= 256.
+ const uint invAlpha = 0x00ff00ffU / alpha;
+ return qRgba((qRed(p)*invAlpha)>>16, (qGreen(p)*invAlpha)>>16, (qBlue(p)*invAlpha)>>16, alpha);
+}
struct quint24 {
quint24(uint value);