From 788a7cb792894d40c7cf37a3d2b9eaa6edaaa3dd Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Fonseca?= Date: Thu, 29 Mar 2012 09:42:41 +0100 Subject: [PATCH] Split gl shader dumping into a separate file. --- CMakeLists.txt | 1 + glstate.cpp | 487 --------------------------------------- glstate_internal.hpp | 2 + glstate_shaders.cpp | 529 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 532 insertions(+), 487 deletions(-) create mode 100644 glstate_shaders.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index acb7dd0..a687e49 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -561,6 +561,7 @@ set (retrace_sources glretrace_main.cpp glstate.cpp glstate_params.cpp + glstate_shaders.cpp retrace.cpp retrace_stdc.cpp glws.cpp diff --git a/glstate.cpp b/glstate.cpp index 8faafe9..614b069 100644 --- a/glstate.cpp +++ b/glstate.cpp @@ -28,8 +28,6 @@ #include #include -#include -#include #include "image.hpp" #include "json.hpp" @@ -117,491 +115,6 @@ Context::restorePixelPackState(void) { } -// Mapping from shader type to shader source, used to accumulated the sources -// of different shaders with same type. -typedef std::map ShaderMap; - - -static void -getShaderSource(ShaderMap &shaderMap, GLuint shader) -{ - if (!shader) { - return; - } - - GLint shader_type = 0; - glGetShaderiv(shader, GL_SHADER_TYPE, &shader_type); - if (!shader_type) { - return; - } - - GLint source_length = 0; - glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &source_length); - if (!source_length) { - return; - } - - GLchar *source = new GLchar[source_length]; - GLsizei length = 0; - source[0] = 0; - glGetShaderSource(shader, source_length, &length, source); - - shaderMap[enumToString(shader_type)] += source; - - delete [] source; -} - - -static void -getShaderObjSource(ShaderMap &shaderMap, GLhandleARB shaderObj) -{ - if (!shaderObj) { - return; - } - - GLint object_type = 0; - glGetObjectParameterivARB(shaderObj, GL_OBJECT_TYPE_ARB, &object_type); - if (object_type != GL_SHADER_OBJECT_ARB) { - return; - } - - GLint shader_type = 0; - glGetObjectParameterivARB(shaderObj, GL_OBJECT_SUBTYPE_ARB, &shader_type); - if (!shader_type) { - return; - } - - GLint source_length = 0; - glGetObjectParameterivARB(shaderObj, GL_OBJECT_SHADER_SOURCE_LENGTH_ARB, &source_length); - if (!source_length) { - return; - } - - GLcharARB *source = new GLcharARB[source_length]; - GLsizei length = 0; - source[0] = 0; - glGetShaderSource(shaderObj, source_length, &length, source); - - shaderMap[enumToString(shader_type)] += source; - - delete [] source; -} - - -static inline void -dumpProgram(JSONWriter &json, GLint program) -{ - GLint attached_shaders = 0; - glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders); - if (!attached_shaders) { - return; - } - - ShaderMap shaderMap; - - GLuint *shaders = new GLuint[attached_shaders]; - GLsizei count = 0; - glGetAttachedShaders(program, attached_shaders, &count, shaders); - std::sort(shaders, shaders + count); - for (GLsizei i = 0; i < count; ++ i) { - getShaderSource(shaderMap, shaders[i]); - } - delete [] shaders; - - for (ShaderMap::const_iterator it = shaderMap.begin(); it != shaderMap.end(); ++it) { - json.beginMember(it->first); - json.writeString(it->second); - json.endMember(); - } -} - - -static inline void -dumpProgramObj(JSONWriter &json, GLhandleARB programObj) -{ - GLint attached_shaders = 0; - glGetObjectParameterivARB(programObj, GL_OBJECT_ATTACHED_OBJECTS_ARB, &attached_shaders); - if (!attached_shaders) { - return; - } - - ShaderMap shaderMap; - - GLhandleARB *shaderObjs = new GLhandleARB[attached_shaders]; - GLsizei count = 0; - glGetAttachedObjectsARB(programObj, attached_shaders, &count, shaderObjs); - std::sort(shaderObjs, shaderObjs + count); - for (GLsizei i = 0; i < count; ++ i) { - getShaderObjSource(shaderMap, shaderObjs[i]); - } - delete [] shaderObjs; - - for (ShaderMap::const_iterator it = shaderMap.begin(); it != shaderMap.end(); ++it) { - json.beginMember(it->first); - json.writeString(it->second); - json.endMember(); - } -} - -/* - * When fetching the uniform name of an array we usually get name[0] - * so we need to cut the trailing "[0]" in order to properly construct - * array names later. Otherwise we endup with stuff like - * uniformArray[0][0], - * uniformArray[0][1], - * instead of - * uniformArray[0], - * uniformArray[1]. - */ -static std::string -resolveUniformName(const GLchar *name, GLint size) -{ - std::string qualifiedName(name); - if (size > 1) { - std::string::size_type nameLength = qualifiedName.length(); - static const char * const arrayStart = "[0]"; - static const int arrayStartLen = 3; - if (qualifiedName.rfind(arrayStart) == (nameLength - arrayStartLen)) { - qualifiedName = qualifiedName.substr(0, nameLength - 3); - } - } - return qualifiedName; -} - -static void -dumpUniform(JSONWriter &json, GLint program, GLint size, GLenum type, const GLchar *name) { - GLenum elemType; - GLint numElems; - __gl_uniform_size(type, elemType, numElems); - if (elemType == GL_NONE) { - return; - } - - GLfloat fvalues[4*4]; - GLdouble dvalues[4*4]; - GLint ivalues[4*4]; - GLuint uivalues[4*4]; - - GLint i, j; - - std::string qualifiedName = resolveUniformName(name, size); - - for (i = 0; i < size; ++i) { - std::stringstream ss; - ss << qualifiedName; - - if (size > 1) { - ss << '[' << i << ']'; - } - - std::string elemName = ss.str(); - - json.beginMember(elemName); - - GLint location = glGetUniformLocation(program, elemName.c_str()); - - if (numElems > 1) { - json.beginArray(); - } - - switch (elemType) { - case GL_FLOAT: - glGetUniformfv(program, location, fvalues); - for (j = 0; j < numElems; ++j) { - json.writeNumber(fvalues[j]); - } - break; - case GL_DOUBLE: - glGetUniformdv(program, location, dvalues); - for (j = 0; j < numElems; ++j) { - json.writeNumber(dvalues[j]); - } - break; - case GL_INT: - glGetUniformiv(program, location, ivalues); - for (j = 0; j < numElems; ++j) { - json.writeNumber(ivalues[j]); - } - break; - case GL_UNSIGNED_INT: - glGetUniformuiv(program, location, uivalues); - for (j = 0; j < numElems; ++j) { - json.writeNumber(uivalues[j]); - } - break; - case GL_BOOL: - glGetUniformiv(program, location, ivalues); - for (j = 0; j < numElems; ++j) { - json.writeBool(ivalues[j]); - } - break; - default: - assert(0); - break; - } - - if (numElems > 1) { - json.endArray(); - } - - json.endMember(); - } -} - - -static void -dumpUniformARB(JSONWriter &json, GLhandleARB programObj, GLint size, GLenum type, const GLchar *name) { - - GLenum elemType; - GLint numElems; - __gl_uniform_size(type, elemType, numElems); - if (elemType == GL_NONE) { - return; - } - - GLfloat fvalues[4*4]; - GLint ivalues[4*4]; - - GLint i, j; - - std::string qualifiedName = resolveUniformName(name, size); - - for (i = 0; i < size; ++i) { - std::stringstream ss; - ss << qualifiedName; - - if (size > 1) { - ss << '[' << i << ']'; - } - - std::string elemName = ss.str(); - - json.beginMember(elemName); - - GLint location = glGetUniformLocationARB(programObj, elemName.c_str()); - - if (numElems > 1) { - json.beginArray(); - } - - switch (elemType) { - case GL_DOUBLE: - // glGetUniformdvARB does not exists - case GL_FLOAT: - glGetUniformfvARB(programObj, location, fvalues); - for (j = 0; j < numElems; ++j) { - json.writeNumber(fvalues[j]); - } - break; - case GL_UNSIGNED_INT: - // glGetUniformuivARB does not exists - case GL_INT: - glGetUniformivARB(programObj, location, ivalues); - for (j = 0; j < numElems; ++j) { - json.writeNumber(ivalues[j]); - } - break; - case GL_BOOL: - glGetUniformivARB(programObj, location, ivalues); - for (j = 0; j < numElems; ++j) { - json.writeBool(ivalues[j]); - } - break; - default: - assert(0); - break; - } - - if (numElems > 1) { - json.endArray(); - } - - json.endMember(); - } -} - - -static inline void -dumpProgramUniforms(JSONWriter &json, GLint program) -{ - GLint active_uniforms = 0; - glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &active_uniforms); - if (!active_uniforms) { - return; - } - - GLint active_uniform_max_length = 0; - glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &active_uniform_max_length); - GLchar *name = new GLchar[active_uniform_max_length]; - if (!name) { - return; - } - - for (GLint index = 0; index < active_uniforms; ++index) { - GLsizei length = 0; - GLint size = 0; - GLenum type = GL_NONE; - glGetActiveUniform(program, index, active_uniform_max_length, &length, &size, &type, name); - - dumpUniform(json, program, size, type, name); - } - - delete [] name; -} - - -static inline void -dumpProgramObjUniforms(JSONWriter &json, GLhandleARB programObj) -{ - GLint active_uniforms = 0; - glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &active_uniforms); - if (!active_uniforms) { - return; - } - - GLint active_uniform_max_length = 0; - glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB, &active_uniform_max_length); - GLchar *name = new GLchar[active_uniform_max_length]; - if (!name) { - return; - } - - for (GLint index = 0; index < active_uniforms; ++index) { - GLsizei length = 0; - GLint size = 0; - GLenum type = GL_NONE; - glGetActiveUniformARB(programObj, index, active_uniform_max_length, &length, &size, &type, name); - - dumpUniformARB(json, programObj, size, type, name); - } - - delete [] name; -} - - -static inline void -dumpArbProgram(JSONWriter &json, GLenum target) -{ - if (!glIsEnabled(target)) { - return; - } - - GLint program_length = 0; - glGetProgramivARB(target, GL_PROGRAM_LENGTH_ARB, &program_length); - if (!program_length) { - return; - } - - GLchar *source = new GLchar[program_length + 1]; - source[0] = 0; - glGetProgramStringARB(target, GL_PROGRAM_STRING_ARB, source); - source[program_length] = 0; - - json.beginMember(enumToString(target)); - json.writeString(source); - json.endMember(); - - delete [] source; -} - - -static inline void -dumpArbProgramUniforms(JSONWriter &json, GLenum target, const char *prefix) -{ - if (!glIsEnabled(target)) { - return; - } - - GLint program_parameters = 0; - glGetProgramivARB(target, GL_PROGRAM_PARAMETERS_ARB, &program_parameters); - if (!program_parameters) { - return; - } - - GLint max_program_local_parameters = 0; - glGetProgramivARB(target, GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, &max_program_local_parameters); - for (GLint index = 0; index < max_program_local_parameters; ++index) { - GLdouble params[4] = {0, 0, 0, 0}; - glGetProgramLocalParameterdvARB(target, index, params); - - if (!params[0] && !params[1] && !params[2] && !params[3]) { - continue; - } - - char name[256]; - snprintf(name, sizeof name, "%sprogram.local[%i]", prefix, index); - - json.beginMember(name); - json.beginArray(); - json.writeNumber(params[0]); - json.writeNumber(params[1]); - json.writeNumber(params[2]); - json.writeNumber(params[3]); - json.endArray(); - json.endMember(); - } - - GLint max_program_env_parameters = 0; - glGetProgramivARB(target, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &max_program_env_parameters); - for (GLint index = 0; index < max_program_env_parameters; ++index) { - GLdouble params[4] = {0, 0, 0, 0}; - glGetProgramEnvParameterdvARB(target, index, params); - - if (!params[0] && !params[1] && !params[2] && !params[3]) { - continue; - } - - char name[256]; - snprintf(name, sizeof name, "%sprogram.env[%i]", prefix, index); - - json.beginMember(name); - json.beginArray(); - json.writeNumber(params[0]); - json.writeNumber(params[1]); - json.writeNumber(params[2]); - json.writeNumber(params[3]); - json.endArray(); - json.endMember(); - } -} - - -static inline void -dumpShadersUniforms(JSONWriter &json) -{ - GLint program = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &program); - - GLhandleARB programObj = glGetHandleARB(GL_PROGRAM_OBJECT_ARB); - - json.beginMember("shaders"); - json.beginObject(); - if (program) { - dumpProgram(json, program); - } else if (programObj) { - dumpProgramObj(json, programObj); - } else { - dumpArbProgram(json, GL_FRAGMENT_PROGRAM_ARB); - dumpArbProgram(json, GL_VERTEX_PROGRAM_ARB); - } - json.endObject(); - json.endMember(); // shaders - - json.beginMember("uniforms"); - json.beginObject(); - if (program) { - dumpProgramUniforms(json, program); - } else if (programObj) { - dumpProgramObjUniforms(json, programObj); - } else { - dumpArbProgramUniforms(json, GL_FRAGMENT_PROGRAM_ARB, "fp."); - dumpArbProgramUniforms(json, GL_VERTEX_PROGRAM_ARB, "vp."); - } - json.endObject(); - json.endMember(); // uniforms -} - - static inline void dumpTextureImage(JSONWriter &json, Context &context, GLenum target, GLint level) { diff --git a/glstate_internal.hpp b/glstate_internal.hpp index 0398dec..785ddc2 100644 --- a/glstate_internal.hpp +++ b/glstate_internal.hpp @@ -59,6 +59,8 @@ void dumpEnum(JSONWriter &json, GLenum pname); void dumpParameters(JSONWriter &json, Context &context); +void dumpShadersUniforms(JSONWriter &json); + void dumpCurrentContext(std::ostream &os); diff --git a/glstate_shaders.cpp b/glstate_shaders.cpp new file mode 100644 index 0000000..90e5d0a --- /dev/null +++ b/glstate_shaders.cpp @@ -0,0 +1,529 @@ +/************************************************************************** + * + * Copyright 2011 Jose Fonseca + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + **************************************************************************/ + + +#include + +#include +#include +#include +#include + +#include "json.hpp" +#include "glproc.hpp" +#include "glsize.hpp" +#include "glstate.hpp" +#include "glstate_internal.hpp" + + +namespace glstate { + + +// Mapping from shader type to shader source, used to accumulated the sources +// of different shaders with same type. +typedef std::map ShaderMap; + + +static void +getShaderSource(ShaderMap &shaderMap, GLuint shader) +{ + if (!shader) { + return; + } + + GLint shader_type = 0; + glGetShaderiv(shader, GL_SHADER_TYPE, &shader_type); + if (!shader_type) { + return; + } + + GLint source_length = 0; + glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &source_length); + if (!source_length) { + return; + } + + GLchar *source = new GLchar[source_length]; + GLsizei length = 0; + source[0] = 0; + glGetShaderSource(shader, source_length, &length, source); + + shaderMap[enumToString(shader_type)] += source; + + delete [] source; +} + + +static void +getShaderObjSource(ShaderMap &shaderMap, GLhandleARB shaderObj) +{ + if (!shaderObj) { + return; + } + + GLint object_type = 0; + glGetObjectParameterivARB(shaderObj, GL_OBJECT_TYPE_ARB, &object_type); + if (object_type != GL_SHADER_OBJECT_ARB) { + return; + } + + GLint shader_type = 0; + glGetObjectParameterivARB(shaderObj, GL_OBJECT_SUBTYPE_ARB, &shader_type); + if (!shader_type) { + return; + } + + GLint source_length = 0; + glGetObjectParameterivARB(shaderObj, GL_OBJECT_SHADER_SOURCE_LENGTH_ARB, &source_length); + if (!source_length) { + return; + } + + GLcharARB *source = new GLcharARB[source_length]; + GLsizei length = 0; + source[0] = 0; + glGetShaderSource(shaderObj, source_length, &length, source); + + shaderMap[enumToString(shader_type)] += source; + + delete [] source; +} + + +static inline void +dumpProgram(JSONWriter &json, GLint program) +{ + GLint attached_shaders = 0; + glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders); + if (!attached_shaders) { + return; + } + + ShaderMap shaderMap; + + GLuint *shaders = new GLuint[attached_shaders]; + GLsizei count = 0; + glGetAttachedShaders(program, attached_shaders, &count, shaders); + std::sort(shaders, shaders + count); + for (GLsizei i = 0; i < count; ++ i) { + getShaderSource(shaderMap, shaders[i]); + } + delete [] shaders; + + for (ShaderMap::const_iterator it = shaderMap.begin(); it != shaderMap.end(); ++it) { + json.beginMember(it->first); + json.writeString(it->second); + json.endMember(); + } +} + + +static inline void +dumpProgramObj(JSONWriter &json, GLhandleARB programObj) +{ + GLint attached_shaders = 0; + glGetObjectParameterivARB(programObj, GL_OBJECT_ATTACHED_OBJECTS_ARB, &attached_shaders); + if (!attached_shaders) { + return; + } + + ShaderMap shaderMap; + + GLhandleARB *shaderObjs = new GLhandleARB[attached_shaders]; + GLsizei count = 0; + glGetAttachedObjectsARB(programObj, attached_shaders, &count, shaderObjs); + std::sort(shaderObjs, shaderObjs + count); + for (GLsizei i = 0; i < count; ++ i) { + getShaderObjSource(shaderMap, shaderObjs[i]); + } + delete [] shaderObjs; + + for (ShaderMap::const_iterator it = shaderMap.begin(); it != shaderMap.end(); ++it) { + json.beginMember(it->first); + json.writeString(it->second); + json.endMember(); + } +} + +/* + * When fetching the uniform name of an array we usually get name[0] + * so we need to cut the trailing "[0]" in order to properly construct + * array names later. Otherwise we endup with stuff like + * uniformArray[0][0], + * uniformArray[0][1], + * instead of + * uniformArray[0], + * uniformArray[1]. + */ +static std::string +resolveUniformName(const GLchar *name, GLint size) +{ + std::string qualifiedName(name); + if (size > 1) { + std::string::size_type nameLength = qualifiedName.length(); + static const char * const arrayStart = "[0]"; + static const int arrayStartLen = 3; + if (qualifiedName.rfind(arrayStart) == (nameLength - arrayStartLen)) { + qualifiedName = qualifiedName.substr(0, nameLength - 3); + } + } + return qualifiedName; +} + +static void +dumpUniform(JSONWriter &json, GLint program, GLint size, GLenum type, const GLchar *name) { + GLenum elemType; + GLint numElems; + __gl_uniform_size(type, elemType, numElems); + if (elemType == GL_NONE) { + return; + } + + GLfloat fvalues[4*4]; + GLdouble dvalues[4*4]; + GLint ivalues[4*4]; + GLuint uivalues[4*4]; + + GLint i, j; + + std::string qualifiedName = resolveUniformName(name, size); + + for (i = 0; i < size; ++i) { + std::stringstream ss; + ss << qualifiedName; + + if (size > 1) { + ss << '[' << i << ']'; + } + + std::string elemName = ss.str(); + + json.beginMember(elemName); + + GLint location = glGetUniformLocation(program, elemName.c_str()); + + if (numElems > 1) { + json.beginArray(); + } + + switch (elemType) { + case GL_FLOAT: + glGetUniformfv(program, location, fvalues); + for (j = 0; j < numElems; ++j) { + json.writeNumber(fvalues[j]); + } + break; + case GL_DOUBLE: + glGetUniformdv(program, location, dvalues); + for (j = 0; j < numElems; ++j) { + json.writeNumber(dvalues[j]); + } + break; + case GL_INT: + glGetUniformiv(program, location, ivalues); + for (j = 0; j < numElems; ++j) { + json.writeNumber(ivalues[j]); + } + break; + case GL_UNSIGNED_INT: + glGetUniformuiv(program, location, uivalues); + for (j = 0; j < numElems; ++j) { + json.writeNumber(uivalues[j]); + } + break; + case GL_BOOL: + glGetUniformiv(program, location, ivalues); + for (j = 0; j < numElems; ++j) { + json.writeBool(ivalues[j]); + } + break; + default: + assert(0); + break; + } + + if (numElems > 1) { + json.endArray(); + } + + json.endMember(); + } +} + + +static void +dumpUniformARB(JSONWriter &json, GLhandleARB programObj, GLint size, GLenum type, const GLchar *name) { + + GLenum elemType; + GLint numElems; + __gl_uniform_size(type, elemType, numElems); + if (elemType == GL_NONE) { + return; + } + + GLfloat fvalues[4*4]; + GLint ivalues[4*4]; + + GLint i, j; + + std::string qualifiedName = resolveUniformName(name, size); + + for (i = 0; i < size; ++i) { + std::stringstream ss; + ss << qualifiedName; + + if (size > 1) { + ss << '[' << i << ']'; + } + + std::string elemName = ss.str(); + + json.beginMember(elemName); + + GLint location = glGetUniformLocationARB(programObj, elemName.c_str()); + + if (numElems > 1) { + json.beginArray(); + } + + switch (elemType) { + case GL_DOUBLE: + // glGetUniformdvARB does not exists + case GL_FLOAT: + glGetUniformfvARB(programObj, location, fvalues); + for (j = 0; j < numElems; ++j) { + json.writeNumber(fvalues[j]); + } + break; + case GL_UNSIGNED_INT: + // glGetUniformuivARB does not exists + case GL_INT: + glGetUniformivARB(programObj, location, ivalues); + for (j = 0; j < numElems; ++j) { + json.writeNumber(ivalues[j]); + } + break; + case GL_BOOL: + glGetUniformivARB(programObj, location, ivalues); + for (j = 0; j < numElems; ++j) { + json.writeBool(ivalues[j]); + } + break; + default: + assert(0); + break; + } + + if (numElems > 1) { + json.endArray(); + } + + json.endMember(); + } +} + + +static inline void +dumpProgramUniforms(JSONWriter &json, GLint program) +{ + GLint active_uniforms = 0; + glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &active_uniforms); + if (!active_uniforms) { + return; + } + + GLint active_uniform_max_length = 0; + glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &active_uniform_max_length); + GLchar *name = new GLchar[active_uniform_max_length]; + if (!name) { + return; + } + + for (GLint index = 0; index < active_uniforms; ++index) { + GLsizei length = 0; + GLint size = 0; + GLenum type = GL_NONE; + glGetActiveUniform(program, index, active_uniform_max_length, &length, &size, &type, name); + + dumpUniform(json, program, size, type, name); + } + + delete [] name; +} + + +static inline void +dumpProgramObjUniforms(JSONWriter &json, GLhandleARB programObj) +{ + GLint active_uniforms = 0; + glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &active_uniforms); + if (!active_uniforms) { + return; + } + + GLint active_uniform_max_length = 0; + glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB, &active_uniform_max_length); + GLchar *name = new GLchar[active_uniform_max_length]; + if (!name) { + return; + } + + for (GLint index = 0; index < active_uniforms; ++index) { + GLsizei length = 0; + GLint size = 0; + GLenum type = GL_NONE; + glGetActiveUniformARB(programObj, index, active_uniform_max_length, &length, &size, &type, name); + + dumpUniformARB(json, programObj, size, type, name); + } + + delete [] name; +} + + +static inline void +dumpArbProgram(JSONWriter &json, GLenum target) +{ + if (!glIsEnabled(target)) { + return; + } + + GLint program_length = 0; + glGetProgramivARB(target, GL_PROGRAM_LENGTH_ARB, &program_length); + if (!program_length) { + return; + } + + GLchar *source = new GLchar[program_length + 1]; + source[0] = 0; + glGetProgramStringARB(target, GL_PROGRAM_STRING_ARB, source); + source[program_length] = 0; + + json.beginMember(enumToString(target)); + json.writeString(source); + json.endMember(); + + delete [] source; +} + + +static inline void +dumpArbProgramUniforms(JSONWriter &json, GLenum target, const char *prefix) +{ + if (!glIsEnabled(target)) { + return; + } + + GLint program_parameters = 0; + glGetProgramivARB(target, GL_PROGRAM_PARAMETERS_ARB, &program_parameters); + if (!program_parameters) { + return; + } + + GLint max_program_local_parameters = 0; + glGetProgramivARB(target, GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, &max_program_local_parameters); + for (GLint index = 0; index < max_program_local_parameters; ++index) { + GLdouble params[4] = {0, 0, 0, 0}; + glGetProgramLocalParameterdvARB(target, index, params); + + if (!params[0] && !params[1] && !params[2] && !params[3]) { + continue; + } + + char name[256]; + snprintf(name, sizeof name, "%sprogram.local[%i]", prefix, index); + + json.beginMember(name); + json.beginArray(); + json.writeNumber(params[0]); + json.writeNumber(params[1]); + json.writeNumber(params[2]); + json.writeNumber(params[3]); + json.endArray(); + json.endMember(); + } + + GLint max_program_env_parameters = 0; + glGetProgramivARB(target, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &max_program_env_parameters); + for (GLint index = 0; index < max_program_env_parameters; ++index) { + GLdouble params[4] = {0, 0, 0, 0}; + glGetProgramEnvParameterdvARB(target, index, params); + + if (!params[0] && !params[1] && !params[2] && !params[3]) { + continue; + } + + char name[256]; + snprintf(name, sizeof name, "%sprogram.env[%i]", prefix, index); + + json.beginMember(name); + json.beginArray(); + json.writeNumber(params[0]); + json.writeNumber(params[1]); + json.writeNumber(params[2]); + json.writeNumber(params[3]); + json.endArray(); + json.endMember(); + } +} + + +void +dumpShadersUniforms(JSONWriter &json) +{ + GLint program = 0; + glGetIntegerv(GL_CURRENT_PROGRAM, &program); + + GLhandleARB programObj = glGetHandleARB(GL_PROGRAM_OBJECT_ARB); + + json.beginMember("shaders"); + json.beginObject(); + if (program) { + dumpProgram(json, program); + } else if (programObj) { + dumpProgramObj(json, programObj); + } else { + dumpArbProgram(json, GL_FRAGMENT_PROGRAM_ARB); + dumpArbProgram(json, GL_VERTEX_PROGRAM_ARB); + } + json.endObject(); + json.endMember(); // shaders + + json.beginMember("uniforms"); + json.beginObject(); + if (program) { + dumpProgramUniforms(json, program); + } else if (programObj) { + dumpProgramObjUniforms(json, programObj); + } else { + dumpArbProgramUniforms(json, GL_FRAGMENT_PROGRAM_ARB, "fp."); + dumpArbProgramUniforms(json, GL_VERTEX_PROGRAM_ARB, "vp."); + } + json.endObject(); + json.endMember(); // uniforms +} + + +} /* namespace glstate */ -- 2.43.0