<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:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">One of the two new functions in GL_ARB_get_texture_sub_image.<br>
---<br>
 src/mesa/main/texgetimage.c | 305 ++++++++++++++++++++++++++++++++++++++------<br>
 src/mesa/main/texgetimage.h |   8 ++<br>
 2 files changed, 277 insertions(+), 36 deletions(-)<br>
<br>
diff --git a/src/mesa/main/texgetimage.c b/src/mesa/main/texgetimage.c<br>
index 71c25bb..e1f238b 100644<br>
--- a/src/mesa/main/texgetimage.c<br>
+++ b/src/mesa/main/texgetimage.c<br>
@@ -44,6 +44,7 @@<br>
 #include "texcompress.h"<br>
 #include "texgetimage.h"<br>
 #include "teximage.h"<br>
+#include "texobj.h"<br>
 #include "texstore.h"<br>
<br>
<br>
@@ -803,41 +804,36 @@ legal_getteximage_target(struct gl_context *ctx, GLenum target)<br>
<br></blockquote><div>In my work with DSA textures, I have discovered that it's more robust to pass in both the texture object and target.  I originally just passed in the texObj instead of the target in error checks and used texObj->Target, but I failed a number of Piglit tests afterwards.  This is because, for non-DSA texture objects, the target passed into the function and the texObj->Target don't always match (especially for proxy targets).<br> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
 /**<br>
- * Do error checking for a glGetTexImage() call.<br>
+ * Do error checking for a glGetTexImage() or glGetTextureSubImage() call.<br>
  * \return GL_TRUE if any error, GL_FALSE if no errors.<br>
  */<br>
 static GLboolean<br>
-getteximage_error_check(struct gl_context *ctx, GLenum target, GLint level,<br>
+getteximage_error_check(struct gl_context *ctx,<br>
+                        struct gl_texture_object *texObj, GLint level,<br>
                         GLenum format, GLenum type, GLsizei clientMemSize,<br>
-                        GLvoid *pixels )<br>
+                        GLvoid *pixels, const char *caller)<br>
 {<br>
-   struct gl_texture_object *texObj;<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 = (target == GL_TEXTURE_3D) ? 3 : 2;<br>
    GLenum baseFormat, err;<br>
<br>
-   if (!legal_getteximage_target(ctx, target)) {<br>
-      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target=0x%x)", target);<br>
-      return GL_TRUE;<br>
-   }<br>
-<br>
    assert(maxLevels != 0);<br>
    if (level < 0 || level >= maxLevels) {<br>
-      _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );<br>
+      _mesa_error(ctx, GL_INVALID_VALUE, "%s(level)", caller);<br>
       return GL_TRUE;<br>
    }<br>
<br>
    err = _mesa_error_check_format_and_type(ctx, format, type);<br>
    if (err != GL_NO_ERROR) {<br>
-      _mesa_error(ctx, err, "glGetTexImage(format/type)");<br>
+      _mesa_error(ctx, err, "%s(format/type)", caller);<br>
       return GL_TRUE;<br>
    }<br>
<br>
    texObj = _mesa_get_current_tex_object(ctx, target);<br>
<br>
    if (!texObj) {<br>
-      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");<br>
+      _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", caller);<br>
       return GL_TRUE;<br>
    }<br>
