Browse Source

GL: implement PixelFormat mapping to unsized/luminance ES2 TextureFormat.

Originally GL::hasTextureFormat() returned false on ES2 for
PixelFormat::R8Unorm, RG8Unorm, RGB8Unorm and RGBA8Unorm because
glTexStorage() didn't work with the matching Luminance, LuminanceAlpha,
RGB and RGBA formats. But since the only ES2 platform is nowadays
basically just WebGL 1, which has neither EXT_texture_rg nor
EXT_texture_storage, this implicit failure made no sense and just made
the textureFormat() (and the new genericPixelFormat() API) useless
there.

Now it maps to them, and it's up to the caller to make sure
glTexStorage() doesn't get called with those, only glTexImage does.
Furthermore, if formats from EXT_texture_rg are used, the
genericPixelFormat() now also provides inverse mapping of them back to
the generic PixelFormat. Before it was basically *no* ES2 TextureFormat
that'd work with either of these, now it's all that have a (vaguely)
corresponding PixelFormat.
pull/168/head
Vladimír Vondruš 3 years ago
parent
commit
423f9a4140
  1. 32
      src/Magnum/GL/Implementation/pixelFormatMapping.hpp
  2. 22
      src/Magnum/GL/PixelFormat.cpp
  3. 50
      src/Magnum/GL/Test/PixelFormatTest.cpp
  4. 21
      src/Magnum/PixelFormat.h

32
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

22
src/Magnum/GL/PixelFormat.cpp

@ -288,6 +288,17 @@ Containers::Optional<Magnum::PixelFormat> 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<Magnum::PixelFormat> 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

50
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};

21
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}

Loading…
Cancel
Save