]> git.tdb.fi Git - libs/gl.git/commitdiff
Remove support for texture borders
authorMikko Rasa <tdb@tdb.fi>
Tue, 30 Nov 2010 13:10:50 +0000 (13:10 +0000)
committerMikko Rasa <tdb@tdb.fi>
Tue, 30 Nov 2010 13:10:50 +0000 (13:10 +0000)
Implement missing Texture3D::sub_image
Add allocate methods to Texture2D and Texture3D
Fix a bug in Texture

12 files changed:
maketex.py
mesh_export.py
source/bloom.cpp
source/pipeline.cpp
source/pixelformat.cpp
source/pixelformat.h
source/shadowmap.cpp
source/texture.cpp
source/texture2d.cpp
source/texture2d.h
source/texture3d.cpp
source/texture3d.h

index 017aa121368057e42a7119ef6973f9a2aadc6ddc..fa8e70d80022d8f3ad84add0af47741f0105b761 100755 (executable)
@@ -26,7 +26,7 @@ def make_tex(fn):
        elif fmt=="L":
                fmt="LUMINANCE"
 
-       result="storage %s %d %d 0;\n"%(fmt, img.size[0], img.size[1])
+       result="storage %s %d %d;\n"%(fmt, img.size[0], img.size[1])
        result+="min_filter LINEAR;\n"
        result+="raw_data \""
        data=list(img.getdata())
index 9e09ef4d39c0d4d970fc24eed6cbdfb98ff102f9..1e0047dc483cf67817fdb27a6797e8871c18b881 100644 (file)
@@ -671,7 +671,7 @@ class Exporter:
                                self.out_file.begin("texture2d")
                                self.out_file.write("min_filter", "NEAREST")
                                self.out_file.write("mag_filter", "NEAREST")
-                               self.out_file.write("storage", "RGB", len(mesh.materials), 1, 0)
+                               self.out_file.write("storage", "RGB", len(mesh.materials), 1)
                                texdata = '"'
                                for m in mesh.materials:
                                        texdata += "\\x%02X\\x%02X\\x%02X"%(int(m.R*255), int(m.G*255), int(m.B*255))
index 040fd6c7b1fa5ea5f995aafc4e45784665a87269..7c4338f8e1fe975706b677ec810e42b9dd91bd36 100644 (file)
@@ -76,7 +76,7 @@ Bloom::Bloom(unsigned w, unsigned h):
        {
                blur_shdata[i].uniform(loc, 0);
                tex[i].set_min_filter(NEAREST);
-               tex[i].storage(RGB16F, w, h, 0);
+               tex[i].storage(RGB16F, w, h);
                tex[i].image(0, RGB, UNSIGNED_BYTE, 0);
        }
 
index f05d15b8271fe0ce9f216b62258f50d10758f231..95f96536f81c1f6891c5be726c2517ca95a08e2a 100644 (file)
@@ -119,7 +119,7 @@ void Pipeline::add_postprocessor(PostProcessor &pp)
                color_buf = new Texture2D;
                color_buf->set_min_filter(NEAREST);
                color_buf->set_mag_filter(NEAREST);
-               color_buf->storage((hdr ? RGB16F : RGB), width, height, 0);
+               color_buf->storage((hdr ? RGB16F : RGB), width, height);
                color_buf->image(0, RGB, UNSIGNED_BYTE, 0);
                fbo->attach(COLOR_ATTACHMENT0, *color_buf, 0);
                depth_buf = new Renderbuffer;
index 27a814e21e1c30b946c24cf2fad6287dc073a664..91f102261cf63006d933b017427656adc8cb867d 100644 (file)
@@ -65,5 +65,25 @@ PixelFormat pixelformat_from_graphics(Graphics::PixelFormat pf)
        }
 }
 
+PixelFormat get_base_pixelformat(PixelFormat pf)
+{
+       switch(pf)
+       {
+       case RGB8:
+       case RGB16F:
+       case RGB32F: return RGB;
+       case RGBA8:
+       case RGBA16F:
+       case RGBA32F: return RGBA;
+       case LUMINANCE8:
+       case LUMINANCE16F:
+       case LUMINANCE32F: return LUMINANCE;
+       case LUMINANCE_ALPHA8:
+       case LUMINANCE_ALPHA16F:
+       case LUMINANCE_ALPHA32F: return LUMINANCE_ALPHA;
+       default: return pf;
+       }
+}
+
 } // namespace GL
 } // namespace Msp
