added support for OpenGL extensions, vendor, version
authorEleni Maria Stea <elene.mst@gmail.com>
Mon, 11 Feb 2013 13:46:49 +0000 (15:46 +0200)
committerEleni Maria Stea <elene.mst@gmail.com>
Mon, 11 Feb 2013 13:46:49 +0000 (15:46 +0200)
INSTALL [new file with mode: 0644]
Makefile [new file with mode: 0644]
README [new file with mode: 0644]
gliar.conf [new file with mode: 0644]
src/cfg.c [new file with mode: 0644]
src/cfg.h [new file with mode: 0644]
src/gliar.c [new file with mode: 0644]

diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..ce94ac5
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,12 @@
+src = $(wildcard src/*.c)
+obj = $(src:.c=.o)
+lib_so = libgliar.so
+
+CFLAGS = -pedantic -Wall -g -fPIC -D_GNU_SOURCE
+
+$(lib_so): $(obj)
+       $(CC) -o $@ -shared $(obj) $(LDFLAGS)
+
+.PHONY: clean
+clean:
+       rm -f $(obj) $(lib_so)
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..e12ff82
--- /dev/null
+++ b/README
@@ -0,0 +1,57 @@
+# libgliar - a library that can fake the OpenGL context info returned by
+# the glGet OpenGL calls
+#
+# authored by: Eleni Maria Stea <elene.mst@gmail.com>
+
+For instructions on how to build the code, see the INSTALL file.
+
+Usage:
+------
+LD_PRELOAD=./libgliar.so <opengl_executable>
+
+The library will read the gliar.conf file in the user's library directory or
+the .gliar.conf file in the user's home directory.
+
+Example gliar.conf:
+-------------------
+[key1]
+value1
+value2
+.
+.
+.
+valueN
+
+[key2]
+value1
+.
+.
+.
+valueN
+
+[keyN]
+value1
+.
+.
+.
+valueN
+
+Currently supported keys:
+"vendor" (the vendor string), "extensions" (the extensions string), "version" (the opengl version string)
+
+Example:
+---------
+gliar.conf:
+[vendor]
+Mutant Stargoat
+
+[extensions]
+GL_MSG_hikiko_ext
+GL_MSG_test
+
+$ LD_PRELOAD=./libgliar glxinfo | grep -A2 "OpenGL extensions"
+OpenGL extensions:
+    GL_MSG_hikiko_ext, GL_MSG_test
+
+
+
diff --git a/gliar.conf b/gliar.conf
new file mode 100644 (file)
index 0000000..1f9c5b5
--- /dev/null
@@ -0,0 +1,6 @@
+[vendor]
+Mutant Stargoat
+
+[extensions]
+GL_MSG_hikiko_ext
+GL_MSG_test
diff --git a/src/cfg.c b/src/cfg.c
new file mode 100644 (file)
index 0000000..4f317d2
--- /dev/null
+++ b/src/cfg.c
@@ -0,0 +1,110 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "cfg.h"
+
+static char *stripspace(char *s);
+
+
+struct cfgopt *gliar_load_cfg(const char *fname)
+{
+       FILE *fp;
+       char buf[512];
+       struct cfgopt *optlist = 0;
+       struct cfgopt *opt = 0;
+
+       if(!(fp = fopen(fname, "r"))) {
+               return 0;
+       }
+
+       while(fgets(buf, sizeof buf, fp)) {
+               char *line = stripspace(buf);
+
+               if(!*line || *line == '#') {
+                       continue;
+               }
+
+               if(*line == '[') {
+                       char *end = strrchr(line, ']');
+                       if(!end) {
+                               fprintf(stderr, "invalid config %s: %s\n", fname, line);
+                               continue;
+                       }
+                       line++;
+                       *end = 0;
+
+                       if(opt) {
+                               opt->next = optlist;
+                               optlist = opt;
+                       }
+
+                       if((opt = malloc(sizeof *opt))) {
+                               if((opt->key = malloc(strlen(line) + 1))) {
+                                       strcpy(opt->key, line);
+                                       opt->val = 0;
+                               } else {
+                                       free(opt);
+                                       opt = 0;
+                               }
+                       }
+               } else {
+                       char *tmp;
+                       int prev_len = opt->val ? strlen(opt->val) : 0;
+
+                       if(opt && (tmp = realloc(opt->val, prev_len + strlen(line) + 2))) {
+                               opt->val = tmp;
+                               if(prev_len) {
+                                       strcat(opt->val, " ");
+                                       strcat(opt->val, line);
+                               } else {
+                                       strcpy(opt->val, line);
+                               }
+                       }
+               }
+       }
+
+       if(opt) {
+               opt->next = optlist;
+               optlist = opt;
+       }
+
+       fclose(fp);
+       return optlist;
+}
+
+const char *gliar_find_opt(struct cfgopt *list, const char *name)
+{
+       if(!list || !name) {
+               return 0;
+       }
+
+       while(list) {
+               if(strcmp(list->key, name) == 0) {
+                       return list->val;
+               }
+               list = list->next;
+       }
+       return 0;
+}
+
+void gliar_print_opt(struct cfgopt *list)
+{
+       printf("OPTIONS\n");
+       while(list) {
+               printf("\"%s\" -> \"%s\"\n", list->key, list->val);
+               list = list->next;
+       }
+}
+
+static char *stripspace(char *s)
+{
+       char *end = s + strlen(s) - 1;
+
+       while(isspace(*s)) s++;
+
+       while(isspace(*end)) {
+               *end-- = 0;
+       }
+       return s;
+}
diff --git a/src/cfg.h b/src/cfg.h
new file mode 100644 (file)
index 0000000..1f8eee2
--- /dev/null
+++ b/src/cfg.h
@@ -0,0 +1,17 @@
+#ifndef CFG_H_
+#define CFG_H_
+
+struct cfgopt {
+       char *key;
+       char *val;
+
+       struct cfgopt *next;
+};
+
+struct cfgopt *gliar_load_cfg(const char *fname);
+
+const char *gliar_find_opt(struct cfgopt *list, const char *name);
+
+void gliar_print_opt(struct cfgopt *list);
+
+#endif /* CFG_H_ */
diff --git a/src/gliar.c b/src/gliar.c
new file mode 100644 (file)
index 0000000..38470f5
--- /dev/null
@@ -0,0 +1,72 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <dlfcn.h>
+#include <pwd.h>
+#include <GL/gl.h>
+#include "cfg.h"
+
+static int done_init;
+static const GLubyte* (*gl_get_string)(GLenum);
+static struct cfgopt *cfglist;
+
+static int init(void)
+{
+       if(done_init) {
+               return 0;
+       }
+
+       if(!(cfglist = gliar_load_cfg("gliar.conf"))) {
+               struct passwd *pw;
+               char *homedir, *path;
+
+               if((pw = getpwuid(getuid()))) {
+                       homedir = pw->pw_dir;
+               } else {
+                       homedir = getenv("HOME");
+               }
+
+               if(homedir) {
+                       path = alloca(strlen(homedir) + strlen(".gliar.conf") + 2);
+                       sprintf(path, "%s/.gliar.conf", homedir);
+
+                       cfglist = gliar_load_cfg(path);
+               }
+       }
+
+       gl_get_string = dlsym(RTLD_NEXT, "glGetString");
+
+       done_init = 1;
+       return 0;
+}
+
+const GLubyte *glGetString(GLenum name)
+{
+       const char *key, *value;
+
+       init();
+
+       switch(name) {
+       case GL_VENDOR:
+               key = "vendor";
+               break;
+
+       case GL_VERSION:
+               key = "version";
+               break;
+
+       case GL_EXTENSIONS:
+               key = "extensions";
+               break;
+
+       default:
+               key = 0;
+       }
+
+       if(key && (value = gliar_find_opt(cfglist, key))) {
+               return value;
+       }
+
+       return gl_get_string(name);
+}