]> git.tdb.fi Git - libs/gl.git/blob - source/bindable.h
Deal with nontrivial image configurations
[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 A helper class for Bindables that revert to a default object on unbind.
38 */
39 template<typename T>
40 class BindableWithDefault: protected Bindable<T>
41 {
42 protected:
43         BindableWithDefault() { }
44
45 public:
46         static const T *current()
47         {
48                 if(!Bindable<T>::cur_obj)
49                         Bindable<T>::cur_obj = &default_object();
50                 return Bindable<T>::cur_obj;
51         }
52
53         static void unbind()
54         {
55                 default_object().bind();
56         }
57
58         static const T &default_object()
59         {
60                 static T obj;
61                 return obj;
62         }
63 };
64
65
66 /**
67 RAII class for binding things.  Binds the thing upon construction and unbinds
68 it upon destruction.  If a null pointer is given, unbinds upon construction and
69 does nothing upon destruction.  Optionally can restore the previous binding.
70 */
71 class Bind
72 {
73 private:
74         struct Base
75         {
76                 virtual ~Base() { }
77         };
78
79         template<typename T>
80         struct Binder1: Base
81         {
82                 const T *obj;
83
84                 Binder1(const T *o):
85                         obj(o)
86                 {
87                         if(obj)
88                                 obj->bind();
89                         else
90                                 T::unbind();
91                 }
92
93                 ~Binder1()
94                 {
95                         if(obj)
96                                 obj->unbind();
97                 }
98         };
99
100         template<typename T, typename U>
101         struct Binder2: Base
102         {
103                 const T *obj;
104                 const U *old;
105
106                 Binder2(const T *o, const U *l):
107                         obj(o),
108                         old(l)
109                 {
110                         if(obj)
111                                 obj->bind();
112                         else
113                                 T::unbind();
114                 }
115
116                 ~Binder2()
117                 {
118                         if(old)
119                                 old->bind();
120                         else if(obj)
121                                 obj->unbind();
122                 }
123         };
124
125         Base *binder;
126
127 public:
128         template<typename T>
129         Bind(const T &o, bool r = false):
130                 binder(r ? create(&o, T::current()) : create(&o))
131         { }
132
133         template<typename T>
134         Bind(const T *o, bool r = false):
135                 binder(r ? create(o, T::current()) : create(o))
136         { }
137
138         template<typename T>
139         Bind(T *o, bool r = false):
140                 binder(r ? create(o, T::current()) : create(o))
141         { }
142
143 private:
144         Bind(const Bind &);
145         Bind &operator=(const Bind &);
146
147 public:
148         ~Bind() { delete binder; }
149
150 private:
151         template<typename T>
152         Base *create(const T *o)
153         { return new Binder1<T>(o); }
154
155         template<typename T, typename U>
156         Base *create(const T *o, const U *l)
157         { return new Binder2<T, U>(o, l); }
158 };
159
160 } // namespace GL
161 } // namespace Msp
162
163 #endif