mesa: Add skeleton implementations of glInvalidateTex{Sub,}Image
authorIan Romanick <ian.d.romanick@intel.com>
Mon, 13 Aug 2012 20:14:25 +0000 (13:14 -0700)
committerIan Romanick <ian.d.romanick@intel.com>
Tue, 14 Aug 2012 21:39:33 +0000 (14:39 -0700)
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 <ian.d.romanick@intel.com>
Reviewed-by: Brian Paul <brianp@vmware.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
src/mesa/main/api_exec.c
src/mesa/main/texobj.c
src/mesa/main/texobj.h

index bb5d17131cad623c1c193e24be0295326634bcb5..6b1499f4f0616d7a279800eea9d9efe107ecfbfe 100644 (file)
@@ -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;
 }
 
index 02e37bebc5ec0569f6d7c010154ea45d9b88984d..1d905b608c46df6de6f56df291cf5843b5b9d8c9 100644 (file)
@@ -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 <texture> 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 <level> 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 <texture> is TEXTURE_RECTANGLE, TEXTURE_BUFFER,
+    *     TEXTURE_2D_MULTISAMPLE, or TEXTURE_2D_MULTISAMPLE_ARRAY, and <level>
+    *     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 -<b> and <dim>+<b> where
+    *     <dim> is the size of the dimension of the texture image, and <b> 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 <zoffset> equal to zero and <depth>
+       *     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;
+}
+
 /*@}*/
index 23e1ade090c10e5c72873e031d8b93903d63ddfc..93e0d77382e021c86381aa0e8828170bbc394ae5 100644 (file)
@@ -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);
+
 /*@}*/