more work on GL_ARB_texture_compression
authorBrian Paul <brian.paul@tungstengraphics.com>
Tue, 6 Jun 2000 17:03:38 +0000 (17:03 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Tue, 6 Jun 2000 17:03:38 +0000 (17:03 +0000)
src/mesa/main/dd.h
src/mesa/main/dlist.c
src/mesa/main/teximage.c

index 106d99d780f4963d8e4ddf8e27b291098c62f51b..ad389df4a5d6da5e688e522c99fc754352c6f218 100644 (file)
@@ -667,6 +667,47 @@ struct dd_function_table {
     * should do the job.
     */
 
+   GLboolean (*CompressedTexSubImage1D)( GLcontext *ctx, GLenum target,
+                                         GLint level, GLint xoffset,
+                                         GLsizei width, GLenum format,
+                                         GLsizei imageSize, const GLvoid *data,
+                                         struct gl_texture_object *texObj,
+                                         struct gl_texture_image *texImage );
+   GLboolean (*CompressedTexSubImage2D)( GLcontext *ctx, GLenum target,
+                                         GLint level, GLint xoffset,
+                                         GLint yoffset, GLsizei width,
+                                         GLint height, GLenum format,
+                                         GLsizei imageSize, const GLvoid *data,
+                                         struct gl_texture_object *texObj,
+                                         struct gl_texture_image *texImage );
+   GLboolean (*CompressedTexSubImage3D)( GLcontext *ctx, GLenum target,
+                                         GLint level, GLint xoffset,
+                                         GLint yoffset, GLint zoffset,
+                                         GLsizei width, GLint height,
+                                         GLint depth, GLenum format,
+                                         GLsizei imageSize, const GLvoid *data,
+                                         struct gl_texture_object *texObj,
+                                         struct gl_texture_image *texImage );
+   /* Called by glCompressedTexSubImage1/2/3D.
+    * Arguments:
+    *   <target>, <level>, <x/z/zoffset>, <width>, <height>, <depth>,
+    *      <imageSize>, and <data> are user specified.
+    *   <texObj> is the target texture object.
+    *   <texImage> is the target texture image.  It will have the texture
+    *      width, height, depth, border and internalFormat information.
+    * Return GL_TRUE if operation completed, return GL_FALSE if core Mesa
+    * should do the job.
+    */
+
+   void (*GetCompressedTexImage)( GLcontext *ctx, GLenum target,
+                                  GLint lod, void *image,
+                                  const struct gl_texture_object *texObj,
+                                  struct gl_texture_image *texImage );
+   /* Called by glGetCompressedTexImageARB.
+    * <target>, <lod>, <image> are specified by user.
+    * <texObj> is the source texture object.
+    * <texImage> is the source texture image.
+    */
 
    void (*TexEnv)( GLcontext *ctx, GLenum target, GLenum pname,
                    const GLfloat *param );
index 2f291a6bdee6249415d2fe225f773956ab49c5f5..637aecff5e6554730e5d19d96215f3aa2a5a9fee 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: dlist.c,v 1.41 2000/05/24 15:04:45 brianp Exp $ */
+/* $Id: dlist.c,v 1.42 2000/06/06 17:03:38 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -245,6 +245,13 @@ typedef enum {
         /* GL_SGIX/SGIS_pixel_texture */
         OPCODE_PIXEL_TEXGEN_SGIX,
         OPCODE_PIXEL_TEXGEN_PARAMETER_SGIS,
+        /* GL_ARB_texture_compression */
+        OPCODE_COMPRESSED_TEX_IMAGE_1D,
+        OPCODE_COMPRESSED_TEX_IMAGE_2D,
+        OPCODE_COMPRESSED_TEX_IMAGE_3D,
+        OPCODE_COMPRESSED_TEX_SUB_IMAGE_1D,
+        OPCODE_COMPRESSED_TEX_SUB_IMAGE_2D,
+        OPCODE_COMPRESSED_TEX_SUB_IMAGE_3D,
        /* The following three are meta instructions */
        OPCODE_ERROR,           /* raise compiled-in error */
        OPCODE_VERTEX_CASSETTE, /* render prebuilt vertex buffer */
@@ -420,6 +427,30 @@ void gl_destroy_list( GLcontext *ctx, GLuint list )
             FREE(n[11].data);
             n += InstSize[n[0].opcode];
             break;
+         case OPCODE_COMPRESSED_TEX_IMAGE_1D:
+            FREE(n[7].data);
+            n += InstSize[n[0].opcode];
+            break;
+         case OPCODE_COMPRESSED_TEX_IMAGE_2D:
+            FREE(n[8].data);
+            n += InstSize[n[0].opcode];
+            break;
+         case OPCODE_COMPRESSED_TEX_IMAGE_3D:
+            FREE(n[9].data);
+            n += InstSize[n[0].opcode];
+            break;
+         case OPCODE_COMPRESSED_TEX_SUB_IMAGE_1D:
+            FREE(n[7].data);
+            n += InstSize[n[0].opcode];
+            break;
+         case OPCODE_COMPRESSED_TEX_SUB_IMAGE_2D:
+            FREE(n[9].data);
+            n += InstSize[n[0].opcode];
+            break;
+         case OPCODE_COMPRESSED_TEX_SUB_IMAGE_3D:
+            FREE(n[11].data);
+            n += InstSize[n[0].opcode];
+            break;
         case OPCODE_CONTINUE:
            n = (Node *) n[1].next;
            FREE( block );
@@ -628,7 +659,14 @@ void gl_init_lists( void )
       InstSize[OPCODE_END_OF_LIST] = 1;
       /* GL_SGIX/SGIS_pixel_texture */
       InstSize[OPCODE_PIXEL_TEXGEN_SGIX] = 2;
-      InstSize[OPCODE_PIXEL_TEXGEN_PARAMETER_SGIS] = 3,
+      InstSize[OPCODE_PIXEL_TEXGEN_PARAMETER_SGIS] = 3;
+      /* GL_ARB_texture_compression */
+      InstSize[OPCODE_COMPRESSED_TEX_IMAGE_1D] = 8;
+      InstSize[OPCODE_COMPRESSED_TEX_IMAGE_2D] = 9;
+      InstSize[OPCODE_COMPRESSED_TEX_IMAGE_3D] = 10;
+      InstSize[OPCODE_COMPRESSED_TEX_SUB_IMAGE_1D] = 8;
+      InstSize[OPCODE_COMPRESSED_TEX_SUB_IMAGE_2D] = 10;
+      InstSize[OPCODE_COMPRESSED_TEX_SUB_IMAGE_3D] = 12;
       /* GL_ARB_multitexture */
       InstSize[OPCODE_ACTIVE_TEXTURE] = 2;
       InstSize[OPCODE_CLIENT_ACTIVE_TEXTURE] = 2;
@@ -3611,28 +3649,136 @@ static void save_PixelTexGenSGIX(GLenum mode)
 /* GL_ARB_texture_compression */
 static void
 save_CompressedTexImage1DARB(GLenum target, GLint level,
-                             GLenum internalformat, GLsizei width,
+                             GLenum internalFormat, GLsizei width,
                              GLint border, GLsizei imageSize,
                              const GLvoid *data)
 {
+   GET_CURRENT_CONTEXT(ctx);
+   if (target == GL_PROXY_TEXTURE_1D) {
+      /* don't compile, execute immediately */
+      (*ctx->Exec->CompressedTexImage1DARB)(target, level, internalFormat,
+                                            width, border, imageSize, data);
+   }
+   else {
+      Node *n;
+      GLvoid *image;
+      FLUSH_VB(ctx, "dlist");
+      /* make copy of image */
+      image = MALLOC(imageSize);
+      if (!image) {
+         gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1DARB");
+         return;
+      }
+      MEMCPY(image, data, imageSize);
+      n = alloc_instruction( ctx, OPCODE_COMPRESSED_TEX_IMAGE_1D, 8 );
+      if (n) {
+         n[1].e = target;
+         n[2].i = level;
+         n[3].e = internalFormat;
+         n[4].i = (GLint) width;
+         n[5].i = border;
+         n[6].i = imageSize;
+         n[7].data = image;
+      }
+      else if (image) {
+         FREE(image);
+      }
+      if (ctx->ExecuteFlag) {
+         (*ctx->Exec->CompressedTexImage1DARB)(target, level, internalFormat,
+                                               width, border, imageSize, data);
+      }
+   }
 }
 
 
 static void
 save_CompressedTexImage2DARB(GLenum target, GLint level,
-                             GLenum internalformat, GLsizei width,
+                             GLenum internalFormat, GLsizei width,
                              GLsizei height, GLint border, GLsizei imageSize,
                              const GLvoid *data)
 {
+   GET_CURRENT_CONTEXT(ctx);
+   if (target == GL_PROXY_TEXTURE_2D) {
+      /* don't compile, execute immediately */
+      (*ctx->Exec->CompressedTexImage2DARB)(target, level, internalFormat,
+                                       width, height, border, imageSize, data);
+   }
+   else {
+      Node *n;
+      GLvoid *image;
+      FLUSH_VB(ctx, "dlist");
+      /* make copy of image */
+      image = MALLOC(imageSize);
+      if (!image) {
+         gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB");
+         return;
+      }
+      MEMCPY(image, data, imageSize);
+      n = alloc_instruction( ctx, OPCODE_COMPRESSED_TEX_IMAGE_2D, 9 );
+      if (n) {
+         n[1].e = target;
+         n[2].i = level;
+         n[3].e = internalFormat;
+         n[4].i = (GLint) width;
+         n[5].i = (GLint) height;
+         n[6].i = border;
+         n[7].i = imageSize;
+         n[8].data = image;
+      }
+      else if (image) {
+         FREE(image);
+      }
+      if (ctx->ExecuteFlag) {
+         (*ctx->Exec->CompressedTexImage2DARB)(target, level, internalFormat,
+                                      width, height, border, imageSize, data);
+      }
+   }
 }
 
 
 static void
 save_CompressedTexImage3DARB(GLenum target, GLint level,
-                             GLenum internalformat, GLsizei width,
+                             GLenum internalFormat, GLsizei width,
                              GLsizei height, GLsizei depth, GLint border,
                              GLsizei imageSize, const GLvoid *data)
 {
+   GET_CURRENT_CONTEXT(ctx);
+   if (target == GL_PROXY_TEXTURE_3D) {
+      /* don't compile, execute immediately */
+      (*ctx->Exec->CompressedTexImage3DARB)(target, level, internalFormat,
+                                width, height, depth, border, imageSize, data);
+   }
+   else {
+      Node *n;
+      GLvoid *image;
+      FLUSH_VB(ctx, "dlist");
+      /* make copy of image */
+      image = MALLOC(imageSize);
+      if (!image) {
+         gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3DARB");
+         return;
+      }
+      MEMCPY(image, data, imageSize);
+      n = alloc_instruction( ctx, OPCODE_COMPRESSED_TEX_IMAGE_3D, 10 );
+      if (n) {
+         n[1].e = target;
+         n[2].i = level;
+         n[3].e = internalFormat;
+         n[4].i = (GLint) width;
+         n[5].i = (GLint) height;
+         n[6].i = (GLint) depth;
+         n[7].i = border;
+         n[8].i = imageSize;
+         n[9].data = image;
+      }
+      else if (image) {
+         FREE(image);
+      }
+      if (ctx->ExecuteFlag) {
+         (*ctx->Exec->CompressedTexImage3DARB)(target, level, internalFormat,
+                                width, height, depth, border, imageSize, data);
+      }
+   }
 }
 
 
@@ -3641,6 +3787,36 @@ save_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
                                 GLsizei width, GLenum format,
                                 GLsizei imageSize, const GLvoid *data)
 {
+   Node *n;
+   GLvoid *image;
+
+   GET_CURRENT_CONTEXT(ctx);
+   FLUSH_VB(ctx, "dlist");
+
+   /* make copy of image */
+   image = MALLOC(imageSize);
+   if (!image) {
+      gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage1DARB");
+      return;
+   }
+   MEMCPY(image, data, imageSize);
+   n = alloc_instruction( ctx, OPCODE_COMPRESSED_TEX_SUB_IMAGE_1D, 8 );
+   if (n) {
+      n[1].e = target;
+      n[2].i = level;
+      n[3].i = xoffset;
+      n[4].i = (GLint) width;
+      n[5].e = format;
+      n[6].i = imageSize;
+      n[7].data = image;
+   }
+   else if (image) {
+      FREE(image);
+   }
+   if (ctx->ExecuteFlag) {
+      (*ctx->Exec->CompressedTexSubImage1DARB)(target, level, xoffset,
+                                               width, format, imageSize, data);
+   }
 }
 
 
@@ -3650,6 +3826,38 @@ save_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
                                 GLenum format, GLsizei imageSize,
                                 const GLvoid *data)
 {
+   Node *n;
+   GLvoid *image;
+
+   GET_CURRENT_CONTEXT(ctx);
+   FLUSH_VB(ctx, "dlist");
+
+   /* make copy of image */
+   image = MALLOC(imageSize);
+   if (!image) {
+      gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage2DARB");
+      return;
+   }
+   MEMCPY(image, data, imageSize);
+   n = alloc_instruction( ctx, OPCODE_COMPRESSED_TEX_SUB_IMAGE_2D, 10 );
+   if (n) {
+      n[1].e = target;
+      n[2].i = level;
+      n[3].i = xoffset;
+      n[4].i = yoffset;
+      n[5].i = (GLint) width;
+      n[6].i = (GLint) height;
+      n[7].e = format;
+      n[8].i = imageSize;
+      n[9].data = image;
+   }
+   else if (image) {
+      FREE(image);
+   }
+   if (ctx->ExecuteFlag) {
+      (*ctx->Exec->CompressedTexSubImage2DARB)(target, level, xoffset, yoffset,
+                                       width, height, format, imageSize, data);
+   }
 }
 
 
