From 057007facbb0e63f99d50f69ac20e26cf121ab2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 5 Sep 2019 18:03:18 +0200 Subject: [PATCH] Make ImageViews of lower dimensions convertible to higher dimensions. Otherwise using GL::TextureArray is quite annoying. --- doc/changelog.dox | 3 + src/Magnum/ImageView.h | 14 ++++ src/Magnum/Test/ImageViewTest.cpp | 122 ++++++++++++++++++++++++++++++ 3 files changed, 139 insertions(+) diff --git a/doc/changelog.dox b/doc/changelog.dox index ab267acb2..562f0f5c0 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -292,6 +292,9 @@ See also: @ref ResourceDataState::NotFound resources - Added comparison operators to @ref Resource (see [mosra/magnum#346](https://github.com/mosra/magnum/pull/346)) +- @ref ImageView and @ref CompressedImageView of smaller dimension count are + now implicitly convertible to views of higher dimension count to make + slice-by-slice uploads to @ref GL::TextureArray and others easier - @ref Image::data(), @ref CompressedImage::data() and @ref Trade::ImageData::data() called on a r-value now return @ref Corrade::Containers::Array instead of being deleted diff --git a/src/Magnum/ImageView.h b/src/Magnum/ImageView.h index ba949963c..576446e2d 100644 --- a/src/Magnum/ImageView.h +++ b/src/Magnum/ImageView.h @@ -355,6 +355,9 @@ template class ImageView { */ template explicit ImageView(U format, const VectorTypeFor& size) noexcept: ImageView{{}, format, size} {} + /** @brief Construct from a view of lower dimension count */ + template::type> /*implicit*/ ImageView(const ImageView& other) noexcept; + /** @brief Convert a mutable view to a const one */ template::value &&!std::is_const::value>::type> /*implicit*/ ImageView(const ImageView& other) noexcept; @@ -721,6 +724,9 @@ template class CompressedImageView { */ template explicit CompressedImageView(U format, const VectorTypeFor& size) noexcept: CompressedImageView{{}, format, size} {} + /** @brief Construct from a view of lower dimension count */ + template::type> /*implicit*/ CompressedImageView(const CompressedImageView& other) noexcept; + /** @brief Convert a mutable view to a const one */ template::value &&!std::is_const::value>::type> /*implicit*/ CompressedImageView(const CompressedImageView& other) noexcept; @@ -877,6 +883,10 @@ template template inline ImageView template ImageView::ImageView(const ImageView& other) noexcept: _storage{other._storage}, _format{other._format}, _formatExtra{other._formatExtra}, _pixelSize{other._pixelSize}, _size{Math::Vector::pad(other._size, 1)}, _data{other._data} {} +#endif + template template ImageView::ImageView(const ImageView& other) noexcept: _storage{other._storage}, _format{other._format}, _formatExtra{other._formatExtra}, _pixelSize{other._pixelSize}, _size{other._size}, _data{other._data} {} template template inline CompressedImageView::CompressedImageView(const CompressedPixelStorage storage, const U format, const VectorTypeFor& size, const Containers::ArrayView data) noexcept: CompressedImageView{storage, UnsignedInt(format), size, data} { @@ -889,6 +899,10 @@ template template inline CompressedIma "format types larger than 32bits are not supported"); } +#ifndef DOXYGEN_GENERATING_OUTPUT /* it complains otherwise. why? don't know, don't want to know */ +template template CompressedImageView::CompressedImageView(const CompressedImageView& other) noexcept: _storage{other._storage}, _format{other._format}, _size{Math::Vector::pad(other._size, 1)}, _data{other._data} {} +#endif + template template CompressedImageView::CompressedImageView(const CompressedImageView& other) noexcept: _storage{other._storage}, _format{other._format}, _size{other._size}, _data{other._data} {} } diff --git a/src/Magnum/Test/ImageViewTest.cpp b/src/Magnum/Test/ImageViewTest.cpp index 6193ad15a..24c910d18 100644 --- a/src/Magnum/Test/ImageViewTest.cpp +++ b/src/Magnum/Test/ImageViewTest.cpp @@ -46,6 +46,11 @@ struct ImageViewTest: TestSuite::Tester { template void constructCompressedImplementationSpecific(); template void constructCompressedImplementationSpecificEmpty(); + void construct3DFrom1D(); + void construct3DFrom2D(); + void constructCompressed3DFrom1D(); + void constructCompressed3DFrom2D(); + void constructFromMutable(); void constructCompressedFromMutable(); @@ -94,6 +99,11 @@ ImageViewTest::ImageViewTest() { &ImageViewTest::constructCompressedImplementationSpecificEmpty, &ImageViewTest::constructCompressedImplementationSpecificEmpty, + &ImageViewTest::construct3DFrom1D, + &ImageViewTest::construct3DFrom2D, + &ImageViewTest::constructCompressed3DFrom1D, + &ImageViewTest::constructCompressed3DFrom2D, + &ImageViewTest::constructFromMutable, &ImageViewTest::constructCompressedFromMutable, @@ -431,6 +441,118 @@ template void ImageViewTest::constructCompressedImplementationSpecificE /* Manual properties not implemented yet */ } +void ImageViewTest::construct3DFrom1D() { + /* Copy of "Manual pixel size" in constructImplementationSpecific(), as + that exposes most fields */ + const char data[3*6]{}; + ImageView1D a{PixelStorage{}.setAlignment(1), 666, 1337, 6, 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(), 3); + CORRADE_COMPARE(a.data(), &data[0]); + CORRADE_COMPARE(a.data().size(), 3*6); + + ImageView3D b = a; /* implicit conversion allowed */ + CORRADE_COMPARE(b.storage().alignment(), 1); + CORRADE_COMPARE(b.format(), pixelFormatWrap(GL::PixelFormat::RGB)); + CORRADE_COMPARE(b.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort)); + CORRADE_COMPARE(b.pixelSize(), 6); + CORRADE_COMPARE(b.size(), (Vector3i{3, 1, 1})); + CORRADE_COMPARE(b.data(), &data[0]); + CORRADE_COMPARE(b.data().size(), 3*6); + + /* Conversion the other way is not allowed (will be later, but explicitly + via a slice<1>() like with StridedArrayView); conversion from const to + mutable is not possible either */ + CORRADE_VERIFY((std::is_convertible::value)); + CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!(std::is_convertible::value)); +} + +void ImageViewTest::construct3DFrom2D() { + /* Copy of "Manual pixel size" in constructImplementationSpecific(), as + that exposes most fields */ + char data[3*6]{}; + MutableImageView2D 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[0]); + CORRADE_COMPARE(a.data().size(), 3*6); + + MutableImageView3D b = a; + CORRADE_COMPARE(b.storage().alignment(), 1); + CORRADE_COMPARE(b.format(), pixelFormatWrap(GL::PixelFormat::RGB)); + CORRADE_COMPARE(b.formatExtra(), UnsignedInt(GL::PixelType::UnsignedShort)); + CORRADE_COMPARE(b.pixelSize(), 6); + CORRADE_COMPARE(b.size(), (Vector3i{1, 3, 1})); + CORRADE_COMPARE(b.data(), &data[0]); + CORRADE_COMPARE(b.data().size(), 3*6); + + /* Conversion the other way is not allowed (will be later, but explicitly + via a slice<1>() like with StridedArrayView) */ + CORRADE_VERIFY((std::is_convertible::value)); + CORRADE_VERIFY(!(std::is_convertible::value)); +} + +void ImageViewTest::constructCompressed3DFrom1D() { + /* Copied from constructCompressedImplementationSpecific(), as that exposes + most fields */ + /** @todo S3TC doesn't have 1D compression so this might blow up once we + check for block sizes */ + const char data[8]{}; + CompressedImageView1D a{CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}), + GL::CompressedPixelFormat::RGBS3tcDxt1, 4, data}; + CORRADE_COMPARE(a.storage().compressedBlockSize(), Vector3i{4}); + CORRADE_COMPARE(a.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1)); + CORRADE_COMPARE(a.size(), 4); + CORRADE_COMPARE(a.data(), &data[0]); + CORRADE_COMPARE(a.data().size(), 8); + + CompressedImageView3D b = a; + CORRADE_COMPARE(b.storage().compressedBlockSize(), Vector3i{4}); + CORRADE_COMPARE(b.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1)); + CORRADE_COMPARE(b.size(), (Vector3i{4, 1, 1})); + CORRADE_COMPARE(b.data(), &data[0]); + CORRADE_COMPARE(b.data().size(), 8); + + /* Conversion the other way is not allowed (will be later, but explicitly + via a slice<1>() like with StridedArrayView); conversion from const to + mutable is not possible either */ + CORRADE_VERIFY((std::is_convertible::value)); + CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!(std::is_convertible::value)); +} + +void ImageViewTest::constructCompressed3DFrom2D() { + /* Copied from constructCompressedImplementationSpecific(), as that exposes + most fields */ + char data[8*2]{}; + MutableCompressedImageView2D a{CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}), + GL::CompressedPixelFormat::RGBS3tcDxt1, {4, 8}, data}; + 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(), &data[0]); + CORRADE_COMPARE(a.data().size(), 8*2); + + MutableCompressedImageView3D b = a; + CORRADE_COMPARE(b.storage().compressedBlockSize(), Vector3i{4}); + CORRADE_COMPARE(b.format(), compressedPixelFormatWrap(GL::CompressedPixelFormat::RGBS3tcDxt1)); + CORRADE_COMPARE(b.size(), (Vector3i{4, 8, 1})); + CORRADE_COMPARE(b.data(), &data[0]); + CORRADE_COMPARE(b.data().size(), 8*2); + + /* Conversion the other way is not allowed (will be later, but explicitly + via a slice<1>() like with StridedArrayView) */ + CORRADE_VERIFY((std::is_convertible::value)); + CORRADE_VERIFY(!(std::is_convertible::value)); +} + void ImageViewTest::constructFromMutable() { /* Copy of "Manual pixel size" in constructImplementationSpecific(), as that exposes most fields */