diff --git a/src/Magnum/BufferImage.cpp b/src/Magnum/BufferImage.cpp index 69a2266cb..0bef6d859 100644 --- a/src/Magnum/BufferImage.cpp +++ b/src/Magnum/BufferImage.cpp @@ -33,6 +33,10 @@ template BufferImage::BufferImage(const Pixe _buffer.setData(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(Implementation::imageDataSize(*this) <= dataSize, "BufferImage::BufferImage(): bad image data size, got" << dataSize << "but expected at least" << Implementation::imageDataSize(*this), ); +} + template BufferImage::BufferImage(const PixelStorage storage, const PixelFormat format, const PixelType type): _storage{storage}, _format{format}, _type{type}, _buffer{Buffer::TargetHint::PixelPack}, _dataSize{0} {} template void BufferImage::setData(const PixelStorage storage, const PixelFormat format, const PixelType type, const VectorTypeFor& size, Containers::ArrayView const data, const BufferUsage usage) { @@ -64,6 +68,16 @@ template CompressedBufferImage::CompressedBu _buffer.setData(data, usage); } +template CompressedBufferImage::CompressedBufferImage( + #ifndef MAGNUM_TARGET_GLES + const CompressedPixelStorage storage, + #endif + const CompressedPixelFormat format, const VectorTypeFor& size, Buffer&& buffer, const std::size_t dataSize) noexcept: + #ifndef MAGNUM_TARGET_GLES + _storage{storage}, + #endif + _format{format}, _size{size}, _buffer{std::move(buffer)}, _dataSize{dataSize} {} + template CompressedBufferImage::CompressedBufferImage( #ifndef MAGNUM_TARGET_GLES const CompressedPixelStorage storage diff --git a/src/Magnum/BufferImage.h b/src/Magnum/BufferImage.h index f292b6f8e..a77e865ce 100644 --- a/src/Magnum/BufferImage.h +++ b/src/Magnum/BufferImage.h @@ -74,6 +74,25 @@ template class BufferImage { */ explicit BufferImage(PixelFormat format, PixelType type, const VectorTypeFor& size, Containers::ArrayView data, BufferUsage usage): BufferImage{{}, format, type, size, data, usage} {} + /** + * @brief Construct from existing buffer + * @param storage Storage of pixel data + * @param format Format of pixel data + * @param type Data type of pixel data + * @param size Image size + * @param buffer Buffer + * @param dataSize Buffer data size + * + * If @p dataSize is 0, the buffer is unconditionally reallocated on + * the first call to @ref setData(). + */ + explicit BufferImage(PixelStorage storage, PixelFormat format, PixelType type, const VectorTypeFor& size, Buffer&& buffer, std::size_t dataSize) noexcept; + + /** @overload + * Similar to the above, but uses default @ref PixelStorage parameters. + */ + explicit BufferImage(PixelFormat format, PixelType type, const VectorTypeFor& size, Buffer&& buffer, std::size_t dataSize) noexcept: BufferImage{{}, format, type, size, std::move(buffer), dataSize} {} + #ifdef MAGNUM_BUILD_DEPRECATED /** @copybrief BufferImage(PixelFormat, PixelType, const VectorTypeFor&, Containers::ArrayView, BufferUsage) * @deprecated Use @ref BufferImage(PixelFormat, PixelType, const VectorTypeFor&, Containers::ArrayView, BufferUsage) @@ -282,6 +301,28 @@ template class CompressedBufferImage { */ explicit CompressedBufferImage(CompressedPixelFormat format, const VectorTypeFor& size, Containers::ArrayView data, BufferUsage usage); + #ifndef MAGNUM_TARGET_GLES + /** + * @brief Constructor + * @param storage Storage of compressed pixel data + * @param format Format of compressed pixel data + * @param size Image size + * @param data Image data + * @param usage Image buffer usage + * + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * @requires_gl Compressed pixel storage is hardcoded in OpenGL ES and + * WebGL. + */ + explicit CompressedBufferImage(CompressedPixelStorage storage, CompressedPixelFormat format, const VectorTypeFor& size, Buffer&& buffer, std::size_t dataSize) noexcept; + #endif + + /** @overload + * Similar the above, but uses default @ref CompressedPixelStorage + * parameters (or the hardcoded ones in OpenGL ES and WebGL). + */ + explicit CompressedBufferImage(CompressedPixelFormat format, const VectorTypeFor& size, Buffer&& buffer, std::size_t dataSize) noexcept; + #ifndef MAGNUM_TARGET_GLES /** * @brief Constructor @@ -460,6 +501,8 @@ template inline CompressedBufferImage& Compr #ifndef MAGNUM_TARGET_GLES template inline CompressedBufferImage::CompressedBufferImage(const CompressedPixelFormat format, const VectorTypeFor& size, const Containers::ArrayView data, const BufferUsage usage): CompressedBufferImage{{}, format, size, data, usage} {} +template inline CompressedBufferImage::CompressedBufferImage(const CompressedPixelFormat format, const VectorTypeFor& size, Buffer&& buffer, const std::size_t dataSize) noexcept: CompressedBufferImage{{}, format, size, std::move(buffer), dataSize} {} + template inline CompressedBufferImage::CompressedBufferImage(): CompressedBufferImage{CompressedPixelStorage{}} {} template inline void CompressedBufferImage::setData(const CompressedPixelFormat format, const VectorTypeFor& size, const Containers::ArrayView data, const BufferUsage usage) { diff --git a/src/Magnum/Test/BufferImageGLTest.cpp b/src/Magnum/Test/BufferImageGLTest.cpp index c7644ac40..5220c2840 100644 --- a/src/Magnum/Test/BufferImageGLTest.cpp +++ b/src/Magnum/Test/BufferImageGLTest.cpp @@ -36,6 +36,8 @@ struct BufferImageGLTest: OpenGLTester { void construct(); void constructCompressed(); + void constructBuffer(); + void constructBufferCompressed(); void constructCopy(); void constructCopyCompressed(); void constructMove(); @@ -51,6 +53,8 @@ struct BufferImageGLTest: OpenGLTester { BufferImageGLTest::BufferImageGLTest() { addTests({&BufferImageGLTest::construct, &BufferImageGLTest::constructCompressed, + &BufferImageGLTest::constructBuffer, + &BufferImageGLTest::constructBufferCompressed, &BufferImageGLTest::constructCopy, &BufferImageGLTest::constructCopyCompressed, &BufferImageGLTest::constructMove, @@ -115,6 +119,70 @@ void BufferImageGLTest::constructCompressed() { #endif } +void BufferImageGLTest::constructBuffer() { + const char data[] = { 'a', 'b', 'c' }; + Buffer buffer; + buffer.setData(data, BufferUsage::StaticDraw); + const UnsignedInt id = buffer.id(); + + BufferImage2D a{PixelStorage{}.setAlignment(1), + PixelFormat::Red, PixelType::UnsignedByte, {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(), 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; + buffer.setData(data, BufferUsage::StaticDraw); + const UnsignedInt id = buffer.id(); + + CompressedBufferImage2D a{ + #ifndef MAGNUM_TARGET_GLES + CompressedPixelStorage{}.setCompressedBlockSize(Vector3i{4}), + #endif + CompressedPixelFormat::RGBAS3tcDxt1, + {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(), 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::constructCopy() { CORRADE_VERIFY(!(std::is_constructible{})); CORRADE_VERIFY(!(std::is_assignable{}));