diff --git a/src/gui/image/qimage_p.h b/src/gui/image/qimage_p.h index ca7a4de4d8..7dbddbc67d 100644 --- a/src/gui/image/qimage_p.h +++ b/src/gui/image/qimage_p.h @@ -322,6 +322,63 @@ inline QImage::Format qt_alphaVersion(QImage::Format format) return QImage::Format_ARGB32_Premultiplied; } +// Returns an opaque version that is compatible with format +inline QImage::Format qt_maybeDataCompatibleOpaqueVersion(QImage::Format format) +{ + switch (format) { + case QImage::Format_ARGB6666_Premultiplied: + return QImage::Format_RGB666; + case QImage::Format_ARGB4444_Premultiplied: + return QImage::Format_RGB444; + case QImage::Format_RGBA8888: + case QImage::Format_RGBA8888_Premultiplied: + return QImage::Format_RGBX8888; + case QImage::Format_A2BGR30_Premultiplied: + return QImage::Format_BGR30; + case QImage::Format_A2RGB30_Premultiplied: + return QImage::Format_RGB30; + case QImage::Format_RGBA64: + case QImage::Format_RGBA64_Premultiplied: + return QImage::Format_RGBX64; + case QImage::Format_RGBA16FPx4: + case QImage::Format_RGBA16FPx4_Premultiplied: + return QImage::Format_RGBX16FPx4; + case QImage::Format_RGBA32FPx4: + case QImage::Format_RGBA32FPx4_Premultiplied: + return QImage::Format_RGBX32FPx4; + case QImage::Format_ARGB32_Premultiplied: + case QImage::Format_ARGB32: + return QImage::Format_RGB32; + case QImage::Format_RGB16: + case QImage::Format_RGB32: + case QImage::Format_RGB444: + case QImage::Format_RGB555: + case QImage::Format_RGB666: + case QImage::Format_RGB888: + case QImage::Format_BGR888: + case QImage::Format_RGBX8888: + case QImage::Format_BGR30: + case QImage::Format_RGB30: + case QImage::Format_RGBX64: + case QImage::Format_RGBX16FPx4: + case QImage::Format_RGBX32FPx4: + case QImage::Format_Grayscale8: + case QImage::Format_Grayscale16: + case QImage::Format_CMYK32: + return format; // Already opaque + case QImage::Format_Mono: + case QImage::Format_MonoLSB: + case QImage::Format_Indexed8: + case QImage::Format_ARGB8565_Premultiplied: + case QImage::Format_ARGB8555_Premultiplied: + case QImage::Format_Alpha8: + case QImage::Format_Invalid: + case QImage::NImageFormats: + break; + } + return format; // No compatible opaque versions +} + constexpr QImage::Format qt_toUnpremultipliedFormat(QImage::Format format) { // Assumes input is already a premultiplied format with an unpremultiplied counterpart @@ -380,10 +437,60 @@ inline bool qt_fpColorPrecision(QImage::Format format) return false; } -inline QImage::Format qt_maybeAlphaVersionWithSameDepth(QImage::Format format) +inline QImage::Format qt_maybeDataCompatibleAlphaVersion(QImage::Format format) { - const QImage::Format toFormat = qt_alphaVersion(format); - return qt_depthForFormat(format) == qt_depthForFormat(toFormat) ? toFormat : format; + switch (format) { + case QImage::Format_RGB32: + return QImage::Format_ARGB32_Premultiplied; + case QImage::Format_RGB666: + return QImage::Format_ARGB6666_Premultiplied; + case QImage::Format_RGB444: + return QImage::Format_ARGB4444_Premultiplied; + case QImage::Format_RGBX8888: + return QImage::Format_RGBA8888_Premultiplied; + case QImage::Format_BGR30: + return QImage::Format_A2BGR30_Premultiplied; + case QImage::Format_RGB30: + return QImage::Format_A2RGB30_Premultiplied; + case QImage::Format_RGBX64: + return QImage::Format_RGBA64_Premultiplied; + case QImage::Format_RGBX16FPx4: + return QImage::Format_RGBA16FPx4_Premultiplied; + case QImage::Format_RGBX32FPx4: + return QImage::Format_RGBA32FPx4_Premultiplied; + case QImage::Format_ARGB32: + case QImage::Format_ARGB32_Premultiplied: + case QImage::Format_ARGB8565_Premultiplied: + case QImage::Format_ARGB8555_Premultiplied: + case QImage::Format_ARGB6666_Premultiplied: + case QImage::Format_ARGB4444_Premultiplied: + case QImage::Format_RGBA8888: + case QImage::Format_RGBA8888_Premultiplied: + case QImage::Format_A2BGR30_Premultiplied: + case QImage::Format_A2RGB30_Premultiplied: + case QImage::Format_Alpha8: + case QImage::Format_RGBA64: + case QImage::Format_RGBA64_Premultiplied: + case QImage::Format_RGBA16FPx4: + case QImage::Format_RGBA16FPx4_Premultiplied: + case QImage::Format_RGBA32FPx4: + case QImage::Format_RGBA32FPx4_Premultiplied: + return format; // Already alpha versions + case QImage::Format_Mono: + case QImage::Format_MonoLSB: + case QImage::Format_Indexed8: + case QImage::Format_RGB16: + case QImage::Format_RGB555: + case QImage::Format_RGB888: + case QImage::Format_BGR888: + case QImage::Format_Grayscale8: + case QImage::Format_Grayscale16: + case QImage::Format_CMYK32: + case QImage::Format_Invalid: + case QImage::NImageFormats: + break; + } + return format; // No data-compatible alpha version } inline QImage::Format qt_opaqueVersionForPainting(QImage::Format format) diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index cea7024aaa..f62373d4ef 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -3713,15 +3713,9 @@ bool QRasterPaintEnginePrivate::canUseImageBlitting(QPainter::CompositionMode mo QImage::Format dFormat = rasterBuffer->format; QImage::Format sFormat = image.format(); - // Formats must match or source format must be a subset of destination format - if (dFormat != sFormat && image.pixelFormat().alphaUsage() == QPixelFormat::IgnoresAlpha) { - if ((sFormat == QImage::Format_RGB32 && dFormat == QImage::Format_ARGB32) - || (sFormat == QImage::Format_RGBX8888 && dFormat == QImage::Format_RGBA8888) - || (sFormat == QImage::Format_RGBX64 && dFormat == QImage::Format_RGBA64)) - sFormat = dFormat; - else - sFormat = qt_maybeAlphaVersionWithSameDepth(sFormat); // this returns premul formats - } + // Formats must match or source format must be an opaque version of destination format + if (dFormat != sFormat && image.pixelFormat().alphaUsage() == QPixelFormat::IgnoresAlpha) + dFormat = qt_maybeDataCompatibleOpaqueVersion(dFormat); return (dFormat == sFormat); } diff --git a/src/gui/painting/qrhibackingstore.cpp b/src/gui/painting/qrhibackingstore.cpp index 72ab28f1fc..586dfb44a4 100644 --- a/src/gui/painting/qrhibackingstore.cpp +++ b/src/gui/painting/qrhibackingstore.cpp @@ -60,7 +60,7 @@ QImage::Format QRhiBackingStore::format() const // image must have an alpha channel. Hence upgrading the format. Matches // what other platforms (Windows, xcb) do. if (QImage::toPixelFormat(fmt).alphaUsage() != QPixelFormat::UsesAlpha) - fmt = qt_maybeAlphaVersionWithSameDepth(fmt); + fmt = qt_maybeDataCompatibleAlphaVersion(fmt); return fmt; } diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.cpp b/src/plugins/platforms/windows/qwindowsbackingstore.cpp index 0f9d0172d9..07918f6094 100644 --- a/src/plugins/platforms/windows/qwindowsbackingstore.cpp +++ b/src/plugins/platforms/windows/qwindowsbackingstore.cpp @@ -117,7 +117,7 @@ void QWindowsBackingStore::resize(const QSize &size, const QRegion ®ion) if (QImage::toPixelFormat(format).alphaUsage() == QPixelFormat::UsesAlpha) m_alphaNeedsFill = true; else // upgrade but here we know app painting does not rely on alpha hence no need to fill - format = qt_maybeAlphaVersionWithSameDepth(format); + format = qt_maybeDataCompatibleAlphaVersion(format); QWindowsNativeImage *oldwni = m_image.data(); auto *newwni = new QWindowsNativeImage(size.width(), size.height(), format); diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp index 0659cf9fc4..8353fac6a9 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp +++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp @@ -173,7 +173,7 @@ void QXcbBackingStoreImage::init(const QSize &size, uint depth, QImage::Format f m_qimage_format = format; m_hasAlpha = QImage::toPixelFormat(m_qimage_format).alphaUsage() == QPixelFormat::UsesAlpha; if (!m_hasAlpha) - m_qimage_format = qt_maybeAlphaVersionWithSameDepth(m_qimage_format); + m_qimage_format = qt_maybeDataCompatibleAlphaVersion(m_qimage_format); memset(&m_shm_info, 0, sizeof m_shm_info);