]> git.tdb.fi Git - gldbg.git/blob - source/glstate.cpp
90b0ac03ff34aaf14fe44761928cad16011aede5
[gldbg.git] / source / glstate.cpp
1 /* $Id$
2
3 This file is part of gldbg
4 Copyright © 2009  Mikko Rasa, Mikkosoft Productions
5 Distributed under the GPL
6 */
7
8 #include <msp/core/except.h>
9 #include "glstate.h"
10
11 using namespace std;
12 using namespace Msp;
13
14 namespace {
15
16 template<typename T>
17 float normalize(T v);
18
19 template<>
20 float normalize<GLubyte>(GLubyte v)
21 { return v/255.0f; }
22
23 template<>
24 float normalize<GLbyte>(GLbyte v)
25 { return (2*v+1)/255.0f; }
26
27 template<typename T, void (*func)(void *, float)>
28 void wrap_normalized(void *user_data, T v0)
29 { func(user_data, v0); }
30
31 template<typename T, void (*func)(void *, float, float)>
32 void wrap_normalized(void *user_data, T v0, T v1)
33 { func(user_data, v0, v1); }
34
35 template<typename T, void (*func)(void *, float, float, float)>
36 void wrap_normalized(void *user_data, T v0, T v1, T v2)
37 { func(user_data, v0, v1, v2); }
38
39 template<typename T, void (*func)(void *, float, float, float, float)>
40 void wrap_normalized(void *user_data, T v0, T v1, T v2, T v3)
41 { func(user_data, v0, v1, v2, v3); }
42
43 template<typename T, void (*func)(void *, T)>
44 void wrap_array(void *user_data, const T *v)
45 { func(user_data, v[0]); }
46
47 template<typename T, void (*func)(void *, T, T)>
48 void wrap_array(void *user_data, const T *v)
49 { func(user_data, v[0], v[1]); }
50
51 template<typename T, void (*func)(void *, T, T, T)>
52 void wrap_array(void *user_data, const T *v)
53 { func(user_data, v[0], v[1], v[2]); }
54
55 template<typename T, void (*func)(void *, T, T, T, T)>
56 void wrap_array(void *user_data, const T *v)
57 { func(user_data, v[0], v[1], v[2], v[3]); }
58
59 }
60
61
62 Vector3::Vector3():
63         x(0), y(0), z(0)
64 { }
65
66
67 Vector4::Vector4():
68         x(0), y(0), z(0), w(1)
69 { }
70
71
72 GlState::GlState():
73         decoder(gldecoder_new(this, NULL)),
74         active_tex(0),
75         array_buffer(0),
76         element_buffer(0)
77 {
78         decoder->glColor3ub = wrap_normalized<GLubyte, glColor3f>;
79         decoder->glColor3ubv = wrap_array<GLubyte, wrap_normalized<GLubyte, glColor3f> >;
80         decoder->glColor4ub = wrap_normalized<GLubyte, glColor4f>;
81         decoder->glColor4ubv = wrap_array<GLubyte, wrap_normalized<GLubyte, glColor4f> >;
82         decoder->glColor3f = glColor3f;
83         decoder->glColor3fv = wrap_array<float, glColor3f>;
84         decoder->glColor4f = glColor4f;
85         decoder->glColor4fv = wrap_array<float, glColor4f>;
86         decoder->glTexCoord1f = glTexCoord1f;
87         decoder->glTexCoord1fv = wrap_array<float, glTexCoord1f>;
88         decoder->glTexCoord2f = glTexCoord2f;
89         decoder->glTexCoord2fv = wrap_array<float, glTexCoord2f>;
90         decoder->glTexCoord3f = glTexCoord3f;
91         decoder->glTexCoord3fv = wrap_array<float, glTexCoord3f>;
92         decoder->glTexCoord4f = glTexCoord4f;
93         decoder->glTexCoord4fv = wrap_array<float, glTexCoord4f>;
94         decoder->glNormal3f = glNormal3f;
95         decoder->glNormal3fv = wrap_array<float, glNormal3f>;
96         decoder->glActiveTexture = glActiveTexture;
97         decoder->glActiveTextureARB = glActiveTexture;
98         decoder->glBindTexture = glBindTexture;
99         decoder->glTexImage2D = glTexImage2D;
100         decoder->glTexParameteri = glTexParameteri;
101         decoder->glTexParameteriv = glTexParameteriv;
102         decoder->glDeleteTextures = glDeleteTextures;
103         decoder->glBindBuffer = glBindBuffer;
104         decoder->glBindBufferARB = glBindBuffer;
105         decoder->glBufferData = glBufferData;
106         decoder->glBufferDataARB = glBufferData;
107         decoder->glBufferSubData = glBufferSubData;
108         decoder->glBufferSubDataARB = glBufferSubData;
109 }
110
111 GlState::~GlState()
112 {
113         gldecoder_delete(decoder);
114 }
115
116 int GlState::decode(const char *data, unsigned len)
117 {
118         return gldecoder_decode(decoder, data, len);
119 }
120
121 const TextureState &GlState::get_texture(unsigned id) const
122 {
123         TextureMap::const_iterator i = textures.find(id);
124         if(i==textures.end())
125                 throw KeyError("Unknown texture");
126         return i->second;
127 }
128
129 const BufferState &GlState::get_buffer(unsigned id) const
130 {
131         BufferMap::const_iterator i = buffers.find(id);
132         if(i==buffers.end())
133                 throw KeyError("Unknown buffer");
134         return i->second;
135 }
136
137 const BufferState *GlState::get_current_buffer(GLenum target) const
138 {
139         return const_cast<GlState *>(this)->get_current_buffer(target);
140 }
141
142 TextureState *GlState::get_current_texture(GLenum target)
143 {
144         return texunits[active_tex].get_current_texture(target);
145 }
146
147 BufferState *GlState::get_current_buffer(GLenum target)
148 {
149         if(target==GL_ARRAY_BUFFER)
150                 return array_buffer;
151         else if(target==GL_ELEMENT_ARRAY_BUFFER)
152                 return element_buffer;
153         return 0;
154 }
155
156 void GlState::set_current_texture(GLenum target, unsigned id)
157 {
158         TexUnitState &unit = texunits[active_tex];
159         TextureState *tex = 0;
160         if(id)
161         {
162                 tex = &textures[id];
163                 if(!tex->id)
164                 {
165                         tex->id = id;
166                         tex->target = target;
167                 }
168                 else if(tex->target!=target)
169                         return;
170         }
171         unit.set_current_texture(target, tex);
172 }
173
174 void GlState::set_current_buffer(GLenum target, unsigned id)
175 {
176         BufferState *buf = 0;
177         if(id)
178         {
179                 buf = &buffers[id];
180                 if(!buf->id)
181                         buf->id = id;
182         }
183
184         if(target==GL_ARRAY_BUFFER)
185                 array_buffer = buf;
186         else if(target==GL_ELEMENT_ARRAY_BUFFER)
187                 element_buffer = buf;
188 }
189
190 // Vertex attributes
191
192 void GlState::glColor3f(void *user_data, float r, float g, float b)
193 { glColor4f(user_data, r, g, b, 1.0f); }
194
195 void GlState::glColor4f(void *user_data, float r, float g, float b, float a)
196 {
197         Vector4 &color = reinterpret_cast<GlState *>(user_data)->color;
198         color.r = r;
199         color.g = g;
200         color.b = b;
201         color.a = a;
202 }
203
204 void GlState::glNormal3f(void *user_data, float x, float y, float z)
205 {
206         Vector3 &normal = reinterpret_cast<GlState *>(user_data)->normal;
207         normal.x = x;
208         normal.y = y;
209         normal.z = z;
210 }
211
212 void GlState::glTexCoord1f(void *user_data, float s)
213 { glTexCoord4f(user_data, s, 0.0f, 0.0f, 1.0f); }
214
215 void GlState::glTexCoord2f(void *user_data, float s, float t)
216 { glTexCoord4f(user_data, s, t, 0.0f, 1.0f); }
217
218 void GlState::glTexCoord3f(void *user_data, float s, float t, float p)
219 { glTexCoord4f(user_data, s, t, p, 1.0f); }
220
221 void GlState::glTexCoord4f(void *user_data, float s, float t, float p, float q)
222 {
223         unsigned index = reinterpret_cast<GlState *>(user_data)->active_tex;
224         glMultiTexCoord4f(user_data, index, s, t, p, q);
225 }
226
227 void GlState::glMultiTexCoord4f(void *user_data, unsigned index, float s, float t, float p, float q)
228 {
229         Vector4 &texcoord = reinterpret_cast<GlState *>(user_data)->texcoord[index];
230         texcoord.s = s;
231         texcoord.t = t;
232         texcoord.p = p;
233         texcoord.q = q;
234 }
235
236 // Textures
237
238 void GlState::glActiveTexture(void *user_data, unsigned index)
239 {
240         reinterpret_cast<GlState *>(user_data)->active_tex = index-GL_TEXTURE0;
241 }
242
243 void GlState::glBindTexture(void *user_data, GLenum target, unsigned id)
244 { reinterpret_cast<GlState *>(user_data)->set_current_texture(target, id); }
245
246 void GlState::glTexImage2D(void *user_data, GLenum target, int level, int ifmt, int width, int height, int, GLenum, GLenum, const void *)
247 {
248         if(TextureState *tex = reinterpret_cast<GlState *>(user_data)->get_current_texture(target))
249                 tex->set_image_2d(level, ifmt, width, height);
250 }
251
252 void GlState::glTexParameteri(void *user_data, GLenum target, GLenum param, int value)
253 { glTexParameteriv(user_data, target, param, &value); }
254
255 void GlState::glTexParameteriv(void *user_data, GLenum target, GLenum param, const int *values)
256 {
257         if(TextureState *tex = reinterpret_cast<GlState *>(user_data)->get_current_texture(target))
258                 tex->set_parameter(param, values);
259 }
260
261 void GlState::glDeleteTextures(void *user_data, int count, const unsigned *ids)
262 {
263         for(int i=0; i<count; ++i)
264                 reinterpret_cast<GlState *>(user_data)->textures.erase(ids[i]);
265 }
266
267 // Buffer objects
268
269 void GlState::glBindBuffer(void *user_data, GLenum target, unsigned id)
270 { reinterpret_cast<GlState *>(user_data)->set_current_buffer(target, id); }
271
272 void GlState::glBufferData(void *user_data, GLenum target, int size, const void *data, GLenum usage)
273 {
274         if(BufferState *buf = reinterpret_cast<GlState *>(user_data)->get_current_buffer(target))
275                 buf->set_data(size, data, usage);
276 }
277
278 void GlState::glBufferSubData(void *user_data, GLenum target, int offset, int size, const void *data)
279 {
280         if(BufferState *buf = reinterpret_cast<GlState *>(user_data)->get_current_buffer(target))
281                 buf->set_sub_data(offset, size, data);
282 }