24
24
#include <X11/Xlib-xcb.h>
25
25
#include <X11/xshmfence.h>
28
#include <X11/keysymdef.h>
26
29
#include <xcb/xcb.h>
30
#ifdef XCB_KEYSYMS_AVAILABLE
31
#include <xcb/xcb_keysyms.h>
27
33
#include <xcb/dri3.h>
28
34
#include <xcb/present.h>
29
35
#include <xcb/shm.h>
61
68
#include <sys/shm.h>
71
#ifndef XCB_PRESENT_OPTION_ASYNC_MAY_TEAR
72
#define XCB_PRESENT_OPTION_ASYNC_MAY_TEAR 16
74
#ifndef XCB_PRESENT_CAPABILITY_ASYNC_MAY_TEAR
75
#define XCB_PRESENT_CAPABILITY_ASYNC_MAY_TEAR 8
64
78
struct wsi_x11_connection {
66
80
bool has_dri3_modifiers;
672
693
xcb_connection_t *conn = x11_surface_get_connection(icd_surface);
673
694
xcb_window_t window = x11_surface_get_window(icd_surface);
695
struct wsi_x11_vk_surface *surface = (struct wsi_x11_vk_surface*)icd_surface;
674
696
struct wsi_x11_connection *wsi_conn =
675
697
wsi_x11_get_connection(wsi_device, conn);
676
698
xcb_get_geometry_cookie_t geom_cookie;
677
699
xcb_generic_error_t *err;
678
700
xcb_get_geometry_reply_t *geom;
679
unsigned visual_depth;
681
702
geom_cookie = xcb_get_geometry(conn, window);
683
/* This does a round-trip. This is why we do get_geometry first and
684
* wait to read the reply until after we have a visual.
686
xcb_visualtype_t *visual =
687
get_visualtype_for_window(conn, window, &visual_depth, NULL);
690
return VK_ERROR_SURFACE_LOST_KHR;
692
704
geom = xcb_get_geometry_reply(conn, geom_cookie, &err);
706
return VK_ERROR_SURFACE_LOST_KHR;
694
708
VkExtent2D extent = { geom->width, geom->height };
695
709
caps->currentExtent = extent;
696
710
caps->minImageExtent = extent;
702
return VK_ERROR_SURFACE_LOST_KHR;
704
if (visual_has_alpha(visual, visual_depth)) {
716
if (surface->has_alpha) {
705
717
caps->supportedCompositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR |
706
718
VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR;
957
969
VkSurfaceKHR *pSurface)
959
971
VK_FROM_HANDLE(vk_instance, instance, _instance);
960
VkIcdSurfaceXcb *surface;
972
struct wsi_x11_vk_surface *surface;
962
974
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR);
964
surface = vk_alloc2(&instance->alloc, pAllocator, sizeof *surface, 8,
976
unsigned visual_depth;
977
xcb_visualtype_t *visual =
978
get_visualtype_for_window(pCreateInfo->connection, pCreateInfo->window, &visual_depth, NULL);
980
return VK_ERROR_OUT_OF_HOST_MEMORY;
982
surface = vk_alloc2(&instance->alloc, pAllocator, sizeof(struct wsi_x11_vk_surface), 8,
965
983
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
966
984
if (surface == NULL)
967
985
return VK_ERROR_OUT_OF_HOST_MEMORY;
969
surface->base.platform = VK_ICD_WSI_PLATFORM_XCB;
970
surface->connection = pCreateInfo->connection;
971
surface->window = pCreateInfo->window;
973
*pSurface = VkIcdSurfaceBase_to_handle(&surface->base);
987
surface->xcb.base.platform = VK_ICD_WSI_PLATFORM_XCB;
988
surface->xcb.connection = pCreateInfo->connection;
989
surface->xcb.window = pCreateInfo->window;
991
surface->has_alpha = visual_has_alpha(visual, visual_depth);
993
*pSurface = VkIcdSurfaceBase_to_handle(&surface->xcb.base);
974
994
return VK_SUCCESS;
981
1001
VkSurfaceKHR *pSurface)
983
1003
VK_FROM_HANDLE(vk_instance, instance, _instance);
984
VkIcdSurfaceXlib *surface;
1004
struct wsi_x11_vk_surface *surface;
986
1006
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR);
988
surface = vk_alloc2(&instance->alloc, pAllocator, sizeof *surface, 8,
1008
unsigned visual_depth;
1009
xcb_visualtype_t *visual =
1010
get_visualtype_for_window(XGetXCBConnection(pCreateInfo->dpy), pCreateInfo->window, &visual_depth, NULL);
1012
return VK_ERROR_OUT_OF_HOST_MEMORY;
1014
surface = vk_alloc2(&instance->alloc, pAllocator, sizeof(struct wsi_x11_vk_surface), 8,
989
1015
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
990
1016
if (surface == NULL)
991
1017
return VK_ERROR_OUT_OF_HOST_MEMORY;
993
surface->base.platform = VK_ICD_WSI_PLATFORM_XLIB;
994
surface->dpy = pCreateInfo->dpy;
995
surface->window = pCreateInfo->window;
997
*pSurface = VkIcdSurfaceBase_to_handle(&surface->base);
1019
surface->xlib.base.platform = VK_ICD_WSI_PLATFORM_XLIB;
1020
surface->xlib.dpy = pCreateInfo->dpy;
1021
surface->xlib.window = pCreateInfo->window;
1023
surface->has_alpha = visual_has_alpha(visual, visual_depth);
1025
*pSurface = VkIcdSurfaceBase_to_handle(&surface->xlib.base);
998
1026
return VK_SUCCESS;
1082
1111
static void x11_present_complete(struct x11_swapchain *swapchain,
1083
1112
struct x11_image *image)
1085
if (image->present_id) {
1114
if (image->signal_present_id) {
1086
1115
pthread_mutex_lock(&swapchain->present_progress_mutex);
1087
1116
if (image->signal_present_id > swapchain->present_id) {
1088
1117
swapchain->present_id = image->signal_present_id;
1576
1605
chain->base.present_mode == VK_PRESENT_MODE_FIFO_RELAXED_KHR)
1577
1606
options |= XCB_PRESENT_OPTION_ASYNC;
1608
if (chain->base.present_mode == VK_PRESENT_MODE_IMMEDIATE_KHR
1609
&& chain->has_async_may_tear)
1610
options |= XCB_PRESENT_OPTION_ASYNC_MAY_TEAR;
1579
1612
#ifdef HAVE_DRI3_MODIFIERS
1580
1613
if (chain->has_dri3_modifiers)
1581
1614
options |= XCB_PRESENT_OPTION_SUBOPTIMAL;
1584
/* Poll for any available event and update the swapchain status. This could
1585
* update the status of the swapchain to SUBOPTIMAL or OUT_OF_DATE if the
1586
* associated X11 surface has been resized.
1588
xcb_generic_event_t *event;
1589
while ((event = xcb_poll_for_special_event(chain->conn, chain->special_event))) {
1590
VkResult result = x11_handle_dri3_present_event(chain, (void *)event);
1591
/* Ensure that VK_SUBOPTIMAL_KHR is reported to the application */
1592
result = x11_swapchain_result(chain, result);
1598
1617
xshmfence_reset(image->shm_fence);
1600
1619
++chain->sent_image_count;
1604
1623
image->present_queued = true;
1605
1624
image->serial = (uint32_t) chain->send_sbc;
1607
xcb_void_cookie_t cookie =
1608
xcb_present_pixmap_checked(chain->conn,
1613
image->update_area, /* update */
1616
XCB_NONE, /* target_crtc */
1622
remainder, 0, NULL);
1623
xcb_generic_error_t *error = xcb_request_check(chain->conn, cookie);
1626
return x11_swapchain_result(chain, VK_ERROR_SURFACE_LOST_KHR);
1626
xcb_present_pixmap(chain->conn,
1631
image->update_area, /* update */
1634
XCB_NONE, /* target_crtc */
1640
remainder, 0, NULL);
1641
xcb_flush(chain->conn);
1629
1642
return x11_swapchain_result(chain, VK_SUCCESS);
1680
1693
return x11_swapchain_result(chain, VK_SUCCESS);
1697
x11_capture_trace(struct x11_swapchain *chain)
1699
#ifdef XCB_KEYSYMS_AVAILABLE
1700
VK_FROM_HANDLE(vk_device, device, chain->base.device);
1701
if (!device->physical->instance->trace_mode)
1704
xcb_query_keymap_cookie_t keys_cookie = xcb_query_keymap(chain->conn);
1706
xcb_generic_error_t *error = NULL;
1707
xcb_query_keymap_reply_t *keys = xcb_query_keymap_reply(chain->conn, keys_cookie, &error);
1713
xcb_key_symbols_t *key_symbols = xcb_key_symbols_alloc(chain->conn);
1714
xcb_keycode_t *keycodes = xcb_key_symbols_get_keycode(key_symbols, XK_F1);
1716
xcb_keycode_t keycode = keycodes[0];
1719
simple_mtx_lock(&device->trace_mtx);
1720
bool capture_key_pressed = keys->keys[keycode / 8] & (1u << (keycode % 8));
1721
device->trace_hotkey_trigger = capture_key_pressed && (capture_key_pressed != chain->base.capture_key_pressed);
1722
chain->base.capture_key_pressed = capture_key_pressed;
1723
simple_mtx_unlock(&device->trace_mtx);
1726
xcb_key_symbols_free(key_symbols);
1684
1732
* Send image to the X server for presentation at target_msc.
1687
1735
x11_present_to_x11(struct x11_swapchain *chain, uint32_t image_index,
1688
1736
uint64_t target_msc)
1738
x11_capture_trace(chain);
1690
1740
VkResult result;
1691
1741
if (chain->base.wsi->sw && !chain->has_mit_shm)
1692
1742
result = x11_present_to_x11_sw(chain, image_index, target_msc);
2183
2238
cookie = xcb_free_pixmap(chain->conn, image->pixmap);
2184
2239
xcb_discard_reply(chain->conn, cookie.sequence);
2186
2242
wsi_destroy_image(&chain->base, &image->base);
2188
2244
return VK_ERROR_INITIALIZATION_FAILED;
2680
2736
chain->has_dri3_modifiers = wsi_conn->has_dri3_modifiers;
2681
2737
chain->has_mit_shm = wsi_conn->has_mit_shm;
2739
xcb_present_query_capabilities_cookie_t present_query_cookie;
2740
xcb_present_query_capabilities_reply_t *present_query_reply;
2741
present_query_cookie = xcb_present_query_capabilities(conn, chain->window);
2742
present_query_reply = xcb_present_query_capabilities_reply(conn, present_query_cookie, NULL);
2743
if (present_query_reply) {
2744
chain->has_async_may_tear = present_query_reply->capabilities & XCB_PRESENT_CAPABILITY_ASYNC_MAY_TEAR;
2745
free(present_query_reply);
2683
2748
/* When images in the swapchain don't fit the window, X can still present them, but it won't
2684
2749
* happen by flip, only by copy. So this is a suboptimal copy, because if the client would change
2685
2750
* the chain extents X may be able to flip