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 * When fetching the uniform name of an array we usually get name[0]
172 * so we need to cut the trailing "[0]" in order to properly construct
173 * array names later. Otherwise we endup with stuff like
174 * uniformArray[0][0],
175 * uniformArray[0][1],
181 resolveUniformName(const GLchar *name, GLint size)
183 std::string qualifiedName(name);
185 std::string::size_type nameLength = qualifiedName.length();
186 static const char * const arrayStart = "[0]";
187 static const int arrayStartLen = 3;
188 if (qualifiedName.rfind(arrayStart) == (nameLength - arrayStartLen)) {
189 qualifiedName = qualifiedName.substr(0, nameLength - 3);
192 return qualifiedName;
196 dumpUniform(JSONWriter &json, GLint program, GLint size, GLenum type, const GLchar *name) {
199 _gl_uniform_size(type, elemType, numElems);
200 if (elemType == GL_NONE) {
204 GLfloat fvalues[4*4];
205 GLdouble dvalues[4*4];
207 GLuint uivalues[4*4];
211 std::string qualifiedName = resolveUniformName(name, size);
213 for (i = 0; i < size; ++i) {
214 std::stringstream ss;
218 ss << '[' << i << ']';
221 std::string elemName = ss.str();
223 json.beginMember(elemName);
225 GLint location = glGetUniformLocation(program, elemName.c_str());
233 glGetUniformfv(program, location, fvalues);
234 for (j = 0; j < numElems; ++j) {
235 json.writeNumber(fvalues[j]);
239 glGetUniformdv(program, location, dvalues);
240 for (j = 0; j < numElems; ++j) {
241 json.writeNumber(dvalues[j]);
245 glGetUniformiv(program, location, ivalues);
246 for (j = 0; j < numElems; ++j) {
247 json.writeNumber(ivalues[j]);
250 case GL_UNSIGNED_INT:
251 glGetUniformuiv(program, location, uivalues);
252 for (j = 0; j < numElems; ++j) {
253 json.writeNumber(uivalues[j]);
257 glGetUniformiv(program, location, ivalues);
258 for (j = 0; j < numElems; ++j) {
259 json.writeBool(ivalues[j]);
277 dumpUniformARB(JSONWriter &json, GLhandleARB programObj, GLint size, GLenum type, const GLchar *name) {
281 _gl_uniform_size(type, elemType, numElems);
282 if (elemType == GL_NONE) {
286 GLfloat fvalues[4*4];
291 std::string qualifiedName = resolveUniformName(name, size);
293 for (i = 0; i < size; ++i) {
294 std::stringstream ss;
298 ss << '[' << i << ']';
301 std::string elemName = ss.str();
303 json.beginMember(elemName);
305 GLint location = glGetUniformLocationARB(programObj, elemName.c_str());
313 // glGetUniformdvARB does not exists
315 glGetUniformfvARB(programObj, location, fvalues);
316 for (j = 0; j < numElems; ++j) {
317 json.writeNumber(fvalues[j]);
320 case GL_UNSIGNED_INT:
321 // glGetUniformuivARB does not exists
323 glGetUniformivARB(programObj, location, ivalues);
324 for (j = 0; j < numElems; ++j) {
325 json.writeNumber(ivalues[j]);
329 glGetUniformivARB(programObj, location, ivalues);
330 for (j = 0; j < numElems; ++j) {
331 json.writeBool(ivalues[j]);
349 dumpProgramUniforms(JSONWriter &json, GLint program)
351 GLint active_uniforms = 0;
352 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &active_uniforms);
353 if (!active_uniforms) {
357 GLint active_uniform_max_length = 0;
358 glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &active_uniform_max_length);
359 GLchar *name = new GLchar[active_uniform_max_length];
364 for (GLint index = 0; index < active_uniforms; ++index) {
367 GLenum type = GL_NONE;
368 glGetActiveUniform(program, index, active_uniform_max_length, &length, &size, &type, name);
370 dumpUniform(json, program, size, type, name);
378 dumpProgramObjUniforms(JSONWriter &json, GLhandleARB programObj)
380 GLint active_uniforms = 0;
381 glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &active_uniforms);
382 if (!active_uniforms) {
386 GLint active_uniform_max_length = 0;
387 glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB, &active_uniform_max_length);
388 GLchar *name = new GLchar[active_uniform_max_length];
393 for (GLint index = 0; index < active_uniforms; ++index) {
396 GLenum type = GL_NONE;
397 glGetActiveUniformARB(programObj, index, active_uniform_max_length, &length, &size, &type, name);
399 dumpUniformARB(json, programObj, size, type, name);
407 dumpArbProgram(JSONWriter &json, GLenum target)
409 if (!glIsEnabled(target)) {
413 GLint program_length = 0;
414 glGetProgramivARB(target, GL_PROGRAM_LENGTH_ARB, &program_length);
415 if (!program_length) {
419 GLchar *source = new GLchar[program_length + 1];
421 glGetProgramStringARB(target, GL_PROGRAM_STRING_ARB, source);
422 source[program_length] = 0;
424 json.beginMember(enumToString(target));
425 json.writeString(source);
433 dumpArbProgramUniforms(JSONWriter &json, GLenum target, const char *prefix)
435 if (!glIsEnabled(target)) {
439 GLint program_parameters = 0;
440 glGetProgramivARB(target, GL_PROGRAM_PARAMETERS_ARB, &program_parameters);
441 if (!program_parameters) {
445 GLint max_program_local_parameters = 0;
446 glGetProgramivARB(target, GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, &max_program_local_parameters);
447 for (GLint index = 0; index < max_program_local_parameters; ++index) {
448 GLdouble params[4] = {0, 0, 0, 0};
449 glGetProgramLocalParameterdvARB(target, index, params);
451 if (!params[0] && !params[1] && !params[2] && !params[3]) {
456 snprintf(name, sizeof name, "%sprogram.local[%i]", prefix, index);
458 json.beginMember(name);
460 json.writeNumber(params[0]);
461 json.writeNumber(params[1]);
462 json.writeNumber(params[2]);
463 json.writeNumber(params[3]);
468 GLint max_program_env_parameters = 0;
469 glGetProgramivARB(target, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &max_program_env_parameters);
470 for (GLint index = 0; index < max_program_env_parameters; ++index) {
471 GLdouble params[4] = {0, 0, 0, 0};
472 glGetProgramEnvParameterdvARB(target, index, params);
474 if (!params[0] && !params[1] && !params[2] && !params[3]) {
479 snprintf(name, sizeof name, "%sprogram.env[%i]", prefix, index);
481 json.beginMember(name);
483 json.writeNumber(params[0]);
484 json.writeNumber(params[1]);
485 json.writeNumber(params[2]);
486 json.writeNumber(params[3]);
494 dumpShadersUniforms(JSONWriter &json, Context &context)
497 glGetIntegerv(GL_CURRENT_PROGRAM, &program);
499 GLhandleARB programObj = 0;
500 if (!context.ES && !program) {
501 programObj = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);
504 json.beginMember("shaders");
507 dumpProgram(json, program);
508 } else if (programObj) {
509 dumpProgramObj(json, programObj);
511 dumpArbProgram(json, GL_FRAGMENT_PROGRAM_ARB);
512 dumpArbProgram(json, GL_VERTEX_PROGRAM_ARB);
515 json.endMember(); // shaders
517 json.beginMember("uniforms");
520 dumpProgramUniforms(json, program);
521 } else if (programObj) {
522 dumpProgramObjUniforms(json, programObj);
524 dumpArbProgramUniforms(json, GL_FRAGMENT_PROGRAM_ARB, "fp.");
525 dumpArbProgramUniforms(json, GL_VERTEX_PROGRAM_ARB, "vp.");
528 json.endMember(); // uniforms
532 } /* namespace glstate */