From b1454b94de41663093f174c7e03af5bf1db636a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 5 Jul 2025 13:34:31 +0200 Subject: [PATCH] GL: properly test assertions for unsupported pixel storage parameters. With the upcoming changes to how image data layout is represented those are going to change, so it's important to have them covered. --- src/Magnum/GL/CMakeLists.txt | 5 +- .../GL/Implementation/RendererState.cpp | 2 +- src/Magnum/GL/Test/CMakeLists.txt | 2 +- src/Magnum/GL/Test/PixelStorageGLTest.cpp | 259 ++++++++++++++++++ 4 files changed, 264 insertions(+), 4 deletions(-) diff --git a/src/Magnum/GL/CMakeLists.txt b/src/Magnum/GL/CMakeLists.txt index 5cc921102..08f4c00a8 100644 --- a/src/Magnum/GL/CMakeLists.txt +++ b/src/Magnum/GL/CMakeLists.txt @@ -48,7 +48,6 @@ set(MagnumGL_SRCS Implementation/FramebufferState.cpp Implementation/MeshState.cpp Implementation/QueryState.cpp - Implementation/RendererState.cpp Implementation/ShaderProgramState.cpp Implementation/ShaderState.cpp Implementation/State.cpp @@ -66,7 +65,9 @@ set(MagnumGL_GracefulAssert_SRCS MeshView.cpp PixelFormat.cpp Sampler.cpp - Shader.cpp) + Shader.cpp + + Implementation/RendererState.cpp) set(MagnumGL_HEADERS AbstractFramebuffer.h diff --git a/src/Magnum/GL/Implementation/RendererState.cpp b/src/Magnum/GL/Implementation/RendererState.cpp index f0bd5a7f0..cc6107d30 100644 --- a/src/Magnum/GL/Implementation/RendererState.cpp +++ b/src/Magnum/GL/Implementation/RendererState.cpp @@ -362,7 +362,7 @@ void RendererState::applyPixelStorageInternal(const Magnum::PixelStorage& storag void RendererState::applyPixelStorageInternal(const CompressedPixelStorage& storage, const bool isUnpack) { #ifdef MAGNUM_TARGET_GLES CORRADE_ASSERT(storage == CompressedPixelStorage{}, - "GL: non-default CompressedPixelStorage parameters are not supported on OpenGLES or WebGL", ); + "GL: non-default CompressedPixelStorage parameters are not supported in OpenGL ES or WebGL", ); static_cast(isUnpack); #else applyPixelStorageInternal(static_cast(storage), isUnpack); diff --git a/src/Magnum/GL/Test/CMakeLists.txt b/src/Magnum/GL/Test/CMakeLists.txt index 62652e10a..5b9236384 100644 --- a/src/Magnum/GL/Test/CMakeLists.txt +++ b/src/Magnum/GL/Test/CMakeLists.txt @@ -153,7 +153,7 @@ if(MAGNUM_BUILD_GL_TESTS) if(NOT (MAGNUM_TARGET_WEBGL AND MAGNUM_TARGET_GLES2)) corrade_add_test(GLAbstractQueryGLTest AbstractQueryGLTest.cpp LIBRARIES MagnumOpenGLTester) - corrade_add_test(GLPixelStorageGLTest PixelStorageGLTest.cpp LIBRARIES MagnumOpenGLTester) + corrade_add_test(GLPixelStorageGLTest PixelStorageGLTest.cpp LIBRARIES MagnumOpenGLTesterTestLib) corrade_add_test(GLSampleQueryGLTest SampleQueryGLTest.cpp LIBRARIES MagnumOpenGLTester) endif() diff --git a/src/Magnum/GL/Test/PixelStorageGLTest.cpp b/src/Magnum/GL/Test/PixelStorageGLTest.cpp index e4e92ee99..368439a99 100644 --- a/src/Magnum/GL/Test/PixelStorageGLTest.cpp +++ b/src/Magnum/GL/Test/PixelStorageGLTest.cpp @@ -25,11 +25,14 @@ */ #include +#include #include "Magnum/Image.h" #include "Magnum/ImageView.h" +#include "Magnum/PixelFormat.h" #include "Magnum/GL/Context.h" #include "Magnum/GL/Extensions.h" +#include "Magnum/GL/Framebuffer.h" #include "Magnum/GL/OpenGLTester.h" #include "Magnum/GL/PixelFormat.h" #include "Magnum/GL/Texture.h" @@ -56,12 +59,25 @@ struct PixelStorageGLTest: OpenGLTester { void alignmentImageHeightRowLengthSkipXYZPack3D(); #endif + #if defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2) + void rowLengthNotSupported(); + #endif + #ifdef MAGNUM_TARGET_GLES2 + void imageHeightNotSupported(); + #elif defined(MAGNUM_TARGET_GLES) + void imageHeightSkipZPackNotSupported(); + #endif + #ifndef MAGNUM_TARGET_GLES void compressedUnpack2D(); void compressedPack2D(); void compressedUnpack3D(); void compressedPack3D(); #endif + + #ifdef MAGNUM_TARGET_GLES + void compressedNotSupported(); + #endif }; PixelStorageGLTest::PixelStorageGLTest() { @@ -74,12 +90,25 @@ PixelStorageGLTest::PixelStorageGLTest() { &PixelStorageGLTest::alignmentImageHeightRowLengthSkipXYZPack3D, #endif + #if defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2) + &PixelStorageGLTest::rowLengthNotSupported, + #endif + #ifdef MAGNUM_TARGET_GLES2 + &PixelStorageGLTest::imageHeightNotSupported, + #elif defined(MAGNUM_TARGET_GLES) + &PixelStorageGLTest::imageHeightSkipZPackNotSupported, + #endif + #ifndef MAGNUM_TARGET_GLES &PixelStorageGLTest::compressedUnpack2D, &PixelStorageGLTest::compressedPack2D, &PixelStorageGLTest::compressedUnpack3D, &PixelStorageGLTest::compressedPack3D #endif + + #ifdef MAGNUM_TARGET_GLES + &PixelStorageGLTest::compressedNotSupported, + #endif }); } @@ -263,6 +292,160 @@ void PixelStorageGLTest::alignmentImageHeightRowLengthSkipXYZPack3D() { } #endif +#if defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2) +void PixelStorageGLTest::rowLengthNotSupported() { + CORRADE_SKIP_IF_NO_ASSERT(); + + char data[4*4*4]{}; + MutableImageView2D image{ + PixelStorage{} + .setRowLength(4), + Magnum::PixelFormat::RGBA8Unorm, + {4, 4}, + data}; + + Texture2D texture; + /* Just to reset all pixel storage parameters potentially set by any of the + above tests to default. The (graceful) assertions would do an early + return somewhere in the middle, leading to some params being left at + their earlier state. */ + texture.setImage(0, + textureFormat(image.format()), + ImageView2D{image.format(), image.size(), image.data()}); + Framebuffer framebuffer{{}}; + framebuffer.attachTexture(Framebuffer::ColorAttachment{0}, texture, 0); + /* ... and similarly to reset unpack parameters */ + framebuffer.read({{}, image.size()}, + MutableImageView2D{image.format(), image.size(), data}); + + MAGNUM_VERIFY_NO_GL_ERROR(); + + Containers::String out; + Error redirectError{&out}; + texture.setImage(0, textureFormat(image.format()), image); + framebuffer.read({{}, image.size()}, image); + CORRADE_COMPARE_AS(out, + "GL: non-default PixelStorage::rowLength() is not supported in WebGL 1.0\n" + "GL: non-default PixelStorage::rowLength() is not supported in WebGL 1.0\n", + TestSuite::Compare::String); + + MAGNUM_VERIFY_NO_GL_ERROR(); + + /* And again to reset these for any tests that might run after */ + texture.setImage(0, + textureFormat(image.format()), + ImageView2D{image.format(), image.size(), image.data()}); + framebuffer.read({{}, image.size()}, + MutableImageView2D{image.format(), image.size(), data}); + + MAGNUM_VERIFY_NO_GL_ERROR(); +} +#endif + +#ifdef MAGNUM_TARGET_GLES2 +void PixelStorageGLTest::imageHeightNotSupported() { + CORRADE_SKIP_IF_NO_ASSERT(); + + char data[4*4*4]{}; + MutableImageView2D image{ + PixelStorage{} + .setImageHeight(4), + Magnum::PixelFormat::RGBA8Unorm, + {4, 4}, + data}; + + Texture2D texture; + /* Just to reset all pixel storage parameters potentially set by any of the + above tests to default. The (graceful) assertions would do an early + return somewhere in the middle, leading to some params being left at + their earlier state. */ + texture.setImage(0, + textureFormat(image.format()), + ImageView2D{image.format(), image.size(), data}); + + Framebuffer framebuffer{{}}; + framebuffer.attachTexture(Framebuffer::ColorAttachment{0}, texture, 0); + /* ... and similarly to reset unpack parameters */ + framebuffer.read({{}, image.size()}, + MutableImageView2D{image.format(), image.size(), data}); + + MAGNUM_VERIFY_NO_GL_ERROR(); + + Containers::String out; + Error redirectError{&out}; + texture.setImage(0, textureFormat(image.format()), image); + framebuffer.read({{}, image.size()}, image); + CORRADE_COMPARE_AS(out, + "GL: non-default PixelStorage::imageHeight() is not supported in OpenGL ES 2\n" + "GL: non-default PixelStorage::imageHeight() is not supported in OpenGL ES 2\n", + TestSuite::Compare::String); + + MAGNUM_VERIFY_NO_GL_ERROR(); + + /* And again to reset these for any tests that might run after */ + texture.setImage(0, + textureFormat(image.format()), + ImageView2D{image.format(), image.size(), data}); + framebuffer.read({{}, image.size()}, + MutableImageView2D{image.format(), image.size(), data}); + + MAGNUM_VERIFY_NO_GL_ERROR(); +} +#elif defined(MAGNUM_TARGET_GLES) +void PixelStorageGLTest::imageHeightSkipZPackNotSupported() { + CORRADE_SKIP_IF_NO_ASSERT(); + + GL::Context::current().resetState(GL::Context::State::PixelStorage); + + char data[4*4*4*2]{}; /* twice for skip Z */ + Texture2D texture; + /* Just so the texure can be correctly read from */ + texture.setImage(0, TextureFormat::RGBA8, + ImageView2D{Magnum::PixelFormat::RGBA8Unorm, {4, 4}, data}); + + Framebuffer framebuffer{{}}; + framebuffer.attachTexture(Framebuffer::ColorAttachment{0}, texture, 0); + /* Just to reset all pixel storage parameters potentially set by any of the + above tests to default. The (graceful) assertions would do an early + return somewhere in the middle, leading to some params being left at + their earlier state. */ + framebuffer.read({{}, {4, 4}}, + MutableImageView2D{Magnum::PixelFormat::RGBA8Unorm, {4, 4}, data}); + + MutableImageView2D imageImageHeight{ + PixelStorage{} + .setImageHeight(4), + Magnum::PixelFormat::RGBA8Unorm, + {4, 4}, + data}; + MutableImageView2D imageSkipZ{ + PixelStorage{} + .setSkip({0, 0, 1}), + Magnum::PixelFormat::RGBA8Unorm, + {4, 4}, + data}; + + MAGNUM_VERIFY_NO_GL_ERROR(); + + Containers::String out; + Error redirectError{&out}; + framebuffer.read({{}, imageImageHeight.size()}, imageImageHeight); + framebuffer.read({{}, imageSkipZ.size()}, imageSkipZ); + CORRADE_COMPARE_AS(out, + "GL: non-default PixelStorage::imageHeight() for pack is not supported in OpenGL ES\n" + "GL: non-default PixelStorage::skip().z() for pack is not supported in OpenGL ES\n", + TestSuite::Compare::String); + + MAGNUM_VERIFY_NO_GL_ERROR(); + + /* And again to reset these for any tests that might run after */ + framebuffer.read({{}, {4, 4}}, + MutableImageView2D{Magnum::PixelFormat::RGBA8Unorm, {4, 4}, data}); + + MAGNUM_VERIFY_NO_GL_ERROR(); +} +#endif + #ifndef MAGNUM_TARGET_GLES constexpr const UnsignedByte CompressedData2D[] = { /* Skip */ @@ -450,6 +633,82 @@ void PixelStorageGLTest::compressedPack3D() { } #endif +#ifdef MAGNUM_TARGET_GLES +void PixelStorageGLTest::compressedNotSupported() { + CORRADE_SKIP_IF_NO_ASSERT(); + + /* Pick a 64-bit 4x4 format. Zero data are uploaded so it doesn't matter + which it is. */ + Magnum::CompressedPixelFormat format; + #ifndef MAGNUM_TARGET_WEBGL + if(Context::current().isExtensionSupported() || + Context::current().isExtensionSupported() || + Context::current().isExtensionSupported()) + #else + if(Context::current().isExtensionSupported()) + #endif + { + format = Magnum::CompressedPixelFormat::Bc1RGBUnorm; + } else + #ifdef MAGNUM_TARGET_WEBGL + if(Context::current().isExtensionSupported()) + #elif defined(MAGNUM_TARGET_GLES2) + if(Context::current().isExtensionSupported()) + #else + /* On ES3 ETC textures are available always */ + #endif + { + format = Magnum::CompressedPixelFormat::Etc2RGB8Unorm; + } + #if defined(MAGNUM_TARGET_WEBGL) || defined(MAGNUM_TARGET_GLES2) + else { + #ifdef MAGNUM_TARGET_WEBGL + CORRADE_SKIP(Extensions::WEBGL::compressed_texture_s3tc::string() << "not supported, can't test"); + #else + CORRADE_SKIP("None of" << Extensions::EXT::texture_compression_s3tc::string() << Debug::nospace << "," << Extensions::EXT::texture_compression_dxt1::string() << Debug::nospace << "," << Extensions::ANGLE::texture_compression_dxt1::string() << "or" << Extensions::ANGLE::compressed_texture_etc::string() << "extensions are supported, can't test"); + #endif + } + #endif + + char data[8]{}; + MutableCompressedImageView2D image{ + /* Just set any random property to make it different from the + default-constructed instance to trigger the assert */ + CompressedPixelStorage{} + .setRowLength(4), + format, + {4, 4}, + data}; + + Texture2D texture; + /* Just to reset all pixel storage parameters potentially set by any of the + above tests to default. The (graceful) assertions would do an early + return somewhere in the middle, leading to some params being left at + their earlier state. */ + texture.setCompressedImage(0, + CompressedImageView2D{image.format(), image.size(), data}); + + MAGNUM_VERIFY_NO_GL_ERROR(); + + Containers::String out; + Error redirectError{&out}; + texture.setCompressedImage(0, image); + /* There isn't any way to use CompressedPixelStorage for pixel pack on + GLES */ + CORRADE_COMPARE_AS(out, + "GL: non-default CompressedPixelStorage parameters are not supported in OpenGL ES or WebGL\n", + TestSuite::Compare::String); + + MAGNUM_VERIFY_NO_GL_ERROR(); + + /* And again to reset these for any tests that might run after */ + texture.setCompressedImage(0, + CompressedImageView2D{image.format(), image.size(), data}); + + MAGNUM_VERIFY_NO_GL_ERROR(); +} +#endif + }}}} CORRADE_TEST_MAIN(Magnum::GL::Test::PixelStorageGLTest)