Submitted By:            Douglas R. Reno <renodr at linuxfromscratch dot org>
Date:                    2020-01-29
Initial Package Version: 19.3.3
Origin:                  Upstream (MR 3614) + Self
Description:             Fixes a Xorg Segmentation Fault when using Xorg under
                         VMWare Workstation (or any device that uses the SVGA
                         driver). This also adapts it to driver changes in
                         Linux 5.3+ for allowing OpenGL 4.5/4.6/Vulkan 1.1 to
                         function in the VMWare DRM driver. This also fixes
                         several graphical glitches and bugs that have been
                         present since Mesa-19.2.0 (with the introduction of
                         OpenGL-4.5).

Update:                  19.3.4 applied one hunk from the previous version of
                         this patch.  That hunk has been removed now.

diff -Naurp mesa-19.3.3.orig/src/gallium/auxiliary/util/u_debug_flush.c mesa-19.3.3/src/gallium/auxiliary/util/u_debug_flush.c
--- mesa-19.3.3.orig/src/gallium/auxiliary/util/u_debug_flush.c	2020-01-28 13:07:35.000000000 -0600
+++ mesa-19.3.3/src/gallium/auxiliary/util/u_debug_flush.c	2020-01-29 12:58:56.174774458 -0600
@@ -51,7 +51,7 @@
 #include <stdio.h>
 
 /* Future improvement: Use realloc instead? */
-#define DEBUG_FLUSH_MAP_DEPTH 16
+#define DEBUG_FLUSH_MAP_DEPTH 32
 
 struct debug_map_item {
    struct debug_stack_frame *frame;
 
diff -Naurp mesa-19.3.3.orig/src/gallium/drivers/svga/svga_pipe_blit.c mesa-19.3.3/src/gallium/drivers/svga/svga_pipe_blit.c
--- mesa-19.3.3.orig/src/gallium/drivers/svga/svga_pipe_blit.c	2020-01-28 13:07:35.000000000 -0600
+++ mesa-19.3.3/src/gallium/drivers/svga/svga_pipe_blit.c	2020-01-29 12:57:13.083255804 -0600
@@ -881,8 +881,10 @@ svga_resource_copy_region(struct pipe_co
           try_blit(svga, &blit))
          goto done;
 
-      copy_region_fallback(svga, dst_tex, dst_level, dstx, dsty, dstz,
-                           src_tex, src_level, src_box);
+      if (!try_cpu_copy_region(svga, &blit)) {
+         if (!try_blit(svga, &blit))
+            debug_printf("Blit failed.\n");
+      }
    }
 
 done:
