winsys/svga: fix display corruption after surface_init
authorCharmaine Lee <charmainel@vmware.com>
Thu, 20 Aug 2020 23:43:00 +0000 (16:43 -0700)
committerMarge Bot <eric+marge@anholt.net>
Fri, 21 Aug 2020 18:04:44 +0000 (18:04 +0000)
When we initialize the buffer surface, do not map the existing storage
with DONTBLOCK, leave it as a synchronized map.
This patch also sets the surface rebind flag after it is bound to a
new buffer and sets the surface buffer pointer accordingly.

This fixes display corruption issue seen with running steam.

Reviewed-by: Neha Bhende <bhenden@vmware.com>
Reviewed-by: Roland Scheidegger <sroland@vmware.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6415>

src/gallium/drivers/svga/svga_resource_buffer_upload.c
src/gallium/winsys/svga/drm/vmw_surface.c

index 78535643563e300e2945c62be427d3b3fa4b9db5..fecc1ae54d086670df94fd8209ac8ae3e89dd629 100644 (file)
@@ -229,12 +229,12 @@ svga_buffer_create_host_surface(struct svga_screen *ss,
       /* Add the new surface to the buffer surface list */
       ret = svga_buffer_add_host_surface(sbuf, sbuf->handle, &sbuf->key,
                                          bind_flags);
-   }
 
-   if (ss->sws->have_gb_objects) {
-      /* Initialize the surface with zero */
-      ss->sws->surface_init(ss->sws, sbuf->handle, svga_surface_size(&sbuf->key),
-                            sbuf->key.flags);
+      if (ss->sws->have_gb_objects) {
+         /* Initialize the surface with zero */
+         ss->sws->surface_init(ss->sws, sbuf->handle, svga_surface_size(&sbuf->key),
+                               sbuf->key.flags);
+      }
    }
 
    return ret;
index f6f40fcdf209abf108dc394c8f217e65445ef736..25c6d320c7408447ce687afe5265aa071098079f 100644 (file)
@@ -44,15 +44,15 @@ vmw_svga_winsys_surface_init(struct svga_winsys_screen *sws,
    struct pb_buffer *pb_buf;
    uint32_t pb_flags;
    struct vmw_winsys_screen *vws = vsrf->screen;
-   pb_flags = PIPE_TRANSFER_READ_WRITE | PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE;
+   pb_flags = PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE;
 
    struct pb_manager *provider;
    struct pb_desc desc;
 
-   data = vmw_svga_winsys_buffer_map(&vws->base, vsrf->buf,
-                                     PIPE_TRANSFER_DONTBLOCK | pb_flags);
+   mtx_lock(&vsrf->mutex);
+   data = vmw_svga_winsys_buffer_map(&vws->base, vsrf->buf, pb_flags);
    if (data)
-      goto out_unlock;
+      goto out_mapped;
 
    provider = vws->pools.mob_fenced;
    memset(&desc, 0, sizeof(desc));
@@ -64,24 +64,25 @@ vmw_svga_winsys_surface_init(struct svga_winsys_screen *sws,
 
       data = vmw_svga_winsys_buffer_map(&vws->base, vbuf, pb_flags);
       if (data) {
-         if (vsrf->buf) {
+         vsrf->rebind = TRUE;
+         if (vsrf->buf)
             vmw_svga_winsys_buffer_destroy(&vws->base, vsrf->buf);
-            vsrf->buf = vbuf;
-            goto out_unlock;
-         } else
-            vmw_svga_winsys_buffer_destroy(&vws->base, vbuf);
+         vsrf->buf = vbuf;
+         goto out_mapped;
+      } else {
+         vmw_svga_winsys_buffer_destroy(&vws->base, vbuf);
+         goto out_unlock;
       }
    }
-
-   data = vmw_svga_winsys_buffer_map(&vws->base, vsrf->buf, pb_flags);
-   if (data == NULL)
+   else {
+      /* Cannot create a buffer, just unlock */
       goto out_unlock;
+   }
 
-out_unlock:
+out_mapped:
    mtx_unlock(&vsrf->mutex);
 
-   if (data)
-   {
+   if (data) {
       if (flags & SVGA3D_SURFACE_BIND_STREAM_OUTPUT) {
          memset(data, 0, surf_size + sizeof(SVGA3dDXSOState));
       }
@@ -89,8 +90,10 @@ out_unlock:
          memset(data, 0, surf_size);
       }
    }
+
    mtx_lock(&vsrf->mutex);
    vmw_svga_winsys_buffer_unmap(&vsrf->screen->base, vsrf->buf);
+out_unlock:
    mtx_unlock(&vsrf->mutex);
 }