]> git.tdb.fi Git - libs/gl.git/blobdiff - source/bindable.h
Add support for multiple binding points in the RAII binders
[libs/gl.git] / source / bindable.h
index f534d7afd8e9788e412dd0d2ddd876eee0091c8e..8651c70ee066b6cbfa2e8f40cd967b0a92f148cd 100644 (file)
@@ -71,8 +71,9 @@ does nothing upon destruction.
 class Bind
 {
 private:
-       typedef void CleanupFunc();
+       typedef void CleanupFunc(int);
 
+       int slot;
        CleanupFunc *cleanup;
 
 public:
@@ -85,6 +86,15 @@ public:
        template<typename T>
        Bind(const T &o) { init(&o); }
 
+       template<typename T, typename S>
+       Bind(T *o, S s) { init(o, s); }
+
+       template<typename T, typename S>
+       Bind(const T *o, S s) { init(o, s); }
+
+       template<typename T, typename S>
+       Bind(const T &o, S s) { init(&o, s); }
+
 private:
        template<typename T>
        void init(const T *o)
@@ -96,14 +106,29 @@ private:
                        T::unbind();
        }
 
+       template<typename T, typename S>
+       void init(const T *o, S s)
+       {
+               cleanup = (o ? &unbind_from<T, S> : 0);
+               slot = s;
+               if(o)
+                       o->bind_to(s);
+               else
+                       T::unbind_from(s);
+       }
+
 public:
        ~Bind()
-       { if(cleanup) cleanup(); }
+       { if(cleanup) cleanup(slot); }
 
 private:
        template<typename T>
-       static void unbind()
+       static void unbind(int)
        { T::unbind(); }
+
+       template<typename T, typename S>
+       static void unbind_from(int s)
+       { T::unbind_from(static_cast<S>(s)); }
 };
 
 
@@ -113,9 +138,10 @@ Similar to Bind, but restores previous binding upon destruction.
 class BindRestore
 {
 private:
-       typedef void CleanupFunc(const void *);
+       typedef void CleanupFunc(const void *, int);
 
        const void *old;
+       int slot;
        CleanupFunc *cleanup;
 
 public:
@@ -128,6 +154,15 @@ public:
        template<typename T>
        BindRestore(const T &o) { init(&o); }
 
+       template<typename T, typename S>
+       BindRestore(T *o, S s) { init(o, s); }
+
+       template<typename T, typename S>
+       BindRestore(const T *o, S s) { init(o, s); }
+
+       template<typename T, typename S>
+       BindRestore(const T &o, S s) { init(&o, s); }
+
 private:
        template<typename T>
        void init(T *o)
@@ -140,19 +175,41 @@ private:
                        T::unbind();
        }
 
+       template<typename T, typename S>
+       void init(T *o, S s)
+       {
+               old = T::current(s);
+               slot = s;
+               cleanup = (o!=old ? &restore_to<T, S> : 0);
+               if(o)
+                       o->bind_to(s);
+               else if(old)
+                       T::unbind_from(s);
+       }
+
 public:
        ~BindRestore()
-       { if(cleanup) cleanup(old); }
+       { if(cleanup) cleanup(old, slot); }
 
 private:
        template<typename T>
-       static void restore(const void *o)
+       static void restore(const void *o, int)
        {
                if(o)
                        reinterpret_cast<const T *>(o)->bind();
                else
                        T::unbind();
        }
+
+       template<typename T, typename S>
+       static void restore_to(const void *o, int si)
+       {
+               S s = static_cast<S>(si);
+               if(o)
+                       reinterpret_cast<const T *>(o)->bind_to(s);
+               else
+                       T::unbind_from(s);
+       }
 };
 
 } // namespace GL