]> git.tdb.fi Git - libs/gl.git/blob - source/bindable.h
Copy the material slot of RenderPass
[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         ~Bindable() { if(cur_obj==this) T::unbind(); }
19
20         static bool set_current(const T *obj)
21         {
22                 if(obj==cur_obj)
23                         return false;
24
25                 cur_obj = obj;
26                 return true;
27         }
28
29 public:
30         static const T *current() { return cur_obj; }
31 };
32
33 template<typename T>
34 const T *Bindable<T>::cur_obj;
35
36
37 /**
38 A helper class for Bindables that revert to a default object on unbind.
39 */
40 template<typename T>
41 class BindableWithDefault: protected Bindable<T>
42 {
43         friend class Bindable<T>;
44
45 protected:
46         BindableWithDefault() { }
47         ~BindableWithDefault() { if(this==&default_object()) Bindable<T>::set_current(0); }
48
49 public:
50         static const T *current()
51         {
52                 if(!Bindable<T>::cur_obj)
53                         Bindable<T>::cur_obj = &default_object();
54                 return Bindable<T>::cur_obj;
55         }
56
57         static void unbind()
58         {
59                 if(Bindable<T>::cur_obj)
60                         default_object().bind();
61         }
62
63         static const T &default_object()
64         {
65                 static T obj;
66                 return obj;
67         }
68 };
69
70
71 /**
72 RAII class for binding things.  Binds the thing upon construction and unbinds
73 it upon destruction.  If a null pointer is given, unbinds upon construction and
74 does nothing upon destruction.
75 */
76 class Bind
77 {
78 private:
79         typedef void CleanupFunc(int);
80
81         int slot;
82         CleanupFunc *cleanup;
83
84 public:
85         template<typename T>
86         Bind(T *o) { init(o); }
87
88         template<typename T>
89         Bind(const T *o) { init(o); }
90
91         template<typename T>
92         Bind(const T &o) { init(&o); }
93
94         template<typename T, typename S>
95         Bind(T *o, S s) { init(o, s); }
96
97         template<typename T, typename S>
98         Bind(const T *o, S s) { init(o, s); }
99
100         template<typename T, typename S>
101         Bind(const T &o, S s) { init(&o, s); }
102
103 private:
104         template<typename T>
105         void init(const T *o)
106         {
107                 cleanup = (o ? static_cast<CleanupFunc *>(&unbind<T>) : 0);
108                 slot = 0;
109                 if(o)
110                         o->bind();
111                 else
112                         T::unbind();
113         }
114
115         template<typename T, typename S>
116         void init(const T *o, S s)
117         {
118                 cleanup = (o ? static_cast<CleanupFunc *>(&unbind_from<T, S>) : 0);
119                 slot = s;
120                 if(o)
121                         o->bind_to(s);
122                 else
123                         T::unbind_from(s);
124         }
125
126 public:
127         ~Bind()
128         { if(cleanup) cleanup(slot); }
129
130 private:
131         template<typename T>
132         static void unbind(int)
133         { T::unbind(); }
134
135         template<typename T, typename S>
136         static void unbind_from(int s)
137         { T::unbind_from(static_cast<S>(s)); }
138 };
139
140
141 /**
142 Similar to Bind, but restores previous binding upon destruction.
143 */
144 class BindRestore
145 {
146 private:
147         typedef void CleanupFunc(const void *, int);
148
149         const void *old;
150         int slot;
151         CleanupFunc *cleanup;
152
153 public:
154         template<typename T>
155         BindRestore(T *o) { init(o); }
156
157         template<typename T>
158         BindRestore(const T *o) { init(o); }
159
160         template<typename T>
161         BindRestore(const T &o) { init(&o); }
162
163         template<typename T, typename S>
164         BindRestore(T *o, S s) { init(o, s); }
165
166         template<typename T, typename S>
167         BindRestore(const T *o, S s) { init(o, s); }
168
169         template<typename T, typename S>
170         BindRestore(const T &o, S s) { init(&o, s); }
171
172 private:
173         template<typename T>
174         void init(T *o)
175         {
176                 old = T::current();
177                 slot = 0;
178                 cleanup = (o!=old ? static_cast<CleanupFunc *>(&restore<T>) : 0);
179                 if(o)
180                         o->bind();
181                 else if(old)
182                         T::unbind();
183         }
184
185         template<typename T, typename S>
186         void init(T *o, S s)
187         {
188                 old = T::current(s);
189                 slot = s;
190                 cleanup = (o!=old ? static_cast<CleanupFunc *>(&restore_to<T, S>) : 0);
191                 if(o)
192                         o->bind_to(s);
193                 else if(old)
194                         T::unbind_from(s);
195         }
196
197 public:
198         ~BindRestore()
199         { if(cleanup) cleanup(old, slot); }
200
201 private:
202         template<typename T>
203         static void restore(const void *o, int)
204         {
205                 if(o)
206                         reinterpret_cast<const T *>(o)->bind();
207                 else
208                         T::unbind();
209         }
210
211         template<typename T, typename S>
212         static void restore_to(const void *o, int si)
213         {
214                 S s = static_cast<S>(si);
215                 if(o)
216                         reinterpret_cast<const T *>(o)->bind_to(s);
217                 else
218                         T::unbind_from(s);
219         }
220 };
221
222 } // namespace GL
223 } // namespace Msp
224
225 #endif