diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2012-01-27 19:34:39 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2012-01-27 19:34:39 +0000 |
commit | ea433995a37f0a9d1579f74029418f22a63a2bc0 (patch) | |
tree | 4bc13a181b1160b29367fa2073bae5c1b675b195 | |
parent | ad910949beb0c42e2d7b864f030b055ca40adacd (diff) |
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>
-rw-r--r-- | src/sna/kgem.c | 5 | ||||
-rw-r--r-- | src/sna/sna_render.c | 103 |
2 files changed, 106 insertions, 2 deletions
diff --git a/src/sna/kgem.c b/src/sna/kgem.c index 4df29d2f..95b67cf7 100644 --- a/src/sna/kgem.c +++ b/src/sna/kgem.c @@ -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; } diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c index 9d7857cf..513b4895 100644 --- a/src/sna/sna_render.c +++ b/src/sna/sna_render.c @@ -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; |