12 float normalize<GLubyte>(GLubyte v)
16 float normalize<GLbyte>(GLbyte v)
17 { return (2*v+1)/255.0f; }
19 template<typename T, void (*func)(void *, float)>
20 void wrap_normalized(void *user_data, T v0)
21 { func(user_data, v0); }
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); }
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); }
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); }
35 template<typename T, void (*func)(void *, T)>
36 void wrap_array(void *user_data, const T *v)
37 { func(user_data, v[0]); }
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]); }
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]); }
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]); }
60 x(0), y(0), z(0), w(1)
65 decoder(gldecoder_new(this, NULL)),
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;
81 decoder->glGetIntegerv = glGetIntegerv;
83 decoder->glEnable = glEnable;
84 decoder->glDisable = glDisable;
85 decoder->glEnableClientState = glEnableClientState;
86 decoder->glDisableClientState = glDisableClientState;
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>;
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;
120 decoder->glDrawElements = glDrawElements;
121 decoder->glDrawRangeElements = glDrawRangeElements;
122 decoder->glDrawRangeElementsEXT = glDrawRangeElements;
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;
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;
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;
167 gldecoder_delete(decoder);
170 int GlState::decode(const char *data, unsigned len)
172 return gldecoder_decode(decoder, data, len);
175 void GlState::glGetIntegerv(void *user_data, GLenum pname, int *param)
177 GlState *self = reinterpret_cast<GlState *>(user_data);
178 if(pname==GL_MAX_TEXTURE_UNITS)
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)
185 self->texcoord_arrays[i].kind = GL_TEXTURE_COORD_ARRAY;
186 self->texcoord_arrays[i].index = i;
189 else if(pname==GL_MAX_VERTEX_ATTRIBS)
191 self->attrib_arrays.resize(*param);
192 for(unsigned i=0; i<self->attrib_arrays.size(); ++i)
193 self->attrib_arrays[i].index = i;
195 else if(pname==GL_MAX_UNIFORM_BUFFER_BINDINGS)
196 self->uniform_bind_points.resize(*param);
201 bool &GlState::get_boolean_state(GLenum state)
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;
216 bool &GlState::get_boolean_client_state(GLenum state)
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;
231 void GlState::glEnable(void *user_data, GLenum state)
233 reinterpret_cast<GlState *>(user_data)->get_boolean_state(state) = true;
236 void GlState::glDisable(void *user_data, GLenum state)
238 reinterpret_cast<GlState *>(user_data)->get_boolean_state(state) = false;
241 void GlState::glEnableClientState(void *user_data, GLenum state)
243 reinterpret_cast<GlState *>(user_data)->get_boolean_client_state(state) = true;
246 void GlState::glDisableClientState(void *user_data, GLenum state)
248 reinterpret_cast<GlState *>(user_data)->get_boolean_client_state(state) = false;
253 void GlState::glColor3f(void *user_data, float r, float g, float b)
255 glColor4f(user_data, r, g, b, 1.0f);
258 void GlState::glColor4f(void *user_data, float r, float g, float b, float a)
260 Vector4 &color = reinterpret_cast<GlState *>(user_data)->color;
267 void GlState::glNormal3f(void *user_data, float x, float y, float z)
269 Vector3 &normal = reinterpret_cast<GlState *>(user_data)->normal;
275 void GlState::glTexCoord1f(void *user_data, float s)
277 glTexCoord4f(user_data, s, 0.0f, 0.0f, 1.0f);
280 void GlState::glTexCoord2f(void *user_data, float s, float t)
282 glTexCoord4f(user_data, s, t, 0.0f, 1.0f);
285 void GlState::glTexCoord3f(void *user_data, float s, float t, float p)
287 glTexCoord4f(user_data, s, t, p, 1.0f);
290 void GlState::glTexCoord4f(void *user_data, float s, float t, float p, float q)
292 unsigned index = reinterpret_cast<GlState *>(user_data)->active_tex;
293 glMultiTexCoord4f(user_data, index, s, t, p, q);
296 void GlState::glMultiTexCoord4f(void *user_data, unsigned index, float s, float t, float p, float q)
298 Vector4 &texcoord = reinterpret_cast<GlState *>(user_data)->texcoord[index];
307 void GlState::glVertexPointer(void *user_data, int size, GLenum type, int stride, const void *data)
309 GlState *self = reinterpret_cast<GlState *>(user_data);
310 self->vertex_array.set(size, type, false, stride, self->array_buffer, reinterpret_cast<long>(data));
313 void GlState::glNormalPointer(void *user_data, GLenum type, int stride, const void *data)
315 GlState *self = reinterpret_cast<GlState *>(user_data);
316 self->normal_array.set(3, type, true, stride, self->array_buffer, reinterpret_cast<long>(data));
319 void GlState::glColorPointer(void *user_data, int size, GLenum type, int stride, const void *data)
321 GlState *self = reinterpret_cast<GlState *>(user_data);
322 self->color_array.set(size, type, true, stride, self->array_buffer, reinterpret_cast<long>(data));
325 void GlState::glClientActiveTexture(void *user_data, unsigned index)
327 reinterpret_cast<GlState *>(user_data)->client_active_tex = index-GL_TEXTURE0;
330 void GlState::glTexCoordPointer(void *user_data, int size, GLenum type, int stride, const void *data)
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));
336 void GlState::glEnableVertexAttribArray(void *user_data, unsigned index)
338 reinterpret_cast<GlState *>(user_data)->attrib_arrays[index].enabled = true;
341 void GlState::glDisableVertexAttribArray(void *user_data, unsigned index)
343 reinterpret_cast<GlState *>(user_data)->attrib_arrays[index].enabled = false;
346 void GlState::glVertexAttribPointer(void *user_data, unsigned index, int size, GLenum type, unsigned char norm, int stride, const void *data)
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));
352 const ArrayState &GlState::get_array(GLenum array) const
354 if(array==GL_VERTEX_ARRAY)
356 else if(array==GL_NORMAL_ARRAY)
358 else if(array==GL_COLOR_ARRAY)
360 else if(array==GL_TEXTURE_COORD_ARRAY)
361 return texcoord_arrays[client_active_tex];
363 throw logic_error("Invalid array");
366 const ArrayState &GlState::get_texture_coord_array(unsigned index) const
368 return texcoord_arrays[index];
371 const ArrayState &GlState::get_attrib_array(unsigned index) const
373 return attrib_arrays[index];
376 // Array draw commands
378 void GlState::glDrawElements(void *user_data, GLenum, int, GLenum type, const void *)
380 if(BufferState *buf = reinterpret_cast<GlState *>(user_data)->element_buffer)
381 buf->content.update_elements(type);
384 void GlState::glDrawRangeElements(void *user_data, GLenum, unsigned, unsigned, int, GLenum type, const void *)
386 if(BufferState *buf = reinterpret_cast<GlState *>(user_data)->element_buffer)
387 buf->content.update_elements(type);
392 void GlState::set_current_buffer(GLenum target, unsigned id)
394 BufferState *buf = 0;
402 if(target==GL_ARRAY_BUFFER)
404 else if(target==GL_ELEMENT_ARRAY_BUFFER)
405 element_buffer = buf;
406 else if(target==GL_UNIFORM_BUFFER)
407 uniform_buffer = buf;
410 BufferState *GlState::get_buffer_object(unsigned id)
412 BufferMap::iterator i = buffers.find(id);
413 return (i==buffers.end() ? 0 : &i->second);
416 BufferState *GlState::get_current_buffer(GLenum target)
418 if(target==GL_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;
427 BufferBindingState *GlState::get_buffer_binding(GLenum target, unsigned index)
429 if(target==GL_UNIFORM_BUFFER)
430 return &uniform_bind_points[index];
434 void GlState::glBindBuffer(void *user_data, GLenum target, unsigned id)
436 reinterpret_cast<GlState *>(user_data)->set_current_buffer(target, id);
439 void GlState::glBindBufferBase(void *user_data, GLenum target, unsigned index, unsigned id)
441 if(BufferState *buffer = reinterpret_cast<GlState *>(user_data)->get_buffer_object(id))
442 glBindBufferRange(user_data, target, index, id, 0, buffer->size);
445 void GlState::glBindBufferRange(void *user_data, GLenum target, unsigned index, unsigned id, int offset, int size)
447 GlState *self = reinterpret_cast<GlState *>(user_data);
448 if(BufferBindingState *binding = self->get_buffer_binding(target, index))
450 binding->buffer = self->get_buffer_object(id);
451 binding->offset = offset;
452 binding->size = size;
456 void GlState::glBufferData(void *user_data, GLenum target, int size, const void *data, GLenum usage)
458 if(BufferState *buf = reinterpret_cast<GlState *>(user_data)->get_current_buffer(target))
459 buf->set_data(size, data, usage);
462 void GlState::glBufferSubData(void *user_data, GLenum target, int offset, int size, const void *data)
464 if(BufferState *buf = reinterpret_cast<GlState *>(user_data)->get_current_buffer(target))
465 buf->set_sub_data(offset, size, data);
468 void GlState::glDeleteBuffers(void *user_data, int count, const unsigned *ids)
470 for(int i=0; i<count; ++i)
471 reinterpret_cast<GlState *>(user_data)->buffers.erase(ids[i]);
474 const BufferState &GlState::get_buffer(unsigned id) const
476 BufferMap::const_iterator i = buffers.find(id);
478 throw runtime_error("Unknown buffer");
482 const BufferState *GlState::get_current_buffer(GLenum target) const
484 return const_cast<GlState *>(this)->get_current_buffer(target);
487 const BufferBindingState &GlState::get_buffer_binding(GLenum target, unsigned index) const
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");
496 void GlState::set_current_texture(GLenum target, unsigned id)
498 TexUnitState &unit = texunits[active_tex];
499 TextureState *tex = 0;
506 tex->target = target;
508 else if(tex->target!=target)
511 unit.set_current_texture(target, tex);
514 TextureState *GlState::get_current_texture(GLenum target)
516 return texunits[active_tex].get_current_texture(target);
519 void GlState::glActiveTexture(void *user_data, unsigned index)
521 reinterpret_cast<GlState *>(user_data)->active_tex = index-GL_TEXTURE0;
524 void GlState::glBindTexture(void *user_data, GLenum target, unsigned id)
526 reinterpret_cast<GlState *>(user_data)->set_current_texture(target, id);
529 void GlState::glTexImage1D(void *user_data, GLenum target, int level, int ifmt, int width, int, GLenum, GLenum, const void *)
531 if(TextureState *tex = reinterpret_cast<GlState *>(user_data)->get_current_texture(target))
532 tex->set_image_1d(level, ifmt, width);
535 void GlState::glTexImage2D(void *user_data, GLenum target, int level, int ifmt, int width, int height, int, GLenum, GLenum, const void *)
538 for(unsigned i=0; i<6; ++i)
539 if(texture_cube_faces[i]==target)
542 target = GL_TEXTURE_CUBE_MAP;
546 if(TextureState *tex = reinterpret_cast<GlState *>(user_data)->get_current_texture(target))
549 tex->set_face_image_2d(face, level, ifmt, width, height);
551 tex->set_image_2d(level, ifmt, width, height);
555 void GlState::glTexImage3D(void *user_data, GLenum target, int level, int ifmt, int width, int height, int depth, int, GLenum, GLenum, const void *)
557 if(TextureState *tex = reinterpret_cast<GlState *>(user_data)->get_current_texture(target))
558 tex->set_image_3d(level, ifmt, width, height, depth);
561 void GlState::glTexParameteri(void *user_data, GLenum target, GLenum param, int value)
563 glTexParameteriv(user_data, target, param, &value);
566 void GlState::glTexParameteriv(void *user_data, GLenum target, GLenum param, const int *values)
568 if(TextureState *tex = reinterpret_cast<GlState *>(user_data)->get_current_texture(target))
569 tex->set_parameter(param, values);
572 void GlState::glDeleteTextures(void *user_data, int count, const unsigned *ids)
574 for(int i=0; i<count; ++i)
575 reinterpret_cast<GlState *>(user_data)->textures.erase(ids[i]);
578 const TextureState &GlState::get_texture(unsigned id) const
580 TextureMap::const_iterator i = textures.find(id);
581 if(i==textures.end())
582 throw runtime_error("Unknown texture");
588 ShaderState *GlState::get_shader(unsigned id, bool create)
590 ShaderMap::iterator i = shaders.find(id);
591 if(i==shaders.end() && create)
593 i = shaders.insert(ShaderMap::value_type(id, ShaderState())).first;
596 return (i!=shaders.end() ? &i->second : 0);
599 void GlState::delete_shader(unsigned id)
601 ShaderMap::iterator i = shaders.find(id);
605 for(ProgramMap::const_iterator j=programs.begin(); j!=programs.end(); ++j)
607 const vector<ShaderState *> &prog_shaders = j->second.shaders;
608 for(vector<ShaderState *>::const_iterator k=prog_shaders.begin(); k!=prog_shaders.end(); ++k)
611 i->second.pending_delete = true;
619 ProgramState *GlState::get_program(unsigned id, bool create)
621 ProgramMap::iterator i = programs.find(id);
622 if(i==programs.end() && create)
624 i = programs.insert(ProgramMap::value_type(id, ProgramState())).first;
627 return (i!=programs.end() ? &i->second : 0);
630 void GlState::delete_program(unsigned id)
632 ProgramMap::iterator i = programs.find(id);
633 if(i==programs.end())
636 vector<ShaderState *> prog_shaders = i->second.shaders;
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);
643 void GlState::glCreateShader(void *user_data, unsigned id, GLenum type)
645 if(ShaderState *shader = reinterpret_cast<GlState *>(user_data)->get_shader(id, true))
649 void GlState::glShaderSource(void *user_data, unsigned id, int count, const char **str, const int *length)
651 if(ShaderState *shader = reinterpret_cast<GlState *>(user_data)->get_shader(id, false))
653 shader->source.clear();
654 for(int i=0; i<count; ++i)
656 if(!length || length[i]<0)
657 shader->source.push_back(str[i]);
659 shader->source.push_back(string(str[i], length[i]));
661 shader->source_changed = true;
665 void GlState::glCompileShader(void *user_data, unsigned id)
667 if(ShaderState *shader = reinterpret_cast<GlState *>(user_data)->get_shader(id, false))
668 shader->source_changed = false;
671 void GlState::glGetShaderiv(void *user_data, unsigned id, GLenum pname, int *param)
673 if(ShaderState *shader = reinterpret_cast<GlState *>(user_data)->get_shader(id, false))
675 if(pname==GL_COMPILE_STATUS)
676 shader->compile_status = *param;
680 void GlState::glGetShaderInfoLog(void *user_data, unsigned id, int, int *, char *log)
682 if(ShaderState *shader = reinterpret_cast<GlState *>(user_data)->get_shader(id, false))
683 shader->info_log = log;
686 void GlState::glDeleteShader(void *user_data, unsigned id)
688 reinterpret_cast<GlState *>(user_data)->delete_shader(id);
691 void GlState::glCreateProgram(void *user_data, unsigned id)
693 reinterpret_cast<GlState *>(user_data)->get_program(id, true);
696 void GlState::glAttachShader(void *user_data, unsigned prog_id, unsigned shader_id)
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);
704 void GlState::glLinkProgram(void *user_data, unsigned id)
706 if(ProgramState *program = reinterpret_cast<GlState *>(user_data)->get_program(id, false))
707 program->shaders_changed = false;
710 void GlState::glGetProgramiv(void *user_data, unsigned id, GLenum pname, int *param)
712 if(ProgramState *program = reinterpret_cast<GlState *>(user_data)->get_program(id, false))
714 if(pname==GL_LINK_STATUS)
715 program->link_status = *param;
719 void GlState::glGetProgramInfoLog(void *user_data, unsigned id, int, int *, char *log)
721 if(ProgramState *program = reinterpret_cast<GlState *>(user_data)->get_program(id, false))
722 program->info_log = log;
725 void GlState::glDeleteProgram(void *user_data, unsigned id)
727 reinterpret_cast<GlState *>(user_data)->delete_program(id);
730 void GlState::glDeleteObjectARB(void *user_data, unsigned id)
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);
739 void GlState::glGetObjectParameterivARB(void *user_data, unsigned id, GLenum pname, int *param)
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);
748 void GlState::glGetInfoLogARB(void *user_data, unsigned id, int bufsize, int *length, char *log)
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);
757 const ShaderState &GlState::get_shader(unsigned id) const
759 ShaderMap::const_iterator i = shaders.find(id);
761 throw runtime_error("Unknown shader");
765 const ProgramState &GlState::get_program(unsigned id) const
767 ProgramMap::const_iterator i = programs.find(id);
768 if(i==programs.end())
769 throw runtime_error("Unknown program");