From 07eb5e7a7a1098297bc49f822bb78c293980c02e Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Thu, 5 Sep 2013 14:00:19 -0700 Subject: [PATCH] Implement all the extension-related options of glenv 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 | 23 +++--- glwrap.c | 213 +++++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 206 insertions(+), 30 deletions(-) diff --git a/glenv.c b/glenv.c index 76f6693..d5ec2e8 100644 --- 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. */ diff --git a/glwrap.c b/glwrap.c index 9c9f309..a229e4b 100644 --- a/glwrap.c +++ b/glwrap.c @@ -28,29 +28,181 @@ #include #include -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) { -- 2.43.0