From 846cb10735cb9af3f4dce0fa5560ab4126371f47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 22 Jun 2022 12:32:28 +0200 Subject: [PATCH] Add PixelFormat decomposition utilities. Similar to what VertexFormat already has -- getting channel count, channel format, sRGB and color vs depth/stencil properties out of a PixelFormat value. Very useful for various image conversion plugins. --- doc/changelog.dox | 2 + src/Magnum/PixelFormat.cpp | 328 ++++++++++++++++++++++++++++ src/Magnum/PixelFormat.h | 56 ++++- src/Magnum/Test/PixelFormatTest.cpp | 151 ++++++++++++- src/Magnum/VertexFormat.h | 7 +- 5 files changed, 538 insertions(+), 6 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index 6fa651105..c04f30639 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -53,6 +53,8 @@ See also: including mapping to @ref GL::PixelFormat / @ref GL::PixelType, @ref GL::TextureFormat and @ref Vk::PixelFormat and (partial) support in @ref DebugTools::CompareImage +- New @ref pixelFormatChannelFormat(), @ref pixelFormatChannelCount(), + @ref isPixelFormatSrgb() and @ref isPixelFormatDepthOrStencil() 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 d4ae29d6f..da887735a 100644 --- a/src/Magnum/PixelFormat.cpp +++ b/src/Magnum/PixelFormat.cpp @@ -118,6 +118,334 @@ UnsignedInt pixelFormatSize(const PixelFormat format) { CORRADE_ASSERT_UNREACHABLE("pixelFormatSize(): invalid format" << format, {}); } +PixelFormat pixelFormatChannelFormat(const PixelFormat format) { + CORRADE_ASSERT(!isPixelFormatImplementationSpecific(format), + "pixelFormatChannelFormat(): can't determine channel format of an implementation-specific format" << reinterpret_cast(pixelFormatUnwrap(format)), {}); + + #ifdef CORRADE_TARGET_GCC + #pragma GCC diagnostic push + #pragma GCC diagnostic error "-Wswitch" + #endif + switch(format) { + case PixelFormat::R8Unorm: + case PixelFormat::RG8Unorm: + case PixelFormat::RGB8Unorm: + case PixelFormat::RGBA8Unorm: + return PixelFormat::R8Unorm; + case PixelFormat::R8Snorm: + case PixelFormat::RG8Snorm: + case PixelFormat::RGB8Snorm: + case PixelFormat::RGBA8Snorm: + return PixelFormat::R8Snorm; + case PixelFormat::R8Srgb: + case PixelFormat::RG8Srgb: + case PixelFormat::RGB8Srgb: + case PixelFormat::RGBA8Srgb: + return PixelFormat::R8Srgb; + case PixelFormat::R8UI: + case PixelFormat::RG8UI: + case PixelFormat::RGB8UI: + case PixelFormat::RGBA8UI: + return PixelFormat::R8UI; + case PixelFormat::R8I: + case PixelFormat::RG8I: + case PixelFormat::RGB8I: + case PixelFormat::RGBA8I: + return PixelFormat::R8I; + case PixelFormat::R16Unorm: + case PixelFormat::RG16Unorm: + case PixelFormat::RGB16Unorm: + case PixelFormat::RGBA16Unorm: + return PixelFormat::R16Unorm; + case PixelFormat::R16Snorm: + case PixelFormat::RG16Snorm: + case PixelFormat::RGB16Snorm: + case PixelFormat::RGBA16Snorm: + return PixelFormat::R16Snorm; + case PixelFormat::R16UI: + case PixelFormat::RG16UI: + case PixelFormat::RGB16UI: + case PixelFormat::RGBA16UI: + return PixelFormat::R16UI; + case PixelFormat::R16I: + case PixelFormat::RG16I: + case PixelFormat::RGB16I: + case PixelFormat::RGBA16I: + return PixelFormat::R16I; + case PixelFormat::R32UI: + case PixelFormat::RG32UI: + case PixelFormat::RGB32UI: + case PixelFormat::RGBA32UI: + return PixelFormat::R32UI; + case PixelFormat::R32I: + case PixelFormat::RG32I: + case PixelFormat::RGB32I: + case PixelFormat::RGBA32I: + return PixelFormat::R32I; + case PixelFormat::R16F: + case PixelFormat::RG16F: + case PixelFormat::RGB16F: + case PixelFormat::RGBA16F: + return PixelFormat::R16F; + case PixelFormat::R32F: + case PixelFormat::RG32F: + case PixelFormat::RGB32F: + case PixelFormat::RGBA32F: + return PixelFormat::R32F; + + case PixelFormat::Stencil8UI: + case PixelFormat::Depth16Unorm: + case PixelFormat::Depth24Unorm: + case PixelFormat::Depth32F: + case PixelFormat::Depth16UnormStencil8UI: + case PixelFormat::Depth24UnormStencil8UI: + case PixelFormat::Depth32FStencil8UI: + CORRADE_ASSERT_UNREACHABLE("pixelFormatChannelFormat(): can't determine channel format of" << format, {}); + } + #ifdef CORRADE_TARGET_GCC + #pragma GCC diagnostic pop + #endif + + CORRADE_ASSERT_UNREACHABLE("pixelFormatChannelFormat(): invalid format" << format, {}); +} + +UnsignedInt pixelFormatChannelCount(const PixelFormat format) { + CORRADE_ASSERT(!isPixelFormatImplementationSpecific(format), + "pixelFormatChannelCount(): can't determine channel count of an implementation-specific format" << reinterpret_cast(pixelFormatUnwrap(format)), {}); + + #ifdef CORRADE_TARGET_GCC + #pragma GCC diagnostic push + #pragma GCC diagnostic error "-Wswitch" + #endif + switch(format) { + case PixelFormat::R8Unorm: + case PixelFormat::R8Snorm: + case PixelFormat::R8Srgb: + case PixelFormat::R8UI: + case PixelFormat::R8I: + case PixelFormat::R16Unorm: + case PixelFormat::R16Snorm: + case PixelFormat::R16UI: + case PixelFormat::R16I: + case PixelFormat::R32UI: + case PixelFormat::R32I: + case PixelFormat::R16F: + case PixelFormat::R32F: + return 1; + case PixelFormat::RG8Unorm: + case PixelFormat::RG8Snorm: + case PixelFormat::RG8Srgb: + case PixelFormat::RG8UI: + case PixelFormat::RG8I: + case PixelFormat::RG16Unorm: + case PixelFormat::RG16Snorm: + case PixelFormat::RG16UI: + case PixelFormat::RG16I: + case PixelFormat::RG32UI: + case PixelFormat::RG32I: + case PixelFormat::RG16F: + case PixelFormat::RG32F: + return 2; + case PixelFormat::RGB8Unorm: + case PixelFormat::RGB8Snorm: + case PixelFormat::RGB8Srgb: + case PixelFormat::RGB8UI: + case PixelFormat::RGB8I: + case PixelFormat::RGB16Unorm: + case PixelFormat::RGB16Snorm: + case PixelFormat::RGB16UI: + case PixelFormat::RGB16I: + case PixelFormat::RGB32UI: + case PixelFormat::RGB32I: + case PixelFormat::RGB16F: + case PixelFormat::RGB32F: + return 3; + case PixelFormat::RGBA8Unorm: + case PixelFormat::RGBA8Snorm: + case PixelFormat::RGBA8Srgb: + case PixelFormat::RGBA8UI: + case PixelFormat::RGBA8I: + case PixelFormat::RGBA16Unorm: + case PixelFormat::RGBA16Snorm: + case PixelFormat::RGBA16UI: + case PixelFormat::RGBA16I: + case PixelFormat::RGBA32UI: + case PixelFormat::RGBA32I: + case PixelFormat::RGBA16F: + case PixelFormat::RGBA32F: + return 4; + case PixelFormat::Depth16Unorm: + case PixelFormat::Depth24Unorm: + case PixelFormat::Depth32F: + case PixelFormat::Stencil8UI: + case PixelFormat::Depth16UnormStencil8UI: + case PixelFormat::Depth24UnormStencil8UI: + case PixelFormat::Depth32FStencil8UI: + CORRADE_ASSERT_UNREACHABLE("pixelFormatChannelCount(): can't determine channel count of" << format, {}); + } + #ifdef CORRADE_TARGET_GCC + #pragma GCC diagnostic pop + #endif + + CORRADE_ASSERT_UNREACHABLE("pixelFormatChannelCount(): invalid format" << format, {}); +} + +bool isPixelFormatSrgb(const PixelFormat format) { + CORRADE_ASSERT(!isPixelFormatImplementationSpecific(format), + "isPixelFormatSrgb(): can't determine colorspace of an implementation-specific format" << reinterpret_cast(pixelFormatUnwrap(format)), {}); + + #ifdef CORRADE_TARGET_GCC + #pragma GCC diagnostic push + #pragma GCC diagnostic error "-Wswitch" + #endif + switch(format) { + case PixelFormat::R8Srgb: + case PixelFormat::RG8Srgb: + case PixelFormat::RGB8Srgb: + case PixelFormat::RGBA8Srgb: + return true; + case PixelFormat::R8Unorm: + case PixelFormat::RG8Unorm: + case PixelFormat::RGB8Unorm: + case PixelFormat::RGBA8Unorm: + case PixelFormat::R8Snorm: + case PixelFormat::RG8Snorm: + case PixelFormat::RGB8Snorm: + case PixelFormat::RGBA8Snorm: + case PixelFormat::R8UI: + case PixelFormat::RG8UI: + case PixelFormat::RGB8UI: + case PixelFormat::RGBA8UI: + case PixelFormat::R8I: + case PixelFormat::RG8I: + case PixelFormat::RGB8I: + case PixelFormat::RGBA8I: + case PixelFormat::R16Unorm: + case PixelFormat::RG16Unorm: + case PixelFormat::RGB16Unorm: + case PixelFormat::RGBA16Unorm: + case PixelFormat::R16Snorm: + case PixelFormat::RG16Snorm: + case PixelFormat::RGB16Snorm: + case PixelFormat::RGBA16Snorm: + case PixelFormat::R16UI: + case PixelFormat::RG16UI: + case PixelFormat::RGB16UI: + case PixelFormat::RGBA16UI: + case PixelFormat::R16I: + case PixelFormat::RG16I: + case PixelFormat::RGB16I: + case PixelFormat::RGBA16I: + case PixelFormat::R32UI: + case PixelFormat::RG32UI: + case PixelFormat::RGB32UI: + case PixelFormat::RGBA32UI: + case PixelFormat::R32I: + case PixelFormat::RG32I: + case PixelFormat::RGB32I: + case PixelFormat::RGBA32I: + case PixelFormat::R16F: + case PixelFormat::RG16F: + case PixelFormat::RGB16F: + case PixelFormat::RGBA16F: + case PixelFormat::R32F: + case PixelFormat::RG32F: + case PixelFormat::RGB32F: + case PixelFormat::RGBA32F: + case PixelFormat::Depth16Unorm: + case PixelFormat::Depth24Unorm: + case PixelFormat::Depth32F: + case PixelFormat::Stencil8UI: + case PixelFormat::Depth16UnormStencil8UI: + case PixelFormat::Depth24UnormStencil8UI: + case PixelFormat::Depth32FStencil8UI: + return false; + } + #ifdef CORRADE_TARGET_GCC + #pragma GCC diagnostic pop + #endif + + CORRADE_ASSERT_UNREACHABLE("isPixelFormatSrgb(): invalid format" << format, {}); +} + +bool isPixelFormatDepthOrStencil(const PixelFormat format) { + CORRADE_ASSERT(!isPixelFormatImplementationSpecific(format), + "isPixelFormatDepthOrStencil(): can't determine type of an implementation-specific format" << reinterpret_cast(pixelFormatUnwrap(format)), {}); + + #ifdef CORRADE_TARGET_GCC + #pragma GCC diagnostic push + #pragma GCC diagnostic error "-Wswitch" + #endif + switch(format) { + case PixelFormat::R8Unorm: + case PixelFormat::RG8Unorm: + case PixelFormat::RGB8Unorm: + case PixelFormat::RGBA8Unorm: + case PixelFormat::R8Snorm: + case PixelFormat::RG8Snorm: + case PixelFormat::RGB8Snorm: + case PixelFormat::RGBA8Snorm: + case PixelFormat::R8Srgb: + case PixelFormat::RG8Srgb: + case PixelFormat::RGB8Srgb: + case PixelFormat::RGBA8Srgb: + case PixelFormat::R8UI: + case PixelFormat::RG8UI: + case PixelFormat::RGB8UI: + case PixelFormat::RGBA8UI: + case PixelFormat::R8I: + case PixelFormat::RG8I: + case PixelFormat::RGB8I: + case PixelFormat::RGBA8I: + case PixelFormat::R16Unorm: + case PixelFormat::RG16Unorm: + case PixelFormat::RGB16Unorm: + case PixelFormat::RGBA16Unorm: + case PixelFormat::R16Snorm: + case PixelFormat::RG16Snorm: + case PixelFormat::RGB16Snorm: + case PixelFormat::RGBA16Snorm: + case PixelFormat::R16UI: + case PixelFormat::RG16UI: + case PixelFormat::RGB16UI: + case PixelFormat::RGBA16UI: + case PixelFormat::R16I: + case PixelFormat::RG16I: + case PixelFormat::RGB16I: + case PixelFormat::RGBA16I: + case PixelFormat::R32UI: + case PixelFormat::RG32UI: + case PixelFormat::RGB32UI: + case PixelFormat::RGBA32UI: + case PixelFormat::R32I: + case PixelFormat::RG32I: + case PixelFormat::RGB32I: + case PixelFormat::RGBA32I: + case PixelFormat::R16F: + case PixelFormat::RG16F: + case PixelFormat::RGB16F: + case PixelFormat::RGBA16F: + case PixelFormat::R32F: + case PixelFormat::RG32F: + case PixelFormat::RGB32F: + case PixelFormat::RGBA32F: + return false; + case PixelFormat::Depth16Unorm: + case PixelFormat::Depth24Unorm: + case PixelFormat::Depth32F: + case PixelFormat::Stencil8UI: + case PixelFormat::Depth16UnormStencil8UI: + case PixelFormat::Depth24UnormStencil8UI: + case PixelFormat::Depth32FStencil8UI: + return true; + } + #ifdef CORRADE_TARGET_GCC + #pragma GCC diagnostic pop + #endif + + CORRADE_ASSERT_UNREACHABLE("isPixelFormatDepthOrStencil(): invalid format" << format, {}); +} + namespace { #ifndef DOXYGEN_GENERATING_OUTPUT /* It gets *really* confused */ diff --git a/src/Magnum/PixelFormat.h b/src/Magnum/PixelFormat.h index d455bbd77..1cf1cd298 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::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::isPixelFormatSrgb(), @ref Magnum::isPixelFormatDepthOrStencil(), @ref Magnum::isPixelFormatImplementationSpecific(), @ref Magnum::pixelFormatWrap(), @ref Magnum::pixelFormatUnwrap(), @ref Magnum::compressedPixelFormatBlockSize(), @ref Magnum::compressedPixelFormatBlockDataSize(), @ref Magnum::isCompressedPixelFormatImplementationSpecific(), @ref Magnum::compressedPixelFormatWrap(), @ref Magnum::compressedPixelFormatUnwrap() */ #include @@ -65,7 +65,9 @@ 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 pixelFormatSize(), @ref CompressedPixelFormat, @ref Image, +@see @ref pixelFormatSize(), @ref pixelFormatChannelFormat(), + @ref pixelFormatChannelCount(), @ref isPixelFormatSrgb(), + @ref isPixelFormatDepthOrStencil(), @ref CompressedPixelFormat, @ref Image, @ref ImageView, @ref VertexFormat */ enum class PixelFormat: UnsignedInt { @@ -776,10 +778,58 @@ enum class PixelFormat: UnsignedInt { @m_since_latest Expects that the pixel format is *not* implementation-specific. -@see @ref isPixelFormatImplementationSpecific(), @ref GL::pixelFormatSize() +@see @ref isPixelFormatImplementationSpecific(), @ref GL::pixelFormatSize(), + @ref vertexFormatSize() */ MAGNUM_EXPORT UnsignedInt pixelFormatSize(PixelFormat format); +/** +@brief Channel format of given pixel format +@m_since_latest + +Returns for example @ref PixelFormat::R8Srgb for +@ref PixelFormat::RGB8Srgb or @ref PixelFormat::R16F for +@ref PixelFormat::RG16F. Calling @ref pixelFormatChannelCount() on the returned +value will always give @cpp 1 @ce. Expects that the pixel format is *not* +implementation-specific and not a depth/stencil format. +@see @ref isPixelFormatImplementationSpecific(), + @ref isPixelFormatDepthOrStencil(), @ref isPixelFormatSrgb(), + @ref vertexFormatComponentFormat() +*/ +MAGNUM_EXPORT PixelFormat pixelFormatChannelFormat(PixelFormat format); + +/** +@brief Channel count of given pixel format +@m_since_latest + +Returns for example @cpp 1 @ce for @ref PixelFormat::R8Unorm or @cpp 3 @ce for +@ref PixelFormat::RGB32F. Expects that the pixel format is *not* +implementation-specific and not a depth/stencil format. +@see @ref isPixelFormatImplementationSpecific(), + @ref isPixelFormatDepthOrStencil(), @ref vertexFormatComponentCount() +*/ +MAGNUM_EXPORT UnsignedInt pixelFormatChannelCount(PixelFormat format); + +/** +@brief Whether given pixel format is sRGB +@m_since_latest + +Returns @cpp true @ce for `*Srgb` formats, @cpp false @ce otherwise. Expects +that the pixel format is *not* implementation-specific. +@see @ref isPixelFormatImplementationSpecific() +*/ +MAGNUM_EXPORT bool isPixelFormatSrgb(PixelFormat format); + +/** +@brief Whether given pixel format is depth or stenil +@m_since_latest + +Returns @cpp true @ce for `Depth*`, `Stencil*` and combined depth/stencil +formats, @cpp false @ce otherwise. Expects that the pixel format is *not* implementation-specific. +@see @ref isPixelFormatImplementationSpecific() +*/ +MAGNUM_EXPORT bool isPixelFormatDepthOrStencil(PixelFormat format); + #ifdef MAGNUM_BUILD_DEPRECATED /** * @brief @copybrief pixelFormatSize() diff --git a/src/Magnum/Test/PixelFormatTest.cpp b/src/Magnum/Test/PixelFormatTest.cpp index f8693b8fd..4c06f7c53 100644 --- a/src/Magnum/Test/PixelFormatTest.cpp +++ b/src/Magnum/Test/PixelFormatTest.cpp @@ -44,6 +44,18 @@ struct PixelFormatTest: TestSuite::Tester { void sizeInvalid(); void sizeImplementationSpecific(); + void channelFormatCount(); + void channelFormatCountInvalid(); + void channelFormatCountDepthStencilImplementationSpecific(); + + void isSrgb(); + void isSrgbInvalid(); + void isSrgbImplementationSpecific(); + + void isDepthOrStencil(); + void isDepthOrStencilInvalid(); + void isDepthOrStencilImplementationSpecific(); + void compressedBlockSize(); void compressedBlockSizeInvalid(); void compressedBlockSizeImplementationSpecific(); @@ -82,6 +94,18 @@ PixelFormatTest::PixelFormatTest() { &PixelFormatTest::sizeInvalid, &PixelFormatTest::sizeImplementationSpecific, + &PixelFormatTest::channelFormatCount, + &PixelFormatTest::channelFormatCountInvalid, + &PixelFormatTest::channelFormatCountDepthStencilImplementationSpecific, + + &PixelFormatTest::isSrgb, + &PixelFormatTest::isSrgbInvalid, + &PixelFormatTest::isSrgbImplementationSpecific, + + &PixelFormatTest::isDepthOrStencil, + &PixelFormatTest::isDepthOrStencilInvalid, + &PixelFormatTest::isDepthOrStencilImplementationSpecific, + &PixelFormatTest::compressedBlockSize, &PixelFormatTest::compressedBlockSizeInvalid, &PixelFormatTest::compressedBlockSizeImplementationSpecific, @@ -122,7 +146,9 @@ void PixelFormatTest::mapping() { /* Each case verifies: - that the entries are ordered by number by comparing a function to expected result (so insertion here is done in proper place) - - that there was no gap (unhandled value inside the range) */ + - that there was no gap (unhandled value inside the range) + - that channel count times size of a channel equals to size of the + format, unless it's a depth/stencil type */ #ifdef CORRADE_TARGET_GCC #pragma GCC diagnostic push #pragma GCC diagnostic error "-Wswitch" @@ -133,6 +159,8 @@ void PixelFormatTest::mapping() { CORRADE_COMPARE(Utility::ConfigurationValue::toString(PixelFormat::format, {}), #format); \ CORRADE_COMPARE(nextHandled, i); \ CORRADE_COMPARE(firstUnhandled, 0xffff); \ + if(!isPixelFormatDepthOrStencil(PixelFormat::format)) \ + CORRADE_COMPARE(pixelFormatChannelCount(PixelFormat::format)*pixelFormatSize(pixelFormatChannelFormat(PixelFormat::format)), pixelFormatSize(PixelFormat::format)); \ ++nextHandled; \ continue; #include "Magnum/Implementation/pixelFormatMapping.hpp" @@ -240,6 +268,127 @@ void PixelFormatTest::sizeImplementationSpecific() { CORRADE_COMPARE(out.str(), "pixelFormatSize(): can't determine size of an implementation-specific format 0xdead\n"); } +void PixelFormatTest::channelFormatCount() { + CORRADE_COMPARE(pixelFormatChannelFormat(PixelFormat::R8Unorm), PixelFormat::R8Unorm); + CORRADE_COMPARE(pixelFormatChannelFormat(PixelFormat::RG8Snorm), PixelFormat::R8Snorm); + CORRADE_COMPARE(pixelFormatChannelFormat(PixelFormat::RGB8Srgb), PixelFormat::R8Srgb); + CORRADE_COMPARE(pixelFormatChannelFormat(PixelFormat::RGBA8UI), PixelFormat::R8UI); + CORRADE_COMPARE(pixelFormatChannelFormat(PixelFormat::RG8I), PixelFormat::R8I); + CORRADE_COMPARE(pixelFormatChannelFormat(PixelFormat::RG16Unorm), PixelFormat::R16Unorm); + CORRADE_COMPARE(pixelFormatChannelFormat(PixelFormat::RGBA16Snorm), PixelFormat::R16Snorm); + CORRADE_COMPARE(pixelFormatChannelFormat(PixelFormat::RG16UI), PixelFormat::R16UI); + CORRADE_COMPARE(pixelFormatChannelFormat(PixelFormat::RGBA16I), PixelFormat::R16I); + CORRADE_COMPARE(pixelFormatChannelFormat(PixelFormat::RGB32UI), PixelFormat::R32UI); + CORRADE_COMPARE(pixelFormatChannelFormat(PixelFormat::RG32I), PixelFormat::R32I); + CORRADE_COMPARE(pixelFormatChannelFormat(PixelFormat::RGB16F), PixelFormat::R16F); + CORRADE_COMPARE(pixelFormatChannelFormat(PixelFormat::RGB32F), PixelFormat::R32F); + + CORRADE_COMPARE(pixelFormatChannelCount(PixelFormat::R16UI), 1); + CORRADE_COMPARE(pixelFormatChannelCount(PixelFormat::RG8Unorm), 2); + CORRADE_COMPARE(pixelFormatChannelCount(PixelFormat::RGB16I), 3); + CORRADE_COMPARE(pixelFormatChannelCount(PixelFormat::RGBA16F), 4); +} + +void PixelFormatTest::channelFormatCountInvalid() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + std::ostringstream out; + Error redirectError{&out}; + pixelFormatChannelFormat(PixelFormat{}); + pixelFormatChannelFormat(PixelFormat(0xdead)); + pixelFormatChannelCount(PixelFormat{}); + pixelFormatChannelCount(PixelFormat(0xdead)); + CORRADE_COMPARE(out.str(), + "pixelFormatChannelFormat(): invalid format PixelFormat(0x0)\n" + "pixelFormatChannelFormat(): invalid format PixelFormat(0xdead)\n" + "pixelFormatChannelCount(): invalid format PixelFormat(0x0)\n" + "pixelFormatChannelCount(): invalid format PixelFormat(0xdead)\n"); +} + +void PixelFormatTest::channelFormatCountDepthStencilImplementationSpecific() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + std::ostringstream out; + Error redirectError{&out}; + pixelFormatChannelFormat(pixelFormatWrap(0xdead)); + pixelFormatChannelFormat(PixelFormat::Depth16Unorm); + pixelFormatChannelCount(pixelFormatWrap(0xdead)); + pixelFormatChannelCount(PixelFormat::Depth16Unorm); + CORRADE_COMPARE(out.str(), + "pixelFormatChannelFormat(): can't determine channel format of an implementation-specific format 0xdead\n" + "pixelFormatChannelFormat(): can't determine channel format of PixelFormat::Depth16Unorm\n" + "pixelFormatChannelCount(): can't determine channel count of an implementation-specific format 0xdead\n" + "pixelFormatChannelCount(): can't determine channel count of PixelFormat::Depth16Unorm\n"); +} + +void PixelFormatTest::isSrgb() { + CORRADE_VERIFY(isPixelFormatSrgb(PixelFormat::RG8Srgb)); + CORRADE_VERIFY(!isPixelFormatSrgb(PixelFormat::RGB16F)); + CORRADE_VERIFY(!isPixelFormatSrgb(PixelFormat::Stencil8UI)); +} + +void PixelFormatTest::isSrgbInvalid() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + std::ostringstream out; + Error redirectError{&out}; + isPixelFormatSrgb(PixelFormat{}); + isPixelFormatSrgb(PixelFormat(0xdead)); + CORRADE_COMPARE(out.str(), + "isPixelFormatSrgb(): invalid format PixelFormat(0x0)\n" + "isPixelFormatSrgb(): invalid format PixelFormat(0xdead)\n"); +} + +void PixelFormatTest::isSrgbImplementationSpecific() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + std::ostringstream out; + Error redirectError{&out}; + isPixelFormatSrgb(pixelFormatWrap(0xdead)); + CORRADE_COMPARE(out.str(), + "isPixelFormatSrgb(): can't determine colorspace of an implementation-specific format 0xdead\n"); +} + +void PixelFormatTest::isDepthOrStencil() { + CORRADE_VERIFY(!isPixelFormatDepthOrStencil(PixelFormat::RG8Srgb)); + CORRADE_VERIFY(!isPixelFormatDepthOrStencil(PixelFormat::RGB16F)); + CORRADE_VERIFY(isPixelFormatDepthOrStencil(PixelFormat::Stencil8UI)); +} + +void PixelFormatTest::isDepthOrStencilInvalid() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + std::ostringstream out; + Error redirectError{&out}; + isPixelFormatDepthOrStencil(PixelFormat{}); + isPixelFormatDepthOrStencil(PixelFormat(0xdead)); + CORRADE_COMPARE(out.str(), + "isPixelFormatDepthOrStencil(): invalid format PixelFormat(0x0)\n" + "isPixelFormatDepthOrStencil(): invalid format PixelFormat(0xdead)\n"); +} + +void PixelFormatTest::isDepthOrStencilImplementationSpecific() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + std::ostringstream out; + Error redirectError{&out}; + isPixelFormatDepthOrStencil(pixelFormatWrap(0xdead)); + CORRADE_COMPARE(out.str(), + "isPixelFormatDepthOrStencil(): can't determine type of an implementation-specific format 0xdead\n"); +} + void PixelFormatTest::compressedBlockSize() { CORRADE_COMPARE(compressedPixelFormatBlockSize(CompressedPixelFormat::Etc2RGB8A1Srgb), (Vector3i{4, 4, 1})); CORRADE_COMPARE(compressedPixelFormatBlockDataSize(CompressedPixelFormat::Etc2RGB8A1Srgb), 8); diff --git a/src/Magnum/VertexFormat.h b/src/Magnum/VertexFormat.h index e9c52c5ae..9cbcc9108 100644 --- a/src/Magnum/VertexFormat.h +++ b/src/Magnum/VertexFormat.h @@ -1366,6 +1366,7 @@ template constexpr T vertexFormatUnwrap(VertexFormat form To get size of a single component, call this function on a result of @ref vertexFormatComponentFormat(). +@see @ref pixelFormatSize() */ MAGNUM_EXPORT UnsignedInt vertexFormatSize(VertexFormat format); @@ -1380,7 +1381,8 @@ The function also removes the normalization aspect from the format --- use Calling @ref vertexFormatComponentCount() on the returned value will always give @cpp 1 @ce; calling @ref isVertexFormatNormalized() on the returned value will always give @cpp false @ce. -@see @ref vertexFormat(VertexFormat, UnsignedInt, bool) +@see @ref vertexFormat(VertexFormat, UnsignedInt, bool), + @ref pixelFormatChannelFormat() */ MAGNUM_EXPORT VertexFormat vertexFormatComponentFormat(VertexFormat format); @@ -1390,7 +1392,8 @@ MAGNUM_EXPORT VertexFormat vertexFormatComponentFormat(VertexFormat format); Returns @cpp 1 @ce for scalar formats and e.g. @cpp 3 @ce for @ref VertexFormat::Vector3ub. -@see @ref vertexFormat(VertexFormat, UnsignedInt, bool) +@see @ref vertexFormat(VertexFormat, UnsignedInt, bool), + @ref pixelFormatChannelCount() */ MAGNUM_EXPORT UnsignedInt vertexFormatComponentCount(VertexFormat format);