index 6063145ad859c042eb5070c5ae787ad94d904d87..81662cb9ea63dd798fe91a4218e8f47f0cdf3fae 100644 (file)
@@ -49,6 +49,8 @@ std::istream &operator>>(std::istream &, PixelFormat &);
 
 PixelFormat pixelformat_from_graphics(Graphics::PixelFormat);
 
+PixelFormat get_base_pixelformat(PixelFormat);
+
 } // namespace GL
 } // namespace Msp
 
index c8730426e6a557b113440914bef162239bc02751..dbc4bd56524688170770d0e5d9fabe68ea3eac3c 100644 (file)
@@ -30,7 +30,7 @@ ShadowMap::ShadowMap(unsigned s, const Scene &c, const Light &l):
        depth_buf.set_compare_enabled(true);
        depth_buf.set_compare_func(LEQUAL);
        depth_buf.set_wrap(CLAMP_TO_EDGE);
-       depth_buf.storage(DEPTH_COMPONENT, size, size, 0);
+       depth_buf.storage(DEPTH_COMPONENT, size, size);
        depth_buf.image(0, DEPTH_COMPONENT, UNSIGNED_BYTE, 0);
        fbo.attach(DEPTH_ATTACHMENT, depth_buf, 0);
 }
index dc69732fe2f33dafff253b51359898bbcaf1c260..52ad074281d30b945f0b2f328883f25ef06704da 100644 (file)
@@ -76,7 +76,7 @@ void Texture::update_parameter(int mask) const
                        glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, gen_mipmap);
                if(mask&COMPARE)
                        glTexParameteri(target, GL_TEXTURE_COMPARE_MODE, (compare ? GL_COMPARE_R_TO_TEXTURE : GL_NONE));
-               if(mask&cmp_func)
+               if(mask&COMPARE_FUNC)
                        glTexParameteri(target, GL_TEXTURE_COMPARE_FUNC, cmp_func);
        }
        else
index 8935933f995117322069ad1652b6b1d9ffc87d0c..c92099cedb35e79c362ab6cab25acd0d7359bd25 100644 (file)
@@ -17,10 +17,11 @@ namespace GL {
 Texture2D::Texture2D():
        Texture(GL_TEXTURE_2D),
        width(0),
-       height(0)
+       height(0),
+       allocated(0)
 { }
 
-void Texture2D::storage(PixelFormat fmt, unsigned wd, unsigned ht, int brd)
+void Texture2D::storage(PixelFormat fmt, unsigned wd, unsigned ht)
 {
        if(width>0)
                throw InvalidState("Texture storage may only be specified once");
@@ -30,22 +31,39 @@ void Texture2D::storage(PixelFormat fmt, unsigned wd, unsigned ht, int brd)
        ifmt = fmt;
        width = wd;
        height = ht;
-       border = brd;
 }
 
-void Texture2D::image(int level, PixelFormat fmt, DataType type, const void *data)
+void Texture2D::allocate(unsigned level)
 {
-       if(width==0)
-               throw InvalidState("Texture storage has not been specified");
+       if(allocated&(1<<level))
+               return;
+
+       image(level, get_base_pixelformat(ifmt), UNSIGNED_BYTE, 0);
+}
+
+void Texture2D::image(unsigned level, PixelFormat fmt, DataType type, const void *data)
+{
+       require_storage();
+
+       unsigned w = width;
+       unsigned h = height;
+       get_level_size(level, w, h);
 
        Bind _bind(this, true);
-       glTexImage2D(target, level, ifmt, width, height, border, fmt, type, data);
+       glTexImage2D(target, level, ifmt, w, h, 0, fmt, type, data);
+
+       allocated |= 1<<level;
+       if(gen_mipmap && level==0)
+       {
+               for(; (w || h); w>>=1, h>>=1, ++level) ;
+               allocated |= (1<<level)-1;
+       }
 }
 
-void Texture2D::sub_image(int level, int x, int y, unsigned wd, unsigned ht, PixelFormat fmt, DataType type, const void *data)
+void Texture2D::sub_image(unsigned level, int x, int y, unsigned wd, unsigned ht, PixelFormat fmt, DataType type, const void *data)
 {
-       if(width==0)
-               throw InvalidState("Texture storage has not been specified");
+       require_storage();
+       allocate(level);
 
        Bind _bind(this, true);
        glTexSubImage2D(target, level, x, y, wd, ht, fmt, type, data);
@@ -65,13 +83,30 @@ void Texture2D::image(const Graphics::Image &img)
        unsigned h = img.get_height();
        PixelFormat fmt = pixelformat_from_graphics(img.get_format());
        if(width==0)
-               storage(fmt, w, h, 0);
+               storage(fmt, w, h);
        else if(w!=width || h!=height)
                throw IncompatibleData("Image does not match texture storage");
 
        image(0, fmt, UNSIGNED_BYTE, img.get_data());
 }
 
+void Texture2D::require_storage()
+{
+       if(width==0 || height==0)
+               throw InvalidState("Texture storage has not been specified");
+}
+
+void Texture2D::get_level_size(unsigned level, unsigned &w, unsigned &h)
+{
+       w >>= level;
+       h >>= level;
+
+       if(!w && h)
+               w = 1;
+       else if(!h && w)
+               h = 1;
+}
+
 
 Texture2D::Loader::Loader(Texture2D &t):
        Texture::Loader(t)
@@ -79,6 +114,7 @@ Texture2D::Loader::Loader(Texture2D &t):
        add("image_data", &Loader::image_data);
        add("raw_data", &Loader::raw_data);
        add("storage", &Loader::storage);
+       add("storage", &Loader::storage_b);
 }
 
 void Texture2D::Loader::image_data(const string &data)
