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