]> git.tdb.fi Git - libs/gl.git/blob - source/bindable.h
Lots of comment updates
[libs/gl.git] / source / bindable.h
1 #ifndef MSP_GL_BINDABLE_H_
2 #define MSP_GL_BINDABLE_H_
3
4 namespace Msp {
5 namespace GL {
6
7 /**
8 A helper class for single-point binding.  Provides tracking of the currently
9 bound object.
10 */
11 template<typename T>
12 class Bindable
13 {
14 protected:
15         static const T *cur_obj;
16
17         Bindable() { }
18
19         static bool set_current(const T *obj)
20         {
21                 if(obj==cur_obj)
22                         return false;
23
24                 cur_obj = obj;
25                 return true;
26         }
27
28 public:
29         static const T *current() { return cur_obj; }
30 };
31
32 template<typename T>
33 const T *Bindable<T>::cur_obj;
34
35
36 /**
37 RAII class for binding things.  Binds the thing upon construction and unbinds
38 it upon destruction.  If a null pointer is given, unbinds upon construction and
39 does nothing upon destruction.  Optionally can restore the previous binding.
40 */
41 class Bind
42 {
43 private:
44         struct Base
45         {
46                 virtual ~Base() { }
47         };
48
49         template<typename T>
50         struct Binder1: Base
51         {
52                 const T *obj;
53
54                 Binder1(const T *o):
55                         obj(o)
56                 {
57                         if(obj)
58                                 obj->bind();
59                         else
60                                 T::unbind();
61                 }
62
63                 ~Binder1()
64                 {
65                         if(obj)
66                                 obj->unbind();
67                 }
68         };
69
70         template<typename T, typename U>
71         struct Binder2: Base
72         {
73                 const T *obj;
74                 const U *old;
75
76                 Binder2(const T *o, const U *l):
77                         obj(o),
78                         old(l)
79                 {
80                         if(obj)
81                                 obj->bind();
82                         else
83                                 T::unbind();
84                 }
85
86                 ~Binder2()
87                 {
88                         if(old)
89                                 old->bind();
90                         else if(obj)
91                                 obj->unbind();
92                 }
93         };
94
95         Base *binder;
96
97 public:
98         template<typename T>
99         Bind(const T &o, bool r = false):
100                 binder(r ? create(&o, T::current()) : create(&o))
101         { }
102
103         template<typename T>
104         Bind(const T *o, bool r = false):
105                 binder(r ? create(o, T::current()) : create(o))
106         { }
107
108         template<typename T>
109         Bind(T *o, bool r = false):
110                 binder(r ? create(o, T::current()) : create(o))
111         { }
112
113 private:
114         Bind(const Bind &);
115         Bind &operator=(const Bind &);
116
117 public:
118         ~Bind() { delete binder; }
119
120 private:
121         template<typename T>
122         Base *create(const T *o)
123         { return new Binder1<T>(o); }
124
125         template<typename T, typename U>
126         Base *create(const T *o, const U *l)
127         { return new Binder2<T, U>(o, l); }
128 };
129
130 } // namespace GL
131 } // namespace Msp
132
133 #endif