]> git.tdb.fi Git - libs/gl.git/blob - source/bindable.h
Rewrite Bind as two different classes
[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.
70 */
71 class Bind
72 {
73 private:
74         typedef void CleanupFunc();
75
76         CleanupFunc *cleanup;
77
78 public:
79         template<typename T>
80         Bind(T *o) { init(o); }
81
82         template<typename T>
83         Bind(const T *o) { init(o); }
84
85         template<typename T>
86         Bind(const T &o) { init(&o); }
87
88 private:
89         template<typename T>
90         void init(const T *o)
91         {
92                 cleanup = (o ? &unbind<T> : 0);
93                 if(o)
94                         o->bind();
95                 else
96                         T::unbind();
97         }
98
99 public:
100         ~Bind()
101         { if(cleanup) cleanup(); }
102
103 private:
104         template<typename T>
105         static void unbind()
106         { T::unbind(); }
107 };
108
109
110 /**
111 Similar to Bind, but restores previous binding upon destruction.
112 */
113 class BindRestore
114 {
115 private:
116         typedef void CleanupFunc(const void *);
117
118         const void *old;
119         CleanupFunc *cleanup;
120
121 public:
122         template<typename T>
123         BindRestore(T *o) { init(o); }
124
125         template<typename T>
126         BindRestore(const T *o) { init(o); }
127
128         template<typename T>
129         BindRestore(const T &o) { init(&o); }
130
131 private:
132         template<typename T>
133         void init(T *o)
134         {
135                 old = T::current();
136                 cleanup = (o!=old ? &restore<T> : 0);
137                 if(o)
138                         o->bind();
139                 else if(old)
140                         T::unbind();
141         }
142
143 public:
144         ~BindRestore()
145         { if(cleanup) cleanup(old); }
146
147 private:
148         template<typename T>
149         static void restore(const void *o)
150         {
151                 if(o)
152                         reinterpret_cast<const T *>(o)->bind();
153                 else
154                         T::unbind();
155         }
156 };
157
158 } // namespace GL
159 } // namespace Msp
160
161 #endif