]> git.cworth.org Git - fips/blobdiff - glwrap.c
Allow fips to compile with OpenGL without GLfixed
[fips] / glwrap.c
index 80c5e36649c7362ba23bef9d730f64bb6326fa01..4b865f55d7e03c04e094efaa47ec0374a9e26eb7 100644 (file)
--- a/glwrap.c
+++ b/glwrap.c
 
 #include "glwrap.h"
 
-#include "metrics.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;
 
+/* Switch metrics operation persistently, (until next SWITCH) */
 #define SWITCH_METRICS_OP(op)                  \
-       metrics_counter_stop ();                \
-       metrics_set_current_op (op);            \
-       metrics_counter_start ();
+       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)
@@ -87,6 +119,8 @@ glwrap_lookup (char *name)
                const char *path;
 
                path = getenv ("FIPS_LIBGL");
+               if (! path)
+                       path = getenv ("GLAZE_LIBGL");
                if (path) {
                        gl_handle = dlopen (path, RTLD_LAZY);
 
@@ -103,7 +137,7 @@ glwrap_lookup (char *name)
        ret = dlwrap_real_dlsym (gl_handle, name);
 
        if (ret == NULL) {
-               fprintf (stderr, "Error: glwrap_lookup failed to dlsym %s\n",
+               fprintf (stderr, "fips: Error: glwrap_lookup failed to dlsym %s\n",
                         name);
                exit (1);
        }
@@ -133,61 +167,77 @@ glUseProgramObjectARB (GLhandleARB programObj)
 void
 glAccum (GLenum op, GLfloat value)
 {
-       SWITCH_METRICS_OP (METRICS_OP_ACCUM);
+       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)
 {
-       SWITCH_METRICS_OP (METRICS_OP_ACCUM);
+       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)
 {
-       SWITCH_METRICS_OP (METRICS_OP_ACCUM);
+       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)
 {
-       SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
+       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)
 {
-       SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
+       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)
 {
-       SWITCH_METRICS_OP (METRICS_OP_BUFFER_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)
 {
-       SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
 
        GLWRAP_DEFER (glNamedBufferSubDataEXT, buffer, offset, size, data);
+
+       RESTORE_METRICS_OP ();
 }
 
 void *
@@ -195,10 +245,12 @@ glMapBuffer (GLenum target, GLenum access)
 {
        void *ret;
 
-       SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
 
        GLWRAP_DEFER_WITH_RETURN (ret, glMapBuffer, target, access);
 
+       RESTORE_METRICS_OP ();
+
        return ret;
 }
 
@@ -207,10 +259,12 @@ glMapBufferARB (GLenum target, GLenum access)
 {
        void *ret;
 
-       SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
 
        GLWRAP_DEFER_WITH_RETURN (ret, glMapBufferARB, target, access);
 
+       RESTORE_METRICS_OP ();
+
        return ret;
 }
 
@@ -220,11 +274,13 @@ glMapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length,
 {
        void *ret;
 
-       SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
 
        GLWRAP_DEFER_WITH_RETURN (ret, glMapBufferRange, target, offset,
                                  length, access);
 
+       RESTORE_METRICS_OP ();
+
        return ret;
 }
 
@@ -233,10 +289,12 @@ glUnmapBuffer (GLenum target)
 {
        GLboolean ret;
 
-       SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
 
        GLWRAP_DEFER_WITH_RETURN (ret, glUnmapBuffer, target);
 
+       RESTORE_METRICS_OP ();
+
        return ret;
 }
 
@@ -245,10 +303,12 @@ glUnmapNamedBufferEXT (GLuint buffer)
 {
        GLboolean ret;
 
-       SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
 
        GLWRAP_DEFER_WITH_RETURN (ret, glUnmapNamedBufferEXT, buffer);
 
+       RESTORE_METRICS_OP ();
+
        return ret;
 }
 
@@ -257,36 +317,44 @@ glUnmapBufferARB (GLenum target)
 {
        GLboolean ret;
 
-       SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
 
        GLWRAP_DEFER_WITH_RETURN (ret, glUnmapBufferARB, target);
 
+       RESTORE_METRICS_OP ();
+
        return ret;
 }
 
 void
 glFlushMappedBufferRange (GLenum target, GLintptr offset, GLsizeiptr length)
 {
-       SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
 
        GLWRAP_DEFER (glFlushMappedBufferRange, target, offset, length);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
 glFlushMappedBufferRangeAPPLE (GLenum target, GLintptr offset, GLsizeiptr size)
 {
-       SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
 
        GLWRAP_DEFER (glFlushMappedBufferRangeAPPLE, target, offset, size);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
 glFlushMappedNamedBufferRangeEXT (GLuint buffer, GLintptr offset,
                                  GLsizeiptr length)
 {
-       SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
 
        GLWRAP_DEFER (glFlushMappedNamedBufferRangeEXT, buffer, offset, length);
+
+       RESTORE_METRICS_OP ();
 }
 
 void *
@@ -294,10 +362,12 @@ glMapNamedBufferEXT (GLuint buffer, GLenum access)
 {
        void *ret;
 
-       SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
 
        GLWRAP_DEFER_WITH_RETURN (ret, glMapNamedBufferEXT, buffer, access);
 
+       RESTORE_METRICS_OP ();
+
        return ret;
 }
 
@@ -307,11 +377,13 @@ glMapNamedBufferRangeEXT (GLuint buffer, GLintptr offset, GLsizeiptr length,
 {
        void *ret;
 
-       SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BUFFER_DATA);
 
        GLWRAP_DEFER_WITH_RETURN (ret, glMapNamedBufferRangeEXT, buffer,
                                  offset, length, access);
 
+       RESTORE_METRICS_OP ();
+
        return ret;
 }
 
@@ -321,10 +393,12 @@ glCopyBufferSubData (GLenum readTarget, GLenum writeTarget,
                     GLintptr readOffset, GLintptr writeOffset,
                     GLsizeiptr size)
 {
-       SWITCH_METRICS_OP (METRICS_OP_BUFFER_SUB_DATA);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BUFFER_SUB_DATA);
 
        GLWRAP_DEFER (glCopyBufferSubData, readTarget, writeTarget,
                      readOffset, writeOffset, size);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
@@ -332,10 +406,12 @@ glNamedCopyBufferSubDataEXT (GLuint readBuffer, GLuint writeBuffer,
                             GLintptr readOffset, GLintptr writeOffset,
                             GLsizeiptr size)
 {
-       SWITCH_METRICS_OP (METRICS_OP_BUFFER_SUB_DATA);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_BUFFER_SUB_DATA);
 
        GLWRAP_DEFER (glNamedCopyBufferSubDataEXT, readBuffer,
                      writeBuffer, readOffset, writeOffset, size);
+
+       RESTORE_METRICS_OP ();
 }
 
 /* METRICS_OP_BITMAP */
@@ -343,21 +419,27 @@ void
 glBitmap (GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig,
          GLfloat xmove, GLfloat ymove, const GLubyte *bitmap)
 {
-       SWITCH_METRICS_OP (METRICS_OP_BITMAP);
+       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
 glBitmapxOES (GLsizei width, GLsizei height, GLfixed xorig, GLfixed yorig,
              GLfixed xmove, GLfixed ymove, const GLubyte *bitmap)
 {
-       SWITCH_METRICS_OP (METRICS_OP_BITMAP);
+       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
@@ -365,10 +447,12 @@ glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
                   GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
                   GLbitfield mask, GLenum filter)
 {
-       SWITCH_METRICS_OP (METRICS_OP_BLIT_FRAMEBUFFER);
+       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
@@ -376,51 +460,63 @@ glBlitFramebufferEXT (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
                      GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
                      GLbitfield mask, GLenum filter)
 {
-       SWITCH_METRICS_OP (METRICS_OP_BLIT_FRAMEBUFFER);
+       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)
 {
-       SWITCH_METRICS_OP (METRICS_OP_CLEAR);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_CLEAR);
 
        GLWRAP_DEFER (glClear, mask);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
 glClearBufferfi (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
 {
-       SWITCH_METRICS_OP (METRICS_OP_CLEAR);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_CLEAR);
 
        GLWRAP_DEFER (glClearBufferfi, buffer, drawbuffer, depth, stencil);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
 glClearBufferfv (GLenum buffer, GLint drawbuffer, const GLfloat *value)
 {
-       SWITCH_METRICS_OP (METRICS_OP_CLEAR);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_CLEAR);
 
        GLWRAP_DEFER (glClearBufferfv, buffer, drawbuffer, value);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
 glClearBufferiv (GLenum buffer, GLint drawbuffer, const GLint *value)
 {
-       SWITCH_METRICS_OP (METRICS_OP_CLEAR);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_CLEAR);
 
        GLWRAP_DEFER (glClearBufferiv, buffer, drawbuffer, value);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
 glClearBufferuiv (GLenum buffer, GLint drawbuffer, const GLuint *value)
 {
-       SWITCH_METRICS_OP (METRICS_OP_CLEAR);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_CLEAR);
 
        GLWRAP_DEFER (glClearBufferuiv, buffer, drawbuffer, value);
+
+       RESTORE_METRICS_OP ();
 }
 
 /* METRICS_OP_CLEAR_BUFFER_DATA */
@@ -429,10 +525,12 @@ void
 glClearBufferData (GLenum target, GLenum internalformat, GLenum format,
                   GLenum type, const void *data)
 {
-       SWITCH_METRICS_OP (METRICS_OP_CLEAR_BUFFER_DATA);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_CLEAR_BUFFER_DATA);
 
        GLWRAP_DEFER (glClearBufferData, target, internalformat, format,
                      type, data);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
@@ -440,20 +538,24 @@ glClearBufferSubData (GLenum target, GLenum internalformat, GLintptr offset,
                      GLsizeiptr size, GLenum format, GLenum type,
                      const void *data)
 {
-       SWITCH_METRICS_OP (METRICS_OP_CLEAR_BUFFER_DATA);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_CLEAR_BUFFER_DATA);
 
        GLWRAP_DEFER (glClearBufferSubData, target, internalformat,
                      offset, size, format, type, data);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
 glClearNamedBufferDataEXT (GLuint buffer, GLenum internalformat, GLenum format,
                           GLenum type, const void *data)
 {
-       SWITCH_METRICS_OP (METRICS_OP_CLEAR_BUFFER_DATA);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_CLEAR_BUFFER_DATA);
 
        GLWRAP_DEFER (glClearNamedBufferDataEXT, buffer, internalformat,
                      format, type, data);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
@@ -461,10 +563,12 @@ glClearNamedBufferSubDataEXT (GLuint buffer, GLenum internalformat,
                              GLenum format, GLenum type, GLsizeiptr offset,
                              GLsizeiptr size, const void *data)
 {
-       SWITCH_METRICS_OP (METRICS_OP_CLEAR_BUFFER_DATA);
+       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 */
@@ -474,9 +578,11 @@ glClearNamedBufferSubDataEXT (GLuint buffer, GLenum internalformat,
 void
 glCopyPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum type )
 {
-       SWITCH_METRICS_OP (METRICS_OP_COPY_PIXELS);
+       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 */
@@ -484,20 +590,24 @@ void
 glCopyTexImage1D (GLenum target, GLint level, GLenum internalformat,
                  GLint x, GLint y, GLsizei width, GLint border)
 {
-       SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
 
        GLWRAP_DEFER (glCopyTexImage1D, target, level, internalformat,
                      x, y, width, border);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
 glCopyTexImage1DEXT (GLenum target, GLint level, GLenum internalformat,
                     GLint x, GLint y, GLsizei width, GLint border)
 {
-       SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
 
        GLWRAP_DEFER (glCopyTexImage1DEXT, target, level, internalformat,
                      x, y, width, border);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
@@ -505,10 +615,12 @@ glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat,
                  GLint x, GLint y, GLsizei width, GLsizei height,
                  GLint border)
 {
-       SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+       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
@@ -516,30 +628,36 @@ glCopyTexImage2DEXT (GLenum target, GLint level, GLenum internalformat,
                     GLint x, GLint y, GLsizei width, GLsizei height,
                     GLint border)
 {
-       SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+       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
 glCopyTexSubImage1D (GLenum target, GLint level, GLint xoffset,
                     GLint x, GLint y, GLsizei width)
 {
-       SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
 
        GLWRAP_DEFER (glCopyTexSubImage1D, target, level, xoffset,
                      x, y, width);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
 glCopyTexSubImage1DEXT (GLenum target, GLint level, GLint xoffset,
                        GLint x, GLint y, GLsizei width)
 {
-       SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
 
        GLWRAP_DEFER (glCopyTexSubImage1DEXT, target, level, xoffset,
                      x, y, width);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
@@ -547,10 +665,12 @@ glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset,
                     GLint yoffset, GLint x, GLint y, GLsizei width,
                     GLsizei height)
 {
-       SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+       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
@@ -558,10 +678,12 @@ glCopyTexSubImage2DEXT (GLenum target, GLint level, GLint xoffset,
                        GLint yoffset, GLint x, GLint y, GLsizei width,
                        GLsizei height)
 {
-       SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+       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
@@ -569,10 +691,12 @@ glCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset,
                     GLint yoffset, GLint zoffset, GLint x, GLint y,
                     GLsizei width, GLsizei height)
 {
-       SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+       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
@@ -580,10 +704,12 @@ glCopyTexSubImage3DEXT (GLenum target, GLint level, GLint xoffset,
                        GLint yoffset, GLint zoffset, GLint x, GLint y,
                        GLsizei width, GLsizei height)
 {
-       SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+       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
@@ -591,10 +717,12 @@ glCopyTextureImage1DEXT (GLuint texture, GLenum target, GLint level,
                         GLenum internalformat, GLint x, GLint y,
                         GLsizei width, GLint border)
 {
-       SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
 
        GLWRAP_DEFER (glCopyTextureImage1DEXT, texture, target, level,
                      internalformat, x, y, width, border);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
@@ -602,20 +730,24 @@ glCopyTextureImage2DEXT (GLuint texture, GLenum target, GLint level,
                         GLenum internalformat, GLint x, GLint y, GLsizei width,
                         GLsizei height, GLint border)
 {
-       SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+       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
 glCopyTextureSubImage1DEXT (GLuint texture, GLenum target, GLint level,
                            GLint xoffset, GLint x, GLint y, GLsizei width)
 {
-       SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
 
        GLWRAP_DEFER (glCopyTextureSubImage1DEXT, texture, target, level,
                      xoffset, x, y, width);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
@@ -623,10 +755,12 @@ glCopyTextureSubImage2DEXT (GLuint texture, GLenum target, GLint level,
                            GLint xoffset, GLint yoffset, GLint x, GLint y,
                            GLsizei width, GLsizei height)
 {
-       SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+       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
@@ -634,10 +768,12 @@ glCopyTextureSubImage3DEXT (GLuint texture, GLenum target, GLint level,
                            GLint xoffset, GLint yoffset, GLint zoffset,
                            GLint x, GLint y, GLsizei width, GLsizei height)
 {
-       SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+       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
@@ -645,10 +781,12 @@ glCopyMultiTexImage1DEXT (GLenum texunit, GLenum target, GLint level,
                          GLenum internalformat, GLint x, GLint y,
                          GLsizei width, GLint border)
 {
-       SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
 
        GLWRAP_DEFER (glCopyMultiTexImage1DEXT, texunit, target, level,
                      internalformat, x, y, width, border);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
@@ -656,20 +794,24 @@ glCopyMultiTexImage2DEXT (GLenum texunit, GLenum target, GLint level,
                          GLenum internalformat, GLint x, GLint y,
                          GLsizei width, GLsizei height, GLint border)
 {
-       SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
 
        GLWRAP_DEFER (glCopyMultiTexImage2DEXT, texunit, target, level,
                      internalformat, x, y, width, height, border);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
 glCopyMultiTexSubImage1DEXT (GLenum texunit, GLenum target, GLint level,
                             GLint xoffset, GLint x, GLint y, GLsizei width)
 {
-       SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
 
        GLWRAP_DEFER (glCopyMultiTexSubImage1DEXT, texunit, target, level,
                      xoffset, x, y, width);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
@@ -677,10 +819,12 @@ glCopyMultiTexSubImage2DEXT (GLenum texunit, GLenum target, GLint level,
                             GLint xoffset, GLint yoffset, GLint x, GLint y,
                             GLsizei width, GLsizei height)
 {
-       SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+       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
@@ -688,10 +832,12 @@ glCopyMultiTexSubImage3DEXT (GLenum texunit, GLenum target, GLint level,
                             GLint xoffset, GLint yoffset, GLint zoffset,
                             GLint x, GLint y, GLsizei width, GLsizei height)
 {
-       SWITCH_METRICS_OP (METRICS_OP_COPY_TEX_IMAGE);
+       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 */
@@ -699,9 +845,11 @@ void
 glDrawPixels (GLsizei width, GLsizei height, GLenum format, GLenum type,
              const GLvoid *pixels)
 {
-       SWITCH_METRICS_OP (METRICS_OP_DRAW_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 */
@@ -710,74 +858,90 @@ void
 glGetCompressedMultiTexImageEXT (GLenum texunit, GLenum target,
                                 GLint lod, GLvoid *img)
 {
-       SWITCH_METRICS_OP (METRICS_OP_GET_TEX_IMAGE);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_GET_TEX_IMAGE);
 
        GLWRAP_DEFER (glGetCompressedMultiTexImageEXT, texunit,
                      target, lod, img);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
 glGetCompressedTexImage (GLenum target, GLint level, GLvoid *img)
 {
-       SWITCH_METRICS_OP (METRICS_OP_GET_TEX_IMAGE);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_GET_TEX_IMAGE);
 
        GLWRAP_DEFER (glGetCompressedTexImage, target, level, img);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
 glGetCompressedTexImageARB (GLenum target, GLint level, GLvoid *img)
 {
-       SWITCH_METRICS_OP (METRICS_OP_GET_TEX_IMAGE);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_GET_TEX_IMAGE);
 
        GLWRAP_DEFER (glGetCompressedTexImageARB, target, level, img);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
 glGetCompressedTextureImageEXT (GLuint texture, GLenum target,
                                GLint lod, GLvoid *img)
 {
-       SWITCH_METRICS_OP (METRICS_OP_GET_TEX_IMAGE);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_GET_TEX_IMAGE);
 
        GLWRAP_DEFER (glGetCompressedTextureImageEXT, texture,
                      target, lod, img);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
 glGetMultiTexImageEXT (GLenum texunit, GLenum target, GLint level,
                       GLenum format, GLenum type, GLvoid *pixels)
 {
-       SWITCH_METRICS_OP (METRICS_OP_GET_TEX_IMAGE);
+       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)
 {
-       SWITCH_METRICS_OP (METRICS_OP_GET_TEX_IMAGE);
+       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)
 {
-       SWITCH_METRICS_OP (METRICS_OP_GET_TEX_IMAGE);
+       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 )
 {
-       SWITCH_METRICS_OP (METRICS_OP_GET_TEX_IMAGE);
+       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 */
@@ -785,19 +949,23 @@ void
 glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height,
              GLenum format, GLenum type, GLvoid *pixels )
 {
-       SWITCH_METRICS_OP (METRICS_OP_READ_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)
 {
-       SWITCH_METRICS_OP (METRICS_OP_READ_PIXELS);
+       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 */
@@ -806,10 +974,12 @@ glTexImage1D (GLenum target, GLint level, GLint internalFormat,
              GLsizei width, GLint border, GLenum format, GLenum type,
              const GLvoid *pixels)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
 
        GLWRAP_DEFER (glTexImage1D, target, level, internalFormat, width,
                      border, format, type, pixels);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
@@ -817,22 +987,27 @@ glTexImage2D (GLenum target, GLint level, GLint internalFormat,
              GLsizei width, GLsizei height, GLint border, GLenum format,
              GLenum type, const GLvoid *pixels )
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       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 internalformat, GLsizei width, GLsizei height,
+                        GLint_or_enum internalformat,
+                        GLsizei width, GLsizei height,
                         GLboolean fixedsamplelocations)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
 
        GLWRAP_DEFER (glTexImage2DMultisample, target, samples,
                      internalformat, width, height, fixedsamplelocations);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
@@ -841,11 +1016,13 @@ glTexImage2DMultisampleCoverageNV (GLenum target, GLsizei coverageSamples,
                                   GLsizei width, GLsizei height,
                                   GLboolean fixedSampleLocations)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
 
        GLWRAP_DEFER (glTexImage2DMultisampleCoverageNV, target,
                      coverageSamples, colorSamples, internalFormat,
                      width, height, fixedSampleLocations);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
@@ -853,10 +1030,12 @@ glTexImage3D (GLenum target, GLint level, GLint internalformat,
              GLsizei width, GLsizei height, GLsizei depth, GLint border,
              GLenum format, GLenum type, const GLvoid *pixels)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       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
@@ -864,22 +1043,27 @@ glTexImage3DEXT (GLenum target, GLint level, GLenum internalformat,
                 GLsizei width, GLsizei height, GLsizei depth, GLint border,
                 GLenum format, GLenum type, const GLvoid *pixels)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       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 internalformat,
+glTexImage3DMultisample (GLenum target, GLsizei samples,
+                        GLint_or_enum internalformat,
                         GLsizei width, GLsizei height, GLsizei depth,
                         GLboolean fixedsamplelocations)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
 
        GLWRAP_DEFER (glTexImage3DMultisample, target, samples,
                      internalformat, width, height, depth,
                      fixedsamplelocations);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
@@ -888,11 +1072,13 @@ glTexImage3DMultisampleCoverageNV (GLenum target, GLsizei coverageSamples,
                                   GLsizei width, GLsizei height, GLsizei depth,
                                   GLboolean fixedSampleLocations)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
 
        GLWRAP_DEFER (glTexImage3DMultisampleCoverageNV, target,
                      coverageSamples, colorSamples, internalFormat,
                      width, height, depth, fixedSampleLocations);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
@@ -901,11 +1087,13 @@ glTexImage4DSGIS (GLenum target, GLint level, GLenum internalformat,
                  GLsizei size4d, GLint border, GLenum format,
                  GLenum type, const GLvoid *pixels)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       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
@@ -913,10 +1101,12 @@ glTexSubImage1D (GLenum target, GLint level, GLint xoffset,
                 GLsizei width, GLenum format, GLenum type,
                 const GLvoid *pixels)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
 
        GLWRAP_DEFER (glTexSubImage1D, target, level, xoffset,
                      width, format, type, pixels);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
@@ -924,10 +1114,12 @@ glTexSubImage1DEXT (GLenum target, GLint level, GLint xoffset,
                    GLsizei width, GLenum format, GLenum type,
                    const GLvoid *pixels)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
 
        GLWRAP_DEFER (glTexSubImage1DEXT, target, level, xoffset,
                      width, format, type, pixels);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
@@ -935,10 +1127,12 @@ glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset,
                 GLsizei width, GLsizei height, GLenum format, GLenum type,
                 const GLvoid *pixels)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       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
@@ -946,10 +1140,12 @@ glTexSubImage2DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset,
                    GLsizei width, GLsizei height, GLenum format, GLenum type,
                    const GLvoid *pixels)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       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
@@ -957,10 +1153,12 @@ glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset,
                 GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
                 GLenum format, GLenum type, const GLvoid *pixels)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       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
@@ -968,10 +1166,12 @@ glTexSubImage3DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset,
                    GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
                    GLenum format, GLenum type, const GLvoid *pixels)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       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
@@ -980,11 +1180,13 @@ glTexSubImage4DSGIS (GLenum target, GLint level, GLint xoffset, GLint yoffset,
                     GLsizei height, GLsizei depth, GLsizei size4d,
                     GLenum format, GLenum type, const GLvoid *pixels)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       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
@@ -993,10 +1195,12 @@ glCompressedMultiTexImage1DEXT (GLenum texunit, GLenum target, GLint level,
                                GLint border, GLsizei imageSize,
                                const GLvoid *bits)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
 
        GLWRAP_DEFER (glCompressedMultiTexImage1DEXT, texunit, target,
                      level, internalformat, width, border, imageSize, bits);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
@@ -1005,10 +1209,12 @@ glCompressedMultiTexImage2DEXT (GLenum texunit, GLenum target, GLint level,
                                GLsizei height, GLint border,
                                GLsizei imageSize, const GLvoid *bits)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       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
@@ -1017,11 +1223,13 @@ glCompressedMultiTexImage3DEXT (GLenum texunit, GLenum target, GLint level,
                                GLsizei height, GLsizei depth, GLint border,
                                GLsizei imageSize, const GLvoid *bits)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       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
@@ -1029,10 +1237,12 @@ glCompressedMultiTexSubImage1DEXT (GLenum texunit, GLenum target, GLint level,
                                   GLint xoffset, GLsizei width, GLenum format,
                                   GLsizei imageSize, const GLvoid *bits)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
 
        GLWRAP_DEFER (glCompressedMultiTexSubImage1DEXT, texunit, target,
                      level, xoffset, width, format, imageSize, bits);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
@@ -1041,10 +1251,12 @@ glCompressedMultiTexSubImage2DEXT (GLenum texunit, GLenum target, GLint level,
                                   GLsizei height, GLenum format,
                                   GLsizei imageSize, const GLvoid *bits)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       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
@@ -1054,11 +1266,13 @@ glCompressedMultiTexSubImage3DEXT (GLenum texunit, GLenum target, GLint level,
                                   GLenum format, GLsizei imageSize,
                                   const GLvoid *bits)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       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
@@ -1066,10 +1280,12 @@ glCompressedTexImage1D (GLenum target, GLint level, GLenum internalformat,
                        GLsizei width, GLint border, GLsizei imageSize,
                        const GLvoid *data)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
 
        GLWRAP_DEFER (glCompressedTexImage1D, target, level,
                      internalformat, width, border, imageSize, data);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
@@ -1077,10 +1293,12 @@ glCompressedTexImage1DARB (GLenum target, GLint level, GLenum internalformat,
                           GLsizei width, GLint border, GLsizei imageSize,
                           const GLvoid *data)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
 
        GLWRAP_DEFER (glCompressedTexImage1DARB, target, level, internalformat,
                      width, border, imageSize, data);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
@@ -1088,10 +1306,12 @@ glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat,
                        GLsizei width, GLsizei height, GLint border,
                        GLsizei imageSize, const GLvoid *data)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
 
        GLWRAP_DEFER (glCompressedTexImage2D, target, level, internalformat,
                      width, height, border, imageSize, data);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
@@ -1099,10 +1319,12 @@ glCompressedTexImage2DARB (GLenum target, GLint level, GLenum internalformat,
                           GLsizei width, GLsizei height, GLint border,
                           GLsizei imageSize, const GLvoid *data)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
 
        GLWRAP_DEFER (glCompressedTexImage2DARB, target, level, internalformat,
                      width, height, border, imageSize, data);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
@@ -1110,10 +1332,12 @@ glCompressedTexImage3D (GLenum target, GLint level, GLenum internalformat,
                        GLsizei width, GLsizei height, GLsizei depth,
                        GLint border, GLsizei imageSize, const GLvoid *data)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       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
@@ -1121,10 +1345,12 @@ glCompressedTexImage3DARB (GLenum target, GLint level, GLenum internalformat,
                           GLsizei width, GLsizei height, GLsizei depth,
                           GLint border, GLsizei imageSize, const GLvoid *data)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       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
@@ -1132,10 +1358,12 @@ glCompressedTexSubImage1D (GLenum target, GLint level, GLint xoffset,
                           GLsizei width, GLenum format, GLsizei imageSize,
                           const GLvoid *data)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
 
        GLWRAP_DEFER (glCompressedTexSubImage1D, target, level, xoffset,
                      width, format, imageSize, data);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
@@ -1143,10 +1371,12 @@ glCompressedTexSubImage1DARB (GLenum target, GLint level, GLint xoffset,
                              GLsizei width, GLenum format, GLsizei imageSize,
                              const GLvoid *data)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
 
        GLWRAP_DEFER (glCompressedTexSubImage1DARB, target, level, xoffset,
                      width, format, imageSize, data);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
@@ -1154,10 +1384,12 @@ glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset,
                           GLint yoffset, GLsizei width, GLsizei height,
                           GLenum format, GLsizei imageSize, const GLvoid *data)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       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
@@ -1166,10 +1398,12 @@ glCompressedTexSubImage2DARB (GLenum target, GLint level, GLint xoffset,
                              GLenum format, GLsizei imageSize,
                              const GLvoid *data)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       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
@@ -1178,11 +1412,13 @@ glCompressedTexSubImage3D (GLenum target, GLint level, GLint xoffset,
                           GLsizei height, GLsizei depth, GLenum format,
                           GLsizei imageSize, const GLvoid *data)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       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
@@ -1191,11 +1427,13 @@ glCompressedTexSubImage3DARB (GLenum target, GLint level, GLint xoffset,
                              GLsizei height, GLsizei depth, GLenum format,
                              GLsizei imageSize, const GLvoid *data)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       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
@@ -1204,10 +1442,12 @@ glCompressedTextureImage1DEXT (GLuint texture, GLenum target, GLint level,
                               GLint border, GLsizei imageSize,
                               const GLvoid *bits)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
 
        GLWRAP_DEFER (glCompressedTextureImage1DEXT, texture, target, level,
                      internalformat, width, border, imageSize, bits);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
@@ -1216,10 +1456,12 @@ glCompressedTextureImage2DEXT (GLuint texture, GLenum target, GLint level,
                               GLsizei height, GLint border,
                               GLsizei imageSize, const GLvoid *bits)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       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
@@ -1228,11 +1470,13 @@ glCompressedTextureImage3DEXT (GLuint texture, GLenum target, GLint level,
                               GLsizei height, GLsizei depth, GLint border,
                               GLsizei imageSize, const GLvoid *bits)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       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
@@ -1240,10 +1484,12 @@ glCompressedTextureSubImage1DEXT (GLuint texture, GLenum target, GLint level,
                                  GLint xoffset, GLsizei width, GLenum format,
                                  GLsizei imageSize, const GLvoid *bits)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
 
        GLWRAP_DEFER (glCompressedTextureSubImage1DEXT, texture, target,
                      level, xoffset, width, format, imageSize, bits);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
@@ -1252,10 +1498,12 @@ glCompressedTextureSubImage2DEXT (GLuint texture, GLenum target, GLint level,
                                  GLsizei height, GLenum format,
                                  GLsizei imageSize, const GLvoid *bits)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       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
@@ -1265,48 +1513,59 @@ glCompressedTextureSubImage3DEXT (GLuint texture, GLenum target, GLint level,
                                  GLenum format, GLsizei imageSize,
                                  const GLvoid *bits)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       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 internalformat, GLsizei width, GLint border,
+                     GLenum_or_int internalformat,
+                     GLsizei width, GLint border,
                      GLenum format, GLenum type, const GLvoid *pixels)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       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 internalformat, GLsizei width, GLsizei height,
+                     GLenum_or_int internalformat,
+                     GLsizei width, GLsizei height,
                      GLint border, GLenum format, GLenum type,
                      const GLvoid *pixels)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       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 internalformat, GLsizei width, GLsizei height,
+                     GLenum_or_int internalformat,
+                     GLsizei width, GLsizei height,
                      GLsizei depth, GLint border, GLenum format,
                      GLenum type, const GLvoid *pixels)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       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
@@ -1314,10 +1573,12 @@ glMultiTexSubImage1DEXT (GLenum texunit, GLenum target, GLint level,
                         GLint xoffset, GLsizei width, GLenum format,
                         GLenum type, const GLvoid *pixels)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       SAVE_THEN_SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
 
        GLWRAP_DEFER (glMultiTexSubImage1DEXT, texunit, target, level,
                      xoffset, width, format, type, pixels);
+
+       RESTORE_METRICS_OP ();
 }
 
 void
@@ -1326,10 +1587,12 @@ glMultiTexSubImage2DEXT (GLenum texunit, GLenum target, GLint level,
                         GLsizei height, GLenum format, GLenum type,
                         const GLvoid *pixels)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       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
@@ -1338,9 +1601,11 @@ glMultiTexSubImage3DEXT (GLenum texunit, GLenum target, GLint level,
                         GLsizei width, GLsizei height, GLsizei depth,
                         GLenum format, GLenum type, const GLvoid *pixels)
 {
-       SWITCH_METRICS_OP (METRICS_OP_TEX_IMAGE);
+       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 ();
 }