@@ -95,9 +131,14 @@ void Texture2D::Loader::raw_data(const string &data)
        t2d.image(0, t2d.ifmt, UNSIGNED_BYTE, data.data());
 }
 
-void Texture2D::Loader::storage(PixelFormat fmt, unsigned w, unsigned h, unsigned b)
+void Texture2D::Loader::storage(PixelFormat fmt, unsigned w, unsigned h)
+{
+       static_cast<Texture2D &>(obj).storage(fmt, w, h);
+}
+
+void Texture2D::Loader::storage_b(PixelFormat fmt, unsigned w, unsigned h, unsigned)
 {
-       static_cast<Texture2D &>(obj).storage(fmt, w, h, b);
+       storage(fmt, w, h);
 }
 
 } // namespace GL
index 012718528af72592039831c2a27c69b6a58aa728..8508b0435847eaa7eaf9485c5b0765017e4dbe6f 100644 (file)
@@ -30,14 +30,15 @@ public:
        private:
                void image_data(const std::string &);
                void raw_data(const std::string &);
-               void storage(PixelFormat, unsigned, unsigned, unsigned);
+               void storage(PixelFormat, unsigned, unsigned);
+               void storage_b(PixelFormat, unsigned, unsigned, unsigned);
        };
 
 private:
        PixelFormat ifmt;
        unsigned width;
        unsigned height;
-       int border;
+       unsigned allocated;
 
 public:
        Texture2D();
@@ -46,20 +47,22 @@ public:
        Defines the texture storage.  This function may only be successfully called
        once.
        */
-       void storage(PixelFormat fmt, unsigned wd, unsigned ht, int brd);
+       void storage(PixelFormat fmt, unsigned wd, unsigned ht);
+
+       /** Allocates texture storage.  If storage has already been allocated, this
+       function does nothing. */
+       void allocate(unsigned level);
        
-       /**
-       Uploads an image to the texture.  storage() must have been called prior to
+       /** Uploads an image to the texture.  storage() must have been called prior to
        this, and the image must have dimensions conforming to the specified
-       storage.
-       */
-       void image(int level, PixelFormat fmt, DataType type, const void *data);
+       storage.  For level>0, mipmapping rules apply to the image dimensions. */
+       void image(unsigned level, PixelFormat fmt, DataType type, const void *data);
 
        /**
        Uploads a sub-image into the texture.  Unlike full image upload, there are
        no constraints on the size of the sub-image.
        */
