Mesa (master): st/xa: Fix render to xa_format_a8, which is backed by a gallium L8 texture

Thomas Hellstrom thomash at kemper.freedesktop.org
Thu Jul 7 08:23:22 UTC 2011


Module: Mesa
Branch: master
Commit: 568d99cc6c8eea75ce50fe29e1ea8a94fe7ff7a7
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=568d99cc6c8eea75ce50fe29e1ea8a94fe7ff7a7

Author: Thomas Hellstrom <thellstrom at vmware.com>
Date:   Wed Jul  6 21:58:33 2011 +0200

st/xa: Fix render to xa_format_a8, which is backed by a gallium L8 texture

Signed-off-by: Thomas Hellstrom <thellstrom at vmware.com>

---

 src/gallium/state_trackers/xa/xa_composite.c |   74 ++++++++++++++++----------
 src/gallium/state_trackers/xa/xa_context.c   |    9 ++-
 src/gallium/state_trackers/xa/xa_priv.h      |   12 ++++
 src/gallium/state_trackers/xa/xa_renderer.c  |    8 +++-
 src/gallium/state_trackers/xa/xa_tgsi.c      |   22 ++++++--
 5 files changed, 87 insertions(+), 38 deletions(-)

diff --git a/src/gallium/state_trackers/xa/xa_composite.c b/src/gallium/state_trackers/xa/xa_composite.c
index 5389af6..cc29484 100644
--- a/src/gallium/state_trackers/xa/xa_composite.c
+++ b/src/gallium/state_trackers/xa/xa_composite.c
@@ -79,6 +79,25 @@ static const struct xa_composite_blend xa_blends[] = {
 };
 
 
+/*
+ * The alpha value stored in a luminance texture is read by the
+ * hardware as color.
+ */
+static unsigned
+xa_convert_blend_for_luminance(unsigned factor)
+{
+    switch(factor) {
+    case PIPE_BLENDFACTOR_DST_ALPHA:
+	return PIPE_BLENDFACTOR_DST_COLOR;
+    case PIPE_BLENDFACTOR_INV_DST_ALPHA:
+	return PIPE_BLENDFACTOR_INV_DST_COLOR;
+    default:
+	break;
+    }
+    return factor;
+}
+
+
 static boolean
 blend_for_op(struct xa_composite_blend *blend,
 	     enum xa_composite_op op,
@@ -104,15 +123,20 @@ blend_for_op(struct xa_composite_blend *blend,
 	}
     }
 
+    if (!dst_pic->srf)
+	return supported;
+
+    if (dst_pic->srf->tex->format == PIPE_FORMAT_L8_UNORM) {
+	blend->rgb_src = xa_convert_blend_for_luminance(blend->rgb_src);
+	blend->rgb_dst = xa_convert_blend_for_luminance(blend->rgb_dst);
+    }
 
     /*
      * If there's no dst alpha channel, adjust the blend op so that we'll treat
      * it as always 1.
      */
 
-    if (dst_pic &&
-	xa_format_a(dst_pic->pict_format) == 0 &&
-	blend->alpha_dst) {
+    if (xa_format_a(dst_pic->pict_format) == 0 && blend->alpha_dst) {
 	if (blend->rgb_src == PIPE_BLENDFACTOR_DST_ALPHA)
 	    blend->rgb_src = PIPE_BLENDFACTOR_ONE;
 	else if (blend->rgb_src == PIPE_BLENDFACTOR_INV_DST_ALPHA)
@@ -237,7 +261,6 @@ bind_composite_blend_state(struct xa_context *ctx,
 
 static unsigned int
 picture_format_fixups(struct xa_picture *src_pic,
-		      struct xa_picture *dst_pic,
 		      int mask)
 {
     boolean set_alpha = FALSE;
@@ -253,22 +276,17 @@ picture_format_fixups(struct xa_picture *src_pic,
     src_hw_format = xa_surface_format(src);
     src_pic_format = src_pic->pict_format;
 
-    if (!src || src_hw_format == src_pic_format) {
-	if (src_pic_format == xa_format_a8) {
-	    if (mask)
-		return FS_MASK_LUMINANCE;
-	    else if (dst_pic->pict_format != xa_format_a8) {
-
-		/*
-		 * if both dst and src are luminance then
-		 * we don't want to swizzle the alpha (X) of the
-		 * source into W component of the dst because
-		 * it will break our destination
-		 */
-		return FS_SRC_LUMINANCE;
-	    }
-	}
-	return 0;
+    set_alpha = (xa_format_type_is_color(src_pic_format) &&
+		 xa_format_a(src_pic_format) == 0);
+
+    if (set_alpha)
+	ret |= mask ? FS_MASK_SET_ALPHA : FS_SRC_SET_ALPHA;
+
+    if (src_hw_format == src_pic_format) {
+	if (src->tex->format == PIPE_FORMAT_L8_UNORM)
+	    return ((mask) ? FS_MASK_LUMINANCE : FS_SRC_LUMINANCE);
+
+	return ret;
     }
 
     src_hw_type = xa_format_type(src_hw_format);
@@ -280,13 +298,8 @@ picture_format_fixups(struct xa_picture *src_pic,
 		 src_pic_type == xa_type_argb)));
 
     if (!swizzle && (src_hw_type != src_pic_type))
-	return 0;
-
-    set_alpha = (xa_format_type_is_color(src_pic_format) &&
-		 xa_format_a(src_pic_type) == 0);
+      return ret;
 
-    if (set_alpha)
-	ret |= mask ? FS_MASK_SET_ALPHA : FS_SRC_SET_ALPHA;
     if (swizzle)
 	ret |= mask ? FS_MASK_SWIZZLE_RGB : FS_SRC_SWIZZLE_RGB;
 
@@ -300,7 +313,6 @@ bind_shaders(struct xa_context *ctx, const struct xa_composite *comp)
     struct xa_shader shader;
     struct xa_picture *src_pic = comp->src;
     struct xa_picture *mask_pic = comp->mask;
-    struct xa_picture *dst_pic = comp->dst;
 
     ctx->has_solid_color = FALSE;
 
@@ -321,7 +333,7 @@ bind_shaders(struct xa_context *ctx, const struct xa_composite *comp)
 	    vs_traits |= VS_COMPOSITE;
 	}
 
-	fs_traits |= picture_format_fixups(src_pic, dst_pic, 0);
+	fs_traits |= picture_format_fixups(src_pic, 0);
     }
 
     if (mask_pic) {
@@ -340,9 +352,12 @@ bind_shaders(struct xa_context *ctx, const struct xa_composite *comp)
 		fs_traits |= FS_CA_FULL;
 	}
 
-	fs_traits |= picture_format_fixups(mask_pic, dst_pic, 1);
+	fs_traits |= picture_format_fixups(mask_pic, 1);
     }
 
+    if (ctx->dst->srf->format == PIPE_FORMAT_L8_UNORM)
+	fs_traits |= FS_DST_LUMINANCE;
+
     shader = xa_shaders_get(ctx->shaders, vs_traits, fs_traits);
     cso_set_vertex_shader_handle(ctx->cso, shader.vs);
     cso_set_fragment_shader_handle(ctx->cso, shader.fs);
@@ -433,6 +448,7 @@ xa_composite_prepare(struct xa_context *ctx,
     if (ret != XA_ERR_NONE)
 	return ret;
 
+    ctx->dst = dst_srf;
     renderer_bind_destination(ctx, dst_srf->srf,
 			      dst_srf->srf->width,
 			      dst_srf->srf->height);
diff --git a/src/gallium/state_trackers/xa/xa_context.c b/src/gallium/state_trackers/xa/xa_context.c
index 3cc25ed..118a390 100644
--- a/src/gallium/state_trackers/xa/xa_context.c
+++ b/src/gallium/state_trackers/xa/xa_context.c
@@ -278,13 +278,16 @@ xa_solid_prepare(struct xa_context *ctx, struct xa_surface *dst,
     int width, height;
     int ret;
 
-    xa_pixel_to_float4(fg, ctx->solid_color);
-    ctx->has_solid_color = 1;
-
     ret = xa_surface_psurf_create(ctx, dst);
     if (ret != XA_ERR_NONE)
 	return ret;
 
+    if (dst->srf->format == PIPE_FORMAT_L8_UNORM)
+	xa_pixel_to_float4_a8(fg, ctx->solid_color);
+    else
+	xa_pixel_to_float4(fg, ctx->solid_color);
+    ctx->has_solid_color = 1;
+
     ctx->dst = dst;
     width = dst->srf->width;
     height = dst->srf->height;
diff --git a/src/gallium/state_trackers/xa/xa_priv.h b/src/gallium/state_trackers/xa/xa_priv.h
index 94627e1..e8f67a1 100644
--- a/src/gallium/state_trackers/xa/xa_priv.h
+++ b/src/gallium/state_trackers/xa/xa_priv.h
@@ -135,6 +135,7 @@ enum xa_fs_traits {
     FS_MASK_SET_ALPHA = 1 << 13,
     FS_SRC_LUMINANCE = 1 << 14,
     FS_MASK_LUMINANCE = 1 << 15,
+    FS_DST_LUMINANCE = 1 << 16,
 
     FS_FILL = (FS_SOLID_FILL | FS_LINGRAD_FILL | FS_RADGRAD_FILL),
     FS_COMPONENT_ALPHA = (FS_CA_FULL | FS_CA_SRCALPHA)
@@ -172,6 +173,17 @@ xa_pixel_to_float4(uint32_t pixel, float *color)
     color[3] = ((float)a) / 255.;
 }
 
+static INLINE void
+xa_pixel_to_float4_a8(uint32_t pixel, float *color)
+{
+    uint32_t a;
+
+    a = (pixel >> 24) & 0xff;
+    color[0] = ((float)a) / 255.;
+    color[1] = ((float)a) / 255.;
+    color[2] = ((float)a) / 255.;
+    color[3] = ((float)a) / 255.;
+}
 
 /*
  * xa_tgsi.c
diff --git a/src/gallium/state_trackers/xa/xa_renderer.c b/src/gallium/state_trackers/xa/xa_renderer.c
index 559b269..ef762f0 100644
--- a/src/gallium/state_trackers/xa/xa_renderer.c
+++ b/src/gallium/state_trackers/xa/xa_renderer.c
@@ -418,6 +418,7 @@ renderer_copy_prepare(struct xa_context *r,
     struct pipe_context *pipe = r->pipe;
     struct pipe_screen *screen = pipe->screen;
     struct xa_shader shader;
+    uint32_t fs_traits = FS_COMPOSITE;
 
     assert(screen->is_format_supported(screen, dst_surface->format,
 				       PIPE_TEXTURE_2D, 0,
@@ -469,7 +470,12 @@ renderer_copy_prepare(struct xa_context *r,
     }
 
     /* shaders */
-    shader = xa_shaders_get(r->shaders, VS_COMPOSITE, FS_COMPOSITE);
+    if (src_texture->format == PIPE_FORMAT_L8_UNORM)
+	fs_traits |= FS_SRC_LUMINANCE;
+    if (dst_surface->format == PIPE_FORMAT_L8_UNORM)
+	fs_traits |= FS_DST_LUMINANCE;
+
+    shader = xa_shaders_get(r->shaders, VS_COMPOSITE, fs_traits);
     cso_set_vertex_shader_handle(r->cso, shader.vs);
     cso_set_fragment_shader_handle(r->cso, shader.fs);
 
diff --git a/src/gallium/state_trackers/xa/xa_tgsi.c b/src/gallium/state_trackers/xa/xa_tgsi.c
index fb6ffef..ed1690e 100644
--- a/src/gallium/state_trackers/xa/xa_tgsi.c
+++ b/src/gallium/state_trackers/xa/xa_tgsi.c
@@ -85,6 +85,7 @@ print_fs_traits(int fs_traits)
 	"FS_MASK_SET_ALPHA",	/* = 1 << 13, */
 	"FS_SRC_LUMINANCE",	/* = 1 << 14, */
 	"FS_MASK_LUMINANCE",	/* = 1 << 15, */
+	"FS_DST_LUMINANCE",     /* = 1 << 15, */
     };
     int i, k;
 
@@ -454,6 +455,7 @@ create_fs(struct pipe_context *pipe, unsigned fs_traits)
     unsigned mask_set_alpha = (fs_traits & FS_MASK_SET_ALPHA) != 0;
     unsigned src_luminance = (fs_traits & FS_SRC_LUMINANCE) != 0;
     unsigned mask_luminance = (fs_traits & FS_MASK_LUMINANCE) != 0;
+    unsigned dst_luminance = (fs_traits & FS_DST_LUMINANCE) != 0;
 
 #if 0
     print_fs_traits(fs_traits);
@@ -508,7 +510,7 @@ create_fs(struct pipe_context *pipe, unsigned fs_traits)
 #endif
 
     if (is_composite) {
-	if (has_mask || src_luminance)
+	if (has_mask || src_luminance || dst_luminance)
 	    src = ureg_DECL_temporary(ureg);
 	else
 	    src = out;
@@ -516,14 +518,14 @@ create_fs(struct pipe_context *pipe, unsigned fs_traits)
 		    src_repeat_none, src_swizzle, src_set_alpha);
     } else if (is_fill) {
 	if (is_solid) {
-	    if (has_mask || src_luminance)
+	    if (has_mask || src_luminance || dst_luminance)
 		src = ureg_dst(src_input);
 	    else
 		ureg_MOV(ureg, out, src_input);
 	} else if (is_lingrad || is_radgrad) {
 	    struct ureg_src coords, const0124, matrow0, matrow1, matrow2;
 
-	    if (has_mask || src_luminance)
+	    if (has_mask || src_luminance || dst_luminance)
 		src = ureg_DECL_temporary(ureg);
 	    else
 		src = out;
@@ -550,7 +552,7 @@ create_fs(struct pipe_context *pipe, unsigned fs_traits)
 	ureg_MOV(ureg, src, ureg_scalar(ureg_src(src), TGSI_SWIZZLE_X));
 	ureg_MOV(ureg, ureg_writemask(src, TGSI_WRITEMASK_XYZ),
 		 ureg_scalar(imm0, TGSI_SWIZZLE_X));
-	if (!has_mask)
+	if (!has_mask && !dst_luminance)
 	    ureg_MOV(ureg, out, ureg_src(src));
     }
 
@@ -559,11 +561,21 @@ create_fs(struct pipe_context *pipe, unsigned fs_traits)
 	xrender_tex(ureg, mask, mask_pos, mask_sampler, imm0,
 		    mask_repeat_none, mask_swizzle, mask_set_alpha);
 	/* src IN mask */
-	src_in_mask(ureg, out, ureg_src(src), ureg_src(mask),
+
+	src_in_mask(ureg, (dst_luminance) ? src : out, ureg_src(src),
+		    ureg_src(mask),
 		    comp_alpha_mask, mask_luminance);
+
 	ureg_release_temporary(ureg, mask);
     }
 
+    if (dst_luminance) {
+	/*
+	 * Make sure the alpha channel goes into the output L8 surface.
+	 */
+	ureg_MOV(ureg, out, ureg_scalar(ureg_src(src), TGSI_SWIZZLE_W));
+    }
+
     ureg_END(ureg);
 
     return ureg_create_shader_and_destroy(ureg, pipe);




More information about the mesa-commit mailing list