Optimize RGBA64PM->RGBA64 for SSE4
And remove direct conversion to take advantage of both the SIMD, but also threading on all platforms. Change-Id: I782ae7c80e82b694e23abee28d69cecd0d28c32f Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>bb10
parent
9505bd84db
commit
0c5d9b953e
|
|
@ -1259,55 +1259,6 @@ static bool convert_RGBA64_to_RGBx64_inplace(QImageData *data, Qt::ImageConversi
|
|||
return true;
|
||||
}
|
||||
|
||||
template<bool MaskAlpha>
|
||||
static void convert_RGBA64PM_to_RGBA64(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
|
||||
{
|
||||
Q_ASSERT(src->format == QImage::Format_RGBA64_Premultiplied);
|
||||
Q_ASSERT(dest->format == QImage::Format_RGBA64 || dest->format == QImage::Format_RGBX64);
|
||||
Q_ASSERT(src->width == dest->width);
|
||||
Q_ASSERT(src->height == dest->height);
|
||||
|
||||
const int src_pad = (src->bytes_per_line >> 3) - src->width;
|
||||
const int dest_pad = (dest->bytes_per_line >> 3) - dest->width;
|
||||
const QRgba64 *src_data = reinterpret_cast<const QRgba64 *>(src->data);
|
||||
QRgba64 *dest_data = reinterpret_cast<QRgba64 *>(dest->data);
|
||||
|
||||
for (int i = 0; i < src->height; ++i) {
|
||||
const QRgba64 *end = src_data + src->width;
|
||||
while (src_data < end) {
|
||||
*dest_data = src_data->unpremultiplied();
|
||||
if (MaskAlpha)
|
||||
dest_data->setAlpha(65535);
|
||||
++src_data;
|
||||
++dest_data;
|
||||
}
|
||||
src_data += src_pad;
|
||||
dest_data += dest_pad;
|
||||
}
|
||||
}
|
||||
|
||||
template<bool MaskAlpha>
|
||||
static bool convert_RGBA64PM_to_RGBA64_inplace(QImageData *data, Qt::ImageConversionFlags)
|
||||
{
|
||||
Q_ASSERT(data->format == QImage::Format_RGBA64_Premultiplied);
|
||||
|
||||
const int pad = (data->bytes_per_line >> 3) - data->width;
|
||||
QRgba64 *rgb_data = reinterpret_cast<QRgba64 *>(data->data);
|
||||
|
||||
for (int i = 0; i < data->height; ++i) {
|
||||
const QRgba64 *end = rgb_data + data->width;
|
||||
while (rgb_data < end) {
|
||||
*rgb_data = rgb_data->unpremultiplied();
|
||||
if (MaskAlpha)
|
||||
rgb_data->setAlpha(65535);
|
||||
++rgb_data;
|
||||
}
|
||||
rgb_data += pad;
|
||||
}
|
||||
data->format = MaskAlpha ? QImage::Format_RGBX64 : QImage::Format_RGBA64;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void convert_gray16_to_RGBA64(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
|
||||
{
|
||||
Q_ASSERT(src->format == QImage::Format_Grayscale16);
|
||||
|
|
@ -2326,8 +2277,6 @@ static void qInitImageConversions()
|
|||
qimage_converter_map[QImage::Format_RGBA64][QImage::Format_RGBA8888] = convert_RGBA64_to_ARGB32<true>;
|
||||
qimage_converter_map[QImage::Format_RGBA64][QImage::Format_RGBX64] = convert_RGBA64_to_RGBx64;
|
||||
|
||||
qimage_converter_map[QImage::Format_RGBA64_Premultiplied][QImage::Format_RGBX64] = convert_RGBA64PM_to_RGBA64<true>;
|
||||
qimage_converter_map[QImage::Format_RGBA64_Premultiplied][QImage::Format_RGBA64] = convert_RGBA64PM_to_RGBA64<false>;
|
||||
qimage_converter_map[QImage::Format_RGBA64_Premultiplied][QImage::Format_Grayscale16] = convert_RGBA64_to_gray16;
|
||||
|
||||
qimage_converter_map[QImage::Format_Grayscale16][QImage::Format_RGBX64] = convert_gray16_to_RGBA64;
|
||||
|
|
@ -2443,11 +2392,6 @@ static void qInitImageConversions()
|
|||
qimage_inplace_converter_map[QImage::Format_RGBA64][QImage::Format_RGBX64] =
|
||||
convert_RGBA64_to_RGBx64_inplace;
|
||||
|
||||
qimage_inplace_converter_map[QImage::Format_RGBA64_Premultiplied][QImage::Format_RGBX64] =
|
||||
convert_RGBA64PM_to_RGBA64_inplace<true>;
|
||||
qimage_inplace_converter_map[QImage::Format_RGBA64_Premultiplied][QImage::Format_RGBA64] =
|
||||
convert_RGBA64PM_to_RGBA64_inplace<false>;
|
||||
|
||||
qimage_inplace_converter_map[QImage::Format_BGR888][QImage::Format_RGB888] =
|
||||
convert_rgbswap_generic_inplace;
|
||||
|
||||
|
|
|
|||
|
|
@ -5141,6 +5141,8 @@ static void qInitDrawhelperFunctions()
|
|||
const QList<QRgb> *, QDitherInfo *);
|
||||
extern void QT_FASTCALL storeRGBA8888FromRGBA64PM_sse4(uchar *dest, const QRgba64 *src, int index, int count,
|
||||
const QList<QRgb> *, QDitherInfo *);
|
||||
extern void QT_FASTCALL storeRGBA64FromRGBA64PM_sse4(uchar *, const QRgba64 *, int, int, const QList<QRgb> *, QDitherInfo *);
|
||||
extern void QT_FASTCALL storeRGBx64FromRGBA64PM_sse4(uchar *, const QRgba64 *, int, int, const QList<QRgb> *, QDitherInfo *);
|
||||
extern void QT_FASTCALL destStore64ARGB32_sse4(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length);
|
||||
extern void QT_FASTCALL destStore64RGBA8888_sse4(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length);
|
||||
# ifndef __AVX2__
|
||||
|
|
@ -5162,6 +5164,8 @@ static void qInitDrawhelperFunctions()
|
|||
qPixelLayouts[QImage::Format_A2RGB30_Premultiplied].storeFromARGB32PM = storeA2RGB30PMFromARGB32PM_sse4<PixelOrderRGB>;
|
||||
qStoreFromRGBA64PM[QImage::Format_ARGB32] = storeARGB32FromRGBA64PM_sse4;
|
||||
qStoreFromRGBA64PM[QImage::Format_RGBA8888] = storeRGBA8888FromRGBA64PM_sse4;
|
||||
qStoreFromRGBA64PM[QImage::Format_RGBX64] = storeRGBx64FromRGBA64PM_sse4;
|
||||
qStoreFromRGBA64PM[QImage::Format_RGBA64] = storeRGBA64FromRGBA64PM_sse4;
|
||||
#if QT_CONFIG(raster_64bit)
|
||||
destStoreProc64[QImage::Format_ARGB32] = destStore64ARGB32_sse4;
|
||||
destStoreProc64[QImage::Format_RGBA8888] = destStore64RGBA8888_sse4;
|
||||
|
|
|
|||
|
|
@ -327,6 +327,90 @@ static inline void convertARGBFromRGBA64PM_sse4(uint *buffer, const QRgba64 *src
|
|||
}
|
||||
}
|
||||
|
||||
template<bool mask>
|
||||
static inline void convertRGBA64FromRGBA64PM_sse4(QRgba64 *buffer, const QRgba64 *src, int count)
|
||||
{
|
||||
int i = 0;
|
||||
if ((_MM_GET_EXCEPTION_MASK() & _MM_MASK_INVALID) == 0) {
|
||||
for (; i < count; ++i) {
|
||||
QRgba64 v = src[i].unpremultiplied();
|
||||
if (mask)
|
||||
v.setAlpha(65535);
|
||||
buffer[i] = v;
|
||||
}
|
||||
return;
|
||||
}
|
||||
const __m128i alphaMask = _mm_set1_epi64x(qint64(Q_UINT64_C(0xffff) << 48));
|
||||
const __m128i zero = _mm_setzero_si128();
|
||||
|
||||
for (; i < count - 3; i += 4) {
|
||||
__m128i srcVector1 = _mm_loadu_si128((const __m128i *)&src[i + 0]);
|
||||
__m128i srcVector2 = _mm_loadu_si128((const __m128i *)&src[i + 2]);
|
||||
bool transparent1 = _mm_testz_si128(srcVector1, alphaMask);
|
||||
bool opaque1 = _mm_testc_si128(srcVector1, alphaMask);
|
||||
bool transparent2 = _mm_testz_si128(srcVector2, alphaMask);
|
||||
bool opaque2 = _mm_testc_si128(srcVector2, alphaMask);
|
||||
|
||||
if (!(transparent1 && transparent2)) {
|
||||
if (!(opaque1 && opaque2)) {
|
||||
__m128i srcVector1Alpha = _mm_srli_epi64(srcVector1, 48);
|
||||
__m128i srcVector2Alpha = _mm_srli_epi64(srcVector2, 48);
|
||||
__m128i srcVectorAlpha = _mm_packus_epi32(srcVector1Alpha, srcVector2Alpha);
|
||||
const __m128 a = _mm_cvtepi32_ps(srcVectorAlpha);
|
||||
const __m128 ia = reciprocal_mul_ps(a, 65535.0f);
|
||||
__m128i src1 = _mm_unpacklo_epi16(srcVector1, zero);
|
||||
__m128i src2 = _mm_unpackhi_epi16(srcVector1, zero);
|
||||
__m128i src3 = _mm_unpacklo_epi16(srcVector2, zero);
|
||||
__m128i src4 = _mm_unpackhi_epi16(srcVector2, zero);
|
||||
__m128 ia1 = _mm_shuffle_ps(ia, ia, _MM_SHUFFLE(0, 0, 0, 0));
|
||||
__m128 ia2 = _mm_shuffle_ps(ia, ia, _MM_SHUFFLE(1, 1, 1, 1));
|
||||
__m128 ia3 = _mm_shuffle_ps(ia, ia, _MM_SHUFFLE(2, 2, 2, 2));
|
||||
__m128 ia4 = _mm_shuffle_ps(ia, ia, _MM_SHUFFLE(3, 3, 3, 3));
|
||||
src1 = _mm_cvtps_epi32(_mm_mul_ps(_mm_cvtepi32_ps(src1), ia1));
|
||||
src2 = _mm_cvtps_epi32(_mm_mul_ps(_mm_cvtepi32_ps(src2), ia2));
|
||||
src3 = _mm_cvtps_epi32(_mm_mul_ps(_mm_cvtepi32_ps(src3), ia3));
|
||||
src4 = _mm_cvtps_epi32(_mm_mul_ps(_mm_cvtepi32_ps(src4), ia4));
|
||||
src1 = _mm_packus_epi32(src1, src2);
|
||||
src3 = _mm_packus_epi32(src3, src4);
|
||||
// Handle potential alpha == 0 values:
|
||||
__m128i srcVector1AlphaMask = _mm_cmpeq_epi64(srcVector1Alpha, zero);
|
||||
__m128i srcVector2AlphaMask = _mm_cmpeq_epi64(srcVector2Alpha, zero);
|
||||
src1 = _mm_andnot_si128(srcVector1AlphaMask, src1);
|
||||
src3 = _mm_andnot_si128(srcVector2AlphaMask, src3);
|
||||
// Fixup alpha values:
|
||||
if (mask) {
|
||||
src1 = _mm_or_si128(src1, alphaMask);
|
||||
src3 = _mm_or_si128(src3, alphaMask);
|
||||
} else {
|
||||
src1 = _mm_blendv_epi8(src1, srcVector1, alphaMask);
|
||||
src3 = _mm_blendv_epi8(src3, srcVector2, alphaMask);
|
||||
}
|
||||
_mm_storeu_si128((__m128i *)&buffer[i + 0], src1);
|
||||
_mm_storeu_si128((__m128i *)&buffer[i + 2], src3);
|
||||
} else {
|
||||
if (mask) {
|
||||
srcVector1 = _mm_or_si128(srcVector1, alphaMask);
|
||||
srcVector2 = _mm_or_si128(srcVector2, alphaMask);
|
||||
}
|
||||
if (mask || src != buffer) {
|
||||
_mm_storeu_si128((__m128i *)&buffer[i + 0], srcVector1);
|
||||
_mm_storeu_si128((__m128i *)&buffer[i + 2], srcVector2);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_mm_storeu_si128((__m128i *)&buffer[i + 0], zero);
|
||||
_mm_storeu_si128((__m128i *)&buffer[i + 2], zero);
|
||||
}
|
||||
}
|
||||
|
||||
SIMD_EPILOGUE(i, count, 3) {
|
||||
QRgba64 v = src[i].unpremultiplied();
|
||||
if (mask)
|
||||
v.setAlpha(65535);
|
||||
buffer[i] = v;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef __AVX2__
|
||||
void QT_FASTCALL convertARGB32ToARGB32PM_sse4(uint *buffer, int count, const QList<QRgb> *)
|
||||
{
|
||||
|
|
@ -446,6 +530,20 @@ void QT_FASTCALL storeRGBA8888FromRGBA64PM_sse4(uchar *dest, const QRgba64 *src,
|
|||
convertARGBFromRGBA64PM_sse4<true>(d, src, count);
|
||||
}
|
||||
|
||||
void QT_FASTCALL storeRGBA64FromRGBA64PM_sse4(uchar *dest, const QRgba64 *src, int index, int count,
|
||||
const QList<QRgb> *, QDitherInfo *)
|
||||
{
|
||||
QRgba64 *d = (QRgba64 *)dest + index;
|
||||
convertRGBA64FromRGBA64PM_sse4<false>(d, src, count);
|
||||
}
|
||||
|
||||
void QT_FASTCALL storeRGBx64FromRGBA64PM_sse4(uchar *dest, const QRgba64 *src, int index, int count,
|
||||
const QList<QRgb> *, QDitherInfo *)
|
||||
{
|
||||
QRgba64 *d = (QRgba64 *)dest + index;
|
||||
convertRGBA64FromRGBA64PM_sse4<true>(d, src, count);
|
||||
}
|
||||
|
||||
template
|
||||
void QT_FASTCALL storeA2RGB30PMFromARGB32PM_sse4<PixelOrderBGR>(uchar *dest, const uint *src, int index, int count,
|
||||
const QList<QRgb> *, QDitherInfo *);
|
||||
|
|
|
|||
Loading…
Reference in New Issue