]> git.tdb.fi Git - libs/gl.git/commitdiff
Store the number of mipmap levels in the Texture base class
authorMikko Rasa <tdb@tdb.fi>
Sat, 4 Dec 2021 00:25:14 +0000 (02:25 +0200)
committerMikko Rasa <tdb@tdb.fi>
Sat, 4 Dec 2021 00:25:42 +0000 (02:25 +0200)
28 files changed:
source/backends/opengl/texture1d_backend.cpp
source/backends/opengl/texture2d_backend.cpp
source/backends/opengl/texture2darray_backend.cpp
source/backends/opengl/texture3d_backend.cpp
source/backends/opengl/texturecube_backend.cpp
source/backends/vulkan/framebuffer_backend.cpp
source/backends/vulkan/texture1d_backend.cpp
source/backends/vulkan/texture1d_backend.h
source/backends/vulkan/texture2d_backend.cpp
source/backends/vulkan/texture2d_backend.h
source/backends/vulkan/texture2darray_backend.cpp
source/backends/vulkan/texture3d_backend.cpp
source/backends/vulkan/texture3d_backend.h
source/backends/vulkan/texture_backend.cpp
source/backends/vulkan/texture_backend.h
source/backends/vulkan/texturecube_backend.cpp
source/backends/vulkan/texturecube_backend.h
source/core/texture.cpp
source/core/texture.h
source/core/texture1d.cpp
source/core/texture1d.h
source/core/texture2d.cpp
source/core/texture2d.h
source/core/texture2darray.cpp
source/core/texture3d.cpp
source/core/texture3d.h
source/core/texturecube.cpp
source/core/texturecube.h

index 8e33d278984ca06c8f81c4222e01717d195b5b55..aa9e1f298f9f5a9a407ccc9b24262762bf86ac8f 100644 (file)
@@ -25,20 +25,20 @@ void OpenGLTexture1D::allocate()
        if(ARB_texture_storage)
        {
                if(ARB_direct_state_access)
-                       glTextureStorage1D(id, self.levels, gl_fmt, self.width);
+                       glTextureStorage1D(id, n_levels, gl_fmt, self.width);
                else
                {
                        bind_scratch();
-                       glTexStorage1D(target, self.levels, gl_fmt, self.width);
+                       glTexStorage1D(target, n_levels, gl_fmt, self.width);
                }
        }
        else
        {
                bind_scratch();
-               glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, self.levels-1);
+               glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, n_levels-1);
                GLenum comp = get_gl_components(get_components(storage_fmt));
                GLenum type = get_gl_type(get_component_type(storage_fmt));
-               for(unsigned i=0; i<self.levels; ++i)
+               for(unsigned i=0; i<n_levels; ++i)
                {
                        unsigned lv_size = self.get_level_size(i);
                        glTexImage1D(target, i, gl_fmt, lv_size, 0, comp, type, 0);
@@ -70,7 +70,7 @@ size_t OpenGLTexture1D::get_data_size() const
 
        size_t level_size = self.width*get_pixel_size(storage_fmt);
        size_t total_size = level_size;
-       for(unsigned i=0; i<self.levels; ++i, level_size>>=2)
+       for(unsigned i=0; i<n_levels; ++i, level_size>>=2)
                total_size += level_size;
        return total_size;
 }
index 54c82280e5b1a0e3e30b0e51bc7a1da6abf28ff6..ed10f6c192739196cd56f9baa5bd2d54479aaebc 100644 (file)
@@ -50,20 +50,20 @@ void OpenGLTexture2D::allocate()
        if(ARB_texture_storage)
        {
                if(ARB_direct_state_access)
-                       glTextureStorage2D(id, self.levels, gl_fmt, self.width, self.height);
+                       glTextureStorage2D(id, n_levels, gl_fmt, self.width, self.height);
                else
                {
                        bind_scratch();
-                       glTexStorage2D(target, self.levels, gl_fmt, self.width, self.height);
+                       glTexStorage2D(target, n_levels, gl_fmt, self.width, self.height);
                }
        }
        else
        {
                bind_scratch();
-               glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, self.levels-1);
+               glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, n_levels-1);
                GLenum comp = get_gl_components(get_components(storage_fmt));
                GLenum type = get_gl_type(get_component_type(storage_fmt));
