<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>