diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2011-11-24 17:14:08 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2011-11-24 22:04:50 +0000 |
commit | a2fab9560ec5dd6efc352917fe7626e59bed69e3 (patch) | |
tree | 6cff1f3d9252fd1cfe4964418608fa99d56a07e5 | |
parent | e0a4492c8b51d6ae09cde0b895da6177284e95e0 (diff) |
sna: Downgrade Y-tiling if we must use the BLT
There are many operations, usually the core drawing acceleration, where
the BLT is much more preferable than using the CPU. However, the BLT is
limited to only using X-tiling, so if we encounter a Y-tiled pixmap
target we need to recreate it as X-tiling before proceeding. Hopefully,
the pixmap is then kept around and rendered multiple times to amoritize
the cost of the copy.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/sna/sna_accel.c | 84 |
1 files changed, 71 insertions, 13 deletions
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c index afc92569..1a35c4de 100644 --- a/src/sna/sna_accel.c +++ b/src/sna/sna_accel.c @@ -252,6 +252,41 @@ static uint32_t sna_pixmap_choose_tiling(PixmapPtr pixmap, uint32_t tiling) pixmap->drawable.bitsPerPixel); } +static bool sna_pixmap_change_tiling(PixmapPtr pixmap, uint32_t tiling) +{ + struct sna_pixmap *priv = sna_pixmap(pixmap); + struct sna *sna = to_sna_from_pixmap(pixmap); + struct kgem_bo *bo; + BoxRec box; + + if (priv->pinned) + return false; + + bo = kgem_create_2d(&sna->kgem, + pixmap->drawable.width, + pixmap->drawable.height, + pixmap->drawable.bitsPerPixel, + tiling, 0); + if (bo == NULL) + return false; + + box.x1 = box.y1 = 0; + box.x2 = pixmap->drawable.width; + box.y2 = pixmap->drawable.height; + + if (!sna->render.copy_boxes(sna, GXcopy, + pixmap, priv->gpu_bo, 0, 0, + pixmap, bo, 0, 0, + &box, 1)) { + kgem_bo_destroy(&sna->kgem, bo); + return false; + } + + kgem_bo_destroy(&sna->kgem, priv->gpu_bo); + priv->gpu_bo = bo; + return true; +} + static inline void sna_set_pixmap(PixmapPtr pixmap, struct sna_pixmap *sna) { dixSetPrivate(&pixmap->devPrivates, &sna_pixmap_index, sna); @@ -1474,8 +1509,10 @@ sna_put_xybitmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region, &damage)) return false; - if (priv->gpu_bo->tiling == I915_TILING_Y) - return false; + if (priv->gpu_bo->tiling == I915_TILING_Y) { + if (!sna_pixmap_change_tiling(pixmap, I915_TILING_X)) + return false; + } assert_pixmap_contains_box(pixmap, RegionExtents(region)); if (damage) @@ -1592,8 +1629,12 @@ sna_put_xypixmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region, &damage)) return false; - if (bo->tiling == I915_TILING_Y) - return false; + if (bo->tiling == I915_TILING_Y) { + if (!sna_pixmap_change_tiling(pixmap, I915_TILING_X)) + return false; + + bo = priv->gpu_bo; + } assert_pixmap_contains_box(pixmap, RegionExtents(region)); if (damage) @@ -3208,7 +3249,8 @@ sna_copy_plane(DrawablePtr src, DrawablePtr dst, GCPtr gc, if (sna_drawable_use_gpu_bo(dst, ®ion.extents, &damage)) { struct sna_pixmap *priv = sna_pixmap(pixmap); - if (priv->gpu_bo->tiling != I915_TILING_Y) { + if (priv->gpu_bo->tiling != I915_TILING_Y || + sna_pixmap_change_tiling(pixmap, I915_TILING_X)) { RegionUninit(®ion); return miDoCopy(src, dst, gc, src_x, src_y, @@ -6819,8 +6861,17 @@ sna_poly_fill_rect_stippled_blt(DrawablePtr drawable, PixmapPtr stipple = gc->stipple; - if (bo->tiling == I915_TILING_Y) - return false; + if (bo->tiling == I915_TILING_Y) { + PixmapPtr pixmap = get_drawable_pixmap(drawable); + + /* This is cheating, but only the gpu_bo can be tiled */ + assert(bo == sna_pixmap(pixmap)->gpu_bo); + + if (!sna_pixmap_change_tiling(pixmap, I915_TILING_X)) + return false; + + bo = sna_pixmap(pixmap)->gpu_bo; + } sna_drawable_move_to_cpu(&stipple->drawable, false); @@ -7121,8 +7172,11 @@ sna_glyph_blt(DrawablePtr drawable, GCPtr gc, bo = priv->gpu_bo; if (bo->tiling == I915_TILING_Y) { - DBG(("%s -- fallback, dst uses Y-tiling\n", __FUNCTION__)); - return false; + if (!sna_pixmap_change_tiling(pixmap, I915_TILING_X)) { + DBG(("%s -- fallback, dst uses Y-tiling\n", __FUNCTION__)); + return false; + } + bo = priv->gpu_bo; } get_drawable_deltas(drawable, pixmap, &dx, &dy); @@ -7664,8 +7718,10 @@ sna_reversed_glyph_blt(DrawablePtr drawable, GCPtr gc, uint8_t rop = transparent ? copy_ROP[gc->alu] : ROP_S; if (priv->gpu_bo->tiling == I915_TILING_Y) { - DBG(("%s -- fallback, dst uses Y-tiling\n", __FUNCTION__)); - return false; + if (!sna_pixmap_change_tiling(pixmap, I915_TILING_X)) { + DBG(("%s -- fallback, dst uses Y-tiling\n", __FUNCTION__)); + return false; + } } get_drawable_deltas(drawable, pixmap, &dx, &dy); @@ -7949,8 +8005,10 @@ sna_push_pixels_solid_blt(GCPtr gc, int n; uint8_t rop = copy_ROP[gc->alu]; - if (priv->gpu_bo->tiling == I915_TILING_Y) - return false; + if (priv->gpu_bo->tiling == I915_TILING_Y) { + if (!sna_pixmap_change_tiling(pixmap, I915_TILING_X)) + return false; + } if (!sna_drawable_use_gpu_bo(drawable, ®ion->extents, &damage)) return false; |