From aaab54772bf47b8d43f295928bf4b9b2c5775738 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 2 Oct 2024 19:42:19 +0200 Subject: [PATCH] Add isCompressedPixelFormat{Normalized,FloatingPoint,Srgb}() helpers. To have feature parity with similar helpers for non-compressed PixelFormat. --- doc/changelog.dox | 7 +- src/Magnum/PixelFormat.cpp | 381 ++++++++++++++++++++++++++++ src/Magnum/PixelFormat.h | 71 +++++- src/Magnum/Test/PixelFormatTest.cpp | 99 ++++++++ src/Magnum/VertexFormat.h | 2 +- 5 files changed, 550 insertions(+), 10 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index 059e70e07..ed2b3cf1e 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -70,8 +70,11 @@ See also: - New @ref pixelFormatChannelFormat(), @ref pixelFormatChannelCount(), @ref isPixelFormatNormalized(), @ref isPixelFormatIntegral(), @ref isPixelFormatFloatingPoint(), @ref isPixelFormatSrgb(), - @ref isPixelFormatDepthOrStencil() and - @ref pixelFormat(PixelFormat, UnsignedInt, bool) helpers + @ref isPixelFormatDepthOrStencil(), + @ref pixelFormat(PixelFormat, UnsignedInt, bool), + @ref isCompressedPixelFormatNormalized(), + @ref isCompressedPixelFormatFloatingPoint() and + @ref isCompressedPixelFormatSrgb() helpers - New @ref Degh, @ref Radh, @ref Range1Dh, @ref Range2Dh and @ref Range3Dh typedefs for half-float angles and ranges - New @ref Range1Dui, @ref Range2Dui and @ref Range3Dui typedefs for unsigned diff --git a/src/Magnum/PixelFormat.cpp b/src/Magnum/PixelFormat.cpp index f57fb25b5..1d0516d51 100644 --- a/src/Magnum/PixelFormat.cpp +++ b/src/Magnum/PixelFormat.cpp @@ -808,6 +808,387 @@ UnsignedInt compressedPixelFormatBlockDataSize(const CompressedPixelFormat forma return (CompressedBlockData[UnsignedInt(format) - 1] & 0xf) + 1; } +bool isCompressedPixelFormatNormalized(const CompressedPixelFormat format) { + CORRADE_ASSERT(!isCompressedPixelFormatImplementationSpecific(format), + "isCompressedPixelFormatNormalized(): can't determine type of an implementation-specific format" << Debug::hex << compressedPixelFormatUnwrap(format), {}); + + #ifdef CORRADE_TARGET_GCC + #pragma GCC diagnostic push + #pragma GCC diagnostic error "-Wswitch" + #endif + switch(format) { + case CompressedPixelFormat::Bc1RGBUnorm: + case CompressedPixelFormat::Bc1RGBSrgb: + case CompressedPixelFormat::Bc1RGBAUnorm: + case CompressedPixelFormat::Bc1RGBASrgb: + case CompressedPixelFormat::Bc2RGBAUnorm: + case CompressedPixelFormat::Bc2RGBASrgb: + case CompressedPixelFormat::Bc3RGBAUnorm: + case CompressedPixelFormat::Bc3RGBASrgb: + case CompressedPixelFormat::Bc4RUnorm: + case CompressedPixelFormat::Bc4RSnorm: + case CompressedPixelFormat::Bc5RGUnorm: + case CompressedPixelFormat::Bc5RGSnorm: + case CompressedPixelFormat::Bc7RGBAUnorm: + case CompressedPixelFormat::Bc7RGBASrgb: + case CompressedPixelFormat::EacR11Unorm: + case CompressedPixelFormat::EacR11Snorm: + case CompressedPixelFormat::EacRG11Unorm: + case CompressedPixelFormat::EacRG11Snorm: + case CompressedPixelFormat::Etc2RGB8Unorm: + case CompressedPixelFormat::Etc2RGB8Srgb: + case CompressedPixelFormat::Etc2RGB8A1Unorm: + case CompressedPixelFormat::Etc2RGB8A1Srgb: + case CompressedPixelFormat::Etc2RGBA8Unorm: + case CompressedPixelFormat::Etc2RGBA8Srgb: + case CompressedPixelFormat::Astc4x4RGBAUnorm: + case CompressedPixelFormat::Astc4x4RGBASrgb: + case CompressedPixelFormat::Astc5x4RGBAUnorm: + case CompressedPixelFormat::Astc5x4RGBASrgb: + case CompressedPixelFormat::Astc5x5RGBAUnorm: + case CompressedPixelFormat::Astc5x5RGBASrgb: + case CompressedPixelFormat::Astc6x5RGBAUnorm: + case CompressedPixelFormat::Astc6x5RGBASrgb: + case CompressedPixelFormat::Astc6x6RGBAUnorm: + case CompressedPixelFormat::Astc6x6RGBASrgb: + case CompressedPixelFormat::Astc8x5RGBAUnorm: + case CompressedPixelFormat::Astc8x5RGBASrgb: + case CompressedPixelFormat::Astc8x6RGBAUnorm: + case CompressedPixelFormat::Astc8x6RGBASrgb: + case CompressedPixelFormat::Astc8x8RGBAUnorm: + case CompressedPixelFormat::Astc8x8RGBASrgb: + case CompressedPixelFormat::Astc10x5RGBAUnorm: + case CompressedPixelFormat::Astc10x5RGBASrgb: + case CompressedPixelFormat::Astc10x6RGBAUnorm: + case CompressedPixelFormat::Astc10x6RGBASrgb: + case CompressedPixelFormat::Astc10x8RGBAUnorm: + case CompressedPixelFormat::Astc10x8RGBASrgb: + case CompressedPixelFormat::Astc10x10RGBAUnorm: + case CompressedPixelFormat::Astc10x10RGBASrgb: + case CompressedPixelFormat::Astc12x10RGBAUnorm: + case CompressedPixelFormat::Astc12x10RGBASrgb: + case CompressedPixelFormat::Astc12x12RGBAUnorm: + case CompressedPixelFormat::Astc12x12RGBASrgb: + case CompressedPixelFormat::Astc3x3x3RGBAUnorm: + case CompressedPixelFormat::Astc3x3x3RGBASrgb: + case CompressedPixelFormat::Astc4x3x3RGBAUnorm: + case CompressedPixelFormat::Astc4x3x3RGBASrgb: + case CompressedPixelFormat::Astc4x4x3RGBAUnorm: + case CompressedPixelFormat::Astc4x4x3RGBASrgb: + case CompressedPixelFormat::Astc4x4x4RGBAUnorm: + case CompressedPixelFormat::Astc4x4x4RGBASrgb: + case CompressedPixelFormat::Astc5x4x4RGBAUnorm: + case CompressedPixelFormat::Astc5x4x4RGBASrgb: + case CompressedPixelFormat::Astc5x5x4RGBAUnorm: + case CompressedPixelFormat::Astc5x5x4RGBASrgb: + case CompressedPixelFormat::Astc5x5x5RGBAUnorm: + case CompressedPixelFormat::Astc5x5x5RGBASrgb: + case CompressedPixelFormat::Astc6x5x5RGBAUnorm: + case CompressedPixelFormat::Astc6x5x5RGBASrgb: + case CompressedPixelFormat::Astc6x6x5RGBAUnorm: + case CompressedPixelFormat::Astc6x6x5RGBASrgb: + case CompressedPixelFormat::Astc6x6x6RGBAUnorm: + case CompressedPixelFormat::Astc6x6x6RGBASrgb: + case CompressedPixelFormat::PvrtcRGB2bppUnorm: + case CompressedPixelFormat::PvrtcRGB2bppSrgb: + case CompressedPixelFormat::PvrtcRGBA2bppUnorm: + case CompressedPixelFormat::PvrtcRGBA2bppSrgb: + case CompressedPixelFormat::PvrtcRGB4bppUnorm: + case CompressedPixelFormat::PvrtcRGB4bppSrgb: + case CompressedPixelFormat::PvrtcRGBA4bppUnorm: + case CompressedPixelFormat::PvrtcRGBA4bppSrgb: + return true; + case CompressedPixelFormat::Bc6hRGBUfloat: + case CompressedPixelFormat::Bc6hRGBSfloat: + case CompressedPixelFormat::Astc4x4RGBAF: + case CompressedPixelFormat::Astc5x4RGBAF: + case CompressedPixelFormat::Astc5x5RGBAF: + case CompressedPixelFormat::Astc6x5RGBAF: + case CompressedPixelFormat::Astc6x6RGBAF: + case CompressedPixelFormat::Astc8x5RGBAF: + case CompressedPixelFormat::Astc8x6RGBAF: + case CompressedPixelFormat::Astc8x8RGBAF: + case CompressedPixelFormat::Astc10x5RGBAF: + case CompressedPixelFormat::Astc10x6RGBAF: + case CompressedPixelFormat::Astc10x8RGBAF: + case CompressedPixelFormat::Astc10x10RGBAF: + case CompressedPixelFormat::Astc12x10RGBAF: + case CompressedPixelFormat::Astc12x12RGBAF: + case CompressedPixelFormat::Astc3x3x3RGBAF: + case CompressedPixelFormat::Astc4x3x3RGBAF: + case CompressedPixelFormat::Astc4x4x3RGBAF: + case CompressedPixelFormat::Astc4x4x4RGBAF: + case CompressedPixelFormat::Astc5x4x4RGBAF: + case CompressedPixelFormat::Astc5x5x4RGBAF: + case CompressedPixelFormat::Astc5x5x5RGBAF: + case CompressedPixelFormat::Astc6x5x5RGBAF: + case CompressedPixelFormat::Astc6x6x5RGBAF: + case CompressedPixelFormat::Astc6x6x6RGBAF: + return false; + } + #ifdef CORRADE_TARGET_GCC + #pragma GCC diagnostic pop + #endif + + CORRADE_ASSERT_UNREACHABLE("isCompressedPixelFormatNormalized(): invalid format" << format, {}); +} + +bool isCompressedPixelFormatFloatingPoint(const CompressedPixelFormat format) { + CORRADE_ASSERT(!isCompressedPixelFormatImplementationSpecific(format), + "isCompressedPixelFormatFloatingPoint(): can't determine type of an implementation-specific format" << Debug::hex << compressedPixelFormatUnwrap(format), {}); + + /* Yes, this is currently the exact inverse of + isCompressedPixelFormatNormalized(), so one function could call the + other and negate the result. But keeping it this way in case there's + some future integer CompressedPixelFormat, which would be false in both + and which would need a new isCompressedPixelFormatIntegral(). */ + + #ifdef CORRADE_TARGET_GCC + #pragma GCC diagnostic push + #pragma GCC diagnostic error "-Wswitch" + #endif + switch(format) { + case CompressedPixelFormat::Bc6hRGBUfloat: + case CompressedPixelFormat::Bc6hRGBSfloat: + case CompressedPixelFormat::Astc4x4RGBAF: + case CompressedPixelFormat::Astc5x4RGBAF: + case CompressedPixelFormat::Astc5x5RGBAF: + case CompressedPixelFormat::Astc6x5RGBAF: + case CompressedPixelFormat::Astc6x6RGBAF: + case CompressedPixelFormat::Astc8x5RGBAF: + case CompressedPixelFormat::Astc8x6RGBAF: + case CompressedPixelFormat::Astc8x8RGBAF: + case CompressedPixelFormat::Astc10x5RGBAF: + case CompressedPixelFormat::Astc10x6RGBAF: + case CompressedPixelFormat::Astc10x8RGBAF: + case CompressedPixelFormat::Astc10x10RGBAF: + case CompressedPixelFormat::Astc12x10RGBAF: + case CompressedPixelFormat::Astc12x12RGBAF: + case CompressedPixelFormat::Astc3x3x3RGBAF: + case CompressedPixelFormat::Astc4x3x3RGBAF: + case CompressedPixelFormat::Astc4x4x3RGBAF: + case CompressedPixelFormat::Astc4x4x4RGBAF: + case CompressedPixelFormat::Astc5x4x4RGBAF: + case CompressedPixelFormat::Astc5x5x4RGBAF: + case CompressedPixelFormat::Astc5x5x5RGBAF: + case CompressedPixelFormat::Astc6x5x5RGBAF: + case CompressedPixelFormat::Astc6x6x5RGBAF: + case CompressedPixelFormat::Astc6x6x6RGBAF: + return true; + case CompressedPixelFormat::Bc1RGBUnorm: + case CompressedPixelFormat::Bc1RGBSrgb: + case CompressedPixelFormat::Bc1RGBAUnorm: + case CompressedPixelFormat::Bc1RGBASrgb: + case CompressedPixelFormat::Bc2RGBAUnorm: + case CompressedPixelFormat::Bc2RGBASrgb: + case CompressedPixelFormat::Bc3RGBAUnorm: + case CompressedPixelFormat::Bc3RGBASrgb: + case CompressedPixelFormat::Bc4RUnorm: + case CompressedPixelFormat::Bc4RSnorm: + case CompressedPixelFormat::Bc5RGUnorm: + case CompressedPixelFormat::Bc5RGSnorm: + case CompressedPixelFormat::Bc7RGBAUnorm: + case CompressedPixelFormat::Bc7RGBASrgb: + case CompressedPixelFormat::EacR11Unorm: + case CompressedPixelFormat::EacR11Snorm: + case CompressedPixelFormat::EacRG11Unorm: + case CompressedPixelFormat::EacRG11Snorm: + case CompressedPixelFormat::Etc2RGB8Unorm: + case CompressedPixelFormat::Etc2RGB8Srgb: + case CompressedPixelFormat::Etc2RGB8A1Unorm: + case CompressedPixelFormat::Etc2RGB8A1Srgb: + case CompressedPixelFormat::Etc2RGBA8Unorm: + case CompressedPixelFormat::Etc2RGBA8Srgb: + case CompressedPixelFormat::Astc4x4RGBAUnorm: + case CompressedPixelFormat::Astc4x4RGBASrgb: + case CompressedPixelFormat::Astc5x4RGBAUnorm: + case CompressedPixelFormat::Astc5x4RGBASrgb: + case CompressedPixelFormat::Astc5x5RGBAUnorm: + case CompressedPixelFormat::Astc5x5RGBASrgb: + case CompressedPixelFormat::Astc6x5RGBAUnorm: + case CompressedPixelFormat::Astc6x5RGBASrgb: + case CompressedPixelFormat::Astc6x6RGBAUnorm: + case CompressedPixelFormat::Astc6x6RGBASrgb: + case CompressedPixelFormat::Astc8x5RGBAUnorm: + case CompressedPixelFormat::Astc8x5RGBASrgb: + case CompressedPixelFormat::Astc8x6RGBAUnorm: + case CompressedPixelFormat::Astc8x6RGBASrgb: + case CompressedPixelFormat::Astc8x8RGBAUnorm: + case CompressedPixelFormat::Astc8x8RGBASrgb: + case CompressedPixelFormat::Astc10x5RGBAUnorm: + case CompressedPixelFormat::Astc10x5RGBASrgb: + case CompressedPixelFormat::Astc10x6RGBAUnorm: + case CompressedPixelFormat::Astc10x6RGBASrgb: + case CompressedPixelFormat::Astc10x8RGBAUnorm: + case CompressedPixelFormat::Astc10x8RGBASrgb: + case CompressedPixelFormat::Astc10x10RGBAUnorm: + case CompressedPixelFormat::Astc10x10RGBASrgb: + case CompressedPixelFormat::Astc12x10RGBAUnorm: + case CompressedPixelFormat::Astc12x10RGBASrgb: + case CompressedPixelFormat::Astc12x12RGBAUnorm: + case CompressedPixelFormat::Astc12x12RGBASrgb: + case CompressedPixelFormat::Astc3x3x3RGBAUnorm: + case CompressedPixelFormat::Astc3x3x3RGBASrgb: + case CompressedPixelFormat::Astc4x3x3RGBAUnorm: + case CompressedPixelFormat::Astc4x3x3RGBASrgb: + case CompressedPixelFormat::Astc4x4x3RGBAUnorm: + case CompressedPixelFormat::Astc4x4x3RGBASrgb: + case CompressedPixelFormat::Astc4x4x4RGBAUnorm: + case CompressedPixelFormat::Astc4x4x4RGBASrgb: + case CompressedPixelFormat::Astc5x4x4RGBAUnorm: + case CompressedPixelFormat::Astc5x4x4RGBASrgb: + case CompressedPixelFormat::Astc5x5x4RGBAUnorm: + case CompressedPixelFormat::Astc5x5x4RGBASrgb: + case CompressedPixelFormat::Astc5x5x5RGBAUnorm: + case CompressedPixelFormat::Astc5x5x5RGBASrgb: + case CompressedPixelFormat::Astc6x5x5RGBAUnorm: + case CompressedPixelFormat::Astc6x5x5RGBASrgb: + case CompressedPixelFormat::Astc6x6x5RGBAUnorm: + case CompressedPixelFormat::Astc6x6x5RGBASrgb: + case CompressedPixelFormat::Astc6x6x6RGBAUnorm: + case CompressedPixelFormat::Astc6x6x6RGBASrgb: + case CompressedPixelFormat::PvrtcRGB2bppUnorm: + case CompressedPixelFormat::PvrtcRGB2bppSrgb: + case CompressedPixelFormat::PvrtcRGBA2bppUnorm: + case CompressedPixelFormat::PvrtcRGBA2bppSrgb: + case CompressedPixelFormat::PvrtcRGB4bppUnorm: + case CompressedPixelFormat::PvrtcRGB4bppSrgb: + case CompressedPixelFormat::PvrtcRGBA4bppUnorm: + case CompressedPixelFormat::PvrtcRGBA4bppSrgb: + return false; + } + #ifdef CORRADE_TARGET_GCC + #pragma GCC diagnostic pop + #endif + + CORRADE_ASSERT_UNREACHABLE("isCompressedPixelFormatFloatingPoint(): invalid format" << format, {}); +} + +bool isCompressedPixelFormatSrgb(const CompressedPixelFormat format) { + CORRADE_ASSERT(!isCompressedPixelFormatImplementationSpecific(format), + "isCompressedPixelFormatSrgb(): can't determine colorspace of an implementation-specific format" << Debug::hex << compressedPixelFormatUnwrap(format), {}); + + #ifdef CORRADE_TARGET_GCC + #pragma GCC diagnostic push + #pragma GCC diagnostic error "-Wswitch" + #endif + switch(format) { + case CompressedPixelFormat::Bc1RGBSrgb: + case CompressedPixelFormat::Bc1RGBASrgb: + case CompressedPixelFormat::Bc2RGBASrgb: + case CompressedPixelFormat::Bc3RGBASrgb: + case CompressedPixelFormat::Bc7RGBASrgb: + case CompressedPixelFormat::Etc2RGB8Srgb: + case CompressedPixelFormat::Etc2RGB8A1Srgb: + case CompressedPixelFormat::Etc2RGBA8Srgb: + case CompressedPixelFormat::Astc4x4RGBASrgb: + case CompressedPixelFormat::Astc5x4RGBASrgb: + case CompressedPixelFormat::Astc5x5RGBASrgb: + case CompressedPixelFormat::Astc6x5RGBASrgb: + case CompressedPixelFormat::Astc6x6RGBASrgb: + case CompressedPixelFormat::Astc8x5RGBASrgb: + case CompressedPixelFormat::Astc8x6RGBASrgb: + case CompressedPixelFormat::Astc8x8RGBASrgb: + case CompressedPixelFormat::Astc10x5RGBASrgb: + case CompressedPixelFormat::Astc10x6RGBASrgb: + case CompressedPixelFormat::Astc10x8RGBASrgb: + case CompressedPixelFormat::Astc10x10RGBASrgb: + case CompressedPixelFormat::Astc12x10RGBASrgb: + case CompressedPixelFormat::Astc12x12RGBASrgb: + case CompressedPixelFormat::Astc3x3x3RGBASrgb: + case CompressedPixelFormat::Astc4x3x3RGBASrgb: + case CompressedPixelFormat::Astc4x4x3RGBASrgb: + case CompressedPixelFormat::Astc4x4x4RGBASrgb: + case CompressedPixelFormat::Astc5x4x4RGBASrgb: + case CompressedPixelFormat::Astc5x5x4RGBASrgb: + case CompressedPixelFormat::Astc5x5x5RGBASrgb: + case CompressedPixelFormat::Astc6x5x5RGBASrgb: + case CompressedPixelFormat::Astc6x6x5RGBASrgb: + case CompressedPixelFormat::Astc6x6x6RGBASrgb: + case CompressedPixelFormat::PvrtcRGB2bppSrgb: + case CompressedPixelFormat::PvrtcRGBA2bppSrgb: + case CompressedPixelFormat::PvrtcRGB4bppSrgb: + case CompressedPixelFormat::PvrtcRGBA4bppSrgb: + return true; + case CompressedPixelFormat::Bc1RGBUnorm: + case CompressedPixelFormat::Bc1RGBAUnorm: + case CompressedPixelFormat::Bc2RGBAUnorm: + case CompressedPixelFormat::Bc3RGBAUnorm: + case CompressedPixelFormat::Bc4RUnorm: + case CompressedPixelFormat::Bc4RSnorm: + case CompressedPixelFormat::Bc5RGUnorm: + case CompressedPixelFormat::Bc5RGSnorm: + case CompressedPixelFormat::Bc6hRGBUfloat: + case CompressedPixelFormat::Bc6hRGBSfloat: + case CompressedPixelFormat::Bc7RGBAUnorm: + case CompressedPixelFormat::EacR11Unorm: + case CompressedPixelFormat::EacR11Snorm: + case CompressedPixelFormat::EacRG11Unorm: + case CompressedPixelFormat::EacRG11Snorm: + case CompressedPixelFormat::Etc2RGB8Unorm: + case CompressedPixelFormat::Etc2RGB8A1Unorm: + case CompressedPixelFormat::Etc2RGBA8Unorm: + case CompressedPixelFormat::Astc4x4RGBAUnorm: + case CompressedPixelFormat::Astc4x4RGBAF: + case CompressedPixelFormat::Astc5x4RGBAUnorm: + case CompressedPixelFormat::Astc5x4RGBAF: + case CompressedPixelFormat::Astc5x5RGBAUnorm: + case CompressedPixelFormat::Astc5x5RGBAF: + case CompressedPixelFormat::Astc6x5RGBAUnorm: + case CompressedPixelFormat::Astc6x5RGBAF: + case CompressedPixelFormat::Astc6x6RGBAUnorm: + case CompressedPixelFormat::Astc6x6RGBAF: + case CompressedPixelFormat::Astc8x5RGBAUnorm: + case CompressedPixelFormat::Astc8x5RGBAF: + case CompressedPixelFormat::Astc8x6RGBAUnorm: + case CompressedPixelFormat::Astc8x6RGBAF: + case CompressedPixelFormat::Astc8x8RGBAUnorm: + case CompressedPixelFormat::Astc8x8RGBAF: + case CompressedPixelFormat::Astc10x5RGBAUnorm: + case CompressedPixelFormat::Astc10x5RGBAF: + case CompressedPixelFormat::Astc10x6RGBAUnorm: + case CompressedPixelFormat::Astc10x6RGBAF: + case CompressedPixelFormat::Astc10x8RGBAUnorm: + case CompressedPixelFormat::Astc10x8RGBAF: + case CompressedPixelFormat::Astc10x10RGBAUnorm: + case CompressedPixelFormat::Astc10x10RGBAF: + case CompressedPixelFormat::Astc12x10RGBAUnorm: + case CompressedPixelFormat::Astc12x10RGBAF: + case CompressedPixelFormat::Astc12x12RGBAUnorm: + case CompressedPixelFormat::Astc12x12RGBAF: + case CompressedPixelFormat::Astc3x3x3RGBAUnorm: + case CompressedPixelFormat::Astc3x3x3RGBAF: + case CompressedPixelFormat::Astc4x3x3RGBAUnorm: + case CompressedPixelFormat::Astc4x3x3RGBAF: + case CompressedPixelFormat::Astc4x4x3RGBAUnorm: + case CompressedPixelFormat::Astc4x4x3RGBAF: + case CompressedPixelFormat::Astc4x4x4RGBAUnorm: + case CompressedPixelFormat::Astc4x4x4RGBAF: + case CompressedPixelFormat::Astc5x4x4RGBAUnorm: + case CompressedPixelFormat::Astc5x4x4RGBAF: + case CompressedPixelFormat::Astc5x5x4RGBAUnorm: + case CompressedPixelFormat::Astc5x5x4RGBAF: + case CompressedPixelFormat::Astc5x5x5RGBAUnorm: + case CompressedPixelFormat::Astc5x5x5RGBAF: + case CompressedPixelFormat::Astc6x5x5RGBAUnorm: + case CompressedPixelFormat::Astc6x5x5RGBAF: + case CompressedPixelFormat::Astc6x6x5RGBAUnorm: + case CompressedPixelFormat::Astc6x6x5RGBAF: + case CompressedPixelFormat::Astc6x6x6RGBAUnorm: + case CompressedPixelFormat::Astc6x6x6RGBAF: + case CompressedPixelFormat::PvrtcRGB2bppUnorm: + case CompressedPixelFormat::PvrtcRGBA2bppUnorm: + case CompressedPixelFormat::PvrtcRGB4bppUnorm: + case CompressedPixelFormat::PvrtcRGBA4bppUnorm: + return false; + } + #ifdef CORRADE_TARGET_GCC + #pragma GCC diagnostic pop + #endif + + CORRADE_ASSERT_UNREACHABLE("isCompressedPixelFormatSrgb(): invalid format" << format, {}); +} + namespace { #ifndef DOXYGEN_GENERATING_OUTPUT diff --git a/src/Magnum/PixelFormat.h b/src/Magnum/PixelFormat.h index 3a5b48243..8c93e76b9 100644 --- a/src/Magnum/PixelFormat.h +++ b/src/Magnum/PixelFormat.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Enum @ref Magnum::PixelFormat, @ref Magnum::CompressedPixelFormat, function @ref Magnum::pixelFormatSize(), @ref Magnum::pixelFormatChannelFormat(), @ref Magnum::pixelFormatChannelCount(), @ref Magnum::isPixelFormatNormalized(), @ref Magnum::isPixelFormatIntegral(), @ref Magnum::isPixelFormatFloatingPoint(), @ref Magnum::isPixelFormatSrgb(), @ref Magnum::isPixelFormatDepthOrStencil(), @ref Magnum::pixelFormat(), @ref Magnum::isPixelFormatImplementationSpecific(), @ref Magnum::pixelFormatWrap(), @ref Magnum::pixelFormatUnwrap(), @ref Magnum::compressedPixelFormatBlockSize(), @ref Magnum::compressedPixelFormatBlockDataSize(), @ref Magnum::isCompressedPixelFormatImplementationSpecific(), @ref Magnum::compressedPixelFormatWrap(), @ref Magnum::compressedPixelFormatUnwrap() + * @brief Enum @ref Magnum::PixelFormat, @ref Magnum::CompressedPixelFormat, function @ref Magnum::pixelFormatSize(), @ref Magnum::pixelFormatChannelFormat(), @ref Magnum::pixelFormatChannelCount(), @ref Magnum::isPixelFormatNormalized(), @ref Magnum::isPixelFormatIntegral(), @ref Magnum::isPixelFormatFloatingPoint(), @ref Magnum::isPixelFormatSrgb(), @ref Magnum::isPixelFormatDepthOrStencil(), @ref Magnum::pixelFormat(), @ref Magnum::isPixelFormatImplementationSpecific(), @ref Magnum::pixelFormatWrap(), @ref Magnum::pixelFormatUnwrap(), @ref Magnum::compressedPixelFormatBlockSize(), @ref Magnum::compressedPixelFormatBlockDataSize(), @ref Magnum::isCompressedPixelFormatNormalized(), @ref Magnum::isCompressedPixelFormatFloatingPoint(), @ref Magnum::isCompressedPixelFormatSrgb(), @ref Magnum::isCompressedPixelFormatImplementationSpecific(), @ref Magnum::compressedPixelFormatWrap(), @ref Magnum::compressedPixelFormatUnwrap() */ #include @@ -840,7 +840,7 @@ For any pixel format, exactly one of @ref isPixelFormatNormalized(), @see @ref isPixelFormatImplementationSpecific(), @ref isPixelFormatDepthOrStencil(), @ref isPixelFormatSrgb(), @ref pixelFormat(PixelFormat, UnsignedInt, bool), - @ref isVertexFormatNormalized() + @ref isCompressedPixelFormatNormalized(), @ref isVertexFormatNormalized() */ MAGNUM_EXPORT bool isPixelFormatNormalized(PixelFormat format); @@ -877,7 +877,8 @@ For any pixel format, exactly one of @ref isPixelFormatNormalized(), @cpp true @ce. @see @ref isPixelFormatImplementationSpecific(), @ref isPixelFormatDepthOrStencil(), @ref isPixelFormatSrgb(), - @ref pixelFormat(PixelFormat, UnsignedInt, bool) + @ref pixelFormat(PixelFormat, UnsignedInt, bool), + @ref isCompressedPixelFormatFloatingPoint() */ MAGNUM_EXPORT bool isPixelFormatFloatingPoint(PixelFormat format); @@ -890,7 +891,8 @@ function returns @cpp true @ce, @ref isPixelFormatNormalized() also returns @cpp true @ce. Expects that the pixel format is *not* implementation-specific and not a depth/stencil format. @see @ref isPixelFormatImplementationSpecific(), - @ref pixelFormat(PixelFormat, UnsignedInt, bool) + @ref pixelFormat(PixelFormat, UnsignedInt, bool), + @ref isCompressedPixelFormatSrgb() */ MAGNUM_EXPORT bool isPixelFormatSrgb(PixelFormat format); @@ -1013,9 +1015,14 @@ For D3D, corresponds to @m_class{m-doc-external} [DXGI_FORMAT](https://docs.micr and import is provided by the @ref Trade::DdsImporter "DdsImporter" plugin; for Metal, corresponds to @m_class{m-doc-external} [MTLPixelFormat](https://developer.apple.com/documentation/metal/mtlpixelformat?language=objc). See documentation of each value for more information about the mapping. -@see @ref compressedPixelFormatBlockSize(), - @ref compressedPixelFormatBlockDataSize(), @ref PixelFormat, - @ref CompressedImage, @ref CompressedImageView + +See also @ref compressedPixelFormatBlockSize(), +@ref compressedPixelFormatBlockDataSize(), +@ref isCompressedPixelFormatNormalized(), +@ref isCompressedPixelFormatFloatingPoint() and +@ref isCompressedPixelFormatSrgb() for querying various aspect of a format. +@see @ref PixelFormat, @ref CompressedImage, @ref CompressedImageView, + @ref VertexFormat */ enum class CompressedPixelFormat: UnsignedInt { /* Zero reserved for an invalid format (but not being a named value) */ @@ -2571,6 +2578,56 @@ CORRADE_DEPRECATED("use compressedPixelFormatBlockDataSize() instead") inline Un } #endif +/** +@brief Whether given compressed pixel format is normalized +@m_since_latest + +Returns @cpp true @ce for `*Unorm`, `*Snorm` and `*Srgb` formats, +@cpp false @ce otherwise. In particular, floating-point formats are *not* +treated as normalized, even though for example they might commonly have values +only in the @f$ [0.0, 1.0] @f$ range (or in the @f$ [-1.0, 1.0] @f$ signed +range). Expects that the pixel format is *not* implementation-specific. + +For any compressed pixel format, exactly one of +@ref isCompressedPixelFormatNormalized() and +@ref isCompressedPixelFormatFloatingPoint() returns @cpp true @ce. +@see @ref isCompressedPixelFormatImplementationSpecific(), + @ref isCompressedPixelFormatSrgb(), @ref isPixelFormatNormalized(), + @ref isVertexFormatNormalized() +*/ +MAGNUM_EXPORT bool isCompressedPixelFormatNormalized(CompressedPixelFormat format); + +/** +@brief Whether given compressed pixel format is floating-point +@m_since_latest + +Returns @cpp true @ce for `*F` formats, @cpp false @ce otherwise. In +particular, normalized integer formats are *not* treated as floating-point, +even though they get expanded to the @f$ [0.0, 1.0] @f$ or @f$ [-1.0, 1.0] @f$ +floating-point range in shaders. Expects that the pixel format is *not* +implementation-specific. + +For any compressed pixel format, exactly one of +@ref isCompressedPixelFormatNormalized() and +@ref isCompressedPixelFormatFloatingPoint() returns @cpp true @ce. +@see @ref isCompressedPixelFormatImplementationSpecific(), + @ref isCompressedPixelFormatSrgb(), @ref isPixelFormatFloatingPoint() +*/ +MAGNUM_EXPORT bool isCompressedPixelFormatFloatingPoint(CompressedPixelFormat format); + +/** +@brief Whether given compressed pixel format is sRGB +@m_since_latest + +Returns @cpp true @ce for `*Srgb` formats, @cpp false @ce otherwise. If this +function returns @cpp true @ce, @ref isCompressedPixelFormatNormalized() also +returns @cpp true @ce. Expects that the pixel format is *not* +implementation-specific. +@see @ref isCompressedPixelFormatImplementationSpecific(), + @ref isPixelFormatSrgb() +*/ +MAGNUM_EXPORT bool isCompressedPixelFormatSrgb(CompressedPixelFormat format); + /** @debugoperatorenum{CompressedPixelFormat} */ MAGNUM_EXPORT Debug& operator<<(Debug& debug, CompressedPixelFormat value); diff --git a/src/Magnum/Test/PixelFormatTest.cpp b/src/Magnum/Test/PixelFormatTest.cpp index 6fb99d6b1..5e441753d 100644 --- a/src/Magnum/Test/PixelFormatTest.cpp +++ b/src/Magnum/Test/PixelFormatTest.cpp @@ -71,6 +71,14 @@ struct PixelFormatTest: TestSuite::Tester { void compressedBlockSizeInvalid(); void compressedBlockSizeImplementationSpecific(); + void compressedIsNormalizedFloatingPoint(); + void compressedIsNormalizedFloatingPointInvalid(); + void compressedIsNormalizedFloatingPointImplementationSpecific(); + + void compressedIsSrgb(); + void compressedIsSrgbInvalid(); + void compressedIsSrgbImplementationSpecific(); + void isImplementationSpecific(); void wrap(); void wrapInvalid(); @@ -153,6 +161,14 @@ PixelFormatTest::PixelFormatTest() { &PixelFormatTest::compressedBlockSizeInvalid, &PixelFormatTest::compressedBlockSizeImplementationSpecific, + &PixelFormatTest::compressedIsNormalizedFloatingPoint, + &PixelFormatTest::compressedIsNormalizedFloatingPointInvalid, + &PixelFormatTest::compressedIsNormalizedFloatingPointImplementationSpecific, + + &PixelFormatTest::compressedIsSrgb, + &PixelFormatTest::compressedIsSrgbInvalid, + &PixelFormatTest::compressedIsSrgbImplementationSpecific, + &PixelFormatTest::isImplementationSpecific, &PixelFormatTest::wrap, &PixelFormatTest::wrapInvalid, @@ -256,6 +272,8 @@ void PixelFormatTest::compressedMapping() { CORRADE_COMPARE_AS(height, 16, TestSuite::Compare::LessOrEqual); \ CORRADE_COMPARE_AS(depth, 16, TestSuite::Compare::LessOrEqual); \ CORRADE_COMPARE_AS(size/8, 16, TestSuite::Compare::LessOrEqual); \ + CORRADE_COMPARE(Int(isCompressedPixelFormatNormalized(CompressedPixelFormat::format)) + Int(isCompressedPixelFormatFloatingPoint(CompressedPixelFormat::format)), 1); \ + CORRADE_VERIFY(!isCompressedPixelFormatSrgb(CompressedPixelFormat::format) || isCompressedPixelFormatNormalized(CompressedPixelFormat::format)); \ ++nextHandled; \ continue; #include "Magnum/Implementation/compressedPixelFormatMapping.hpp" @@ -601,6 +619,87 @@ void PixelFormatTest::compressedBlockSizeImplementationSpecific() { "compressedPixelFormatBlockDataSize(): can't determine size of an implementation-specific format 0xdead\n"); } +void PixelFormatTest::compressedIsNormalizedFloatingPoint() { + /* Verification that exactly one of the two returns true is done in + compressedMapping() above */ + + CORRADE_VERIFY(isCompressedPixelFormatNormalized(CompressedPixelFormat::Bc2RGBAUnorm)); + CORRADE_VERIFY(isCompressedPixelFormatNormalized(CompressedPixelFormat::Etc2RGB8Srgb)); + CORRADE_VERIFY(isCompressedPixelFormatNormalized(CompressedPixelFormat::Bc5RGSnorm)); + CORRADE_VERIFY(isCompressedPixelFormatNormalized(CompressedPixelFormat::Astc10x5RGBAUnorm)); + CORRADE_VERIFY(isCompressedPixelFormatNormalized(CompressedPixelFormat::PvrtcRGB2bppUnorm)); + CORRADE_VERIFY(isCompressedPixelFormatFloatingPoint(CompressedPixelFormat::Bc6hRGBUfloat)); + CORRADE_VERIFY(isCompressedPixelFormatFloatingPoint(CompressedPixelFormat::Astc5x5RGBAF)); + + /* Floating-point aren't marked as normalized */ + CORRADE_VERIFY(!isCompressedPixelFormatNormalized(CompressedPixelFormat::Bc6hRGBSfloat)); + CORRADE_VERIFY(!isCompressedPixelFormatNormalized(CompressedPixelFormat::Astc6x6x6RGBAF)); + + /* Normalized aren't marked as floating-point even though they're treated + like float values in calculations */ + CORRADE_VERIFY(!isCompressedPixelFormatFloatingPoint(CompressedPixelFormat::EacRG11Unorm)); +} + +void PixelFormatTest::compressedIsNormalizedFloatingPointInvalid() { + CORRADE_SKIP_IF_NO_ASSERT(); + + std::ostringstream out; + Error redirectError{&out}; + isCompressedPixelFormatNormalized(CompressedPixelFormat{}); + isCompressedPixelFormatNormalized(CompressedPixelFormat(0xdead)); + isCompressedPixelFormatFloatingPoint(CompressedPixelFormat{}); + isCompressedPixelFormatFloatingPoint(CompressedPixelFormat(0xdead)); + CORRADE_COMPARE(out.str(), + "isCompressedPixelFormatNormalized(): invalid format CompressedPixelFormat(0x0)\n" + "isCompressedPixelFormatNormalized(): invalid format CompressedPixelFormat(0xdead)\n" + "isCompressedPixelFormatFloatingPoint(): invalid format CompressedPixelFormat(0x0)\n" + "isCompressedPixelFormatFloatingPoint(): invalid format CompressedPixelFormat(0xdead)\n"); +} + +void PixelFormatTest::compressedIsNormalizedFloatingPointImplementationSpecific() { + CORRADE_SKIP_IF_NO_ASSERT(); + + std::ostringstream out; + Error redirectError{&out}; + isCompressedPixelFormatNormalized(compressedPixelFormatWrap(0xdead)); + isCompressedPixelFormatFloatingPoint(compressedPixelFormatWrap(0xdead)); + CORRADE_COMPARE_AS(out.str(), + "isCompressedPixelFormatNormalized(): can't determine type of an implementation-specific format 0xdead\n" + "isCompressedPixelFormatFloatingPoint(): can't determine type of an implementation-specific format 0xdead\n", + TestSuite::Compare::String); +} + +void PixelFormatTest::compressedIsSrgb() { + /* Verification that it's never both Srgb and FloatingPoint is done in + compressedMapping() above */ + + CORRADE_VERIFY(isCompressedPixelFormatSrgb(CompressedPixelFormat::Bc7RGBASrgb)); + CORRADE_VERIFY(!isCompressedPixelFormatSrgb(CompressedPixelFormat::Bc5RGSnorm)); + CORRADE_VERIFY(!isCompressedPixelFormatSrgb(CompressedPixelFormat::Astc8x5RGBAF)); +} + +void PixelFormatTest::compressedIsSrgbInvalid() { + CORRADE_SKIP_IF_NO_ASSERT(); + + std::ostringstream out; + Error redirectError{&out}; + isCompressedPixelFormatSrgb(CompressedPixelFormat{}); + isCompressedPixelFormatSrgb(CompressedPixelFormat(0xdead)); + CORRADE_COMPARE(out.str(), + "isCompressedPixelFormatSrgb(): invalid format CompressedPixelFormat(0x0)\n" + "isCompressedPixelFormatSrgb(): invalid format CompressedPixelFormat(0xdead)\n"); +} + +void PixelFormatTest::compressedIsSrgbImplementationSpecific() { + CORRADE_SKIP_IF_NO_ASSERT(); + + std::ostringstream out; + Error redirectError{&out}; + isCompressedPixelFormatSrgb(compressedPixelFormatWrap(0xdead)); + CORRADE_COMPARE(out.str(), + "isCompressedPixelFormatSrgb(): can't determine colorspace of an implementation-specific format 0xdead\n"); +} + void PixelFormatTest::isImplementationSpecific() { constexpr bool a = isPixelFormatImplementationSpecific(PixelFormat::RGBA8Unorm); constexpr bool b = isPixelFormatImplementationSpecific(PixelFormat(0x8000dead)); diff --git a/src/Magnum/VertexFormat.h b/src/Magnum/VertexFormat.h index 2bcfa086f..cd343a273 100644 --- a/src/Magnum/VertexFormat.h +++ b/src/Magnum/VertexFormat.h @@ -1441,7 +1441,7 @@ range (or normals in the @f$ [-1.0, 1.0] @f$ range). Expects that the vertex format is *not* implementation-specific. @see @ref isVertexFormatImplementationSpecific(), @ref vertexFormat(VertexFormat, UnsignedInt, bool), - @ref isPixelFormatNormalized() + @ref isPixelFormatNormalized(), @ref isCompressedPixelFormatNormalized() */ MAGNUM_EXPORT bool isVertexFormatNormalized(VertexFormat format);