v3dv: VK_KHR_display extension support
authorSteven Houston <steven@shouston.net>
Wed, 4 Nov 2020 17:45:10 +0000 (17:45 +0000)
committerMarge Bot <eric+marge@anholt.net>
Wed, 11 Nov 2020 08:36:05 +0000 (08:36 +0000)
When VK_KHR_display is enabled it needs to open the primary
node on the vc4/vc5 display device, so pass it to
physical_device_init().
Extension functions call through to the wsi_common_display.c
implementations.

v2: Follow Mesa conventions for comments and char *
    Refer to vc4 display device in comments.
v3: Added Copyright © 2020 Raspberry Pi
v4: Test device has primary node when using simulator.
v5: Assert that we have a primary device. Fix trailing blank space.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/3692
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7515>

src/broadcom/vulkan/meson.build
src/broadcom/vulkan/v3dv_device.c
src/broadcom/vulkan/v3dv_wsi_display.c [new file with mode: 0644]

index 29fc4cc..58f4bce 100644 (file)
@@ -105,6 +105,11 @@ if with_platform_x11
   libv3dv_files += files('v3dv_wsi_x11.c')
 endif
 
+if system_has_kms_drm and not with_platform_android
+ v3dv_flags += '-DVK_USE_PLATFORM_DISPLAY_KHR'
+ libv3dv_files += files('v3dv_wsi_display.c')
+endif
+
 libvulkan_broadcom = shared_library(
   'vulkan_broadcom',
   [libv3dv_files, v3dv_entrypoints, v3dv_extensions_c, v3dv_extensions_h, sha1_h],
index 3e1078d..36031ca 100644 (file)
@@ -446,7 +446,8 @@ init_uuids(struct v3dv_physical_device *device)
 static VkResult
 physical_device_init(struct v3dv_physical_device *device,
                      struct v3dv_instance *instance,
-                     drmDevicePtr drm_device)
+                     drmDevicePtr drm_render_device,
+                     drmDevicePtr drm_primary_device)
 {
    VkResult result = VK_SUCCESS;
    int32_t display_fd = -1;
@@ -454,7 +455,7 @@ physical_device_init(struct v3dv_physical_device *device,
    device->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
    device->instance = instance;
 
-   const char *path = drm_device->nodes[DRM_NODE_RENDER];
+   const char *path = drm_render_device->nodes[DRM_NODE_RENDER];
    int32_t render_fd = open(path, O_RDWR | O_CLOEXEC);
    if (render_fd < 0)
       return vk_error(instance, VK_ERROR_INCOMPATIBLE_DRIVER);
@@ -463,23 +464,37 @@ physical_device_init(struct v3dv_physical_device *device,
     * device so we can allocate winsys BOs for the v3d core to render into.
     */
 #if !using_v3d_simulator
+   if (instance->enabled_extensions.KHR_display) {
+      /* Open the primary node on the vc4 display device */
+      assert(drm_primary_device);
+      const char *primary_path = drm_primary_device->nodes[DRM_NODE_PRIMARY];
+      display_fd = open(primary_path, O_RDWR | O_CLOEXEC);
+   }
+
 #ifdef VK_USE_PLATFORM_XCB_KHR
-   display_fd = create_display_fd_xcb();
+   if (display_fd == -1)
+      display_fd = create_display_fd_xcb();
 #endif
 
    if (display_fd == -1) {
       result = VK_ERROR_INCOMPATIBLE_DRIVER;
       goto fail;
    }
+#else
+   /* using_v3d_simulator */
+   if (instance->enabled_extensions.KHR_display) {
+      /* There is only one device with primary and render nodes.
+       * Open its primary node.
+       */
+      const char *primary_path = drm_render_device->nodes[DRM_NODE_PRIMARY];
+      display_fd = open(primary_path, O_RDWR | O_CLOEXEC);
+   }
+   device->sim_file = v3d_simulator_init(render_fd);
 #endif
 
    device->render_fd = render_fd;       /* The v3d render node  */
    device->display_fd = display_fd;    /* The vc4 primary node */
 
-#if using_v3d_simulator
-   device->sim_file = v3d_simulator_init(device->render_fd);
-#endif
-
    if (!v3d_get_device_info(device->render_fd, &device->devinfo, &v3dv_ioctl)) {
       result = VK_ERROR_INCOMPATIBLE_DRIVER;
       goto fail;
@@ -565,11 +580,12 @@ enumerate_devices(struct v3dv_instance *instance)
    for (unsigned i = 0; i < (unsigned)max_devices; i++) {
 #if using_v3d_simulator
       /* In the simulator, we look for an Intel render node */
-      if (devices[i]->available_nodes & 1 << DRM_NODE_RENDER &&
-          devices[i]->bustype == DRM_BUS_PCI &&
-          devices[i]->deviceinfo.pci->vendor_id == 0x8086) {
+      const int required_nodes = (1 << DRM_NODE_RENDER) | (1 << DRM_NODE_PRIMARY);
+      if ((devices[i]->available_nodes & required_nodes) == required_nodes &&
+           devices[i]->bustype == DRM_BUS_PCI &&
+           devices[i]->deviceinfo.pci->vendor_id == 0x8086) {
          result = physical_device_init(&instance->physicalDevice, instance,
-                                       devices[i]);
+                                       devices[i], NULL);
          if (result != VK_ERROR_INCOMPATIBLE_DRIVER)
             break;
       }
@@ -614,7 +630,7 @@ enumerate_devices(struct v3dv_instance *instance)
       result = VK_ERROR_INCOMPATIBLE_DRIVER;
    else
       result = physical_device_init(&instance->physicalDevice, instance,
-                                    devices[v3d_idx]);
+                                    devices[v3d_idx], devices[vc4_idx]);
 #endif
 
    drmFreeDevices(devices, max_devices);
diff --git a/src/broadcom/vulkan/v3dv_wsi_display.c b/src/broadcom/vulkan/v3dv_wsi_display.c
new file mode 100644 (file)
index 0000000..2e43a5f
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright © 2020 Raspberry Pi
+ * based on KHR_display extension code:
+ * Copyright © 2017 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+#include "v3dv_private.h"
+#include "wsi_common_display.h"
+
+VkResult
+v3dv_GetPhysicalDeviceDisplayPropertiesKHR(VkPhysicalDevice physical_device,
+                                           uint32_t *property_count,
+                                           VkDisplayPropertiesKHR *properties)
+{
+   V3DV_FROM_HANDLE(v3dv_physical_device, pdevice, physical_device);
+
+   return wsi_display_get_physical_device_display_properties(
+      physical_device,
+      &pdevice->wsi_device,
+      property_count,
+      properties);
+}
+
+VkResult
+v3dv_GetPhysicalDeviceDisplayPlanePropertiesKHR(
+   VkPhysicalDevice physical_device,
+   uint32_t *property_count,
+   VkDisplayPlanePropertiesKHR *properties)
+{
+   V3DV_FROM_HANDLE(v3dv_physical_device, pdevice, physical_device);
+
+   return wsi_display_get_physical_device_display_plane_properties(
+      physical_device,
+      &pdevice->wsi_device,
+      property_count,
+      properties);
+}
+
+VkResult
+v3dv_GetDisplayPlaneSupportedDisplaysKHR(VkPhysicalDevice physical_device,
+                                         uint32_t plane_index,
+                                         uint32_t *display_count,
+                                         VkDisplayKHR *displays)
+{
+   V3DV_FROM_HANDLE(v3dv_physical_device, pdevice, physical_device);
+
+   return wsi_display_get_display_plane_supported_displays(
+      physical_device,
+      &pdevice->wsi_device,
+      plane_index,
+      display_count,
+      displays);
+}
+
+VkResult
+v3dv_GetDisplayModePropertiesKHR(VkPhysicalDevice physical_device,
+                                 VkDisplayKHR display,
+                                 uint32_t *property_count,
+                                 VkDisplayModePropertiesKHR *properties)
+{
+   V3DV_FROM_HANDLE(v3dv_physical_device, pdevice, physical_device);
+
+   return wsi_display_get_display_mode_properties(physical_device,
+                                                  &pdevice->wsi_device,
+                                                  display,
+                                                  property_count,
+                                                  properties);
+}
+
+VkResult
+v3dv_CreateDisplayModeKHR(VkPhysicalDevice physical_device,
+                          VkDisplayKHR display,
+                          const VkDisplayModeCreateInfoKHR *create_info,
+                          const VkAllocationCallbacks *allocator,
+                          VkDisplayModeKHR *mode)
+{
+   V3DV_FROM_HANDLE(v3dv_physical_device, pdevice, physical_device);
+
+   return wsi_display_create_display_mode(physical_device,
+                                          &pdevice->wsi_device,
+                                          display,
+                                          create_info,
+                                          allocator,
+                                          mode);
+}
+
+VkResult
+v3dv_GetDisplayPlaneCapabilitiesKHR(VkPhysicalDevice physical_device,
+                                    VkDisplayModeKHR mode_khr,
+                                    uint32_t plane_index,
+                                    VkDisplayPlaneCapabilitiesKHR *capabilities)
+{
+   V3DV_FROM_HANDLE(v3dv_physical_device, pdevice, physical_device);
+
+   return wsi_get_display_plane_capabilities(physical_device,
+                                             &pdevice->wsi_device,
+                                             mode_khr,
+                                             plane_index,
+                                             capabilities);
+}
+
+VkResult
+v3dv_CreateDisplayPlaneSurfaceKHR(
+    VkInstance _instance,
+    const VkDisplaySurfaceCreateInfoKHR *create_info,
+    const VkAllocationCallbacks *allocator,
+    VkSurfaceKHR *surface)
+{
+   V3DV_FROM_HANDLE(v3dv_instance, instance, _instance);
+   const VkAllocationCallbacks *alloc;
+
+   if (allocator)
+      alloc = allocator;
+   else
+      alloc = &instance->alloc;
+
+   return wsi_create_display_surface(_instance, alloc,
+                                     create_info, surface);
+}