v3dv: use VkSurface to retrieve an authenticated display fd
We still need a fallback for the case where the application makes WSI allocations without a surface (Zink), but for the general case, this is the right way to do this, as it would ensure that we use the same display connection that was used to create the surface. Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7631>
This commit is contained in:
parent
0fcd379184
commit
5c305c8e36
|
@ -49,6 +49,7 @@
|
|||
#ifdef VK_USE_PLATFORM_XCB_KHR
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/dri3.h>
|
||||
#include <X11/Xlib-xcb.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_V3D_SIMULATOR
|
||||
|
@ -335,17 +336,23 @@ compute_heap_size()
|
|||
return available_ram;
|
||||
}
|
||||
|
||||
/* When running on the simulator we do everything on a single render node so
|
||||
* we don't need to get an authenticated display fd from the display server.
|
||||
*/
|
||||
#if !using_v3d_simulator
|
||||
#ifdef VK_USE_PLATFORM_XCB_KHR
|
||||
static int
|
||||
create_display_fd_xcb()
|
||||
create_display_fd_xcb(VkIcdSurfaceBase *surface)
|
||||
{
|
||||
int fd = -1;
|
||||
|
||||
xcb_connection_t *conn = xcb_connect(NULL, NULL);
|
||||
xcb_connection_t *conn;
|
||||
if (surface) {
|
||||
if (surface->platform == VK_ICD_WSI_PLATFORM_XLIB)
|
||||
conn = XGetXCBConnection(((VkIcdSurfaceXlib *)surface)->dpy);
|
||||
else
|
||||
conn = ((VkIcdSurfaceXcb *)surface)->connection;
|
||||
} else {
|
||||
conn = xcb_connect(NULL, NULL);
|
||||
}
|
||||
|
||||
if (xcb_connection_has_error(conn))
|
||||
goto finish;
|
||||
|
||||
|
@ -367,6 +374,7 @@ create_display_fd_xcb()
|
|||
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
|
||||
|
||||
finish:
|
||||
if (!surface)
|
||||
xcb_disconnect(conn);
|
||||
if (reply)
|
||||
free(reply);
|
||||
|
@ -374,14 +382,64 @@ finish:
|
|||
return fd;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Acquire an authenticated display fd without a surface reference. This is the
|
||||
* case where the application is making WSI allocations outside the Vulkan
|
||||
* swapchain context (only Zink, for now). Since we lack information about the
|
||||
* underlying surface we just try our best to figure out the correct display
|
||||
* and platform to use. It should work in most cases.
|
||||
*/
|
||||
static void
|
||||
acquire_display_device_no_surface(struct v3dv_instance *instance,
|
||||
struct v3dv_physical_device *pdevice)
|
||||
{
|
||||
#ifdef VK_USE_PLATFORM_XCB_KHR
|
||||
pdevice->display_fd = create_display_fd_xcb(NULL);
|
||||
#endif
|
||||
|
||||
#ifdef VK_USE_PLATFORM_DISPLAY_KHR
|
||||
if (pdevice->display_fd == - 1 && pdevice->master_fd >= 0)
|
||||
pdevice->display_fd = dup(pdevice->master_fd);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Acquire an authenticated display fd from the surface. This is the regular
|
||||
* case where the application is using swapchains to create WSI allocations.
|
||||
* In this case we use the surface information to figure out the correct
|
||||
* display and platform combination.
|
||||
*/
|
||||
static void
|
||||
acquire_display_device_surface(struct v3dv_instance *instance,
|
||||
struct v3dv_physical_device *pdevice,
|
||||
VkIcdSurfaceBase *surface)
|
||||
{
|
||||
/* Mesa will set both of VK_USE_PLATFORM_{XCB,XLIB} when building with
|
||||
* platform X11, so only check for XCB and rely on XCB to get an
|
||||
* authenticated device also for Xlib.
|
||||
*/
|
||||
#ifdef VK_USE_PLATFORM_XCB_KHR
|
||||
if (surface->platform == VK_ICD_WSI_PLATFORM_XCB ||
|
||||
surface->platform == VK_ICD_WSI_PLATFORM_XLIB) {
|
||||
pdevice->display_fd = create_display_fd_xcb(surface);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef VK_USE_PLATFORM_DISPLAY_KHR
|
||||
if (surface->platform == VK_ICD_WSI_PLATFORM_DISPLAY &&
|
||||
pdevice->master_fd >= 0) {
|
||||
pdevice->display_fd = dup(pdevice->master_fd);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif /* !using_v3d_simulator */
|
||||
|
||||
/* Attempts to get an authenticated display fd from the display server that
|
||||
* we can use to allocate BOs for presentable images.
|
||||
*/
|
||||
VkResult
|
||||
v3dv_physical_device_acquire_display(struct v3dv_instance *instance,
|
||||
struct v3dv_physical_device *pdevice)
|
||||
struct v3dv_physical_device *pdevice,
|
||||
VkIcdSurfaceBase *surface)
|
||||
{
|
||||
VkResult result = VK_SUCCESS;
|
||||
mtx_lock(&pdevice->mutex);
|
||||
|
@ -392,43 +450,11 @@ v3dv_physical_device_acquire_display(struct v3dv_instance *instance,
|
|||
/* When running on the simulator we do everything on a single render node so
|
||||
* we don't need to get an authenticated display fd from the display server.
|
||||
*/
|
||||
|
||||
#if !using_v3d_simulator
|
||||
/* Mesa will set both of VK_USE_PLATFORM_{XCB,XLIB} when building with
|
||||
* platform X11, so only check for XCB and rely on XCB to get an
|
||||
* authenticated device also for Xlib.
|
||||
*/
|
||||
#ifdef VK_USE_PLATFORM_XCB_KHR
|
||||
if (instance->enabled_extensions.KHR_xcb_surface ||
|
||||
instance->enabled_extensions.KHR_xlib_surface) {
|
||||
pdevice->display_fd = create_display_fd_xcb();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If we are not running under a compositor and we are doing
|
||||
* direct display we want to make our display_fd be the
|
||||
* master_fd, which shoud be authenticated.
|
||||
*/
|
||||
if (pdevice->display_fd == -1 &&
|
||||
instance->enabled_extensions.KHR_display) {
|
||||
assert(pdevice->master_fd >= 0);
|
||||
pdevice->display_fd = dup(pdevice->master_fd);
|
||||
}
|
||||
|
||||
/* Fallback cases.
|
||||
*
|
||||
* Some applications seem to try and create a swapchain without
|
||||
* the instance extension enables, so if we have not managed to
|
||||
* create a display_fd above, try again without the extension checks
|
||||
* as a last resort.
|
||||
*/
|
||||
#ifdef VK_USE_PLATFORM_XCB_KHR
|
||||
if (pdevice->display_fd == -1)
|
||||
pdevice->display_fd = create_display_fd_xcb();
|
||||
#endif
|
||||
|
||||
if (pdevice->display_fd == -1 && pdevice->master_fd >= 0)
|
||||
pdevice->display_fd = dup(pdevice->master_fd);
|
||||
if (surface)
|
||||
acquire_display_device_surface(instance, pdevice, surface);
|
||||
else
|
||||
acquire_display_device_no_surface(instance, pdevice);
|
||||
|
||||
if (pdevice->display_fd == -1)
|
||||
result = VK_ERROR_INITIALIZATION_FAILED;
|
||||
|
@ -1684,7 +1710,7 @@ device_alloc_for_wsi(struct v3dv_device *device,
|
|||
struct v3dv_instance *instance = device->instance;
|
||||
struct v3dv_physical_device *pdevice = &device->instance->physicalDevice;
|
||||
if (unlikely(pdevice->display_fd < 0)) {
|
||||
result = v3dv_physical_device_acquire_display(instance, pdevice);
|
||||
result = v3dv_physical_device_acquire_display(instance, pdevice, NULL);
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -165,7 +165,8 @@ struct v3dv_physical_device {
|
|||
};
|
||||
|
||||
VkResult v3dv_physical_device_acquire_display(struct v3dv_instance *instance,
|
||||
struct v3dv_physical_device *pdevice);
|
||||
struct v3dv_physical_device *pdevice,
|
||||
VkIcdSurfaceBase *surface);
|
||||
|
||||
VkResult v3dv_wsi_init(struct v3dv_physical_device *physical_device);
|
||||
void v3dv_wsi_finish(struct v3dv_physical_device *physical_device);
|
||||
|
|
|
@ -182,7 +182,9 @@ VkResult v3dv_CreateSwapchainKHR(
|
|||
struct v3dv_physical_device *pdevice = &instance->physicalDevice;
|
||||
struct wsi_device *wsi_device = &pdevice->wsi_device;
|
||||
|
||||
VkResult result = v3dv_physical_device_acquire_display(instance, pdevice);
|
||||
ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pCreateInfo->surface);
|
||||
VkResult result =
|
||||
v3dv_physical_device_acquire_display(instance, pdevice, surface);
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
|
||||
|
|
Loading…
Reference in New Issue