summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenneth Graunke <[email protected]>2016-04-12 10:19:09 -0700
committerKenneth Graunke <[email protected]>2016-04-18 10:39:31 -0700
commitc092f9b96a0bdc415fec1760b8b345166b115483 (patch)
treebb7ad2d2d6a1550b6b74bac14c5e7b02e6ef678f
parenta33f94ba8c3a4a344fbc5a8386cec7f2a620b97e (diff)
meta: Don't botch color masks when changing drawbuffers.
Color clears should respect each drawbuffer's color mask state. Previously, we tried to leave the color mask untouched. However, _mesa_meta_drawbuffers_from_bitfield() ended up rebinding all the color drawbuffers in a different order, so we ended up pairing drawbuffers with the wrong color mask state. The new _mesa_meta_drawbuffers_and_colormask() function does the same job as the old _mesa_meta_drawbuffers_from_bitfield(), but also rearranges the color mask state to match the new drawbuffer configuration. This code was largely ripped off from Gallium's st_Clear code. This fixes ES31-CTS.draw_buffers_indexed.color_masks, which binds up to 8 drawbuffers, sets color masks for each, and then calls glClearBufferfv to clear each buffer individually. ClearBuffer causes us to rebind only one drawbuffer, at which point we used ctx->Color.ColorMask[0] (draw buffer 0's state) for everything. We could probably delete _mesa_meta_drawbuffers_from_bitfield(), but I'd rather not think about the i965 fast clear code. Topi is rewriting a bunch of that soon anyway, so let's delete it then. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=94847 Signed-off-by: Kenneth Graunke <[email protected]> Reviewed-by: Jason Ekstrand <[email protected]>
-rw-r--r--src/mesa/drivers/common/meta.c82
1 files changed, 75 insertions, 7 deletions
diff --git a/src/mesa/drivers/common/meta.c b/src/mesa/drivers/common/meta.c
index eedfb7c262b..6dcbc8bdfd8 100644
--- a/src/mesa/drivers/common/meta.c
+++ b/src/mesa/drivers/common/meta.c
@@ -1618,6 +1618,79 @@ _mesa_meta_drawbuffers_from_bitfield(GLbitfield bits)
}
/**
+ * Return if all of the color channels are masked.
+ */
+static inline GLboolean
+is_color_disabled(struct gl_context *ctx, int i)
+{
+ return !ctx->Color.ColorMask[i][0] &&
+ !ctx->Color.ColorMask[i][1] &&
+ !ctx->Color.ColorMask[i][2] &&
+ !ctx->Color.ColorMask[i][3];
+}
+
+/**
+ * Given a bitfield of BUFFER_BIT_x draw buffers, call glDrawBuffers to
+ * set GL to only draw to those buffers. Also, update color masks to
+ * reflect the new draw buffer ordering.
+ */
+static void
+_mesa_meta_drawbuffers_and_colormask(struct gl_context *ctx, GLbitfield mask)
+{
+ GLenum enums[MAX_DRAW_BUFFERS];
+ GLubyte colormask[MAX_DRAW_BUFFERS][4];
+ int num_bufs = 0;
+
+ /* This function is only legal for color buffer bitfields. */
+ assert((mask & ~BUFFER_BITS_COLOR) == 0);
+
+ /* Make sure we don't overflow any arrays. */
+ assert(_mesa_bitcount(mask) <= MAX_DRAW_BUFFERS);
+
+ enums[0] = GL_NONE;
+
+ for (int i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
+ int b = ctx->DrawBuffer->_ColorDrawBufferIndexes[i];
+ int colormask_idx = ctx->Extensions.EXT_draw_buffers2 ? i : 0;
+
+ if (b < 0 || !(mask & (1 << b)) || is_color_disabled(ctx, colormask_idx))
+ continue;
+
+ switch (b) {
+ case BUFFER_FRONT_LEFT:
+ enums[num_bufs] = GL_FRONT_LEFT;
+ break;
+ case BUFFER_FRONT_RIGHT:
+ enums[num_bufs] = GL_FRONT_RIGHT;
+ break;
+ case BUFFER_BACK_LEFT:
+ enums[num_bufs] = GL_BACK_LEFT;
+ break;
+ case BUFFER_BACK_RIGHT:
+ enums[num_bufs] = GL_BACK_RIGHT;
+ break;
+ default:
+ assert(b >= BUFFER_COLOR0 && b <= BUFFER_COLOR7);
+ enums[num_bufs] = GL_COLOR_ATTACHMENT0 + (b - BUFFER_COLOR0);
+ break;
+ }
+
+ for (int k = 0; k < 4; k++)
+ colormask[num_bufs][k] = ctx->Color.ColorMask[colormask_idx][k];
+
+ num_bufs++;
+ }
+
+ _mesa_DrawBuffers(num_bufs, enums);
+
+ for (int i = 0; i < num_bufs; i++) {
+ _mesa_ColorMaski(i, colormask[i][0], colormask[i][1],
+ colormask[i][2], colormask[i][3]);
+ }
+}
+
+
+/**
* Meta implementation of ctx->Driver.Clear() in terms of polygon rendering.
*/
static void
@@ -1633,6 +1706,7 @@ meta_clear(struct gl_context *ctx, GLbitfield buffers, bool glsl)
metaSave = (MESA_META_ALPHA_TEST |
MESA_META_BLEND |
+ MESA_META_COLOR_MASK |
MESA_META_DEPTH_TEST |
MESA_META_RASTERIZATION |
MESA_META_SHADER |
@@ -1655,11 +1729,6 @@ meta_clear(struct gl_context *ctx, GLbitfield buffers, bool glsl)
if (buffers & BUFFER_BITS_COLOR) {
metaSave |= MESA_META_DRAW_BUFFERS;
- } else {
- /* We'll use colormask to disable color writes. Otherwise,
- * respect color mask
- */
- metaSave |= MESA_META_COLOR_MASK;
}
_mesa_meta_begin(ctx, metaSave);
@@ -1695,7 +1764,7 @@ meta_clear(struct gl_context *ctx, GLbitfield buffers, bool glsl)
/* GL_COLOR_BUFFER_BIT */
if (buffers & BUFFER_BITS_COLOR) {
/* Only draw to the buffers we were asked to clear. */
- _mesa_meta_drawbuffers_from_bitfield(buffers & BUFFER_BITS_COLOR);
+ _mesa_meta_drawbuffers_and_colormask(ctx, buffers & BUFFER_BITS_COLOR);
/* leave colormask state as-is */
@@ -1704,7 +1773,6 @@ meta_clear(struct gl_context *ctx, GLbitfield buffers, bool glsl)
_mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE);
}
else {
- assert(metaSave & MESA_META_COLOR_MASK);
_mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
}