[cairo-commit] 16 commits - src/cairo-gl-surface.c src/cairo-gstate.c src/cairo-surface.c src/drm test/Makefile.am test/rounded-rectangle-fill.ref.png test/rounded-rectangle-stroke.ref.png test/xcb-surface-source.c

Chris Wilson ickle at kemper.freedesktop.org
Thu Mar 4 00:25:29 PST 2010


 src/cairo-gl-surface.c                |    1 
 src/cairo-gstate.c                    |  100 ++++++++++++++++++------------
 src/cairo-surface.c                   |   22 ++----
 src/drm/cairo-drm-i915-glyphs.c       |   13 ---
 src/drm/cairo-drm-i915-private.h      |   23 ++++---
 src/drm/cairo-drm-i915-shader.c       |   83 +++++++++++++------------
 src/drm/cairo-drm-i915-spans.c        |   42 ------------
 src/drm/cairo-drm-i915-surface.c      |  111 ++++++++++++++++++++++------------
 src/drm/cairo-drm-i965-private.h      |   11 ---
 src/drm/cairo-drm-i965-shader.c       |   26 +------
 src/drm/cairo-drm-i965-surface.c      |   73 ++--------------------
 src/drm/cairo-drm-intel.c             |    2 
 test/Makefile.am                      |    2 
 test/rounded-rectangle-fill.ref.png   |binary
 test/rounded-rectangle-stroke.ref.png |binary
 test/xcb-surface-source.c             |   23 ++++---
 16 files changed, 241 insertions(+), 291 deletions(-)

New commits:
commit 271752b944ef0898b5d1be57f26de83c8e40ae3a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Mar 4 08:24:08 2010 +0000

    gl: Pad the gradient texture.
    
    Fixes test/linear-gradient-subset

diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 076fc3f..5130bcb 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -1166,6 +1166,7 @@ _render_gradient (const cairo_gl_context_t *ctx,
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     pixman_image_set_filter (gradient, PIXMAN_FILTER_BILINEAR, NULL, 0);
+    pixman_image_set_repeat (gradient, PIXMAN_REPEAT_PAD);
 
     image = pixman_image_create_bits (PIXMAN_a8r8g8b8, width, 1,
 				      bytes, sizeof(uint32_t)*width);
commit afe6f4f0519606c4bc7e9b705b0cae75692d7af2
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Mar 3 23:06:43 2010 +0000

    drm/i915: Use a preserved temporary to store the radial texcoord.

diff --git a/src/drm/cairo-drm-i915-shader.c b/src/drm/cairo-drm-i915-shader.c
index 10363aa..5bd3ff2 100644
--- a/src/drm/cairo-drm-i915-shader.c
+++ b/src/drm/cairo-drm-i915-shader.c
@@ -372,8 +372,8 @@ i915_shader_radial_init (struct i915_shader_radial *r,
 /* Max instruction count: 10 */
 static void
 i915_shader_radial_coord (i915_device_t *device,
-			   enum i915_shader_radial_mode mode,
-			   int in, int g0, int g1, int out)
+			  enum i915_shader_radial_mode mode,
+			  int in, int g0, int g1, int out)
 {
     switch (mode) {
     case RADIAL_ONE:
@@ -651,9 +651,9 @@ i915_set_shader_program (i915_device_t *device,
 	i915_shader_radial_coord (device, shader->source.base.mode,
 				  FS_T0, /* input */
 				  FS_C0, FS_C1, /* gradient constants */
-				  FS_U3); /* coordinate */
+				  FS_R0); /* coordinate */
 
-	i915_fs_texld (out_reg, FS_S0, FS_U3);
+	i915_fs_texld (out_reg, FS_S0, FS_R0);
 	constant_offset += 2;
 	texture_offset += 1;
 	sampler_offset += 1;
@@ -722,9 +722,9 @@ i915_set_shader_program (i915_device_t *device,
 				  FS_T0 + texture_offset, /* input */
 				  FS_C0 + constant_offset,
 				  FS_C0 + constant_offset + 1, /* gradient constants */
-				  FS_U3); /* coordinate */
+				  FS_R1); /* coordinate */
 
-	i915_fs_texld (FS_R1, FS_S0 + sampler_offset, FS_U3);
+	i915_fs_texld (FS_R1, FS_S0 + sampler_offset, FS_R1);
 	constant_offset += 2;
 	texture_offset += 1;
 	sampler_offset += 1;
commit 4b2e0478822cb8415be4bac21950dbf03c0f01c8
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Mar 3 21:45:31 2010 +0000

    drm/i915: Eliminate redundant radial vertex shader.
    
    It is always equivalent to a simple texture transformation, so reduce it
    to the texture shader.

diff --git a/src/drm/cairo-drm-i915-glyphs.c b/src/drm/cairo-drm-i915-glyphs.c
index f85e96d..2302a30 100644
--- a/src/drm/cairo-drm-i915-glyphs.c
+++ b/src/drm/cairo-drm-i915-glyphs.c
@@ -96,10 +96,6 @@ i915_emit_glyph_rectangle_general (i915_device_t *device,
     case VS_LINEAR:
 	*v++ = i915_shader_linear_texcoord (&shader->source.linear, s, t);
 	break;
-    case VS_RADIAL:
-	cairo_matrix_transform_point (&shader->source.base.matrix, &s, &t);
-	*v++ = s; *v++ = t;
-	break;
     case VS_TEXTURE:
 	cairo_matrix_transform_point (&shader->source.base.matrix, &s, &t);
 	*v++ = s; *v++ = t;
@@ -120,10 +116,6 @@ i915_emit_glyph_rectangle_general (i915_device_t *device,
     case VS_LINEAR:
 	*v++ = i915_shader_linear_texcoord (&shader->source.linear, s, t);
 	break;
-    case VS_RADIAL:
-	cairo_matrix_transform_point (&shader->source.base.matrix, &s, &t);
-	*v++ = s; *v++ = t;
-	break;
     case VS_TEXTURE:
 	cairo_matrix_transform_point (&shader->source.base.matrix, &s, &t);
 	*v++ = s; *v++ = t;
@@ -144,10 +136,6 @@ i915_emit_glyph_rectangle_general (i915_device_t *device,
     case VS_LINEAR:
 	*v++ = i915_shader_linear_texcoord (&shader->source.linear, s, t);
 	break;
-    case VS_RADIAL:
-	cairo_matrix_transform_point (&shader->source.base.matrix, &s, &t);
-	*v++ = s; *v++ = t;
-	break;
     case VS_TEXTURE:
 	cairo_matrix_transform_point (&shader->source.base.matrix, &s, &t);
 	*v++ = s; *v++ = t;
@@ -387,7 +375,6 @@ i915_surface_glyphs (void			*abstract_surface,
 	break;
     default:
     case VS_LINEAR:
-    case VS_RADIAL:
     case VS_TEXTURE:
     case VS_TEXTURE_16:
 	emit_func = i915_emit_glyph_rectangle_general;
diff --git a/src/drm/cairo-drm-i915-private.h b/src/drm/cairo-drm-i915-private.h
index 203dba1..e95375f 100644
--- a/src/drm/cairo-drm-i915-private.h
+++ b/src/drm/cairo-drm-i915-private.h
@@ -711,7 +711,6 @@ enum {
 typedef enum {
     VS_CONSTANT,
     VS_LINEAR,
-    VS_RADIAL,
     VS_TEXTURE,
     VS_TEXTURE_16,
 } i915_vertex_shader_t;
diff --git a/src/drm/cairo-drm-i915-shader.c b/src/drm/cairo-drm-i915-shader.c
index 960d992..10363aa 100644
--- a/src/drm/cairo-drm-i915-shader.c
+++ b/src/drm/cairo-drm-i915-shader.c
@@ -1220,7 +1220,7 @@ i915_shader_acquire_radial (i915_shader_t *shader,
 
     i915_shader_radial_init (&src->radial, radial);
 
-    src->type.vertex = VS_RADIAL;
+    src->type.vertex = VS_TEXTURE;
     src->type.fragment = FS_RADIAL;
     src->type.pattern = PATTERN_RADIAL;
     src->base.texfmt = TEXCOORDFMT_2D;
@@ -2590,7 +2590,6 @@ i915_composite_vertex (float *v,
     case VS_LINEAR:
 	*v++ = i915_shader_linear_texcoord (&shader->source.linear, x, y);
 	break;
-    case VS_RADIAL:
     case VS_TEXTURE:
 	s = x, t = y;
 	cairo_matrix_transform_point (&shader->source.base.matrix, &s, &t);
@@ -2608,11 +2607,6 @@ i915_composite_vertex (float *v,
     case VS_LINEAR:
 	*v++ = i915_shader_linear_texcoord (&shader->mask.linear, x, y);
 	break;
-    case VS_RADIAL:
-	s = x, t = y;
-	cairo_matrix_transform_point (&shader->mask.base.matrix, &s, &t);
-	*v++ = s; *v++ = t;
-	break;
     case VS_TEXTURE:
 	s = x, t = y;
 	cairo_matrix_transform_point (&shader->mask.base.matrix, &s, &t);
diff --git a/src/drm/cairo-drm-i915-spans.c b/src/drm/cairo-drm-i915-spans.c
index e137149..38bdfed 100644
--- a/src/drm/cairo-drm-i915-spans.c
+++ b/src/drm/cairo-drm-i915-spans.c
@@ -179,41 +179,9 @@ i915_span_linear (i915_spans_t *spans,
 }
 
 static void
-i915_span_radial (i915_spans_t *spans,
-		  int x0, int x1, int y0, int y1,
-		  int alpha)
-{
-    float *vertices;
-    float a = alpha / 255.;
-    double s, t;
-
-    vertices = spans->get_rectangle (spans);
-
-    *vertices++ = x1;
-    *vertices++ = y1;
-    s = x0, t = y0;
-    cairo_matrix_transform_point (&spans->shader.source.base.matrix, &s, &t);
-    *vertices++ = s; *vertices++ = t;
-    *vertices++ = a;
-
-    *vertices++ = x0;
-    *vertices++ = y1;
-    s = x1, t = y0;
-    cairo_matrix_transform_point (&spans->shader.source.base.matrix, &s, &t);
-    *vertices++ = s; *vertices++ = t;
-    *vertices++ = a;
-
-    *vertices++ = x0;
-    *vertices++ = y0;
-    s = x1, t = y1;
-    cairo_matrix_transform_point (&spans->shader.source.base.matrix, &s, &t);
-    *vertices++ = s; *vertices++ = t;
-    *vertices++ = a;
-}
-
-static void
 i915_span_texture (i915_spans_t *spans,
-		   int x0, int x1, int y0, int y1, int alpha)
+		   int x0, int x1, int y0, int y1,
+		   int alpha)
 {
     float *vertices;
     float a = alpha / 255.;
@@ -300,7 +268,6 @@ i915_span_generic (i915_spans_t *spans,
     case VS_LINEAR:
 	*vertices++ = i915_shader_linear_texcoord (&spans->shader.source.linear, s, t);
 	break;
-    case VS_RADIAL:
     case VS_TEXTURE:
 	cairo_matrix_transform_point (&spans->shader.source.base.matrix, &s, &t);
 	*vertices++ = s; *vertices++ = t;
@@ -326,7 +293,6 @@ i915_span_generic (i915_spans_t *spans,
     case VS_LINEAR:
 	*vertices++ = i915_shader_linear_texcoord (&spans->shader.source.linear, s, t);
 	break;
-    case VS_RADIAL:
     case VS_TEXTURE:
 	cairo_matrix_transform_point (&spans->shader.source.base.matrix, &s, &t);
 	*vertices++ = s; *vertices++ = t;
@@ -352,7 +318,6 @@ i915_span_generic (i915_spans_t *spans,
     case VS_LINEAR:
 	*vertices++ = i915_shader_linear_texcoord (&spans->shader.source.linear, s, t);
 	break;
-    case VS_RADIAL:
     case VS_TEXTURE:
 	cairo_matrix_transform_point (&spans->shader.source.base.matrix, &s, &t);
 	*vertices++ = s; *vertices++ = t;
@@ -586,9 +551,6 @@ i915_spans_init (i915_spans_t *spans,
 	case VS_LINEAR:
 	    spans->span = i915_span_linear;
 	    break;
-	case VS_RADIAL:
-	    spans->span = i915_span_radial;
-	    break;
 	case VS_TEXTURE:
 	    spans->span = i915_span_texture;
 	    break;
commit 51610517982a4cf70ca8d396d0ad4c58a477c5e9
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Mar 3 21:56:56 2010 +0000

    drm/i915: Fix encoding of negated operand channels
    
    Long ago when converting the pixel shader structs into macros and
    reducing the code size by ~100k (the inlines were too depth for constant
    propagation and CSE), I broke the encoding of negated channels. So
    instead use a single bit to indicate a negation rather than 2s
    complement (with sign extension into neighbouring channels, oops). The
    disadvantage is that expressing the negated channel is a little more
    ugly.

diff --git a/src/drm/cairo-drm-i915-private.h b/src/drm/cairo-drm-i915-private.h
index 6ef1474..203dba1 100644
--- a/src/drm/cairo-drm-i915-private.h
+++ b/src/drm/cairo-drm-i915-private.h
@@ -306,11 +306,11 @@
 #define FS_U3			((REG_TYPE_U << REG_TYPE_SHIFT) | 3)
 
 #define X_CHANNEL_SHIFT (REG_TYPE_SHIFT + 3)
-#define Y_CHANNEL_SHIFT (X_CHANNEL_SHIFT + 3)
-#define Z_CHANNEL_SHIFT (Y_CHANNEL_SHIFT + 3)
-#define W_CHANNEL_SHIFT (Z_CHANNEL_SHIFT + 3)
+#define Y_CHANNEL_SHIFT (X_CHANNEL_SHIFT + 4)
+#define Z_CHANNEL_SHIFT (Y_CHANNEL_SHIFT + 4)
+#define W_CHANNEL_SHIFT (Z_CHANNEL_SHIFT + 4)
 
-#define REG_CHANNEL_MASK 0x7
+#define REG_CHANNEL_MASK 0xf
 
 #define REG_NR(reg)		((reg) & REG_NR_MASK)
 #define REG_TYPE(reg)		(((reg) >> REG_TYPE_SHIFT) & REG_TYPE_MASK)
@@ -320,12 +320,18 @@
 #define REG_W(reg)		(((reg) >> W_CHANNEL_SHIFT) & REG_CHANNEL_MASK)
 
 enum i915_fs_channel {
-    X_CHANNEL_VAL = 1,
+    X_CHANNEL_VAL = 0,
     Y_CHANNEL_VAL,
     Z_CHANNEL_VAL,
     W_CHANNEL_VAL,
     ZERO_CHANNEL_VAL,
-    ONE_CHANNEL_VAL
+    ONE_CHANNEL_VAL,
+
+    NEG_X_CHANNEL_VAL = X_CHANNEL_VAL | 0x8,
+    NEG_Y_CHANNEL_VAL = Y_CHANNEL_VAL | 0x8,
+    NEG_Z_CHANNEL_VAL = Z_CHANNEL_VAL | 0x8,
+    NEG_W_CHANNEL_VAL = W_CHANNEL_VAL | 0x8,
+    NEG_ONE_CHANNEL_VAL = ONE_CHANNEL_VAL | 0x8
 };
 
 #define i915_fs_operand(reg, x, y, z, w) \
@@ -342,7 +348,7 @@ enum i915_fs_channel {
     i915_fs_operand(reg, X, Y, Z, W)
 
 #define i915_fs_operand_reg_negate(reg)					\
-    i915_fs_operand(reg, -X, -Y, -Z, -W)
+    i915_fs_operand(reg, NEG_X, NEG_Y, NEG_Z, NEG_W)
 
 /**
  * Returns an operand containing (0.0, 0.0, 0.0, 0.0).
@@ -360,7 +366,7 @@ enum i915_fs_channel {
 #define i915_fs_operand_one() i915_fs_operand(FS_R0, ONE, ONE, ONE, ONE)
 
 #define i915_get_hardware_channel_val(val, shift, negate) \
-    (((int) val < 0) ?  (~val << shift) | negate : (val - 1) << shift)
+    (((val & 0x7) << shift) | ((val & 0x8) ? negate : 0))
 
 /**
  * Outputs a fragment shader command to declare a sampler or texture register.
diff --git a/src/drm/cairo-drm-i915-shader.c b/src/drm/cairo-drm-i915-shader.c
index 98a31d6..960d992 100644
--- a/src/drm/cairo-drm-i915-shader.c
+++ b/src/drm/cairo-drm-i915-shader.c
@@ -318,7 +318,7 @@ i915_shader_linear_color (i915_device_t *device,
 
     /* interpolate */
     i915_fs_mad (out, 0,
-		 i915_fs_operand (tmp, -X, -X, -X, -X),
+		 i915_fs_operand (tmp, NEG_X, NEG_X, NEG_X, NEG_X),
 		 i915_fs_operand_reg (c0),
 		 i915_fs_operand_reg (c0));
     i915_fs_mad (out, 0,
@@ -385,7 +385,7 @@ i915_shader_radial_coord (i915_device_t *device,
 	i915_fs_mad (FS_U0, MASK_X | MASK_Y,
 		     i915_fs_operand (in, X, Y, ZERO, ZERO),
 		     i915_fs_operand (g0, Z, Z, ZERO, ZERO),
-		     i915_fs_operand (g0, -X, -Y, ZERO, ZERO));
+		     i915_fs_operand (g0, NEG_X, NEG_Y, ZERO, ZERO));
 	i915_fs_dp2add (FS_U0, MASK_X,
 			i915_fs_operand (FS_U0, X, Y, ZERO, ZERO),
 			i915_fs_operand (FS_U0, X, Y, ZERO, ZERO),
@@ -418,7 +418,7 @@ i915_shader_radial_coord (i915_device_t *device,
 	/* u1.x = pdx² + pdy² - r1²; [C] */
 	i915_fs_dp3 (FS_U1, MASK_X,
 		     i915_fs_operand (FS_U0, X, Y, Z, ZERO),
-		     i915_fs_operand (FS_U0, X, Y, -Z, ZERO));
+		     i915_fs_operand (FS_U0, X, Y, NEG_Z, ZERO));
 	/* u1.x = C, u1.y = B, u1.z=-4*A; */
 	i915_fs_mov_masked (FS_U1, MASK_Y, i915_fs_operand (FS_U0, W, W, W, W));
 	i915_fs_mov_masked (FS_U1, MASK_Z, i915_fs_operand (g0, W, W, W, W));
@@ -433,8 +433,8 @@ i915_shader_radial_coord (i915_device_t *device,
 	i915_fs_rsq (out, MASK_X, i915_fs_operand (FS_U1, X, X, X, X));
 	i915_fs_mad (out, MASK_X | MASK_Y,
 		     i915_fs_operand (out, X, X, ZERO, ZERO),
-		     i915_fs_operand (FS_U1, X, -X, ZERO, ZERO),
-		     i915_fs_operand (FS_U0, -W, -W, ZERO, ZERO));
+		     i915_fs_operand (FS_U1, X, NEG_X, ZERO, ZERO),
+		     i915_fs_operand (FS_U0, NEG_W, NEG_W, ZERO, ZERO));
 	/* out.x = (-B + sqrt (B² - 4*A*C)) / (2 * A),
 	 * out.y = (-B - sqrt (B² - 4*A*C)) / (2 * A)
 	 */
@@ -816,7 +816,7 @@ i915_set_shader_program (i915_device_t *device,
 		dest_reg = FS_OC;
 	    } else {
 		i915_fs_add (FS_U0,
-			     i915_fs_operand (source_reg, -W, -W, -W, -W),
+			     i915_fs_operand (source_reg, NEG_W, NEG_W, NEG_W, NEG_W),
 			     i915_fs_operand_one ());
 		i915_fs_mul (FS_U0,
 			     i915_fs_operand_reg (FS_U0),
@@ -847,7 +847,7 @@ i915_set_shader_program (i915_device_t *device,
 		source_reg = FS_R3;
 	    } else {
 		i915_fs_add (FS_U0,
-			     i915_fs_operand (source_reg, -W, -W, -W, -W),
+			     i915_fs_operand (source_reg, NEG_W, NEG_W, NEG_W, NEG_W),
 			     i915_fs_operand_one ());
 		i915_fs_mul (FS_R3,
 			     i915_fs_operand_reg (FS_U0),
@@ -932,7 +932,7 @@ i915_set_shader_program (i915_device_t *device,
 
 	    i915_fs_add (mask_reg,
 			 i915_fs_operand_one (),
-			 i915_fs_operand (mask_reg, -W, -W, -W, -W));
+			 i915_fs_operand (mask_reg, NEG_W, NEG_W, NEG_W, NEG_W));
 
 	    if (dest_reg != FS_OC) {
 		if (dest_reg == ~0U) {
commit 5b973c670807bda2bb355c90ea817e2a2f092f0b
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Mar 3 21:25:11 2010 +0000

    drm/i915: Fix crash with linear-step-function
    
    Avoid the potential divide by zero by falling back to pixman rendered
    gradient textures for such troublesome input.

diff --git a/src/drm/cairo-drm-i915-shader.c b/src/drm/cairo-drm-i915-shader.c
index a1bb9bf..98a31d6 100644
--- a/src/drm/cairo-drm-i915-shader.c
+++ b/src/drm/cairo-drm-i915-shader.c
@@ -985,7 +985,7 @@ i915_set_shader_program (i915_device_t *device,
     FS_END ();
 }
 
-static void
+static cairo_bool_t
 i915_shader_linear_init (struct i915_shader_linear *l,
 			 const cairo_linear_pattern_t *linear)
 {
@@ -994,9 +994,12 @@ i915_shader_linear_init (struct i915_shader_linear *l,
 
     dx = _cairo_fixed_to_double (linear->p2.x - linear->p1.x);
     dy = _cairo_fixed_to_double (linear->p2.y - linear->p1.y);
-    sf = 1. / (dx * dx + dy * dy);
-    dx *= sf;
-    dy *= sf;
+    sf = dx * dx + dy * dy;
+    if (sf <= 1e-5)
+	return FALSE;
+
+    dx /= sf;
+    dy /= sf;
 
     x0 = _cairo_fixed_to_double (linear->p1.x);
     y0 = _cairo_fixed_to_double (linear->p1.y);
@@ -1015,6 +1018,8 @@ i915_shader_linear_init (struct i915_shader_linear *l,
 	l->dy = m.xy;
 	l->offset = m.x0;
     }
+
+    return TRUE;
 }
 
 static cairo_bool_t
@@ -1130,8 +1135,8 @@ i915_shader_acquire_linear (i915_shader_t *shader,
     cairo_bool_t mode = LINEAR_TEXTURE;
     cairo_status_t status;
 
-    i915_shader_linear_init (&src->linear, linear);
-    if (linear->base.n_stops == 2 &&
+    if (i915_shader_linear_init (&src->linear, linear) &&
+	linear->base.n_stops == 2 &&
 	linear->base.stops[0].offset == 0.0 &&
 	linear->base.stops[1].offset == 1.0)
     {
commit 404ead7eebafa7ca077e1d012dde0a598b64245a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Mar 3 21:01:49 2010 +0000

    drm/i915: Ensure simple alpha is written to green on alpha-only surfaces.
    
    The intricacies of h/w make convoluted s/w.

diff --git a/src/drm/cairo-drm-i915-shader.c b/src/drm/cairo-drm-i915-shader.c
index 65873d9..a1bb9bf 100644
--- a/src/drm/cairo-drm-i915-shader.c
+++ b/src/drm/cairo-drm-i915-shader.c
@@ -960,15 +960,23 @@ i915_set_shader_program (i915_device_t *device,
     }
 
     if (source_reg != FS_OC) {
-	if (source_reg == ~0U)
-	    if (source_pure)
-		i915_fs_mov (FS_OC, i915_fs_operand_pure (source_pure));
-	    else
+	if (source_reg == ~0U) {
+	    if (source_pure) {
+		if ((shader->content & CAIRO_CONTENT_COLOR) == 0) {
+		    if (source_pure & (1 << 3))
+			i915_fs_mov (FS_OC, i915_fs_operand_one ());
+		    else
+			i915_fs_mov (FS_OC, i915_fs_operand_zero ());
+		} else
+		    i915_fs_mov (FS_OC, i915_fs_operand_pure (source_pure));
+	    } else {
 		i915_fs_mov (FS_OC, i915_fs_operand_one ());
-	else if ((shader->content & CAIRO_CONTENT_COLOR) == 0)
+	    }
+	} else if ((shader->content & CAIRO_CONTENT_COLOR) == 0) {
 	    i915_fs_mov (FS_OC, i915_fs_operand (source_reg, W, W, W, W));
-	else
+	} else {
 	    i915_fs_mov (FS_OC, i915_fs_operand_reg (source_reg));
+	}
     } else {
 	if ((shader->content & CAIRO_CONTENT_COLOR) == 0)
 	    i915_fs_mov (FS_OC, i915_fs_operand (FS_OC, W, W, W, W));
commit 1f2daf652480ef768f847467d9171b5e4a7f01a3
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Mar 3 20:06:08 2010 +0000

    drm/i915: Avoid double multiplication of linear alpha.

diff --git a/src/drm/cairo-drm-i915-shader.c b/src/drm/cairo-drm-i915-shader.c
index 9c9dac0..65873d9 100644
--- a/src/drm/cairo-drm-i915-shader.c
+++ b/src/drm/cairo-drm-i915-shader.c
@@ -640,7 +640,7 @@ i915_set_shader_program (i915_device_t *device,
 	/* XXX can we defer premultiplication? */
 	i915_fs_mul (out_reg,
 		     i915_fs_operand_reg (FS_U3),
-		     i915_fs_operand (FS_U3, W, W, W, W));
+		     i915_fs_operand (FS_U3, W, W, W, ONE));
 
 	constant_offset += 2;
 	texture_offset += 1;
@@ -711,11 +711,7 @@ i915_set_shader_program (i915_device_t *device,
 				  FS_T0 + texture_offset, /* input */
 				  FS_C0 + constant_offset,
 				  FS_C0 + constant_offset + 1, /* colour ramp */
-				  FS_U3); /* unpremultiplied output */
-	i915_fs_mul (FS_R1,
-		     i915_fs_operand_reg (FS_U3),
-		     i915_fs_operand (source_reg, W, W, W, W));
-
+				  FS_R1); /* unpremultiplied output */
 	constant_offset += 2;
 	texture_offset += 1;
 	mask_reg = FS_R1;
commit cdaef58c19a191632473fcbbe688e6231c02b9b2
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Mar 3 18:52:40 2010 +0000

    drm/i915: Acquire device before shader commit.

diff --git a/src/drm/cairo-drm-i915-shader.c b/src/drm/cairo-drm-i915-shader.c
index 6f37804..9c9dac0 100644
--- a/src/drm/cairo-drm-i915-shader.c
+++ b/src/drm/cairo-drm-i915-shader.c
@@ -2669,6 +2669,8 @@ i915_shader_commit (i915_shader_t *shader,
     unsigned floats_per_vertex;
     cairo_status_t status;
 
+    assert (CAIRO_MUTEX_IS_LOCKED (device->intel.base.base.mutex));
+
     i915_shader_combine_source (shader, device);
     i915_shader_combine_mask (shader);
     i915_shader_setup_dst (shader);
diff --git a/src/drm/cairo-drm-i915-surface.c b/src/drm/cairo-drm-i915-surface.c
index 039497a..3071ee3 100644
--- a/src/drm/cairo-drm-i915-surface.c
+++ b/src/drm/cairo-drm-i915-surface.c
@@ -334,6 +334,8 @@ i915_batch_add_reloc (i915_device_t *device,
 void
 i915_vbo_finish (i915_device_t *device)
 {
+    assert (CAIRO_MUTEX_IS_LOCKED (device->intel.base.base.mutex));
+
     if (device->vbo_used == 0)
 	return;
 
@@ -447,6 +449,8 @@ i915_batch_flush (i915_device_t *device)
     uint32_t length, offset;
     int n;
 
+    assert (CAIRO_MUTEX_IS_LOCKED (device->intel.base.base.mutex));
+
     i915_vbo_finish (device);
 
     if (device->batch.used == 0)
@@ -655,6 +659,7 @@ i915_fixup_unbounded (i915_surface_t *dst,
 		      cairo_clip_t *clip)
 {
     i915_shader_t shader;
+    i915_device_t *device;
     cairo_status_t status;
 
     if (clip != NULL) {
@@ -691,10 +696,15 @@ i915_fixup_unbounded (i915_surface_t *dst,
 	assert (status == CAIRO_STATUS_SUCCESS);
     }
 
-    status = i915_shader_commit (&shader, i915_device (dst));
+    device =  i915_device (dst);
+    status = cairo_device_acquire (&device->intel.base.base);
     if (unlikely (status))
 	return status;
 
+    status = i915_shader_commit (&shader, device);
+    if (unlikely (status))
+	goto BAIL;
+
     /* top */
     if (extents->bounded.y != extents->unbounded.y) {
 	shader.add_rectangle (&shader,
@@ -732,7 +742,9 @@ i915_fixup_unbounded (i915_surface_t *dst,
     }
 
     i915_shader_fini (&shader);
-    return CAIRO_STATUS_SUCCESS;
+  BAIL:
+    cairo_device_release (&device->intel.base.base);
+    return status;
 }
 
 static cairo_status_t
@@ -807,6 +819,7 @@ i915_fixup_unbounded_boxes (i915_surface_t *dst,
 
     if (likely (status == CAIRO_STATUS_SUCCESS && clear.num_boxes)) {
 	i915_shader_t shader;
+	i915_device_t *device;
 
 	if (clip != NULL) {
 	    i915_shader_init (&shader, dst, CAIRO_OPERATOR_DEST_OVER);
@@ -824,20 +837,29 @@ i915_fixup_unbounded_boxes (i915_surface_t *dst,
 						  &extents->unbounded);
 	    assert (status == CAIRO_STATUS_SUCCESS);
 	}
-	status = i915_shader_commit (&shader,
-				     (i915_device_t *) dst->intel.drm.base.device);
-	if (likely (status == CAIRO_STATUS_SUCCESS)) {
-	    for (chunk = &clear.chunks; chunk != NULL; chunk = chunk->next) {
-		for (i = 0; i < chunk->count; i++) {
-		    int x1 = _cairo_fixed_integer_part (chunk->base[i].p1.x);
-		    int y1 = _cairo_fixed_integer_part (chunk->base[i].p1.y);
-		    int x2 = _cairo_fixed_integer_part (chunk->base[i].p2.x);
-		    int y2 = _cairo_fixed_integer_part (chunk->base[i].p2.y);
-
-		    shader.add_rectangle (&shader, x1, y1, x2 - x1, y2 - y1);
-		}
+
+	device =  i915_device (dst);
+	status = cairo_device_acquire (&device->intel.base.base);
+	if (unlikely (status))
+	    goto err_shader;
+
+	status = i915_shader_commit (&shader, device);
+	if (unlikely (status))
+	    goto err_device;
+
+	for (chunk = &clear.chunks; chunk != NULL; chunk = chunk->next) {
+	    for (i = 0; i < chunk->count; i++) {
+		int x1 = _cairo_fixed_integer_part (chunk->base[i].p1.x);
+		int y1 = _cairo_fixed_integer_part (chunk->base[i].p1.y);
+		int x2 = _cairo_fixed_integer_part (chunk->base[i].p2.x);
+		int y2 = _cairo_fixed_integer_part (chunk->base[i].p2.y);
+
+		shader.add_rectangle (&shader, x1, y1, x2 - x1, y2 - y1);
 	    }
 	}
+err_device:
+	cairo_device_release (&device->intel.base.base);
+err_shader:
 	i915_shader_fini (&shader);
     }
 
@@ -860,6 +882,7 @@ _composite_boxes (i915_surface_t *dst,
     const struct _cairo_boxes_chunk *chunk;
     cairo_status_t status;
     i915_shader_t shader;
+    i915_device_t *device;
     int i;
 
     /* If the boxes are not pixel-aligned, we will need to compute a real mask */
@@ -885,25 +908,34 @@ _composite_boxes (i915_surface_t *dst,
 	    i915_shader_set_clip (&shader, clip);
     }
 
-    status = i915_shader_commit (&shader,
-				 (i915_device_t *) dst->intel.drm.base.device);
-    if (likely (status == CAIRO_STATUS_SUCCESS)) {
-	for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
-	    cairo_box_t *box = chunk->base;
-	    for (i = 0; i < chunk->count; i++) {
-		int x1 = _cairo_fixed_integer_round (box[i].p1.x);
-		int y1 = _cairo_fixed_integer_round (box[i].p1.y);
-		int x2 = _cairo_fixed_integer_round (box[i].p2.x);
-		int y2 = _cairo_fixed_integer_round (box[i].p2.y);
+    device = i915_device (dst);
+    status = cairo_device_acquire (&device->intel.base.base);
+    if (unlikely (status))
+	goto err_shader;
 
-		if (x2 > x1 && y2 > y1)
-		    shader.add_rectangle (&shader, x1, y1, x2 - x1, y2 - y1);
-	    }
-	}
+    status = i915_shader_commit (&shader, device);
+    if (unlikely (status))
+	goto err_device;
 
-	if (! extents->is_bounded)
-	    status = i915_fixup_unbounded_boxes (dst, extents, clip, boxes);
+    for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
+	cairo_box_t *box = chunk->base;
+	for (i = 0; i < chunk->count; i++) {
+	    int x1 = _cairo_fixed_integer_round (box[i].p1.x);
+	    int y1 = _cairo_fixed_integer_round (box[i].p1.y);
+	    int x2 = _cairo_fixed_integer_round (box[i].p2.x);
+	    int y2 = _cairo_fixed_integer_round (box[i].p2.y);
+
+	    if (x2 > x1 && y2 > y1)
+		shader.add_rectangle (&shader, x1, y1, x2 - x1, y2 - y1);
+	}
     }
+
+    if (! extents->is_bounded)
+	status = i915_fixup_unbounded_boxes (dst, extents, clip, boxes);
+
+  err_device:
+    cairo_device_release (&device->intel.base.base);
+  err_shader:
     i915_shader_fini (&shader);
 
     return status;
@@ -1041,6 +1073,7 @@ i915_surface_mask (void				*abstract_dst,
 		   cairo_clip_t			*clip)
 {
     i915_surface_t *dst = abstract_dst;
+    i915_device_t *device;
     cairo_composite_rectangles_t extents;
     i915_shader_t shader;
     cairo_clip_t local_clip;
@@ -1077,14 +1110,14 @@ i915_surface_mask (void				*abstract_dst,
 					  source,
 					  &extents.bounded);
     if (unlikely (status))
-	goto BAIL;
+	goto err_shader;
 
     status = i915_shader_acquire_pattern (&shader,
 					  &shader.mask,
 					  mask,
 					  &extents.bounded);
     if (unlikely (status))
-	goto BAIL;
+	goto err_shader;
 
     if (clip != NULL) {
 	status = _cairo_clip_get_region (clip, &clip_region);
@@ -1094,10 +1127,14 @@ i915_surface_mask (void				*abstract_dst,
 	    i915_shader_set_clip (&shader, clip);
     }
 
-    status = i915_shader_commit (&shader,
-				 (i915_device_t *) dst->intel.drm.base.device);
+    device = i915_device (dst);
+    status = cairo_device_acquire (&device->intel.base.base);
     if (unlikely (status))
-	goto BAIL;
+	goto err_shader;
+
+    status = i915_shader_commit (&shader, device);
+    if (unlikely (status))
+	goto err_device;
 
     if (clip_region != NULL) {
 	unsigned int n, num_rectangles;
@@ -1122,7 +1159,9 @@ i915_surface_mask (void				*abstract_dst,
     if (! extents.is_bounded)
 	status = i915_fixup_unbounded (dst, &extents, clip);
 
-  BAIL:
+  err_device:
+    cairo_device_release (&device->intel.base.base);
+  err_shader:
     i915_shader_fini (&shader);
     if (have_clip)
 	_cairo_clip_fini (&local_clip);
commit dd6f96dd4aeb48262d5af8a3006e6404521c151b
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Mar 3 16:06:25 2010 +0000

    drm/i965: Ignore flushing on device finish.

diff --git a/src/drm/cairo-drm-i965-surface.c b/src/drm/cairo-drm-i965-surface.c
index 59e975d..0e5ba28 100644
--- a/src/drm/cairo-drm-i965-surface.c
+++ b/src/drm/cairo-drm-i965-surface.c
@@ -1660,6 +1660,9 @@ _i965_device_flush (cairo_drm_device_t *device)
 {
     cairo_status_t status;
 
+    if (unlikely (device->base.finished))
+	return CAIRO_STATUS_SUCCESS;
+
     status = cairo_device_acquire (&device->base);
     if (likely (status == CAIRO_STATUS_SUCCESS))
 	status = i965_device_flush ((i965_device_t *) device);
commit 3692597567f62dd300e8ce8c43d43ac449616041
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Mar 3 13:56:48 2010 +0000

    drm/i965: Merge the constants into the surface stream.
    
    As we can use an offset from the surface base for the constant buffers,
    we need to fold the constants into the surface stream.

diff --git a/src/drm/cairo-drm-i965-private.h b/src/drm/cairo-drm-i965-private.h
index 84c7134..e13ea78 100644
--- a/src/drm/cairo-drm-i965-private.h
+++ b/src/drm/cairo-drm-i965-private.h
@@ -339,9 +339,8 @@ struct i965_stream {
 };
 
 #define I965_BATCH_SIZE (16 * 4096)
-#define I965_SURFACE_SIZE (16 * 4096)
 #define I965_GENERAL_SIZE (16 * 4096)
-#define I965_CONSTANT_SIZE (16 * 4096)
+#define I965_SURFACE_SIZE (32 * 4096)
 #define I965_VERTEX_SIZE (128 * 4096)
 
 #define I965_TILING_DEFAULT I915_TILING_Y
@@ -402,12 +401,12 @@ struct i965_device {
 
     i965_stream_t batch;
     uint8_t batch_base[I965_BATCH_SIZE];
-    struct drm_i915_gem_relocation_entry batch_relocations[1024];
+    struct drm_i915_gem_relocation_entry batch_relocations[2048];
 
     i965_stream_t surface;
     uint8_t surface_base[I965_SURFACE_SIZE];
     struct i965_pending_relocation surface_pending_relocations[1];
-    struct drm_i915_gem_relocation_entry surface_relocations[512];
+    struct drm_i915_gem_relocation_entry surface_relocations[1024];
 
     i965_stream_t general;
     uint8_t general_base[I965_GENERAL_SIZE];
@@ -417,10 +416,6 @@ struct i965_device {
     uint8_t vertex_base[I965_VERTEX_SIZE];
     struct i965_pending_relocation vertex_pending_relocations[512];
 
-    i965_stream_t constant;
-    uint8_t constant_base[I965_CONSTANT_SIZE];
-    struct i965_pending_relocation constant_pending_relocations[512];
-
     struct {
 	size_t gtt_size;
 
diff --git a/src/drm/cairo-drm-i965-shader.c b/src/drm/cairo-drm-i965-shader.c
index 39c89a9..27e1644 100644
--- a/src/drm/cairo-drm-i965-shader.c
+++ b/src/drm/cairo-drm-i965-shader.c
@@ -2572,17 +2572,12 @@ i965_emit_composite (i965_device_t *device,
 	assert (size <= 64 * URB_CS_ENTRY_SIZE);
 	assert (((sizeof (float) * shader->constants_size + 31) & -32) == 32 * i965_shader_const_urb_length (shader));
 
-	OUT_BATCH (BRW_CONSTANT_BUFFER | (1 << 8));
-	assert ((device->constant.used & 63) == 0);
-	i965_stream_add_pending_relocation (&device->constant,
-					    device->batch.used,
-					    I915_GEM_DOMAIN_INSTRUCTION, 0,
-					    device->constant.used + size / 64 - 1);
-	OUT_BATCH (0); /* pending relocation */
-
-	device->constants = i965_stream_alloc (&device->constant, 0, size);
+	device->constants = i965_stream_alloc (&device->surface, 64, size);
 	memcpy (device->constants, shader->constants, size);
 	device->constants_size = shader->constants_size;
+
+	OUT_BATCH (BRW_CONSTANT_BUFFER | (1 << 8));
+	OUT_BATCH (i965_stream_offsetof (&device->surface, device->constants) + size / 64 - 1);
     }
 
     i965_emit_vertex_element (device, shader);
@@ -2596,6 +2591,8 @@ i965_flush_vertices (i965_device_t *device)
     if (device->vertex.used == device->vertex.committed)
 	return;
 
+    assert (device->vertex.used > device->vertex.committed);
+
     vertex_start = device->vertex.committed / device->vertex_size;
     vertex_count =
 	(device->vertex.used - device->vertex.committed) / device->vertex_size;
@@ -2630,10 +2627,6 @@ i965_flush_vertices (i965_device_t *device)
     OUT_BATCH (0);
 
     device->vertex.committed = device->vertex.used;
-
-#if 1
-    OUT_BATCH (MI_FLUSH);
-#endif
 }
 
 void
@@ -2726,13 +2719,6 @@ recheck:
 	goto recheck;
     }
 
-    if (unlikely (device->constant.used + sizeof (device->constants) > device->constant.size ||
-		  device->constant.num_pending_relocations == device->constant.max_pending_relocations))
-    {
-	i965_stream_commit (device, &device->constant);
-	goto recheck;
-    }
-
     if (unlikely (device->general.used + 512 > device->general.size)) {
 	i965_stream_commit (device, &device->general);
 	i965_general_state_reset (device);
diff --git a/src/drm/cairo-drm-i965-surface.c b/src/drm/cairo-drm-i965-surface.c
index 273273d..59e975d 100644
--- a/src/drm/cairo-drm-i965-surface.c
+++ b/src/drm/cairo-drm-i965-surface.c
@@ -290,8 +290,7 @@ static void
 i965_device_reset (i965_device_t *device)
 {
     device->exec.count = 0;
-    device->exec.gtt_size = I965_CONSTANT_SIZE +
-	                    I965_VERTEX_SIZE +
+    device->exec.gtt_size = I965_VERTEX_SIZE +
 	                    I965_SURFACE_SIZE +
 			    I965_GENERAL_SIZE +
 			    I965_BATCH_SIZE;
@@ -532,14 +531,8 @@ i965_device_flush (i965_device_t *device)
 
     /* Combine vertex+constant+surface+batch streams? */
     max = aligned = device->vertex.used;
-    if (device->constant.used) {
-	aligned = (aligned + 63) & -64;
-	aligned += device->constant.used;
-	if (device->constant.used > max)
-	    max = device->constant.used;
-    }
     if (device->surface.used) {
-	aligned = (aligned + 31) & -32;
+	aligned = (aligned + 63) & -64;
 	aligned += device->surface.used;
 	if (device->surface.used > max)
 	    max = device->surface.used;
@@ -564,15 +557,10 @@ i965_device_flush (i965_device_t *device)
 	    _copy_to_bo_and_apply_relocations (device, bo, &device->vertex, 0);
 
 	aligned = device->vertex.used;
-	if (device->constant.used) {
-	    aligned = (aligned + 63) & -64;
-	    _copy_to_bo_and_apply_relocations (device, bo, &device->constant, aligned);
-	    aligned += device->constant.used;
-	}
 
 	batch_num_relocations = device->batch.num_relocations;
 	if (device->surface.used) {
-	    aligned = (aligned + 31) & -32;
+	    aligned = (aligned + 63) & -64;
 	    _copy_to_bo_and_apply_relocations (device, bo, &device->surface, aligned);
 
 	    batch_num_relocations = device->batch.num_relocations;
@@ -624,49 +612,8 @@ i965_device_flush (i965_device_t *device)
 	}
     } else {
 	i965_stream_commit (device, &device->vertex);
-
-	if (device->constant.used && device->surface.used){
-	    aligned = (device->constant.used + 31) & -32;
-	    aligned += device->surface.used;
-
-	    max = MAX (device->constant.used, device->surface.used);
-	    if (aligned <= next_bo_size (max)) {
-		if (aligned <= 8192)
-		    max = aligned;
-
-		bo = intel_bo_create (&device->intel, max, FALSE);
-		if (unlikely (bo == NULL))
-		    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-		assert (aligned <= bo->base.size);
-
-		_copy_to_bo_and_apply_relocations (device, bo, &device->constant, 0);
-
-		aligned = (device->constant.used + 31) & -32;
-
-		_copy_to_bo_and_apply_relocations (device, bo, &device->surface, aligned);
-
-		if (device->surface.num_relocations) {
-		    assert (bo->exec != NULL);
-
-		    for (n = 0; n < device->surface.num_relocations; n++)
-			device->surface.relocations[n].offset += aligned;
-
-		    bo->exec->relocs_ptr = (uintptr_t) device->surface.relocations;
-		    bo->exec->relocation_count = device->surface.num_relocations;
-		}
-
-		i965_stream_reset (&device->surface);
-		i965_stream_reset (&device->constant);
-
-		intel_bo_destroy (&device->intel, bo);
-	    }
-	} else {
-	    if (device->constant.used)
-		i965_stream_commit (device, &device->constant);
-	    if (device->surface.used)
-		i965_stream_commit (device, &device->surface);
-	}
+	if (device->surface.used)
+	    i965_stream_commit (device, &device->surface);
 
 	bo = intel_bo_create (&device->intel, device->batch.used, FALSE);
 	if (unlikely (bo == NULL))
@@ -697,7 +644,6 @@ i965_device_flush (i965_device_t *device)
 
     i965_stream_reset (&device->vertex);
     i965_stream_reset (&device->surface);
-    i965_stream_reset (&device->constant);
     i965_stream_reset (&device->batch);
 
     intel_glyph_cache_unpin (&device->intel);
@@ -1873,12 +1819,6 @@ _cairo_drm_i965_device_create (int fd, dev_t dev, int vendor_id, int chip_id)
 		      ARRAY_LENGTH (device->vertex_pending_relocations),
 		      NULL, 0);
 
-    i965_stream_init (&device->constant,
-		      device->constant_base, sizeof (device->constant_base),
-		      device->constant_pending_relocations,
-		      ARRAY_LENGTH (device->constant_pending_relocations),
-		      NULL, 0);
-
     cairo_list_init (&device->flush);
     i965_device_reset (device);
     device->vs_offset = (uint32_t) -1;
commit cc585947574f6e17d299a5987ee69162f63d5a52
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Mar 3 23:06:23 2010 +0000

    drm/intel: Set the 1D gradient texture to be untiled.

diff --git a/src/drm/cairo-drm-intel.c b/src/drm/cairo-drm-intel.c
index e7523f9..a6f7371 100644
--- a/src/drm/cairo-drm-intel.c
+++ b/src/drm/cairo-drm-intel.c
@@ -1472,6 +1472,7 @@ intel_gradient_render (intel_device_t *device,
 	pixman_image_unref (image);
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
+    intel_bo_set_tiling (device, buffer->bo, I915_TILING_NONE, 0);
 
     intel_bo_write (device, buffer->bo, 0, 4*width, pixman_image_get_data (image));
     pixman_image_unref (image);
commit 543cf073643b259096ee2a95d91b9067395a7e09
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Mar 3 21:19:41 2010 +0000

    drm/intel: Set default extend mode for rendering gradient subsets.

diff --git a/src/drm/cairo-drm-intel.c b/src/drm/cairo-drm-intel.c
index c530a08..e7523f9 100644
--- a/src/drm/cairo-drm-intel.c
+++ b/src/drm/cairo-drm-intel.c
@@ -1450,6 +1450,7 @@ intel_gradient_render (intel_device_t *device,
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     pixman_image_set_filter (gradient, PIXMAN_FILTER_BILINEAR, NULL, 0);
+    pixman_image_set_repeat (gradient, PIXMAN_REPEAT_PAD);
 
     image = pixman_image_create_bits (PIXMAN_a8r8g8b8, width, 1, NULL, 0);
     if (unlikely (image == NULL)) {
commit 521d1c1d2c51bca07db1aed3c7f62d860cece3f4
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Mar 3 20:25:54 2010 +0000

    surface: Simplify is_clear logic.
    
    As we pre-check whether the operation is a no-op on an already cleared
    surface, then for all but a paint with CLEAR and no clip, the result is
    a non-clear surface.

diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 0b9293f..a67c7cb 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -1899,13 +1899,8 @@ _cairo_surface_paint (cairo_surface_t	*surface,
     if (clip && clip->all_clipped)
 	return CAIRO_STATUS_SUCCESS;
 
-    if (op == CAIRO_OPERATOR_CLEAR) {
-	if (surface->is_clear)
-	    return CAIRO_STATUS_SUCCESS;
-
-	if (clip == NULL)
-	    surface->is_clear = TRUE;
-    }
+    if (op == CAIRO_OPERATOR_CLEAR && surface->is_clear)
+	return CAIRO_STATUS_SUCCESS;
 
     _cairo_surface_begin_modification (surface);
 
@@ -1918,7 +1913,7 @@ _cairo_surface_paint (cairo_surface_t	*surface,
     status = _cairo_surface_fallback_paint (surface, op, source, clip);
 
  FINISH:
-    surface->is_clear &= op == CAIRO_OPERATOR_CLEAR;
+    surface->is_clear = op == CAIRO_OPERATOR_CLEAR && clip == NULL;
 
     return _cairo_surface_set_error (surface, status);
 }
@@ -1959,7 +1954,7 @@ _cairo_surface_mask (cairo_surface_t		*surface,
     status = _cairo_surface_fallback_mask (surface, op, source, mask, clip);
 
  FINISH:
-    surface->is_clear &= op == CAIRO_OPERATOR_CLEAR;
+    surface->is_clear = FALSE;
 
     return _cairo_surface_set_error (surface, status);
 }
@@ -2030,8 +2025,7 @@ _cairo_surface_fill_stroke (cairo_surface_t	    *surface,
 	goto FINISH;
 
   FINISH:
-    surface->is_clear &= fill_op == CAIRO_OPERATOR_CLEAR;
-    surface->is_clear &= stroke_op == CAIRO_OPERATOR_CLEAR;
+    surface->is_clear = FALSE;
 
     return _cairo_surface_set_error (surface, status);
 }
@@ -2079,7 +2073,7 @@ _cairo_surface_stroke (cairo_surface_t		*surface,
 					     clip);
 
  FINISH:
-    surface->is_clear &= op == CAIRO_OPERATOR_CLEAR;
+    surface->is_clear = FALSE;
 
     return _cairo_surface_set_error (surface, status);
 }
@@ -2123,7 +2117,7 @@ _cairo_surface_fill (cairo_surface_t	*surface,
 					   clip);
 
  FINISH:
-    surface->is_clear &= op == CAIRO_OPERATOR_CLEAR;
+    surface->is_clear = FALSE;
 
     return _cairo_surface_set_error (surface, status);
 }
@@ -2525,7 +2519,7 @@ _cairo_surface_show_text_glyphs (cairo_surface_t	    *surface,
     if (dev_scaled_font != scaled_font)
 	cairo_scaled_font_destroy (dev_scaled_font);
 
-    surface->is_clear &= op == CAIRO_OPERATOR_CLEAR;
+    surface->is_clear = FALSE;
 
     return _cairo_surface_set_error (surface, status);
 }
commit 017db956644fa1da22033653490f362d1e3e47e0
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Mar 3 20:06:30 2010 +0000

    gstate: Use _cairo_pattern_clear for CLEAR.

diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index 19d80e8..478b400 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -987,21 +987,23 @@ _clipped (cairo_gstate_t *gstate)
 }
 
 static cairo_operator_t
-_reduce_op (cairo_gstate_t *gstate,
-	    const cairo_pattern_union_t *pattern)
+_reduce_op (cairo_gstate_t *gstate)
 {
     cairo_operator_t op;
+    const cairo_pattern_t *pattern;
 
     op = gstate->op;
+    pattern = gstate->source;
     if (op == CAIRO_OPERATOR_SOURCE &&
 	pattern->type == CAIRO_PATTERN_TYPE_SOLID)
     {
-	if (pattern->solid.color.alpha_short <= 0x00ff) {
+	const cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern;
+	if (solid->color.alpha_short <= 0x00ff) {
 	    op = CAIRO_OPERATOR_CLEAR;
 	} else if ((gstate->target->content & CAIRO_CONTENT_ALPHA) == 0) {
-	    if ((pattern->solid.color.red_short |
-		 pattern->solid.color.green_short |
-		 pattern->solid.color.blue_short) <= 0x00ff)
+	    if ((solid->color.red_short |
+		 solid->color.green_short |
+		 solid->color.blue_short) <= 0x00ff)
 	    {
 		op = CAIRO_OPERATOR_CLEAR;
 	    }
@@ -1014,9 +1016,11 @@ _reduce_op (cairo_gstate_t *gstate,
 cairo_status_t
 _cairo_gstate_paint (cairo_gstate_t *gstate)
 {
-    cairo_pattern_union_t pattern;
+    cairo_pattern_union_t source_pattern;
+    const cairo_pattern_t *pattern;
     cairo_clip_t clip;
     cairo_status_t status;
+    cairo_operator_t op;
 
     if (unlikely (gstate->source->status))
 	return gstate->source->status;
@@ -1027,11 +1031,16 @@ _cairo_gstate_paint (cairo_gstate_t *gstate)
     if (_clipped (gstate))
 	return CAIRO_STATUS_SUCCESS;
 
-    _cairo_gstate_copy_transformed_source (gstate, &pattern.base);
+    op = _reduce_op (gstate);
+    if (op == CAIRO_OPERATOR_CLEAR) {
+	pattern = &_cairo_pattern_clear.base;
+    } else {
+	_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
+	pattern = &source_pattern.base;
+    }
 
     status = _cairo_surface_paint (gstate->target,
-				   _reduce_op (gstate, &pattern),
-				   &pattern.base,
+				   op, pattern,
 				   _gstate_get_clip (gstate, &clip));
     _cairo_clip_fini (&clip);
 
@@ -1043,6 +1052,8 @@ _cairo_gstate_mask (cairo_gstate_t  *gstate,
 		    cairo_pattern_t *mask)
 {
     cairo_pattern_union_t source_pattern, mask_pattern;
+    const cairo_pattern_t *source;
+    cairo_operator_t op;
     cairo_clip_t clip;
     cairo_status_t status;
 
@@ -1067,40 +1078,44 @@ _cairo_gstate_mask (cairo_gstate_t  *gstate,
 	return CAIRO_STATUS_SUCCESS;
     }
 
-    _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
+    op = _reduce_op (gstate);
+    if (op == CAIRO_OPERATOR_CLEAR) {
+	source = &_cairo_pattern_clear.base;
+    } else {
+	_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
+	source = &source_pattern.base;
+    }
     _cairo_gstate_copy_transformed_mask (gstate, &mask_pattern.base, mask);
 
-    if (source_pattern.type == CAIRO_PATTERN_TYPE_SOLID &&
+    if (source->type == CAIRO_PATTERN_TYPE_SOLID &&
 	mask_pattern.type == CAIRO_PATTERN_TYPE_SOLID)
     {
+	const cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) source;
 	cairo_color_t combined;
 
 	if (mask_pattern.base.has_component_alpha) {
 #define M(R, A, B, c) R.c = A.c * B.c
-	    M(combined, source_pattern.solid.color, mask_pattern.solid.color, red);
-	    M(combined, source_pattern.solid.color, mask_pattern.solid.color, green);
-	    M(combined, source_pattern.solid.color, mask_pattern.solid.color, blue);
-	    M(combined, source_pattern.solid.color, mask_pattern.solid.color, alpha);
+	    M(combined, solid->color, mask_pattern.solid.color, red);
+	    M(combined, solid->color, mask_pattern.solid.color, green);
+	    M(combined, solid->color, mask_pattern.solid.color, blue);
+	    M(combined, solid->color, mask_pattern.solid.color, alpha);
 #undef M
 	} else {
-	    combined = source_pattern.solid.color;
+	    combined = solid->color;
 	    _cairo_color_multiply_alpha (&combined, mask_pattern.solid.color.alpha);
 	}
 
 	_cairo_pattern_init_solid (&source_pattern.solid, &combined,
-				   source_pattern.solid.content |
-				   mask_pattern.solid.content);
+				   solid->content | mask_pattern.solid.content);
 
-	status = _cairo_surface_paint (gstate->target,
-				       _reduce_op (gstate, &source_pattern),
+	status = _cairo_surface_paint (gstate->target, op,
 				       &source_pattern.base,
 				       _gstate_get_clip (gstate, &clip));
     }
     else
     {
-	status = _cairo_surface_mask (gstate->target,
-				      _reduce_op (gstate, &source_pattern),
-				      &source_pattern.base,
+	status = _cairo_surface_mask (gstate->target, op,
+				      source,
 				      &mask_pattern.base,
 				      _gstate_get_clip (gstate, &clip));
     }
@@ -1142,7 +1157,7 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
     _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
 
     status = _cairo_surface_stroke (gstate->target,
-				    _reduce_op (gstate, &source_pattern),
+				    gstate->op,
 				    &source_pattern.base,
 				    path,
 				    &style,
@@ -1238,14 +1253,19 @@ _cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
 				       &_cairo_pattern_clear.base,
 				       _gstate_get_clip (gstate, &clip));
     } else {
-	cairo_pattern_union_t pattern;
+	cairo_pattern_union_t source_pattern;
+	const cairo_pattern_t *pattern;
 	cairo_operator_t op;
 	cairo_rectangle_int_t extents;
 	cairo_box_t box;
 
-	_cairo_gstate_copy_transformed_source (gstate, &pattern.base);
-
-	op = _reduce_op (gstate, &pattern);
+	op = _reduce_op (gstate);
+	if (op == CAIRO_OPERATOR_CLEAR) {
+	    pattern = &_cairo_pattern_clear.base;
+	} else {
+	    _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
+	    pattern = &source_pattern.base;
+	}
 
 	/* Toolkits often paint the entire background with a fill */
 	if (_cairo_surface_get_extents (gstate->target, &extents) &&
@@ -1255,12 +1275,12 @@ _cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
 	    box.p2.x >= _cairo_fixed_from_int (extents.x + extents.width) &&
 	    box.p2.y >= _cairo_fixed_from_int (extents.y + extents.height))
 	{
-	    status = _cairo_surface_paint (gstate->target, op, &pattern.base,
+	    status = _cairo_surface_paint (gstate->target, op, pattern,
 					   _gstate_get_clip (gstate, &clip));
 	}
 	else
 	{
-	    status = _cairo_surface_fill (gstate->target, op, &pattern.base,
+	    status = _cairo_surface_fill (gstate->target, op, pattern,
 					  path,
 					  gstate->fill_rule,
 					  gstate->tolerance,
@@ -1861,10 +1881,12 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t		   *gstate,
 				cairo_text_cluster_flags_t  cluster_flags)
 {
     cairo_pattern_union_t source_pattern;
+    const cairo_pattern_t *pattern;
     cairo_glyph_t stack_transformed_glyphs[CAIRO_STACK_ARRAY_LENGTH (cairo_glyph_t)];
     cairo_glyph_t *transformed_glyphs;
     cairo_text_cluster_t stack_transformed_clusters[CAIRO_STACK_ARRAY_LENGTH (cairo_text_cluster_t)];
     cairo_text_cluster_t *transformed_clusters;
+    cairo_operator_t op;
     cairo_status_t status;
     cairo_clip_t clip;
 
@@ -1916,7 +1938,13 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t		   *gstate,
     if (status || num_glyphs == 0)
 	goto CLEANUP_GLYPHS;
 
-    _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
+    op = _reduce_op (gstate);
+    if (op == CAIRO_OPERATOR_CLEAR) {
+	pattern = &_cairo_pattern_clear.base;
+    } else {
+	_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
+	pattern = &source_pattern.base;
+    }
 
     /* For really huge font sizes, we can just do path;fill instead of
      * show_glyphs, as show_glyphs would put excess pressure on the cache,
@@ -1931,9 +1959,7 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t		   *gstate,
     if (cairo_surface_has_show_text_glyphs (gstate->target) ||
 	_cairo_scaled_font_get_max_scale (gstate->scaled_font) <= 10240)
     {
-	status = _cairo_surface_show_text_glyphs (gstate->target,
-						  _reduce_op (gstate, &source_pattern),
-						  &source_pattern.base,
+	status = _cairo_surface_show_text_glyphs (gstate->target, op, pattern,
 						  utf8, utf8_len,
 						  transformed_glyphs, num_glyphs,
 						  transformed_clusters, num_clusters,
@@ -1952,9 +1978,7 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t		   *gstate,
 						&path);
 
 	if (status == CAIRO_STATUS_SUCCESS) {
-	    status = _cairo_surface_fill (gstate->target,
-					  _reduce_op (gstate, &source_pattern),
-					  &source_pattern.base,
+	    status = _cairo_surface_fill (gstate->target, op, pattern,
 					  &path,
 					  CAIRO_FILL_RULE_WINDING,
 					  gstate->tolerance,
commit 70412bba0e9fd0ac6e7343d7aebe953355207aab
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Mar 3 17:34:39 2010 +0000

    test: Avoid derefencing a NULL xcb connection

diff --git a/test/xcb-surface-source.c b/test/xcb-surface-source.c
index d359cf2..d2c7a13 100644
--- a/test/xcb-surface-source.c
+++ b/test/xcb-surface-source.c
@@ -90,6 +90,7 @@ static cairo_surface_t *
 create_source_surface (int size)
 {
 #if CAIRO_HAS_XCB_SURFACE
+    xcb_connection_t *connection;
     xcb_render_pictforminfo_t *render_format;
     struct closure *data;
     cairo_surface_t *surface;
@@ -97,30 +98,34 @@ create_source_surface (int size)
     xcb_void_cookie_t cookie;
     void *formats;
 
+    connection = xcb_connect (NULL, NULL);
+    if (connection == NULL)
+	return NULL;
+
     data = xmalloc (sizeof (struct closure));
+    data->connection = connection;
 
-    data->connection = xcb_connect (NULL, NULL);
-    render_format = find_depth (data->connection, 32, &formats);
+    render_format = find_depth (connection, 32, &formats);
     if (render_format == NULL) {
-	xcb_disconnect (data->connection);
+	xcb_disconnect (connection);
 	free (data);
 	return NULL;
     }
 
-    root = xcb_setup_roots_iterator (xcb_get_setup (data->connection)).data;
+    root = xcb_setup_roots_iterator (xcb_get_setup (connection)).data;
 
-    data->pixmap = xcb_generate_id (data->connection);
-    cookie = xcb_create_pixmap_checked (data->connection, 32,
+    data->pixmap = xcb_generate_id (connection);
+    cookie = xcb_create_pixmap_checked (connection, 32,
 					data->pixmap, root->root, size, size);
     /* slow, but sure */
-    if (xcb_request_check (data->connection, cookie) != NULL) {
+    if (xcb_request_check (connection, cookie) != NULL) {
 	free (formats);
-	xcb_disconnect (data->connection);
+	xcb_disconnect (connection);
 	free (data);
 	return NULL;
     }
 
-    surface = cairo_xcb_surface_create_with_xrender_format (data->connection,
+    surface = cairo_xcb_surface_create_with_xrender_format (connection,
 							    root,
 							    data->pixmap,
 							    render_format,
commit 5bfea8447b1b2333218295f51a9474d061192d49
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Mar 3 21:32:13 2010 +0000

    test: Add references for rounded-rectangle-{fill,stroke}

diff --git a/test/Makefile.am b/test/Makefile.am
index 77e8237..fc0c59c 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -838,7 +838,9 @@ REFERENCE_IMAGES = \
 	rotated-clip.ref.png \
 	rotated-clip.ps.ref.png \
 	rotated-clip.xlib.ref.png \
+	rounded-rectangle-fill.ref.png \
 	rounded-rectangle-fill.xlib.ref.png \
+	rounded-rectangle-stroke.ref.png \
 	rounded-rectangle-stroke.xlib.ref.png \
 	scale-down-source-surface-paint.ref.png \
 	scale-offset-image.gl.ref.png \
diff --git a/test/rounded-rectangle-fill.ref.png b/test/rounded-rectangle-fill.ref.png
new file mode 100644
index 0000000..3232c07
Binary files /dev/null and b/test/rounded-rectangle-fill.ref.png differ
diff --git a/test/rounded-rectangle-stroke.ref.png b/test/rounded-rectangle-stroke.ref.png
new file mode 100644
index 0000000..0e8bb25
Binary files /dev/null and b/test/rounded-rectangle-stroke.ref.png differ


More information about the cairo-commit mailing list