]> git.tdb.fi Git - gldbg.git/blob - flavors/gl/source/glstate.cpp
Decode and display element buffer contents
[gldbg.git] / flavors / gl / source / glstate.cpp
1 /* $Id$
2
3 This file is part of gldbg
4 Copyright © 2009-2010  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         client_active_tex(0),
76         array_buffer(0),
77         element_buffer(0)
78 {
79         vertex_array.kind = GL_VERTEX_ARRAY;
80         normal_array.kind = GL_NORMAL_ARRAY;
81         color_array.kind = GL_COLOR_ARRAY;
82         for(unsigned i=0; i<8; ++i)
83         {
84                 texcoord_arrays[i].kind = GL_TEXTURE_COORD_ARRAY;
85                 texcoord_arrays[i].index = i;
86         }
87
88         decoder->glColor3ub = wrap_normalized<GLubyte, glColor3f>;
89         decoder->glColor3ubv = wrap_array<GLubyte, wrap_normalized<GLubyte, glColor3f> >;
90         decoder->glColor4ub = wrap_normalized<GLubyte, glColor4f>;
91         decoder->glColor4ubv = wrap_array<GLubyte, wrap_normalized<GLubyte, glColor4f> >;
92         decoder->glColor3f = glColor3f;
93         decoder->glColor3fv = wrap_array<float, glColor3f>;
94         decoder->glColor4f = glColor4f;
95         decoder->glColor4fv = wrap_array<float, glColor4f>;
96         decoder->glTexCoord1f = glTexCoord1f;
97         decoder->glTexCoord1fv = wrap_array<float, glTexCoord1f>;
98         decoder->glTexCoord2f = glTexCoord2f;
99         decoder->glTexCoord2fv = wrap_array<float, glTexCoord2f>;
100         decoder->glTexCoord3f = glTexCoord3f;
101         decoder->glTexCoord3fv = wrap_array<float, glTexCoord3f>;
102         decoder->glTexCoord4f = glTexCoord4f;
103         decoder->glTexCoord4fv = wrap_array<float, glTexCoord4f>;
104         decoder->glNormal3f = glNormal3f;
105         decoder->glNormal3fv = wrap_array<float, glNormal3f>;
106
107         decoder->glActiveTexture = glActiveTexture;
108         decoder->glActiveTextureARB = glActiveTexture;
109         decoder->glBindTexture = glBindTexture;
110         decoder->glTexImage2D = glTexImage2D;
111         decoder->glTexParameteri = glTexParameteri;
112         decoder->glTexParameteriv = glTexParameteriv;
113         decoder->glDeleteTextures = glDeleteTextures;
114
115         decoder->glVertexPointer = glVertexPointer;
116         decoder->glNormalPointer = glNormalPointer;
117         decoder->glColorPointer = glColorPointer;
118         decoder->glClientActiveTexture = glClientActiveTexture;
119         decoder->glClientActiveTextureARB = glClientActiveTexture;
120         decoder->glTexCoordPointer = glTexCoordPointer;
121
122         decoder->glBindBuffer = glBindBuffer;
123         decoder->glBindBufferARB = glBindBuffer;
124         decoder->glBufferData = glBufferData;
125         decoder->glBufferDataARB = glBufferData;
126         decoder->glBufferSubData = glBufferSubData;
127         decoder->glBufferSubDataARB = glBufferSubData;
128         decoder->glDeleteBuffers = glDeleteBuffers;
129         decoder->glDeleteBuffersARB = glDeleteBuffers;
130
131         decoder->glDrawElements = glDrawElements;
132         decoder->glDrawRangeElements = glDrawRangeElements;
133         decoder->glDrawRangeElementsEXT = glDrawRangeElements;
134 }
135
136 GlState::~GlState()
137 {
138         gldecoder_delete(decoder);
139 }
140
141 int GlState::decode(const char *data, unsigned len)
142 {
143         return gldecoder_decode(decoder, data, len);
144 }
145
146 const TextureState &GlState::get_texture(unsigned id) const
147 {
148         TextureMap::const_iterator i = textures.find(id);
149         if(i==textures.end())
150                 throw KeyError("Unknown texture");
151         return i->second;
152 }
153
154 const BufferState &GlState::get_buffer(unsigned id) const
155 {
156         BufferMap::const_iterator i = buffers.find(id);
157         if(i==buffers.end())
158                 throw KeyError("Unknown buffer");
159         return i->second;
160 }
161
162 const BufferState *GlState::get_current_buffer(GLenum target) const
163 {
164         return const_cast<GlState *>(this)->get_current_buffer(target);
165 }
166
167 bool &GlState::get_boolean_state(GLenum state)
168 {
169         if(state==GL_VERTEX_ARRAY)
170                 return vertex_array.enabled;
171         else if(state==GL_NORMAL_ARRAY)
172                 return normal_array.enabled;
173         else if(state==GL_COLOR_ARRAY)
174                 return color_array.enabled;
175         else if(state==GL_TEXTURE_COORD_ARRAY)
176                 return texcoord_arrays[client_active_tex].enabled;
177
178         static bool dummy;
179         return dummy;
180 }
181
182 TextureState *GlState::get_current_texture(GLenum target)
183 {
184         return texunits[active_tex].get_current_texture(target);
185 }
186
187 BufferState *GlState::get_current_buffer(GLenum target)
188 {
189         if(target==GL_ARRAY_BUFFER)
190                 return array_buffer;
191         else if(target==GL_ELEMENT_ARRAY_BUFFER)
192                 return element_buffer;
193         return 0;
194 }
195
196 const ArrayState &GlState::get_array(GLenum array) const
197 {
198         if(array==GL_VERTEX_ARRAY)
199                 return vertex_array;
200         else if(array==GL_NORMAL_ARRAY)
201                 return normal_array;
202         else if(array==GL_COLOR_ARRAY)
203                 return color_array;
204         else if(array==GL_TEXTURE_COORD_ARRAY)
205                 return texcoord_arrays[client_active_tex];
206         else
207                 throw InvalidParameterValue("Invalid array");
208 }
209
210 const ArrayState &GlState::get_texture_coord_array(unsigned index) const
211 {
212         return texcoord_arrays[index];
213 }
214
215 const ArrayState &GlState::get_attrib_array(unsigned index) const
216 {
217         map<unsigned, ArrayState>::const_iterator i = attrib_arrays.find(index);
218         if(i!=attrib_arrays.end())
219                 return i->second;
220
221         // XXX Return a dummy?
222         throw KeyError("Unknown attribute array");
223 }
224
225 void GlState::set_current_texture(GLenum target, unsigned id)
226 {
227         TexUnitState &unit = texunits[active_tex];
228         TextureState *tex = 0;
229         if(id)
230         {
231                 tex = &textures[id];
232                 if(!tex->id)
233                 {
234                         tex->id = id;
235                         tex->target = target;
236                 }
237                 else if(tex->target!=target)
238                         return;
239         }
240         unit.set_current_texture(target, tex);
241 }
242
243 void GlState::set_current_buffer(GLenum target, unsigned id)
244 {
245         BufferState *buf = 0;
246         if(id)
247         {
248                 buf = &buffers[id];
249                 if(!buf->id)
250                         buf->id = id;
251         }
252
253         if(target==GL_ARRAY_BUFFER)
254                 array_buffer = buf;
255         else if(target==GL_ELEMENT_ARRAY_BUFFER)
256                 element_buffer = buf;
257 }
258
259 // Boolean state
260
261 void GlState::glEnableClientState(void *user_data, GLenum state)
262 {
263         reinterpret_cast<GlState *>(user_data)->get_boolean_state(state) = true;
264 }
265
266 void GlState::glDisableClientState(void *user_data, GLenum state)
267 {
268         reinterpret_cast<GlState *>(user_data)->get_boolean_state(state) = false;
269 }
270
271 void GlState::glEnableVertexAttribArray(void *user_data, unsigned index)
272 {
273         reinterpret_cast<GlState *>(user_data)->attrib_arrays[index].enabled = true;
274 }
275
276 void GlState::glDisableVertexAttribArray(void *user_data, unsigned index)
277 {
278         reinterpret_cast<GlState *>(user_data)->attrib_arrays[index].enabled = false;
279 }
280
281 // Vertex attributes
282
283 void GlState::glColor3f(void *user_data, float r, float g, float b)
284 { glColor4f(user_data, r, g, b, 1.0f); }
285
286 void GlState::glColor4f(void *user_data, float r, float g, float b, float a)
287 {
288         Vector4 &color = reinterpret_cast<GlState *>(user_data)->color;
289         color.r = r;
290         color.g = g;
291         color.b = b;
292         color.a = a;
293 }
294
295 void GlState::glNormal3f(void *user_data, float x, float y, float z)
296 {
297         Vector3 &normal = reinterpret_cast<GlState *>(user_data)->normal;
298         normal.x = x;
299         normal.y = y;
300         normal.z = z;
301 }
302
303 void GlState::glTexCoord1f(void *user_data, float s)
304 { glTexCoord4f(user_data, s, 0.0f, 0.0f, 1.0f); }
305
306 void GlState::glTexCoord2f(void *user_data, float s, float t)
307 { glTexCoord4f(user_data, s, t, 0.0f, 1.0f); }
308
309 void GlState::glTexCoord3f(void *user_data, float s, float t, float p)
310 { glTexCoord4f(user_data, s, t, p, 1.0f); }
311
312 void GlState::glTexCoord4f(void *user_data, float s, float t, float p, float q)
313 {
314         unsigned index = reinterpret_cast<GlState *>(user_data)->active_tex;
315         glMultiTexCoord4f(user_data, index, s, t, p, q);
316 }
317
318 void GlState::glMultiTexCoord4f(void *user_data, unsigned index, float s, float t, float p, float q)
319 {
320         Vector4 &texcoord = reinterpret_cast<GlState *>(user_data)->texcoord[index];
321         texcoord.s = s;
322         texcoord.t = t;
323         texcoord.p = p;
324         texcoord.q = q;
325 }
326
327 // Textures
328
329 void GlState::glActiveTexture(void *user_data, unsigned index)
330 {
331         reinterpret_cast<GlState *>(user_data)->active_tex = index-GL_TEXTURE0;
332 }
333
334 void GlState::glBindTexture(void *user_data, GLenum target, unsigned id)
335 {
336         reinterpret_cast<GlState *>(user_data)->set_current_texture(target, id);
337 }
338
339 void GlState::glTexImage2D(void *user_data, GLenum target, int level, int ifmt, int width, int height, int, GLenum, GLenum, const void *)
340 {
341         if(TextureState *tex = reinterpret_cast<GlState *>(user_data)->get_current_texture(target))
342                 tex->set_image_2d(level, ifmt, width, height);
343 }
344
345 void GlState::glTexParameteri(void *user_data, GLenum target, GLenum param, int value)
346 { glTexParameteriv(user_data, target, param, &value); }
347
348 void GlState::glTexParameteriv(void *user_data, GLenum target, GLenum param, const int *values)
349 {
350         if(TextureState *tex = reinterpret_cast<GlState *>(user_data)->get_current_texture(target))
351                 tex->set_parameter(param, values);
352 }
353
354 void GlState::glDeleteTextures(void *user_data, int count, const unsigned *ids)
355 {
356         for(int i=0; i<count; ++i)
357                 reinterpret_cast<GlState *>(user_data)->textures.erase(ids[i]);
358 }
359
360 // Vertex arrays
361
362 void GlState::glVertexPointer(void *user_data, int size, GLenum type, int stride, const void *data)
363 {
364         GlState *self = reinterpret_cast<GlState *>(user_data);
365         self->vertex_array.set(size, type, false, stride, self->array_buffer, reinterpret_cast<long>(data));
366 }
367
368 void GlState::glNormalPointer(void *user_data, GLenum type, int stride, const void *data)
369 {
370         GlState *self = reinterpret_cast<GlState *>(user_data);
371         self->normal_array.set(3, type, true, stride, self->array_buffer, reinterpret_cast<long>(data));
372 }
373
374 void GlState::glColorPointer(void *user_data, int size, GLenum type, int stride, const void *data)
375 {
376         GlState *self = reinterpret_cast<GlState *>(user_data);
377         self->color_array.set(size, type, true, stride, self->array_buffer, reinterpret_cast<long>(data));
378 }
379
380 void GlState::glClientActiveTexture(void *user_data, unsigned index)
381 {
382         reinterpret_cast<GlState *>(user_data)->client_active_tex = index-GL_TEXTURE0;
383 }
384
385 void GlState::glTexCoordPointer(void *user_data, int size, GLenum type, int stride, const void *data)
386 {
387         GlState *self = reinterpret_cast<GlState *>(user_data);
388         self->texcoord_arrays[self->client_active_tex].set(size, type, false, stride, self->array_buffer, reinterpret_cast<long>(data));
389 }
390
391 void GlState::glVertexAttribPointer(void *user_data, unsigned index, int size, GLenum type, int norm, int stride, const void *data)
392 {
393         GlState *self = reinterpret_cast<GlState *>(user_data);
394         self->attrib_arrays[index].set(size, type, norm, stride, self->array_buffer, reinterpret_cast<long>(data));
395 }
396
397 // Buffer objects
398
399 void GlState::glBindBuffer(void *user_data, GLenum target, unsigned id)
400 { reinterpret_cast<GlState *>(user_data)->set_current_buffer(target, id); }
401
402 void GlState::glBufferData(void *user_data, GLenum target, int size, const void *data, GLenum usage)
403 {
404         if(BufferState *buf = reinterpret_cast<GlState *>(user_data)->get_current_buffer(target))
405                 buf->set_data(size, data, usage);
406 }
407
408 void GlState::glBufferSubData(void *user_data, GLenum target, int offset, int size, const void *data)
409 {
410         if(BufferState *buf = reinterpret_cast<GlState *>(user_data)->get_current_buffer(target))
411                 buf->set_sub_data(offset, size, data);
412 }
413
414 void GlState::glDeleteBuffers(void *user_data, int count, const unsigned *ids)
415 {
416         for(int i=0; i<count; ++i)
417                 reinterpret_cast<GlState *>(user_data)->buffers.erase(ids[i]);
418 }
419
420 void GlState::glDrawElements(void *user_data, GLenum, int, GLenum type, const void *)
421 {
422         if(BufferState *buf = reinterpret_cast<GlState *>(user_data)->element_buffer)
423                 buf->content.update_elements(type);
424 }
425
426 void GlState::glDrawRangeElements(void *user_data, GLenum, unsigned, unsigned, int, GLenum type, const void *)
427 {
428         if(BufferState *buf = reinterpret_cast<GlState *>(user_data)->element_buffer)
429                 buf->content.update_elements(type);
430 }