]> git.cworth.org Git - glenv/commitdiff
Initial import of glenv utility
authorCarl Worth <cworth@cworth.org>
Sat, 31 Aug 2013 01:06:52 +0000 (18:06 -0700)
committerCarl Worth <cworth@cworth.org>
Sat, 31 Aug 2013 01:08:02 +0000 (18:08 -0700)
This uses Glaze to alter the OpenGL environment provided to a program.

The query and extension-related options are not yet fully implemented.

.gitignore [new file with mode: 0644]
Makefile [new file with mode: 0644]
configure [new file with mode: 0755]
glenv.c [new file with mode: 0644]
glwrap.c [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..e144d6c
--- /dev/null
@@ -0,0 +1,3 @@
+glenv
+libglenv.so
+Makefile.config
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..50e2194
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,37 @@
+all:
+
+# Get settings from the output of configure by running it to generate
+# Makefile.config if it doesn't exist yet.
+
+# If Makefile.config doesn't exist, then srcdir won't be
+# set. Conditionally set it (assuming a plain srcdir build) so that
+# the rule to generate Makefile.config can actually work.
+srcdir ?= .
+
+include Makefile.config
+Makefile.config: $(srcdir)/configure
+ifeq ($(configure_options),)
+       @echo ""
+       @echo "Note: Calling ./configure with no command-line arguments. This is often fine,"
+       @echo "      but if you want to specify any arguments (such as an alternate prefix"
+       @echo "      into which to install), call ./configure explicitly and then make again."
+       @echo "      See \"./configure --help\" for more details."
+       @echo ""
+endif
+       $(srcdir)/configure $(configure_options)
+
+TARGETS = glenv libglenv.so
+
+all: $(TARGETS)
+
+GLENV_CFLAGS = $(CFLAGS) $(WARN_CFLAGS) $(GLAZE_CFLAGS)
+GLENV_LDFLAGS = $(GLAZE_LDFLAGS)
+
+glenv: glenv.c
+       $(CC) $(GLENV_CFLAGS) $(GLENV_LDFLAGS) -o $@ $<
+
+libglenv.so: glwrap.c
+       $(CC) $(GLENV_CFLAGS) $(GLENV_LDFLAGS) -fPIC -shared -Wl,-Bsymbolic -o $@ $<
+
+clean:
+       rm -f $(TARGETS)
diff --git a/configure b/configure
new file mode 100755 (executable)
index 0000000..7d7657c
--- /dev/null
+++ b/configure
@@ -0,0 +1,321 @@
+#! /bin/sh
+
+PROJECT=glenv
+PROJECT_BLURB="run an OpenGL program in a modified environment"
+
+srcdir=$(dirname "$0")
+
+# For a non-srcdir configure invocation (such as ../configure), create
+# the directory structure and copy Makefiles.
+if [ "$srcdir" != "." ]; then
+
+    for dir in . $(grep "^subdirs *=" "$srcdir"/Makefile | sed -e "s/subdirs *= *//"); do
+       mkdir -p "$dir"
+       cp "$srcdir"/"$dir"/Makefile.local "$dir"
+       cp "$srcdir"/"$dir"/Makefile "$dir"
+    done
+fi
+
+# Set several defaults (optionally specified by the user in
+# environment variables)
+CC=${CC:-gcc}
+CFLAGS=${CFLAGS:--O2}
+LDFLAGS=${LDFLAGS:-}
+
+# Set the defaults for values the user can specify with command-line
+# options.
+PREFIX=/usr/local
+
+usage ()
+{
+    cat <<EOF
+Usage: ./configure [options]...
+
+This script configures ${PROJECT} to build on your system.
+
+It verifies that dependencies are available, determines flags needed
+to compile and link against various required libraries, and identifies
+whether various system functions can be used or if locally-provided
+replacements will be built instead.
+
+Finally, it allows you to control various aspects of the build and
+installation process.
+
+First, some common variables can specified via environment variables:
+
+       CC              The C compiler to use
+       CFLAGS          Flags to pass to the C compiler
+       LDFLAGS         Flags to pass when linking
+
+Each of these values can further be controlled by specifying them
+later on the "make" command line.
+
+Additionally, various options can be specified on the configure
+command line.
+
+       --prefix=PREFIX Install files in PREFIX [$PREFIX]
+
+By default, "make install" will install the resulting program to
+$PREFIX/bin, documentation to $PREFIX/man, etc. You can
+specify an installation prefix other than $PREFIX using
+--prefix, for instance:
+
+       ./configure --prefix=\$HOME
+
+Fine tuning of some installation directories is available:
+
+       --bindir=DIR            Install executables to DIR [PREFIX/bin]
+       --libdir=DIR            Install libraries to DIR [PREFIX/lib]
+       --mandir=DIR            Install man pages to DIR [PREFIX/share/man]
+       --sysconfdir=DIR        Read-only single-machine data [PREFIX/etc]
+
+Additional options are accepted for compatibility with other
+configure-script calling conventions, but don't do anything yet:
+
+       --build=<cpu>-<vendor>-<os>     Currently ignored
+       --host=<cpu>-<vendor>-<os>      Currently ignored
+       --infodir=DIR                   Currently ignored
+       --datadir=DIR                   Currently ignored
+       --localstatedir=DIR             Currently ignored
+       --libexecdir=DIR                Currently ignored
+       --disable-maintainer-mode       Currently ignored
+       --disable-dependency-tracking   Currently ignored
+
+EOF
+}
+
+# Parse command-line options
+for option; do
+    if [ "${option}" = '--help' ] ; then
+       usage
+       exit 0
+    elif [ "${option%%=*}" = '--prefix' ] ; then
+       PREFIX="${option#*=}"
+    elif [ "${option%%=*}" = '--bindir' ] ; then
+       BINDIR="${option#*=}"
+    elif [ "${option%%=*}" = '--libdir' ] ; then
+       LIBDIR="${option#*=}"
+    elif [ "${option%%=*}" = '--mandir' ] ; then
+       MANDIR="${option#*=}"
+    elif [ "${option%%=*}" = '--sysconfdir' ] ; then
+       SYSCONFDIR="${option#*=}"
+    elif [ "${option%%=*}" = '--build' ] ; then
+       true
+    elif [ "${option%%=*}" = '--host' ] ; then
+       true
+    elif [ "${option%%=*}" = '--infodir' ] ; then
+       true
+    elif [ "${option%%=*}" = '--datadir' ] ; then
+       true
+    elif [ "${option%%=*}" = '--localstatedir' ] ; then
+       true
+    elif [ "${option%%=*}" = '--libexecdir' ] ; then
+       true
+    elif [ "${option}" = '--disable-maintainer-mode' ] ; then
+       true
+    elif [ "${option}" = '--disable-dependency-tracking' ] ; then
+       true
+    else
+       echo "Unrecognized option: ${option}"
+       echo "See:"
+       echo "  $0 --help"
+       echo ""
+       exit 1
+    fi
+done
+
+printf "Checking for working C compiler (${CC})... "
+printf "int main(void){return 42;}\n" > minimal.c
+if ${CC} -o minimal minimal.c > /dev/null 2>&1
+then
+    printf "Yes.\n"
+else
+    printf "No.\n"
+    cat <<EOF
+
+*** Error: No functioning C compiler found. Either set the CC environment
+to a working C compiler, or else install gcc:
+
+       http://gcc.gnu.org/
+
+You may be able to install gcc with a command such as:
+
+       sudo apt-get install build-essential
+    or:
+       sudo yum install make automake gcc gcc-c++ kernel-devel
+
+EOF
+
+exit 1
+
+fi
+
+WARN_CFLAGS=""
+printf "Checking for available C compiler warning flags:\n"
+for flag in -Wall -Wextra -Wmissing-declarations -Werror=attributes; do
+    if ${CC} $flag -o minimal minimal.c > /dev/null 2>&1
+    then
+       WARN_CFLAGS="${WARN_CFLAGS}${WARN_CFLAGS:+ }${flag}"
+    fi
+done
+printf "\t${WARN_CFLAGS}\n"
+
+rm -f minimal minimal.c
+
+printf "#include <features.h>\nint main(void){return 0;}\n" > arch-minimal.c
+
+printf "Checking for machine-dependent compiler support:\n"
+
+printf "       Compiler can create 32-bit binaries... "
+have_m32=Yes
+if ${CC} -m32 -o arch-minimal arch-minimal.c > /dev/null 2>&1
+then
+    printf "Yes.\n"
+else
+    printf "No.\n"
+    have_m32=No
+fi
+
+printf "       Compiler can create 64-bit binaries... "
+have_m64=Yes
+if ${CC} -m64 -o arch-minimal arch-minimal.c > /dev/null 2>&1
+then
+    printf "Yes.\n"
+else
+    printf "No.\n"
+    have_m64=No
+fi
+
+if [ "$have_m32" = "No" ] || [ "$have_m64" = "No" ]; then
+    cat <<EOF
+
+* Warning: Cannot create both 32 and 64-bit glenv libraries. Glenv will not
+           support applications of the non-native size. Fixing this may be
+           as simple as running a command such as:
+
+               sudo apt-get install gcc-multilib
+EOF
+fi
+
+rm -f arch-minimal arch-minimal.c
+
+errors=0
+
+printf "Checking for pkg-config... "
+if pkg-config --version > /dev/null 2>&1; then
+    printf "Yes.\n"
+else
+    printf "No.\n"
+    cat <<EOF
+
+*** Error: This configure script requires pkg-config to find the
+compilation flags required to link against the various libraries
+needed by ${PROJECT}. The pkg-config program can be obtained from:
+
+       http://www.freedesktop.org/wiki/Software/pkg-config/
+
+Or you may be able install it with a command such as:
+
+       sudo apt-get install pkg-config
+    or:
+       sudo yum install pkgconfig
+
+EOF
+
+exit 1
+
+fi
+
+printf "Checking for glaze... "
+if pkg-config --exists glaze; then
+    printf "Yes.\n"
+    have_glazec=1
+    glaze_cflags=$(pkg-config --cflags glaze)
+    glaze_ldflags=$(pkg-config --libs glaze)
+else
+    printf "No.\n"
+    have_glaze=0
+    errors=$((errors + 1))
+fi
+
+if [ $errors -gt 0 ]; then
+    cat <<EOF
+
+*** Error: The dependencies of ${PROJECT} could not be satisfied. You will
+need to install the following packages before being able to compile
+${PROJECT}:
+
+EOF
+    if [ $have_glaze -eq 0 ]; then
+       echo "  The glaze library"
+       echo "  git://git.cworth.org/git/glaze/"
+       echo
+    fi
+
+    exit 1
+fi
+
+# construct the Makefile.config
+cat > Makefile.config <<EOF
+# This Makefile.config was automatically generated by the ./configure
+# script of ${PROJECT}. If the configure script identified anything
+# incorrectly, then you can edit this file to try to correct things,
+# but be warned that if configure is run again it will destroy your
+# changes, (and this could happen by simply calling "make" if the
+# configure script is updated).
+
+# The top-level directory for the source, (the directory containing
+# the configure script). This may be different than the build
+# directory (the current directory at the time configure was run).
+srcdir = ${srcdir}
+
+configure_options = $@
+
+# We use vpath directives (rather than the VPATH variable) since the
+# VPATH variable matches targets as well as prerequisites, (which is
+# not useful since then a target left-over from a srcdir build would
+# cause a target to not be built in the non-srcdir build).
+vpath % \$(srcdir)
+
+# The C compiler to use
+CC = ${CC}
+
+# Default FLAGS for C compiler (can be overridden by user such as "make CFLAGS=-g")
+CFLAGS = ${CFLAGS}
+
+# Default FLAGS for the linker (can be overridden by user such as "make LDFLAGS=-znow")
+LDFLAGS = ${LDFLAGS}
+
+# Flags to enable warnings when using the C compiler
+WARN_CFLAGS = ${WARN_CFLAGS}
+
+# The prefix to which ${PROJECT} should be installed
+PREFIX = ${PREFIX}
+
+# The directory to which executables should be installed
+BINDIR = ${BINDIR:-\$(PREFIX)/bin}
+
+# The directory to which libraries should be installed
+LIBDIR = ${LIBDIR:-\$(PREFIX)/lib}
+
+# The directory to which headers should be installed
+INCLUDEDIR = ${INCLUDEDIR:-\$(PREFIX)/include}
+
+# Whether compiler can create 32 or 64-bit binaries
+COMPILER_SUPPORTS_32 = ${have_m32}
+COMPILER_SUPPORTS_64 = ${have_m64}
+
+# Flags needed to compile and link against Glaze
+GLAZE_CFLAGS = ${glaze_cflags}
+GLAZE_LDFLAGS = ${glaze_ldflags}
+
+EOF
+
+cat <<EOF
+
+You may now run the following commands to compile and install ${PROJECT}:
+
+       make
+       sudo make install
+
+EOF
diff --git a/glenv.c b/glenv.c
new file mode 100644 (file)
index 0000000..824b8b8
--- /dev/null
+++ b/glenv.c
@@ -0,0 +1,203 @@
+/* Copyright © 2013, Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <limits.h>
+#include <getopt.h>
+
+#include <glaze.h>
+
+typedef struct options {
+       bool query;
+       char *vendor;
+       char *renderer;
+       char *version;
+       char *shading_language_version;
+       char *extensions;
+       char *extensions_whitelist;
+       char *extensions_blacklist;
+} options_t;
+
+static void
+export_options (options_t *options)
+{
+       if (options->query)
+               setenv ("GLENV_QUERY", "1", 1);
+       else
+               unsetenv ("GLENV_QUERY");
+
+       if (options->vendor)
+               setenv ("GLENV_GL_VENDOR", options->vendor, 1);
+       else
+               unsetenv ("GLENV_GL_VENDOR");
+
+       if (options->renderer)
+               setenv ("GLENV_GL_RENDERER", options->renderer, 1);
+       else
+               unsetenv ("GLENV_GL_RENDERER");
+
+       if (options->version)
+               setenv ("GLENV_GL_VERSION", options->version, 1);
+       else
+               unsetenv ("GLENV_GL_VERSION");
+
+       if (options->shading_language_version)
+               setenv ("GLENV_GL_SHADING_LANGUAGE_VERSION",
+                       options->shading_language_version, 1);
+       else
+               unsetenv ("GLENV_GL_SHADING_LANGUAGE_VERSION");
+
+       if (options->extensions)
+               setenv ("GLENV_EXTENSIONS", options->extensions, 1);
+       else
+               unsetenv ("GLENV_EXTENSIONS");
+
+       if (options->extensions_whitelist)
+               setenv ("GLENV_EXTENSIONS_WHITELIST", options->extensions_whitelist, 1);
+       else
+               unsetenv ("GLENV_EXTENSIONS_WHITELIST");
+
+       if (options->extensions_blacklist)
+               setenv ("GLENV_EXTENSIONS_BLACKLIST", options->extensions_blacklist, 1);
+       else
+               unsetenv ("GLENV_EXTENSIONS_BLACKLIST");
+}
+
+static void
+usage (void)
+{
+       printf ("Usage: glenv [OPTIONS...] <program> [program args...]\n"
+               "\n"
+               "Execute <program> with alternate OpenGL environment.\n"
+               "\n"
+               "Options:\n"
+               "       -h, --help                      Show this help message.\n"
+               "       -q, --query                     Query and report current environment\n"
+               "                                       then terminate program.\n"
+               "       --vendor=STR                    Set GL_VENDOR to STR.\n"
+               "       --renderer=STR                  Set GL_RENDERER to STR.\n"
+               "       --version=STR                   Set GL_VERSION to STR.\n"
+               "       --shading-language-version=STR  Set GL_SHADING_LANGUAGE_VERSION to STR.\n"
+               "       --extensions=STR                Set GL_EXTENSIONS to STR.\n"
+               "       --extensions-whitelist=STR      Remove from GL_EXTENSIONS all names\n"
+               "                                       not appearing in STR (space-separated).\n"
+               "       --extensions-blacklist=STR      Remove from GL_EXTENSIONS any names\n"
+               "                                       appearing in STR (space-separated).\n");
+}
+
+enum {
+       VENDOR_OPT = CHAR_MAX + 1,
+       RENDERER_OPT,
+       VERSION_OPT,
+       SHADING_LANGUAGE_VERSION_OPT,
+       EXTENSIONS_OPT,
+       EXTENSIONS_WHITELIST_OPT,
+       EXTENSIONS_BLACKLIST_OPT
+};
+
+int
+main (int argc, char *argv[])
+{
+       int opt;
+       options_t options = {
+               .query = false,
+               .vendor = NULL,
+               .renderer = NULL,
+               .version = NULL,
+               .shading_language_version = NULL,
+               .extensions = NULL,
+               .extensions_whitelist = NULL,
+               .extensions_blacklist = NULL
+       };
+
+       const char *short_options="hq";
+       const struct option long_options[] = {
+               {"help", no_argument, 0, 'h'},
+               {"query", no_argument, 0, 'q'},
+               {"vendor", required_argument, 0, VENDOR_OPT},
+               {"renderer", required_argument, 0, RENDERER_OPT},
+               {"version", required_argument, 0, VERSION_OPT},
+               {"shading-language-version", required_argument, 0, SHADING_LANGUAGE_VERSION_OPT},
+               {"extensions", required_argument, 0, EXTENSIONS_OPT},
+               {"extensions-whitelist", required_argument, 0, EXTENSIONS_WHITELIST_OPT},
+               {"extensions-blacklist", required_argument, 0, EXTENSIONS_BLACKLIST_OPT},
+               {0, 0, 0, 0}
+       };
+
+       while (1)
+       {
+               opt = getopt_long (argc, argv, short_options, long_options, NULL);
+               if (opt == -1)
+                       break;
+
+               switch (opt) {
+               case 'h':
+                       usage ();
+                       return 0;
+               case '?':
+                       exit (1);
+                       break;
+               case 'q':
+                       options.query = true;
+                       break;
+               case VENDOR_OPT:
+                       options.vendor = optarg;
+                       break;
+               case RENDERER_OPT:
+                       options.renderer = optarg;
+                       break;
+               case VERSION_OPT:
+                       options.version = optarg;
+                       break;
+               case SHADING_LANGUAGE_VERSION_OPT:
+                       options.shading_language_version = optarg;
+                       break;
+               case EXTENSIONS_OPT:
+                       options.extensions = optarg;
+                       break;
+               case EXTENSIONS_WHITELIST_OPT:
+                       options.extensions_whitelist = optarg;
+                       break;
+               case EXTENSIONS_BLACKLIST_OPT:
+                       options.extensions_blacklist = optarg;
+                       break;
+               default:
+                       fprintf (stderr, "Internal error: "
+                                "unexpected getopt value: %d\n", opt);
+                       exit (1);
+               }
+       }
+
+       if (optind >= argc) {
+               fprintf (stderr, "Error: No program name provided, "
+                        "see (glenv --help)\n");
+               exit (1);
+       }
+
+       export_options (&options);
+
+       glaze_execute (argc - optind, &argv[optind], "libglenv.so");
+
+       /* If glaze_execute returns then something went wrong. */
+       return 1;
+}
diff --git a/glwrap.c b/glwrap.c
new file mode 100644 (file)
index 0000000..faf6a81
--- /dev/null
+++ b/glwrap.c
@@ -0,0 +1,220 @@
+/* Copyright © 2013, Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#define GL_GLEXT_PROTOTYPES
+#include <GL/gl.h>
+
+#include <glaze.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static int
+glenv_num_extensions (void)
+{
+       /* FIXME */
+       return 0;
+}
+
+static int
+glenv_major_version (void)
+{
+       const char *version = getenv ("GLENV_GL_VERSION");
+       if (version == NULL)
+               return 0;
+
+       return atoi (version);
+}
+
+static int
+glenv_minor_version (void)
+{
+       const char *version = getenv ("GLENV_GL_VERSION");
+       const char *decimal;
+
+       if (version == NULL)
+               return 0;
+
+       decimal = strchr (version, '.');
+
+       if (decimal == NULL)
+               return 0;
+
+       return atoi (decimal + 1);
+}
+
+void
+glGetDoublev (GLenum pname, GLdouble *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;
+       }
+
+       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;
+       }
+
+       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;
+       }
+
+       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;
+       }
+
+       GLAZE_DEFER (glGetInteger64v, pname, params);
+}
+
+const GLubyte *
+glGetString (GLenum name)
+{
+       const GLubyte *ret;
+
+       switch (name) {
+       case GL_VENDOR:
+               ret = (GLubyte *) getenv ("GLENV_GL_VENDOR");
+               if (ret)
+                       return ret;
+               break;
+       case GL_RENDERER:
+               ret = (GLubyte *) getenv ("GLENV_GL_RENDERER");
+               if (ret)
+                       return ret;
+               break;
+       case GL_VERSION:
+               ret = (GLubyte *) getenv ("GLENV_GL_VERSION");
+               if (ret)
+                       return ret;
+               break;
+       case GL_SHADING_LANGUAGE_VERSION:
+               ret = (GLubyte *) getenv ("GLENV_GL_SHADING_LANGUAGE_VERSION");
+               if (ret)
+                       return ret;
+               break;
+       case GL_EXTENSIONS:
+               ret = (GLubyte *) getenv ("GLENV_GL_EXTENSIONS");
+               if (ret)
+                       return ret;
+               break;
+       }
+
+       GLAZE_DEFER_WITH_RETURN (ret, glGetString, name);
+
+       return ret;
+}
+
+const GLubyte *
+glGetStringi (GLenum name, GLuint index)
+{
+       const GLubyte *ret;
+
+       switch (name) {
+       case GL_EXTENSIONS:
+               /* FIXME */
+               break;
+       case GL_SHADING_LANGUAGE_VERSION:
+               if (index == 0) {
+                       ret = (GLubyte *) getenv ("GLENV_GL_SHADING_LANGUAGE_VERSION");
+                       if (ret)
+                               return ret;
+               }
+               break;
+       }
+
+       GLAZE_DEFER_WITH_RETURN (ret, glGetStringi, name, index);
+
+       return ret;
+}