[Mesa-dev] [PATCH] mesa/main: add ARB_clear_texture entrypoints

Brian Paul brianp at vmware.com
Mon Mar 3 09:37:49 PST 2014


On 03/01/2014 03:09 PM, Ilia Mirkin wrote:
> This adds enough code to let drivers implement texture clearing, but
> doesn't actually do that for any of them.
>
> Signed-off-by: Ilia Mirkin <imirkin at alum.mit.edu>
> ---
>
> Thought I'd give this a shot. Am I on the right track here? Is the dd API
> reasonable? I haven't written a piglit test for all the "generic" error cases
> yet, but I'll get to that in a bit. I'm a little confused between all the
> different formats on a teximage... BaseFormat appears to be some
> generalization of the format, but what's the difference between InternalFormat
> and TexFormat?

InternalFormat is what the user requested when the texture was created, 
such as GL_RGB565 or GL_DEPTH_COMPONENT24.  BaseFormat is the 
internalFormat boiled down to a basic format, such as GL_RGB or 
GL_DEPTH_COMPONENT.  The BaseFormat was originally used for applying the 
glTexEnv mode.  It's also used to check for compatibility of src/dest 
surfaces for glCopyTexImage, etc.



> Just the type, but otherwise equivalent? Or are they
> representing different things?
>
> BTW, this is the first time I'm adding stuff to mesa/main, so forgive me if I
> left out a step.
>
>   src/mapi/glapi/gen/ARB_clear_texture.xml |  34 ++++++++
>   src/mapi/glapi/gen/gl_API.xml            |   2 +
>   src/mesa/main/dd.h                       |  11 +++
>   src/mesa/main/formatquery.c              |   9 +++
>   src/mesa/main/mtypes.h                   |   1 +
>   src/mesa/main/tests/dispatch_sanity.cpp  |   4 +
>   src/mesa/main/teximage.c                 | 131 +++++++++++++++++++++++++++++++
>   src/mesa/main/teximage.h                 |  10 +++
>   8 files changed, 202 insertions(+)
>   create mode 100644 src/mapi/glapi/gen/ARB_clear_texture.xml
>
> diff --git a/src/mapi/glapi/gen/ARB_clear_texture.xml b/src/mapi/glapi/gen/ARB_clear_texture.xml
> new file mode 100644
> index 0000000..bd9116f
> --- /dev/null
> +++ b/src/mapi/glapi/gen/ARB_clear_texture.xml
> @@ -0,0 +1,34 @@
> +<?xml version="1.0"?>
> +<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd">
> +
> +<OpenGLAPI>
> +
> +<category name="GL_ARB_clear_texture" number="145">
> +
> +    <enum name="CLEAR_TEXTURE" value="0x9365"/>
> +
> +    <function name ="ClearTexImage" offset="assign">
> +        <param name="texture" type="GLuint"/>
> +        <param name="level" type="GLint"/>
> +        <param name="format" type="GLenum"/>
> +        <param name="type" type="GLenum"/>
> +        <param name="data" type="const GLvoid *"/>

s/GLvoid/void/  The ARB has deprecated the GLvoid type.


> +    </function>
> +
> +    <function name ="ClearTexSubImage" offset="assign">
> +        <param name="texture" type="GLuint"/>
> +        <param name="level" type="GLint"/>
> +        <param name="xoffset" type="GLint"/>
> +        <param name="yoffset" type="GLint"/>
> +        <param name="zoffset" type="GLint"/>
> +        <param name="width" type="GLsizei"/>
> +        <param name="height" type="GLsizei"/>
> +        <param name="depth" type="GLsizei"/>
> +        <param name="format" type="GLenum"/>
> +        <param name="type" type="GLenum"/>
> +        <param name="data" type="const GLvoid *"/>

s/GLvoid/void/


> +    </function>
> +
> +</category>
> +
> +</OpenGLAPI>
> diff --git a/src/mapi/glapi/gen/gl_API.xml b/src/mapi/glapi/gen/gl_API.xml
> index 7e1946e..15f8e32 100644
> --- a/src/mapi/glapi/gen/gl_API.xml
> +++ b/src/mapi/glapi/gen/gl_API.xml
> @@ -8515,6 +8515,8 @@
>       </function>
>   </category>
>
> +<xi:include href="ARB_clear_texture.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
> +
>   <!-- Non-ARB extensions sorted by extension number. -->
>
>   <category name="GL_EXT_blend_color" number="2">
> diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h
> index 9715241..d824bca 100644
> --- a/src/mesa/main/dd.h
> +++ b/src/mesa/main/dd.h
> @@ -275,6 +275,17 @@ struct dd_function_table {
>                                     GLint level, mesa_format format,
>                                     GLint width, GLint height,
>                                     GLint depth, GLint border);
> +
> +
> +   void (*ClearTexSubImage)(struct gl_context *ctx,
> +                            struct gl_texture_image *texImage,
> +                            GLint xoffset, GLint yoffset, GLint zoffset,
> +                            GLsizei width, GLsizei height, GLsizei depth,
> +                            GLenum format, GLenum type, const GLvoid *data);

