From c961d1a6d29af8ea385c042ec0d2d419e3bbfa84 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Fri, 12 Oct 2018 11:10:07 +0200 Subject: [PATCH] Make convert_generic_to_rgb64 more generic This makes it possible to get rid of specialized functions for converting to RGBA64PM, while at the same time making the conversion faster as the painter routines are better optimized. Change-Id: I3e73856b2c1411977450e72af1741aab0ecf537e Reviewed-by: Eirik Aavitsland --- src/gui/image/qimage.cpp | 8 +- src/gui/image/qimage_conversions.cpp | 127 ++++-------------- .../qimageconversion/tst_qimageconversion.cpp | 10 ++ 3 files changed, 35 insertions(+), 110 deletions(-) diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 4c00c7705ad..efef5eee58b 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -2062,13 +2062,7 @@ QImage QImage::convertToFormat_helper(Format format, Qt::ImageConversionFlags fl Image_Converter converter = qimage_converter_map[d->format][format]; if (!converter && format > QImage::Format_Indexed8 && d->format > QImage::Format_Indexed8) { if (highColorPrecision(format) && highColorPrecision(d->format)) { - // Convert over RGBA64_Premultiplied - if (format == QImage::Format_RGBA64_Premultiplied) - converter = convert_generic_to_rgb64; - else { - Q_ASSERT(d->format != QImage::Format_RGBA64_Premultiplied); - return convertToFormat(Format_RGBA64_Premultiplied, flags).convertToFormat(format, flags); - } + converter = convert_generic_to_rgb64; } else converter = convert_generic; } diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp index ea9347183e4..82ffb8af8bd 100644 --- a/src/gui/image/qimage_conversions.cpp +++ b/src/gui/image/qimage_conversions.cpp @@ -223,18 +223,29 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio void convert_generic_to_rgb64(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) { - Q_ASSERT(dest->format == QImage::Format_RGBA64_Premultiplied); + Q_ASSERT(dest->format > QImage::Format_Indexed8); Q_ASSERT(src->format > QImage::Format_Indexed8); + QRgba64 buf[BufferSize]; + QRgba64 *buffer = buf; const QPixelLayout *srcLayout = &qPixelLayouts[src->format]; + const QPixelLayout *destLayout = &qPixelLayouts[dest->format]; const uchar *srcData = src->data; uchar *destData = dest->data; const FetchAndConvertPixelsFunc64 fetch = srcLayout->fetchToRGBA64PM; + const ConvertAndStorePixelsFunc64 store = qStoreFromRGBA64PM[dest->format]; for (int y = 0; y < src->height; ++y) { - const QRgba64 *ptr = fetch((QRgba64*)destData, srcData, 0, src->width, nullptr, nullptr); - if (ptr != (const QRgba64*)destData) { - memcpy(destData, ptr, dest->bytes_per_line); + int x = 0; + while (x < src->width) { + int l = src->width - x; + if (destLayout->bpp == QPixelLayout::BPP64) + buffer = reinterpret_cast(destData) + x; + else + l = qMin(l, BufferSize); + const QRgba64 *ptr = fetch(buffer, srcData, x, l, nullptr, nullptr); + store(destData, ptr, x, l, nullptr, nullptr); + x += l; } srcData += src->bytes_per_line; destData += dest->bytes_per_line; @@ -1204,33 +1215,6 @@ static void convert_RGBA64_to_ARGB32(QImageData *dest, const QImageData *src, Qt } } -template -static void convert_RGBA64PM_to_ARGB32(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) -{ - Q_ASSERT(src->format == QImage::Format_RGBA64_Premultiplied); - Q_ASSERT(RGBA || dest->format == QImage::Format_ARGB32); - Q_ASSERT(!RGBA || dest->format == QImage::Format_RGBA8888); - 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 >> 2) - dest->width; - const QRgba64 *src_data = reinterpret_cast(src->data); - uint *dest_data = reinterpret_cast(dest->data); - - for (int i = 0; i < src->height; ++i) { - const QRgba64 *end = src_data + src->width; - while (src_data < end) { - QRgba64 s = src_data->unpremultiplied(); - *dest_data = RGBA ? ARGB2RGBA(s.toArgb32()) : s.toArgb32(); - ++src_data; - ++dest_data; - } - src_data += src_pad; - dest_data += dest_pad; - } -} - template static void convert_ARGB32_to_RGBA64(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) { @@ -1240,74 +1224,14 @@ static void convert_ARGB32_to_RGBA64(QImageData *dest, const QImageData *src, Qt Q_ASSERT(src->width == dest->width); Q_ASSERT(src->height == dest->height); - const int src_pad = (src->bytes_per_line >> 2) - src->width; - const int dest_pad = (dest->bytes_per_line >> 3) - dest->width; - const uint *src_data = reinterpret_cast(src->data); - QRgba64 *dest_data = reinterpret_cast(dest->data); + const uchar *src_data = src->data; + uchar *dest_data = dest->data; + const FetchAndConvertPixelsFunc64 fetch = qPixelLayouts[src->format + 1].fetchToRGBA64PM; for (int i = 0; i < src->height; ++i) { - const uint *end = src_data + src->width; - while (src_data < end) { - if (RGBA) - *dest_data = QRgba64::fromArgb32(RGBA2ARGB(*src_data)); - else - *dest_data = QRgba64::fromArgb32(*src_data); - ++src_data; - ++dest_data; - } - src_data += src_pad; - dest_data += dest_pad; - } -} - -template -static void convert_RGBA64PM_to_RGB30(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) -{ - Q_ASSERT(src->format == QImage::Format_RGBA64_Premultiplied); - Q_ASSERT(dest->format == QImage::Format_RGB30 || dest->format == QImage::Format_BGR30); - 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 >> 2) - dest->width; - const QRgba64 *src_data = reinterpret_cast(src->data); - uint *dest_data = reinterpret_cast(dest->data); - - for (int i = 0; i < src->height; ++i) { - const QRgba64 *end = src_data + src->width; - while (src_data < end) { - *dest_data = 0xc0000000 | qConvertRgb64ToRgb30(src_data->unpremultiplied()); - ++src_data; - ++dest_data; - } - src_data += src_pad; - dest_data += dest_pad; - } -} - -template -static void convert_RGBA64PM_to_A2RGB30(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) -{ - Q_ASSERT(src->format == QImage::Format_RGBA64_Premultiplied); - Q_ASSERT(dest->format == QImage::Format_A2RGB30_Premultiplied - || dest->format == QImage::Format_A2BGR30_Premultiplied); - 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 >> 2) - dest->width; - const QRgba64 *src_data = reinterpret_cast(src->data); - uint *dest_data = reinterpret_cast(dest->data); - - for (int i = 0; i < src->height; ++i) { - const QRgba64 *end = src_data + src->width; - while (src_data < end) { - *dest_data = qConvertRgb64ToRgb30(*src_data); - ++src_data; - ++dest_data; - } - src_data += src_pad; - dest_data += dest_pad; + fetch(reinterpret_cast(dest_data), src_data, 0, src->width, nullptr, nullptr); + src_data += src->bytes_per_line;; + dest_data += dest->bytes_per_line; } } @@ -2958,7 +2882,6 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - convert_RGBA64PM_to_ARGB32, 0, 0, 0, @@ -2970,12 +2893,10 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - convert_RGBA64PM_to_ARGB32, 0, - convert_RGBA64PM_to_RGB30, - convert_RGBA64PM_to_A2RGB30, - convert_RGBA64PM_to_RGB30, - convert_RGBA64PM_to_A2RGB30, + 0, + 0, + 0, 0, 0, 0, 0, 0, convert_RGBA64PM_to_RGBA64, convert_RGBA64PM_to_RGBA64, diff --git a/tests/benchmarks/gui/image/qimageconversion/tst_qimageconversion.cpp b/tests/benchmarks/gui/image/qimageconversion/tst_qimageconversion.cpp index e0f69bee11b..605df100ee7 100644 --- a/tests/benchmarks/gui/image/qimageconversion/tst_qimageconversion.cpp +++ b/tests/benchmarks/gui/image/qimageconversion/tst_qimageconversion.cpp @@ -200,6 +200,8 @@ void tst_QImageConversion::convertRgb32_data() 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("argb32 -> rgba64") << argb32 << QImage::Format_RGBA64; + QTest::newRow("argb32 -> rgba64pm") << argb32 << QImage::Format_RGBA64_Premultiplied; QTest::newRow("argb32pm -> rgb16") << argb32pm << QImage::Format_RGB16; QTest::newRow("argb32pm -> rgb32") << argb32pm << QImage::Format_RGB32; @@ -239,6 +241,7 @@ void tst_QImageConversion::convertGeneric_data() QImage a2rgb30 = argb32.convertToFormat(QImage::Format_A2RGB30_Premultiplied); QImage rgb666 = rgb32.convertToFormat(QImage::Format_RGB666); QImage argb4444 = argb32.convertToFormat(QImage::Format_ARGB4444_Premultiplied); + QImage rgba64pm = argb32.convertToFormat(QImage::Format_RGBA64_Premultiplied); QTest::newRow("indexed8 -> rgb32") << i8 << QImage::Format_RGB32; QTest::newRow("indexed8 -> argb32") << i8 << QImage::Format_ARGB32; @@ -289,6 +292,13 @@ void tst_QImageConversion::convertGeneric_data() 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; + + QTest::newRow("rgba64pm -> argb32") << rgba64pm << QImage::Format_ARGB32; + QTest::newRow("rgba64pm -> rgbx8888") << rgba64pm << QImage::Format_RGBX8888; + QTest::newRow("rgba64pm -> rgba8888pm") << rgba64pm << QImage::Format_RGBA8888_Premultiplied; + QTest::newRow("rgba64pm -> rgb30") << rgba64pm << QImage::Format_RGB30; + QTest::newRow("rgba64pm -> a2bgr30") << rgba64pm << QImage::Format_A2BGR30_Premultiplied; + QTest::newRow("rgba64pm -> rgba64") << rgba64pm << QImage::Format_RGBA64; } void tst_QImageConversion::convertGeneric()