-               for(unsigned i=0; i<self.levels; ++i)
+               for(unsigned i=0; i<n_levels; ++i)
                {
                        auto lv_size = self.get_level_size(i);
                        glTexImage2D(target, i, gl_fmt, lv_size.x, lv_size.y, 0, comp, type, 0);
@@ -107,7 +107,7 @@ uint64_t OpenGLTexture2D::get_data_size() const
 
        size_t level_size = self.width*self.height*get_pixel_size(format);
        size_t total_size = level_size;
-       for(unsigned i=0; i<self.levels; ++i, level_size>>=2)
+       for(unsigned i=0; i<n_levels; ++i, level_size>>=2)
                total_size += level_size;
        return total_size;
 }
index edca615d91a8440ca7cabfa3fca8b7db235a9a0e..5e04dc0da482d754e57adb9d4607b7afb9445045 100644 (file)
@@ -17,7 +17,7 @@ size_t OpenGLTexture2DArray::get_data_size() const
 
        size_t level_size = width*height*get_pixel_size(format);
        size_t total_size = level_size;
-       for(unsigned i=0; i<levels; ++i, level_size>>=2)
+       for(unsigned i=0; i<n_levels; ++i, level_size>>=2)
                total_size += level_size*depth;
        return total_size;
 }
index f446e653cfc4a90df6cabc3ce3fe8661541de24d..81783850383c0db70670768e0e318b7cd8e88b13 100644 (file)
@@ -30,11 +30,11 @@ void OpenGLTexture3D::allocate()
        if(ARB_texture_storage)
        {
                if(ARB_direct_state_access)
-                       glTextureStorage3D(id, self.levels, gl_fmt, self.width, self.height, self.depth);
+                       glTextureStorage3D(id, n_levels, gl_fmt, self.width, self.height, self.depth);
                else
                {
                        bind_scratch();
-                       glTexStorage3D(target, self.levels, gl_fmt, self.width, self.height, self.depth);
+                       glTexStorage3D(target, n_levels, gl_fmt, self.width, self.height, self.depth);
                }
        }
        else
@@ -42,12 +42,12 @@ void OpenGLTexture3D::allocate()
                bind_scratch();
                GLenum comp = get_gl_components(get_components(storage_fmt));
                GLenum type = get_gl_type(get_component_type(storage_fmt));
-               for(unsigned i=0; i<self.levels; ++i)
+               for(unsigned i=0; i<n_levels; ++i)
                {
                        auto lv_size = self.get_level_size(i);
                        glTexImage3D(target, i, gl_fmt, lv_size.x, lv_size.y, lv_size.z, 0, comp, type, 0);
                }
-               glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, self.levels-1);
+               glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, n_levels-1);
        }
 
        apply_swizzle();
@@ -80,7 +80,7 @@ size_t OpenGLTexture3D::get_data_size() const
 
        size_t level_size = self.width*self.height*self.depth*get_pixel_size(format);
        size_t total_size = level_size;
-       for(unsigned i=0; i<self.levels; ++i, level_size>>=2)
+       for(unsigned i=0; i<n_levels; ++i, level_size>>=2)
                total_size += level_size;
        return total_size;
 }
index 142e343dd9984bb881148ee3dd66739c9cddf3e3..e363f6fb50c77f25a687942f8bea484d2c77ef36 100644 (file)
@@ -37,11 +37,11 @@ void OpenGLTextureCube::allocate()
        if(ARB_texture_storage)
        {
                if(ARB_direct_state_access)
-                       glTextureStorage2D(id, self.levels, gl_fmt, self.size, self.size);
+                       glTextureStorage2D(id, n_levels, gl_fmt, self.size, self.size);
                else
                {
                        bind_scratch();
-                       glTexStorage2D(target, self.levels, gl_fmt, self.size, self.size);
+                       glTexStorage2D(target, n_levels, gl_fmt, self.size, self.size);
                }
        }
        else
@@ -49,13 +49,13 @@ void OpenGLTextureCube::allocate()
                bind_scratch();
                GLenum comp = get_gl_components(get_components(storage_fmt));
                GLenum type = get_gl_type(get_component_type(storage_fmt));
-               for(unsigned i=0; i<self.levels; ++i)
+               for(unsigned i=0; i<n_levels; ++i)
                {
                        unsigned lv_size = static_cast<const TextureCube *>(this)->get_level_size(i);
                        for(unsigned j=0; j<6; ++j)
                                glTexImage2D(get_gl_cube_face(j), i, gl_fmt, lv_size, lv_size, 0, comp, type, 0);
                }