-       void sub_image(int level, int x, int y, unsigned wd, unsigned ht, PixelFormat fmt, DataType type, const void *data);
+       void sub_image(unsigned level, int x, int y, unsigned wd, unsigned ht, PixelFormat fmt, DataType type, const void *data);
 
        /**
        Loads an image from a file and uploads it to the texture.  If storage() has
@@ -72,6 +75,8 @@ public:
 
 private:
        void image(const Graphics::Image &);
+       void require_storage();
+       void get_level_size(unsigned, unsigned &, unsigned &);
 };
 
 } // namespace GL
index 7edc908098c73ed0866ff6d9733874f4efa7993d..6515946bb2bba5885dd6dd6d5c425438804cc400 100644 (file)
@@ -22,12 +22,13 @@ Texture3D::Texture3D():
        Texture(GL_TEXTURE_3D),
        width(0),
        height(0),
-       depth(0)
+       depth(0),
+       allocated(0)
 {
        static RequireVersion _ver(1, 2);
 }
 
-void Texture3D::storage(PixelFormat f, unsigned w, unsigned h, unsigned d, int b)
+void Texture3D::storage(PixelFormat f, unsigned w, unsigned h, unsigned d)
 {
        if(width>0)
                throw InvalidState("Textures storage may only be specified once");
@@ -38,18 +39,45 @@ void Texture3D::storage(PixelFormat f, unsigned w, unsigned h, unsigned d, int b
        height = h;
        depth = d;
        ifmt = f;
-       border = b;
 
        image(0, ifmt, UNSIGNED_BYTE, 0);
 }
 
-void Texture3D::image(int level, PixelFormat fmt, DataType type, const void *data)
+void Texture3D::allocate(unsigned level)
 {
-       if(width==0)
-               throw InvalidState("Texture storage has not been specified");
+       if(allocated&(1<<level))
+               return;
+
+       image(level, get_base_pixelformat(ifmt), UNSIGNED_BYTE, 0);
+}
+
+void Texture3D::image(unsigned level, PixelFormat fmt, DataType type, const void *data)
+{
+       require_storage();
+
+       unsigned w = width;
+       unsigned h = height;
+       unsigned d = depth;
+       get_level_size(level, w, h, d);
+
+       Bind _bind(this, true);
+       glTexImage3D(target, level, ifmt, width, height, depth, 0, fmt, type, data);
+
+       allocated |= 1<<level;
+       if(gen_mipmap && level==0)
+       {
+               for(; (w || h || d); w>>=1, h>>=1, d>>=1, ++level) ;
+               allocated |= (1<<level)-1;
+       }
+}
+
+void Texture3D::sub_image(unsigned level, int x, int y, int z, unsigned wd, unsigned ht, unsigned dp, PixelFormat fmt, DataType type, const void *data)
+{
+       require_storage();
+       allocate(level);
 
        Bind _bind(this, true);
-       glTexImage3D(target, level, ifmt, width, height, depth, border, fmt, type, data);
+       glTexSubImage3D(target, level, x, y, z, wd, ht, dp, fmt, type, data);
 }
 
 void Texture3D::load_image(const string &fn, int dp)
@@ -81,12 +109,32 @@ void Texture3D::load_image(const string &fn, int dp)
 
        PixelFormat fmt = pixelformat_from_graphics(img.get_format());
        if(width==0)
-               storage(fmt, w, h, d, 0);
+               storage(fmt, w, h, d);
        else if(w!=width || h!=height || d!=depth)
                throw IncompatibleData("Image does not match texture storage");
 
        image(0, fmt, UNSIGNED_INT, img.get_data());
 }
 
+void Texture3D::require_storage()
+{
+       if(width==0 || height==0 || depth==0)
+               throw InvalidState("Texture storage has not been specified");
+}
+
+void Texture3D::get_level_size(unsigned level, unsigned &w, unsigned &h, unsigned &d)
+{
+       w >>= level;
+       h >>= level;
+       d >>= level;
+
+       if(!w && (h || d))
+               w = 1;
+       if(!h && (w || d))
+               h = 1;
+       if(!d && (w || h))
+               d = 1;
+}
+
 } // namespace GL
 } // namespace Msp
index 50e4555aa56cca44e3ec0d66ee09d2641a81f3ab..15d244dec10f116eca42f8c53515e3994720e90a 100644 (file)
@@ -23,17 +23,21 @@ private:
        unsigned width;
        unsigned height;
        unsigned depth;
-       int border;
+       unsigned allocated;
 
 public:
        Texture3D();
-       void storage(PixelFormat, unsigned, unsigned, unsigned, int);
-       void image(int, PixelFormat, DataType, const void *);
-       void sub_image(int, int, int, unsigned, unsigned, unsigned, PixelFormat, DataType, const void *);
+       void storage(PixelFormat, unsigned, unsigned, unsigned);
+       void allocate(unsigned);
+       void image(unsigned, PixelFormat, DataType, const void *);
+       void sub_image(unsigned, int, int, int, unsigned, unsigned, unsigned, PixelFormat, DataType, const void *);
        void load_image(const std::string &fn, int dp = -1);
        unsigned get_width() const { return width; }
        unsigned get_height() const { return height; }
        unsigned get_depth() const { return depth; }
+private:
+       void require_storage();
+       void get_level_size(unsigned, unsigned &, unsigned &, unsigned &);
 };
 
 } // namespace GL