#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)
{
{
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")) {
{
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")) {
{
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")) {
{
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")) {
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;
}
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) {