summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/amd/vulkan/radv_wsi.c14
-rw-r--r--src/intel/vulkan/anv_wsi.c14
-rw-r--r--src/vulkan/wsi/wsi_common.c14
-rw-r--r--src/vulkan/wsi/wsi_common.h7
-rw-r--r--src/vulkan/wsi/wsi_common_display.c41
-rw-r--r--src/vulkan/wsi/wsi_common_private.h5
-rw-r--r--src/vulkan/wsi/wsi_common_wayland.c21
-rw-r--r--src/vulkan/wsi/wsi_common_x11.c61
8 files changed, 177 insertions, 0 deletions
diff --git a/src/amd/vulkan/radv_wsi.c b/src/amd/vulkan/radv_wsi.c
index 8b165ea3916..43103a4ef85 100644
--- a/src/amd/vulkan/radv_wsi.c
+++ b/src/amd/vulkan/radv_wsi.c
@@ -284,3 +284,17 @@ VkResult radv_GetDeviceGroupSurfacePresentModesKHR(
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);
+}
diff --git a/src/intel/vulkan/anv_wsi.c b/src/intel/vulkan/anv_wsi.c
index 1c9a54804e8..5d672c211c4 100644
--- a/src/intel/vulkan/anv_wsi.c
+++ b/src/intel/vulkan/anv_wsi.c
@@ -293,3 +293,17 @@ VkResult anv_GetDeviceGroupSurfacePresentModesKHR(
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);
+}
diff --git a/src/vulkan/wsi/wsi_common.c b/src/vulkan/wsi/wsi_common.c
index 1e3c4e0028b..ad4b8c9075e 100644
--- a/src/vulkan/wsi/wsi_common.c
+++ b/src/vulkan/wsi/wsi_common.c
@@ -804,6 +804,20 @@ wsi_common_get_surface_present_modes(struct wsi_device *wsi_device,
}
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,
int fd,
diff --git a/src/vulkan/wsi/wsi_common.h b/src/vulkan/wsi/wsi_common.h
index 424330de566..5b69c573d9e 100644
--- a/src/vulkan/wsi/wsi_common.h
+++ b/src/vulkan/wsi/wsi_common.h
@@ -200,6 +200,13 @@ wsi_common_get_surface_present_modes(struct wsi_device *wsi_device,
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,
VkSurfaceKHR surface,
diff --git a/src/vulkan/wsi/wsi_common_display.c b/src/vulkan/wsi/wsi_common_display.c
index c004060a205..2315717ef8e 100644
--- a/src/vulkan/wsi/wsi_common_display.c
+++ b/src/vulkan/wsi/wsi_common_display.c
@@ -934,6 +934,46 @@ wsi_display_surface_get_present_modes(VkIcdSurfaceBase *surface,
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)
@@ -1810,6 +1850,7 @@ wsi_display_init_wsi(struct wsi_device *wsi_device,
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;
diff --git a/src/vulkan/wsi/wsi_common_private.h b/src/vulkan/wsi/wsi_common_private.h
index accc1170163..d8290b69331 100644
--- a/src/vulkan/wsi/wsi_common_private.h
+++ b/src/vulkan/wsi/wsi_common_private.h
@@ -118,6 +118,11 @@ struct wsi_interface {
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,
diff --git a/src/vulkan/wsi/wsi_common_wayland.c b/src/vulkan/wsi/wsi_common_wayland.c
index 67d5f8d4c80..dccb530dae3 100644
--- a/src/vulkan/wsi/wsi_common_wayland.c
+++ b/src/vulkan/wsi/wsi_common_wayland.c
@@ -601,6 +601,26 @@ wsi_wl_surface_get_present_modes(VkIcdSurfaceBase *surface,
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)
@@ -1012,6 +1032,7 @@ wsi_wl_init_wsi(struct wsi_device *wsi_device,
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;
diff --git a/src/vulkan/wsi/wsi_common_x11.c b/src/vulkan/wsi/wsi_common_x11.c
index 75aa83bb7b4..8c621ddf568 100644
--- a/src/vulkan/wsi/wsi_common_x11.c
+++ b/src/vulkan/wsi/wsi_common_x11.c
@@ -599,6 +599,66 @@ x11_surface_get_present_modes(VkIcdSurfaceBase *surface,
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)
@@ -1470,6 +1530,7 @@ wsi_x11_init_wsi(struct wsi_device *wsi_device,
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;