summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2014-07-04 11:02:39 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2014-07-04 11:25:28 +0100
commit64bcb91f58fba3956f2c66fa37707b9e496da936 (patch)
tree14574fbf608ce24de0973a8a77abdd69d8212555
parent821ef20b27f84cc26aec266b0f616a7f39ba9e3d (diff)
sna: Utilise existing cached upload for promoting to GPU bo
If we already have a buffer that represents the data on the GPU, we can simply use that when we need to promote the pixmap onto the GPU. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/sna_accel.c55
-rw-r--r--src/sna/sna_damage.h1
2 files changed, 35 insertions, 21 deletions
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 9191fe2f..0b16bd00 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -4091,24 +4091,19 @@ sna_pixmap_move_to_gpu(PixmapPtr pixmap, unsigned flags)
goto active;
}
- if (kgem_bo_discard_cache(priv->gpu_bo, flags & (MOVE_WRITE | __MOVE_FORCE))) {
- DBG(("%s: discarding cached upload buffer\n", __FUNCTION__));
- assert(DAMAGE_IS_ALL(priv->cpu_damage));
- assert(priv->gpu_damage == NULL || DAMAGE_IS_ALL(priv->gpu_damage)); /* magical upload buffer */
- assert(!priv->pinned);
- assert(!priv->mapped);
- sna_damage_destroy(&priv->gpu_damage);
- kgem_bo_destroy(&sna->kgem, priv->gpu_bo);
- priv->gpu_bo = NULL;
- }
-
if ((flags & MOVE_READ) == 0)
sna_damage_destroy(&priv->cpu_damage);
sna_damage_reduce(&priv->cpu_damage);
assert_pixmap_damage(pixmap);
DBG(("%s: CPU damage? %d\n", __FUNCTION__, priv->cpu_damage != NULL));
- if (priv->gpu_bo == NULL) {
+ if (priv->gpu_bo == NULL ||
+ kgem_bo_discard_cache(priv->gpu_bo, flags & (MOVE_WRITE | __MOVE_FORCE))) {
+ struct kgem_bo *proxy;
+
+ proxy = priv->gpu_bo;
+ priv->gpu_bo = NULL;
+
DBG(("%s: creating GPU bo (%dx%d@%d), create=%x\n",
__FUNCTION__,
pixmap->drawable.width,
@@ -4116,9 +4111,9 @@ sna_pixmap_move_to_gpu(PixmapPtr pixmap, unsigned flags)
pixmap->drawable.bitsPerPixel,
priv->create));
assert(!priv->mapped);
- if (flags & __MOVE_FORCE || priv->create & KGEM_CAN_CREATE_GPU) {
- unsigned create;
+ assert(list_is_empty(&priv->flush_list));
+ if (flags & __MOVE_FORCE || priv->create & KGEM_CAN_CREATE_GPU) {
assert(pixmap->drawable.width > 0);
assert(pixmap->drawable.height > 0);
assert(pixmap->drawable.bitsPerPixel >= 8);
@@ -4138,21 +4133,39 @@ sna_pixmap_move_to_gpu(PixmapPtr pixmap, unsigned flags)
pixmap->devPrivate.ptr = NULL;
sna_damage_all(&priv->gpu_damage, pixmap);
sna_damage_destroy(&priv->cpu_damage);
- goto done;
- }
-
- create = 0;
- if (flags & MOVE_INPLACE_HINT || (priv->cpu_damage && priv->cpu_bo == NULL))
- create = CREATE_GTT_MAP | CREATE_INACTIVE;
+ } else {
+ unsigned create = 0;
+ if (flags & MOVE_INPLACE_HINT || (priv->cpu_damage && priv->cpu_bo == NULL))
+ create = CREATE_GTT_MAP | CREATE_INACTIVE;
- sna_pixmap_alloc_gpu(sna, pixmap, priv, create);
+ sna_pixmap_alloc_gpu(sna, pixmap, priv, create);
+ }
}
+
if (priv->gpu_bo == NULL) {
DBG(("%s: not creating GPU bo\n", __FUNCTION__));
assert(priv->gpu_damage == NULL);
+ priv->gpu_bo = proxy;
+ if (proxy)
+ sna_damage_all(&priv->cpu_damage, pixmap);
return NULL;
}
+ if (proxy) {
+ DBG(("%s: promoting upload proxy handle=%d to GPU\n", __FUNCTION__, proxy->handle));
+
+ if (priv->cpu_damage &&
+ sna->render.copy_boxes(sna, GXcopy,
+ &pixmap->drawable, proxy, 0, 0,
+ &pixmap->drawable, priv->gpu_bo, 0, 0,
+ region_rects(DAMAGE_REGION(priv->cpu_damage)),
+ region_num_rects(DAMAGE_REGION(priv->cpu_damage)),
+ 0))
+ sna_damage_destroy(&priv->cpu_damage);
+
+ kgem_bo_destroy(&sna->kgem, proxy);
+ }
+
if (flags & MOVE_WRITE && priv->cpu_damage == NULL) {
/* Presume that we will only ever write to the GPU
* bo. Readbacks are expensive but fairly constant
diff --git a/src/sna/sna_damage.h b/src/sna/sna_damage.h
index 28f7ee60..a55f8598 100644
--- a/src/sna/sna_damage.h
+++ b/src/sna/sna_damage.h
@@ -25,6 +25,7 @@ struct sna_damage {
#define DAMAGE_IS_ALL(ptr) (((uintptr_t)(ptr))&1)
#define DAMAGE_MARK_ALL(ptr) ((struct sna_damage *)(((uintptr_t)(ptr))|1))
#define DAMAGE_PTR(ptr) ((struct sna_damage *)(((uintptr_t)(ptr))&~1))
+#define DAMAGE_REGION(ptr) (&DAMAGE_PTR(ptr)->region)
struct sna_damage *sna_damage_create(void);