diff --git a/src/Magnum/GL/Implementation/pixelFormatMapping.hpp b/src/Magnum/GL/Implementation/pixelFormatMapping.hpp index c55504dbf..046ef107e 100644 --- a/src/Magnum/GL/Implementation/pixelFormatMapping.hpp +++ b/src/Magnum/GL/Implementation/pixelFormatMapping.hpp @@ -35,15 +35,26 @@ _c(R8Unorm, Red, UnsignedByte, R8) _c(RG8Unorm, RG, UnsignedByte, RG8) #else -_n(R8Unorm, Luminance, UnsignedByte) -_n(RG8Unorm, LuminanceAlpha, UnsignedByte) +/* Luminance / LuminanceAlpha isn't allowed in glTexStorage(). Usually though + there's either both the EXT_texture_rg and EXT_texture_storage extensions or + neither of them (such as in WebGL), and unconditionally failing for single- + and two-channel formats isn't desirable. */ +/** @todo ideally there would be some variant of this mapping for when + EXT_texture_rg is supported */ +_c(R8Unorm, Luminance, UnsignedByte, Luminance) +_c(RG8Unorm, LuminanceAlpha, UnsignedByte, LuminanceAlpha) #endif #ifndef MAGNUM_TARGET_GLES2 _c(RGB8Unorm, RGB, UnsignedByte, RGB8) _c(RGBA8Unorm, RGBA, UnsignedByte, RGBA8) #else -_n(RGB8Unorm, RGB, UnsignedByte) -_n(RGBA8Unorm, RGBA, UnsignedByte) +/* (Unsized) RGB / RGBA isn't allowed in glTexStorage(), however + unconditionally failing for for these in WebGL isn't really desirable + either. */ +/** @todo ideally there would be some variant of this mapping for when + EXT_texture_rg is supported */ +_c(RGB8Unorm, RGB, UnsignedByte, RGB) +_c(RGBA8Unorm, RGBA, UnsignedByte, RGBA) #endif #ifndef MAGNUM_TARGET_GLES2 _c(R8Snorm, Red, Byte, R8Snorm) @@ -79,8 +90,13 @@ _dn(RG8Srgb, LuminanceAlpha, UnsignedByte) _d(RGB8Srgb, RGB, UnsignedByte, SRGB8) _d(RGBA8Srgb, RGBA, UnsignedByte, SRGB8Alpha8) #else -_dn(RGB8Srgb, RGB, UnsignedByte) -_dn(RGBA8Srgb, RGBA, UnsignedByte) +/* (Unsized) SRGB / SRGBA isn't allowed in glTexStorage(), however + unconditionally failing for for these in WebGL isn't really desirable + either. */ +/** @todo ideally there would be some variant of this mapping for when + EXT_texture_rg is supported */ +_d(RGB8Srgb, RGB, UnsignedByte, SRGB) +_d(RGBA8Srgb, RGBA, UnsignedByte, SRGBAlpha) #endif #ifndef MAGNUM_TARGET_GLES2 _c(R8UI, RedInteger, UnsignedByte, R8UI) @@ -195,6 +211,8 @@ _n(Depth24Unorm, DepthComponent, UnsignedInt) #ifndef MAGNUM_TARGET_GLES2 _c(Depth32F, DepthComponent, Float, DepthComponent32F) #else +/* There isn't any possibility to have a depth / stencil texture on ES2, so not + even any unsized format */ _s(Depth32F) #endif #ifndef MAGNUM_TARGET_WEBGL @@ -211,6 +229,8 @@ _n(Depth24UnormStencil8UI, DepthStencil, UnsignedInt248) #ifndef MAGNUM_TARGET_GLES2 _c(Depth32FStencil8UI, DepthStencil, Float32UnsignedInt248Rev, Depth32FStencil8) #else +/* There isn't any possibility to have a depth / stencil texture on ES2, so not + even any unsized format */ _s(Depth32FStencil8UI) #endif #endif diff --git a/src/Magnum/GL/PixelFormat.cpp b/src/Magnum/GL/PixelFormat.cpp index e7ddc365d..119dde644 100644 --- a/src/Magnum/GL/PixelFormat.cpp +++ b/src/Magnum/GL/PixelFormat.cpp @@ -288,6 +288,17 @@ Containers::Optional genericPixelFormat(const PixelFormat f #undef _n #undef _d #undef _c + + #if defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + /* The mapping defaults to Luminance and LuminanceAlpha on ES2. + Recognize also the R and RG formats from EXT_texture_rg. */ + /** @todo ideally there would be some variant of the above mapping for + when EXT_texture_rg is supported, to have it consistent */ + case (UnsignedLong(PixelFormat::Red) << 32)|UnsignedLong(PixelType::UnsignedByte): + return Magnum::PixelFormat::R8Unorm; + case (UnsignedLong(PixelFormat::RG) << 32)|UnsignedLong(PixelType::UnsignedByte): + return Magnum::PixelFormat::RG8Unorm; + #endif } return {}; @@ -308,6 +319,17 @@ Containers::Optional genericPixelFormat(const TextureFormat #undef _d #undef _c + #if defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + /* The mapping defaults to Luminance, LuminanceAlpha, RGB and RGBA on + ES2. Recognize also the sized formats from EXT_texture_rg. */ + /** @todo ideally there would be some variant of the above mapping for + when EXT_texture_rg is supported, to have it consistent */ + case TextureFormat::R8: return Magnum::PixelFormat::R8Unorm; + case TextureFormat::RG8: return Magnum::PixelFormat::RG8Unorm; + case TextureFormat::RGB8: return Magnum::PixelFormat::RGB8Unorm; + case TextureFormat::RGBA8: return Magnum::PixelFormat::RGBA8Unorm; + #endif + /* For compressed formats it returns NullOpt too instead of asserting, as -- compared to the generic-to-GL translation, which is O(1) -- the inverse mapping is potentially a linear lookup and forcing the diff --git a/src/Magnum/GL/Test/PixelFormatTest.cpp b/src/Magnum/GL/Test/PixelFormatTest.cpp index d475026af..1ab31990c 100644 --- a/src/Magnum/GL/Test/PixelFormatTest.cpp +++ b/src/Magnum/GL/Test/PixelFormatTest.cpp @@ -109,18 +109,58 @@ void PixelFormatTest::mapFormatTypeTextureFormat() { CORRADE_COMPARE(pixelFormat(Magnum::PixelFormat::RGBA8Unorm), PixelFormat::RGBA); CORRADE_COMPARE(pixelType(Magnum::PixelFormat::RGBA8Unorm), PixelType::UnsignedByte); CORRADE_COMPARE(genericPixelFormat(PixelFormat::RGB, PixelType::UnsignedByte), Magnum::PixelFormat::RGB8Unorm); - #ifndef MAGNUM_TARGET_GLES2 CORRADE_VERIFY(hasTextureFormat(Magnum::PixelFormat::RGBA8Unorm)); + #ifndef MAGNUM_TARGET_GLES2 CORRADE_COMPARE(textureFormat(Magnum::PixelFormat::RGBA8Unorm), TextureFormat::RGBA8); CORRADE_COMPARE(genericPixelFormat(TextureFormat::RGB8), Magnum::PixelFormat::RGB8Unorm); #else - CORRADE_VERIFY(!hasTextureFormat(Magnum::PixelFormat::RGBA8Unorm)); - CORRADE_COMPARE(genericPixelFormat(TextureFormat::RGB), Containers::NullOpt); + CORRADE_COMPARE(textureFormat(Magnum::PixelFormat::RGBA8Unorm), TextureFormat::RGBA); + CORRADE_COMPARE(genericPixelFormat(TextureFormat::RGB), Magnum::PixelFormat::RGB8Unorm); + #endif + + /* No mapping for these */ + CORRADE_COMPARE(genericPixelFormat(TextureFormat::RGB565), Containers::NullOpt); + #ifdef MAGNUM_TARGET_GLES2 + CORRADE_VERIFY(!hasTextureFormat(Magnum::PixelFormat::Depth32F)); #endif + /* sRGB formats have N:1 mapping, conversion back is losing the sRGB bit */ CORRADE_COMPARE(genericPixelFormat(pixelFormat(Magnum::PixelFormat::R8Srgb), pixelType(Magnum::PixelFormat::R8Srgb)), Magnum::PixelFormat::R8Unorm); CORRADE_COMPARE(genericPixelFormat(pixelFormat(Magnum::PixelFormat::RGBA8Srgb), pixelType(Magnum::PixelFormat::RGBA8Srgb)), Magnum::PixelFormat::RGBA8Unorm); + /* On ES2, forward PixelFormat mapping goes to luminance, but backwards + mapping from R and RG works too. For TextureFormat, forward mapping goes + to unsized formats and luminance (which aren't usable in glTexStorage() + then, only glTexImage()), but backwards mapping from sized formats works + too. */ + #ifdef MAGNUM_TARGET_GLES2 + CORRADE_COMPARE(pixelFormat(Magnum::PixelFormat::R8Unorm), PixelFormat::Luminance); + CORRADE_COMPARE(pixelFormat(Magnum::PixelFormat::RG8Unorm), PixelFormat::LuminanceAlpha); + CORRADE_COMPARE(pixelType(Magnum::PixelFormat::R8Unorm), PixelType::UnsignedByte); + CORRADE_COMPARE(pixelType(Magnum::PixelFormat::RG8Unorm), PixelType::UnsignedByte); + CORRADE_COMPARE(genericPixelFormat(PixelFormat::Luminance, PixelType::UnsignedByte), Magnum::PixelFormat::R8Unorm); + CORRADE_COMPARE(genericPixelFormat(PixelFormat::LuminanceAlpha, PixelType::UnsignedByte), Magnum::PixelFormat::RG8Unorm); + #ifndef MAGNUM_TARGET_WEBGL + CORRADE_COMPARE(genericPixelFormat(PixelFormat::Red, PixelType::UnsignedByte), Magnum::PixelFormat::R8Unorm); + CORRADE_COMPARE(genericPixelFormat(PixelFormat::RG, PixelType::UnsignedByte), Magnum::PixelFormat::RG8Unorm); + #endif + + CORRADE_COMPARE(textureFormat(Magnum::PixelFormat::R8Unorm), TextureFormat::Luminance); + CORRADE_COMPARE(textureFormat(Magnum::PixelFormat::RG8Unorm), TextureFormat::LuminanceAlpha); + CORRADE_COMPARE(textureFormat(Magnum::PixelFormat::RGB8Unorm), TextureFormat::RGB); + CORRADE_COMPARE(textureFormat(Magnum::PixelFormat::RGBA8Unorm), TextureFormat::RGBA); + CORRADE_COMPARE(genericPixelFormat(TextureFormat::Luminance), Magnum::PixelFormat::R8Unorm); + CORRADE_COMPARE(genericPixelFormat(TextureFormat::LuminanceAlpha), Magnum::PixelFormat::RG8Unorm); + CORRADE_COMPARE(genericPixelFormat(TextureFormat::RGB), Magnum::PixelFormat::RGB8Unorm); + CORRADE_COMPARE(genericPixelFormat(TextureFormat::RGBA), Magnum::PixelFormat::RGBA8Unorm); + #ifndef MAGNUM_TARGET_WEBGL + CORRADE_COMPARE(genericPixelFormat(TextureFormat::R8), Magnum::PixelFormat::R8Unorm); + CORRADE_COMPARE(genericPixelFormat(TextureFormat::RG8), Magnum::PixelFormat::RG8Unorm); + CORRADE_COMPARE(genericPixelFormat(TextureFormat::RGB8), Magnum::PixelFormat::RGB8Unorm); + CORRADE_COMPARE(genericPixelFormat(TextureFormat::RGBA8), Magnum::PixelFormat::RGBA8Unorm); + #endif + #endif + /* This goes through the first 16 bits, which should be enough. Going through 32 bits takes 8 seconds, too much. */ UnsignedInt firstUnhandled = 0xffff; @@ -343,8 +383,8 @@ void PixelFormatTest::mapTextureFormatUnsupported() { std::ostringstream out; Error redirectError{&out}; - textureFormat(Magnum::PixelFormat::RGB8Unorm); - CORRADE_COMPARE(out.str(), "GL::textureFormat(): format PixelFormat::RGB8Unorm is not supported on this target\n"); + textureFormat(Magnum::PixelFormat::Depth32F); + CORRADE_COMPARE(out.str(), "GL::textureFormat(): format PixelFormat::Depth32F is not supported on this target\n"); #else std::ostringstream out; Error redirectError{&out}; diff --git a/src/Magnum/PixelFormat.h b/src/Magnum/PixelFormat.h index c1ccb1348..fcab00b5a 100644 --- a/src/Magnum/PixelFormat.h +++ b/src/Magnum/PixelFormat.h @@ -83,8 +83,10 @@ enum class PixelFormat: UnsignedInt { * Red component, normalized unsigned byte. * * Corresponds to @ref GL::PixelFormat::Red and - * @ref GL::PixelType::UnsignedByte, @ref GL::TextureFormat::R8; - * @ref Vk::PixelFormat::R8Unorm; + * @ref GL::PixelType::UnsignedByte, @ref GL::TextureFormat::R8 or + * alternatively @ref GL::PixelFormat::Luminance and + * @ref GL::TextureFormat::Luminance on unextended OpenGL 2.1 and OpenGL ES + * 2.0; @ref Vk::PixelFormat::R8Unorm; * @m_class{m-doc-external} [DXGI_FORMAT_R8_UNORM](https://docs.microsoft.com/en-us/windows/win32/api/dxgiformat/ne-dxgiformat-dxgi_format) * or @m_class{m-doc-external} [MTLPixelFormatR8Unorm](https://developer.apple.com/documentation/metal/mtlpixelformat/mtlpixelformatr8unorm?language=objc). * @m_keywords{DXGI_FORMAT_R8_UNORM MTLPixelFormatR8Unorm} @@ -95,8 +97,10 @@ enum class PixelFormat: UnsignedInt { * Red and green component, normalized unsigned byte. * * Corresponds to @ref GL::PixelFormat::RG and - * @ref GL::PixelType::UnsignedByte, @ref GL::TextureFormat::RG8; - * @ref Vk::PixelFormat::RG8Unorm; + * @ref GL::PixelType::UnsignedByte, @ref GL::TextureFormat::RG8 or + * alternatively @ref GL::PixelFormat::LuminanceAlpha and + * @ref GL::TextureFormat::LuminanceAlpha on unextended OpenGL 2.1 and + * OpenGL ES 2.0; @ref Vk::PixelFormat::RG8Unorm; * @m_class{m-doc-external} [DXGI_FORMAT_R8G8_UNORM](https://docs.microsoft.com/en-us/windows/win32/api/dxgiformat/ne-dxgiformat-dxgi_format) * or @m_class{m-doc-external} [MTLPixelFormatRG8Unorm](https://developer.apple.com/documentation/metal/mtlpixelformat/mtlpixelformatrg8unorm?language=objc). * @m_keywords{DXGI_FORMAT_R8G8_UNORM MTLPixelFormatRG8Unorm} @@ -108,7 +112,9 @@ enum class PixelFormat: UnsignedInt { * * Corresponds to @ref GL::PixelFormat::RGB and * @ref GL::PixelType::UnsignedByte, @ref GL::TextureFormat::RGB8 or - * @ref Vk::PixelFormat::RGB8Unorm. No 24-bit D3D or Metal equivalent. + * alternatively @ref GL::TextureFormat::RGB on unextended OpenGL 2.1 and + * OpenGL ES 2.0; @ref Vk::PixelFormat::RGB8Unorm. No 24-bit D3D or Metal + * equivalent. */ RGB8Unorm, @@ -116,8 +122,9 @@ enum class PixelFormat: UnsignedInt { * RGBA, normalized unsigned byte. * * Corresponds to @ref GL::PixelFormat::RGBA and - * @ref GL::PixelType::UnsignedByte, @ref GL::TextureFormat::RGBA8; - * @ref Vk::PixelFormat::RGBA8Unorm; + * @ref GL::PixelType::UnsignedByte, @ref GL::TextureFormat::RGBA8 or + * alternatively @ref GL::TextureFormat::RGBA on unextended OpenGL 2.1 and + * OpenGL ES 2.0; @ref Vk::PixelFormat::RGBA8Unorm; * @m_class{m-doc-external} [DXGI_FORMAT_R8G8B8A8_UNORM](https://docs.microsoft.com/en-us/windows/win32/api/dxgiformat/ne-dxgiformat-dxgi_format) * or @m_class{m-doc-external} [MTLPixelFormatRGBA8Unorm](https://developer.apple.com/documentation/metal/mtlpixelformat/mtlpixelformatrgba8unorm?language=objc). * @m_keywords{DXGI_FORMAT_R8G8B8A8_UNORM MTLPixelFormatRGBA8Unorm}