@@ -3659,6 +3867,40 @@ save_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
                                 GLsizei height, GLsizei depth, GLenum format,
                                 GLsizei imageSize, const GLvoid *data)
 {
+   Node *n;
+   GLvoid *image;
+
+   GET_CURRENT_CONTEXT(ctx);
+   FLUSH_VB(ctx, "dlist");
+
+   /* make copy of image */
+   image = MALLOC(imageSize);
+   if (!image) {
+      gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage3DARB");
+      return;
+   }
+   MEMCPY(image, data, imageSize);
+   n = alloc_instruction( ctx, OPCODE_COMPRESSED_TEX_SUB_IMAGE_3D, 12 );
+   if (n) {
+      n[1].e = target;
+      n[2].i = level;
+      n[3].i = xoffset;
+      n[4].i = yoffset;
+      n[5].i = zoffset;
+      n[6].i = (GLint) width;
+      n[7].i = (GLint) height;
+      n[8].i = (GLint) depth;
+      n[9].e = format;
+      n[10].i = imageSize;
+      n[11].data = image;
+   }
+   else if (image) {
+      FREE(image);
+   }
+   if (ctx->ExecuteFlag) {
+      (*ctx->Exec->CompressedTexSubImage3DARB)(target, level, xoffset, yoffset,
+                       zoffset, width, height, depth, format, imageSize, data);
+   }
 }
 
 
