[Mesa-dev] [PATCH 5/5] meta: Add a meta implementation of GL_ARB_clear_texture

Pohjolainen, Topi topi.pohjolainen at intel.com
Wed Jul 2 04:51:11 PDT 2014


On Sat, Jun 14, 2014 at 01:59:31AM +0100, Neil Roberts wrote:
> Adds an implementation of the ClearTexSubImage driver entry point that tries
> to set up an FBO to render to the texture and then calls glClear with a
> scissor to perform the actual clear. If an FBO can't be created for the
> texture then it will fall back to using _mesa_store_ClearTexSubImage.
> ---
>  src/mesa/drivers/common/driverfuncs.c |   2 +-
>  src/mesa/drivers/common/meta.c        | 162 ++++++++++++++++++++++++++++++++++
>  src/mesa/drivers/common/meta.h        |   7 ++
>  3 files changed, 170 insertions(+), 1 deletion(-)
> 
> diff --git a/src/mesa/drivers/common/driverfuncs.c b/src/mesa/drivers/common/driverfuncs.c
> index 34b6fef..1ac2aee 100644
> --- a/src/mesa/drivers/common/driverfuncs.c
> +++ b/src/mesa/drivers/common/driverfuncs.c
> @@ -95,7 +95,7 @@ _mesa_init_driver_functions(struct dd_function_table *driver)
>     driver->TexImage = _mesa_store_teximage;
>     driver->TexSubImage = _mesa_store_texsubimage;
>     driver->GetTexImage = _mesa_meta_GetTexImage;
> -   driver->ClearTexSubImage = _mesa_store_cleartexsubimage;
> +   driver->ClearTexSubImage = _mesa_meta_ClearTexSubImage;
>     driver->CopyTexSubImage = _mesa_meta_CopyTexSubImage;
>     driver->GenerateMipmap = _mesa_meta_GenerateMipmap;
>     driver->TestProxyTexImage = _mesa_test_proxy_teximage;
> diff --git a/src/mesa/drivers/common/meta.c b/src/mesa/drivers/common/meta.c
> index cab0dd8..7308ce6 100644
> --- a/src/mesa/drivers/common/meta.c
> +++ b/src/mesa/drivers/common/meta.c
> @@ -40,6 +40,7 @@
>  #include "main/blit.h"
>  #include "main/bufferobj.h"
>  #include "main/buffers.h"
> +#include "main/clear.h"
>  #include "main/colortab.h"
>  #include "main/condrender.h"
>  #include "main/depth.h"
> @@ -47,6 +48,7 @@
>  #include "main/fbobject.h"
>  #include "main/feedback.h"
>  #include "main/formats.h"
> +#include "main/format_unpack.h"
>  #include "main/glformats.h"
>  #include "main/image.h"
>  #include "main/macros.h"
> @@ -71,6 +73,7 @@
>  #include "main/teximage.h"
>  #include "main/texparam.h"
>  #include "main/texstate.h"
> +#include "main/texstore.h"
>  #include "main/transformfeedback.h"
>  #include "main/uniforms.h"
>  #include "main/varray.h"
> @@ -3360,3 +3363,162 @@ _mesa_meta_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z,
>  
>     _mesa_meta_end(ctx);
>  }
> +
> +static void
> +set_color_clear_value(struct gl_context *ctx,
> +                      mesa_format format,
> +                      const GLvoid *clearValue)
> +{
> +   if (clearValue == 0) {
> +         memset(&ctx->Color.ClearColor, 0, sizeof ctx->Color.ClearColor);
> +   }
> +   else {

This should go to the previous line with the closing '{'. (The rest of the
patch uses this style correctly).

> +      switch (_mesa_get_format_datatype(format)) {
> +      case GL_UNSIGNED_INT:
> +      case GL_INT:
> +         _mesa_unpack_uint_rgba_row(format, 1, clearValue,
> +                                    (GLuint (*)[4]) ctx->Color.ClearColor.ui);
> +         break;
> +      default:
> +         _mesa_unpack_rgba_row(format, 1, clearValue,
> +                               (GLfloat (*)[4]) ctx->Color.ClearColor.f);
> +         break;
> +      }
> +   }
> +}
> +
> +static bool
> +cleartexsubimage_using_fbo_for_zoffset(struct gl_context *ctx,
> +                                       struct gl_texture_image *texImage,
> +                                       GLint xoffset, GLint yoffset,
> +                                       GLint zoffset,
> +                                       GLsizei width, GLsizei height,
> +                                       const GLvoid *clearValue)
> +{
> +   GLuint fbo;
> +   bool success = false;
> +   GLbitfield mask;
> +   GLenum status;
> +   GLuint depthStencilValue[2];
> +   GLfloat depthValue;

The scope for these two could be reduced by placing them into the if-block.

> +
> +   _mesa_GenFramebuffers(1, &fbo);
> +   _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
> +
> +   if (texImage->_BaseFormat == GL_DEPTH_STENCIL ||
> +       texImage->_BaseFormat == GL_DEPTH_COMPONENT) {
> +      _mesa_meta_bind_fbo_image(GL_DEPTH_ATTACHMENT, texImage, zoffset);
> +      mask = GL_DEPTH_BUFFER_BIT;
> +
> +      if (clearValue)
> +         _mesa_unpack_float_32_uint_24_8_depth_stencil_row(texImage->TexFormat,
> +                                                           1, /* n */
> +                                                           clearValue,
> +                                                           depthStencilValue);

I wouldn't mind having a little explanation why the clear value for
depth/stencil is always "float_32_uint_24_8" - I guess this is forced
somewhere else. This is not obvious to me after having looked at the spec and
the implementation of _mesa_store_teximage() that seems to allow all the
different variants:

      table[MESA_FORMAT_S8_UINT_Z24_UNORM] = _mesa_texstore_z24_s8;
      table[MESA_FORMAT_Z24_UNORM_S8_UINT] = _mesa_texstore_s8_z24;
      table[MESA_FORMAT_Z_UNORM16] = _mesa_texstore_z16;
      table[MESA_FORMAT_Z24_UNORM_X8_UINT] = _mesa_texstore_x8_z24;
      table[MESA_FORMAT_X8_UINT_Z24_UNORM] = _mesa_texstore_z24_x8;
      table[MESA_FORMAT_Z_UNORM32] = _mesa_texstore_z32;
      table[MESA_FORMAT_Z_FLOAT32] = _mesa_texstore_z32;
      table[MESA_FORMAT_Z32_FLOAT_S8X24_UINT] = _mesa_texstore_z32f_x24s8;

Quote from the spec:

    "5. Should depth/stencil textures be supported? If so, are the depth
     and stencil values provided separately?

     RESOLVED. Depth/stencil textures are supported in the same manner
     they are for TexSubImage.  The format and type describe how the
     data is interpreted."

> +      else
> +         memset(depthStencilValue, 0, sizeof depthStencilValue);

Would it be a little clearer to assign the clear value directly instead of
the temporary copy:

            ctx->Depth.Clear = (GLfloat)depthStencilValue[0];
         } else {
            ctx->Depth.Clear = 0;
            depthStencilValue[1] = 0;
         }

> +
> +      memcpy(&depthValue, depthStencilValue, sizeof depthValue);
> +      ctx->Depth.Clear = depthValue;
> +
> +      if (texImage->_BaseFormat == GL_DEPTH_STENCIL) {
> +         _mesa_meta_bind_fbo_image(GL_STENCIL_ATTACHMENT, texImage, zoffset);
> +         mask |= GL_STENCIL_BUFFER_BIT;
> +         ctx->Stencil.Clear = depthStencilValue[1] & 0xff;
> +      }
> +      _mesa_DrawBuffer(GL_NONE);
> +   } else {
> +      _mesa_meta_bind_fbo_image(GL_COLOR_ATTACHMENT0, texImage, zoffset);
> +      _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0);
> +      mask = GL_COLOR_BUFFER_BIT;
> +
> +      set_color_clear_value(ctx, texImage->TexFormat, clearValue);
> +   }
> +
> +   status = _mesa_CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
> +   if (status != GL_FRAMEBUFFER_COMPLETE)
> +      goto out;
> +
> +   _mesa_set_enable(ctx, GL_SCISSOR_TEST, GL_TRUE);
> +   _mesa_Scissor(xoffset, yoffset, width, height);
> +   _mesa_Clear(mask);
> +
> +   success = true;
> +
> + out:
> +   _mesa_DeleteFramebuffers(1, &fbo);
> +   return success;
> +}
> +
> +static bool
> +cleartexsubimage_using_fbo(struct gl_context *ctx,
> +                           struct gl_texture_image *texImage,
> +                           GLint xoffset, GLint yoffset, GLint zoffset,
> +                           GLsizei width, GLsizei height, GLsizei depth,
> +                           const GLvoid *clearValue)
> +{
> +   union gl_color_union saveColorValue;
> +   bool success = false;
> +
> +   if (!ctx->Extensions.ARB_framebuffer_object)
> +      return false;
> +
> +   /* This probably won't work with images that have a border */
> +   if (texImage->Border != 0)
> +      return false;
> +
> +   _mesa_meta_begin(ctx,
> +                    MESA_META_SCISSOR |
> +                    MESA_META_COLOR_MASK |
> +                    MESA_META_DEPTH_TEST |
> +                    MESA_META_STENCIL_TEST);
> +
> +   /* _mesa_meta_begin doesn't seem to save this */
> +   saveColorValue = ctx->Color.ClearColor;

Don't we need to save the depth and stencil clear colors as well?

> +
> +   while (depth-- > 0) {
> +      if (!cleartexsubimage_using_fbo_for_zoffset(ctx, texImage,
> +                                                  xoffset, yoffset, zoffset++,
> +                                                  width, height,
> +                                                  clearValue))
> +         goto out;
> +   }
> +
> +   success = true;
> +
> + out:
> +   ctx->Color.ClearColor = saveColorValue;
> +   _mesa_meta_end(ctx);
> +   return success;
> +}
> +
> +extern void
> +_mesa_meta_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)
> +{
> +   bool res;
> +
> +   _mesa_unlock_texture(ctx, texImage->TexObject);
> +
> +   res = cleartexsubimage_using_fbo(ctx, texImage,
> +                                    xoffset, yoffset, zoffset,
> +                                    width, height, depth,
> +                                    clearValue);
> +
> +   _mesa_lock_texture(ctx, texImage->TexObject);
> +
> +   if (res)
> +      return;
> +
> +   _mesa_warning(ctx,
> +                 "Falling back to mapping the texture in "
> +                 "glClearTexSubImage\n");
> +
> +   _mesa_store_cleartexsubimage(ctx, texImage,
> +                                xoffset, yoffset, zoffset,
> +                                width, height, depth,
> +                                clearValue);
> +}
> diff --git a/src/mesa/drivers/common/meta.h b/src/mesa/drivers/common/meta.h
> index 765f8df..863ab3f 100644
> --- a/src/mesa/drivers/common/meta.h
> +++ b/src/mesa/drivers/common/meta.h
> @@ -473,6 +473,13 @@ _mesa_meta_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
>                             GLsizei width, GLsizei height);
>  
>  extern void
> +_mesa_meta_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);
> +
> +extern void
>  _mesa_meta_GetTexImage(struct gl_context *ctx,
>                         GLenum format, GLenum type, GLvoid *pixels,
>                         struct gl_texture_image *texImage);
> -- 
> 1.9.3
> 
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list