Avoid qMin in format conversions when possible

Calling qMin often prevents effective vectorization, and it is only
necessary when converting from formats with mixed color-channel widths.

Change-Id: I2a0f3f3fb528d45be1fd025758f9d915ee1736c0
Reviewed-by: Gunnar Sletta <gunnar@sletta.org>
bb10
Allan Sandfeld Jensen 2016-02-25 14:08:11 +01:00
parent fc78bc2c06
commit 6cc050c969
2 changed files with 69 additions and 20 deletions

View File

@ -245,17 +245,36 @@ static const uint *QT_FASTCALL convertARGBPMToARGB32PM(uint *buffer, const uint
Q_CONSTEXPR uchar greenRightShift = 2 * greenWidth<Format>() - 8;
Q_CONSTEXPR uchar blueRightShift = 2 * blueWidth<Format>() - 8;
for (int i = 0; i < count; ++i) {
uint alpha = (src[i] >> alphaShift<Format>()) & alphaMask;
uint red = (src[i] >> redShift<Format>()) & redMask;
uint green = (src[i] >> greenShift<Format>()) & greenMask;
uint blue = (src[i] >> blueShift<Format>()) & blueMask;
Q_CONSTEXPR bool mustMin = (alphaWidth<Format>() != redWidth<Format>()) ||
(alphaWidth<Format>() != greenWidth<Format>()) ||
(alphaWidth<Format>() != blueWidth<Format>());
alpha = (alpha << alphaLeftShift) | (alpha >> alphaRightShift);
red = qMin(alpha, (red << redLeftShift) | (red >> redRightShift));
green = qMin(alpha, (green << greenLeftShift) | (green >> greenRightShift));
blue = qMin(alpha, (blue << blueLeftShift) | (blue >> blueRightShift));
buffer[i] = (alpha << 24) | (red << 16) | (green << 8) | blue;
if (mustMin) {
for (int i = 0; i < count; ++i) {
uint alpha = (src[i] >> alphaShift<Format>()) & alphaMask;
uint red = (src[i] >> redShift<Format>()) & redMask;
uint green = (src[i] >> greenShift<Format>()) & greenMask;
uint blue = (src[i] >> blueShift<Format>()) & blueMask;
alpha = (alpha << alphaLeftShift) | (alpha >> alphaRightShift);
red = qMin(alpha, (red << redLeftShift) | (red >> redRightShift));
green = qMin(alpha, (green << greenLeftShift) | (green >> greenRightShift));
blue = qMin(alpha, (blue << blueLeftShift) | (blue >> blueRightShift));
buffer[i] = (alpha << 24) | (red << 16) | (green << 8) | blue;
}
} else {
for (int i = 0; i < count; ++i) {
uint alpha = (src[i] >> alphaShift<Format>()) & alphaMask;
uint red = (src[i] >> redShift<Format>()) & redMask;
uint green = (src[i] >> greenShift<Format>()) & greenMask;
uint blue = (src[i] >> blueShift<Format>()) & blueMask;
alpha = ((alpha << alphaLeftShift) | (alpha >> alphaRightShift)) << 24;
red = ((red << redLeftShift) | (red >> redRightShift)) << 16;
green = ((green << greenLeftShift) | (green >> greenRightShift)) << 8;
blue = (blue << blueLeftShift) | (blue >> blueRightShift);
buffer[i] = alpha | red | green | blue;
}
}
return buffer;
@ -280,17 +299,36 @@ static const QRgba64 *QT_FASTCALL convertARGBPMToARGB64PM(QRgba64 *buffer, const
Q_CONSTEXPR uchar greenRightShift = 2 * greenWidth<Format>() - 8;
Q_CONSTEXPR uchar blueRightShift = 2 * blueWidth<Format>() - 8;
for (int i = 0; i < count; ++i) {
uint alpha = (src[i] >> alphaShift<Format>()) & alphaMask;
uint red = (src[i] >> redShift<Format>()) & redMask;
uint green = (src[i] >> greenShift<Format>()) & greenMask;
uint blue = (src[i] >> blueShift<Format>()) & blueMask;
Q_CONSTEXPR bool mustMin = (alphaWidth<Format>() != redWidth<Format>()) ||
(alphaWidth<Format>() != greenWidth<Format>()) ||
(alphaWidth<Format>() != blueWidth<Format>());
alpha = (alpha << alphaLeftShift) | (alpha >> alphaRightShift);
red = qMin(alpha, (red << redLeftShift) | (red >> redRightShift));
green = qMin(alpha, (green << greenLeftShift) | (green >> greenRightShift));
blue = qMin(alpha, (blue << blueLeftShift) | (blue >> blueRightShift));
buffer[i] = QRgba64::fromRgba(red, green, blue, alpha);
if (mustMin) {
for (int i = 0; i < count; ++i) {
uint alpha = (src[i] >> alphaShift<Format>()) & alphaMask;
uint red = (src[i] >> redShift<Format>()) & redMask;
uint green = (src[i] >> greenShift<Format>()) & greenMask;
uint blue = (src[i] >> blueShift<Format>()) & blueMask;
alpha = (alpha << alphaLeftShift) | (alpha >> alphaRightShift);
red = qMin(alpha, (red << redLeftShift) | (red >> redRightShift));
green = qMin(alpha, (green << greenLeftShift) | (green >> greenRightShift));
blue = qMin(alpha, (blue << blueLeftShift) | (blue >> blueRightShift));
buffer[i] = QRgba64::fromRgba(red, green, blue, alpha);
}
} else {
for (int i = 0; i < count; ++i) {
uint alpha = (src[i] >> alphaShift<Format>()) & alphaMask;
uint red = (src[i] >> redShift<Format>()) & redMask;
uint green = (src[i] >> greenShift<Format>()) & greenMask;
uint blue = (src[i] >> blueShift<Format>()) & blueMask;
alpha = (alpha << alphaLeftShift) | (alpha >> alphaRightShift);
red = (red << redLeftShift) | (red >> redRightShift);
green = (green << greenLeftShift) | (green >> greenRightShift);
blue = (blue << blueLeftShift) | (blue >> blueRightShift);
buffer[i] = QRgba64::fromRgba(red, green, blue, alpha);
}
}
return buffer;

View File

@ -199,6 +199,7 @@ void tst_QImageConversion::convertRgb32_data()
QTest::newRow("argb32 -> rgb666") << argb32 << QImage::Format_RGB666;
QTest::newRow("argb32 -> argb8565pm") << argb32 << QImage::Format_ARGB8565_Premultiplied;
QTest::newRow("argb32 -> argb4444pm") << argb32 << QImage::Format_ARGB4444_Premultiplied;
QTest::newRow("argb32 -> argb6666pm") << argb32 << QImage::Format_ARGB6666_Premultiplied;
QTest::newRow("argb32pm -> rgb16") << argb32pm << QImage::Format_RGB16;
QTest::newRow("argb32pm -> rgb32") << argb32pm << QImage::Format_RGB32;
@ -212,6 +213,7 @@ void tst_QImageConversion::convertRgb32_data()
QTest::newRow("argb32pm -> rgb666") << argb32pm << QImage::Format_RGB666;
QTest::newRow("argb32pm -> argb8565pm") << argb32pm << QImage::Format_ARGB8565_Premultiplied;
QTest::newRow("argb32pm -> argb4444pm") << argb32pm << QImage::Format_ARGB4444_Premultiplied;
QTest::newRow("argb32pm -> argb6666pm") << argb32pm << QImage::Format_ARGB6666_Premultiplied;
}
void tst_QImageConversion::convertRgb32()
@ -235,6 +237,7 @@ void tst_QImageConversion::convertGeneric_data()
QImage bgr30 = rgb32.convertToFormat(QImage::Format_BGR30);
QImage a2rgb30 = argb32.convertToFormat(QImage::Format_A2RGB30_Premultiplied);
QImage rgb666 = rgb32.convertToFormat(QImage::Format_RGB666);
QImage argb4444 = argb32.convertToFormat(QImage::Format_ARGB4444_Premultiplied);
QTest::newRow("rgba8888 -> rgb32") << rgba32 << QImage::Format_RGB32;
QTest::newRow("rgba8888 -> argb32") << rgba32 << QImage::Format_ARGB32;
@ -271,6 +274,14 @@ void tst_QImageConversion::convertGeneric_data()
QTest::newRow("rgb666 -> rgb16") << rgb666 << QImage::Format_RGB16;
QTest::newRow("rgb666 -> rgb555") << rgb666 << QImage::Format_RGB555;
QTest::newRow("rgb666 -> rgb30") << rgb666 << QImage::Format_RGB30;
QTest::newRow("argb4444pm -> rgb32") << argb4444 << QImage::Format_RGB32;
QTest::newRow("argb4444pm -> argb32") << argb4444 << QImage::Format_ARGB32;
QTest::newRow("argb4444pm -> argb32pm") << argb4444 << QImage::Format_ARGB32_Premultiplied;
QTest::newRow("argb4444pm -> rgbx8888") << argb4444 << QImage::Format_RGBX8888;
QTest::newRow("argb4444pm -> rgba8888pm") << argb4444 << QImage::Format_RGBA8888_Premultiplied;
QTest::newRow("argb4444pm -> rgb30") << argb4444 << QImage::Format_RGB30;
QTest::newRow("argb4444pm -> a2bgr30") << argb4444 << QImage::Format_A2BGR30_Premultiplied;
}
void tst_QImageConversion::convertGeneric()