<br>
@@ -854,64 +850,79 @@ getteximage_error_check(struct gl_context *ctx, GLenum target, GLint level,<br>
     */<br>
    if (_mesa_is_color_format(format)<br>
        && !_mesa_is_color_format(baseFormat)) {<br>
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");<br>
+      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(format mismatch)", caller);<br>
       return GL_TRUE;<br>
    }<br>
    else if (_mesa_is_depth_format(format)<br>
             && !_mesa_is_depth_format(baseFormat)<br>
             && !_mesa_is_depthstencil_format(baseFormat)) {<br>
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");<br>
+      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(format mismatch)", caller);<br>
       return GL_TRUE;<br>
    }<br>
    else if (_mesa_is_stencil_format(format)<br>
             && !ctx->Extensions.ARB_texture_stencil8) {<br>
-      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format=GL_STENCIL_INDEX)");<br>
+      _mesa_error(ctx, GL_INVALID_ENUM, "%s(format=GL_STENCIL_INDEX)", caller);<br>
       return GL_TRUE;<br>
    }<br>
    else if (_mesa_is_ycbcr_format(format)<br>
             && !_mesa_is_ycbcr_format(baseFormat)) {<br>
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");<br>
+      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(format mismatch)", caller);<br>
       return GL_TRUE;<br>
    }<br>
    else if (_mesa_is_depthstencil_format(format)<br>
             && !_mesa_is_depthstencil_format(baseFormat)) {<br>
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");<br>
+      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(format mismatch)", caller);<br>
       return GL_TRUE;<br>
    }<br>
    else if (_mesa_is_enum_format_integer(format) !=<br>
             _mesa_is_format_integer(texImage->TexFormat)) {<br>
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");<br>
+      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(format mismatch)", caller);<br>
       return GL_TRUE;<br>
    }<br>
<br>
-   if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width,<br>
-                                  texImage->Height, texImage->Depth,<br>
-                                  format, type, clientMemSize, pixels)) {<br>
+   return GL_FALSE;<br>
+}<br>
+<br>
+<br>
+/**<br>
+ * Do error checking related to the PBO and image size.<br>
+ */<br>
+static bool<br>
+pbo_error_check(struct gl_context *ctx, GLenum target,<br>
+                GLenum format, GLenum type,<br>
+                GLsizei width, GLsizei height, GLsizei depth,<br>
+                GLsizei bufferSize, void *pixels,<br>
+                const char *caller)<br>
+{<br>
+   const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;<br>
+<br>
+   if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack,<br>
+                                  width, height, depth,<br>
+                                  format, type, bufferSize, pixels)) {<br>
       if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {<br>
          _mesa_error(ctx, GL_INVALID_OPERATION,<br>
-                     "glGetTexImage(out of bounds PBO access)");<br>
+                     "%s(out of bounds PBO access)", caller);<br>
       } else {<br>
          _mesa_error(ctx, GL_INVALID_OPERATION,<br>
-                     "glGetnTexImageARB(out of bounds access:"<br>
-                     " bufSize (%d) is too small)", clientMemSize);<br>
+                     "%s(out of bounds access: bufSize (%d) is too small)",<br>
+                     caller, bufferSize);<br>
       }<br>
-      return GL_TRUE;<br>
+      return true;<br>
    }<br>
<br>
    if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {<br>
       /* PBO should not be mapped */<br>
       if (_mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) {<br>
          _mesa_error(ctx, GL_INVALID_OPERATION,<br>
-                     "glGetTexImage(PBO is mapped)");<br>
-         return GL_TRUE;<br>
+                     "%s(PBO is mapped)", caller);<br>
+         return true;<br>
       }<br>
    }<br>
<br>
-   return GL_FALSE;<br>
+   return false;<br>
 }<br>
<br>
<br>
-<br>
 /**<br>
  * Get texture image.  Called by glGetTexImage.<br>
  *<br>
@@ -932,21 +943,36 @@ _mesa_GetnTexImageARB( GLenum target, GLint level, GLenum format,<br>
<br>
    FLUSH_VERTICES(ctx, 0);<br>
<br>
-   if (getteximage_error_check(ctx, target, level, format, type,<br>
-                               bufSize, pixels)) {<br>
+   if (!legal_getteximage_target(ctx, target)) {<br>
+      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target=0x%x)", target);<br>
       return;<br>
    }<br>
<br>
-   if (!_mesa_is_bufferobj(ctx->Pack.BufferObj) && !pixels) {<br>
-      /* not an error, do nothing */<br>
+   texObj = _mesa_get_current_tex_object(ctx, target);<br>
+<br>
+   if (getteximage_error_check(ctx, texObj, level, format, type,<br>
+                               bufSize, pixels, "glGet[n]TexImage")) {<br>
       return;<br>
    }<br>