@@ -4433,6 +4675,31 @@ static void execute_list( GLcontext *ctx, GLuint list )
          case OPCODE_PIXEL_TEXGEN_PARAMETER_SGIS:  /* GL_SGIS_pixel_texture */
             (*ctx->Exec->PixelTexGenParameteriSGIS)( n[1].e, n[2].i );
             break;
+         case OPCODE_COMPRESSED_TEX_IMAGE_1D: /* GL_ARB_texture_compression */
+            (*ctx->Exec->CompressedTexImage1DARB)(n[1].e, n[2].i, n[3].e,
+                                            n[4].i, n[5].i, n[6].i, n[7].data);
+            break;
+         case OPCODE_COMPRESSED_TEX_IMAGE_2D: /* GL_ARB_texture_compression */
+            (*ctx->Exec->CompressedTexImage2DARB)(n[1].e, n[2].i, n[3].e,
+                                    n[4].i, n[5].i, n[6].i, n[7].i, n[8].data);
+            break;
+         case OPCODE_COMPRESSED_TEX_IMAGE_3D: /* GL_ARB_texture_compression */
+            (*ctx->Exec->CompressedTexImage3DARB)(n[1].e, n[2].i, n[3].e,
+                            n[4].i, n[5].i, n[6].i, n[7].i, n[8].i, n[9].data);
+            break;
+         case OPCODE_COMPRESSED_TEX_SUB_IMAGE_1D: /* GL_ARB_texture_compress */
+            (*ctx->Exec->CompressedTexSubImage1DARB)(n[1].e, n[2].i, n[3].i,
+                                            n[4].i, n[5].e, n[6].i, n[7].data);
+            break;
+         case OPCODE_COMPRESSED_TEX_SUB_IMAGE_2D: /* GL_ARB_texture_compress */
+            (*ctx->Exec->CompressedTexSubImage2DARB)(n[1].e, n[2].i, n[3].i,
+                            n[4].i, n[5].i, n[6].i, n[7].e, n[8].i, n[9].data);
+            break;
+         case OPCODE_COMPRESSED_TEX_SUB_IMAGE_3D: /* GL_ARB_texture_compress */
+            (*ctx->Exec->CompressedTexSubImage3DARB)(n[1].e, n[2].i, n[3].i,
+                                        n[4].i, n[5].i, n[6].i, n[7].i, n[8].i,
+                                        n[9].e, n[10].i, n[11].data);
+            break;
         case OPCODE_CONTINUE:
            n = (Node *) n[1].next;
            break;
