]> git.tdb.fi Git - libs/gl.git/commitdiff
Rewrite Bind as two different classes
authorMikko Rasa <tdb@tdb.fi>
Sat, 21 Dec 2013 09:36:40 +0000 (11:36 +0200)
committerMikko Rasa <tdb@tdb.fi>
Sat, 21 Dec 2013 09:56:06 +0000 (11:56 +0200)
Boolean flag parameters are not too clear without seeing the declaration.
This new implementation also doesn't use dynamic allocation.

source/ambientocclusion.cpp
source/bindable.h
source/bloom.cpp
source/font.cpp
source/framebuffer.cpp
source/pipeline.cpp
source/renderbuffer.cpp
source/shadowmap.cpp
source/texture2d.cpp
source/texture3d.cpp
source/texturecube.cpp

index 4ef376251a6a065013666f85bfe4803db1b4f2e9..f42069bebae007ed15105e34536dada4a98eec98 100644 (file)
@@ -135,11 +135,11 @@ void AmbientOcclusion::render(const Texture2D &color, const Texture2D &depth)
        combine_texturing.attach(0, depth);
        combine_texturing.attach(1, color);
 
-       Bind unbind_dtest(static_cast<DepthTest *>(0), true);
-       Bind unbind_blend(static_cast<Blend *>(0), true);
+       BindRestore unbind_dtest(static_cast<DepthTest *>(0));
+       BindRestore unbind_blend(static_cast<Blend *>(0));
 
        {
-               Bind bind_fbo(fbo, true);
+               BindRestore bind_fbo(fbo);
                Bind bind_tex(occlude_texturing);
                Bind bind_shader(occlude_shader);
                occlude_shdata.apply();
index bde5e85a11752b3a95a07de5187ad174b3c4a50a..f534d7afd8e9788e412dd0d2ddd876eee0091c8e 100644 (file)
@@ -66,95 +66,93 @@ public:
 /**
 RAII class for binding things.  Binds the thing upon construction and unbinds
 it upon destruction.  If a null pointer is given, unbinds upon construction and
-does nothing upon destruction.  Optionally can restore the previous binding.
+does nothing upon destruction.
 */
 class Bind
 {
 private:
-       struct Base
-       {
-               virtual ~Base() { }
-       };
+       typedef void CleanupFunc();
+
+       CleanupFunc *cleanup;
 
+public:
        template<typename T>
-       struct Binder1: Base
-       {
-               const T *obj;
-
-               Binder1(const T *o):
-                       obj(o)
-               {
-                       if(obj)
-                               obj->bind();
-                       else
-                               T::unbind();
-               }
-
-               ~Binder1()
-               {
-                       if(obj)
-                               obj->unbind();
-               }
-       };
-
-       template<typename T, typename U>
-       struct Binder2: Base
+       Bind(T *o) { init(o); }
+
+       template<typename T>
+       Bind(const T *o) { init(o); }
+
+       template<typename T>
+       Bind(const T &o) { init(&o); }
+
+private:
+       template<typename T>
+       void init(const T *o)
        {
-               const T *obj;
-               const U *old;
-
-               Binder2(const T *o, const U *l):
-                       obj(o),
-                       old(l)
-               {
-                       if(obj)
-                               obj->bind();
-                       else
-                               T::unbind();
-               }
-
-               ~Binder2()
-               {
-                       if(old)
-                               old->bind();
-                       else if(obj)
-                               obj->unbind();
-               }
-       };
-
-       Base *binder;
+               cleanup = (o ? &unbind<T> : 0);
+               if(o)
+                       o->bind();
+               else
+                       T::unbind();
+       }
+
+public:
+       ~Bind()
+       { if(cleanup) cleanup(); }
+
+private:
+       template<typename T>
+       static void unbind()
+       { T::unbind(); }
+};
+
+
+/**
+Similar to Bind, but restores previous binding upon destruction.
+*/
+class BindRestore
+{
+private:
+       typedef void CleanupFunc(const void *);
+
+       const void *old;
+       CleanupFunc *cleanup;
 
 public:
        template<typename T>
-       Bind(const T &o, bool r = false):
-               binder(r ? create(&o, T::current()) : create(&o))
-       { }
+       BindRestore(T *o) { init(o); }
 
        template<typename T>
-       Bind(const T *o, bool r = false):
-               binder(r ? create(o, T::current()) : create(o))
-       { }
+       BindRestore(const T *o) { init(o); }
 
        template<typename T>
-       Bind(T *o, bool r = false):
-               binder(r ? create(o, T::current()) : create(o))
-       { }
+       BindRestore(const T &o) { init(&o); }
 
 private:
-       Bind(const Bind &);
-       Bind &operator=(const Bind &);
+       template<typename T>
+       void init(T *o)
+       {
+               old = T::current();
+               cleanup = (o!=old ? &restore<T> : 0);
+               if(o)
+                       o->bind();
+               else if(old)
+                       T::unbind();
+       }
 
 public:
-       ~Bind() { delete binder; }
+       ~BindRestore()
+       { if(cleanup) cleanup(old); }
 
 private:
        template<typename T>
-       Base *create(const T *o)
-       { return new Binder1<T>(o); }
-
-       template<typename T, typename U>
-       Base *create(const T *o, const U *l)
-       { return new Binder2<T, U>(o, l); }
+       static void restore(const void *o)
+       {
+               if(o)
+                       reinterpret_cast<const T *>(o)->bind();
+               else
+                       T::unbind();
+       }
 };
 
 } // namespace GL
