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

Pohjolainen, Topi topi.pohjolainen at intel.com
Mon Jul 7 02:00:11 PDT 2014


On Fri, Jul 04, 2014 at 05:26:44PM +0100, Neil Roberts wrote:
> Here is version 3 of the glClearTexImage implementation. I figured out
> I could avoid the whole issue of preserving the glClearColor state by
> using glClearBuffer instead of glClear. I think the patch is a lot
> neater this way.

I like it also, just a small nit below.

> 
> I also fixed using sRGB textures and explicitly disabled dithering.
> 
> - Neil
> 
> ------- >8 --------------- (use git am --scissors to automatically chop here)
> 
> Adds an implementation of the ClearTexSubImage driver entry point that tries
> to set up an FBO to render to the texture and then calls glClearBuffer 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.
> 
> When used in combination with _mesa_store_ClearTexSubImage this should provide
> an implementation that works for all DRI-based drivers. However as this has
> only been tested with the i965 driver it is currently only enabled there.
> 
> v2: Only enable the extension for the i965 driver instead of all DRI drivers.
>     Remove an unnecessary goto. Don't require GL_ARB_framebuffer_object. Add
>     some more comments.
> 
> v3: Use glClearBuffer* to avoid having to modify glClearColor and friends.
>     Handle sRGB textures. Explicitly disable dithering.
> 
> Reviewed-by: Topi Pohjolainen <topi.pohjolainen at intel.com>
> ---
>  src/mesa/drivers/common/driverfuncs.c        |   1 +
>  src/mesa/drivers/common/meta.c               | 189 +++++++++++++++++++++++++++
>  src/mesa/drivers/common/meta.h               |   7 +
>  src/mesa/drivers/dri/i965/intel_extensions.c |   1 +
>  4 files changed, 198 insertions(+)
> 
> diff --git a/src/mesa/drivers/common/driverfuncs.c b/src/mesa/drivers/common/driverfuncs.c
> index 6ece5d8..4f0f7a6 100644
> --- a/src/mesa/drivers/common/driverfuncs.c
> +++ b/src/mesa/drivers/common/driverfuncs.c
> @@ -95,6 +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_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 10dd418..a47b7b9 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"
> @@ -3347,3 +3350,189 @@ _mesa_meta_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z,
>  
>     _mesa_meta_end(ctx);
>  }
> +
> +static bool
> +cleartexsubimage_color(struct gl_context *ctx,
> +                       struct gl_texture_image *texImage,
> +                       const GLvoid *clearValue,
> +                       GLint zoffset)
> +{
> +   mesa_format format;
> +   union gl_color_union colorValue;
> +   GLenum datatype;
> +   GLenum status;
> +
> +   _mesa_meta_bind_fbo_image(GL_COLOR_ATTACHMENT0, texImage, zoffset);
> +
> +   status = _mesa_CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
> +   if (status != GL_FRAMEBUFFER_COMPLETE)
> +      return false;
> +
> +   /* We don't want to apply an sRGB conversion so override the format */
> +   format = _mesa_get_srgb_format_linear(texImage->TexFormat);
> +   datatype = _mesa_get_format_datatype(format);
> +
> +   switch (datatype) {
> +   case GL_UNSIGNED_INT:
> +   case GL_INT:
> +      if (clearValue)
> +         _mesa_unpack_uint_rgba_row(format, 1, clearValue,
> +                                    (GLuint (*)[4]) colorValue.ui);
> +      else
> +         memset(&colorValue, 0, sizeof colorValue);
> +      if (datatype == GL_INT)
> +         glClearBufferiv(GL_COLOR, 0, colorValue.i);
> +      else
> +         glClearBufferuiv(GL_COLOR, 0, colorValue.ui);
> +      break;
> +   default:
> +      if (clearValue)
> +         _mesa_unpack_rgba_row(format, 1, clearValue,
> +                               (GLfloat (*)[4]) colorValue.f);
> +      else
> +         memset(&colorValue, 0, sizeof colorValue);
> +      glClearBufferfv(GL_COLOR, 0, colorValue.f);

Here in this function you use glClearBuffer*() and later on
in cleartexsubimage_depth_stencil() you use _mesa_ClearBuffer*() - I would
switch to the latter here also.

> +      break;
> +   }
> +
> +   return true;
> +}
> +
> +static bool
> +cleartexsubimage_depth_stencil(struct gl_context *ctx,
> +                               struct gl_texture_image *texImage,
> +                               const GLvoid *clearValue,
> +                               GLint zoffset)
> +{
> +   GLint stencilValue;
> +   GLfloat depthValue;
> +   GLenum status;
> +
> +   _mesa_meta_bind_fbo_image(GL_DEPTH_ATTACHMENT, texImage, zoffset);
> +
> +   if (texImage->_BaseFormat == GL_DEPTH_STENCIL)
> +      _mesa_meta_bind_fbo_image(GL_STENCIL_ATTACHMENT, texImage, zoffset);
> +
> +   status = _mesa_CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
> +   if (status != GL_FRAMEBUFFER_COMPLETE)
> +      return false;
> +
> +   if (clearValue) {
> +      GLuint depthStencilValue[2];
> +
> +      /* Convert the clearValue from whatever format it's in to a floating
> +       * point value for the depth and an integer value for the stencil index
> +       */
> +      _mesa_unpack_float_32_uint_24_8_depth_stencil_row(texImage->TexFormat,
> +                                                        1, /* n */
> +                                                        clearValue,
> +                                                        depthStencilValue);
> +      /* We need a memcpy here instead of a cast because we need to
> +       * reinterpret the bytes as a float rather than converting it
> +       */
> +      memcpy(&depthValue, depthStencilValue, sizeof depthValue);
> +      stencilValue = depthStencilValue[1] & 0xff;
> +   } else {
> +      depthValue = 0.0f;
> +      stencilValue = 0;
> +   }
> +
> +   if (texImage->_BaseFormat == GL_DEPTH_STENCIL)
> +      _mesa_ClearBufferfi(GL_DEPTH_STENCIL, 0, depthValue, stencilValue);
> +   else
> +      _mesa_ClearBufferfv(GL_DEPTH, 0, &depthValue);
> +
> +   return true;
> +}
> +
> +static bool
> +cleartexsubimage_for_zoffset(struct gl_context *ctx,
> +                             struct gl_texture_image *texImage,
> +                             GLint zoffset,
> +                             const GLvoid *clearValue)
> +{
> +   GLuint fbo;
> +   bool success;
> +
> +   _mesa_GenFramebuffers(1, &fbo);
> +   _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
> +
> +   switch(texImage->_BaseFormat) {
> +   case GL_DEPTH_STENCIL:
> +   case GL_DEPTH_COMPONENT:
> +      success = cleartexsubimage_depth_stencil(ctx, texImage,
> +                                               clearValue, zoffset);
> +      break;
> +   default:
> +      success = cleartexsubimage_color(ctx, texImage, clearValue, zoffset);
> +      break;
> +   }
> +
> +   _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)
> +{
> +   bool success = true;
> +   GLint z;
> +
> +   _mesa_meta_begin(ctx,
> +                    MESA_META_SCISSOR |
> +                    MESA_META_COLOR_MASK |
> +                    MESA_META_DITHER |
> +                    MESA_META_FRAMEBUFFER_SRGB);
> +
> +   _mesa_set_enable(ctx, GL_DITHER, GL_FALSE);
> +
> +   _mesa_set_enable(ctx, GL_SCISSOR_TEST, GL_TRUE);
> +   _mesa_Scissor(xoffset, yoffset, width, height);
> +
> +   for (z = zoffset; z < zoffset + depth; z++) {
> +      if (!cleartexsubimage_for_zoffset(ctx, texImage, z, clearValue)) {
> +         success = false;
> +         break;
> +      }
> +   }
> +
> +   _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 b8d992c..b269dce 100644
> --- a/src/mesa/drivers/common/meta.h
> +++ b/src/mesa/drivers/common/meta.h
> @@ -477,6 +477,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);
> diff --git a/src/mesa/drivers/dri/i965/intel_extensions.c b/src/mesa/drivers/dri/i965/intel_extensions.c
> index fe40068..4ee8636 100644
> --- a/src/mesa/drivers/dri/i965/intel_extensions.c
> +++ b/src/mesa/drivers/dri/i965/intel_extensions.c
> @@ -163,6 +163,7 @@ intelInitExtensions(struct gl_context *ctx)
>     assert(brw->gen >= 4);
>  
>     ctx->Extensions.ARB_buffer_storage = true;
> +   ctx->Extensions.ARB_clear_texture = true;
>     ctx->Extensions.ARB_depth_buffer_float = true;
>     ctx->Extensions.ARB_depth_clamp = true;
>     ctx->Extensions.ARB_depth_texture = true;
> -- 
> 1.9.3
> 


More information about the mesa-dev mailing list