static bool _loadUniform(struct Configuration* description, size_t pass, struct mGLES2Uniform* uniform) { unsigned passId; if (sscanf(uniform->name, "pass.%u.uniform.", &passId) < 1 || passId != pass) { return false; } const char* type = ConfigurationGetValue(description, uniform->name, "type"); if (!type) { return false; } if (!strcmp(type, "float")) { uniform->type = GL_FLOAT; } else if (!strcmp(type, "float2")) { uniform->type = GL_FLOAT_VEC2; } else if (!strcmp(type, "float3")) { uniform->type = GL_FLOAT_VEC3; } else if (!strcmp(type, "float4")) { uniform->type = GL_FLOAT_VEC4; } else if (!strcmp(type, "float2x2")) { uniform->type = GL_FLOAT_MAT2; } else if (!strcmp(type, "float3x3")) { uniform->type = GL_FLOAT_MAT3; } else if (!strcmp(type, "float4x4")) { uniform->type = GL_FLOAT_MAT4; } else if (!strcmp(type, "int")) { uniform->type = GL_INT; } else if (!strcmp(type, "int2")) { uniform->type = GL_INT_VEC2; } else if (!strcmp(type, "int3")) { uniform->type = GL_INT_VEC3; } else if (!strcmp(type, "int4")) { uniform->type = GL_INT_VEC4; } else if (!strcmp(type, "bool")) { uniform->type = GL_BOOL; } else if (!strcmp(type, "bool2")) { uniform->type = GL_BOOL_VEC2; } else if (!strcmp(type, "bool3")) { uniform->type = GL_BOOL_VEC3; } else if (!strcmp(type, "bool4")) { uniform->type = GL_BOOL_VEC4; } else { return false; } _loadValue(description, uniform->name, uniform->type, "default", &uniform->value); _loadValue(description, uniform->name, uniform->type, "min", &uniform->min); _loadValue(description, uniform->name, uniform->type, "max", &uniform->max); const char* readable = ConfigurationGetValue(description, uniform->name, "readableName"); if (readable) { uniform->readableName = strdup(readable); } else { uniform->readableName = 0; } uniform->name = strdup(strstr(uniform->name, "uniform.") + strlen("uniform.")); return true; }
static const char* _lookupValue(const struct GBAConfig* config, const char* key) { const char* value; if (config->port) { value = ConfigurationGetValue(&config->configTable, config->port, key); if (value) { return value; } } value = ConfigurationGetValue(&config->configTable, 0, key); if (value) { return value; } if (config->port) { value = ConfigurationGetValue(&config->defaultsTable, config->port, key); if (value) { return value; } } return ConfigurationGetValue(&config->defaultsTable, 0, key); }
static bool _lookupFloatValue(const struct Configuration* config, const char* section, const char* key, float* out) { const char* charValue = ConfigurationGetValue(config, section, key); if (!charValue) { return false; } char* end; float value = strtof_u(charValue, &end); if (*end) { return false; } *out = value; return true; }
static bool _lookupIntValue(const struct Configuration* config, const char* section, const char* key, int* out) { const char* charValue = ConfigurationGetValue(config, section, key); if (!charValue) { return false; } char* end; unsigned long value = strtol(charValue, &end, 10); if (*end) { return false; } *out = value; return true; }
static bool _lookupBoolValue(const struct Configuration* config, const char* section, const char* key, GLboolean* out) { const char* charValue = ConfigurationGetValue(config, section, key); if (!charValue) { return false; } if (!strcmp(charValue, "true")) { *out = GL_TRUE; return true; } if (!strcmp(charValue, "false")) { *out = GL_FALSE; return true; } char* end; unsigned long value = strtol(charValue, &end, 10); if (*end) { return false; } *out = value; return true; }
bool mGLES2ShaderLoad(struct VideoShader* shader, struct VDir* dir) { struct VFile* manifest = dir->openFile(dir, "manifest.ini", O_RDONLY); if (!manifest) { return false; } bool success = false; struct Configuration description; ConfigurationInit(&description); if (ConfigurationReadVFile(&description, manifest)) { int inShaders; success = _lookupIntValue(&description, "shader", "passes", &inShaders); if (inShaders > MAX_PASSES || inShaders < 1) { success = false; } if (success) { struct mGLES2Shader* shaderBlock = malloc(sizeof(struct mGLES2Shader) * inShaders); int n; for (n = 0; n < inShaders; ++n) { char passName[12]; snprintf(passName, sizeof(passName), "pass.%u", n); const char* fs = ConfigurationGetValue(&description, passName, "fragmentShader"); const char* vs = ConfigurationGetValue(&description, passName, "vertexShader"); if (fs && (fs[0] == '.' || strstr(fs, PATH_SEP))) { success = false; break; } if (vs && (vs[0] == '.' || strstr(vs, PATH_SEP))) { success = false; break; } char* fssrc = 0; char* vssrc = 0; if (fs) { struct VFile* fsf = dir->openFile(dir, fs, O_RDONLY); if (!fsf) { success = false; break; } fssrc = malloc(fsf->size(fsf) + 1); fssrc[fsf->size(fsf)] = '\0'; fsf->read(fsf, fssrc, fsf->size(fsf)); fsf->close(fsf); } if (vs) { struct VFile* vsf = dir->openFile(dir, vs, O_RDONLY); if (!vsf) { success = false; free(fssrc); break; } vssrc = malloc(vsf->size(vsf) + 1); vssrc[vsf->size(vsf)] = '\0'; vsf->read(vsf, vssrc, vsf->size(vsf)); vsf->close(vsf); } int width = 0; int height = 0; int scaling = 0; _lookupIntValue(&description, passName, "width", &width); _lookupIntValue(&description, passName, "height", &height); _lookupIntValue(&description, passName, "integerScaling", &scaling); struct mGLES2UniformList uniformVector; mGLES2UniformListInit(&uniformVector, 0); ConfigurationEnumerateSections(&description, _uniformHandler, &uniformVector); size_t u; for (u = 0; u < mGLES2UniformListSize(&uniformVector); ++u) { struct mGLES2Uniform* uniform = mGLES2UniformListGetPointer(&uniformVector, u); if (!_loadUniform(&description, n, uniform)) { mGLES2UniformListShift(&uniformVector, u, 1); --u; } } u = mGLES2UniformListSize(&uniformVector); struct mGLES2Uniform* uniformBlock = malloc(sizeof(*uniformBlock) * u); memcpy(uniformBlock, mGLES2UniformListGetPointer(&uniformVector, 0), sizeof(*uniformBlock) * u); mGLES2UniformListDeinit(&uniformVector); mGLES2ShaderInit(&shaderBlock[n], vssrc, fssrc, width, height, scaling, uniformBlock, u); int b = 0; _lookupIntValue(&description, passName, "blend", &b); if (b) { shaderBlock[n].blend = b; } b = 0; _lookupIntValue(&description, passName, "filter", &b); if (b) { shaderBlock[n].filter = b; } free(fssrc); free(vssrc); } if (success) { shader->nPasses = inShaders; shader->passes = shaderBlock; shader->name = ConfigurationGetValue(&description, "shader", "name"); if (shader->name) { shader->name = strdup(shader->name); } shader->author = ConfigurationGetValue(&description, "shader", "author"); if (shader->author) { shader->author = strdup(shader->author); } shader->description = ConfigurationGetValue(&description, "shader", "description"); if (shader->description) { shader->description = strdup(shader->description); } } else { inShaders = n; for (n = 0; n < inShaders; ++n) { mGLES2ShaderDeinit(&shaderBlock[n]); } } } } manifest->close(manifest); ConfigurationDeinit(&description); return success; }