summaryrefslogtreecommitdiffstats
path: root/src/gui/painting/qdrawingprimitive_sse2_p.h
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2015-05-06 14:23:57 +0200
committerAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2015-06-03 12:01:26 +0000
commit8f760808e0fe0fe6dd89d561f118b19ed8085e7a (patch)
tree8cc259b6098d83b91b6ec8ac22745546947860c7 /src/gui/painting/qdrawingprimitive_sse2_p.h
parent754efa57d89c62d1796e01b407e9222e67450f52 (diff)
Fix premul conversion from ARGB32 to A2RGB30 formats.
When a premultiplied alpha changes value because it is rounded to fewer bits the premultiplied colors may need to be recalculated with the new value. Otherwise the color will both be wrong and potentially invalid. Change-Id: I9ec74a22aac73cd7ffab04e180cf2bf35bb4c315 Reviewed-by: Gunnar Sletta <gunnar@sletta.org>
Diffstat (limited to 'src/gui/painting/qdrawingprimitive_sse2_p.h')
-rw-r--r--src/gui/painting/qdrawingprimitive_sse2_p.h38
1 files changed, 38 insertions, 0 deletions
diff --git a/src/gui/painting/qdrawingprimitive_sse2_p.h b/src/gui/painting/qdrawingprimitive_sse2_p.h
index 1a7dddf0d5..c74055e440 100644
--- a/src/gui/painting/qdrawingprimitive_sse2_p.h
+++ b/src/gui/painting/qdrawingprimitive_sse2_p.h
@@ -35,6 +35,7 @@
#define QDRAWINGPRIMITIVE_SSE2_P_H
#include <private/qsimd_p.h>
+#include "qdrawhelper_p.h"
#ifdef __SSE2__
@@ -256,6 +257,43 @@ inline QRgb qUnpremultiply_sse4(QRgb p)
vl = _mm_packus_epi16(vl, vl);
return _mm_cvtsi128_si32(vl);
}
+
+template<enum QtPixelOrder PixelOrder>
+QT_FUNCTION_TARGET(SSE4_1)
+inline uint qConvertArgb32ToA2rgb30_sse4(QRgb p)
+{
+ const uint alpha = qAlpha(p);
+ if (alpha == 255)
+ return qConvertRgb32ToRgb30<PixelOrder>(p);
+ if (alpha == 0)
+ return 0;
+ Q_CONSTEXPR uint mult = 255 / (255 >> 6);
+ const uint invAlpha = qt_inv_premul_factor[alpha];
+ const uint newalpha = (alpha >> 6);
+ const __m128i via = _mm_set1_epi32(invAlpha);
+ const __m128i vna = _mm_set1_epi32(mult * newalpha);
+ const __m128i vr1 = _mm_set1_epi32(0x1000);
+ const __m128i vr2 = _mm_set1_epi32(0x80);
+ __m128i vl = _mm_cvtepu8_epi32(_mm_cvtsi32_si128(p));
+ vl = _mm_mullo_epi32(vl, via);
+ vl = _mm_add_epi32(vl, vr1);
+ vl = _mm_srli_epi32(vl, 14);
+ vl = _mm_mullo_epi32(vl, vna);
+ vl = _mm_add_epi32(vl, _mm_srli_epi32(vl, 8));
+ vl = _mm_add_epi32(vl, vr2);
+ vl = _mm_srli_epi32(vl, 8);
+ vl = _mm_packus_epi32(vl, vl);
+ uint rgb30 = (newalpha << 30);
+ rgb30 |= ((uint)_mm_extract_epi16(vl, 1)) << 10;
+ if (PixelOrder == PixelOrderRGB) {
+ rgb30 |= ((uint)_mm_extract_epi16(vl, 2)) << 20;
+ rgb30 |= ((uint)_mm_extract_epi16(vl, 0));
+ } else {
+ rgb30 |= ((uint)_mm_extract_epi16(vl, 0)) << 20;
+ rgb30 |= ((uint)_mm_extract_epi16(vl, 2));
+ }
+ return rgb30;
+}
#endif
QT_END_NAMESPACE