sna: Experiment with a partial source

If the source is thin enough such that the pitch is within the sampler's
constraints and the sample size is small enough, just fudge the origin
of the bo such that it can be sampled.

This avoids having to create a temporary bo and use the BLT to extract
it and helps, for example, firefox-asteroids which uses an 64x11200
texture atlas.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
Chris Wilson 2012-01-27 19:34:39 +00:00
parent ad910949be
commit ea433995a3
2 changed files with 106 additions and 2 deletions

View File

@ -2967,7 +2967,6 @@ struct kgem_bo *kgem_create_proxy(struct kgem_bo *target,
DBG(("%s: target handle=%d, offset=%d, length=%d, io=%d\n",
__FUNCTION__, target->handle, offset, length, target->io));
assert(target->proxy == NULL);
assert(target->tiling == I915_TILING_NONE);
bo = __kgem_bo_alloc(target->handle, length);
if (bo == NULL)
@ -2975,9 +2974,11 @@ struct kgem_bo *kgem_create_proxy(struct kgem_bo *target,
bo->io = target->io;
bo->dirty = target->dirty;
bo->reusable = false;
bo->tiling = target->tiling;
bo->pitch = target->pitch;
bo->proxy = kgem_bo_reference(target);
bo->delta = offset;
bo->reusable = false;
return bo;
}

View File

@ -800,6 +800,103 @@ cleanup_tmp:
return ret;
}
static int
sna_render_picture_partial(struct sna *sna,
PicturePtr picture,
struct sna_composite_channel *channel,
int16_t x, int16_t y,
int16_t w, int16_t h,
int16_t dst_x, int16_t dst_y)
{
struct kgem_bo *bo = NULL;
PixmapPtr pixmap = get_drawable_pixmap(picture->pDrawable);
BoxRec box;
DBG(("%s (%d, %d)x(%d, %d) [dst=(%d, %d)]\n",
__FUNCTION__, x, y, w, h, dst_x, dst_y));
box.x1 = x;
box.y1 = y;
box.x2 = x + w;
box.y2 = y + h;
if (channel->transform)
pixman_transform_bounds(channel->transform, &box);
DBG(("%s sample=(%d, %d), (%d, %d): (%d, %d)/(%d, %d), repeat=%d\n", __FUNCTION__,
box.x1, box.y1, box.x2, box.y2, w, h,
pixmap->drawable.width, pixmap->drawable.height,
channel->repeat));
if (channel->repeat == RepeatNone || channel->repeat == RepeatPad) {
if (box.x1 < 0)
box.x1 = 0;
if (box.y1 < 0)
box.y1 = 0;
if (box.x2 > pixmap->drawable.width)
box.x2 = pixmap->drawable.width;
if (box.y2 > pixmap->drawable.height)
box.y2 = pixmap->drawable.height;
} else {
if (box.x1 < 0 ||
box.y1 < 0 ||
box.x2 > pixmap->drawable.width ||
box.y2 > pixmap->drawable.height) {
box.x1 = box.y1 = 0;
box.x2 = pixmap->drawable.width;
box.y2 = pixmap->drawable.height;
if (!channel->is_affine)
return 0;
}
}
/* Presume worst case tile-row alignment for Y-tiling */
box.y1 = box.y1 & (64 - 1);
box.y2 = ALIGN(box.y2, 64);
w = box.x2 - box.x1;
h = box.y2 - box.y1;
DBG(("%s box=(%d, %d), (%d, %d): (%d, %d)/(%d, %d)\n", __FUNCTION__,
box.x1, box.y1, box.x2, box.y2, w, h,
pixmap->drawable.width, pixmap->drawable.height));
if (w <= 0 || h <= 0 || h > sna->render.max_3d_size)
return 0;
memset(&channel->embedded_transform,
0,
sizeof(channel->embedded_transform));
channel->embedded_transform.matrix[0][0] = 1 << 16;
channel->embedded_transform.matrix[0][2] = 0;
channel->embedded_transform.matrix[1][1] = 1 << 16;
channel->embedded_transform.matrix[1][2] = -box.y1 << 16;
channel->embedded_transform.matrix[2][2] = 1 << 16;
if (channel->transform)
pixman_transform_multiply(&channel->embedded_transform,
&channel->embedded_transform,
channel->transform);
channel->transform = &channel->embedded_transform;
if (use_cpu_bo(sna, pixmap, &box)) {
if (!sna_pixmap_move_to_cpu(pixmap, MOVE_READ))
return 0;
bo = sna_pixmap(pixmap)->cpu_bo;
} else {
if (!sna_pixmap_force_to_gpu(pixmap, MOVE_READ))
return 0;
bo = sna_pixmap(pixmap)->gpu_bo;
}
channel->offset[0] = x - dst_x;
channel->offset[1] = y - dst_y;
channel->scale[0] = 1.f/pixmap->drawable.width;
channel->scale[1] = 1.f/h;
channel->width = pixmap->drawable.width;
channel->height = h;
channel->bo = kgem_create_proxy(bo, box.y1 * bo->pitch, h * bo->pitch);
return channel->bo != NULL;
}
int
sna_render_picture_extract(struct sna *sna,
PicturePtr picture,
@ -825,6 +922,12 @@ sna_render_picture_extract(struct sna *sna,
return -1;
}
if (pixmap->drawable.width < sna->render.max_3d_size &&
sna_render_picture_partial(sna, picture, channel,
x, y, w, h,
dst_x, dst_y))
return 1;
ow = w;
oh = h;