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