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:
parent
ea433995a3
commit
d02bd80b2f
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue