[Mesa-dev] [PATCH 1/5] mesa: change ctx->Color.ColorMask into a 32-bit bitmask

Marek Olšák maraeo at gmail.com
Wed Jan 31 19:55:11 UTC 2018


From: Marek Olšák <marek.olsak at amd.com>

4 bits per draw buffer, 8 draw buffers in total --> 32 bits.

This is easier to work with.
---
 src/mesa/drivers/common/driverfuncs.c            |  8 ++--
 src/mesa/drivers/common/meta.c                   | 41 +++++++-----------
 src/mesa/drivers/common/meta.h                   |  2 +-
 src/mesa/drivers/dri/i915/intel_clear.c          |  5 +--
 src/mesa/drivers/dri/i915/intel_pixel.c          |  5 +--
 src/mesa/drivers/dri/i915/intel_pixel_copy.c     |  5 +--
 src/mesa/drivers/dri/i965/brw_blorp.c            |  9 ++--
 src/mesa/drivers/dri/i965/brw_wm_surface_state.c |  8 ++--
 src/mesa/drivers/dri/i965/genX_state_upload.c    | 13 +++---
 src/mesa/drivers/dri/i965/intel_pixel.c          |  5 +--
 src/mesa/drivers/dri/i965/intel_pixel_copy.c     |  5 +--
 src/mesa/drivers/dri/nouveau/nouveau_driver.c    |  8 +++-
 src/mesa/drivers/dri/nouveau/nv04_context.c      |  5 +--
 src/mesa/drivers/dri/nouveau/nv04_state_raster.c |  8 ++--
 src/mesa/drivers/dri/nouveau/nv10_state_raster.c |  8 ++--
 src/mesa/drivers/dri/nouveau/nv20_context.c      |  8 ++--
 src/mesa/drivers/dri/r200/r200_state.c           |  8 ++--
 src/mesa/drivers/dri/radeon/radeon_state.c       |  8 ++--
 src/mesa/drivers/x11/xm_dd.c                     |  4 +-
 src/mesa/main/accum.c                            | 16 +++----
 src/mesa/main/attrib.c                           | 16 +++----
 src/mesa/main/blend.c                            | 53 +++++++++---------------
 src/mesa/main/blend.h                            | 10 +++++
 src/mesa/main/clear.c                            |  2 +-
 src/mesa/main/get.c                              | 16 +++----
 src/mesa/main/mtypes.h                           |  8 +++-
 src/mesa/state_tracker/st_atom_blend.c           | 27 ++++--------
 src/mesa/state_tracker/st_cb_clear.c             | 39 ++---------------
 src/mesa/swrast/s_clear.c                        |  8 +++-
 src/mesa/swrast/s_context.c                      | 10 +----
 src/mesa/swrast/s_masking.c                      | 24 +++++++----
 src/mesa/swrast/s_span.c                         |  6 +--
 src/mesa/swrast/s_triangle.c                     |  8 ++--
 33 files changed, 174 insertions(+), 232 deletions(-)

diff --git a/src/mesa/drivers/common/driverfuncs.c b/src/mesa/drivers/common/driverfuncs.c
index 99c1520..8f2e3e0 100644
--- a/src/mesa/drivers/common/driverfuncs.c
+++ b/src/mesa/drivers/common/driverfuncs.c
@@ -225,24 +225,24 @@ _mesa_init_driver_state(struct gl_context *ctx)
                                      ctx->Color.Blend[0].EquationRGB,
                                      ctx->Color.Blend[0].EquationA);
 
    ctx->Driver.BlendFuncSeparate(ctx,
                                  ctx->Color.Blend[0].SrcRGB,
                                  ctx->Color.Blend[0].DstRGB,
                                  ctx->Color.Blend[0].SrcA,
                                  ctx->Color.Blend[0].DstA);
 
    ctx->Driver.ColorMask(ctx,
-                         ctx->Color.ColorMask[0][RCOMP],
-                         ctx->Color.ColorMask[0][GCOMP],
-                         ctx->Color.ColorMask[0][BCOMP],
-                         ctx->Color.ColorMask[0][ACOMP]);
+                         GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 0),
+                         GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 1),
+                         GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 2),
+                         GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 3));
 
    ctx->Driver.CullFace(ctx, ctx->Polygon.CullFaceMode);
    ctx->Driver.DepthFunc(ctx, ctx->Depth.Func);
    ctx->Driver.DepthMask(ctx, ctx->Depth.Mask);
 
    ctx->Driver.Enable(ctx, GL_ALPHA_TEST, ctx->Color.AlphaEnabled);
    ctx->Driver.Enable(ctx, GL_BLEND, ctx->Color.BlendEnabled);
    ctx->Driver.Enable(ctx, GL_COLOR_LOGIC_OP, ctx->Color.ColorLogicOpEnabled);
    ctx->Driver.Enable(ctx, GL_COLOR_SUM, ctx->Fog.ColorSumEnabled);
    ctx->Driver.Enable(ctx, GL_CULL_FACE, ctx->Polygon.CullFlag);
diff --git a/src/mesa/drivers/common/meta.c b/src/mesa/drivers/common/meta.c
index a48f700..a7dd139 100644
--- a/src/mesa/drivers/common/meta.c
+++ b/src/mesa/drivers/common/meta.c
@@ -508,24 +508,22 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state)
       save->ColorLogicOpEnabled = ctx->Color.ColorLogicOpEnabled;
       if (ctx->Color.ColorLogicOpEnabled)
          _mesa_set_enable(ctx, GL_COLOR_LOGIC_OP, GL_FALSE);
    }
 
    if (state & MESA_META_DITHER) {
       save->DitherFlag = ctx->Color.DitherFlag;
       _mesa_set_enable(ctx, GL_DITHER, GL_TRUE);
    }
 
-   if (state & MESA_META_COLOR_MASK) {
-      memcpy(save->ColorMask, ctx->Color.ColorMask,
-             sizeof(ctx->Color.ColorMask));
-   }
+   if (state & MESA_META_COLOR_MASK)
+      save->ColorMask = ctx->Color.ColorMask;
 
    if (state & MESA_META_DEPTH_TEST) {
       save->Depth = ctx->Depth; /* struct copy */
       if (ctx->Depth.Test)
          _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_FALSE);
    }
 
    if (state & MESA_META_FOG) {
       save->Fog = ctx->Fog.Enabled;
       if (ctx->Fog.Enabled)
@@ -873,31 +871,34 @@ _mesa_meta_end(struct gl_context *ctx)
       if (ctx->Color.ColorLogicOpEnabled != save->ColorLogicOpEnabled)
          _mesa_set_enable(ctx, GL_COLOR_LOGIC_OP, save->ColorLogicOpEnabled);
    }
 
    if (state & MESA_META_DITHER)
       _mesa_set_enable(ctx, GL_DITHER, save->DitherFlag);
 
    if (state & MESA_META_COLOR_MASK) {
       GLuint i;
       for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
-         if (!TEST_EQ_4V(ctx->Color.ColorMask[i], save->ColorMask[i])) {
+         if (GET_COLORMASK(ctx->Color.ColorMask, i) !=
+             GET_COLORMASK(save->ColorMask, i)) {
             if (i == 0) {
-               _mesa_ColorMask(save->ColorMask[i][0], save->ColorMask[i][1],
-                               save->ColorMask[i][2], save->ColorMask[i][3]);
+               _mesa_ColorMask(GET_COLORMASK_BIT(save->ColorMask, i, 0),
+                               GET_COLORMASK_BIT(save->ColorMask, i, 1),
+                               GET_COLORMASK_BIT(save->ColorMask, i, 2),
+                               GET_COLORMASK_BIT(save->ColorMask, i, 3));
             }
             else {
                _mesa_ColorMaski(i,
-                                      save->ColorMask[i][0],
-                                      save->ColorMask[i][1],
-                                      save->ColorMask[i][2],
-                                      save->ColorMask[i][3]);
+                                GET_COLORMASK_BIT(save->ColorMask, i, 0),
+                                GET_COLORMASK_BIT(save->ColorMask, i, 1),
+                                GET_COLORMASK_BIT(save->ColorMask, i, 2),
+                                GET_COLORMASK_BIT(save->ColorMask, i, 3));
             }
          }
       }
    }
 
    if (state & MESA_META_DEPTH_TEST) {
       if (ctx->Depth.Test != save->Depth.Test)
          _mesa_set_enable(ctx, GL_DEPTH_TEST, save->Depth.Test);
       _mesa_DepthFunc(save->Depth.Func);
       _mesa_DepthMask(save->Depth.Mask);
@@ -1624,32 +1625,20 @@ _mesa_meta_drawbuffers_from_bitfield(GLbitfield bits)
 
    for (n = 0; n < MAX_COLOR_ATTACHMENTS; n++) {
       if (bits & (1 << (BUFFER_COLOR0 + n)))
          enums[i++] = GL_COLOR_ATTACHMENT0 + n;
    }
 
    _mesa_DrawBuffers(i, enums);
 }
 
 /**
- * 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;
@@ -1659,21 +1648,22 @@ _mesa_meta_drawbuffers_and_colormask(struct gl_context *ctx, GLbitfield mask)
 
    /* 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++) {
       gl_buffer_index 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))
+      if (b < 0 || !(mask & (1 << b)) ||
+          GET_COLORMASK(ctx->Color.ColorMask, colormask_idx) == 0)
          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:
@@ -1682,21 +1672,22 @@ _mesa_meta_drawbuffers_and_colormask(struct gl_context *ctx, GLbitfield mask)
       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];
+         colormask[num_bufs][k] = GET_COLORMASK_BIT(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]);
    }
diff --git a/src/mesa/drivers/common/meta.h b/src/mesa/drivers/common/meta.h
index 3d9c291..1c35ea3 100644
--- a/src/mesa/drivers/common/meta.h
+++ b/src/mesa/drivers/common/meta.h
@@ -83,21 +83,21 @@ struct save_state
    GLclampf AlphaRef;
 
    /** MESA_META_BLEND */
    GLbitfield BlendEnabled;
    GLboolean ColorLogicOpEnabled;
 
    /** MESA_META_DITHER */
    GLboolean DitherFlag;
 
    /** MESA_META_COLOR_MASK */
-   GLubyte ColorMask[MAX_DRAW_BUFFERS][4];
+   GLbitfield ColorMask;
 
    /** MESA_META_DEPTH_TEST */
    struct gl_depthbuffer_attrib Depth;
 
    /** MESA_META_FOG */
    GLboolean Fog;
 
    /** MESA_META_PIXEL_STORE */
    struct gl_pixelstore_attrib Pack, Unpack;
 
diff --git a/src/mesa/drivers/dri/i915/intel_clear.c b/src/mesa/drivers/dri/i915/intel_clear.c
index f8df2e0..c9722cb 100644
--- a/src/mesa/drivers/dri/i915/intel_clear.c
+++ b/src/mesa/drivers/dri/i915/intel_clear.c
@@ -74,30 +74,27 @@ debug_mask(const char *name, GLbitfield mask)
    }
 }
 
 /**
  * Called by ctx->Driver.Clear.
  */
 static void
 intelClear(struct gl_context *ctx, GLbitfield mask)
 {
    struct intel_context *intel = intel_context(ctx);
-   GLuint colorMask;
    GLbitfield tri_mask = 0;
    GLbitfield blit_mask = 0;
    GLbitfield swrast_mask = 0;
    struct gl_framebuffer *fb = ctx->DrawBuffer;
    struct intel_renderbuffer *irb;
    int i;
 
-   memcpy(&colorMask, &ctx->Color.ColorMask[0], sizeof(colorMask));
-
    if (mask & (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_FRONT_RIGHT)) {
       intel->front_buffer_dirty = true;
    }
 
    if (0)
       fprintf(stderr, "%s\n", __func__);
 
    /* Get SW clears out of the way: Anything without an intel_renderbuffer */
    for (i = 0; i < BUFFER_COUNT; i++) {
       if (!(mask & (1 << i)))
@@ -108,21 +105,21 @@ intelClear(struct gl_context *ctx, GLbitfield mask)
 	 swrast_mask |= (1 << i);
 	 mask &= ~(1 << i);
       }
    }
    if (unlikely(swrast_mask)) {
       debug_mask("swrast", swrast_mask);
       _swrast_Clear(ctx, swrast_mask);
    }
 
    /* HW color buffers (front, back, aux, generic FBO, etc) */
-   if (colorMask == ~0) {
+   if (GET_COLORMASK(ctx->Color.ColorMask, 0) == 0xf) {
       /* clear all R,G,B,A */
       blit_mask |= (mask & BUFFER_BITS_COLOR);
    }
    else {
       /* glColorMask in effect */
       tri_mask |= (mask & BUFFER_BITS_COLOR);
    }
 
    /* Make sure we have up to date buffers before we start looking at
     * the tiling bits to determine how to clear. */
diff --git a/src/mesa/drivers/dri/i915/intel_pixel.c b/src/mesa/drivers/dri/i915/intel_pixel.c
index 084b563..eaca8e3 100644
--- a/src/mesa/drivers/dri/i915/intel_pixel.c
+++ b/src/mesa/drivers/dri/i915/intel_pixel.c
@@ -76,24 +76,21 @@ intel_check_blit_fragment_ops(struct gl_context * ctx, bool src_alpha_is_one)
 	ctx->Color.Blend[0].EquationA != GL_FUNC_ADD)) {
       DBG("fallback due to blend\n");
       return false;
    }
 
    if (ctx->Texture._MaxEnabledTexImageUnit != -1) {
       DBG("fallback due to texturing\n");
       return false;
    }
 
-   if (!(ctx->Color.ColorMask[0][0] &&
-	 ctx->Color.ColorMask[0][1] &&
-	 ctx->Color.ColorMask[0][2] &&
-	 ctx->Color.ColorMask[0][3])) {
+   if (GET_COLORMASK(ctx->Color.ColorMask, 0) != 0xf) {
       DBG("fallback due to color masking\n");
       return false;
    }
 
    if (ctx->Color.AlphaEnabled) {
       DBG("fallback due to alpha\n");
       return false;
    }
 
    if (ctx->Depth.Test) {
diff --git a/src/mesa/drivers/dri/i915/intel_pixel_copy.c b/src/mesa/drivers/dri/i915/intel_pixel_copy.c
index 0dea8f9..1b1993e 100644
--- a/src/mesa/drivers/dri/i915/intel_pixel_copy.c
+++ b/src/mesa/drivers/dri/i915/intel_pixel_copy.c
@@ -123,24 +123,21 @@ do_blit_copypixels(struct gl_context * ctx,
       perf_debug("glCopyPixels(): Unsupported fragment shader state\n");
       return false;
    }
 
    if (ctx->Color.AlphaEnabled ||
        ctx->Color.BlendEnabled) {
       perf_debug("glCopyPixels(): Unsupported blend state\n");
       return false;
    }
 
-   if (!ctx->Color.ColorMask[0][0] ||
-       !ctx->Color.ColorMask[0][1] ||
-       !ctx->Color.ColorMask[0][2] ||
-       !ctx->Color.ColorMask[0][3]) {
+   if (GET_COLORMASK(ctx->Color.ColorMask, 0) != 0xf) {
       perf_debug("glCopyPixels(): Unsupported color mask state\n");
       return false;
    }
 
    if (ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F) {
       perf_debug("glCopyPixels(): Unsupported pixel zoom\n");
       return false;
    }
 
    intel_prepare_render(intel);
diff --git a/src/mesa/drivers/dri/i965/brw_blorp.c b/src/mesa/drivers/dri/i965/brw_blorp.c
index 82d9de1..30120df 100644
--- a/src/mesa/drivers/dri/i965/brw_blorp.c
+++ b/src/mesa/drivers/dri/i965/brw_blorp.c
@@ -1110,36 +1110,36 @@ brw_blorp_download_miptree(struct brw_context *brw,
    brw_emit_mi_flush(brw);
 
 err:
    brw_bo_unreference(dst_bo);
 
    return result;
 }
 
 static bool
 set_write_disables(const struct intel_renderbuffer *irb,
-                   const GLubyte *color_mask, bool *color_write_disable)
+                   const unsigned color_mask, bool *color_write_disable)
 {
    /* Format information in the renderbuffer represents the requirements
     * given by the client. There are cases where the backing miptree uses,
     * for example, RGBA to represent RGBX. Since the client is only expecting
     * RGB we can treat alpha as not used and write whatever we like into it.
     */
    const GLenum base_format = irb->Base.Base._BaseFormat;
    const int components = _mesa_base_format_component_count(base_format);
    bool disables = false;
 
    assert(components > 0);
 
    for (int i = 0; i < components; i++) {
-      color_write_disable[i] = !color_mask[i];
-      disables = disables || !color_mask[i];
+      color_write_disable[i] = !(color_mask & (1 << i));
+      disables = disables || color_write_disable[i];
    }
 
    return disables;
 }
 
 static void
 do_single_blorp_clear(struct brw_context *brw, struct gl_framebuffer *fb,
                       struct gl_renderbuffer *rb, unsigned buf,
                       bool partial_clear, bool encode_srgb)
 {
@@ -1162,21 +1162,22 @@ do_single_blorp_clear(struct brw_context *brw, struct gl_framebuffer *fb,
       y1 = rb->Height - fb->_Ymin;
    }
 
    /* If the clear region is empty, just return. */
    if (x0 == x1 || y0 == y1)
       return;
 
    bool can_fast_clear = !partial_clear;
 
    bool color_write_disable[4] = { false, false, false, false };
-   if (set_write_disables(irb, ctx->Color.ColorMask[buf], color_write_disable))
+   if (set_write_disables(irb, GET_COLORMASK(ctx->Color.ColorMask, buf),
+                          color_write_disable))
       can_fast_clear = false;
 
    /* We store clear colors as floats or uints as needed.  If there are
     * texture views in play, the formats will not properly be respected
     * during resolves because the resolve operations only know about the
     * miptree and not the renderbuffer.
     */
    if (irb->Base.Base.Format != irb->mt->format)
       can_fast_clear = false;
 
diff --git a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
index 611e850..92ac1e4 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
@@ -912,32 +912,32 @@ gen4_update_renderbuffer_surface(struct brw_context *brw,
 	      (tile_y / 2) << BRW_SURFACE_Y_OFFSET_SHIFT |
 	      (mt->surf.image_alignment_el.height == 4 ?
                   BRW_SURFACE_VERTICAL_ALIGN_ENABLE : 0));
 
    if (devinfo->gen < 6) {
       /* _NEW_COLOR */
       if (!ctx->Color.ColorLogicOpEnabled && !ctx->Color._AdvancedBlendMode &&
           (ctx->Color.BlendEnabled & (1 << unit)))
 	 surf[0] |= BRW_SURFACE_BLEND_ENABLED;
 
-      if (!ctx->Color.ColorMask[unit][0])
+      if (!GET_COLORMASK_BIT(ctx->Color.ColorMask, unit, 0))
 	 surf[0] |= 1 << BRW_SURFACE_WRITEDISABLE_R_SHIFT;
-      if (!ctx->Color.ColorMask[unit][1])
+      if (!GET_COLORMASK_BIT(ctx->Color.ColorMask, unit, 1))
 	 surf[0] |= 1 << BRW_SURFACE_WRITEDISABLE_G_SHIFT;
-      if (!ctx->Color.ColorMask[unit][2])
+      if (!GET_COLORMASK_BIT(ctx->Color.ColorMask, unit, 2))
 	 surf[0] |= 1 << BRW_SURFACE_WRITEDISABLE_B_SHIFT;
 
       /* As mentioned above, disable writes to the alpha component when the
        * renderbuffer is XRGB.
        */
       if (ctx->DrawBuffer->Visual.alphaBits == 0 ||
-	  !ctx->Color.ColorMask[unit][3]) {
+	  !GET_COLORMASK_BIT(ctx->Color.ColorMask, unit, 3)) {
 	 surf[0] |= 1 << BRW_SURFACE_WRITEDISABLE_A_SHIFT;
       }
    }
 
    return offset;
 }
 
 static void
 update_renderbuffer_surfaces(struct brw_context *brw)
 {
diff --git a/src/mesa/drivers/dri/i965/genX_state_upload.c b/src/mesa/drivers/dri/i965/genX_state_upload.c
index aa4d64d..4a422e5 100644
--- a/src/mesa/drivers/dri/i965/genX_state_upload.c
+++ b/src/mesa/drivers/dri/i965/genX_state_upload.c
@@ -1722,24 +1722,21 @@ brw_color_buffer_write_enabled(struct brw_context *brw)
    unsigned i;
 
    /* _NEW_BUFFERS */
    for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
       struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[i];
       uint64_t outputs_written = fp->info.outputs_written;
 
       /* _NEW_COLOR */
       if (rb && (outputs_written & BITFIELD64_BIT(FRAG_RESULT_COLOR) ||
                  outputs_written & BITFIELD64_BIT(FRAG_RESULT_DATA0 + i)) &&
-          (ctx->Color.ColorMask[i][0] ||
-           ctx->Color.ColorMask[i][1] ||
-           ctx->Color.ColorMask[i][2] ||
-           ctx->Color.ColorMask[i][3])) {
+          GET_COLORMASK(ctx->Color.ColorMask, i)) {
          return true;
       }
    }
 
    return false;
 }
 
 static void
 genX(upload_wm)(struct brw_context *brw)
 {
@@ -2964,24 +2961,24 @@ genX(upload_blend_state)(struct brw_context *brw)
           * So, generally, we want clamping to the render target's range.
           * And, good news, the hardware tables for both pre- and
           * post-blend color clamping are either ignored, or any are
           * allowed, or clamping is required but RT range clamping is a
           * valid option.
           */
          entry.PreBlendColorClampEnable = true;
          entry.PostBlendColorClampEnable = true;
          entry.ColorClampRange = COLORCLAMP_RTFORMAT;
 
-         entry.WriteDisableRed   = !ctx->Color.ColorMask[i][0];
-         entry.WriteDisableGreen = !ctx->Color.ColorMask[i][1];
-         entry.WriteDisableBlue  = !ctx->Color.ColorMask[i][2];
-         entry.WriteDisableAlpha = !ctx->Color.ColorMask[i][3];
+         entry.WriteDisableRed   = !GET_COLORMASK_BIT(ctx->Color.ColorMask, i, 0);
+         entry.WriteDisableGreen = !GET_COLORMASK_BIT(ctx->Color.ColorMask, i, 1);
+         entry.WriteDisableBlue  = !GET_COLORMASK_BIT(ctx->Color.ColorMask, i, 2);
+         entry.WriteDisableAlpha = !GET_COLORMASK_BIT(ctx->Color.ColorMask, i, 3);
 
 #if GEN_GEN >= 8
          GENX(BLEND_STATE_ENTRY_pack)(NULL, &blend_map[1 + i * 2], &entry);
 #else
          GENX(BLEND_STATE_ENTRY_pack)(NULL, &blend_map[i * 2], &entry);
 #endif
       }
    }
 
 #if GEN_GEN >= 8
