From 8fa9b898820b44b96eee3a2a5f73c83684965263 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 18 Apr 2018 23:59:29 +0200 Subject: [PATCH] Split the OpenGL layer out, pt 10: test the new image APIs. With the previous commits the original tests passed (which is desired), but these were using deprecated functionality and not covering the new stuff. These tests are not using the deprecated functionality, which means I don't need to build them as part of the GL library anymore. The GL::BufferImage test is still using the deprecated functionality though, in order to check I didn't break anything by accident. --- src/Magnum/CMakeLists.txt | 4 +- src/Magnum/GL/BufferImage.cpp | 6 +- src/Magnum/GL/CMakeLists.txt | 4 +- src/Magnum/GL/Test/BufferImageGLTest.cpp | 223 +++++++++ src/Magnum/GL/Test/CMakeLists.txt | 8 +- src/Magnum/Image.cpp | 2 +- src/Magnum/ImageView.cpp | 4 +- src/Magnum/Test/CMakeLists.txt | 6 + src/Magnum/Test/ImageTest.cpp | 576 +++++++++++++++++++---- src/Magnum/Test/ImageViewTest.cpp | 515 ++++++++++++++++++-- src/Magnum/Test/PixelStorageTest.cpp | 222 +++------ src/Magnum/Trade/CMakeLists.txt | 53 ++- src/Magnum/Trade/ImageData.cpp | 2 +- src/Magnum/Trade/Test/CMakeLists.txt | 2 +- src/Magnum/Trade/Test/ImageDataTest.cpp | 476 +++++++++++++++---- src/Magnum/Trade/visibility.h | 2 +- src/Magnum/visibility.h | 2 +- 17 files changed, 1730 insertions(+), 377 deletions(-) diff --git a/src/Magnum/CMakeLists.txt b/src/Magnum/CMakeLists.txt index 35529456e..30e551b41 100644 --- a/src/Magnum/CMakeLists.txt +++ b/src/Magnum/CMakeLists.txt @@ -28,13 +28,13 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure.h.cmake # Files shared between main library and unit test library set(Magnum_SRCS - Image.cpp - ImageView.cpp PixelStorage.cpp Resource.cpp Timeline.cpp) set(Magnum_GracefulAssert_SRCS + Image.cpp + ImageView.cpp PixelFormat.cpp) set(Magnum_HEADERS diff --git a/src/Magnum/GL/BufferImage.cpp b/src/Magnum/GL/BufferImage.cpp index 173227a40..c63ae79c9 100644 --- a/src/Magnum/GL/BufferImage.cpp +++ b/src/Magnum/GL/BufferImage.cpp @@ -37,7 +37,7 @@ template BufferImage::BufferImage(const Pixe template BufferImage::BufferImage(const PixelStorage storage, const Magnum::PixelFormat format, const VectorTypeFor& size, Containers::ArrayView const data, const BufferUsage usage): BufferImage{storage, GL::pixelFormat(format), GL::pixelType(format), size, data, usage} {} template BufferImage::BufferImage(const PixelStorage storage, const PixelFormat format, const PixelType type, const VectorTypeFor& size, Buffer&& buffer, const std::size_t dataSize) noexcept: _storage{storage}, _format{format}, _type{type}, _size{size}, _buffer{std::move(buffer)}, _dataSize{dataSize} { - CORRADE_ASSERT(Magnum::Implementation::imageDataSize(*this) <= dataSize, "GL::BufferImage::BufferImage(): bad image data size, got" << dataSize << "but expected at least" << Magnum::Implementation::imageDataSize(*this), ); + CORRADE_ASSERT(Magnum::Implementation::imageDataSize(*this) <= dataSize, "GL::BufferImage::BufferImage(): data too small, got" << dataSize << "but expected at least" << Magnum::Implementation::imageDataSize(*this) << "bytes", ); } template BufferImage::BufferImage(const PixelStorage storage, const Magnum::PixelFormat format, const VectorTypeFor& size, Buffer&& buffer, const std::size_t dataSize) noexcept: BufferImage{storage, GL::pixelFormat(format), GL::pixelType(format), size, std::move(buffer), dataSize} {} @@ -58,9 +58,9 @@ template void BufferImage::setData(const Pix /* Keep the old storage if zero-sized nullptr buffer was passed */ if(data.data() == nullptr && data.size() == 0) - CORRADE_ASSERT(Magnum::Implementation::imageDataSize(*this) <= _dataSize, "GL::BufferImage::setData(): bad current storage size, got" << _dataSize << "but expected at least" << Magnum::Implementation::imageDataSize(*this), ); + CORRADE_ASSERT(Magnum::Implementation::imageDataSize(*this) <= _dataSize, "GL::BufferImage::setData(): current storage too small, got" << _dataSize << "but expected at least" << Magnum::Implementation::imageDataSize(*this) << "bytes", ); else { - CORRADE_ASSERT(Magnum::Implementation::imageDataSize(*this) <= data.size(), "GL::BufferImage::setData(): bad image data size, got" << data.size() << "but expected at least" << Magnum::Implementation::imageDataSize(*this), ); + CORRADE_ASSERT(Magnum::Implementation::imageDataSize(*this) <= data.size(), "GL::BufferImage::setData(): data too small, got" << data.size() << "but expected at least" << Magnum::Implementation::imageDataSize(*this) << "bytes", ); _buffer.setData(data, usage); _dataSize = data.size(); } diff --git a/src/Magnum/GL/CMakeLists.txt b/src/Magnum/GL/CMakeLists.txt index 6e68d70c9..b57d246cc 100644 --- a/src/Magnum/GL/CMakeLists.txt +++ b/src/Magnum/GL/CMakeLists.txt @@ -109,13 +109,15 @@ endif() # OpenGL ES 3.0 and WebGL 2.0 stuff if(NOT TARGET_GLES2) list(APPEND MagnumGL_SRCS - BufferImage.cpp PrimitiveQuery.cpp TextureArray.cpp TransformFeedback.cpp Implementation/TransformFeedbackState.cpp) + list(APPEND MagnumGL_GracefulAssert_SRCS + BufferImage.cpp) + list(APPEND MagnumGL_HEADERS BufferImage.h PrimitiveQuery.h diff --git a/src/Magnum/GL/Test/BufferImageGLTest.cpp b/src/Magnum/GL/Test/BufferImageGLTest.cpp index 3304f1f43..bb4687e58 100644 --- a/src/Magnum/GL/Test/BufferImageGLTest.cpp +++ b/src/Magnum/GL/Test/BufferImageGLTest.cpp @@ -23,6 +23,7 @@ DEALINGS IN THE SOFTWARE. */ +#include #include #include @@ -36,16 +37,26 @@ struct BufferImageGLTest: OpenGLTester { explicit BufferImageGLTest(); void construct(); + void constructGeneric(); void constructCompressed(); + void constructCompressedGeneric(); void constructBuffer(); + void constructBufferGeneric(); void constructBufferCompressed(); + void constructBufferCompressedGeneric(); + + void constructInvalidSize(); + void constructCompressedInvalidSize(); + void constructCopy(); void constructCopyCompressed(); void constructMove(); void constructMoveCompressed(); void setData(); + void setDataGeneric(); void setDataCompressed(); + void setDataCompressedGeneric(); void release(); void releaseCompressed(); @@ -53,16 +64,26 @@ struct BufferImageGLTest: OpenGLTester { BufferImageGLTest::BufferImageGLTest() { addTests({&BufferImageGLTest::construct, + &BufferImageGLTest::constructGeneric, &BufferImageGLTest::constructCompressed, + &BufferImageGLTest::constructCompressedGeneric, &BufferImageGLTest::constructBuffer, + &BufferImageGLTest::constructBufferGeneric, &BufferImageGLTest::constructBufferCompressed, + &BufferImageGLTest::constructBufferCompressedGeneric, + + &BufferImageGLTest::constructInvalidSize, + &BufferImageGLTest::constructCompressedInvalidSize, + &BufferImageGLTest::constructCopy, &BufferImageGLTest::constructCopyCompressed, &BufferImageGLTest::constructMove, &BufferImageGLTest::constructMoveCompressed, &BufferImageGLTest::setData, + &BufferImageGLTest::setDataGeneric, &BufferImageGLTest::setDataCompressed, + &BufferImageGLTest::setDataCompressedGeneric, &BufferImageGLTest::release, &BufferImageGLTest::releaseCompressed}); @@ -91,6 +112,29 @@ void BufferImageGLTest::construct() { #endif } +void BufferImageGLTest::constructGeneric() { + const char data[] = { 'a', 'b', 'c' }; + BufferImage2D a{PixelStorage{}.setAlignment(1), + Magnum::PixelFormat::R8Unorm, {1, 3}, data, BufferUsage::StaticDraw}; + + #ifndef MAGNUM_TARGET_GLES + const auto imageData = a.buffer().data(); + #endif + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(a.storage().alignment(), 1); + CORRADE_COMPARE(a.format(), GL::PixelFormat::Red); + CORRADE_COMPARE(a.type(), PixelType::UnsignedByte); + CORRADE_COMPARE(a.size(), Vector2i(1, 3)); + + /** @todo How to verify the contents in ES? */ + #ifndef MAGNUM_TARGET_GLES + CORRADE_COMPARE_AS(imageData, Containers::arrayView(data), + TestSuite::Compare::Container); + #endif +} + void BufferImageGLTest::constructCompressed() { const char data[] = { 'a', 0, 0, 0, 'b', 0, 0, 0 }; CompressedBufferImage2D a{ @@ -120,6 +164,35 @@ void BufferImageGLTest::constructCompressed() { #endif } +void BufferImageGLTest::constructCompressedGeneric() { + const char data[] = { 'a', 0, 0, 0, 'b', 0, 0, 0 }; + CompressedBufferImage2D a{ + #ifndef MAGNUM_TARGET_GLES + CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}), + #endif + Magnum::CompressedPixelFormat::Bc1RGBAUnorm, + {4, 4}, data, BufferUsage::StaticDraw}; + + #ifndef MAGNUM_TARGET_GLES + const auto imageData = a.buffer().data(); + #endif + + MAGNUM_VERIFY_NO_ERROR(); + + #ifndef MAGNUM_TARGET_GLES + CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{4}); + #endif + CORRADE_COMPARE(a.format(), GL::CompressedPixelFormat::RGBAS3tcDxt1); + CORRADE_COMPARE(a.size(), Vector2i(4, 4)); + CORRADE_COMPARE(a.dataSize(), 8); + + /** @todo How to verify the contents in ES? */ + #ifndef MAGNUM_TARGET_GLES + CORRADE_COMPARE_AS(imageData, Containers::arrayView(data), + TestSuite::Compare::Container); + #endif +} + void BufferImageGLTest::constructBuffer() { const char data[] = { 'a', 'b', 'c' }; Buffer buffer; @@ -149,6 +222,35 @@ void BufferImageGLTest::constructBuffer() { #endif } +void BufferImageGLTest::constructBufferGeneric() { + const char data[] = { 'a', 'b', 'c' }; + Buffer buffer; + buffer.setData(data, BufferUsage::StaticDraw); + const UnsignedInt id = buffer.id(); + + BufferImage2D a{PixelStorage{}.setAlignment(1), + Magnum::PixelFormat::R8Unorm, {1, 3}, std::move(buffer), sizeof(data)}; + + #ifndef MAGNUM_TARGET_GLES + const auto imageData = a.buffer().data(); + #endif + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_VERIFY(!buffer.id()); + CORRADE_COMPARE(a.buffer().id(), id); + CORRADE_COMPARE(a.storage().alignment(), 1); + CORRADE_COMPARE(a.format(), GL::PixelFormat::Red); + CORRADE_COMPARE(a.type(), PixelType::UnsignedByte); + CORRADE_COMPARE(a.size(), Vector2i(1, 3)); + + /** @todo How to verify the contents in ES? */ + #ifndef MAGNUM_TARGET_GLES + CORRADE_COMPARE_AS(imageData, Containers::arrayView(data), + TestSuite::Compare::Container); + #endif +} + void BufferImageGLTest::constructBufferCompressed() { const char data[] = { 'a', 0, 0, 0, 'b', 0, 0, 0 }; Buffer buffer; @@ -184,6 +286,69 @@ void BufferImageGLTest::constructBufferCompressed() { #endif } +void BufferImageGLTest::constructBufferCompressedGeneric() { + const char data[] = { 'a', 0, 0, 0, 'b', 0, 0, 0 }; + Buffer buffer; + buffer.setData(data, BufferUsage::StaticDraw); + const UnsignedInt id = buffer.id(); + + CompressedBufferImage2D a{ + #ifndef MAGNUM_TARGET_GLES + CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}), + #endif + Magnum::CompressedPixelFormat::Bc1RGBAUnorm, + {4, 4}, std::move(buffer), sizeof(data)}; + + #ifndef MAGNUM_TARGET_GLES + const auto imageData = a.buffer().data(); + #endif + + MAGNUM_VERIFY_NO_ERROR(); + + #ifndef MAGNUM_TARGET_GLES + CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{4}); + #endif + CORRADE_VERIFY(!buffer.id()); + CORRADE_COMPARE(a.buffer().id(), id); + CORRADE_COMPARE(a.format(), GL::CompressedPixelFormat::RGBAS3tcDxt1); + CORRADE_COMPARE(a.size(), Vector2i(4, 4)); + CORRADE_COMPARE(a.dataSize(), 8); + + /** @todo How to verify the contents in ES? */ + #ifndef MAGNUM_TARGET_GLES + CORRADE_COMPARE_AS(imageData, Containers::arrayView(data), + TestSuite::Compare::Container); + #endif +} + +void BufferImageGLTest::constructInvalidSize() { + std::ostringstream out; + Error redirectError{&out}; + + /* Doesn't consider alignment */ + BufferImage2D{PixelFormat::RGB8Unorm, {1, 3}, Containers::Array{3*3}, BufferUsage::StaticDraw}; + CORRADE_COMPARE(out.str(), "GL::BufferImage::BufferImage(): data too small, got 9 but expected at least 12 bytes\n"); +} + +void BufferImageGLTest::constructCompressedInvalidSize() { + CORRADE_EXPECT_FAIL("Size checking for compressed image data is not implemented yet."); + + /* Too small for given format */ + { + std::ostringstream out; + Error redirectError{&out}; + CompressedBufferImage2D{CompressedPixelFormat::Bc2RGBAUnorm, {4, 4}, Containers::Array{2}, BufferUsage::StaticDraw}; + CORRADE_COMPARE(out.str(), "GL::CompressedBufferImage::CompressedBufferImage(): data too small, got 2 but expected at least 4 bytes\n"); + + /* Size should be rounded up even if the image size is not full block */ + } { + std::ostringstream out; + Error redirectError{&out}; + CompressedBufferImage2D{CompressedPixelFormat::Bc2RGBAUnorm, {2, 2}, Containers::Array{2}, BufferUsage::StaticDraw}; + CORRADE_COMPARE(out.str(), "GL::CompressedBufferImage::CompressedBufferImage(): data too small, got 2 but expected at least 4 bytes\n"); + } +} + void BufferImageGLTest::constructCopy() { CORRADE_VERIFY(!(std::is_constructible{})); CORRADE_VERIFY(!(std::is_assignable{})); @@ -306,6 +471,33 @@ void BufferImageGLTest::setData() { #endif } +void BufferImageGLTest::setDataGeneric() { + const char data[4] = { 'a', 'b', 'c', 'd' }; + BufferImage2D a{PixelStorage{}.setAlignment(1), + PixelFormat::Red, PixelType::UnsignedByte, {4, 1}, data, BufferUsage::StaticDraw}; + + const UnsignedShort data2[2*4] = { 1, 2, 3, 4, 5, 6, 7, 8 }; + a.setData(Magnum::PixelFormat::RGBA16Unorm, {1, 2}, data2, BufferUsage::StaticDraw); + + #ifndef MAGNUM_TARGET_GLES + const auto imageData = a.buffer().data(); + #endif + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(a.storage().alignment(), 4); + CORRADE_COMPARE(a.format(), GL::PixelFormat::RGBA); + CORRADE_COMPARE(a.type(), PixelType::UnsignedShort); + CORRADE_COMPARE(a.size(), Vector2i(1, 2)); + + /** @todo How to verify the contents in ES? */ + #ifndef MAGNUM_TARGET_GLES + CORRADE_COMPARE_AS(Containers::arrayCast(imageData), + Containers::arrayView(data2), + TestSuite::Compare::Container); + #endif +} + void BufferImageGLTest::setDataCompressed() { const char data[] = { 'a', 0, 0, 0, 'b', 0, 0, 0 }; CompressedBufferImage2D a{CompressedPixelFormat::RGBAS3tcDxt1, {4, 4}, data, BufferUsage::StaticDraw}; @@ -337,6 +529,37 @@ void BufferImageGLTest::setDataCompressed() { #endif } +void BufferImageGLTest::setDataCompressedGeneric() { + const char data[] = { 'a', 0, 0, 0, 'b', 0, 0, 0 }; + CompressedBufferImage2D a{CompressedPixelFormat::RGBAS3tcDxt1, {4, 4}, data, BufferUsage::StaticDraw}; + + const char data2[] = { 'a', 0, 0, 0, 'b', 0, 0, 0, 'c', 0, 0, 0, 'd', 0, 0, 0 }; + a.setData( + #ifndef MAGNUM_TARGET_GLES + CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}), + #endif + Magnum::CompressedPixelFormat::Bc2RGBAUnorm, {8, 4}, data2, BufferUsage::StaticDraw); + + #ifndef MAGNUM_TARGET_GLES + const auto imageData = a.buffer().data(); + #endif + + MAGNUM_VERIFY_NO_ERROR(); + + #ifndef MAGNUM_TARGET_GLES + CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{4}); + #endif + CORRADE_COMPARE(a.format(), GL::CompressedPixelFormat::RGBAS3tcDxt3); + CORRADE_COMPARE(a.size(), Vector2i(8, 4)); + CORRADE_COMPARE(a.dataSize(), 16); + + /** @todo How to verify the contents in ES? */ + #ifndef MAGNUM_TARGET_GLES + CORRADE_COMPARE_AS(imageData, Containers::arrayView(data2), + TestSuite::Compare::Container); + #endif +} + void BufferImageGLTest::release() { BufferImage2D a{PixelFormat::RGBA, PixelType::UnsignedByte}; const UnsignedInt id = a.buffer().id(); diff --git a/src/Magnum/GL/Test/CMakeLists.txt b/src/Magnum/GL/Test/CMakeLists.txt index 817dbeef4..ac090e867 100644 --- a/src/Magnum/GL/Test/CMakeLists.txt +++ b/src/Magnum/GL/Test/CMakeLists.txt @@ -30,11 +30,8 @@ corrade_add_test(GLContextTest ContextTest.cpp LIBRARIES MagnumGL) corrade_add_test(GLCubeMapTextureTest CubeMapTextureTest.cpp LIBRARIES MagnumGL) corrade_add_test(GLDefaultFramebufferTest DefaultFramebufferTest.cpp LIBRARIES MagnumGL) corrade_add_test(GLFramebufferTest FramebufferTest.cpp LIBRARIES MagnumGL) -corrade_add_test(GLImageTest ../../Test/ImageTest.cpp LIBRARIES MagnumGL) # temporary -corrade_add_test(GLImageViewTest ../../Test/ImageViewTest.cpp LIBRARIES MagnumGL) # temporary corrade_add_test(GLMeshTest MeshTest.cpp LIBRARIES MagnumGL) corrade_add_test(GLPixelFormatTest PixelFormatTest.cpp LIBRARIES MagnumGLTestLib) -corrade_add_test(GLPixelStorageTest ../../Test/PixelStorageTest.cpp LIBRARIES MagnumGL) # temporary corrade_add_test(GLRendererTest RendererTest.cpp LIBRARIES MagnumGL) corrade_add_test(GLRenderbufferTest RenderbufferTest.cpp LIBRARIES MagnumGL) corrade_add_test(GLSamplerTest SamplerTest.cpp LIBRARIES MagnumGL) @@ -50,10 +47,7 @@ set_target_properties( GLCubeMapTextureTest GLDefaultFramebufferTest GLFramebufferTest - GLImageTest - GLImageViewTest GLMeshTest - GLPixelStorageTest GLPixelFormatTest GLRendererTest GLRenderbufferTest @@ -179,7 +173,7 @@ if(BUILD_GL_TESTS) endif() if(NOT MAGNUM_TARGET_GLES2) - corrade_add_test(GLBufferImageGLTest BufferImageGLTest.cpp LIBRARIES MagnumOpenGLTester) + corrade_add_test(GLBufferImageGLTest BufferImageGLTest.cpp LIBRARIES MagnumGLTestLib MagnumOpenGLTester) corrade_add_test(GLBufferTextureGLTest BufferTextureGLTest.cpp LIBRARIES MagnumOpenGLTester) corrade_add_test(GLCubeMapTextureArrayGLTest CubeMapTextureArrayGLTest.cpp LIBRARIES MagnumOpenGLTester) corrade_add_test(GLMultisampleTextureGLTest MultisampleTextureGLTest.cpp LIBRARIES MagnumOpenGLTester) diff --git a/src/Magnum/Image.cpp b/src/Magnum/Image.cpp index 70ff21b93..4e22ab68b 100644 --- a/src/Magnum/Image.cpp +++ b/src/Magnum/Image.cpp @@ -34,7 +34,7 @@ template Image::Image(const PixelStorage sto template Image::Image(const PixelStorage storage, const UnsignedInt format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor& size, Containers::Array&& data) noexcept: Image{storage, pixelFormatWrap(format), formatExtra, pixelSize, size, std::move(data)} {} template Image::Image(const PixelStorage storage, const PixelFormat format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor& size, Containers::Array&& data) noexcept: _storage{storage}, _format{format}, _formatExtra{formatExtra}, _pixelSize{pixelSize}, _size{size}, _data{std::move(data)} { - CORRADE_ASSERT(Implementation::imageDataSize(*this) <= _data.size(), "Image::Image(): bad image data size, got" << _data.size() << "but expected at least" << Implementation::imageDataSize(*this), ); + CORRADE_ASSERT(Implementation::imageDataSize(*this) <= _data.size(), "Image::Image(): data too small, got" << _data.size() << "but expected at least" << Implementation::imageDataSize(*this) << "bytes", ); } template Image::Image(const PixelStorage storage, const PixelFormat format) noexcept: Image{storage, format, {}, Magnum::pixelSize(format)} {} diff --git a/src/Magnum/ImageView.cpp b/src/Magnum/ImageView.cpp index 69f0f5a77..67e8d682e 100644 --- a/src/Magnum/ImageView.cpp +++ b/src/Magnum/ImageView.cpp @@ -34,7 +34,7 @@ template ImageView::ImageView(const PixelSto template ImageView::ImageView(const PixelStorage storage, const UnsignedInt format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor& size, const Containers::ArrayView data) noexcept: ImageView{storage, pixelFormatWrap(format), formatExtra, pixelSize, size, data} {} template ImageView::ImageView(const PixelStorage storage, const PixelFormat format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor& size, const Containers::ArrayView data) noexcept: _storage{storage}, _format{format}, _formatExtra{formatExtra}, _pixelSize{pixelSize}, _size{size}, _data{reinterpret_cast(data.data()), data.size()} { - CORRADE_ASSERT(!_data || Implementation::imageDataSize(*this) <= _data.size(), "ImageView::ImageView(): bad image data size, got" << _data.size() << "but expected at least" << Implementation::imageDataSize(*this), ); + CORRADE_ASSERT(!_data || Implementation::imageDataSize(*this) <= _data.size(), "ImageView::ImageView(): data too small, got" << _data.size() << "but expected at least" << Implementation::imageDataSize(*this) << "bytes", ); } template ImageView::ImageView(const PixelStorage storage, const PixelFormat format, const VectorTypeFor& size) noexcept: ImageView{storage, format, {}, Magnum::pixelSize(format), size} {} @@ -44,7 +44,7 @@ template ImageView::ImageView(const PixelSto template ImageView::ImageView(const PixelStorage storage, const PixelFormat format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor& size) noexcept: _storage{storage}, _format{format}, _formatExtra{formatExtra}, _pixelSize{pixelSize}, _size{size}, _data{nullptr} {} template void ImageView::setData(const Containers::ArrayView data) { - CORRADE_ASSERT(Implementation::imageDataSize(*this) <= data.size(), "ImageView::setData(): bad image data size, got" << data.size() << "but expected at least" << Implementation::imageDataSize(*this), ); + CORRADE_ASSERT(Implementation::imageDataSize(*this) <= data.size(), "ImageView::setData(): data too small, got" << data.size() << "but expected at least" << Implementation::imageDataSize(*this) << "bytes", ); _data = {reinterpret_cast(data.data()), data.size()}; } diff --git a/src/Magnum/Test/CMakeLists.txt b/src/Magnum/Test/CMakeLists.txt index 8c98849ac..588435c99 100644 --- a/src/Magnum/Test/CMakeLists.txt +++ b/src/Magnum/Test/CMakeLists.txt @@ -24,8 +24,11 @@ # corrade_add_test(ArrayTest ArrayTest.cpp LIBRARIES Magnum) +corrade_add_test(ImageTest ImageTest.cpp LIBRARIES MagnumTestLib) +corrade_add_test(ImageViewTest ImageViewTest.cpp LIBRARIES MagnumTestLib) corrade_add_test(PixelFormatTest PixelFormatTest.cpp LIBRARIES MagnumTestLib) target_compile_definitions(PixelFormatTest PRIVATE "CORRADE_GRACEFUL_ASSERT") +corrade_add_test(PixelStorageTest PixelStorageTest.cpp LIBRARIES Magnum) corrade_add_test(ResourceManagerTest ResourceManagerTest.cpp LIBRARIES Magnum) target_compile_definitions(ResourceManagerTest PRIVATE "CORRADE_GRACEFUL_ASSERT") @@ -40,7 +43,10 @@ corrade_add_test(TagsTest TagsTest.cpp LIBRARIES Magnum) set_target_properties( ArrayTest + ImageTest + ImageViewTest PixelFormatTest + PixelStorageTest ResourceManagerTest ResourceManagerLocalInstanceTestLib ResourceManagerLocalInstanceTest diff --git a/src/Magnum/Test/ImageTest.cpp b/src/Magnum/Test/ImageTest.cpp index e90fc1f57..49623e67e 100644 --- a/src/Magnum/Test/ImageTest.cpp +++ b/src/Magnum/Test/ImageTest.cpp @@ -23,6 +23,7 @@ DEALINGS IN THE SOFTWARE. */ +#include #include #include "Magnum/Image.h" @@ -33,60 +34,366 @@ namespace Magnum { namespace Test { struct ImageTest: TestSuite::Tester { explicit ImageTest(); - void construct(); - void constructCompressed(); + void constructGeneric(); + void constructGenericPlaceholder(); + void constructImplementationSpecific(); + void constructImplementationSpecificPlaceholder(); + void constructCompressedGeneric(); + void constructCompressedGenericPlaceholder(); + void constructCompressedImplementationSpecific(); + + void constructInvalidSize(); + void constructCompressedInvalidSize(); + void constructCopy(); void constructCopyCompressed(); - void constructMove(); - void constructMoveCompressed(); - void toView(); - void toViewCompressed(); + void constructMoveGeneric(); + void constructMoveImplementationSpecific(); + void constructMoveCompressedGeneric(); + void constructMoveCompressedImplementationSpecific(); + + void toViewGeneric(); + void toViewImplementationSpecific(); + void toViewCompressedGeneric(); + void toViewCompressedImplementationSpecific(); + + void access(); + void accessCompressed(); + void release(); void releaseCompressed(); }; ImageTest::ImageTest() { - addTests({&ImageTest::construct, - &ImageTest::constructCompressed, + addTests({&ImageTest::constructGeneric, + &ImageTest::constructGenericPlaceholder, + &ImageTest::constructImplementationSpecific, + &ImageTest::constructImplementationSpecificPlaceholder, + &ImageTest::constructCompressedGeneric, + &ImageTest::constructCompressedGenericPlaceholder, + &ImageTest::constructCompressedImplementationSpecific, + + &ImageTest::constructInvalidSize, + &ImageTest::constructCompressedInvalidSize, + &ImageTest::constructCopy, &ImageTest::constructCopyCompressed, - &ImageTest::constructMove, - &ImageTest::constructMoveCompressed, - &ImageTest::toView, - &ImageTest::toViewCompressed, + &ImageTest::constructMoveGeneric, + &ImageTest::constructMoveImplementationSpecific, + &ImageTest::constructMoveCompressedGeneric, + &ImageTest::constructMoveCompressedImplementationSpecific, + + &ImageTest::toViewGeneric, + &ImageTest::toViewImplementationSpecific, + &ImageTest::toViewCompressedGeneric, + &ImageTest::toViewCompressedImplementationSpecific, + + &ImageTest::access, + &ImageTest::accessCompressed, + &ImageTest::release, &ImageTest::releaseCompressed}); } -void ImageTest::construct() { - auto data = new char[3*4]; - Image2D a{PixelStorage{}.setAlignment(1), - PixelFormat::RGBA, PixelType::UnsignedByte, {1, 3}, Containers::Array{data, 3*4}}; +namespace { - CORRADE_COMPARE(a.storage().alignment(), 1); - CORRADE_COMPARE(a.format(), PixelFormat::RGBA); - CORRADE_COMPARE(a.type(), PixelType::UnsignedByte); - CORRADE_COMPARE(a.size(), Vector2i(1, 3)); - CORRADE_COMPARE(a.data(), data); +namespace GL { + enum class PixelFormat { RGB = 666 }; + enum class PixelType { UnsignedShort = 1337 }; + UnsignedInt pixelSize(PixelFormat format, PixelType type) { + CORRADE_INTERNAL_ASSERT(format == PixelFormat::RGB); + CORRADE_INTERNAL_ASSERT(type == PixelType::UnsignedShort); + return 6; + } + + enum class CompressedPixelFormat { RGBS3tcDxt1 = 21 }; } -void ImageTest::constructCompressed() { - auto data = new char[8]; - CompressedImage2D a{ - #ifndef MAGNUM_TARGET_GLES - CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}), - #endif - CompressedPixelFormat::RGBAS3tcDxt1, {4, 4}, Containers::Array{data, 8}}; - - #ifndef MAGNUM_TARGET_GLES - CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{4}); - #endif - CORRADE_COMPARE(a.format(), CompressedPixelFormat::RGBAS3tcDxt1); - CORRADE_COMPARE(a.size(), Vector2i(4, 4)); - CORRADE_COMPARE(a.data(), data); - CORRADE_COMPARE(a.data().size(), 8); +namespace Vk { + enum class PixelFormat { R32G32B32F = 42 }; + UnsignedInt pixelSize(PixelFormat format) { + CORRADE_INTERNAL_ASSERT(format == PixelFormat::R32G32B32F); + return 12; + } + + enum class CompressedPixelFormat { Bc1SRGBAlpha = 42 }; +} + +} + +void ImageTest::constructGeneric() { + { + auto data = new char[4*4]; + Image2D a{PixelFormat::RGBA8Unorm, {1, 3}, Containers::Array{data, 4*4}}; + + CORRADE_COMPARE(a.storage().alignment(), 4); + CORRADE_COMPARE(a.format(), PixelFormat::RGBA8Unorm); + CORRADE_COMPARE(a.formatExtra(), 0); + CORRADE_COMPARE(a.pixelSize(), 4); + CORRADE_COMPARE(a.size(), (Vector2i{1, 3})); + CORRADE_COMPARE(a.data(), data); + CORRADE_COMPARE(a.data().size(), 4*4); + } { + auto data = new char[3*2]; + Image2D a{PixelStorage{}.setAlignment(1), + PixelFormat::R16UI, {1, 3}, Containers::Array{data, 3*2}}; + + CORRADE_COMPARE(a.storage().alignment(), 1); + CORRADE_COMPARE(a.format(), PixelFormat::R16UI); + CORRADE_COMPARE(a.formatExtra(), 0); + CORRADE_COMPARE(a.pixelSize(), 2); + CORRADE_COMPARE(a.size(), (Vector2i{1, 3})); + CORRADE_COMPARE(a.data(), data); + CORRADE_COMPARE(a.data().size(), 3*2); + } +} + +void ImageTest::constructGenericPlaceholder() { + { + Image2D a{PixelFormat::RG32F}; + + CORRADE_COMPARE(a.storage().alignment(), 4); + CORRADE_COMPARE(a.format(), PixelFormat::RG32F); + CORRADE_COMPARE(a.formatExtra(), 0); + CORRADE_COMPARE(a.pixelSize(), 8); + CORRADE_COMPARE(a.size(), Vector2i{}); + CORRADE_COMPARE(a.data(), nullptr); + } { + Image2D a{PixelStorage{}.setAlignment(1), + PixelFormat::RGB16F}; + + CORRADE_COMPARE(a.storage().alignment(), 1); + CORRADE_COMPARE(a.format(), PixelFormat::RGB16F); + CORRADE_COMPARE(a.formatExtra(), 0); + CORRADE_COMPARE(a.pixelSize(), 6); + CORRADE_COMPARE(a.size(), Vector2i{}); + CORRADE_COMPARE(a.data(), nullptr); + } +} + +void ImageTest::constructImplementationSpecific() { + /* Single format */ + { + auto data = new char[3*12]; + Image2D a{Vk::PixelFormat::R32G32B32F, {1, 3}, Containers::Array{data, 3*12}}; + + CORRADE_COMPARE(a.storage().alignment(), 4); + CORRADE_COMPARE(a.format(), pixelFormatWrap(Vk::PixelFormat::R32G32B32F)); + CORRADE_COMPARE(a.formatExtra(), 0); + CORRADE_COMPARE(a.pixelSize(), 12); + CORRADE_COMPARE(a.size(), (Vector2i{1, 3})); + CORRADE_COMPARE(a.data(), data); + CORRADE_COMPARE(a.data().size(), 3*12); + } { + auto data = new char[3*12]; + Image2D a{PixelStorage{}.setAlignment(1), + Vk::PixelFormat::R32G32B32F, {1, 3}, Containers::Array{data, 3*12}}; + + CORRADE_COMPARE(a.storage().alignment(), 1); + CORRADE_COMPARE(a.format(), pixelFormatWrap(Vk::PixelFormat::R32G32B32F)); + CORRADE_COMPARE(a.formatExtra(), 0); + CORRADE_COMPARE(a.pixelSize(), 12); + CORRADE_COMPARE(a.size(), (Vector2i{1, 3})); + CORRADE_COMPARE(a.data(), data); + CORRADE_COMPARE(a.data().size(), 3*12); + } + + /* Format + extra */ + { + auto data = new char[3*8]; + Image2D a{GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, Containers::Array{data, 3*8}}; + + CORRADE_COMPARE(a.storage().alignment(), 4); + CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB)); + CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort)); + CORRADE_COMPARE(a.pixelSize(), 6); + CORRADE_COMPARE(a.size(), (Vector2i{1, 3})); + CORRADE_COMPARE(a.data(), data); + CORRADE_COMPARE(a.data().size(), 3*8); + } { + auto data = new char[3*6]; + Image2D a{PixelStorage{}.setAlignment(1), + GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, Containers::Array{data, 3*6}}; + + CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB)); + CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort)); + CORRADE_COMPARE(a.pixelSize(), 6); + CORRADE_COMPARE(a.size(), (Vector2i{1, 3})); + CORRADE_COMPARE(a.data(), data); + CORRADE_COMPARE(a.data().size(), 3*6); + } + + /* Manual pixel size */ + { + auto data = new char[3*6]; + Image2D a{PixelStorage{}.setAlignment(1), 666, 1337, 6, {1, 3}, Containers::Array{data, 3*6}}; + + CORRADE_COMPARE(a.storage().alignment(), 1); + CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB)); + CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort)); + CORRADE_COMPARE(a.pixelSize(), 6); + CORRADE_COMPARE(a.size(), (Vector2i{1, 3})); + CORRADE_COMPARE(a.data(), data); + CORRADE_COMPARE(a.data().size(), 3*6); + } +} + +void ImageTest::constructImplementationSpecificPlaceholder() { + /* Single format */ + { + Image2D a{Vk::PixelFormat::R32G32B32F}; + + CORRADE_COMPARE(a.storage().alignment(), 4); + CORRADE_COMPARE(a.format(), pixelFormatWrap(Vk::PixelFormat::R32G32B32F)); + CORRADE_COMPARE(a.formatExtra(), 0); + CORRADE_COMPARE(a.pixelSize(), 12); + CORRADE_COMPARE(a.size(), Vector2i{}); + CORRADE_COMPARE(a.data(), nullptr); + } { + Image2D a{PixelStorage{}.setAlignment(1), + Vk::PixelFormat::R32G32B32F}; + + CORRADE_COMPARE(a.storage().alignment(), 1); + CORRADE_COMPARE(a.format(), pixelFormatWrap(Vk::PixelFormat::R32G32B32F)); + CORRADE_COMPARE(a.formatExtra(), 0); + CORRADE_COMPARE(a.pixelSize(), 12); + CORRADE_COMPARE(a.size(), Vector2i{}); + CORRADE_COMPARE(a.data(), nullptr); + } + + /* Format + extra */ + { + Image2D a{GL::PixelFormat::RGB, GL::PixelType::UnsignedShort}; + + CORRADE_COMPARE(a.storage().alignment(), 4); + CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB)); + CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort)); + CORRADE_COMPARE(a.pixelSize(), 6); + CORRADE_COMPARE(a.size(), Vector2i{}); + CORRADE_COMPARE(a.data(), nullptr); + } { + Image2D a{PixelStorage{}.setAlignment(1), + GL::PixelFormat::RGB, GL::PixelType::UnsignedShort}; + + CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB)); + CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort)); + CORRADE_COMPARE(a.pixelSize(), 6); + CORRADE_COMPARE(a.size(), Vector2i{}); + CORRADE_COMPARE(a.data(), nullptr); + } + + /* Manual pixel size */ + { + Image2D a{PixelStorage{}.setAlignment(1), 666, 1337, 6}; + + CORRADE_COMPARE(a.storage().alignment(), 1); + CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB)); + CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort)); + CORRADE_COMPARE(a.pixelSize(), 6); + CORRADE_COMPARE(a.size(), Vector2i{}); + CORRADE_COMPARE(a.data(), nullptr); + } +} + +void ImageTest::constructCompressedGeneric() { + { + auto data = new char[8]; + CompressedImage2D a{CompressedPixelFormat::Bc1RGBAUnorm, {4, 4}, + Containers::Array{data, 8}}; + + CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{0}); + CORRADE_COMPARE(a.format(), CompressedPixelFormat::Bc1RGBAUnorm); + CORRADE_COMPARE(a.size(), (Vector2i{4, 4})); + CORRADE_COMPARE(a.data(), data); + CORRADE_COMPARE(a.data().size(), 8); + } { + auto data = new char[8]; + CompressedImage2D a{CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}), + CompressedPixelFormat::Bc1RGBAUnorm, {4, 4}, + Containers::Array{data, 8}}; + + CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{4}); + CORRADE_COMPARE(a.format(), CompressedPixelFormat::Bc1RGBAUnorm); + CORRADE_COMPARE(a.size(), Vector2i(4, 4)); + CORRADE_COMPARE(a.data(), data); + CORRADE_COMPARE(a.data().size(), 8); + } +} + +void ImageTest::constructCompressedGenericPlaceholder() { + { + CompressedImage2D a; + + CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{0}); + CORRADE_COMPARE(a.format(), CompressedPixelFormat{}); + CORRADE_COMPARE(a.size(), Vector2i{}); + CORRADE_COMPARE(a.data(), nullptr); + } { + CompressedImage2D a{CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4})}; + + CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{4}); + CORRADE_COMPARE(a.format(), CompressedPixelFormat{}); + CORRADE_COMPARE(a.size(), Vector2i{}); + CORRADE_COMPARE(a.data(), nullptr); + } +} + +void ImageTest::constructCompressedImplementationSpecific() { + /* Format with autodetection */ + { + auto data = new char[8]; + CompressedImage2D a{GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 4}, + Containers::Array{data, 8}}; + + CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{0}); + CORRADE_COMPARE(a.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1)); + CORRADE_COMPARE(a.size(), (Vector2i{4, 4})); + CORRADE_COMPARE(a.data(), data); + CORRADE_COMPARE(a.data().size(), 8); + } { + auto data = new char[8]; + CompressedImage2D a{CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}), + GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 4}, + Containers::Array{data, 8}}; + + CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{4}); + CORRADE_COMPARE(a.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1)); + CORRADE_COMPARE(a.size(), (Vector2i{4, 4})); + CORRADE_COMPARE(a.data(), data); + CORRADE_COMPARE(a.data().size(), 8); + } + + /* Manual properties not implemented yet */ +} + +void ImageTest::constructInvalidSize() { + std::ostringstream out; + Error redirectError{&out}; + + /* Doesn't consider alignment */ + Image2D{PixelFormat::RGB8Unorm, {1, 3}, Containers::Array{3*3}}; + CORRADE_COMPARE(out.str(), "Image::Image(): data too small, got 9 but expected at least 12 bytes\n"); +} + +void ImageTest::constructCompressedInvalidSize() { + CORRADE_EXPECT_FAIL("Size checking for compressed image data is not implemented yet."); + + /* Too small for given format */ + { + std::ostringstream out; + Error redirectError{&out}; + CompressedImage2D{CompressedPixelFormat::Bc2RGBAUnorm, {4, 4}, Containers::Array{2}}; + CORRADE_COMPARE(out.str(), "CompressedImage::CompressedImage(): data too small, got 2 but expected at least 4 bytes\n"); + + /* Size should be rounded up even if the image size is not full block */ + } { + std::ostringstream out; + Error redirectError{&out}; + CompressedImage2D{CompressedPixelFormat::Bc2RGBAUnorm, {2, 2}, Containers::Array{2}}; + CORRADE_COMPARE(out.str(), "CompressedImage::CompressedImage(): data too small, got 2 but expected at least 4 bytes\n"); + } } void ImageTest::constructCopy() { @@ -99,106 +406,209 @@ void ImageTest::constructCopyCompressed() { CORRADE_VERIFY(!(std::is_assignable{})); } -void ImageTest::constructMove() { - auto data = new char[3*3]; +void ImageTest::constructMoveGeneric() { + auto data = new char[3*16]; Image2D a{PixelStorage{}.setAlignment(1), - PixelFormat::RGB, PixelType::UnsignedByte, {1, 3}, Containers::Array{data, 3*3}}; + PixelFormat::RGBA32F, {1, 3}, Containers::Array{data, 3*16}}; Image2D b(std::move(a)); CORRADE_COMPARE(a.data(), nullptr); - CORRADE_COMPARE(a.size(), Vector2i()); + CORRADE_COMPARE(a.size(), Vector2i{}); + + CORRADE_COMPARE(b.storage().alignment(), 1); + CORRADE_COMPARE(b.format(), PixelFormat::RGBA32F); + CORRADE_COMPARE(b.formatExtra(), 0); + CORRADE_COMPARE(b.pixelSize(), 16); + CORRADE_COMPARE(b.size(), (Vector2i{1, 3})); + CORRADE_COMPARE(b.data(), data); + CORRADE_COMPARE(b.data().size(), 3*16); + + auto data2 = new char[24]; + Image2D c{PixelFormat::R8I, {2, 6}, Containers::Array{data2, 24}}; + c = std::move(b); + + CORRADE_COMPARE(b.data(), data2); + CORRADE_COMPARE(b.size(), (Vector2i{2, 6})); + + CORRADE_COMPARE(c.storage().alignment(), 1); + CORRADE_COMPARE(c.format(), PixelFormat::RGBA32F); + CORRADE_COMPARE(c.formatExtra(), 0); + CORRADE_COMPARE(c.pixelSize(), 16); + CORRADE_COMPARE(c.size(), (Vector2i{1, 3})); + CORRADE_COMPARE(c.data(), data); + CORRADE_COMPARE(c.data().size(), 3*16); +} + +void ImageTest::constructMoveImplementationSpecific() { + auto data = new char[3*6]; + Image2D a{PixelStorage{}.setAlignment(1), + GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, Containers::Array{data, 3*6}}; + Image2D b(std::move(a)); + + CORRADE_COMPARE(a.data(), nullptr); + CORRADE_COMPARE(a.size(), Vector2i{}); CORRADE_COMPARE(b.storage().alignment(), 1); - CORRADE_COMPARE(b.format(), PixelFormat::RGB); - CORRADE_COMPARE(b.type(), PixelType::UnsignedByte); - CORRADE_COMPARE(b.size(), Vector2i(1, 3)); + CORRADE_COMPARE(b.format(), pixelFormatWrap(GL::PixelFormat::RGB)); + CORRADE_COMPARE(b.formatExtra(), 1337); + CORRADE_COMPARE(b.pixelSize(), 6); + CORRADE_COMPARE(b.size(), (Vector2i{1, 3})); CORRADE_COMPARE(b.data(), data); + CORRADE_COMPARE(b.data().size(), 3*6); auto data2 = new char[12*4*2]; - Image2D c{PixelFormat::RGBA, PixelType::UnsignedShort, {2, 6}, Containers::Array{data2, 12*4*2}}; + Image2D c{PixelStorage{}, + 1, 2, 8, {2, 6}, Containers::Array{data2, 12*4*2}}; c = std::move(b); CORRADE_COMPARE(b.data(), data2); CORRADE_COMPARE(b.size(), Vector2i(2, 6)); CORRADE_COMPARE(c.storage().alignment(), 1); - CORRADE_COMPARE(c.format(), PixelFormat::RGB); - CORRADE_COMPARE(c.type(), PixelType::UnsignedByte); - CORRADE_COMPARE(c.size(), Vector2i(1, 3)); + CORRADE_COMPARE(c.format(), pixelFormatWrap(GL::PixelFormat::RGB)); + CORRADE_COMPARE(c.formatExtra(), 1337); + CORRADE_COMPARE(c.pixelSize(), 6); + CORRADE_COMPARE(c.size(), (Vector2i{1, 3})); CORRADE_COMPARE(c.data(), data); + CORRADE_COMPARE(c.data().size(), 3*6); } -void ImageTest::constructMoveCompressed() { +void ImageTest::constructMoveCompressedGeneric() { auto data = new char[8]; - CompressedImage2D a{CompressedPixelFormat::RGBAS3tcDxt1, {4, 4}, Containers::Array{data, 8}}; + CompressedImage2D a{ + CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}), + CompressedPixelFormat::Bc3RGBAUnorm, {4, 4}, Containers::Array{data, 8}}; CompressedImage2D b{std::move(a)}; CORRADE_COMPARE(a.data(), nullptr); - CORRADE_COMPARE(a.size(), Vector2i()); + CORRADE_COMPARE(a.size(), Vector2i{}); - #ifndef MAGNUM_TARGET_GLES - CORRADE_COMPARE(b.storage().compressedBlockSize(), Vector3i{0}); - #endif - CORRADE_COMPARE(b.format(), CompressedPixelFormat::RGBAS3tcDxt1); - CORRADE_COMPARE(b.size(), Vector2i(4, 4)); + CORRADE_COMPARE(b.storage().compressedBlockSize(), Vector3i{4}); + CORRADE_COMPARE(b.format(), CompressedPixelFormat::Bc3RGBAUnorm); + CORRADE_COMPARE(b.size(), (Vector2i{4, 4})); CORRADE_COMPARE(b.data(), data); CORRADE_COMPARE(b.data().size(), 8); auto data2 = new char[16]; - CompressedImage2D c{ - #ifndef MAGNUM_TARGET_GLES + CompressedImage2D c{CompressedPixelFormat::Bc1RGBAUnorm, {8, 4}, Containers::Array{data2, 16}}; + c = std::move(b); + + CORRADE_COMPARE(b.data(), data2); + CORRADE_COMPARE(b.size(), (Vector2i{8, 4})); + + CORRADE_COMPARE(c.storage().compressedBlockSize(), Vector3i{4}); + CORRADE_COMPARE(c.format(), CompressedPixelFormat::Bc3RGBAUnorm); + CORRADE_COMPARE(c.size(), (Vector2i{4, 4})); + CORRADE_COMPARE(c.data(), data); + CORRADE_COMPARE(c.data().size(), 8); +} + +void ImageTest::constructMoveCompressedImplementationSpecific() { + auto data = new char[8]; + CompressedImage2D a{ CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}), - #endif - CompressedPixelFormat::RGBAS3tcDxt3, {8, 4}, Containers::Array{data2, 16}}; + GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 4}, Containers::Array{data, 8}}; + CompressedImage2D b{std::move(a)}; + + CORRADE_COMPARE(a.data(), nullptr); + CORRADE_COMPARE(a.size(), Vector2i{}); + + CORRADE_COMPARE(b.storage().compressedBlockSize(), Vector3i{4}); + CORRADE_COMPARE(b.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1)); + CORRADE_COMPARE(b.size(), (Vector2i{4, 4})); + CORRADE_COMPARE(b.data(), data); + CORRADE_COMPARE(b.data().size(), 8); + + auto data2 = new char[16]; + CompressedImage2D c{CompressedPixelFormat::Bc2RGBAUnorm, {8, 4}, Containers::Array{data2, 16}}; c = std::move(b); - CORRADE_COMPARE_AS(b.data(), data2, char*); - CORRADE_COMPARE(b.data().size(), 16); - CORRADE_COMPARE(b.size(), Vector2i(8, 4)); + CORRADE_COMPARE(b.data(), data2); + CORRADE_COMPARE(b.size(), (Vector2i{8, 4})); - #ifndef MAGNUM_TARGET_GLES - CORRADE_COMPARE(c.storage().compressedBlockSize(), Vector3i{0}); - #endif - CORRADE_COMPARE(c.format(), CompressedPixelFormat::RGBAS3tcDxt1); - CORRADE_COMPARE(c.size(), Vector2i(4, 4)); + CORRADE_COMPARE(c.storage().compressedBlockSize(), Vector3i{4}); + CORRADE_COMPARE(c.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1)); + CORRADE_COMPARE(c.size(), (Vector2i{4, 4})); CORRADE_COMPARE(c.data(), data); CORRADE_COMPARE(c.data().size(), 8); } -void ImageTest::toView() { - auto data = new char[3*3]; +void ImageTest::toViewGeneric() { + auto data = new char[3*4]; const Image2D a{PixelStorage{}.setAlignment(1), - PixelFormat::RGB, PixelType::UnsignedByte, {1, 3}, Containers::Array{data, 3*3}}; + PixelFormat::RG16I, {1, 3}, Containers::Array{data, 3*4}}; ImageView2D b = a; CORRADE_COMPARE(b.storage().alignment(), 1); - CORRADE_COMPARE(b.format(), PixelFormat::RGB); - CORRADE_COMPARE(b.type(), PixelType::UnsignedByte); - CORRADE_COMPARE(b.size(), Vector2i(1, 3)); + CORRADE_COMPARE(b.format(), PixelFormat::RG16I); + CORRADE_COMPARE(b.formatExtra(), 0); + CORRADE_COMPARE(b.pixelSize(), 4); + CORRADE_COMPARE(b.size(), (Vector2i{1, 3})); + CORRADE_COMPARE(b.data(), data); +} + +void ImageTest::toViewImplementationSpecific() { + auto data = new char[3*6]; + const Image2D a{PixelStorage{}.setAlignment(1), + GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, Containers::Array{data, 3*6}}; + ImageView2D b = a; + + CORRADE_COMPARE(b.storage().alignment(), 1); + CORRADE_COMPARE(b.format(), pixelFormatWrap(GL::PixelFormat::RGB)); + CORRADE_COMPARE(b.formatExtra(), 1337); + CORRADE_COMPARE(b.pixelSize(), 6); + CORRADE_COMPARE(b.size(), (Vector2i{1, 3})); + CORRADE_COMPARE(b.data(), data); +} + +void ImageTest::toViewCompressedGeneric() { + auto data = new char[8]; + const CompressedImage2D a{ + CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}), + CompressedPixelFormat::Bc1RGBUnorm, {4, 4}, Containers::Array{data, 8}}; + CompressedImageView2D b = a; + + CORRADE_COMPARE(b.storage().compressedBlockSize(), Vector3i{4}); + CORRADE_COMPARE(b.format(), CompressedPixelFormat::Bc1RGBUnorm); + CORRADE_COMPARE(b.size(), (Vector2i{4, 4})); CORRADE_COMPARE(b.data(), data); + CORRADE_COMPARE(b.data().size(), 8); } -void ImageTest::toViewCompressed() { +void ImageTest::toViewCompressedImplementationSpecific() { auto data = new char[8]; const CompressedImage2D a{ - #ifndef MAGNUM_TARGET_GLES CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}), - #endif - CompressedPixelFormat::RGBAS3tcDxt1, {4, 4}, Containers::Array{data, 8}}; + GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 4}, Containers::Array{data, 8}}; CompressedImageView2D b = a; - #ifndef MAGNUM_TARGET_GLES CORRADE_COMPARE(b.storage().compressedBlockSize(), Vector3i{4}); - #endif - CORRADE_COMPARE(b.format(), CompressedPixelFormat::RGBAS3tcDxt1); - CORRADE_COMPARE(b.size(), Vector2i(4, 4)); + CORRADE_COMPARE(b.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1)); + CORRADE_COMPARE(b.size(), (Vector2i{4, 4})); CORRADE_COMPARE(b.data(), data); CORRADE_COMPARE(b.data().size(), 8); } +void ImageTest::access() { + auto data = new char[4*4]; + Image2D a{PixelFormat::RGBA8Unorm, {1, 3}, Containers::Array{data, 4*4}}; + const Image2D& ca = a; + CORRADE_COMPARE(a.data(), data); + CORRADE_COMPARE(ca.data(), data); +} + +void ImageTest::accessCompressed() { + auto data = new char[8]; + CompressedImage2D a{CompressedPixelFormat::Bc1RGBAUnorm, {4, 4}, + Containers::Array{data, 8}}; + const CompressedImage2D& ca = a; + CORRADE_COMPARE(a.data(), data); + CORRADE_COMPARE(ca.data(), data); +} + void ImageTest::release() { char data[] = {'c', 'a', 'f', 'e'}; - Image2D a(PixelFormat::RGBA, PixelType::UnsignedByte, {1, 1}, Containers::Array{data, 4}); + Image2D a(PixelFormat::RGBA8Unorm, {1, 1}, Containers::Array{data, 4}); const char* const pointer = a.release().release(); CORRADE_COMPARE(pointer, data); @@ -208,7 +618,7 @@ void ImageTest::release() { void ImageTest::releaseCompressed() { char data[8]; - CompressedImage2D a{CompressedPixelFormat::RGBAS3tcDxt1, {4, 4}, Containers::Array{data, 8}}; + CompressedImage2D a{CompressedPixelFormat::Bc1RGBAUnorm, {4, 4}, Containers::Array{data, 8}}; const char* const pointer = a.release().release(); CORRADE_COMPARE(pointer, data); diff --git a/src/Magnum/Test/ImageViewTest.cpp b/src/Magnum/Test/ImageViewTest.cpp index 366acf304..46aec51c7 100644 --- a/src/Magnum/Test/ImageViewTest.cpp +++ b/src/Magnum/Test/ImageViewTest.cpp @@ -23,6 +23,7 @@ DEALINGS IN THE SOFTWARE. */ +#include #include #include "Magnum/ImageView.h" @@ -33,68 +34,467 @@ namespace Magnum { namespace Test { struct ImageViewTest: TestSuite::Tester { explicit ImageViewTest(); - void construct(); - void constructNullptr(); - void constructCompressed(); + void constructGeneric(); + void constructGenericEmpty(); + void constructGenericEmptyNullptr(); + void constructImplementationSpecific(); + void constructImplementationSpecificEmpty(); + void constructImplementationSpecificEmptyNullptr(); + void constructCompressedGeneric(); + void constructCompressedGenericEmpty(); + void constructCompressedImplementationSpecific(); + void constructCompressedImplementationSpecificEmpty(); + + void constructInvalidSize(); + void constructCompressedInvalidSize(); void setData(); void setDataCompressed(); + + void setDataInvalidSize(); + void setDataCompressedInvalidSize(); }; ImageViewTest::ImageViewTest() { - addTests({&ImageViewTest::construct, - &ImageViewTest::constructNullptr, - &ImageViewTest::constructCompressed, + addTests({&ImageViewTest::constructGeneric, + &ImageViewTest::constructGenericEmpty, + &ImageViewTest::constructGenericEmptyNullptr, + &ImageViewTest::constructImplementationSpecific, + &ImageViewTest::constructImplementationSpecificEmpty, + &ImageViewTest::constructImplementationSpecificEmptyNullptr, + &ImageViewTest::constructCompressedGeneric, + &ImageViewTest::constructCompressedGenericEmpty, + &ImageViewTest::constructCompressedImplementationSpecific, + &ImageViewTest::constructCompressedImplementationSpecificEmpty, + + &ImageViewTest::constructInvalidSize, + &ImageViewTest::constructCompressedInvalidSize, &ImageViewTest::setData, - &ImageViewTest::setDataCompressed}); + &ImageViewTest::setDataCompressed, + + &ImageViewTest::setDataInvalidSize, + &ImageViewTest::setDataCompressedInvalidSize}); } -void ImageViewTest::construct() { - const char data[3*3]{}; - ImageView2D a{PixelStorage{}.setAlignment(1), - PixelFormat::RGB, PixelType::UnsignedByte, {1, 3}, data}; +namespace { - CORRADE_COMPARE(a.storage().alignment(), 1); - CORRADE_COMPARE(a.format(), PixelFormat::RGB); - CORRADE_COMPARE(a.type(), PixelType::UnsignedByte); - CORRADE_COMPARE(a.size(), Vector2i(1, 3)); - CORRADE_COMPARE(a.data(), data); +namespace GL { + enum class PixelFormat { RGB = 666 }; + enum class PixelType { UnsignedShort = 1337 }; + UnsignedInt pixelSize(PixelFormat format, PixelType type) { + CORRADE_INTERNAL_ASSERT(format == PixelFormat::RGB); + CORRADE_INTERNAL_ASSERT(type == PixelType::UnsignedShort); + return 6; + } + + enum class CompressedPixelFormat { RGBS3tcDxt1 = 21 }; } -void ImageViewTest::constructNullptr() { - /* Just verify that it won't assert when passing nullptr array -- useful - e.g. for old-style texture allocation using setImage() */ - ImageView2D a{PixelFormat::RGBA, PixelType::UnsignedByte, {256, 128}, nullptr}; - CORRADE_COMPARE(a.size(), (Vector2i{256, 128})); +namespace Vk { + enum class PixelFormat { R32G32B32F = 42 }; + UnsignedInt pixelSize(PixelFormat format) { + CORRADE_INTERNAL_ASSERT(format == PixelFormat::R32G32B32F); + return 12; + } + + enum class CompressedPixelFormat { Bc1SRGBAlpha = 42 }; } -void ImageViewTest::constructCompressed() { - const char data[8]{}; - CompressedImageView2D a{ - #ifndef MAGNUM_TARGET_GLES - CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}), - #endif - CompressedPixelFormat::RGBAS3tcDxt1, {4, 4}, data}; +} - #ifndef MAGNUM_TARGET_GLES - CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{4}); - #endif - CORRADE_COMPARE(a.format(), CompressedPixelFormat::RGBAS3tcDxt1); - CORRADE_COMPARE(a.size(), Vector2i(4, 4)); - CORRADE_COMPARE(a.data(), data); +void ImageViewTest::constructGeneric() { + { + const char data[4*4]{}; + ImageView2D a{PixelFormat::RGBA8Unorm, {1, 3}, data}; + + CORRADE_COMPARE(a.storage().alignment(), 4); + CORRADE_COMPARE(a.format(), PixelFormat::RGBA8Unorm); + CORRADE_COMPARE(a.formatExtra(), 0); + CORRADE_COMPARE(a.pixelSize(), 4); + CORRADE_COMPARE(a.size(), (Vector2i{1, 3})); + CORRADE_COMPARE(a.data(), data); + CORRADE_COMPARE(a.data().size(), 4*4); + } { + const char data[3*2]{}; + ImageView2D a{PixelStorage{}.setAlignment(1), + PixelFormat::R16UI, {1, 3}, data}; + + CORRADE_COMPARE(a.storage().alignment(), 1); + CORRADE_COMPARE(a.format(), PixelFormat::R16UI); + CORRADE_COMPARE(a.formatExtra(), 0); + CORRADE_COMPARE(a.pixelSize(), 2); + CORRADE_COMPARE(a.size(), (Vector2i{1, 3})); + CORRADE_COMPARE(a.data(), data); + CORRADE_COMPARE(a.data().size(), 3*2); + } +} + +void ImageViewTest::constructGenericEmpty() { + { + ImageView2D a{PixelFormat::RG32F, {2, 6}}; + + CORRADE_COMPARE(a.storage().alignment(), 4); + CORRADE_COMPARE(a.format(), PixelFormat::RG32F); + CORRADE_COMPARE(a.formatExtra(), 0); + CORRADE_COMPARE(a.pixelSize(), 8); + CORRADE_COMPARE(a.size(), (Vector2i{2, 6})); + CORRADE_COMPARE(a.data(), nullptr); + } { + ImageView2D a{PixelStorage{}.setAlignment(1), + PixelFormat::RGB16F, {8, 3}}; + + CORRADE_COMPARE(a.storage().alignment(), 1); + CORRADE_COMPARE(a.format(), PixelFormat::RGB16F); + CORRADE_COMPARE(a.formatExtra(), 0); + CORRADE_COMPARE(a.pixelSize(), 6); + CORRADE_COMPARE(a.size(), (Vector2i{8, 3})); + CORRADE_COMPARE(a.data(), nullptr); + } +} + +void ImageViewTest::constructGenericEmptyNullptr() { + /* This should be deprecated/removed, as it doesn't provide anything over + the above and can lead to silent errors */ + + { + ImageView2D a{PixelFormat::RG32F, {2, 6}, nullptr}; + + CORRADE_COMPARE(a.storage().alignment(), 4); + CORRADE_COMPARE(a.format(), PixelFormat::RG32F); + CORRADE_COMPARE(a.formatExtra(), 0); + CORRADE_COMPARE(a.pixelSize(), 8); + CORRADE_COMPARE(a.size(), (Vector2i{2, 6})); + CORRADE_COMPARE(a.data(), nullptr); + } { + ImageView2D a{PixelStorage{}.setAlignment(1), + PixelFormat::RGB16F, {8, 3}, nullptr}; + + CORRADE_COMPARE(a.storage().alignment(), 1); + CORRADE_COMPARE(a.format(), PixelFormat::RGB16F); + CORRADE_COMPARE(a.formatExtra(), 0); + CORRADE_COMPARE(a.pixelSize(), 6); + CORRADE_COMPARE(a.size(), (Vector2i{8, 3})); + CORRADE_COMPARE(a.data(), nullptr); + } +} + +void ImageViewTest::constructImplementationSpecific() { + /* Single format */ + { + const char data[3*12]{}; + ImageView2D a{Vk::PixelFormat::R32G32B32F, {1, 3}, data}; + + CORRADE_COMPARE(a.storage().alignment(), 4); + CORRADE_COMPARE(a.format(), pixelFormatWrap(Vk::PixelFormat::R32G32B32F)); + CORRADE_COMPARE(a.formatExtra(), 0); + CORRADE_COMPARE(a.pixelSize(), 12); + CORRADE_COMPARE(a.size(), (Vector2i{1, 3})); + CORRADE_COMPARE(a.data(), data); + CORRADE_COMPARE(a.data().size(), 3*12); + } { + const char data[3*12]{}; + ImageView2D a{PixelStorage{}.setAlignment(1), + Vk::PixelFormat::R32G32B32F, {1, 3}, data}; + + CORRADE_COMPARE(a.storage().alignment(), 1); + CORRADE_COMPARE(a.format(), pixelFormatWrap(Vk::PixelFormat::R32G32B32F)); + CORRADE_COMPARE(a.formatExtra(), 0); + CORRADE_COMPARE(a.pixelSize(), 12); + CORRADE_COMPARE(a.size(), (Vector2i{1, 3})); + CORRADE_COMPARE(a.data(), data); + CORRADE_COMPARE(a.data().size(), 3*12); + } + + /* Format + extra */ + { + const char data[3*8]{}; + ImageView2D a{GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, data}; + + CORRADE_COMPARE(a.storage().alignment(), 4); + CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB)); + CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort)); + CORRADE_COMPARE(a.pixelSize(), 6); + CORRADE_COMPARE(a.size(), Vector2i(1, 3)); + CORRADE_COMPARE(a.data(), data); + CORRADE_COMPARE(a.data().size(), 3*8); + } { + const char data[3*6]{}; + ImageView2D a{PixelStorage{}.setAlignment(1), + GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, data}; + + CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB)); + CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort)); + CORRADE_COMPARE(a.pixelSize(), 6); + CORRADE_COMPARE(a.size(), Vector2i(1, 3)); + CORRADE_COMPARE(a.data(), data); + CORRADE_COMPARE(a.data().size(), 3*6); + } + + /* Manual pixel size */ + { + const char data[3*6]{}; + ImageView2D a{PixelStorage{}.setAlignment(1), 666, 1337, 6, {1, 3}, data}; + + CORRADE_COMPARE(a.storage().alignment(), 1); + CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB)); + CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort)); + CORRADE_COMPARE(a.pixelSize(), 6); + CORRADE_COMPARE(a.size(), Vector2i(1, 3)); + CORRADE_COMPARE(a.data(), data); + CORRADE_COMPARE(a.data().size(), 3*6); + } +} + +void ImageViewTest::constructImplementationSpecificEmpty() { + /* Single format */ + { + ImageView2D a{Vk::PixelFormat::R32G32B32F, {2, 16}}; + + CORRADE_COMPARE(a.storage().alignment(), 4); + CORRADE_COMPARE(a.format(), pixelFormatWrap(Vk::PixelFormat::R32G32B32F)); + CORRADE_COMPARE(a.formatExtra(), 0); + CORRADE_COMPARE(a.pixelSize(), 12); + CORRADE_COMPARE(a.size(), (Vector2i{2, 16})); + CORRADE_COMPARE(a.data(), nullptr); + } { + ImageView2D a{PixelStorage{}.setAlignment(1), + Vk::PixelFormat::R32G32B32F, {1, 2}}; + + CORRADE_COMPARE(a.storage().alignment(), 1); + CORRADE_COMPARE(a.format(), pixelFormatWrap(Vk::PixelFormat::R32G32B32F)); + CORRADE_COMPARE(a.formatExtra(), 0); + CORRADE_COMPARE(a.pixelSize(), 12); + CORRADE_COMPARE(a.size(), (Vector2i{1, 2})); + CORRADE_COMPARE(a.data(), nullptr); + } + + /* Format + extra */ + { + ImageView2D a{GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}}; + + CORRADE_COMPARE(a.storage().alignment(), 4); + CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB)); + CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort)); + CORRADE_COMPARE(a.pixelSize(), 6); + CORRADE_COMPARE(a.size(), (Vector2i{1, 3})); + CORRADE_COMPARE(a.data(), nullptr); + } { + ImageView2D a{PixelStorage{}.setAlignment(1), + GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {8, 2}}; + + CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB)); + CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort)); + CORRADE_COMPARE(a.pixelSize(), 6); + CORRADE_COMPARE(a.size(), (Vector2i{8, 2})); + CORRADE_COMPARE(a.data(), nullptr); + } + + /* Manual pixel size */ + { + ImageView2D a{PixelStorage{}.setAlignment(1), 666, 1337, 6, {3, 3}}; + + CORRADE_COMPARE(a.storage().alignment(), 1); + CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB)); + CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort)); + CORRADE_COMPARE(a.pixelSize(), 6); + CORRADE_COMPARE(a.size(), (Vector2i{3, 3})); + CORRADE_COMPARE(a.data(), nullptr); + } +} + +void ImageViewTest::constructImplementationSpecificEmptyNullptr() { + /* This should be deprecated/removed, as it doesn't provide anything over + the above and can lead to silent errors */ + + /* Single format */ + { + ImageView2D a{Vk::PixelFormat::R32G32B32F, {2, 16}, nullptr}; + + CORRADE_COMPARE(a.storage().alignment(), 4); + CORRADE_COMPARE(a.format(), pixelFormatWrap(Vk::PixelFormat::R32G32B32F)); + CORRADE_COMPARE(a.formatExtra(), 0); + CORRADE_COMPARE(a.pixelSize(), 12); + CORRADE_COMPARE(a.size(), (Vector2i{2, 16})); + CORRADE_COMPARE(a.data(), nullptr); + } { + ImageView2D a{PixelStorage{}.setAlignment(1), + Vk::PixelFormat::R32G32B32F, {1, 2}, nullptr}; + + CORRADE_COMPARE(a.storage().alignment(), 1); + CORRADE_COMPARE(a.format(), pixelFormatWrap(Vk::PixelFormat::R32G32B32F)); + CORRADE_COMPARE(a.formatExtra(), 0); + CORRADE_COMPARE(a.pixelSize(), 12); + CORRADE_COMPARE(a.size(), (Vector2i{1, 2})); + CORRADE_COMPARE(a.data(), nullptr); + } + + /* Format + extra */ + { + ImageView2D a{GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, nullptr}; + + CORRADE_COMPARE(a.storage().alignment(), 4); + CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB)); + CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort)); + CORRADE_COMPARE(a.pixelSize(), 6); + CORRADE_COMPARE(a.size(), (Vector2i{1, 3})); + CORRADE_COMPARE(a.data(), nullptr); + } { + ImageView2D a{PixelStorage{}.setAlignment(1), + GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {8, 2}, nullptr}; + + CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB)); + CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort)); + CORRADE_COMPARE(a.pixelSize(), 6); + CORRADE_COMPARE(a.size(), (Vector2i{8, 2})); + CORRADE_COMPARE(a.data(), nullptr); + } + + /* Manual pixel size */ + { + ImageView2D a{PixelStorage{}.setAlignment(1), 666, 1337, 6, {3, 3}, nullptr}; + + CORRADE_COMPARE(a.storage().alignment(), 1); + CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB)); + CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort)); + CORRADE_COMPARE(a.pixelSize(), 6); + CORRADE_COMPARE(a.size(), (Vector2i{3, 3})); + CORRADE_COMPARE(a.data(), nullptr); + } +} + +void ImageViewTest::constructCompressedGeneric() { + { + const char data[8]{}; + CompressedImageView2D a{CompressedPixelFormat::Bc1RGBAUnorm, {4, 4}, data}; + + CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{0}); + CORRADE_COMPARE(a.format(), CompressedPixelFormat::Bc1RGBAUnorm); + CORRADE_COMPARE(a.size(), (Vector2i{4, 4})); + CORRADE_COMPARE(a.data(), data); + CORRADE_COMPARE(a.data().size(), 8); + } { + const char data[8]{}; + CompressedImageView2D a{CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}), + CompressedPixelFormat::Bc1RGBAUnorm, {4, 4}, + data}; + + CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{4}); + CORRADE_COMPARE(a.format(), CompressedPixelFormat::Bc1RGBAUnorm); + CORRADE_COMPARE(a.size(), (Vector2i{4, 4})); + CORRADE_COMPARE(a.data(), data); + CORRADE_COMPARE(a.data().size(), 8); + } +} + +void ImageViewTest::constructCompressedGenericEmpty() { + { + CompressedImageView2D a{CompressedPixelFormat::Bc1RGBAUnorm, {8, 16}}; + + CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{0}); + CORRADE_COMPARE(a.format(), CompressedPixelFormat::Bc1RGBAUnorm); + CORRADE_COMPARE(a.size(), (Vector2i{8, 16})); + CORRADE_COMPARE(a.data(), nullptr); + } { + CompressedImageView2D a{CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}), + CompressedPixelFormat::Bc1RGBAUnorm, {8, 16}}; + + CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{4}); + CORRADE_COMPARE(a.format(), CompressedPixelFormat::Bc1RGBAUnorm); + CORRADE_COMPARE(a.size(), (Vector2i{8, 16})); + CORRADE_COMPARE(a.data(), nullptr); + } +} + +void ImageViewTest::constructCompressedImplementationSpecific() { + /* Format with autodetection */ + { + const char data[8]{}; + CompressedImageView2D a{GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 4}, + data}; + + CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{0}); + CORRADE_COMPARE(a.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1)); + CORRADE_COMPARE(a.size(), (Vector2i{4, 4})); + CORRADE_COMPARE(a.data(), data); + CORRADE_COMPARE(a.data().size(), 8); + } { + const char data[8]{}; + CompressedImageView2D a{CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}), + GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 4}, data}; + + CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{4}); + CORRADE_COMPARE(a.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1)); + CORRADE_COMPARE(a.size(), (Vector2i{4, 4})); + CORRADE_COMPARE(a.data(), data); + CORRADE_COMPARE(a.data().size(), 8); + } + + /* Manual properties not implemented yet */ +} + +void ImageViewTest::constructCompressedImplementationSpecificEmpty() { + /* Format with autodetection */ + { + CompressedImageView2D a{GL::CompressedPixelFormat::RGBS3tcDxt1, {8, 16}}; + + CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{0}); + CORRADE_COMPARE(a.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1)); + CORRADE_COMPARE(a.size(), (Vector2i{8, 16})); + CORRADE_COMPARE(a.data(), nullptr); + } { + CompressedImageView2D a{CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}), + GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 8}}; + + CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{4}); + CORRADE_COMPARE(a.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1)); + CORRADE_COMPARE(a.size(), (Vector2i{4, 8})); + CORRADE_COMPARE(a.data(), nullptr); + } + + /* Manual properties not implemented yet */ +} + +void ImageViewTest::constructInvalidSize() { + std::ostringstream out; + Error redirectError{&out}; + + /* Doesn't consider alignment */ + const char data[3*3]{}; + ImageView2D{PixelFormat::RGB8Unorm, {1, 3}, data}; + CORRADE_COMPARE(out.str(), "ImageView::ImageView(): data too small, got 9 but expected at least 12 bytes\n"); +} + +void ImageViewTest::constructCompressedInvalidSize() { + CORRADE_EXPECT_FAIL("Size checking for compressed image data is not implemented yet."); + + const char data[2]{}; + + /* Too small for given format */ + { + std::ostringstream out; + Error redirectError{&out}; + CompressedImageView2D{CompressedPixelFormat::Bc2RGBAUnorm, {4, 4}, data}; + CORRADE_COMPARE(out.str(), "CompressedImageView::CompressedImageView(): data too small, got 2 but expected at least 4 bytes\n"); + + /* Size should be rounded up even if the image size is not full block */ + } { + std::ostringstream out; + Error redirectError{&out}; + CompressedImageView2D{CompressedPixelFormat::Bc2RGBAUnorm, {2, 2}, data}; + CORRADE_COMPARE(out.str(), "CompressedImageView::CompressedImageView(): data too small, got 2 but expected at least 4 bytes\n"); + } } void ImageViewTest::setData() { const char data[3*3]{}; ImageView2D a{PixelStorage{}.setAlignment(1), - PixelFormat::RGB, PixelType::UnsignedByte, {1, 3}, data}; + PixelFormat::RGB8Snorm, {1, 3}, data}; const char data2[3*3]{}; a.setData(data2); CORRADE_COMPARE(a.storage().alignment(), 1); - CORRADE_COMPARE(a.format(), PixelFormat::RGB); - CORRADE_COMPARE(a.type(), PixelType::UnsignedByte); + CORRADE_COMPARE(a.format(), PixelFormat::RGB8Snorm); CORRADE_COMPARE(a.size(), Vector2i(1, 3)); CORRADE_COMPARE(a.data(), data2); } @@ -102,21 +502,50 @@ void ImageViewTest::setData() { void ImageViewTest::setDataCompressed() { const char data[8]{}; CompressedImageView2D a{ - #ifndef MAGNUM_TARGET_GLES CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}), - #endif - CompressedPixelFormat::RGBAS3tcDxt1, {4, 4}, data}; + CompressedPixelFormat::Bc1RGBAUnorm, {4, 4}, data}; const char data2[16]{}; a.setData(data2); - #ifndef MAGNUM_TARGET_GLES CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{4}); - #endif - CORRADE_COMPARE(a.format(), CompressedPixelFormat::RGBAS3tcDxt1); + CORRADE_COMPARE(a.format(), CompressedPixelFormat::Bc1RGBAUnorm); CORRADE_COMPARE(a.size(), Vector2i(4, 4)); CORRADE_COMPARE(a.data(), data2); } +void ImageViewTest::setDataInvalidSize() { + std::ostringstream out; + Error redirectError{&out}; + + ImageView2D image{PixelFormat::RGB8Unorm, {1, 3}}; + const char data[3*3]{}; + + /* Doesn't consider alignment */ + image.setData(data); + CORRADE_COMPARE(out.str(), "ImageView::setData(): data too small, got 9 but expected at least 12 bytes\n"); +} + +void ImageViewTest::setDataCompressedInvalidSize() { + CORRADE_EXPECT_FAIL("Size checking for compressed image data is not implemented yet."); + + const char data[2]{}; + + /* Too small for given format */ + { + std::ostringstream out; + Error redirectError{&out}; + CompressedImageView2D{CompressedPixelFormat::Bc2RGBAUnorm, {4, 4}, data}; + CORRADE_COMPARE(out.str(), "CompressedImageView::setData(): data too small, got 2 but expected at least 4 bytes\n"); + + /* Size should be rounded up even if the image size is not that big */ + } { + std::ostringstream out; + Error redirectError{&out}; + CompressedImageView2D{CompressedPixelFormat::Bc2RGBAUnorm, {2, 2}, data}; + CORRADE_COMPARE(out.str(), "CompressedImageView::setData(): data too small, got 2 but expected at least 4 bytes\n"); + } +} + }} CORRADE_TEST_MAIN(Magnum::Test::ImageViewTest) diff --git a/src/Magnum/Test/PixelStorageTest.cpp b/src/Magnum/Test/PixelStorageTest.cpp index 430bd9d15..261ae6aa3 100644 --- a/src/Magnum/Test/PixelStorageTest.cpp +++ b/src/Magnum/Test/PixelStorageTest.cpp @@ -34,103 +34,63 @@ namespace Magnum { namespace Test { struct PixelStorageTest: TestSuite::Tester { explicit PixelStorageTest(); - void pixelSize(); - void compare(); - #ifndef MAGNUM_TARGET_GLES void compareCompressed(); - #endif void dataProperties(); void dataPropertiesAlignment(); - #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) void dataPropertiesRowLength(); - #endif - #ifndef MAGNUM_TARGET_GLES2 void dataPropertiesImageHeight(); - #endif void dataSize1D(); void dataSize2D(); void dataSize3D(); - #ifndef MAGNUM_TARGET_GLES void dataPropertiesCompressed(); void dataPropertiesCompressedRowLength(); void dataPropertiesCompressedImageHeight(); void dataOffsetSizeCompressed(); - #endif }; typedef Math::Vector3 Vector3st; PixelStorageTest::PixelStorageTest() { - addTests({&PixelStorageTest::pixelSize, - - &PixelStorageTest::compare, - #ifndef MAGNUM_TARGET_GLES + addTests({&PixelStorageTest::compare, &PixelStorageTest::compareCompressed, - #endif &PixelStorageTest::dataProperties, &PixelStorageTest::dataPropertiesAlignment, - #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) &PixelStorageTest::dataPropertiesRowLength, - #endif - #ifndef MAGNUM_TARGET_GLES2 &PixelStorageTest::dataPropertiesImageHeight, - #endif &PixelStorageTest::dataSize1D, &PixelStorageTest::dataSize2D, &PixelStorageTest::dataSize3D, - #ifndef MAGNUM_TARGET_GLES &PixelStorageTest::dataPropertiesCompressed, &PixelStorageTest::dataPropertiesCompressedRowLength, &PixelStorageTest::dataPropertiesCompressedImageHeight, - &PixelStorageTest::dataOffsetSizeCompressed - #endif - }); -} - -void PixelStorageTest::pixelSize() { - CORRADE_COMPARE(PixelStorage::pixelSize(PixelFormat::RGBA, PixelType::UnsignedInt), 4*4); - CORRADE_COMPARE(PixelStorage::pixelSize(PixelFormat::DepthComponent, PixelType::UnsignedShort), 2); - #ifndef MAGNUM_TARGET_WEBGL - CORRADE_COMPARE(PixelStorage::pixelSize(PixelFormat::StencilIndex, PixelType::UnsignedByte), 1); - #endif - CORRADE_COMPARE(PixelStorage::pixelSize(PixelFormat::DepthStencil, PixelType::UnsignedInt248), 4); + &PixelStorageTest::dataOffsetSizeCompressed}); } void PixelStorageTest::compare() { PixelStorage a; - a - #if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) - .setRowLength(1) - #endif - #ifndef MAGNUM_TARGET_GLES2 + a.setRowLength(1) .setImageHeight(15) - #endif .setSkip({1, 3, 4}) .setAlignment(3); CORRADE_VERIFY(a == a); CORRADE_VERIFY(a != PixelStorage{}); CORRADE_VERIFY(PixelStorage{} == PixelStorage{}); - #if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) CORRADE_VERIFY(PixelStorage{}.setRowLength(15) != PixelStorage{}.setRowLength(17)); - #endif - #ifndef MAGNUM_TARGET_GLES2 CORRADE_VERIFY(PixelStorage{}.setImageHeight(32) != PixelStorage{}.setImageHeight(31)); - #endif CORRADE_VERIFY(PixelStorage{}.setSkip({1, 5, 7}) != PixelStorage{}.setSkip({7, 1, 5})); CORRADE_VERIFY(PixelStorage{}.setAlignment(3) != PixelStorage{}.setAlignment(5)); } -#ifndef MAGNUM_TARGET_GLES void PixelStorageTest::compareCompressed() { CompressedPixelStorage a; a.setSkip({16, 2, 1}) @@ -144,24 +104,21 @@ void PixelStorageTest::compareCompressed() { CORRADE_VERIFY(CompressedPixelStorage{}.setCompressedBlockSize({2, 7, 19}) != CompressedPixelStorage{}.setCompressedBlockSize({2, 7, 16})); CORRADE_VERIFY(CompressedPixelStorage{}.setCompressedBlockDataSize(32) != CompressedPixelStorage{}.setCompressedBlockDataSize(30)); } -#endif void PixelStorageTest::dataProperties() { PixelStorage storage; storage.setAlignment(1); - CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{0}), - (std::tuple{{}, {0, 0, 0}, 4})); - CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{1}), - (std::tuple{{}, {4, 1, 1}, 4})); - #if !defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2) - CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {8, 2, 1}), - (std::tuple{{}, {8, 2, 1}, 1})); - CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {2, 4, 1}), - (std::tuple{{}, {2, 4, 1}, 1})); - CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {2, 4, 6}), - (std::tuple{{}, {2, 4, 6}, 1})); - #endif + CORRADE_COMPARE(storage.dataProperties(pixelSize(PixelFormat::RGBA8Unorm), Vector3i{0}), + (std::pair{{}, {0, 0, 0}})); + CORRADE_COMPARE(storage.dataProperties(pixelSize(PixelFormat::RGBA8Unorm), Vector3i{1}), + (std::pair{{}, {4, 1, 1}})); + CORRADE_COMPARE(storage.dataProperties(pixelSize(PixelFormat::R8Unorm), {8, 2, 1}), + (std::pair{{}, {8, 2, 1}})); + CORRADE_COMPARE(storage.dataProperties(pixelSize(PixelFormat::R8Unorm), {2, 4, 1}), + (std::pair{{}, {2, 4, 1}})); + CORRADE_COMPARE(storage.dataProperties(pixelSize(PixelFormat::R8Unorm), {2, 4, 6}), + (std::pair{{}, {2, 4, 6}})); } void PixelStorageTest::dataPropertiesAlignment() { @@ -169,144 +126,120 @@ void PixelStorageTest::dataPropertiesAlignment() { storage.setAlignment(8) .setSkip({3, 2, 1}); - CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{0}), - (std::tuple{{3*4, 0, 0}, {0, 0, 0}, 4})); - CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{1}), - (std::tuple{{12, 16, 8}, {8, 1, 1}, 4})); - #if !defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2) - CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {8, 2, 1}), - (std::tuple{{3, 16, 16}, {8, 2, 1}, 1})); - CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {2, 4, 1}), - (std::tuple{{3, 16, 32}, {8, 4, 1}, 1})); - CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {2, 4, 6}), - (std::tuple{{3, 16, 32}, {8, 4, 6}, 1})); - #endif + CORRADE_COMPARE(storage.dataProperties(pixelSize(PixelFormat::RGBA8Unorm), Vector3i{0}), + (std::pair{{3*4, 0, 0}, {0, 0, 0}})); + CORRADE_COMPARE(storage.dataProperties(pixelSize(PixelFormat::RGBA8Unorm), Vector3i{1}), + (std::pair{{12, 16, 8}, {8, 1, 1}})); + CORRADE_COMPARE(storage.dataProperties(pixelSize(PixelFormat::R8Unorm), {8, 2, 1}), + (std::pair{{3, 16, 16}, {8, 2, 1}})); + CORRADE_COMPARE(storage.dataProperties(pixelSize(PixelFormat::R8Unorm), {2, 4, 1}), + (std::pair{{3, 16, 32}, {8, 4, 1}})); + CORRADE_COMPARE(storage.dataProperties(pixelSize(PixelFormat::R8Unorm), {2, 4, 6}), + (std::pair{{3, 16, 32}, {8, 4, 6}})); } -#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) void PixelStorageTest::dataPropertiesRowLength() { PixelStorage storage; storage.setAlignment(4) .setRowLength(15) .setSkip({3, 7, 0}); - CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{0}), - (std::tuple{{3*4, 7*15*4, 0}, {0, 0, 0}, 4})); - CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{1}), - (std::tuple{{3*4, 7*15*4, 0}, {60, 1, 1}, 4})); - CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {4, 2, 1}), - (std::tuple{{3, 7*16, 0}, {16, 2, 1}, 1})); - CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {2, 4, 1}), - (std::tuple{{3, 7*16, 0}, {16, 4, 1}, 1})); - CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {2, 4, 6}), - (std::tuple{{3, 7*16, 0}, {16, 4, 6}, 1})); + CORRADE_COMPARE(storage.dataProperties(pixelSize(PixelFormat::RGBA8Unorm), Vector3i{0}), + (std::pair{{3*4, 7*15*4, 0}, {0, 0, 0}})); + CORRADE_COMPARE(storage.dataProperties(pixelSize(PixelFormat::RGBA8Unorm), Vector3i{1}), + (std::pair{{3*4, 7*15*4, 0}, {60, 1, 1}})); + CORRADE_COMPARE(storage.dataProperties(pixelSize(PixelFormat::R8Unorm), {4, 2, 1}), + (std::pair{{3, 7*16, 0}, {16, 2, 1}})); + CORRADE_COMPARE(storage.dataProperties(pixelSize(PixelFormat::R8Unorm), {2, 4, 1}), + (std::pair{{3, 7*16, 0}, {16, 4, 1}})); + CORRADE_COMPARE(storage.dataProperties(pixelSize(PixelFormat::R8Unorm), {2, 4, 6}), + (std::pair{{3, 7*16, 0}, {16, 4, 6}})); } -#endif -#ifndef MAGNUM_TARGET_GLES2 void PixelStorageTest::dataPropertiesImageHeight() { PixelStorage storage; storage.setAlignment(1) .setImageHeight(128) .setSkip({3, 7, 2}); - CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{0}), - (std::tuple{{3*4, 0, 0}, {0, 0, 0}, 4})); - CORRADE_COMPARE(storage.dataProperties(PixelFormat::RGBA, PixelType::UnsignedByte, Vector3i{1}), - (std::tuple{{3*4, 7*1*4, 2*128*1*4}, {4, 128, 1}, 4})); - CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {4, 2, 1}), - (std::tuple{{3, 7*1*4, 2*128*4}, {4, 128, 1}, 1})); - CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {2, 4, 1}), - (std::tuple{{3, 7*1*2, 2*128*2}, {2, 128, 1}, 1})); - CORRADE_COMPARE(storage.dataProperties(PixelFormat::Red, PixelType::UnsignedByte, {2, 4, 6}), - (std::tuple{{3, 7*1*2, 2*128*2}, {2, 128, 6}, 1})); + CORRADE_COMPARE(storage.dataProperties(pixelSize(PixelFormat::RGBA8Unorm), Vector3i{0}), + (std::pair{{3*4, 0, 0}, {0, 0, 0}})); + CORRADE_COMPARE(storage.dataProperties(pixelSize(PixelFormat::RGBA8Unorm), Vector3i{1}), + (std::pair{{3*4, 7*1*4, 2*128*1*4}, {4, 128, 1}})); + CORRADE_COMPARE(storage.dataProperties(pixelSize(PixelFormat::R8Unorm), {4, 2, 1}), + (std::pair{{3, 7*1*4, 2*128*4}, {4, 128, 1}})); + CORRADE_COMPARE(storage.dataProperties(pixelSize(PixelFormat::R8Unorm), {2, 4, 1}), + (std::pair{{3, 7*1*2, 2*128*2}, {2, 128, 1}})); + CORRADE_COMPARE(storage.dataProperties(pixelSize(PixelFormat::R8Unorm), {2, 4, 6}), + (std::pair{{3, 7*1*2, 2*128*2}, {2, 128, 6}})); } -#endif void PixelStorageTest::dataSize1D() { - const Image1D image{PixelStorage{}.setAlignment(2) - .setSkip({2, 0, 0}), - PixelFormat::RGB, PixelType::UnsignedByte}; + const Image1D image{ + PixelStorage{}.setAlignment(2).setSkip({2, 0, 0}), + PixelFormat::RGB8Unorm}; CORRADE_COMPARE(Implementation::imageDataSizeFor(image, Math::Vector<1, Int>{3}), 16); } void PixelStorageTest::dataSize2D() { - const Image2D image{PixelStorage{}.setAlignment(2) - #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) - .setRowLength(7) - #endif - .setSkip({2, 3, 0}), - PixelFormat::RGB, PixelType::UnsignedByte}; - - #if defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2) - CORRADE_COMPARE(Implementation::imageDataSizeFor(image, Vector2i{5, 9}), - (3 + 9)*16); - #else + const Image2D image{ + PixelStorage{}.setAlignment(2) + .setRowLength(7) + .setSkip({2, 3, 0}), + PixelFormat::RGB8Unorm}; + CORRADE_COMPARE(Implementation::imageDataSizeFor(image, Vector2i{5, 9}), (3 + 9)*22); - #endif - #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) /* This shouldn't overflow the 128x128 rectangle */ - const Image2D image2{PixelStorage{}.setSkip({64, 0, 0}) - .setRowLength(128), - PixelFormat::RGBA, PixelType::UnsignedByte}; + const Image2D image2{ + PixelStorage{}.setSkip({64, 0, 0}) + .setRowLength(128), + PixelFormat::RGBA8Unorm}; CORRADE_COMPARE(Implementation::imageDataSizeFor(image2, Vector2i{64, 128}), 65536); /* This shouldn't overflow the 128x128 rectangle */ - const Image2D image3{PixelStorage{}.setSkip({64, 64, 0}) - .setRowLength(128), - PixelFormat::RGBA, PixelType::UnsignedByte}; + const Image2D image3{ + PixelStorage{}.setSkip({64, 64, 0}) + .setRowLength(128), + PixelFormat::RGBA8Unorm}; CORRADE_COMPARE(Implementation::imageDataSizeFor(image3, Vector2i{64, 64}), 65536); - #endif } void PixelStorageTest::dataSize3D() { - const Image3D image{PixelStorage{}.setAlignment(2) - #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) - .setRowLength(7) - #endif - #ifndef MAGNUM_TARGET_GLES2 - .setImageHeight(10) - #endif - .setSkip({2, 3, 1}), - PixelFormat::RGB, PixelType::UnsignedByte}; - - #if defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2) - CORRADE_COMPARE(Implementation::imageDataSizeFor(image, Vector3i{5, 9, 3}), - (1 + 3)*9*16); - #elif defined(MAGNUM_TARGET_GLES2) - CORRADE_COMPARE(Implementation::imageDataSizeFor(image, Vector3i{5, 9, 3}), - (1 + 3)*9*22); - #else + const Image3D image{ + PixelStorage{}.setAlignment(2) + .setRowLength(7) + .setImageHeight(10) + .setSkip({2, 3, 1}), + PixelFormat::RGB8Unorm}; + CORRADE_COMPARE(Implementation::imageDataSizeFor(image, Vector3i{5, 9, 3}), (1 + 3)*10*22); - #endif - #ifndef MAGNUM_TARGET_GLES2 /* This shouldn't overflow the 128x128x128 cube */ - const Image3D image2{PixelStorage{}.setSkip({64, 64, 0}) - .setRowLength(128) - .setImageHeight(128), - PixelFormat::RGBA, PixelType::UnsignedByte}; + const Image3D image2{ + PixelStorage{}.setSkip({64, 64, 0}) + .setRowLength(128) + .setImageHeight(128), + PixelFormat::RGBA8Unorm}; CORRADE_COMPARE(Implementation::imageDataSizeFor(image2, Vector3i{64, 64, 128}), 8388608); /* This shouldn't overflow the 128x128x128 cube */ - const Image3D image3{PixelStorage{}.setSkip({64, 64, 64}) - .setRowLength(128) - .setImageHeight(128), - PixelFormat::RGBA, PixelType::UnsignedByte}; + const Image3D image3{ + PixelStorage{}.setSkip({64, 64, 64}) + .setRowLength(128) + .setImageHeight(128), + PixelFormat::RGBA8Unorm}; CORRADE_COMPARE(Implementation::imageDataSizeFor(image3, Vector3i{64, 64, 64}), 8388608); - #endif } -#ifndef MAGNUM_TARGET_GLES void PixelStorageTest::dataPropertiesCompressed() { CompressedPixelStorage storage; storage.setCompressedBlockSize({3, 4, 5}) @@ -349,7 +282,6 @@ void PixelStorageTest::dataOffsetSizeCompressed() { CORRADE_COMPARE(Implementation::compressedImageDataOffsetSizeFor(image, Vector3i{4, 4, 1}), (std::pair{16*4*4 + 16*2 + 16, 16})); } -#endif }} diff --git a/src/Magnum/Trade/CMakeLists.txt b/src/Magnum/Trade/CMakeLists.txt index 67eed167f..6384715e0 100644 --- a/src/Magnum/Trade/CMakeLists.txt +++ b/src/Magnum/Trade/CMakeLists.txt @@ -29,7 +29,6 @@ set(MagnumTrade_SRCS AbstractImageConverter.cpp AbstractImporter.cpp AbstractMaterialData.cpp - ImageData.cpp LightData.cpp MeshData2D.cpp MeshData3D.cpp @@ -40,6 +39,10 @@ set(MagnumTrade_SRCS PhongMaterialData.cpp SceneData.cpp TextureData.cpp) + +set(MagnumTrade_GracefulAssert_SRCS + ImageData.cpp) + set(MagnumTrade_HEADERS AbstractImporter.h AbstractImageConverter.h @@ -65,9 +68,26 @@ if(NOT CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT) ${CMAKE_CURRENT_BINARY_DIR}/configure.h) endif() +# Objects shared between main and test library +add_library(MagnumTradeObjects OBJECT + ${MagnumTrade_SRCS} + ${MagnumTrade_HEADERS}) +target_include_directories(MagnumTradeObjects PUBLIC + $ + $ + $) +if(NOT BUILD_STATIC) + target_compile_definitions(MagnumTradeObjects PRIVATE "MagnumTradeObjects_EXPORTS") +endif() +if(NOT BUILD_STATIC OR BUILD_STATIC_PIC) + set_target_properties(MagnumTradeObjects PROPERTIES POSITION_INDEPENDENT_CODE ON) +endif() +set_target_properties(MagnumTradeObjects PROPERTIES FOLDER "Magnum/Trade") + # Trade library add_library(MagnumTrade ${SHARED_OR_STATIC} - ${MagnumTrade_SRCS}) + $ + ${MagnumTrade_GracefulAssert_SRCS}) set_target_properties(MagnumTrade PROPERTIES DEBUG_POSTFIX "-d" FOLDER "Magnum/Trade") @@ -101,6 +121,35 @@ if(WITH_IMAGECONVERTER) endif() if(BUILD_TESTS) + # Library with graceful assert for testing + add_library(MagnumTradeTestLib ${SHARED_OR_STATIC} + $ + ${MagnumTrade_GracefulAssert_SRCS}) + target_include_directories(MagnumTradeTestLib PUBLIC + ${PROJECT_SOURCE_DIR}/src + ${PROJECT_BINARY_DIR}/src) + target_compile_definitions(MagnumTradeTestLib PRIVATE + "CORRADE_GRACEFUL_ASSERT" "MagnumTrade_EXPORTS") + set_target_properties(MagnumTradeTestLib PROPERTIES + DEBUG_POSTFIX "-d" + FOLDER "Magnum") + if(BUILD_STATIC_PIC) + set_target_properties(MagnumTradeTestLib PROPERTIES POSITION_INDEPENDENT_CODE ON) + endif() + target_link_libraries(MagnumTradeTestLib + Magnum + MagnumGL + Corrade::PluginManager) + + # On Windows we need to install first and then run the tests to avoid "DLL + # not found" hell, thus we need to install this too + if(CORRADE_TARGET_WINDOWS AND NOT CMAKE_CROSSCOMPILING AND NOT BUILD_STATIC) + install(TARGETS MagnumTradeTestLib + RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR} + LIBRARY DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR} + ARCHIVE DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}) + endif() + add_subdirectory(Test) endif() diff --git a/src/Magnum/Trade/ImageData.cpp b/src/Magnum/Trade/ImageData.cpp index ac8c5e619..6bc1e0846 100644 --- a/src/Magnum/Trade/ImageData.cpp +++ b/src/Magnum/Trade/ImageData.cpp @@ -34,7 +34,7 @@ template ImageData::ImageData(const PixelSto template ImageData::ImageData(const PixelStorage storage, const UnsignedInt format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor& size, Containers::Array&& data, const void* const importerState) noexcept: ImageData{storage, pixelFormatWrap(format), formatExtra, pixelSize, size, std::move(data), importerState} {} template ImageData::ImageData(const PixelStorage storage, const PixelFormat format, const UnsignedInt formatExtra, const UnsignedInt pixelSize, const VectorTypeFor& size, Containers::Array&& data, const void* const importerState) noexcept: _compressed{false}, _storage{storage}, _format{format}, _formatExtra{formatExtra}, _pixelSize{pixelSize}, _size{size}, _data{std::move(data)}, _importerState{importerState} { - CORRADE_ASSERT(Implementation::imageDataSize(*this) <= _data.size(), "Trade::ImageData::ImageData(): bad image data size, got" << _data.size() << "but expected at least" << Implementation::imageDataSize(*this), ); + CORRADE_ASSERT(Implementation::imageDataSize(*this) <= _data.size(), "Trade::ImageData::ImageData(): data too small, got" << _data.size() << "but expected at least" << Implementation::imageDataSize(*this) << "bytes", ); } template ImageData::ImageData(const CompressedPixelStorage storage, const CompressedPixelFormat format, const VectorTypeFor& size, Containers::Array&& data, const void* const importerState) noexcept: _compressed{true}, _compressedStorage{storage}, _compressedFormat{format}, _size{size}, _data{std::move(data)}, _importerState{importerState} {} diff --git a/src/Magnum/Trade/Test/CMakeLists.txt b/src/Magnum/Trade/Test/CMakeLists.txt index 0dc1635f8..7ba133bd1 100644 --- a/src/Magnum/Trade/Test/CMakeLists.txt +++ b/src/Magnum/Trade/Test/CMakeLists.txt @@ -41,7 +41,7 @@ corrade_add_test(TradeAbstractImporterTest AbstractImporterTest.cpp FILES file.bin) target_include_directories(TradeAbstractImporterTest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) corrade_add_test(TradeCameraDataTest CameraDataTest.cpp LIBRARIES MagnumTrade) -corrade_add_test(TradeImageDataTest ImageDataTest.cpp LIBRARIES MagnumTrade) +corrade_add_test(TradeImageDataTest ImageDataTest.cpp LIBRARIES MagnumTradeTestLib) corrade_add_test(TradeLightDataTest LightDataTest.cpp LIBRARIES MagnumTrade) corrade_add_test(TradeMaterialDataTest MaterialDataTest.cpp LIBRARIES MagnumTrade) corrade_add_test(TradeMeshData2DTest MeshData2DTest.cpp LIBRARIES MagnumTrade) diff --git a/src/Magnum/Trade/Test/ImageDataTest.cpp b/src/Magnum/Trade/Test/ImageDataTest.cpp index 0e8d79067..12a3ff7c2 100644 --- a/src/Magnum/Trade/Test/ImageDataTest.cpp +++ b/src/Magnum/Trade/Test/ImageDataTest.cpp @@ -23,6 +23,7 @@ DEALINGS IN THE SOFTWARE. */ +#include #include #include "Magnum/PixelFormat.h" @@ -33,60 +34,250 @@ namespace Magnum { namespace Trade { namespace Test { struct ImageDataTest: TestSuite::Tester { explicit ImageDataTest(); - void construct(); - void constructCompressed(); + void constructGeneric(); + void constructImplementationSpecific(); + void constructCompressedGeneric(); + void constructCompressedImplementationSpecific(); + + void constructInvalidSize(); + void constructCompressedInvalidSize(); + void constructCopy(); - void constructMove(); - void constructMoveCompressed(); - void toView(); - void toViewCompressed(); + void constructMoveGeneric(); + void constructMoveImplementationSpecific(); + void constructMoveCompressedGeneric(); + void constructMoveCompressedImplementationSpecific(); + + void toViewGeneric(); + void toViewImplementationSpecific(); + void toViewCompressedGeneric(); + void toViewCompressedImplementationSpecific(); + + void access(); + void release(); void releaseCompressed(); }; ImageDataTest::ImageDataTest() { - addTests({&ImageDataTest::construct, - &ImageDataTest::constructCompressed, + addTests({&ImageDataTest::constructGeneric, + &ImageDataTest::constructImplementationSpecific, + &ImageDataTest::constructCompressedGeneric, + &ImageDataTest::constructCompressedImplementationSpecific, + + &ImageDataTest::constructInvalidSize, + &ImageDataTest::constructCompressedInvalidSize, + &ImageDataTest::constructCopy, - &ImageDataTest::constructMove, - &ImageDataTest::constructMoveCompressed, - &ImageDataTest::toView, - &ImageDataTest::toViewCompressed, + &ImageDataTest::constructMoveGeneric, + &ImageDataTest::constructMoveImplementationSpecific, + &ImageDataTest::constructMoveCompressedGeneric, + &ImageDataTest::constructMoveCompressedImplementationSpecific, + + &ImageDataTest::toViewGeneric, + &ImageDataTest::toViewImplementationSpecific, + &ImageDataTest::toViewCompressedGeneric, + &ImageDataTest::toViewCompressedImplementationSpecific, + + &ImageDataTest::access, + &ImageDataTest::release, &ImageDataTest::releaseCompressed}); } -void ImageDataTest::construct() { - auto data = new char[3*3]; - Trade::ImageData2D a{PixelStorage{}.setAlignment(1), - PixelFormat::RGB, PixelType::UnsignedByte, {1, 3}, Containers::Array{data, 3*3}}; +namespace { - CORRADE_VERIFY(!a.isCompressed()); - CORRADE_COMPARE(a.storage().alignment(), 1); - CORRADE_COMPARE(a.format(), PixelFormat::RGB); - CORRADE_COMPARE(a.type(), PixelType::UnsignedByte); - CORRADE_COMPARE(a.size(), Vector2i(1, 3)); - CORRADE_COMPARE(a.data(), data); +namespace GL { + enum class PixelFormat { RGB = 666 }; + enum class PixelType { UnsignedShort = 1337 }; + UnsignedInt pixelSize(PixelFormat format, PixelType type) { + CORRADE_INTERNAL_ASSERT(format == PixelFormat::RGB); + CORRADE_INTERNAL_ASSERT(type == PixelType::UnsignedShort); + return 6; + } + + enum class CompressedPixelFormat { RGBS3tcDxt1 = 21 }; +} + +namespace Vk { + enum class PixelFormat { R32G32B32F = 42 }; + UnsignedInt pixelSize(PixelFormat format) { + CORRADE_INTERNAL_ASSERT(format == PixelFormat::R32G32B32F); + return 12; + } + + enum class CompressedPixelFormat { Bc1SRGBAlpha = 42 }; } -void ImageDataTest::constructCompressed() { - auto data = new char[8]; - Trade::ImageData2D a{ - #ifndef MAGNUM_TARGET_GLES - CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}), - #endif - CompressedPixelFormat::RGBAS3tcDxt1, {4, 4}, Containers::Array{data, 8}}; - - CORRADE_VERIFY(a.isCompressed()); - #ifndef MAGNUM_TARGET_GLES - CORRADE_COMPARE(a.compressedStorage().compressedBlockSize(), Vector3i{4}); - #endif - CORRADE_COMPARE(a.compressedFormat(), CompressedPixelFormat::RGBAS3tcDxt1); - CORRADE_COMPARE(a.size(), Vector2i(4, 4)); - CORRADE_COMPARE(a.data(), data); - CORRADE_COMPARE(a.data().size(), 8); +} + +void ImageDataTest::constructGeneric() { + { + auto data = new char[4*4]; + int state; + ImageData2D a{PixelFormat::RGBA8Unorm, {1, 3}, Containers::Array{data, 4*4}, &state}; + + CORRADE_VERIFY(!a.isCompressed()); + CORRADE_COMPARE(a.storage().alignment(), 4); + CORRADE_COMPARE(a.format(), PixelFormat::RGBA8Unorm); + CORRADE_COMPARE(a.formatExtra(), 0); + CORRADE_COMPARE(a.pixelSize(), 4); + CORRADE_COMPARE(a.size(), (Vector2i{1, 3})); + CORRADE_COMPARE(a.data(), data); + CORRADE_COMPARE(a.data().size(), 4*4); + CORRADE_COMPARE(a.importerState(), &state); + } { + auto data = new char[3*2]; + int state; + ImageData2D a{PixelStorage{}.setAlignment(1), + PixelFormat::R16UI, {1, 3}, Containers::Array{data, 3*2}, &state}; + + CORRADE_VERIFY(!a.isCompressed()); + CORRADE_COMPARE(a.storage().alignment(), 1); + CORRADE_COMPARE(a.format(), PixelFormat::R16UI); + CORRADE_COMPARE(a.formatExtra(), 0); + CORRADE_COMPARE(a.pixelSize(), 2); + CORRADE_COMPARE(a.size(), (Vector2i{1, 3})); + CORRADE_COMPARE(a.data(), data); + CORRADE_COMPARE(a.data().size(), 3*2); + CORRADE_COMPARE(a.importerState(), &state); + } +} + +void ImageDataTest::constructImplementationSpecific() { + /* Single format */ + { + auto data = new char[3*12]; + int state; + ImageData2D a{PixelStorage{}.setAlignment(1), + Vk::PixelFormat::R32G32B32F, {1, 3}, Containers::Array{data, 3*12}, &state}; + + CORRADE_VERIFY(!a.isCompressed()); + CORRADE_COMPARE(a.storage().alignment(), 1); + CORRADE_COMPARE(a.format(), pixelFormatWrap(Vk::PixelFormat::R32G32B32F)); + CORRADE_COMPARE(a.formatExtra(), 0); + CORRADE_COMPARE(a.pixelSize(), 12); + CORRADE_COMPARE(a.size(), (Vector2i{1, 3})); + CORRADE_COMPARE(a.data(), data); + CORRADE_COMPARE(a.data().size(), 3*12); + CORRADE_COMPARE(a.importerState(), &state); + } + + /* Format + extra */ + { + auto data = new char[3*6]; + int state; + ImageData2D a{PixelStorage{}.setAlignment(1), + GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, Containers::Array{data, 3*6}, &state}; + + CORRADE_VERIFY(!a.isCompressed()); + CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB)); + CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort)); + CORRADE_COMPARE(a.pixelSize(), 6); + CORRADE_COMPARE(a.size(), (Vector2i{1, 3})); + CORRADE_COMPARE(a.data(), data); + CORRADE_COMPARE(a.data().size(), 3*6); + CORRADE_COMPARE(a.importerState(), &state); + } + + /* Manual pixel size */ + { + auto data = new char[3*6]; + int state; + ImageData2D a{PixelStorage{}.setAlignment(1), 666, 1337, 6, {1, 3}, Containers::Array{data, 3*6}, &state}; + + CORRADE_VERIFY(!a.isCompressed()); + CORRADE_COMPARE(a.storage().alignment(), 1); + CORRADE_COMPARE(a.format(), pixelFormatWrap(GL::PixelFormat::RGB)); + CORRADE_COMPARE(a.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort)); + CORRADE_COMPARE(a.pixelSize(), 6); + CORRADE_COMPARE(a.size(), (Vector2i{1, 3})); + CORRADE_COMPARE(a.data(), data); + CORRADE_COMPARE(a.data().size(), 3*6); + CORRADE_COMPARE(a.importerState(), &state); + } +} + +void ImageDataTest::constructCompressedGeneric() { + { + auto data = new char[8]; + int state; + ImageData2D a{CompressedPixelFormat::Bc1RGBAUnorm, {4, 4}, + Containers::Array{data, 8}, &state}; + + CORRADE_VERIFY(a.isCompressed()); + CORRADE_COMPARE(a.compressedStorage().compressedBlockSize(), Vector3i{0}); + CORRADE_COMPARE(a.compressedFormat(), CompressedPixelFormat::Bc1RGBAUnorm); + CORRADE_COMPARE(a.size(), (Vector2i{4, 4})); + CORRADE_COMPARE(a.data(), data); + CORRADE_COMPARE(a.data().size(), 8); + CORRADE_COMPARE(a.importerState(), &state); + } { + auto data = new char[8]; + int state; + ImageData2D a{CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}), + CompressedPixelFormat::Bc1RGBAUnorm, {4, 4}, + Containers::Array{data, 8}, &state}; + + CORRADE_VERIFY(a.isCompressed()); + CORRADE_COMPARE(a.compressedStorage().compressedBlockSize(), Vector3i{4}); + CORRADE_COMPARE(a.compressedFormat(), CompressedPixelFormat::Bc1RGBAUnorm); + CORRADE_COMPARE(a.size(), Vector2i(4, 4)); + CORRADE_COMPARE(a.data(), data); + CORRADE_COMPARE(a.data().size(), 8); + CORRADE_COMPARE(a.importerState(), &state); + } +} + +void ImageDataTest::constructCompressedImplementationSpecific() { + /* Format with autodetection */ + { + auto data = new char[8]; + int state; + ImageData2D a{CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}), + GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 4}, + Containers::Array{data, 8}, &state}; + + CORRADE_VERIFY(a.isCompressed()); + CORRADE_COMPARE(a.compressedStorage().compressedBlockSize(), Vector3i{4}); + CORRADE_COMPARE(a.compressedFormat(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1)); + CORRADE_COMPARE(a.size(), (Vector2i{4, 4})); + CORRADE_COMPARE(a.data(), data); + CORRADE_COMPARE(a.data().size(), 8); + CORRADE_COMPARE(a.importerState(), &state); + } + + /* Manual properties not implemented yet */ +} + +void ImageDataTest::constructInvalidSize() { + std::ostringstream out; + Error redirectError{&out}; + + /* Doesn't consider alignment */ + ImageData2D{PixelFormat::RGB8Unorm, {1, 3}, Containers::Array{3*3}}; + CORRADE_COMPARE(out.str(), "Trade::ImageData::ImageData(): data too small, got 9 but expected at least 12 bytes\n"); +} + +void ImageDataTest::constructCompressedInvalidSize() { + CORRADE_EXPECT_FAIL("Size checking for compressed image data is not implemented yet."); + + /* Too small for given format */ + { + std::ostringstream out; + Error redirectError{&out}; + ImageData2D{CompressedPixelFormat::Bc2RGBAUnorm, {4, 4}, Containers::Array{2}}; + CORRADE_COMPARE(out.str(), "Trade::ImageData::ImageData(): data too small, got 2 but expected at least 4 bytes\n"); + + /* Size should be rounded up even if the image size is not full block */ + } { + std::ostringstream out; + Error redirectError{&out}; + ImageData2D{CompressedPixelFormat::Bc2RGBAUnorm, {2, 2}, Containers::Array{2}}; + CORRADE_COMPARE(out.str(), "Trade::ImageData::ImageData(): data too small, got 2 but expected at least 4 bytes\n"); + } } void ImageDataTest::constructCopy() { @@ -94,24 +285,67 @@ void ImageDataTest::constructCopy() { CORRADE_VERIFY(!(std::is_assignable{})); } -void ImageDataTest::constructMove() { - auto data = new char[3*3]; - Trade::ImageData2D a{PixelStorage{}.setAlignment(1), - PixelFormat::RGB, PixelType::UnsignedByte, {1, 3}, Containers::Array{data, 3*3}}; - Trade::ImageData2D b(std::move(a)); +void ImageDataTest::constructMoveGeneric() { + auto data = new char[3*16]; + int state; + ImageData2D a{PixelStorage{}.setAlignment(1), + PixelFormat::RGBA32F, {1, 3}, Containers::Array{data, 3*16}, &state}; + ImageData2D b(std::move(a)); CORRADE_COMPARE(a.data(), nullptr); - CORRADE_COMPARE(a.size(), Vector2i()); + CORRADE_COMPARE(a.size(), Vector2i{}); CORRADE_VERIFY(!b.isCompressed()); CORRADE_COMPARE(b.storage().alignment(), 1); - CORRADE_COMPARE(b.format(), PixelFormat::RGB); - CORRADE_COMPARE(b.type(), PixelType::UnsignedByte); - CORRADE_COMPARE(b.size(), Vector2i(1, 3)); + CORRADE_COMPARE(b.format(), PixelFormat::RGBA32F); + CORRADE_COMPARE(b.formatExtra(), 0); + CORRADE_COMPARE(b.pixelSize(), 16); + CORRADE_COMPARE(b.size(), (Vector2i{1, 3})); CORRADE_COMPARE(b.data(), data); + CORRADE_COMPARE(b.data().size(), 3*16); + CORRADE_COMPARE(b.importerState(), &state); - auto data2 = new char[2*2*6*4]; - Trade::ImageData2D c{PixelFormat::RGBA, PixelType::UnsignedShort, {2, 6}, Containers::Array{data2, 2*2*6*4}}; + auto data2 = new char[24]; + ImageData2D c{PixelFormat::R8I, {2, 6}, Containers::Array{data2, 24}}; + c = std::move(b); + + CORRADE_COMPARE(b.data(), data2); + CORRADE_COMPARE(b.size(), (Vector2i{2, 6})); + + CORRADE_VERIFY(!c.isCompressed()); + CORRADE_COMPARE(c.storage().alignment(), 1); + CORRADE_COMPARE(c.format(), PixelFormat::RGBA32F); + CORRADE_COMPARE(c.formatExtra(), 0); + CORRADE_COMPARE(c.pixelSize(), 16); + CORRADE_COMPARE(c.size(), (Vector2i{1, 3})); + CORRADE_COMPARE(c.data(), data); + CORRADE_COMPARE(c.data().size(), 3*16); + CORRADE_COMPARE(c.importerState(), &state); +} + +void ImageDataTest::constructMoveImplementationSpecific() { + auto data = new char[3*6]; + int state; + ImageData2D a{PixelStorage{}.setAlignment(1), + GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, Containers::Array{data, 3*6}, &state}; + ImageData2D b(std::move(a)); + + CORRADE_COMPARE(a.data(), nullptr); + CORRADE_COMPARE(a.size(), Vector2i{}); + + CORRADE_VERIFY(!b.isCompressed()); + CORRADE_COMPARE(b.storage().alignment(), 1); + CORRADE_COMPARE(b.format(), pixelFormatWrap(GL::PixelFormat::RGB)); + CORRADE_COMPARE(b.formatExtra(), 1337); + CORRADE_COMPARE(b.pixelSize(), 6); + CORRADE_COMPARE(b.size(), (Vector2i{1, 3})); + CORRADE_COMPARE(b.data(), data); + CORRADE_COMPARE(b.data().size(), 3*6); + CORRADE_COMPARE(b.importerState(), &state); + + auto data2 = new char[12*4*2]; + ImageData2D c{PixelStorage{}, + 1, 2, 8, {2, 6}, Containers::Array{data2, 12*4*2}}; c = std::move(b); CORRADE_COMPARE(b.data(), data2); @@ -119,78 +353,152 @@ void ImageDataTest::constructMove() { CORRADE_VERIFY(!c.isCompressed()); CORRADE_COMPARE(c.storage().alignment(), 1); - CORRADE_COMPARE(c.format(), PixelFormat::RGB); - CORRADE_COMPARE(c.type(), PixelType::UnsignedByte); - CORRADE_COMPARE(c.size(), Vector2i(1, 3)); + CORRADE_COMPARE(c.format(), pixelFormatWrap(GL::PixelFormat::RGB)); + CORRADE_COMPARE(c.formatExtra(), 1337); + CORRADE_COMPARE(c.pixelSize(), 6); + CORRADE_COMPARE(c.size(), (Vector2i{1, 3})); CORRADE_COMPARE(c.data(), data); + CORRADE_COMPARE(c.data().size(), 3*6); + CORRADE_COMPARE(c.importerState(), &state); } -void ImageDataTest::constructMoveCompressed() { +void ImageDataTest::constructMoveCompressedGeneric() { auto data = new char[8]; - Trade::ImageData2D a{ - #ifndef MAGNUM_TARGET_GLES + int state; + ImageData2D a{ CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}), - #endif - CompressedPixelFormat::RGBAS3tcDxt1, {4, 4}, Containers::Array{data, 8}}; - Trade::ImageData2D b{std::move(a)}; + CompressedPixelFormat::Bc3RGBAUnorm, {4, 4}, Containers::Array{data, 8}, &state}; + ImageData2D b{std::move(a)}; CORRADE_COMPARE(a.data(), nullptr); - CORRADE_COMPARE(a.size(), Vector2i()); + CORRADE_COMPARE(a.size(), Vector2i{}); + + CORRADE_VERIFY(b.isCompressed()); + CORRADE_COMPARE(b.compressedStorage().compressedBlockSize(), Vector3i{4}); + CORRADE_COMPARE(b.compressedFormat(), CompressedPixelFormat::Bc3RGBAUnorm); + CORRADE_COMPARE(b.size(), (Vector2i{4, 4})); + CORRADE_COMPARE(b.data(), data); + CORRADE_COMPARE(b.data().size(), 8); + CORRADE_COMPARE(b.importerState(), &state); + + auto data2 = new char[16]; + ImageData2D c{CompressedPixelFormat::Bc1RGBAUnorm, {8, 4}, Containers::Array{data2, 16}}; + c = std::move(b); + + CORRADE_COMPARE(b.data(), data2); + CORRADE_COMPARE(b.size(), (Vector2i{8, 4})); + + CORRADE_VERIFY(c.isCompressed()); + CORRADE_COMPARE(c.compressedStorage().compressedBlockSize(), Vector3i{4}); + CORRADE_COMPARE(c.compressedFormat(), CompressedPixelFormat::Bc3RGBAUnorm); + CORRADE_COMPARE(c.size(), (Vector2i{4, 4})); + CORRADE_COMPARE(c.data(), data); + CORRADE_COMPARE(c.data().size(), 8); + CORRADE_COMPARE(c.importerState(), &state); +} + +void ImageDataTest::constructMoveCompressedImplementationSpecific() { + auto data = new char[8]; + int state; + ImageData2D a{ + CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}), + GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 4}, Containers::Array{data, 8}, &state}; + ImageData2D b{std::move(a)}; + + CORRADE_COMPARE(a.data(), nullptr); + CORRADE_COMPARE(a.size(), Vector2i{}); CORRADE_VERIFY(b.isCompressed()); - #ifndef MAGNUM_TARGET_GLES CORRADE_COMPARE(b.compressedStorage().compressedBlockSize(), Vector3i{4}); - #endif - CORRADE_COMPARE(b.compressedFormat(), CompressedPixelFormat::RGBAS3tcDxt1); - CORRADE_COMPARE(b.size(), Vector2i(4, 4)); + CORRADE_COMPARE(b.compressedFormat(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1)); + CORRADE_COMPARE(b.size(), (Vector2i{4, 4})); CORRADE_COMPARE(b.data(), data); CORRADE_COMPARE(b.data().size(), 8); + CORRADE_COMPARE(b.importerState(), &state); auto data2 = new char[16]; - Trade::ImageData2D c{CompressedPixelFormat::RGBAS3tcDxt3, {8, 4}, Containers::Array{data2, 16}}; + ImageData2D c{CompressedPixelFormat::Bc2RGBAUnorm, {8, 4}, Containers::Array{data2, 16}}; c = std::move(b); - CORRADE_COMPARE_AS(b.data(), data2, char*); - CORRADE_COMPARE(b.data().size(), 16); - CORRADE_COMPARE(b.size(), Vector2i(8, 4)); + CORRADE_COMPARE(b.data(), data2); + CORRADE_COMPARE(b.size(), (Vector2i{8, 4})); CORRADE_VERIFY(c.isCompressed()); - #ifndef MAGNUM_TARGET_GLES CORRADE_COMPARE(c.compressedStorage().compressedBlockSize(), Vector3i{4}); - #endif - CORRADE_COMPARE(c.compressedFormat(), CompressedPixelFormat::RGBAS3tcDxt1); - CORRADE_COMPARE(c.size(), Vector2i(4, 4)); + CORRADE_COMPARE(c.compressedFormat(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1)); + CORRADE_COMPARE(c.size(), (Vector2i{4, 4})); CORRADE_COMPARE(c.data(), data); CORRADE_COMPARE(c.data().size(), 8); + CORRADE_COMPARE(c.importerState(), &state); } -void ImageDataTest::toView() { - auto data = new char[3*3]; - const Trade::ImageData2D a{PixelStorage{}.setAlignment(1), - PixelFormat::RGB, PixelType::UnsignedByte, {1, 3}, Containers::Array{data, 3*3}}; +void ImageDataTest::toViewGeneric() { + auto data = new char[3*4]; + const ImageData2D a{PixelStorage{}.setAlignment(1), + PixelFormat::RG16I, {1, 3}, Containers::Array{data, 3*4}}; ImageView2D b = a; CORRADE_COMPARE(b.storage().alignment(), 1); - CORRADE_COMPARE(b.format(), PixelFormat::RGB); - CORRADE_COMPARE(b.type(), PixelType::UnsignedByte); - CORRADE_COMPARE(b.size(), Vector2i(1, 3)); + CORRADE_COMPARE(b.format(), PixelFormat::RG16I); + CORRADE_COMPARE(b.formatExtra(), 0); + CORRADE_COMPARE(b.pixelSize(), 4); + CORRADE_COMPARE(b.size(), (Vector2i{1, 3})); + CORRADE_COMPARE(b.data(), data); +} + +void ImageDataTest::toViewImplementationSpecific() { + auto data = new char[3*6]; + const ImageData2D a{PixelStorage{}.setAlignment(1), + GL::PixelFormat::RGB, GL::PixelType::UnsignedShort, {1, 3}, Containers::Array{data, 3*6}}; + ImageView2D b = a; + + CORRADE_COMPARE(b.storage().alignment(), 1); + CORRADE_COMPARE(b.format(), pixelFormatWrap(GL::PixelFormat::RGB)); + CORRADE_COMPARE(b.formatExtra(), 1337); + CORRADE_COMPARE(b.pixelSize(), 6); + CORRADE_COMPARE(b.size(), (Vector2i{1, 3})); + CORRADE_COMPARE(b.data(), data); +} + +void ImageDataTest::toViewCompressedGeneric() { + auto data = new char[8]; + const ImageData2D a{ + CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}), + CompressedPixelFormat::Bc1RGBUnorm, {4, 4}, Containers::Array{data, 8}}; + CompressedImageView2D b = a; + + CORRADE_COMPARE(b.storage().compressedBlockSize(), Vector3i{4}); + CORRADE_COMPARE(b.format(), CompressedPixelFormat::Bc1RGBUnorm); + CORRADE_COMPARE(b.size(), (Vector2i{4, 4})); CORRADE_COMPARE(b.data(), data); + CORRADE_COMPARE(b.data().size(), 8); } -void ImageDataTest::toViewCompressed() { +void ImageDataTest::toViewCompressedImplementationSpecific() { auto data = new char[8]; - const Trade::ImageData2D a{CompressedPixelFormat::RGBAS3tcDxt1, {4, 4}, Containers::Array{data, 8}}; + const ImageData2D a{ + CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}), + GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 4}, Containers::Array{data, 8}}; CompressedImageView2D b = a; - CORRADE_COMPARE(b.format(), CompressedPixelFormat::RGBAS3tcDxt1); - CORRADE_COMPARE(b.size(), Vector2i(4, 4)); + CORRADE_COMPARE(b.storage().compressedBlockSize(), Vector3i{4}); + CORRADE_COMPARE(b.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1)); + CORRADE_COMPARE(b.size(), (Vector2i{4, 4})); CORRADE_COMPARE(b.data(), data); CORRADE_COMPARE(b.data().size(), 8); } +void ImageDataTest::access() { + auto data = new char[4*4]; + ImageData2D a{PixelFormat::RGBA8Unorm, {1, 3}, Containers::Array{data, 4*4}}; + const ImageData2D& ca = a; + CORRADE_COMPARE(a.data(), data); + CORRADE_COMPARE(ca.data(), data); +} + void ImageDataTest::release() { char data[] = {'b', 'e', 'e', 'r'}; - Trade::ImageData2D a{PixelFormat::RGBA, PixelType::UnsignedByte, {1, 1}, Containers::Array{data, 4}}; + Trade::ImageData2D a{PixelFormat::RGBA8Unorm, {1, 1}, Containers::Array{data, 4}}; const char* const pointer = a.release().release(); CORRADE_COMPARE(pointer, data); @@ -200,7 +508,7 @@ void ImageDataTest::release() { void ImageDataTest::releaseCompressed() { char data[8]; - Trade::ImageData2D a{CompressedPixelFormat::RGBAS3tcDxt1, {4, 4}, Containers::Array{data, 8}}; + Trade::ImageData2D a{CompressedPixelFormat::Bc1RGBAUnorm, {4, 4}, Containers::Array{data, 8}}; const char* const pointer = a.release().release(); CORRADE_COMPARE(pointer, data); diff --git a/src/Magnum/Trade/visibility.h b/src/Magnum/Trade/visibility.h index ef36e84c2..6ee67774c 100644 --- a/src/Magnum/Trade/visibility.h +++ b/src/Magnum/Trade/visibility.h @@ -31,7 +31,7 @@ #ifndef DOXYGEN_GENERATING_OUTPUT #ifndef MAGNUM_BUILD_STATIC - #ifdef MagnumTrade_EXPORTS + #if defined(MagnumTrade_EXPORTS) || defined(MagnumTradeObjects_EXPORTS) #define MAGNUM_TRADE_EXPORT CORRADE_VISIBILITY_EXPORT #else #define MAGNUM_TRADE_EXPORT CORRADE_VISIBILITY_IMPORT diff --git a/src/Magnum/visibility.h b/src/Magnum/visibility.h index 3d24ba694..b62cc6d3c 100644 --- a/src/Magnum/visibility.h +++ b/src/Magnum/visibility.h @@ -31,7 +31,7 @@ #ifndef DOXYGEN_GENERATING_OUTPUT #ifndef MAGNUM_BUILD_STATIC - #if defined(Magnum_EXPORTS) || defined(MagnumMathObjects_EXPORTS) + #if defined(Magnum_EXPORTS) || defined(MagnumObjects_EXPORTS) || defined(MagnumMathObjects_EXPORTS) #define MAGNUM_EXPORT CORRADE_VISIBILITY_EXPORT #else #define MAGNUM_EXPORT CORRADE_VISIBILITY_IMPORT