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 d4ccd28..ab301b9 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 b7b6eae..74cf66f 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);