xf86-video-intel: 10 commits - src/sna/kgem.c src/sna/sna_accel.c src/sna/sna_composite.c src/sna/sna_damage.c src/sna/sna_display.c src/sna/sna_dri.c src/sna/sna.h src/sna/sna_io.c

Chris Wilson ickle at kemper.freedesktop.org
Mon Jul 1 10:23:55 PDT 2013


 src/sna/kgem.c          |   57 +++++++++++--
 src/sna/sna.h           |    4 
 src/sna/sna_accel.c     |   94 ++++++++++++++---------
 src/sna/sna_composite.c |    6 -
 src/sna/sna_damage.c    |    2 
 src/sna/sna_display.c   |    2 
 src/sna/sna_dri.c       |    4 
 src/sna/sna_io.c        |  196 ++++++++++++++++++++++++++----------------------
 8 files changed, 221 insertions(+), 144 deletions(-)

New commits:
commit 1c8a33a72e29261d6bf5a6c160765cbafa4d0b88
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Jul 1 17:41:41 2013 +0100

    sna: Allow scanouts to be untiled if need be
    
    Fixes regression from
    commit 77fa8ab08b441934218ddb8f690be1a919f0ec64 [2.21.11]
    Author: Chris Wilson <chris at chris-wilson.co.uk>
    Date:   Tue Jun 25 22:25:25 2013 +0100
    
        sna: Free just-allocated bo if we fail to set-tiling on CREATE_EXACT
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index e0925b2..ac6e739 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -3693,13 +3693,14 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem,
 	uint32_t pitch, tiled_height, size;
 	uint32_t handle;
 	int i, bucket, retry;
+	bool exact = flags & (CREATE_EXACT | CREATE_SCANOUT);
 
 	if (tiling < 0)
-		tiling = -tiling, flags |= CREATE_EXACT;
+		exact = true, tiling = -tiling;
+
 
 	DBG(("%s(%dx%d, bpp=%d, tiling=%d, exact=%d, inactive=%d, cpu-mapping=%d, gtt-mapping=%d, scanout?=%d, prime?=%d, temp?=%d)\n", __FUNCTION__,
-	     width, height, bpp, tiling,
-	     !!(flags & CREATE_EXACT),
+	     width, height, bpp, tiling, exact,
 	     !!(flags & CREATE_INACTIVE),
 	     !!(flags & CREATE_CPU_MAP),
 	     !!(flags & CREATE_GTT_MAP),
@@ -3998,7 +3999,7 @@ search_again:
 		}
 	}
 