diff --git a/src/mesa/drivers/dri/i965/intel_pixel.c b/src/mesa/drivers/dri/i965/intel_pixel.c
index c69c3cc..0cbb572 100644
--- a/src/mesa/drivers/dri/i965/intel_pixel.c
+++ b/src/mesa/drivers/dri/i965/intel_pixel.c
@@ -73,24 +73,21 @@ intel_check_blit_fragment_ops(struct gl_context * ctx, bool src_alpha_is_one)
 	ctx->Color.Blend[0].EquationA != GL_FUNC_ADD)) {
       DBG("fallback due to blend\n");
       return false;
    }
 
    if (ctx->Texture._MaxEnabledTexImageUnit != -1) {
       DBG("fallback due to texturing\n");
       return false;
    }
 
-   if (!(ctx->Color.ColorMask[0][0] &&
-	 ctx->Color.ColorMask[0][1] &&
-	 ctx->Color.ColorMask[0][2] &&
-	 ctx->Color.ColorMask[0][3])) {
+   if (GET_COLORMASK(ctx->Color.ColorMask, 0) != 0xf) {
       DBG("fallback due to color masking\n");
       return false;
    }
 
    if (ctx->Color.AlphaEnabled) {
       DBG("fallback due to alpha\n");
       return false;
    }
 
    if (ctx->Depth.Test) {
diff --git a/src/mesa/drivers/dri/i965/intel_pixel_copy.c b/src/mesa/drivers/dri/i965/intel_pixel_copy.c
index a23c5b1..8029ffb 100644
--- a/src/mesa/drivers/dri/i965/intel_pixel_copy.c
+++ b/src/mesa/drivers/dri/i965/intel_pixel_copy.c
@@ -127,24 +127,21 @@ do_blit_copypixels(struct gl_context * ctx,
       perf_debug("glCopyPixels(): Unsupported fragment shader state\n");
       return false;
    }
 
    if (ctx->Color.AlphaEnabled ||
        ctx->Color.BlendEnabled) {
       perf_debug("glCopyPixels(): Unsupported blend state\n");
       return false;
    }
 
-   if (!ctx->Color.ColorMask[0][0] ||
-       !ctx->Color.ColorMask[0][1] ||
-       !ctx->Color.ColorMask[0][2] ||
-       !ctx->Color.ColorMask[0][3]) {
+   if (GET_COLORMASK(ctx->Color.ColorMask, 0) != 0xf) {
       perf_debug("glCopyPixels(): Unsupported color mask state\n");
       return false;
    }
 
    if (ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F) {
       perf_debug("glCopyPixels(): Unsupported pixel zoom\n");
       return false;
    }
 
    intel_batchbuffer_flush(brw);
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_driver.c b/src/mesa/drivers/dri/nouveau/nouveau_driver.c
index 998e751..018f65a 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_driver.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_driver.c
@@ -125,21 +125,27 @@ nouveau_clear(struct gl_context *ctx, GLbitfield buffers)
 		if (buf & BUFFER_BITS_COLOR) {
 			const float *color = ctx->Color.ClearColor.f;
 
 			if (fb->Attachment[i].Renderbuffer->_BaseFormat ==
 			    GL_LUMINANCE_ALPHA)
 				value = pack_la_clamp_f(
 						s->format, color[0], color[3]);
 			else
 				value = pack_rgba_clamp_f(s->format, color);
 
-			mask = pack_rgba_i(s->format, ctx->Color.ColorMask[0]);
+			const uint8_t colormask[4] = {
+				GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 0) ? 0xf : 0,
+				GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 1) ? 0xf : 0,
+				GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 2) ? 0xf : 0,
+				GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 3) ? 0xf : 0,
+			};
+			mask = pack_rgba_i(s->format, colormask);
 
 			if (mask)
 				context_drv(ctx)->surface_fill(
 					ctx, s, mask, value, x, y, w, h);
 
 			buffers &= ~buf;
 
 		} else if (buf & (BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL)) {
 			mask = pack_zs_i(s->format,
 					 (buffers & BUFFER_BIT_DEPTH &&
diff --git a/src/mesa/drivers/dri/nouveau/nv04_context.c b/src/mesa/drivers/dri/nouveau/nv04_context.c
index 3cc219b..4dbb950 100644
--- a/src/mesa/drivers/dri/nouveau/nv04_context.c
+++ b/src/mesa/drivers/dri/nouveau/nv04_context.c
@@ -50,24 +50,21 @@ nv04_context_engine(struct gl_context *ctx)
 {
 	struct nv04_context *nctx = to_nv04_context(ctx);
 	struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw;
 	struct nouveau_pushbuf *push = context_push(ctx);
 	struct nouveau_object *fahrenheit;
 
 	if ((ctx->Texture.Unit[0]._Current &&
 	     texunit_needs_combiners(&ctx->Texture.Unit[0])) ||
 	    ctx->Texture.Unit[1]._Current ||
 	    ctx->Stencil.Enabled ||
-	    !(ctx->Color.ColorMask[0][RCOMP] &&
-	      ctx->Color.ColorMask[0][GCOMP] &&
-	      ctx->Color.ColorMask[0][BCOMP] &&
-	      ctx->Color.ColorMask[0][ACOMP]))
+	    GET_COLORMASK(ctx->Color.ColorMask, 0) != 0xf)
 		fahrenheit = hw->eng3dm;
 	else
 		fahrenheit = hw->eng3d;
 
 	if (fahrenheit != nctx->eng3d) {
 		BEGIN_NV04(push, NV01_SUBC(3D, OBJECT), 1);
 		PUSH_DATA (push, fahrenheit->handle);
 		nctx->eng3d = fahrenheit;
 	}
 
diff --git a/src/mesa/drivers/dri/nouveau/nv04_state_raster.c b/src/mesa/drivers/dri/nouveau/nv04_state_raster.c
index 69664fb..a2b0ab9 100644
--- a/src/mesa/drivers/dri/nouveau/nv04_state_raster.c
+++ b/src/mesa/drivers/dri/nouveau/nv04_state_raster.c
@@ -155,27 +155,27 @@ nv04_emit_control(struct gl_context *ctx, int emit)
 	nv04->ctrl[0] |= get_comparison_op(ctx->Depth.Func) << 16;
 
 	/* Alpha test. */
 	if (ctx->Color.AlphaEnabled)
 		nv04->ctrl[0] |= NV04_TEXTURED_TRIANGLE_CONTROL_ALPHA_ENABLE;
 
 	nv04->ctrl[0] |= get_comparison_op(ctx->Color.AlphaFunc) << 8 |
 			 FLOAT_TO_UBYTE(ctx->Color.AlphaRef);
 
 	/* Color mask. */
-	if (ctx->Color.ColorMask[0][RCOMP])
+	if (GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 0))
 		nv04->ctrl[0] |= NV04_MULTITEX_TRIANGLE_CONTROL0_RED_WRITE;
-	if (ctx->Color.ColorMask[0][GCOMP])
+	if (GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 1))
 		nv04->ctrl[0] |= NV04_MULTITEX_TRIANGLE_CONTROL0_GREEN_WRITE;
-	if (ctx->Color.ColorMask[0][BCOMP])
+	if (GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 2))
 		nv04->ctrl[0] |= NV04_MULTITEX_TRIANGLE_CONTROL0_BLUE_WRITE;
