Needed for GL_ARB_get_texture_sub_image. But at this point, the offsets are always zero and the sizes match the whole texture image.
v2: Fixes, suggestions from Laura Ekstrand: * Fix calls to ctx->Driver.UnmapTextureImage() to pass the correct slice value. * Added comments and assertions to check zoffset+depth<=tex->Depth before the 'img' loops. * Added a new zoffset==0 assert in get_tex_memcpy(). --- src/mesa/main/texgetimage.c | 128 +++++++++++++++++++++++++++----------------- 1 file changed, 78 insertions(+), 50 deletions(-) diff --git a/src/mesa/main/texgetimage.c b/src/mesa/main/texgetimage.c index 03ad5f4..bf52638 100644 --- a/src/mesa/main/texgetimage.c +++ b/src/mesa/main/texgetimage.c @@ -74,12 +74,11 @@ type_needs_clamping(GLenum type) */ static void get_tex_depth(struct gl_context *ctx, GLuint dimensions, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLint depth, GLenum format, GLenum type, GLvoid *pixels, struct gl_texture_image *texImage) { - const GLint width = texImage->Width; - GLint height = texImage->Height; - GLint depth = texImage->Depth; GLint img, row; GLfloat *depthRow = malloc(width * sizeof(GLfloat)); @@ -93,14 +92,18 @@ get_tex_depth(struct gl_context *ctx, GLuint dimensions, height = 1; } + /* Note that we also checked for zoffset + img < texImage->Depth + * in dimensions_error_check(). + */ + assert(zoffset + depth <= texImage->Depth); for (img = 0; img < depth; img++) { GLubyte *srcMap; GLint srcRowStride; /* map src texture buffer */ - ctx->Driver.MapTextureImage(ctx, texImage, img, - 0, 0, width, height, GL_MAP_READ_BIT, - &srcMap, &srcRowStride); + ctx->Driver.MapTextureImage(ctx, texImage, zoffset + img, + xoffset, yoffset, width, height, + GL_MAP_READ_BIT, &srcMap, &srcRowStride); if (srcMap) { for (row = 0; row < height; row++) { @@ -112,7 +115,7 @@ get_tex_depth(struct gl_context *ctx, GLuint dimensions, _mesa_pack_depth_span(ctx, width, dest, type, depthRow, &ctx->Pack); } - ctx->Driver.UnmapTextureImage(ctx, texImage, img); + ctx->Driver.UnmapTextureImage(ctx, texImage, zoffset + img); } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); @@ -129,26 +132,29 @@ get_tex_depth(struct gl_context *ctx, GLuint dimensions, */ static void get_tex_depth_stencil(struct gl_context *ctx, GLuint dimensions, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLint depth, GLenum format, GLenum type, GLvoid *pixels, struct gl_texture_image *texImage) { - const GLint width = texImage->Width; - const GLint height = texImage->Height; - const GLint depth = texImage->Depth; GLint img, row; assert(format == GL_DEPTH_STENCIL); assert(type == GL_UNSIGNED_INT_24_8 || type == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); + /* Note that we also checked for zoffset + img < texImage->Depth + * in dimensions_error_check(). + */ + assert(zoffset + depth <= texImage->Depth); for (img = 0; img < depth; img++) { GLubyte *srcMap; GLint rowstride; /* map src texture buffer */ - ctx->Driver.MapTextureImage(ctx, texImage, img, - 0, 0, width, height, GL_MAP_READ_BIT, - &srcMap, &rowstride); + ctx->Driver.MapTextureImage(ctx, texImage, zoffset + img, + xoffset, yoffset, width, height, + GL_MAP_READ_BIT, &srcMap, &rowstride); if (srcMap) { for (row = 0; row < height; row++) { @@ -165,7 +171,7 @@ get_tex_depth_stencil(struct gl_context *ctx, GLuint dimensions, } } - ctx->Driver.UnmapTextureImage(ctx, texImage, img); + ctx->Driver.UnmapTextureImage(ctx, texImage, zoffset + img); } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); @@ -180,22 +186,25 @@ get_tex_depth_stencil(struct gl_context *ctx, GLuint dimensions, */ static void get_tex_ycbcr(struct gl_context *ctx, GLuint dimensions, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLint depth, GLenum format, GLenum type, GLvoid *pixels, struct gl_texture_image *texImage) { - const GLint width = texImage->Width; - const GLint height = texImage->Height; - const GLint depth = texImage->Depth; GLint img, row; + /* Note that we also checked for zoffset + img < texImage->Depth + * in dimensions_error_check(). + */ + assert(zoffset + depth <= texImage->Depth); for (img = 0; img < depth; img++) { GLubyte *srcMap; GLint rowstride; /* map src texture buffer */ - ctx->Driver.MapTextureImage(ctx, texImage, img, - 0, 0, width, height, GL_MAP_READ_BIT, - &srcMap, &rowstride); + ctx->Driver.MapTextureImage(ctx, texImage, zoffset + img, + xoffset, yoffset, width, height, + GL_MAP_READ_BIT, &srcMap, &rowstride); if (srcMap) { for (row = 0; row < height; row++) { @@ -218,7 +227,7 @@ get_tex_ycbcr(struct gl_context *ctx, GLuint dimensions, } } - ctx->Driver.UnmapTextureImage(ctx, texImage, img); + ctx->Driver.UnmapTextureImage(ctx, texImage, zoffset + img); } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); @@ -233,6 +242,8 @@ get_tex_ycbcr(struct gl_context *ctx, GLuint dimensions, */ static void get_tex_rgba_compressed(struct gl_context *ctx, GLuint dimensions, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLint depth, GLenum format, GLenum type, GLvoid *pixels, struct gl_texture_image *texImage, GLbitfield transferOps) @@ -243,9 +254,6 @@ get_tex_rgba_compressed(struct gl_context *ctx, GLuint dimensions, const GLenum baseFormat = _mesa_get_format_base_format(texFormat); const GLenum destBaseFormat = _mesa_base_tex_format(ctx, format); GLenum rebaseFormat = GL_NONE; - const GLuint width = texImage->Width; - const GLuint height = texImage->Height; - const GLuint depth = texImage->Depth; GLfloat *tempImage, *tempSlice, *srcRow; GLuint row, slice; @@ -264,15 +272,15 @@ get_tex_rgba_compressed(struct gl_context *ctx, GLuint dimensions, tempSlice = tempImage + slice * 4 * width * height; - ctx->Driver.MapTextureImage(ctx, texImage, slice, - 0, 0, width, height, + ctx->Driver.MapTextureImage(ctx, texImage, zoffset + slice, + xoffset, yoffset, width, height, GL_MAP_READ_BIT, &srcMap, &srcRowStride); if (srcMap) { _mesa_decompress_image(texFormat, width, height, srcMap, srcRowStride, tempSlice); - ctx->Driver.UnmapTextureImage(ctx, texImage, slice); + ctx->Driver.UnmapTextureImage(ctx, texImage, zoffset + slice); } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); @@ -368,6 +376,8 @@ _mesa_base_pack_format(GLenum format) */ static void get_tex_rgba_uncompressed(struct gl_context *ctx, GLuint dimensions, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLint depth, GLenum format, GLenum type, GLvoid *pixels, struct gl_texture_image *texImage, GLbitfield transferOps) @@ -375,11 +385,8 @@ get_tex_rgba_uncompressed(struct gl_context *ctx, GLuint dimensions, /* don't want to apply sRGB -> RGB conversion here so override the format */ const mesa_format texFormat = _mesa_get_srgb_format_linear(texImage->TexFormat); - const GLuint width = texImage->Width; GLenum destBaseFormat = _mesa_base_pack_format(format); GLenum rebaseFormat = GL_NONE; - GLuint height = texImage->Height; - GLuint depth = texImage->Depth; GLuint img, row; GLfloat (*rgba)[4]; GLuint (*rgba_uint)[4]; @@ -398,6 +405,8 @@ get_tex_rgba_uncompressed(struct gl_context *ctx, GLuint dimensions, if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) { depth = height; height = 1; + zoffset = yoffset; + yoffset = 0; } if (texImage->_BaseFormat == GL_LUMINANCE || @@ -472,9 +481,9 @@ get_tex_rgba_uncompressed(struct gl_context *ctx, GLuint dimensions, GLint rowstride; /* map src texture buffer */ - ctx->Driver.MapTextureImage(ctx, texImage, img, - 0, 0, width, height, GL_MAP_READ_BIT, - &srcMap, &rowstride); + ctx->Driver.MapTextureImage(ctx, texImage, zoffset + img, + xoffset, yoffset, width, height, + GL_MAP_READ_BIT, &srcMap, &rowstride); if (srcMap) { for (row = 0; row < height; row++) { const GLubyte *src = srcMap + row * rowstride; @@ -506,7 +515,7 @@ get_tex_rgba_uncompressed(struct gl_context *ctx, GLuint dimensions, } /* Unmap the src texture buffer */ - ctx->Driver.UnmapTextureImage(ctx, texImage, img); + ctx->Driver.UnmapTextureImage(ctx, texImage, zoffset + img); } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); @@ -524,6 +533,8 @@ get_tex_rgba_uncompressed(struct gl_context *ctx, GLuint dimensions, */ static void get_tex_rgba(struct gl_context *ctx, GLuint dimensions, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLint depth, GLenum format, GLenum type, GLvoid *pixels, struct gl_texture_image *texImage) { @@ -545,11 +556,17 @@ get_tex_rgba(struct gl_context *ctx, GLuint dimensions, } if (_mesa_is_format_compressed(texImage->TexFormat)) { - get_tex_rgba_compressed(ctx, dimensions, format, type, + get_tex_rgba_compressed(ctx, dimensions, + xoffset, yoffset, zoffset, + width, height, depth, + format, type, pixels, texImage, transferOps); } else { - get_tex_rgba_uncompressed(ctx, dimensions, format, type, + get_tex_rgba_uncompressed(ctx, dimensions, + xoffset, yoffset, zoffset, + width, height, depth, + format, type, pixels, texImage, transferOps); } } @@ -560,8 +577,10 @@ get_tex_rgba(struct gl_context *ctx, GLuint dimensions, * \return GL_TRUE if done, GL_FALSE otherwise */ static GLboolean -get_tex_memcpy(struct gl_context *ctx, GLenum format, GLenum type, - GLvoid *pixels, +get_tex_memcpy(struct gl_context *ctx, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLint depth, + GLenum format, GLenum type, GLvoid *pixels, struct gl_texture_image *texImage) { const GLenum target = texImage->TexObject->Target; @@ -585,27 +604,30 @@ get_tex_memcpy(struct gl_context *ctx, GLenum format, GLenum type, if (memCopy) { const GLuint bpp = _mesa_get_format_bytes(texImage->TexFormat); - const GLuint bytesPerRow = texImage->Width * bpp; + const GLuint bytesPerRow = width * bpp; GLubyte *dst = - _mesa_image_address2d(&ctx->Pack, pixels, texImage->Width, - texImage->Height, format, type, 0, 0); + _mesa_image_address2d(&ctx->Pack, pixels, width, height, + format, type, 0, 0); const GLint dstRowStride = - _mesa_image_row_stride(&ctx->Pack, texImage->Width, format, type); + _mesa_image_row_stride(&ctx->Pack, width, format, type); GLubyte *src; GLint srcRowStride; + /* Since only 1D, 2D, RECT textures are supported here */ + assert(zoffset == 0); + /* map src texture buffer */ ctx->Driver.MapTextureImage(ctx, texImage, 0, - 0, 0, texImage->Width, texImage->Height, + xoffset, yoffset, width, height, GL_MAP_READ_BIT, &src, &srcRowStride); if (src) { if (bytesPerRow == dstRowStride && bytesPerRow == srcRowStride) { - memcpy(dst, src, bytesPerRow * texImage->Height); + memcpy(dst, src, bytesPerRow * height); } else { GLuint row; - for (row = 0; row < texImage->Height; row++) { + for (row = 0; row < height; row++) { memcpy(dst, src, bytesPerRow); dst += dstRowStride; src += srcRowStride; @@ -663,20 +685,26 @@ _mesa_get_texsubimage(struct gl_context *ctx, pixels = ADD_POINTERS(buf, pixels); } - if (get_tex_memcpy(ctx, format, type, pixels, texImage)) { + if (get_tex_memcpy(ctx, xoffset, yoffset, zoffset, width, height, depth, + format, type, pixels, texImage)) { /* all done */ } else if (format == GL_DEPTH_COMPONENT) { - get_tex_depth(ctx, dimensions, format, type, pixels, texImage); + get_tex_depth(ctx, dimensions, xoffset, yoffset, zoffset, + width, height, depth, format, type, pixels, texImage); } else if (format == GL_DEPTH_STENCIL_EXT) { - get_tex_depth_stencil(ctx, dimensions, format, type, pixels, texImage); + get_tex_depth_stencil(ctx, dimensions, xoffset, yoffset, zoffset, + width, height, depth, + format, type, pixels, texImage); } else if (format == GL_YCBCR_MESA) { - get_tex_ycbcr(ctx, dimensions, format, type, pixels, texImage); + get_tex_ycbcr(ctx, dimensions, xoffset, yoffset, zoffset, + width, height, depth, format, type, pixels, texImage); } else { - get_tex_rgba(ctx, dimensions, format, type, pixels, texImage); + get_tex_rgba(ctx, dimensions, xoffset, yoffset, zoffset, + width, height, depth, format, type, pixels, texImage); } if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { -- 1.9.1 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev