[Mesa-dev] [PATCH 1/2] meta: Add a GLSL-based _mesa_meta_Clear() variant.

Ian Romanick idr at freedesktop.org
Tue Jul 19 13:46:38 PDT 2011


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 07/18/2011 09:33 AM, Eric Anholt wrote:
> This cuts out a large portion of the overhead of glClear() from
> resetting the texenv state and recomputing the fixed function
> programs.  It also means less use of fixed function internally in our
> GLES2 drivers, which is rather bogus.
> ---
>  src/mesa/drivers/common/meta.c |  166 ++++++++++++++++++++++++++++++++++++++++
>  src/mesa/drivers/common/meta.h |    3 +
>  2 files changed, 169 insertions(+), 0 deletions(-)
> 
> diff --git a/src/mesa/drivers/common/meta.c b/src/mesa/drivers/common/meta.c
> index 0e58aec..09d7186 100644
> --- a/src/mesa/drivers/common/meta.c
> +++ b/src/mesa/drivers/common/meta.c
> @@ -62,6 +62,7 @@
>  #include "main/teximage.h"
>  #include "main/texparam.h"
>  #include "main/texstate.h"
> +#include "main/uniforms.h"
>  #include "main/varray.h"
>  #include "main/viewport.h"
>  #include "program/program.h"
> @@ -235,6 +236,8 @@ struct clear_state
>  {
>     GLuint ArrayObj;
>     GLuint VBO;
> +   GLuint ShaderProg;
> +   GLint ColorLocation;
>  };
>  
>  
> @@ -1589,6 +1592,169 @@ _mesa_meta_Clear(struct gl_context *ctx, GLbitfield buffers)
>     _mesa_meta_end(ctx);
>  }
>  
> +static void
> +meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear)
> +{
> +   const char *vs_source =
> +      "attribute vec4 position;\n"
> +      "void main()\n"
> +      "{\n"
> +      "   gl_Position = position;\n"
> +      "}\n";
> +   const char *fs_source =
> +      "uniform vec4 color;\n"
> +      "void main()\n"
> +      "{\n"
> +      "   gl_FragColor = color;\n"
> +      "}\n";
> +   GLuint vs, fs;
> +
> +   if (clear->ArrayObj != 0)
> +      return;
> +
> +   /* create vertex array object */
> +   _mesa_GenVertexArrays(1, &clear->ArrayObj);
> +   _mesa_BindVertexArray(clear->ArrayObj);
> +
> +   /* create vertex array buffer */
> +   _mesa_GenBuffersARB(1, &clear->VBO);
> +   _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO);
> +
> +   /* setup vertex arrays */
> +   _mesa_VertexAttribPointerARB(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float),
> +				(void *)0);
> +   _mesa_EnableVertexAttribArrayARB(0);
> +
> +   vs = _mesa_CreateShaderObjectARB(GL_VERTEX_SHADER);
> +   _mesa_ShaderSourceARB(vs, 1, &vs_source, NULL);
> +   _mesa_CompileShaderARB(vs);
> +
> +   fs = _mesa_CreateShaderObjectARB(GL_FRAGMENT_SHADER);
> +   _mesa_ShaderSourceARB(fs, 1, &fs_source, NULL);
> +   _mesa_CompileShaderARB(fs);
> +
> +   clear->ShaderProg = _mesa_CreateProgramObjectARB();
> +   _mesa_AttachShader(clear->ShaderProg, fs);
> +   _mesa_AttachShader(clear->ShaderProg, vs);
> +   _mesa_BindAttribLocationARB(clear->ShaderProg, 0, "position");
> +   _mesa_LinkProgramARB(clear->ShaderProg);
> +
> +   _mesa_DeleteShader(fs);
> +   _mesa_DeleteShader(vs);
> +
> +   clear->ColorLocation = _mesa_GetUniformLocationARB(clear->ShaderProg,
> +						      "color");
> +}
> +
> +/**
> + * Meta implementation of ctx->Driver.Clear() in terms of polygon rendering.
> + */
> +void
> +_mesa_meta_glsl_Clear(struct gl_context *ctx, GLbitfield buffers)
> +{
> +   struct clear_state *clear = &ctx->Meta->Clear;
> +   /* save all state but scissor, pixel pack/unpack */
> +   GLbitfield metaSave = (META_ALL -
> +			  META_SCISSOR -
> +			  META_PIXEL_STORE -
> +			  META_CONDITIONAL_RENDER);
> +   const GLuint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1;
> +   struct gl_framebuffer *fb = ctx->DrawBuffer;
> +   const float x0 = ((float)fb->_Xmin / fb->Width) * 2.0 - 1.0;
> +   const float y0 = ((float)fb->_Ymin / fb->Height) * 2.0 - 1.0;
> +   const float x1 = ((float)fb->_Xmax / fb->Width) * 2.0 - 1.0;
> +   const float y1 = ((float)fb->_Ymax / fb->Height) * 2.0 - 1.0;
> +   const float z = -invert_z(ctx->Depth.Clear);
> +   struct vertex {
> +      GLfloat x, y, z;
> +   } verts[4];
> +
> +   metaSave = (META_ALPHA_TEST |
> +	       META_BLEND |
> +	       META_DEPTH_TEST |
> +	       META_RASTERIZATION |
> +	       META_SHADER |
> +	       META_STENCIL_TEST |
> +	       META_VERTEX |
> +	       META_VIEWPORT |
> +	       META_CLAMP_FRAGMENT_COLOR);

Why is metaSave initialized twice?  Also, BITS - OTHER_BITS - MORE_BITS
is non-obvious.  This should result in the same compile-time constant as
BITS & ~(OTHER_BITS | MORE_BITS), right?

> +
> +   if (!(buffers & BUFFER_BITS_COLOR)) {
> +      /* We'll use colormask to disable color writes.  Otherwise,
> +       * respect color mask
> +       */
> +      metaSave |= META_COLOR_MASK;
> +   }
> +
> +   _mesa_meta_begin(ctx, metaSave);
> +
> +   meta_glsl_clear_init(ctx, clear);
> +
> +   _mesa_UseProgramObjectARB(clear->ShaderProg);
> +   _mesa_Uniform4fvARB(clear->ColorLocation, 1,
> +		       ctx->Color.ClearColorUnclamped);
> +
> +   _mesa_BindVertexArray(clear->ArrayObj);
> +   _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO);
> +
> +   /* GL_COLOR_BUFFER_BIT */
> +   if (buffers & BUFFER_BITS_COLOR) {
> +      /* leave colormask, glDrawBuffer state as-is */
> +
> +      /* Clears never have the color clamped. */
> +      _mesa_ClampColorARB(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE);
> +   }
> +   else {
> +      ASSERT(metaSave & META_COLOR_MASK);
> +      _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
> +   }
> +
> +   /* GL_DEPTH_BUFFER_BIT */
> +   if (buffers & BUFFER_BIT_DEPTH) {
> +      _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_TRUE);
> +      _mesa_DepthFunc(GL_ALWAYS);
> +      _mesa_DepthMask(GL_TRUE);
> +   }
> +   else {
> +      assert(!ctx->Depth.Test);
> +   }
> +
> +   /* GL_STENCIL_BUFFER_BIT */
> +   if (buffers & BUFFER_BIT_STENCIL) {
> +      _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_TRUE);
> +      _mesa_StencilOpSeparate(GL_FRONT_AND_BACK,
> +                              GL_REPLACE, GL_REPLACE, GL_REPLACE);
> +      _mesa_StencilFuncSeparate(GL_FRONT_AND_BACK, GL_ALWAYS,
> +                                ctx->Stencil.Clear & stencilMax,
> +                                ctx->Stencil.WriteMask[0]);
> +   }
> +   else {
> +      assert(!ctx->Stencil.Enabled);
> +   }
> +
> +   /* vertex positions */
> +   verts[0].x = x0;
> +   verts[0].y = y0;
> +   verts[0].z = z;
> +   verts[1].x = x1;
> +   verts[1].y = y0;
> +   verts[1].z = z;
> +   verts[2].x = x1;
> +   verts[2].y = y1;
> +   verts[2].z = z;
> +   verts[3].x = x0;
> +   verts[3].y = y1;
> +   verts[3].z = z;
> +
> +   /* upload new vertex data */
> +   _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), verts,
> +		       GL_DYNAMIC_DRAW_ARB);
> +
> +   /* draw quad */
> +   _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
> +
> +   _mesa_meta_end(ctx);
> +}
>  
>  /**
>   * Meta implementation of ctx->Driver.CopyPixels() in terms
> diff --git a/src/mesa/drivers/common/meta.h b/src/mesa/drivers/common/meta.h
> index b0797d3..32c789e 100644
> --- a/src/mesa/drivers/common/meta.h
> +++ b/src/mesa/drivers/common/meta.h
> @@ -43,6 +43,9 @@ extern void
>  _mesa_meta_Clear(struct gl_context *ctx, GLbitfield buffers);
>  
>  extern void
> +_mesa_meta_glsl_Clear(struct gl_context *ctx, GLbitfield buffers);
> +
> +extern void
>  _mesa_meta_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
>                        GLsizei width, GLsizei height,
>                        GLint dstx, GLint dsty, GLenum type);

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/

iEYEARECAAYFAk4l7S4ACgkQX1gOwKyEAw+USwCfUsYNoG+96WVdfvzjtGwsio8h
3DQAnjX4K1TnNd/5loeKzRN7Q6FhEYdy
=A97M
-----END PGP SIGNATURE-----


More information about the mesa-dev mailing list