]> git.cworth.org Git - fips/blobdiff - glwrap.c
Allow fips to compile with OpenGL without GLfixed
[fips] / glwrap.c
index 8e8b64d193194aa8ffd7a127e00d59448d8f0a36..4b865f55d7e03c04e094efaa47ec0374a9e26eb7 100644 (file)
--- a/glwrap.c
+++ b/glwrap.c
  * THE SOFTWARE.
  */
 
-#include "fips.h"
-
-#include "glwrap.h"
-
-#include "metrics.h"
+#include "dlwrap.h"
 
 /* The prototypes for some OpenGL functions changed at one point from:
  *
 #define GL_GLEXT_PROTOTYPES
 #include <GL/gl.h>
 
-#include "dlwrap.h"
+#include "fips.h"
+
+#include "glwrap.h"
+
+#include "context.h"
+
+/* The first appearance of the GLfixed datatype in Mesa was with
+ * glext.h of version 20130624. So we'll assume that any older glext.h
+ * cannot have any function accepting a GLfixed parameter. */
+#if GL_GLEXT_VERSION >= 20130624
+#define HAVE_GLFIXED 1
+#endif
+
+/* As of glext.h version 20131008 some types changed.
+ *
+ * I have no idea why some internalFormats changed from GLenum to
+ * GLint while others changed from GLint to GLenum.
+ *
+ * But, in order to compile with either version, we track these.
+ */
+#if GL_GLEXT_VERSION >= 20131008
+#define GLint_or_enum GLenum
+#define GLenum_or_int GLint
+#else
+#define GLint_or_enum GLint
+#define GLenum_or_int GLenum
+#endif
+
+static void *gl_handle;
 
-static int inside_new_list = 0;
+/* Switch metrics operation persistently, (until next SWITCH) */
+#define SWITCH_METRICS_OP(op)                  \
+       context_counter_stop ();                \
+       context_set_current_op (op);            \
+       context_counter_start ();
+
+/* Switch metrics operation temporarily, see RESTORE_METRICS_OP */
+#define SAVE_THEN_SWITCH_METRICS_OP(op)                        \
+       metrics_op_t save = context_get_current_op ();  \
+       SWITCH_METRICS_OP (op);
+
+/* Switch back to metrics operation saved by SAVE_THEN_SWITCH_METRICS_OP */
+#define RESTORE_METRICS_OP(op)                         \
+       SWITCH_METRICS_OP (save);
+
+void
+glwrap_set_gl_handle (void *handle)
+{
+       if (gl_handle == NULL)
+               gl_handle = handle;
+}
 
 void *
 glwrap_lookup (char *name)
 {
-       const char *libgl_filename = "libGL.so.1";
-       static void *libgl_handle = NULL;
+       void *ret;
+
+       /* We don't call dlopen here to find the library in which to
+        * perform a dlsym lookup. That's because the application may
+        * be loading libGL.so or libGLESv2.so for its OpenGL symbols.
+        *
+        * So we instead watch for one of those filenames to go by in
+        * our dlopen wrapper, which will then call
+        * glwrap_set_gl_handle to give us the handle to use here.
+        *
+        * If the application hasn't called dlopen on a "libGL"
+        * library, then presumably the application is linked directly
+        * to an OpenGL implementation. In this case, we can use
+        * RTLD_NEXT to find the symbol.
+        *
+        * But just in case, we also let the user override that by
+        * specifying the FIPS_LIBGL environment variable to the path
+        * of the real libGL.so library that fips should dlopen here.
+        */
+       if (gl_handle == NULL) {
+               const char *path;
+
+               path = getenv ("FIPS_LIBGL");
+               if (! path)
+                       path = getenv ("GLAZE_LIBGL");
+               if (path) {
+                       gl_handle = dlopen (path, RTLD_LAZY);
 
-       if (! libgl_handle) {
-               libgl_handle = dlwrap_real_dlopen (libgl_filename, RTLD_NOW | RTLD_DEEPBIND);
-               if (! libgl_handle) {
-                       fprintf (stderr, "Error: Failed to dlopen %s\n",
-                                libgl_filename);
-                       exit (1);
+                       if (gl_handle == NULL) {
+                               fprintf (stderr, "Failed to dlopen FIPS_LIBGL: "
+                                        "%s\n", path);
+                               exit (1);
+                       }
+               } else {
+                       gl_handle = RTLD_NEXT;
                }
        }
 
-       return dlwrap_real_dlsym (libgl_handle, name);
+       ret = dlwrap_real_dlsym (gl_handle, name);
+
+       if (ret == NULL) {
+               fprintf (stderr, "fips: Error: glwrap_lookup failed to dlsym %s\n",
+                        name);
+               exit (1);
+       }
+
+       return ret;
+}
+
+/* With a program change, we stop the counter, update the
+ * active program, then start the counter up again. */
+void
+glUseProgram (GLuint program)
+{
+       SWITCH_METRICS_OP (METRICS_OP_SHADER + program);
+
+       GLWRAP_DEFER(glUseProgram, program);
+}
+
+void
+glUseProgramObjectARB (GLhandleARB programObj)
+{
+       SWITCH_METRICS_OP (METRICS_OP_SHADER + programObj);
+
+       GLWRAP_DEFER(glUseProgramObjectARB, programObj);
+}
+
+/* METRICS_OP_ACCUM */
+void
+glAccum (GLenum op, GLfloat value)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_ACCUM);
+
+       GLWRAP_DEFER (glAccum, op, value);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glClearAccum (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_ACCUM);
+
+       GLWRAP_DEFER (glClearAccum, red, green, blue, alpha);
+
+       RESTORE_METRICS_OP ();
+}
+
+#if HAVE_GLFIXED
+void
+glClearAccumxOES (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_ACCUM);
+
+       GLWRAP_DEFER (glClearAccumxOES, red, green, blue, alpha);
+
+       RESTORE_METRICS_OP ();
+}
+#endif
+
+/* METRICS_OP_BUFFER_DATA */
+void
+glBufferData (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
+
+       GLWRAP_DEFER (glBufferData, target, size, data, usage);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glNamedBufferDataEXT (GLuint buffer, GLsizeiptr size, const GLvoid *data,
+                     GLenum usage)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
+
+       GLWRAP_DEFER (glNamedBufferDataEXT, buffer, size, data, usage);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size,
+                const GLvoid *data)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
+
+       GLWRAP_DEFER (glBufferSubData, target, offset, size, data);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glNamedBufferSubDataEXT (GLuint buffer, GLintptr offset, GLsizeiptr size,
+                        const GLvoid *data)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
+
+       GLWRAP_DEFER (glNamedBufferSubDataEXT, buffer, offset, size, data);
+
+       RESTORE_METRICS_OP ();
+}
+
+void *
+glMapBuffer (GLenum target, GLenum access)
+{
+       void *ret;
+
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
+
+       GLWRAP_DEFER_WITH_RETURN (ret, glMapBuffer, target, access);
+
+       RESTORE_METRICS_OP ();
+
+       return ret;
+}
+
+void *
+glMapBufferARB (GLenum target, GLenum access)
+{
+       void *ret;
+
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
+
+       GLWRAP_DEFER_WITH_RETURN (ret, glMapBufferARB, target, access);
+
+       RESTORE_METRICS_OP ();
+
+       return ret;
+}
+
+void *
+glMapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length,
+                 GLbitfield access)
+{
+       void *ret;
+
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
+
+       GLWRAP_DEFER_WITH_RETURN (ret, glMapBufferRange, target, offset,
+                                 length, access);
+
+       RESTORE_METRICS_OP ();
+
+       return ret;
+}
+
+GLboolean
+glUnmapBuffer (GLenum target)
+{
+       GLboolean ret;
+
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
+
+       GLWRAP_DEFER_WITH_RETURN (ret, glUnmapBuffer, target);
+
+       RESTORE_METRICS_OP ();
+
+       return ret;
+}
+
+GLboolean
+glUnmapNamedBufferEXT (GLuint buffer)
+{
+       GLboolean ret;
+
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
+
+       GLWRAP_DEFER_WITH_RETURN (ret, glUnmapNamedBufferEXT, buffer);
+
+       RESTORE_METRICS_OP ();
+
+       return ret;
 }
 
