sna: Track whether damage is a complete representation of the dirt

The previous commit undoes a premature optimisation that assumed that
the current damage captured all pixels written. However, it happens to
be a useful optimisation along that path (tracking upload of partial
images), so add the necessary booking that watches for when the union
of cpu and gpu damage is no longer the complete set of all pixels
written, that is if we either migrate from one pixmap to the other, the
undamaged region goes untracked. We also take advantage of whenever we
damage the whole pixel to restore knowledge that our tracking of all
pixels written is complete.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
Chris Wilson 2012-01-17 13:44:12 +00:00
parent a9b705f9a7
commit e4efde920b
5 changed files with 54 additions and 15 deletions

View File

@ -144,6 +144,7 @@ struct sna_pixmap {
uint8_t pinned :1;
uint8_t mapped :1;
uint8_t flush :1;
uint8_t undamaged :1;
uint8_t gpu :1;
uint8_t header :1;
};

View File

@ -315,6 +315,7 @@ static inline uint32_t default_tiling(PixmapPtr pixmap)
pixmap->drawable.width,
pixmap->drawable.height)) {
sna_damage_destroy(&priv->gpu_damage);
priv->undamaged = false;
return I915_TILING_Y;
}
@ -786,6 +787,7 @@ _sna_pixmap_move_to_cpu(PixmapPtr pixmap, unsigned int flags)
pixmap->drawable.width,
pixmap->drawable.height);
sna_damage_destroy(&priv->cpu_damage);
priv->undamaged = false;
list_del(&priv->list);
if (priv->cpu_bo)
sna_pixmap_free_cpu(sna, priv);
@ -849,6 +851,7 @@ skip_inplace_map:
__sna_damage_destroy(DAMAGE_PTR(priv->gpu_damage));
priv->gpu_damage = NULL;
priv->undamaged = true;
}
if (flags & MOVE_WRITE) {
@ -857,6 +860,7 @@ skip_inplace_map:
pixmap->drawable.width,
pixmap->drawable.height);
sna_pixmap_free_gpu(sna, priv);
priv->undamaged = false;
if (priv->flush)
list_move(&priv->list, &sna->dirty_pixmaps);
@ -1059,11 +1063,12 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
pixmap->devKind = priv->gpu_bo->pitch;
sna_damage_subtract(&priv->cpu_damage, region);
if (priv->cpu_damage == NULL)
if (priv->cpu_damage == NULL) {
sna_damage_all(&priv->gpu_damage,
pixmap->drawable.width,
pixmap->drawable.height);
else
priv->undamaged = false;
} else
sna_damage_add(&priv->gpu_damage,
region);
@ -1096,11 +1101,12 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
pixmap->devKind = priv->gpu_bo->pitch;
sna_damage_subtract(&priv->cpu_damage, region);
if (priv->cpu_damage == NULL)
if (priv->cpu_damage == NULL) {
sna_damage_all(&priv->gpu_damage,
pixmap->drawable.width,
pixmap->drawable.height);
else
priv->undamaged = false;
} else
sna_damage_add(&priv->gpu_damage, region);
return true;
@ -1170,6 +1176,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
box, n);
}
sna_damage_destroy(&priv->gpu_damage);
priv->undamaged = true;
}
if (sna_damage_contains_box(priv->gpu_damage,
@ -1243,6 +1250,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
box, n);
sna_damage_destroy(&priv->gpu_damage);
priv->undamaged = true;
} else if (DAMAGE_IS_ALL(priv->gpu_damage) ||
sna_damage_contains_box__no_reduce(priv->gpu_damage,
&r->extents)) {
@ -1263,6 +1271,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
box, n);
sna_damage_subtract(&priv->gpu_damage, r);
priv->undamaged = true;
} else {
RegionRec need;
@ -1285,6 +1294,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
box, n);
sna_damage_subtract(&priv->gpu_damage, r);
priv->undamaged = true;
RegionUninit(&need);
}
}
@ -1304,6 +1314,7 @@ done:
pixmap->drawable.height)) {
DBG(("%s: replaced entire pixmap\n", __FUNCTION__));
sna_pixmap_free_gpu(sna, priv);
priv->undamaged = false;
}
if (priv->flush)
list_move(&priv->list, &sna->dirty_pixmaps);
@ -1434,6 +1445,7 @@ sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, BoxPtr box)
sna_damage_destroy(&priv->cpu_damage);
list_del(&priv->list);
priv->undamaged = true;
} else if (DAMAGE_IS_ALL(priv->cpu_damage) ||
sna_damage_contains_box__no_reduce(priv->cpu_damage, box)) {
Bool ok = FALSE;
@ -1453,6 +1465,7 @@ sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, BoxPtr box)
sna_damage_subtract(&priv->cpu_damage, &r);
if (priv->cpu_damage == NULL)
list_del(&priv->list);
priv->undamaged = true;
} else if (sna_damage_intersect(priv->cpu_damage, &r, &i)) {
int n = REGION_NUM_RECTS(&i);
Bool ok;
@ -1473,6 +1486,7 @@ sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, BoxPtr box)
box, n);
sna_damage_subtract(&priv->cpu_damage, &r);
priv->undamaged = true;
RegionUninit(&i);
if (priv->cpu_damage == NULL)
@ -1786,6 +1800,7 @@ sna_pixmap_force_to_gpu(PixmapPtr pixmap, unsigned flags)
sna_damage_all(&priv->gpu_damage,
pixmap->drawable.width,
pixmap->drawable.height);
priv->undamaged = false;
DBG(("%s: marking as all-damaged for GPU\n",
__FUNCTION__));
}
@ -1848,8 +1863,10 @@ sna_pixmap_move_to_gpu(PixmapPtr pixmap, unsigned flags)
sna_damage_all(&priv->gpu_damage,
pixmap->drawable.width,
pixmap->drawable.height);
priv->undamaged = false;
DBG(("%s: marking as all-damaged for GPU\n",
__FUNCTION__));
goto active;
}
}
@ -1892,12 +1909,15 @@ sna_pixmap_move_to_gpu(PixmapPtr pixmap, unsigned flags)
__sna_damage_destroy(DAMAGE_PTR(priv->cpu_damage));
priv->cpu_damage = NULL;
priv->undamaged = true;
done:
list_del(&priv->list);
sna_damage_reduce_all(&priv->gpu_damage,
pixmap->drawable.width,
pixmap->drawable.height);
if (DAMAGE_IS_ALL(priv->gpu_damage))
priv->undamaged = false;
active:
if (!priv->pinned)
list_move(&priv->inactive, &sna->active_pixmaps);
@ -2214,11 +2234,12 @@ sna_put_zpixmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region,
list_del(&priv->list);
} else
sna_damage_subtract(&priv->cpu_damage, region);
if (priv->cpu_damage == NULL)
if (priv->cpu_damage == NULL) {
sna_damage_all(&priv->gpu_damage,
pixmap->drawable.width,
pixmap->drawable.height);
else
priv->undamaged = false;
} else
sna_damage_add(&priv->gpu_damage, region);
}
@ -2256,11 +2277,12 @@ sna_put_zpixmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region,
list_del(&priv->list);
} else
sna_damage_subtract(&priv->cpu_damage, region);
if (priv->cpu_damage == NULL)
if (priv->cpu_damage == NULL) {
sna_damage_all(&priv->gpu_damage,
pixmap->drawable.width,
pixmap->drawable.height);
else
priv->undamaged = false;
} else
sna_damage_add(&priv->gpu_damage, region);
}
@ -2277,12 +2299,16 @@ sna_put_zpixmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region,
return false;
} else {
sna_damage_destroy(&priv->cpu_damage);
priv->undamaged = false;
list_del(&priv->list);
}
}
sna_damage_all(&priv->gpu_damage,
pixmap->drawable.width,
pixmap->drawable.height);
if (priv->undamaged) {
sna_damage_all(&priv->gpu_damage,
pixmap->drawable.width,
pixmap->drawable.height);
priv->undamaged = false;
}
sna_pixmap_free_cpu(sna, priv);
}
}
@ -2308,6 +2334,7 @@ sna_put_zpixmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region,
pixmap->drawable.width,
pixmap->drawable.height);
sna_pixmap_free_gpu(sna, priv);
priv->undamaged = false;
} else {
sna_damage_subtract(&priv->gpu_damage, region);
sna_damage_add(&priv->cpu_damage, region);
@ -2317,6 +2344,7 @@ sna_put_zpixmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region,
pixmap->drawable.height)) {
DBG(("%s: replaced entire pixmap\n", __FUNCTION__));
sna_pixmap_free_gpu(sna, priv);
priv->undamaged = false;
}
}
if (priv->flush)
@ -3000,6 +3028,7 @@ sna_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
sna_damage_all(&dst_priv->gpu_damage,
dst_pixmap->drawable.width,
dst_pixmap->drawable.height);
dst_priv->undamaged = false;
} else {
RegionTranslate(&region, dst_dx, dst_dy);
assert_pixmap_contains_box(dst_pixmap,
@ -3029,6 +3058,7 @@ sna_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
sna_damage_all(&dst_priv->gpu_damage,
dst_pixmap->drawable.width,
dst_pixmap->drawable.height);
dst_priv->undamaged = false;
} else {
RegionTranslate(&region, dst_dx, dst_dy);
assert_pixmap_contains_box(dst_pixmap,
@ -3125,6 +3155,7 @@ sna_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
sna_damage_all(&dst_priv->gpu_damage,
dst_pixmap->drawable.width,
dst_pixmap->drawable.height);
dst_priv->undamaged = false;
}
} else {
DBG(("%s: dst is on the GPU, src is on the CPU, uploading into dst\n",
@ -6909,11 +6940,12 @@ sna_poly_fill_rect_blt(DrawablePtr drawable,
if (damage) {
assert_pixmap_contains_box(pixmap, &r);
if (r.x2 - r.x1 == pixmap->drawable.width &&
r.y2 - r.y1 == pixmap->drawable.height)
r.y2 - r.y1 == pixmap->drawable.height) {
sna_damage_all(damage,
pixmap->drawable.width,
pixmap->drawable.height);
else
sna_pixmap(pixmap)->undamaged = false;
} else
sna_damage_add_box(damage, &r);
}
} else
@ -10010,6 +10042,8 @@ static void sna_accel_inactive(struct sna *sna)
list_del(&priv->list);
sna_pixmap_free_cpu(sna, priv);
priv->undamaged = false;
list_add(&priv->inactive, &preserve);
} else {
DBG(("%s: discarding inactive GPU bo handle=%d\n",

View File

@ -774,10 +774,11 @@ sna_composite_rectangles(CARD8 op,
if (region.data == NULL &&
region.extents.x2 - region.extents.x1 == pixmap->drawable.width &&
region.extents.y2 - region.extents.y1 == pixmap->drawable.height)
region.extents.y2 - region.extents.y1 == pixmap->drawable.height) {
sna_damage_all(&priv->gpu_damage,
pixmap->drawable.width, pixmap->drawable.height);
else
priv->undamaged = false;
} else
sna_damage_add(&priv->gpu_damage, &region);
}

View File

@ -342,6 +342,7 @@ damage_all:
pixmap->drawable.width,
pixmap->drawable.height);
sna_damage_destroy(&priv->cpu_damage);
priv->undamaged = false;
} else {
BoxPtr box = RegionExtents(region);
if (region->data == NULL &&
@ -364,6 +365,7 @@ static void set_bo(PixmapPtr pixmap, struct kgem_bo *bo)
pixmap->drawable.width,
pixmap->drawable.height);
sna_damage_destroy(&priv->cpu_damage);
priv->undamaged = false;
kgem_bo_destroy(&sna->kgem, priv->gpu_bo);
priv->gpu_bo = ref(bo);

View File

@ -3947,6 +3947,7 @@ static void mark_damaged(PixmapPtr pixmap, struct sna_pixmap *priv,
sna_damage_all(&priv->gpu_damage,
pixmap->drawable.width,
pixmap->drawable.height);
priv->undamaged = false;
} else {
sna_damage_add_box(&priv->gpu_damage, box);
sna_damage_subtract_box(&priv->cpu_damage, box);