sna/dri2: Recreate buffer in reuse rather than force recreate
authorChris Wilson <chris@chris-wilson.co.uk>
Wed, 23 Jul 2014 07:37:46 +0000 (08:37 +0100)
committerChris Wilson <chris@chris-wilson.co.uk>
Wed, 23 Jul 2014 07:43:02 +0000 (08:43 +0100)
By marking the buffer->attachment as invalid we forced the recreation of
the buffer on the next DRI2GetBuffers. The only small problem with that
was that the client didn't always immediately call DRI2GetBuffers after
the invalidation - and if they did a DRI2CopyRegion with its stale
buffers the unfound attachment would generate a BadValue and kill the
client. So instead of messing around with the attachment, explicitly
recreate the buffer if we attempt to reuse a buffer of the wrong size.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
src/sna/sna_dri2.c

index 69496c3..d4d099d 100644 (file)
@@ -142,19 +142,19 @@ sna_dri2_get_back(struct sna *sna,
 {
        struct kgem_bo *bo;
        uint32_t name;
-
-       if ((draw->height << 16 | draw->width) != get_private(back)->size)
-               return;
-
-       get_private(back)->stale = false;
-
-       bo = get_private(back)->bo;
-       assert(bo->refcnt);
-       DBG(("%s: back buffer handle=%d, scanout?=%d, refcnt=%d\n",
-            __FUNCTION__, bo->handle, bo->active_scanout, get_private(back)->refcnt));
-       if (bo->active_scanout == 0) {
-               DBG(("%s: reuse unattached back\n", __FUNCTION__));
-               return;
+       bool reuse;
+
+       reuse = (draw->height << 16 | draw->width) == get_private(back)->size;
+       if (reuse) {
+               bo = get_private(back)->bo;
+               assert(bo->refcnt);
+               DBG(("%s: back buffer handle=%d, scanout?=%d, refcnt=%d\n",
+                                       __FUNCTION__, bo->handle, bo->active_scanout, get_private(back)->refcnt));
+               if (bo->active_scanout == 0) {
+                       DBG(("%s: reuse unattached back\n", __FUNCTION__));
+                       get_private(back)->stale = false;
+                       return;
+               }
        }
 
        bo = NULL;
@@ -187,7 +187,7 @@ sna_dri2_get_back(struct sna *sna,
        }
        assert(bo->active_scanout == 0);
 
-       if (info) {
+       if (info && reuse) {
                bool found = false;
                struct dri_bo *c;
 
@@ -210,8 +210,13 @@ sna_dri2_get_back(struct sna *sna,
 
        assert(bo != get_private(back)->bo);
        kgem_bo_destroy(&sna->kgem, get_private(back)->bo);
+
        get_private(back)->bo = bo;
+       get_private(back)->size = draw->height << 16 | draw->width;
+       back->pitch = bo->pitch;
        back->name = name;
+
+       get_private(back)->stale = false;
 }
 
 struct dri2_window {
@@ -1935,11 +1940,9 @@ static void sna_dri2_xchg_crtc(struct sna *sna, DrawablePtr draw, xf86CrtcPtr cr
        sna_shadow_set_crtc(sna, crtc, get_private(back)->bo);
        DamageRegionProcessPending(&win->drawable);
 
-       if (get_private(front)->size == (draw->height << 16 | draw->width)) {
-               front->attachment = DRI2BufferBackLeft;
-               get_private(front)->stale = true;
-       } else
-               front->attachment = -1;
+       front->attachment = DRI2BufferBackLeft;
+       get_private(front)->stale = true;
+
        back->attachment = DRI2BufferFrontLeft;
        if (get_private(back)->proxy == NULL) {
                get_private(back)->proxy = sna_dri2_reference_buffer(sna_pixmap_get_buffer(pixmap));