On Fri, Jun 13, 2014 at 8:59 PM, Neil Roberts <n...@linux.intel.com> wrote: > This adds the driver entry point for glClearTexSubImage and fills in the > _mesa_ClearTexImage and _mesa_ClearTexSubImage functions that call it. > --- > src/mesa/main/dd.h | 14 +++ > src/mesa/main/teximage.c | 241 > ++++++++++++++++++++++++++++++++++++++++++++++- > src/mesa/main/teximage.h | 12 +++ > 3 files changed, 266 insertions(+), 1 deletion(-) > > diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h > index 633ea2c..8976535 100644 > --- a/src/mesa/main/dd.h > +++ b/src/mesa/main/dd.h > @@ -239,6 +239,20 @@ struct dd_function_table { > struct gl_texture_image *texImage ); > > /** > + * Called by glClearTex[Sub]Image > + * > + * Clears a rectangular region of the image to a given value. The > + * clearValue argument is either NULL or points to a single texel to use > as > + * the clear value in the same internal format as the texture image. If it > + * is NULL then the texture should be cleared to zeroes. > + */ > + void (*ClearTexSubImage)(struct gl_context *ctx, > + struct gl_texture_image *texImage, > + GLint xoffset, GLint yoffset, GLint zoffset, > + GLsizei width, GLsizei height, GLsizei depth, > + const GLvoid *clearValue); > + > + /** > * Called by glCopyTex[Sub]Image[123]D(). > * > * This function should copy a rectangular region in the rb to a single > diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c > index a893c70..d5baac8 100644 > --- a/src/mesa/main/teximage.c > +++ b/src/mesa/main/teximage.c > @@ -51,6 +51,7 @@ > #include "textureview.h" > #include "mtypes.h" > #include "glformats.h" > +#include "texstore.h" > > > /** > @@ -3848,20 +3849,259 @@ _mesa_CopyTexSubImage3D( GLenum target, GLint level, > x, y, width, height); > } > > +static bool > +clear_tex_image(struct gl_context *ctx, > + const char *function, > + struct gl_texture_image *texImage, GLint level, > + GLint xoffset, GLint yoffset, GLint zoffset, > + GLsizei width, GLsizei height, GLsizei depth, > + GLenum format, GLenum type, > + const void *data) > +{ > + struct gl_texture_object *texObj = texImage->TexObject; > + static const GLubyte zeroData[MAX_PIXEL_BYTES]; > + GLubyte clearValue[MAX_PIXEL_BYTES]; > + GLubyte *clearValuePtr = clearValue; > + GLenum internalFormat = texImage->InternalFormat; > + GLenum err; > + > + if (texObj->Target == GL_TEXTURE_BUFFER) { > + _mesa_error(ctx, GL_INVALID_OPERATION, > + "%s(buffer texture)", function); > + return false; > + } > + > + if (_mesa_is_compressed_format(ctx, internalFormat)) { > + _mesa_error(ctx, GL_INVALID_OPERATION, > + "%s(compressed texture)", function); > + return false; > + } > + > + err = _mesa_error_check_format_and_type(ctx, format, type); > + if (err != GL_NO_ERROR) { > + _mesa_error(ctx, err, > + "%s(incompatible format = %s, type = %s)", > + function, > + _mesa_lookup_enum_by_nr(format), > + _mesa_lookup_enum_by_nr(type)); > + return false; > + } > + > + /* make sure internal format and format basically agree */ > + if (!texture_formats_agree(internalFormat, format)) { > + _mesa_error(ctx, GL_INVALID_OPERATION, > + "%s(incompatible internalFormat = %s, format = %s)", > + function, > + _mesa_lookup_enum_by_nr(internalFormat), > + _mesa_lookup_enum_by_nr(format)); > + return false; > + } > + > + if (ctx->Version >= 30 || ctx->Extensions.EXT_texture_integer) {
Just ctx->Extensions.EXT_texture_integer should be enough here, no? > + /* both source and dest must be integer-valued, or neither */ > + if (_mesa_is_format_integer_color(texImage->TexFormat) != > + _mesa_is_enum_format_integer(format)) { > + _mesa_error(ctx, GL_INVALID_OPERATION, > + "%s(integer/non-integer format mismatch)", > + function); > + return false; > + } > + } > + > + if (!_mesa_texstore(ctx, > + 1, /* dims */ > + texImage->_BaseFormat, > + texImage->TexFormat, > + 0, /* dstRowStride */ > + &clearValuePtr, > + 1, 1, 1, /* srcWidth/Height/Depth */ > + format, type, > + data ? data : zeroData, > + &ctx->DefaultPacking)) { > + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid format)", function); > + return false; > + } > + > + ctx->Driver.ClearTexSubImage(ctx, > + texImage, > + xoffset, yoffset, zoffset, > + width, height, depth, > + data ? clearValue : NULL); > + > + return true; > +} > + > +static struct gl_texture_object * > +get_tex_obj_for_clear(struct gl_context *ctx, > + const char *function, > + GLuint texture) > +{ > + struct gl_texture_object *texObj; > + > + if (texture == 0) { > + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(zero texture)", function); > + return NULL; > + } > + > + texObj = _mesa_lookup_texture(ctx, texture); > + > + if (texObj == NULL) { > + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(non-gen name)", function); > + return NULL; > + } > + > + if (texObj->Target == 0) { > + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unbound tex)", function); > + return NULL; > + } > + > + return texObj; > +} > + > +static int > +get_tex_images_for_clear(struct gl_context *ctx, > + const char *function, > + struct gl_texture_object *texObj, > + GLint level, > + struct gl_texture_image **texImages) > +{ > + GLenum target; > + int i; > + > + if (level < 0 || level >= MAX_TEXTURE_LEVELS) { > + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid level)", function); > + return 0; > + } > + > + if (texObj->Target == GL_TEXTURE_CUBE_MAP) { > + for (i = 0; i < MAX_FACES; i++) { > + target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i; > + > + texImages[i] = _mesa_select_tex_image(ctx, texObj, target, level); > + if (texImages[i] == NULL) { > + _mesa_error(ctx, GL_INVALID_OPERATION, > + "%s(invalid level)", function); > + return 0; > + } > + } > + > + return MAX_FACES; > + } > + > + texImages[0] = _mesa_select_tex_image(ctx, texObj, texObj->Target, level); > + > + if (texImages[0] == NULL) { > + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid level)", function); > + return 0; > + } > + > + return 1; > +} > + > void GLAPIENTRY > _mesa_ClearTexSubImage( GLuint texture, GLint level, > GLint xoffset, GLint yoffset, GLint zoffset, > GLsizei width, GLsizei height, GLsizei depth, > GLenum format, GLenum type, const void *data ) > { > + GET_CURRENT_CONTEXT(ctx); > + struct gl_texture_object *texObj; > + struct gl_texture_image *texImages[MAX_FACES]; > + int i, numImages; > + int minDepth, maxDepth; > + bool res; > > + texObj = get_tex_obj_for_clear(ctx, "glClearTexSubImage", texture); > + > + if (texObj == NULL) > + return; > + > + _mesa_lock_texture(ctx, texObj); > + > + numImages = get_tex_images_for_clear(ctx, "glClearTexSubImage", > + texObj, level, texImages); > + if (numImages == 0) > + goto out; > + > + if (numImages == 1) { > + minDepth = -(int) texImages[0]->Border; > + maxDepth = texImages[0]->Depth; > + } else { > + minDepth = 0; > + maxDepth = numImages; > + } > + > + if (xoffset < -(GLint) texImages[0]->Border || > + yoffset < -(GLint) texImages[0]->Border || > + zoffset < minDepth || > + width < 0 || > + height < 0 || > + depth < 0 || > + xoffset + width > texImages[0]->Width || > + yoffset + height > texImages[0]->Height || > + zoffset + depth > maxDepth) { > + _mesa_error(ctx, GL_INVALID_OPERATION, > + "glClearSubTexImage(invalid dimensions)"); > + goto out; > + } > + > + if (numImages == 1) { > + clear_tex_image(ctx, "glClearTexSubImage", > + texImages[0], level, > + xoffset, yoffset, zoffset, > + width, height, depth, > + format, type, data); > + } else { > + for (i = zoffset; i < zoffset + depth; i++) { > + res = clear_tex_image(ctx, "glClearTexSubImage", > + texImages[i], level, > + xoffset, yoffset, 0, > + width, height, 1, > + format, type, data); > + if (!res) > + break; > + } > + } > + > + out: > + _mesa_unlock_texture(ctx, texObj); > } > > void GLAPIENTRY > _mesa_ClearTexImage( GLuint texture, GLint level, > GLenum format, GLenum type, const void *data ) > { > + GET_CURRENT_CONTEXT(ctx); > + struct gl_texture_object *texObj; > + struct gl_texture_image *texImages[MAX_FACES]; > + int i, numImages; > + bool res; > + > + texObj = get_tex_obj_for_clear(ctx, "glClearTexImage", texture); > > + if (texObj == NULL) > + return; > + > + _mesa_lock_texture(ctx, texObj); > + > + numImages = get_tex_images_for_clear(ctx, "glClearTexImage", > + texObj, level, texImages); > + > + for (i = 0; i < numImages; i++) { > + res = clear_tex_image(ctx, "glClearTexImage", > + texImages[i], level, > + -(GLint) texImages[i]->Border, /* xoffset */ > + -(GLint) texImages[i]->Border, /* yoffset */ > + -(GLint) texImages[i]->Border, /* zoffset */ > + texImages[i]->Width, > + texImages[i]->Height, > + texImages[i]->Depth, > + format, type, data); > + if (!res) > + break; > + } > + > + _mesa_unlock_texture(ctx, texObj); > } > > > @@ -4624,7 +4864,6 @@ _mesa_TexStorage2DMultisample(GLenum target, GLsizei > samples, > "glTexStorage2DMultisample"); > } > > - > void GLAPIENTRY > _mesa_TexStorage3DMultisample(GLenum target, GLsizei samples, > GLenum internalformat, GLsizei width, > diff --git a/src/mesa/main/teximage.h b/src/mesa/main/teximage.h > index 42305f4..984321c 100644 > --- a/src/mesa/main/teximage.h > +++ b/src/mesa/main/teximage.h > @@ -336,6 +336,18 @@ _mesa_TexStorage3DMultisample(GLenum target, GLsizei > samples, > GLsizei height, GLsizei depth, > GLboolean fixedsamplelocations); > > +extern void GLAPIENTRY > +_mesa_ClearTexImage(GLuint texture, GLint level, > + GLenum format, GLenum type, > + const void *data); > + > +extern void GLAPIENTRY > +_mesa_ClearTexSubImage(GLuint texture, GLint level, > + GLint xoffset, GLint yoffset, GLint zoffset, > + GLsizei width, GLsizei height, GLsizei depth, > + GLenum format, GLenum type, > + const void *data); > + > bool > _mesa_compressed_texture_pixel_storage_error_check(struct gl_context *ctx, > GLint dimensions, > -- > 1.9.3 > > _______________________________________________ > 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