diff --git a/src/AbstractTexture.cpp b/src/AbstractTexture.cpp index 70d443b5b..22c898d27 100644 --- a/src/AbstractTexture.cpp +++ b/src/AbstractTexture.cpp @@ -978,19 +978,6 @@ template void AbstractTexture::image<3>(GLenum, GLint, BufferImage<3>&, Buffer:: #endif #ifndef DOXYGEN_GENERATING_OUTPUT -#ifndef MAGNUM_TARGET_GLES2 -namespace Implementation { - template const GLvoid* ImageHelper>::dataOrPixelUnpackBuffer(BufferImage* image) { - image->buffer()->bind(Buffer::Target::PixelUnpack); - return nullptr; - } - - template struct ImageHelper; - template struct ImageHelper; - template struct ImageHelper; -} -#endif - #ifndef MAGNUM_TARGET_GLES Math::Vector<1, GLint> AbstractTexture::DataHelper<1>::imageSize(AbstractTexture* texture, GLenum target, GLint level) { Math::Vector<1, GLint> value; @@ -1014,6 +1001,84 @@ Vector3i AbstractTexture::DataHelper<3>::imageSize(AbstractTexture* texture, GLe } #endif +#ifndef MAGNUM_TARGET_GLES +void AbstractTexture::DataHelper<1>::setImage(AbstractTexture* const texture, const GLenum target, const GLint level, const TextureFormat internalFormat, const ImageReference1D& image) { + Buffer::unbind(Buffer::Target::PixelUnpack); + (texture->*image1DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), image.data()); +} + +void AbstractTexture::DataHelper<1>::setImage(AbstractTexture* const texture, const GLenum target, const GLint level, const TextureFormat internalFormat, BufferImage1D& image) { + image.buffer()->bind(Buffer::Target::PixelUnpack); + (texture->*image1DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), nullptr); +} + +void AbstractTexture::DataHelper<1>::setSubImage(AbstractTexture* const texture, const GLenum target, const GLint level, const Math::Vector<1, GLint>& offset, const ImageReference1D& image) { + Buffer::unbind(Buffer::Target::PixelUnpack); + (texture->*subImage1DImplementation)(target, level, offset, image.size(), image.format(), image.type(), image.data()); +} + +void AbstractTexture::DataHelper<1>::setSubImage(AbstractTexture* const texture, const GLenum target, const GLint level, const Math::Vector<1, GLint>& offset, BufferImage1D& image) { + image.buffer()->bind(Buffer::Target::PixelUnpack); + (texture->*subImage1DImplementation)(target, level, offset, image.size(), image.format(), image.type(), nullptr); +} +#endif + +void AbstractTexture::DataHelper<2>::setImage(AbstractTexture* const texture, const GLenum target, const GLint level, const TextureFormat internalFormat, const ImageReference2D& image) { + #ifndef MAGNUM_TARGET_GLES2 + Buffer::unbind(Buffer::Target::PixelUnpack); + #endif + (texture->*image2DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), image.data()); +} + +#ifndef MAGNUM_TARGET_GLES2 +void AbstractTexture::DataHelper<2>::setImage(AbstractTexture* const texture, const GLenum target, const GLint level, const TextureFormat internalFormat, BufferImage2D& image) { + image.buffer()->bind(Buffer::Target::PixelUnpack); + (texture->*image2DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), nullptr); +} +#endif + +void AbstractTexture::DataHelper<2>::setSubImage(AbstractTexture* const texture, const GLenum target, const GLint level, const Vector2i& offset, const ImageReference2D& image) { + #ifndef MAGNUM_TARGET_GLES2 + Buffer::unbind(Buffer::Target::PixelUnpack); + #endif + (texture->*subImage2DImplementation)(target, level, offset, image.size(), image.format(), image.type(), image.data()); +} + +#ifndef MAGNUM_TARGET_GLES2 +void AbstractTexture::DataHelper<2>::setSubImage(AbstractTexture* const texture, const GLenum target, const GLint level, const Vector2i& offset, BufferImage2D& image) { + image.buffer()->bind(Buffer::Target::PixelUnpack); + (texture->*subImage2DImplementation)(target, level, offset, image.size(), image.format(), image.type(), nullptr); +} +#endif + +void AbstractTexture::DataHelper<3>::setImage(AbstractTexture* const texture, const GLenum target, const GLint level, const TextureFormat internalFormat, const ImageReference3D& image) { + #ifndef MAGNUM_TARGET_GLES2 + Buffer::unbind(Buffer::Target::PixelUnpack); + #endif + (texture->*image3DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), image.data()); +} + +#ifndef MAGNUM_TARGET_GLES2 +void AbstractTexture::DataHelper<3>::setImage(AbstractTexture* const texture, const GLenum target, const GLint level, const TextureFormat internalFormat, BufferImage3D& image) { + image.buffer()->bind(Buffer::Target::PixelUnpack); + (texture->*image3DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), nullptr); +} +#endif + +void AbstractTexture::DataHelper<3>::setSubImage(AbstractTexture* const texture, const GLenum target, const GLint level, const Vector3i& offset, const ImageReference3D& image) { + #ifndef MAGNUM_TARGET_GLES2 + Buffer::unbind(Buffer::Target::PixelUnpack); + #endif + (texture->*subImage3DImplementation)(target, level, offset, image.size(), image.format(), image.type(), image.data()); +} + +#ifndef MAGNUM_TARGET_GLES2 +void AbstractTexture::DataHelper<3>::setSubImage(AbstractTexture* const texture, const GLenum target, const GLint level, const Vector3i& offset, BufferImage3D& image) { + image.buffer()->bind(Buffer::Target::PixelUnpack); + (texture->*subImage3DImplementation)(target, level, offset, image.size(), image.format(), image.type(), nullptr); +} +#endif + void AbstractTexture::DataHelper<2>::setWrapping(AbstractTexture* texture, const Array2D& wrapping) { #ifndef MAGNUM_TARGET_GLES CORRADE_ASSERT(texture->_target != GL_TEXTURE_RECTANGLE || ((wrapping.x() == Sampler::Wrapping::ClampToEdge || wrapping.x() == Sampler::Wrapping::ClampToBorder) && (wrapping.y() == Sampler::Wrapping::ClampToEdge || wrapping.y() == Sampler::Wrapping::ClampToEdge)), "AbstractTexture: rectangle texture wrapping must either clamp to border or to edge", ); diff --git a/src/AbstractTexture.h b/src/AbstractTexture.h index 83b0d3249..0cf278646 100644 --- a/src/AbstractTexture.h +++ b/src/AbstractTexture.h @@ -419,25 +419,8 @@ class MAGNUM_EXPORT AbstractTexture { }; #ifndef DOXYGEN_GENERATING_OUTPUT -namespace Implementation { - template struct ImageHelper { - static const GLvoid* dataOrPixelUnpackBuffer(Image* image) { - #ifndef MAGNUM_TARGET_GLES2 - Buffer::unbind(Buffer::Target::PixelUnpack); - #endif - return image->data(); - } - }; - - #ifndef MAGNUM_TARGET_GLES2 - template struct MAGNUM_EXPORT ImageHelper> { - static const GLvoid* dataOrPixelUnpackBuffer(BufferImage* image); - }; - #endif -} - #ifndef MAGNUM_TARGET_GLES -template<> struct AbstractTexture::DataHelper<1> { +template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<1> { enum class Target: GLenum { Texture1D = GL_TEXTURE_1D }; @@ -454,13 +437,11 @@ template<> struct AbstractTexture::DataHelper<1> { (texture->*storage1DImplementation)(target, levels, internalFormat, size); } - template static typename std::enable_if::type setImage(AbstractTexture* texture, GLenum target, GLint level, TextureFormat internalFormat, Image* image) { - (texture->*image1DImplementation)(target, level, internalFormat, image->size(), image->format(), image->type(), Implementation::ImageHelper::dataOrPixelUnpackBuffer(image)); - } + static void setImage(AbstractTexture* texture, GLenum target, GLint level, TextureFormat internalFormat, const ImageReference1D& image); + static void setImage(AbstractTexture* texture, GLenum target, GLint level, TextureFormat internalFormat, BufferImage1D& image); - template static typename std::enable_if::type setSubImage(AbstractTexture* texture, GLenum target, GLint level, const Math::Vector<1, GLint>& offset, Image* image) { - (texture->*subImage1DImplementation)(target, level, offset, image->size(), image->format(), image->type(), Implementation::ImageHelper::dataOrPixelUnpackBuffer(image)); - } + static void setSubImage(AbstractTexture* texture, GLenum target, GLint level, const Math::Vector<1, GLint>& offset, const ImageReference1D& image); + static void setSubImage(AbstractTexture* texture, GLenum target, GLint level, const Math::Vector<1, GLint>& offset, BufferImage1D& image); static void invalidateSubImage(AbstractTexture* texture, GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLint>& size) { (texture->*invalidateSubImageImplementation)(level, {offset[0], 0, 0}, {size[0], 1, 1}); @@ -489,17 +470,15 @@ template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<2> { (texture->*storage2DImplementation)(target, levels, internalFormat, size); } - template static typename std::enable_if::type setImage(AbstractTexture* texture, GLenum target, GLint level, TextureFormat internalFormat, Image* image) { - (texture->*image2DImplementation)(target, level, internalFormat, image->size(), image->format(), image->type(), Implementation::ImageHelper::dataOrPixelUnpackBuffer(image)); - } - - template static typename std::enable_if::type setSubImage(AbstractTexture* texture, GLenum target, GLint level, const Vector2i& offset, Image* image) { - (texture->*subImage2DImplementation)(target, level, offset, image->size(), image->format(), image->type(), Implementation::ImageHelper::dataOrPixelUnpackBuffer(image)); - } + static void setImage(AbstractTexture* texture, GLenum target, GLint level, TextureFormat internalFormat, const ImageReference2D& image); + #ifndef MAGNUM_TARGET_GLES2 + static void setImage(AbstractTexture* texture, GLenum target, GLint level, TextureFormat internalFormat, BufferImage2D& image); + #endif - template static typename std::enable_if::type setSubImage(AbstractTexture* texture, GLenum target, GLint level, const Vector2i& offset, Image* image) { - (texture->*subImage2DImplementation)(target, level, offset, Vector2i(image->size(), 1), image->format(), image->type(), Implementation::ImageHelper::dataOrPixelUnpackBuffer(image)); - } + static void setSubImage(AbstractTexture* texture, GLenum target, GLint level, const Vector2i& offset, const ImageReference2D& image); + #ifndef MAGNUM_TARGET_GLES2 + static void setSubImage(AbstractTexture* texture, GLenum target, GLint level, const Vector2i& offset, BufferImage2D& image); + #endif static void invalidateSubImage(AbstractTexture* texture, GLint level, const Vector2i& offset, const Vector2i& size) { (texture->*invalidateSubImageImplementation)(level, {offset, 0}, {size, 1}); @@ -530,17 +509,15 @@ template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<3> { (texture->*storage3DImplementation)(target, levels, internalFormat, size); } - template static typename std::enable_if::type setImage(AbstractTexture* texture, GLenum target, GLint level, TextureFormat internalFormat, Image* image) { - (texture->*image3DImplementation)(target, level, internalFormat, image->size(), image->format(), image->type(), Implementation::ImageHelper::dataOrPixelUnpackBuffer(image)); - } - - template static typename std::enable_if::type setSubImage(AbstractTexture* texture, GLenum target, GLint level, const Vector3i& offset, Image* image) { - (texture->*subImage3DImplementation)(target, level, offset, image->size(), image->format(), image->type(), Implementation::ImageHelper::dataOrPixelUnpackBuffer(image)); - } + static void setImage(AbstractTexture* texture, GLenum target, GLint level, TextureFormat internalFormat, const ImageReference3D& image); + #ifndef MAGNUM_TARGET_GLES2 + static void setImage(AbstractTexture* texture, GLenum target, GLint level, TextureFormat internalFormat, BufferImage3D& image); + #endif - template static typename std::enable_if::type setSubImage(AbstractTexture* texture, GLenum target, GLint level, const Vector3i& offset, Image* image) { - (texture->*subImage3DImplementation)(target, level, offset, Vector3i(image->size(), 1), image->format(), image->type(), Implementation::ImageHelper::dataOrPixelUnpackBuffer(image)); - } + static void setSubImage(AbstractTexture* texture, GLenum target, GLint level, const Vector3i& offset, const ImageReference3D& image); + #ifndef MAGNUM_TARGET_GLES2 + static void setSubImage(AbstractTexture* texture, GLenum target, GLint level, const Vector3i& offset, BufferImage3D& image); + #endif static void invalidateSubImage(AbstractTexture* texture, GLint level, const Vector3i& offset, const Vector3i& size) { (texture->*invalidateSubImageImplementation)(level, offset, size); diff --git a/src/CubeMapTexture.h b/src/CubeMapTexture.h index 0bc8a642c..2308568f2 100644 --- a/src/CubeMapTexture.h +++ b/src/CubeMapTexture.h @@ -165,33 +165,47 @@ class CubeMapTexture: public AbstractTexture { * @param coordinate Coordinate * @param level Mip level * @param internalFormat Internal format - * @param image Image, ImageReference, BufferImage or - * Trade::ImageData of the same dimension count + * @param image %Image * @return Pointer to self (for method chaining) * * See Texture::setImage() for more information. */ - template CubeMapTexture* setImage(Coordinate coordinate, Int level, TextureFormat internalFormat, Image* image) { + CubeMapTexture* setImage(Coordinate coordinate, Int level, TextureFormat internalFormat, const ImageReference2D& image) { DataHelper<2>::setImage(this, static_cast(coordinate), level, internalFormat, image); return this; } + #ifndef MAGNUM_TARGET_GLES2 + /** @overload */ + CubeMapTexture* setImage(Coordinate coordinate, Int level, TextureFormat internalFormat, BufferImage2D& image) { + DataHelper<2>::setImage(this, static_cast(coordinate), level, internalFormat, image); + return this; + } + #endif + /** * @brief Set image subdata * @param coordinate Coordinate * @param level Mip level * @param offset Offset where to put data in the texture - * @param image Image, ImageReference, BufferImage or - * Trade::ImageData of the same or one less dimension count + * @param image %Image * @return Pointer to self (for method chaining) * * See Texture::setSubImage() for more information. */ - template CubeMapTexture* setSubImage(Coordinate coordinate, Int level, const Vector2i& offset, const Image* image) { + CubeMapTexture* setSubImage(Coordinate coordinate, Int level, const Vector2i& offset, const ImageReference2D& image) { DataHelper<2>::setSubImage(this, static_cast(coordinate), level, offset, image); return this; } + #ifndef MAGNUM_TARGET_GLES2 + /** @overload */ + CubeMapTexture* setSubImage(Coordinate coordinate, Int level, const Vector2i& offset, BufferImage2D& image) { + DataHelper<2>::setSubImage(this, static_cast(coordinate), level, offset, image); + return this; + } + #endif + /** * @brief Invalidate texture subimage * @param level Mip level diff --git a/src/CubeMapTextureArray.h b/src/CubeMapTextureArray.h index 0f64d3720..7219706c8 100644 --- a/src/CubeMapTextureArray.h +++ b/src/CubeMapTextureArray.h @@ -175,7 +175,13 @@ class CubeMapTextureArray: public AbstractTexture { * * See Texture::setImage() for more information. */ - template CubeMapTextureArray* setImage(Int level, TextureFormat internalFormat, T* image) { + CubeMapTextureArray* setImage(Int level, TextureFormat internalFormat, const ImageReference3D& image) { + DataHelper<3>::setImage(this, GL_TEXTURE_CUBE_MAP_ARRAY, level, internalFormat, image); + return this; + } + + /** @overload */ + CubeMapTextureArray* setImage(Int level, TextureFormat internalFormat, BufferImage3D& image) { DataHelper<3>::setImage(this, GL_TEXTURE_CUBE_MAP_ARRAY, level, internalFormat, image); return this; } @@ -199,27 +205,14 @@ class CubeMapTextureArray: public AbstractTexture { * * @see setSubImage(Int, Coordinate, Int, const Math::Vector<2, Int>&, const Image*) */ - template CubeMapTextureArray* setSubImage(Int level, const Vector3i& offset, const Image* image) { - DataHelper<3>::setSubImage(this, GL_TEXTURE_CUBE_MAP_ARRAY, level, offset, image, Vector3i(Math::Vector())); + CubeMapTextureArray* setSubImage(Int level, const Vector3i& offset, const ImageReference3D& image) { + DataHelper<3>::setSubImage(this, GL_TEXTURE_CUBE_MAP_ARRAY, level, offset, image); return this; } - /** - * @brief Set texture image 2D subdata - * @param layer Array layer - * @param coordinate Coordinate - * @param level Mip level - * @param offset Offset where to put data in the texture - * @param image Image2D, ImageReference2D, BufferImage2D or - * Trade::ImageData2D - * @return Pointer to self (for method chaining) - * - * See Texture::setSubImage() for more information. - * - * @see setSubImage(Int, const Math::Vector<3, Int>&, const Image*) - */ - template CubeMapTextureArray* setSubImage(Int layer, Coordinate coordinate, Int level, const Vector2i& offset, const Image* image) { - DataHelper<3>::setSubImage(this, GL_TEXTURE_CUBE_MAP_ARRAY, level, Vector3i(offset, layer*6+static_cast(coordinate)), image, Vector2i(Math::Vector())); + /** @overload */ + CubeMapTextureArray* setSubImage(Int level, const Vector3i& offset, BufferImage3D& image) { + DataHelper<3>::setSubImage(this, GL_TEXTURE_CUBE_MAP_ARRAY, level, offset, image); return this; } diff --git a/src/Text/DistanceFieldGlyphCache.cpp b/src/Text/DistanceFieldGlyphCache.cpp index 83daad155..78ce1b833 100644 --- a/src/Text/DistanceFieldGlyphCache.cpp +++ b/src/Text/DistanceFieldGlyphCache.cpp @@ -25,10 +25,10 @@ #include "DistanceFieldGlyphCache.h" #include "Extensions.h" -#include "Image.h" #ifndef CORRADE_NO_ASSERT #include "ImageFormat.h" #endif +#include "ImageReference.h" #include "TextureFormat.h" #include "TextureTools/DistanceField.h" @@ -52,25 +52,25 @@ DistanceFieldGlyphCache::DistanceFieldGlyphCache(const Vector2i& originalSize, c initialize(internalFormat, distanceFieldSize); } -void DistanceFieldGlyphCache::setImage(const Vector2i& offset, Image2D* const image) { +void DistanceFieldGlyphCache::setImage(const Vector2i& offset, const ImageReference2D& image) { #ifndef MAGNUM_TARGET_GLES MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::texture_rg); #endif #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES3) const TextureFormat internalFormat = TextureFormat::R8; - CORRADE_ASSERT(image->format() == ImageFormat::Red, - "Text::DistanceFieldGlyphCache::setImage(): expected" << ImageFormat::Red << "but got" << image->format(), ); + CORRADE_ASSERT(image.format() == ImageFormat::Red, + "Text::DistanceFieldGlyphCache::setImage(): expected" << ImageFormat::Red << "but got" << image.format(), ); #else TextureFormat internalFormat; if(Context::current()->isExtensionSupported()) { internalFormat = TextureFormat::Red; - CORRADE_ASSERT(image->format() == ImageFormat::Red, - "Text::DistanceFieldGlyphCache::setImage(): expected" << ImageFormat::Red << "but got" << image->format(), ); + CORRADE_ASSERT(image.format() == ImageFormat::Red, + "Text::DistanceFieldGlyphCache::setImage(): expected" << ImageFormat::Red << "but got" << image.format(), ); } else { internalFormat = TextureFormat::Luminance; - CORRADE_ASSERT(image->format() == ImageFormat::Luminance, - "Text::DistanceFieldGlyphCache::setImage(): expected" << ImageFormat::Luminance << "but got" << image->format(), ); + CORRADE_ASSERT(image.format() == ImageFormat::Luminance, + "Text::DistanceFieldGlyphCache::setImage(): expected" << ImageFormat::Luminance << "but got" << image.format(), ); } #endif @@ -81,10 +81,10 @@ void DistanceFieldGlyphCache::setImage(const Vector2i& offset, Image2D* const im ->setImage(0, internalFormat, image); /* Create distance field from input texture */ - TextureTools::distanceField(&input, &_texture, Rectanglei::fromSize(offset*scale, image->size()*scale), radius, image->size()); + TextureTools::distanceField(&input, &_texture, Rectanglei::fromSize(offset*scale, image.size()*scale), radius, image.size()); } -void DistanceFieldGlyphCache::setDistanceFieldImage(const Vector2i& offset, Image2D* const image) { +void DistanceFieldGlyphCache::setDistanceFieldImage(const Vector2i& offset, const ImageReference2D& image) { _texture.setSubImage(0, offset, image); } diff --git a/src/Text/DistanceFieldGlyphCache.h b/src/Text/DistanceFieldGlyphCache.h index bb5d1194c..011d11943 100644 --- a/src/Text/DistanceFieldGlyphCache.h +++ b/src/Text/DistanceFieldGlyphCache.h @@ -78,7 +78,7 @@ class MAGNUM_TEXT_EXPORT DistanceFieldGlyphCache: public GlyphCache { * Uploads image for one or more glyphs to given offset in original * cache texture. The texture is then converted to distance field. */ - void setImage(const Vector2i& offset, Image2D* image) override; + void setImage(const Vector2i& offset, const ImageReference2D& image) override; /** * @brief Set distance field cache image @@ -86,7 +86,7 @@ class MAGNUM_TEXT_EXPORT DistanceFieldGlyphCache: public GlyphCache { * Uploads already computed distance field image to given offset in * distance field texture. */ - void setDistanceFieldImage(const Vector2i& offset, Image2D* image); + void setDistanceFieldImage(const Vector2i& offset, const ImageReference2D& image); private: const Vector2 scale; diff --git a/src/Text/GlyphCache.cpp b/src/Text/GlyphCache.cpp index 8d96ef2a3..115e1ece6 100644 --- a/src/Text/GlyphCache.cpp +++ b/src/Text/GlyphCache.cpp @@ -77,7 +77,7 @@ void GlyphCache::insert(const UnsignedInt glyph, Vector2i position, Rectanglei r glyphs.insert({glyph, {position, rectangle}}); } -void GlyphCache::setImage(const Vector2i& offset, Image2D* const image) { +void GlyphCache::setImage(const Vector2i& offset, const ImageReference2D& image) { _texture.setSubImage(0, offset, image); } diff --git a/src/Text/GlyphCache.h b/src/Text/GlyphCache.h index 35d93cf52..39dacc9c0 100644 --- a/src/Text/GlyphCache.h +++ b/src/Text/GlyphCache.h @@ -135,7 +135,7 @@ class MAGNUM_TEXT_EXPORT GlyphCache { * Uploads image for one or more glyphs to given offset in cache * texture. */ - virtual void setImage(const Vector2i& offset, Image2D* image); + virtual void setImage(const Vector2i& offset, const ImageReference2D& image); #ifdef DOXYGEN_GENERATING_OUTPUT private: diff --git a/src/Texture.h b/src/Texture.h index a6c6e0a68..dce833157 100644 --- a/src/Texture.h +++ b/src/Texture.h @@ -346,12 +346,9 @@ template class Texture: public AbstractTexture { * @brief Set image data * @param level Mip level * @param internalFormat Internal format - * @param image Image, ImageReference, BufferImage or - * Trade::ImageData of the same dimension count + * @param image %Image * @return Pointer to self (for method chaining) * - * The image is not deleted afterwards. - * * For better performance when generating mipmaps using * generateMipmap() or calling setImage() more than once use * setStorage() and setSubImage() instead. @@ -364,28 +361,26 @@ template class Texture: public AbstractTexture { * @fn_gl_extension{TextureImage2D,EXT,direct_state_access}/ * @fn_gl_extension{TextureImage3D,EXT,direct_state_access} */ - template Texture* setImage(Int level, TextureFormat internalFormat, Image* image) { + Texture* setImage(Int level, TextureFormat internalFormat, const ImageReference& image) { DataHelper::setImage(this, _target, level, internalFormat, image); return this; } + #ifndef MAGNUM_TARGET_GLES2 + /** @overload */ + Texture* setImage(Int level, TextureFormat internalFormat, BufferImage& image) { + DataHelper::setImage(this, _target, level, internalFormat, image); + return this; + } + #endif + /** * @brief Set image subdata * @param level Mip level * @param offset Offset where to put data in the texture - * @param image Image, ImageReference, BufferImage or - * Trade::ImageData of the same or one less dimension count + * @param image %Image * @return Pointer to self (for method chaining) * - * The image is not deleted afterwards. The image can have either the - * same dimension count or have one dimension less, but at least one - * dimension. - * - * If the image has one dimension less than the texture, the image is - * taken as if it had the last dimension equal to 1. It can be used - * for e.g. updating 3D texture with multiple 2D images or for filling - * 1D texture array (which is two-dimensional) with 1D images. - * * If @extension{EXT,direct_state_access} is not available, the * texture is bound to some layer before the operation. * @see setStorage(), setImage(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} @@ -394,10 +389,18 @@ template class Texture: public AbstractTexture { * @fn_gl_extension{TextureSubImage2D,EXT,direct_state_access}/ * @fn_gl_extension{TextureSubImage3D,EXT,direct_state_access} */ - template Texture* setSubImage(Int level, const typename DimensionTraits::VectorType& offset, Image* image) { + Texture* setSubImage(Int level, const typename DimensionTraits::VectorType& offset, const ImageReference& image) { + DataHelper::setSubImage(this, _target, level, offset, image); + return this; + } + + #ifndef MAGNUM_TARGET_GLES2 + /** @overload */ + Texture* setSubImage(Int level, const typename DimensionTraits::VectorType& offset, BufferImage& image) { DataHelper::setSubImage(this, _target, level, offset, image); return this; } + #endif /** * @brief Invalidate texture subimage