From 07e12c49175e0bf23dbd8bdc3afd7aa79ccc7140 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 13 Aug 2012 13:14:25 -0700 Subject: [PATCH] mesa: Add skeleton implementations of glInvalidateTex{Sub,}Image These are part of GL_ARB_invalidate_subdata (but not OpenGL ES 3.0). v2: Add comment explaining why minimum dimensions are set to 1 for some texture targets. Add default case to switch statement to silence compiler warnings and detect new texture targets. Both changes suggested by Brian. Also use _mesa_is_desktop_gl as suggested by Ken. Signed-off-by: Ian Romanick Reviewed-by: Brian Paul Reviewed-by: Kenneth Graunke --- src/mesa/main/api_exec.c | 6 ++ src/mesa/main/texobj.c | 211 +++++++++++++++++++++++++++++++++++++++ src/mesa/main/texobj.h | 8 ++ 3 files changed, 225 insertions(+) diff --git a/src/mesa/main/api_exec.c b/src/mesa/main/api_exec.c index bb5d17131ca..6b1499f4f06 100644 --- a/src/mesa/main/api_exec.c +++ b/src/mesa/main/api_exec.c @@ -827,10 +827,16 @@ _mesa_create_exec_table(struct gl_context *ctx) _mesa_init_sampler_object_dispatch(exec); #endif + if (_mesa_is_desktop_gl(ctx)) { + SET_InvalidateTexSubImage(exec, _mesa_InvalidateTexSubImage); + SET_InvalidateTexImage(exec, _mesa_InvalidateTexImage); + } + if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) { SET_InvalidateSubFramebuffer(exec, _mesa_InvalidateSubFramebuffer); SET_InvalidateFramebuffer(exec, _mesa_InvalidateFramebuffer); } + return exec; } diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c index 02e37bebc5e..1d905b608c4 100644 --- a/src/mesa/main/texobj.c +++ b/src/mesa/main/texobj.c @@ -877,7 +877,58 @@ _mesa_total_texture_memory(struct gl_context *ctx) return total; } +static struct gl_texture_object * +invalidate_tex_image_error_check(struct gl_context *ctx, GLuint texture, + GLint level, const char *name) +{ + /* The GL_ARB_invalidate_subdata spec says: + * + * "If is zero or is not the name of a texture, the error + * INVALID_VALUE is generated." + * + * This performs the error check in a different order than listed in the + * spec. We have to get the texture object before we can validate the + * other parameters against values in the texture object. + */ + struct gl_texture_object *const t = _mesa_lookup_texture(ctx, texture); + if (texture == 0 || t == NULL) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(texture)", name); + return NULL; + } + /* The GL_ARB_invalidate_subdata spec says: + * + * "If is less than zero or greater than the base 2 logarithm + * of the maximum texture width, height, or depth, the error + * INVALID_VALUE is generated." + */ + if (level < 0 || level > t->MaxLevel) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(level)", name); + return NULL; + } + + /* The GL_ARB_invalidate_subdata spec says: + * + * "If the target of is TEXTURE_RECTANGLE, TEXTURE_BUFFER, + * TEXTURE_2D_MULTISAMPLE, or TEXTURE_2D_MULTISAMPLE_ARRAY, and + * is not zero, the error INVALID_VALUE is generated." + */ + if (level != 0) { + switch (t->Target) { + case GL_TEXTURE_RECTANGLE: + case GL_TEXTURE_BUFFER: + case GL_TEXTURE_2D_MULTISAMPLE: + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: + _mesa_error(ctx, GL_INVALID_VALUE, "%s(level)", name); + return NULL; + + default: + break; + } + } + + return t; +} /*@}*/ @@ -1346,4 +1397,164 @@ _mesa_unlock_context_textures( struct gl_context *ctx ) _glthread_UNLOCK_MUTEX(ctx->Shared->TexMutex); } +void GLAPIENTRY +_mesa_InvalidateTexSubImage(GLuint texture, GLint level, GLint xoffset, + GLint yoffset, GLint zoffset, GLsizei width, + GLsizei height, GLsizei depth) +{ + struct gl_texture_object *t; + struct gl_texture_image *image; + GET_CURRENT_CONTEXT(ctx); + + ASSERT_OUTSIDE_BEGIN_END(ctx); + + t = invalidate_tex_image_error_check(ctx, texture, level, + "glInvalidateTexSubImage"); + + /* The GL_ARB_invalidate_subdata spec says: + * + * "...the specified subregion must be between - and + where + * is the size of the dimension of the texture image, and is + * the size of the border of that texture image, otherwise + * INVALID_VALUE is generated (border is not applied to dimensions that + * don't exist in a given texture target)." + */ + image = t->Image[0][level]; + if (image) { + int xBorder; + int yBorder; + int zBorder; + int imageWidth; + int imageHeight; + int imageDepth; + + /* The GL_ARB_invalidate_subdata spec says: + * + * "For texture targets that don't have certain dimensions, this + * command treats those dimensions as having a size of 1. For + * example, to invalidate a portion of a two-dimensional texture, + * the application would use equal to zero and + * equal to one." + */ + switch (t->Target) { + case GL_TEXTURE_BUFFER: + xBorder = 0; + yBorder = 0; + zBorder = 0; + imageWidth = 1; + imageHeight = 1; + imageDepth = 1; + break; + case GL_TEXTURE_1D: + xBorder = image->Border; + yBorder = 0; + zBorder = 0; + imageWidth = image->Width; + imageHeight = 1; + imageDepth = 1; + break; + case GL_TEXTURE_1D_ARRAY: + xBorder = image->Border; + yBorder = 0; + zBorder = 0; + imageWidth = image->Width; + imageHeight = image->Height; + imageDepth = 1; + break; + case GL_TEXTURE_2D: + case GL_TEXTURE_CUBE_MAP: + case GL_TEXTURE_RECTANGLE: + case GL_TEXTURE_2D_MULTISAMPLE: + xBorder = image->Border; + yBorder = image->Border; + zBorder = 0; + imageWidth = image->Width; + imageHeight = image->Height; + imageDepth = 1; + break; + case GL_TEXTURE_2D_ARRAY: + case GL_TEXTURE_CUBE_MAP_ARRAY: + xBorder = image->Border; + yBorder = image->Border; + zBorder = 0; + imageWidth = image->Width; + imageHeight = image->Height; + imageDepth = image->Depth; + break; + case GL_TEXTURE_3D: + xBorder = image->Border; + yBorder = image->Border; + zBorder = image->Border; + imageWidth = image->Width; + imageHeight = image->Height; + imageDepth = image->Depth; + break; + default: + assert(!"Should not get here."); + xBorder = 0; + yBorder = 0; + zBorder = 0; + imageWidth = 0; + imageHeight = 0; + imageDepth = 0; + break; + } + + if (xoffset < -xBorder) { + _mesa_error(ctx, GL_INVALID_VALUE, "glInvalidateSubTexImage(xoffset)"); + return; + } + + if (xoffset + width > imageWidth + xBorder) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glInvalidateSubTexImage(xoffset+width)"); + return; + } + + if (yoffset < -yBorder) { + _mesa_error(ctx, GL_INVALID_VALUE, "glInvalidateSubTexImage(yoffset)"); + return; + } + + if (yoffset + height > imageHeight + yBorder) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glInvalidateSubTexImage(yoffset+height)"); + return; + } + + if (zoffset < -zBorder) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glInvalidateSubTexImage(zoffset)"); + return; + } + + if (zoffset + depth > imageDepth + zBorder) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glInvalidateSubTexImage(zoffset+depth)"); + return; + } + } + + /* We don't actually do anything for this yet. Just return after + * validating the parameters and generating the required errors. + */ + return; +} + +void GLAPIENTRY +_mesa_InvalidateTexImage(GLuint texture, GLint level) +{ + GET_CURRENT_CONTEXT(ctx); + + ASSERT_OUTSIDE_BEGIN_END(ctx); + + invalidate_tex_image_error_check(ctx, texture, level, + "glInvalidateTexImage"); + + /* We don't actually do anything for this yet. Just return after + * validating the parameters and generating the required errors. + */ + return; +} + /*@}*/ diff --git a/src/mesa/main/texobj.h b/src/mesa/main/texobj.h index 23e1ade090c..93e0d77382e 100644 --- a/src/mesa/main/texobj.h +++ b/src/mesa/main/texobj.h @@ -152,6 +152,14 @@ _mesa_AreTexturesResident( GLsizei n, const GLuint *textures, extern GLboolean GLAPIENTRY _mesa_IsTexture( GLuint texture ); +extern void GLAPIENTRY +_mesa_InvalidateTexSubImage(GLuint texture, GLint level, GLint xoffset, + GLint yoffset, GLint zoffset, GLsizei width, + GLsizei height, GLsizei depth); + +extern void GLAPIENTRY +_mesa_InvalidateTexImage(GLuint texture, GLint level); + /*@}*/