Browse Source

Make ImageViews of lower dimensions convertible to higher dimensions.

Otherwise using GL::TextureArray is quite annoying.
pull/326/merge
Vladimír Vondruš 7 years ago
parent
commit
057007facb
  1. 3
      doc/changelog.dox
  2. 14
      src/Magnum/ImageView.h
  3. 122
      src/Magnum/Test/ImageViewTest.cpp

3
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

14
src/Magnum/ImageView.h

@ -355,6 +355,9 @@ template<UnsignedInt dimensions, class T> class ImageView {
*/
template<class U> explicit ImageView(U format, const VectorTypeFor<dimensions, Int>& size) noexcept: ImageView{{}, format, size} {}
/** @brief Construct from a view of lower dimension count */
template<UnsignedInt otherDimensions, class = typename std::enable_if<otherDimensions < dimensions>::type> /*implicit*/ ImageView(const ImageView<otherDimensions, T>& other) noexcept;
/** @brief Convert a mutable view to a const one */
template<class U, class = typename std::enable_if<std::is_const<T>::value &&!std::is_const<U>::value>::type> /*implicit*/ ImageView(const ImageView<dimensions, U>& other) noexcept;
@ -721,6 +724,9 @@ template<UnsignedInt dimensions, class T> class CompressedImageView {
*/
template<class U> explicit CompressedImageView(U format, const VectorTypeFor<dimensions, Int>& size) noexcept: CompressedImageView{{}, format, size} {}
/** @brief Construct from a view of lower dimension count */
template<UnsignedInt otherDimensions, class = typename std::enable_if<otherDimensions < dimensions>::type> /*implicit*/ CompressedImageView(const CompressedImageView<otherDimensions, T>& other) noexcept;
/** @brief Convert a mutable view to a const one */
template<class U, class = typename std::enable_if<std::is_const<T>::value &&!std::is_const<U>::value>::type> /*implicit*/ CompressedImageView(const CompressedImageView<dimensions, U>& other) noexcept;
@ -877,6 +883,10 @@ template<UnsignedInt dimensions, class T> template<class U> inline ImageView<dim
"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<UnsignedInt dimensions, class T> template<UnsignedInt otherDimensions, class> ImageView<dimensions, T>::ImageView(const ImageView<otherDimensions, T>& other) noexcept: _storage{other._storage}, _format{other._format}, _formatExtra{other._formatExtra}, _pixelSize{other._pixelSize}, _size{Math::Vector<dimensions, Int>::pad(other._size, 1)}, _data{other._data} {}
#endif
template<UnsignedInt dimensions, class T> template<class U, class> ImageView<dimensions, T>::ImageView(const ImageView<dimensions, U>& other) noexcept: _storage{other._storage}, _format{other._format}, _formatExtra{other._formatExtra}, _pixelSize{other._pixelSize}, _size{other._size}, _data{other._data} {}
template<UnsignedInt dimensions, class T> template<class U> inline CompressedImageView<dimensions, T>::CompressedImageView(const CompressedPixelStorage storage, const U format, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<ErasedType> data) noexcept: CompressedImageView{storage, UnsignedInt(format), size, data} {
@ -889,6 +899,10 @@ template<UnsignedInt dimensions, class T> template<class U> 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<UnsignedInt dimensions, class T> template<UnsignedInt otherDimensions, class> CompressedImageView<dimensions, T>::CompressedImageView(const CompressedImageView<otherDimensions, T>& other) noexcept: _storage{other._storage}, _format{other._format}, _size{Math::Vector<dimensions, Int>::pad(other._size, 1)}, _data{other._data} {}
#endif
template<UnsignedInt dimensions, class T> template<class U, class> CompressedImageView<dimensions, T>::CompressedImageView(const CompressedImageView<dimensions, U>& other) noexcept: _storage{other._storage}, _format{other._format}, _size{other._size}, _data{other._data} {}
}

122
src/Magnum/Test/ImageViewTest.cpp

@ -46,6 +46,11 @@ struct ImageViewTest: TestSuite::Tester {
template<class T> void constructCompressedImplementationSpecific();
template<class T> void constructCompressedImplementationSpecificEmpty();
void construct3DFrom1D();
void construct3DFrom2D();
void constructCompressed3DFrom1D();
void constructCompressed3DFrom2D();
void constructFromMutable();
void constructCompressedFromMutable();
@ -94,6 +99,11 @@ ImageViewTest::ImageViewTest() {
&ImageViewTest::constructCompressedImplementationSpecificEmpty<const char>,
&ImageViewTest::constructCompressedImplementationSpecificEmpty<char>,
&ImageViewTest::construct3DFrom1D,
&ImageViewTest::construct3DFrom2D,
&ImageViewTest::constructCompressed3DFrom1D,
&ImageViewTest::constructCompressed3DFrom2D,
&ImageViewTest::constructFromMutable,
&ImageViewTest::constructCompressedFromMutable,
@ -431,6 +441,118 @@ template<class T> 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<ImageView1D, ImageView3D>::value));
CORRADE_VERIFY(!(std::is_convertible<ImageView3D, ImageView1D>::value));
CORRADE_VERIFY(!(std::is_convertible<ImageView1D, MutableImageView3D>::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<MutableImageView1D, MutableImageView3D>::value));
CORRADE_VERIFY(!(std::is_convertible<MutableImageView3D, MutableImageView1D>::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<CompressedImageView1D, CompressedImageView3D>::value));
CORRADE_VERIFY(!(std::is_convertible<CompressedImageView3D, CompressedImageView1D>::value));
CORRADE_VERIFY(!(std::is_convertible<CompressedImageView1D, MutableCompressedImageView3D>::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<MutableCompressedImageView1D, MutableCompressedImageView3D>::value));
CORRADE_VERIFY(!(std::is_convertible<MutableCompressedImageView3D, MutableCompressedImageView1D>::value));
}
void ImageViewTest::constructFromMutable() {
/* Copy of "Manual pixel size" in constructImplementationSpecific(), as
that exposes most fields */

Loading…
Cancel
Save