sna: Utilise existing cached upload for promoting to GPU bo
authorChris Wilson <chris@chris-wilson.co.uk>
Fri, 4 Jul 2014 10:02:39 +0000 (11:02 +0100)
committerChris Wilson <chris@chris-wilson.co.uk>
Fri, 4 Jul 2014 10:25:28 +0000 (11:25 +0100)
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>
src/sna/sna_accel.c
src/sna/sna_damage.h

index 9191fe2..0b16bd0 100644 (file)
@@ -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
index 28f7ee6..a55f859 100644 (file)
@@ -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);