summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2013-06-27 12:32:24 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2013-06-27 12:50:59 +0100
commit5124f35168c0cc162cf5e8bcaafdf756945f6ca9 (patch)
tree84b312825295c6383ec7c252172997d4f9b896b1 /src
parent18ee5c20d5f8f1752b89f2377e9b9c3f1c140d53 (diff)
sna: Support operations inplace on CPU mappings of a region
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src')
-rw-r--r--src/sna/sna_accel.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 2bbca72f..3783933c 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -2341,6 +2341,56 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
priv->mapped = false;
}
+ if (priv->gpu_damage &&
+ (DAMAGE_IS_ALL(priv->gpu_damage) ||
+ sna_damage_contains_box__no_reduce(priv->gpu_damage,
+ &region->extents)) &&
+ priv->gpu_bo->tiling == I915_TILING_NONE &&
+ (priv->gpu_bo->domain == DOMAIN_CPU || sna->kgem.has_llc) &&
+ ((flags & (MOVE_WRITE | MOVE_ASYNC_HINT)) == 0 ||
+ !__kgem_bo_is_busy(&sna->kgem, priv->gpu_bo))) {
+ DBG(("%s: try to operate inplace (CPU)\n", __FUNCTION__));
+ assert(priv->cow == NULL || (flags & MOVE_WRITE) == 0);
+
+ assert(!priv->mapped);
+ pixmap->devPrivate.ptr =
+ kgem_bo_map__cpu(&sna->kgem, priv->gpu_bo);
+ if (pixmap->devPrivate.ptr != NULL) {
+ assert(has_coherent_map(sna, priv->gpu_bo));
+ assert(IS_CPU_MAP(priv->gpu_bo->map));
+ pixmap->devKind = priv->gpu_bo->pitch;
+ priv->cpu = true;
+ priv->mapped = true;
+ if (flags & MOVE_WRITE) {
+ if (!DAMAGE_IS_ALL(priv->gpu_damage)) {
+ sna_damage_add(&priv->gpu_damage, region);
+ if (sna_damage_is_all(&priv->gpu_damage,
+ pixmap->drawable.width,
+ pixmap->drawable.height)) {
+ DBG(("%s: replaced entire pixmap, destroying CPU shadow\n",
+ __FUNCTION__));
+ assert(priv->cpu == false || (priv->mapped && IS_CPU_MAP(priv->gpu_bo->map)));
+ sna_damage_destroy(&priv->cpu_damage);
+ list_del(&priv->flush_list);
+ } else
+ sna_damage_subtract(&priv->cpu_damage,
+ region);
+ }
+ priv->clear = false;
+ }
+ assert_pixmap_damage(pixmap);
+ kgem_bo_sync__cpu_full(&sna->kgem, priv->gpu_bo,
+ FORCE_FULL_SYNC || flags & MOVE_WRITE);
+ assert(pixmap->devPrivate.ptr == (void *)((unsigned long)priv->gpu_bo->map & ~3));
+ assert((flags & MOVE_WRITE) == 0 || !kgem_bo_is_busy(priv->gpu_bo));
+ assert_pixmap_damage(pixmap);
+ if (dx | dy)
+ RegionTranslate(region, -dx, -dy);
+ DBG(("%s: operate inplace (CPU)\n", __FUNCTION__));
+ return true;
+ }
+ }
+
if ((priv->clear || (flags & MOVE_READ) == 0) &&
priv->cpu_bo && !priv->cpu_bo->flush &&
__kgem_bo_is_busy(&sna->kgem, priv->cpu_bo)) {