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