diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2012-07-01 10:53:07 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2012-07-01 11:07:50 +0100 |
commit | 35b1ac138002c206a6d6b866d49a0d73705dd3ac (patch) | |
tree | 7d11e0a67af29e4024e86b425e250c4362333dd2 /src/sna | |
parent | e625c02e6266403fcd8a72ccce2c6c6291e2e5fc (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.h | 1 | ||||
-rw-r--r-- | src/sna/sna_accel.c | 36 |
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(®ion, 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(®ion, 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 { |