-	if (--retry && flags & CREATE_EXACT) {
+	if (--retry && exact) {
 		if (kgem->gen >= 040) {
 			for (i = I915_TILING_NONE; i <= I915_TILING_Y; i++) {
 				if (i == tiling)
@@ -4041,7 +4042,7 @@ search_again:
 		goto search_again;
 	}
 
-	if ((flags & CREATE_EXACT) == 0) { /* allow an active near-miss? */
+	if (!exact) { /* allow an active near-miss? */
 		i = tiling;
 		while (--i >= 0) {
 			tiled_height = kgem_surface_size(kgem, kgem->has_relaxed_fencing, flags,
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 32a74ea..9d8bd4c 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -1492,7 +1492,7 @@ sna_pixmap_create_mappable_gpu(PixmapPtr pixmap,
 
 	create = CREATE_GTT_MAP | CREATE_INACTIVE;
 	if (pixmap->usage_hint == SNA_CREATE_FB)
-		create |= CREATE_EXACT | CREATE_SCANOUT;
+		create |= CREATE_SCANOUT;
 
 	priv->gpu_bo =
 		kgem_create_2d(&sna->kgem,
@@ -2899,7 +2899,7 @@ sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, const BoxRec *box, unsigned int fl
 
 			create = CREATE_INACTIVE;
 			if (pixmap->usage_hint == SNA_CREATE_FB)
-				create |= CREATE_EXACT | CREATE_SCANOUT;
+				create |= CREATE_SCANOUT;
 
 			tiling = (flags & MOVE_SOURCE_HINT) ? I915_TILING_Y : DEFAULT_TILING;
 			tiling = sna_pixmap_choose_tiling(pixmap, tiling);
@@ -3621,7 +3621,7 @@ sna_pixmap_move_to_gpu(PixmapPtr pixmap, unsigned flags)
 			if (flags & MOVE_INPLACE_HINT || (priv->cpu_damage && priv->cpu_bo == NULL))
 				create = CREATE_GTT_MAP | CREATE_INACTIVE;
 			if (pixmap->usage_hint == SNA_CREATE_FB)
-				create |= CREATE_EXACT | CREATE_SCANOUT;
+				create |= CREATE_SCANOUT;
 
 			priv->gpu_bo =
 				kgem_create_2d(&sna->kgem,
@@ -3987,7 +3987,7 @@ create_upload_tiled_x(struct kgem *kgem,
 	assert(priv->gpu_bo == NULL);
 	assert(priv->gpu_damage == NULL);
 
-	create = CREATE_CPU_MAP | CREATE_INACTIVE | CREATE_EXACT;
+	create = CREATE_CPU_MAP | CREATE_INACTIVE;
 	if (pixmap->usage_hint == SNA_CREATE_FB)
 		create |= CREATE_SCANOUT;
 	if (!kgem->has_llc)
@@ -3998,7 +3998,7 @@ create_upload_tiled_x(struct kgem *kgem,
 			       pixmap->drawable.width,
 			       pixmap->drawable.height,
 			       pixmap->drawable.bitsPerPixel,
-			       I915_TILING_X, create);
+			       -I915_TILING_X, create);
 	return priv->gpu_bo != NULL;
 }
 
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 0b40fb2..d22eeaa 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -1250,7 +1250,7 @@ static struct kgem_bo *sna_crtc_attach(xf86CrtcPtr crtc)
 		bo = kgem_create_2d(&sna->kgem,
 				    crtc->mode.HDisplay, crtc->mode.VDisplay,
 				    scrn->bitsPerPixel,
-				    tiling, CREATE_EXACT | CREATE_SCANOUT);
+				    tiling, CREATE_SCANOUT);
 		if (bo == NULL)
 			return NULL;
 
diff --git a/src/sna/sna_dri.c b/src/sna/sna_dri.c
index ca5f088..b65ebff 100644
--- a/src/sna/sna_dri.c
+++ b/src/sna/sna_dri.c
@@ -243,7 +243,7 @@ sna_dri_create_buffer(DrawablePtr draw,
 	struct sna_dri_private *private;
 	PixmapPtr pixmap;
 	struct kgem_bo *bo;
-	unsigned flags = CREATE_EXACT;
+	unsigned flags = 0;
 	uint32_t size;
 	int bpp;
 
@@ -1612,7 +1612,7 @@ sna_dri_flip_get_back(struct sna *sna, struct sna_dri_frame_event *info)
 				    info->draw->height,
 				    info->draw->bitsPerPixel,
 				    get_private(info->front)->bo->tiling,
-				    CREATE_SCANOUT | CREATE_EXACT);
+				    CREATE_SCANOUT);
 		if (bo == NULL)
 			return;
 
commit 9cb6756ce16491e42c6e21bc74a5f7de5432510f
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Jul 1 17:27:17 2013 +0100

    sna: Always create the clear Picture
    
    As we unconditionally use it irrespective of whether we then call
    accelerated code paths or not.
    
    Fixes regression from
    commit dc18eaa585c36c8e5f5b4ec405a976a835fd2ac3 [2.20.10]
    Author: Chris Wilson <chris at chris-wilson.co.uk>
    Date:   Sun Aug 12 10:34:10 2012 +0100
    
        sna: Make the failure to create render caches non-fatal
    
    in the event we need to start with a hung GPU.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_composite.c b/src/sna/sna_composite.c
index da3fd62..566f042 100644
--- a/src/sna/sna_composite.c
+++ b/src/sna/sna_composite.c
@@ -46,9 +46,6 @@ bool sna_composite_create(struct sna *sna)
 	xRenderColor color = { 0 };
 	int error;
 
-	if (!can_render(sna))
-		return true;
-
 	sna->clear = CreateSolidPicture(0, &color, &error);
 	return sna->clear != NULL;
 }
@@ -562,7 +559,8 @@ sna_composite(CARD8 op,
 	if (op == PictOpClear) {
 		DBG(("%s: discarding source and mask for clear\n", __FUNCTION__));
 		mask = NULL;
-		src = sna->clear;
+		if (sna->clear)
+			src = sna->clear;
 	}
 
 	if (mask && sna_composite_mask_is_opaque(mask)) {
commit c6c6ae71bedce43ff6617179c015c303cbaee9ae
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Jul 1 17:00:17 2013 +0100

    sna: Make sure we are consistent in applying USE_INPLACE debug option
    
    A few new paths were missing the debug check, and clarify a few indirect
    uses by performing the explicit check.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 1b1d53f..32a74ea 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -1906,7 +1906,8 @@ skip_inplace_map:
 
 	assert(priv->gpu_bo == NULL || priv->gpu_bo->proxy == NULL);
 
-	if (operate_inplace(priv, flags) &&
+	if (USE_INPLACE &&
+	    operate_inplace(priv, flags) &&
 	    pixmap_inplace(sna, pixmap, priv, flags) &&
 	     sna_pixmap_create_mappable_gpu(pixmap, (flags & MOVE_READ) == 0)) {
 		DBG(("%s: try to operate inplace (GTT)\n", __FUNCTION__));
@@ -1946,7 +1947,8 @@ skip_inplace_map:
 		priv->mapped = false;
 	}
 
-	if (priv->gpu_damage && priv->cpu_damage == NULL && !priv->cow &&
+	if (USE_INPLACE &&
+	    priv->gpu_damage && priv->cpu_damage == NULL && !priv->cow &&
 	    (flags & MOVE_READ || kgem_bo_can_map__cpu(&sna->kgem, priv->gpu_bo, flags & MOVE_WRITE)) &&
 	    priv->gpu_bo->tiling == I915_TILING_NONE &&
 	    ((flags & (MOVE_WRITE | MOVE_ASYNC_HINT)) == 0 ||
@@ -2293,7 +2295,8 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
 		return _sna_pixmap_move_to_cpu(pixmap, flags);
 	}
 
-	if (operate_inplace(priv, flags) &&
+	if (USE_INPLACE &&
+	    operate_inplace(priv, flags) &&
 	    region_inplace(sna, pixmap, region, priv, flags) &&
 	     sna_pixmap_create_mappable_gpu(pixmap, false)) {
 		DBG(("%s: try to operate inplace\n", __FUNCTION__));
@@ -2347,7 +2350,8 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
 		priv->mapped = false;
 	}
 
-	if (priv->gpu_damage &&
+	if (USE_INPLACE &&
+	    priv->gpu_damage &&
 	    (DAMAGE_IS_ALL(priv->gpu_damage) ||
 	     sna_damage_contains_box__no_reduce(priv->gpu_damage,
 						&region->extents)) &&
@@ -14382,6 +14386,9 @@ sna_get_image_inplace(PixmapPtr pixmap,
 	struct sna *sna = to_sna_from_pixmap(pixmap);
 	char *src;
 
+	if (!USE_INPLACE)
+		return false;
+
 	if (priv == NULL || priv->gpu_bo == NULL)
 		return false;
 
commit cce2351056eda1282a521b96f90ba12436e86492
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Jul 1 16:13:47 2013 +0100

    sna: Debug options for forcing mmap syncs
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index e905f20..e0925b2 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -76,6 +76,8 @@ search_snoop_cache(struct kgem *kgem, unsigned int num_pages, unsigned flags);
 #define DBG_NO_HANDLE_LUT 0
 #define DBG_DUMP 0
 
+#define FORCE_MMAP_SYNC 0 /* ((1 << DOMAIN_CPU) | (1 << DOMAIN_GTT)) */
+
 #ifndef DEBUG_SYNC
 #define DEBUG_SYNC 0
 #endif
@@ -4768,7 +4770,7 @@ void *kgem_bo_map(struct kgem *kgem, struct kgem_bo *bo)
 		DBG(("%s: caching GTT vma for %d\n", __FUNCTION__, bo->handle));
 	}
 
-	if (bo->domain != DOMAIN_GTT) {
+	if (bo->domain != DOMAIN_GTT || FORCE_MMAP_SYNC & (1 << DOMAIN_GTT)) {
 		struct drm_i915_gem_set_domain set_domain;
 
 		DBG(("%s: sync: needs_flush? %d, domain? %d, busy? %d\n", __FUNCTION__,
@@ -5039,7 +5041,7 @@ void kgem_bo_sync__cpu(struct kgem *kgem, struct kgem_bo *bo)
 	while (bo->proxy)
 		bo = bo->proxy;
 
-	if (bo->domain != DOMAIN_CPU) {
+	if (bo->domain != DOMAIN_CPU || FORCE_MMAP_SYNC & (1 << DOMAIN_CPU)) {
 		struct drm_i915_gem_set_domain set_domain;
 
 		DBG(("%s: SYNC: handle=%d, needs_flush? %d, domain? %d, busy? %d\n",
@@ -5070,7 +5072,7 @@ void kgem_bo_sync__cpu_full(struct kgem *kgem, struct kgem_bo *bo, bool write)
 	while (bo->proxy)
 		bo = bo->proxy;
 
-	if (bo->domain != DOMAIN_CPU) {
+	if (bo->domain != DOMAIN_CPU || FORCE_MMAP_SYNC & (1 << DOMAIN_CPU)) {
 		struct drm_i915_gem_set_domain set_domain;
 
 		DBG(("%s: SYNC: handle=%d, needs_flush? %d, domain? %d, busy? %d\n",
@@ -5097,7 +5099,7 @@ void kgem_bo_sync__gtt(struct kgem *kgem, struct kgem_bo *bo)
 	assert(bo->proxy == NULL);
 	kgem_bo_submit(kgem, bo);
 
-	if (bo->domain != DOMAIN_GTT) {
+	if (bo->domain != DOMAIN_GTT || FORCE_MMAP_SYNC & (1 << DOMAIN_GTT)) {
 		struct drm_i915_gem_set_domain set_domain;
 
 		DBG(("%s: SYNC: handle=%d, needs_flush? %d, domain? %d, busy? %d\n",
commit 7aff6beb37c91df85c46372d44ae4a5fefae5ae8
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Jul 1 17:57:49 2013 +0100

    sna: Improve the message about where to find the hang state
    
    Search the few canonical locations for our hang state so that we can be
    more explicit to the user about what to include.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index aadc5f2..e905f20 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -2833,6 +2833,32 @@ void _kgem_submit(struct kgem *kgem)
 	assert(kgem->next_request != NULL);
 }
 
+static void find_hang_state(struct kgem *kgem, char *path, int maxlen)
+{
+	int i;
+
+	/* Search for our hang state in a few canonical locations.
+	 * In the unlikely event of having multiple devices, we
+	 * will need to check which minor actually corresponds to ours.
+	 */
+
+	for (i = 0; i < DRM_MAX_MINOR; i++) {
+		snprintf(path, maxlen, "/sys/class/drm/card%d/error", i);
+		if (access(path, R_OK) == 0)
+			return;
+
+		snprintf(path, maxlen, "/sys/kernel/debug/dri%d/i915_error_state", i);
+		if (access(path, R_OK) == 0)
+			return;
+
+		snprintf(path, maxlen, "/debug/dri%d/i915_error_state", i);
+		if (access(path, R_OK) == 0)
+			return;
+	}
+
+	path[0] = '\0';
+}
+
 void kgem_throttle(struct kgem *kgem)
 {
 	kgem->need_throttle = 0;
@@ -2841,10 +2867,16 @@ void kgem_throttle(struct kgem *kgem)
 
 	kgem->wedged = __kgem_throttle(kgem);
 	if (kgem->wedged) {
+		char path[128];
+
+		find_hang_state(kgem, path, sizeof(path));
+
 		xf86DrvMsg(kgem_get_screen_index(kgem), X_ERROR,
 			   "Detected a hung GPU, disabling acceleration.\n");
-		xf86DrvMsg(kgem_get_screen_index(kgem), X_ERROR,
-			   "When reporting this, please include i915_error_state from debugfs and the full dmesg.\n");
+		if (*path != '\0')
+			xf86DrvMsg(kgem_get_screen_index(kgem), X_ERROR,
+				   "When reporting this, please include %s and the full dmesg.\n",
+				   path);
 	}
 }
 
commit e0e84e6686be390ef204117525d4a5c6aebbbe07
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Jul 1 16:49:50 2013 +0100

    sna: Mark an inplace getimage as preferring the CPU mapping afterwards
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 82b9ec0..1b1d53f 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -14437,6 +14437,13 @@ sna_get_image_inplace(PixmapPtr pixmap,
 			   region->extents.y2 - region->extents.y1);
 	}
 
+	if (!priv->shm) {
+		pixmap->devPrivate.ptr = src;
+		pixmap->devKind = priv->gpu_bo->pitch;
+		priv->mapped = true;
+		priv->cpu = true;
+	}
+
 	return true;
 }
 
commit e648c1f39cc17d39eff077639f23687894724b7b
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Jul 1 15:27:38 2013 +0100

    sna: Assert that we do not have overlapping damage
    
    Double check that the results of the box query match with the slow
    queries.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index a51e289..82b9ec0 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -2358,6 +2358,8 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
 		DBG(("%s: try to operate inplace (CPU), read? %d, write? %d\n",
 		     __FUNCTION__, !!(flags & MOVE_READ), !!(flags & MOVE_WRITE)));
 		assert(priv->cow == NULL || (flags & MOVE_WRITE) == 0);
+		assert(sna_damage_contains_box(priv->gpu_damage, &region->extents) == PIXMAN_REGION_IN);
+		assert(sna_damage_contains_box(priv->cpu_damage, &region->extents) == PIXMAN_REGION_OUT);
 
 		assert(!priv->mapped);
 		pixmap->devPrivate.ptr =
@@ -2515,6 +2517,9 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
 		} else {
 			if (sna_damage_contains_box__no_reduce(priv->cpu_damage,
 							       &region->extents)) {
+				assert(sna_damage_contains_box(priv->gpu_damage, &region->extents) == PIXMAN_REGION_OUT);
+				assert(sna_damage_contains_box(priv->cpu_damage, &region->extents) == PIXMAN_REGION_IN);
+
 				DBG(("%s: region already in CPU damage\n",
 				     __FUNCTION__));
 				goto done;
@@ -2613,6 +2618,9 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
 				DBG(("%s: region wholly inside damage\n",
 				     __FUNCTION__));
 
+				assert(sna_damage_contains_box(priv->gpu_damage, &r->extents) == PIXMAN_REGION_IN);
+				assert(sna_damage_contains_box(priv->cpu_damage, &r->extents) == PIXMAN_REGION_OUT);
+
 				if (use_cpu_bo_for_download(sna, priv, n, box)) {
 					DBG(("%s: using CPU bo for download from GPU\n", __FUNCTION__));
 					ok = sna->render.copy_boxes(sna, GXcopy,
@@ -2965,6 +2973,10 @@ sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, const BoxRec *box, unsigned int fl
 	} else if (DAMAGE_IS_ALL(priv->cpu_damage) ||
 		   sna_damage_contains_box__no_reduce(priv->cpu_damage, box)) {
 		bool ok = false;
+
+		assert(sna_damage_contains_box(priv->gpu_damage, box) == PIXMAN_REGION_OUT);
+		assert(sna_damage_contains_box(priv->cpu_damage, box) == PIXMAN_REGION_IN);
+
 		if (use_cpu_bo_for_upload(sna, priv, 0)) {
 			DBG(("%s: using CPU bo for upload to GPU\n", __FUNCTION__));
 			ok = sna->render.copy_boxes(sna, GXcopy,
@@ -3243,6 +3255,8 @@ create_gpu_bo:
 							       &region.extents)) {
 				DBG(("%s: region wholly contained within GPU damage\n",
 				     __FUNCTION__));
+				assert(sna_damage_contains_box(priv->gpu_damage, &region.extents) == PIXMAN_REGION_IN);
+				assert(sna_damage_contains_box(priv->cpu_damage, &region.extents) == PIXMAN_REGION_OUT);
 				goto use_gpu_bo;
 			} else {
 				DBG(("%s: partial GPU damage with no CPU damage, continuing to use GPU\n",
@@ -3410,9 +3424,11 @@ cpu_fail:
 	} else {
 		if (priv->cpu_damage &&
 		    sna_damage_contains_box__no_reduce(priv->cpu_damage,
-						       &region.extents))
+						       &region.extents)) {
+			assert(sna_damage_contains_box(priv->gpu_damage, &region.extents) == PIXMAN_REGION_OUT);
+			assert(sna_damage_contains_box(priv->cpu_damage, &region.extents) == PIXMAN_REGION_IN);
 			*damage = NULL;
-		else
+		} else
 			*damage = &priv->cpu_damage;
 	}
 
@@ -14327,6 +14343,9 @@ sna_get_image_blt(PixmapPtr pixmap,
 
 	DBG(("%s: download through a temporary map\n", __FUNCTION__));
 
+	assert(sna_damage_contains_box(priv->gpu_damage, &region->extents) == PIXMAN_REGION_IN);
+	assert(sna_damage_contains_box(priv->cpu_damage, &region->extents) == PIXMAN_REGION_OUT);
+
 	pitch = PixmapBytePad(region->extents.x2 - region->extents.x1,
 			      pixmap->drawable.depth);
 	dst_bo = kgem_create_map(&sna->kgem, dst,
@@ -14385,6 +14404,9 @@ sna_get_image_inplace(PixmapPtr pixmap,
 						 &region->extents)))
 		return false;
 
+	assert(sna_damage_contains_box(priv->gpu_damage, &region->extents) == PIXMAN_REGION_IN);
+	assert(sna_damage_contains_box(priv->cpu_damage, &region->extents) == PIXMAN_REGION_OUT);
+
 	src = kgem_bo_map__cpu(&sna->kgem, priv->gpu_bo);
 	if (src == NULL)
 		return false;
commit 7c6cc0c9edb8f1ebcc8be5edb78c9d858dce1965
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Jul 1 15:04:58 2013 +0100

    sna: Check whether the query box is contained within the damage
    
    We can improve our query for whether the rectangle of interest is within
    the damage by checking whether the damage extents contains the entire
    box rather than just checking for an overlap.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_damage.c b/src/sna/sna_damage.c
index 377b5ac..d2a876d 100644
--- a/src/sna/sna_damage.c
+++ b/src/sna/sna_damage.c
@@ -1345,7 +1345,7 @@ bool _sna_damage_contains_box__no_reduce(const struct sna_damage *damage,
 	int ret;
 
 	assert(damage && damage->mode != DAMAGE_ALL);
-	if (!sna_damage_overlaps_box(damage, box))
+	if (!box_contains(&damage->extents, box))
 		return false;
 
 	ret = pixman_region_contains_rectangle(&damage->region, (BoxPtr)box);
commit 64cb923588df0547880009bbeaeecb7ac3ee8ecf
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Jul 1 14:30:21 2013 +0100

    sna: Experiment with cpu mappings for migration
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna.h b/src/sna/sna.h
index 7fe7359..2f14fad 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -802,9 +802,7 @@ void sna_glyphs__shared(CARD8 op,
 void sna_glyph_unrealize(ScreenPtr screen, GlyphPtr glyph);
 void sna_glyphs_close(struct sna *sna);
 
-void sna_read_boxes(struct sna *sna,
-		    struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
-		    PixmapPtr dst, int16_t dst_dx, int16_t dst_dy,
+void sna_read_boxes(struct sna *sna, PixmapPtr dst, struct kgem_bo *src_bo,
 		    const BoxRec *box, int n);
 bool sna_write_boxes(struct sna *sna, PixmapPtr dst,
 		     struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index dfa3356..a51e289 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -138,10 +138,7 @@ static void __sna_fallback_flush(DrawablePtr d)
 					   0);
 
 	DBG(("%s: comparing with direct read...\n", __FUNCTION__));
-	sna_read_boxes(sna,
-		       priv->gpu_bo, 0, 0,
-		       tmp, 0, 0,
-		       &box, 1);
+	sna_read_boxes(sna, tmp, priv->gpu_bo, &box, 1);
 
 	src = pixmap->devPrivate.ptr;
 	dst = tmp->devPrivate.ptr;
@@ -2054,9 +2051,7 @@ skip_inplace_map:
 			}
 			if (!ok) {
 				assert(has_coherent_ptr(sna_pixmap(pixmap)));
-				sna_read_boxes(sna,
-					       priv->gpu_bo, 0, 0,
-					       pixmap, 0, 0,
+				sna_read_boxes(sna, pixmap, priv->gpu_bo,
 					       box, n);
 			}
 		}
@@ -2491,9 +2486,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
 			}
 			if (!ok) {
 				assert(has_coherent_ptr(sna_pixmap(pixmap)));
-				sna_read_boxes(sna,
-					       priv->gpu_bo, 0, 0,
-					       pixmap, 0, 0,
+				sna_read_boxes(sna, pixmap, priv->gpu_bo,
 					       box, n);
 			}
 		}
@@ -2515,9 +2508,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
 			    region->extents.y2 - region->extents.y1 == 1) {
 				/*  Often associated with synchronisation, KISS */
 				DBG(("%s: single pixel read\n", __FUNCTION__));
-				sna_read_boxes(sna,
-					       priv->gpu_bo, 0, 0,
-					       pixmap, 0, 0,
+				sna_read_boxes(sna, pixmap, priv->gpu_bo,
 					       &region->extents, 1);
 				goto done;
 			}
@@ -2542,9 +2533,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
 			if ((flags & MOVE_WRITE) == 0 &&
 			    region->extents.x2 - region->extents.x1 == 1 &&
 			    region->extents.y2 - region->extents.y1 == 1) {
-				sna_read_boxes(sna,
-					       priv->gpu_bo, 0, 0,
-					       pixmap, 0, 0,
+				sna_read_boxes(sna, pixmap, priv->gpu_bo,
 					       &region->extents, 1);
 				goto done;
 			}
@@ -2608,9 +2597,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
 
 					if (!ok) {
 						assert(has_coherent_ptr(sna_pixmap(pixmap)));
-						sna_read_boxes(sna,
-							       priv->gpu_bo, 0, 0,
-							       pixmap, 0, 0,
+						sna_read_boxes(sna, pixmap, priv->gpu_bo,
 							       box, n);
 					}
 				}
@@ -2635,9 +2622,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
 				}
 				if (!ok) {
 					assert(has_coherent_ptr(sna_pixmap(pixmap)));
-					sna_read_boxes(sna,
-						       priv->gpu_bo, 0, 0,
-						       pixmap, 0, 0,
+					sna_read_boxes(sna, pixmap, priv->gpu_bo,
 						       box, n);
 				}
 
@@ -2663,9 +2648,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
 					}
 					if (!ok) {
 						assert(has_coherent_ptr(sna_pixmap(pixmap)));
-						sna_read_boxes(sna,
-							       priv->gpu_bo, 0, 0,
-							       pixmap, 0, 0,
+						sna_read_boxes(sna, pixmap, priv->gpu_bo,
 							       box, n);
 					}
 
diff --git a/src/sna/sna_io.c b/src/sna/sna_io.c
index a4932b8..7861462 100644
--- a/src/sna/sna_io.c
+++ b/src/sna/sna_io.c
@@ -53,55 +53,91 @@ static inline bool must_tile(struct sna *sna, int width, int height)
 		upload_too_large(sna, width, height));
 }
 
-static bool bo_inplace_tiled(struct kgem *kgem, struct kgem_bo *bo, bool write)
+static bool download_inplace__cpu(struct kgem *kgem,
+				  PixmapPtr p, struct kgem_bo *bo,
+				  const BoxRec *box, int nbox)
 {
-	if (bo->tiling != I915_TILING_X)
-		return false;
+	BoxRec extents;
 
-	return kgem_bo_can_map__cpu(kgem, bo, write);
-}
+	switch (bo->tiling) {
+	case I915_TILING_X:
+		if (!kgem->memcpy_from_tiled_x)
+			return false;
+	case I915_TILING_NONE:
+		break;
+	default:
+		return false;
+	}
 
-static bool download_inplace__tiled(struct kgem *kgem, struct kgem_bo *bo)
-{
-	if (!kgem->memcpy_from_tiled_x)
+	if (!kgem_bo_can_map__cpu(kgem, bo, false))
 		return false;
 
-	return bo_inplace_tiled(kgem, bo, false);
+	if (kgem->has_llc)
+		return true;
+
+	extents = *box;
+	while (--nbox) {
+		++box;
+		if (box->x1 < extents.x1)
+			extents.x1 = box->x1;
+		if (box->x2 > extents.x2)
+			extents.x2 = box->x2;
+		extents.y2 = box->y2;
+	}
+
+	if (extents.x2 - extents.x1 == p->drawable.width &&
+	    extents.y2 - extents.y1 == p->drawable.height)
+		return true;
+
+	return __kgem_bo_size(bo) <= PAGE_SIZE;
 }
 
 static bool
-read_boxes_inplace__tiled(struct kgem *kgem,
-			  struct kgem_bo *bo, int16_t src_dx, int16_t src_dy,
-			  PixmapPtr pixmap, int16_t dst_dx, int16_t dst_dy,
-			  const BoxRec *box, int n)
+read_boxes_inplace__cpu(struct kgem *kgem,
+			PixmapPtr pixmap, struct kgem_bo *bo,
+			const BoxRec *box, int n)
 {
 	int bpp = pixmap->drawable.bitsPerPixel;
 	void *src, *dst = pixmap->devPrivate.ptr;
 	int src_pitch = bo->pitch;
 	int dst_pitch = pixmap->devKind;
 
-	assert(bo->tiling == I915_TILING_X);
+	if (!download_inplace__cpu(kgem, dst, bo, box, n))
+		return false;
+
+	assert(kgem_bo_can_map__cpu(kgem, bo, false));
+	assert(bo->tiling != I915_TILING_Y);
 
 	src = __kgem_bo_map__cpu(kgem, bo);
 	if (src == NULL)
 		return false;
 
 	kgem_bo_sync__cpu_full(kgem, bo, 0);
-	do {
-		memcpy_from_tiled_x(kgem, src, dst, bpp, src_pitch, dst_pitch,
-				  box->x1 + src_dx, box->y1 + src_dy,
-				  box->x1 + dst_dx, box->y1 + dst_dy,
-				  box->x2 - box->x1, box->y2 - box->y1);
-		box++;
-	} while (--n);
+	if (bo->tiling == I915_TILING_X) {
+		assert(kgem->memcpy_from_tiled_x);
+		do {
+			memcpy_from_tiled_x(kgem, src, dst, bpp, src_pitch, dst_pitch,
+					    box->x1, box->y1,
+					    box->x1, box->y1,
+					    box->x2 - box->x1, box->y2 - box->y1);
+			box++;
+		} while (--n);
+	} else {
+		do {
+			memcpy_blt(src, dst, bpp, src_pitch, dst_pitch,
+				   box->x1, box->y1,
+				   box->x1, box->y1,
+				   box->x2 - box->x1, box->y2 - box->y1);
+			box++;
+		} while (--n);
+	}
 	__kgem_bo_unmap__cpu(kgem, bo, src);
 
 	return true;
 }
 
 static void read_boxes_inplace(struct kgem *kgem,
-			       struct kgem_bo *bo, int16_t src_dx, int16_t src_dy,
-			       PixmapPtr pixmap, int16_t dst_dx, int16_t dst_dy,
+			       PixmapPtr pixmap, struct kgem_bo *bo,
 			       const BoxRec *box, int n)
 {
 	int bpp = pixmap->drawable.bitsPerPixel;
@@ -109,10 +145,7 @@ static void read_boxes_inplace(struct kgem *kgem,
 	int src_pitch = bo->pitch;
 	int dst_pitch = pixmap->devKind;
 
-	if (download_inplace__tiled(kgem, bo) &&
-	    read_boxes_inplace__tiled(kgem, bo, src_dx, src_dy,
-				      pixmap, dst_dx, dst_dy,
-				      box, n))
+	if (read_boxes_inplace__cpu(kgem, pixmap, bo, box, n))
 		return;
 
 	DBG(("%s x %d, tiling=%d\n", __FUNCTION__, n, bo->tiling));
@@ -134,31 +167,36 @@ static void read_boxes_inplace(struct kgem *kgem,
 		assert(box->x2 > box->x1);
 		assert(box->y2 > box->y1);
 
-		assert(box->x1 + src_dx >= 0);
-		assert(box->y1 + src_dy >= 0);
-		assert(box->x2 + src_dx <= pixmap->drawable.width);
-		assert(box->y2 + src_dy <= pixmap->drawable.height);
+		assert(box->x1 >= 0);
+		assert(box->y1 >= 0);
+		assert(box->x2 <= pixmap->drawable.width);
+		assert(box->y2 <= pixmap->drawable.height);
 
-		assert(box->x1 + dst_dx >= 0);
-		assert(box->y1 + dst_dy >= 0);
-		assert(box->x2 + dst_dx <= pixmap->drawable.width);
-		assert(box->y2 + dst_dy <= pixmap->drawable.height);
+		assert(box->x1 >= 0);
+		assert(box->y1 >= 0);
+		assert(box->x2 <= pixmap->drawable.width);
+		assert(box->y2 <= pixmap->drawable.height);
 
 		memcpy_blt(src, dst, bpp,
 			   src_pitch, dst_pitch,
-			   box->x1 + src_dx, box->y1 + src_dy,
-			   box->x1 + dst_dx, box->y1 + dst_dy,
+			   box->x1, box->y1,
+			   box->x1, box->y1,
 			   box->x2 - box->x1, box->y2 - box->y1);
 		box++;
 	} while (--n);
 }
 
-static bool download_inplace(struct kgem *kgem, struct kgem_bo *bo)
+static bool download_inplace(struct kgem *kgem,
+			     PixmapPtr p, struct kgem_bo *bo,
+			     const BoxRec *box, int nbox)
 {
+	bool cpu;
+
 	if (unlikely(kgem->wedged))
 		return true;
 
-	if (!kgem_bo_can_map(kgem, bo) && !download_inplace__tiled(kgem, bo))
+	cpu = download_inplace__cpu(kgem, p, bo, box, nbox);
+	if (!cpu && !kgem_bo_can_map(kgem, bo))
 		return false;
 
 	if (FORCE_INPLACE)
@@ -167,14 +205,10 @@ static bool download_inplace(struct kgem *kgem, struct kgem_bo *bo)
 	if (kgem->can_blt_cpu && kgem->max_cpu_size)
 		return false;
 
-	return !__kgem_bo_is_busy(kgem, bo) ||
-		bo->tiling == I915_TILING_NONE ||
-		download_inplace__tiled(kgem, bo);
+	return !__kgem_bo_is_busy(kgem, bo) || cpu;
 }
 
-void sna_read_boxes(struct sna *sna,
-		    struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
-		    PixmapPtr dst, int16_t dst_dx, int16_t dst_dy,
+void sna_read_boxes(struct sna *sna, PixmapPtr dst, struct kgem_bo *src_bo,
 		    const BoxRec *box, int nbox)
 {
 	struct kgem *kgem = &sna->kgem;
@@ -188,20 +222,19 @@ void sna_read_boxes(struct sna *sna,
 	int n, cmd, br13;
 	bool can_blt;
 
-	DBG(("%s x %d, src=(handle=%d, offset=(%d,%d)), dst=(size=(%d, %d), offset=(%d,%d))\n",
-	     __FUNCTION__, nbox, src_bo->handle, src_dx, src_dy,
-	     dst->drawable.width, dst->drawable.height, dst_dx, dst_dy));
+	DBG(("%s x %d, src=(handle=%d), dst=(size=(%d, %d)\n",
+	     __FUNCTION__, nbox, src_bo->handle, src_dy,
+	     dst->drawable.width, dst->drawable.height));
 
 #ifndef NDEBUG
 	for (n = 0; n < nbox; n++) {
-		if (box[n].x1 + src_dx < 0 || box[n].y1 + src_dy < 0 ||
-		    (box[n].x2 + src_dx) * dst->drawable.bitsPerPixel/8 > src_bo->pitch ||
-		    (box[n].y2 + src_dy) * src_bo->pitch > kgem_bo_size(src_bo))
+		if (box[n].x1 < 0 || box[n].y1 < 0 ||
+		    box[n].x2 * dst->drawable.bitsPerPixel/8 > src_bo->pitch ||
+		    box[n].y2 * src_bo->pitch > kgem_bo_size(src_bo))
 		{
-			FatalError("source out-of-bounds box[%d]=(%d, %d), (%d, %d) + (%d, %d), pitch=%d, size=%d\n", n,
+			FatalError("source out-of-bounds box[%d]=(%d, %d), (%d, %d), pitch=%d, size=%d\n", n,
 				   box[n].x1, box[n].y1,
 				   box[n].x2, box[n].y2,
-				   src_dx, src_dy,
 				   src_bo->pitch, kgem_bo_size(src_bo));
 		}
 	}
@@ -213,12 +246,9 @@ void sna_read_boxes(struct sna *sna,
 	 * this path.
 	 */
 
-	if (download_inplace(kgem, src_bo)) {
+	if (download_inplace(kgem, dst, src_bo, box ,nbox)) {
 fallback:
-		read_boxes_inplace(kgem,
-				   src_bo, src_dx, src_dy,
-				   dst, dst_dx, dst_dy,
-				   box, nbox);
+		read_boxes_inplace(kgem, dst, src_bo, box, nbox);
 		return;
 	}
 
@@ -297,11 +327,10 @@ fallback:
 						if (!box_intersect(c, &tile))
 							continue;
 
-						DBG(("%s: box(%d, %d), (%d, %d), src=(%d, %d), dst=(%d, %d)\n",
+						DBG(("%s: box(%d, %d), (%d, %d),, dst=(%d, %d)\n",
 						     __FUNCTION__,
 						     c->x1, c->y1,
 						     c->x2, c->y2,
-						     src_dx, src_dy,
 						     c->x1 - tile.x1,
 						     c->y1 - tile.y1));
 						c++;
@@ -322,7 +351,7 @@ fallback:
 					}
 
 					if (!sna->render.copy_boxes(sna, GXcopy,
-								    dst, src_bo, src_dx, src_dy,
+								    dst, src_bo, 0, 0,
 								    &tmp, dst_bo, -tile.x1, -tile.y1,
 								    clipped, c-clipped, COPY_LAST)) {
 						kgem_bo_destroy(&sna->kgem, dst_bo);
@@ -339,8 +368,7 @@ fallback:
 							   dst_bo->pitch, dst->devKind,
 							   c->x1 - tile.x1,
 							   c->y1 - tile.y1,
-							   c->x1 + dst_dx,
-							   c->y1 + dst_dy,
+							   c->x1, c->y1,
 							   c->x2 - c->x1,
 							   c->y2 - c->y1);
 					}
@@ -362,7 +390,7 @@ fallback:
 				goto fallback;
 
 			if (!sna->render.copy_boxes(sna, GXcopy,
-						    dst, src_bo, src_dx, src_dy,
+						    dst, src_bo, 0, 0,
 						    &tmp, dst_bo, -extents.x1, -extents.y1,
 						    box, nbox, COPY_LAST)) {
 				kgem_bo_destroy(&sna->kgem, dst_bo);
@@ -377,8 +405,7 @@ fallback:
 					   dst_bo->pitch, dst->devKind,
 					   box[n].x1 - extents.x1,
 					   box[n].y1 - extents.y1,
-					   box[n].x1 + dst_dx,
-					   box[n].y1 + dst_dy,
+					   box[n].x1, box[n].y1,
 					   box[n].x2 - box[n].x1,
 					   box[n].y2 - box[n].y1);
 			}
@@ -401,10 +428,7 @@ fallback:
 
 	dst_bo = kgem_create_buffer(kgem, offset, KGEM_BUFFER_LAST, &ptr);
 	if (!dst_bo) {
-		read_boxes_inplace(kgem,
-				   src_bo, src_dx, src_dy,
-				   dst, dst_dx, dst_dy,
-				   box, nbox);
+		read_boxes_inplace(kgem, dst, src_bo, box, nbox);
 		return;
 	}
 
@@ -455,15 +479,13 @@ fallback:
 			uint32_t *b = kgem->batch + kgem->nbatch;
 
 			DBG(("    blt offset %x: (%d, %d) x (%d, %d), pitch=%d\n",
-			     offset,
-			     tmp_box[n].x1 + src_dx,
-			     tmp_box[n].y1 + src_dy,
+			     offset, tmp_box[n].x1, tmp_box[n].y1,
 			     width, height, pitch));
 
-			assert(tmp_box[n].x1 + src_dx >= 0);
-			assert((tmp_box[n].x2 + src_dx) * dst->drawable.bitsPerPixel/8 <= src_bo->pitch);
-			assert(tmp_box[n].y1 + src_dy >= 0);
-			assert((tmp_box[n].y2 + src_dy) * src_bo->pitch <= kgem_bo_size(src_bo));
+			assert(tmp_box[n].x1 >= 0);
+			assert(tmp_box[n].x2 * dst->drawable.bitsPerPixel/8 <= src_bo->pitch);
+			assert(tmp_box[n].y1 >= 0);
+			assert(tmp_box[n].y2 * src_bo->pitch <= kgem_bo_size(src_bo));
 
 			b[0] = cmd;
 			b[1] = br13 | pitch;
@@ -474,7 +496,7 @@ fallback:
 					      I915_GEM_DOMAIN_RENDER |
 					      KGEM_RELOC_FENCED,
 					      offset);
-			b[5] = (tmp_box[n].y1 + src_dy) << 16 | (tmp_box[n].x1 + src_dx);
+			b[5] = tmp_box[n].y1 << 16 | tmp_box[n].x1;
 			b[6] = src_pitch;
 			b[7] = kgem_add_reloc(kgem, kgem->nbatch + 7, src_bo,
 					      I915_GEM_DOMAIN_RENDER << 16 |
@@ -505,20 +527,19 @@ fallback:
 		DBG(("    copy offset %lx [%08x...%08x...%08x]: (%d, %d) x (%d, %d), src pitch=%d, dst pitch=%d, bpp=%d\n",
 		     (long)((char *)src - (char *)ptr),
 		     *(uint32_t*)src, *(uint32_t*)(src+pitch*height/2 + pitch/2 - 4), *(uint32_t*)(src+pitch*height - 4),
-		     box->x1 + dst_dx,
-		     box->y1 + dst_dy,
+		     box->x1, box->y1,
 		     width, height,
 		     pitch, dst->devKind, cpp*8));
 
-		assert(box->x1 + dst_dx >= 0);
-		assert(box->x2 + dst_dx <= dst->drawable.width);
-		assert(box->y1 + dst_dy >= 0);
-		assert(box->y2 + dst_dy <= dst->drawable.height);
+		assert(box->x1 >= 0);
+		assert(box->x2 <= dst->drawable.width);
+		assert(box->y1 >= 0);
+		assert(box->y2 <= dst->drawable.height);
 
 		memcpy_blt(src, dst->devPrivate.ptr, cpp*8,
 			   pitch, dst->devKind,
 			   0, 0,
-			   box->x1 + dst_dx, box->y1 + dst_dy,
+			   box->x1, box->y1,
 			   width, height);
 		box++;
 
@@ -534,7 +555,10 @@ static bool upload_inplace__tiled(struct kgem *kgem, struct kgem_bo *bo)
 	if (!kgem->memcpy_to_tiled_x)
 		return false;
 
-	return bo_inplace_tiled(kgem, bo, true);
+	if (bo->tiling != I915_TILING_X)
+		return false;
+
+	return kgem_bo_can_map__cpu(kgem, bo, true);
 }
 
 static bool
commit 12c013d25ed0c08f748b0a7250cbcef1cded26b0
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Jul 1 13:28:57 2013 +0100

    sna: Do not use userptr for GetImage on unsupported architectures
    
    If the system cannot blt to a CPU buffer, we should even attempt to do
    so for GetImage.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 80bc198..dfa3356 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -14324,6 +14324,9 @@ sna_get_image_blt(PixmapPtr pixmap,
 	if (!sna->kgem.has_userptr || !USE_USERPTR_DOWNLOADS)
 		return false;
 
+	if (!sna->kgem.can_blt_cpu)
+		return false;
+
 	if (flags & (MOVE_WHOLE_HINT | MOVE_INPLACE_HINT))
 		return false;
 


More information about the xorg-commit mailing list