-/* Execute a glBeginQuery/glEndQuery pair around an OpenGL call. */
-#define TIMED_DEFER(function,...) do {                                 \
-       if (! inside_new_list) {                                        \
-               unsigned counter;                                       \
-               counter = metrics_add_counter ();                       \
-               glBeginQuery (GL_TIME_ELAPSED, counter);                \
-       }                                                               \
-       GLWRAP_DEFER(function, __VA_ARGS__);                            \
-       if (! inside_new_list) {                                        \
-               glEndQuery (GL_TIME_ELAPSED);                           \
-       }                                                               \
-} while (0);
+GLboolean
+glUnmapBufferARB (GLenum target)
+{
+       GLboolean ret;
+
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
+
+       GLWRAP_DEFER_WITH_RETURN (ret, glUnmapBufferARB, target);
+
+       RESTORE_METRICS_OP ();
+
+       return ret;
+}
 
-/* Thanks to apitrace source code for the list of OpenGL draw calls. */
 void
-glDrawArrays (GLenum mode, GLint first, GLsizei count)
+glFlushMappedBufferRange (GLenum target, GLintptr offset, GLsizeiptr length)
 {
-       TIMED_DEFER (glDrawArrays, mode, first, count);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
+
+       GLWRAP_DEFER (glFlushMappedBufferRange, target, offset, length);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
-glDrawArraysEXT (GLenum mode, GLint first, GLsizei count)
+glFlushMappedBufferRangeAPPLE (GLenum target, GLintptr offset, GLsizeiptr size)
 {
-       TIMED_DEFER (glDrawArraysEXT, mode, first, count);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
+
+       GLWRAP_DEFER (glFlushMappedBufferRangeAPPLE, target, offset, size);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
-glDrawArraysIndirect (GLenum mode, const GLvoid *indirect)
+glFlushMappedNamedBufferRangeEXT (GLuint buffer, GLintptr offset,
+                                 GLsizeiptr length)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
+
+       GLWRAP_DEFER (glFlushMappedNamedBufferRangeEXT, buffer, offset, length);
+
+       RESTORE_METRICS_OP ();
+}
+
+void *
+glMapNamedBufferEXT (GLuint buffer, GLenum access)
+{
+       void *ret;
+
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
+
+       GLWRAP_DEFER_WITH_RETURN (ret, glMapNamedBufferEXT, buffer, access);
+
+       RESTORE_METRICS_OP ();
+
+       return ret;
+}
+
+void *
+glMapNamedBufferRangeEXT (GLuint buffer, GLintptr offset, GLsizeiptr length,
+                         GLbitfield access)
 {
-       TIMED_DEFER (glDrawArraysIndirect, mode, indirect);
+       void *ret;
+
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
+
+       GLWRAP_DEFER_WITH_RETURN (ret, glMapNamedBufferRangeEXT, buffer,
+                                 offset, length, access);
+
+       RESTORE_METRICS_OP ();
+
+       return ret;
 }
 
+/* METRICS_OP_BUFFER_SUB_DATA */
 void
-glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count,
-                      GLsizei primcount)
+glCopyBufferSubData (GLenum readTarget, GLenum writeTarget,
+                    GLintptr readOffset, GLintptr writeOffset,
+                    GLsizeiptr size)
 {
-       TIMED_DEFER (glDrawArraysInstanced, mode, first, count, primcount);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BUFFER_SUB_DATA);
+
+       GLWRAP_DEFER (glCopyBufferSubData, readTarget, writeTarget,
+                     readOffset, writeOffset, size);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
-glDrawArraysInstancedARB (GLenum mode, GLint first, GLsizei count,
-                         GLsizei primcount)
+glNamedCopyBufferSubDataEXT (GLuint readBuffer, GLuint writeBuffer,
+                            GLintptr readOffset, GLintptr writeOffset,
+                            GLsizeiptr size)
 {
-       TIMED_DEFER (glDrawArraysInstancedARB, mode, first, count, primcount);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BUFFER_SUB_DATA);
+
+       GLWRAP_DEFER (glNamedCopyBufferSubDataEXT, readBuffer,
+                     writeBuffer, readOffset, writeOffset, size);
+
+       RESTORE_METRICS_OP ();
 }
 
+/* METRICS_OP_BITMAP */
 void
-glDrawArraysInstancedEXT (GLenum mode, GLint start, GLsizei count,
-                         GLsizei primcount)
+glBitmap (GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig,
+         GLfloat xmove, GLfloat ymove, const GLubyte *bitmap)
 {
-       TIMED_DEFER (glDrawArraysInstancedEXT, mode, start, count, primcount);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BITMAP);
+
+       GLWRAP_DEFER (glBitmap, width, height, xorig, yorig,
+                     xmove, ymove, bitmap);
+
+       RESTORE_METRICS_OP ();
 }
 
