sna: Use a proxy rather than a temporary bo for too-tall but thin targets

If the render target is thin enough to fit within the 3D pipeline, but is
too tall, we can fudge the address of the origin and coordinates to fit
within the constaints of the pipeline.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
Chris Wilson 2012-01-27 20:12:49 +00:00
parent ea433995a3
commit d02bd80b2f
4 changed files with 82 additions and 12 deletions

View File

@ -187,6 +187,11 @@ static struct sna_damage *_sna_damage_create(void)
return damage;
}
struct sna_damage *sna_damage_create(void)
{
return _sna_damage_create();
}
static bool _sna_damage_create_boxes(struct sna_damage *damage,
int count)
{
@ -1395,6 +1400,21 @@ int _sna_damage_get_boxes(struct sna_damage *damage, BoxPtr *boxes)
}
#endif
struct sna_damage *_sna_damage_combine(struct sna_damage *l,
struct sna_damage *r,
int dx, int dy)
{
if (r->dirty)
__sna_damage_reduce(r);
if (pixman_region_not_empty(&r->region)) {
pixman_region_translate(&r->region, dx, dy);
l = __sna_damage_add(l, &r->region);
}
return l;
}
void __sna_damage_destroy(struct sna_damage *damage)
{
free_list(&damage->embedded_box.list);

View File

@ -27,6 +27,18 @@ struct sna_damage {
#define DAMAGE_MARK_ALL(ptr) ((struct sna_damage *)(((uintptr_t)(ptr))|1))
#define DAMAGE_PTR(ptr) ((struct sna_damage *)(((uintptr_t)(ptr))&~1))
struct sna_damage *sna_damage_create(void);
struct sna_damage *_sna_damage_combine(struct sna_damage *l,
struct sna_damage *r,
int dx, int dy);
static inline void sna_damage_combine(struct sna_damage **l,
struct sna_damage *r,
int dx, int dy)
{
*l = _sna_damage_combine(*l, r, dx, dy);
}
fastcall struct sna_damage *_sna_damage_add(struct sna_damage *damage,
RegionPtr region);
static inline void sna_damage_add(struct sna_damage **damage,

View File

@ -1519,14 +1519,39 @@ sna_render_composite_redirect(struct sna *sna,
if (!width || !height)
return FALSE;
priv = sna_pixmap(op->dst.pixmap);
if (priv->gpu_bo == NULL) {
priv = sna_pixmap_force_to_gpu(op->dst.pixmap, MOVE_READ | MOVE_WRITE);
if (priv == NULL) {
DBG(("%s: fallback -- no GPU bo attached\n", __FUNCTION__));
return FALSE;
}
if (!sna_pixmap_move_to_gpu(op->dst.pixmap, MOVE_READ | MOVE_WRITE))
return FALSE;
if (op->dst.pixmap->drawable.width <= sna->render.max_3d_size) {
int y1, y2;
assert(op->dst.pixmap.drawable.height > sna->render.max_3d_size);
y1 = y + op->dst.y;
y2 = y1 + height;
y1 &= y1 & (64 - 1);
y2 = ALIGN(y2, 64);
if (y2 - y1 <= sna->render.max_3d_size) {
t->box.x2 = t->box.x1 = op->dst.x;
t->box.y2 = t->box.y1 = op->dst.y;
t->real_bo = priv->gpu_bo;
t->real_damage = op->damage;
if (op->damage) {
t->damage = sna_damage_create();
op->damage = &t->damage;
}
op->dst.bo = kgem_create_proxy(priv->gpu_bo,
y1 * priv->gpu_bo->pitch,
(y2 - y1) * priv->gpu_bo->pitch);
op->dst.y += -y1;
op->dst.height = y2 - y1;
return TRUE;
}
}
/* We can process the operation in a single pass,
* but the target is too large for the 3D pipeline.
@ -1557,12 +1582,17 @@ sna_render_composite_redirect(struct sna *sna,
}
t->real_bo = priv->gpu_bo;
t->real_damage = op->damage;
if (op->damage) {
t->damage = sna_damage_create();
op->damage = &t->damage;
}
op->dst.bo = bo;
op->dst.x = -x;
op->dst.y = -y;
op->dst.width = width;
op->dst.height = height;
op->damage = NULL;
return TRUE;
}
@ -1573,13 +1603,20 @@ sna_render_composite_redirect_done(struct sna *sna,
const struct sna_composite_redirect *t = &op->redirect;
if (t->real_bo) {
DBG(("%s: copying temporary to dst\n", __FUNCTION__));
sna_blt_copy_boxes(sna, GXcopy,
op->dst.bo, -t->box.x1, -t->box.y1,
t->real_bo, 0, 0,
op->dst.pixmap->drawable.bitsPerPixel,
&t->box, 1);
if (t->box.x2 > t->box.x1) {
DBG(("%s: copying temporary to dst\n", __FUNCTION__));
sna_blt_copy_boxes(sna, GXcopy,
op->dst.bo, -t->box.x1, -t->box.y1,
t->real_bo, 0, 0,
op->dst.pixmap->drawable.bitsPerPixel,
&t->box, 1);
}
if (t->damage) {
sna_damage_combine(t->real_damage, t->damage,
t->box.x1 - op->dst.x,
t->box.y1 - op->dst.y);
__sna_damage_destroy(t->damage);
}
kgem_bo_destroy(&sna->kgem, op->dst.bo);
}

View File

@ -86,6 +86,7 @@ struct sna_composite_op {
struct sna_composite_redirect {
struct kgem_bo *real_bo;
struct sna_damage **real_damage, *damage;
BoxRec box;
} redirect;