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

Neil Roberts neil at linux.intel.com
Fri Jun 13 17:59:31 PDT 2014


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 {
+      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;
+
+   _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);
+      else
+         memset(depthStencilValue, 0, sizeof depthStencilValue);
+
+      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;
+
+   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



More information about the mesa-dev mailing list