X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=glwrap.c;h=64fb95c2cee9c7a5d3e8d49f963b8fd06d94852d;hb=91d728328c25fbc6bbecb90949b293cd71295ff7;hp=faf6a81ef3285ec0814e34d99e87bebdc2a6b854;hpb=206fae5fae316c85de55e636c1f7d04b8cdc9193;p=glenv diff --git a/glwrap.c b/glwrap.c index faf6a81..64fb95c 100644 --- a/glwrap.c +++ b/glwrap.c @@ -28,13 +28,181 @@ #include #include +typedef GLubyte * (get_string_type_t) (GLenum); + +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) +{ + 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; + } + + /* 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) { @@ -62,100 +230,79 @@ glenv_minor_version (void) return atoi (decimal + 1); } -void -glGetDoublev (GLenum pname, GLdouble *params) +/* Read the user-specified glenv value for 'name'. + * + * Returns true if a value is available and is written to 'value'. + */ +static int +glenv_get_integer (GLenum name, int *value) { - switch (pname) { + switch (name) { case GL_NUM_EXTENSIONS: - *params = glenv_num_extensions(); + if (glenv_gl_extensions) { + *value = glenv_num_gl_extensions; + return 1; + } break; case GL_MAJOR_VERSION: if (getenv ("GLENV_GL_VERSION")) { - *params = glenv_major_version(); - return; + *value = glenv_major_version(); + return 1; } break; case GL_MINOR_VERSION: if (getenv ("GLENV_GL_VERSION")) { - *params = glenv_minor_version(); - return; + *value = glenv_minor_version(); + return 1; } break; } - GLAZE_DEFER (glGetDoublev, pname, params); + return 0; +} + +void +glGetDoublev (GLenum pname, GLdouble *params) +{ + int value; + + if (glenv_get_integer (pname, &value)) + *params = value; + else + GLAZE_DEFER (glGetDoublev, pname, params); } void glGetFloatv (GLenum pname, GLfloat *params) { - switch (pname) { - case GL_NUM_EXTENSIONS: - *params = glenv_num_extensions(); - break; - case GL_MAJOR_VERSION: - if (getenv ("GLENV_GL_VERSION")) { - *params = glenv_major_version(); - return; - } - break; - case GL_MINOR_VERSION: - if (getenv ("GLENV_GL_VERSION")) { - *params = glenv_minor_version(); - return; - } - break; - } + int value; - GLAZE_DEFER (glGetFloatv, pname, params); + if (glenv_get_integer (pname, &value)) + *params = value; + else + GLAZE_DEFER (glGetFloatv, pname, params); } void glGetIntegerv (GLenum pname, GLint *params) { - switch (pname) { - case GL_NUM_EXTENSIONS: - *params = glenv_num_extensions(); - break; - case GL_MAJOR_VERSION: - if (getenv ("GLENV_GL_VERSION")) { - *params = glenv_major_version(); - return; - } - break; - case GL_MINOR_VERSION: - if (getenv ("GLENV_GL_VERSION")) { - *params = glenv_minor_version(); - return; - } - break; - } + int value; - GLAZE_DEFER (glGetIntegerv, pname, params); + if (glenv_get_integer (pname, &value)) + *params = value; + else + GLAZE_DEFER (glGetIntegerv, pname, params); } void glGetInteger64v (GLenum pname, GLint64 * params) { - switch (pname) { - case GL_NUM_EXTENSIONS: - *params = glenv_num_extensions(); - break; - case GL_MAJOR_VERSION: - if (getenv ("GLENV_GL_VERSION")) { - *params = glenv_major_version(); - return; - } - break; - case GL_MINOR_VERSION: - if (getenv ("GLENV_GL_VERSION")) { - *params = glenv_minor_version(); - return; - } - break; - } + int value; - GLAZE_DEFER (glGetInteger64v, pname, params); + if (glenv_get_integer (pname, &value)) + *params = value; + else + GLAZE_DEFER (glGetInteger64v, pname, params); } const GLubyte * @@ -185,9 +332,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; } @@ -203,7 +349,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) {