]> git.tdb.fi Git - gldbg.git/blob - flavors/gl/source/glstate.cpp
7f67596f099aa6581f2ef58c353d5cc40fb276ae
[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
85         decoder->glColor3ub = wrap_normalized<GLubyte, glColor3f>;
86         decoder->glColor3ubv = wrap_array<GLubyte, wrap_normalized<GLubyte, glColor3f> >;
87         decoder->glColor4ub = wrap_normalized<GLubyte, glColor4f>;
88         decoder->glColor4ubv = wrap_array<GLubyte, wrap_normalized<GLubyte, glColor4f> >;
89         decoder->glColor3f = glColor3f;
90         decoder->glColor3fv = wrap_array<float, glColor3f>;
91         decoder->glColor4f = glColor4f;
92         decoder->glColor4fv = wrap_array<float, glColor4f>;
93         decoder->glTexCoord1f = glTexCoord1f;
94         decoder->glTexCoord1fv = wrap_array<float, glTexCoord1f>;
95         decoder->glTexCoord2f = glTexCoord2f;
96         decoder->glTexCoord2fv = wrap_array<float, glTexCoord2f>;
97         decoder->glTexCoord3f = glTexCoord3f;
98         decoder->glTexCoord3fv = wrap_array<float, glTexCoord3f>;
99         decoder->glTexCoord4f = glTexCoord4f;
100         decoder->glTexCoord4fv = wrap_array<float, glTexCoord4f>;
101         decoder->glNormal3f = glNormal3f;
102         decoder->glNormal3fv = wrap_array<float, glNormal3f>;
103
104         decoder->glVertexPointer = glVertexPointer;
105         decoder->glNormalPointer = glNormalPointer;
106         decoder->glColorPointer = glColorPointer;
107         decoder->glClientActiveTexture = glClientActiveTexture;
108         decoder->glClientActiveTextureARB = glClientActiveTexture;
109         decoder->glTexCoordPointer = glTexCoordPointer;
110         decoder->glEnableVertexAttribArray = glEnableVertexAttribArray;
111         decoder->glEnableVertexAttribArrayARB = glEnableVertexAttribArray;
112         decoder->glDisableVertexAttribArray = glDisableVertexAttribArray;
113         decoder->glDisableVertexAttribArrayARB = glDisableVertexAttribArray;
114         decoder->glVertexAttribPointer = glVertexAttribPointer;
115         decoder->glVertexAttribPointerARB = glVertexAttribPointer;
116
117         decoder->glDrawElements = glDrawElements;
118         decoder->glDrawRangeElements = glDrawRangeElements;
119         decoder->glDrawRangeElementsEXT = glDrawRangeElements;
120
121         decoder->glBindBuffer = glBindBuffer;
122         decoder->glBindBufferARB = glBindBuffer;
123         decoder->glBindBufferBase = glBindBufferBase;
124         decoder->glBindBufferRange = glBindBufferRange;
125         decoder->glBufferData = glBufferData;
126         decoder->glBufferDataARB = glBufferData;
127         decoder->glBufferSubData = glBufferSubData;
128         decoder->glBufferSubDataARB = glBufferSubData;
129         decoder->glDeleteBuffers = glDeleteBuffers;
130         decoder->glDeleteBuffersARB = glDeleteBuffers;
131
132         decoder->glActiveTexture = glActiveTexture;
133         decoder->glActiveTextureARB = glActiveTexture;
134         decoder->glBindTexture = glBindTexture;
135         decoder->glTexImage2D = glTexImage2D;
136         decoder->glTexParameteri = glTexParameteri;
137         decoder->glTexParameteriv = glTexParameteriv;
138         decoder->glDeleteTextures = glDeleteTextures;
139
140         decoder->glCreateShader = glCreateShader;
141         decoder->glCreateShaderObjectARB = glCreateShader;
142         decoder->glShaderSource = glShaderSource;
143         decoder->glShaderSourceARB = glShaderSource;
144         decoder->glCompileShader = glCompileShader;
145         decoder->glCompileShaderARB = glCompileShader;
146         decoder->glGetShaderiv = glGetShaderiv;
147         decoder->glGetShaderInfoLog = glGetShaderInfoLog;
148         decoder->glDeleteShader = glDeleteShader;
149         decoder->glCreateProgram = glCreateProgram;
150         decoder->glCreateProgramObjectARB = glCreateProgram;
151         decoder->glAttachShader = glAttachShader;
152         decoder->glAttachObjectARB = glAttachShader;
153         decoder->glLinkProgram = glLinkProgram;
154         decoder->glLinkProgramARB = glLinkProgram;
155         decoder->glGetProgramiv = glGetProgramiv;
156         decoder->glGetProgramInfoLog = glGetProgramInfoLog;
157         decoder->glDeleteObjectARB = glDeleteObjectARB;
158         decoder->glGetObjectParameterivARB = glGetObjectParameterivARB;
159         decoder->glGetInfoLogARB = glGetInfoLogARB;
160 }
161
162 GlState::~GlState()
163 {
164         gldecoder_delete(decoder);
165 }
166
167 int GlState::decode(const char *data, unsigned len)
168 {
169         return gldecoder_decode(decoder, data, len);
170 }
171
172 // Boolean state
173
174 bool &GlState::get_boolean_state(GLenum state)
175 {
176         if(state==GL_VERTEX_ARRAY)
177                 return vertex_array.enabled;
178         else if(state==GL_NORMAL_ARRAY)
179                 return normal_array.enabled;
180         else if(state==GL_COLOR_ARRAY)
181                 return color_array.enabled;
182         else if(state==GL_TEXTURE_COORD_ARRAY)
183                 return texcoord_arrays[client_active_tex].enabled;
184
185         static bool dummy;
186         return dummy;
187 }
188
189 void GlState::glEnableClientState(void *user_data, GLenum state)
190 {
191         reinterpret_cast<GlState *>(user_data)->get_boolean_state(state) = true;
192 }
193
194 void GlState::glDisableClientState(void *user_data, GLenum state)
195 {
196         reinterpret_cast<GlState *>(user_data)->get_boolean_state(state) = false;
197 }
198
199 // Vertex attributes
200
201 void GlState::glColor3f(void *user_data, float r, float g, float b)
202 {
203         glColor4f(user_data, r, g, b, 1.0f);
204 }
205
206 void GlState::glColor4f(void *user_data, float r, float g, float b, float a)
207 {
208         Vector4 &color = reinterpret_cast<GlState *>(user_data)->color;
209         color.r = r;
210         color.g = g;
211         color.b = b;
212         color.a = a;
213 }
214
215 void GlState::glNormal3f(void *user_data, float x, float y, float z)
216 {
217         Vector3 &normal = reinterpret_cast<GlState *>(user_data)->normal;
218         normal.x = x;
219         normal.y = y;
220         normal.z = z;
221 }
222
223 void GlState::glTexCoord1f(void *user_data, float s)
224 {
225         glTexCoord4f(user_data, s, 0.0f, 0.0f, 1.0f);
226 }
227
228 void GlState::glTexCoord2f(void *user_data, float s, float t)
229 {
230         glTexCoord4f(user_data, s, t, 0.0f, 1.0f);
231 }
232
233 void GlState::glTexCoord3f(void *user_data, float s, float t, float p)
234 {
235         glTexCoord4f(user_data, s, t, p, 1.0f);
236 }
237
238 void GlState::glTexCoord4f(void *user_data, float s, float t, float p, float q)
239 {
240         unsigned index = reinterpret_cast<GlState *>(user_data)->active_tex;
241         glMultiTexCoord4f(user_data, index, s, t, p, q);
242 }
243
244 void GlState::glMultiTexCoord4f(void *user_data, unsigned index, float s, float t, float p, float q)
245 {
246         Vector4 &texcoord = reinterpret_cast<GlState *>(user_data)->texcoord[index];
247         texcoord.s = s;
248         texcoord.t = t;
249         texcoord.p = p;
250         texcoord.q = q;
251 }
252
253 // Vertex arrays
254
255 ArrayState &GlState::get_attrib_array(unsigned index)
256 {
257         map<unsigned, ArrayState>::iterator i = attrib_arrays.find(index);
258         if(i!=attrib_arrays.end())
259                 return i->second;
260
261         ArrayState &array = attrib_arrays[index];
262         array.index = index;
263
264         return array;
265 }
266
267 void GlState::glVertexPointer(void *user_data, int size, GLenum type, int stride, const void *data)
268 {
269         GlState *self = reinterpret_cast<GlState *>(user_data);
270         self->vertex_array.set(size, type, false, stride, self->array_buffer, reinterpret_cast<long>(data));
271 }
272
273 void GlState::glNormalPointer(void *user_data, GLenum type, int stride, const void *data)
274 {
275         GlState *self = reinterpret_cast<GlState *>(user_data);
276         self->normal_array.set(3, type, true, stride, self->array_buffer, reinterpret_cast<long>(data));
277 }
278
279 void GlState::glColorPointer(void *user_data, int size, GLenum type, int stride, const void *data)
280 {
281         GlState *self = reinterpret_cast<GlState *>(user_data);
282         self->color_array.set(size, type, true, stride, self->array_buffer, reinterpret_cast<long>(data));
283 }
284
285 void GlState::glClientActiveTexture(void *user_data, unsigned index)
286 {
287         reinterpret_cast<GlState *>(user_data)->client_active_tex = index-GL_TEXTURE0;
288 }
289
290 void GlState::glTexCoordPointer(void *user_data, int size, GLenum type, int stride, const void *data)
291 {
292         GlState *self = reinterpret_cast<GlState *>(user_data);
293         self->texcoord_arrays[self->client_active_tex].set(size, type, false, stride, self->array_buffer, reinterpret_cast<long>(data));
294 }
295
296 void GlState::glEnableVertexAttribArray(void *user_data, unsigned index)
297 {
298         reinterpret_cast<GlState *>(user_data)->attrib_arrays[index].enabled = true;
299 }
300
301 void GlState::glDisableVertexAttribArray(void *user_data, unsigned index)
302 {
303         reinterpret_cast<GlState *>(user_data)->attrib_arrays[index].enabled = false;
304 }
305
306 void GlState::glVertexAttribPointer(void *user_data, unsigned index, int size, GLenum type, unsigned char norm, int stride, const void *data)
307 {
308         GlState *self = reinterpret_cast<GlState *>(user_data);
309         self->get_attrib_array(index).set(size, type, norm, stride, self->array_buffer, reinterpret_cast<long>(data));
310 }
311
312 const ArrayState &GlState::get_array(GLenum array) const
313 {
314         if(array==GL_VERTEX_ARRAY)
315                 return vertex_array;
316         else if(array==GL_NORMAL_ARRAY)
317                 return normal_array;
318         else if(array==GL_COLOR_ARRAY)
319                 return color_array;
320         else if(array==GL_TEXTURE_COORD_ARRAY)
321                 return texcoord_arrays[client_active_tex];
322         else
323                 throw logic_error("Invalid array");
324 }
325
326 const ArrayState &GlState::get_texture_coord_array(unsigned index) const
327 {
328         return texcoord_arrays[index];
329 }
330
331 const ArrayState &GlState::get_attrib_array(unsigned index) const
332 {
333         map<unsigned, ArrayState>::const_iterator i = attrib_arrays.find(index);
334         if(i!=attrib_arrays.end())
335                 return i->second;
336
337         // XXX Return a dummy?
338         throw runtime_error("Unknown attribute array");
339 }
340
341 // Array draw commands
342
343 void GlState::glDrawElements(void *user_data, GLenum, int, GLenum type, const void *)
344 {
345         if(BufferState *buf = reinterpret_cast<GlState *>(user_data)->element_buffer)
346                 buf->content.update_elements(type);
347 }
348
349 void GlState::glDrawRangeElements(void *user_data, GLenum, unsigned, unsigned, int, GLenum type, const void *)
350 {
351         if(BufferState *buf = reinterpret_cast<GlState *>(user_data)->element_buffer)
352                 buf->content.update_elements(type);
353 }
354
355 // Buffer objects
356
357 void GlState::set_current_buffer(GLenum target, unsigned id)
358 {
359         BufferState *buf = 0;
360         if(id)
361         {
362                 buf = &buffers[id];
363                 if(!buf->id)
364                         buf->id = id;
365         }
366
367         if(target==GL_ARRAY_BUFFER)
368                 array_buffer = buf;
369         else if(target==GL_ELEMENT_ARRAY_BUFFER)
370                 element_buffer = buf;
371         else if(target==GL_UNIFORM_BUFFER)
372                 uniform_buffer = buf;
373 }
374
375 BufferState *GlState::get_buffer_object(unsigned id)
376 {
377         BufferMap::iterator i = buffers.find(id);
378         return (i==buffers.end() ? 0 : &i->second);
379 }
380
381 BufferState *GlState::get_current_buffer(GLenum target)
382 {
383         if(target==GL_ARRAY_BUFFER)
384                 return array_buffer;
385         else if(target==GL_ELEMENT_ARRAY_BUFFER)
386                 return element_buffer;
387         else if(target==GL_UNIFORM_BUFFER)
388                 return uniform_buffer;
389         return 0;
390 }
391
392 BufferBindingState *GlState::get_buffer_binding(GLenum target, unsigned index)
393 {
394         if(target==GL_UNIFORM_BUFFER)
395                 return &uniform_bind_points[index];
396         return 0;
397 }
398
399 void GlState::glBindBuffer(void *user_data, GLenum target, unsigned id)
400 {
401         reinterpret_cast<GlState *>(user_data)->set_current_buffer(target, id);
402 }
403
404 void GlState::glBindBufferBase(void *user_data, GLenum target, unsigned index, unsigned id)
405 {
406         if(BufferState *buffer = reinterpret_cast<GlState *>(user_data)->get_buffer_object(id))
407                 glBindBufferRange(user_data, target, index, id, 0, buffer->size);
408 }
409
410 void GlState::glBindBufferRange(void *user_data, GLenum target, unsigned index, unsigned id, int offset, int size)
411 {
412         GlState *self = reinterpret_cast<GlState *>(user_data);
413         if(BufferBindingState *binding = self->get_buffer_binding(target, index))
414         {
415                 binding->buffer = self->get_buffer_object(id);
416                 binding->offset = offset;
417                 binding->size = size;
418         }
419 }
420
421 void GlState::glBufferData(void *user_data, GLenum target, int size, const void *data, GLenum usage)
422 {
423         if(BufferState *buf = reinterpret_cast<GlState *>(user_data)->get_current_buffer(target))
424                 buf->set_data(size, data, usage);
425 }
426
427 void GlState::glBufferSubData(void *user_data, GLenum target, int offset, int size, const void *data)
428 {
429         if(BufferState *buf = reinterpret_cast<GlState *>(user_data)->get_current_buffer(target))
430                 buf->set_sub_data(offset, size, data);
431 }
432
433 void GlState::glDeleteBuffers(void *user_data, int count, const unsigned *ids)
434 {
435         for(int i=0; i<count; ++i)
436                 reinterpret_cast<GlState *>(user_data)->buffers.erase(ids[i]);
437 }
438
439 const BufferState &GlState::get_buffer(unsigned id) const
440 {
441         BufferMap::const_iterator i = buffers.find(id);
442         if(i==buffers.end())
443                 throw runtime_error("Unknown buffer");
444         return i->second;
445 }
446
447 const BufferState *GlState::get_current_buffer(GLenum target) const
448 {
449         return const_cast<GlState *>(this)->get_current_buffer(target);
450 }
451
452 const BufferBindingState &GlState::get_buffer_binding(GLenum target, unsigned index) const
453 {
454         if(target==GL_UNIFORM_BUFFER)
455                 return uniform_bind_points[index];
456         throw runtime_error("This buffer target does not have indexed binding points");
457 }
458
459 // Textures
460
461 void GlState::set_current_texture(GLenum target, unsigned id)
462 {
463         TexUnitState &unit = texunits[active_tex];
464         TextureState *tex = 0;
465         if(id)
466         {
467                 tex = &textures[id];
468                 if(!tex->id)
469                 {
470                         tex->id = id;
471                         tex->target = target;
472                 }
473                 else if(tex->target!=target)
474                         return;
475         }
476         unit.set_current_texture(target, tex);
477 }
478
479 TextureState *GlState::get_current_texture(GLenum target)
480 {
481         return texunits[active_tex].get_current_texture(target);
482 }
483
484 void GlState::glActiveTexture(void *user_data, unsigned index)
485 {
486         reinterpret_cast<GlState *>(user_data)->active_tex = index-GL_TEXTURE0;
487 }
488
489 void GlState::glBindTexture(void *user_data, GLenum target, unsigned id)
490 {
491         reinterpret_cast<GlState *>(user_data)->set_current_texture(target, id);
492 }
493
494 void GlState::glTexImage2D(void *user_data, GLenum target, int level, int ifmt, int width, int height, int, GLenum, GLenum, const void *)
495 {
496         if(TextureState *tex = reinterpret_cast<GlState *>(user_data)->get_current_texture(target))
497                 tex->set_image_2d(level, ifmt, width, height);
498 }
499
500 void GlState::glTexParameteri(void *user_data, GLenum target, GLenum param, int value)
501 {
502         glTexParameteriv(user_data, target, param, &value);
503 }
504
505 void GlState::glTexParameteriv(void *user_data, GLenum target, GLenum param, const int *values)
506 {
507         if(TextureState *tex = reinterpret_cast<GlState *>(user_data)->get_current_texture(target))
508                 tex->set_parameter(param, values);
509 }
510
511 void GlState::glDeleteTextures(void *user_data, int count, const unsigned *ids)
512 {
513         for(int i=0; i<count; ++i)
514                 reinterpret_cast<GlState *>(user_data)->textures.erase(ids[i]);
515 }
516
517 const TextureState &GlState::get_texture(unsigned id) const
518 {
519         TextureMap::const_iterator i = textures.find(id);
520         if(i==textures.end())
521                 throw runtime_error("Unknown texture");
522         return i->second;
523 }
524
525 // Shaders
526
527 ShaderState *GlState::get_shader(unsigned id, bool create)
528 {
529         ShaderMap::iterator i = shaders.find(id);
530         if(i==shaders.end() && create)
531         {
532                 i = shaders.insert(ShaderMap::value_type(id, ShaderState())).first;
533                 i->second.id = id;
534         }
535         return (i!=shaders.end() ? &i->second : 0);
536 }
537
538 void GlState::delete_shader(unsigned id)
539 {
540         ShaderMap::iterator i = shaders.find(id);
541         if(i==shaders.end())
542                 return;
543
544         for(ProgramMap::const_iterator j=programs.begin(); j!=programs.end(); ++j)
545         {
546                 const vector<ShaderState *> &prog_shaders = j->second.shaders;
547                 for(vector<ShaderState *>::const_iterator k=prog_shaders.begin(); k!=prog_shaders.end(); ++k)
548                         if(*k==&i->second)
549                         {
550                                 i->second.pending_delete = true;
551                                 return;
552                         }
553         }
554
555         shaders.erase(i);
556 }
557
558 ProgramState *GlState::get_program(unsigned id, bool create)
559 {
560         ProgramMap::iterator i = programs.find(id);
561         if(i==programs.end() && create)
562         {
563                 i = programs.insert(ProgramMap::value_type(id, ProgramState())).first;
564                 i->second.id = id;
565         }
566         return (i!=programs.end() ? &i->second : 0);
567 }
568
569 void GlState::delete_program(unsigned id)
570 {
571         ProgramMap::iterator i = programs.find(id);
572         if(i==programs.end())
573                 return;
574
575         vector<ShaderState *> prog_shaders = i->second.shaders;
576         programs.erase(i);
577         for(vector<ShaderState *>::const_iterator j=prog_shaders.begin(); j!=prog_shaders.end(); ++j)
578                 if((*j)->pending_delete)
579                         delete_shader((*j)->id);
580 }
581
582 void GlState::glCreateShader(void *user_data, unsigned id, GLenum type)
583 {
584         if(ShaderState *shader = reinterpret_cast<GlState *>(user_data)->get_shader(id, true))
585                 shader->type = type;
586 }
587
588 void GlState::glShaderSource(void *user_data, unsigned id, int count, const char **str, const int *length)
589 {
590         if(ShaderState *shader = reinterpret_cast<GlState *>(user_data)->get_shader(id, false))
591         {
592                 shader->source.clear();
593                 for(int i=0; i<count; ++i)
594                 {
595                         if(!length || length[i]<0)
596                                 shader->source.push_back(str[i]);
597                         else
598                                 shader->source.push_back(string(str[i], length[i]));
599                 }
600                 shader->source_changed = true;
601         }
602 }
603
604 void GlState::glCompileShader(void *user_data, unsigned id)
605 {
606         if(ShaderState *shader = reinterpret_cast<GlState *>(user_data)->get_shader(id, false))
607                 shader->source_changed = false;
608 }
609
610 void GlState::glGetShaderiv(void *user_data, unsigned id, GLenum pname, int *param)
611 {
612         if(ShaderState *shader = reinterpret_cast<GlState *>(user_data)->get_shader(id, false))
613         {
614                 if(pname==GL_COMPILE_STATUS)
615                         shader->compile_status = *param;
616         }
617 }
618
619 void GlState::glGetShaderInfoLog(void *user_data, unsigned id, int, int *, char *log)
620 {
621         if(ShaderState *shader = reinterpret_cast<GlState *>(user_data)->get_shader(id, false))
622                 shader->info_log = log;
623 }
624
625 void GlState::glDeleteShader(void *user_data, unsigned id)
626 {
627         reinterpret_cast<GlState *>(user_data)->delete_shader(id);
628 }
629
630 void GlState::glCreateProgram(void *user_data, unsigned id)
631 {
632         reinterpret_cast<GlState *>(user_data)->get_program(id, true);
633 }
634
635 void GlState::glAttachShader(void *user_data, unsigned prog_id, unsigned shader_id)
636 {
637         GlState *self = reinterpret_cast<GlState *>(user_data);
638         if(ProgramState *prog = self->get_program(prog_id, false))
639                 if(ShaderState *shader = self->get_shader(shader_id, false))
640                         prog->shaders.push_back(shader);
641 }
642
643 void GlState::glLinkProgram(void *user_data, unsigned id)
644 {
645         if(ProgramState *program = reinterpret_cast<GlState *>(user_data)->get_program(id, false))
646                 program->shaders_changed = false;
647 }
648
649 void GlState::glGetProgramiv(void *user_data, unsigned id, GLenum pname, int *param)
650 {
651         if(ProgramState *program = reinterpret_cast<GlState *>(user_data)->get_program(id, false))
652         {
653                 if(pname==GL_LINK_STATUS)
654                         program->link_status = *param;
655         }
656 }
657
658 void GlState::glGetProgramInfoLog(void *user_data, unsigned id, int, int *, char *log)
659 {
660         if(ProgramState *program = reinterpret_cast<GlState *>(user_data)->get_program(id, false))
661                 program->info_log = log;
662 }
663
664 void GlState::glDeleteProgram(void *user_data, unsigned id)
665 {
666         reinterpret_cast<GlState *>(user_data)->delete_program(id);
667 }
668
669 void GlState::glDeleteObjectARB(void *user_data, unsigned id)
670 {
671         GlState *self = reinterpret_cast<GlState *>(user_data);
672         if(self->shaders.count(id))
673                 self->delete_shader(id);
674         else if(self->programs.count(id))
675                 self->delete_program(id);
676 }
677
678 void GlState::glGetObjectParameterivARB(void *user_data, unsigned id, GLenum pname, int *param)
679 {
680         GlState *self = reinterpret_cast<GlState *>(user_data);
681         if(self->shaders.count(id))
682                 glGetShaderiv(user_data, id, pname, param);
683         else if(self->programs.count(id))
684                 glGetProgramiv(user_data, id, pname, param);
685 }
686
687 void GlState::glGetInfoLogARB(void *user_data, unsigned id, int bufsize, int *length, char *log)
688 {
689         GlState *self = reinterpret_cast<GlState *>(user_data);
690         if(self->shaders.count(id))
691                 glGetShaderInfoLog(user_data, id, bufsize, length, log);
692         else if(self->programs.count(id))
693                 glGetProgramInfoLog(user_data, id, bufsize, length, log);
694 }
695
696 const ShaderState &GlState::get_shader(unsigned id) const
697 {
698         ShaderMap::const_iterator i = shaders.find(id);
699         if(i==shaders.end())
700                 throw runtime_error("Unknown shader");
701         return i->second;
702 }
703
704 const ProgramState &GlState::get_program(unsigned id) const
705 {
706         ProgramMap::const_iterator i = programs.find(id);
707         if(i==programs.end())
708                 throw runtime_error("Unknown program");
709         return i->second;
710 }