<p dir="ltr"><br>
On Apr 12, 2016 1:42 PM, "Kenneth Graunke" <<a href="mailto:kenneth@whitecape.org">kenneth@whitecape.org</a>> wrote:<br>
><br>
> Color clears should respect each drawbuffer's color mask state.<br>
><br>
> Previously, we tried to leave the color mask untouched.  However,<br>
> _mesa_meta_drawbuffers_from_bitfield() ended up rebinding all the<br>
> color drawbuffers in a different order, so we ended up pairing<br>
> drawbuffers with the wrong color mask state.<br>
><br>
> The new _mesa_meta_drawbuffers_and_colormask() function does the<br>
> same job as the old _mesa_meta_drawbuffers_from_bitfield(), but<br>
> also rearranges the color mask state to match the new drawbuffer<br>
> configuration.</p>
<p dir="ltr">Arrrrrrggggghhhh.... I don't like this patch either.</p>
<p dir="ltr">I really wish we could let meta_begin stomp color masks.  Unfortunately, the only way to do that would be to split up the save and re-arrange code across the meta_begin which also seems terrible.  I don't know what say.  Oh well...</p>
<p dir="ltr">Reviewed-by: Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>></p>
<p dir="ltr">Feel free to put a Naked-by on there too if you'd like.</p>
<p dir="ltr">> This code was largely ripped off from Gallium's st_Clear code.<br>
><br>
> This fixes ES31-CTS.draw_buffers_indexed.color_masks, which binds<br>
> up to 8 drawbuffers, sets color masks for each, and then calls<br>
> glClearBufferfv to clear each buffer individually.  ClearBuffer<br>
> causes us to rebind only one drawbuffer, at which point we used<br>
> ctx->Color.ColorMask[0] (draw buffer 0's state) for everything.<br>
><br>
> We could probably delete _mesa_meta_drawbuffers_from_bitfield(),<br>
> but I'd rather not think about the i965 fast clear code.  Topi is<br>
> rewriting a bunch of that soon anyway, so let's delete it then.<br>
><br>
> Bugzilla: <a href="https://bugs.freedesktop.org/show_bug.cgi?id=94847">https://bugs.freedesktop.org/show_bug.cgi?id=94847</a><br>
> Signed-off-by: Kenneth Graunke <<a href="mailto:kenneth@whitecape.org">kenneth@whitecape.org</a>><br>
> ---<br>
>  src/mesa/drivers/common/meta.c | 82 ++++++++++++++++++++++++++++++++++++++----<br>
>  1 file changed, 75 insertions(+), 7 deletions(-)<br>
><br>
> diff --git a/src/mesa/drivers/common/meta.c b/src/mesa/drivers/common/meta.c<br>
> index eedfb7c..6dcbc8b 100644<br>
> --- a/src/mesa/drivers/common/meta.c<br>
> +++ b/src/mesa/drivers/common/meta.c<br>
> @@ -1618,6 +1618,79 @@ _mesa_meta_drawbuffers_from_bitfield(GLbitfield bits)<br>
>  }<br>
><br>
>  /**<br>
> + * Return if all of the color channels are masked.<br>
> + */<br>
> +static inline GLboolean<br>
> +is_color_disabled(struct gl_context *ctx, int i)<br>
> +{<br>
> +   return !ctx->Color.ColorMask[i][0] &&<br>
> +          !ctx->Color.ColorMask[i][1] &&<br>
> +          !ctx->Color.ColorMask[i][2] &&<br>
> +          !ctx->Color.ColorMask[i][3];<br>
> +}<br>
> +<br>
> +/**<br>
> + * Given a bitfield of BUFFER_BIT_x draw buffers, call glDrawBuffers to<br>
> + * set GL to only draw to those buffers.  Also, update color masks to<br>
> + * reflect the new draw buffer ordering.<br>
> + */<br>
> +static void<br>
> +_mesa_meta_drawbuffers_and_colormask(struct gl_context *ctx, GLbitfield mask)<br>
> +{<br>
> +   GLenum enums[MAX_DRAW_BUFFERS];<br>
> +   GLubyte colormask[MAX_DRAW_BUFFERS][4];<br>
> +   int num_bufs = 0;<br>
> +<br>
> +   /* This function is only legal for color buffer bitfields. */<br>
> +   assert((mask & ~BUFFER_BITS_COLOR) == 0);<br>
> +<br>
> +   /* Make sure we don't overflow any arrays. */<br>
> +   assert(_mesa_bitcount(mask) <= MAX_DRAW_BUFFERS);<br>
> +<br>
> +   enums[0] = GL_NONE;<br>
> +<br>
> +   for (int i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {<br>
> +      int b = ctx->DrawBuffer->_ColorDrawBufferIndexes[i];<br>
> +      int colormask_idx = ctx->Extensions.EXT_draw_buffers2 ? i : 0;<br>
> +<br>
> +      if (b < 0 || !(mask & (1 << b)) || is_color_disabled(ctx, colormask_idx))<br>
> +         continue;<br>
> +<br>
> +      switch (b) {<br>
> +      case BUFFER_FRONT_LEFT:<br>
> +         enums[num_bufs] = GL_FRONT_LEFT;<br>
> +         break;<br>
> +      case BUFFER_FRONT_RIGHT:<br>
> +         enums[num_bufs] = GL_FRONT_RIGHT;<br>
> +         break;<br>
> +      case BUFFER_BACK_LEFT:<br>
> +         enums[num_bufs] = GL_BACK_LEFT;<br>
> +         break;<br>
> +      case BUFFER_BACK_RIGHT:<br>
> +         enums[num_bufs] = GL_BACK_RIGHT;<br>
> +         break;<br>
> +      default:<br>
> +         assert(b >= BUFFER_COLOR0 && b <= BUFFER_COLOR7);<br>
> +         enums[num_bufs] = GL_COLOR_ATTACHMENT0 + (b - BUFFER_COLOR0);<br>
> +         break;<br>
> +      }<br>
> +<br>
> +      for (int k = 0; k < 4; k++)<br>
> +         colormask[num_bufs][k] = ctx->Color.ColorMask[colormask_idx][k];<br>
> +<br>
> +      num_bufs++;<br>
> +   }<br>
> +<br>
> +   _mesa_DrawBuffers(num_bufs, enums);<br>
> +<br>
> +   for (int i = 0; i < num_bufs; i++) {<br>
> +      _mesa_ColorMaski(i, colormask[i][0], colormask[i][1],<br>
> +                          colormask[i][2], colormask[i][3]);<br>
> +   }<br>
> +}<br>
> +<br>
> +<br>
> +/**<br>
>   * Meta implementation of ctx->Driver.Clear() in terms of polygon rendering.<br>
>   */<br>
>  static void<br>
> @@ -1633,6 +1706,7 @@ meta_clear(struct gl_context *ctx, GLbitfield buffers, bool glsl)<br>
><br>
>     metaSave = (MESA_META_ALPHA_TEST |<br>
>                MESA_META_BLEND |<br>
> +               MESA_META_COLOR_MASK |<br>
>                MESA_META_DEPTH_TEST |<br>
>                MESA_META_RASTERIZATION |<br>
>                MESA_META_SHADER |<br>
> @@ -1655,11 +1729,6 @@ meta_clear(struct gl_context *ctx, GLbitfield buffers, bool glsl)<br>
><br>
>     if (buffers & BUFFER_BITS_COLOR) {<br>
>        metaSave |= MESA_META_DRAW_BUFFERS;<br>
> -   } else {<br>
> -      /* We'll use colormask to disable color writes.  Otherwise,<br>
> -       * respect color mask<br>
> -       */<br>
> -      metaSave |= MESA_META_COLOR_MASK;<br>
>     }<br>
><br>
>     _mesa_meta_begin(ctx, metaSave);<br>
> @@ -1695,7 +1764,7 @@ meta_clear(struct gl_context *ctx, GLbitfield buffers, bool glsl)<br>
>     /* GL_COLOR_BUFFER_BIT */<br>
>     if (buffers & BUFFER_BITS_COLOR) {<br>
>        /* Only draw to the buffers we were asked to clear. */<br>
> -      _mesa_meta_drawbuffers_from_bitfield(buffers & BUFFER_BITS_COLOR);<br>
> +      _mesa_meta_drawbuffers_and_colormask(ctx, buffers & BUFFER_BITS_COLOR);<br>
><br>
>        /* leave colormask state as-is */<br>
><br>
> @@ -1704,7 +1773,6 @@ meta_clear(struct gl_context *ctx, GLbitfield buffers, bool glsl)<br>
>           _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE);<br>
>     }<br>
>     else {<br>
> -      assert(metaSave & MESA_META_COLOR_MASK);<br>
>        _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);<br>
>     }<br>
><br>
> --<br>
> 2.8.0<br>
><br>
> _______________________________________________<br>
> mesa-dev mailing list<br>
> <a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
> <a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev">https://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
</p>