diff --git a/src/Magnum/DebugTools/Test/TextureImageGLTest.cpp b/src/Magnum/DebugTools/Test/TextureImageGLTest.cpp index ac87bfc69..b1af30676 100644 --- a/src/Magnum/DebugTools/Test/TextureImageGLTest.cpp +++ b/src/Magnum/DebugTools/Test/TextureImageGLTest.cpp @@ -38,6 +38,7 @@ #include "Magnum/GL/PixelFormat.h" #include "Magnum/GL/Texture.h" #include "Magnum/GL/TextureFormat.h" +#include "Magnum/Math/Half.h" #include "Magnum/Math/Range.h" #ifndef MAGNUM_TARGET_GLES2 @@ -73,6 +74,8 @@ struct TextureImageGLTest: GL::OpenGLTester { void subImage2DUInt(); void subImage2DFloat(); void subImage2DFloatGeneric(); + void subImage2DHalf(); + void subImage2DHalfGeneric(); #endif }; @@ -96,10 +99,14 @@ TextureImageGLTest::TextureImageGLTest() { &TextureImageGLTest::subImage2DUInt, &TextureImageGLTest::subImage2DFloat, &TextureImageGLTest::subImage2DFloatGeneric, + &TextureImageGLTest::subImage2DHalf, + &TextureImageGLTest::subImage2DHalfGeneric, #endif }); } +using namespace Math::Literals; + constexpr UnsignedByte Data2D[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, @@ -422,6 +429,46 @@ void TextureImageGLTest::subImage2DFloatGeneric() { Containers::arrayView(Data2DFloat), TestSuite::Compare::Container); } + +const Half Data2DHalf[] = { 1.0_h, + 3.14159_h, + 2.71828_h, + 1.41421_h }; + +void TextureImageGLTest::subImage2DHalf() { + GL::Texture2D texture; + texture + .setStorage(1, GL::TextureFormat::R16F, Vector2i{2}) + .setSubImage(0, {}, ImageView2D{GL::PixelFormat::Red, GL::PixelType::Half, Vector2i{2}, Data2DHalf}); + + Image2D image = textureSubImage(texture, 0, {{}, Vector2i{2}}, {GL::PixelFormat::Red, GL::PixelType::Half}); + MAGNUM_VERIFY_NO_GL_ERROR(); + CORRADE_COMPARE(image.size(), Vector2i{2}); + CORRADE_COMPARE(image.format(), pixelFormatWrap(GL::PixelFormat::Red)); + CORRADE_COMPARE(GL::PixelType(image.formatExtra()), GL::PixelType::Half); + CORRADE_COMPARE(image.pixelSize(), 2); + CORRADE_COMPARE_AS(Containers::arrayCast(image.data()), + Containers::arrayView(Data2DHalf), + TestSuite::Compare::Container); +} + +void TextureImageGLTest::subImage2DHalfGeneric() { + GL::Texture2D texture; + texture + .setStorage(1, GL::TextureFormat::R16F, Vector2i{2}) + .setSubImage(0, {}, ImageView2D{GL::PixelFormat::Red, GL::PixelType::Half, Vector2i{2}, Data2DHalf}); + + Image2D image = textureSubImage(texture, 0, {{}, Vector2i{2}}, {PixelFormat::R16F}); + MAGNUM_VERIFY_NO_GL_ERROR(); + CORRADE_COMPARE(image.size(), Vector2i{2}); + CORRADE_COMPARE(image.format(), PixelFormat::R16F); + CORRADE_COMPARE(image.formatExtra(), 0); + CORRADE_COMPARE(image.pixelSize(), 2); + CORRADE_COMPARE_AS(Containers::arrayCast(image.data()), + Containers::arrayView(Data2DHalf), + TestSuite::Compare::Container); +} + #endif }}}} diff --git a/src/Magnum/DebugTools/TextureImage.cpp b/src/Magnum/DebugTools/TextureImage.cpp index f874bcf04..56b65a4fb 100644 --- a/src/Magnum/DebugTools/TextureImage.cpp +++ b/src/Magnum/DebugTools/TextureImage.cpp @@ -115,9 +115,27 @@ void textureSubImage(GL::Texture2D& texture, const Int level, const Range2Di& ra } #endif + /* While I cannot reproduce this on any drivers I tried, not even on WebGL, + the ES3.0 and 3.1 spec says that Float isn't guaranteed to be supported, + only UnsignedByte and Int or UnsignedInt. I could probably do some + comparison against fb.implementationColorReadFormat() but this is more + straightforward. + + ES3.2 says Float is supported. What still isn't guaranteed to be + supported are one-, two- and three-component formats, but so far I + didn't have a problem with these anywhere. + + Half floats aren't guaranteed to be supported either, but given that I + cannot reproduce this issue anywhere anymore, I don't think I should + waste time implementing a half-float variant. */ + /** @todo or just remove this altogether? */ #if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_GLES2) GL::PixelType type = GL::pixelType(image.format(), image.formatExtra()); - if(type == GL::PixelType::Float) { + if(type == GL::PixelType::Float + #ifndef MAGNUM_TARGET_WEBGL + && !GL::Context::current().isVersionSupported(GL::Version::GLES320) + #endif + ) { GL::TextureFormat textureFormat; GL::PixelFormat reinterpretFormat; GL::PixelFormat format = GL::pixelFormat(image.format()); @@ -224,6 +242,11 @@ void textureSubImage(GL::CubeMapTexture& texture, const GL::CubeMapCoordinate co GL::Framebuffer fb{range}; fb.attachCubeMapTexture(GL::Framebuffer::ColorAttachment{0}, texture, coordinate, level); + /* Compared to textureSubImage(GL::Texture2D&), here's no specialized code + path for float formats, as it's impossible to sample it in a shader with + 2D coordinates. It's also questionable if that's still needed. */ + /** @todo or just remove this altogether? */ + CORRADE_ASSERT(fb.checkStatus(GL::FramebufferTarget::Read) == GL::Framebuffer::Status::Complete, "DebugTools::textureSubImage(): texture format not framebuffer-readable:" << fb.checkStatus(GL::FramebufferTarget::Read), ); diff --git a/src/Magnum/DebugTools/TextureImage.h b/src/Magnum/DebugTools/TextureImage.h index 7d75a3608..5b82a8a97 100644 --- a/src/Magnum/DebugTools/TextureImage.h +++ b/src/Magnum/DebugTools/TextureImage.h @@ -50,11 +50,13 @@ is available, it's just an alias to @ref GL::Texture2D::subImage(). The function expects that @p texture has a @ref GL::TextureFormat that's framebuffer-readable and that the @ref GL::PixelFormat and @ref GL::PixelType combination or the generic @relativeref{Magnum,PixelFormat} is compatible with -it. In addition, on OpenGL ES 3.0, images with @ref GL::PixelType::Float -are supported --- they are reinterpreted as @ref GL::PixelType::UnsignedInt -using an additional shader and the @glsl floatBitsToUint() @ce GLSL function -and then reinterpreted back to @ref GL::PixelType::Float when read to client -memory. +it. On OpenGL ES 3.0 and 3.1, @ref GL::PixelType::Float isn't guaranteed to be +supported for reading so such images are reinterpreted as +@ref GL::PixelType::UnsignedInt using an additional shader and the +@glsl floatBitsToUint() @ce GLSL function and then reinterpreted back to +@ref GL::PixelType::Float when read to client memory. On OpenGL ES 3.2 and on +desktop GL, @ref GL::PixelType::Float is guaranteed to be supported. No similar +treatment is done for any other types. @note This function is available only if Magnum is compiled with @ref MAGNUM_TARGET_GL "TARGET_GL" enabled (done by default). See