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