<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Sat, Dec 13, 2014 at 6:42 AM, Brian Paul <span dir="ltr"><<a href="mailto:brianp@vmware.com" target="_blank">brianp@vmware.com</a>></span> wrote:<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">---<br>
 src/mesa/main/texgetimage.c | 440 +++++++++++++++++++++++++++++---------------<br>
 src/mesa/main/texgetimage.h |   7 +<br>
 2 files changed, 297 insertions(+), 150 deletions(-)<br>
<br>
diff --git a/src/mesa/main/texgetimage.c b/src/mesa/main/texgetimage.c<br>
index ced6a34..ac0be35 100644<br>
--- a/src/mesa/main/texgetimage.c<br>
+++ b/src/mesa/main/texgetimage.c<br>
@@ -25,7 +25,8 @@<br>
<br>
<br>
 /**<br>
- * Code for glGetTexImage() and glGetCompressedTexImage().<br>
+ * Code for glGetTexImage(), glGetCompressedTexImage(),<br>
+ * glGetTextureSubImage() and glGetCompressedTextureSubImage(),<br>
  */<br>
<br>
<br>
@@ -717,10 +718,8 @@ _mesa_get_compressed_texsubimage(struct gl_context *ctx,<br>
    GLubyte *dest;<br>
<br>
    _mesa_compute_compressed_pixelstore(dimensions, texImage->TexFormat,<br>
-                                       texImage->Width, texImage->Height,<br>
-                                       texImage->Depth,<br>
-                                       &ctx->Pack,<br>
-                                       &store);<br>
+                                       width, height, depth,<br>
+                                       &ctx->Pack, &store);<br>
<br>
    if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {<br>
       /* pack texture image into a PBO */<br>
@@ -731,7 +730,7 @@ _mesa_get_compressed_texsubimage(struct gl_context *ctx,<br>
       if (!dest) {<br>
          /* out of memory or other unexpected error */<br>
          _mesa_error(ctx, GL_OUT_OF_MEMORY,<br>
-                     "glGetCompresssedTexImage(map PBO failed)");<br>
+                "glGetCompresssedTexImage/TextureSubImage(map PBO failed)");<br>
          return;<br>
       }<br>
       dest = ADD_POINTERS(dest, img);<br>
@@ -746,25 +745,27 @@ _mesa_get_compressed_texsubimage(struct gl_context *ctx,<br>
       GLubyte *src;<br>
<br>
       /* map src texture buffer */<br>
-      ctx->Driver.MapTextureImage(ctx, texImage, 0,<br>
-                                  0, 0, texImage->Width, texImage->Height,<br>
+      ctx->Driver.MapTextureImage(ctx, texImage, zoffset + slice,<br>
+                                  xoffset, yoffset, width, height,<br>
                                   GL_MAP_READ_BIT, &src, &srcRowStride);<br>
<br>
       if (src) {<br>
-<br>
+         /* Copy a row of blocks */<br>
          for (i = 0; i < store.CopyRowsPerSlice; i++) {<br>
             memcpy(dest, src, store.CopyBytesPerRow);<br>
             dest += store.TotalBytesPerRow;<br>
             src += srcRowStride;<br>
          }<br>
<br>
-         ctx->Driver.UnmapTextureImage(ctx, texImage, 0);<br>
+         ctx->Driver.UnmapTextureImage(ctx, texImage, zoffset + slice);<br>
<br>
          /* Advance to next slice */<br>
          dest += store.TotalBytesPerRow * (store.TotalRowsPerSlice - store.CopyRowsPerSlice);<br>
<br>
       } else {<br>
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetCompresssedTexImage");<br>
+         _mesa_error(ctx, GL_OUT_OF_MEMORY,<br>
+                     "glGetCompresssedTexImage/TextureSubImage");<br>
+         break; /* don't try the remaining slices */<br>
       }<br>
    }<br>
<br>
@@ -821,6 +822,12 @@ getteximage_error_check(struct gl_context *ctx,<br>
    const GLint maxLevels = _mesa_max_texture_levels(ctx, target);<br>
    GLenum baseFormat, err;<br>
<br>
+   if (maxLevels == 0) {<br>
+      /* invalid texture (gen'd but never defined) */<br>
+      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid texture)", caller);<br>
+      return GL_TRUE;<br>
+   }<br>
+<br>
    assert(maxLevels != 0);<br>
    if (level < 0 || level >= maxLevels) {<br>
       _mesa_error(ctx, GL_INVALID_VALUE, "%s(level)", caller);<br>
@@ -888,7 +895,9 @@ getteximage_error_check(struct gl_context *ctx,<br>
<br>
<br>
 /**<br>
- * Do error checking related to the PBO and image size.<br>
+ * Do error checking related to the PBO and image size (for returning<br>
+ * uncompressed images only).<br>
+ * \return true if error is found, false otherwise.<br>
  */<br>
 static bool<br>
 pbo_error_check(struct gl_context *ctx, GLenum target,<br>
@@ -1006,145 +1015,36 @@ _mesa_GetTexImage( GLenum target, GLint level, GLenum format,<br>
<br>
<br>
 /**<br>
- * Do error checking for a glGetCompressedTexImage() call.<br>
- * \return GL_TRUE if any error, GL_FALSE if no errors.<br>
+ * Compute the number of bytes that will be read/written from/to a buffer<br>
+ * when packing/unpacking a compressed image.  This observes the given GL<br>
+ * pixel store state which may specify non-default GL_SKIP_PIXEL,<br>
+ * GL_ROW_LENGTH, etc. values for compressed images.<br>
+ * Basically, if the value we compute here is larger than the dest/src buffer<br>
+ * size, we'll have to raise an GL_INVALID_OPERATION (out of bounds) error.<br>
+ *<br>
+ * \return number of bytes which will be read/written.<br>
  */<br>
-static GLboolean<br>
-getcompressedteximage_error_check(struct gl_context *ctx, GLenum target,<br>
-                                  GLint level, GLsizei clientMemSize, GLvoid *img)<br>
+static GLsizei<br>
+packed_compressed_size(GLuint dimensions, mesa_format format,<br>
+                       GLsizei width, GLsizei height, GLsizei depth,<br>
+                       const struct gl_pixelstore_attrib *packing)<br>
 {<br>
-   struct gl_texture_object *texObj;<br>
-   struct gl_texture_image *texImage;<br>
-   const GLint maxLevels = _mesa_max_texture_levels(ctx, target);<br>
-   GLuint compressedSize, dimensions;<br>
-<br>
-   if (!legal_getteximage_target(ctx, target)) {<br>
-      _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImage(target=0x%x)",<br>
-                  target);<br>
-      return GL_TRUE;<br>
-   }<br>
-<br>
-   assert(maxLevels != 0);<br>
-   if (level < 0 || level >= maxLevels) {<br>
-      _mesa_error(ctx, GL_INVALID_VALUE,<br>
-                  "glGetCompressedTexImageARB(bad level = %d)", level);<br>
-      return GL_TRUE;<br>
-   }<br>
-<br>
-   texObj = _mesa_get_current_tex_object(ctx, target);<br>
-   if (!texObj) {<br>
-      _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");<br>
-      return GL_TRUE;<br>
-   }<br>
-<br>
-   texImage = _mesa_select_tex_image(ctx, texObj, target, level);<br>
-<br>
-   if (!texImage) {<br>
-      /* probably invalid mipmap level */<br>
-      _mesa_error(ctx, GL_INVALID_VALUE,<br>
-                  "glGetCompressedTexImageARB(level)");<br>
-      return GL_TRUE;<br>
-   }<br>
-<br>
-   if (!_mesa_is_format_compressed(texImage->TexFormat)) {<br>
-      _mesa_error(ctx, GL_INVALID_OPERATION,<br>
-                  "glGetCompressedTexImageARB(texture is not compressed)");<br>
-      return GL_TRUE;<br>
-   }<br>
-<br>
-   compressedSize = _mesa_format_image_size(texImage->TexFormat,<br>
-                                            texImage->Width,<br>
-                                            texImage->Height,<br>
-                                            texImage->Depth);<br>
-<br>
-   /* Check for invalid pixel storage modes */<br>
-   dimensions = _mesa_get_texture_dimensions(texImage->TexObject->Target);<br>
-   if (!_mesa_compressed_pixel_storage_error_check(ctx, dimensions,<br>
-                                              &ctx->Pack,<br>
-                                              "glGetCompressedTexImageARB")) {<br>
-      return GL_TRUE;<br>
-   }<br>
-<br>
-   if (!_mesa_is_bufferobj(ctx->Pack.BufferObj)) {<br>
-      /* do bounds checking on writing to client memory */<br>
-      if (clientMemSize < (GLsizei) compressedSize) {<br>
-         _mesa_error(ctx, GL_INVALID_OPERATION,<br>
-                     "glGetnCompressedTexImageARB(out of bounds access:"<br>
-                     " bufSize (%d) is too small)", clientMemSize);<br>
-         return GL_TRUE;<br>
-      }<br>
-   } else {<br>
-      /* do bounds checking on PBO write */<br>
-      if ((const GLubyte *) img + compressedSize ><br>
-          (const GLubyte *) ctx->Pack.BufferObj->Size) {<br>
-         _mesa_error(ctx, GL_INVALID_OPERATION,<br>
-                     "glGetCompressedTexImage(out of bounds PBO access)");<br>
-         return GL_TRUE;<br>
-      }<br>
-<br>
-      /* make sure PBO is not mapped */<br>
-      if (_mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) {<br>
-         _mesa_error(ctx, GL_INVALID_OPERATION,<br>
-                     "glGetCompressedTexImage(PBO is mapped)");<br>
-         return GL_TRUE;<br>
-      }<br>
-   }<br>
-<br>
-   return GL_FALSE;<br>
+   struct compressed_pixelstore st;<br>
+   GLsizei totalBytes;<br>
+<br>
+   _mesa_compute_compressed_pixelstore(dimensions, format,<br>
+                                       width, height, depth,<br>
+                                       packing, &st);<br>
+   totalBytes =<br>
+      (st.CopySlices - 1) * st.TotalRowsPerSlice * st.TotalBytesPerRow +<br>
+      st.SkipBytes +<br>
+      (st.CopyRowsPerSlice - 1) * st.TotalBytesPerRow +<br>
+      st.CopyBytesPerRow;<br>
+<br>
+   return totalBytes;<br>
 }<br>
<br>
<br>
-void GLAPIENTRY<br>
-_mesa_GetnCompressedTexImageARB(GLenum target, GLint level, GLsizei bufSize,<br>
-                                GLvoid *img)<br>
-{<br>
-   struct gl_texture_object *texObj;<br>
-   struct gl_texture_image *texImage;<br>
-   GET_CURRENT_CONTEXT(ctx);<br>
-<br>
-   FLUSH_VERTICES(ctx, 0);<br>
-<br>
-   if (getcompressedteximage_error_check(ctx, target, level, bufSize, img)) {<br>
-      return;<br>
-   }<br>
-<br>
-   if (!_mesa_is_bufferobj(ctx->Pack.BufferObj) && !img) {<br>
-      /* not an error, do nothing */<br>
-      return;<br>
-   }<br>
-<br>
-   texObj = _mesa_get_current_tex_object(ctx, target);<br>
-   texImage = _mesa_select_tex_image(ctx, texObj, target, level);<br>
-<br>
-   if (_mesa_is_zero_size_texture(texImage))<br>
-      return;<br>
-<br>
-   if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) {<br>
-      _mesa_debug(ctx,<br>
-                  "glGetCompressedTexImage(tex %u) format = %s, w=%d, h=%d\n",<br>
-                  texObj->Name,<br>
-                  _mesa_get_format_name(texImage->TexFormat),<br>
-                  texImage->Width, texImage->Height);<br>
-   }<br>
-<br>
-   _mesa_lock_texture(ctx, texObj);<br>
-   {<br>
-      ctx->Driver.GetCompressedTexSubImage(ctx, texImage,<br>
-                                           0, 0, 0,<br>
-                                           texImage->Width, texImage->Height,<br>
-                                           texImage->Depth, img);<br>
-   }<br>
-   _mesa_unlock_texture(ctx, texObj);<br>
-}<br>
-<br>
-void GLAPIENTRY<br>
-_mesa_GetCompressedTexImage(GLenum target, GLint level, GLvoid *img)<br>
-{<br>
-   _mesa_GetnCompressedTexImageARB(target, level, INT_MAX, img);<br>
-}<br>
-<br>
-<br>
-<br>
 /**<br>
  * Error-check the offset and size arguments to<br>
  * glGet[Compressed]TextureSubImage().<br>
@@ -1154,7 +1054,8 @@ static bool<br></blockquote><div>You didn't use the new variable caller in dimensions_error_check. <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
 dimensions_error_check(struct gl_context *ctx,<br>
                        struct gl_texture_image *texImage,<br>
                        GLint xoffset, GLint yoffset, GLint zoffset,<br>
-                       GLsizei width, GLsizei height, GLsizei depth)<br>
+                       GLsizei width, GLsizei height, GLsizei depth,<br>
+                       const char *caller)<br>
 {<br>
    const GLenum target = texImage->TexObject->Target;<br>
<br>
@@ -1277,6 +1178,169 @@ dimensions_error_check(struct gl_context *ctx,<br>
 }<br>
<br>
<br>
+/**<br>
+ * Do error checking for glGetCompressedTexImage() and<br>
+ * glGetCompressedTextureSubImage().<br>
+ * \return true if any error, false if no errors.<br>
+ */<br></blockquote><div>Again, pass in target, too. <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+static bool<br>
+getcompressedteximage_error_check(struct gl_context *ctx,<br>
+                                  struct gl_texture_object *texObj,<br>
+                                  GLint level,<br>
+                                  GLint xoffset, GLint yoffset, GLint zoffset,<br>
+                                  GLsizei width, GLint height, GLint depth,<br>
+                                  GLsizei clientMemSize, GLvoid *img,<br>
+                                  const char *caller)<br>
+{<br>
+   GLenum target = texObj->Target;<br>
+   struct gl_texture_image *texImage;<br>
+   const GLint maxLevels = _mesa_max_texture_levels(ctx, target);<br>
+   const GLuint dimensions = _mesa_get_texture_dimensions(texObj->Target);<br>
+   GLsizei totalBytes;<br>
+<br>
+   assert(maxLevels != 0);<br>
+   if (level < 0 || level >= maxLevels) {<br>
+      _mesa_error(ctx, GL_INVALID_VALUE,<br>
+                  "%s(bad level = %d)", caller, level);<br>
+      return true;<br>
+   }<br>
+<br>
+   texImage = _mesa_select_tex_image(ctx, texObj, target, level);<br>
+<br>
+   if (!texImage) {<br>
+      /* probably invalid mipmap level */<br>
+      _mesa_error(ctx, GL_INVALID_VALUE, "%s(level)", caller);<br>
+      return true;<br>
+   }<br>
+<br>
+   if (!_mesa_is_format_compressed(texImage->TexFormat)) {<br>
+      _mesa_error(ctx, GL_INVALID_OPERATION,<br>
+                  "%s(texture is not compressed)", caller);<br>
+      return true;<br>
+   }<br>
+<br>
+   /* check offset, size against texture and block size */<br>
+   if (dimensions_error_check(ctx, texImage, xoffset, yoffset, zoffset,<br>
+                              width, height, depth, caller)) {<br>
+      return true;<br>
+   }<br>
+<br>
+   /* Check for invalid pixel storage modes */<br>
+   if (!_mesa_compressed_pixel_storage_error_check(ctx, dimensions,<br>
+                                                   &ctx->Pack,<br>
+                                                   caller)) {<br>
+      return true;<br>
+   }<br>
+<br>
+   /* Compute number of bytes that may be touched in the dest buffer */<br>
+   totalBytes = packed_compressed_size(dimensions, texImage->TexFormat,<br>
+                                       width, height, depth,<br>
+                                       &ctx->Pack);<br>
+<br>
+   /* Do dest buffer bounds checking */<br>
+   if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {<br>
+      /* do bounds checking on PBO write */<br>
+      if ((GLubyte *) img + totalBytes ><br>
+          (GLubyte *) ctx->Pack.BufferObj->Size) {<br>
+         _mesa_error(ctx, GL_INVALID_OPERATION,<br>
+                     "%s(out of bounds PBO access)", caller);<br>
+         return true;<br>
+      }<br>
+<br>
+      /* make sure PBO is not mapped */<br>
+      if (_mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) {<br>
+         _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", caller);<br>
+         return true;<br>
+      }<br>
+   }<br>
+   else {<br>
+      /* do bounds checking on writing to client memory */<br>
+      if (totalBytes > clientMemSize) {<br>
+         _mesa_error(ctx, GL_INVALID_OPERATION,<br>
+                     "%s(out of bounds access: bufSize (%d) is too small)",<br>
+                     caller, clientMemSize);<br>
+         return true;<br>
+      }<br>
+   }<br>
+<br>
+   return false;<br>
+}<br>
+<br>
+<br>
+void GLAPIENTRY<br>
+_mesa_GetnCompressedTexImageARB(GLenum target, GLint level, GLsizei bufSize,<br>
+                                GLvoid *img)<br>
+{<br>
+   struct gl_texture_object *texObj;<br>
+   struct gl_texture_image *texImage;<br>
+   GLsizei width, height, depth;<br>
+   GET_CURRENT_CONTEXT(ctx);<br>
+<br>
+   FLUSH_VERTICES(ctx, 0);<br>
+<br>
+   if (!legal_getteximage_target(ctx, target)) {<br>
+      _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImage(target=0x%x)",<br>
+                  target);<br>
+      return;<br>
+   }<br>
+<br></blockquote><div>It seems like you could get NULL in a really weird edge case, so maybe you should remove the assert.<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+   texObj = _mesa_get_current_tex_object(ctx, target);<br>
+   assert(texObj);<br>
+   if (!texObj) {<br>
+      return; /* should never happen */<br>
+   }<br>
+<br>
+   texImage = _mesa_select_tex_image(ctx, texObj, target, level);<br>
+   if (texImage) {<br>
+      width = texImage->Width;<br>
+      height = texImage->Height;<br>
+      depth = texImage->Depth;<br>
+   }<br>
+   else {<br></blockquote><div>Hope this doesn't segfault somewhere else.  It might be better if you return here. <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+      /* some error, we'll find it later */<br></blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+      width = height = depth = 0;<br>
+   }<br>
+<br>
+   if (getcompressedteximage_error_check(ctx, texObj, level,<br>
+                                         0, 0, 0, width, height, depth,<br>
+                                         bufSize, img,<br>
+                                         "glGet[n]CompressedTexImage")) {<br>
+      return;<br>
+   }<br>
+<br>
+   if (!_mesa_is_bufferobj(ctx->Pack.BufferObj) && !img) {<br>
+      /* not an error, do nothing */<br>
+      return;<br>
+   }<br>
+<br>
+   if (_mesa_is_zero_size_texture(texImage))<br>
+      return;<br>
+<br>
+   if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) {<br>
+      _mesa_debug(ctx,<br>
+                  "glGetCompressedTexImage(tex %u) format = %s, w=%d, h=%d\n",<br>
+                  texObj->Name,<br>
+                  _mesa_get_format_name(texImage->TexFormat),<br>
+                  texImage->Width, texImage->Height);<br>
+   }<br>
+<br>
+   _mesa_lock_texture(ctx, texObj);<br>
+   {<br>
+      ctx->Driver.GetCompressedTexSubImage(ctx, texImage,<br>
+                                           0, 0, 0,<br>
+                                           texImage->Width, texImage->Height,<br>
+                                           texImage->Depth, img);<br>
+   }<br>
+   _mesa_unlock_texture(ctx, texObj);<br>
+}<br>
+<br>
+void GLAPIENTRY<br>
+_mesa_GetCompressedTexImage(GLenum target, GLint level, GLvoid *img)<br>
+{<br>
+   _mesa_GetnCompressedTexImageARB(target, level, INT_MAX, img);<br>
+}<br>
+<br>
+<br>
<br>
 void GLAPIENTRY<br>
 _mesa_GetTextureSubImage(GLuint texture, GLint level,<br>
@@ -1293,8 +1357,8 @@ _mesa_GetTextureSubImage(GLuint texture, GLint level,<br>
<br>
    texObj = _mesa_lookup_texture(ctx, texture);<br>
    if (!texObj) {<br>
-      _mesa_error(ctx, GL_INVALID_VALUE,<br>
-                  "glGetTextureSubImage(invalid texture ID %u\n", texture);<br></blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+      _mesa_error(ctx, GL_INVALID_OPERATION,<br>
+                  "glGetTextureSubImage(invalid texture ID %u)\n", texture);<br>
       return;<br>
    }<br>
<br>
@@ -1324,7 +1388,7 @@ _mesa_GetTextureSubImage(GLuint texture, GLint level,<br>
<br>
    /* check dimensions */<br>
    if (dimensions_error_check(ctx, texImage, xoffset, yoffset, zoffset,<br>
-                              width, height, depth)) {<br>
+                              width, height, depth, "glGetTextureSubImage")) {<br>
       return;<br>
    }<br>
<br>
@@ -1349,3 +1413,79 @@ _mesa_GetTextureSubImage(GLuint texture, GLint level,<br>
    }<br>
    _mesa_unlock_texture(ctx, texObj);<br>
 }<br>
+<br>
+<br>
+void APIENTRY<br>
+_mesa_GetCompressedTextureSubImage(GLuint texture, GLint level,<br>
+                                   GLint xoffset, GLint yoffset,<br>
+                                   GLint zoffset, GLsizei width,<br>
+                                   GLsizei height, GLsizei depth,<br>
+                                   GLsizei bufSize, void *pixels)<br>
+{<br>
+   struct gl_texture_object *texObj;<br>
+   struct gl_texture_image *texImage;<br>
+   GLenum target;<br>
+<br>
+   GET_CURRENT_CONTEXT(ctx);<br>
+<br>
+   texObj = _mesa_lookup_texture(ctx, texture);<br></blockquote><div>Checking for texObj->Target == 0 here is kind of awkward.  It would be better to do that in a legal_texgetimage_target check. <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+   if (!texObj || texObj->Target == 0) {<br>
+      _mesa_error(ctx, GL_INVALID_OPERATION,<br>
+                  "glGetCompressedTextureSubImage(invalid texture ID %u)\n",<br>
+                  texture);<br>
+      return;<br>
+   }<br>
+<br>
+   /* common error checking */<br>
+   if (getcompressedteximage_error_check(ctx, texObj, level,<br>
+                                         xoffset, yoffset, zoffset,<br>
+                                         width, height, depth,<br>
+                                         bufSize, pixels,<br>
+                                         "glGetCompressedTextureSubImage")) {<br>
+      return;<br>
+   }<br>
+  </blockquote><div>I'd do the legal_tex_target check for consistency. <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+   target = texObj->Target;<br></blockquote><div>Again, this doesn't allow the user to get more than one face.  But it may be easier to do that when it is merged with my DSA GetTextureImage. <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+   if (target == GL_TEXTURE_CUBE_MAP) {<br>
+      /* convert z to face/target */<br>
+      if (zoffset >= 6) {<br>
+         _mesa_error(ctx, GL_INVALID_VALUE,<br>
+                     "glGetCompressedTextureSubImage(cube, zoffset = %d\n",<br>
+                     zoffset);<br>
+         return;<br>
+      }<br>
+      if (depth != 1) {<br>
+         _mesa_error(ctx, GL_INVALID_VALUE,<br>
+                     "glGetCompressedTextureSubImage(cube, depth = %d\n",<br>
+                     depth);<br>
+         return;<br>
+      }<br>
+      target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + zoffset;<br>
+   }<br>
+<br>
+   texImage = _mesa_select_tex_image(ctx, texObj, target, level);<br>
+<br>
+   /* check dimensions */<br>
+   if (dimensions_error_check(ctx, texImage, xoffset, yoffset, zoffset,<br>
+                              width, height, depth,<br>
+                              "glGetCompressedTextureSubImage")) {<br>
+      return;<br>
+   }<br>
+<br>
+   if (_mesa_is_zero_size_texture(texImage)) {<br>
+      return;  /* nothing to get */<br>
+   }<br>
+<br>
+   if (!_mesa_is_bufferobj(ctx->Pack.BufferObj) && pixels == NULL) {<br>
+      return;  /* not an error, do nothing */<br>
+   }<br>
+<br>
+   _mesa_lock_texture(ctx, texObj);<br>
+   {<br>
+      ctx->Driver.GetCompressedTexSubImage(ctx, texImage,<br>
+                                           xoffset, yoffset, zoffset,<br>
+                                           width, height, depth,<br>
+                                           pixels);<br>
+   }<br>
+   _mesa_unlock_texture(ctx, texObj);<br>
+}<br>
diff --git a/src/mesa/main/texgetimage.h b/src/mesa/main/texgetimage.h<br>
index 593d5b0..65a1ed2 100644<br>
--- a/src/mesa/main/texgetimage.h<br>
+++ b/src/mesa/main/texgetimage.h<br>
@@ -75,5 +75,12 @@ _mesa_GetTextureSubImage(GLuint texture, GLint level,<br>
                          GLenum format, GLenum type, GLsizei bufSize,<br>
                          void *pixels);<br>
<br>
+extern void APIENTRY<br>
+_mesa_GetCompressedTextureSubImage(GLuint texture, GLint level,<br>
+                                   GLint xoffset, GLint yoffset,<br>
+                                   GLint zoffset, GLsizei width,<br>
+                                   GLsizei height, GLsizei depth,<br>
+                                   GLsizei bufSize, void *pixels);<br>
+<br>
<br>
 #endif /* TEXGETIMAGE_H */<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.9.1<br>
<br>
_______________________________________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/mesa-dev" target="_blank">http://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
</font></span></blockquote></div></div></div>