I think we may want to follow the example of ClearBufferSubData() and 
pass a clearValue and clearValueSize instead of format/type/data.


> +
> +   GLenum (*QuerySupportForClearTex)(struct gl_context *ctx,
> +                                     GLenum internalFormat);

The spec says the GL_CLEAR_TEXTURE query is only supported if 
GL_ARB_internalformat_query2 is supported (and we don't).  So I'm not 
sure we need this function at this time.


> +
>      /*@}*/
>
>
> diff --git a/src/mesa/main/formatquery.c b/src/mesa/main/formatquery.c
> index 40eca87..7997cb4 100644
> --- a/src/mesa/main/formatquery.c
> +++ b/src/mesa/main/formatquery.c
> @@ -140,6 +140,15 @@ _mesa_GetInternalformativ(GLenum target, GLenum internalformat, GLenum pname,
>         count = 1;
>         break;
>      }
> +   case GL_CLEAR_TEXTURE:
> +      if (ctx->Extensions.ARB_clear_texture) {
> +         const GLenum support = ctx->Driver.QuerySupportForClearTex(
> +               ctx, internalformat);
> +         buffer[0] = (GLint) support;
> +         count = 1;
> +         break;
> +      }
> +      /* fallthrough */

I'm not sure this is needed.  See above.


>      default:
>         _mesa_error(ctx, GL_INVALID_ENUM,
>                     "glGetInternalformativ(pname=%s)",
> diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
> index 7246b1e..e4a3837 100644
> --- a/src/mesa/main/mtypes.h
> +++ b/src/mesa/main/mtypes.h
> @@ -3490,6 +3490,7 @@ struct gl_extensions
>      GLboolean ARB_base_instance;
>      GLboolean ARB_blend_func_extended;
>      GLboolean ARB_buffer_storage;
> +   GLboolean ARB_clear_texture;

I suspect that we should be able to implement this for all drivers so 
this flag may not be needed.  It's OK for now though.


>      GLboolean ARB_color_buffer_float;
>      GLboolean ARB_compute_shader;
>      GLboolean ARB_conservative_depth;
> diff --git a/src/mesa/main/tests/dispatch_sanity.cpp b/src/mesa/main/tests/dispatch_sanity.cpp
> index d1b0011..8690b5d 100644
> --- a/src/mesa/main/tests/dispatch_sanity.cpp
> +++ b/src/mesa/main/tests/dispatch_sanity.cpp
> @@ -936,6 +936,10 @@ const struct function gl_core_functions_possible[] = {
>      /* GL_ARB_buffer_storage */
>      { "glBufferStorage", 43, -1 },
>
> +   /* GL_ARB_clear_texture */
> +   { "glClearTexImage", 13, -1 },
> +   { "glClearTexSubImage", 13, -1 },
> +
>      { NULL, 0, -1 }
>   };
>
> diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c
> index 0519d22..9171187 100644
> --- a/src/mesa/main/teximage.c
> +++ b/src/mesa/main/teximage.c
> @@ -3768,6 +3768,137 @@ _mesa_CopyTexSubImage3D( GLenum target, GLint level,
>                      x, y, width, height);
>   }
>
> +static struct gl_texture_image *
> +get_tex_image(struct gl_context *ctx, GLuint texture, GLint level, GLint zoffset)
> +{
> +   GLenum target = 0;
> +   struct gl_texture_object *texObj = _mesa_lookup_texture(ctx, texture);
> +   struct gl_texture_image *texImage;
> +
> +   if (!texture || !texObj) {
> +      _mesa_error(ctx, GL_INVALID_OPERATION,
> +                  "glClearTexSubImage(invalid texture)");
> +      return NULL;
> +   }
> +
> +   switch (texObj->Target) {
> +   case GL_TEXTURE_BUFFER:
> +      _mesa_error(ctx, GL_INVALID_OPERATION,
> +                  "glClearTexSubImage(texture can't be buffer)");
> +      return NULL;
> +   case GL_TEXTURE_CUBE_MAP_ARB:
> +   case GL_TEXTURE_CUBE_MAP_ARRAY:
> +      target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + zoffset;
> +      break;
> +   default:
> +      break;
> +   }
> +
> +   texImage = _mesa_select_tex_image(ctx, texObj, target, level);
> +   if (!texImage) {
> +      _mesa_error(ctx, GL_INVALID_OPERATION,
> +                  "glClearTexSubImage(missing image)");
> +      return NULL;
> +   }
> +
> +   return texImage;
> +}
> +
> +static void
> +clear_tex_sub_image(struct gl_context *ctx, struct gl_texture_image *texImage,
> +                    GLint xoffset, GLint yoffset, GLint zoffset,
> +                    GLsizei width, GLsizei height, GLsizei depth,
> +                    GLenum format, GLenum type, const void *data)
> +{
> +   if (!texImage)
> +      return;
> +
> +   if (_mesa_is_compressed_format(ctx, texImage->InternalFormat)) {
> +      _mesa_error(ctx, GL_INVALID_OPERATION,
> +                  "glClearTexSubImage(compressed format)");
> +      return;
> +   }
> +
> +   if (texImage->_BaseFormat == GL_DEPTH_COMPONENT &&
> +       format != GL_DEPTH_COMPONENT) {
> +      _mesa_error(ctx, GL_INVALID_OPERATION,
> +                  "glClearTexSubImage(invalid format)");
> +      return;
> +   }
> +   if (texImage->_BaseFormat == GL_DEPTH_STENCIL &&
> +       format != GL_DEPTH_STENCIL) {
> +      _mesa_error(ctx, GL_INVALID_OPERATION,
> +                  "glClearTexSubImage(invalid format)");
> +      return;
> +   }
> +   if (texImage->_BaseFormat == GL_STENCIL_INDEX &&
> +       format != GL_STENCIL_INDEX) {
> +      _mesa_error(ctx, GL_INVALID_OPERATION,
> +                  "glClearTexSubImage(invalid format)");
> +      return;
> +   }
> +   if (texImage->_BaseFormat == GL_RGBA &&

_BaseFormat may also be GL_RGB, GL_ALPHA, GL_LUMINANCE, etc.

I think if you used else-ifs above, by time you get here you can be sure 
the _BaseFormat is a color format.  Or, you could use 
_mesa_is_color_format(_BaseFormat).


> +       (format == GL_DEPTH_COMPONENT ||
> +        format == GL_DEPTH_STENCIL ||
> +        format == GL_STENCIL_INDEX)) {
> +      _mesa_error(ctx, GL_INVALID_OPERATION,
> +                  "glClearTexSubImage(invalid format)");
> +      return;
> +   }
> +   if (_mesa_is_format_integer_color(texImage->InternalFormat) !=
> +       _mesa_is_format_integer_color(format)) {
> +      _mesa_error(ctx, GL_INVALID_OPERATION,
> +                  "glClearTexSubImage(invalid format)");
> +      return;
> +   }
> +
> +   if (xoffset < -texImage->Border ||
> +       xoffset + width > texImage->Width - texImage->Border ||
> +       yoffset < -texImage->Border ||
> +       yoffset + height > texImage->Height - texImage->Border ||
> +       zoffset < -texImage->Border ||
> +       zoffset + depth > texImage->Depth - texImage->Border) {
> +      _mesa_error(ctx, GL_INVALID_OPERATION,
> +                  "glClearTexSubImage(invalid bounds)");
> +   }
> +
> +   ctx->Driver.ClearTexSubImage(ctx, texImage, xoffset, yoffset, zoffset,
> +                                width, height, depth, format, type, data);

If we change the driver function to take clearValue and clearValueSize, 
you'd use the convert_clear_buffer_data() function to convert the clear 
value from the user's format to the texture mesa_format.


> +}
> +
> +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_image *texImage =
> +      get_tex_image(ctx, texture, level, zoffset);

check if texImage is NULL here, as you do below.


> +
> +   clear_tex_sub_image(ctx, texImage, xoffset, yoffset, zoffset,
> +                       width, height, depth, format, type, data);
> +}
> +
> +void GLAPIENTRY
> +_mesa_ClearTexImage( GLuint texture, GLint level,
> +                     GLenum format, GLenum type, const void *data )
> +{
> +   GET_CURRENT_CONTEXT(ctx);
> +
> +   struct gl_texture_image *texImage
> +      = get_tex_image(ctx, texture, level, 0);
> +   if (!texImage)
> +      return;
> +
> +   /* XXX figure out which dimensions the texImage has, and pass in 0's for
> +    * the border.
> +    */
> +   clear_tex_sub_image(ctx, texImage,
> +                       -texImage->Border, -texImage->Border, -texImage->Border,
> +                       texImage->Width, texImage->Height, texImage->Depth,

Even though we don't really support borders anymore, I believe this 
should be:

texImage->Width + 2 * texImage->Boarder, etc.


> +                       format, type, data);
> +}
>
>
>
> diff --git a/src/mesa/main/teximage.h b/src/mesa/main/teximage.h
> index 5f8a477..4d01ff9 100644
> --- a/src/mesa/main/teximage.h
> +++ b/src/mesa/main/teximage.h
> @@ -261,6 +261,16 @@ _mesa_CopyTexSubImage3D( GLenum target, GLint level,
>
>
>   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 );
> +
> +extern void GLAPIENTRY
> +_mesa_ClearTexImage( GLuint texture, GLint level,
> +                     GLenum format, GLenum type, const void *data );
> +
> +extern void GLAPIENTRY
>   _mesa_CompressedTexImage1D(GLenum target, GLint level,
>                                 GLenum internalformat, GLsizei width,
>                                 GLint border, GLsizei imageSize,
>


This looks good in general.  I think you should proceed with fallback 
tex-clear functions for the state tracker and legacy drivers to flesh 
out the clearValue/clearValueSize issue.

-Brian



More information about the mesa-dev mailing list