summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-01-27 18:05:51 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2012-01-27 18:25:00 +0000
commit6402e7f1195f60f96dc269a701532c3270d8920f (patch)
tree5708945627e879ce4e27ce72f72b216b90bdcb8e
parent6c5fb84f4de346b06e5a538e683c5a118f2579bc (diff)
sna: Ensure that we have a source bo for tiled fills
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/sna_accel.c63
1 files changed, 56 insertions, 7 deletions
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 3c8f2be3..840012f0 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -2016,8 +2016,10 @@ sna_pixmap_move_to_gpu(PixmapPtr pixmap, unsigned flags)
__FUNCTION__, pixmap->drawable.serialNumber, pixmap->usage_hint));
priv = sna_pixmap(pixmap);
- if (priv == NULL)
+ if (priv == NULL) {
+ DBG(("%s: not attached\n", __FUNCTION__));
return NULL;
+ }
if (DAMAGE_IS_ALL(priv->gpu_damage)) {
DBG(("%s: already all-damaged\n", __FUNCTION__));
@@ -2039,6 +2041,7 @@ sna_pixmap_move_to_gpu(PixmapPtr pixmap, unsigned flags)
sna_pixmap_choose_tiling(pixmap),
priv->cpu_damage ? CREATE_GTT_MAP | CREATE_INACTIVE : 0);
if (priv->gpu_bo == NULL) {
+ DBG(("%s: not creating GPU bo\n", __FUNCTION__));
assert(list_is_empty(&priv->list));
return NULL;
}
@@ -8391,6 +8394,45 @@ out:
RegionUninit(&data.region);
}
+static struct kgem_bo *
+sna_pixmap_get_source_bo(PixmapPtr pixmap)
+{
+ struct sna_pixmap *priv = sna_pixmap(pixmap);
+
+ if (priv == NULL) {
+ struct kgem_bo *upload;
+ struct sna *sna = to_sna_from_pixmap(pixmap);
+ void *ptr;
+
+ upload = kgem_create_buffer_2d(&sna->kgem,
+ pixmap->drawable.width,
+ pixmap->drawable.height,
+ pixmap->drawable.bitsPerPixel,
+ KGEM_BUFFER_WRITE_INPLACE,
+ &ptr);
+ memcpy_blt(pixmap->devPrivate.ptr, ptr,
+ pixmap->drawable.bitsPerPixel,
+ pixmap->devKind, upload->pitch,
+ 0, 0,
+ 0, 0,
+ pixmap->drawable.width,
+ pixmap->drawable.height);
+
+ return upload;
+ }
+
+ if (priv->gpu_damage && !sna_pixmap_move_to_gpu(pixmap, MOVE_READ))
+ return NULL;
+
+ if (priv->cpu_damage && priv->cpu_bo)
+ return kgem_bo_reference(priv->cpu_bo);
+
+ if (!sna_pixmap_force_to_gpu(pixmap, MOVE_READ))
+ return NULL;
+
+ return kgem_bo_reference(priv->gpu_bo);
+}
+
static Bool
sna_poly_fill_rect_tiled_blt(DrawablePtr drawable,
struct kgem_bo *bo,
@@ -8401,6 +8443,7 @@ sna_poly_fill_rect_tiled_blt(DrawablePtr drawable,
PixmapPtr pixmap = get_drawable_pixmap(drawable);
struct sna *sna = to_sna_from_pixmap(pixmap);
PixmapPtr tile = gc->tile.pixmap;
+ struct kgem_bo *tile_bo;
const DDXPointRec * const origin = &gc->patOrg;
struct sna_copy_op copy;
CARD32 alu = gc->alu;
@@ -8412,25 +8455,30 @@ sna_poly_fill_rect_tiled_blt(DrawablePtr drawable,
tile_width = tile->drawable.width;
tile_height = tile->drawable.height;
- if ((tile_width | tile_height) == 1)
+ if ((tile_width | tile_height) == 1) {
+ DBG(("%s: single pixel tile pixmap ,converting to solid fill\n",
+ __FUNCTION__));
return sna_poly_fill_rect_blt(drawable, bo, damage,
gc, get_pixel(tile),
n, rect,
extents, clipped);
+ }
/* XXX [248]x[238] tiling can be reduced to a pattern fill.
* Also we can do the lg2 reduction for BLT and use repeat modes for
* RENDER.
*/
- if (!sna_pixmap_move_to_gpu(tile, MOVE_READ))
+ tile_bo = sna_pixmap_get_source_bo(tile);
+ if (tile_bo == NULL) {
+ DBG(("%s: unable to move tile go GPU, fallback\n",
+ __FUNCTION__));
return FALSE;
+ }
- if (!sna_copy_init_blt(&copy, sna,
- tile, sna_pixmap_get_bo(tile),
- pixmap, bo,
- alu)) {
+ if (!sna_copy_init_blt(&copy, sna, tile, tile_bo, pixmap, bo, alu)) {
DBG(("%s: unsupported blt\n", __FUNCTION__));
+ kgem_bo_destroy(&sna->kgem, tile_bo);
return FALSE;
}
@@ -8620,6 +8668,7 @@ sna_poly_fill_rect_tiled_blt(DrawablePtr drawable,
}
done:
copy.done(sna, &copy);
+ kgem_bo_destroy(&sna->kgem, tile_bo);
return TRUE;
}