index d94b65fb3a7486c1f8979f7b9863cbfce061db14..0d25df6d81ef112cccd682e13e42406ccc66e17f 100644 (file)
@@ -1125,11 +1125,13 @@ subtexture_error_check( GLcontext *ctx, GLuint dimensions,
       }
    }
 
-   if (!_mesa_is_legal_format_and_type(format, type)) {
-      char message[100];
-      sprintf(message, "glTexSubImage%dD(format or type)", dimensions);
-      gl_error(ctx, GL_INVALID_ENUM, message);
-      return GL_TRUE;
+   if (!is_compressed_format(destTex->IntFormat)) {
+      if (!_mesa_is_legal_format_and_type(format, type)) {
+         char message[100];
+         sprintf(message, "glTexSubImage%dD(format or type)", dimensions);
+         gl_error(ctx, GL_INVALID_ENUM, message);
+         return GL_TRUE;
+      }
    }
 
    return GL_FALSE;
@@ -1810,19 +1812,45 @@ _mesa_GetTexImage( GLenum target, GLint level, GLenum format,
    switch (target) {
       case GL_TEXTURE_1D:
          texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[1];
+         texImage = texObj->Image[level];
          break;
       case GL_TEXTURE_2D:
          texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[2];
+         texImage = texObj->Image[level];
+         break;
+      case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
+         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
+         texImage = texObj->Image[level];
+         break;
+      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
+         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
+         texImage = texObj->NegX[level];
+         break;
+      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
+         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
+         texImage = texObj->PosY[level];
+         break;
+      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
+         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
+         texImage = texObj->NegY[level];
+         break;
+      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
+         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
+         texImage = texObj->PosZ[level];
+         break;
+      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
+         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
+         texImage = texObj->NegZ[level];
          break;
       case GL_TEXTURE_3D:
          texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[3];
+         texImage = texObj->Image[level];
          break;
       default:
          gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(target)" );
          return;
    }
 
-   texImage = texObj->Image[level];
    if (!texImage) {
       /* invalid mipmap level */
       return;
@@ -2581,7 +2609,10 @@ _mesa_CompressedTexImage2DARB(GLenum target, GLint level,
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage2DARB");
 
-   if (target == GL_TEXTURE_2D) {
+   if (target==GL_TEXTURE_2D ||
+       (ctx->Extensions.HaveTextureCubeMap &&
+        target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
+        target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
       struct gl_texture_unit *texUnit;
       struct gl_texture_object *texObj;
       struct gl_texture_image *texImage;
@@ -2678,7 +2709,7 @@ _mesa_CompressedTexImage3DARB(GLenum target, GLint level,
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage3DARB");
 
-   if (target == GL_TEXTURE_1D) {
+   if (target == GL_TEXTURE_3D) {
       struct gl_texture_unit *texUnit;
       struct gl_texture_object *texObj;
       struct gl_texture_image *texImage;
@@ -2771,6 +2802,35 @@ _mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
                                  GLsizei width, GLenum format,
                                  GLsizei imageSize, const GLvoid *data)
 {
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_texture_unit *texUnit;
+   struct gl_texture_object *texObj;
+   struct gl_texture_image *texImage;
+   GLboolean success = GL_FALSE;
+
+   if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
+                              width, 1, 1, format, GL_NONE)) {
+      return;   /* error was detected */
+   }
+
+   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+   texObj = _mesa_select_tex_object(ctx, texUnit, target);
+   texImage = texObj->Image[level];
+   assert(texImage);
+
+   if (width == 0 || !data)
+      return;  /* no-op, not an error */
+
+   if (ctx->Driver.CompressedTexSubImage1D) {
+      success = (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level,
+                   xoffset, width, format, imageSize, data, texObj, texImage);
+   }
+   if (!success) {
+      /* XXX what else can we do? */
+      gl_problem(ctx, "glCompressedTexSubImage1DARB failed!");
+      return;
+   }
+
 }
 
 
@@ -2780,6 +2840,35 @@ _mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
                                  GLenum format, GLsizei imageSize,
                                  const GLvoid *data)
 {
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_texture_unit *texUnit;
+   struct gl_texture_object *texObj;
+   struct gl_texture_image *texImage;
+   GLboolean success = GL_FALSE;
+
+   if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
+                              width, height, 1, format, GL_NONE)) {
+      return;   /* error was detected */
+   }
+
+   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+   texObj = _mesa_select_tex_object(ctx, texUnit, target);
+   texImage = texObj->Image[level];
+   assert(texImage);
+
+   if (width == 0 || height == 0 || !data)
+      return;  /* no-op, not an error */
+
+   if (ctx->Driver.CompressedTexSubImage2D) {
+      success = (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level,
+                                       xoffset, yoffset, width, height, format,
+                                       imageSize, data, texObj, texImage);
+   }
+   if (!success) {
+      /* XXX what else can we do? */
+      gl_problem(ctx, "glCompressedTexSubImage2DARB failed!");
+      return;
+   }
 }
 
 
@@ -2789,10 +2878,113 @@ _mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
                                  GLsizei height, GLsizei depth, GLenum format,
                                  GLsizei imageSize, const GLvoid *data)
 {
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_texture_unit *texUnit;
+   struct gl_texture_object *texObj;
+   struct gl_texture_image *texImage;
+   GLboolean success = GL_FALSE;
+
+   if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
+                              width, height, depth, format, GL_NONE)) {
+      return;   /* error was detected */
+   }
+
+   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+   texObj = _mesa_select_tex_object(ctx, texUnit, target);
+   texImage = texObj->Image[level];
+   assert(texImage);
+
+   if (width == 0 || height == 0 || depth == 0 || !data)
+      return;  /* no-op, not an error */
+
+   if (ctx->Driver.CompressedTexSubImage3D) {
+      success = (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level,
+                               xoffset, yoffset, zoffset, width, height, depth,
+                               format, imageSize, data, texObj, texImage);
+   }
+   if (!success) {
+      /* XXX what else can we do? */
+      gl_problem(ctx, "glCompressedTexSubImage3DARB failed!");
+      return;
+   }
 }
 
 
 void
-_mesa_GetCompressedTexImageARB(GLenum target, GLint lod, GLvoid *img)
+_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
 {
+   GET_CURRENT_CONTEXT(ctx);
+   const struct gl_texture_object *texObj;
+   struct gl_texture_image *texImage;
+
+   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetCompressedTexImageARB");
+
+   if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
+      gl_error( ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)" );
+      return;
+   }
+
+   switch (target) {
+      case GL_TEXTURE_1D:
+         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[1];
+         texImage = texObj->Image[level];
+         break;
+      case GL_TEXTURE_2D:
+         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[2];
+         texImage = texObj->Image[level];
+         break;
+      case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
+         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
+         texImage = texObj->Image[level];
+         break;
+      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
+         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
+         texImage = texObj->NegX[level];
+         break;
+      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
+         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
+         texImage = texObj->PosY[level];
+         break;
+      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
+         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
+         texImage = texObj->NegY[level];
+         break;
+      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
+         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
+         texImage = texObj->PosZ[level];
+         break;
+      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
+         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
+         texImage = texObj->NegZ[level];
+         break;
+      case GL_TEXTURE_3D:
+         texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[3];
+         texImage = texObj->Image[level];
+         break;
+      default:
+         gl_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");
+         return;
+   }
+
+   if (!texImage) {
+      /* invalid mipmap level */
+      gl_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
+      return;
+   }
+
+   if (!texImage->IsCompressed) {
+      gl_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB");
+      return;
+   }
+
+   if (!img)
+      return;
+
+   if (ctx->Driver.GetCompressedTexImage) {
+      (*ctx->Driver.GetCompressedTexImage)(ctx, target, level, img, texObj,
+                                           texImage);
+   }
+   else {
+      gl_problem(ctx, "Driver doesn't implement GetCompressedTexImage");
+   }
 }