vulkan/wsi/x11: Add support for DRI3 v1.2
Adds support for multiple planes and buffer modifiers. v4: Rename "has_dri3_v1_1" to "has_dri3_modifiers" v12: Multi-planar/modifier support is now DRI3 v1.2; also update release versions
This commit is contained in:
@@ -92,6 +92,7 @@ WAYLAND_REQUIRED=1.11
|
|||||||
WAYLAND_PROTOCOLS_REQUIRED=1.8
|
WAYLAND_PROTOCOLS_REQUIRED=1.8
|
||||||
XCB_REQUIRED=1.9.3
|
XCB_REQUIRED=1.9.3
|
||||||
XCBDRI2_REQUIRED=1.8
|
XCBDRI2_REQUIRED=1.8
|
||||||
|
XCBDRI3_REQUIRED=1.13
|
||||||
XCBGLX_REQUIRED=1.8.1
|
XCBGLX_REQUIRED=1.8.1
|
||||||
XDAMAGE_REQUIRED=1.1
|
XDAMAGE_REQUIRED=1.1
|
||||||
XSHMFENCE_REQUIRED=1.1
|
XSHMFENCE_REQUIRED=1.1
|
||||||
@@ -1849,7 +1850,7 @@ fi
|
|||||||
if test x"$enable_dri3" = xyes; then
|
if test x"$enable_dri3" = xyes; then
|
||||||
DEFINES="$DEFINES -DHAVE_DRI3"
|
DEFINES="$DEFINES -DHAVE_DRI3"
|
||||||
|
|
||||||
dri3_modules="x11-xcb xcb >= $XCB_REQUIRED xcb-dri3 xcb-xfixes xcb-present xcb-sync xshmfence >= $XSHMFENCE_REQUIRED"
|
dri3_modules="x11-xcb xcb >= $XCB_REQUIRED xcb-dri3 >= $XCBDRI3_REQUIRED xcb-xfixes xcb-present xcb-sync xshmfence >= $XSHMFENCE_REQUIRED"
|
||||||
PKG_CHECK_MODULES([XCB_DRI3], [$dri3_modules])
|
PKG_CHECK_MODULES([XCB_DRI3], [$dri3_modules])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@@ -1234,7 +1234,7 @@ if with_platform_x11
|
|||||||
|
|
||||||
if with_dri3
|
if with_dri3
|
||||||
pre_args += '-DHAVE_DRI3'
|
pre_args += '-DHAVE_DRI3'
|
||||||
dep_xcb_dri3 = dependency('xcb-dri3')
|
dep_xcb_dri3 = dependency('xcb-dri3', version : '>= 1.13')
|
||||||
dep_xcb_present = dependency('xcb-present')
|
dep_xcb_present = dependency('xcb-present')
|
||||||
dep_xcb_sync = dependency('xcb-sync')
|
dep_xcb_sync = dependency('xcb-sync')
|
||||||
dep_xshmfence = dependency('xshmfence', version : '>= 1.1')
|
dep_xshmfence = dependency('xshmfence', version : '>= 1.1')
|
||||||
|
@@ -36,6 +36,7 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <xf86drm.h>
|
#include <xf86drm.h>
|
||||||
|
#include <drm_fourcc.h>
|
||||||
#include "util/hash_table.h"
|
#include "util/hash_table.h"
|
||||||
|
|
||||||
#include "vk_util.h"
|
#include "vk_util.h"
|
||||||
@@ -50,6 +51,7 @@
|
|||||||
|
|
||||||
struct wsi_x11_connection {
|
struct wsi_x11_connection {
|
||||||
bool has_dri3;
|
bool has_dri3;
|
||||||
|
bool has_dri3_modifiers;
|
||||||
bool has_present;
|
bool has_present;
|
||||||
bool is_proprietary_x11;
|
bool is_proprietary_x11;
|
||||||
};
|
};
|
||||||
@@ -164,6 +166,17 @@ wsi_x11_connection_create(const VkAllocationCallbacks *alloc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
wsi_conn->has_dri3 = dri3_reply->present != 0;
|
wsi_conn->has_dri3 = dri3_reply->present != 0;
|
||||||
|
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, 2);
|
||||||
|
ver_reply = xcb_dri3_query_version_reply(conn, ver_cookie, NULL);
|
||||||
|
wsi_conn->has_dri3_modifiers =
|
||||||
|
(ver_reply->major_version > 1 || ver_reply->minor_version >= 2);
|
||||||
|
free(ver_reply);
|
||||||
|
}
|
||||||
|
|
||||||
wsi_conn->has_present = pres_reply->present != 0;
|
wsi_conn->has_present = pres_reply->present != 0;
|
||||||
wsi_conn->is_proprietary_x11 = false;
|
wsi_conn->is_proprietary_x11 = false;
|
||||||
if (amd_reply && amd_reply->present)
|
if (amd_reply && amd_reply->present)
|
||||||
@@ -620,6 +633,8 @@ struct x11_image {
|
|||||||
struct x11_swapchain {
|
struct x11_swapchain {
|
||||||
struct wsi_swapchain base;
|
struct wsi_swapchain base;
|
||||||
|
|
||||||
|
bool has_dri3_modifiers;
|
||||||
|
|
||||||
xcb_connection_t * conn;
|
xcb_connection_t * conn;
|
||||||
xcb_window_t window;
|
xcb_window_t window;
|
||||||
xcb_gc_t gc;
|
xcb_gc_t gc;
|
||||||
@@ -966,7 +981,9 @@ static VkResult
|
|||||||
x11_image_init(VkDevice device_h, struct x11_swapchain *chain,
|
x11_image_init(VkDevice device_h, struct x11_swapchain *chain,
|
||||||
const VkSwapchainCreateInfoKHR *pCreateInfo,
|
const VkSwapchainCreateInfoKHR *pCreateInfo,
|
||||||
const VkAllocationCallbacks* pAllocator,
|
const VkAllocationCallbacks* pAllocator,
|
||||||
struct x11_image *image)
|
const uint64_t *const *modifiers,
|
||||||
|
const uint32_t *num_modifiers,
|
||||||
|
int num_tranches, struct x11_image *image)
|
||||||
{
|
{
|
||||||
xcb_void_cookie_t cookie;
|
xcb_void_cookie_t cookie;
|
||||||
VkResult result;
|
VkResult result;
|
||||||
@@ -976,28 +993,57 @@ x11_image_init(VkDevice device_h, struct x11_swapchain *chain,
|
|||||||
result = wsi_create_prime_image(&chain->base, pCreateInfo, &image->base);
|
result = wsi_create_prime_image(&chain->base, pCreateInfo, &image->base);
|
||||||
} else {
|
} else {
|
||||||
result = wsi_create_native_image(&chain->base, pCreateInfo,
|
result = wsi_create_native_image(&chain->base, pCreateInfo,
|
||||||
0, NULL, NULL, &image->base);
|
num_tranches, num_modifiers, modifiers,
|
||||||
|
&image->base);
|
||||||
}
|
}
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
image->pixmap = xcb_generate_id(chain->conn);
|
image->pixmap = xcb_generate_id(chain->conn);
|
||||||
|
|
||||||
/* Without passing modifiers, we can't have multi-plane RGB images. */
|
if (image->base.drm_modifier != DRM_FORMAT_MOD_INVALID) {
|
||||||
assert(image->base.num_planes == 1);
|
/* If the image has a modifier, we must have DRI3 v1.1. */
|
||||||
|
assert(chain->has_dri3_modifiers);
|
||||||
|
|
||||||
|
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 {
|
||||||
|
/* 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]);
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
xcb_discard_reply(chain->conn, cookie.sequence);
|
||||||
image->base.fds[0] = -1; /* XCB has now taken ownership of the FD */
|
|
||||||
|
/* XCB has now taken ownership of the FDs. */
|
||||||
|
for (int i = 0; i < image->base.num_planes; i++)
|
||||||
|
image->base.fds[i] = -1;
|
||||||
|
|
||||||
int fence_fd = xshmfence_alloc_shm();
|
int fence_fd = xshmfence_alloc_shm();
|
||||||
if (fence_fd < 0)
|
if (fence_fd < 0)
|
||||||
@@ -1048,6 +1094,82 @@ x11_image_finish(struct x11_swapchain *chain,
|
|||||||
wsi_destroy_image(&chain->base, &image->base);
|
wsi_destroy_image(&chain->base, &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, uint32_t *num_modifiers_in,
|
||||||
|
uint32_t *num_tranches_in,
|
||||||
|
const VkAllocationCallbacks *pAllocator)
|
||||||
|
{
|
||||||
|
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_window_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_window_modifiers) {
|
||||||
|
counts[n] = mod_reply->num_window_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_window_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]) {
|
||||||
|
if (n > 0)
|
||||||
|
vk_free(pAllocator, modifiers[0]);
|
||||||
|
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;
|
||||||
|
|
||||||
|
out:
|
||||||
|
*num_tranches_in = 0;
|
||||||
|
}
|
||||||
|
|
||||||
static VkResult
|
static VkResult
|
||||||
x11_swapchain_destroy(struct wsi_swapchain *anv_chain,
|
x11_swapchain_destroy(struct wsi_swapchain *anv_chain,
|
||||||
const VkAllocationCallbacks *pAllocator)
|
const VkAllocationCallbacks *pAllocator)
|
||||||
@@ -1097,8 +1219,13 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
|
|||||||
|
|
||||||
const unsigned num_images = pCreateInfo->minImageCount;
|
const unsigned num_images = pCreateInfo->minImageCount;
|
||||||
|
|
||||||
/* Check for whether or not we have a window up-front */
|
|
||||||
xcb_connection_t *conn = x11_surface_get_connection(icd_surface);
|
xcb_connection_t *conn = x11_surface_get_connection(icd_surface);
|
||||||
|
struct wsi_x11_connection *wsi_conn =
|
||||||
|
wsi_x11_get_connection(wsi_device, pAllocator, conn);
|
||||||
|
if (!wsi_conn)
|
||||||
|
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||||
|
|
||||||
|
/* Check for whether or not we have a window up-front */
|
||||||
xcb_window_t window = x11_surface_get_window(icd_surface);
|
xcb_window_t window = x11_surface_get_window(icd_surface);
|
||||||
xcb_get_geometry_reply_t *geometry =
|
xcb_get_geometry_reply_t *geometry =
|
||||||
xcb_get_geometry_reply(conn, xcb_get_geometry(conn, window), NULL);
|
xcb_get_geometry_reply(conn, xcb_get_geometry(conn, window), NULL);
|
||||||
@@ -1132,6 +1259,7 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
|
|||||||
chain->last_present_msc = 0;
|
chain->last_present_msc = 0;
|
||||||
chain->threaded = false;
|
chain->threaded = false;
|
||||||
chain->status = VK_SUCCESS;
|
chain->status = VK_SUCCESS;
|
||||||
|
chain->has_dri3_modifiers = wsi_conn->has_dri3_modifiers;
|
||||||
|
|
||||||
if (!wsi_x11_check_dri3_compatible(conn, local_fd))
|
if (!wsi_x11_check_dri3_compatible(conn, local_fd))
|
||||||
chain->base.use_prime_blit = true;
|
chain->base.use_prime_blit = true;
|
||||||
@@ -1163,9 +1291,20 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
|
|||||||
(uint32_t []) { 0 });
|
(uint32_t []) { 0 });
|
||||||
xcb_discard_reply(chain->conn, cookie.sequence);
|
xcb_discard_reply(chain->conn, cookie.sequence);
|
||||||
|
|
||||||
|
uint64_t *modifiers[2] = {NULL, NULL};
|
||||||
|
uint32_t num_modifiers[2] = {0, 0};
|
||||||
|
uint32_t num_tranches = 0;
|
||||||
|
if (wsi_device->supports_modifiers)
|
||||||
|
wsi_x11_get_dri3_modifiers(wsi_conn, conn, window, chain->depth, 32,
|
||||||
|
pCreateInfo->compositeAlpha,
|
||||||
|
modifiers, num_modifiers, &num_tranches,
|
||||||
|
pAllocator);
|
||||||
|
|
||||||
uint32_t image = 0;
|
uint32_t image = 0;
|
||||||
for (; image < chain->base.image_count; image++) {
|
for (; image < chain->base.image_count; image++) {
|
||||||
result = x11_image_init(device, chain, pCreateInfo, pAllocator,
|
result = x11_image_init(device, chain, pCreateInfo, pAllocator,
|
||||||
|
(const uint64_t *const *)modifiers,
|
||||||
|
num_modifiers, num_tranches,
|
||||||
&chain->images[image]);
|
&chain->images[image]);
|
||||||
if (result != VK_SUCCESS)
|
if (result != VK_SUCCESS)
|
||||||
goto fail_init_images;
|
goto fail_init_images;
|
||||||
@@ -1202,6 +1341,8 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++)
|
||||||
|
vk_free(pAllocator, modifiers[i]);
|
||||||
*swapchain_out = &chain->base;
|
*swapchain_out = &chain->base;
|
||||||
|
|
||||||
return VK_SUCCESS;
|
return VK_SUCCESS;
|
||||||
@@ -1211,6 +1352,9 @@ fail_init_images:
|
|||||||
x11_image_finish(chain, pAllocator, &chain->images[j]);
|
x11_image_finish(chain, pAllocator, &chain->images[j]);
|
||||||
|
|
||||||
fail_register:
|
fail_register:
|
||||||
|
for (int i = 0; i < 2; i++)
|
||||||
|
vk_free(pAllocator, modifiers[i]);
|
||||||
|
|
||||||
xcb_unregister_for_special_event(chain->conn, chain->special_event);
|
xcb_unregister_for_special_event(chain->conn, chain->special_event);
|
||||||
|
|
||||||
wsi_swapchain_finish(&chain->base);
|
wsi_swapchain_finish(&chain->base);
|
||||||
|
Reference in New Issue
Block a user