+#if HAVE_GLFIXED
 void
-glDrawArraysInstancedBaseInstance (GLenum mode, GLint first, GLsizei count,
-                                  GLsizei primcount, GLuint baseinstance)
+glBitmapxOES (GLsizei width, GLsizei height, GLfixed xorig, GLfixed yorig,
+             GLfixed xmove, GLfixed ymove, const GLubyte *bitmap)
 {
-       TIMED_DEFER (glDrawArraysInstancedBaseInstance, mode,
-                    first, count, primcount, baseinstance);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BITMAP);
+
+       GLWRAP_DEFER (glBitmapxOES, width, height, xorig, yorig,
+                     xmove, ymove, bitmap);
+
+       RESTORE_METRICS_OP ();
 }
+#endif
 
+/* METRICS_OP_BLIT_FRAMEBUFFER */
 void
-glDrawMeshArraysSUN (GLenum mode, GLint first, GLsizei count, GLsizei width)
+glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+                  GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+                  GLbitfield mask, GLenum filter)
 {
-       TIMED_DEFER (glDrawMeshArraysSUN, mode, first, count, width);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BLIT_FRAMEBUFFER);
+
+       GLWRAP_DEFER (glBlitFramebuffer, srcX0, srcY0, srcX1, srcY1,
+                     dstX0, dstY0, dstX1, dstY1, mask, filter);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
-glMultiDrawArrays (GLenum mode, const GLint *first,
-                  const GLsizei *count, GLsizei primcount)
+glBlitFramebufferEXT (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+                     GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+                     GLbitfield mask, GLenum filter)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BLIT_FRAMEBUFFER);
+
+       GLWRAP_DEFER (glBlitFramebufferEXT, srcX0, srcY0, srcX1, srcY1,
+                     dstX0, dstY0, dstX1, dstY1, mask, filter);
+
+       RESTORE_METRICS_OP ();
+}
+
+/* METRICS_OP_CLEAR */
+void 
+glClear (GLbitfield mask)
 {
-       TIMED_DEFER (glMultiDrawArrays, mode, first, count, primcount);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_CLEAR);
+
+       GLWRAP_DEFER (glClear, mask);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
-glMultiDrawArraysEXT (GLenum mode, const GLint *first,
-                     const GLsizei *count, GLsizei primcount)
+glClearBufferfi (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
 {
-       TIMED_DEFER (glMultiDrawArraysEXT, mode, first, count, primcount);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_CLEAR);
+
+       GLWRAP_DEFER (glClearBufferfi, buffer, drawbuffer, depth, stencil);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
-glMultiModeDrawArraysIBM (const GLenum *mode, const GLint *first,
-                         const GLsizei *count, GLsizei primcount,
-                         GLint modestride)
+glClearBufferfv (GLenum buffer, GLint drawbuffer, const GLfloat *value)
 {
-       TIMED_DEFER (glMultiModeDrawArraysIBM, mode,
-                    first, count, primcount, modestride);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_CLEAR);
+
+       GLWRAP_DEFER (glClearBufferfv, buffer, drawbuffer, value);
+
+       RESTORE_METRICS_OP ();
 }
 
-/* FIXME?
 void
-glMultiDrawArraysIndirect (...)
+glClearBufferiv (GLenum buffer, GLint drawbuffer, const GLint *value)
 {
-       TIMED_DEFER (glMultiDrawArraysIndirect, ...);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_CLEAR);
+
+       GLWRAP_DEFER (glClearBufferiv, buffer, drawbuffer, value);
+
+       RESTORE_METRICS_OP ();
 }
-*/
 
 void
-glMultiDrawArraysIndirectAMD (GLenum mode, const GLvoid *indirect,
-                             GLsizei primcount, GLsizei stride)
+glClearBufferuiv (GLenum buffer, GLint drawbuffer, const GLuint *value)
 {
-       TIMED_DEFER (glMultiDrawArraysIndirectAMD, mode,
-                    indirect, primcount, stride);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_CLEAR);
+
+       GLWRAP_DEFER (glClearBufferuiv, buffer, drawbuffer, value);
+
+       RESTORE_METRICS_OP ();
 }
 
+/* METRICS_OP_CLEAR_BUFFER_DATA */
+
 void
-glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)
+glClearBufferData (GLenum target, GLenum internalformat, GLenum format,
+                  GLenum type, const void *data)
 {
-       TIMED_DEFER (glDrawElements, mode, count, type, indices);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_CLEAR_BUFFER_DATA);
+
+       GLWRAP_DEFER (glClearBufferData, target, internalformat, format,
+                     type, data);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
-glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum type,
-                         const GLvoid *indices, GLint basevertex)
+glClearBufferSubData (GLenum target, GLenum internalformat, GLintptr offset,
+                     GLsizeiptr size, GLenum format, GLenum type,
+                     const void *data)
 {
-       TIMED_DEFER (glDrawElementsBaseVertex, mode, count,
-                    type, indices, basevertex);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_CLEAR_BUFFER_DATA);
+
+       GLWRAP_DEFER (glClearBufferSubData, target, internalformat,
+                     offset, size, format, type, data);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
-glDrawElementsIndirect (GLenum mode, GLenum type, const GLvoid *indirect)
+glClearNamedBufferDataEXT (GLuint buffer, GLenum internalformat, GLenum format,
+                          GLenum type, const void *data)
 {
-       TIMED_DEFER (glDrawElementsIndirect, mode, type, indirect);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_CLEAR_BUFFER_DATA);
+
+       GLWRAP_DEFER (glClearNamedBufferDataEXT, buffer, internalformat,
+                     format, type, data);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
-glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type,
-                        const GLvoid *indices, GLsizei primcount)
+glClearNamedBufferSubDataEXT (GLuint buffer, GLenum internalformat,
+                             GLenum format, GLenum type, GLsizeiptr offset,
+                             GLsizeiptr size, const void *data)
 {
-       TIMED_DEFER (glDrawElementsInstanced, mode, count,
-                    type, indices, primcount);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_CLEAR_BUFFER_DATA);
+
+       GLWRAP_DEFER (glClearNamedBufferSubDataEXT, buffer,
+                     internalformat, format, type, offset, size, data);
+
+       RESTORE_METRICS_OP ();
 }
 
