summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-12-12 16:26:13 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2011-12-13 01:38:09 +0000
commit3c163d105e964a1084d665500ef917254d8f2179 (patch)
treeb8c00cc05a09359b8cffdedfb66ce2d21bb89206
parentc481bec356b2e40e66a000dbaaf261bf7aae930d (diff)
sna: Use the CPU bo as a render source if compatible and no GPU bo
This is principally to catch the cases of compositing after a fresh PutImage. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/kgem.c4
-rw-r--r--src/sna/sna_render.c58
2 files changed, 58 insertions, 4 deletions
diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 6a17bfe5..1a098491 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -1447,13 +1447,13 @@ int kgem_choose_tiling(struct kgem *kgem, int tiling, int width, int height, int
goto done;
}
- if (tiling == I915_TILING_X && width * bpp < 8*512/2) {
+ if (tiling == I915_TILING_X && width * bpp <= 8*512/2) {
DBG(("%s: too thin [width %d, %d bpp] for TILING_X\n",
__FUNCTION__, width, bpp));
tiling = I915_TILING_NONE;
goto done;
}
- if (tiling == I915_TILING_Y && width * bpp < 8*32/2) {
+ if (tiling == I915_TILING_Y && width * bpp <= 8*32/2) {
DBG(("%s: too thin [%d] for TILING_Y\n",
__FUNCTION__, width));
tiling = I915_TILING_NONE;
diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c
index 13c0526d..f1ed78bb 100644
--- a/src/sna/sna_render.c
+++ b/src/sna/sna_render.c
@@ -245,6 +245,59 @@ void no_render_init(struct sna *sna)
sna->kgem.ring = KGEM_BLT;
}
+static struct kgem_bo *
+use_cpu_bo(struct sna *sna, PixmapPtr pixmap, const BoxRec *box)
+{
+ struct sna_pixmap *priv;
+
+ priv = sna_pixmap(pixmap);
+ if (priv == NULL || priv->cpu_bo == NULL) {
+ DBG(("%s: no cpu bo\n", __FUNCTION__));
+ return NULL;
+ }
+
+ if (priv->gpu_bo &&
+ sna_damage_contains_box(priv->cpu_damage,
+ box) == PIXMAN_REGION_OUT) {
+ DBG(("%s: has GPU bo and no damage to upload\n", __FUNCTION__));
+ return NULL;
+ }
+
+ if (sna_damage_contains_box(priv->gpu_damage,
+ box) != PIXMAN_REGION_OUT) {
+ DBG(("%s: box is damaged on the GPU\n", __FUNCTION__));
+ return NULL;
+ }
+
+ if (pixmap->usage_hint)
+ goto done;
+
+ if (priv->gpu_bo) {
+ if (priv->gpu_bo != I915_TILING_NONE) {
+ DBG(("%s: GPU bo exists and is tiled [%d], upload\n",
+ __FUNCTION__, priv->gpu_bo->tiling));
+ return NULL;
+ }
+ } else {
+ int w = box->x2 - box->x1;
+ int h = box->y2 - box->y1;
+ if (priv->source_count*w*h >= pixmap->drawable.width * pixmap->drawable.height &&
+ I915_TILING_NONE != kgem_choose_tiling(&sna->kgem, I915_TILING_X,
+ pixmap->drawable.width,
+ pixmap->drawable.height,
+ pixmap->drawable.bitsPerPixel)) {
+ DBG(("%s: pitch (%d) requires tiling\n",
+ __FUNCTION__, priv->cpu_bo->pitch));
+ return NULL;
+ }
+ }
+
+done:
+ DBG(("%s for box=(%d, %d), (%d, %d)\n",
+ __FUNCTION__, box->x1, box->y1, box->x2, box->y2));
+ return kgem_bo_reference(priv->cpu_bo);
+}
+
static Bool
move_to_gpu(PixmapPtr pixmap, const BoxRec *box)
{
@@ -425,7 +478,8 @@ sna_render_pixmap_bo(struct sna *sna,
channel->offset[0], channel->offset[1],
pixmap->drawable.width, pixmap->drawable.height));
- if (texture_is_cpu(pixmap, &box) && !move_to_gpu(pixmap, &box)) {
+ bo = use_cpu_bo(sna, pixmap, &box);
+ if (bo == NULL && texture_is_cpu(pixmap, &box) && !move_to_gpu(pixmap, &box)) {
/* If we are using transient data, it is better to copy
* to an amalgamated upload buffer so that we don't
* stall on releasing the cpu bo immediately upon
@@ -795,7 +849,7 @@ sna_render_picture_extract(struct sna *sna,
&box,
pixmap->devKind,
pixmap->drawable.bitsPerPixel);
- if (!bo) {
+ if (bo == NULL) {
DBG(("%s: failed to upload source image, using clear\n",
__FUNCTION__));
return 0;