vulkan/wsi: disable the hardware cursor
[mesa.git] / src / vulkan / wsi / wsi_common_display.c
index 08e9e5fe3fce0bde4242e131235473062b212773..0f9a1ffe8d3af271f0ee5848e1c6090b75efc6b1 100644 (file)
@@ -32,7 +32,7 @@
 #include <math.h>
 #include <xf86drm.h>
 #include <xf86drmMode.h>
-#include <drm_fourcc.h>
+#include "drm-uapi/drm_fourcc.h"
 #ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
 #include <xcb/randr.h>
 #include <X11/Xlib-xcb.h>
@@ -171,17 +171,9 @@ wsi_display_mode_refresh(struct wsi_display_mode *wsi)
                                           (double) MAX2(wsi->vscan, 1));
 }
 
-static uint64_t wsi_get_current_monotonic(void)
-{
-   struct timespec tv;
-
-   clock_gettime(CLOCK_MONOTONIC, &tv);
-   return tv.tv_nsec + tv.tv_sec*1000000000ull;
-}
-
 static uint64_t wsi_rel_to_abs_time(uint64_t rel_time)
 {
-   uint64_t current_time = wsi_get_current_monotonic();
+   uint64_t current_time = wsi_common_get_current_time();
 
    /* check for overflow */
    if (rel_time > UINT64_MAX - current_time)
@@ -766,10 +758,27 @@ wsi_get_display_plane_capabilities2(
    assert(capabilities->sType ==
           VK_STRUCTURE_TYPE_DISPLAY_PLANE_CAPABILITIES_2_KHR);
 
-   return wsi_get_display_plane_capabilities(physical_device, wsi_device,
-                                             pDisplayPlaneInfo->mode,
-                                             pDisplayPlaneInfo->planeIndex,
-                                             &capabilities->capabilities);
+   VkResult result =
+      wsi_get_display_plane_capabilities(physical_device, wsi_device,
+                                         pDisplayPlaneInfo->mode,
+                                         pDisplayPlaneInfo->planeIndex,
+                                         &capabilities->capabilities);
+
+   vk_foreach_struct(ext, capabilities->pNext) {
+      switch (ext->sType) {
+      case VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR: {
+         VkSurfaceProtectedCapabilitiesKHR *protected = (void *)ext;
+         protected->supportsProtected = VK_FALSE;
+         break;
+      }
+
+      default:
+         /* Ignored */
+         break;
+      }
+   }
+
+   return result;
 }
 
 VkResult
@@ -887,6 +896,23 @@ static const struct {
    { .format = VK_FORMAT_B8G8R8A8_UNORM, .drm_format = DRM_FORMAT_XRGB8888 },
 };
 
+static void
+get_sorted_vk_formats(struct wsi_device *wsi_device, VkFormat *sorted_formats)
+{
+   for (unsigned i = 0; i < ARRAY_SIZE(available_surface_formats); i++)
+      sorted_formats[i] = available_surface_formats[i].format;
+
+   if (wsi_device->force_bgra8_unorm_first) {
+      for (unsigned i = 0; i < ARRAY_SIZE(available_surface_formats); i++) {
+         if (sorted_formats[i] == VK_FORMAT_B8G8R8A8_UNORM) {
+            sorted_formats[i] = sorted_formats[0];
+            sorted_formats[0] = VK_FORMAT_B8G8R8A8_UNORM;
+            break;
+         }
+      }
+   }
+}
+
 static VkResult
 wsi_display_surface_get_formats(VkIcdSurfaceBase *icd_surface,
                                 struct wsi_device *wsi_device,
@@ -895,9 +921,12 @@ wsi_display_surface_get_formats(VkIcdSurfaceBase *icd_surface,
 {
    VK_OUTARRAY_MAKE(out, surface_formats, surface_format_count);
 
-   for (unsigned i = 0; i < ARRAY_SIZE(available_surface_formats); i++) {
+   VkFormat sorted_formats[ARRAY_SIZE(available_surface_formats)];
+   get_sorted_vk_formats(wsi_device, sorted_formats);
+
+   for (unsigned i = 0; i < ARRAY_SIZE(sorted_formats); i++) {
       vk_outarray_append(&out, f) {
-         f->format = available_surface_formats[i].format;
+         f->format = sorted_formats[i];
          f->colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
       }
    }
@@ -914,10 +943,13 @@ wsi_display_surface_get_formats2(VkIcdSurfaceBase *surface,
 {
    VK_OUTARRAY_MAKE(out, surface_formats, surface_format_count);
 
-   for (unsigned i = 0; i < ARRAY_SIZE(available_surface_formats); i++) {
+   VkFormat sorted_formats[ARRAY_SIZE(available_surface_formats)];
+   get_sorted_vk_formats(wsi_device, sorted_formats);
+
+   for (unsigned i = 0; i < ARRAY_SIZE(sorted_formats); i++) {
       vk_outarray_append(&out, f) {
          assert(f->sType == VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR);
-         f->surfaceFormat.format = available_surface_formats[i].format;
+         f->surfaceFormat.format = sorted_formats[i];
          f->surfaceFormat.colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
       }
    }
@@ -965,8 +997,8 @@ static void
 wsi_display_destroy_buffer(struct wsi_display *wsi,
                            uint32_t buffer)
 {
-   (void) drmIoctl(wsi->fd, DRM_IOCTL_MODE_DESTROY_DUMB,
-                   &((struct drm_mode_destroy_dumb) { .handle = buffer }));
+   (void) drmIoctl(wsi->fd, DRM_IOCTL_GEM_CLOSE,
+                   &((struct drm_gem_close) { .handle = buffer }));
 }
 
 static VkResult
@@ -1436,8 +1468,8 @@ wsi_display_fence_wait(struct wsi_fence *fence_wsi, uint64_t timeout)
 
    wsi_display_debug("%9lu wait fence %lu %ld\n",
                      pthread_self(), fence->sequence,
-                     (int64_t) (timeout - wsi_get_current_monotonic()));
-   wsi_display_debug_code(uint64_t start_ns = wsi_get_current_monotonic());
+                     (int64_t) (timeout - wsi_common_get_current_time()));
+   wsi_display_debug_code(uint64_t start_ns = wsi_common_get_current_time());
    pthread_mutex_lock(&wsi->wait_mutex);
 
    VkResult result;
@@ -1469,7 +1501,7 @@ wsi_display_fence_wait(struct wsi_fence *fence_wsi, uint64_t timeout)
    pthread_mutex_unlock(&wsi->wait_mutex);
    wsi_display_debug("%9lu fence wait %f ms\n",
                      pthread_self(),
-                     ((int64_t) (wsi_get_current_monotonic() - start_ns)) /
+                     ((int64_t) (wsi_common_get_current_time() - start_ns)) /
                      1.0e6);
    return result;
 }
@@ -1655,6 +1687,15 @@ _wsi_display_queue_next(struct wsi_swapchain *drv_chain)
                               &connector->id, 1,
                               &connector->current_drm_mode);
          if (ret == 0) {
+            /* Disable the HW cursor as the app doesn't have a mechanism
+             * to control it.
+             * Refer to question 12 of the VK_KHR_display spec.
+             */
+            ret = drmModeSetCursor(wsi->fd, connector->crtc_id, 0, 0, 0 );
+            if (ret != 0) {
+               wsi_display_debug("failed to hide cursor err %d %s\n", ret, strerror(-ret));
+            }
+
             /* Assume that the mode set is synchronous and that any
              * previous image is now idle.
              */
@@ -1748,7 +1789,7 @@ wsi_display_surface_create_swapchain(
    chain->base.get_wsi_image = wsi_display_get_wsi_image;
    chain->base.acquire_next_image = wsi_display_acquire_next_image;
    chain->base.queue_present = wsi_display_queue_present;
-   chain->base.present_mode = create_info->presentMode;
+   chain->base.present_mode = wsi_swapchain_get_present_mode(wsi_device, create_info);
    chain->base.image_count = num_images;
 
    chain->wsi = wsi;
@@ -1803,6 +1844,30 @@ fail_attr_init:
    return ret;
 }
 
+
+/*
+ * Local version fo the libdrm helper. Added to avoid depending on bleeding
+ * edge version of the library.
+ */
+static int
+local_drmIsMaster(int fd)
+{
+   /* Detect master by attempting something that requires master.
+    *
+    * Authenticating magic tokens requires master and 0 is an
+    * internal kernel detail which we could use. Attempting this on
+    * a master fd would fail therefore fail with EINVAL because 0
+    * is invalid.
+    *
+    * A non-master fd will fail with EACCES, as the kernel checks
+    * for master before attempting to do anything else.
+    *
+    * Since we don't want to leak implementation details, use
+    * EACCES.
+    */
+   return drmAuthMagic(fd, 0) != -EACCES;
+}
+
 VkResult
 wsi_display_init_wsi(struct wsi_device *wsi_device,
                      const VkAllocationCallbacks *alloc,
@@ -1818,6 +1883,9 @@ wsi_display_init_wsi(struct wsi_device *wsi_device,
    }
 
    wsi->fd = display_fd;
+   if (wsi->fd != -1 && !local_drmIsMaster(wsi->fd))
+      wsi->fd = -1;
+
    wsi->alloc = alloc;
 
    list_inithead(&wsi->connectors);