<br>
-   texObj = _mesa_get_current_tex_object(ctx, target);<br>
    texImage = _mesa_select_tex_image(ctx, texObj, target, level);<br>
+   if (!texImage) {<br>
+      return;  /* no texture image */<br>
+   }<br>
<br>
-   if (_mesa_is_zero_size_texture(texImage))<br>
+   if (pbo_error_check(ctx, target, format, type,<br>
+                       texImage->Width, texImage->Height, texImage->Depth,<br>
+                       bufSize, pixels, "glGet[n]TexImage")) {<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) {<br>
+      return;  /* not an error, do nothing */<br>
+   }<br>
<br>
    if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) {<br>
       _mesa_debug(ctx, "glGetTexImage(tex %u) format = %s, w=%d, h=%d,"<br>
@@ -1110,3 +1136,210 @@ _mesa_GetCompressedTexImage(GLenum target, GLint level, GLvoid *img)<br>
 {<br>
    _mesa_GetnCompressedTexImageARB(target, level, INT_MAX, img);<br>
 }<br></blockquote><div><br></div><div>Note:  When this gets merged with my DSA work, the target should maybe get passed into this function.  This is because DSA and traditional functions share a backend function, and that backend function will have to resemble your GetTextureSubImage function (thus calling dimensions_error_check).  As aforementioned, not passing the target could cause trouble.<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+<br>
+<br>
+<br>
+/**<br>
+ * Error-check the offset and size arguments to<br>
+ * glGet[Compressed]TextureSubImage().<br>
+ * \return true if error, false if no error.<br>
+ */<br>
+static bool<br>
+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>
+{<br>
+   const GLenum target = texImage->TexObject->Target;<br>
+<br>
+   switch (target) {<br>
+   case GL_TEXTURE_1D:<br>
+      if (yoffset != 0) {<br>
+         _mesa_error(ctx, GL_INVALID_VALUE,<br>
+                     "glGetTextureSubImage(1D, yoffset = %d)\n", yoffset);<br>
+         return true;<br>
+      }<br>
+      if (height != 1) {<br>
+         _mesa_error(ctx, GL_INVALID_VALUE,<br>
+                     "glGetTextureSubImage(1D, height = %d)\n", height);<br>
+         return true;<br>
+      }<br>
+      /* fall-through */<br>
+   case GL_TEXTURE_1D_ARRAY:<br>
+   case GL_TEXTURE_2D:<br>
+   case GL_TEXTURE_RECTANGLE:<br>
+      if (zoffset != 0) {<br>
+         _mesa_error(ctx, GL_INVALID_VALUE,<br>
+                     "glGetTextureSubImage(zoffset = %d)\n", zoffset);<br>
+         return true;<br>
+      }<br>
+      if (depth != 1) {<br>
+         _mesa_error(ctx, GL_INVALID_VALUE,<br>
+                     "glGetTextureSubImage(depth = %d)\n", depth);<br>
+         return true;<br>
+      }<br>
+      break;<br>
+   default:<br>
+      ; /* nothing */<br>
+   }<br>
+<br>
+   if (xoffset < 0) {<br>
+      _mesa_error(ctx, GL_INVALID_VALUE,<br>
+                  "glGetTextureSubImage(xoffset = %d)\n", xoffset);<br>
+      return true;<br>
+   }<br>
+<br>
+   if (yoffset < 0) {<br>
+      _mesa_error(ctx, GL_INVALID_VALUE,<br>
+                  "glGetTextureSubImage(yoffset = %d)\n", yoffset);<br>
+      return true;<br>
+   }<br>
+<br>
+   if (zoffset < 0) {<br>
+      _mesa_error(ctx, GL_INVALID_VALUE,<br>
+                  "glGetTextureSubImage(zoffset = %d)\n", zoffset);<br>
+      return true;<br>
+   }<br>
+<br></blockquote><div>Why didn't you put xoffset %d + width %d > image_width %u ? <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+   if (xoffset + width > texImage->Width) {<br>
+      _mesa_error(ctx, GL_INVALID_VALUE,<br>
+                  "glGetTextureSubImage(xoffset %d + width %d > %u)\n",<br>
+                  xoffset, width, texImage->Width);<br>
+      return true;<br>
+   }<br>
+<br>
+   if (yoffset + height > texImage->Height) {<br>
+      _mesa_error(ctx, GL_INVALID_VALUE,<br>
+                  "glGetTextureSubImage(yoffset %d + height %d > %u)\n",<br>
+                  yoffset, height, texImage->Height);<br>
+      return true;<br>
+   }<br>
+<br>
+   if (zoffset + depth > texImage->Depth) {<br>
+      _mesa_error(ctx, GL_INVALID_VALUE,<br>
+                  "glGetTextureSubImage(zoffset %d + depth %d > %u)\n",<br>
+                  zoffset, depth, texImage->Depth);<br>
+      return true;<br>
+   }<br>
+<br>
+   /* Extra checks for compressed textures */<br>
+   {<br>
+      GLuint bw, bh;<br>
+      _mesa_get_format_block_size(texImage->TexFormat, &bw, &bh);<br></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+      if (bw > 1 || bh > 1) {<br>
+         /* offset must be multiple of block size */<br></blockquote><div>This should be an INVALID_VALUE error according to the GL 4.5 spec. <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+         if (xoffset % bw != 0) {<br>
+            _mesa_error(ctx, GL_INVALID_OPERATION,<br>
+                        "glGetTextureSubImage(xoffset = %d)", xoffset);<br>
+            return true;<br>
+         }<br>
+         if (target != GL_TEXTURE_1D && target != GL_TEXTURE_1D_ARRAY) {<br></blockquote><div>This should be an INVALID_VALUE error according to the GL 4.5 spec.  Also, shouldn't it be yoffset % bh != 0 ?  You have bw.<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+            if (yoffset % bw != 0) {<br>
+               _mesa_error(ctx, GL_INVALID_OPERATION,<br>
+                           "glGetTextureSubImage(yoffset = %d)", yoffset);<br>
+               return true;<br>
+            }<br>
+         }<br></blockquote><div>Why is there no similar zoffset check?  Is it because Mesa doesn't have a concept of block depth?<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+<br>
+         /* The size must be a multiple of bw x bh, or we must be using a<br>
+          * offset+size that exactly hits the edge of the image.<br>
+          */<br></blockquote><div>Note: xoffset + width != (GLint) texImage->Width is more permissive than the spec document, which says (xoffset != 0) || (width != (GLint) texImage->Width).<br></div><div>Again, the spec document says INVALID_VALUE.<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+         if ((width % bw != 0) &&<br>
+             (xoffset + width != (GLint) texImage->Width)) {<br>
+            _mesa_error(ctx, GL_INVALID_OPERATION,<br>
+                        "glGetTextureSubImage(width = %d)", width);<br>
+            return true;<br>
+         }<br>
+<br></blockquote><div>Again, the spec document says INVALID_VALUE. <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+         if ((height % bh != 0) &&<br>
+             (yoffset + height != (GLint) texImage->Height)) {<br>
+            _mesa_error(ctx, GL_INVALID_OPERATION,<br>
+                        "glGetTextureSubImage(height = %d)", height);<br>
+            return true;<br>
+         }<br>
+      }<br>
+   }<br></blockquote><div>No depth check? <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+<br>
+   if (width == 0 || height == 0 || depth == 0) {<br>
+      /* Not an error, but nothing to do.  Return 'true' so that the<br>
+       * caller simply returns.<br>
+       */<br>
+      return true;<br>
+   }<br>
+<br>
+   return false;<br>
+}<br>
+<br>
+<br>
+<br>
+void GLAPIENTRY<br>
+_mesa_GetTextureSubImage(GLuint texture, GLint level,<br>
+                         GLint xoffset, GLint yoffset, GLint zoffset,<br>
+                         GLsizei width, GLsizei height, GLsizei depth,<br>
+                         GLenum format, GLenum type, GLsizei bufSize,<br>
+                         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>
+   if (!texObj) {<br></blockquote><div><br></div><div>I think this error might be a mistake in the spec.  According to <a href="https://www.opengl.org/registry/specs/ARB/get_texture_sub_image.txt" target="_blank">https://www.opengl.org/registry/specs/ARB/get_texture_sub_image.txt</a>, it should be INVALID_OPERATION in the case where the user passed in an unknown texture name.  Oddly enough, the OpenGL 4.5 core spec (30.10.2014) has INVALID_VALUE (consistent with what you have here) in section 8.11 Texture Queries.  But that is very strange because all the DSA functions consistently throw INVALID_OPERATION for this error (such as GetTextureImage and TextureSubImage*D, etc.) in the OpenGL 4.5 spec.  I'm not sure why they wouldn't agree.<br><br>In my DSA patch series, I have a convenience function for throwing INVALID_OPERATION for an unknown texture name because this occurs absolutely everywhere (_mesa_lookup_texture_err).<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+      _mesa_error(ctx, GL_INVALID_VALUE,<br>
+                  "glGetTextureSubImage(invalid texture ID %u\n", texture);<br>
+      return;<br>
+   }<br>
+<br>
+   /* common error checking */<br>
+   if (getteximage_error_check(ctx, texObj, level, format, type, bufSize,<br>
+                               pixels, "glGetTextureSubImage")) {<br>
+      return;<br>
+   }<br>
+<br></blockquote><div><br></div><div>You forgot to call legal_getteximage_target. <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+   target = texObj->Target;<br></blockquote><div><br></div><div>This doesn't seem like it will return more than one face of the cube map.  In fact, it will throw INVALID_OPERATION if the user tries to do so (depth != 1).  But the GL 4.5 spec says the user should be able to get as many faces as he or she wants from GetTextureSubImage (up to all six).<br></div><div>In my GetTextureImage patch, I just call the backend _mesa_get_texture_image multiple times.  When they are merged, the backend will be _mesa_get_texture_sub_image and GetTextureSubImage can call that multiple times in the same way.<br><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);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>
+                     "glGetTextureSubImage(cube, zoffset = %d\n", zoffset);<br>
+         return;<br>
+      }<br>
+      if (depth != 1) {<br>
+         _mesa_error(ctx, GL_INVALID_VALUE,<br>
+                     "glGetTextureSubImage(cube, depth = %d\n", 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>
+      return;<br>
+   }<br>
+<br>
+   if (pbo_error_check(ctx, target, format, type,<br>
+                       width, height, depth,<br>
+                       bufSize, pixels, "glGetTextureSubImage")) {<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.GetTexSubImage(ctx, xoffset, yoffset, zoffset, width, height,<br>
+                                 depth, format, type, pixels, texImage);<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 c9af5b9..40f152c 100644<br>
--- a/src/mesa/main/texgetimage.h<br>
+++ b/src/mesa/main/texgetimage.h<br>
@@ -65,4 +65,12 @@ extern void GLAPIENTRY<br>
 _mesa_GetnCompressedTexImageARB(GLenum target, GLint level, GLsizei bufSize,<br>
                                 GLvoid *img);<br>
<br>
+extern void GLAPIENTRY<br>
+_mesa_GetTextureSubImage(GLuint texture, GLint level,<br>
+                         GLint xoffset, GLint yoffset, GLint zoffset,<br>
+                         GLsizei width, GLsizei height, GLsizei depth,<br>
+                         GLenum format, GLenum type, GLsizei bufSize,<br>
+                         void *pixels);<br>
+<br>
+<br>
 #endif /* TEXGETIMAGE_H */<br>
<span><font color="#888888">--<br>
1.9.1<br>
<br>
_______________________________________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org" target="_blank">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>