+/* METRICS_OP_CLEAR_TEX_IMAGE */
+
+
+/* METRICS_OP_COPY_PIXELS */
 void
-glDrawElementsInstancedARB (GLenum mode, GLsizei count, GLenum type,
-                           const GLvoid *indices, GLsizei primcount)
+glCopyPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum type )
 {
-       TIMED_DEFER (glDrawElementsInstancedARB, mode, count,
-                    type, indices, primcount);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_COPY_PIXELS);
+
+       GLWRAP_DEFER (glCopyPixels, x, y, width, height, type);
+
+       RESTORE_METRICS_OP ();
 }
 
+/* METRICS_OP_COPY_TEX_IMAGE */
 void
-glDrawElementsInstancedEXT (GLenum mode, GLsizei count, GLenum type,
-                           const GLvoid *indices, GLsizei primcount)
+glCopyTexImage1D (GLenum target, GLint level, GLenum internalformat,
+                 GLint x, GLint y, GLsizei width, GLint border)
 {
-       TIMED_DEFER (glDrawElementsInstancedEXT, mode, count,
-                    type, indices, primcount);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCopyTexImage1D, target, level, internalformat,
+                     x, y, width, border);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
-glDrawElementsInstancedBaseVertex (GLenum mode, GLsizei count, GLenum type,
-                                  const GLvoid *indices, GLsizei primcount,
-                                  GLint basevertex)
+glCopyTexImage1DEXT (GLenum target, GLint level, GLenum internalformat,
+                    GLint x, GLint y, GLsizei width, GLint border)
 {
-       TIMED_DEFER (glDrawElementsInstancedBaseVertex, mode, count,
-                    type, indices, primcount, basevertex);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCopyTexImage1DEXT, target, level, internalformat,
+                     x, y, width, border);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
-glDrawElementsInstancedBaseInstance (GLenum mode, GLsizei count, GLenum type,
-                                    const void *indices, GLsizei primcount,
-                                    GLuint baseinstance)
+glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat,
+                 GLint x, GLint y, GLsizei width, GLsizei height,
+                 GLint border)
 {
-       TIMED_DEFER (glDrawElementsInstancedBaseInstance, mode, count, type,
-                    indices, primcount, baseinstance);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCopyTexImage2D, target, level, internalformat,
+                     x, y, width, height, border);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
-glDrawElementsInstancedBaseVertexBaseInstance (GLenum mode, GLsizei count,
-                     GLenum type, const void *indices, GLsizei primcount,
-                     GLint basevertex, GLuint baseinstance)
+glCopyTexImage2DEXT (GLenum target, GLint level, GLenum internalformat,
+                    GLint x, GLint y, GLsizei width, GLsizei height,
+                    GLint border)
 {
-       TIMED_DEFER (glDrawElementsInstancedBaseVertexBaseInstance, mode,
-                    count, type, indices, primcount, basevertex, baseinstance);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCopyTexImage2DEXT, target, level, internalformat,
+                     x, y, width, height, border);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
-glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count,
-                    GLenum type, const GLvoid *indices)
+glCopyTexSubImage1D (GLenum target, GLint level, GLint xoffset,
+                    GLint x, GLint y, GLsizei width)
 {
-       TIMED_DEFER (glDrawRangeElements, mode, start, end,
-                    count, type, indices);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCopyTexSubImage1D, target, level, xoffset,
+                     x, y, width);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
-glDrawRangeElementsEXT (GLenum mode, GLuint start, GLuint end, GLsizei count,
-                       GLenum type, const GLvoid *indices)
+glCopyTexSubImage1DEXT (GLenum target, GLint level, GLint xoffset,
+                       GLint x, GLint y, GLsizei width)
 {
-       TIMED_DEFER (glDrawRangeElementsEXT, mode, start, end,
-                    count, type, indices);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCopyTexSubImage1DEXT, target, level, xoffset,
+                     x, y, width);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
-glDrawRangeElementsBaseVertex (GLenum mode, GLuint start, GLuint end,
-                              GLsizei count, GLenum type,
-                              const GLvoid *indices, GLint basevertex)
+glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset,
+                    GLint yoffset, GLint x, GLint y, GLsizei width,
+                    GLsizei height)
 {
-       TIMED_DEFER (glDrawRangeElementsBaseVertex, mode, start, end,
-                    count, type, indices, basevertex);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCopyTexSubImage2D, target, level, xoffset, yoffset,
+                     x, y, width, height);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
-glMultiDrawElements (GLenum mode, const GLsizei *count, GLenum type,
-                    const GLvoid* *indices, GLsizei primcount)
+glCopyTexSubImage2DEXT (GLenum target, GLint level, GLint xoffset,
+                       GLint yoffset, GLint x, GLint y, GLsizei width,
+                       GLsizei height)
 {
-       TIMED_DEFER (glMultiDrawElements, mode, count, type,
-                    indices, primcount);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCopyTexSubImage2DEXT, target, level, xoffset, yoffset,
+                     x, y, width, height);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
-glMultiDrawElementsBaseVertex (GLenum mode, const GLsizei *count,
-                              GLenum type, const GLvoid* *indices,
-                              GLsizei primcount, const GLint *basevertex)
+glCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset,
+                    GLint yoffset, GLint zoffset, GLint x, GLint y,
+                    GLsizei width, GLsizei height)
 {
-       TIMED_DEFER (glMultiDrawElementsBaseVertex, mode, count,
-                    type, indices, primcount, basevertex);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCopyTexSubImage3D, target, level, xoffset, yoffset,
+                     zoffset, x, y, width, height);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
-glMultiDrawElementsEXT (GLenum mode, const GLsizei *count, GLenum type,
-                       const GLvoid* *indices, GLsizei primcount)
+glCopyTexSubImage3DEXT (GLenum target, GLint level, GLint xoffset,
+                       GLint yoffset, GLint zoffset, GLint x, GLint y,
+                       GLsizei width, GLsizei height)
 {
-       TIMED_DEFER (glMultiDrawElementsEXT, mode, count,
-                    type, indices, primcount);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCopyTexSubImage3DEXT, target, level, xoffset, yoffset,
+                     zoffset, x, y, width, height);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
-glMultiModeDrawElementsIBM (const GLenum *mode, const GLsizei *count,
-                           GLenum type, const GLvoid* const *indices,
-                           GLsizei primcount, GLint modestride)
+glCopyTextureImage1DEXT (GLuint texture, GLenum target, GLint level,
+                        GLenum internalformat, GLint x, GLint y,
+                        GLsizei width, GLint border)
 {
-       TIMED_DEFER (glMultiModeDrawElementsIBM, mode, count,
-                    type, indices, primcount, modestride);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCopyTextureImage1DEXT, texture, target, level,
+                     internalformat, x, y, width, border);
+
+       RESTORE_METRICS_OP ();
 }
 