-               glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, self.levels-1);
+               glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, n_levels-1);
        }
 
        apply_swizzle();
@@ -83,7 +83,7 @@ size_t OpenGLTextureCube::get_data_size() const
 
        size_t level_size = self.size*self.size*get_pixel_size(storage_fmt);
        size_t total_size = level_size;
-       for(unsigned i=0; i<self.levels; ++i, level_size>>=2)
+       for(unsigned i=0; i<n_levels; ++i, level_size>>=2)
                total_size += level_size;
        return total_size;
 }
index 2ebd8b33d067fb6844a237e7bf6e38995d7b446b..8ef69ecd72a206c87db8b3997afecc250d7dc063 100644 (file)
@@ -85,7 +85,7 @@ void VulkanFramebuffer::update(unsigned) const
 void VulkanFramebuffer::prepare_image_layouts(bool discard) const
 {
        for(const Framebuffer::Attachment &a: static_cast<const Framebuffer *>(this)->attachments)
-               a.tex->change_layout(0, a.level, get_vulkan_attachment_layout(get_components(a.tex->get_format())), discard);
+               a.tex->change_layout(a.level, get_vulkan_attachment_layout(get_components(a.tex->get_format())), discard);
 }
 
 void VulkanFramebuffer::set_debug_name(const string &name)
index e27f371bdc33c75608303d5926198acc49840cd1..d74164842960f8189b3398f34a428e6e07624c46 100644 (file)
@@ -19,7 +19,6 @@ void VulkanTexture1D::fill_image_info(void *ii) const
        VkImageCreateInfo *image_info = static_cast<VkImageCreateInfo *>(ii);
        image_info->imageType = VK_IMAGE_TYPE_1D;
        image_info->extent.width = self.width;
-       image_info->mipLevels = self.levels;
 }
 
 void VulkanTexture1D::sub_image(unsigned level, int x, unsigned wd, const void *data)
