]> git.cworth.org Git - glenv/commitdiff
Implement all the extension-related options of glenv
authorCarl Worth <cworth@cworth.org>
Thu, 5 Sep 2013 21:00:19 +0000 (14:00 -0700)
committerCarl Worth <cworth@cworth.org>
Thu, 5 Sep 2013 21:00:19 +0000 (14:00 -0700)
We use the first_gl_callback mechanism of Glaze in order to read the
original list of available extensions and then modify it according to
the user-requested options.

glenv.c
glwrap.c

diff --git a/glenv.c b/glenv.c
index 76f669334eba354d270fafd752576fcee0704587..d5ec2e8735457a7bc80a6fcd7671f875cd23886b 100644 (file)
--- a/glenv.c
+++ b/glenv.c
@@ -41,10 +41,11 @@ typedef struct options {
 static void
 export_options (options_t *options)
 {
-       if (options->query) {
-               glaze_set_first_gl_call_callback ("glenv_query");
-       }
-
+       if (options->query)
+               setenv ("GLENV_QUERY", "1", 1);
+       else
+               unsetenv ("GLENV_QUERY");
+               
        if (options->vendor)
                setenv ("GLENV_GL_VENDOR", options->vendor, 1);
        else
@@ -67,19 +68,19 @@ export_options (options_t *options)
                unsetenv ("GLENV_GL_SHADING_LANGUAGE_VERSION");
 
        if (options->extensions)
-               setenv ("GLENV_EXTENSIONS", options->extensions, 1);
+               setenv ("GLENV_GL_EXTENSIONS", options->extensions, 1);
        else
-               unsetenv ("GLENV_EXTENSIONS");
+               unsetenv ("GLENV_GL_EXTENSIONS");
 
        if (options->extensions_whitelist)
-               setenv ("GLENV_EXTENSIONS_WHITELIST", options->extensions_whitelist, 1);
+               setenv ("GLENV_GL_EXTENSIONS_WHITELIST", options->extensions_whitelist, 1);
        else
-               unsetenv ("GLENV_EXTENSIONS_WHITELIST");
+               unsetenv ("GLENV_GL_EXTENSIONS_WHITELIST");
 
        if (options->extensions_blacklist)
-               setenv ("GLENV_EXTENSIONS_BLACKLIST", options->extensions_blacklist, 1);
+               setenv ("GLENV_GL_EXTENSIONS_BLACKLIST", options->extensions_blacklist, 1);
        else
-               unsetenv ("GLENV_EXTENSIONS_BLACKLIST");
+               unsetenv ("GLENV_GL_EXTENSIONS_BLACKLIST");
 }
 
 static void
@@ -215,6 +216,8 @@ main (int argc, char *argv[])
 
        export_options (&options);
 
+       glaze_set_first_gl_call_callback ("glenv_first_gl_call");
+
        glaze_execute (argc - optind, &argv[optind], "libglenv.so");
 
        /* If glaze_execute returns then something went wrong. */
index 9c9f3093b304078438d2e212a5c52d84473513e9..a229e4bcd28b0a64432554c3f3479ff7ca4ad9f1 100644 (file)
--- a/glwrap.c
+++ b/glwrap.c
 #include <stdlib.h>
 #include <string.h>
 
-void glenv_query (void);
-
 typedef GLubyte * (get_string_type_t) (GLenum);
 
-void
-glenv_query (void)
+static char *glenv_gl_extensions;
+static char **glenv_gl_extensions_array;
+static unsigned int glenv_num_gl_extensions;
+
+static char *
+xstrdup (const char *str)
+{
+       char *ret;
+
+       ret = strdup (str);
+       if (ret == NULL) {
+               fprintf (stderr, "Out of memory.\n");
+               exit (1);
+       }
+
+       return ret;
+}
+
+static int
+extension_list_count (const char *list)
+{
+       int count = 0;
+
+       if (list == NULL)
+               return 0;
+
+       while (list && *list) {
+               /* Skip consecutive spaces before and between extensions */
+               while (*list == ' ')
+                       list++;
+               if (*list)
+                       count++;
+               /* Skip to next space */
+               list = strchr (list, ' ');
+       }
+
+       return count;
+}
+
+static void
+extension_list_append (char **list, const char *extension)
 {
-       printf ("--vendor=\"%s\"\n", glGetString (GL_VENDOR));
-       printf ("--renderer=\"%s\"\n", glGetString (GL_RENDERER));
-       printf ("--version=\"%s\"\n", glGetString (GL_VERSION));
-       printf ("--shading-language-version=\"%s\"\n", glGetString (GL_SHADING_LANGUAGE_VERSION));
-       printf ("--extensions=\"%s\"\n", glGetString (GL_EXTENSIONS));
+       char *new_list;
+
+       /* Nothing to do if extension is empty. */
+       if (extension == NULL || strlen (extension) == 0)
+               return;
+
+       /* If initial list is empty, just copy extension */
+       if (*list == NULL) {
+               *list = xstrdup (extension);
+               return;
+       }
 
-       exit (0);
+       /* Append one space, then extension onto current list. */
+       new_list = malloc (strlen (*list) + 1 + strlen (extension) + 1);
+       if (new_list == NULL) {
+               fprintf (stderr, "Out of memory.\n");
+               exit (1);
+       }
+
+       strcpy (new_list, *list);
+       strcat (new_list, " ");
+       strcat (new_list, extension);
+
+       free (*list);
+       *list = new_list;
 }
 
 static int
-glenv_num_extensions (void)
+extension_list_contains (const char *list, const char *extension)
 {
-       /* FIXME */
+       const char *match;
+       int length = strlen (extension);
+
+       while (1) {
+               match = strstr (list, extension);
+               if (match == NULL)
+                       return 0;
+               if (match[length] == ' ' || match[length] == '\0')
+                       return 1;
+               list = match + length;
+       }
+
        return 0;
 }
 
+/* When the first GL call is made, (that is, after the OpenGL context
+ * has been initialized with glX or some other system), then we can
+ * finally implement the "glenv --query" option if it was specified.
+ *
+ * Similarly, at this point, we can read the original extensions
+ * string from the OpenGL environment and modify it according to the
+ * blacklist or whitelist that the user may have specified.
+ */
+void glenv_first_gl_call (void);
+
+void
+glenv_first_gl_call (void)
+{
+       get_string_type_t *get_string = glaze_lookup ("glGetString");
+       char *orig_extensions;
+       const char *extension;
+
+       orig_extensions = xstrdup ((char *) get_string (GL_EXTENSIONS));
+
+       if (getenv ("GLENV_GL_EXTENSIONS"))
+       {
+               glenv_gl_extensions = getenv ("GLENV_GL_EXTENSIONS");
+       }
+       else if (getenv ("GLENV_GL_EXTENSIONS_BLACKLIST"))
+       {
+               const char *blacklist = getenv ("GLENV_GL_EXTENSIONS_BLACKLIST");
+
+               for (extension = strtok (orig_extensions, " ");
+                    extension;
+                    extension = strtok (NULL, " "))
+               {
+                       if (! extension_list_contains (blacklist, extension))
+                               extension_list_append (&glenv_gl_extensions, extension);
+               }
+       }
+       else if (getenv ("GLENV_GL_EXTENSIONS_WHITELIST"))
+       {
+               const char *whitelist = getenv ("GLENV_GL_EXTENSIONS_WHITELIST");
+
+               for (extension = strtok (orig_extensions, " ");
+                    extension;
+                    extension = strtok (NULL, " "))
+               {
+                       if (extension_list_contains (whitelist, extension))
+                               extension_list_append (&glenv_gl_extensions, extension);
+               }
+       }
+
+       free (orig_extensions);
+
+       if (glenv_gl_extensions) {
+               int i;
+               char *extensions_copy;
+
+               glenv_num_gl_extensions = extension_list_count (glenv_gl_extensions);
+
+               glenv_gl_extensions_array = malloc (sizeof (char *) * glenv_num_gl_extensions);
+
+               extensions_copy = xstrdup (glenv_gl_extensions);
+
+               for (i = 0, extension = strtok (extensions_copy, " ");
+                    extension;
+                    i++, extension = strtok (NULL, " "))
+               {
+                       glenv_gl_extensions_array[i] = xstrdup (extension);
+               }
+
+               free (extensions_copy);
+       }
+
+       /* We deliberately call glGetString directly here rather than
+        * use the get_string function pointer to the underlying
+        * glGetString function. That's because we want --query to
+        * reflect any modifications the user made with other
+        * options. */
+       if (getenv ("GLENV_QUERY")) {
+               printf ("--vendor=\"%s\"\n", glGetString (GL_VENDOR));
+               printf ("--renderer=\"%s\"\n", glGetString (GL_RENDERER));
+               printf ("--version=\"%s\"\n", glGetString (GL_VERSION));
+               printf ("--shading-language-version=\"%s\"\n", glGetString (GL_SHADING_LANGUAGE_VERSION));
+               printf ("--extensions=\"%s\"\n", glGetString (GL_EXTENSIONS));
+
+               exit (0);
+       }
+}
+
 static int
 glenv_major_version (void)
 {
@@ -83,7 +235,10 @@ glGetDoublev (GLenum pname, GLdouble *params)
 {
        switch (pname) {
        case GL_NUM_EXTENSIONS:
-               *params = glenv_num_extensions();
+               if (glenv_gl_extensions) {
+                       *params = glenv_num_gl_extensions;
+                       return;
+               }
                break;
        case GL_MAJOR_VERSION:
                if (getenv ("GLENV_GL_VERSION")) {
@@ -107,7 +262,10 @@ glGetFloatv (GLenum pname, GLfloat *params)
 {
        switch (pname) {
        case GL_NUM_EXTENSIONS:
-               *params = glenv_num_extensions();
+               if (glenv_gl_extensions) {
+                       *params = glenv_num_gl_extensions;
+                       return;
+               }
                break;
        case GL_MAJOR_VERSION:
                if (getenv ("GLENV_GL_VERSION")) {
@@ -131,7 +289,10 @@ glGetIntegerv (GLenum pname, GLint *params)
 {
        switch (pname) {
        case GL_NUM_EXTENSIONS:
-               *params = glenv_num_extensions();
+               if (glenv_gl_extensions) {
+                       *params = glenv_num_gl_extensions;
+                       return;
+               }
                break;
        case GL_MAJOR_VERSION:
                if (getenv ("GLENV_GL_VERSION")) {
@@ -155,7 +316,10 @@ glGetInteger64v (GLenum pname, GLint64 * params)
 {
        switch (pname) {
        case GL_NUM_EXTENSIONS:
-               *params = glenv_num_extensions();
+               if (glenv_gl_extensions) {
+                       *params = glenv_num_gl_extensions;
+                       return;
+               }
                break;
        case GL_MAJOR_VERSION:
                if (getenv ("GLENV_GL_VERSION")) {
@@ -201,9 +365,8 @@ glGetString (GLenum name)
                        return ret;
                break;
        case GL_EXTENSIONS:
-               ret = (GLubyte *) getenv ("GLENV_GL_EXTENSIONS");
-               if (ret)
-                       return ret;
+               if (glenv_gl_extensions)
+                       return (GLubyte *) glenv_gl_extensions;
                break;
        }
 
@@ -219,7 +382,17 @@ glGetStringi (GLenum name, GLuint index)
 
        switch (name) {
        case GL_EXTENSIONS:
-               /* FIXME */
+               if (glenv_gl_extensions) {
+                       if (index < glenv_num_gl_extensions) {
+                               return (GLubyte *) glenv_gl_extensions_array[index];
+                       } else {
+                               /* Force index to an value that will
+                                * guarantee an INVALID_VALUE value
+                                * from the underlying glGetStringi.
+                                */
+                               index = (GLuint) -1;
+                       }
+               }
                break;
        case GL_SHADING_LANGUAGE_VERSION:
                if (index == 0) {