1 /**************************************************************************
3 * Copyright 2011 Jose Fonseca
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 **************************************************************************/
37 #include "glstate.hpp"
38 #include "glstate_internal.hpp"
44 // Mapping from shader type to shader source, used to accumulated the sources
45 // of different shaders with same type.
46 typedef std::map<std::string, std::string> ShaderMap;
50 getShaderSource(ShaderMap &shaderMap, GLuint shader)
56 GLint shader_type = 0;
57 glGetShaderiv(shader, GL_SHADER_TYPE, &shader_type);
62 GLint source_length = 0;
63 glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &source_length);
68 GLchar *source = new GLchar[source_length];
71 glGetShaderSource(shader, source_length, &length, source);
73 shaderMap[enumToString(shader_type)] += source;
80 getShaderObjSource(ShaderMap &shaderMap, GLhandleARB shaderObj)
86 GLint object_type = 0;
87 glGetObjectParameterivARB(shaderObj, GL_OBJECT_TYPE_ARB, &object_type);
88 if (object_type != GL_SHADER_OBJECT_ARB) {
92 GLint shader_type = 0;
93 glGetObjectParameterivARB(shaderObj, GL_OBJECT_SUBTYPE_ARB, &shader_type);
98 GLint source_length = 0;
99 glGetObjectParameterivARB(shaderObj, GL_OBJECT_SHADER_SOURCE_LENGTH_ARB, &source_length);
100 if (!source_length) {
104 GLcharARB *source = new GLcharARB[source_length];
107 glGetShaderSource(shaderObj, source_length, &length, source);
109 shaderMap[enumToString(shader_type)] += source;
116 dumpProgram(JSONWriter &json, GLint program)
118 GLint attached_shaders = 0;
119 glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders);
120 if (!attached_shaders) {
126 GLuint *shaders = new GLuint[attached_shaders];
128 glGetAttachedShaders(program, attached_shaders, &count, shaders);
129 std::sort(shaders, shaders + count);
130 for (GLsizei i = 0; i < count; ++ i) {
131 getShaderSource(shaderMap, shaders[i]);
135 for (ShaderMap::const_iterator it = shaderMap.begin(); it != shaderMap.end(); ++it) {
136 json.beginMember(it->first);
137 json.writeString(it->second);
144 dumpProgramObj(JSONWriter &json, GLhandleARB programObj)
146 GLint attached_shaders = 0;
147 glGetObjectParameterivARB(programObj, GL_OBJECT_ATTACHED_OBJECTS_ARB, &attached_shaders);
148 if (!attached_shaders) {
154 GLhandleARB *shaderObjs = new GLhandleARB[attached_shaders];
156 glGetAttachedObjectsARB(programObj, attached_shaders, &count, shaderObjs);
157 std::sort(shaderObjs, shaderObjs + count);
158 for (GLsizei i = 0; i < count; ++ i) {
159 getShaderObjSource(shaderMap, shaderObjs[i]);
161 delete [] shaderObjs;
163 for (ShaderMap::const_iterator it = shaderMap.begin(); it != shaderMap.end(); ++it) {
164 json.beginMember(it->first);
165 json.writeString(it->second);
171 * Built-in uniforms can't be queried through glGetUniform*.
174 isBuiltinUniform(const GLchar *name)
176 return name[0] == 'g' && name[1] == 'l' && name[2] == '_';
180 * When fetching the uniform name of an array we usually get name[0]
181 * so we need to cut the trailing "[0]" in order to properly construct
182 * array names later. Otherwise we endup with stuff like
183 * uniformArray[0][0],
184 * uniformArray[0][1],
190 resolveUniformName(const GLchar *name, GLint size)
192 std::string qualifiedName(name);
194 std::string::size_type nameLength = qualifiedName.length();
195 static const char * const arrayStart = "[0]";
196 static const int arrayStartLen = 3;
197 if (qualifiedName.rfind(arrayStart) == (nameLength - arrayStartLen)) {
198 qualifiedName = qualifiedName.substr(0, nameLength - 3);
201 return qualifiedName;
205 dumpUniform(JSONWriter &json, GLint program, GLint size, GLenum type, const GLchar *name) {
208 _gl_uniform_size(type, elemType, numElems);
209 if (elemType == GL_NONE) {
213 GLfloat fvalues[4*4];
214 GLdouble dvalues[4*4];
216 GLuint uivalues[4*4];
220 std::string qualifiedName = resolveUniformName(name, size);
222 for (i = 0; i < size; ++i) {
223 std::stringstream ss;
227 ss << '[' << i << ']';
230 std::string elemName = ss.str();
232 json.beginMember(elemName);
234 GLint location = glGetUniformLocation(program, elemName.c_str());
242 glGetUniformfv(program, location, fvalues);
243 for (j = 0; j < numElems; ++j) {
244 json.writeNumber(fvalues[j]);
248 glGetUniformdv(program, location, dvalues);
249 for (j = 0; j < numElems; ++j) {
250 json.writeNumber(dvalues[j]);
254 glGetUniformiv(program, location, ivalues);
255 for (j = 0; j < numElems; ++j) {
256 json.writeNumber(ivalues[j]);
259 case GL_UNSIGNED_INT:
260 glGetUniformuiv(program, location, uivalues);
261 for (j = 0; j < numElems; ++j) {
262 json.writeNumber(uivalues[j]);
266 glGetUniformiv(program, location, ivalues);
267 for (j = 0; j < numElems; ++j) {
268 json.writeBool(ivalues[j]);
273 for (j = 0; j < numElems; ++j) {
292 dumpUniformARB(JSONWriter &json, GLhandleARB programObj, GLint size, GLenum type, const GLchar *name) {
296 _gl_uniform_size(type, elemType, numElems);
297 if (elemType == GL_NONE) {
301 GLfloat fvalues[4*4];
306 std::string qualifiedName = resolveUniformName(name, size);
308 for (i = 0; i < size; ++i) {
309 std::stringstream ss;
313 ss << '[' << i << ']';
316 std::string elemName = ss.str();
318 json.beginMember(elemName);
320 GLint location = glGetUniformLocationARB(programObj, elemName.c_str());
328 // glGetUniformdvARB does not exists
330 glGetUniformfvARB(programObj, location, fvalues);
331 for (j = 0; j < numElems; ++j) {
332 json.writeNumber(fvalues[j]);
335 case GL_UNSIGNED_INT:
336 // glGetUniformuivARB does not exists
338 glGetUniformivARB(programObj, location, ivalues);
339 for (j = 0; j < numElems; ++j) {
340 json.writeNumber(ivalues[j]);
344 glGetUniformivARB(programObj, location, ivalues);
345 for (j = 0; j < numElems; ++j) {
346 json.writeBool(ivalues[j]);
351 for (j = 0; j < numElems; ++j) {
370 dumpProgramUniforms(JSONWriter &json, GLint program)
372 GLint active_uniforms = 0;
373 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &active_uniforms);
374 if (!active_uniforms) {
378 GLint active_uniform_max_length = 0;
379 glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &active_uniform_max_length);
380 GLchar *name = new GLchar[active_uniform_max_length];
385 for (GLint index = 0; index < active_uniforms; ++index) {
388 GLenum type = GL_NONE;
389 glGetActiveUniform(program, index, active_uniform_max_length, &length, &size, &type, name);
391 if (!isBuiltinUniform(name)) {
392 dumpUniform(json, program, size, type, name);
401 dumpProgramObjUniforms(JSONWriter &json, GLhandleARB programObj)
403 GLint active_uniforms = 0;
404 glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &active_uniforms);
405 if (!active_uniforms) {
409 GLint active_uniform_max_length = 0;
410 glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB, &active_uniform_max_length);
411 GLchar *name = new GLchar[active_uniform_max_length];
416 for (GLint index = 0; index < active_uniforms; ++index) {
419 GLenum type = GL_NONE;
420 glGetActiveUniformARB(programObj, index, active_uniform_max_length, &length, &size, &type, name);
422 if (!isBuiltinUniform(name)) {
423 dumpUniformARB(json, programObj, size, type, name);
432 dumpArbProgram(JSONWriter &json, GLenum target)
434 if (!glIsEnabled(target)) {
438 GLint program_length = 0;
439 glGetProgramivARB(target, GL_PROGRAM_LENGTH_ARB, &program_length);
440 if (!program_length) {
444 GLchar *source = new GLchar[program_length + 1];
446 glGetProgramStringARB(target, GL_PROGRAM_STRING_ARB, source);
447 source[program_length] = 0;
449 json.beginMember(enumToString(target));
450 json.writeString(source);
458 dumpArbProgramUniforms(JSONWriter &json, GLenum target, const char *prefix)
460 if (!glIsEnabled(target)) {
464 GLint program_parameters = 0;
465 glGetProgramivARB(target, GL_PROGRAM_PARAMETERS_ARB, &program_parameters);
466 if (!program_parameters) {
470 GLint max_program_local_parameters = 0;
471 glGetProgramivARB(target, GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, &max_program_local_parameters);
472 for (GLint index = 0; index < max_program_local_parameters; ++index) {
473 GLdouble params[4] = {0, 0, 0, 0};
474 glGetProgramLocalParameterdvARB(target, index, params);
476 if (!params[0] && !params[1] && !params[2] && !params[3]) {
481 snprintf(name, sizeof name, "%sprogram.local[%i]", prefix, index);
483 json.beginMember(name);
485 json.writeNumber(params[0]);
486 json.writeNumber(params[1]);
487 json.writeNumber(params[2]);
488 json.writeNumber(params[3]);
493 GLint max_program_env_parameters = 0;
494 glGetProgramivARB(target, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &max_program_env_parameters);
495 for (GLint index = 0; index < max_program_env_parameters; ++index) {
496 GLdouble params[4] = {0, 0, 0, 0};
497 glGetProgramEnvParameterdvARB(target, index, params);
499 if (!params[0] && !params[1] && !params[2] && !params[3]) {
504 snprintf(name, sizeof name, "%sprogram.env[%i]", prefix, index);
506 json.beginMember(name);
508 json.writeNumber(params[0]);
509 json.writeNumber(params[1]);
510 json.writeNumber(params[2]);
511 json.writeNumber(params[3]);
519 dumpShadersUniforms(JSONWriter &json, Context &context)
522 glGetIntegerv(GL_CURRENT_PROGRAM, &program);
524 GLhandleARB programObj = 0;
525 if (!context.ES && !program) {
526 programObj = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);
529 json.beginMember("shaders");
532 dumpProgram(json, program);
533 } else if (programObj) {
534 dumpProgramObj(json, programObj);
536 dumpArbProgram(json, GL_FRAGMENT_PROGRAM_ARB);
537 dumpArbProgram(json, GL_VERTEX_PROGRAM_ARB);
540 json.endMember(); // shaders
542 json.beginMember("uniforms");
545 dumpProgramUniforms(json, program);
546 } else if (programObj) {
547 dumpProgramObjUniforms(json, programObj);
549 dumpArbProgramUniforms(json, GL_FRAGMENT_PROGRAM_ARB, "fp.");
550 dumpArbProgramUniforms(json, GL_VERTEX_PROGRAM_ARB, "vp.");
553 json.endMember(); // uniforms
557 } /* namespace glstate */