index ad7ec26943c4230a97ec0a5f0b30750f7680a22f..5ffa82f673010713fa89bed65c5a0d406a559245 100644 (file)
@@ -100,15 +100,15 @@ void Bloom::set_strength(float s)
 
 void Bloom::render(const Texture2D &src, const Texture2D &)
 {
-       Bind unbind_dtest(static_cast<DepthTest *>(0), true);
-       Bind unbind_blend(static_cast<Blend *>(0), true);
+       BindRestore unbind_dtest(static_cast<DepthTest *>(0));
+       BindRestore unbind_blend(static_cast<Blend *>(0));
 
        {
                Bind bind_shader(blur_shader);
                blur_shdata_common.apply();
                for(unsigned i=0; i<2; ++i)
                {
-                       Bind bind_fbo(fbo[i], true);
+                       BindRestore bind_fbo(fbo[i]);
                        Bind bind_tex(i ? tex[0] : src);
                        blur_shdata[i].apply();
                        quad.draw();
index 1639f4a3726bbe853a8b324c65c3d3296f82626b..1005609eb16a8ed1a08377c276a7c152c61d22a0 100644 (file)
@@ -64,7 +64,7 @@ float Font::get_string_width(const string &str, StringCodec::Decoder &dec) const
 
 void Font::draw_string(const string &str, StringCodec::Decoder &dec, const Color &color) const
 {
-       Bind bind_tex(get_texture(), true);
+       BindRestore bind_tex(get_texture());
        Immediate imm((TEXCOORD2, COLOR4_UBYTE, VERTEX2));
        imm.color(color);
        build_string(str, dec, imm);
index ae8f4dd471a936881f77e8e569de8e97ba5bc8c0..672495182f7f641bbf419c2ea5b35dd28af6c28e 100644 (file)
@@ -213,7 +213,7 @@ void Framebuffer::detach(FramebufferAttachment attch)
 
 FramebufferStatus Framebuffer::check_status() const
 {
-       Bind _bind(this, true);
+       BindRestore _bind(this);
        return static_cast<FramebufferStatus>(glCheckFramebufferStatus(GL_FRAMEBUFFER));
 }
 
@@ -226,7 +226,7 @@ void Framebuffer::require_complete() const
 
 void Framebuffer::clear(BufferBits bits)
 {
-       Bind _bind(this, true);
+       BindRestore _bind(this);
        glClear(bits);
 }
 
index 8229515f96d6830846f0505590d811329715c946..0546a4e847829f33844cf6236db2047816ba0b2f 100644 (file)
@@ -147,9 +147,7 @@ void Pipeline::render(Renderer &renderer, const Tag &tag) const
                setup_frame();
 
        const Framebuffer *out_fbo = Framebuffer::current();
-       /* Binding the current object is a no-op, but this will restore the original
-       FBO in case an exception is thrown. */
-       Bind restore_fbo(out_fbo, true);
+       // XXX Make sure the correct FBO is restored if an exception is thrown
 
        if(target[0])
        {
index 89b255003c57dae72f21b1fac010f60e9d243d75..b2b25a0890212b41bc08251845d80385abf7451a 100644 (file)
@@ -20,7 +20,7 @@ Renderbuffer::~Renderbuffer()
 void Renderbuffer::storage(PixelFormat fmt, unsigned wd, unsigned ht)
 {
        require_pixelformat(fmt);
-       Bind _bind(this, true);
+       BindRestore _bind(this);
        width = wd;
        height = ht;
        glRenderbufferStorage(GL_RENDERBUFFER, fmt, width, height);
@@ -31,7 +31,7 @@ void Renderbuffer::storage_multisample(unsigned samples, PixelFormat fmt, unsign
        static Require _req(EXT_framebuffer_multisample);
        require_pixelformat(fmt);
 
-       Bind _bind(this, true);
+       BindRestore _bind(this);
        width = wd;
        height = ht;
        glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, fmt, width, height);
index 8151a7cffe48c41429005470ac3595916fb309e1..21e67c38a5efeeb08a20fcbd917dc2b767f9ed39 100644 (file)
@@ -104,7 +104,7 @@ void ShadowMap::setup_frame() const
        shadow_matrix.translate(-0.5, -0.5, depth_bias/size-0.5);
        shadow_matrix.invert();
 
-       Bind bind_fbo(fbo, true);
+       BindRestore bind_fbo(fbo);
        Bind bind_depth(DepthTest::lequal());
        fbo.clear(DEPTH_BUFFER_BIT);
        renderable.render("shadow");
index 7a9701f5e616f448465c1335f695b871d3d34d04..973afebfcf277b75d217e2d0262e83846e06e41a 100644 (file)
@@ -46,7 +46,7 @@ void Texture2D::image(unsigned level, PixelFormat fmt, DataType type, const void
        unsigned h = height;
        get_level_size(level, w, h);
 
-       Bind _bind(this, true);
+       BindRestore _bind(this);
        glTexImage2D(target, level, ifmt, w, h, 0, fmt, type, data);
 
        allocated |= 1<<level;
@@ -64,7 +64,7 @@ void Texture2D::sub_image(unsigned level, int x, int y, unsigned wd, unsigned ht
 
        allocate(level);
 
-       Bind _bind(this, true);
+       BindRestore _bind(this);
        glTexSubImage2D(target, level, x, y, wd, ht, fmt, type, data);
 }
 
@@ -87,7 +87,7 @@ void Texture2D::image(const Graphics::Image &img)
                throw incompatible_data("Texture2D::image");
 
        PixelStore pstore = PixelStore::from_image(img);
-       Bind _bind_ps(pstore, true);
+       BindRestore _bind_ps(pstore);
 
        image(0, fmt, UNSIGNED_BYTE, img.get_data());
 }
index 3d322d4b9bd9c14834097c81773c085e9bda7584..3846ef1c1294e18d78b183e4208366648c76a46f 100644 (file)
@@ -53,7 +53,7 @@ void Texture3D::image(unsigned level, PixelFormat fmt, DataType type, const void
        unsigned d = depth;
        get_level_size(level, w, h, d);
 
-       Bind _bind(this, true);
+       BindRestore _bind(this);
        glTexImage3D(target, level, ifmt, width, height, depth, 0, fmt, type, data);
 
        allocated |= 1<<level;
@@ -71,7 +71,7 @@ void Texture3D::sub_image(unsigned level, int x, int y, int z, unsigned wd, unsi
 
        allocate(level);
 
-       Bind _bind(this, true);
+       BindRestore _bind(this);
        glTexSubImage3D(target, level, x, y, z, wd, ht, dp, fmt, type, data);
 }
 
@@ -116,7 +116,7 @@ void Texture3D::load_image(const string &fn, int dp)
                throw incompatible_data("Texture3D::load_image");
 
        PixelStore pstore = PixelStore::from_image(img);
-       Bind _bind_ps(pstore, true);
+       BindRestore _bind_ps(pstore);
 
        image(0, fmt, UNSIGNED_BYTE, img.get_data());
 }
index 38d99367fe4441d431a7699d08515fc8977ae025..7f8301187c35e07257037aec9967ad6b502e83a8 100644 (file)
@@ -59,7 +59,7 @@ void TextureCube::image(TextureCubeFace face, unsigned level, PixelFormat fmt, D
        if(s==0)
                throw out_of_range("TextureCube::image");
 
-       Bind _bind(this, true);
+       BindRestore _bind(this);
        glTexImage2D(face, level, ifmt, s, s, 0, fmt, type, data);
 
        // XXX Allocation should be tracked per-face, but we'll run out of bits
@@ -87,7 +87,7 @@ void TextureCube::image(TextureCubeFace face, const Graphics::Image &img)
                throw incompatible_data("TextureCube::image");
 
        PixelStore pstore = PixelStore::from_image(img);
-       Bind _bind_ps(pstore, true);
+       BindRestore _bind_ps(pstore);
 
        image(face, 0, fmt, UNSIGNED_BYTE, img.get_data());
 }