-	if (ctx->Color.ColorMask[0][ACOMP])
+	if (GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 3))
 		nv04->ctrl[0] |= NV04_MULTITEX_TRIANGLE_CONTROL0_ALPHA_WRITE;
 
 	/* Stencil test. */
 	if (ctx->Stencil.WriteMask[0])
 		nv04->ctrl[0] |= NV04_MULTITEX_TRIANGLE_CONTROL0_STENCIL_WRITE;
 
 	if (_mesa_stencil_is_enabled(ctx))
 		nv04->ctrl[1] |= NV04_MULTITEX_TRIANGLE_CONTROL1_STENCIL_ENABLE;
 
 	nv04->ctrl[1] |= get_comparison_op(ctx->Stencil.Function[0]) << 4 |
diff --git a/src/mesa/drivers/dri/nouveau/nv10_state_raster.c b/src/mesa/drivers/dri/nouveau/nv10_state_raster.c
index 047f539..3f4ff73 100644
--- a/src/mesa/drivers/dri/nouveau/nv10_state_raster.c
+++ b/src/mesa/drivers/dri/nouveau/nv10_state_raster.c
@@ -80,24 +80,24 @@ nv10_emit_blend_func(struct gl_context *ctx, int emit)
 	PUSH_DATA (push, nvgl_blend_func(ctx->Color.Blend[0].SrcRGB));
 	PUSH_DATA (push, nvgl_blend_func(ctx->Color.Blend[0].DstRGB));
 }
 
 void
 nv10_emit_color_mask(struct gl_context *ctx, int emit)
 {
 	struct nouveau_pushbuf *push = context_push(ctx);
 
 	BEGIN_NV04(push, NV10_3D(COLOR_MASK), 1);
-	PUSH_DATA (push, ((ctx->Color.ColorMask[0][3] ? 1 << 24 : 0) |
-			(ctx->Color.ColorMask[0][0] ? 1 << 16 : 0) |
-			(ctx->Color.ColorMask[0][1] ? 1 << 8 : 0) |
-			(ctx->Color.ColorMask[0][2] ? 1 << 0 : 0)));
+	PUSH_DATA (push, ((GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 3) ? 1 << 24 : 0) |
+			(GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 0) ? 1 << 16 : 0) |
+			(GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 1) ? 1 << 8 : 0) |
+			(GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 2) ? 1 << 0 : 0)));
 }
 
 void
 nv10_emit_depth(struct gl_context *ctx, int emit)
 {
 	struct nouveau_pushbuf *push = context_push(ctx);
 	struct gl_framebuffer *fb = ctx->DrawBuffer;
 
 	BEGIN_NV04(push, NV10_3D(DEPTH_TEST_ENABLE), 1);
 	PUSH_DATAb(push, ctx->Depth.Test && fb->Visual.depthBits > 0);
diff --git a/src/mesa/drivers/dri/nouveau/nv20_context.c b/src/mesa/drivers/dri/nouveau/nv20_context.c
index 0ab2db0..887aa5f 100644
--- a/src/mesa/drivers/dri/nouveau/nv20_context.c
+++ b/src/mesa/drivers/dri/nouveau/nv20_context.c
@@ -48,27 +48,27 @@ nv20_clear(struct gl_context *ctx, GLbitfield buffers)
 	nouveau_pushbuf_bufctx(push, nctx->hw.bufctx);
 	if (nouveau_pushbuf_validate(push)) {
 		nouveau_pushbuf_bufctx(push, NULL);
 		return;
 	}
 
 	if (buffers & BUFFER_BITS_COLOR) {
 		struct nouveau_surface *s = &to_nouveau_renderbuffer(
 			fb->_ColorDrawBuffers[0])->surface;
 
-		if (ctx->Color.ColorMask[0][RCOMP])
+		if (GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 0))
 			clear |= NV20_3D_CLEAR_BUFFERS_COLOR_R;
-		if (ctx->Color.ColorMask[0][GCOMP])
+		if (GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 1))
 			clear |= NV20_3D_CLEAR_BUFFERS_COLOR_G;
-		if (ctx->Color.ColorMask[0][BCOMP])
+		if (GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 2))
 			clear |= NV20_3D_CLEAR_BUFFERS_COLOR_B;
-		if (ctx->Color.ColorMask[0][ACOMP])
+		if (GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 3))
 			clear |= NV20_3D_CLEAR_BUFFERS_COLOR_A;
 
 		BEGIN_NV04(push, NV20_3D(CLEAR_VALUE), 1);
 		PUSH_DATA (push, pack_rgba_clamp_f(s->format, ctx->Color.ClearColor.f));
 
 		buffers &= ~BUFFER_BITS_COLOR;
 	}
 
 	if (buffers & (BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL)) {
 		struct nouveau_surface *s = &to_nouveau_renderbuffer(
diff --git a/src/mesa/drivers/dri/r200/r200_state.c b/src/mesa/drivers/dri/r200/r200_state.c
index 62a089e..33b6963 100644
--- a/src/mesa/drivers/dri/r200/r200_state.c
+++ b/src/mesa/drivers/dri/r200/r200_state.c
@@ -681,24 +681,24 @@ static void r200ColorMask( struct gl_context *ctx,
 {
    r200ContextPtr rmesa = R200_CONTEXT(ctx);
    GLuint mask;
    struct radeon_renderbuffer *rrb;
    GLuint flag = rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] & ~R200_PLANE_MASK_ENABLE;
 
    rrb = radeon_get_colorbuffer(&rmesa->radeon);
    if (!rrb)
      return;
    mask = radeonPackColor( rrb->cpp,
-			   ctx->Color.ColorMask[0][RCOMP],
-			   ctx->Color.ColorMask[0][GCOMP],
-			   ctx->Color.ColorMask[0][BCOMP],
-			   ctx->Color.ColorMask[0][ACOMP] );
+			   GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 0),
+			   GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 1),
+			   GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 2),
+			   GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 3) );
 
 
    if (!(r && g && b && a))
       flag |= R200_PLANE_MASK_ENABLE;
 
    if ( rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] != flag ) {
       R200_STATECHANGE( rmesa, ctx );
       rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = flag;
    }
 
diff --git a/src/mesa/drivers/dri/radeon/radeon_state.c b/src/mesa/drivers/dri/radeon/radeon_state.c
index a5c7be3..e413df3 100644
--- a/src/mesa/drivers/dri/radeon/radeon_state.c
+++ b/src/mesa/drivers/dri/radeon/radeon_state.c
@@ -497,24 +497,24 @@ static void radeonColorMask( struct gl_context *ctx,
 {
    r100ContextPtr rmesa = R100_CONTEXT(ctx);
    struct radeon_renderbuffer *rrb;
    GLuint mask;
 
    rrb = radeon_get_colorbuffer(&rmesa->radeon);
    if (!rrb)
      return;
 
    mask = radeonPackColor( rrb->cpp,
-			   ctx->Color.ColorMask[0][RCOMP],
-			   ctx->Color.ColorMask[0][GCOMP],
-			   ctx->Color.ColorMask[0][BCOMP],
-			   ctx->Color.ColorMask[0][ACOMP] );
+			   GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 0),
+			   GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 1),
+			   GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 2),
+			   GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 3) );
 
    if ( rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] != mask ) {
       RADEON_STATECHANGE( rmesa, msk );
       rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = mask;
    }
 }
 
 
 /* =============================================================
  * Polygon state
diff --git a/src/mesa/drivers/x11/xm_dd.c b/src/mesa/drivers/x11/xm_dd.c
index 3e61342..3c576c7 100644
--- a/src/mesa/drivers/x11/xm_dd.c
+++ b/src/mesa/drivers/x11/xm_dd.c
@@ -238,40 +238,40 @@ clear_nbit_ximage(struct gl_context *ctx, struct xmesa_renderbuffer *xrb,
    }
 }
 
 
 
 static void
 clear_buffers(struct gl_context *ctx, GLbitfield buffers)
 {
    if (_mesa_is_winsys_fbo(ctx->DrawBuffer)) {
       /* this is a window system framebuffer */
-      const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask[0];
       const XMesaContext xmesa = XMESA_CONTEXT(ctx);
       XMesaBuffer b = XMESA_BUFFER(ctx->DrawBuffer);
       const GLint x = ctx->DrawBuffer->_Xmin;
       const GLint y = ctx->DrawBuffer->_Ymin;
       const GLint width = ctx->DrawBuffer->_Xmax - x;
       const GLint height = ctx->DrawBuffer->_Ymax - y;
 
       _mesa_unclamped_float_rgba_to_ubyte(xmesa->clearcolor,
                                           ctx->Color.ClearColor.f);
       xmesa->clearpixel = xmesa_color_to_pixel(ctx,
                                                xmesa->clearcolor[0],
                                                xmesa->clearcolor[1],
                                                xmesa->clearcolor[2],
                                                xmesa->clearcolor[3],
                                                xmesa->xm_visual->undithered_pf);
       XMesaSetForeground(xmesa->display, b->cleargc, xmesa->clearpixel);
 
       /* we can't handle color or index masking */
