diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2014-06-11 10:12:01 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2014-06-11 11:05:07 +0100 |
commit | 277e6ab84bb0c692358a34a76e7962c64efb0362 (patch) | |
tree | ac53ad304c5b51e8b99cb3047c1e2952ce570a42 /src | |
parent | eb9de37daaea45e917fa7f44444a9782070f7333 (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.h | 4 | ||||
-rw-r--r-- | src/sna/sna_accel.c | 35 | ||||
-rw-r--r-- | src/sna/sna_display.c | 35 |
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, ®ion->extents) && @@ -4454,6 +4452,9 @@ try_upload_blt(PixmapPtr pixmap, RegionRec *region, return false; } + if (!sna_pixmap_move_area_to_gpu(pixmap, ®ion->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) |