summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2014-06-11 10:12:01 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2014-06-11 11:05:07 +0100
commit277e6ab84bb0c692358a34a76e7962c64efb0362 (patch)
treeac53ad304c5b51e8b99cb3047c1e2952ce570a42 /src
parenteb9de37daaea45e917fa7f44444a9782070f7333 (diff)
sna: Discard TearFree damage before checking for an overwriting upload
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src')
-rw-r--r--src/sna/sna.h4
-rw-r--r--src/sna/sna_accel.c35
-rw-r--r--src/sna/sna_display.c35
3 files changed, 42 insertions, 32 deletions
diff --git a/src/sna/sna.h b/src/sna/sna.h
index e504ee0d..a44235b9 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -428,8 +428,8 @@ extern void sna_mode_wakeup(struct sna *sna);
extern void sna_mode_redisplay(struct sna *sna);
extern void sna_shadow_set_crtc(struct sna *sna, xf86CrtcPtr crtc, struct kgem_bo *bo);
extern void sna_shadow_unset_crtc(struct sna *sna, xf86CrtcPtr crtc);
-extern void sna_pixmap_discard_shadow_damage(struct sna_pixmap *priv,
- RegionPtr region);
+extern bool sna_pixmap_discard_shadow_damage(struct sna_pixmap *priv,
+ const RegionRec *region);
extern void sna_mode_close(struct sna *sna);
extern void sna_mode_fini(struct sna *sna);
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index c5f3f56b..55b64514 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -474,12 +474,16 @@ sna_copy_init_blt(struct sna_copy_op *copy,
static void sna_pixmap_free_gpu(struct sna *sna, struct sna_pixmap *priv)
{
+ DBG(("%s: handle=%d (pinned? %d)\n", __FUNCTION__, priv->gpu_bo ? priv->gpu_bo->handle : 0, priv->pinned));
assert(priv->gpu_damage == NULL || priv->gpu_bo);
if (priv->cow)
- sna_pixmap_undo_cow(sna, priv, 0);
+ sna_pixmap_undo_cow(sna, priv, MOVE_WRITE);
assert(priv->cow == NULL);
+ if (priv->move_to_gpu)
+ priv->move_to_gpu(sna, priv, MOVE_WRITE);
+
sna_damage_destroy(&priv->gpu_damage);
priv->clear = false;
@@ -4423,7 +4427,7 @@ try_upload_blt(PixmapPtr pixmap, RegionRec *region,
if (priv == NULL)
return false;
- if (DAMAGE_IS_ALL(priv->cpu_damage) || priv->gpu_damage == NULL) {
+ if (DAMAGE_IS_ALL(priv->cpu_damage) || priv->gpu_damage == NULL || priv->cpu) {
DBG(("%s: no, no gpu damage\n", __FUNCTION__));
return false;
}
@@ -4433,19 +4437,13 @@ try_upload_blt(PixmapPtr pixmap, RegionRec *region,
if ((priv->create & (KGEM_CAN_CREATE_GTT | KGEM_CAN_CREATE_LARGE)) == KGEM_CAN_CREATE_GTT &&
kgem_bo_can_map(&sna->kgem, priv->gpu_bo) &&
- !__kgem_bo_is_busy(&sna->kgem, priv->gpu_bo)) {
+ (priv->cow == NULL &&
+ (priv->move_to_gpu == NULL || sna_pixmap_discard_shadow_damage(priv, region)) &&
+ !__kgem_bo_is_busy(&sna->kgem, priv->gpu_bo))) {
DBG(("%s: no, target is idle\n", __FUNCTION__));
return false;
}
- if (priv->cow || priv->move_to_gpu) {
- if (!region_subsumes_drawable(region, &pixmap->drawable) ||
- !sna_pixmap_move_to_gpu(pixmap, MOVE_WRITE)) {
- DBG(("%s: no, target is a partial COW\n", __FUNCTION__));
- return false;
- }
- }
-
if (priv->cpu_damage &&
sna_damage_contains_box__no_reduce(priv->cpu_damage,
&region->extents) &&
@@ -4454,6 +4452,9 @@ try_upload_blt(PixmapPtr pixmap, RegionRec *region,
return false;
}
+ if (!sna_pixmap_move_area_to_gpu(pixmap, &region->extents, MOVE_WRITE | MOVE_ASYNC_HINT | (region->data ? MOVE_READ : 0)))
+ return false;
+
src_bo = kgem_create_map(&sna->kgem, bits, stride * h, true);
if (src_bo == NULL)
return false;
@@ -4500,9 +4501,9 @@ try_upload_blt(PixmapPtr pixmap, RegionRec *region,
list_del(&priv->flush_list);
if (sna_pixmap_free_cpu(sna, priv, priv->cpu))
sna_damage_all(&priv->gpu_damage, pixmap);
- priv->cpu = false;
}
}
+ priv->cpu = false;
priv->clear = false;
return true;
@@ -4543,7 +4544,8 @@ try_upload_tiled_x(PixmapPtr pixmap, RegionRec *region,
if (priv->gpu_bo && replaces) {
if (UNDO) kgem_bo_pair_undo(&sna->kgem, priv->gpu_bo, priv->cpu_bo);
if (can_create_upload_tiled_x(&sna->kgem, pixmap, priv, true) &&
- (__kgem_bo_is_busy(&sna->kgem, priv->gpu_bo) ||
+ (priv->cow ||
+ __kgem_bo_is_busy(&sna->kgem, priv->gpu_bo) ||
!kgem_bo_can_map__cpu(&sna->kgem, priv->gpu_bo, true))) {
DBG(("%s: discarding unusable target bo (busy? %d, mappable? %d)\n", __FUNCTION__,
kgem_bo_is_busy(priv->gpu_bo),
@@ -4554,9 +4556,10 @@ try_upload_tiled_x(PixmapPtr pixmap, RegionRec *region,
}
assert(priv->gpu_bo == NULL || priv->gpu_bo->proxy == NULL);
- if ((priv->cow || priv->move_to_gpu) &&
- (!replaces || !sna_pixmap_move_to_gpu(pixmap, MOVE_WRITE))) {
- DBG(("%s: no, has COW or pending move-to-gpu\n", __FUNCTION__));
+ if (priv->cow ||
+ (priv->move_to_gpu && !sna_pixmap_discard_shadow_damage(priv, replaces ? NULL : region))) {
+ DBG(("%s: no, has pending COW? %d or move-to-gpu? %d\n",
+ __FUNCTION__, priv->cow != NULL, priv->move_to_gpu != NULL));
return false;
}
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index b0f6ea7c..36084d0b 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -1205,30 +1205,37 @@ done:
return ret;
}
-void sna_pixmap_discard_shadow_damage(struct sna_pixmap *priv,
- RegionPtr region)
+bool sna_pixmap_discard_shadow_damage(struct sna_pixmap *priv,
+ const RegionRec *region)
{
struct sna *sna;
if (priv->move_to_gpu != wait_for_shadow)
- return;
+ return false;
sna = priv->move_to_gpu_data;
- DBG(("%s: discarding region %dx[(%d, %d), (%d, %d)] from damage %dx[(%d, %d], (%d, %d)]\n",
- __FUNCTION__,
- region_num_rects(region),
- region->extents.x1, region->extents.y1,
- region->extents.x2, region->extents.y2,
- region_num_rects(&sna->mode.shadow_region),
- sna->mode.shadow_region.extents.x1, sna->mode.shadow_region.extents.y1,
- sna->mode.shadow_region.extents.x2, sna->mode.shadow_region.extents.y2));
+ if (region) {
+ DBG(("%s: discarding region %dx[(%d, %d), (%d, %d)] from damage %dx[(%d, %d], (%d, %d)]\n",
+ __FUNCTION__,
+ region_num_rects(region),
+ region->extents.x1, region->extents.y1,
+ region->extents.x2, region->extents.y2,
+ region_num_rects(&sna->mode.shadow_region),
+ sna->mode.shadow_region.extents.x1, sna->mode.shadow_region.extents.y1,
+ sna->mode.shadow_region.extents.x2, sna->mode.shadow_region.extents.y2));
- if (region)
RegionSubtract(&sna->mode.shadow_region,
&sna->mode.shadow_region,
- region);
- else
+ (RegionPtr)region);
+ } else {
+ DBG(("%s: discarding all damage %dx[(%d, %d], (%d, %d)]\n",
+ region_num_rects(&sna->mode.shadow_region),
+ sna->mode.shadow_region.extents.x1, sna->mode.shadow_region.extents.y1,
+ sna->mode.shadow_region.extents.x2, sna->mode.shadow_region.extents.y2));
RegionEmpty(&sna->mode.shadow_region);
+ }
+
+ return RegionNil(&sna->mode.shadow_region);
}
static bool sna_mode_enable_shadow(struct sna *sna)