diff -Naurp mesa-19.3.3.orig/src/gallium/drivers/svga/svga_resource_texture.c mesa-19.3.3/src/gallium/drivers/svga/svga_resource_texture.c
--- mesa-19.3.3.orig/src/gallium/drivers/svga/svga_resource_texture.c	2020-01-28 13:07:35.000000000 -0600
+++ mesa-19.3.3/src/gallium/drivers/svga/svga_resource_texture.c	2020-01-29 12:59:39.539999310 -0600
@@ -531,7 +531,7 @@ svga_texture_transfer_map(struct pipe_co
    struct svga_transfer *st;
    struct svga_winsys_surface *surf = tex->handle;
    boolean use_direct_map = svga_have_gb_objects(svga) &&
-                            !svga_have_gb_dma(svga);
+        (!svga_have_gb_dma(svga) || (usage & PIPE_TRANSFER_WRITE));
    void *map = NULL;
    int64_t begin = svga_get_time(svga);
 
diff -Naurp mesa-19.3.3.orig/src/gallium/drivers/svga/svga_state_tgsi_transform.c mesa-19.3.3/src/gallium/drivers/svga/svga_state_tgsi_transform.c
--- mesa-19.3.3.orig/src/gallium/drivers/svga/svga_state_tgsi_transform.c	2020-01-28 13:07:35.000000000 -0600
+++ mesa-19.3.3/src/gallium/drivers/svga/svga_state_tgsi_transform.c	2020-01-29 12:58:30.420642705 -0600
@@ -131,7 +131,7 @@ emulate_point_sprite(struct svga_context
          tgsi_dump(new_tokens, 0);
       }
 
-      templ.tokens = new_tokens;
+      pipe_shader_state_from_tgsi(&templ, new_tokens);
       templ.stream_output.num_outputs = 0;
 
       if (streamout) {
diff -Naurp mesa-19.3.3.orig/src/gallium/winsys/svga/drm/vmwgfx_drm.h mesa-19.3.3/src/gallium/winsys/svga/drm/vmwgfx_drm.h
--- mesa-19.3.3.orig/src/gallium/winsys/svga/drm/vmwgfx_drm.h	2020-01-28 13:07:35.000000000 -0600
+++ mesa-19.3.3/src/gallium/winsys/svga/drm/vmwgfx_drm.h	2020-01-29 13:06:18.679201111 -0600
@@ -71,6 +71,7 @@ extern "C" {
 #define DRM_VMW_CREATE_EXTENDED_CONTEXT 26
 #define DRM_VMW_GB_SURFACE_CREATE_EXT   27
 #define DRM_VMW_GB_SURFACE_REF_EXT      28
+#define DRM_VMW_MSG                     29
 
 /*************************************************************************/
 /**
@@ -1213,6 +1214,22 @@ union drm_vmw_gb_surface_reference_ext_a
 	struct drm_vmw_surface_arg req;
 };
 
+/**
+ * struct drm_vmw_msg_arg
+ *
+ * @send: Pointer to user-space msg string (null terminated).
+ * @receive: Pointer to user-space receive buffer.
+ * @send_only: Boolean for whether this is only sending or receiving too.
+ *
+ * Argument to the DRM_VMW_MSG ioctl.
+ */
+struct drm_vmw_msg_arg {
+   __u64 send;
+   __u64 receive;
+   __s32 send_only;
+   __u32 receive_len;
+};
+
 #if defined(__cplusplus)
 }
 #endif
diff -Naurp mesa-19.3.3.orig/src/gallium/winsys/svga/drm/vmw_msg.c mesa-19.3.3/src/gallium/winsys/svga/drm/vmw_msg.c
--- mesa-19.3.3.orig/src/gallium/winsys/svga/drm/vmw_msg.c	2020-01-28 13:07:35.000000000 -0600
+++ mesa-19.3.3/src/gallium/winsys/svga/drm/vmw_msg.c	2020-01-29 13:17:24.572151101 -0600
@@ -31,6 +31,9 @@
 #include "pipe/p_defines.h"
 #include "svga_winsys.h"
 #include "vmw_msg.h"
+#include "vmwgfx_drm.h"
+#include "vmw_screen.h"
+#include "xf86drm.h"
 
 
 #define MESSAGE_STATUS_SUCCESS  0x0001
@@ -424,6 +427,7 @@ void
 vmw_svga_winsys_host_log(struct svga_winsys_screen *sws, const char *log)
 {
    struct rpc_channel channel;
+   struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
    char *msg;
    int msg_len;
    int ret;
@@ -444,9 +448,20 @@ vmw_svga_winsys_host_log(struct svga_win
 
    sprintf(msg, "log %s", log);
 
-   if (!(ret = vmw_open_channel(&channel, RPCI_PROTOCOL_NUM))) {
-      ret = vmw_send_msg(&channel, msg);
-      vmw_close_channel(&channel);
+   if (vws->ioctl.have_drm_2_17) {
+      struct drm_vmw_msg_arg msg_arg;
+
+      memset(&msg_arg, 0, sizeof(msg_arg));
+      msg_arg.send = (uint64_t) (unsigned long) (msg);
+      msg_arg.send_only = 1;
+
+      ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_MSG,
+                                &msg_arg, sizeof(msg_arg));
+   } else {
+      if (!(ret = vmw_open_channel(&channel, RPCI_PROTOCOL_NUM))) {
+         ret = vmw_send_msg(&channel, msg);
+         vmw_close_channel(&channel);
+      }
    }
 
    if (ret)
diff -Naurp mesa-19.3.3.orig/src/gallium/winsys/svga/drm/vmw_screen.h mesa-19.3.3/src/gallium/winsys/svga/drm/vmw_screen.h
--- mesa-19.3.3.orig/src/gallium/winsys/svga/drm/vmw_screen.h	2020-01-28 13:07:35.000000000 -0600
+++ mesa-19.3.3/src/gallium/winsys/svga/drm/vmw_screen.h	2020-01-29 13:03:29.288242444 -0600
@@ -78,6 +78,8 @@ struct vmw_winsys_screen
       boolean have_drm_2_9;
       uint32_t drm_execbuf_version;
       boolean have_drm_2_15;
+      boolean have_drm_2_16;
+      boolean have_drm_2_17;
    } ioctl;
 
    struct {
diff -Naurp mesa-19.3.3.orig/src/gallium/winsys/svga/drm/vmw_screen_ioctl.c mesa-19.3.3/src/gallium/winsys/svga/drm/vmw_screen_ioctl.c
--- mesa-19.3.3.orig/src/gallium/winsys/svga/drm/vmw_screen_ioctl.c	2020-01-28 13:07:35.000000000 -0600
+++ mesa-19.3.3/src/gallium/winsys/svga/drm/vmw_screen_ioctl.c	2020-01-29 13:04:44.757665966 -0600
@@ -694,6 +694,7 @@ vmw_ioctl_region_map(struct vmw_region *
 	 return NULL;
       }
 
+      (void) madvise(map, region->size, MADV_HUGEPAGE);
       region->data = map;
    }
 
@@ -973,7 +974,6 @@ vmw_ioctl_init(struct vmw_winsys_screen
    drmVersionPtr version;
    boolean drm_gb_capable;
    boolean have_drm_2_5;
-   boolean have_drm_2_16;
    const char *getenv_val;
 
    VMW_FUNC;
@@ -990,8 +990,10 @@ vmw_ioctl_init(struct vmw_winsys_screen
       (version->version_major == 2 && version->version_minor > 8);
    vws->ioctl.have_drm_2_15 = version->version_major > 2 ||
       (version->version_major == 2 && version->version_minor > 14);
-   have_drm_2_16 = version->version_major > 2 ||
+   vws->ioctl.have_drm_2_16 = version->version_major > 2 ||
       (version->version_major == 2 && version->version_minor > 15);
+   vws->ioctl.have_drm_2_17 = version->version_major > 2 ||
+      (version->version_major == 2 && version->version_minor > 16);
 
    vws->ioctl.drm_execbuf_version = vws->ioctl.have_drm_2_9 ? 2 : 1;
 
@@ -1116,7 +1118,7 @@ vmw_ioctl_init(struct vmw_winsys_screen
       else
          vws->ioctl.num_cap_3d = SVGA3D_DEVCAP_MAX;
 
-      if (have_drm_2_16) {
+      if (vws->ioctl.have_drm_2_16) {
          vws->base.have_coherent = TRUE;
          getenv_val = getenv("SVGA_FORCE_COHERENT");
          if (getenv_val && strcmp(getenv_val, "0") != 0)
