diff --git a/include/vulkan/vk_platform.h b/include/vulkan/vk_platform.h index 71858453fa2b384630faabd839e1d3f743192376..2e2133c57123f5c4af8a2751f662fe4716caebaf 100644 --- a/include/vulkan/vk_platform.h +++ b/include/vulkan/vk_platform.h @@ -77,6 +77,12 @@ extern "C" #endif #endif // !defined(VK_NO_STDINT_H) +#ifdef VK_USE_PLATFORM_WAYLAND_KHR + // Forward declared for VK_EXT_acquire_wl_display + struct zwp_drm_lease_device_v1; + struct zwp_drm_lease_connector_v1; +#endif // VK_USE_PLATFORM_WAYLAND_KHR + #ifdef __cplusplus } // extern "C" #endif // __cplusplus diff --git a/include/vulkan/vulkan_wayland.h b/include/vulkan/vulkan_wayland.h index f7b307e519be8f97ccd76e7fd79cbb10d498229b..f2120c733540fc2385a741818aeccd709fef7c5d 100644 --- a/include/vulkan/vulkan_wayland.h +++ b/include/vulkan/vulkan_wayland.h @@ -47,6 +47,26 @@ VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWaylandPresentationSupportKHR( struct wl_display* display); #endif + +#define VK_EXT_acquire_wl_display 1 +#define VK_EXT_ACQUIRE_WL_DISPLAY_SPEC_VERSION 1 +#define VK_EXT_ACQUIRE_WL_DISPLAY_EXTENSION_NAME "VK_EXT_acquire_wl_display" +typedef struct VkWaylandLeaseConnectorEXT { + struct zwp_drm_lease_connector_v1* pConnector; + VkDisplayKHR pDisplay; +} VkWaylandLeaseConnectorEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkAcquireWaylandDisplayEXT)(VkPhysicalDevice physicalDevice, struct wl_display* display, struct zwp_drm_lease_device_v1* leaseDevice, uint32_t pConnectorCount, VkWaylandLeaseConnectorEXT* pConnectors); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkAcquireWaylandDisplayEXT( + VkPhysicalDevice physicalDevice, + struct wl_display* display, + struct zwp_drm_lease_device_v1* leaseDevice, + uint32_t pConnectorCount, + VkWaylandLeaseConnectorEXT* pConnectors); +#endif + #ifdef __cplusplus } #endif diff --git a/meson.build b/meson.build index 827651f088f6d4ffd0a3f07f2d847cc84aa7e4cb..5f01fdf6dfa9cb841c790f32639c654037fd7df3 100644 --- a/meson.build +++ b/meson.build @@ -419,6 +419,13 @@ else with_xlib_lease = _xlib_lease == 'enabled' endif +_wl_lease = get_option('wl-lease') +if _wl_lease == 'auto' + with_wl_lease = with_platform_wayland and system_has_kms_drm +else + with_wl_lease = _wl_lease == 'enabled' +endif + _egl = get_option('egl') if _egl == 'true' _egl = 'enabled' diff --git a/meson_options.txt b/meson_options.txt index 599a2b3fd898e3b6e8bbb4aa52e8be140e172bcc..3715dc937dc9e8fe558ceb9a4078b5177720654e 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -420,6 +420,13 @@ option( choices : ['auto', 'true', 'false', 'enabled', 'disabled'], description : 'Enable VK_EXT_acquire_xlib_display.' ) +option( + 'wl-lease', + type : 'combo', + value : 'auto', + choices : ['auto', 'enabled', 'disabled'], + description : 'Enable VK_EXT_acquire_wl_display.' +) option( 'glx-direct', type : 'boolean', diff --git a/src/amd/vulkan/radv_extensions.py b/src/amd/vulkan/radv_extensions.py index 3f6373469095b36ff36b281a19113a074be6fca9..7a2fbdc6d4a1d98c9cd6c65b821f83b8ff106c3e 100644 --- a/src/amd/vulkan/radv_extensions.py +++ b/src/amd/vulkan/radv_extensions.py @@ -121,6 +121,7 @@ EXTENSIONS = [ Extension('VK_KHR_xlib_surface', 6, 'VK_USE_PLATFORM_XLIB_KHR'), Extension('VK_KHR_zero_initialize_workgroup_memory', 1, True), Extension('VK_EXT_4444_formats', 1, True), + Extension('VK_EXT_acquire_wl_display', 1, 'VK_USE_PLATFORM_WAYLAND_KHR'), Extension('VK_EXT_acquire_xlib_display', 1, 'VK_USE_PLATFORM_XLIB_XRANDR_EXT'), Extension('VK_EXT_buffer_device_address', 2, True), Extension('VK_EXT_calibrated_timestamps', 1, 'RADV_SUPPORT_CALIBRATED_TIMESTAMPS'), diff --git a/src/amd/vulkan/radv_wsi_display.c b/src/amd/vulkan/radv_wsi_display.c index 64c7acd373441dffc21815979160f233cea22d1c..e3256834fb25381d68f812ab70b230beffdd324a 100644 --- a/src/amd/vulkan/radv_wsi_display.c +++ b/src/amd/vulkan/radv_wsi_display.c @@ -367,3 +367,25 @@ radv_GetSwapchainCounterEXT(VkDevice _device, value); } +#ifdef VK_USE_PLATFORM_WAYLAND_KHR + +/* VK_EXT_acquire_wl_display */ + +VkResult +radv_AcquireWaylandDisplayEXT(VkPhysicalDevice physical_device, + struct wl_display* display, + struct zwp_drm_lease_device_v1* lease_device, + uint32_t nConnectors, + VkWaylandLeaseConnectorEXT* pConnectors) +{ + RADV_FROM_HANDLE(radv_physical_device, pdevice, physical_device); + + return wsi_acquire_wl_display(physical_device, + &pdevice->wsi_device, + display, + lease_device, + nConnectors, + pConnectors); +} + +#endif /* VK_USE_PLATFORM_WAYLAND_KHR */ diff --git a/src/vulkan/meson.build b/src/vulkan/meson.build index 22610a5493f519fc18dc954edbf18e290b2a27bb..5fe9909b0a119efa5cbb51ee58fb091a77727475 100644 --- a/src/vulkan/meson.build +++ b/src/vulkan/meson.build @@ -42,7 +42,7 @@ if with_platform_x11 vulkan_wsi_list += ['xcb', 'x11'] endif if with_platform_wayland - vulkan_wsi_args += ['-DVK_USE_PLATFORM_WAYLAND_KHR'] + vulkan_wsi_args += ['-DVK_USE_PLATFORM_WAYLAND_KHR', '-DVK_USE_PLATFORM_WAYLAND'] vulkan_wsi_deps += dep_wayland_client vulkan_wsi_list += ['wayland'] endif @@ -57,7 +57,6 @@ if with_xlib_lease vulkan_wsi_list += ['xlib_xrandr'] endif - subdir('util') subdir('wsi') if with_vulkan_overlay_layer diff --git a/src/vulkan/registry/vk.xml b/src/vulkan/registry/vk.xml index fa31b42f0dc90dd64ea7b0162cbc68c76949427f..6a248fbbccf804460d57c5b610210f84dc1287f2 100644 --- a/src/vulkan/registry/vk.xml +++ b/src/vulkan/registry/vk.xml @@ -108,6 +108,8 @@ branch of the member gitlab server. + + @@ -5148,6 +5150,10 @@ typedef void CAMetalLayer; uint32_t mutableDescriptorTypeListCount const VkMutableDescriptorTypeListVALVE* pMutableDescriptorTypeLists + + struct zwp_drm_lease_connector_v1* pConnector + VkDisplayKHR pDisplay + Vulkan enumerant (token) definitions @@ -9306,6 +9312,14 @@ typedef void CAMetalLayer; const uint32_t* pMaxPrimitiveCounts VkAccelerationStructureBuildSizesInfoKHR* pSizeInfo + + VkResult vkAcquireWaylandDisplayEXT + VkPhysicalDevice physicalDevice + struct wl_display* display + struct zwp_drm_lease_device_v1* leaseDevice + uint32_t pConnectorCount + VkWaylandLeaseConnectorEXT* pConnectors + @@ -13904,10 +13918,11 @@ typedef void CAMetalLayer; - + - - + + + diff --git a/src/vulkan/wsi/drm-lease-unstable-v1.xml b/src/vulkan/wsi/drm-lease-unstable-v1.xml new file mode 100644 index 0000000000000000000000000000000000000000..62641c2194295ed54a27d65827ea2534dcc3dda5 --- /dev/null +++ b/src/vulkan/wsi/drm-lease-unstable-v1.xml @@ -0,0 +1,260 @@ + + + + Copyright © 2018 NXP + Copyright © 2019 Status Research & Development GmbH. + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice (including the next + paragraph) shall be included in all copies or substantial portions of the + Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + + + + This protocol is used by Wayland compositors which act as Direct + Renderering Manager (DRM) masters to lease DRM resources to Wayland + clients. Once leased, the compositor will not use the leased resources + until the lease is revoked or the client closes the file descriptor. The + compositor will advertise one zwp_drm_lease_device_v1 for each DRM node + which has resources available for leasing. + + The lease device is used to advertise connectors which are available for + leasing, and by the client to negotiate a lease request. + + Warning! The protocol described in this file is experimental and + backward incompatible changes may be made. Backward compatible changes + may be added together with the corresponding interface version bump. + Backward incompatible changes are done by bumping the version number in + the protocol and interface names and resetting the interface version. + Once the protocol is to be declared stable, the 'z' prefix and the + version number in the protocol and interface names are removed and the + interface version number is reset. + + + + + Creates a lease request object. + + See the documentation for zwp_drm_lease_request_v1 for details. + + + + + + + Indicates the client no longer wishes to receive connector events. The + compositor may still send connector events until it sends the finish + event, however. + The client must not send any requests after this one, doing so will + raise a wl_display error. + + + + + + The compositor will send this event when the zwp_drm_lease_device_v1 + global is bound, although there are no guarantees as to how long this + takes - the compositor might need to wait until regaining DRM master. + The included fd is a non-master DRM file descriptor opened for this + device and the compositor must not authenticate it. + The purpose of this event is to give the client the ability to + query DRM and discover information which may help them pick the + appropriate DRM device or select the appropriate connectors therein. + + + + + + + The compositor will use this event to advertise connectors available for + lease by clients. Clients are guaranteed that no disconnected + connectors will be advertised. This object may be passed into a lease + request to indicate the client would like to lease that connector, see + zwp_drm_lease_request_v1.request_connector for details. + + When this global is bound, the compositor will send all connectors + available for lease, but may send additional connectors at any time. + + + + + + + This event indicates that the compositor is done sending connector + events. The compositor will destroy this object immediately after + sending this event, and it will become invalid. The client should + release any resources associated with this device after receiving this + event. + + + + + + + Represents a DRM connector which is available for lease. These objects are + created via zwp_drm_lease_device_v1.connector, and should be passed into + lease requests via zwp_drm_lease_request_v1.request_connector. + + + + + The compositor sends this event once the connector is created to + indicate the name of this connector. This will not change for the + duration of the Wayland session, but is not guaranteed to be consistent + between sessions. + + If the compositor also supports zxdg_output_manager_v1 and this + connector corresponds to a zxdg_output_v1, this name will match the + name of this zxdg_output_v1 object. + + + + + + + The compositor sends this event once the connector is created to provide + a human-readable description for this connector, which may be presented + to the user. + + + + + + + The compositor will send this event to indicate the DRM ID which + represents the underlying connector that is being offered. Note that + the final lease may include additional object IDs, such as CRTCs and + planes. + + + + + + + Sent to indicate that the compositor will no longer honor requests for + DRM leases which include this connector. The client may still issue a + lease request including this connector, but the compositor will send + zwp_drm_lease_v1.finished without issuing a lease fd. + Compositors are encouraged to send this event when it loses access to + connector because of hot-unplug or because of losing DRM master as well + as when the connector gets leased to a client. + + + + + + The client may send this request to indicate that it will not issue a + lease request for this connector. Clients are encouraged to send this + after receiving the "withdrawn" request so that the server can release + the resources associated with this connector offer. + Destroyed connectors will be removed from lease requests. Existing + leases will however not be affected. + + + + + + + A client that wishes to lease DRM resources will attach the list of + connectors advertised with zwp_drm_lease_device_v1.connector that they + wish to lease, then use zwp_drm_lease_request_v1.submit to submit the + request. + + + + + + + + + Indicates that the client will no longer use this lease request. + + + + + + Indicates that the client would like to lease the given connector. + This is only used as a suggestion, the compositor may choose to + include any resources in the lease it issues, or change the set of + leased resources at any time. Compositors are however encouraged to + include the requested connector and other resources necessary + to drive the connected output in the lease. + + Requested connectors that were created from a different lease device + than this lease request as well as requests for adding connectors that + already are requested will be ignored by the compositor. + + + + + + + Submits the lease request and creates a new zwp_drm_lease_v1 object. + After calling submit, issuing any other request than destroy will cause + the submitted_lease error to be raised. + The compositor doesn't make any guarantees about the events of the + lease object, clients cannot expect an immediate response. + + + + + + + + A DRM lease object is used to transfer the DRM file descriptor to the + client and manage the lifetime of the lease. + + + + + This event returns a file descriptor suitable for use with DRM-related + ioctls. The client should use drmModeGetLease to enumerate the DRM + objects which have been leased to them. If the compositor cannot or + will not grant a lease for the requested connectors, it will not send + this event, instead sending the finished event. + + The compositor will only send this event at most once during this + objects lifetime. + + + + + + + When the compositor revokes the lease, it will issue this event to + notify clients of the change. If the client requires a new lease, they + should destroy this object and submit a new lease request. The + compositor will send no further events for this object after sending + the finish event. + Compositors should revoke the lease when any of the leased resources + become unavailable, namely when a hot-unplug occurs or when the + compositor loses DRM master. + + + + + + The client should send this to indicate that it no longer wishes to use + this lease. The compositor should use drmModeRevokeLease on the + appropriate file descriptor, if necessary. + + + + diff --git a/src/vulkan/wsi/meson.build b/src/vulkan/wsi/meson.build index ca948cefb26ab01b99b0696b68ad6bb2e18115b8..ea06c62fb734fd5cf520f82a4e220c50896c5a0a 100644 --- a/src/vulkan/wsi/meson.build +++ b/src/vulkan/wsi/meson.build @@ -42,6 +42,27 @@ if system_has_kms_drm and not with_platform_android files_vulkan_wsi += files('wsi_common_display.c') endif +if with_wl_lease + drm_lease_unstable_v1_protocol_c = custom_target( + 'drm-lease-unstable-v1-protocol.c', + input : 'drm-lease-unstable-v1.xml', + output : 'drm-lease-unstable-v1-protocol.c', + command : [prog_wl_scanner, wl_scanner_arg, '@INPUT@', '@OUTPUT@'], + ) + + drm_lease_unstable_v1_client_protocol_h = custom_target( + 'linux-dmabuf-unstable-v1-client-protocol.h', + input : 'drm-lease-unstable-v1.xml', + output : 'drm-lease-unstable-v1-client-protocol.h', + command : [prog_wl_scanner, 'client-header', '@INPUT@', '@OUTPUT@'], + ) + + files_vulkan_wsi += [ + drm_lease_unstable_v1_protocol_c, + drm_lease_unstable_v1_client_protocol_h, + ] +endif + libvulkan_wsi = static_library( 'vulkan_wsi', files_vulkan_wsi, diff --git a/src/vulkan/wsi/wsi_common_display.c b/src/vulkan/wsi/wsi_common_display.c index f6eea5906f8c8d3a10f08d84eaffecb33fcbd5e8..cf1af2795375bdad1d2fdff3b4401f1fc7bec2ca 100644 --- a/src/vulkan/wsi/wsi_common_display.c +++ b/src/vulkan/wsi/wsi_common_display.c @@ -37,6 +37,9 @@ #include #include #endif +#ifdef VK_USE_PLATFORM_WAYLAND_KHR +#include "drm-lease-unstable-v1-client-protocol.h" +#endif #include "util/hash_table.h" #include "util/list.h" @@ -83,6 +86,9 @@ typedef struct wsi_display_connector { #ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT xcb_randr_output_t output; #endif +#ifdef VK_USE_PLATFORM_WAYLAND_KHR + struct wlr_drm_lease_v1 *drm_lease; +#endif } wsi_display_connector; struct wsi_display { @@ -2598,3 +2604,91 @@ wsi_get_swapchain_counter(VkDevice device, return VK_SUCCESS; } +#ifdef VK_USE_PLATFORM_WAYLAND_KHR + +static void drm_lease_handle_lease_fd( + void *data, + struct zwp_drm_lease_v1 *zwp_drm_lease_v1, + int32_t leased_fd) +{ + struct wsi_display *wsi = data; + wsi->fd = leased_fd; +} + +static void drm_lease_handle_finished( + void *data, + struct zwp_drm_lease_v1 *zwp_drm_lease_v1) +{ + struct wsi_display *wsi = data; + if (wsi->fd > 0) { + close(wsi->fd); + wsi->fd = -1; + } +} + +static const struct zwp_drm_lease_v1_listener drm_lease_listener = { + drm_lease_handle_lease_fd, + drm_lease_handle_finished, +}; + +/* VK_EXT_acquire_wl_display */ +VkResult +wsi_acquire_wl_display(VkPhysicalDevice physical_device, + struct wsi_device *wsi_device, + struct wl_display *display, + struct zwp_drm_lease_device_v1 *lease_device, + uint32_t connectorsCount, + VkWaylandLeaseConnectorEXT *connectors) +{ + struct wsi_display *wsi = + (struct wsi_display *) wsi_device->wsi[VK_ICD_WSI_PLATFORM_DISPLAY]; + + /* XXX no support for mulitple leases yet */ + if (wsi->fd >= 0) + return VK_ERROR_INITIALIZATION_FAILED; + + /* XXX no support for mulitple connectors yet */ + /* The solution will eventually involve adding a listener to each + * connector, round tripping, and matching EDIDs once the lease is + * granted. */ + if (connectorsCount > 1) + return VK_ERROR_INITIALIZATION_FAILED; + + struct zwp_drm_lease_request_v1 *lease_request = + zwp_drm_lease_device_v1_create_lease_request(lease_device); + for (int i = 0; i < connectorsCount; ++i) { + zwp_drm_lease_request_v1_request_connector(lease_request, + connectors[i].pConnector); + } + + struct zwp_drm_lease_v1 *drm_lease = + zwp_drm_lease_request_v1_submit(lease_request); + zwp_drm_lease_request_v1_destroy(lease_request); + zwp_drm_lease_v1_add_listener(drm_lease, &drm_lease_listener, wsi); + wl_display_roundtrip(display); + + if (wsi->fd < 0) + return VK_ERROR_INITIALIZATION_FAILED; + + int nconn = 0; + drmModeResPtr res = drmModeGetResources(wsi->fd); + drmModeObjectListPtr lease = drmModeGetLease(wsi->fd); + for (uint32_t i = 0; i < res->count_connectors; ++i) { + for (uint32_t j = 0; j < lease->count; ++j) { + if (res->connectors[i] != lease->objects[j]) { + continue; + } + struct wsi_display_connector *connector = + wsi_display_get_connector(wsi_device, res->connectors[i]); + /* TODO: Match EDID with requested connector */ + connectors[nconn].pDisplay = + wsi_display_connector_to_handle(connector); + ++nconn; + } + } + drmModeFreeResources(res); + + return VK_SUCCESS; +} + +#endif /* VK_USE_PLATFORM_WAYLAND_KHR */ diff --git a/src/vulkan/wsi/wsi_common_display.h b/src/vulkan/wsi/wsi_common_display.h index d65517ab941d2642430762433f89938ec7d204d6..de856994c200c4c2d8ae581cf17055b943a08fe6 100644 --- a/src/vulkan/wsi/wsi_common_display.h +++ b/src/vulkan/wsi/wsi_common_display.h @@ -157,4 +157,17 @@ wsi_get_swapchain_counter(VkDevice device, VkSurfaceCounterFlagBitsEXT flag_bits, uint64_t *value); +#ifdef VK_USE_PLATFORM_WAYLAND_KHR + +/* VK_EXT_acquire_wl_display */ +VkResult +wsi_acquire_wl_display(VkPhysicalDevice physical_device, + struct wsi_device *wsi_device, + struct wl_display *display, + struct zwp_drm_lease_device_v1 *lease_device, + uint32_t connectorsCount, + VkWaylandLeaseConnectorEXT *connectors); + +#endif /* VK_USE_PLATFORM_WAYLAND_KHR */ + #endif