diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2011-08-27 11:42:19 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2011-08-27 11:44:13 +0100 |
commit | ac1b83240e5d4dc5d5bacad3ed49446143cc5589 (patch) | |
tree | 2ce54bbd6d9acda5433f995818e253ec2bb8667a | |
parent | 786a770f528a0daee2971494352672cb89f48384 (diff) |
sna/accel: Simplify single pixel read-back
The single pixel case is usually assocated with synchronisation of perf
clients and so we do not want to incur extra complication along that
path. Also the cost of tracking a single pixel of non-damage outweighs
its benefit.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/sna/sna_accel.c | 126 |
1 files changed, 69 insertions, 57 deletions
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c index 79717115..8a7cec2a 100644 --- a/src/sna/sna_accel.c +++ b/src/sna/sna_accel.c @@ -464,67 +464,79 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable, if (sna_damage_contains_box(priv->gpu_damage, REGION_EXTENTS(NULL, region))) { - RegionRec want, need, *r; - - DBG(("%s: region intersects gpu damage\n", __FUNCTION__)); - - r = region; - /* expand the region to move 32x32 pixel blocks at a time */ - if (priv->cpu_damage == NULL) { - int n = REGION_NUM_RECTS(region), i; - BoxPtr boxes = REGION_RECTS(region); - BoxPtr blocks = malloc(sizeof(BoxRec) * REGION_NUM_RECTS(region)); - if (blocks) { - for (i = 0; i < n; i++) { - blocks[i].x1 = boxes[i].x1 & ~31; - if (blocks[i].x1 < 0) - blocks[i].x1 = 0; - - blocks[i].x2 = (boxes[i].x2 + 31) & ~31; - if (blocks[i].x2 > pixmap->drawable.width) - blocks[i].x2 = pixmap->drawable.width; - - blocks[i].y1 = boxes[i].y1 & ~31; - if (blocks[i].y1 < 0) - blocks[i].y1 = 0; - - blocks[i].y2 = (boxes[i].y2 + 31) & ~31; - if (blocks[i].y2 > pixmap->drawable.height) - blocks[i].y2 = pixmap->drawable.height; + DBG(("%s: region (%dx%d) intersects gpu damage\n", + __FUNCTION__, + region->extents.x2 - region->extents.x1, + region->extents.y2 - region->extents.y1)); + + if (region->extents.x2 - region->extents.x1 == 1 && + region->extents.y2 - region->extents.y1 == 1) { + /* Oftenassociated with synchonrisation, KISS */ + sna_read_boxes(sna, + priv->gpu_bo, 0, 0, + pixmap, 0, 0, + ®ion->extents, 1); + } else { + RegionRec want, need, *r; + + r = region; + /* expand the region to move 32x32 pixel blocks at a time */ + if (priv->cpu_damage == NULL) { + int n = REGION_NUM_RECTS(region), i; + BoxPtr boxes = REGION_RECTS(region); + BoxPtr blocks = malloc(sizeof(BoxRec) * REGION_NUM_RECTS(region)); + if (blocks) { + for (i = 0; i < n; i++) { + blocks[i].x1 = boxes[i].x1 & ~31; + if (blocks[i].x1 < 0) + blocks[i].x1 = 0; + + blocks[i].x2 = (boxes[i].x2 + 31) & ~31; + if (blocks[i].x2 > pixmap->drawable.width) + blocks[i].x2 = pixmap->drawable.width; + + blocks[i].y1 = boxes[i].y1 & ~31; + if (blocks[i].y1 < 0) + blocks[i].y1 = 0; + + blocks[i].y2 = (boxes[i].y2 + 31) & ~31; + if (blocks[i].y2 > pixmap->drawable.height) + blocks[i].y2 = pixmap->drawable.height; + } + if (pixman_region_init_rects(&want, blocks, i)) + r = &want; + free(blocks); } - if (pixman_region_init_rects(&want, blocks, i)) - r = &want; - free(blocks); } - } - - pixman_region_init(&need); - if (sna_damage_intersect(priv->gpu_damage, r, &need)) { - BoxPtr box = REGION_RECTS(&need); - int n = REGION_NUM_RECTS(&need); - struct kgem_bo *dst_bo; - Bool ok = FALSE; - - dst_bo = NULL; - if (sna->kgem.gen >= 30) - dst_bo = pixmap_vmap(&sna->kgem, pixmap); - if (dst_bo) - ok = sna->render.copy_boxes(sna, GXcopy, - pixmap, priv->gpu_bo, 0, 0, - pixmap, dst_bo, 0, 0, - box, n); - if (!ok) - sna_read_boxes(sna, - priv->gpu_bo, 0, 0, - pixmap, 0, 0, - box, n); - sna_damage_subtract(&priv->gpu_damage, - n <= REGION_NUM_RECTS(r) ? &need : r); - RegionUninit(&need); + pixman_region_init(&need); + if (sna_damage_intersect(priv->gpu_damage, r, &need)) { + BoxPtr box = REGION_RECTS(&need); + int n = REGION_NUM_RECTS(&need); + struct kgem_bo *dst_bo; + Bool ok = FALSE; + + dst_bo = NULL; + if (sna->kgem.gen >= 30) + dst_bo = pixmap_vmap(&sna->kgem, pixmap); + if (dst_bo) + ok = sna->render.copy_boxes(sna, GXcopy, + pixmap, priv->gpu_bo, 0, 0, + pixmap, dst_bo, 0, 0, + box, n); + if (!ok) + sna_read_boxes(sna, + priv->gpu_bo, 0, 0, + pixmap, 0, 0, + box, n); + + sna_damage_subtract(&priv->gpu_damage, + n <= REGION_NUM_RECTS(r) ? &need : r); + RegionUninit(&need); + } + if (r == &want) + pixman_region_fini(&want); } - if (r == &want) - pixman_region_fini(&want); } done: |