summaryrefslogtreecommitdiff
path: root/src/sna
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-07-01 10:53:07 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2012-07-01 11:07:50 +0100
commit35b1ac138002c206a6d6b866d49a0d73705dd3ac (patch)
tree7d11e0a67af29e4024e86b425e250c4362333dd2 /src/sna
parente625c02e6266403fcd8a72ccce2c6c6291e2e5fc (diff)
sna: After an operation on the CPU, prefer not to use the GPU
A nasty habit of applications is to fill an area, only to read it back with GetImage, render locally and replace with PutImage. This causes a readback of an active bo everytime, so let's try to mitigate that by preferring not to use the GPU after a forced readback. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src/sna')
-rw-r--r--src/sna/sna.h1
-rw-r--r--src/sna/sna_accel.c36
2 files changed, 36 insertions, 1 deletions
diff --git a/src/sna/sna.h b/src/sna/sna.h
index 66ee6c00..9d365439 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -140,6 +140,7 @@ struct sna_pixmap {
uint8_t undamaged :1;
uint8_t create :3;
uint8_t header :1;
+ uint8_t cpu :1;
};
struct sna_glyph {
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index d280f84c..cb507c10 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -1108,6 +1108,7 @@ _sna_pixmap_move_to_cpu(PixmapPtr pixmap, unsigned int flags)
pixmap->drawable.height);
sna_damage_destroy(&priv->cpu_damage);
priv->undamaged = false;
+ priv->cpu = false;
list_del(&priv->list);
if (priv->cpu_bo) {
assert(!priv->cpu_bo->sync);
@@ -1134,6 +1135,7 @@ skip_inplace_map:
list_del(&priv->list);
priv->undamaged = false;
}
+ priv->cpu = false;
assert(!priv->cpu_bo->sync);
sna_pixmap_free_cpu(sna, priv);
}
@@ -1167,6 +1169,7 @@ skip_inplace_map:
list_del(&priv->list);
priv->undamaged = false;
priv->clear = false;
+ priv->cpu = false;
}
assert_pixmap_damage(pixmap);
@@ -1266,6 +1269,7 @@ done:
DBG(("%s: syncing CPU bo\n", __FUNCTION__));
kgem_bo_sync__cpu(&sna->kgem, priv->cpu_bo);
}
+ priv->cpu = true;
assert(pixmap->devPrivate.ptr);
assert(pixmap->devKind);
assert_pixmap_damage(pixmap);
@@ -1369,6 +1373,11 @@ static inline bool region_inplace(struct sna *sna,
if (wedged(sna))
return false;
+ if (priv->cpu) {
+ DBG(("%s: no, preferring last action of CPU\n", __FUNCTION__));
+ return false;
+ }
+
if (!write_only && priv->cpu_damage &&
region_overlaps_damage(region, priv->cpu_damage)) {
DBG(("%s: no, uncovered CPU damage pending\n", __FUNCTION__));
@@ -1504,6 +1513,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
region);
priv->clear = false;
+ priv->cpu = false;
assert_pixmap_damage(pixmap);
if (dx | dy)
RegionTranslate(region, -dx, -dy);
@@ -1553,6 +1563,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
assert_pixmap_damage(pixmap);
priv->clear = false;
+ priv->cpu = false;
if (dx | dy)
RegionTranslate(region, -dx, -dy);
return true;
@@ -1587,6 +1598,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
}
assert_pixmap_damage(pixmap);
priv->clear = false;
+ priv->cpu = false;
if (dx | dy)
RegionTranslate(region, -dx, -dy);
return true;
@@ -1871,10 +1883,11 @@ out:
priv->source_count = SOURCE_BIAS;
assert(priv->gpu_bo == NULL || priv->gpu_bo->proxy == NULL);
}
- if (priv->cpu_bo) {
+ if ((flags & MOVE_ASYNC_HINT) == 0 && priv->cpu_bo) {
DBG(("%s: syncing cpu bo\n", __FUNCTION__));
kgem_bo_sync__cpu(&sna->kgem, priv->cpu_bo);
}
+ priv->cpu = true;
assert(pixmap->devPrivate.ptr);
assert(pixmap->devKind);
assert_pixmap_damage(pixmap);
@@ -2206,6 +2219,9 @@ sna_drawable_use_bo(DrawablePtr drawable,
goto use_cpu_bo;
}
+ if (priv->cpu)
+ prefer_gpu = false;
+
if (!prefer_gpu && priv->gpu_bo && !kgem_bo_is_busy(priv->gpu_bo))
goto use_cpu_bo;
@@ -2457,6 +2473,7 @@ sna_pixmap_mark_active(struct sna *sna, struct sna_pixmap *priv)
(priv->create & KGEM_CAN_CREATE_LARGE) == 0)
list_move(&priv->inactive, &sna->active_pixmaps);
priv->clear = false;
+ priv->cpu = false;
return priv;
}
@@ -2527,6 +2544,8 @@ sna_pixmap_force_to_gpu(PixmapPtr pixmap, unsigned flags)
if (!sna_pixmap_move_to_gpu(pixmap, flags | __MOVE_FORCE))
return NULL;
+ assert(!priv->cpu);
+
/* For large bo, try to keep only a single copy around */
if (priv->create & KGEM_CAN_CREATE_LARGE && priv->ptr) {
sna_damage_all(&priv->gpu_damage,
@@ -2986,6 +3005,7 @@ sna_put_zpixmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region,
if (upload_inplace(sna, pixmap, priv, region) &&
sna_put_image_upload_blt(drawable, gc, region,
x, y, w, h, bits, stride)) {
+ assert(priv->cpu == false);
if (!DAMAGE_IS_ALL(priv->gpu_damage)) {
DBG(("%s: marking damage\n", __FUNCTION__));
if (region_subsumes_drawable(region, &pixmap->drawable))
@@ -3055,6 +3075,7 @@ sna_put_zpixmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region,
assert_pixmap_damage(pixmap);
priv->clear = false;
+ priv->cpu = false;
return true;
}
} else {
@@ -3124,6 +3145,7 @@ sna_put_zpixmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region,
sna_pixmap_free_gpu(sna, priv);
priv->undamaged = false;
priv->clear = false;
+ priv->cpu = false;
}
if (!DAMAGE_IS_ALL(priv->cpu_damage)) {
@@ -3150,6 +3172,7 @@ sna_put_zpixmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region,
if (priv->flush)
list_move(&priv->list, &sna->dirty_pixmaps);
}
+ priv->cpu = true;
blt:
get_drawable_deltas(drawable, pixmap, &dx, &dy);
@@ -3832,6 +3855,7 @@ sna_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
list_del(&dst_priv->list);
dst_priv->undamaged = true;
dst_priv->clear = false;
+ dst_priv->cpu = false;
}
if (src_priv == NULL &&
@@ -3913,6 +3937,7 @@ sna_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
fill.done(sna, &fill);
}
+ dst_priv->cpu = false;
if (!DAMAGE_IS_ALL(dst_priv->gpu_damage)) {
if (replaces) {
sna_damage_destroy(&dst_priv->cpu_damage);
@@ -3946,6 +3971,7 @@ sna_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
goto fallback;
}
+ dst_priv->cpu = false;
if (!DAMAGE_IS_ALL(dst_priv->gpu_damage)) {
if (replaces) {
sna_damage_destroy(&dst_priv->cpu_damage);
@@ -3973,6 +3999,7 @@ sna_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
goto fallback;
}
+ dst_priv->cpu = false;
if (!DAMAGE_IS_ALL(dst_priv->gpu_damage)) {
if (replaces) {
sna_damage_destroy(&dst_priv->cpu_damage);
@@ -4042,6 +4069,7 @@ sna_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
}
tmp->drawable.pScreen->DestroyPixmap(tmp);
+ dst_priv->cpu = false;
if (!DAMAGE_IS_ALL(dst_priv->gpu_damage)) {
RegionTranslate(&region, dst_dx, dst_dy);
assert_pixmap_contains_box(dst_pixmap,
@@ -4076,6 +4104,7 @@ sna_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
bits, stride))
goto fallback;
+ dst_priv->cpu = false;
if (!DAMAGE_IS_ALL(dst_priv->gpu_damage)) {
sna_damage_destroy(&dst_priv->cpu_damage);
sna_damage_all(&dst_priv->gpu_damage,
@@ -4096,6 +4125,7 @@ sna_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
box, n))
goto fallback;
+ dst_priv->cpu = false;
if (!DAMAGE_IS_ALL(dst_priv->gpu_damage)) {
if (replaces) {
sna_damage_destroy(&dst_priv->cpu_damage);
@@ -4130,6 +4160,7 @@ sna_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
goto fallback;
}
+ dst_priv->cpu = true;
if (replaces) {
sna_damage_all(&dst_priv->cpu_damage,
dst_pixmap->drawable.width,
@@ -10492,6 +10523,8 @@ sna_poly_fill_rect(DrawablePtr draw, GCPtr gc, int n, xRectangle *rect)
if (region_subsumes_damage(&region, priv->cpu_damage)) {
sna_damage_destroy(&priv->cpu_damage);
list_del(&priv->list);
+ priv->undamaged = false;
+ priv->cpu = false;
}
}
@@ -12598,6 +12631,7 @@ static void sna_accel_inactive(struct sna *sna)
assert(priv->cpu_bo == NULL || !priv->cpu_bo->sync);
sna_pixmap_free_cpu(sna, priv);
priv->undamaged = false;
+ priv->cpu = false;
list_add(&priv->inactive, &preserve);
} else {