Brian, what happened to this series? Was there some conflict with DSA and so you held off?
On Sat, Dec 13, 2014 at 9:42 AM, Brian Paul <bri...@vmware.com> wrote: > One of the two new functions in GL_ARB_get_texture_sub_image. > --- > src/mesa/main/texgetimage.c | 305 > ++++++++++++++++++++++++++++++++++++++------ > src/mesa/main/texgetimage.h | 8 ++ > 2 files changed, 277 insertions(+), 36 deletions(-) > > diff --git a/src/mesa/main/texgetimage.c b/src/mesa/main/texgetimage.c > index 71c25bb..e1f238b 100644 > --- a/src/mesa/main/texgetimage.c > +++ b/src/mesa/main/texgetimage.c > @@ -44,6 +44,7 @@ > #include "texcompress.h" > #include "texgetimage.h" > #include "teximage.h" > +#include "texobj.h" > #include "texstore.h" > > > @@ -803,41 +804,36 @@ legal_getteximage_target(struct gl_context *ctx, GLenum > target) > > > /** > - * Do error checking for a glGetTexImage() call. > + * Do error checking for a glGetTexImage() or glGetTextureSubImage() call. > * \return GL_TRUE if any error, GL_FALSE if no errors. > */ > static GLboolean > -getteximage_error_check(struct gl_context *ctx, GLenum target, GLint level, > +getteximage_error_check(struct gl_context *ctx, > + struct gl_texture_object *texObj, GLint level, > GLenum format, GLenum type, GLsizei clientMemSize, > - GLvoid *pixels ) > + GLvoid *pixels, const char *caller) > { > - struct gl_texture_object *texObj; > + GLenum target = texObj->Target; > struct gl_texture_image *texImage; > const GLint maxLevels = _mesa_max_texture_levels(ctx, target); > - const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2; > GLenum baseFormat, err; > > - if (!legal_getteximage_target(ctx, target)) { > - _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target=0x%x)", > target); > - return GL_TRUE; > - } > - > assert(maxLevels != 0); > if (level < 0 || level >= maxLevels) { > - _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" ); > + _mesa_error(ctx, GL_INVALID_VALUE, "%s(level)", caller); > return GL_TRUE; > } > > err = _mesa_error_check_format_and_type(ctx, format, type); > if (err != GL_NO_ERROR) { > - _mesa_error(ctx, err, "glGetTexImage(format/type)"); > + _mesa_error(ctx, err, "%s(format/type)", caller); > return GL_TRUE; > } > > texObj = _mesa_get_current_tex_object(ctx, target); > > if (!texObj) { > - _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)"); > + _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", caller); > return GL_TRUE; > } > > @@ -854,64 +850,79 @@ getteximage_error_check(struct gl_context *ctx, GLenum > target, GLint level, > */ > if (_mesa_is_color_format(format) > && !_mesa_is_color_format(baseFormat)) { > - _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format > mismatch)"); > + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(format mismatch)", caller); > return GL_TRUE; > } > else if (_mesa_is_depth_format(format) > && !_mesa_is_depth_format(baseFormat) > && !_mesa_is_depthstencil_format(baseFormat)) { > - _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format > mismatch)"); > + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(format mismatch)", caller); > return GL_TRUE; > } > else if (_mesa_is_stencil_format(format) > && !ctx->Extensions.ARB_texture_stencil8) { > - _mesa_error(ctx, GL_INVALID_ENUM, > "glGetTexImage(format=GL_STENCIL_INDEX)"); > + _mesa_error(ctx, GL_INVALID_ENUM, "%s(format=GL_STENCIL_INDEX)", > caller); > return GL_TRUE; > } > else if (_mesa_is_ycbcr_format(format) > && !_mesa_is_ycbcr_format(baseFormat)) { > - _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format > mismatch)"); > + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(format mismatch)", caller); > return GL_TRUE; > } > else if (_mesa_is_depthstencil_format(format) > && !_mesa_is_depthstencil_format(baseFormat)) { > - _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format > mismatch)"); > + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(format mismatch)", caller); > return GL_TRUE; > } > else if (_mesa_is_enum_format_integer(format) != > _mesa_is_format_integer(texImage->TexFormat)) { > - _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format > mismatch)"); > + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(format mismatch)", caller); > return GL_TRUE; > } > > - if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width, > - texImage->Height, texImage->Depth, > - format, type, clientMemSize, pixels)) { > + return GL_FALSE; > +} > + > + > +/** > + * Do error checking related to the PBO and image size. > + */ > +static bool > +pbo_error_check(struct gl_context *ctx, GLenum target, > + GLenum format, GLenum type, > + GLsizei width, GLsizei height, GLsizei depth, > + GLsizei bufferSize, void *pixels, > + const char *caller) > +{ > + const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2; > + > + if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, > + width, height, depth, > + format, type, bufferSize, pixels)) { > if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { > _mesa_error(ctx, GL_INVALID_OPERATION, > - "glGetTexImage(out of bounds PBO access)"); > + "%s(out of bounds PBO access)", caller); > } else { > _mesa_error(ctx, GL_INVALID_OPERATION, > - "glGetnTexImageARB(out of bounds access:" > - " bufSize (%d) is too small)", clientMemSize); > + "%s(out of bounds access: bufSize (%d) is too small)", > + caller, bufferSize); > } > - return GL_TRUE; > + return true; > } > > if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { > /* PBO should not be mapped */ > if (_mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) { > _mesa_error(ctx, GL_INVALID_OPERATION, > - "glGetTexImage(PBO is mapped)"); > - return GL_TRUE; > + "%s(PBO is mapped)", caller); > + return true; > } > } > > - return GL_FALSE; > + return false; > } > > > - > /** > * Get texture image. Called by glGetTexImage. > * > @@ -932,21 +943,36 @@ _mesa_GetnTexImageARB( GLenum target, GLint level, > GLenum format, > > FLUSH_VERTICES(ctx, 0); > > - if (getteximage_error_check(ctx, target, level, format, type, > - bufSize, pixels)) { > + if (!legal_getteximage_target(ctx, target)) { > + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target=0x%x)", > target); > return; > } > > - if (!_mesa_is_bufferobj(ctx->Pack.BufferObj) && !pixels) { > - /* not an error, do nothing */ > + texObj = _mesa_get_current_tex_object(ctx, target); > + > + if (getteximage_error_check(ctx, texObj, level, format, type, > + bufSize, pixels, "glGet[n]TexImage")) { > return; > } > > - texObj = _mesa_get_current_tex_object(ctx, target); > texImage = _mesa_select_tex_image(ctx, texObj, target, level); > + if (!texImage) { > + return; /* no texture image */ > + } > > - if (_mesa_is_zero_size_texture(texImage)) > + if (pbo_error_check(ctx, target, format, type, > + texImage->Width, texImage->Height, texImage->Depth, > + bufSize, pixels, "glGet[n]TexImage")) { > return; > + } > + > + if (_mesa_is_zero_size_texture(texImage)) { > + return; /* nothing to get */ > + } > + > + if (!_mesa_is_bufferobj(ctx->Pack.BufferObj) && !pixels) { > + return; /* not an error, do nothing */ > + } > > if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) { > _mesa_debug(ctx, "glGetTexImage(tex %u) format = %s, w=%d, h=%d," > @@ -1110,3 +1136,210 @@ _mesa_GetCompressedTexImage(GLenum target, GLint > level, GLvoid *img) > { > _mesa_GetnCompressedTexImageARB(target, level, INT_MAX, img); > } > + > + > + > +/** > + * Error-check the offset and size arguments to > + * glGet[Compressed]TextureSubImage(). > + * \return true if error, false if no error. > + */ > +static bool > +dimensions_error_check(struct gl_context *ctx, > + struct gl_texture_image *texImage, > + GLint xoffset, GLint yoffset, GLint zoffset, > + GLsizei width, GLsizei height, GLsizei depth) > +{ > + const GLenum target = texImage->TexObject->Target; > + > + switch (target) { > + case GL_TEXTURE_1D: > + if (yoffset != 0) { > + _mesa_error(ctx, GL_INVALID_VALUE, > + "glGetTextureSubImage(1D, yoffset = %d)\n", yoffset); > + return true; > + } > + if (height != 1) { > + _mesa_error(ctx, GL_INVALID_VALUE, > + "glGetTextureSubImage(1D, height = %d)\n", height); > + return true; > + } > + /* fall-through */ > + case GL_TEXTURE_1D_ARRAY: > + case GL_TEXTURE_2D: > + case GL_TEXTURE_RECTANGLE: > + if (zoffset != 0) { > + _mesa_error(ctx, GL_INVALID_VALUE, > + "glGetTextureSubImage(zoffset = %d)\n", zoffset); > + return true; > + } > + if (depth != 1) { > + _mesa_error(ctx, GL_INVALID_VALUE, > + "glGetTextureSubImage(depth = %d)\n", depth); > + return true; > + } > + break; > + default: > + ; /* nothing */ > + } > + > + if (xoffset < 0) { > + _mesa_error(ctx, GL_INVALID_VALUE, > + "glGetTextureSubImage(xoffset = %d)\n", xoffset); > + return true; > + } > + > + if (yoffset < 0) { > + _mesa_error(ctx, GL_INVALID_VALUE, > + "glGetTextureSubImage(yoffset = %d)\n", yoffset); > + return true; > + } > + > + if (zoffset < 0) { > + _mesa_error(ctx, GL_INVALID_VALUE, > + "glGetTextureSubImage(zoffset = %d)\n", zoffset); > + return true; > + } > + > + if (xoffset + width > texImage->Width) { > + _mesa_error(ctx, GL_INVALID_VALUE, > + "glGetTextureSubImage(xoffset %d + width %d > %u)\n", > + xoffset, width, texImage->Width); > + return true; > + } > + > + if (yoffset + height > texImage->Height) { > + _mesa_error(ctx, GL_INVALID_VALUE, > + "glGetTextureSubImage(yoffset %d + height %d > %u)\n", > + yoffset, height, texImage->Height); > + return true; > + } > + > + if (zoffset + depth > texImage->Depth) { > + _mesa_error(ctx, GL_INVALID_VALUE, > + "glGetTextureSubImage(zoffset %d + depth %d > %u)\n", > + zoffset, depth, texImage->Depth); > + return true; > + } > + > + /* Extra checks for compressed textures */ > + { > + GLuint bw, bh; > + _mesa_get_format_block_size(texImage->TexFormat, &bw, &bh); > + if (bw > 1 || bh > 1) { > + /* offset must be multiple of block size */ > + if (xoffset % bw != 0) { > + _mesa_error(ctx, GL_INVALID_OPERATION, > + "glGetTextureSubImage(xoffset = %d)", xoffset); > + return true; > + } > + if (target != GL_TEXTURE_1D && target != GL_TEXTURE_1D_ARRAY) { > + if (yoffset % bw != 0) { > + _mesa_error(ctx, GL_INVALID_OPERATION, > + "glGetTextureSubImage(yoffset = %d)", yoffset); > + return true; > + } > + } > + > + /* The size must be a multiple of bw x bh, or we must be using a > + * offset+size that exactly hits the edge of the image. > + */ > + if ((width % bw != 0) && > + (xoffset + width != (GLint) texImage->Width)) { > + _mesa_error(ctx, GL_INVALID_OPERATION, > + "glGetTextureSubImage(width = %d)", width); > + return true; > + } > + > + if ((height % bh != 0) && > + (yoffset + height != (GLint) texImage->Height)) { > + _mesa_error(ctx, GL_INVALID_OPERATION, > + "glGetTextureSubImage(height = %d)", height); > + return true; > + } > + } > + } > + > + if (width == 0 || height == 0 || depth == 0) { > + /* Not an error, but nothing to do. Return 'true' so that the > + * caller simply returns. > + */ > + return true; > + } > + > + return false; > +} > + > + > + > +void GLAPIENTRY > +_mesa_GetTextureSubImage(GLuint texture, GLint level, > + GLint xoffset, GLint yoffset, GLint zoffset, > + GLsizei width, GLsizei height, GLsizei depth, > + GLenum format, GLenum type, GLsizei bufSize, > + void *pixels) > +{ > + struct gl_texture_object *texObj; > + struct gl_texture_image *texImage; > + GLenum target; > + > + GET_CURRENT_CONTEXT(ctx); > + > + texObj = _mesa_lookup_texture(ctx, texture); > + if (!texObj) { > + _mesa_error(ctx, GL_INVALID_VALUE, > + "glGetTextureSubImage(invalid texture ID %u\n", texture); > + return; > + } > + > + /* common error checking */ > + if (getteximage_error_check(ctx, texObj, level, format, type, bufSize, > + pixels, "glGetTextureSubImage")) { > + return; > + } > + > + target = texObj->Target; > + if (target == GL_TEXTURE_CUBE_MAP) { > + /* convert z to face/target */ > + if (zoffset >= 6) { > + _mesa_error(ctx, GL_INVALID_VALUE, > + "glGetTextureSubImage(cube, zoffset = %d\n", zoffset); > + return; > + } > + if (depth != 1) { > + _mesa_error(ctx, GL_INVALID_VALUE, > + "glGetTextureSubImage(cube, depth = %d\n", depth); > + return; > + } > + target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + zoffset; > + } > + > + texImage = _mesa_select_tex_image(ctx, texObj, target, level); > + > + /* check dimensions */ > + if (dimensions_error_check(ctx, texImage, xoffset, yoffset, zoffset, > + width, height, depth)) { > + return; > + } > + > + if (pbo_error_check(ctx, target, format, type, > + width, height, depth, > + bufSize, pixels, "glGetTextureSubImage")) { > + return; > + } > + > + if (_mesa_is_zero_size_texture(texImage)) { > + return; /* nothing to get */ > + } > + > + if (!_mesa_is_bufferobj(ctx->Pack.BufferObj) && pixels == NULL) { > + return; /* not an error, do nothing */ > + } > + > + _mesa_lock_texture(ctx, texObj); > + { > + ctx->Driver.GetTexSubImage(ctx, xoffset, yoffset, zoffset, width, > height, > + depth, format, type, pixels, texImage); > + } > + _mesa_unlock_texture(ctx, texObj); > +} > diff --git a/src/mesa/main/texgetimage.h b/src/mesa/main/texgetimage.h > index c9af5b9..40f152c 100644 > --- a/src/mesa/main/texgetimage.h > +++ b/src/mesa/main/texgetimage.h > @@ -65,4 +65,12 @@ extern void GLAPIENTRY > _mesa_GetnCompressedTexImageARB(GLenum target, GLint level, GLsizei bufSize, > GLvoid *img); > > +extern void GLAPIENTRY > +_mesa_GetTextureSubImage(GLuint texture, GLint level, > + GLint xoffset, GLint yoffset, GLint zoffset, > + GLsizei width, GLsizei height, GLsizei depth, > + GLenum format, GLenum type, GLsizei bufSize, > + void *pixels); > + > + > #endif /* TEXGETIMAGE_H */ > -- > 1.9.1 > > _______________________________________________ > mesa-dev mailing list > mesa-dev@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/mesa-dev _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev