[Mesa-dev] [RFC v5 18/19] RFC: vulkan/wsi: Add support for DRI3 v1.1
Louis-Francis Ratté-Boulianne
lfrb at collabora.com
Mon Nov 6 22:02:48 UTC 2017
From: Daniel Stone <daniels at collabora.com>
Adds support for multiple planes and buffer modifiers.
v4: Rename "has_dri3_v1_1" to "has_dri3_modifiers"
---
src/vulkan/wsi/wsi_common_x11.c | 238 +++++++++++++++++++++++++++++++++-------
1 file changed, 199 insertions(+), 39 deletions(-)
diff --git a/src/vulkan/wsi/wsi_common_x11.c b/src/vulkan/wsi/wsi_common_x11.c
index e48d746305..0417166409 100644
--- a/src/vulkan/wsi/wsi_common_x11.c
+++ b/src/vulkan/wsi/wsi_common_x11.c
@@ -36,6 +36,7 @@
#include <fcntl.h>
#include <poll.h>
#include <xf86drm.h>
+#include <drm_fourcc.h>
#include "util/hash_table.h"
#include "vk_util.h"
@@ -50,6 +51,7 @@
struct wsi_x11_connection {
bool has_dri3;
+ bool has_dri3_modifiers;
bool has_present;
bool is_proprietary_x11;
};
@@ -164,6 +166,19 @@ wsi_x11_connection_create(const VkAllocationCallbacks *alloc,
}
wsi_conn->has_dri3 = dri3_reply->present != 0;
+#if XCB_DRI3_MAJOR_VERSION > 1 || XCB_DRI3_MINOR_VERSION >= 1
+ if (wsi_conn->has_dri3) {
+ xcb_dri3_query_version_cookie_t ver_cookie;
+ xcb_dri3_query_version_reply_t *ver_reply;
+
+ ver_cookie = xcb_dri3_query_version(conn, 1, 1);
+ ver_reply = xcb_dri3_query_version_reply(conn, ver_cookie, NULL);
+ wsi_conn->has_dri3_v1_1 =
+ (ver_reply->major_version > 1 || ver_reply->minor_version >= 1);
+ free(ver_reply);
+ }
+#endif
+
wsi_conn->has_present = pres_reply->present != 0;
wsi_conn->is_proprietary_x11 = false;
if (amd_reply && amd_reply->present)
@@ -626,6 +641,8 @@ struct x11_image {
struct x11_swapchain {
struct wsi_swapchain base;
+ bool has_dri3_modifiers;
+
xcb_connection_t * conn;
xcb_window_t window;
xcb_gc_t gc;
@@ -679,7 +696,10 @@ x11_get_image_and_linear(struct wsi_swapchain *drv_chain,
{
struct x11_swapchain *chain = (struct x11_swapchain *)drv_chain;
*image = chain->images[imageIndex].base.image;
- *linear_image = chain->images[imageIndex].linear_base.image;
+ if (chain->images[imageIndex].base.linear_image != VK_NULL_HANDLE)
+ *linear_image = chain->images[imageIndex].base.linear_image;
+ else
+ *linear_image = chain->images[imageIndex].linear_base.image;
}
static VkResult
@@ -954,56 +974,100 @@ static VkResult
x11_image_init(VkDevice device_h, struct x11_swapchain *chain,
const VkSwapchainCreateInfoKHR *pCreateInfo,
const VkAllocationCallbacks* pAllocator,
- struct x11_image *image)
+ uint64_t **modifiers, int *num_modifiers,
+ int num_tranches, struct x11_image *image)
{
xcb_void_cookie_t cookie;
VkResult result;
uint32_t bpp = 32;
-
- result = chain->base.image_fns->create_wsi_image(device_h,
- pCreateInfo,
- pAllocator,
- !chain->base.needs_linear_copy,
- false,
- &image->base);
- if (result != VK_SUCCESS)
- return result;
-
- if (chain->base.needs_linear_copy) {
+ int i;
+
+ image->linear_base.image = VK_NULL_HANDLE;
+ image->linear_base.memory = VK_NULL_HANDLE;
+
+ if (chain->base.image_fns->create_wsi_image_with_modifiers) {
+ result = chain->base.image_fns->create_wsi_image_with_modifiers(device_h,
+ pCreateInfo,
+ pAllocator,
+ chain->base.needs_linear_copy,
+ modifiers,
+ num_modifiers,
+ num_tranches,
+ &image->base);
+ if (result != VK_SUCCESS)
+ return result;
+ } else {
result = chain->base.image_fns->create_wsi_image(device_h,
pCreateInfo,
pAllocator,
- true,
- true,
- &image->linear_base);
-
- if (result != VK_SUCCESS) {
- chain->base.image_fns->free_wsi_image(device_h, pAllocator,
- &image->base);
+ !chain->base.needs_linear_copy,
+ false,
+ &image->base);
+ if (result != VK_SUCCESS)
return result;
+
+ if (chain->base.needs_linear_copy) {
+ result = chain->base.image_fns->create_wsi_image(device_h,
+ pCreateInfo,
+ pAllocator,
+ true,
+ true,
+ &image->linear_base);
+
+ if (result != VK_SUCCESS) {
+ chain->base.image_fns->free_wsi_image(device_h, pAllocator,
+ &image->base);
+ return result;
+ }
}
}
image->pixmap = xcb_generate_id(chain->conn);
- struct wsi_image_base *image_ws =
- chain->base.needs_linear_copy ? &image->linear_base : &image->base;
-
- /* Without passing modifiers, we can't have multi-plane RGB images. */
- assert(image_ws->num_planes == 1);
-
- cookie =
- xcb_dri3_pixmap_from_buffer_checked(chain->conn,
- image->pixmap,
- chain->window,
- image_ws->sizes[0],
- pCreateInfo->imageExtent.width,
- pCreateInfo->imageExtent.height,
- image_ws->row_pitches[0],
- chain->depth, bpp,
- image_ws->fds[0]);
+#if XCB_DRI3_MAJOR_VERSION > 1 || XCB_DRI3_MINOR_VERSION >= 1
+ if (chain->has_dri3_modifiers &&
+ image->base.drm_modifier != DRM_FORMAT_MOD_INVALID) {
+ cookie =
+ xcb_dri3_pixmap_from_buffers_checked(chain->conn,
+ image->pixmap,
+ chain->window,
+ image->base.num_planes,
+ pCreateInfo->imageExtent.width,
+ pCreateInfo->imageExtent.height,
+ image->base.row_pitches[0],
+ image->base.offsets[0],
+ image->base.row_pitches[1],
+ image->base.offsets[1],
+ image->base.row_pitches[2],
+ image->base.offsets[2],
+ image->base.row_pitches[3],
+ image->base.offsets[3],
+ chain->depth, bpp,
+ image->base.drm_modifier,
+ image->base.fds);
+ } else
+#endif
+ {
+ /* Without passing modifiers, we can't have multi-plane RGB images. */
+ assert(image->base.num_planes == 1);
+
+ cookie =
+ xcb_dri3_pixmap_from_buffer_checked(chain->conn,
+ image->pixmap,
+ chain->window,
+ image->base.sizes[0],
+ pCreateInfo->imageExtent.width,
+ pCreateInfo->imageExtent.height,
+ image->base.row_pitches[0],
+ chain->depth, bpp,
+ image->base.fds[0]);
+ }
+
xcb_discard_reply(chain->conn, cookie.sequence);
- image_ws->fds[0] = -1; /* XCB has now taken ownership of the FD */
+
+ /* XCB has now taken ownership of the FDs. */
+ for (i = 0; i < image->base.num_planes; i++)
+ image->base.fds[i] = -1;
int fence_fd = xshmfence_alloc_shm();
if (fence_fd < 0)
@@ -1032,7 +1096,7 @@ fail_pixmap:
cookie = xcb_free_pixmap(chain->conn, image->pixmap);
xcb_discard_reply(chain->conn, cookie.sequence);
- if (chain->base.needs_linear_copy) {
+ if (image->linear_base.image != VK_NULL_HANDLE) {
chain->base.image_fns->free_wsi_image(device_h, pAllocator,
&image->linear_base);
}
@@ -1055,7 +1119,7 @@ x11_image_finish(struct x11_swapchain *chain,
cookie = xcb_free_pixmap(chain->conn, image->pixmap);
xcb_discard_reply(chain->conn, cookie.sequence);
- if (chain->base.needs_linear_copy) {
+ if (image->linear_base.image != VK_NULL_HANDLE) {
chain->base.image_fns->free_wsi_image(chain->base.device, pAllocator,
&image->linear_base);
}
@@ -1063,6 +1127,82 @@ x11_image_finish(struct x11_swapchain *chain,
&image->base);
}
+static void
+wsi_x11_get_dri3_modifiers(struct wsi_x11_connection *wsi_conn,
+ xcb_connection_t *conn, xcb_window_t window,
+ uint8_t depth, uint8_t bpp,
+ VkCompositeAlphaFlagsKHR vk_alpha,
+ uint64_t **modifiers_in, int *num_modifiers_in,
+ int *num_tranches_in,
+ const VkAllocationCallbacks *pAllocator)
+{
+#if XCB_DRI3_MAJOR_VERSION > 1 || XCB_DRI3_MINOR_VERSION >= 1
+ if (!wsi_conn->has_dri3_modifiers)
+ goto out;
+
+ xcb_generic_error_t *error = NULL;
+ xcb_dri3_get_supported_modifiers_cookie_t mod_cookie =
+ xcb_dri3_get_supported_modifiers(conn, window, depth, bpp);
+ xcb_dri3_get_supported_modifiers_reply_t *mod_reply =
+ xcb_dri3_get_supported_modifiers_reply(conn, mod_cookie, &error);
+ free(error);
+
+ if (!mod_reply || (mod_reply->num_drawable_modifiers == 0 &&
+ mod_reply->num_screen_modifiers == 0)) {
+ free(mod_reply);
+ goto out;
+ }
+
+ uint32_t n = 0;
+ uint32_t counts[2];
+ uint64_t *modifiers[2];
+
+ if (mod_reply->num_drawable_modifiers) {
+ counts[n] = mod_reply->num_drawable_modifiers;
+ modifiers[n] = vk_alloc(pAllocator,
+ counts[n] * sizeof(uint64_t),
+ 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ if (!modifiers[n]) {
+ free(mod_reply);
+ goto out;
+ }
+
+ memcpy(modifiers[n],
+ xcb_dri3_get_supported_modifiers_drawable_modifiers(mod_reply),
+ counts[n] * sizeof(uint64_t));
+ n++;
+ }
+
+ if (mod_reply->num_screen_modifiers) {
+ counts[n] = mod_reply->num_screen_modifiers;
+ modifiers[n] = vk_alloc(pAllocator,
+ counts[n] * sizeof(uint64_t),
+ 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ if (!modifiers[n]) {
+ free(mod_reply);
+ goto out;
+ }
+
+ memcpy(modifiers[n],
+ xcb_dri3_get_supported_modifiers_screen_modifiers(mod_reply),
+ counts[n] * sizeof(uint64_t));
+ n++;
+ }
+
+ for (int i = 0; i < n; i++) {
+ modifiers_in[i] = modifiers[i];
+ num_modifiers_in[i] = counts[i];
+ }
+ *num_tranches_in = n;
+
+ free(mod_reply);
+ return;
+#endif
+
+out:
+ *num_tranches_in = 0;
+}
+
static VkResult
x11_swapchain_destroy(struct wsi_swapchain *anv_chain,
const VkAllocationCallbacks *pAllocator)
@@ -1104,6 +1244,9 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
struct wsi_swapchain **swapchain_out)
{
struct x11_swapchain *chain;
+ uint64_t *modifiers[2] = {NULL, NULL};
+ int num_modifiers[2] = {0, 0};
+ int num_tranches = 0;
xcb_void_cookie_t cookie;
VkResult result;
@@ -1145,10 +1288,21 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
free(geometry);
+ struct wsi_x11_connection *wsi_conn =
+ wsi_x11_get_connection(wsi_device, pAllocator, conn);
+ if (!wsi_conn)
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+ chain->has_dri3_modifiers = wsi_conn->has_dri3_modifiers;
+
chain->base.needs_linear_copy = false;
if (!wsi_x11_check_dri3_compatible(conn, local_fd))
chain->base.needs_linear_copy = true;
+ wsi_x11_get_dri3_modifiers(wsi_conn, conn, window, chain->depth, 32,
+ pCreateInfo->compositeAlpha,
+ modifiers, num_modifiers, &num_tranches, pAllocator);
+
chain->event_id = xcb_generate_id(chain->conn);
xcb_present_select_input(chain->conn, chain->event_id, chain->window,
XCB_PRESENT_EVENT_MASK_CONFIGURE_NOTIFY |
@@ -1179,6 +1333,7 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
uint32_t image = 0;
for (; image < chain->base.image_count; image++) {
result = x11_image_init(device, chain, pCreateInfo, pAllocator,
+ modifiers, num_modifiers, num_tranches,
&chain->images[image]);
if (result != VK_SUCCESS)
goto fail_init_images;
@@ -1215,6 +1370,8 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
}
}
+ for (int i = 0; i < 2; i++)
+ vk_free(pAllocator, modifiers[i]);
*swapchain_out = &chain->base;
return VK_SUCCESS;
@@ -1224,6 +1381,9 @@ fail_init_images:
x11_image_finish(chain, pAllocator, &chain->images[j]);
fail_register:
+ for (int i = 0; i < 2; i++)
+ vk_free(pAllocator, modifiers[i]);
+
xcb_unregister_for_special_event(chain->conn, chain->special_event);
vk_free(pAllocator, chain);
--
2.13.0
More information about the mesa-dev
mailing list