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