From 2ba5af95fb7341b0e6b212e28d03208c6747aae5 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Mon, 1 Feb 2021 22:17:35 +0200 Subject: [PATCH] Require texture data to be uploaded in a format matching the storage This is almost always the case anyway. It makes things simpler as I don't have to figure out what to do if someone tries to upload RGB data into a LUMINANCE_ALPHA texture, which is really an RG texture in disguise. There are some potential exceptions, like uploading FLOAT data to a texture with HALF_FLOAT storage. I'll write conversion routines if those become relevant. --- source/ambientocclusion.cpp | 2 +- source/colorcurve.cpp | 6 ++--- source/texture.cpp | 30 ++++++++++------------ source/texture.h | 6 ++--- source/texture1d.cpp | 46 ++++++++++++++++++++++----------- source/texture1d.h | 6 +++-- source/texture2d.cpp | 46 ++++++++++++++++++++++----------- source/texture2d.h | 24 +++++++++-------- source/texture2darray.cpp | 17 ++++++++++--- source/texture2darray.h | 3 ++- source/texture3d.cpp | 46 ++++++++++++++++++++++----------- source/texture3d.h | 26 +++++++++++-------- source/texturecube.cpp | 51 ++++++++++++++++++++++++------------- source/texturecube.h | 18 ++++++++----- 14 files changed, 205 insertions(+), 122 deletions(-) diff --git a/source/ambientocclusion.cpp b/source/ambientocclusion.cpp index b1dccc0e..1cfdff09 100644 --- a/source/ambientocclusion.cpp +++ b/source/ambientocclusion.cpp @@ -34,7 +34,7 @@ AmbientOcclusion::AmbientOcclusion(unsigned w, unsigned h, float): data[i*4+2] = 255-s; data[i*4+3] = ((i+i/4)%2)*255; } - rotate_lookup.image(0, RGBA, UNSIGNED_BYTE, data); + rotate_lookup.image(0, data); texturing.attach(3, rotate_lookup); diff --git a/source/colorcurve.cpp b/source/colorcurve.cpp index 1f6f7bf9..78a7fc16 100644 --- a/source/colorcurve.cpp +++ b/source/colorcurve.cpp @@ -50,7 +50,7 @@ void ColorCurve::set_gamma(float g) unsigned char curve_data[256]; for(unsigned i=0; i<256; ++i) curve_data[i] = pow(i/255.0f, 1/g)*255+0.5f; - curve.image(0, LUMINANCE, UNSIGNED_BYTE, curve_data); + curve.image(0, curve_data); } void ColorCurve::set_srgb() @@ -59,7 +59,7 @@ void ColorCurve::set_srgb() curve_data[0] = 0; for(unsigned i=1; i<256; ++i) curve_data[i] = to_srgb(i/255.0f)*255+0.5f; - curve.image(0, LUMINANCE, UNSIGNED_BYTE, curve_data); + curve.image(0, curve_data); } void ColorCurve::set_linear() @@ -67,7 +67,7 @@ void ColorCurve::set_linear() unsigned char curve_data[256]; for(unsigned i=0; i<256; ++i) curve_data[i] = i; - curve.image(0, LUMINANCE, UNSIGNED_BYTE, curve_data); + curve.image(0, curve_data); } void ColorCurve::render(Renderer &renderer, const Texture2D &color_buf, const Texture2D &) diff --git a/source/texture.cpp b/source/texture.cpp index cf32ca30..b747a2a6 100644 --- a/source/texture.cpp +++ b/source/texture.cpp @@ -25,7 +25,8 @@ int Texture::swizzle_orders[] = Texture::Texture(GLenum t, ResourceManager *m): id(0), target(t), - ifmt(RGB8), + format(RGB8), + storage_fmt(RGB8), swizzle(NO_SWIZZLE), auto_gen_mipmap(false), default_sampler(*this) @@ -47,45 +48,40 @@ Texture::~Texture() glDeleteTextures(1, &id); } -void Texture::set_internal_format(PixelFormat fmt) +void Texture::set_format(PixelFormat fmt) { PixelComponents comp = get_components(fmt); + PixelComponents st_comp = comp; FormatSwizzle swiz = NO_SWIZZLE; switch(comp) { case LUMINANCE: - comp = RED; + st_comp = RED; swiz = R_TO_LUMINANCE; break; case LUMINANCE_ALPHA: - comp = RG; + st_comp = RG; swiz = RG_TO_LUMINANCE_ALPHA; break; case BGR: - comp = RGB; + st_comp = RGB; swiz = RGB_TO_BGR; break; case BGRA: - comp = RGBA; + st_comp = RGBA; swiz = RGB_TO_BGR; break; default:; } - fmt = make_pixelformat(comp, get_component_type(fmt)); - require_pixelformat(fmt); + PixelFormat st_fmt = make_pixelformat(st_comp, get_component_type(fmt)); + require_pixelformat(st_fmt); if(swiz!=NO_SWIZZLE) static Require _req(ARB_texture_swizzle); - ifmt = fmt; - swizzle = swiz; -} -PixelComponents Texture::get_upload_components(PixelComponents comp) const -{ - if(comp==LUMINANCE || comp==LUMINANCE_ALPHA || comp==BGR || comp==BGRA) - return get_components(ifmt); - else - return comp; + format = fmt; + storage_fmt = st_fmt; + swizzle = swiz; } void Texture::apply_swizzle() diff --git a/source/texture.h b/source/texture.h index 6c0fbf25..30c6496a 100644 --- a/source/texture.h +++ b/source/texture.h @@ -70,7 +70,8 @@ protected: unsigned id; GLenum target; - PixelFormat ifmt; + PixelFormat format; + PixelFormat storage_fmt; FormatSwizzle swizzle; bool auto_gen_mipmap; Sampler default_sampler; @@ -84,8 +85,7 @@ public: ~Texture(); protected: - void set_internal_format(PixelFormat); - PixelComponents get_upload_components(PixelComponents) const; + void set_format(PixelFormat); void apply_swizzle(); void set_parameter_i(GLenum, int) const; diff --git a/source/texture1d.cpp b/source/texture1d.cpp index 24266150..553d4ffa 100644 --- a/source/texture1d.cpp +++ b/source/texture1d.cpp @@ -26,7 +26,7 @@ void Texture1D::storage(PixelFormat fmt, unsigned wd, unsigned lv) if(wd==0) throw invalid_argument("Texture1D::storage"); - set_internal_format(fmt); + set_format(fmt); width = wd; levels = get_n_levels(); if(lv) @@ -46,17 +46,17 @@ void Texture1D::allocate(unsigned level) { Conditional _bind(!ARB_direct_state_access, this); if(ARB_direct_state_access) - glTextureStorage1D(id, levels, ifmt, width); + glTextureStorage1D(id, levels, storage_fmt, width); else - glTexStorage1D(target, levels, ifmt, width); + glTexStorage1D(target, levels, storage_fmt, width); apply_swizzle(); allocated |= (1< _bind(!ARB_direct_state_access, this); allocate(level); - comp = get_upload_components(comp); + PixelComponents comp = get_components(storage_fmt); + DataType type = get_component_type(storage_fmt); if(ARB_direct_state_access) glTextureSubImage1D(id, level, x, wd, comp, type, data); else @@ -101,6 +112,13 @@ void Texture1D::sub_image(unsigned level, int x, unsigned wd, PixelComponents co generate_mipmap(); } +void Texture1D::sub_image(unsigned level, int x, unsigned wd, PixelComponents comp, DataType type, const void *data) +{ + if(comp!=get_components(format) || type!=get_component_type(format)) + throw incompatible_data("Texture1D::sub_image"); + sub_image(level, x, wd, data); +} + void Texture1D::image(const Graphics::Image &img, unsigned lv, bool srgb) { if(img.get_height()!=1) @@ -108,14 +126,12 @@ void Texture1D::image(const Graphics::Image &img, unsigned lv, bool srgb) unsigned w = img.get_width(); PixelFormat fmt = pixelformat_from_image(img); - PixelComponents comp = get_components(fmt); - DataType type = get_component_type(fmt); if(width==0) - storage(make_pixelformat(comp, type, srgb), w, lv); + storage(make_pixelformat(get_components(fmt), get_component_type(fmt), srgb), w, lv); else if(w!=width) throw incompatible_data("Texture1D::image"); - image(0, comp, type, img.get_data()); + image(0, img.get_data()); } unsigned Texture1D::get_n_levels() const @@ -132,7 +148,7 @@ unsigned Texture1D::get_level_size(unsigned level) const UInt64 Texture1D::get_data_size() const { - return id ? width*get_pixel_size(ifmt) : 0; + return id ? width*get_pixel_size(storage_fmt) : 0; } @@ -157,7 +173,7 @@ void Texture1D::Loader::init() void Texture1D::Loader::raw_data(const string &data) { - obj.image(0, get_components(obj.ifmt), get_component_type(obj.ifmt), data.data()); + obj.image(0, data.data()); } void Texture1D::Loader::storage(PixelFormat fmt, unsigned w) diff --git a/source/texture1d.h b/source/texture1d.h index b0a9c681..2b2a6b19 100644 --- a/source/texture1d.h +++ b/source/texture1d.h @@ -36,8 +36,10 @@ public: { storage(make_pixelformat(c, UNSIGNED_BYTE), w, l); } void allocate(unsigned); - void image(unsigned, PixelComponents, DataType, const void *); - void sub_image(unsigned, int, unsigned, PixelComponents, DataType, const void *); + void image(unsigned, const void *); + DEPRECATED void image(unsigned, PixelComponents, DataType, const void *); + void sub_image(unsigned, int, unsigned, const void *); + DEPRECATED void sub_image(unsigned, int, unsigned, PixelComponents, DataType, const void *); virtual void image(const Graphics::Image &, unsigned, bool = false); using Texture::image; unsigned get_width() const { return width; } diff --git a/source/texture2d.cpp b/source/texture2d.cpp index 8846a555..fa92f1c9 100644 --- a/source/texture2d.cpp +++ b/source/texture2d.cpp @@ -53,7 +53,7 @@ void Texture2D::storage(PixelFormat fmt, unsigned wd, unsigned ht, unsigned lv) if(wd==0 || ht==0) throw invalid_argument("Texture2D::storage"); - set_internal_format(fmt); + set_format(fmt); width = wd; height = ht; levels = get_n_levels(); @@ -74,17 +74,17 @@ void Texture2D::allocate(unsigned level) { Conditional _bind(!ARB_direct_state_access, this); if(ARB_direct_state_access) - glTextureStorage2D(id, levels, ifmt, width, height); + glTextureStorage2D(id, levels, storage_fmt, width, height); else - glTexStorage2D(target, levels, ifmt, width, height); + glTexStorage2D(target, levels, storage_fmt, width, height); apply_swizzle(); allocated |= (1< _bind(!ARB_direct_state_access, this); allocate(level); - comp = get_upload_components(comp); + PixelComponents comp = get_components(storage_fmt); + DataType type = get_component_type(storage_fmt); if(ARB_direct_state_access) glTextureSubImage2D(id, level, x, y, wd, ht, comp, type, data); else @@ -131,6 +142,13 @@ void Texture2D::sub_image(unsigned level, int x, int y, unsigned wd, unsigned ht generate_mipmap(); } +void Texture2D::sub_image(unsigned level, int x, int y, unsigned wd, unsigned ht, PixelComponents comp, DataType type, const void *data) +{ + if(comp!=get_components(format) || type!=get_component_type(format)) + throw incompatible_data("Texture2D::sub_image"); + sub_image(level, x, y, wd, ht, data); +} + void Texture2D::image(const Graphics::Image &img, unsigned lv, bool srgb) { image(img, lv, srgb, false); @@ -141,17 +159,15 @@ void Texture2D::image(const Graphics::Image &img, unsigned lv, bool srgb, bool f unsigned w = img.get_width(); unsigned h = img.get_height(); PixelFormat fmt = pixelformat_from_image(img); - PixelComponents comp = get_components(fmt); - DataType type = get_component_type(fmt); if(width==0) - storage(make_pixelformat(comp, type, srgb), w, h, lv); + storage(make_pixelformat(get_components(fmt), get_component_type(fmt), srgb), w, h, lv); else if(w!=width || h!=height || (lv && lv!=levels)) throw incompatible_data("Texture2D::image"); PixelStore pstore = PixelStore::from_image(img); BindRestore _bind_ps(pstore); - image(0, comp, type, from_buffer ? 0 : img.get_data()); + image(0, from_buffer ? 0 : img.get_data()); } unsigned Texture2D::get_n_levels() const @@ -182,7 +198,7 @@ Resource::AsyncLoader *Texture2D::load(IO::Seekable &io, const Resources *res) UInt64 Texture2D::get_data_size() const { - return id ? width*height*get_pixel_size(ifmt) : 0; + return id ? width*height*get_pixel_size(format) : 0; } void Texture2D::unload() @@ -215,7 +231,7 @@ void Texture2D::Loader::init() void Texture2D::Loader::raw_data(const string &data) { - obj.image(0, get_components(obj.ifmt), get_component_type(obj.ifmt), data.data()); + obj.image(0, data.data()); } void Texture2D::Loader::storage(PixelFormat fmt, unsigned w, unsigned h) diff --git a/source/texture2d.h b/source/texture2d.h index 801d18dd..b7070e8f 100644 --- a/source/texture2d.h +++ b/source/texture2d.h @@ -55,20 +55,24 @@ public: undefined. If storage has already been allocated, does nothing. */ void allocate(unsigned level); - /** Uploads an image to the texture. Storage must be defined beforehand. - The image data must have dimensions and format compatible with the defined - storage. */ - void image(unsigned level, PixelComponents fmt, DataType type, const void *data); + /** Updates the contents of the entire texture. Storage must be defined + beforehand. The image data must have dimensions and format matching the + defined storage. */ + virtual void image(unsigned level, const void *data); + + DEPRECATED void image(unsigned level, PixelComponents fmt, DataType type, const void *data); /** Updates a rectangular region of the texture. Storage must be defined - and allocated beforehand. The update region must be fully inside the - texture. */ - void sub_image(unsigned level, int x, int y, unsigned wd, unsigned ht, + beforehand. The image data must be in a format mathing the defined storage + and the update region must be fully inside the texture. */ + void sub_image(unsigned level, int x, int y, unsigned wd, unsigned ht, const void *data); + + DEPRECATED void sub_image(unsigned level, int x, int y, unsigned wd, unsigned ht, PixelComponents fmt, DataType type, const void *data); - /** Uploads an image to the texture. If storage has not been defined, it - will be set to match the image. Otherwise the image must be compatible with - the defined storage. + /** Updates the contents of the entire texture from an image. If storage + has not been defined, it will be set to match the image. Otherwise the + image must match the defined storage. If srgb is true and storage is determined by this call, then an sRGB pixel format will be used. */ diff --git a/source/texture2darray.cpp b/source/texture2darray.cpp index 34b9532d..c080481b 100644 --- a/source/texture2darray.cpp +++ b/source/texture2darray.cpp @@ -15,14 +15,21 @@ Texture2DArray::Texture2DArray(): static Require _req(EXT_texture_array); } -void Texture2DArray::layer_image(unsigned level, unsigned z, PixelComponents comp, DataType type, const void *data) +void Texture2DArray::layer_image(unsigned level, unsigned z, const void *data) { unsigned w = get_width(); unsigned h = get_height(); unsigned d = get_depth(); get_level_size(level, w, h, d); - sub_image(level, 0, 0, z, w, h, 1, comp, type, data); + sub_image(level, 0, 0, z, w, h, 1, data); +} + +void Texture2DArray::layer_image(unsigned level, unsigned z, PixelComponents comp, DataType type, const void *data) +{ + if(comp!=get_components(format) || type!=get_component_type(format)) + throw incompatible_data("Texture2DArray::layer_image"); + layer_image(level, z, data); } void Texture2DArray::layer_image(unsigned level, unsigned z, const Graphics::Image &img) @@ -32,14 +39,16 @@ void Texture2DArray::layer_image(unsigned level, unsigned z, const Graphics::Ima unsigned w = img.get_width(); unsigned h = img.get_height(); - PixelFormat fmt = pixelformat_from_image(img); if(w!=get_width() || h!=get_height()) throw incompatible_data("Texture2DArray::layer_image"); + PixelFormat fmt = pixelformat_from_image(img); + if(get_components(fmt)!=get_components(format) || get_component_type(fmt)!=get_component_type(format)) + throw incompatible_data("Texture2DArray::layer_image"); PixelStore pstore = PixelStore::from_image(img); BindRestore _bind_ps(pstore); - layer_image(level, z, get_components(fmt), get_component_type(fmt), img.get_data()); + layer_image(level, z, img.get_data()); } diff --git a/source/texture2darray.h b/source/texture2darray.h index 6aa4886c..bd7d03be 100644 --- a/source/texture2darray.h +++ b/source/texture2darray.h @@ -27,7 +27,8 @@ public: Texture2DArray(); - void layer_image(unsigned, unsigned, PixelComponents, DataType, const void *); + void layer_image(unsigned, unsigned, const void *); + DEPRECATED void layer_image(unsigned, unsigned, PixelComponents, DataType, const void *); void layer_image(unsigned, unsigned, const Graphics::Image &); unsigned get_layers() const { return get_depth(); } diff --git a/source/texture3d.cpp b/source/texture3d.cpp index 010609a8..13bb3ff4 100644 --- a/source/texture3d.cpp +++ b/source/texture3d.cpp @@ -40,7 +40,7 @@ void Texture3D::storage(PixelFormat fmt, unsigned wd, unsigned ht, unsigned dp, if(wd==0 || ht==0 || dp==0) throw invalid_argument("Texture3D::storage"); - set_internal_format(fmt); + set_format(fmt); width = wd; height = ht; depth = dp; @@ -62,17 +62,17 @@ void Texture3D::allocate(unsigned level) { Conditional _bind(!ARB_direct_state_access, this); if(ARB_direct_state_access) - glTextureStorage3D(id, levels, ifmt, width, height, depth); + glTextureStorage3D(id, levels, storage_fmt, width, height, depth); else - glTexStorage3D(target, levels, ifmt, width, height, depth); + glTexStorage3D(target, levels, storage_fmt, width, height, depth); apply_swizzle(); allocated |= (1< _bind(!ARB_direct_state_access, this); allocate(level); - comp = get_upload_components(comp); + PixelComponents comp = get_components(storage_fmt); + DataType type = get_component_type(storage_fmt); if(ARB_direct_state_access) glTextureSubImage3D(id, level, x, y, z, wd, ht, dp, comp, type, data); else @@ -120,6 +131,13 @@ void Texture3D::sub_image(unsigned level, int x, int y, int z, unsigned wd, unsi generate_mipmap(); } +void Texture3D::sub_image(unsigned level, int x, int y, int z, unsigned wd, unsigned ht, unsigned dp, PixelComponents comp, DataType type, const void *data) +{ + if(comp!=get_components(format) || type!=get_component_type(format)) + throw incompatible_data("Texture3D::sub_image"); + sub_image(level, x, y, z, wd, ht, dp, data); +} + void Texture3D::image(const Graphics::Image &img, unsigned lv, bool srgb) { unsigned w = img.get_width(); @@ -142,17 +160,15 @@ void Texture3D::image(const Graphics::Image &img, unsigned lv, bool srgb) } PixelFormat fmt = pixelformat_from_image(img); - PixelComponents comp = get_components(fmt); - DataType type = get_component_type(fmt); if(width==0) - storage(make_pixelformat(comp, type, srgb), w, h, d, lv); + storage(make_pixelformat(get_components(fmt), get_component_type(fmt), srgb), w, h, d, lv); else if(w!=width || h!=height || d!=depth) throw incompatible_data("Texture3D::load_image"); PixelStore pstore = PixelStore::from_image(img); BindRestore _bind_ps(pstore); - image(0, comp, type, img.get_data()); + image(0, img.get_data()); } unsigned Texture3D::get_n_levels() const @@ -182,7 +198,7 @@ void Texture3D::get_level_size(unsigned level, unsigned &w, unsigned &h, unsigne UInt64 Texture3D::get_data_size() const { - return id ? width*height*depth*get_pixel_size(ifmt) : 0; + return id ? width*height*depth*get_pixel_size(storage_fmt) : 0; } @@ -207,7 +223,7 @@ void Texture3D::Loader::init() void Texture3D::Loader::raw_data(const string &data) { - obj.image(0, get_components(obj.ifmt), get_component_type(obj.ifmt), data.data()); + obj.image(0, data.data()); } void Texture3D::Loader::storage(PixelFormat fmt, unsigned w, unsigned h, unsigned d) diff --git a/source/texture3d.h b/source/texture3d.h index ecdff9d6..d67d03be 100644 --- a/source/texture3d.h +++ b/source/texture3d.h @@ -53,22 +53,26 @@ public: undefined. If storage has already been allocated, does nothing. */ void allocate(unsigned level); - /** Uploads an image to the texture. Storage must be defined beforehand. - The image data must have dimensions and format compatible with the defined - storage. */ - void image(unsigned level, PixelComponents, DataType type, const void *data); + /** Updates the contents of the entire texture. Storage must be defined + beforehand. The image data must have dimensions and format matching the + defined storage. */ + void image(unsigned level, const void *data); + + DEPRECATED void image(unsigned level, PixelComponents comp, DataType type, const void *data); /** Updates a cuboid-shaped region of the texture. Storage must be defined - and allocated beforehand. The update region must be fully inside the - texture. */ - void sub_image(unsigned level, + beforehand. The image data must be in a format mathing the defined storage + and the update region must be fully inside the texture. */ + void sub_image(unsigned level, int x, int y, int z, unsigned wd, unsigned ht, unsigned dp, const void *data); + + DEPRECATED void sub_image(unsigned level, int x, int y, int z, unsigned wd, unsigned ht, unsigned dp, PixelComponents comp, DataType type, const void *data); - /** Uploads an image to the texture. If storage has not been defined, it - will be set to match the image. In this case the image will be treated as - a stack of square layers and its height must be divisible by its width. - Otherwise the image must be compatible with the defined storage. + /** Updates the contents of the entire texture from an image. If storage + has not been defined, it will be set to match the image. In this case the + image will be treated as a stack of square layers and its height must be + divisible by its width. Otherwise the image must match the defined storage. If srgb is true and storage is determined by this call, then an sRGB pixel format will be used. */ diff --git a/source/texturecube.cpp b/source/texturecube.cpp index b0887ca8..824ff2cc 100644 --- a/source/texturecube.cpp +++ b/source/texturecube.cpp @@ -58,7 +58,7 @@ void TextureCube::storage(PixelFormat fmt, unsigned sz, unsigned lv) if(sz==0) throw invalid_argument("TextureCube::storage"); - set_internal_format(fmt); + set_format(fmt); size = sz; levels = get_n_levels(); if(lv>0) @@ -77,20 +77,18 @@ void TextureCube::allocate(unsigned level) if(ARB_texture_storage) { BindRestore _bind(this); - glTexStorage2D(target, levels, ifmt, size, size); + glTexStorage2D(target, levels, storage_fmt, size, size); apply_swizzle(); allocated |= (1<(img.get_data()); unsigned face_size = img.get_stride()*size; for(unsigned i=0; i<6; ++i) - image(enumerate_faces(i), 0, comp, type, cdata+i*face_size); + image(enumerate_faces(i), 0, cdata+i*face_size); } unsigned TextureCube::get_n_levels() const @@ -255,7 +270,7 @@ Vector3 TextureCube::get_texel_direction(TextureCubeFace face, unsigned u, unsig UInt64 TextureCube::get_data_size() const { - return id ? size*size*6*get_pixel_size(ifmt) : 0; + return id ? size*size*6*get_pixel_size(storage_fmt) : 0; } @@ -300,7 +315,7 @@ void TextureCube::Loader::image_data(TextureCubeFace face, const string &data) void TextureCube::Loader::raw_data(TextureCubeFace face, const string &data) { - obj.image(face, 0, get_components(obj.ifmt), get_component_type(obj.ifmt), data.data()); + obj.image(face, 0, data.data()); } void TextureCube::Loader::storage(PixelFormat fmt, unsigned s) diff --git a/source/texturecube.h b/source/texturecube.h index f7160983..82356200 100644 --- a/source/texturecube.h +++ b/source/texturecube.h @@ -77,16 +77,20 @@ public: undefined. If storage has already been allocated, does nothing. */ void allocate(unsigned level); - /** Uploads image data to a face. Storage must be defined beforehand. The - image data must have dimensions and format compatible with the defined + /** Updates the contents of a face. Storage must be defined beforehand. + The image data must have dimensions and format matching the defined storage. */ - void image(TextureCubeFace face, unsigned level, + void image(TextureCubeFace face, unsigned level, const void *data); + + DEPRECATED void image(TextureCubeFace face, unsigned level, PixelComponents comp, DataType type, const void *data); - /** Updates a rectangular region of a face. Storage must be defined and - allocated beforehand. The update region must be fully inside the texture. - The data format must be compatible with the defined storage. */ - void sub_image(TextureCubeFace face, unsigned level, + /** Updates a rectangular region of a face. Storage must be defined + beforehand. The image data must be in a format mathing the defined storage + and the update region must be fully inside the face. */ + void sub_image(TextureCubeFace face, unsigned level, int x, int y, unsigned w, unsigned h, const void *data); + + DEPRECATED void sub_image(TextureCubeFace face, unsigned level, int x, int y, unsigned w, unsigned h, PixelComponents comp, DataType type, const void *data); -- 2.45.2