@@ -32,8 +31,7 @@ void VulkanTexture1D::sub_image(unsigned level, int x, unsigned wd, const void *
        size_t data_size = wd*get_pixel_size(storage_fmt);
        void *staging = device.get_transfer_queue().prepare_transfer(this, false, data_size,
                [this, level, discard](){
-                       unsigned n_levels = static_cast<const Texture1D *>(this)->levels;
-                       change_layout(n_levels, level, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, discard);
+                       change_layout(level, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, discard);
                },
                [this, level, x, wd](VkCommandBuffer cmd_buf, VkBuffer staging_buf, size_t src_off){
                        const VulkanFunctions &vk = device.get_functions();
@@ -52,11 +50,6 @@ void VulkanTexture1D::sub_image(unsigned level, int x, unsigned wd, const void *
        stage_pixels(staging, data, wd);
 }
 
-void VulkanTexture1D::generate_mipmap()
-{
-       generate_mipmap_levels(static_cast<const Texture1D *>(this)->levels);
-}
-
 void VulkanTexture1D::fill_mipmap_blit(unsigned level, void *b)
 {
        const Texture1D &self = *static_cast<const Texture1D *>(this);
index 675da1b2c94cf43e7111748cab43215f42275b5a..fdc74d9dfd6b016471ec85baaf5dc6d1f63524a5 100644 (file)
@@ -13,7 +13,6 @@ protected:
 
        virtual void fill_image_info(void *) const;
        void sub_image(unsigned, int, unsigned, const void *);
-       virtual void generate_mipmap();
        virtual void fill_mipmap_blit(unsigned, void *);
 
 public:
index 3b94e766dc21ff4be2ec2b88ad4c49d7d5c7c1bf..3e88898b835118c6dfd11b4db0c350d5dc2eef5b 100644 (file)
@@ -20,7 +20,6 @@ void VulkanTexture2D::fill_image_info(void *ii) const
        image_info->imageType = VK_IMAGE_TYPE_2D;
        image_info->extent.width = self.width;
        image_info->extent.height = self.height;
-       image_info->mipLevels = self.levels;
 }
 
 void VulkanTexture2D::sub_image(unsigned level, int x, int y, unsigned wd, unsigned ht, const void *data)
@@ -33,8 +32,7 @@ void VulkanTexture2D::sub_image(unsigned level, int x, int y, unsigned wd, unsig
        size_t data_size = wd*ht*get_pixel_size(storage_fmt);
        void *staging = device.get_transfer_queue().prepare_transfer(this, false, data_size,
                [this, level, discard](){
-                       unsigned n_levels = static_cast<const Texture2D *>(this)->levels;
-                       change_layout(n_levels, level, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, discard);
+                       change_layout(level, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, discard);
                },
                [this, level, x, y, wd, ht](VkCommandBuffer cmd_buf, VkBuffer staging_buf, size_t src_off){
                        const VulkanFunctions &vk = device.get_functions();
@@ -53,11 +51,6 @@ void VulkanTexture2D::sub_image(unsigned level, int x, int y, unsigned wd, unsig
        stage_pixels(staging, data, wd*ht);
 }
 
-void VulkanTexture2D::generate_mipmap()
-{
-       generate_mipmap_levels(static_cast<const Texture2D *>(this)->levels);
-}
-
 void VulkanTexture2D::fill_mipmap_blit(unsigned level, void *b)
 {
        const Texture2D &self = *static_cast<const Texture2D *>(this);
index cfd5ff3d447a84d14f282e4c57ec01f13b2c815c..d4b7db1d934cbcdd44a33f504857cf452857715c 100644 (file)
@@ -13,7 +13,6 @@ protected:
 
        virtual void fill_image_info(void *) const;
        void sub_image(unsigned, int, int, unsigned, unsigned, const void *);
-       virtual void generate_mipmap();
        virtual void fill_mipmap_blit(unsigned, void *);
 
 public:
index cff3a8160744b1b8c6818ec789f64a9cce5cd282..63e969e8da56c3ab5b6851d8a7d4253bdbe68746 100644 (file)
@@ -14,7 +14,6 @@ void VulkanTexture2DArray::fill_image_info(void *ii) const
        image_info->imageType = VK_IMAGE_TYPE_2D;
        image_info->extent.width = width;
        image_info->extent.height = height;
-       image_info->mipLevels = levels;
        image_info->arrayLayers = depth;
 }
 
index ee3490a77263e43e25ddb6d967e2d839926897ab..05ed51829d6bacb200fc5eef3a16cba36f5cf580 100644 (file)
@@ -25,7 +25,6 @@ void VulkanTexture3D::fill_image_info(void *ii) const
        image_info->extent.width = self.width;
        image_info->extent.height = self.height;
        image_info->extent.depth = self.depth;
-       image_info->mipLevels = self.levels;
 }
 
 void VulkanTexture3D::sub_image(unsigned level, int x, int y, int z, unsigned wd, unsigned ht, unsigned dp, const void *data)
@@ -38,8 +37,7 @@ void VulkanTexture3D::sub_image(unsigned level, int x, int y, int z, unsigned wd
        size_t data_size = wd*ht*dp*get_pixel_size(storage_fmt);
        void *staging = device.get_transfer_queue().prepare_transfer(this, false, data_size,
                [this, level, discard](){
-                       unsigned n_levels = static_cast<const Texture3D *>(this)->levels;
-                       change_layout(n_levels, level, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, discard);
+                       change_layout(level, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, discard);
                },
                [this, level, x, y, z, wd, ht, dp](VkCommandBuffer cmd_buf, VkBuffer staging_buf, size_t src_off){
                        const VulkanFunctions &vk = device.get_functions();
@@ -58,11 +56,6 @@ void VulkanTexture3D::sub_image(unsigned level, int x, int y, int z, unsigned wd
        stage_pixels(staging, data, wd*ht*dp);
 }
 
-void VulkanTexture3D::generate_mipmap()
-{
-       generate_mipmap_levels(static_cast<const Texture3D *>(this)->levels);
-}
-
 void VulkanTexture3D::fill_mipmap_blit(unsigned level, void *b)
 {
        const Texture3D &self = *static_cast<const Texture3D *>(this);
index e1c8f8f5469deeb20aad8c4d3f1d065828b80a69..49b7497c97181a86209c0cb2dee81e91caa1eab9 100644 (file)
@@ -14,7 +14,6 @@ protected:
 
        virtual void fill_image_info(void *) const;
        void sub_image(unsigned, int, int, int, unsigned, unsigned, unsigned, const void *);
-       virtual void generate_mipmap();
        virtual void fill_mipmap_blit(unsigned, void *);
 
        bool is_array() const;
index dd19c63664b88658fe06917798742bbcbb4fd2f5..ec6d504732f9f0a13055eff1f42086d2fe4858a7 100644 (file)
@@ -49,7 +49,7 @@ void VulkanTexture::allocate()
        image_info.extent.width = 1;
        image_info.extent.height = 1;
        image_info.extent.depth = 1;
-       image_info.mipLevels = 1;
+       image_info.mipLevels = self.n_levels;
        image_info.arrayLayers = 1;
        image_info.samples = VK_SAMPLE_COUNT_1_BIT;
        image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
@@ -73,7 +73,7 @@ void VulkanTexture::allocate()
                memory_id = device.get_allocator().allocate(handle, DEVICE_MEMORY);
 
                // Trigger a layout transition if the image is used before uploading data.
-               change_layout(0, -1, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, true);
+               change_layout(-1, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, true);
        }
 
        VkImageViewCreateInfo view_info = { };
@@ -137,15 +137,17 @@ void VulkanTexture::stage_pixels(void *staging, const void *data, size_t count)
        }
 }
 
-void VulkanTexture::generate_mipmap_levels(unsigned n_levels)
+void VulkanTexture::generate_mipmap()
 {
+       unsigned n_levels = static_cast<const Texture *>(this)->n_levels;
+
        TransferQueue &tq = device.get_transfer_queue();
        for(unsigned i=0; i+1<n_levels; ++i)
        {
                tq.prepare_transfer(this, true, 0,
-                       [this, n_levels, i](){
-                               change_layout((i==0 ? n_levels : 0), i, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, false);
-                               change_layout(0, i+1, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true);
+                       [this, i](){
+                               change_layout(i, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, false);
+                               change_layout(i+1, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true);
                        },
                        [this, i](VkCommandBuffer cmd_buf, VkBuffer, size_t){
                                const VulkanFunctions &vk = device.get_functions();
@@ -166,11 +168,13 @@ void VulkanTexture::generate_mipmap_levels(unsigned n_levels)
        }
 }
 
-void VulkanTexture::change_layout(unsigned n_levels, int level, unsigned layout, bool discard) const
+void VulkanTexture::change_layout(int level, unsigned layout, bool discard) const
 {
-       unsigned aspect = get_vulkan_aspect(get_components(static_cast<const Texture *>(this)->storage_fmt));
-       if(n_levels>0)
-               device.get_synchronizer().split_image_mipmap(handle, aspect, n_levels);
+       const Texture &self = *static_cast<const Texture *>(this);
+
+       unsigned aspect = get_vulkan_aspect(get_components(self.storage_fmt));
+       if(level>=0)
+               device.get_synchronizer().split_image_mipmap(handle, aspect, self.n_levels);
        device.get_synchronizer().change_image_layout(handle, aspect, level, layout, discard);
 }
 
index dad8834b2940487d1c2b0bbc3676b5e633b26b5a..0907fea058000fe849167ae1b36d385dff479dbc 100644 (file)
@@ -32,11 +32,10 @@ protected:
 
        void stage_pixels(void *, const void *, size_t);
 
-       virtual void generate_mipmap() = 0;
-       void generate_mipmap_levels(unsigned);
+       void generate_mipmap();
        virtual void fill_mipmap_blit(unsigned, void *) = 0;
 
-       void change_layout(unsigned, int, unsigned, bool) const;
+       void change_layout(int, unsigned, bool) const;
 
        void set_debug_name(const std::string &);
        void set_vulkan_object_names() const;
index 6a4e598c0c103b0ece427cbcd34bc07faa330f09..4e0cfe61259e2dec6c362e798991c68dabfd45eb 100644 (file)
@@ -21,7 +21,6 @@ void VulkanTextureCube::fill_image_info(void *ii) const
        image_info->imageType = VK_IMAGE_TYPE_2D;
        image_info->extent.width = self.size;
        image_info->extent.height = self.size;
-       image_info->mipLevels = self.levels;
        image_info->arrayLayers = 6;
 }
 
@@ -35,8 +34,7 @@ void VulkanTextureCube::sub_image(unsigned face, unsigned level, int x, int y, u
        size_t data_size = wd*ht*get_pixel_size(storage_fmt);
        void *staging = device.get_transfer_queue().prepare_transfer(this, false, data_size,
                [this, level, discard](){
-                       unsigned n_levels = static_cast<const TextureCube *>(this)->levels;
-                       change_layout(n_levels, level, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, discard);
+                       change_layout(level, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, discard);
                },
                [this, face, level, x, y, wd, ht](VkCommandBuffer cmd_buf, VkBuffer staging_buf, size_t src_off){
                        const VulkanFunctions &vk = device.get_functions();
@@ -55,11 +53,6 @@ void VulkanTextureCube::sub_image(unsigned face, unsigned level, int x, int y, u
        stage_pixels(staging, data, wd*ht);
 }
 
-void VulkanTextureCube::generate_mipmap()
-{
-       generate_mipmap_levels(static_cast<const TextureCube *>(this)->levels);
-}
-
 void VulkanTextureCube::fill_mipmap_blit(unsigned level, void *b)
 {
        const TextureCube &self = *static_cast<const TextureCube *>(this);
index d77308972ecb246f531957a6b028ea8690c46cd3..1146c7051f52f1a147980ac489e138895e89ae17 100644 (file)
@@ -13,7 +13,6 @@ protected:
 
        virtual void fill_image_info(void *) const;
        void sub_image(unsigned, unsigned, int, int, unsigned, unsigned, const void *);
-       virtual void generate_mipmap();
        virtual void fill_mipmap_blit(unsigned, void *);
 
 public:
index 73dd39b6c5cf79a5662a31ff3846b8981fc677b6..0d7a81512e7f73f5c0a49659b4feddc16739c582 100644 (file)
@@ -34,6 +34,13 @@ void Texture::set_format(PixelFormat fmt)
        swizzle = swiz;
 }
 
+unsigned Texture::count_levels(unsigned size)
+{
+       unsigned n = 0;
+       for(; size; size>>=1, ++n) ;
+       return n;
+}
+
 void Texture::load_image(const string &fn, unsigned lv)
 {
        Graphics::Image img;
index 24d74964e04dd35c6e8f6092d41b0b854b713c98..eb5275c6e4fd71e60b6d0af04d179a229a94a56a 100644 (file)
@@ -73,12 +73,14 @@ protected:
        PixelFormat format = NO_PIXELFORMAT;
        PixelFormat storage_fmt = NO_PIXELFORMAT;
        ComponentSwizzle swizzle = NO_SWIZZLE;
+       unsigned n_levels = 0;
        bool use_srgb_format = false;
        bool auto_gen_mipmap = false;
 
        Texture(unsigned);
 
        void set_format(PixelFormat);
+       static unsigned count_levels(unsigned);
 
 public:
        PixelFormat get_format() const { return format; }
index d6aa1a347c7e974b43397ab595d8de7b0edd3ef8..ce5d3727fad5f260d274a4694561b77e40abf07b 100644 (file)
@@ -10,7 +10,7 @@ void Texture1D::storage(PixelFormat fmt, unsigned wd, unsigned lv)
 {
        if(width>0)
        {
-               if(fmt!=format || wd!=width || (lv && lv!=levels))
+               if(fmt!=format || wd!=width || (lv && lv!=n_levels))
                        throw incompatible_data("Texture1D::storage");
                return;
        }
@@ -19,9 +19,9 @@ void Texture1D::storage(PixelFormat fmt, unsigned wd, unsigned lv)
 
        set_format(fmt);
        width = wd;
-       levels = get_n_levels();
+       n_levels = count_levels(width);
        if(lv)
-               levels = min(levels, lv);
+               n_levels = min(n_levels, lv);
 
        allocate();
 }
@@ -35,7 +35,7 @@ void Texture1D::sub_image(unsigned level, unsigned x, unsigned wd, const void *d
 {
        if(width==0)
                throw invalid_operation("Texture1D::sub_image");
-       if(level>=levels || x>width || x+wd>width)
+       if(level>=n_levels || x>width || x+wd>width)
                throw out_of_range("Texture1D::sub_image");
 
        Texture1DBackend::sub_image(level, x, wd, data);
@@ -50,13 +50,6 @@ void Texture1D::image(const Graphics::Image &img, unsigned lv)
        image(0, img.get_pixels());
 }
 
-unsigned Texture1D::get_n_levels() const
-{
-       unsigned n = 0;
-       for(unsigned s=width; s; s>>=1, ++n) ;
-       return n;
-}
-
 unsigned Texture1D::get_level_size(unsigned level) const
 {
        return width>>level;
index 16c88a1830a969b9f7625d97b6690e4d99267d82..abe6c8879e5dbd07469bc1319e2fc2e6ac91230a 100644 (file)
@@ -29,7 +29,6 @@ public:
 
 private:
        unsigned width = 0;
-       unsigned levels = 0;
 
 public:
        /** Sets storage format and size and allocates memory for the texture.  If
@@ -49,7 +48,6 @@ public:
        unsigned get_width() const { return width; }
 
 private:
-       unsigned get_n_levels() const;
        unsigned get_level_size(unsigned) const;
 };
 
index c9aab79a9cf16c5a2488af530f9d081a3e148547..7ac1c5ec84f599fcef2285b94e8f5531c3631958 100644 (file)
@@ -15,7 +15,7 @@ void Texture2D::storage(PixelFormat fmt, unsigned wd, unsigned ht, unsigned lv)
 {
        if(width>0)
        {
-               if(fmt!=format || wd!=width || ht!=height || (lv && lv!=levels))
+               if(fmt!=format || wd!=width || ht!=height || (lv && lv!=n_levels))
                        throw incompatible_data("Texture2D::storage");
                return;
        }
@@ -25,9 +25,9 @@ void Texture2D::storage(PixelFormat fmt, unsigned wd, unsigned ht, unsigned lv)
        set_format(fmt);
        width = wd;
        height = ht;
-       levels = get_n_levels();
+       n_levels = count_levels(max(width, height));
        if(lv>0)
-               levels = min(levels, lv);
+               n_levels = min(n_levels, lv);
 
        allocate();
 }
@@ -42,7 +42,7 @@ void Texture2D::sub_image(unsigned level, unsigned x, unsigned y, unsigned wd, u
 {
        if(width==0 || height==0)
                throw invalid_operation("Texture2D::sub_image");
-       if(level>=levels || x>width || x+wd>width || y>height || y+ht>height)
+       if(level>=n_levels || x>width || x+wd>width || y>height || y+ht>height)
                throw out_of_range("Texture2D::sub_image");
 
        Texture2DBackend::sub_image(level, x, y, wd, ht, data);
@@ -54,13 +54,6 @@ void Texture2D::image(const Graphics::Image &img, unsigned lv)
        image(0, img.get_pixels());
 }
 
-unsigned Texture2D::get_n_levels() const
-{
-       unsigned n = 0;
-       for(unsigned s=max(width, height); s; s>>=1, ++n) ;
-       return n;
-}
-
 LinAl::Vector<unsigned, 2> Texture2D::get_level_size(unsigned level) const
 {
        unsigned w = width>>level;
index fbcee696686d0dbb93e067341badb2af2b809849..05c3283b73bd1aba1dd98f348c0c620753611114 100644 (file)
@@ -31,7 +31,6 @@ public:
 private:
        unsigned width = 0;
        unsigned height = 0;
-       unsigned levels = 0;
 
 public:
        Texture2D() = default;
index 52f5fd7139fab95d8f72c9bcbbefbc76b0640a9a..07f04c691b7dad0f9387ecd5362ece69196a6264 100644 (file)
@@ -8,7 +8,7 @@ namespace GL {
 
 void Texture2DArray::layer_image(unsigned level, unsigned z, const void *data)
 {
-       if(level>=levels || z>=depth)
+       if(level>=n_levels || z>=depth)
                throw out_of_range("Texture2DArray::layer_image");
 
        LinAl::Vector<unsigned, 3> size = get_level_size(level);
index 496b5f1fbe80370fefda9e169ad428d98464d274..0ee2e800086b2b940e634352be929da5b4cacd27 100644 (file)
@@ -15,7 +15,7 @@ void Texture3D::storage(PixelFormat fmt, unsigned wd, unsigned ht, unsigned dp,
 {
        if(width>0)
        {
-               if(fmt!=format || wd!=width || ht!=height || dp!=depth || (lv && lv!=levels))
+               if(fmt!=format || wd!=width || ht!=height || dp!=depth || (lv && lv!=n_levels))
                        throw incompatible_data("Texture3D::storage");
                return;
        }
@@ -26,9 +26,12 @@ void Texture3D::storage(PixelFormat fmt, unsigned wd, unsigned ht, unsigned dp,
        width = wd;
        height = ht;
        depth = dp;
-       levels = get_n_levels();
+       unsigned size = max(width, height);
+       if(!is_array())
+               size = max(size, depth);
+       n_levels = count_levels(size);
        if(lv>0)
-               levels = min(levels, lv);
+               n_levels = min(n_levels, lv);
 
        allocate();
 }
@@ -43,7 +46,7 @@ void Texture3D::sub_image(unsigned level, unsigned x, unsigned y, unsigned z, un
 {
        if(width==0 || height==0 || depth==0)
                throw invalid_operation("Texture3D::sub_image");
-       if(level>=levels || x>width || x+wd>width || y>height || y+ht>height || z>depth || z+dp>depth)
+       if(level>=n_levels || x>width || x+wd>width || y>height || y+ht>height || z>depth || z+dp>depth)
                throw out_of_range("Texture3D::sub_image");
 
        Texture3DBackend::sub_image(level, x, y, z, wd, ht, dp, data);
@@ -63,16 +66,6 @@ void Texture3D::image(const Graphics::Image &img, unsigned lv)
        image(0, img.get_pixels());
 }
 
-unsigned Texture3D::get_n_levels() const
-{
-       unsigned s = max(width, height);
-       if(!is_array())
-               s = max(s, depth);
-       unsigned n = 0;
-       for(; s; s>>=1, ++n) ;
-       return n;
-}
-
 LinAl::Vector<unsigned, 3> Texture3D::get_level_size(unsigned level) const
 {
        unsigned w = width>>level;
index 3009e1487a6d57b48ecfb03dd47665db532287e1..e7e3a79e951909f081349e32a53661b5f844cb1a 100644 (file)
@@ -32,7 +32,6 @@ protected:
        unsigned width = 0;
        unsigned height = 0;
        unsigned depth = 0;
-       unsigned levels = 0;
 
        Texture3D(unsigned);
 public:
@@ -63,7 +62,6 @@ public:
        unsigned get_height() const { return height; }
        unsigned get_depth() const { return depth; }
 protected:
-       unsigned get_n_levels() const;
        LinAl::Vector<unsigned, 3> get_level_size(unsigned) const;
 };
 
index 2f36f33624cee007b2667daeb993caaf212e9a04..bfa63873b2e188f2f339940fc48bf09e4c38034e 100644 (file)
@@ -33,7 +33,7 @@ void TextureCube::storage(PixelFormat fmt, unsigned sz, unsigned lv)
 {
        if(size>0)
        {
-               if(fmt!=format || sz!=size || (lv && lv!=levels))
+               if(fmt!=format || sz!=size || (lv && lv!=n_levels))
                        throw incompatible_data("TextureCube::storage");
                return;
        }
@@ -42,9 +42,9 @@ void TextureCube::storage(PixelFormat fmt, unsigned sz, unsigned lv)
 
        set_format(fmt);
        size = sz;
-       levels = get_n_levels();
+       n_levels = count_levels(size);
        if(lv>0)
-               levels = min(levels, lv);
+               n_levels = min(n_levels, lv);
 
        allocate();
 }
@@ -67,7 +67,7 @@ void TextureCube::sub_image(TextureCubeFace face, unsigned level, unsigned x, un
 {
        if(size==0)
                throw invalid_operation("TextureCube::sub_image");
-       if(level>=levels || x>size || x+wd>size || y>size || y+ht>size)
+       if(level>=n_levels || x>size || x+wd>size || y>size || y+ht>size)
                throw out_of_range("TextureCube::sub_image");
 
        TextureCubeBackend::sub_image(face, level, x, y, wd, ht, data);
@@ -101,13 +101,6 @@ void TextureCube::image(const Graphics::Image &img, unsigned lv)
        image(0, img.get_pixels());
 }
 
-unsigned TextureCube::get_n_levels() const
-{
-       unsigned n = 0;
-       for(unsigned s=size; s; s>>=1, ++n) ;
-       return n;
-}
-
 unsigned TextureCube::get_level_size(unsigned level) const
 {
        return size>>level;
index d444fee5dfefc8bb084956281a1957efbf9c0447..127251d6497735b50267672807e8f4459b608988 100644 (file)
@@ -49,7 +49,6 @@ public:
 
 private:
        unsigned size = 0;
-       unsigned levels = 0;
 
        static const Vector3 directions[6];
        static const unsigned orientations[12];
@@ -82,7 +81,6 @@ public:
 
        unsigned get_size() const { return size; }
 private:
-       unsigned get_n_levels() const;
        unsigned get_level_size(unsigned) const;
 
 public: