[Mesa-dev,1/4] xa: handle solid-fill src/mask

Submitted by Rob Clark on April 1, 2014, 3:04 p.m.

Details

Message ID 1396364670-31780-2-git-send-email-robdclark@gmail.com
State New
Headers show

Not browsing as part of any series.

Commit Message

Rob Clark April 1, 2014, 3:04 p.m.
From: Rob Clark <robclark@freedesktop.org>

Add support to property handle solid-fill src and/or mask.  Without this
we fallback to sw a lot for common things like text rendering.

Signed-off-by: Rob Clark <robclark@freedesktop.org>
---
 src/gallium/state_trackers/xa/xa_composite.c |  88 ++++----
 src/gallium/state_trackers/xa/xa_priv.h      |   7 +-
 src/gallium/state_trackers/xa/xa_renderer.c  | 289 ++++++++++++++++-----------
 src/gallium/state_trackers/xa/xa_tgsi.c      |  31 ++-
 4 files changed, 242 insertions(+), 173 deletions(-)

Patch hide | download patch | download mbox

diff --git a/src/gallium/state_trackers/xa/xa_composite.c b/src/gallium/state_trackers/xa/xa_composite.c
index abe5be2..f63cf49 100644
--- a/src/gallium/state_trackers/xa/xa_composite.c
+++ b/src/gallium/state_trackers/xa/xa_composite.c
@@ -111,12 +111,6 @@  blend_for_op(struct xa_composite_blend *blend,
     boolean supported = FALSE;
 
     /*
-     * Temporarily disable component alpha since it appears buggy.
-     */
-    if (mask_pic && mask_pic->component_alpha)
-	return FALSE;
-
-    /*
      * our default in case something goes wrong
      */
     *blend = xa_blends[XA_BLEND_OP_OVER];
@@ -125,6 +119,7 @@  blend_for_op(struct xa_composite_blend *blend,
 	if (xa_blends[i].op == op) {
 	    *blend = xa_blends[i];
 	    supported = TRUE;
+	    break;
 	}
     }
 
@@ -227,14 +222,6 @@  xa_composite_check_accelerated(const struct xa_composite *comp)
     if (src_pic->src_pict) {
 	if (src_pic->src_pict->type != xa_src_pict_solid_fill)
 	    return -XA_ERR_INVAL;
-
-	/*
-	 * Currently we don't support solid fill with a mask.
-	 * We can easily do that, but that would require shader,
-	 * sampler view setup and vertex setup modification.
-	 */
-	if (comp->mask)
-	    return -XA_ERR_INVAL;
     }
 
     if (blend_for_op(&blend, comp->op, comp->src, comp->mask, comp->dst)) {
@@ -322,6 +309,12 @@  picture_format_fixups(struct xa_picture *src_pic,
 }
 
 static int
+is_solid_fill(struct xa_picture *pic)
+{
+    return pic->src_pict && (pic->src_pict->type == xa_src_pict_solid_fill);
+}
+
+static int
 bind_shaders(struct xa_context *ctx, const struct xa_composite *comp)
 {
     unsigned vs_traits = 0, fs_traits = 0;
@@ -336,8 +329,8 @@  bind_shaders(struct xa_context *ctx, const struct xa_composite *comp)
 	    fs_traits |= FS_SRC_REPEAT_NONE;
 
 	if (src_pic->src_pict) {
-	    if (src_pic->src_pict->type == xa_src_pict_solid_fill) {
-		fs_traits |= FS_SOLID_FILL | FS_FILL;
+	    if (is_solid_fill(src_pic)) {
+		fs_traits |= FS_SOLID_FILL;
 		vs_traits |= VS_SOLID_FILL;
 		xa_pixel_to_float4(src_pic->src_pict->solid_fill.color,
 				   ctx->solid_color);
@@ -358,9 +351,17 @@  bind_shaders(struct xa_context *ctx, const struct xa_composite *comp)
 	    mask_pic->has_transform)
 	    fs_traits |= FS_MASK_REPEAT_NONE;
 
+	if (is_solid_fill(mask_pic)) {
+		fs_traits |= FS_SOLID_MASK;
+		vs_traits |= VS_SOLID_MASK;
+		xa_pixel_to_float4(mask_pic->src_pict->solid_fill.color,
+				   ctx->solid_mask);
+		ctx->has_solid_mask = TRUE;
+	}
+
 	if (mask_pic->component_alpha) {
 	    struct xa_composite_blend blend;
-	    if (!blend_for_op(&blend, comp->op, src_pic, mask_pic, NULL))
+	    if (!blend_for_op(&blend, comp->op, src_pic, mask_pic, comp->dst))
 		return -XA_ERR_INVAL;
 
 	    if (blend.alpha_src) {
@@ -399,7 +400,7 @@  bind_samplers(struct xa_context *ctx,
     memset(&mask_sampler, 0, sizeof(struct pipe_sampler_state));
 
     if (src_pic) {
-	if (ctx->has_solid_color) {
+	if (is_solid_fill(src_pic)) {
 	    samplers[0] = NULL;
 	    pipe_sampler_view_reference(&ctx->bound_sampler_views[0], NULL);
 	} else {
@@ -427,27 +428,31 @@  bind_samplers(struct xa_context *ctx,
     }
 
     if (mask_pic) {
-	unsigned mask_wrap = xa_repeat_to_gallium(mask_pic->wrap);
-	int filter;
-
-	(void) xa_filter_to_gallium(mask_pic->filter, &filter);
-
-	mask_sampler.wrap_s = mask_wrap;
-	mask_sampler.wrap_t = mask_wrap;
-	mask_sampler.min_img_filter = filter;
-	mask_sampler.mag_img_filter = filter;
-	src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
-	mask_sampler.normalized_coords = 1;
-	samplers[1] = &mask_sampler;
-	ctx->num_bound_samplers = 2;
-	u_sampler_view_default_template(&view_templ,
-					mask_pic->srf->tex,
-					mask_pic->srf->tex->format);
-	src_view = pipe->create_sampler_view(pipe, mask_pic->srf->tex,
-					     &view_templ);
-	pipe_sampler_view_reference(&ctx->bound_sampler_views[1], NULL);
-	ctx->bound_sampler_views[1] = src_view;
+	if (is_solid_fill(mask_pic)) {
+	    samplers[1] = NULL;
+	    pipe_sampler_view_reference(&ctx->bound_sampler_views[1], NULL);
+	} else {
+	    unsigned mask_wrap = xa_repeat_to_gallium(mask_pic->wrap);
+	    int filter;
+
+	    (void) xa_filter_to_gallium(mask_pic->filter, &filter);
 
+	    mask_sampler.wrap_s = mask_wrap;
+	    mask_sampler.wrap_t = mask_wrap;
+	    mask_sampler.min_img_filter = filter;
+	    mask_sampler.mag_img_filter = filter;
+	    src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
+	    mask_sampler.normalized_coords = 1;
+	    samplers[1] = &mask_sampler;
+	    ctx->num_bound_samplers = 2;
+	    u_sampler_view_default_template(&view_templ,
+					    mask_pic->srf->tex,
+					    mask_pic->srf->tex->format);
+	    src_view = pipe->create_sampler_view(pipe, mask_pic->srf->tex,
+		    &view_templ);
+	    pipe_sampler_view_reference(&ctx->bound_sampler_views[1], NULL);
+	    ctx->bound_sampler_views[1] = src_view;
+	}
 
 	/*
 	 * If src is a solid color, we have no src view, so set up a
@@ -488,10 +493,10 @@  xa_composite_prepare(struct xa_context *ctx,
 	return ret;
     bind_samplers(ctx, comp);
 
-    if (ctx->num_bound_samplers == 0 ) { /* solid fill */
+    if (ctx->num_bound_samplers == 0 && !ctx->has_solid_mask) { /* solid fill */
 	renderer_begin_solid(ctx);
     } else {
-	renderer_begin_textures(ctx);
+	renderer_begin_textures(ctx, comp);
 	ctx->comp = comp;
     }
 
@@ -504,7 +509,7 @@  xa_composite_rect(struct xa_context *ctx,
 		  int srcX, int srcY, int maskX, int maskY,
 		  int dstX, int dstY, int width, int height)
 {
-    if (ctx->num_bound_samplers == 0 ) { /* solid fill */
+    if ((ctx->num_bound_samplers == 0) && !ctx->has_solid_mask) { /* solid fill */
 	renderer_solid(ctx, dstX, dstY, dstX + width, dstY + height,
 		       ctx->solid_color);
     } else {
@@ -530,6 +535,7 @@  xa_composite_done(struct xa_context *ctx)
 
     ctx->comp = NULL;
     ctx->has_solid_color = FALSE;
+    ctx->has_solid_mask = FALSE;
     xa_ctx_sampler_views_destroy(ctx);
 }
 
diff --git a/src/gallium/state_trackers/xa/xa_priv.h b/src/gallium/state_trackers/xa/xa_priv.h
index b99c214..348a98e 100644
--- a/src/gallium/state_trackers/xa/xa_priv.h
+++ b/src/gallium/state_trackers/xa/xa_priv.h
@@ -110,6 +110,9 @@  struct xa_context {
     int has_solid_color;
     float solid_color[4];
 
+    int has_solid_mask;
+    float solid_mask[4];
+
     unsigned int num_bound_samplers;
     struct pipe_sampler_view *bound_sampler_views[XA_MAX_SAMPLERS];
     const struct xa_composite *comp;
@@ -122,6 +125,7 @@  enum xa_vs_traits {
     VS_LINGRAD_FILL = 1 << 3,
     VS_RADGRAD_FILL = 1 << 4,
     VS_YUV = 1 << 5,
+    VS_SOLID_MASK = 1 << 6,
 
     VS_FILL = (VS_SOLID_FILL | VS_LINGRAD_FILL | VS_RADGRAD_FILL)
 };
@@ -144,6 +148,7 @@  enum xa_fs_traits {
     FS_SRC_LUMINANCE = 1 << 14,
     FS_MASK_LUMINANCE = 1 << 15,
     FS_DST_LUMINANCE = 1 << 16,
+    FS_SOLID_MASK = 1 << 17,
 
     FS_FILL = (FS_SOLID_FILL | FS_LINGRAD_FILL | FS_RADGRAD_FILL),
     FS_COMPONENT_ALPHA = (FS_CA_FULL | FS_CA_SRCALPHA)
@@ -258,7 +263,7 @@  void renderer_begin_solid(struct xa_context *r);
 void renderer_solid(struct xa_context *r,
 		    int x0, int y0, int x1, int y1, float *color);
 void
-renderer_begin_textures(struct xa_context *r);
+renderer_begin_textures(struct xa_context *r, const struct xa_composite *comp);
 
 void
 renderer_texture(struct xa_context *r,
diff --git a/src/gallium/state_trackers/xa/xa_renderer.c b/src/gallium/state_trackers/xa/xa_renderer.c
index 9ba78be..056648a 100644
--- a/src/gallium/state_trackers/xa/xa_renderer.c
+++ b/src/gallium/state_trackers/xa/xa_renderer.c
@@ -124,7 +124,7 @@  renderer_init_state(struct xa_context *r)
 }
 
 static INLINE void
-add_vertex_color(struct xa_context *r, float x, float y, float color[4])
+add_vertex_coord(struct xa_context *r, float x, float y)
 {
     float *vertex = r->buffer + r->buffer_size;
 
@@ -133,98 +133,84 @@  add_vertex_color(struct xa_context *r, float x, float y, float color[4])
     vertex[2] = 0.f;		/*z */
     vertex[3] = 1.f;		/*w */
 
-    vertex[4] = color[0];	/*r */
-    vertex[5] = color[1];	/*g */
-    vertex[6] = color[2];	/*b */
-    vertex[7] = color[3];	/*a */
-
-    r->buffer_size += 8;
-}
-
-static INLINE void
-add_vertex_1tex(struct xa_context *r, float x, float y, float s, float t)
-{
-    float *vertex = r->buffer + r->buffer_size;
-
-    vertex[0] = x;
-    vertex[1] = y;
-    vertex[2] = 0.f;		/*z */
-    vertex[3] = 1.f;		/*w */
-
-    vertex[4] = s;		/*s */
-    vertex[5] = t;		/*t */
-    vertex[6] = 0.f;		/*r */
-    vertex[7] = 1.f;		/*q */
-
-    r->buffer_size += 8;
+    r->buffer_size += 4;
 }
 
 static INLINE void
-add_vertex_2tex(struct xa_context *r,
-		float x, float y, float s0, float t0, float s1, float t1)
+add_vertex_color(struct xa_context *r, const float *color)
 {
     float *vertex = r->buffer + r->buffer_size;
 
-    vertex[0] = x;
-    vertex[1] = y;
-    vertex[2] = 0.f;		/*z */
-    vertex[3] = 1.f;		/*w */
-
-    vertex[4] = s0;		/*s */
-    vertex[5] = t0;		/*t */
-    vertex[6] = 0.f;		/*r */
-    vertex[7] = 1.f;		/*q */
+    vertex[0] = color[0];	/*r */
+    vertex[1] = color[1];	/*g */
+    vertex[2] = color[2];	/*b */
+    vertex[3] = color[3];	/*a */
 
-    vertex[8] = s1;		/*s */
-    vertex[9] = t1;		/*t */
-    vertex[10] = 0.f;		/*r */
-    vertex[11] = 1.f;		/*q */
-
-    r->buffer_size += 12;
+    r->buffer_size += 4;
 }
 
 static void
 add_vertex_data1(struct xa_context *r,
                  float srcX, float srcY,  float dstX, float dstY,
                  float width, float height,
-                 struct pipe_resource *src, const float *src_matrix)
+                 struct pipe_resource *src, const float *src_matrix,
+                 const float *src_color)
 {
     float s0, t0, s1, t1, s2, t2, s3, t3;
-    float pt0[2], pt1[2], pt2[2], pt3[2];
-
-    pt0[0] = srcX;
-    pt0[1] = srcY;
-    pt1[0] = (srcX + width);
-    pt1[1] = srcY;
-    pt2[0] = (srcX + width);
-    pt2[1] = (srcY + height);
-    pt3[0] = srcX;
-    pt3[1] = (srcY + height);
 
-    if (src_matrix) {
-	map_point((float *)src_matrix, pt0[0], pt0[1], &pt0[0], &pt0[1]);
-	map_point((float *)src_matrix, pt1[0], pt1[1], &pt1[0], &pt1[1]);
-	map_point((float *)src_matrix, pt2[0], pt2[1], &pt2[0], &pt2[1]);
-	map_point((float *)src_matrix, pt3[0], pt3[1], &pt3[0], &pt3[1]);
+    if (!src_color) {
+	float pt0[2], pt1[2], pt2[2], pt3[2];
+
+	pt0[0] = srcX;
+	pt0[1] = srcY;
+	pt1[0] = (srcX + width);
+	pt1[1] = srcY;
+	pt2[0] = (srcX + width);
+	pt2[1] = (srcY + height);
+	pt3[0] = srcX;
+	pt3[1] = (srcY + height);
+
+	if (src_matrix) {
+	    map_point((float *)src_matrix, pt0[0], pt0[1], &pt0[0], &pt0[1]);
+	    map_point((float *)src_matrix, pt1[0], pt1[1], &pt1[0], &pt1[1]);
+	    map_point((float *)src_matrix, pt2[0], pt2[1], &pt2[0], &pt2[1]);
+	    map_point((float *)src_matrix, pt3[0], pt3[1], &pt3[0], &pt3[1]);
+	}
+
+	s0 =  pt0[0] / src->width0;
+	s1 =  pt1[0] / src->width0;
+	s2 =  pt2[0] / src->width0;
+	s3 =  pt3[0] / src->width0;
+	t0 =  pt0[1] / src->height0;
+	t1 =  pt1[1] / src->height0;
+	t2 =  pt2[1] / src->height0;
+	t3 =  pt3[1] / src->height0;
     }
 
-    s0 =  pt0[0] / src->width0;
-    s1 =  pt1[0] / src->width0;
-    s2 =  pt2[0] / src->width0;
-    s3 =  pt3[0] / src->width0;
-    t0 =  pt0[1] / src->height0;
-    t1 =  pt1[1] / src->height0;
-    t2 =  pt2[1] / src->height0;
-    t3 =  pt3[1] / src->height0;
-
     /* 1st vertex */
-    add_vertex_1tex(r, dstX, dstY, s0, t0);
+    add_vertex_coord(r, dstX, dstY);
+    if (src_color)
+	add_vertex_color(r, src_color);
+    else
+	add_vertex_coord(r, s0, t0);
     /* 2nd vertex */
-    add_vertex_1tex(r, dstX + width, dstY, s1, t1);
+    add_vertex_coord(r, dstX + width, dstY);
+    if (src_color)
+	add_vertex_color(r, src_color);
+    else
+	add_vertex_coord(r, s1, t1);
     /* 3rd vertex */
-    add_vertex_1tex(r, dstX + width, dstY + height, s2, t2);
+    add_vertex_coord(r, dstX + width, dstY + height);
+    if (src_color)
+	add_vertex_color(r, src_color);
+    else
+	add_vertex_coord(r, s2, t2);
     /* 4th vertex */
-    add_vertex_1tex(r, dstX, dstY + height, s3, t3);
+    add_vertex_coord(r, dstX, dstY + height);
+    if (src_color)
+	add_vertex_color(r, src_color);
+    else
+	add_vertex_coord(r, s3, t3);
 }
 
 static void
@@ -233,55 +219,91 @@  add_vertex_data2(struct xa_context *r,
                  float dstX, float dstY, float width, float height,
                  struct pipe_resource *src,
                  struct pipe_resource *mask,
-                 const float *src_matrix, const float *mask_matrix)
+                 const float *src_matrix, const float *src_color,
+                 const float *mask_matrix, const float *mask_color)
 {
     float src_s0, src_t0, src_s1, src_t1;
     float mask_s0, mask_t0, mask_s1, mask_t1;
-    float spt0[2], spt1[2];
-    float mpt0[2], mpt1[2];
 
-    spt0[0] = srcX;
-    spt0[1] = srcY;
-    spt1[0] = srcX + width;
-    spt1[1] = srcY + height;
 
-    mpt0[0] = maskX;
-    mpt0[1] = maskY;
-    mpt1[0] = maskX + width;
-    mpt1[1] = maskY + height;
+    if (!src_color) {
+	float spt0[2], spt1[2];
 
-    if (src_matrix) {
-	map_point((float *)src_matrix, spt0[0], spt0[1], &spt0[0], &spt0[1]);
-	map_point((float *)src_matrix, spt1[0], spt1[1], &spt1[0], &spt1[1]);
-    }
+	spt0[0] = srcX;
+	spt0[1] = srcY;
+	spt1[0] = srcX + width;
+	spt1[1] = srcY + height;
 
-    if (mask_matrix) {
-	map_point((float *)mask_matrix, mpt0[0], mpt0[1], &mpt0[0], &mpt0[1]);
-	map_point((float *)mask_matrix, mpt1[0], mpt1[1], &mpt1[0], &mpt1[1]);
+	if (src_matrix) {
+	    map_point((float *)src_matrix, spt0[0], spt0[1], &spt0[0], &spt0[1]);
+	    map_point((float *)src_matrix, spt1[0], spt1[1], &spt1[0], &spt1[1]);
+	}
+
+	src_s0 = spt0[0] / src->width0;
+	src_t0 = spt0[1] / src->height0;
+	src_s1 = spt1[0] / src->width0;
+	src_t1 = spt1[1] / src->height0;
     }
 
-    src_s0 = spt0[0] / src->width0;
-    src_t0 = spt0[1] / src->height0;
-    src_s1 = spt1[0] / src->width0;
-    src_t1 = spt1[1] / src->height0;
+    if (!mask_color) {
+	float mpt0[2], mpt1[2];
+
+	mpt0[0] = maskX;
+	mpt0[1] = maskY;
+	mpt1[0] = maskX + width;
+	mpt1[1] = maskY + height;
 
-    mask_s0 = mpt0[0] / mask->width0;
-    mask_t0 = mpt0[1] / mask->height0;
-    mask_s1 = mpt1[0] / mask->width0;
-    mask_t1 = mpt1[1] / mask->height0;
+	if (mask_matrix) {
+	    map_point((float *)mask_matrix, mpt0[0], mpt0[1], &mpt0[0], &mpt0[1]);
+	    map_point((float *)mask_matrix, mpt1[0], mpt1[1], &mpt1[0], &mpt1[1]);
+	}
+
+	mask_s0 = mpt0[0] / mask->width0;
+	mask_t0 = mpt0[1] / mask->height0;
+	mask_s1 = mpt1[0] / mask->width0;
+	mask_t1 = mpt1[1] / mask->height0;
+    }
 
     /* 1st vertex */
-    add_vertex_2tex(r, dstX, dstY,
-		    src_s0, src_t0, mask_s0, mask_t0);
+    add_vertex_coord(r, dstX, dstY);
+    if (src_color)
+	add_vertex_color(r, src_color);
+    else
+	add_vertex_coord(r, src_s0, src_t0);
+    if (mask_color)
+	add_vertex_color(r, mask_color);
+    else
+	add_vertex_coord(r, mask_s0, mask_t0);
     /* 2nd vertex */
-    add_vertex_2tex(r, dstX + width, dstY,
-		    src_s1, src_t0, mask_s1, mask_t0);
+    add_vertex_coord(r, dstX + width, dstY);
+    if (src_color)
+	add_vertex_color(r, src_color);
+    else
+	add_vertex_coord(r, src_s1, src_t0);
+    if (mask_color)
+	add_vertex_color(r, mask_color);
+    else
+	add_vertex_coord(r, mask_s1, mask_t0);
     /* 3rd vertex */
-    add_vertex_2tex(r, dstX + width, dstY + height,
-		    src_s1, src_t1, mask_s1, mask_t1);
+    add_vertex_coord(r, dstX + width, dstY + height);
+    if (src_color)
+	add_vertex_color(r, src_color);
+    else
+	add_vertex_coord(r, src_s1, src_t1);
+    if (mask_color)
+	add_vertex_color(r, mask_color);
+    else
+	add_vertex_coord(r, mask_s1, mask_t1);
     /* 4th vertex */
-    add_vertex_2tex(r, dstX, dstY + height,
-		    src_s0, src_t1, mask_s0, mask_t1);
+    add_vertex_coord(r, dstX, dstY + height);
+    if (src_color)
+	add_vertex_color(r, src_color);
+    else
+	add_vertex_coord(r, src_s0, src_t1);
+    if (mask_color)
+	add_vertex_color(r, mask_color);
+    else
+	add_vertex_coord(r, mask_s0, mask_t1);
 }
 
 static void
@@ -310,13 +332,17 @@  setup_vertex_data_yuv(struct xa_context *r,
     t1 = spt1[1] / tex->height0;
 
     /* 1st vertex */
-    add_vertex_1tex(r, dstX, dstY, s0, t0);
+    add_vertex_coord(r, dstX, dstY);
+    add_vertex_coord(r, s0, t0);
     /* 2nd vertex */
-    add_vertex_1tex(r, dstX + dstW, dstY, s1, t0);
+    add_vertex_coord(r, dstX + dstW, dstY);
+    add_vertex_coord(r, s1, t0);
     /* 3rd vertex */
-    add_vertex_1tex(r, dstX + dstW, dstY + dstH, s1, t1);
+    add_vertex_coord(r, dstX + dstW, dstY + dstH);
+    add_vertex_coord(r, s1, t1);
     /* 4th vertex */
-    add_vertex_1tex(r, dstX, dstY + dstH, s0, t1);
+    add_vertex_coord(r, dstX, dstY + dstH);
+    add_vertex_coord(r, s0, t1);
 }
 
 /* Set up framebuffer, viewport and vertex shader constant buffer
@@ -493,10 +519,14 @@  renderer_copy(struct xa_context *r,
 
     /* draw quad */
     renderer_draw_conditional(r, 4 * 8);
-    add_vertex_1tex(r, x0, y0, s0, t0);
-    add_vertex_1tex(r, x1, y0, s1, t0);
-    add_vertex_1tex(r, x1, y1, s1, t1);
-    add_vertex_1tex(r, x0, y1, s0, t1);
+    add_vertex_coord(r, x0, y0);
+    add_vertex_coord(r, s0, t0);
+    add_vertex_coord(r, x1, y0);
+    add_vertex_coord(r, s1, t0);
+    add_vertex_coord(r, x1, y1);
+    add_vertex_coord(r, s1, t1);
+    add_vertex_coord(r, x0, y1);
+    add_vertex_coord(r, s0, t1);
 }
 
 void
@@ -539,13 +569,17 @@  renderer_solid(struct xa_context *r,
     renderer_draw_conditional(r, 4 * 8);
 
     /* 1st vertex */
-    add_vertex_color(r, x0, y0, color);
+    add_vertex_coord(r, x0, y0);
+    add_vertex_color(r, color);
     /* 2nd vertex */
-    add_vertex_color(r, x1, y0, color);
+    add_vertex_coord(r, x1, y0);
+    add_vertex_color(r, color);
     /* 3rd vertex */
-    add_vertex_color(r, x1, y1, color);
+    add_vertex_coord(r, x1, y1);
+    add_vertex_color(r, color);
     /* 4th vertex */
-    add_vertex_color(r, x0, y1, color);
+    add_vertex_coord(r, x0, y1);
+    add_vertex_color(r, color);
 }
 
 void
@@ -555,9 +589,14 @@  renderer_draw_flush(struct xa_context *r)
 }
 
 void
-renderer_begin_textures(struct xa_context *r)
+renderer_begin_textures(struct xa_context *r,
+	const struct xa_composite *comp)
 {
-    r->attrs_per_vertex = 1 + r->num_bound_samplers;
+    r->attrs_per_vertex = 1;
+    if (comp->src)
+	r->attrs_per_vertex++;
+    if (comp->mask)
+	r->attrs_per_vertex++;
     r->buffer_size = 0;
 }
 
@@ -592,7 +631,9 @@  renderer_texture(struct xa_context *r,
 			 pos[0], pos[1], /* src */
 			 pos[4], pos[5], /* dst */
 			 width, height,
-			 sampler_view[0]->texture, src_matrix);
+			 sampler_view[0]->texture,
+			 r->has_solid_color ? NULL : src_matrix,
+			 r->has_solid_color ? r->solid_color : NULL);
 	break;
     case 3:
 	renderer_draw_conditional(r, 4 * 12);
@@ -601,8 +642,12 @@  renderer_texture(struct xa_context *r,
 			 pos[2], pos[3], /* mask */
 			 pos[4], pos[5], /* dst */
 			 width, height,
-			 sampler_view[0]->texture, sampler_view[1]->texture,
-			 src_matrix, mask_matrix);
+			 r->has_solid_color ? NULL : sampler_view[0]->texture,
+			 r->has_solid_mask ? NULL : sampler_view[1]->texture,
+			 r->has_solid_color ? NULL : src_matrix,
+			 r->has_solid_color ? r->solid_color : NULL,
+			 r->has_solid_mask ? NULL : mask_matrix,
+			 r->has_solid_mask ? r->solid_mask : NULL);
 	break;
     default:
 	break;
diff --git a/src/gallium/state_trackers/xa/xa_tgsi.c b/src/gallium/state_trackers/xa/xa_tgsi.c
index c7454c9..9cda4c3 100644
--- a/src/gallium/state_trackers/xa/xa_tgsi.c
+++ b/src/gallium/state_trackers/xa/xa_tgsi.c
@@ -42,14 +42,14 @@ 
 /* Vertex shader:
  * IN[0]    = vertex pos
  * IN[1]    = src tex coord | solid fill color
- * IN[2]    = mask tex coord
+ * IN[2]    = mask tex coord | solid mask color
  * IN[3]    = dst tex coord
  * CONST[0] = (2/dst_width, 2/dst_height, 1, 1)
  * CONST[1] = (-1, -1, 0, 0)
  *
  * OUT[0]   = vertex pos
  * OUT[1]   = src tex coord | solid fill color
- * OUT[2]   = mask tex coord
+ * OUT[2]   = mask tex coord | solid mask color
  * OUT[3]   = dst tex coord
  */
 
@@ -58,7 +58,7 @@ 
  * SAMP[1]  = mask
  * SAMP[2]  = dst
  * IN[0]    = pos src | solid fill color
- * IN[1]    = pos mask
+ * IN[1]    = pos mask | solid mask color
  * IN[2]    = pos dst
  * CONST[0] = (0, 0, 0, 1)
  *
@@ -268,6 +268,7 @@  create_vs(struct pipe_context *pipe, unsigned vs_traits)
     boolean is_fill = (vs_traits & VS_FILL) != 0;
     boolean is_composite = (vs_traits & VS_COMPOSITE) != 0;
     boolean has_mask = (vs_traits & VS_MASK) != 0;
+    boolean is_solid_mask = (vs_traits & VS_SOLID_MASK) != 0;
     boolean is_yuv = (vs_traits & VS_YUV) != 0;
     unsigned input_slot = 0;
 
@@ -296,15 +297,17 @@  create_vs(struct pipe_context *pipe, unsigned vs_traits)
 	src = ureg_DECL_vs_input(ureg, input_slot++);
 	dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 0);
 	ureg_MOV(ureg, dst, src);
-    }
-
-    if (is_fill) {
+    } else if (is_fill) {
 	src = ureg_DECL_vs_input(ureg, input_slot++);
 	dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
 	ureg_MOV(ureg, dst, src);
     }
 
-    if (has_mask) {
+    if (is_solid_mask) {
+	src = ureg_DECL_vs_input(ureg, input_slot++);
+	dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 1);
+	ureg_MOV(ureg, dst, src);
+    } else if (has_mask) {
 	src = ureg_DECL_vs_input(ureg, input_slot++);
 	dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 1);
 	ureg_MOV(ureg, dst, src);
@@ -436,6 +439,7 @@  create_fs(struct pipe_context *pipe, unsigned fs_traits)
     struct ureg_dst out;
     struct ureg_src imm0 = { 0 };
     unsigned has_mask = (fs_traits & FS_MASK) != 0;
+    unsigned is_solid_mask = (fs_traits & FS_SOLID_MASK) != 0;
     unsigned is_fill = (fs_traits & FS_FILL) != 0;
     unsigned is_composite = (fs_traits & FS_COMPOSITE) != 0;
     unsigned is_solid = (fs_traits & FS_SOLID_FILL) != 0;
@@ -492,7 +496,11 @@  create_fs(struct pipe_context *pipe, unsigned fs_traits)
 	return create_yuv_shader(pipe, ureg);
     }
 
-    if (has_mask) {
+    if (is_solid_mask) {
+	mask_pos = ureg_DECL_fs_input(ureg,
+				       TGSI_SEMANTIC_COLOR, 1,
+				       TGSI_INTERPOLATE_PERSPECTIVE);
+    } else if (has_mask) {
 	mask_sampler = ureg_DECL_sampler(ureg, 1);
 	mask_pos = ureg_DECL_fs_input(ureg,
 				      TGSI_SEMANTIC_GENERIC, 1,
@@ -552,10 +560,15 @@  create_fs(struct pipe_context *pipe, unsigned fs_traits)
 	    ureg_MOV(ureg, out, ureg_src(src));
     }
 
-    if (has_mask) {
+    if (is_solid_mask) {
+	mask = ureg_dst(mask_pos);
+    } else if (has_mask) {
 	mask = ureg_DECL_temporary(ureg);
 	xrender_tex(ureg, mask, mask_pos, mask_sampler, imm0,
 		    mask_repeat_none, mask_swizzle, mask_set_alpha);
+    }
+
+    if (has_mask) {
 	/* src IN mask */
 
 	src_in_mask(ureg, (dst_luminance) ? src : out, ureg_src(src),

Comments

On 04/01/2014 05:04 PM, Rob Clark wrote:
> From: Rob Clark <robclark@freedesktop.org>
>
> Add support to property handle solid-fill src and/or mask.  Without this
> we fallback to sw a lot for common things like text rendering.
>
> Signed-off-by: Rob Clark <robclark@freedesktop.org>
> ---
>  src/gallium/state_trackers/xa/xa_composite.c |  88 ++++----
>  src/gallium/state_trackers/xa/xa_priv.h      |   7 +-
>  src/gallium/state_trackers/xa/xa_renderer.c  | 289 ++++++++++++++++-----------
>  src/gallium/state_trackers/xa/xa_tgsi.c      |  31 ++-
>  4 files changed, 242 insertions(+), 173 deletions(-)

Rob,
While testing this patch it looks like we sometimes set two samplers,
and the first one is NULL.
The SVGA driver asserts on that condition.
We might need to move the active sampler to the first entry in that
case, and adjust tex coords and shader accordingly.

I'll discuss with BrianP.

/Thomas

> diff --git a/src/gallium/state_trackers/xa/xa_composite.c b/src/gallium/state_trackers/xa/xa_composite.c
> index abe5be2..f63cf49 100644
> --- a/src/gallium/state_trackers/xa/xa_composite.c
> +++ b/src/gallium/state_trackers/xa/xa_composite.c
> @@ -111,12 +111,6 @@ blend_for_op(struct xa_composite_blend *blend,
>      boolean supported = FALSE;
>  
>      /*
> -     * Temporarily disable component alpha since it appears buggy.
> -     */
> -    if (mask_pic && mask_pic->component_alpha)
> -	return FALSE;
> -
> -    /*
>       * our default in case something goes wrong
>       */
>      *blend = xa_blends[XA_BLEND_OP_OVER];
> @@ -125,6 +119,7 @@ blend_for_op(struct xa_composite_blend *blend,
>  	if (xa_blends[i].op == op) {
>  	    *blend = xa_blends[i];
>  	    supported = TRUE;
> +	    break;
>  	}
>      }
>  
> @@ -227,14 +222,6 @@ xa_composite_check_accelerated(const struct xa_composite *comp)
>      if (src_pic->src_pict) {
>  	if (src_pic->src_pict->type != xa_src_pict_solid_fill)
>  	    return -XA_ERR_INVAL;
> -
> -	/*
> -	 * Currently we don't support solid fill with a mask.
> -	 * We can easily do that, but that would require shader,
> -	 * sampler view setup and vertex setup modification.
> -	 */
> -	if (comp->mask)
> -	    return -XA_ERR_INVAL;
>      }
>  
>      if (blend_for_op(&blend, comp->op, comp->src, comp->mask, comp->dst)) {
> @@ -322,6 +309,12 @@ picture_format_fixups(struct xa_picture *src_pic,
>  }
>  
>  static int
> +is_solid_fill(struct xa_picture *pic)
> +{
> +    return pic->src_pict && (pic->src_pict->type == xa_src_pict_solid_fill);
> +}
> +
> +static int
>  bind_shaders(struct xa_context *ctx, const struct xa_composite *comp)
>  {
>      unsigned vs_traits = 0, fs_traits = 0;
> @@ -336,8 +329,8 @@ bind_shaders(struct xa_context *ctx, const struct xa_composite *comp)
>  	    fs_traits |= FS_SRC_REPEAT_NONE;
>  
>  	if (src_pic->src_pict) {
> -	    if (src_pic->src_pict->type == xa_src_pict_solid_fill) {
> -		fs_traits |= FS_SOLID_FILL | FS_FILL;
> +	    if (is_solid_fill(src_pic)) {
> +		fs_traits |= FS_SOLID_FILL;
>  		vs_traits |= VS_SOLID_FILL;
>  		xa_pixel_to_float4(src_pic->src_pict->solid_fill.color,
>  				   ctx->solid_color);
> @@ -358,9 +351,17 @@ bind_shaders(struct xa_context *ctx, const struct xa_composite *comp)
>  	    mask_pic->has_transform)
>  	    fs_traits |= FS_MASK_REPEAT_NONE;
>  
> +	if (is_solid_fill(mask_pic)) {
> +		fs_traits |= FS_SOLID_MASK;
> +		vs_traits |= VS_SOLID_MASK;
> +		xa_pixel_to_float4(mask_pic->src_pict->solid_fill.color,
> +				   ctx->solid_mask);
> +		ctx->has_solid_mask = TRUE;
> +	}
> +
>  	if (mask_pic->component_alpha) {
>  	    struct xa_composite_blend blend;
> -	    if (!blend_for_op(&blend, comp->op, src_pic, mask_pic, NULL))
> +	    if (!blend_for_op(&blend, comp->op, src_pic, mask_pic, comp->dst))
>  		return -XA_ERR_INVAL;
>  
>  	    if (blend.alpha_src) {
> @@ -399,7 +400,7 @@ bind_samplers(struct xa_context *ctx,
>      memset(&mask_sampler, 0, sizeof(struct pipe_sampler_state));
>  
>      if (src_pic) {
> -	if (ctx->has_solid_color) {
> +	if (is_solid_fill(src_pic)) {
>  	    samplers[0] = NULL;
>  	    pipe_sampler_view_reference(&ctx->bound_sampler_views[0], NULL);
>  	} else {
> @@ -427,27 +428,31 @@ bind_samplers(struct xa_context *ctx,
>      }
>  
>      if (mask_pic) {
> -	unsigned mask_wrap = xa_repeat_to_gallium(mask_pic->wrap);
> -	int filter;
> -
> -	(void) xa_filter_to_gallium(mask_pic->filter, &filter);
> -
> -	mask_sampler.wrap_s = mask_wrap;
> -	mask_sampler.wrap_t = mask_wrap;
> -	mask_sampler.min_img_filter = filter;
> -	mask_sampler.mag_img_filter = filter;
> -	src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
> -	mask_sampler.normalized_coords = 1;
> -	samplers[1] = &mask_sampler;
> -	ctx->num_bound_samplers = 2;
> -	u_sampler_view_default_template(&view_templ,
> -					mask_pic->srf->tex,
> -					mask_pic->srf->tex->format);
> -	src_view = pipe->create_sampler_view(pipe, mask_pic->srf->tex,
> -					     &view_templ);
> -	pipe_sampler_view_reference(&ctx->bound_sampler_views[1], NULL);
> -	ctx->bound_sampler_views[1] = src_view;
> +	if (is_solid_fill(mask_pic)) {
> +	    samplers[1] = NULL;
> +	    pipe_sampler_view_reference(&ctx->bound_sampler_views[1], NULL);
> +	} else {
> +	    unsigned mask_wrap = xa_repeat_to_gallium(mask_pic->wrap);
> +	    int filter;
> +
> +	    (void) xa_filter_to_gallium(mask_pic->filter, &filter);
>  
> +	    mask_sampler.wrap_s = mask_wrap;
> +	    mask_sampler.wrap_t = mask_wrap;
> +	    mask_sampler.min_img_filter = filter;
> +	    mask_sampler.mag_img_filter = filter;
> +	    src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
> +	    mask_sampler.normalized_coords = 1;
> +	    samplers[1] = &mask_sampler;
> +	    ctx->num_bound_samplers = 2;
> +	    u_sampler_view_default_template(&view_templ,
> +					    mask_pic->srf->tex,
> +					    mask_pic->srf->tex->format);
> +	    src_view = pipe->create_sampler_view(pipe, mask_pic->srf->tex,
> +		    &view_templ);
> +	    pipe_sampler_view_reference(&ctx->bound_sampler_views[1], NULL);
> +	    ctx->bound_sampler_views[1] = src_view;
> +	}
>  
>  	/*
>  	 * If src is a solid color, we have no src view, so set up a
> @@ -488,10 +493,10 @@ xa_composite_prepare(struct xa_context *ctx,
>  	return ret;
>      bind_samplers(ctx, comp);
>  
> -    if (ctx->num_bound_samplers == 0 ) { /* solid fill */
> +    if (ctx->num_bound_samplers == 0 && !ctx->has_solid_mask) { /* solid fill */
>  	renderer_begin_solid(ctx);
>      } else {
> -	renderer_begin_textures(ctx);
> +	renderer_begin_textures(ctx, comp);
>  	ctx->comp = comp;
>      }
>  
> @@ -504,7 +509,7 @@ xa_composite_rect(struct xa_context *ctx,
>  		  int srcX, int srcY, int maskX, int maskY,
>  		  int dstX, int dstY, int width, int height)
>  {
> -    if (ctx->num_bound_samplers == 0 ) { /* solid fill */
> +    if ((ctx->num_bound_samplers == 0) && !ctx->has_solid_mask) { /* solid fill */
>  	renderer_solid(ctx, dstX, dstY, dstX + width, dstY + height,
>  		       ctx->solid_color);
>      } else {
> @@ -530,6 +535,7 @@ xa_composite_done(struct xa_context *ctx)
>  
>      ctx->comp = NULL;
>      ctx->has_solid_color = FALSE;
> +    ctx->has_solid_mask = FALSE;
>      xa_ctx_sampler_views_destroy(ctx);
>  }
>  
> diff --git a/src/gallium/state_trackers/xa/xa_priv.h b/src/gallium/state_trackers/xa/xa_priv.h
> index b99c214..348a98e 100644
> --- a/src/gallium/state_trackers/xa/xa_priv.h
> +++ b/src/gallium/state_trackers/xa/xa_priv.h
> @@ -110,6 +110,9 @@ struct xa_context {
>      int has_solid_color;
>      float solid_color[4];
>  
> +    int has_solid_mask;
> +    float solid_mask[4];
> +
>      unsigned int num_bound_samplers;
>      struct pipe_sampler_view *bound_sampler_views[XA_MAX_SAMPLERS];
>      const struct xa_composite *comp;
> @@ -122,6 +125,7 @@ enum xa_vs_traits {
>      VS_LINGRAD_FILL = 1 << 3,
>      VS_RADGRAD_FILL = 1 << 4,
>      VS_YUV = 1 << 5,
> +    VS_SOLID_MASK = 1 << 6,
>  
>      VS_FILL = (VS_SOLID_FILL | VS_LINGRAD_FILL | VS_RADGRAD_FILL)
>  };
> @@ -144,6 +148,7 @@ enum xa_fs_traits {
>      FS_SRC_LUMINANCE = 1 << 14,
>      FS_MASK_LUMINANCE = 1 << 15,
>      FS_DST_LUMINANCE = 1 << 16,
> +    FS_SOLID_MASK = 1 << 17,
>  
>      FS_FILL = (FS_SOLID_FILL | FS_LINGRAD_FILL | FS_RADGRAD_FILL),
>      FS_COMPONENT_ALPHA = (FS_CA_FULL | FS_CA_SRCALPHA)
> @@ -258,7 +263,7 @@ void renderer_begin_solid(struct xa_context *r);
>  void renderer_solid(struct xa_context *r,
>  		    int x0, int y0, int x1, int y1, float *color);
>  void
> -renderer_begin_textures(struct xa_context *r);
> +renderer_begin_textures(struct xa_context *r, const struct xa_composite *comp);
>  
>  void
>  renderer_texture(struct xa_context *r,
> diff --git a/src/gallium/state_trackers/xa/xa_renderer.c b/src/gallium/state_trackers/xa/xa_renderer.c
> index 9ba78be..056648a 100644
> --- a/src/gallium/state_trackers/xa/xa_renderer.c
> +++ b/src/gallium/state_trackers/xa/xa_renderer.c
> @@ -124,7 +124,7 @@ renderer_init_state(struct xa_context *r)
>  }
>  
>  static INLINE void
> -add_vertex_color(struct xa_context *r, float x, float y, float color[4])
> +add_vertex_coord(struct xa_context *r, float x, float y)
>  {
>      float *vertex = r->buffer + r->buffer_size;
>  
> @@ -133,98 +133,84 @@ add_vertex_color(struct xa_context *r, float x, float y, float color[4])
>      vertex[2] = 0.f;		/*z */
>      vertex[3] = 1.f;		/*w */
>  
> -    vertex[4] = color[0];	/*r */
> -    vertex[5] = color[1];	/*g */
> -    vertex[6] = color[2];	/*b */
> -    vertex[7] = color[3];	/*a */
> -
> -    r->buffer_size += 8;
> -}
> -
> -static INLINE void
> -add_vertex_1tex(struct xa_context *r, float x, float y, float s, float t)
> -{
> -    float *vertex = r->buffer + r->buffer_size;
> -
> -    vertex[0] = x;
> -    vertex[1] = y;
> -    vertex[2] = 0.f;		/*z */
> -    vertex[3] = 1.f;		/*w */
> -
> -    vertex[4] = s;		/*s */
> -    vertex[5] = t;		/*t */
> -    vertex[6] = 0.f;		/*r */
> -    vertex[7] = 1.f;		/*q */
> -
> -    r->buffer_size += 8;
> +    r->buffer_size += 4;
>  }
>  
>  static INLINE void
> -add_vertex_2tex(struct xa_context *r,
> -		float x, float y, float s0, float t0, float s1, float t1)
> +add_vertex_color(struct xa_context *r, const float *color)
>  {
>      float *vertex = r->buffer + r->buffer_size;
>  
> -    vertex[0] = x;
> -    vertex[1] = y;
> -    vertex[2] = 0.f;		/*z */
> -    vertex[3] = 1.f;		/*w */
> -
> -    vertex[4] = s0;		/*s */
> -    vertex[5] = t0;		/*t */
> -    vertex[6] = 0.f;		/*r */
> -    vertex[7] = 1.f;		/*q */
> +    vertex[0] = color[0];	/*r */
> +    vertex[1] = color[1];	/*g */
> +    vertex[2] = color[2];	/*b */
> +    vertex[3] = color[3];	/*a */
>  
> -    vertex[8] = s1;		/*s */
> -    vertex[9] = t1;		/*t */
> -    vertex[10] = 0.f;		/*r */
> -    vertex[11] = 1.f;		/*q */
> -
> -    r->buffer_size += 12;
> +    r->buffer_size += 4;
>  }
>  
>  static void
>  add_vertex_data1(struct xa_context *r,
>                   float srcX, float srcY,  float dstX, float dstY,
>                   float width, float height,
> -                 struct pipe_resource *src, const float *src_matrix)
> +                 struct pipe_resource *src, const float *src_matrix,
> +                 const float *src_color)
>  {
>      float s0, t0, s1, t1, s2, t2, s3, t3;
> -    float pt0[2], pt1[2], pt2[2], pt3[2];
> -
> -    pt0[0] = srcX;
> -    pt0[1] = srcY;
> -    pt1[0] = (srcX + width);
> -    pt1[1] = srcY;
> -    pt2[0] = (srcX + width);
> -    pt2[1] = (srcY + height);
> -    pt3[0] = srcX;
> -    pt3[1] = (srcY + height);
>  
> -    if (src_matrix) {
> -	map_point((float *)src_matrix, pt0[0], pt0[1], &pt0[0], &pt0[1]);
> -	map_point((float *)src_matrix, pt1[0], pt1[1], &pt1[0], &pt1[1]);
> -	map_point((float *)src_matrix, pt2[0], pt2[1], &pt2[0], &pt2[1]);
> -	map_point((float *)src_matrix, pt3[0], pt3[1], &pt3[0], &pt3[1]);
> +    if (!src_color) {
> +	float pt0[2], pt1[2], pt2[2], pt3[2];
> +
> +	pt0[0] = srcX;
> +	pt0[1] = srcY;
> +	pt1[0] = (srcX + width);
> +	pt1[1] = srcY;
> +	pt2[0] = (srcX + width);
> +	pt2[1] = (srcY + height);
> +	pt3[0] = srcX;
> +	pt3[1] = (srcY + height);
> +
> +	if (src_matrix) {
> +	    map_point((float *)src_matrix, pt0[0], pt0[1], &pt0[0], &pt0[1]);
> +	    map_point((float *)src_matrix, pt1[0], pt1[1], &pt1[0], &pt1[1]);
> +	    map_point((float *)src_matrix, pt2[0], pt2[1], &pt2[0], &pt2[1]);
> +	    map_point((float *)src_matrix, pt3[0], pt3[1], &pt3[0], &pt3[1]);
> +	}
> +
> +	s0 =  pt0[0] / src->width0;
> +	s1 =  pt1[0] / src->width0;
> +	s2 =  pt2[0] / src->width0;
> +	s3 =  pt3[0] / src->width0;
> +	t0 =  pt0[1] / src->height0;
> +	t1 =  pt1[1] / src->height0;
> +	t2 =  pt2[1] / src->height0;
> +	t3 =  pt3[1] / src->height0;
>      }
>  
> -    s0 =  pt0[0] / src->width0;
> -    s1 =  pt1[0] / src->width0;
> -    s2 =  pt2[0] / src->width0;
> -    s3 =  pt3[0] / src->width0;
> -    t0 =  pt0[1] / src->height0;
> -    t1 =  pt1[1] / src->height0;
> -    t2 =  pt2[1] / src->height0;
> -    t3 =  pt3[1] / src->height0;
> -
>      /* 1st vertex */
> -    add_vertex_1tex(r, dstX, dstY, s0, t0);
> +    add_vertex_coord(r, dstX, dstY);
> +    if (src_color)
> +	add_vertex_color(r, src_color);
> +    else
> +	add_vertex_coord(r, s0, t0);
>      /* 2nd vertex */
> -    add_vertex_1tex(r, dstX + width, dstY, s1, t1);
> +    add_vertex_coord(r, dstX + width, dstY);
> +    if (src_color)
> +	add_vertex_color(r, src_color);
> +    else
> +	add_vertex_coord(r, s1, t1);
>      /* 3rd vertex */
> -    add_vertex_1tex(r, dstX + width, dstY + height, s2, t2);
> +    add_vertex_coord(r, dstX + width, dstY + height);
> +    if (src_color)
> +	add_vertex_color(r, src_color);
> +    else
> +	add_vertex_coord(r, s2, t2);
>      /* 4th vertex */
> -    add_vertex_1tex(r, dstX, dstY + height, s3, t3);
> +    add_vertex_coord(r, dstX, dstY + height);
> +    if (src_color)
> +	add_vertex_color(r, src_color);
> +    else
> +	add_vertex_coord(r, s3, t3);
>  }
>  
>  static void
> @@ -233,55 +219,91 @@ add_vertex_data2(struct xa_context *r,
>                   float dstX, float dstY, float width, float height,
>                   struct pipe_resource *src,
>                   struct pipe_resource *mask,
> -                 const float *src_matrix, const float *mask_matrix)
> +                 const float *src_matrix, const float *src_color,
> +                 const float *mask_matrix, const float *mask_color)
>  {
>      float src_s0, src_t0, src_s1, src_t1;
>      float mask_s0, mask_t0, mask_s1, mask_t1;
> -    float spt0[2], spt1[2];
> -    float mpt0[2], mpt1[2];
>  
> -    spt0[0] = srcX;
> -    spt0[1] = srcY;
> -    spt1[0] = srcX + width;
> -    spt1[1] = srcY + height;
>  
> -    mpt0[0] = maskX;
> -    mpt0[1] = maskY;
> -    mpt1[0] = maskX + width;
> -    mpt1[1] = maskY + height;
> +    if (!src_color) {
> +	float spt0[2], spt1[2];
>  
> -    if (src_matrix) {
> -	map_point((float *)src_matrix, spt0[0], spt0[1], &spt0[0], &spt0[1]);
> -	map_point((float *)src_matrix, spt1[0], spt1[1], &spt1[0], &spt1[1]);
> -    }
> +	spt0[0] = srcX;
> +	spt0[1] = srcY;
> +	spt1[0] = srcX + width;
> +	spt1[1] = srcY + height;
>  
> -    if (mask_matrix) {
> -	map_point((float *)mask_matrix, mpt0[0], mpt0[1], &mpt0[0], &mpt0[1]);
> -	map_point((float *)mask_matrix, mpt1[0], mpt1[1], &mpt1[0], &mpt1[1]);
> +	if (src_matrix) {
> +	    map_point((float *)src_matrix, spt0[0], spt0[1], &spt0[0], &spt0[1]);
> +	    map_point((float *)src_matrix, spt1[0], spt1[1], &spt1[0], &spt1[1]);
> +	}
> +
> +	src_s0 = spt0[0] / src->width0;
> +	src_t0 = spt0[1] / src->height0;
> +	src_s1 = spt1[0] / src->width0;
> +	src_t1 = spt1[1] / src->height0;
>      }
>  
> -    src_s0 = spt0[0] / src->width0;
> -    src_t0 = spt0[1] / src->height0;
> -    src_s1 = spt1[0] / src->width0;
> -    src_t1 = spt1[1] / src->height0;
> +    if (!mask_color) {
> +	float mpt0[2], mpt1[2];
> +
> +	mpt0[0] = maskX;
> +	mpt0[1] = maskY;
> +	mpt1[0] = maskX + width;
> +	mpt1[1] = maskY + height;
>  
> -    mask_s0 = mpt0[0] / mask->width0;
> -    mask_t0 = mpt0[1] / mask->height0;
> -    mask_s1 = mpt1[0] / mask->width0;
> -    mask_t1 = mpt1[1] / mask->height0;
> +	if (mask_matrix) {
> +	    map_point((float *)mask_matrix, mpt0[0], mpt0[1], &mpt0[0], &mpt0[1]);
> +	    map_point((float *)mask_matrix, mpt1[0], mpt1[1], &mpt1[0], &mpt1[1]);
> +	}
> +
> +	mask_s0 = mpt0[0] / mask->width0;
> +	mask_t0 = mpt0[1] / mask->height0;
> +	mask_s1 = mpt1[0] / mask->width0;
> +	mask_t1 = mpt1[1] / mask->height0;
> +    }
>  
>      /* 1st vertex */
> -    add_vertex_2tex(r, dstX, dstY,
> -		    src_s0, src_t0, mask_s0, mask_t0);
> +    add_vertex_coord(r, dstX, dstY);
> +    if (src_color)
> +	add_vertex_color(r, src_color);
> +    else
> +	add_vertex_coord(r, src_s0, src_t0);
> +    if (mask_color)
> +	add_vertex_color(r, mask_color);
> +    else
> +	add_vertex_coord(r, mask_s0, mask_t0);
>      /* 2nd vertex */
> -    add_vertex_2tex(r, dstX + width, dstY,
> -		    src_s1, src_t0, mask_s1, mask_t0);
> +    add_vertex_coord(r, dstX + width, dstY);
> +    if (src_color)
> +	add_vertex_color(r, src_color);
> +    else
> +	add_vertex_coord(r, src_s1, src_t0);
> +    if (mask_color)
> +	add_vertex_color(r, mask_color);
> +    else
> +	add_vertex_coord(r, mask_s1, mask_t0);
>      /* 3rd vertex */
> -    add_vertex_2tex(r, dstX + width, dstY + height,
> -		    src_s1, src_t1, mask_s1, mask_t1);
> +    add_vertex_coord(r, dstX + width, dstY + height);
> +    if (src_color)
> +	add_vertex_color(r, src_color);
> +    else
> +	add_vertex_coord(r, src_s1, src_t1);
> +    if (mask_color)
> +	add_vertex_color(r, mask_color);
> +    else
> +	add_vertex_coord(r, mask_s1, mask_t1);
>      /* 4th vertex */
> -    add_vertex_2tex(r, dstX, dstY + height,
> -		    src_s0, src_t1, mask_s0, mask_t1);
> +    add_vertex_coord(r, dstX, dstY + height);
> +    if (src_color)
> +	add_vertex_color(r, src_color);
> +    else
> +	add_vertex_coord(r, src_s0, src_t1);
> +    if (mask_color)
> +	add_vertex_color(r, mask_color);
> +    else
> +	add_vertex_coord(r, mask_s0, mask_t1);
>  }
>  
>  static void
> @@ -310,13 +332,17 @@ setup_vertex_data_yuv(struct xa_context *r,
>      t1 = spt1[1] / tex->height0;
>  
>      /* 1st vertex */
> -    add_vertex_1tex(r, dstX, dstY, s0, t0);
> +    add_vertex_coord(r, dstX, dstY);
> +    add_vertex_coord(r, s0, t0);
>      /* 2nd vertex */
> -    add_vertex_1tex(r, dstX + dstW, dstY, s1, t0);
> +    add_vertex_coord(r, dstX + dstW, dstY);
> +    add_vertex_coord(r, s1, t0);
>      /* 3rd vertex */
> -    add_vertex_1tex(r, dstX + dstW, dstY + dstH, s1, t1);
> +    add_vertex_coord(r, dstX + dstW, dstY + dstH);
> +    add_vertex_coord(r, s1, t1);
>      /* 4th vertex */
> -    add_vertex_1tex(r, dstX, dstY + dstH, s0, t1);
> +    add_vertex_coord(r, dstX, dstY + dstH);
> +    add_vertex_coord(r, s0, t1);
>  }
>  
>  /* Set up framebuffer, viewport and vertex shader constant buffer
> @@ -493,10 +519,14 @@ renderer_copy(struct xa_context *r,
>  
>      /* draw quad */
>      renderer_draw_conditional(r, 4 * 8);
> -    add_vertex_1tex(r, x0, y0, s0, t0);
> -    add_vertex_1tex(r, x1, y0, s1, t0);
> -    add_vertex_1tex(r, x1, y1, s1, t1);
> -    add_vertex_1tex(r, x0, y1, s0, t1);
> +    add_vertex_coord(r, x0, y0);
> +    add_vertex_coord(r, s0, t0);
> +    add_vertex_coord(r, x1, y0);
> +    add_vertex_coord(r, s1, t0);
> +    add_vertex_coord(r, x1, y1);
> +    add_vertex_coord(r, s1, t1);
> +    add_vertex_coord(r, x0, y1);
> +    add_vertex_coord(r, s0, t1);
>  }
>  
>  void
> @@ -539,13 +569,17 @@ renderer_solid(struct xa_context *r,
>      renderer_draw_conditional(r, 4 * 8);
>  
>      /* 1st vertex */
> -    add_vertex_color(r, x0, y0, color);
> +    add_vertex_coord(r, x0, y0);
> +    add_vertex_color(r, color);
>      /* 2nd vertex */
> -    add_vertex_color(r, x1, y0, color);
> +    add_vertex_coord(r, x1, y0);
> +    add_vertex_color(r, color);
>      /* 3rd vertex */
> -    add_vertex_color(r, x1, y1, color);
> +    add_vertex_coord(r, x1, y1);
> +    add_vertex_color(r, color);
>      /* 4th vertex */
> -    add_vertex_color(r, x0, y1, color);
> +    add_vertex_coord(r, x0, y1);
> +    add_vertex_color(r, color);
>  }
>  
>  void
> @@ -555,9 +589,14 @@ renderer_draw_flush(struct xa_context *r)
>  }
>  
>  void
> -renderer_begin_textures(struct xa_context *r)
> +renderer_begin_textures(struct xa_context *r,
> +	const struct xa_composite *comp)
>  {
> -    r->attrs_per_vertex = 1 + r->num_bound_samplers;
> +    r->attrs_per_vertex = 1;
> +    if (comp->src)
> +	r->attrs_per_vertex++;
> +    if (comp->mask)
> +	r->attrs_per_vertex++;
>      r->buffer_size = 0;
>  }
>  
> @@ -592,7 +631,9 @@ renderer_texture(struct xa_context *r,
>  			 pos[0], pos[1], /* src */
>  			 pos[4], pos[5], /* dst */
>  			 width, height,
> -			 sampler_view[0]->texture, src_matrix);
> +			 sampler_view[0]->texture,
> +			 r->has_solid_color ? NULL : src_matrix,
> +			 r->has_solid_color ? r->solid_color : NULL);
>  	break;
>      case 3:
>  	renderer_draw_conditional(r, 4 * 12);
> @@ -601,8 +642,12 @@ renderer_texture(struct xa_context *r,
>  			 pos[2], pos[3], /* mask */
>  			 pos[4], pos[5], /* dst */
>  			 width, height,
> -			 sampler_view[0]->texture, sampler_view[1]->texture,
> -			 src_matrix, mask_matrix);
> +			 r->has_solid_color ? NULL : sampler_view[0]->texture,
> +			 r->has_solid_mask ? NULL : sampler_view[1]->texture,
> +			 r->has_solid_color ? NULL : src_matrix,
> +			 r->has_solid_color ? r->solid_color : NULL,
> +			 r->has_solid_mask ? NULL : mask_matrix,
> +			 r->has_solid_mask ? r->solid_mask : NULL);
>  	break;
>      default:
>  	break;
> diff --git a/src/gallium/state_trackers/xa/xa_tgsi.c b/src/gallium/state_trackers/xa/xa_tgsi.c
> index c7454c9..9cda4c3 100644
> --- a/src/gallium/state_trackers/xa/xa_tgsi.c
> +++ b/src/gallium/state_trackers/xa/xa_tgsi.c
> @@ -42,14 +42,14 @@
>  /* Vertex shader:
>   * IN[0]    = vertex pos
>   * IN[1]    = src tex coord | solid fill color
> - * IN[2]    = mask tex coord
> + * IN[2]    = mask tex coord | solid mask color
>   * IN[3]    = dst tex coord
>   * CONST[0] = (2/dst_width, 2/dst_height, 1, 1)
>   * CONST[1] = (-1, -1, 0, 0)
>   *
>   * OUT[0]   = vertex pos
>   * OUT[1]   = src tex coord | solid fill color
> - * OUT[2]   = mask tex coord
> + * OUT[2]   = mask tex coord | solid mask color
>   * OUT[3]   = dst tex coord
>   */
>  
> @@ -58,7 +58,7 @@
>   * SAMP[1]  = mask
>   * SAMP[2]  = dst
>   * IN[0]    = pos src | solid fill color
> - * IN[1]    = pos mask
> + * IN[1]    = pos mask | solid mask color
>   * IN[2]    = pos dst
>   * CONST[0] = (0, 0, 0, 1)
>   *
> @@ -268,6 +268,7 @@ create_vs(struct pipe_context *pipe, unsigned vs_traits)
>      boolean is_fill = (vs_traits & VS_FILL) != 0;
>      boolean is_composite = (vs_traits & VS_COMPOSITE) != 0;
>      boolean has_mask = (vs_traits & VS_MASK) != 0;
> +    boolean is_solid_mask = (vs_traits & VS_SOLID_MASK) != 0;
>      boolean is_yuv = (vs_traits & VS_YUV) != 0;
>      unsigned input_slot = 0;
>  
> @@ -296,15 +297,17 @@ create_vs(struct pipe_context *pipe, unsigned vs_traits)
>  	src = ureg_DECL_vs_input(ureg, input_slot++);
>  	dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 0);
>  	ureg_MOV(ureg, dst, src);
> -    }
> -
> -    if (is_fill) {
> +    } else if (is_fill) {
>  	src = ureg_DECL_vs_input(ureg, input_slot++);
>  	dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
>  	ureg_MOV(ureg, dst, src);
>      }
>  
> -    if (has_mask) {
> +    if (is_solid_mask) {
> +	src = ureg_DECL_vs_input(ureg, input_slot++);
> +	dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 1);
> +	ureg_MOV(ureg, dst, src);
> +    } else if (has_mask) {
>  	src = ureg_DECL_vs_input(ureg, input_slot++);
>  	dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 1);
>  	ureg_MOV(ureg, dst, src);
> @@ -436,6 +439,7 @@ create_fs(struct pipe_context *pipe, unsigned fs_traits)
>      struct ureg_dst out;
>      struct ureg_src imm0 = { 0 };
>      unsigned has_mask = (fs_traits & FS_MASK) != 0;
> +    unsigned is_solid_mask = (fs_traits & FS_SOLID_MASK) != 0;
>      unsigned is_fill = (fs_traits & FS_FILL) != 0;
>      unsigned is_composite = (fs_traits & FS_COMPOSITE) != 0;
>      unsigned is_solid = (fs_traits & FS_SOLID_FILL) != 0;
> @@ -492,7 +496,11 @@ create_fs(struct pipe_context *pipe, unsigned fs_traits)
>  	return create_yuv_shader(pipe, ureg);
>      }
>  
> -    if (has_mask) {
> +    if (is_solid_mask) {
> +	mask_pos = ureg_DECL_fs_input(ureg,
> +				       TGSI_SEMANTIC_COLOR, 1,
> +				       TGSI_INTERPOLATE_PERSPECTIVE);
> +    } else if (has_mask) {
>  	mask_sampler = ureg_DECL_sampler(ureg, 1);
>  	mask_pos = ureg_DECL_fs_input(ureg,
>  				      TGSI_SEMANTIC_GENERIC, 1,
> @@ -552,10 +560,15 @@ create_fs(struct pipe_context *pipe, unsigned fs_traits)
>  	    ureg_MOV(ureg, out, ureg_src(src));
>      }
>  
> -    if (has_mask) {
> +    if (is_solid_mask) {
> +	mask = ureg_dst(mask_pos);
> +    } else if (has_mask) {
>  	mask = ureg_DECL_temporary(ureg);
>  	xrender_tex(ureg, mask, mask_pos, mask_sampler, imm0,
>  		    mask_repeat_none, mask_swizzle, mask_set_alpha);
> +    }
> +
> +    if (has_mask) {
>  	/* src IN mask */
>  
>  	src_in_mask(ureg, (dst_luminance) ? src : out, ureg_src(src),
On Thu, Apr 3, 2014 at 1:17 AM, Thomas Hellstrom <thellstrom@vmware.com> wrote:
> On 04/01/2014 05:04 PM, Rob Clark wrote:
>> From: Rob Clark <robclark@freedesktop.org>
>>
>> Add support to property handle solid-fill src and/or mask.  Without this
>> we fallback to sw a lot for common things like text rendering.
>>
>> Signed-off-by: Rob Clark <robclark@freedesktop.org>
>> ---
>>  src/gallium/state_trackers/xa/xa_composite.c |  88 ++++----
>>  src/gallium/state_trackers/xa/xa_priv.h      |   7 +-
>>  src/gallium/state_trackers/xa/xa_renderer.c  | 289 ++++++++++++++++-----------
>>  src/gallium/state_trackers/xa/xa_tgsi.c      |  31 ++-
>>  4 files changed, 242 insertions(+), 173 deletions(-)
>
> Rob,
> While testing this patch it looks like we sometimes set two samplers,
> and the first one is NULL.
> The SVGA driver asserts on that condition.
> We might need to move the active sampler to the first entry in that
> case, and adjust tex coords and shader accordingly.

Yeah, I saw that.. but the code looked like it was originally intended
to work that way, so I'd assumed it was a valid condition that I just
wasn't dealing with in freedreno.

BR,
-R

> I'll discuss with BrianP.
>
> /Thomas
>
>> diff --git a/src/gallium/state_trackers/xa/xa_composite.c b/src/gallium/state_trackers/xa/xa_composite.c
>> index abe5be2..f63cf49 100644
>> --- a/src/gallium/state_trackers/xa/xa_composite.c
>> +++ b/src/gallium/state_trackers/xa/xa_composite.c
>> @@ -111,12 +111,6 @@ blend_for_op(struct xa_composite_blend *blend,
>>      boolean supported = FALSE;
>>
>>      /*
>> -     * Temporarily disable component alpha since it appears buggy.
>> -     */
>> -    if (mask_pic && mask_pic->component_alpha)
>> -     return FALSE;
>> -
>> -    /*
>>       * our default in case something goes wrong
>>       */
>>      *blend = xa_blends[XA_BLEND_OP_OVER];
>> @@ -125,6 +119,7 @@ blend_for_op(struct xa_composite_blend *blend,
>>       if (xa_blends[i].op == op) {
>>           *blend = xa_blends[i];
>>           supported = TRUE;
>> +         break;
>>       }
>>      }
>>
>> @@ -227,14 +222,6 @@ xa_composite_check_accelerated(const struct xa_composite *comp)
>>      if (src_pic->src_pict) {
>>       if (src_pic->src_pict->type != xa_src_pict_solid_fill)
>>           return -XA_ERR_INVAL;
>> -
>> -     /*
>> -      * Currently we don't support solid fill with a mask.
>> -      * We can easily do that, but that would require shader,
>> -      * sampler view setup and vertex setup modification.
>> -      */
>> -     if (comp->mask)
>> -         return -XA_ERR_INVAL;
>>      }
>>
>>      if (blend_for_op(&blend, comp->op, comp->src, comp->mask, comp->dst)) {
>> @@ -322,6 +309,12 @@ picture_format_fixups(struct xa_picture *src_pic,
>>  }
>>
>>  static int
>> +is_solid_fill(struct xa_picture *pic)
>> +{
>> +    return pic->src_pict && (pic->src_pict->type == xa_src_pict_solid_fill);
>> +}
>> +
>> +static int
>>  bind_shaders(struct xa_context *ctx, const struct xa_composite *comp)
>>  {
>>      unsigned vs_traits = 0, fs_traits = 0;
>> @@ -336,8 +329,8 @@ bind_shaders(struct xa_context *ctx, const struct xa_composite *comp)
>>           fs_traits |= FS_SRC_REPEAT_NONE;
>>
>>       if (src_pic->src_pict) {
>> -         if (src_pic->src_pict->type == xa_src_pict_solid_fill) {
>> -             fs_traits |= FS_SOLID_FILL | FS_FILL;
>> +         if (is_solid_fill(src_pic)) {
>> +             fs_traits |= FS_SOLID_FILL;
>>               vs_traits |= VS_SOLID_FILL;
>>               xa_pixel_to_float4(src_pic->src_pict->solid_fill.color,
>>                                  ctx->solid_color);
>> @@ -358,9 +351,17 @@ bind_shaders(struct xa_context *ctx, const struct xa_composite *comp)
>>           mask_pic->has_transform)
>>           fs_traits |= FS_MASK_REPEAT_NONE;
>>
>> +     if (is_solid_fill(mask_pic)) {
>> +             fs_traits |= FS_SOLID_MASK;
>> +             vs_traits |= VS_SOLID_MASK;
>> +             xa_pixel_to_float4(mask_pic->src_pict->solid_fill.color,
>> +                                ctx->solid_mask);
>> +             ctx->has_solid_mask = TRUE;
>> +     }
>> +
>>       if (mask_pic->component_alpha) {
>>           struct xa_composite_blend blend;
>> -         if (!blend_for_op(&blend, comp->op, src_pic, mask_pic, NULL))
>> +         if (!blend_for_op(&blend, comp->op, src_pic, mask_pic, comp->dst))
>>               return -XA_ERR_INVAL;
>>
>>           if (blend.alpha_src) {
>> @@ -399,7 +400,7 @@ bind_samplers(struct xa_context *ctx,
>>      memset(&mask_sampler, 0, sizeof(struct pipe_sampler_state));
>>
>>      if (src_pic) {
>> -     if (ctx->has_solid_color) {
>> +     if (is_solid_fill(src_pic)) {
>>           samplers[0] = NULL;
>>           pipe_sampler_view_reference(&ctx->bound_sampler_views[0], NULL);
>>       } else {
>> @@ -427,27 +428,31 @@ bind_samplers(struct xa_context *ctx,
>>      }
>>
>>      if (mask_pic) {
>> -     unsigned mask_wrap = xa_repeat_to_gallium(mask_pic->wrap);
>> -     int filter;
>> -
>> -     (void) xa_filter_to_gallium(mask_pic->filter, &filter);
>> -
>> -     mask_sampler.wrap_s = mask_wrap;
>> -     mask_sampler.wrap_t = mask_wrap;
>> -     mask_sampler.min_img_filter = filter;
>> -     mask_sampler.mag_img_filter = filter;
>> -     src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
>> -     mask_sampler.normalized_coords = 1;
>> -     samplers[1] = &mask_sampler;
>> -     ctx->num_bound_samplers = 2;
>> -     u_sampler_view_default_template(&view_templ,
>> -                                     mask_pic->srf->tex,
>> -                                     mask_pic->srf->tex->format);
>> -     src_view = pipe->create_sampler_view(pipe, mask_pic->srf->tex,
>> -                                          &view_templ);
>> -     pipe_sampler_view_reference(&ctx->bound_sampler_views[1], NULL);
>> -     ctx->bound_sampler_views[1] = src_view;
>> +     if (is_solid_fill(mask_pic)) {
>> +         samplers[1] = NULL;
>> +         pipe_sampler_view_reference(&ctx->bound_sampler_views[1], NULL);
>> +     } else {
>> +         unsigned mask_wrap = xa_repeat_to_gallium(mask_pic->wrap);
>> +         int filter;
>> +
>> +         (void) xa_filter_to_gallium(mask_pic->filter, &filter);
>>
>> +         mask_sampler.wrap_s = mask_wrap;
>> +         mask_sampler.wrap_t = mask_wrap;
>> +         mask_sampler.min_img_filter = filter;
>> +         mask_sampler.mag_img_filter = filter;
>> +         src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
>> +         mask_sampler.normalized_coords = 1;
>> +         samplers[1] = &mask_sampler;
>> +         ctx->num_bound_samplers = 2;
>> +         u_sampler_view_default_template(&view_templ,
>> +                                         mask_pic->srf->tex,
>> +                                         mask_pic->srf->tex->format);
>> +         src_view = pipe->create_sampler_view(pipe, mask_pic->srf->tex,
>> +                 &view_templ);
>> +         pipe_sampler_view_reference(&ctx->bound_sampler_views[1], NULL);
>> +         ctx->bound_sampler_views[1] = src_view;
>> +     }
>>
>>       /*
>>        * If src is a solid color, we have no src view, so set up a
>> @@ -488,10 +493,10 @@ xa_composite_prepare(struct xa_context *ctx,
>>       return ret;
>>      bind_samplers(ctx, comp);
>>
>> -    if (ctx->num_bound_samplers == 0 ) { /* solid fill */
>> +    if (ctx->num_bound_samplers == 0 && !ctx->has_solid_mask) { /* solid fill */
>>       renderer_begin_solid(ctx);
>>      } else {
>> -     renderer_begin_textures(ctx);
>> +     renderer_begin_textures(ctx, comp);
>>       ctx->comp = comp;
>>      }
>>
>> @@ -504,7 +509,7 @@ xa_composite_rect(struct xa_context *ctx,
>>                 int srcX, int srcY, int maskX, int maskY,
>>                 int dstX, int dstY, int width, int height)
>>  {
>> -    if (ctx->num_bound_samplers == 0 ) { /* solid fill */
>> +    if ((ctx->num_bound_samplers == 0) && !ctx->has_solid_mask) { /* solid fill */
>>       renderer_solid(ctx, dstX, dstY, dstX + width, dstY + height,
>>                      ctx->solid_color);
>>      } else {
>> @@ -530,6 +535,7 @@ xa_composite_done(struct xa_context *ctx)
>>
>>      ctx->comp = NULL;
>>      ctx->has_solid_color = FALSE;
>> +    ctx->has_solid_mask = FALSE;
>>      xa_ctx_sampler_views_destroy(ctx);
>>  }
>>
>> diff --git a/src/gallium/state_trackers/xa/xa_priv.h b/src/gallium/state_trackers/xa/xa_priv.h
>> index b99c214..348a98e 100644
>> --- a/src/gallium/state_trackers/xa/xa_priv.h
>> +++ b/src/gallium/state_trackers/xa/xa_priv.h
>> @@ -110,6 +110,9 @@ struct xa_context {
>>      int has_solid_color;
>>      float solid_color[4];
>>
>> +    int has_solid_mask;
>> +    float solid_mask[4];
>> +
>>      unsigned int num_bound_samplers;
>>      struct pipe_sampler_view *bound_sampler_views[XA_MAX_SAMPLERS];
>>      const struct xa_composite *comp;
>> @@ -122,6 +125,7 @@ enum xa_vs_traits {
>>      VS_LINGRAD_FILL = 1 << 3,
>>      VS_RADGRAD_FILL = 1 << 4,
>>      VS_YUV = 1 << 5,
>> +    VS_SOLID_MASK = 1 << 6,
>>
>>      VS_FILL = (VS_SOLID_FILL | VS_LINGRAD_FILL | VS_RADGRAD_FILL)
>>  };
>> @@ -144,6 +148,7 @@ enum xa_fs_traits {
>>      FS_SRC_LUMINANCE = 1 << 14,
>>      FS_MASK_LUMINANCE = 1 << 15,
>>      FS_DST_LUMINANCE = 1 << 16,
>> +    FS_SOLID_MASK = 1 << 17,
>>
>>      FS_FILL = (FS_SOLID_FILL | FS_LINGRAD_FILL | FS_RADGRAD_FILL),
>>      FS_COMPONENT_ALPHA = (FS_CA_FULL | FS_CA_SRCALPHA)
>> @@ -258,7 +263,7 @@ void renderer_begin_solid(struct xa_context *r);
>>  void renderer_solid(struct xa_context *r,
>>                   int x0, int y0, int x1, int y1, float *color);
>>  void
>> -renderer_begin_textures(struct xa_context *r);
>> +renderer_begin_textures(struct xa_context *r, const struct xa_composite *comp);
>>
>>  void
>>  renderer_texture(struct xa_context *r,
>> diff --git a/src/gallium/state_trackers/xa/xa_renderer.c b/src/gallium/state_trackers/xa/xa_renderer.c
>> index 9ba78be..056648a 100644
>> --- a/src/gallium/state_trackers/xa/xa_renderer.c
>> +++ b/src/gallium/state_trackers/xa/xa_renderer.c
>> @@ -124,7 +124,7 @@ renderer_init_state(struct xa_context *r)
>>  }
>>
>>  static INLINE void
>> -add_vertex_color(struct xa_context *r, float x, float y, float color[4])
>> +add_vertex_coord(struct xa_context *r, float x, float y)
>>  {
>>      float *vertex = r->buffer + r->buffer_size;
>>
>> @@ -133,98 +133,84 @@ add_vertex_color(struct xa_context *r, float x, float y, float color[4])
>>      vertex[2] = 0.f;         /*z */
>>      vertex[3] = 1.f;         /*w */
>>
>> -    vertex[4] = color[0];    /*r */
>> -    vertex[5] = color[1];    /*g */
>> -    vertex[6] = color[2];    /*b */
>> -    vertex[7] = color[3];    /*a */
>> -
>> -    r->buffer_size += 8;
>> -}
>> -
>> -static INLINE void
>> -add_vertex_1tex(struct xa_context *r, float x, float y, float s, float t)
>> -{
>> -    float *vertex = r->buffer + r->buffer_size;
>> -
>> -    vertex[0] = x;
>> -    vertex[1] = y;
>> -    vertex[2] = 0.f;         /*z */
>> -    vertex[3] = 1.f;         /*w */
>> -
>> -    vertex[4] = s;           /*s */
>> -    vertex[5] = t;           /*t */
>> -    vertex[6] = 0.f;         /*r */
>> -    vertex[7] = 1.f;         /*q */
>> -
>> -    r->buffer_size += 8;
>> +    r->buffer_size += 4;
>>  }
>>
>>  static INLINE void
>> -add_vertex_2tex(struct xa_context *r,
>> -             float x, float y, float s0, float t0, float s1, float t1)
>> +add_vertex_color(struct xa_context *r, const float *color)
>>  {
>>      float *vertex = r->buffer + r->buffer_size;
>>
>> -    vertex[0] = x;
>> -    vertex[1] = y;
>> -    vertex[2] = 0.f;         /*z */
>> -    vertex[3] = 1.f;         /*w */
>> -
>> -    vertex[4] = s0;          /*s */
>> -    vertex[5] = t0;          /*t */
>> -    vertex[6] = 0.f;         /*r */
>> -    vertex[7] = 1.f;         /*q */
>> +    vertex[0] = color[0];    /*r */
>> +    vertex[1] = color[1];    /*g */
>> +    vertex[2] = color[2];    /*b */
>> +    vertex[3] = color[3];    /*a */
>>
>> -    vertex[8] = s1;          /*s */
>> -    vertex[9] = t1;          /*t */
>> -    vertex[10] = 0.f;                /*r */
>> -    vertex[11] = 1.f;                /*q */
>> -
>> -    r->buffer_size += 12;
>> +    r->buffer_size += 4;
>>  }
>>
>>  static void
>>  add_vertex_data1(struct xa_context *r,
>>                   float srcX, float srcY,  float dstX, float dstY,
>>                   float width, float height,
>> -                 struct pipe_resource *src, const float *src_matrix)
>> +                 struct pipe_resource *src, const float *src_matrix,
>> +                 const float *src_color)
>>  {
>>      float s0, t0, s1, t1, s2, t2, s3, t3;
>> -    float pt0[2], pt1[2], pt2[2], pt3[2];
>> -
>> -    pt0[0] = srcX;
>> -    pt0[1] = srcY;
>> -    pt1[0] = (srcX + width);
>> -    pt1[1] = srcY;
>> -    pt2[0] = (srcX + width);
>> -    pt2[1] = (srcY + height);
>> -    pt3[0] = srcX;
>> -    pt3[1] = (srcY + height);
>>
>> -    if (src_matrix) {
>> -     map_point((float *)src_matrix, pt0[0], pt0[1], &pt0[0], &pt0[1]);
>> -     map_point((float *)src_matrix, pt1[0], pt1[1], &pt1[0], &pt1[1]);
>> -     map_point((float *)src_matrix, pt2[0], pt2[1], &pt2[0], &pt2[1]);
>> -     map_point((float *)src_matrix, pt3[0], pt3[1], &pt3[0], &pt3[1]);
>> +    if (!src_color) {
>> +     float pt0[2], pt1[2], pt2[2], pt3[2];
>> +
>> +     pt0[0] = srcX;
>> +     pt0[1] = srcY;
>> +     pt1[0] = (srcX + width);
>> +     pt1[1] = srcY;
>> +     pt2[0] = (srcX + width);
>> +     pt2[1] = (srcY + height);
>> +     pt3[0] = srcX;
>> +     pt3[1] = (srcY + height);
>> +
>> +     if (src_matrix) {
>> +         map_point((float *)src_matrix, pt0[0], pt0[1], &pt0[0], &pt0[1]);
>> +         map_point((float *)src_matrix, pt1[0], pt1[1], &pt1[0], &pt1[1]);
>> +         map_point((float *)src_matrix, pt2[0], pt2[1], &pt2[0], &pt2[1]);
>> +         map_point((float *)src_matrix, pt3[0], pt3[1], &pt3[0], &pt3[1]);
>> +     }
>> +
>> +     s0 =  pt0[0] / src->width0;
>> +     s1 =  pt1[0] / src->width0;
>> +     s2 =  pt2[0] / src->width0;
>> +     s3 =  pt3[0] / src->width0;
>> +     t0 =  pt0[1] / src->height0;
>> +     t1 =  pt1[1] / src->height0;
>> +     t2 =  pt2[1] / src->height0;
>> +     t3 =  pt3[1] / src->height0;
>>      }
>>
>> -    s0 =  pt0[0] / src->width0;
>> -    s1 =  pt1[0] / src->width0;
>> -    s2 =  pt2[0] / src->width0;
>> -    s3 =  pt3[0] / src->width0;
>> -    t0 =  pt0[1] / src->height0;
>> -    t1 =  pt1[1] / src->height0;
>> -    t2 =  pt2[1] / src->height0;
>> -    t3 =  pt3[1] / src->height0;
>> -
>>      /* 1st vertex */
>> -    add_vertex_1tex(r, dstX, dstY, s0, t0);
>> +    add_vertex_coord(r, dstX, dstY);
>> +    if (src_color)
>> +     add_vertex_color(r, src_color);
>> +    else
>> +     add_vertex_coord(r, s0, t0);
>>      /* 2nd vertex */
>> -    add_vertex_1tex(r, dstX + width, dstY, s1, t1);
>> +    add_vertex_coord(r, dstX + width, dstY);
>> +    if (src_color)
>> +     add_vertex_color(r, src_color);
>> +    else
>> +     add_vertex_coord(r, s1, t1);
>>      /* 3rd vertex */
>> -    add_vertex_1tex(r, dstX + width, dstY + height, s2, t2);
>> +    add_vertex_coord(r, dstX + width, dstY + height);
>> +    if (src_color)
>> +     add_vertex_color(r, src_color);
>> +    else
>> +     add_vertex_coord(r, s2, t2);
>>      /* 4th vertex */
>> -    add_vertex_1tex(r, dstX, dstY + height, s3, t3);
>> +    add_vertex_coord(r, dstX, dstY + height);
>> +    if (src_color)
>> +     add_vertex_color(r, src_color);
>> +    else
>> +     add_vertex_coord(r, s3, t3);
>>  }
>>
>>  static void
>> @@ -233,55 +219,91 @@ add_vertex_data2(struct xa_context *r,
>>                   float dstX, float dstY, float width, float height,
>>                   struct pipe_resource *src,
>>                   struct pipe_resource *mask,
>> -                 const float *src_matrix, const float *mask_matrix)
>> +                 const float *src_matrix, const float *src_color,
>> +                 const float *mask_matrix, const float *mask_color)
>>  {
>>      float src_s0, src_t0, src_s1, src_t1;
>>      float mask_s0, mask_t0, mask_s1, mask_t1;
>> -    float spt0[2], spt1[2];
>> -    float mpt0[2], mpt1[2];
>>
>> -    spt0[0] = srcX;
>> -    spt0[1] = srcY;
>> -    spt1[0] = srcX + width;
>> -    spt1[1] = srcY + height;
>>
>> -    mpt0[0] = maskX;
>> -    mpt0[1] = maskY;
>> -    mpt1[0] = maskX + width;
>> -    mpt1[1] = maskY + height;
>> +    if (!src_color) {
>> +     float spt0[2], spt1[2];
>>
>> -    if (src_matrix) {
>> -     map_point((float *)src_matrix, spt0[0], spt0[1], &spt0[0], &spt0[1]);
>> -     map_point((float *)src_matrix, spt1[0], spt1[1], &spt1[0], &spt1[1]);
>> -    }
>> +     spt0[0] = srcX;
>> +     spt0[1] = srcY;
>> +     spt1[0] = srcX + width;
>> +     spt1[1] = srcY + height;
>>
>> -    if (mask_matrix) {
>> -     map_point((float *)mask_matrix, mpt0[0], mpt0[1], &mpt0[0], &mpt0[1]);
>> -     map_point((float *)mask_matrix, mpt1[0], mpt1[1], &mpt1[0], &mpt1[1]);
>> +     if (src_matrix) {
>> +         map_point((float *)src_matrix, spt0[0], spt0[1], &spt0[0], &spt0[1]);
>> +         map_point((float *)src_matrix, spt1[0], spt1[1], &spt1[0], &spt1[1]);
>> +     }
>> +
>> +     src_s0 = spt0[0] / src->width0;
>> +     src_t0 = spt0[1] / src->height0;
>> +     src_s1 = spt1[0] / src->width0;
>> +     src_t1 = spt1[1] / src->height0;
>>      }
>>
>> -    src_s0 = spt0[0] / src->width0;
>> -    src_t0 = spt0[1] / src->height0;
>> -    src_s1 = spt1[0] / src->width0;
>> -    src_t1 = spt1[1] / src->height0;
>> +    if (!mask_color) {
>> +     float mpt0[2], mpt1[2];
>> +
>> +     mpt0[0] = maskX;
>> +     mpt0[1] = maskY;
>> +     mpt1[0] = maskX + width;
>> +     mpt1[1] = maskY + height;
>>
>> -    mask_s0 = mpt0[0] / mask->width0;
>> -    mask_t0 = mpt0[1] / mask->height0;
>> -    mask_s1 = mpt1[0] / mask->width0;
>> -    mask_t1 = mpt1[1] / mask->height0;
>> +     if (mask_matrix) {
>> +         map_point((float *)mask_matrix, mpt0[0], mpt0[1], &mpt0[0], &mpt0[1]);
>> +         map_point((float *)mask_matrix, mpt1[0], mpt1[1], &mpt1[0], &mpt1[1]);
>> +     }
>> +
>> +     mask_s0 = mpt0[0] / mask->width0;
>> +     mask_t0 = mpt0[1] / mask->height0;
>> +     mask_s1 = mpt1[0] / mask->width0;
>> +     mask_t1 = mpt1[1] / mask->height0;
>> +    }
>>
>>      /* 1st vertex */
>> -    add_vertex_2tex(r, dstX, dstY,
>> -                 src_s0, src_t0, mask_s0, mask_t0);
>> +    add_vertex_coord(r, dstX, dstY);
>> +    if (src_color)
>> +     add_vertex_color(r, src_color);
>> +    else
>> +     add_vertex_coord(r, src_s0, src_t0);
>> +    if (mask_color)
>> +     add_vertex_color(r, mask_color);
>> +    else
>> +     add_vertex_coord(r, mask_s0, mask_t0);
>>      /* 2nd vertex */
>> -    add_vertex_2tex(r, dstX + width, dstY,
>> -                 src_s1, src_t0, mask_s1, mask_t0);
>> +    add_vertex_coord(r, dstX + width, dstY);
>> +    if (src_color)
>> +     add_vertex_color(r, src_color);
>> +    else
>> +     add_vertex_coord(r, src_s1, src_t0);
>> +    if (mask_color)
>> +     add_vertex_color(r, mask_color);
>> +    else
>> +     add_vertex_coord(r, mask_s1, mask_t0);
>>      /* 3rd vertex */
>> -    add_vertex_2tex(r, dstX + width, dstY + height,
>> -                 src_s1, src_t1, mask_s1, mask_t1);
>> +    add_vertex_coord(r, dstX + width, dstY + height);
>> +    if (src_color)
>> +     add_vertex_color(r, src_color);
>> +    else
>> +     add_vertex_coord(r, src_s1, src_t1);
>> +    if (mask_color)
>> +     add_vertex_color(r, mask_color);
>> +    else
>> +     add_vertex_coord(r, mask_s1, mask_t1);
>>      /* 4th vertex */
>> -    add_vertex_2tex(r, dstX, dstY + height,
>> -                 src_s0, src_t1, mask_s0, mask_t1);
>> +    add_vertex_coord(r, dstX, dstY + height);
>> +    if (src_color)
>> +     add_vertex_color(r, src_color);
>> +    else
>> +     add_vertex_coord(r, src_s0, src_t1);
>> +    if (mask_color)
>> +     add_vertex_color(r, mask_color);
>> +    else
>> +     add_vertex_coord(r, mask_s0, mask_t1);
>>  }
>>
>>  static void
>> @@ -310,13 +332,17 @@ setup_vertex_data_yuv(struct xa_context *r,
>>      t1 = spt1[1] / tex->height0;
>>
>>      /* 1st vertex */
>> -    add_vertex_1tex(r, dstX, dstY, s0, t0);
>> +    add_vertex_coord(r, dstX, dstY);
>> +    add_vertex_coord(r, s0, t0);
>>      /* 2nd vertex */
>> -    add_vertex_1tex(r, dstX + dstW, dstY, s1, t0);
>> +    add_vertex_coord(r, dstX + dstW, dstY);
>> +    add_vertex_coord(r, s1, t0);
>>      /* 3rd vertex */
>> -    add_vertex_1tex(r, dstX + dstW, dstY + dstH, s1, t1);
>> +    add_vertex_coord(r, dstX + dstW, dstY + dstH);
>> +    add_vertex_coord(r, s1, t1);
>>      /* 4th vertex */
>> -    add_vertex_1tex(r, dstX, dstY + dstH, s0, t1);
>> +    add_vertex_coord(r, dstX, dstY + dstH);
>> +    add_vertex_coord(r, s0, t1);
>>  }
>>
>>  /* Set up framebuffer, viewport and vertex shader constant buffer
>> @@ -493,10 +519,14 @@ renderer_copy(struct xa_context *r,
>>
>>      /* draw quad */
>>      renderer_draw_conditional(r, 4 * 8);
>> -    add_vertex_1tex(r, x0, y0, s0, t0);
>> -    add_vertex_1tex(r, x1, y0, s1, t0);
>> -    add_vertex_1tex(r, x1, y1, s1, t1);
>> -    add_vertex_1tex(r, x0, y1, s0, t1);
>> +    add_vertex_coord(r, x0, y0);
>> +    add_vertex_coord(r, s0, t0);
>> +    add_vertex_coord(r, x1, y0);
>> +    add_vertex_coord(r, s1, t0);
>> +    add_vertex_coord(r, x1, y1);
>> +    add_vertex_coord(r, s1, t1);
>> +    add_vertex_coord(r, x0, y1);
>> +    add_vertex_coord(r, s0, t1);
>>  }
>>
>>  void
>> @@ -539,13 +569,17 @@ renderer_solid(struct xa_context *r,
>>      renderer_draw_conditional(r, 4 * 8);
>>
>>      /* 1st vertex */
>> -    add_vertex_color(r, x0, y0, color);
>> +    add_vertex_coord(r, x0, y0);
>> +    add_vertex_color(r, color);
>>      /* 2nd vertex */
>> -    add_vertex_color(r, x1, y0, color);
>> +    add_vertex_coord(r, x1, y0);
>> +    add_vertex_color(r, color);
>>      /* 3rd vertex */
>> -    add_vertex_color(r, x1, y1, color);
>> +    add_vertex_coord(r, x1, y1);
>> +    add_vertex_color(r, color);
>>      /* 4th vertex */
>> -    add_vertex_color(r, x0, y1, color);
>> +    add_vertex_coord(r, x0, y1);
>> +    add_vertex_color(r, color);
>>  }
>>
>>  void
>> @@ -555,9 +589,14 @@ renderer_draw_flush(struct xa_context *r)
>>  }
>>
>>  void
>> -renderer_begin_textures(struct xa_context *r)
>> +renderer_begin_textures(struct xa_context *r,
>> +     const struct xa_composite *comp)
>>  {
>> -    r->attrs_per_vertex = 1 + r->num_bound_samplers;
>> +    r->attrs_per_vertex = 1;
>> +    if (comp->src)
>> +     r->attrs_per_vertex++;
>> +    if (comp->mask)
>> +     r->attrs_per_vertex++;
>>      r->buffer_size = 0;
>>  }
>>
>> @@ -592,7 +631,9 @@ renderer_texture(struct xa_context *r,
>>                        pos[0], pos[1], /* src */
>>                        pos[4], pos[5], /* dst */
>>                        width, height,
>> -                      sampler_view[0]->texture, src_matrix);
>> +                      sampler_view[0]->texture,
>> +                      r->has_solid_color ? NULL : src_matrix,
>> +                      r->has_solid_color ? r->solid_color : NULL);
>>       break;
>>      case 3:
>>       renderer_draw_conditional(r, 4 * 12);
>> @@ -601,8 +642,12 @@ renderer_texture(struct xa_context *r,
>>                        pos[2], pos[3], /* mask */
>>                        pos[4], pos[5], /* dst */
>>                        width, height,
>> -                      sampler_view[0]->texture, sampler_view[1]->texture,
>> -                      src_matrix, mask_matrix);
>> +                      r->has_solid_color ? NULL : sampler_view[0]->texture,
>> +                      r->has_solid_mask ? NULL : sampler_view[1]->texture,
>> +                      r->has_solid_color ? NULL : src_matrix,
>> +                      r->has_solid_color ? r->solid_color : NULL,
>> +                      r->has_solid_mask ? NULL : mask_matrix,
>> +                      r->has_solid_mask ? r->solid_mask : NULL);
>>       break;
>>      default:
>>       break;
>> diff --git a/src/gallium/state_trackers/xa/xa_tgsi.c b/src/gallium/state_trackers/xa/xa_tgsi.c
>> index c7454c9..9cda4c3 100644
>> --- a/src/gallium/state_trackers/xa/xa_tgsi.c
>> +++ b/src/gallium/state_trackers/xa/xa_tgsi.c
>> @@ -42,14 +42,14 @@
>>  /* Vertex shader:
>>   * IN[0]    = vertex pos
>>   * IN[1]    = src tex coord | solid fill color
>> - * IN[2]    = mask tex coord
>> + * IN[2]    = mask tex coord | solid mask color
>>   * IN[3]    = dst tex coord
>>   * CONST[0] = (2/dst_width, 2/dst_height, 1, 1)
>>   * CONST[1] = (-1, -1, 0, 0)
>>   *
>>   * OUT[0]   = vertex pos
>>   * OUT[1]   = src tex coord | solid fill color
>> - * OUT[2]   = mask tex coord
>> + * OUT[2]   = mask tex coord | solid mask color
>>   * OUT[3]   = dst tex coord
>>   */
>>
>> @@ -58,7 +58,7 @@
>>   * SAMP[1]  = mask
>>   * SAMP[2]  = dst
>>   * IN[0]    = pos src | solid fill color
>> - * IN[1]    = pos mask
>> + * IN[1]    = pos mask | solid mask color
>>   * IN[2]    = pos dst
>>   * CONST[0] = (0, 0, 0, 1)
>>   *
>> @@ -268,6 +268,7 @@ create_vs(struct pipe_context *pipe, unsigned vs_traits)
>>      boolean is_fill = (vs_traits & VS_FILL) != 0;
>>      boolean is_composite = (vs_traits & VS_COMPOSITE) != 0;
>>      boolean has_mask = (vs_traits & VS_MASK) != 0;
>> +    boolean is_solid_mask = (vs_traits & VS_SOLID_MASK) != 0;
>>      boolean is_yuv = (vs_traits & VS_YUV) != 0;
>>      unsigned input_slot = 0;
>>
>> @@ -296,15 +297,17 @@ create_vs(struct pipe_context *pipe, unsigned vs_traits)
>>       src = ureg_DECL_vs_input(ureg, input_slot++);
>>       dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 0);
>>       ureg_MOV(ureg, dst, src);
>> -    }
>> -
>> -    if (is_fill) {
>> +    } else if (is_fill) {
>>       src = ureg_DECL_vs_input(ureg, input_slot++);
>>       dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
>>       ureg_MOV(ureg, dst, src);
>>      }
>>
>> -    if (has_mask) {
>> +    if (is_solid_mask) {
>> +     src = ureg_DECL_vs_input(ureg, input_slot++);
>> +     dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 1);
>> +     ureg_MOV(ureg, dst, src);
>> +    } else if (has_mask) {
>>       src = ureg_DECL_vs_input(ureg, input_slot++);
>>       dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 1);
>>       ureg_MOV(ureg, dst, src);
>> @@ -436,6 +439,7 @@ create_fs(struct pipe_context *pipe, unsigned fs_traits)
>>      struct ureg_dst out;
>>      struct ureg_src imm0 = { 0 };
>>      unsigned has_mask = (fs_traits & FS_MASK) != 0;
>> +    unsigned is_solid_mask = (fs_traits & FS_SOLID_MASK) != 0;
>>      unsigned is_fill = (fs_traits & FS_FILL) != 0;
>>      unsigned is_composite = (fs_traits & FS_COMPOSITE) != 0;
>>      unsigned is_solid = (fs_traits & FS_SOLID_FILL) != 0;
>> @@ -492,7 +496,11 @@ create_fs(struct pipe_context *pipe, unsigned fs_traits)
>>       return create_yuv_shader(pipe, ureg);
>>      }
>>
>> -    if (has_mask) {
>> +    if (is_solid_mask) {
>> +     mask_pos = ureg_DECL_fs_input(ureg,
>> +                                    TGSI_SEMANTIC_COLOR, 1,
>> +                                    TGSI_INTERPOLATE_PERSPECTIVE);
>> +    } else if (has_mask) {
>>       mask_sampler = ureg_DECL_sampler(ureg, 1);
>>       mask_pos = ureg_DECL_fs_input(ureg,
>>                                     TGSI_SEMANTIC_GENERIC, 1,
>> @@ -552,10 +560,15 @@ create_fs(struct pipe_context *pipe, unsigned fs_traits)
>>           ureg_MOV(ureg, out, ureg_src(src));
>>      }
>>
>> -    if (has_mask) {
>> +    if (is_solid_mask) {
>> +     mask = ureg_dst(mask_pos);
>> +    } else if (has_mask) {
>>       mask = ureg_DECL_temporary(ureg);
>>       xrender_tex(ureg, mask, mask_pos, mask_sampler, imm0,
>>                   mask_repeat_none, mask_swizzle, mask_set_alpha);
>> +    }
>> +
>> +    if (has_mask) {
>>       /* src IN mask */
>>
>>       src_in_mask(ureg, (dst_luminance) ? src : out, ureg_src(src),
On 04/02/2014 11:17 PM, Thomas Hellstrom wrote:
> On 04/01/2014 05:04 PM, Rob Clark wrote:
>> From: Rob Clark <robclark@freedesktop.org>
>>
>> Add support to property handle solid-fill src and/or mask.  Without this
>> we fallback to sw a lot for common things like text rendering.
>>
>> Signed-off-by: Rob Clark <robclark@freedesktop.org>
>> ---
>>   src/gallium/state_trackers/xa/xa_composite.c |  88 ++++----
>>   src/gallium/state_trackers/xa/xa_priv.h      |   7 +-
>>   src/gallium/state_trackers/xa/xa_renderer.c  | 289 ++++++++++++++++-----------
>>   src/gallium/state_trackers/xa/xa_tgsi.c      |  31 ++-
>>   4 files changed, 242 insertions(+), 173 deletions(-)
>
> Rob,
> While testing this patch it looks like we sometimes set two samplers,
> and the first one is NULL.
> The SVGA driver asserts on that condition.
> We might need to move the active sampler to the first entry in that
> case, and adjust tex coords and shader accordingly.
>
> I'll discuss with BrianP.

I think the root problem is a disagreement between texture samplers and 
sampler views.  If a texture sampler is non-null, the corresponding 
sampler view be should be non-null too, and vice versa.

We're tripping over an assertion when a a sampler view is non-null but 
the corresponding sampler is NULL.

I'm going to write a patch for the driver to be more resilient in that 
situation.

-Brian
On Thu, Apr 3, 2014 at 10:07 AM, Brian Paul <brianp@vmware.com> wrote:
> On 04/02/2014 11:17 PM, Thomas Hellstrom wrote:
>>
>> On 04/01/2014 05:04 PM, Rob Clark wrote:
>>>
>>> From: Rob Clark <robclark@freedesktop.org>
>>>
>>> Add support to property handle solid-fill src and/or mask.  Without this
>>> we fallback to sw a lot for common things like text rendering.
>>>
>>> Signed-off-by: Rob Clark <robclark@freedesktop.org>
>>> ---
>>>   src/gallium/state_trackers/xa/xa_composite.c |  88 ++++----
>>>   src/gallium/state_trackers/xa/xa_priv.h      |   7 +-
>>>   src/gallium/state_trackers/xa/xa_renderer.c  | 289
>>> ++++++++++++++++-----------
>>>   src/gallium/state_trackers/xa/xa_tgsi.c      |  31 ++-
>>>   4 files changed, 242 insertions(+), 173 deletions(-)
>>
>>
>> Rob,
>> While testing this patch it looks like we sometimes set two samplers,
>> and the first one is NULL.
>> The SVGA driver asserts on that condition.
>> We might need to move the active sampler to the first entry in that
>> case, and adjust tex coords and shader accordingly.
>>
>> I'll discuss with BrianP.
>
>
> I think the root problem is a disagreement between texture samplers and
> sampler views.  If a texture sampler is non-null, the corresponding sampler
> view be should be non-null too, and vice versa.
>
> We're tripping over an assertion when a a sampler view is non-null but the
> corresponding sampler is NULL.

Right..

Well, I think it would be not to hard to make things always start with
SAMP[0], which would avoid this.  But I am pretty fuzzy about whether
it is the driver or state tracker that is wrong here..  I started with
the assumption that it was just a freedreno bug, but if it causes
problem w/ vmware too, then maybe the state tracker is at fault.

BR,
-R

> I'm going to write a patch for the driver to be more resilient in that
> situation.
>
> -Brian
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
On 04/03/2014 08:13 AM, Rob Clark wrote:
> On Thu, Apr 3, 2014 at 10:07 AM, Brian Paul <brianp@vmware.com> wrote:
>> On 04/02/2014 11:17 PM, Thomas Hellstrom wrote:
>>>
>>> On 04/01/2014 05:04 PM, Rob Clark wrote:
>>>>
>>>> From: Rob Clark <robclark@freedesktop.org>
>>>>
>>>> Add support to property handle solid-fill src and/or mask.  Without this
>>>> we fallback to sw a lot for common things like text rendering.
>>>>
>>>> Signed-off-by: Rob Clark <robclark@freedesktop.org>
>>>> ---
>>>>    src/gallium/state_trackers/xa/xa_composite.c |  88 ++++----
>>>>    src/gallium/state_trackers/xa/xa_priv.h      |   7 +-
>>>>    src/gallium/state_trackers/xa/xa_renderer.c  | 289
>>>> ++++++++++++++++-----------
>>>>    src/gallium/state_trackers/xa/xa_tgsi.c      |  31 ++-
>>>>    4 files changed, 242 insertions(+), 173 deletions(-)
>>>
>>>
>>> Rob,
>>> While testing this patch it looks like we sometimes set two samplers,
>>> and the first one is NULL.
>>> The SVGA driver asserts on that condition.
>>> We might need to move the active sampler to the first entry in that
>>> case, and adjust tex coords and shader accordingly.
>>>
>>> I'll discuss with BrianP.
>>
>>
>> I think the root problem is a disagreement between texture samplers and
>> sampler views.  If a texture sampler is non-null, the corresponding sampler
>> view be should be non-null too, and vice versa.
>>
>> We're tripping over an assertion when a a sampler view is non-null but the
>> corresponding sampler is NULL.
>
> Right..
>
> Well, I think it would be not to hard to make things always start with
> SAMP[0], which would avoid this.  But I am pretty fuzzy about whether
> it is the driver or state tracker that is wrong here..  I started with
> the assumption that it was just a freedreno bug, but if it causes
> problem w/ vmware too, then maybe the state tracker is at fault.

I believe the general policy is that drivers can assume they're being 
passed valid input and consistent state.  State trackers shouldn't pass 
inconsistent state to drivers.

In this case, the number of texture samplers and sampler views is 
inconsistent.  The drivers could examine the current shader to determine 
which samplers/views are actually used (which might be a subset of what 
was specified by the state tracker).  But that's extra work that all 
drivers would have to implement.  It seems much more economical to take 
care of this in the state trackers.

-Brian
On Thu, Apr 3, 2014 at 10:41 AM, Brian Paul <brianp@vmware.com> wrote:
> On 04/03/2014 08:13 AM, Rob Clark wrote:
>>
>> On Thu, Apr 3, 2014 at 10:07 AM, Brian Paul <brianp@vmware.com> wrote:
>>>
>>> On 04/02/2014 11:17 PM, Thomas Hellstrom wrote:
>>>>
>>>>
>>>> On 04/01/2014 05:04 PM, Rob Clark wrote:
>>>>>
>>>>>
>>>>> From: Rob Clark <robclark@freedesktop.org>
>>>>>
>>>>> Add support to property handle solid-fill src and/or mask.  Without
>>>>> this
>>>>> we fallback to sw a lot for common things like text rendering.
>>>>>
>>>>> Signed-off-by: Rob Clark <robclark@freedesktop.org>
>>>>> ---
>>>>>    src/gallium/state_trackers/xa/xa_composite.c |  88 ++++----
>>>>>    src/gallium/state_trackers/xa/xa_priv.h      |   7 +-
>>>>>    src/gallium/state_trackers/xa/xa_renderer.c  | 289
>>>>> ++++++++++++++++-----------
>>>>>    src/gallium/state_trackers/xa/xa_tgsi.c      |  31 ++-
>>>>>    4 files changed, 242 insertions(+), 173 deletions(-)
>>>>
>>>>
>>>>
>>>> Rob,
>>>> While testing this patch it looks like we sometimes set two samplers,
>>>> and the first one is NULL.
>>>> The SVGA driver asserts on that condition.
>>>> We might need to move the active sampler to the first entry in that
>>>> case, and adjust tex coords and shader accordingly.
>>>>
>>>> I'll discuss with BrianP.
>>>
>>>
>>>
>>> I think the root problem is a disagreement between texture samplers and
>>> sampler views.  If a texture sampler is non-null, the corresponding
>>> sampler
>>> view be should be non-null too, and vice versa.
>>>
>>> We're tripping over an assertion when a a sampler view is non-null but
>>> the
>>> corresponding sampler is NULL.
>>
>>
>> Right..
>>
>> Well, I think it would be not to hard to make things always start with
>> SAMP[0], which would avoid this.  But I am pretty fuzzy about whether
>> it is the driver or state tracker that is wrong here..  I started with
>> the assumption that it was just a freedreno bug, but if it causes
>> problem w/ vmware too, then maybe the state tracker is at fault.
>
>
> I believe the general policy is that drivers can assume they're being passed
> valid input and consistent state.  State trackers shouldn't pass
> inconsistent state to drivers.
>
> In this case, the number of texture samplers and sampler views is
> inconsistent.  The drivers could examine the current shader to determine
> which samplers/views are actually used (which might be a subset of what was
> specified by the state tracker).  But that's extra work that all drivers
> would have to implement.  It seems much more economical to take care of this
> in the state trackers.

ok.. I'll have a go later today at re-working this patch to just use
SAMP[0..n] rather than hard-coding SAMP[0] to src and SAMP[1] to mask.
 That seems like the easiest way to fix this.

I don't suppose you tested just the other 3 patches?  If those are ok
for vmware, I think we could go ahead and push 2/4 thru 4/4.

BR,
-R

> -Brian
On 04/03/2014 08:41 AM, Brian Paul wrote:
> On 04/03/2014 08:13 AM, Rob Clark wrote:
>> On Thu, Apr 3, 2014 at 10:07 AM, Brian Paul <brianp@vmware.com> wrote:
>>> On 04/02/2014 11:17 PM, Thomas Hellstrom wrote:
>>>>
>>>> On 04/01/2014 05:04 PM, Rob Clark wrote:
>>>>>
>>>>> From: Rob Clark <robclark@freedesktop.org>
>>>>>
>>>>> Add support to property handle solid-fill src and/or mask.  Without
>>>>> this
>>>>> we fallback to sw a lot for common things like text rendering.
>>>>>
>>>>> Signed-off-by: Rob Clark <robclark@freedesktop.org>
>>>>> ---
>>>>>    src/gallium/state_trackers/xa/xa_composite.c |  88 ++++----
>>>>>    src/gallium/state_trackers/xa/xa_priv.h      |   7 +-
>>>>>    src/gallium/state_trackers/xa/xa_renderer.c  | 289
>>>>> ++++++++++++++++-----------
>>>>>    src/gallium/state_trackers/xa/xa_tgsi.c      |  31 ++-
>>>>>    4 files changed, 242 insertions(+), 173 deletions(-)
>>>>
>>>>
>>>> Rob,
>>>> While testing this patch it looks like we sometimes set two samplers,
>>>> and the first one is NULL.
>>>> The SVGA driver asserts on that condition.
>>>> We might need to move the active sampler to the first entry in that
>>>> case, and adjust tex coords and shader accordingly.
>>>>
>>>> I'll discuss with BrianP.
>>>
>>>
>>> I think the root problem is a disagreement between texture samplers and
>>> sampler views.  If a texture sampler is non-null, the corresponding
>>> sampler
>>> view be should be non-null too, and vice versa.
>>>
>>> We're tripping over an assertion when a a sampler view is non-null
>>> but the
>>> corresponding sampler is NULL.
>>
>> Right..
>>
>> Well, I think it would be not to hard to make things always start with
>> SAMP[0], which would avoid this.  But I am pretty fuzzy about whether
>> it is the driver or state tracker that is wrong here..  I started with
>> the assumption that it was just a freedreno bug, but if it causes
>> problem w/ vmware too, then maybe the state tracker is at fault.
>
> I believe the general policy is that drivers can assume they're being
> passed valid input and consistent state.  State trackers shouldn't pass
> inconsistent state to drivers.
>
> In this case, the number of texture samplers and sampler views is
> inconsistent.  The drivers could examine the current shader to determine
> which samplers/views are actually used (which might be a subset of what
> was specified by the state tracker).  But that's extra work that all
> drivers would have to implement.  It seems much more economical to take
> care of this in the state trackers.

Though, with the DX10-level SAMPLE instructions, samplers and sampler 
views really are independent so the number could be different there. 
But with TEX instructions, the numbers should be the same.

-Brian
btw, I think I've tracked down at least one of the rendercheck issues
I was having.  Which seems to be a pre-existing condition.  The
problem is a composite operation with xrgb src and a8 dst.  Ends up
generating a shader along the lines of:

  0: TEX TEMP[0], IN[0], SAMP[0], 2D
  1: MOV TEMP[0].w, IMM[..]
  2: MOV OUT[0], TEMP[0].wwww
  3: END

in this case, my compiler optimizes out the texture fetch.  But that
causes a bit of confusion in freedreno because half the driver thinks
there is a texture and sets things up accordingly.

I'm not entirely sure if XA should detect this.. or if that should be
fixed in the driver..

BR,
-R


On Thu, Apr 3, 2014 at 10:53 AM, Brian Paul <brianp@vmware.com> wrote:
> On 04/03/2014 08:41 AM, Brian Paul wrote:
>>
>> On 04/03/2014 08:13 AM, Rob Clark wrote:
>>>
>>> On Thu, Apr 3, 2014 at 10:07 AM, Brian Paul <brianp@vmware.com> wrote:
>>>>
>>>> On 04/02/2014 11:17 PM, Thomas Hellstrom wrote:
>>>>>
>>>>>
>>>>> On 04/01/2014 05:04 PM, Rob Clark wrote:
>>>>>>
>>>>>>
>>>>>> From: Rob Clark <robclark@freedesktop.org>
>>>>>>
>>>>>> Add support to property handle solid-fill src and/or mask.  Without
>>>>>> this
>>>>>> we fallback to sw a lot for common things like text rendering.
>>>>>>
>>>>>> Signed-off-by: Rob Clark <robclark@freedesktop.org>
>>>>>> ---
>>>>>>    src/gallium/state_trackers/xa/xa_composite.c |  88 ++++----
>>>>>>    src/gallium/state_trackers/xa/xa_priv.h      |   7 +-
>>>>>>    src/gallium/state_trackers/xa/xa_renderer.c  | 289
>>>>>> ++++++++++++++++-----------
>>>>>>    src/gallium/state_trackers/xa/xa_tgsi.c      |  31 ++-
>>>>>>    4 files changed, 242 insertions(+), 173 deletions(-)
>>>>>
>>>>>
>>>>>
>>>>> Rob,
>>>>> While testing this patch it looks like we sometimes set two samplers,
>>>>> and the first one is NULL.
>>>>> The SVGA driver asserts on that condition.
>>>>> We might need to move the active sampler to the first entry in that
>>>>> case, and adjust tex coords and shader accordingly.
>>>>>
>>>>> I'll discuss with BrianP.
>>>>
>>>>
>>>>
>>>> I think the root problem is a disagreement between texture samplers and
>>>> sampler views.  If a texture sampler is non-null, the corresponding
>>>> sampler
>>>> view be should be non-null too, and vice versa.
>>>>
>>>> We're tripping over an assertion when a a sampler view is non-null
>>>> but the
>>>> corresponding sampler is NULL.
>>>
>>>
>>> Right..
>>>
>>> Well, I think it would be not to hard to make things always start with
>>> SAMP[0], which would avoid this.  But I am pretty fuzzy about whether
>>> it is the driver or state tracker that is wrong here..  I started with
>>> the assumption that it was just a freedreno bug, but if it causes
>>> problem w/ vmware too, then maybe the state tracker is at fault.
>>
>>
>> I believe the general policy is that drivers can assume they're being
>> passed valid input and consistent state.  State trackers shouldn't pass
>> inconsistent state to drivers.
>>
>> In this case, the number of texture samplers and sampler views is
>> inconsistent.  The drivers could examine the current shader to determine
>> which samplers/views are actually used (which might be a subset of what
>> was specified by the state tracker).  But that's extra work that all
>> drivers would have to implement.  It seems much more economical to take
>> care of this in the state trackers.
>
>
> Though, with the DX10-level SAMPLE instructions, samplers and sampler views
> really are independent so the number could be different there. But with TEX
> instructions, the numbers should be the same.
>
> -Brian
>
>
Am 08.04.2014 13:49, schrieb Rob Clark:
> btw, I think I've tracked down at least one of the rendercheck issues
> I was having.  Which seems to be a pre-existing condition.  The
> problem is a composite operation with xrgb src and a8 dst.  Ends up
> generating a shader along the lines of:
> 
>   0: TEX TEMP[0], IN[0], SAMP[0], 2D
>   1: MOV TEMP[0].w, IMM[..]
>   2: MOV OUT[0], TEMP[0].wwww
>   3: END
> 
> in this case, my compiler optimizes out the texture fetch.  But that
> causes a bit of confusion in freedreno because half the driver thinks
> there is a texture and sets things up accordingly.
> 
> I'm not entirely sure if XA should detect this.. or if that should be
> fixed in the driver..
I think the driver should handle that correctly in any case - I could easily
see such shaders being generated in other places too. Obviously, a
driver can optimize away the tex instruction but is not required to do
so (though it would be better if it did...), the shader is perfectly
valid (but needs the sampler to be set up correctly).
If the state tracker should avoid it in the first place, I'm not
certain. If it doesn't add too much complexity, sounds like a good idea.
But just relying on dead code elimination in the drivers doesn't sound
too unreasonable to me neither.

Roland
On Tue, Apr 8, 2014 at 5:41 PM, Roland Scheidegger <sroland@vmware.com> wrote:
> Am 08.04.2014 13:49, schrieb Rob Clark:
>> btw, I think I've tracked down at least one of the rendercheck issues
>> I was having.  Which seems to be a pre-existing condition.  The
>> problem is a composite operation with xrgb src and a8 dst.  Ends up
>> generating a shader along the lines of:
>>
>>   0: TEX TEMP[0], IN[0], SAMP[0], 2D
>>   1: MOV TEMP[0].w, IMM[..]
>>   2: MOV OUT[0], TEMP[0].wwww
>>   3: END
>>
>> in this case, my compiler optimizes out the texture fetch.  But that
>> causes a bit of confusion in freedreno because half the driver thinks
>> there is a texture and sets things up accordingly.
>>
>> I'm not entirely sure if XA should detect this.. or if that should be
>> fixed in the driver..
> I think the driver should handle that correctly in any case - I could easily
> see such shaders being generated in other places too. Obviously, a
> driver can optimize away the tex instruction but is not required to do
> so (though it would be better if it did...), the shader is perfectly
> valid (but needs the sampler to be set up correctly).
> If the state tracker should avoid it in the first place, I'm not
> certain. If it doesn't add too much complexity, sounds like a good idea.
> But just relying on dead code elimination in the drivers doesn't sound
> too unreasonable to me neither.

fwiw, the patch to avoid this in XA turned out to not be too bad (I
included it in the series I sent earlier today).  I also fixed it in
freedreno, because the same issue could happen with binning pass
shaders (basically a simplified version of vertex shader used for
binning pass).  But for more conventional gpus I think avoiding
binding textures is probably a nice thing.

BR,
-R


> Roland
On 04/03/2014 04:07 PM, Brian Paul wrote:
> On 04/02/2014 11:17 PM, Thomas Hellstrom wrote:
>> On 04/01/2014 05:04 PM, Rob Clark wrote:
>>> From: Rob Clark <robclark@freedesktop.org>
>>>
>>> Add support to property handle solid-fill src and/or mask.  Without
>>> this
>>> we fallback to sw a lot for common things like text rendering.
>>>
>>> Signed-off-by: Rob Clark <robclark@freedesktop.org>
>>> ---
>>>   src/gallium/state_trackers/xa/xa_composite.c |  88 ++++----
>>>   src/gallium/state_trackers/xa/xa_priv.h      |   7 +-
>>>   src/gallium/state_trackers/xa/xa_renderer.c  | 289
>>> ++++++++++++++++-----------
>>>   src/gallium/state_trackers/xa/xa_tgsi.c      |  31 ++-
>>>   4 files changed, 242 insertions(+), 173 deletions(-)
>>
>> Rob,
>> While testing this patch it looks like we sometimes set two samplers,
>> and the first one is NULL.
>> The SVGA driver asserts on that condition.
>> We might need to move the active sampler to the first entry in that
>> case, and adjust tex coords and shader accordingly.
>>
>> I'll discuss with BrianP.
>
> I think the root problem is a disagreement between texture samplers
> and sampler views.  If a texture sampler is non-null, the
> corresponding sampler view be should be non-null too, and vice versa.
>
> We're tripping over an assertion when a a sampler view is non-null but
> the corresponding sampler is NULL.
>
> I'm going to write a patch for the driver to be more resilient in that
> situation.
>
> -Brian

Brian, This is a different problem.
Here, the state tracker sets up sampler[0] and sampler_view[0] to NULL,
but sampler[1] and sampler_view[1] to NON-NULL, but
samplers and sampler views are consistent.

The question is whether that's OK, or whether that's not allowed.

/Thomas








>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev@lists.freedesktop.org
> https://urldefense.proofpoint.com/v1/url?u=http://lists.freedesktop.org/mailman/listinfo/mesa-dev&k=oIvRg1%2BdGAgOoM1BIlLLqw%3D%3D%0A&r=l5Ago9ekmVFZ3c4M6eauqrJWGwjf6fTb%2BP3CxbBFkVM%3D%0A&m=VGqKhmPosyC9QpnoVvQFOszMOE3eB%2B956me7wcCEnEs%3D%0A&s=5dd06c74671afd42afbd55b02f0c81895463044783e8d6f7a692963750b02123
>
On 04/09/2014 11:50 AM, Thomas Hellstrom wrote:
> On 04/03/2014 04:07 PM, Brian Paul wrote:
>> On 04/02/2014 11:17 PM, Thomas Hellstrom wrote:
>>> On 04/01/2014 05:04 PM, Rob Clark wrote:
>>>> From: Rob Clark <robclark@freedesktop.org>
>>>>
>>>> Add support to property handle solid-fill src and/or mask.  Without
>>>> this
>>>> we fallback to sw a lot for common things like text rendering.
>>>>
>>>> Signed-off-by: Rob Clark <robclark@freedesktop.org>
>>>> ---
>>>>    src/gallium/state_trackers/xa/xa_composite.c |  88 ++++----
>>>>    src/gallium/state_trackers/xa/xa_priv.h      |   7 +-
>>>>    src/gallium/state_trackers/xa/xa_renderer.c  | 289
>>>> ++++++++++++++++-----------
>>>>    src/gallium/state_trackers/xa/xa_tgsi.c      |  31 ++-
>>>>    4 files changed, 242 insertions(+), 173 deletions(-)
>>>
>>> Rob,
>>> While testing this patch it looks like we sometimes set two samplers,
>>> and the first one is NULL.
>>> The SVGA driver asserts on that condition.
>>> We might need to move the active sampler to the first entry in that
>>> case, and adjust tex coords and shader accordingly.
>>>
>>> I'll discuss with BrianP.
>>
>> I think the root problem is a disagreement between texture samplers
>> and sampler views.  If a texture sampler is non-null, the
>> corresponding sampler view be should be non-null too, and vice versa.
>>
>> We're tripping over an assertion when a a sampler view is non-null but
>> the corresponding sampler is NULL.
>>
>> I'm going to write a patch for the driver to be more resilient in that
>> situation.
>>
>> -Brian
>
> Brian, This is a different problem.
> Here, the state tracker sets up sampler[0] and sampler_view[0] to NULL,
> but sampler[1] and sampler_view[1] to NON-NULL, but
> samplers and sampler views are consistent.
>
> The question is whether that's OK, or whether that's not allowed.

I think that's OK.

-Brian