diff --git a/src/Magnum/BufferImage.cpp b/src/Magnum/BufferImage.cpp index ae8b793c9..b4f33ea45 100644 --- a/src/Magnum/BufferImage.cpp +++ b/src/Magnum/BufferImage.cpp @@ -28,20 +28,27 @@ namespace Magnum { #ifndef MAGNUM_TARGET_GLES2 -template BufferImage::BufferImage(const PixelStorage storage, const PixelFormat format, const PixelType type, const VectorTypeFor& size, Containers::ArrayView const data, const BufferUsage usage): _storage{storage}, _format{format}, _type{type}, _size{size}, _buffer{Buffer::TargetHint::PixelPack} { +template BufferImage::BufferImage(const PixelStorage storage, const PixelFormat format, const PixelType type, const VectorTypeFor& size, Containers::ArrayView const data, const BufferUsage usage): _storage{storage}, _format{format}, _type{type}, _size{size}, _buffer{Buffer::TargetHint::PixelPack}, _dataSize{data.size()} { CORRADE_ASSERT(Implementation::imageDataSize(*this) <= data.size(), "BufferImage::BufferImage(): bad image data size, got" << data.size() << "but expected at least" << Implementation::imageDataSize(*this), ); _buffer.setData(data, usage); } -template BufferImage::BufferImage(const PixelStorage storage, const PixelFormat format, const PixelType type): _storage{storage}, _format{format}, _type{type}, _buffer{Buffer::TargetHint::PixelPack} {} +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) { _storage = storage; _format = format; _type = type; _size = size; - CORRADE_ASSERT(Implementation::imageDataSize(*this) <= data.size(), "BufferImage::setData(): bad image data size, got" << data.size() << "but expected at least" << Implementation::imageDataSize(*this), ); - _buffer.setData(data, usage); + + /* Keep the old storage if zero-sized nullptr buffer was passed */ + if(data.data() == nullptr && data.size() == 0) + CORRADE_ASSERT(Implementation::imageDataSize(*this) <= _dataSize, "BufferImage::setData(): bad current storage size, got" << _dataSize << "but expected at least" << Implementation::imageDataSize(*this), ); + else { + CORRADE_ASSERT(Implementation::imageDataSize(*this) <= data.size(), "BufferImage::setData(): bad image data size, got" << data.size() << "but expected at least" << Implementation::imageDataSize(*this), ); + _buffer.setData(data, usage); + _dataSize = data.size(); + } } template CompressedBufferImage::CompressedBufferImage( diff --git a/src/Magnum/BufferImage.h b/src/Magnum/BufferImage.h index e6a8f36c2..b50beb09c 100644 --- a/src/Magnum/BufferImage.h +++ b/src/Magnum/BufferImage.h @@ -148,6 +148,9 @@ template class BufferImage { return Implementation::imageDataProperties(*this); } + /** @brief Currently allocated data size */ + std::size_t dataSize() const { return _dataSize; } + /** @brief Image buffer */ Buffer& buffer() { return _buffer; } @@ -160,7 +163,9 @@ template class BufferImage { * @param data Image data * @param usage Image buffer usage * - * Updates the image buffer with given data. + * Updates the image buffer with given data. Passing `nullptr` + * zero-sized @p data will not reallocate current storage, but expects + * that current data size is large enough for the new parameters. * @see @ref Buffer::setData() * @todo Make it more flexible (usable with * @extension{ARB,buffer_storage}, avoiding relocations...) @@ -201,6 +206,7 @@ template class BufferImage { PixelType _type; Math::Vector _size; Buffer _buffer; + std::size_t _dataSize; }; /** @brief One-dimensional buffer image */