<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>