diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-04-04 17:45:28 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-05-02 14:20:55 +0000 |
commit | 648ee7aa020d04b160ec56187f49f761ffab93cc (patch) | |
tree | 3d68cc7feb1393c26259ea92f52f4e3fba99fb0d /src/gui/image | |
parent | 6a39e49a6cdeb28a04a3657bb6a22f848d5dfa9d (diff) |
Merge drawhelper convert-from and store
Avoids using an intermediate buffer on store and simplifies the code.
Change-Id: I2dc4e735eb770f90dc99fe0f513b4df3b35ee793
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
Diffstat (limited to 'src/gui/image')
-rw-r--r-- | src/gui/image/qimage.cpp | 27 | ||||
-rw-r--r-- | src/gui/image/qimage_conversions.cpp | 107 | ||||
-rw-r--r-- | src/gui/image/qimage_sse4.cpp | 8 | ||||
-rw-r--r-- | src/gui/image/qpixmap_blitter.cpp | 8 | ||||
-rw-r--r-- | src/gui/image/qpixmap_raster.cpp | 11 |
5 files changed, 69 insertions, 92 deletions
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index e1cac2011d..907f90f3a5 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -2303,8 +2303,7 @@ QRgb QImage::pixel(int x, int y) const } const QPixelLayout *layout = &qPixelLayouts[d->format]; uint result; - const uint *ptr = qFetchPixels[layout->bpp](&result, s, x, 1); - return *layout->convertToARGB32PM(&result, ptr, 1, 0, 0); + return *layout->fetchToARGB32PM(&result, s, x, 1, nullptr, nullptr); } /*! @@ -2405,9 +2404,7 @@ void QImage::setPixel(int x, int y, uint index_or_rgb) } const QPixelLayout *layout = &qPixelLayouts[d->format]; - uint result; - const uint *ptr = layout->convertFromARGB32PM(&result, &index_or_rgb, 1, 0, 0); - qStorePixels[layout->bpp](s, ptr, x, 1); + layout->storeFromARGB32PM(s, &index_or_rgb, x, 1, nullptr, nullptr); } /*! @@ -2584,14 +2581,13 @@ bool QImage::allGray() const uint buffer[BufferSize]; const QPixelLayout *layout = &qPixelLayouts[d->format]; - FetchPixelsFunc fetch = qFetchPixels[layout->bpp]; + const auto fetch = layout->fetchToARGB32PM; for (int j = 0; j < d->height; ++j) { const uchar *b = constScanLine(j); int x = 0; while (x < d->width) { int l = qMin(d->width - x, BufferSize); - const uint *ptr = fetch(buffer, b, x, l); - ptr = layout->convertToARGB32PM(buffer, ptr, l, 0, 0); + const uint *ptr = fetch(buffer, b, x, l, nullptr, nullptr); for (int i = 0; i < l; ++i) { if (!qIsGray(ptr[i])) return false; @@ -3209,9 +3205,7 @@ void QImage::mirrored_inplace(bool horizontal, bool vertical) inline void rgbSwapped_generic(int width, int height, const QImage *src, QImage *dst, const QPixelLayout* layout) { - FetchPixelsFunc fetch = qFetchPixels[layout->bpp]; - StorePixelsFunc store = qStorePixels[layout->bpp]; - RbSwapFunc func = layout->rbSwap; + const RbSwapFunc func = layout->rbSwap; if (!func) { qWarning("Trying to rb-swap an image format where it doesn't make sense"); if (src != dst) @@ -3219,19 +3213,10 @@ inline void rgbSwapped_generic(int width, int height, const QImage *src, QImage return; } - uint buffer[BufferSize]; for (int i = 0; i < height; ++i) { uchar *q = dst->scanLine(i); const uchar *p = src->constScanLine(i); - int x = 0; - while (x < width) { - int l = qMin(width - x, BufferSize); - const uint *ptr = fetch(buffer, p, x, l); - ptr = func(buffer, ptr, l); - if (q != (const uchar *)ptr) - store(q, ptr, x, l); - x += l; - } + func(q, p, width); } } diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp index 16ad0a3edc..ce47b78682 100644 --- a/src/gui/image/qimage_conversions.cpp +++ b/src/gui/image/qimage_conversions.cpp @@ -118,26 +118,35 @@ void qGamma_correct_back_to_linear_cs(QImage *image) Internal routines for converting image depth. *****************************************************************************/ -// The drawhelper conversions from/to RGB32 are passthroughs which is not always correct for general image conversion. -static const uint *QT_FASTCALL convertRGB32FromARGB32PM(uint *buffer, const uint *src, int count, - const QVector<QRgb> *, QDitherInfo *) +// The drawhelper conversions from/to RGB32 are passthroughs which is not always correct for general image conversion +static void QT_FASTCALL storeRGB32FromARGB32PM(uchar *dest, const uint *src, int index, int count, + const QVector<QRgb> *, QDitherInfo *) { + uint *d = reinterpret_cast<uint *>(dest) + index; for (int i = 0; i < count; ++i) - buffer[i] = 0xff000000 | qUnpremultiply(src[i]); - return buffer; + d[i] = 0xff000000 | qUnpremultiply(src[i]); +} + +static void QT_FASTCALL storeRGB32FromARGB32(uchar *dest, const uint *src, int index, int count, + const QVector<QRgb> *, QDitherInfo *) +{ + uint *d = reinterpret_cast<uint *>(dest) + index; + for (int i = 0; i < count; ++i) + d[i] = 0xff000000 | src[i]; } -static const uint *QT_FASTCALL maskRGB32(uint *buffer, const uint *src, int count, - const QVector<QRgb> *, QDitherInfo *) +static const uint *QT_FASTCALL fetchRGB32ToARGB32PM(uint *buffer, const uchar *src, int index, int count, + const QVector<QRgb> *, QDitherInfo *) { + const uint *s = reinterpret_cast<const uint *>(src) + index; for (int i = 0; i < count; ++i) - buffer[i] = 0xff000000 |src[i]; + buffer[i] = 0xff000000 | s[i]; return buffer; } #ifdef QT_COMPILER_SUPPORTS_SSE4_1 -extern const uint *QT_FASTCALL convertRGB32FromARGB32PM_sse4(uint *buffer, const uint *src, int count, - const QVector<QRgb> *, QDitherInfo *); +extern void QT_FASTCALL storeRGB32FromARGB32PM_sse4(uchar *dest, const uint *src, int index, int count, + const QVector<QRgb> *, QDitherInfo *); #endif void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags flags) @@ -152,34 +161,32 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio const uchar *srcData = src->data; uchar *destData = dest->data; - const FetchPixelsFunc fetch = qFetchPixels[srcLayout->bpp]; - const StorePixelsFunc store = qStorePixels[destLayout->bpp]; - ConvertFunc convertToARGB32PM = srcLayout->convertToARGB32PM; - ConvertFunc convertFromARGB32PM = destLayout->convertFromARGB32PM; - if (!srcLayout->hasAlphaChannel && destLayout->convertFromRGB32) { - // If the source doesn't have an alpha channel, we can use the faster convertFromRGB32 method. - convertFromARGB32PM = destLayout->convertFromRGB32; + FetchAndConvertPixelsFunc fetch = srcLayout->fetchToARGB32PM; + ConvertAndStorePixelsFunc store = destLayout->storeFromARGB32PM; + if (!srcLayout->hasAlphaChannel && destLayout->storeFromRGB32) { + // If the source doesn't have an alpha channel, we can use the faster storeFromRGB32 method. + store = destLayout->storeFromRGB32; } else { // The drawhelpers do not mask the alpha value in RGB32, we want to here. if (src->format == QImage::Format_RGB32) - convertToARGB32PM = maskRGB32; + fetch = fetchRGB32ToARGB32PM; if (dest->format == QImage::Format_RGB32) { #ifdef QT_COMPILER_SUPPORTS_SSE4_1 if (qCpuHasFeature(SSE4_1)) - convertFromARGB32PM = convertRGB32FromARGB32PM_sse4; + store = storeRGB32FromARGB32PM_sse4; else #endif - convertFromARGB32PM = convertRGB32FromARGB32PM; + store = storeRGB32FromARGB32PM; } } if ((src->format == QImage::Format_ARGB32 || src->format == QImage::Format_RGBA8888) && - !destLayout->hasAlphaChannel && destLayout->convertFromRGB32) { + !destLayout->hasAlphaChannel && destLayout->storeFromRGB32) { // Avoid unnecessary premultiply and unpremultiply when converting from unpremultiplied src format. - convertToARGB32PM = qPixelLayouts[src->format + 1].convertToARGB32PM; + fetch = qPixelLayouts[src->format + 1].fetchToARGB32PM; if (dest->format == QImage::Format_RGB32) - convertFromARGB32PM = maskRGB32; + store = storeRGB32FromARGB32; else - convertFromARGB32PM = destLayout->convertFromRGB32; + store = destLayout->storeFromRGB32; } QDitherInfo dither; QDitherInfo *ditherPtr = 0; @@ -196,11 +203,8 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio buffer = reinterpret_cast<uint *>(destData) + x; else l = qMin(l, BufferSize); - const uint *ptr = fetch(buffer, srcData, x, l); - ptr = convertToARGB32PM(buffer, ptr, l, 0, ditherPtr); - ptr = convertFromARGB32PM(buffer, ptr, l, 0, ditherPtr); - if (ptr != reinterpret_cast<uint *>(destData)) - store(destData, ptr, x, l); + const uint *ptr = fetch(buffer, srcData, x, l, 0, ditherPtr); + store(destData, ptr, x, l, 0, ditherPtr); x += l; } srcData += src->bytes_per_line; @@ -216,38 +220,37 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im if (data->depth != qt_depthForFormat(dst_format)) return false; - uint buffer[BufferSize]; + uint buf[BufferSize]; + uint *buffer = buf; const QPixelLayout *srcLayout = &qPixelLayouts[data->format]; const QPixelLayout *destLayout = &qPixelLayouts[dst_format]; uchar *srcData = data->data; - const FetchPixelsFunc fetch = qFetchPixels[srcLayout->bpp]; - const StorePixelsFunc store = qStorePixels[destLayout->bpp]; - ConvertFunc convertToARGB32PM = srcLayout->convertToARGB32PM; - ConvertFunc convertFromARGB32PM = destLayout->convertFromARGB32PM; - if (!srcLayout->hasAlphaChannel && destLayout->convertFromRGB32) { - // If the source doesn't have an alpha channel, we can use the faster convertFromRGB32 method. - convertFromARGB32PM = destLayout->convertFromRGB32; + FetchAndConvertPixelsFunc fetch = srcLayout->fetchToARGB32PM; + ConvertAndStorePixelsFunc store = destLayout->storeFromARGB32PM; + if (!srcLayout->hasAlphaChannel && destLayout->storeFromRGB32) { + // If the source doesn't have an alpha channel, we can use the faster storeFromRGB32 method. + store = destLayout->storeFromRGB32; } else { if (data->format == QImage::Format_RGB32) - convertToARGB32PM = maskRGB32; + fetch = fetchRGB32ToARGB32PM; if (dst_format == QImage::Format_RGB32) { #ifdef QT_COMPILER_SUPPORTS_SSE4_1 if (qCpuHasFeature(SSE4_1)) - convertFromARGB32PM = convertRGB32FromARGB32PM_sse4; + store = storeRGB32FromARGB32PM_sse4; else #endif - convertFromARGB32PM = convertRGB32FromARGB32PM; + store = storeRGB32FromARGB32PM; } } if ((data->format == QImage::Format_ARGB32 || data->format == QImage::Format_RGBA8888) && - !destLayout->hasAlphaChannel && destLayout->convertFromRGB32) { + !destLayout->hasAlphaChannel && destLayout->storeFromRGB32) { // Avoid unnecessary premultiply and unpremultiply when converting from unpremultiplied src format. - convertToARGB32PM = qPixelLayouts[data->format + 1].convertToARGB32PM; - if (dst_format == QImage::Format_RGB32) - convertFromARGB32PM = maskRGB32; + fetch = qPixelLayouts[data->format + 1].fetchToARGB32PM; + if (data->format == QImage::Format_RGB32) + store = storeRGB32FromARGB32; else - convertFromARGB32PM = destLayout->convertFromRGB32; + store = destLayout->storeFromRGB32; } QDitherInfo dither; QDitherInfo *ditherPtr = 0; @@ -259,13 +262,13 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im int x = 0; while (x < data->width) { dither.x = x; - int l = qMin(data->width - x, BufferSize); - const uint *ptr = fetch(buffer, srcData, x, l); - ptr = convertToARGB32PM(buffer, ptr, l, 0, ditherPtr); - ptr = convertFromARGB32PM(buffer, ptr, l, 0, ditherPtr); - // The conversions might be passthrough and not use the buffer, in that case we are already done. - if (srcData != (const uchar*)ptr) - store(srcData, ptr, x, l); + int l = data->width - x; + if (destLayout->bpp == QPixelLayout::BPP32) + buffer = reinterpret_cast<uint *>(srcData) + x; + else + l = qMin(l, BufferSize); + const uint *ptr = fetch(buffer, srcData, x, l, nullptr, ditherPtr); + store(srcData, ptr, x, l, nullptr, ditherPtr); x += l; } srcData += data->bytes_per_line; diff --git a/src/gui/image/qimage_sse4.cpp b/src/gui/image/qimage_sse4.cpp index 0e2c2f492e..2f6649c1bc 100644 --- a/src/gui/image/qimage_sse4.cpp +++ b/src/gui/image/qimage_sse4.cpp @@ -47,12 +47,12 @@ QT_BEGIN_NAMESPACE -const uint *QT_FASTCALL convertRGB32FromARGB32PM_sse4(uint *buffer, const uint *src, int count, - const QVector<QRgb> *, QDitherInfo *) +void QT_FASTCALL storeRGB32FromARGB32PM_sse4(uchar *dest, const uint *src, int index, int count, + const QVector<QRgb> *, QDitherInfo *) { + uint *d = reinterpret_cast<uint *>(dest) + index; for (int i = 0; i < count; ++i) - buffer[i] = 0xff000000 | qUnpremultiply_sse4(src[i]); - return buffer; + d[i] = 0xff000000 | qUnpremultiply_sse4(src[i]); } void convert_ARGB_to_ARGB_PM_sse4(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) diff --git a/src/gui/image/qpixmap_blitter.cpp b/src/gui/image/qpixmap_blitter.cpp index 646e737afa..649a25250c 100644 --- a/src/gui/image/qpixmap_blitter.cpp +++ b/src/gui/image/qpixmap_blitter.cpp @@ -150,13 +150,7 @@ void QBlittablePlatformPixmap::fill(const QColor &color) m_alpha = true; } - uint pixel = qPremultiply(color.rgba()); - const QPixelLayout *layout = &qPixelLayouts[blittable()->lock()->format()]; - Q_ASSERT(layout->convertFromARGB32PM); - layout->convertFromARGB32PM(&pixel, &pixel, 1, 0, 0); - - //so premultiplied formats are supported and ARGB32 and RGB32 - blittable()->lock()->fill(pixel); + blittable()->lock()->fill(color); } } diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp index 431002d032..13c1c29d5b 100644 --- a/src/gui/image/qpixmap_raster.cpp +++ b/src/gui/image/qpixmap_raster.cpp @@ -193,17 +193,12 @@ void QRasterPlatformPixmap::fill(const QColor &color) if (alpha != 255) { if (!image.hasAlphaChannel()) { QImage::Format toFormat = qt_alphaVersionForPainting(image.format()); - if (!image.isNull() && qt_depthForFormat(image.format()) == qt_depthForFormat(toFormat)) { - image.detach(); - image.d->format = toFormat; - } else { + if (!image.reinterpretAsFormat(toFormat)) image = QImage(image.width(), image.height(), toFormat); - } } } - pixel = qPremultiply(color.rgba()); - const QPixelLayout *layout = &qPixelLayouts[image.format()]; - layout->convertFromARGB32PM(&pixel, &pixel, 1, 0, 0); + image.fill(color); + return; } else if (image.format() == QImage::Format_Alpha8) { pixel = qAlpha(color.rgba()); } else if (image.format() == QImage::Format_Grayscale8) { |