-      if (*colorMask == 0xffffffff && ctx->Color.IndexMask == 0xffffffff) {
+      if (GET_COLORMASK(ctx->Color.ColorMask, 0) == 0xf &&
+          ctx->Color.IndexMask == 0xffffffff) {
          if (buffers & BUFFER_BIT_FRONT_LEFT) {
             /* clear front color buffer */
             struct gl_renderbuffer *frontRb
                = ctx->DrawBuffer->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
             if (b->frontxrb == xmesa_renderbuffer(frontRb)) {
                /* renderbuffer is not wrapped - great! */
                b->frontxrb->clearFunc(ctx, b->frontxrb, x, y, width, height);
                buffers &= ~BUFFER_BIT_FRONT_LEFT;
             }
             else {
diff --git a/src/mesa/main/accum.c b/src/mesa/main/accum.c
index 2b15b6e..5fbee8f 100644
--- a/src/mesa/main/accum.c
+++ b/src/mesa/main/accum.c
@@ -291,24 +291,24 @@ accum_return(struct gl_context *ctx, GLfloat value,
                                GL_MAP_READ_BIT,
                                &accMap, &accRowStride);
    if (!accMap) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAccum");
       return;
    }
 
    /* Loop over destination buffers */
    for (buffer = 0; buffer < fb->_NumColorDrawBuffers; buffer++) {
       struct gl_renderbuffer *colorRb = fb->_ColorDrawBuffers[buffer];
-      const GLboolean masking = (!ctx->Color.ColorMask[buffer][RCOMP] ||
-                                 !ctx->Color.ColorMask[buffer][GCOMP] ||
-                                 !ctx->Color.ColorMask[buffer][BCOMP] ||
-                                 !ctx->Color.ColorMask[buffer][ACOMP]);
+      const GLboolean masking = (!GET_COLORMASK_BIT(ctx->Color.ColorMask, buffer, 0) ||
+                                 !GET_COLORMASK_BIT(ctx->Color.ColorMask, buffer, 1) ||
+                                 !GET_COLORMASK_BIT(ctx->Color.ColorMask, buffer, 2) ||
+                                 !GET_COLORMASK_BIT(ctx->Color.ColorMask, buffer, 3));
       GLbitfield mappingFlags = GL_MAP_WRITE_BIT;
 
       if (masking)
          mappingFlags |= GL_MAP_READ_BIT;
 
       /* Map color buffer */
       ctx->Driver.MapRenderbuffer(ctx, colorRb, xpos, ypos, width, height,
                                   mappingFlags, &colorMap, &colorRowStride);
       if (!colorMap) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAccum");
@@ -333,33 +333,33 @@ accum_return(struct gl_context *ctx, GLfloat value,
                   rgba[i][2] = acc[i * 4 + 2] * scale;
                   rgba[i][3] = acc[i * 4 + 3] * scale;
                }
 
                if (masking) {
 
                   /* get existing colors from dest buffer */
                   _mesa_unpack_rgba_row(colorRb->Format, width, colorMap, dest);
 
                   /* use the dest colors where mask[channel] = 0 */
-                  if (ctx->Color.ColorMask[buffer][RCOMP] == 0) {
+                  if (!GET_COLORMASK_BIT(ctx->Color.ColorMask, buffer, 0)) {
                      for (i = 0; i < width; i++)
                         rgba[i][RCOMP] = dest[i][RCOMP];
                   }
-                  if (ctx->Color.ColorMask[buffer][GCOMP] == 0) {
+                  if (!GET_COLORMASK_BIT(ctx->Color.ColorMask, buffer, 1)) {
                      for (i = 0; i < width; i++)
                         rgba[i][GCOMP] = dest[i][GCOMP];
                   }
-                  if (ctx->Color.ColorMask[buffer][BCOMP] == 0) {
+                  if (!GET_COLORMASK_BIT(ctx->Color.ColorMask, buffer, 2)) {
                      for (i = 0; i < width; i++)
                         rgba[i][BCOMP] = dest[i][BCOMP];
                   }
-                  if (ctx->Color.ColorMask[buffer][ACOMP] == 0) {
+                  if (!GET_COLORMASK_BIT(ctx->Color.ColorMask, buffer, 3)) {
                      for (i = 0; i < width; i++)
                         rgba[i][ACOMP] = dest[i][ACOMP];
                   }
                }
 
                _mesa_pack_float_rgba_row(colorRb->Format, width,
                                          (const GLfloat (*)[4]) rgba, colorMap);
 
                accMap += accRowStride;
                colorMap += colorRowStride;
diff --git a/src/mesa/main/attrib.c b/src/mesa/main/attrib.c
index 0b4b63f..a9e4a11 100644
--- a/src/mesa/main/attrib.c
+++ b/src/mesa/main/attrib.c
@@ -960,33 +960,33 @@ _mesa_PopAttrib(void)
                const struct gl_colorbuffer_attrib *color;
 
                color = (const struct gl_colorbuffer_attrib *) attr->data;
                _mesa_ClearIndex((GLfloat) color->ClearIndex);
                _mesa_ClearColor(color->ClearColor.f[0],
                                 color->ClearColor.f[1],
                                 color->ClearColor.f[2],
                                 color->ClearColor.f[3]);
                _mesa_IndexMask(color->IndexMask);
                if (!ctx->Extensions.EXT_draw_buffers2) {
-                  _mesa_ColorMask((GLboolean) (color->ColorMask[0][0] != 0),
-                                  (GLboolean) (color->ColorMask[0][1] != 0),
-                                  (GLboolean) (color->ColorMask[0][2] != 0),
-                                  (GLboolean) (color->ColorMask[0][3] != 0));
+                  _mesa_ColorMask(GET_COLORMASK_BIT(color->ColorMask, 0, 0),
+                                  GET_COLORMASK_BIT(color->ColorMask, 0, 1),
+                                  GET_COLORMASK_BIT(color->ColorMask, 0, 2),
+                                  GET_COLORMASK_BIT(color->ColorMask, 0, 3));
                }
                else {
                   GLuint i;
                   for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
                      _mesa_ColorMaski(i,
-                                  (GLboolean) (color->ColorMask[i][0] != 0),
-                                  (GLboolean) (color->ColorMask[i][1] != 0),
-                                  (GLboolean) (color->ColorMask[i][2] != 0),
-                                  (GLboolean) (color->ColorMask[i][3] != 0));
+                                      GET_COLORMASK_BIT(color->ColorMask, i, 0),
+                                      GET_COLORMASK_BIT(color->ColorMask, i, 1),
+                                      GET_COLORMASK_BIT(color->ColorMask, i, 2),
+                                      GET_COLORMASK_BIT(color->ColorMask, i, 3));
                   }
                }
                {
                   /* Need to determine if more than one color output is
                    * specified.  If so, call glDrawBuffersARB, else call
                    * glDrawBuffer().  This is a subtle, but essential point
                    * since GL_FRONT (for example) is illegal for the former
                    * function, but legal for the later.
                    */
                   GLboolean multipleBuffers = GL_FALSE;
diff --git a/src/mesa/main/blend.c b/src/mesa/main/blend.c
index ec8e27e..34e8d11 100644
--- a/src/mesa/main/blend.c
+++ b/src/mesa/main/blend.c
@@ -967,86 +967,73 @@ _mesa_IndexMask( GLuint mask )
  *
  * Sets the appropriate value of gl_colorbuffer_attrib::ColorMask.  On a
  * change, flushes the vertices and notifies the driver via the
  * dd_function_table::ColorMask callback.
  */
 void GLAPIENTRY
 _mesa_ColorMask( GLboolean red, GLboolean green,
                  GLboolean blue, GLboolean alpha )
 {
    GET_CURRENT_CONTEXT(ctx);
-   GLubyte tmp[4];
-   GLuint i;
-   GLboolean flushed;
 
    if (MESA_VERBOSE & VERBOSE_API)
       _mesa_debug(ctx, "glColorMask(%d, %d, %d, %d)\n",
                   red, green, blue, alpha);
 
-   /* Shouldn't have any information about channel depth in core mesa
-    * -- should probably store these as the native booleans:
-    */
-   tmp[RCOMP] = red    ? 0xff : 0x0;
-   tmp[GCOMP] = green  ? 0xff : 0x0;
-   tmp[BCOMP] = blue   ? 0xff : 0x0;
-   tmp[ACOMP] = alpha  ? 0xff : 0x0;
-
-   flushed = GL_FALSE;
-   for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
-      if (!TEST_EQ_4V(tmp, ctx->Color.ColorMask[i])) {
-         if (!flushed) {
-            FLUSH_VERTICES(ctx, ctx->DriverFlags.NewColorMask ? 0 : _NEW_COLOR);
-            ctx->NewDriverState |= ctx->DriverFlags.NewColorMask;
-         }
-         flushed = GL_TRUE;
-         COPY_4UBV(ctx->Color.ColorMask[i], tmp);
-      }
-   }
+   GLbitfield mask = (!!red) |
+                     ((!!green) << 1) |
+                     ((!!blue) << 2) |
+                     ((!!alpha) << 3);
+   mask = _mesa_replicate_colormask(mask, ctx->Const.MaxDrawBuffers);
+
+   if (ctx->Color.ColorMask == mask)
+      return;
+
+   FLUSH_VERTICES(ctx, ctx->DriverFlags.NewColorMask ? 0 : _NEW_COLOR);
+   ctx->NewDriverState |= ctx->DriverFlags.NewColorMask;
+   ctx->Color.ColorMask = mask;
 
    if (ctx->Driver.ColorMask)
       ctx->Driver.ColorMask( ctx, red, green, blue, alpha );
 }
 
 
 /**
  * For GL_EXT_draw_buffers2 and GL3
  */
 void GLAPIENTRY
 _mesa_ColorMaski(GLuint buf, GLboolean red, GLboolean green,
                  GLboolean blue, GLboolean alpha)
 {
-   GLubyte tmp[4];
    GET_CURRENT_CONTEXT(ctx);
 
    if (MESA_VERBOSE & VERBOSE_API)
       _mesa_debug(ctx, "glColorMaski %u %d %d %d %d\n",
                   buf, red, green, blue, alpha);
 
    if (buf >= ctx->Const.MaxDrawBuffers) {
       _mesa_error(ctx, GL_INVALID_VALUE, "glColorMaski(buf=%u)", buf);
       return;
    }
 
-   /* Shouldn't have any information about channel depth in core mesa
-    * -- should probably store these as the native booleans:
-    */
-   tmp[RCOMP] = red    ? 0xff : 0x0;
-   tmp[GCOMP] = green  ? 0xff : 0x0;
-   tmp[BCOMP] = blue   ? 0xff : 0x0;
-   tmp[ACOMP] = alpha  ? 0xff : 0x0;
+   GLbitfield mask = (!!red) |
+                     ((!!green) << 1) |
+                     ((!!blue) << 2) |
+                     ((!!alpha) << 3);
 
-   if (TEST_EQ_4V(tmp, ctx->Color.ColorMask[buf]))
+   if (GET_COLORMASK(ctx->Color.ColorMask, buf) == mask)
       return;
 
    FLUSH_VERTICES(ctx, ctx->DriverFlags.NewColorMask ? 0 : _NEW_COLOR);
    ctx->NewDriverState |= ctx->DriverFlags.NewColorMask;
-   COPY_4UBV(ctx->Color.ColorMask[buf], tmp);
+   ctx->Color.ColorMask &= ~(0xf << (4 * buf));
+   ctx->Color.ColorMask |= mask << (4 * buf);
 }
 
 
 void GLAPIENTRY
 _mesa_ClampColor(GLenum target, GLenum clamp)
 {
    GET_CURRENT_CONTEXT(ctx);
 
    /* Check for both the extension and the GL version, since the Intel driver
     * does not advertise the extension in core profiles.
@@ -1183,21 +1170,21 @@ _mesa_get_render_format(const struct gl_context *ctx, mesa_format format)
  *
  * Initializes the related fields in the context color attribute group,
  * __struct gl_contextRec::Color.
  */
 void _mesa_init_color( struct gl_context * ctx )
 {
    GLuint i;
 
    /* Color buffer group */
    ctx->Color.IndexMask = ~0u;
-   memset(ctx->Color.ColorMask, 0xff, sizeof(ctx->Color.ColorMask));
+   ctx->Color.ColorMask = 0xffffffff;
    ctx->Color.ClearIndex = 0;
    ASSIGN_4V( ctx->Color.ClearColor.f, 0, 0, 0, 0 );
    ctx->Color.AlphaEnabled = GL_FALSE;
    ctx->Color.AlphaFunc = GL_ALWAYS;
    ctx->Color.AlphaRef = 0;
    ctx->Color.BlendEnabled = 0x0;
    for (i = 0; i < ARRAY_SIZE(ctx->Color.Blend); i++) {
       ctx->Color.Blend[i].SrcRGB = GL_ONE;
       ctx->Color.Blend[i].DstRGB = GL_ZERO;
       ctx->Color.Blend[i].SrcA = GL_ONE;
diff --git a/src/mesa/main/blend.h b/src/mesa/main/blend.h
index c95bc57..6e56f2f 100644
--- a/src/mesa/main/blend.h
+++ b/src/mesa/main/blend.h
@@ -191,11 +191,21 @@ _mesa_flush_vertices_for_blend_adv(struct gl_context *ctx,
    if (_mesa_has_KHR_blend_equation_advanced(ctx) &&
        _mesa_advanded_blend_sh_constant_changed(ctx, new_blend_enabled,
                                                 new_mode)) {
       FLUSH_VERTICES(ctx, _NEW_COLOR);
       ctx->NewDriverState |= ctx->DriverFlags.NewBlend;
       return;
    }
    _mesa_flush_vertices_for_blend_state(ctx);
 }
 
+static inline GLbitfield
+_mesa_replicate_colormask(GLbitfield mask0, unsigned num_buffers)
+{
+   GLbitfield mask = mask0;
+
+   for (unsigned i = 1; i < num_buffers; i++)
+      mask |= mask0 << (i * 4);
+   return mask;
+}
+
 #endif
diff --git a/src/mesa/main/clear.c b/src/mesa/main/clear.c
index be60442..6beff9e 100644
--- a/src/mesa/main/clear.c
+++ b/src/mesa/main/clear.c
@@ -111,21 +111,21 @@ _mesa_ClearColorIuiEXT(GLuint r, GLuint g, GLuint b, GLuint a)
  * XRGB).
  */
 static bool
 color_buffer_writes_enabled(const struct gl_context *ctx, unsigned idx)
 {
    struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[idx];
    GLuint c;
 
    if (rb) {
       for (c = 0; c < 4; c++) {
-         if (ctx->Color.ColorMask[idx][c] &&
+         if (GET_COLORMASK_BIT(ctx->Color.ColorMask, idx, c) &&
              _mesa_format_has_color_component(rb->Format, c)) {
             return true;
          }
       }
    }
 
    return false;
 }
 
 
diff --git a/src/mesa/main/get.c b/src/mesa/main/get.c
index cf9a2f6..16ad8f6 100644
--- a/src/mesa/main/get.c
+++ b/src/mesa/main/get.c
@@ -670,24 +670,24 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu
 
    case GL_CURRENT_TEXTURE_COORDS:
       unit = ctx->Texture.CurrentUnit;
       v->value_float_4[0] = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit][0];
       v->value_float_4[1] = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit][1];
       v->value_float_4[2] = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit][2];
       v->value_float_4[3] = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit][3];
       break;
 
    case GL_COLOR_WRITEMASK:
-      v->value_int_4[0] = ctx->Color.ColorMask[0][RCOMP] ? 1 : 0;
-      v->value_int_4[1] = ctx->Color.ColorMask[0][GCOMP] ? 1 : 0;
-      v->value_int_4[2] = ctx->Color.ColorMask[0][BCOMP] ? 1 : 0;
-      v->value_int_4[3] = ctx->Color.ColorMask[0][ACOMP] ? 1 : 0;
+      v->value_int_4[0] = GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 0) ? 1 : 0;
+      v->value_int_4[1] = GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 1) ? 1 : 0;
+      v->value_int_4[2] = GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 2) ? 1 : 0;
+      v->value_int_4[3] = GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 3) ? 1 : 0;
       break;
 
    case GL_EDGE_FLAG:
       v->value_bool = ctx->Current.Attrib[VERT_ATTRIB_EDGEFLAG][0] == 1.0F;
       break;
 
    case GL_READ_BUFFER:
       v->value_enum = ctx->ReadBuffer->ColorReadBuffer;
       break;
 
@@ -2255,24 +2255,24 @@ find_value_indexed(const char *func, GLenum pname, GLuint index, union value *v)
       if (!ctx->Extensions.ARB_draw_buffers_blend)
          goto invalid_enum;
       v->value_int = ctx->Color.Blend[index].EquationA;
       return TYPE_INT;
 
    case GL_COLOR_WRITEMASK:
       if (index >= ctx->Const.MaxDrawBuffers)
          goto invalid_value;
       if (!ctx->Extensions.EXT_draw_buffers2)
          goto invalid_enum;
-      v->value_int_4[0] = ctx->Color.ColorMask[index][RCOMP] ? 1 : 0;
-      v->value_int_4[1] = ctx->Color.ColorMask[index][GCOMP] ? 1 : 0;
-      v->value_int_4[2] = ctx->Color.ColorMask[index][BCOMP] ? 1 : 0;
-      v->value_int_4[3] = ctx->Color.ColorMask[index][ACOMP] ? 1 : 0;
+      v->value_int_4[0] = GET_COLORMASK_BIT(ctx->Color.ColorMask, index, 0) ? 1 : 0;
+      v->value_int_4[1] = GET_COLORMASK_BIT(ctx->Color.ColorMask, index, 1) ? 1 : 0;
+      v->value_int_4[2] = GET_COLORMASK_BIT(ctx->Color.ColorMask, index, 2) ? 1 : 0;
+      v->value_int_4[3] = GET_COLORMASK_BIT(ctx->Color.ColorMask, index, 3) ? 1 : 0;
       return TYPE_INT_4;
 
    case GL_SCISSOR_BOX:
       if (index >= ctx->Const.MaxViewports)
          goto invalid_value;
       v->value_int_4[0] = ctx->Scissor.ScissorArray[index].X;
       v->value_int_4[1] = ctx->Scissor.ScissorArray[index].Y;
       v->value_int_4[2] = ctx->Scissor.ScissorArray[index].Width;
       v->value_int_4[3] = ctx->Scissor.ScissorArray[index].Height;
       return TYPE_INT_4;
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index f6fa6f4..5c73ad2 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -74,20 +74,24 @@ typedef GLuint64 GLbitfield64;
 /** Set a single bit */
 #define BITFIELD64_BIT(b)      ((GLbitfield64)1 << (b))
 /** Set all bits up to excluding bit b */
 #define BITFIELD64_MASK(b)      \
    ((b) == 64 ? (~(GLbitfield64)0) : BITFIELD64_BIT(b) - 1)
 /** Set count bits starting from bit b  */
 #define BITFIELD64_RANGE(b, count) \
    (BITFIELD64_MASK((b) + (count)) & ~BITFIELD64_MASK(b))
 
 
+#define GET_COLORMASK_BIT(mask, buf, chan) (((mask) >> (4 * (buf) + (chan))) & 0x1)
+#define GET_COLORMASK(mask, buf) (((mask) >> (4 * (buf))) & 0xf)
+
+
 /**
  * \name Some forward type declarations
  */
 /*@{*/
 struct _mesa_HashTable;
 struct gl_attrib_node;
 struct gl_list_extensions;
 struct gl_meta_state;
 struct gl_program_cache;
 struct gl_texture_object;
@@ -452,21 +456,23 @@ enum PACKED gl_logicop_mode {
 };
 
 /**
  * Color buffer attribute group (GL_COLOR_BUFFER_BIT).
  */
 struct gl_colorbuffer_attrib
 {
    GLuint ClearIndex;                      /**< Index for glClear */
    union gl_color_union ClearColor;        /**< Color for glClear, unclamped */
    GLuint IndexMask;                       /**< Color index write mask */
-   GLubyte ColorMask[MAX_DRAW_BUFFERS][4]; /**< Each flag is 0xff or 0x0 */
+
+   /** 4 colormask bits per draw buffer, max 8 draw buffers. 4*8 = 32 bits */
+   GLbitfield ColorMask;
 
    GLenum16 DrawBuffer[MAX_DRAW_BUFFERS];  /**< Which buffer to draw into */
 
    /**
     * \name alpha testing
     */
    /*@{*/
    GLboolean AlphaEnabled;		/**< Alpha test enabled flag */
    GLenum16 AlphaFunc;			/**< Alpha test function */
    GLfloat AlphaRefUnclamped;
diff --git a/src/mesa/state_tracker/st_atom_blend.c b/src/mesa/state_tracker/st_atom_blend.c
index 8bc5a5f..f7327d6 100644
--- a/src/mesa/state_tracker/st_atom_blend.c
+++ b/src/mesa/state_tracker/st_atom_blend.c
@@ -33,20 +33,21 @@
  
 
 #include "st_context.h"
 #include "st_atom.h"
 
 #include "pipe/p_context.h"
 #include "pipe/p_defines.h"
 #include "cso_cache/cso_context.h"
 
 #include "framebuffer.h"
+#include "main/blend.h"
 #include "main/macros.h"
 
 /**
  * Convert GLenum blend tokens to pipe tokens.
  * Both blend factors and blend funcs are accepted.
  */
 static GLuint
 translate_blend(GLenum blend)
 {
    switch (blend) {
@@ -106,28 +107,25 @@ translate_blend(GLenum blend)
       return 0;
    }
 }
 
 /**
  * Figure out if colormasks are different per rt.
  */
 static GLboolean
 colormask_per_rt(const struct gl_context *ctx)
 {
-   /* a bit suboptimal have to compare lots of values */
-   unsigned i;
-   for (i = 1; i < ctx->Const.MaxDrawBuffers; i++) {
-      if (memcmp(ctx->Color.ColorMask[0], ctx->Color.ColorMask[i], 4)) {
-         return GL_TRUE;
-      }
-   }
-   return GL_FALSE;
+   GLbitfield repl_mask0 =
+      _mesa_replicate_colormask(GET_COLORMASK(ctx->Color.ColorMask, 0),
+                                ctx->Const.MaxDrawBuffers);
+
+   return ctx->Color.ColorMask != repl_mask0;
 }
 
 /**
  * Figure out if blend enables/state are different per rt.
  */
 static GLboolean
 blend_per_rt(const struct gl_context *ctx)
 {
    if (ctx->Color.BlendEnabled &&
       (ctx->Color.BlendEnabled != ((1U << ctx->Const.MaxDrawBuffers) - 1))) {
@@ -199,31 +197,22 @@ st_update_blend( struct st_context *st )
                translate_blend(ctx->Color.Blend[j].SrcA);
             blend->rt[i].alpha_dst_factor =
                translate_blend(ctx->Color.Blend[j].DstA);
          }
       }
    }
    else {
       /* no blending / logicop */
    }
 
-   /* Colormask - maybe reverse these bits? */
-   for (i = 0; i < num_state; i++) {
-      if (ctx->Color.ColorMask[i][0])
-         blend->rt[i].colormask |= PIPE_MASK_R;
-      if (ctx->Color.ColorMask[i][1])
-         blend->rt[i].colormask |= PIPE_MASK_G;
-      if (ctx->Color.ColorMask[i][2])
-         blend->rt[i].colormask |= PIPE_MASK_B;
-      if (ctx->Color.ColorMask[i][3])
-         blend->rt[i].colormask |= PIPE_MASK_A;
-   }
+   for (i = 0; i < num_state; i++)
+      blend->rt[i].colormask = GET_COLORMASK(ctx->Color.ColorMask, i);
 
    blend->dither = ctx->Color.DitherFlag;
 
    if (_mesa_is_multisample_enabled(ctx) &&
        !(ctx->DrawBuffer->_IntegerBuffers & 0x1)) {
       /* Unlike in gallium/d3d10 these operations are only performed
        * if both msaa is enabled and we have a multisample buffer.
        */
       blend->alpha_to_coverage = ctx->Multisample.SampleAlphaToCoverage;
       blend->alpha_to_one = ctx->Multisample.SampleAlphaToOne;
diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c
index f50f844..6867718 100644
--- a/src/mesa/state_tracker/st_cb_clear.c
+++ b/src/mesa/state_tracker/st_cb_clear.c
@@ -219,28 +219,21 @@ clear_with_quad(struct gl_context *ctx, unsigned clear_buffers)
          int num_buffers = ctx->Extensions.EXT_draw_buffers2 ?
                            ctx->DrawBuffer->_NumColorDrawBuffers : 1;
          int i;
 
          blend.independent_blend_enable = num_buffers > 1;
 
          for (i = 0; i < num_buffers; i++) {
             if (!(clear_buffers & (PIPE_CLEAR_COLOR0 << i)))
                continue;
 
-            if (ctx->Color.ColorMask[i][0])
-               blend.rt[i].colormask |= PIPE_MASK_R;
-            if (ctx->Color.ColorMask[i][1])
-               blend.rt[i].colormask |= PIPE_MASK_G;
-            if (ctx->Color.ColorMask[i][2])
-               blend.rt[i].colormask |= PIPE_MASK_B;
-            if (ctx->Color.ColorMask[i][3])
-               blend.rt[i].colormask |= PIPE_MASK_A;
+            blend.rt[i].colormask = GET_COLORMASK(ctx->Color.ColorMask, i);
          }
 
          if (ctx->Color.DitherFlag)
             blend.dither = 1;
       }
       cso_set_blend(cso, &blend);
    }
 
    /* depth_stencil state: always pass/set to ref value */
    {
@@ -331,46 +324,20 @@ static inline bool
 is_window_rectangle_enabled(struct gl_context *ctx)
 {
    if (ctx->DrawBuffer == ctx->WinSysDrawBuffer)
       return false;
    return ctx->Scissor.NumWindowRects > 0 ||
       ctx->Scissor.WindowRectMode == GL_INCLUSIVE_EXT;
 }
 
 
 /**
- * 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];
-}
-
-
-/**
- * Return if any of the color channels are masked.
- */
-static inline GLboolean
-is_color_masked(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];
-}
-
-
-/**
  * Return if all of the stencil bits are masked.
  */
 static inline GLboolean
 is_stencil_disabled(struct gl_context *ctx, struct gl_renderbuffer *rb)
 {
    const GLuint stencilMax = 0xff;
 
    assert(_mesa_get_format_bits(rb->Format, GL_STENCIL_BITS) > 0);
    return (ctx->Stencil.WriteMask[0] & stencilMax) == 0;
 }
