return VK_SUCCESS;
}
+
+VkResult radv_GetPhysicalDevicePresentRectanglesKHR(
+ VkPhysicalDevice physicalDevice,
+ VkSurfaceKHR surface,
+ uint32_t* pRectCount,
+ VkRect2D* pRects)
+{
+ RADV_FROM_HANDLE(radv_physical_device, device, physicalDevice);
+
+ return wsi_common_get_present_rectangles(&device->wsi_device,
+ device->local_fd,
+ surface,
+ pRectCount, pRects);
+}
return VK_SUCCESS;
}
+
+VkResult anv_GetPhysicalDevicePresentRectanglesKHR(
+ VkPhysicalDevice physicalDevice,
+ VkSurfaceKHR surface,
+ uint32_t* pRectCount,
+ VkRect2D* pRects)
+{
+ ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);
+
+ return wsi_common_get_present_rectangles(&device->wsi_device,
+ device->local_fd,
+ surface,
+ pRectCount, pRects);
+}
pPresentModes);
}
+VkResult
+wsi_common_get_present_rectangles(struct wsi_device *wsi_device,
+ int local_fd,
+ VkSurfaceKHR _surface,
+ uint32_t* pRectCount,
+ VkRect2D* pRects)
+{
+ ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
+ struct wsi_interface *iface = wsi_device->wsi[surface->platform];
+
+ return iface->get_present_rectangles(surface, wsi_device, local_fd,
+ pRectCount, pRects);
+}
+
VkResult
wsi_common_create_swapchain(struct wsi_device *wsi,
VkDevice device,
uint32_t *pPresentModeCount,
VkPresentModeKHR *pPresentModes);
+VkResult
+wsi_common_get_present_rectangles(struct wsi_device *wsi,
+ int local_fd,
+ VkSurfaceKHR surface,
+ uint32_t* pRectCount,
+ VkRect2D* pRects);
+
VkResult
wsi_common_get_surface_capabilities2ext(
struct wsi_device *wsi_device,
return vk_outarray_status(&conn);
}
+static bool
+fds_are_same_gpu(int fd1, int fd2)
+{
+ if (fd1 == -1 || fd2 == -1)
+ return false;
+
+ char *fd1_dev = drmGetRenderDeviceNameFromFd(fd1);
+ char *fd2_dev = drmGetRenderDeviceNameFromFd(fd2);
+
+ int ret = strcmp(fd1_dev, fd2_dev);
+
+ free(fd1_dev);
+ free(fd2_dev);
+
+ return ret == 0;
+}
+
+static VkResult
+wsi_display_surface_get_present_rectangles(VkIcdSurfaceBase *surface_base,
+ struct wsi_device *wsi_device,
+ int local_fd,
+ uint32_t* pRectCount,
+ VkRect2D* pRects)
+{
+ VkIcdSurfaceDisplay *surface = (VkIcdSurfaceDisplay *) surface_base;
+ wsi_display_mode *mode = wsi_display_mode_from_handle(surface->displayMode);
+ VK_OUTARRAY_MAKE(out, pRects, pRectCount);
+
+ if (fds_are_same_gpu(local_fd, mode->connector->wsi->fd)) {
+ vk_outarray_append(&out, rect) {
+ *rect = (VkRect2D) {
+ .offset = { 0, 0 },
+ .extent = { mode->hdisplay, mode->vdisplay },
+ };
+ }
+ }
+
+ return vk_outarray_status(&out);
+}
+
static void
wsi_display_destroy_buffer(struct wsi_display *wsi,
uint32_t buffer)
wsi->base.get_formats = wsi_display_surface_get_formats;
wsi->base.get_formats2 = wsi_display_surface_get_formats2;
wsi->base.get_present_modes = wsi_display_surface_get_present_modes;
+ wsi->base.get_present_rectangles = wsi_display_surface_get_present_rectangles;
wsi->base.create_swapchain = wsi_display_surface_create_swapchain;
wsi_device->wsi[VK_ICD_WSI_PLATFORM_DISPLAY] = &wsi->base;
VkResult (*get_present_modes)(VkIcdSurfaceBase *surface,
uint32_t* pPresentModeCount,
VkPresentModeKHR* pPresentModes);
+ VkResult (*get_present_rectangles)(VkIcdSurfaceBase *surface,
+ struct wsi_device *wsi_device,
+ int local_fd,
+ uint32_t* pRectCount,
+ VkRect2D* pRects);
VkResult (*create_swapchain)(VkIcdSurfaceBase *surface,
VkDevice device,
struct wsi_device *wsi_device,
return VK_SUCCESS;
}
+static VkResult
+wsi_wl_surface_get_present_rectangles(VkIcdSurfaceBase *surface,
+ struct wsi_device *wsi_device,
+ int local_fd,
+ uint32_t* pRectCount,
+ VkRect2D* pRects)
+{
+ VK_OUTARRAY_MAKE(out, pRects, pRectCount);
+
+ vk_outarray_append(&out, rect) {
+ /* We don't know a size so just return the usual "I don't know." */
+ *rect = (VkRect2D) {
+ .offset = { 0, 0 },
+ .extent = { -1, -1 },
+ };
+ }
+
+ return vk_outarray_status(&out);
+}
+
VkResult wsi_create_wl_surface(const VkAllocationCallbacks *pAllocator,
const VkWaylandSurfaceCreateInfoKHR *pCreateInfo,
VkSurfaceKHR *pSurface)
wsi->base.get_formats = wsi_wl_surface_get_formats;
wsi->base.get_formats2 = wsi_wl_surface_get_formats2;
wsi->base.get_present_modes = wsi_wl_surface_get_present_modes;
+ wsi->base.get_present_rectangles = wsi_wl_surface_get_present_rectangles;
wsi->base.create_swapchain = wsi_wl_surface_create_swapchain;
wsi_device->wsi[VK_ICD_WSI_PLATFORM_WAYLAND] = &wsi->base;
VK_INCOMPLETE : VK_SUCCESS;
}
+static bool
+x11_surface_is_local_to_gpu(struct wsi_device *wsi_dev,
+ int local_fd,
+ xcb_connection_t *conn)
+{
+ struct wsi_x11_connection *wsi_conn =
+ wsi_x11_get_connection(wsi_dev, conn);
+
+ if (!wsi_conn)
+ return false;
+
+ if (!wsi_x11_check_for_dri3(wsi_conn))
+ return false;
+
+ if (!wsi_x11_check_dri3_compatible(conn, local_fd))
+ return false;
+
+ return true;
+}
+
+static VkResult
+x11_surface_get_present_rectangles(VkIcdSurfaceBase *icd_surface,
+ struct wsi_device *wsi_device,
+ int local_fd,
+ uint32_t* pRectCount,
+ VkRect2D* pRects)
+{
+ xcb_connection_t *conn = x11_surface_get_connection(icd_surface);
+ xcb_window_t window = x11_surface_get_window(icd_surface);
+ VK_OUTARRAY_MAKE(out, pRects, pRectCount);
+
+ if (x11_surface_is_local_to_gpu(wsi_device, local_fd, conn)) {
+ vk_outarray_append(&out, rect) {
+ xcb_generic_error_t *err = NULL;
+ xcb_get_geometry_cookie_t geom_cookie = xcb_get_geometry(conn, window);
+ xcb_get_geometry_reply_t *geom =
+ xcb_get_geometry_reply(conn, geom_cookie, &err);
+ free(err);
+ if (geom) {
+ *rect = (VkRect2D) {
+ .offset = { 0, 0 },
+ .extent = { geom->width, geom->height },
+ };
+ } else {
+ /* This can happen if the client didn't wait for the configure event
+ * to come back from the compositor. In that case, we don't know the
+ * size of the window so we just return valid "I don't know" stuff.
+ */
+ *rect = (VkRect2D) {
+ .offset = { 0, 0 },
+ .extent = { -1, -1 },
+ };
+ }
+ free(geom);
+ }
+ }
+
+ return vk_outarray_status(&out);
+}
+
VkResult wsi_create_xcb_surface(const VkAllocationCallbacks *pAllocator,
const VkXcbSurfaceCreateInfoKHR *pCreateInfo,
VkSurfaceKHR *pSurface)
wsi->base.get_formats = x11_surface_get_formats;
wsi->base.get_formats2 = x11_surface_get_formats2;
wsi->base.get_present_modes = x11_surface_get_present_modes;
+ wsi->base.get_present_rectangles = x11_surface_get_present_rectangles;
wsi->base.create_swapchain = x11_surface_create_swapchain;
wsi_device->wsi[VK_ICD_WSI_PLATFORM_XCB] = &wsi->base;