close(device->render_fd);
if (device->display_fd >= 0)
close(device->display_fd);
- if (device->master_fd >= 0)
- close(device->master_fd);
free(device->name);
return MIN2(heap_size, heap_used + heap_available);
}
-#if !using_v3d_simulator
-#ifdef VK_USE_PLATFORM_XCB_KHR
-static int
-create_display_fd_xcb(VkIcdSurfaceBase *surface)
-{
- int fd = -1;
-
- xcb_connection_t *conn;
- xcb_dri3_open_reply_t *reply = NULL;
- 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;
-
- const xcb_setup_t *setup = xcb_get_setup(conn);
- xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup);
- xcb_screen_t *screen = iter.data;
-
- xcb_dri3_open_cookie_t cookie;
- cookie = xcb_dri3_open(conn, screen->root, None);
- reply = xcb_dri3_open_reply(conn, cookie, NULL);
- if (!reply)
- goto finish;
-
- if (reply->nfd != 1)
- goto finish;
-
- fd = xcb_dri3_open_reply_fds(conn, reply)[0];
- fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
-
-finish:
- if (!surface)
- xcb_disconnect(conn);
- if (reply)
- free(reply);
-
- return fd;
-}
-#endif
-
-#ifdef VK_USE_PLATFORM_WAYLAND_KHR
-struct v3dv_wayland_info {
- struct wl_drm *wl_drm;
- int fd;
- bool is_set;
- bool authenticated;
-};
-
-static void
-v3dv_drm_handle_device(void *data, struct wl_drm *drm, const char *device)
-{
- struct v3dv_wayland_info *info = data;
- info->fd = open(device, O_RDWR | O_CLOEXEC);
- info->is_set = info->fd != -1;
- if (!info->is_set) {
- fprintf(stderr, "v3dv_drm_handle_device: could not open %s (%s)\n",
- device, strerror(errno));
- return;
- }
-
- drm_magic_t magic;
- if (drmGetMagic(info->fd, &magic)) {
- fprintf(stderr, "v3dv_drm_handle_device: drmGetMagic failed\n");
- close(info->fd);
- info->fd = -1;
- info->is_set = false;
- return;
- }
- wl_drm_authenticate(info->wl_drm, magic);
-}
-
-static void
-v3dv_drm_handle_format(void *data, struct wl_drm *drm, uint32_t format)
-{
-}
-
-static void
-v3dv_drm_handle_authenticated(void *data, struct wl_drm *drm)
-{
- struct v3dv_wayland_info *info = data;
- info->authenticated = true;
-}
-
-static void
-v3dv_drm_handle_capabilities(void *data, struct wl_drm *drm, uint32_t value)
-{
-}
-
-struct wl_drm_listener v3dv_drm_listener = {
- .device = v3dv_drm_handle_device,
- .format = v3dv_drm_handle_format,
- .authenticated = v3dv_drm_handle_authenticated,
- .capabilities = v3dv_drm_handle_capabilities
-};
-
-static void
-v3dv_registry_global(void *data,
- struct wl_registry *registry,
- uint32_t name,
- const char *interface,
- uint32_t version)
-{
- struct v3dv_wayland_info *info = data;
- if (strcmp(interface, wl_drm_interface.name) == 0) {
- info->wl_drm = wl_registry_bind(registry, name, &wl_drm_interface,
- MIN2(version, 2));
- wl_drm_add_listener(info->wl_drm, &v3dv_drm_listener, data);
- };
-}
-
-static void
-v3dv_registry_global_remove_cb(void *data,
- struct wl_registry *registry,
- uint32_t name)
-{
-}
-
-static int
-create_display_fd_wayland(VkIcdSurfaceBase *surface)
-{
- struct wl_display *display;
- struct wl_registry *registry = NULL;
-
- struct v3dv_wayland_info info = {
- .wl_drm = NULL,
- .fd = -1,
- .is_set = false,
- .authenticated = false
- };
-
- if (surface)
- display = ((VkIcdSurfaceWayland *) surface)->display;
- else
- display = wl_display_connect(NULL);
-
- if (!display)
- return -1;
-
- registry = wl_display_get_registry(display);
- if (!registry) {
- if (!surface)
- wl_display_disconnect(display);
- return -1;
- }
-
- static const struct wl_registry_listener registry_listener = {
- v3dv_registry_global,
- v3dv_registry_global_remove_cb
- };
- wl_registry_add_listener(registry, ®istry_listener, &info);
-
- wl_display_roundtrip(display); /* For the registry advertisement */
- wl_display_roundtrip(display); /* For the DRM device event */
- wl_display_roundtrip(display); /* For the authentication event */
-
- wl_drm_destroy(info.wl_drm);
- wl_registry_destroy(registry);
-
- if (!surface)
- wl_display_disconnect(display);
-
- if (!info.is_set)
- return -1;
-
- if (!info.authenticated)
- return -1;
-
- return info.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_physical_device *pdevice)
-{
-#ifdef VK_USE_PLATFORM_WAYLAND_KHR
- pdevice->display_fd = create_display_fd_wayland(NULL);
-#endif
-
-#ifdef VK_USE_PLATFORM_XCB_KHR
- if (pdevice->display_fd == -1)
- 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_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_WAYLAND_KHR
- if (surface->platform == VK_ICD_WSI_PLATFORM_WAYLAND)
- pdevice->display_fd = create_display_fd_wayland(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_physical_device *pdevice,
- VkIcdSurfaceBase *surface)
-{
- VkResult result = VK_SUCCESS;
- mtx_lock(&pdevice->mutex);
-
- if (pdevice->display_fd != -1)
- goto done;
-
- /* 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
- if (surface)
- acquire_display_device_surface(pdevice, surface);
- else
- acquire_display_device_no_surface(pdevice);
-
- if (pdevice->display_fd == -1)
- result = VK_ERROR_INITIALIZATION_FAILED;
-#endif
-
-done:
- mtx_unlock(&pdevice->mutex);
- return result;
-}
-
static bool
v3d_has_feature(struct v3dv_physical_device *device, enum drm_v3d_param feature)
{
drmDevicePtr display_device)
{
VkResult result = VK_SUCCESS;
- int32_t master_fd = -1;
+ int32_t display_fd = -1;
int32_t render_fd = -1;
struct v3dv_physical_device *device =
#endif
if (instance->vk.enabled_extensions.KHR_display ||
+ instance->vk.enabled_extensions.KHR_xcb_surface ||
+ instance->vk.enabled_extensions.KHR_xlib_surface ||
+ instance->vk.enabled_extensions.KHR_wayland_surface ||
instance->vk.enabled_extensions.EXT_acquire_drm_display) {
#if !using_v3d_simulator
/* Open the primary node on the vc4 display device */
assert(display_device);
- master_fd = open(primary_path, O_RDWR | O_CLOEXEC);
+ display_fd = open(primary_path, O_RDWR | O_CLOEXEC);
#else
/* There is only one device with primary and render nodes.
* Open its primary node.
*/
- master_fd = open(primary_path, O_RDWR | O_CLOEXEC);
+ display_fd = open(primary_path, O_RDWR | O_CLOEXEC);
#endif
}
#endif
device->render_fd = render_fd; /* The v3d render node */
- device->display_fd = -1; /* Authenticated vc4 primary node */
- device->master_fd = master_fd; /* Master vc4 primary node */
+ device->display_fd = display_fd; /* Master vc4 primary node */
if (!v3d_get_device_info(device->render_fd, &device->devinfo, &v3dv_ioctl)) {
result = vk_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,
if (render_fd >= 0)
close(render_fd);
- if (master_fd >= 0)
- close(master_fd);
+ if (display_fd >= 0)
+ close(display_fd);
return result;
}
#if using_v3d_simulator
return device_alloc(device, mem, size);
#else
- /* If we are allocating for WSI we should have a swapchain and thus,
- * we should've initialized the display device. However, Zink doesn't
- * use swapchains, so in that case we can get here without acquiring the
- * display device and we need to do it now.
- */
VkResult result;
struct v3dv_physical_device *pdevice = device->pdevice;
- if (unlikely(pdevice->display_fd < 0)) {
- result = v3dv_physical_device_acquire_display(pdevice, NULL);
- if (result != VK_SUCCESS)
- return result;
- }
assert(pdevice->display_fd != -1);
mem->is_for_wsi = true;
*/
#include "v3dv_private.h"
-#include "drm-uapi/drm_fourcc.h"
-#include "wsi_common_entrypoints.h"
#include "vk_util.h"
#include "wsi_common.h"
#include "wsi_common_drm.h"
v3dv_wsi_can_present_on_device(VkPhysicalDevice _pdevice, int fd)
{
V3DV_FROM_HANDLE(v3dv_physical_device, pdevice, _pdevice);
-
- /* There are some instances with direct display extensions where this may be
- * called before we have ever tried to create a swapchain, and therefore,
- * before we have ever tried to acquire the display device, in which case we
- * have to do it now.
- */
- if (unlikely(pdevice->display_fd < 0 && pdevice->master_fd >= 0)) {
- VkResult result =
- v3dv_physical_device_acquire_display(pdevice, NULL);
- if (result != VK_SUCCESS)
- return false;
- }
-
+ assert(pdevice->display_fd != -1);
return wsi_common_drm_devices_equal(fd, pdevice->display_fd);
}
v3dv_physical_device_to_handle(physical_device),
v3dv_wsi_proc_addr,
&physical_device->vk.instance->alloc,
- physical_device->master_fd, NULL,
+ physical_device->display_fd, NULL,
&(struct wsi_device_options){.sw_device = false});
if (result != VK_SUCCESS)
&physical_device->vk.instance->alloc);
}
-static void
-constraint_surface_capabilities(VkSurfaceCapabilitiesKHR *caps)
-{
- /* Our display pipeline requires that images are linear, so we cannot
- * ensure that our swapchain images can be sampled. If we are running under
- * a compositor in windowed mode, the DRM modifier negotiation should
- * probably end up selecting an UIF layout for the swapchain images but it
- * may still choose linear and send images directly for scanout if the
- * surface is in fullscreen mode for example. If we are not running under
- * a compositor, then we would always need them to be linear anyway.
- */
- caps->supportedUsageFlags &= ~VK_IMAGE_USAGE_SAMPLED_BIT;
-}
-
-VKAPI_ATTR VkResult VKAPI_CALL
-v3dv_GetPhysicalDeviceSurfaceCapabilitiesKHR(
- VkPhysicalDevice physicalDevice,
- VkSurfaceKHR surface,
- VkSurfaceCapabilitiesKHR* pSurfaceCapabilities)
-{
- VkResult result;
- result = wsi_GetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice,
- surface,
- pSurfaceCapabilities);
- constraint_surface_capabilities(pSurfaceCapabilities);
- return result;
-}
-
-VKAPI_ATTR VkResult VKAPI_CALL
-v3dv_GetPhysicalDeviceSurfaceCapabilities2KHR(
- VkPhysicalDevice physicalDevice,
- const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
- VkSurfaceCapabilities2KHR* pSurfaceCapabilities)
-{
- VkResult result;
- result = wsi_GetPhysicalDeviceSurfaceCapabilities2KHR(physicalDevice,
- pSurfaceInfo,
- pSurfaceCapabilities);
- constraint_surface_capabilities(&pSurfaceCapabilities->surfaceCapabilities);
- return result;
-}
-
-VKAPI_ATTR VkResult VKAPI_CALL
-v3dv_CreateSwapchainKHR(
- VkDevice _device,
- const VkSwapchainCreateInfoKHR* pCreateInfo,
- const VkAllocationCallbacks* pAllocator,
- VkSwapchainKHR* pSwapchain)
-{
- V3DV_FROM_HANDLE(v3dv_device, device, _device);
- struct v3dv_physical_device *pdevice = device->pdevice;
-
- ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pCreateInfo->surface);
- VkResult result =
- v3dv_physical_device_acquire_display(pdevice, surface);
- if (result != VK_SUCCESS)
- return result;
-
- return wsi_CreateSwapchainKHR(_device, pCreateInfo, pAllocator, pSwapchain);
-}
-
struct v3dv_image *
v3dv_wsi_get_image_from_swapchain(VkSwapchainKHR swapchain, uint32_t index)
{