@@ -416,26 +383,26 @@ st_Clear(struct gl_context *ctx, GLbitfield mask)
 
          if (b != BUFFER_NONE && mask & (1 << b)) {
             struct gl_renderbuffer *rb
                = ctx->DrawBuffer->Attachment[b].Renderbuffer;
             struct st_renderbuffer *strb = st_renderbuffer(rb);
             int colormask_index = ctx->Extensions.EXT_draw_buffers2 ? i : 0;
 
             if (!strb || !strb->surface)
                continue;
 
-            if (is_color_disabled(ctx, colormask_index))
+            if (!GET_COLORMASK(ctx->Color.ColorMask, colormask_index))
                continue;
 
             if (is_scissor_enabled(ctx, rb) ||
                 is_window_rectangle_enabled(ctx) ||
-                is_color_masked(ctx, colormask_index))
+                GET_COLORMASK(ctx->Color.ColorMask, colormask_index) != 0xf)
                quad_buffers |= PIPE_CLEAR_COLOR0 << i;
             else
                clear_buffers |= PIPE_CLEAR_COLOR0 << i;
          }
       }
    }
 
    if (mask & BUFFER_BIT_DEPTH) {
       struct st_renderbuffer *strb = st_renderbuffer(depthRb);
 
diff --git a/src/mesa/swrast/s_clear.c b/src/mesa/swrast/s_clear.c
index c26b4be..ddafb67 100644
--- a/src/mesa/swrast/s_clear.c
+++ b/src/mesa/swrast/s_clear.c
@@ -180,21 +180,27 @@ clear_color_buffers(struct gl_context *ctx)
    for (buf = 0; buf < ctx->DrawBuffer->_NumColorDrawBuffers; buf++) {
       struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[buf];
 
       /* If this is an ES2 context or GL_ARB_ES2_compatibility is supported,
        * the framebuffer can be complete with some attachments be missing.  In
        * this case the _ColorDrawBuffers pointer will be NULL.
        */
       if (rb == NULL)
 	 continue;
 
-      clear_rgba_buffer(ctx, rb, ctx->Color.ColorMask[buf]);
+      const GLubyte colormask[4] = {
+         GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 0) ? 0xff : 0,
+         GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 1) ? 0xff : 0,
+         GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 2) ? 0xff : 0,
+         GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 3) ? 0xff : 0,
+      };
+      clear_rgba_buffer(ctx, rb, colormask);
    }
 }
 
 
 /**
  * Called via the device driver's ctx->Driver.Clear() function if the
  * device driver can't clear one or more of the buffers itself.
  * \param buffers  bitfield of BUFFER_BIT_* values indicating which
  *                 renderbuffers are to be cleared.
  * \param all  if GL_TRUE, clear whole buffer, else clear specified region.
diff --git a/src/mesa/swrast/s_context.c b/src/mesa/swrast/s_context.c
index 9f3d21f..f7f08b1 100644
--- a/src/mesa/swrast/s_context.c
+++ b/src/mesa/swrast/s_context.c
@@ -58,24 +58,21 @@ _swrast_update_rasterflags( struct gl_context *ctx )
    GLbitfield rasterMask = 0;
    GLuint i;
 
    if (ctx->Color.AlphaEnabled)           rasterMask |= ALPHATEST_BIT;
    if (ctx->Color.BlendEnabled)           rasterMask |= BLEND_BIT;
    if (ctx->Depth.Test)                   rasterMask |= DEPTH_BIT;
    if (swrast->_FogEnabled)               rasterMask |= FOG_BIT;
    if (ctx->Scissor.EnableFlags)          rasterMask |= CLIP_BIT;
    if (_mesa_stencil_is_enabled(ctx))     rasterMask |= STENCIL_BIT;
    for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
-      if (!ctx->Color.ColorMask[i][0] ||
-          !ctx->Color.ColorMask[i][1] ||
-          !ctx->Color.ColorMask[i][2] ||
-          !ctx->Color.ColorMask[i][3]) {
+      if (GET_COLORMASK(ctx->Color.ColorMask, i) != 0xf) {
          rasterMask |= MASKING_BIT;
          break;
       }
    }
    if (ctx->Color.ColorLogicOpEnabled) rasterMask |= LOGIC_OP_BIT;
    if (ctx->Texture._MaxEnabledTexImageUnit >= 0) rasterMask |= TEXTURE_BIT;
    if (   ctx->ViewportArray[0].X < 0
        || ctx->ViewportArray[0].X + ctx->ViewportArray[0].Width > (GLfloat) ctx->DrawBuffer->Width
        || ctx->ViewportArray[0].Y < 0
        || ctx->ViewportArray[0].Y + ctx->ViewportArray[0].Height > (GLfloat) ctx->DrawBuffer->Height) {
@@ -89,24 +86,21 @@ _swrast_update_rasterflags( struct gl_context *ctx )
    /* If we're not drawing to exactly one color buffer set the
     * MULTI_DRAW_BIT flag.  Also set it if we're drawing to no
     * buffers or the RGBA or CI mask disables all writes.
     */
    if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) {
       /* more than one color buffer designated for writing (or zero buffers) */
       rasterMask |= MULTI_DRAW_BIT;
    }
 
    for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
-      if (ctx->Color.ColorMask[i][0] +
-          ctx->Color.ColorMask[i][1] +
-          ctx->Color.ColorMask[i][2] +
-          ctx->Color.ColorMask[i][3] == 0) {
+      if (GET_COLORMASK(ctx->Color.ColorMask, i) == 0) {
          rasterMask |= MULTI_DRAW_BIT; /* all RGBA channels disabled */
          break;
       }
    }
 
 
    if (_swrast_use_fragment_program(ctx)) {
       rasterMask |= FRAGPROG_BIT;
    }
 
diff --git a/src/mesa/swrast/s_masking.c b/src/mesa/swrast/s_masking.c
index c10bf1a..8941375 100644
--- a/src/mesa/swrast/s_masking.c
+++ b/src/mesa/swrast/s_masking.c
@@ -49,53 +49,59 @@ _swrast_mask_rgba_span(struct gl_context *ctx, struct gl_renderbuffer *rb,
    assert(n < SWRAST_MAX_WIDTH);
    assert(span->arrayMask & SPAN_RGBA);
 
    rbPixels = _swrast_get_dest_rgba(ctx, rb, span);
 
    /*
     * Do component masking.
     * Note that we're not using span->array->mask[] here.  We could...
     */
    if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+      const GLubyte colormask[4] = {
+         GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 0) ? 0xff : 0,
+         GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 1) ? 0xff : 0,
+         GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 2) ? 0xff : 0,
+         GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 3) ? 0xff : 0,
+      };
       GLuint srcMask;
-      memcpy(&srcMask, ctx->Color.ColorMask[buf], sizeof(srcMask));
+      memcpy(&srcMask, colormask, sizeof(srcMask));
       const GLuint dstMask = ~srcMask;
       const GLuint *dst = (const GLuint *) rbPixels;
       GLuint *src = (GLuint *) span->array->rgba8;
       GLuint i;
       for (i = 0; i < n; i++) {
          src[i] = (src[i] & srcMask) | (dst[i] & dstMask);
       }
    }
    else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
       /* 2-byte components */
       /* XXX try to use 64-bit arithmetic someday */
-      const GLushort rMask = ctx->Color.ColorMask[buf][RCOMP] ? 0xffff : 0x0;
-      const GLushort gMask = ctx->Color.ColorMask[buf][GCOMP] ? 0xffff : 0x0;
-      const GLushort bMask = ctx->Color.ColorMask[buf][BCOMP] ? 0xffff : 0x0;
-      const GLushort aMask = ctx->Color.ColorMask[buf][ACOMP] ? 0xffff : 0x0;
+      const GLushort rMask = GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 0) ? 0xffff : 0x0;
+      const GLushort gMask = GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 1) ? 0xffff : 0x0;
+      const GLushort bMask = GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 2) ? 0xffff : 0x0;
+      const GLushort aMask = GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 3) ? 0xffff : 0x0;
       const GLushort (*dst)[4] = (const GLushort (*)[4]) rbPixels;
       GLushort (*src)[4] = span->array->rgba16;
       GLuint i;
       for (i = 0; i < n; i++) {
          src[i][RCOMP] = (src[i][RCOMP] & rMask) | (dst[i][RCOMP] & ~rMask);
          src[i][GCOMP] = (src[i][GCOMP] & gMask) | (dst[i][GCOMP] & ~gMask);
          src[i][BCOMP] = (src[i][BCOMP] & bMask) | (dst[i][BCOMP] & ~bMask);
          src[i][ACOMP] = (src[i][ACOMP] & aMask) | (dst[i][ACOMP] & ~aMask);
       }
    }
    else {
       /* 4-byte components */
-      const GLuint rMask = ctx->Color.ColorMask[buf][RCOMP] ? ~0x0 : 0x0;
-      const GLuint gMask = ctx->Color.ColorMask[buf][GCOMP] ? ~0x0 : 0x0;
-      const GLuint bMask = ctx->Color.ColorMask[buf][BCOMP] ? ~0x0 : 0x0;
-      const GLuint aMask = ctx->Color.ColorMask[buf][ACOMP] ? ~0x0 : 0x0;
+      const GLuint rMask = GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 0) ? ~0x0 : 0x0;
+      const GLuint gMask = GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 1) ? ~0x0 : 0x0;
+      const GLuint bMask = GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 2) ? ~0x0 : 0x0;
+      const GLuint aMask = GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 3) ? ~0x0 : 0x0;
       const GLuint (*dst)[4] = (const GLuint (*)[4]) rbPixels;
       GLuint (*src)[4] = (GLuint (*)[4]) span->array->attribs[VARYING_SLOT_COL0];
       GLuint i;
       for (i = 0; i < n; i++) {
          src[i][RCOMP] = (src[i][RCOMP] & rMask) | (dst[i][RCOMP] & ~rMask);
          src[i][GCOMP] = (src[i][GCOMP] & gMask) | (dst[i][GCOMP] & ~gMask);
          src[i][BCOMP] = (src[i][BCOMP] & bMask) | (dst[i][BCOMP] & ~bMask);
          src[i][ACOMP] = (src[i][ACOMP] & aMask) | (dst[i][ACOMP] & ~aMask);
       }
    }
diff --git a/src/mesa/swrast/s_span.c b/src/mesa/swrast/s_span.c
index 47a73e9..9bc1f22 100644
--- a/src/mesa/swrast/s_span.c
+++ b/src/mesa/swrast/s_span.c
@@ -1126,21 +1126,20 @@ _swrast_put_row(struct gl_context *ctx, struct gl_renderbuffer *rb,
  * Apply all the per-fragment operations to a span.
  * This now includes texturing (_swrast_write_texture_span() is history).
  * This function may modify any of the array values in the span.
  * span->interpMask and span->arrayMask may be changed but will be restored
  * to their original values before returning.
  */
 void
 _swrast_write_rgba_span( struct gl_context *ctx, SWspan *span)
 {
    const SWcontext *swrast = SWRAST_CONTEXT(ctx);
-   const GLuint *colorMask = (GLuint *) ctx->Color.ColorMask;
    const GLbitfield origInterpMask = span->interpMask;
    const GLbitfield origArrayMask = span->arrayMask;
    const GLbitfield64 origArrayAttribs = span->arrayAttribs;
    const GLenum origChanType = span->array->ChanType;
    void * const origRgba = span->array->rgba;
    const GLboolean shader = (_swrast_use_fragment_program(ctx)
                              || _mesa_ati_fragment_shader_enabled(ctx));
    const GLboolean shaderOrTexture = shader || ctx->Texture._EnabledCoordUnits;
    struct gl_framebuffer *fb = ctx->DrawBuffer;
 
@@ -1244,21 +1243,22 @@ _swrast_write_rgba_span( struct gl_context *ctx, SWspan *span)
       /* update count of 'passed' fragments */
       struct gl_query_object *q = ctx->Query.CurrentOcclusionObject;
       GLuint i;
       for (i = 0; i < span->end; i++)
          q->Result += span->array->mask[i];
    }
 
    /* We had to wait until now to check for glColorMask(0,0,0,0) because of
     * the occlusion test.
     */
-   if (fb->_NumColorDrawBuffers == 1 && colorMask[0] == 0x0) {
+   if (fb->_NumColorDrawBuffers == 1 &&
+       !GET_COLORMASK(ctx->Color.ColorMask, 0)) {
       /* no colors to write */
       goto end;
    }
 
    /* If we were able to defer fragment color computation to now, there's
     * a good chance that many fragments will have already been killed by
     * Z/stencil testing.
     */
    if (shaderOrTexture && swrast->_DeferredTexture) {
       shade_texture_span(ctx, span);
@@ -1361,21 +1361,21 @@ _swrast_write_rgba_span( struct gl_context *ctx, SWspan *span)
                    rb->_BaseFormat == GL_RG ||
 		   rb->_BaseFormat == GL_ALPHA);
 
             if (ctx->Color.ColorLogicOpEnabled) {
                _swrast_logicop_rgba_span(ctx, rb, span);
             }
             else if ((ctx->Color.BlendEnabled >> buf) & 1) {
                _swrast_blend_span(ctx, rb, span);
             }
 
-            if (colorMask[buf] != 0xffffffff) {
+            if (GET_COLORMASK(ctx->Color.ColorMask, buf) != 0xf) {
                _swrast_mask_rgba_span(ctx, rb, span, buf);
             }
 
             if (span->arrayMask & SPAN_XY) {
                /* array of pixel coords */
                put_values(ctx, rb,
                           span->array->ChanType, span->end,
                           span->array->x, span->array->y,
                           span->array->rgba, span->array->mask);
             }
diff --git a/src/mesa/swrast/s_triangle.c b/src/mesa/swrast/s_triangle.c
index a4113e5..c84cfec 100644
--- a/src/mesa/swrast/s_triangle.c
+++ b/src/mesa/swrast/s_triangle.c
@@ -1020,24 +1020,24 @@ _swrast_choose_triangle( struct gl_context *ctx )
       }
 
       /* special case for occlusion testing */
       if (ctx->Query.CurrentOcclusionObject &&
           ctx->Depth.Test &&
           ctx->Depth.Mask == GL_FALSE &&
           ctx->Depth.Func == GL_LESS &&
           !_mesa_stencil_is_enabled(ctx) &&
           depthRb &&
           depthRb->Format == MESA_FORMAT_Z_UNORM16) {
-         if (ctx->Color.ColorMask[0][0] == 0 &&
-	     ctx->Color.ColorMask[0][1] == 0 &&
-	     ctx->Color.ColorMask[0][2] == 0 &&
-	     ctx->Color.ColorMask[0][3] == 0) {
+         if (GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 0) == 0 &&
+	     GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 1) == 0 &&
+	     GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 2) == 0 &&
+	     GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 3) == 0) {
             USE(occlusion_zless_16_triangle);
             return;
          }
       }
 
       /*
        * XXX should examine swrast->_ActiveAttribMask to determine what
        * needs to be interpolated.
        */
       if (ctx->Texture._EnabledCoordUnits ||
-- 
2.7.4



More information about the mesa-dev mailing list