-/* FIXME?
 void
-glMultiDrawElementsIndirect (...)
+glCopyTextureImage2DEXT (GLuint texture, GLenum target, GLint level,
+                        GLenum internalformat, GLint x, GLint y, GLsizei width,
+                        GLsizei height, GLint border)
 {
-       TIMED_DEFER (glMultiDrawElementsIndirect, ...);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCopyTextureImage2DEXT, texture, target,
+                     level, internalformat, x, y, width, height, border);
+
+       RESTORE_METRICS_OP ();
 }
-*/
 
 void
-glMultiDrawElementsIndirectAMD (GLenum mode, GLenum type,
-                               const GLvoid *indirect,
-                               GLsizei primcount, GLsizei stride)
+glCopyTextureSubImage1DEXT (GLuint texture, GLenum target, GLint level,
+                           GLint xoffset, GLint x, GLint y, GLsizei width)
 {
-       TIMED_DEFER (glMultiDrawElementsIndirectAMD, mode, type,
-                    indirect, primcount, stride);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCopyTextureSubImage1DEXT, texture, target, level,
+                     xoffset, x, y, width);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
-glCallList (GLuint list)
+glCopyTextureSubImage2DEXT (GLuint texture, GLenum target, GLint level,
+                           GLint xoffset, GLint yoffset, GLint x, GLint y,
+                           GLsizei width, GLsizei height)
 {
-       TIMED_DEFER (glCallList, list);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCopyTextureSubImage2DEXT, texture, target, level,
+                     xoffset, yoffset, x, y, width, height);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
-glCallLists (GLsizei n, GLenum type, const GLvoid *lists)
+glCopyTextureSubImage3DEXT (GLuint texture, GLenum target, GLint level,
+                           GLint xoffset, GLint yoffset, GLint zoffset,
+                           GLint x, GLint y, GLsizei width, GLsizei height)
 {
-       TIMED_DEFER (glCallLists, n, type, lists);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCopyTextureSubImage3DEXT, texture, target, level,
+                     xoffset, yoffset, zoffset, x, y, width, height);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
-glClear (GLbitfield mask)
+glCopyMultiTexImage1DEXT (GLenum texunit, GLenum target, GLint level,
+                         GLenum internalformat, GLint x, GLint y,
+                         GLsizei width, GLint border)
 {
-       TIMED_DEFER (glClear, mask);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCopyMultiTexImage1DEXT, texunit, target, level,
+                     internalformat, x, y, width, border);
+
+       RESTORE_METRICS_OP ();
 }
 
-/* We can't just use TIMED_DEFER for glBegin/glEnd since the
- * glBeginQuery/glEndQuery calls must both be outside
- * glBegin/glEnd. */
 void
-glBegin (GLenum mode)
+glCopyMultiTexImage2DEXT (GLenum texunit, GLenum target, GLint level,
+                         GLenum internalformat, GLint x, GLint y,
+                         GLsizei width, GLsizei height, GLint border)
 {
-       if (! inside_new_list)
-       {
-               unsigned counter;
-               counter = metrics_add_counter ();
-               glBeginQuery (GL_TIME_ELAPSED, counter);
-       }
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
 
-       GLWRAP_DEFER (glBegin, mode);
+       GLWRAP_DEFER (glCopyMultiTexImage2DEXT, texunit, target, level,
+                     internalformat, x, y, width, height, border);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
-glEnd (void)
+glCopyMultiTexSubImage1DEXT (GLenum texunit, GLenum target, GLint level,
+                            GLint xoffset, GLint x, GLint y, GLsizei width)
 {
-       GLWRAP_DEFER (glEnd);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
 
-       if (! inside_new_list) {
-               glEndQuery (GL_TIME_ELAPSED);
-       }
+       GLWRAP_DEFER (glCopyMultiTexSubImage1DEXT, texunit, target, level,
+                     xoffset, x, y, width);
+
+       RESTORE_METRICS_OP ();
 }
 
-/* And we need to track display lists to avoid inserting queries
- * inside the list while it's being constructed. */
 void
-glNewList (GLuint list, GLenum mode)
+glCopyMultiTexSubImage2DEXT (GLenum texunit, GLenum target, GLint level,
+                            GLint xoffset, GLint yoffset, GLint x, GLint y,
+                            GLsizei width, GLsizei height)
 {
-       inside_new_list = 1;
-       GLWRAP_DEFER (glNewList, list, mode);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCopyMultiTexSubImage2DEXT, texunit, target, level,
+                     xoffset, yoffset, x, y, width, height);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
-glEndList (void)
+glCopyMultiTexSubImage3DEXT (GLenum texunit, GLenum target, GLint level,
+                            GLint xoffset, GLint yoffset, GLint zoffset,
+                            GLint x, GLint y, GLsizei width, GLsizei height)
 {
-       GLWRAP_DEFER (glEndList);
-       inside_new_list = 0;
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCopyMultiTexSubImage3DEXT, texunit, target, level,
+                     xoffset, yoffset, zoffset, x, y, width, height);
+
+       RESTORE_METRICS_OP ();
 }
 
+/* METRICS_OP_DRAW_PIXELS */
 void
-glDrawPixels (GLsizei width, GLsizei height, GLenum format,
-             GLenum type, const GLvoid *pixels)
+glDrawPixels (GLsizei width, GLsizei height, GLenum format, GLenum type,
+             const GLvoid *pixels)
 {
-       TIMED_DEFER (glDrawPixels, width, height, format, type, pixels);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_DRAW_PIXELS);
+
+       GLWRAP_DEFER (glDrawPixels, width, height, format, type, pixels);
+
+       RESTORE_METRICS_OP ();
 }
 
+/* METRICS_OP_GET_TEX_IMAGE */
+
 void
-glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
-                  GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
-                  GLbitfield mask, GLenum filter)
+glGetCompressedMultiTexImageEXT (GLenum texunit, GLenum target,
+                                GLint lod, GLvoid *img)
 {
-       TIMED_DEFER (glBlitFramebuffer,
-                    srcX0, srcY0, srcX1, srcY1,
-                    dstX0, dstY0, dstX1, dstY1,
-                    mask, filter);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_GET_TEX_IMAGE);
+
+       GLWRAP_DEFER (glGetCompressedMultiTexImageEXT, texunit,
+                     target, lod, img);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
-glBlitFramebufferEXT (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
-                     GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
-                     GLbitfield mask, GLenum filter)
+glGetCompressedTexImage (GLenum target, GLint level, GLvoid *img)
 {
-       TIMED_DEFER (glBlitFramebufferEXT,
-                    srcX0, srcY0, srcX1, srcY1,
-                    dstX0, dstY0, dstX1, dstY1,
-                    mask, filter);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_GET_TEX_IMAGE);
+
+       GLWRAP_DEFER (glGetCompressedTexImage, target, level, img);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
-glUseProgram (GLuint program)
+glGetCompressedTexImageARB (GLenum target, GLint level, GLvoid *img)
 {
-       metrics_set_current_program (program);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_GET_TEX_IMAGE);
 
-       GLWRAP_DEFER(glUseProgram, program);
+       GLWRAP_DEFER (glGetCompressedTexImageARB, target, level, img);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
-glUseProgramObjectARB (GLhandleARB programObj)
+glGetCompressedTextureImageEXT (GLuint texture, GLenum target,
+                               GLint lod, GLvoid *img)
 {
-       metrics_set_current_program (programObj);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_GET_TEX_IMAGE);
 
-       GLWRAP_DEFER(glUseProgramObjectARB, programObj);
+       GLWRAP_DEFER (glGetCompressedTextureImageEXT, texture,
+                     target, lod, img);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glGetMultiTexImageEXT (GLenum texunit, GLenum target, GLint level,
+                      GLenum format, GLenum type, GLvoid *pixels)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_GET_TEX_IMAGE);
+
+       GLWRAP_DEFER (glGetMultiTexImageEXT, texunit,
+                     target, level, format, type, pixels);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glGetnCompressedTexImageARB (GLenum target, GLint lod,
+                            GLsizei bufSize, GLvoid *img)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_GET_TEX_IMAGE);
+
+       GLWRAP_DEFER (glGetnCompressedTexImageARB, target, lod, bufSize, img);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glGetnTexImageARB (GLenum target, GLint level, GLenum format,
+                  GLenum type, GLsizei bufSize, GLvoid *img)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_GET_TEX_IMAGE);
+
+       GLWRAP_DEFER (glGetnTexImageARB, target, level,
+                     format, type, bufSize, img);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glGetTexImage (GLenum target, GLint level, GLenum format, GLenum type,
+              GLvoid *pixels )
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_GET_TEX_IMAGE);
+
+       GLWRAP_DEFER (glGetTexImage, target, level, format, type, pixels);
+
+       RESTORE_METRICS_OP ();
+}
+
+/* METRICS_OP_READ_PIXELS */
+void
+glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height,
+             GLenum format, GLenum type, GLvoid *pixels )
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_READ_PIXELS);
+
+       GLWRAP_DEFER (glReadPixels, x, y, width, height, format, type, pixels);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glReadnPixelsARB (GLint x, GLint y, GLsizei width, GLsizei height,
+                 GLenum format, GLenum type, GLsizei bufSize, GLvoid *data)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_READ_PIXELS);
+
+       GLWRAP_DEFER (glReadnPixelsARB, x, y, width, height,
+                     format, type, bufSize, data);
+
+       RESTORE_METRICS_OP ();
+}
+
+/* METRICS_OP_TEX_IMAGE */
+void
+glTexImage1D (GLenum target, GLint level, GLint internalFormat,
+             GLsizei width, GLint border, GLenum format, GLenum type,
+             const GLvoid *pixels)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glTexImage1D, target, level, internalFormat, width,
+                     border, format, type, pixels);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glTexImage2D (GLenum target, GLint level, GLint internalFormat,
+             GLsizei width, GLsizei height, GLint border, GLenum format,
+             GLenum type, const GLvoid *pixels )
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glTexImage2D, target, level, internalFormat,
+                     width, height, border, format, type, pixels);
+
+       RESTORE_METRICS_OP ();
+}
+
+
+void
+glTexImage2DMultisample (GLenum target, GLsizei samples,
+                        GLint_or_enum internalformat,
+                        GLsizei width, GLsizei height,
+                        GLboolean fixedsamplelocations)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glTexImage2DMultisample, target, samples,
+                     internalformat, width, height, fixedsamplelocations);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glTexImage2DMultisampleCoverageNV (GLenum target, GLsizei coverageSamples,
+                                  GLsizei colorSamples, GLint internalFormat,
+                                  GLsizei width, GLsizei height,
+                                  GLboolean fixedSampleLocations)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glTexImage2DMultisampleCoverageNV, target,
+                     coverageSamples, colorSamples, internalFormat,
+                     width, height, fixedSampleLocations);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glTexImage3D (GLenum target, GLint level, GLint internalformat,
+             GLsizei width, GLsizei height, GLsizei depth, GLint border,
+             GLenum format, GLenum type, const GLvoid *pixels)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glTexImage3D, target, level, internalformat,
+                     width, height, depth, border, format, type, pixels);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glTexImage3DEXT (GLenum target, GLint level, GLenum internalformat,
+                GLsizei width, GLsizei height, GLsizei depth, GLint border,
+                GLenum format, GLenum type, const GLvoid *pixels)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glTexImage3DEXT, target, level, internalformat,
+                     width, height, depth, border, format, type, pixels);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glTexImage3DMultisample (GLenum target, GLsizei samples,
+                        GLint_or_enum internalformat,
+                        GLsizei width, GLsizei height, GLsizei depth,
+                        GLboolean fixedsamplelocations)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glTexImage3DMultisample, target, samples,
+                     internalformat, width, height, depth,
+                     fixedsamplelocations);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glTexImage3DMultisampleCoverageNV (GLenum target, GLsizei coverageSamples,
+                                  GLsizei colorSamples, GLint internalFormat,
+                                  GLsizei width, GLsizei height, GLsizei depth,
+                                  GLboolean fixedSampleLocations)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glTexImage3DMultisampleCoverageNV, target,
+                     coverageSamples, colorSamples, internalFormat,
+                     width, height, depth, fixedSampleLocations);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glTexImage4DSGIS (GLenum target, GLint level, GLenum internalformat,
+                 GLsizei width, GLsizei height, GLsizei depth,
+                 GLsizei size4d, GLint border, GLenum format,
+                 GLenum type, const GLvoid *pixels)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glTexImage4DSGIS, target, level,
+                     internalformat, width, height, depth,
+                     size4d, border, format, type, pixels);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glTexSubImage1D (GLenum target, GLint level, GLint xoffset,
+                GLsizei width, GLenum format, GLenum type,
+                const GLvoid *pixels)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glTexSubImage1D, target, level, xoffset,
+                     width, format, type, pixels);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glTexSubImage1DEXT (GLenum target, GLint level, GLint xoffset,
+                   GLsizei width, GLenum format, GLenum type,
+                   const GLvoid *pixels)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glTexSubImage1DEXT, target, level, xoffset,
+                     width, format, type, pixels);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset,
+                GLsizei width, GLsizei height, GLenum format, GLenum type,
+                const GLvoid *pixels)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glTexSubImage2D, target, level, xoffset, yoffset,
+                     width, height, format, type, pixels);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glTexSubImage2DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset,
+                   GLsizei width, GLsizei height, GLenum format, GLenum type,
+                   const GLvoid *pixels)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glTexSubImage2DEXT, target, level, xoffset, yoffset,
+                     width, height, format, type, pixels);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset,
+                GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+                GLenum format, GLenum type, const GLvoid *pixels)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glTexSubImage3D, target, level, xoffset, yoffset,
+                     zoffset, width, height, depth, format, type, pixels);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glTexSubImage3DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset,
+                   GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+                   GLenum format, GLenum type, const GLvoid *pixels)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glTexSubImage3DEXT, target, level, xoffset, yoffset,
+                     zoffset, width, height, depth, format, type, pixels);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glTexSubImage4DSGIS (GLenum target, GLint level, GLint xoffset, GLint yoffset,
+                    GLint zoffset, GLint woffset, GLsizei width,
+                    GLsizei height, GLsizei depth, GLsizei size4d,
+                    GLenum format, GLenum type, const GLvoid *pixels)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glTexSubImage4DSGIS, target, level, xoffset,
+                     yoffset, zoffset, woffset, width, height,
+                     depth, size4d, format, type, pixels);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glCompressedMultiTexImage1DEXT (GLenum texunit, GLenum target, GLint level,
+                               GLenum internalformat, GLsizei width,
+                               GLint border, GLsizei imageSize,
+                               const GLvoid *bits)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCompressedMultiTexImage1DEXT, texunit, target,
+                     level, internalformat, width, border, imageSize, bits);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glCompressedMultiTexImage2DEXT (GLenum texunit, GLenum target, GLint level,
+                               GLenum internalformat, GLsizei width,
+                               GLsizei height, GLint border,
+                               GLsizei imageSize, const GLvoid *bits)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCompressedMultiTexImage2DEXT, texunit, target, level,
+                     internalformat, width, height, border, imageSize, bits);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glCompressedMultiTexImage3DEXT (GLenum texunit, GLenum target, GLint level,
+                               GLenum internalformat, GLsizei width,
+                               GLsizei height, GLsizei depth, GLint border,
+                               GLsizei imageSize, const GLvoid *bits)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCompressedMultiTexImage3DEXT, texunit, target,
+                     level, internalformat, width, height, depth,
+                     border, imageSize, bits);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glCompressedMultiTexSubImage1DEXT (GLenum texunit, GLenum target, GLint level,
+                                  GLint xoffset, GLsizei width, GLenum format,
+                                  GLsizei imageSize, const GLvoid *bits)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCompressedMultiTexSubImage1DEXT, texunit, target,
+                     level, xoffset, width, format, imageSize, bits);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glCompressedMultiTexSubImage2DEXT (GLenum texunit, GLenum target, GLint level,
+                                  GLint xoffset, GLint yoffset, GLsizei width,
+                                  GLsizei height, GLenum format,
+                                  GLsizei imageSize, const GLvoid *bits)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCompressedMultiTexSubImage2DEXT, texunit, target, level,
+                     xoffset, yoffset, width, height, format, imageSize, bits);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glCompressedMultiTexSubImage3DEXT (GLenum texunit, GLenum target, GLint level,
+                                  GLint xoffset, GLint yoffset, GLint zoffset,
+                                  GLsizei width, GLsizei height, GLsizei depth,
+                                  GLenum format, GLsizei imageSize,
+                                  const GLvoid *bits)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCompressedMultiTexSubImage3DEXT, texunit, target,
+                     level, xoffset, yoffset, zoffset, width, height,
+                     depth, format, imageSize, bits);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glCompressedTexImage1D (GLenum target, GLint level, GLenum internalformat,
+                       GLsizei width, GLint border, GLsizei imageSize,
+                       const GLvoid *data)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCompressedTexImage1D, target, level,
+                     internalformat, width, border, imageSize, data);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glCompressedTexImage1DARB (GLenum target, GLint level, GLenum internalformat,
+                          GLsizei width, GLint border, GLsizei imageSize,
+                          const GLvoid *data)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCompressedTexImage1DARB, target, level, internalformat,
+                     width, border, imageSize, data);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat,
+                       GLsizei width, GLsizei height, GLint border,
+                       GLsizei imageSize, const GLvoid *data)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCompressedTexImage2D, target, level, internalformat,
+                     width, height, border, imageSize, data);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glCompressedTexImage2DARB (GLenum target, GLint level, GLenum internalformat,
+                          GLsizei width, GLsizei height, GLint border,
+                          GLsizei imageSize, const GLvoid *data)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCompressedTexImage2DARB, target, level, internalformat,
+                     width, height, border, imageSize, data);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glCompressedTexImage3D (GLenum target, GLint level, GLenum internalformat,
+                       GLsizei width, GLsizei height, GLsizei depth,
+                       GLint border, GLsizei imageSize, const GLvoid *data)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCompressedTexImage3D, target, level, internalformat,
+                     width, height, depth, border, imageSize, data);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glCompressedTexImage3DARB (GLenum target, GLint level, GLenum internalformat,
+                          GLsizei width, GLsizei height, GLsizei depth,
+                          GLint border, GLsizei imageSize, const GLvoid *data)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCompressedTexImage3DARB, target, level, internalformat,
+                     width, height, depth, border, imageSize, data);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glCompressedTexSubImage1D (GLenum target, GLint level, GLint xoffset,
+                          GLsizei width, GLenum format, GLsizei imageSize,
+                          const GLvoid *data)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCompressedTexSubImage1D, target, level, xoffset,
+                     width, format, imageSize, data);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glCompressedTexSubImage1DARB (GLenum target, GLint level, GLint xoffset,
+                             GLsizei width, GLenum format, GLsizei imageSize,
+                             const GLvoid *data)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCompressedTexSubImage1DARB, target, level, xoffset,
+                     width, format, imageSize, data);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset,
+                          GLint yoffset, GLsizei width, GLsizei height,
+                          GLenum format, GLsizei imageSize, const GLvoid *data)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCompressedTexSubImage2D, target, level, xoffset,
+                     yoffset, width, height, format, imageSize, data);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glCompressedTexSubImage2DARB (GLenum target, GLint level, GLint xoffset,
+                             GLint yoffset, GLsizei width, GLsizei height,
+                             GLenum format, GLsizei imageSize,
+                             const GLvoid *data)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCompressedTexSubImage2DARB, target, level, xoffset,
+                     yoffset, width, height, format, imageSize, data);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glCompressedTexSubImage3D (GLenum target, GLint level, GLint xoffset,
+                          GLint yoffset, GLint zoffset, GLsizei width,
+                          GLsizei height, GLsizei depth, GLenum format,
+                          GLsizei imageSize, const GLvoid *data)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCompressedTexSubImage3D, target, level, xoffset,
+                     yoffset, zoffset, width, height, depth, format,
+                     imageSize, data);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glCompressedTexSubImage3DARB (GLenum target, GLint level, GLint xoffset,
+                             GLint yoffset, GLint zoffset, GLsizei width,
+                             GLsizei height, GLsizei depth, GLenum format,
+                             GLsizei imageSize, const GLvoid *data)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCompressedTexSubImage3DARB, target, level, xoffset,
+                     yoffset, zoffset, width, height, depth, format,
+                     imageSize, data);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glCompressedTextureImage1DEXT (GLuint texture, GLenum target, GLint level,
+                              GLenum internalformat, GLsizei width,
+                              GLint border, GLsizei imageSize,
+                              const GLvoid *bits)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCompressedTextureImage1DEXT, texture, target, level,
+                     internalformat, width, border, imageSize, bits);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glCompressedTextureImage2DEXT (GLuint texture, GLenum target, GLint level,
+                              GLenum internalformat, GLsizei width,
+                              GLsizei height, GLint border,
+                              GLsizei imageSize, const GLvoid *bits)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCompressedTextureImage2DEXT, texture, target, level,
+                     internalformat, width, height, border, imageSize, bits);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glCompressedTextureImage3DEXT (GLuint texture, GLenum target, GLint level,
+                              GLenum internalformat, GLsizei width,
+                              GLsizei height, GLsizei depth, GLint border,
+                              GLsizei imageSize, const GLvoid *bits)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCompressedTextureImage3DEXT, texture, target,
+                     level, internalformat, width, height, depth,
+                     border, imageSize, bits);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glCompressedTextureSubImage1DEXT (GLuint texture, GLenum target, GLint level,
+                                 GLint xoffset, GLsizei width, GLenum format,
+                                 GLsizei imageSize, const GLvoid *bits)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCompressedTextureSubImage1DEXT, texture, target,
+                     level, xoffset, width, format, imageSize, bits);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glCompressedTextureSubImage2DEXT (GLuint texture, GLenum target, GLint level,
+                                 GLint xoffset, GLint yoffset, GLsizei width,
+                                 GLsizei height, GLenum format,
+                                 GLsizei imageSize, const GLvoid *bits)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCompressedTextureSubImage2DEXT, texture, target, level,
+                     xoffset, yoffset, width, height, format, imageSize, bits);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glCompressedTextureSubImage3DEXT (GLuint texture, GLenum target, GLint level,
+                                 GLint xoffset, GLint yoffset, GLint zoffset,
+                                 GLsizei width, GLsizei height, GLsizei depth,
+                                 GLenum format, GLsizei imageSize,
+                                 const GLvoid *bits)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glCompressedTextureSubImage3DEXT, texture, target,
+                     level, xoffset, yoffset, zoffset, width, height,
+                     depth, format, imageSize, bits);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glMultiTexImage1DEXT (GLenum texunit, GLenum target, GLint level,
+                     GLenum_or_int internalformat,
+                     GLsizei width, GLint border,
+                     GLenum format, GLenum type, const GLvoid *pixels)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glMultiTexImage1DEXT, texunit, target, level,
+                     internalformat, width, border, format, type, pixels);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glMultiTexImage2DEXT (GLenum texunit, GLenum target, GLint level,
+                     GLenum_or_int internalformat,
+                     GLsizei width, GLsizei height,
+                     GLint border, GLenum format, GLenum type,
+                     const GLvoid *pixels)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glMultiTexImage2DEXT, texunit, target, level,
+                     internalformat, width, height, border, format,
+                     type, pixels);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glMultiTexImage3DEXT (GLenum texunit, GLenum target, GLint level,
+                     GLenum_or_int internalformat,
+                     GLsizei width, GLsizei height,
+                     GLsizei depth, GLint border, GLenum format,
+                     GLenum type, const GLvoid *pixels)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glMultiTexImage3DEXT, texunit, target, level,
+                     internalformat, width, height, depth, border,
+                     format, type, pixels);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glMultiTexSubImage1DEXT (GLenum texunit, GLenum target, GLint level,
+                        GLint xoffset, GLsizei width, GLenum format,
+                        GLenum type, const GLvoid *pixels)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glMultiTexSubImage1DEXT, texunit, target, level,
+                     xoffset, width, format, type, pixels);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glMultiTexSubImage2DEXT (GLenum texunit, GLenum target, GLint level,
+                        GLint xoffset, GLint yoffset, GLsizei width,
+                        GLsizei height, GLenum format, GLenum type,
+                        const GLvoid *pixels)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glMultiTexSubImage2DEXT, texunit, target, level, xoffset,
+                     yoffset, width, height, format, type, pixels);
+
+       RESTORE_METRICS_OP ();
+}
+
+void
+glMultiTexSubImage3DEXT (GLenum texunit, GLenum target, GLint level,
+                        GLint xoffset, GLint yoffset, GLint zoffset,
+                        GLsizei width, GLsizei height, GLsizei depth,
+                        GLenum format, GLenum type, const GLvoid *pixels)
+{
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+
+       GLWRAP_DEFER (glMultiTexSubImage3DEXT, texunit, target, level,
+                     xoffset, yoffset, zoffset, width, height, depth,
+                     format, type, pixels);
+
+       RESTORE_METRICS_OP ();
 }