diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2014-06-18 10:18:26 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2014-06-18 10:54:57 +0100 |
commit | e52f917a2370026073ed6851161393a69ee94abe (patch) | |
tree | 7523e9f54659da4619f4e18ec93b9c0a16a7ccf4 | |
parent | b90f6c5aa7359ea6936ae4a7951fcd3bdad05d58 (diff) |
sna: Use nxm tiled blits for small regions of large tiles
If the region we are blitting is either narrow or short, we may be able
to construct a tiling pattern out of a large pixmap.
In the process, spot a regression due to
commit 542aeca6e67fc64f9133ca3e27ac8eca28af6d25
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date: Tue Jun 17 12:26:30 2014 +0100
sna: Tweak creation 8x8 tiled patterns
which copied too much from the source line.
References: https://bugs.freedesktop.org/show_bug.cgi?id=79888
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/sna/sna_accel.c | 89 | ||||
-rw-r--r-- | src/sna/sna_blt.c | 6 |
2 files changed, 72 insertions, 23 deletions
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c index 57e62d5e..a2e93c21 100644 --- a/src/sna/sna_accel.c +++ b/src/sna/sna_accel.c @@ -12276,43 +12276,76 @@ sna_poly_fill_rect_tiled_nxm_blt(DrawablePtr drawable, PixmapPtr pixmap = get_drawable_pixmap(drawable); struct sna *sna = to_sna_from_pixmap(pixmap); PixmapPtr tile = gc->tile.pixmap; - int w, h, bpp = tile->drawable.bitsPerPixel; + int w, h, tx, ty, tw, th, bpp = tile->drawable.bitsPerPixel; + const DDXPointRec origin = gc->patOrg; struct kgem_bo *upload; + uint8_t *src, *dst; void *ptr; bool ret; - DBG(("%s: %dx%d\n", __FUNCTION__, - tile->drawable.width, tile->drawable.height)); - assert(tile->drawable.height && tile->drawable.height <= 8); - assert(tile->drawable.width && tile->drawable.width <= 8); + tx = 0, tw = tile->drawable.width; + if (tw > extents->x2 - extents->x1) { + tx = (extents->x1 - gc->patOrg.x) % tw; + tw = extents->x2 - extents->x1; + gc->patOrg.x = extents->x1; + } + + ty = 0, th = tile->drawable.height; + if (th > extents->y2 - extents->y1) { + ty = (extents->y1 - gc->patOrg.y) % th; + th = extents->y2 - extents->y1; + gc->patOrg.y = extents->y1; + } + + DBG(("%s: %dx%d+%d+%d (full tile size %dx%d)\n", __FUNCTION__, + tw, th, tx, ty, tile->drawable.width, tile->drawable.height)); + assert(tw && tw <= 8); + assert(th && th <= 8); if (!sna_pixmap_move_to_cpu(tile, MOVE_READ)) return false; - upload = kgem_create_buffer(&sna->kgem, 8*bpp, - tile->drawable.height < 8 ? KGEM_BUFFER_WRITE : KGEM_BUFFER_WRITE_INPLACE, - &ptr); + assert(tile->devKind); + assert(has_coherent_ptr(sna, sna_pixmap(tile), MOVE_READ)); + + src = tile->devPrivate.ptr; + src += tile->devKind * ty; + src += tx * bpp/8; + + if ((tw | th) == 1) { + uint32_t pixel; + switch (bpp) { + case 32: pixel = *(uint32_t *)src; + case 16: pixel = *(uint16_t *)src; + default: pixel = *(uint8_t *)src; + } + return sna_poly_fill_rect_blt(drawable, bo, damage, + gc, pixel, n, rect, + extents, clipped); + } + + upload = kgem_create_buffer(&sna->kgem, 8*bpp, KGEM_BUFFER_WRITE, &ptr); if (upload == NULL) return false; upload->pitch = bpp; /* for sanity checks */ - assert(tile->devKind); - assert(has_coherent_ptr(sna, sna_pixmap(tile), MOVE_READ)); - for (h = 0; h < tile->drawable.height; h++) { - uint8_t *src = (uint8_t *)tile->devPrivate.ptr + tile->devKind*h; - uint8_t *dst = (uint8_t *)ptr + bpp*h; - - w = tile->drawable.width*bpp/8; + dst = ptr; + for (h = 0; h < th; h++) { + w = tw*bpp/8; memcpy(dst, src, w); while (w < bpp) { - memcpy(dst+w, src, w); + memcpy(dst+w, dst, w); w *= 2; } assert(w == bpp); + + src += tile->devKind; + dst += bpp; } while (h < 8) { - memcpy((uint8_t*)ptr + bpp*h, ptr, bpp*h); + memcpy(dst, ptr, bpp*h); + dst += bpp * h; h *= 2; } assert(h == 8); @@ -12322,6 +12355,7 @@ sna_poly_fill_rect_tiled_nxm_blt(DrawablePtr drawable, extents, clipped); kgem_bo_destroy(&sna->kgem, upload); + gc->patOrg = origin; return ret; } @@ -12346,6 +12380,9 @@ sna_poly_fill_rect_tiled_blt(DrawablePtr drawable, __FUNCTION__, n, rect->x, rect->y, rect->width, rect->height, clipped)); + assert(tile->drawable.depth == drawable->depth); + assert(bo); + tile_width = tile->drawable.width; tile_height = tile->drawable.height; if ((tile_width | tile_height) == 1) { @@ -12362,7 +12399,7 @@ sna_poly_fill_rect_tiled_blt(DrawablePtr drawable, * RENDER. */ - if ((tile->drawable.width | tile->drawable.height) == 8) { + if ((tile_width | tile_height) == 8) { bool ret; tile_bo = sna_pixmap_get_source_bo(tile); @@ -12380,9 +12417,19 @@ sna_poly_fill_rect_tiled_blt(DrawablePtr drawable, return true; } } else { - if ((tile->drawable.width | tile->drawable.height) <= 0xf && - is_power_of_two(tile->drawable.width) && - is_power_of_two(tile->drawable.height)) + int w = tile_width, h = tile_height; + struct sna_pixmap *priv = sna_pixmap(tile); + + if (priv == NULL || priv->gpu_damage == NULL) { + if (w > extents->x2 - extents->x1) + w = extents->x2 - extents->x1; + if (h > extents->y2 - extents->y1) + h = extents->y2 - extents->y1; + DBG(("%s: triming size for unattached tile: %dx%d\n", + __FUNCTION__, w, h)); + } + + if ((w | h) < 0x10 && is_power_of_two(w) && is_power_of_two(h)) return sna_poly_fill_rect_tiled_nxm_blt(drawable, bo, damage, gc, n, rect, extents, clipped); diff --git a/src/sna/sna_blt.c b/src/sna/sna_blt.c index f3a9cc2c..f3caf612 100644 --- a/src/sna/sna_blt.c +++ b/src/sna/sna_blt.c @@ -378,8 +378,10 @@ static bool sna_blt_alpha_fixup_init(struct sna *sna, { struct kgem *kgem = &sna->kgem; - assert(kgem_bo_can_blt (kgem, src)); - assert(kgem_bo_can_blt (kgem, dst)); + DBG(("%s: dst handle=%d, src handle=%d, bpp=%d, fixup=%08x\n", + __FUNCTION__, dst->handle, src->handle, bpp, alpha)); + assert(kgem_bo_can_blt(kgem, src)); + assert(kgem_bo_can_blt(kgem, dst)); blt->bo[0] = src; blt->bo[1] = dst; |