[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

xserver-xorg-video-intel: Changes to 'upstream-experimental'



 src/intel_glamor.c          |   14 ---
 src/intel_glamor.h          |    2 
 src/sna/blt.c               |    4 
 src/sna/gen3_render.c       |  152 +++++++++++++++++++---------------
 src/sna/kgem.c              |  192 ++++++++++++++++++++++++++++++++------------
 src/sna/kgem.h              |    3 
 src/sna/sna.h               |   20 ++++
 src/sna/sna_accel.c         |  151 ++++++++++++++++++++++++++--------
 src/sna/sna_blt.c           |   23 ++++-
 src/sna/sna_composite.c     |   22 +++++
 src/sna/sna_damage.c        |  188 ++++++++++++++++++++++++++++++-------------
 src/sna/sna_damage.h        |    4 
 src/sna/sna_render_inline.h |    4 
 src/sna/sna_trapezoids.c    |   14 +--
 uxa/uxa-accel.c             |  142 +++++++++++++++++++++++++++++++-
 uxa/uxa-glamor.h            |   11 ++
 uxa/uxa.c                   |   12 ++
 17 files changed, 709 insertions(+), 249 deletions(-)

New commits:
commit 4119e68fb157fc612bce5e9c5669112ce35b4ca1
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Wed Jan 4 19:35:30 2012 +0000

    sna/damage: Fix reduction to copy the boxes correctly
    
    We need to be carefully to copy the boxes in a strict lifo order so as
    to avoid overwritting the last boxes when reusing the array allocations.
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/sna_damage.c b/src/sna/sna_damage.c
index 4cccbdc..18ca10d 100644
--- a/src/sna/sna_damage.c
+++ b/src/sna/sna_damage.c
@@ -219,7 +219,8 @@ _sna_damage_create_elt(struct sna_damage *damage,
 {
 	int n;
 
-	DBG(("    %s: prev=(remain %d)\n", __FUNCTION__, damage->remain));
+	DBG(("    %s: prev=(remain %d), count=%d\n",
+	     __FUNCTION__, damage->remain, count));
 
 	damage->dirty = true;
 	n = count;
@@ -297,7 +298,8 @@ _sna_damage_create_elt_from_rectangles(struct sna_damage *damage,
 {
 	int i, n;
 
-	DBG(("    %s: prev=(remain %d)\n", __FUNCTION__, damage->remain));
+	DBG(("    %s: prev=(remain %d), count=%d\n",
+	     __FUNCTION__, damage->remain, count));
 
 	n = count;
 	if (n > damage->remain)
@@ -340,7 +342,8 @@ _sna_damage_create_elt_from_points(struct sna_damage *damage,
 {
 	int i, n;
 
-	DBG(("    %s: prev=(remain %d)\n", __FUNCTION__, damage->remain));
+	DBG(("    %s: prev=(remain %d), count=%d\n",
+	     __FUNCTION__, damage->remain, count));
 
 	n = count;
 	if (n > damage->remain)
@@ -412,6 +415,7 @@ static void __sna_damage_reduce(struct sna_damage *damage)
 			  list);
 	n = iter->size - damage->remain;
 	boxes = (BoxRec *)(iter+1);
+	DBG(("   last box count=%d/%d, need=%d\n", n, iter->size, nboxes));
 	if (nboxes > iter->size) {
 		boxes = malloc(sizeof(BoxRec)*nboxes);
 		if (boxes == NULL)
@@ -422,29 +426,36 @@ static void __sna_damage_reduce(struct sna_damage *damage)
 
 	if (boxes != damage->embedded_box.box) {
 		if (list_is_empty(&damage->embedded_box.list)) {
+			DBG(("   copying embedded boxes\n"));
 			memcpy(boxes,
 			       damage->embedded_box.box,
 			       n*sizeof(BoxRec));
 		} else {
-			if (damage->mode == DAMAGE_ADD)
-				nboxes -= REGION_NUM_RECTS(region);
+			if (boxes != (BoxPtr)(iter+1)) {
+				DBG(("   copying %d boxes from last\n", n));
+				memcpy(boxes, iter+1, n*sizeof(BoxRec));
+			}
 
-			memcpy(boxes,
-			       damage->embedded_box.box,
-			       sizeof(damage->embedded_box.box));
-			n = damage->embedded_box.size;
-
-			list_for_each_entry(iter, &damage->embedded_box.list, list) {
-				int len = iter->size;
-				if (n + len > nboxes)
-					len = nboxes - n;
-				DBG(("   copy %d/%d boxes from %d\n", len, iter->size, n));
-				memcpy(boxes + n, iter+1, len * sizeof(BoxRec));
-				n += len;
+			iter = list_entry(iter->list.prev,
+					  struct sna_damage_box,
+					  list);
+			while (&iter->list != &damage->embedded_box.list) {
+				DBG(("   copy %d boxes from %d\n",
+				     iter->size, n));
+				memcpy(boxes + n, iter+1,
+				       iter->size * sizeof(BoxRec));
+				n += iter->size;
+
+				iter = list_entry(iter->list.prev,
+						  struct sna_damage_box,
+						  list);
 			}
 
-			if (damage->mode == DAMAGE_ADD)
-				nboxes += REGION_NUM_RECTS(region);
+			DBG(("   copying embedded boxes to %d\n", n));
+			memcpy(boxes + n,
+			       damage->embedded_box.box,
+			       sizeof(damage->embedded_box.box));
+			n += damage->embedded_box.size;
 		}
 	}
 
@@ -455,19 +466,28 @@ static void __sna_damage_reduce(struct sna_damage *damage)
 		assert(n + REGION_NUM_RECTS(region) == nboxes);
 		pixman_region_fini(region);
 		pixman_region_init_rects(region, boxes, nboxes);
+
+		assert(damage->extents.x1 == region->extents.x1 &&
+		       damage->extents.y1 == region->extents.y1 &&
+		       damage->extents.x2 == region->extents.x2 &&
+		       damage->extents.y2 == region->extents.y2);
 	} else {
 		pixman_region16_t tmp;
 
 		pixman_region_init_rects(&tmp, boxes, nboxes);
 		pixman_region_subtract(region, region, &tmp);
 		pixman_region_fini(&tmp);
+
+		assert(damage->extents.x1 <= region->extents.x1 &&
+		       damage->extents.y1 <= region->extents.y1 &&
+		       damage->extents.x2 >= region->extents.x2 &&
+		       damage->extents.y2 >= region->extents.y2);
+		damage->extents = region->extents;
 	}
 
 	if (free_boxes)
 		free(boxes);
 
-	damage->extents = region->extents;
-
 done:
 	damage->mode = DAMAGE_ADD;
 	free_list(&damage->embedded_box.list);
@@ -595,7 +615,7 @@ __sna_damage_add_boxes(struct sna_damage *damage,
 	_sna_damage_create_elt_from_boxes(damage, box, n, dx, dy);
 
 	if (REGION_NUM_RECTS(&damage->region) == 0) {
-		damage->region.extents = box[0];
+		damage->region.extents = damage->embedded_box.box[0];
 		damage->region.data = NULL;
 		damage->extents = extents;
 	} else {
@@ -698,10 +718,7 @@ __sna_damage_add_rectangles(struct sna_damage *damage,
 	_sna_damage_create_elt_from_rectangles(damage, r, n, dx, dy);
 
 	if (REGION_NUM_RECTS(&damage->region) == 0) {
-		damage->region.extents.x1 = r[0].x + dx;
-		damage->region.extents.x2 = r[0].x + r[0].width + dx;
-		damage->region.extents.y1 = r[0].y + dy;
-		damage->region.extents.y2 = r[0].y + r[0].height + dy;
+		damage->region.extents = damage->embedded_box.box[0];
 		damage->region.data = NULL;
 		damage->extents = extents;
 	} else {
@@ -795,10 +812,7 @@ __sna_damage_add_points(struct sna_damage *damage,
 	_sna_damage_create_elt_from_points(damage, p, n, dx, dy);
 
 	if (REGION_NUM_RECTS(&damage->region) == 0) {
-		damage->region.extents.x1 = p[0].x + dx;
-		damage->region.extents.x2 = p[0].x + dx + 1;
-		damage->region.extents.y1 = p[0].y + dy;
-		damage->region.extents.y2 = p[0].y + dy + 1;
+		damage->region.extents = damage->embedded_box.box[0];
 		damage->region.data = NULL;
 		damage->extents = extents;
 	} else {
@@ -940,12 +954,18 @@ struct sna_damage *_sna_damage_all(struct sna_damage *damage,
 struct sna_damage *_sna_damage_is_all(struct sna_damage *damage,
 				      int width, int height)
 {
+	DBG(("%s(%d, %d)%s\n", __FUNCTION__, width, height,
+	     damage->dirty ? "*" : ""));
+	assert(damage->mode == DAMAGE_ADD);
+
+	assert(damage->extents.x1 == 0 &&
+	       damage->extents.y1 == 0 &&
+	       damage->extents.x2 == width &&
+	       damage->extents.y2 == height);
+
 	if (damage->dirty) {
 		__sna_damage_reduce(damage);
-		if (!RegionNotEmpty(&damage->region)) {
-			__sna_damage_destroy(damage);
-			return NULL;
-		}
+		assert(RegionNotEmpty(&damage->region));
 	}
 
 	if (damage->region.data)

commit 71b0924b586d9a60397e92e941e3d0cfa636ee61
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Wed Jan 4 19:34:41 2012 +0000

    sna: Mark tiny CPU pixmaps as completely dirty
    
    Avoid the overhead of tracking damage on small pixmaps when using CPU
    rasterisation; the extra cost of sending the whole pixmap compared to
    the damage is negligble should it ever be required on the GPU.
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index da13efa..68c10a5 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -897,6 +897,9 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
 		return true;
 	}
 
+	if (priv->stride == 0 && priv->gpu_bo == NULL && flags & MOVE_WRITE)
+		return _sna_pixmap_move_to_cpu(pixmap, flags);
+
 	get_drawable_deltas(drawable, pixmap, &dx, &dy);
 	DBG(("%s: delta=(%d, %d)\n", __FUNCTION__, dx, dy));
 	if (dx | dy)

commit fc14e63256a9b756c7c77ffe73f2f13784396c5a
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Wed Jan 4 19:33:30 2012 +0000

    sna: Only request page size allocations for the replacement buffer
    
    A precondition on bo creation is that the size must be page aligned.
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index d34fbd5..51b56eb 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -3131,6 +3131,7 @@ kgem_replace_bo(struct kgem *kgem,
 	assert(src->tiling == I915_TILING_NONE);
 
 	size = height * pitch;
+	size = ALIGN(size, PAGE_SIZE);
 
 	dst = search_linear_cache(kgem, size, 0);
 	if (dst == NULL)

commit 89739b711f42c3dbed7d3f4e6da0cdd61a5205ae
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Wed Jan 4 17:41:16 2012 +0000

    sna: Expand small stipples into 8x8 patterns
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/sna.h b/src/sna/sna.h
index 32288ca..b4d109c 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -703,4 +703,9 @@ memcpy_blt(const void *src, void *dst, int bpp,
 #define SNA_CREATE_FB 0x10
 #define SNA_CREATE_SCRATCH 0x11
 
+inline static bool is_power_of_two(unsigned x)
+{
+	return (x & (x-1)) == 0;
+}
+
 #endif /* _SNA_H */
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index ea178f3..da13efa 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -7008,6 +7008,58 @@ sna_poly_fill_rect_stippled_8x8_blt(DrawablePtr drawable,
 }
 
 static bool
+sna_poly_fill_rect_stippled_nxm_blt(DrawablePtr drawable,
+				    struct kgem_bo *bo,
+				    struct sna_damage **damage,
+				    GCPtr gc, int n, xRectangle *r,
+				    const BoxRec *extents, unsigned clipped)
+{
+	PixmapPtr scratch, stipple;
+	uint8_t bytes[8], *dst = bytes;
+	const uint8_t *src, *end;
+	int j, stride;
+	bool ret;
+
+	DBG(("%s: expanding %dx%d stipple to 8x8\n",
+	     __FUNCTION__,
+	     gc->stipple->drawable.width,
+	     gc->stipple->drawable.height));
+
+	scratch = GetScratchPixmapHeader(drawable->pScreen,
+					 8, 8, 1, 1, 1, bytes);
+	if (scratch == NullPixmap)
+		return false;
+
+	stipple = gc->stipple;
+	gc->stipple = scratch;
+
+	stride = stipple->devKind;
+	src = stipple->devPrivate.ptr;
+	end = src + stride * stipple->drawable.height;
+	for(j = 0; j < 8; j++) {
+		switch (stipple->drawable.width) {
+		case 1: *dst = (*src & 1) * 0xff; break;
+		case 2: *dst = (*src & 3) * 0x55; break;
+		case 4: *dst = (*src & 15) * 0x11; break;
+		case 8: *dst = *src; break;
+		default: assert(0); break;
+		}
+		dst++;
+		src += stride;
+		if (src == end)
+			src = stipple->devPrivate.ptr;
+	}
+
+	ret = sna_poly_fill_rect_stippled_8x8_blt(drawable, bo, damage,
+						  gc, n, r, extents, clipped);
+
+	gc->stipple = stipple;
+	FreeScratchPixmapHeader(scratch);
+
+	return ret;
+}
+
+static bool
 sna_poly_fill_rect_stippled_1_blt(DrawablePtr drawable,
 				  struct kgem_bo *bo,
 				  struct sna_damage **damage,
@@ -7685,11 +7737,18 @@ sna_poly_fill_rect_stippled_blt(DrawablePtr drawable,
 	     extents->y2 - gc->patOrg.y - drawable->y,
 	     stipple->drawable.width, stipple->drawable.height));
 
-	if (stipple->drawable.width == 8 && stipple->drawable.height == 8)
+	if ((stipple->drawable.width | stipple->drawable.height) == 8)
 		return sna_poly_fill_rect_stippled_8x8_blt(drawable, bo, damage,
 							   gc, n, rect,
 							   extents, clipped);
 
+	if ((stipple->drawable.width | stipple->drawable.height) <= 0xc &&
+	    is_power_of_two(stipple->drawable.width) &&
+	    is_power_of_two(stipple->drawable.height))
+		return sna_poly_fill_rect_stippled_nxm_blt(drawable, bo, damage,
+							   gc, n, rect,
+							   extents, clipped);
+
 	if (extents->x2 - gc->patOrg.x - drawable->x <= stipple->drawable.width &&
 	    extents->y2 - gc->patOrg.y - drawable->y <= stipple->drawable.height) {
 		if (stipple->drawable.width <= 8 && stipple->drawable.height <= 8)

commit 878fbfe509da0a25dff8515d6d3b38ca3826466e
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Wed Jan 4 16:56:55 2012 +0000

    sna: Align tiled stipple uploads with the stipple pixmap correctly
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 43d7aa1..ea178f3 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -7474,15 +7474,15 @@ sna_poly_fill_rect_stippled_n_box(struct sna *sna,
 			bx2 = ox + (x2 - x1);
 			if (bx2 - bx1 > gc->stipple->drawable.width) {
 				bx2 = bx1 + gc->stipple->drawable.width;
-				x2 = x1 + (bx2 - bx1);
+				x2 = x1 + (bx1-ox) + gc->stipple->drawable.width;
 			}
-			bx2 = (bx2 + 7) &~7;
+			bx2 = (bx2 + 7) & ~7;
 			bw = (bx2 - bx1)/8;
 			bw = ALIGN(bw, 2);
 			bh = y2 - y1;
 
-			DBG(("%s: box(%d, %d), (%d, %d) pat=(%d, %d)\n",
-			     __FUNCTION__, x1, y1, x2, y2, ox, oy));
+			DBG(("%s: box(%d, %d), (%d, %d) pat=(%d, %d), up=(%d, %d)\n",
+			     __FUNCTION__, x1, y1, x2, y2, ox, oy, bx1, bx2));
 
 			len = bw*bh;
 			len = ALIGN(len, 8) / 4;
@@ -7494,8 +7494,7 @@ sna_poly_fill_rect_stippled_n_box(struct sna *sna,
 			}
 
 			b = sna->kgem.batch + sna->kgem.nbatch;
-			b[0] = XY_MONO_SRC_COPY_IMM | (5 + len) | br00;
-			b[0] |= (ox & 7) << 17;
+			b[0] = br00 | (5 + len) | (ox & 7) << 17;
 			b[1] = br13;
 			b[2] = y1 << 16 | x1;
 			b[3] = y2 << 16 | x2;
@@ -7541,10 +7540,11 @@ sna_poly_fill_rect_stippled_n_blt(DrawablePtr drawable,
 	int16_t dx, dy;
 	uint32_t br00, br13;
 
-	DBG(("%s: upload (%d, %d), (%d, %d), origin (%d, %d)\n", __FUNCTION__,
+	DBG(("%s: upload (%d, %d), (%d, %d), origin (%d, %d), clipped=%d\n", __FUNCTION__,
 	     extents->x1, extents->y1,
 	     extents->x2, extents->y2,
-	     origin.x, origin.y));
+	     origin.x, origin.y,
+	     clipped));
 
 	if (gc->stipple->drawable.width > 32 ||
 	    gc->stipple->drawable.height > 32)
@@ -7553,7 +7553,7 @@ sna_poly_fill_rect_stippled_n_blt(DrawablePtr drawable,
 	get_drawable_deltas(drawable, pixmap, &dx, &dy);
 	kgem_set_mode(&sna->kgem, KGEM_BLT);
 
-	br00 = 3 << 20;
+	br00 = XY_MONO_SRC_COPY_IMM | 3 << 20;
 	br13 = bo->pitch;
 	if (sna->kgem.gen >= 40) {
 		if (bo->tiling)

commit 28a222a66bb450c7f6d61aef16fe73332854c8ce
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Wed Jan 4 12:48:25 2012 +0000

    sna: Always prefer to use cacheable operations after the GPU is wedged
    
    As rasterisation will be performed upon the CPU we need to avoid the
    readbacks form uncached memory and so we should restrict ourselves to
    only create further damage within the CPU pixmap.
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index ff02849..43d7aa1 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -662,6 +662,9 @@ static inline bool pixmap_inplace(struct sna *sna,
 	if (FORCE_INPLACE)
 		return FORCE_INPLACE > 0;
 
+	if (wedged(sna))
+		return false;
+
 	if (priv->mapped)
 		return true;
 
@@ -838,6 +841,9 @@ static inline bool region_inplace(struct sna *sna,
 	if (FORCE_INPLACE)
 		return FORCE_INPLACE > 0;
 
+	if (wedged(sna))
+		return false;
+
 	if (priv->mapped)
 		return true;
 

commit 99ff83a3bebf1aa25c44a87f2c344307d20bc062
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Wed Jan 4 12:35:12 2012 +0000

    sna: Prevent creation of bo purely for GTT mapping when wedged
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index c9f4add..ff02849 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -853,6 +853,9 @@ sna_pixmap_create_mappable_gpu(PixmapPtr pixmap)
 	struct sna *sna = to_sna_from_pixmap(pixmap);
 	struct sna_pixmap *priv = sna_pixmap(pixmap);;
 
+	if (wedged(sna))
+		return false;
+
 	assert(priv->gpu_bo == NULL);
 	priv->gpu_bo =
 		kgem_create_2d(&sna->kgem,

commit a7c35fa4c3155d10ad75ac33aefb03dafa010aba
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Wed Jan 4 12:33:09 2012 +0000

    sna: Only allow mappable pixmaps to be mapped
    
    If we did not allocate the pixel data, such as for wedged pixmaps or
    scratch buffers, then we cannot perform the pointer dance nor do we want
    to create the GPU buffer.
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 3b3dc92..c9f4add 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -225,11 +225,14 @@ sna_pixmap_alloc_cpu(struct sna *sna,
 done:
 	pixmap->devPrivate.ptr = priv->ptr;
 	pixmap->devKind = priv->stride;
+	assert(priv->stride);
 	return priv->ptr != NULL;
 }
 
 static void sna_pixmap_free_cpu(struct sna *sna, struct sna_pixmap *priv)
 {
+	assert(priv->stride);
+
 	if (priv->cpu_bo) {
 		DBG(("%s: discarding CPU buffer, handle=%d, size=%d\n",
 		     __FUNCTION__, priv->cpu_bo->handle, priv->cpu_bo->size));
@@ -941,7 +944,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
 			}
 		}
 
-		if (priv->gpu_bo == NULL &&
+		if (priv->gpu_bo == NULL && priv->stride &&
 		    sna_pixmap_choose_tiling(pixmap) != I915_TILING_NONE &&
 		    region_inplace(sna, pixmap, region, priv) &&
 		    sna_pixmap_create_mappable_gpu(pixmap)) {

commit 2cbc97d28aae138566e49df05e16d274b533ea86
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Wed Jan 4 12:32:06 2012 +0000

    sna: Force creation of ordinary pixmaps when wedged.
    
    If the pixmap was intended for scanout, then the GPU bo will be created
    upon attachment to the fb.
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 9279b58..3b3dc92 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -563,6 +563,11 @@ static PixmapPtr sna_create_pixmap(ScreenPtr screen,
 	DBG(("%s(%d, %d, %d, usage=%x)\n", __FUNCTION__,
 	     width, height, depth, usage));
 
+	if (wedged(sna))
+		return create_pixmap(sna, screen,
+				     width, height, depth,
+				     usage);
+
 	if (usage == CREATE_PIXMAP_USAGE_SCRATCH)
 #if USE_BO_FOR_SCRATCH_PIXMAP
 		return sna_pixmap_create_scratch(screen,

commit f6cc73ba66f34d190b7c17421a62aa1256698431
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Wed Jan 4 12:56:31 2012 +0000

    sna: The batch is counted in dwords, not bytes!
    
    Yikes, I choose the wrong units for the max_batch_size.
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 6db2e92..d34fbd5 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -520,7 +520,7 @@ void kgem_init(struct kgem *kgem, int fd, struct pci_device *dev, int gen)
 	kgem->max_batch_size = ARRAY_SIZE(kgem->batch);
 	if (gen == 22)
 		/* 865g cannot handle a batch spanning multiple pages */
-		kgem->max_batch_size = 4096;
+		kgem->max_batch_size = PAGE_SIZE / sizeof(uint32_t);
 
 	kgem->half_cpu_cache_pages = cpu_cache_size() >> 13;
 

commit 227fbb90c4884bbc58c6c0cfff9663ec9ca54171
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Wed Jan 4 11:47:32 2012 +0000

    sna: Carefully free the freed_pixmap upon exit
    
    As the contents of the pixmap are now rubbish, we need to manually
    destroy it rather than pass it to the normal sna_pixmap_destroy()
    routines.
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index ab975a9..9279b58 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -9664,7 +9664,8 @@ void sna_accel_close(struct sna *sna)
 {
 	if (sna->freed_pixmap) {
 		assert(sna->freed_pixmap->refcnt == 1);
-		sna_destroy_pixmap(sna->freed_pixmap);
+		free(sna_pixmap(sna->freed_pixmap));
+		fbDestroyPixmap(sna->freed_pixmap);
 		sna->freed_pixmap = NULL;
 	}
 

commit 0ed758cd2176ee4f34e03d05d05130d52d75e577
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Wed Jan 4 12:18:20 2012 +0000

    sna: Limit batch to a single page on 865g
    
    Verified on real hw, this undocumented (at least in the bspec before me)
    bug truly exists.
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 0e83dfb..6db2e92 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -517,6 +517,11 @@ void kgem_init(struct kgem *kgem, int fd, struct pci_device *dev, int gen)
 	kgem->wedged = drmCommandNone(kgem->fd, DRM_I915_GEM_THROTTLE) == -EIO;
 	kgem->wedged |= DBG_NO_HW;
 
+	kgem->max_batch_size = ARRAY_SIZE(kgem->batch);
+	if (gen == 22)
+		/* 865g cannot handle a batch spanning multiple pages */
+		kgem->max_batch_size = 4096;
+
 	kgem->half_cpu_cache_pages = cpu_cache_size() >> 13;
 
 	list_init(&kgem->partial);
@@ -1121,7 +1126,7 @@ static int kgem_batch_write(struct kgem *kgem, uint32_t handle, uint32_t size)
 	assert(!kgem_busy(kgem, handle));
 
 	/* If there is no surface data, just upload the batch */
-	if (kgem->surface == ARRAY_SIZE(kgem->batch))
+	if (kgem->surface == kgem->max_batch_size)
 		return gem_write(kgem->fd, handle,
 				 0, sizeof(uint32_t)*kgem->nbatch,
 				 kgem->batch);
@@ -1184,7 +1189,7 @@ void kgem_reset(struct kgem *kgem)
 	kgem->aperture = 0;
 	kgem->aperture_fenced = 0;
 	kgem->nbatch = 0;
-	kgem->surface = ARRAY_SIZE(kgem->batch);
+	kgem->surface = kgem->max_batch_size;
 	kgem->mode = KGEM_NONE;
 	kgem->flush = 0;
 
@@ -1198,7 +1203,7 @@ static int compact_batch_surface(struct kgem *kgem)
 	int size, shrink, n;
 
 	/* See if we can pack the contents into one or two pages */
-	size = ARRAY_SIZE(kgem->batch) - kgem->surface + kgem->nbatch;
+	size = kgem->max_batch_size - kgem->surface + kgem->nbatch;
 	if (size > 2048)
 		return sizeof(kgem->batch);
 	else if (size > 1024)
@@ -1237,7 +1242,7 @@ void _kgem_submit(struct kgem *kgem)
 	     kgem->mode, kgem->ring, batch_end, kgem->nbatch, kgem->surface,
 	     kgem->nreloc, kgem->nexec, kgem->nfence, kgem->aperture));
 
-	assert(kgem->nbatch <= ARRAY_SIZE(kgem->batch));
+	assert(kgem->nbatch <= kgem->max_batch_size);
 	assert(kgem->nbatch <= kgem->surface);
 	assert(kgem->nreloc <= ARRAY_SIZE(kgem->reloc));
 	assert(kgem->nexec < ARRAY_SIZE(kgem->exec));
@@ -1247,7 +1252,7 @@ void _kgem_submit(struct kgem *kgem)
 #endif
 
 	rq = kgem->next_request;
-	if (kgem->surface != ARRAY_SIZE(kgem->batch))
+	if (kgem->surface != kgem->max_batch_size)
 		size = compact_batch_surface(kgem);
 	else
 		size = kgem->nbatch * sizeof(kgem->batch[0]);
diff --git a/src/sna/kgem.h b/src/sna/kgem.h
index 7f2ebaf..6aeb1fe 100644
--- a/src/sna/kgem.h
+++ b/src/sna/kgem.h
@@ -116,6 +116,7 @@ struct kgem {
 	uint16_t nexec;
 	uint16_t nreloc;
 	uint16_t nfence;
+	uint16_t max_batch_size;
 	uint16_t vma_count;
 
 	uint32_t flush:1;
@@ -146,7 +147,7 @@ struct kgem {
 #define KGEM_EXEC_RESERVED 1
 
 #define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
-#define KGEM_BATCH_SIZE(K) (ARRAY_SIZE((K)->batch)-KGEM_BATCH_RESERVED)
+#define KGEM_BATCH_SIZE(K) ((K)->max_batch_size-KGEM_BATCH_RESERVED)
 #define KGEM_EXEC_SIZE(K) (int)(ARRAY_SIZE((K)->exec)-KGEM_EXEC_RESERVED)
 #define KGEM_RELOC_SIZE(K) (int)(ARRAY_SIZE((K)->reloc)-KGEM_RELOC_RESERVED)
 
diff --git a/src/sna/sna_render_inline.h b/src/sna/sna_render_inline.h
index 0369123..33fb166 100644
--- a/src/sna/sna_render_inline.h
+++ b/src/sna/sna_render_inline.h
@@ -47,7 +47,7 @@ static inline float pack_2s(int16_t x, int16_t y)
 
 static inline int batch_space(struct sna *sna)
 {
-	return KGEM_BATCH_SIZE(&sna->kgem) - sna->kgem.nbatch;
+	return sna->kgem.surface - sna->kgem.nbatch - KGEM_BATCH_RESERVED;
 }
 
 static inline void batch_emit(struct sna *sna, uint32_t dword)

commit 3449f1cbe184a618e662d2a662167f05362b82e5
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Wed Jan 4 02:38:16 2012 +0000

    sna: Guard against NULL damage deref
    
    The fast version of damage checking assumes that the damage has already
    been determined to be non-NULL, so make sure it is.
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 186041f..ab975a9 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -1296,7 +1296,9 @@ _sna_drawable_use_cpu_bo(DrawablePtr drawable,
 
 done:
 	*damage = &priv->cpu_damage;
-	if (sna_damage_contains_box__no_reduce(priv->cpu_damage, &extents))
+	if (priv->cpu_damage &&
+	    (priv->cpu_damage->mode == DAMAGE_ALL ||
+	     sna_damage_contains_box__no_reduce(priv->cpu_damage, &extents)))
 		*damage = NULL;
 
 	return TRUE;

commit 04a6260016fb5ebefc1056ed6acf5001ec535d5c
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Wed Jan 4 01:14:19 2012 +0000

    sna: Fix typo during partial list deletion
    
    And keep the asserts that lead to its discovery.
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 1e4d08f..0e83dfb 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -111,6 +111,33 @@ struct kgem_partial_bo {
 static struct kgem_bo *__kgem_freed_bo;
 static struct drm_i915_gem_exec_object2 _kgem_dummy_exec;
 
+#ifndef NDEBUG
+static bool validate_partials(struct kgem *kgem)
+{
+	struct kgem_partial_bo *bo, *next;
+
+	list_for_each_entry_safe(bo, next, &kgem->partial, base.list) {
+		if (bo->base.list.next == &kgem->partial)
+			return true;
+		if (bo->alloc - bo->used < next->alloc - next->used) {
+			ErrorF("this rem: %d, next rem: %d\n",
+			       bo->alloc - bo->used,
+			       next->alloc - next->used);
+			goto err;
+		}
+	}
+	return true;
+
+err:
+	list_for_each_entry(bo, &kgem->partial, base.list)
+		ErrorF("bo: used=%d / %d, rem=%d\n",
+		       bo->used, bo->alloc, bo->alloc - bo->used);
+	return false;
+}
+#else
+#define validate_partials(kgem) 1
+#endif
+
 static void kgem_sna_reset(struct kgem *kgem)
 {
 	struct sna *sna = container_of(kgem, struct sna, kgem);
@@ -2141,12 +2168,13 @@ static void _kgem_bo_delete_partial(struct kgem *kgem, struct kgem_bo *bo)
 		while (io->base.list.prev != &kgem->partial) {
 			struct kgem_partial_bo *p;
 
-			p = list_entry(&io->base.list.prev,
+			p = list_entry(io->base.list.prev,
 				       struct kgem_partial_bo,
 				       base.list);
-			if (remain < p->alloc - p->used)
+			if (remain <= p->alloc - p->used)
 				break;
 
+			assert(p->base.list.next == &io->base.list);
 			io->base.list.prev = p->base.list.prev;
 			p->base.list.prev->next = &io->base.list;
 			p->base.list.prev = &io->base.list;
@@ -2154,8 +2182,13 @@ static void _kgem_bo_delete_partial(struct kgem *kgem, struct kgem_bo *bo)
 			p->base.list.next = io->base.list.next;
 			io->base.list.next->prev = &p->base.list;
 			io->base.list.next = &p->base.list;
+
+			assert(p->base.list.next->prev == &p->base.list);
+			assert(io->base.list.prev->next == &io->base.list);
 		}
 	}
+
+	assert(validate_partials(kgem));
 }
 
 void _kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo)
@@ -2712,31 +2745,6 @@ struct kgem_bo *kgem_create_proxy(struct kgem_bo *target,
 	return bo;
 }
 
-#ifndef NDEBUG
-static bool validate_partials(struct kgem *kgem)
-{
-	struct kgem_partial_bo *bo, *next;
-
-	list_for_each_entry_safe(bo, next, &kgem->partial, base.list) {
-		if (bo->base.list.next == &kgem->partial)
-			return true;
-		if (bo->alloc - bo->used < next->alloc - next->used) {
-			ErrorF("this rem: %d, next rem: %d\n",
-			       bo->alloc - bo->used,
-			       next->alloc - next->used);
-			goto err;
-		}
-	}
-	return true;
-
-err:
-	list_for_each_entry(bo, &kgem->partial, base.list)
-		ErrorF("bo: used=%d / %d, rem=%d\n",
-		       bo->used, bo->alloc, bo->alloc - bo->used);
-	return false;
-}
-#endif
-
 struct kgem_bo *kgem_create_buffer(struct kgem *kgem,
 				   uint32_t size, uint32_t flags,
 				   void **ret)

commit f1dc1eadd84097fc691e85c636535ceeeb601a18
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Wed Jan 4 00:09:30 2012 +0000

    sna/gen3: Remove incorrect premultiplication of solid component-alpha mask
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/gen3_render.c b/src/sna/gen3_render.c
index fdd2805..fcbe9c7 100644
--- a/src/sna/gen3_render.c
+++ b/src/sna/gen3_render.c
@@ -2271,10 +2271,10 @@ gen3_composite_set_target(struct sna *sna,
 	return TRUE;
 }
 
-static inline uint8_t mult(uint32_t s, uint32_t m, int shift)
+static inline uint8_t multa(uint32_t s, uint32_t m, int shift)
 {
 	s = (s >> shift) & 0xff;
-	m = (m >> shift) & 0xff;
+	m >>= 24;
 	return (s * m) >> 8;
 }
 
@@ -2292,7 +2292,6 @@ static inline bool is_constant_ps(uint32_t type)
 	}
 }
 
-
 static bool
 is_solid(PicturePtr picture)
 {
@@ -2315,6 +2314,7 @@ source_fallback(PicturePtr p)
 
 static bool
 gen3_composite_fallback(struct sna *sna,
+			uint8_t op,
 			PicturePtr src,
 			PicturePtr mask,
 			PicturePtr dst)
@@ -2347,6 +2347,15 @@ gen3_composite_fallback(struct sna *sna,
 		return TRUE;
 	}
 
+	if (mask &&
+	    mask->componentAlpha && PICT_FORMAT_RGB(mask->format) &&
+	    op != PictOpOver)
+	{
+		DBG(("%s: component-alpha mask with op=%d, should fallback\n",
+		     __FUNCTION__, op));
+		return TRUE;
+	}
+
 	/* If anything is on the GPU, push everything out to the GPU */
 	priv = sna_pixmap(dst_pixmap);
 	if (priv && priv->gpu_damage) {
@@ -2482,7 +2491,7 @@ gen3_render_composite(struct sna *sna,
 			      tmp))
 		return TRUE;
 
-	if (gen3_composite_fallback(sna, src, mask, dst))
+	if (gen3_composite_fallback(sna, op, src, mask, dst))
 		return FALSE;
 
 	if (need_tiling(sna, width, height))
@@ -2563,7 +2572,6 @@ gen3_render_composite(struct sna *sna,
 			}
 		}
 		DBG(("%s: mask type=%d\n", __FUNCTION__, tmp->mask.u.gen3.type));
-
 		if (tmp->mask.u.gen3.type == SHADER_ZERO) {
 			if (tmp->src.bo) {
 				kgem_bo_destroy(&sna->kgem,
@@ -2574,53 +2582,60 @@ gen3_render_composite(struct sna *sna,
 			tmp->mask.u.gen3.type = SHADER_NONE;
 		}
 
-		if (tmp->mask.u.gen3.type != SHADER_NONE &&
-		    mask->componentAlpha && PICT_FORMAT_RGB(mask->format)) {
-			/* Check if it's component alpha that relies on a source alpha
-			 * and on the source value.  We can only get one of those
-			 * into the single source value that we get to blend with.
-			 */
-			tmp->has_component_alpha = TRUE;
-			if (tmp->mask.u.gen3.type == SHADER_WHITE) {
-				tmp->mask.u.gen3.type = SHADER_NONE;
-				tmp->has_component_alpha = FALSE;
-			} else if (is_constant_ps(tmp->src.u.gen3.type) &&
-				   is_constant_ps(tmp->mask.u.gen3.type)) {
-				uint32_t a,r,g,b;
-
-				a = mult(tmp->src.u.gen3.mode,
-					 tmp->mask.u.gen3.mode,
-					 24);
-				r = mult(tmp->src.u.gen3.mode,
-					 tmp->mask.u.gen3.mode,
-					 16);
-				g = mult(tmp->src.u.gen3.mode,
-					 tmp->mask.u.gen3.mode,
-					 8);
-				b = mult(tmp->src.u.gen3.mode,
-					 tmp->mask.u.gen3.mode,
-					 0);
-
-				DBG(("%s: combining constant source/mask: %x x %x -> %x\n",
-				     __FUNCTION__,
-				     tmp->src.u.gen3.mode,
-				     tmp->mask.u.gen3.mode,
-				     a << 24 | r << 16 | g << 8 | b));
-
-				tmp->src.u.gen3.type = SHADER_CONSTANT;
-				tmp->src.u.gen3.mode =
-					a << 24 | r << 16 | g << 8 | b;
-
-				tmp->mask.u.gen3.type = SHADER_NONE;
-				tmp->has_component_alpha = FALSE;
-			} else if (gen3_blend_op[op].src_alpha &&
-				   (gen3_blend_op[op].src_blend != BLENDFACT_ZERO)) {
-				if (op != PictOpOver)
-					goto cleanup_mask;
-
-				tmp->need_magic_ca_pass = TRUE;
-				tmp->op = PictOpOutReverse;
-				sna->render.vertex_start = sna->render.vertex_index;
+		if (tmp->mask.u.gen3.type != SHADER_NONE) {
+			if (mask->componentAlpha && PICT_FORMAT_RGB(mask->format)) {
+				/* Check if it's component alpha that relies on a source alpha
+				 * and on the source value.  We can only get one of those
+				 * into the single source value that we get to blend with.
+				 */
+				DBG(("%s: component-alpha mask: %d\n",
+				     __FUNCTION__, tmp->mask.u.gen3.type));
+				tmp->has_component_alpha = TRUE;
+				if (tmp->mask.u.gen3.type == SHADER_WHITE) {
+					tmp->mask.u.gen3.type = SHADER_NONE;
+					tmp->has_component_alpha = FALSE;
+				} else if (gen3_blend_op[op].src_alpha &&
+					   (gen3_blend_op[op].src_blend != BLENDFACT_ZERO)) {


Reply to: