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