static char *stripspace(char *s);
static void concat_values(struct cfgopt *opt);
+/* linked list of valid value filters */
+static struct cfgopt *valid_vals;
+
+/* adds a new filter set of valid values for the key "key" */
+void gliar_value_set(const char *key, char **valid, int vcount)
+{
+ int i;
+ struct cfgopt *node;
+
+ if(!(node = malloc(sizeof *node))) {
+ return;
+ }
+ if(!(node->key = malloc(strlen(key) + 1))) {
+ free(node);
+ return;
+ }
+ strcpy(node->key, key);
+
+ if(!(node->str_val = malloc(vcount * sizeof *node->str_val))) {
+ free(node->key);
+ free(node);
+ return;
+ }
+ for(i=0; i<vcount; i++) {
+ if(!(node->str_val[i] = malloc(strlen(valid[i]) + 1))) {
+ for(; i>=0; i--) {
+ free(node->str_val[i]);
+ free(node->key);
+ free(node);
+ return;
+ }
+ }
+ strcpy(node->str_val[i], valid[i]);
+ }
+
+ node->str_count = vcount;
+
+ node->next = valid_vals;
+ valid_vals = node;
+}
+
struct cfgopt *gliar_load_cfg(const char *fname)
{
FILE *fp;
char buf[512];
struct cfgopt *optlist = 0;
struct cfgopt *opt = 0;
+ const struct cfgopt *filter;
if(!(fp = fopen(fname, "r"))) {
return 0;
}
if(*line == '[') {
+ /* found a new key */
char *end = strrchr(line, ']');
if(!end) {
fprintf(stderr, "invalid config %s: %s\n", fname, line);
concat_values(opt);
}
+ /* find the valid values for this particular key (if any) */
+ filter = gliar_find_opt(valid_vals, line);
+
if((opt = malloc(sizeof *opt))) {
if((opt->key = malloc(strlen(line) + 1))) {
strcpy(opt->key, line);
}
}
} else {
- int new_sz = opt->str_count + 1;
+ /* found a value for the current key (opt->key) */
+ int i, num, new_sz = opt->str_count + 1;
char **tmp;
-
char *end;
- int num = strtol(line, &end, 10);
+ if(filter) {
+ for(i=0; i<filter->str_count; i++) {
+ if(strcmp(line, filter->str_val[i]) == 0) {
+ break;
+ }
+ }
+
+ if(i == filter->str_count) {
+ /* the string is not in the valid list, ignore it */
+ fprintf(stderr, "GLIAR: extension %s not supported, ignoring\n", line);
+ continue;
+ }
+ }
+
+ num = strtol(line, &end, 10);
if(!*end) {
- opt->num_val = line;
+ opt->num_val = num;
opt->type = GLIAR_NUMBER;
}
int i;
int sz = opt->str_count - 1;
+ if(!opt->str_count) {
+ opt->conc_vals = 0;
+ return;
+ }
+
for(i=0; i<opt->str_count; i++) {
sz += strlen(opt->str_val[i]);
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
+#include <ctype.h>
#include <unistd.h>
#include <dlfcn.h>
#include <pwd.h>
#include <GL/gl.h>
#include "cfg.h"
+#ifndef GL_NUM_SHADING_LANGUAGE_VERSIONS
+#define GL_NUM_SHADING_LANGUAGE_VERSIONS 0x82E9
+#endif
+
+static int init_valid_extensions(void);
+
static int done_init;
static const GLubyte* (*gl_get_string)(GLenum);
-/*static const GLubyte* (*gl_get_stringi)(GLenum, GLuint);
+static const GLubyte* (*gl_get_stringi)(GLenum, GLuint);
+static const void* (*gl_get_integerv)(GLenum, GLint*);
-static const void* (*gl_get_booleanv)(GLenum, GLboolean*);
+/*static const void* (*gl_get_booleanv)(GLenum, GLboolean*);
static const void* (*gl_get_doublev)(GLenum, GLdouble*);
static const void* (*gl_get_floatv)(GLenum, GLfloat*);
-static const void* (*gl_get_integerv)(GLenum, GLint*);
static const void* (*gl_get_integer64v)(GLenum, GLint64*);
static const void* (*gl_get_booleani_v)(GLenum, GLuint, GLboolean*);
static struct cfgopt *cfglist;
+
static int init(void)
{
if(done_init) {
return 0;
}
+ gl_get_string = dlsym(RTLD_NEXT, "glGetString");
+ gl_get_stringi = dlsym(RTLD_NEXT, "glGetStringi");
+ gl_get_integerv = dlsym(RTLD_NEXT, "glGetIntegerv");
+
+ /*gl_get_booleanv = dlsym(RTLD_NEXT, "glGetBooleanv");
+ gl_get_doublev = dlsym(RTLD_NEXT, "glGetDoublev");
+ gl_get_floatv = dlsym(RTLD_NEXT, "glGetFloatv");
+ gl_get_integer64v = dlsym(RTLD_NEXT, "glGetInteger64v");
+
+ gl_get_booleani_v = dlsym(RTLD_NEXT, "glGetBooleani_v");
+ gl_get_doublei_v = dlsym(RTLD_NEXT, "glGetDoublei_v");
+ gl_get_floati_v = dlsym(RTLD_NEXT, "glGetFloati_v");
+ gl_get_integeri_v = dlsym(RTLD_NEXT, "glGetIntegeri_v");
+ gl_get_integer64i_v = dlsym(RTLD_NEXT, "glGetInteger64i_v");*/
+
+ if(init_valid_extensions() == -1) {
+ fprintf(stderr, "GLIAR: failed to initialize the valid extension list, might end up with unavailable extensions!\n");
+ }
+
if(!(cfglist = gliar_load_cfg("gliar.conf"))) {
struct passwd *pw;
char *homedir, *path;
}
}
- gl_get_string = dlsym(RTLD_NEXT, "glGetString");
-/* gl_get_stringi = dlsym(RTLD_NEXT, "glGetStringi");
+ done_init = 1;
+ return 0;
+}
- gl_get_booleanv = dlsym(RTLD_NEXT, "glGetBooleanv");
- gl_get_doublev = dlsym(RTLD_NEXT, "glGetDoublev");
- gl_get_floatv = dlsym(RTLD_NEXT, "glGetFloatv");
- gl_get_integerv = dlsym(RTLD_NEXT, "glGetIntegerv");
- gl_get_integer64v = dlsym(RTLD_NEXT, "glGetInteger64v");
+static int init_valid_extensions(void)
+{
+ int i, num_ext, prev_space = 0;
+ const char *gl_ext_str;
+ char *ext_str, *tok, *ptr, **ext_table;
- gl_get_booleani_v = dlsym(RTLD_NEXT, "glGetBooleani_v");
- gl_get_doublei_v = dlsym(RTLD_NEXT, "glGetDoublei_v");
- gl_get_floati_v = dlsym(RTLD_NEXT, "glGetFloati_v");
- gl_get_integeri_v = dlsym(RTLD_NEXT, "glGetIntegeri_v");
- gl_get_integer64i_v = dlsym(RTLD_NEXT, "glGetInteger64i_v");*/
+ /* initialize the list of valid extensions */
+ if(!(gl_ext_str = (const char*)gl_get_string(GL_EXTENSIONS))) {
+ return -1;
+ }
- done_init = 1;
+ if(!(ext_str = malloc(strlen(gl_ext_str) + 1))) {
+ return -1;
+ }
+ strcpy(ext_str, gl_ext_str);
+
+ /* count the extensions */
+ num_ext = 0;
+ ptr = ext_str;
+ while(*ptr) {
+ if(isspace(*ptr) && prev_space == 0) {
+ prev_space = 1;
+ num_ext++;
+ } else {
+ prev_space = 0;
+ }
+ ptr++;
+ }
+
+ /* allocate extension table */
+ if(!(ext_table = malloc(num_ext * sizeof *ext_table))) {
+ free(ext_str);
+ return -1;
+ }
+
+ /* setup the ext_table slots to point to the start of each substring (extension) */
+ for(i=0; i<num_ext; i++) {
+ if(!(tok = strtok(i == 0 ? ext_str : 0, " \t\v\n\r"))) {
+ fprintf(stderr, "DEBUG: strtok returned 0 at token %d\n", i);
+ num_ext = i;
+ }
+ ext_table[i] = tok;
+ }
+
+ gliar_value_set("extensions", ext_table, num_ext);
+
+ free(ext_table);
+ free(ext_str);
return 0;
}
return gl_get_string(name);
}
+
+const GLubyte *glGetStringi(GLenum name, GLuint index)
+{
+ char *key;
+ const struct cfgopt *option;
+
+ init();
+
+ switch(name) {
+ case GL_EXTENSIONS:
+ key = "extensions";
+ break;
+
+ case GL_SHADING_LANGUAGE_VERSION:
+ key = "sl version";
+ break;
+
+ default:
+ key = 0;
+ }
+
+ if(key && (option = gliar_find_opt(cfglist, key))) {
+ return (const GLubyte*)option->str_val[index];
+ }
+
+ return gl_get_stringi(name, index);
+}
+
+void glGetIntegerv(GLenum name, GLint *val)
+{
+ char *key;
+ const struct cfgopt *option;
+
+ init();
+
+ switch(name) {
+ case GL_NUM_EXTENSIONS:
+ if(1) {
+ key = "extensions";
+ } else {
+ case GL_NUM_SHADING_LANGUAGE_VERSIONS:
+ key = "sl version";
+ }
+ if(key && (option = gliar_find_opt(cfglist, key))) {
+ *val = option->str_count;
+ return;
+ }
+ break;
+
+ case GL_MAX_TEXTURE_UNITS:
+ key = "max texture units";
+ break;
+
+ case GL_MAX_TEXTURE_SIZE:
+ key = "max texture size";
+ break;
+
+ default:
+ key = 0;
+ }
+
+ if(key && (option = gliar_find_opt(cfglist, key)) && option->type == GLIAR_NUMBER) {
+ *val = option->num_val;
+ return;
+ }
+
+ gl_get_integerv(name, val);
+}