i965: Fix handling of drawing to MESA_FORMAT_XRGB8888
authorIan Romanick <ian.d.romanick@intel.com>
Wed, 9 Dec 2009 05:13:05 +0000 (21:13 -0800)
committerIan Romanick <ian.d.romanick@intel.com>
Thu, 10 Dec 2009 23:12:30 +0000 (15:12 -0800)
It turns out that 965 and friends cannot actually render to an xRGB
surfaces.  Instead, the surface has to be RGBA with writes to alpha
disabled and the blend function modified to always use 1.0 for
destination alpha.

src/mesa/drivers/dri/i965/brw_cc.c
src/mesa/drivers/dri/i965/brw_wm_surface_state.c

index d4ccd28c9e85d6cd2ff564e0d4aa7a051f5ce115..ab301b9a3a07b6f87a0ec1565543d82b5ffe51fe 100644 (file)
@@ -34,6 +34,7 @@
 #include "brw_state.h"
 #include "brw_defines.h"
 #include "brw_util.h"
+#include "intel_fbo.h"
 #include "main/macros.h"
 #include "main/enums.h"
 
@@ -89,6 +90,28 @@ struct brw_cc_unit_key {
    GLenum depth_func;
 };
 
+/**
+ * Modify blend function to force destination alpha to 1.0
+ *
+ * If \c function specifies a blend function that uses destination alpha,
+ * replace it with a function that hard-wires destination alpha to 1.0.  This
+ * is used when rendering to xRGB targets.
+ */
+static GLenum
+fix_xRGB_alpha(GLenum function)
+{
+   switch (function) {
+   case GL_DST_ALPHA:
+      return GL_ONE;
+
+   case GL_ONE_MINUS_DST_ALPHA:
+   case GL_SRC_ALPHA_SATURATE:
+      return GL_ZERO;
+   }
+
+   return function;
+}
+
 static void
 cc_unit_populate_key(struct brw_context *brw, struct brw_cc_unit_key *key)
 {
@@ -132,6 +155,17 @@ cc_unit_populate_key(struct brw_context *brw, struct brw_cc_unit_key *key)
       key->blend_dst_rgb = ctx->Color.BlendDstRGB;
       key->blend_src_a = ctx->Color.BlendSrcA;
       key->blend_dst_a = ctx->Color.BlendDstA;
+
+      /* If the renderbuffer is XRGB, we have to frob the blend function to
+       * force the destination alpha to 1.0.  This means replacing GL_DST_ALPHA
+       * with GL_ONE and GL_ONE_MINUS_DST_ALPAH with GL_ZERO.
+       */
+      if (ctx->Visual.alphaBits == 0) {
+        key->blend_src_rgb = fix_xRGB_alpha(key->blend_src_rgb);
+        key->blend_src_a   = fix_xRGB_alpha(key->blend_src_a);
+        key->blend_dst_rgb = fix_xRGB_alpha(key->blend_dst_rgb);
+        key->blend_dst_a   = fix_xRGB_alpha(key->blend_dst_a);
+      }
    }
 
    key->alpha_enabled = ctx->Color.AlphaEnabled;
index b7b6eaec2bb842143042301a752eff694b6d2593..74cf66f9f8b85740e1f8af86705b871c99ccea13 100644 (file)
@@ -538,11 +538,15 @@ brw_update_renderbuffer_surface(struct brw_context *brw,
 
       key.surface_type = BRW_SURFACE_2D;
       switch (irb->Base.Format) {
+      /* XRGB and ARGB are treated the same here because the chips in this
+       * family cannot render to XRGB targets.  This means that we have to
+       * mask writes to alpha (ala glColorMask) and reconfigure the alpha
+       * blending hardware to use GL_ONE (or GL_ZERO) for cases where
+       * GL_DST_ALPHA (or GL_ONE_MINUS_DST_ALPHA) is used.
+       */
       case MESA_FORMAT_ARGB8888:
-        key.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
-        break;
       case MESA_FORMAT_XRGB8888:
-        key.surface_format = BRW_SURFACEFORMAT_B8G8R8X8_UNORM;
+        key.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
         break;
       case MESA_FORMAT_RGB565:
         key.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM;
@@ -579,6 +583,13 @@ brw_update_renderbuffer_surface(struct brw_context *brw,
    /* _NEW_COLOR */
    memcpy(key.color_mask, ctx->Color.ColorMask,
          sizeof(key.color_mask));
+
+   /* As mentioned above, disable writes to the alpha component when the
+    * renderbuffer is XRGB.
+    */
+   if (ctx->Visual.alphaBits == 0)
+     key.color_mask[3] = GL_FALSE;
+
    key.color_blend = (!ctx->Color._LogicOpEnabled &&
                      ctx->Color.BlendEnabled);