~mmach/netext73/mesa-ryzen

« back to all changes in this revision

Viewing changes to src/vulkan/wsi/wsi_common_x11.c

  • Committer: mmach
  • Date: 2023-11-02 21:31:35 UTC
  • Revision ID: netbit73@gmail.com-20231102213135-18d4tzh7tj0uz752
2023-11-02 22:11:57

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
 
24
24
#include <X11/Xlib-xcb.h>
25
25
#include <X11/xshmfence.h>
 
26
#define XK_MISCELLANY
 
27
#define XK_LATIN1
 
28
#include <X11/keysymdef.h>
26
29
#include <xcb/xcb.h>
 
30
#ifdef XCB_KEYSYMS_AVAILABLE
 
31
#include <xcb/xcb_keysyms.h>
 
32
#endif
27
33
#include <xcb/dri3.h>
28
34
#include <xcb/present.h>
29
35
#include <xcb/shm.h>
50
56
#include "vk_format.h"
51
57
#include "vk_instance.h"
52
58
#include "vk_physical_device.h"
 
59
#include "vk_device.h"
53
60
#include "vk_util.h"
54
61
#include "vk_enum_to_str.h"
55
62
#include "wsi_common_entrypoints.h"
61
68
#include <sys/shm.h>
62
69
#endif
63
70
 
 
71
#ifndef XCB_PRESENT_OPTION_ASYNC_MAY_TEAR
 
72
#define XCB_PRESENT_OPTION_ASYNC_MAY_TEAR 16
 
73
#endif
 
74
#ifndef XCB_PRESENT_CAPABILITY_ASYNC_MAY_TEAR
 
75
#define XCB_PRESENT_CAPABILITY_ASYNC_MAY_TEAR 8
 
76
#endif
 
77
 
64
78
struct wsi_x11_connection {
65
79
   bool has_dri3;
66
80
   bool has_dri3_modifiers;
79
93
   struct hash_table *connections;
80
94
};
81
95
 
 
96
struct wsi_x11_vk_surface {
 
97
   union {
 
98
      VkIcdSurfaceXlib xlib;
 
99
      VkIcdSurfaceXcb xcb;
 
100
   };
 
101
   bool has_alpha;
 
102
};
82
103
 
83
104
/**
84
105
 * Wrapper around xcb_dri3_open. Returns the opened fd or -1 on error.
671
692
{
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;
680
701
 
681
702
   geom_cookie = xcb_get_geometry(conn, window);
682
703
 
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.
685
 
    */
686
 
   xcb_visualtype_t *visual =
687
 
      get_visualtype_for_window(conn, window, &visual_depth, NULL);
688
 
 
689
 
   if (!visual)
690
 
      return VK_ERROR_SURFACE_LOST_KHR;
691
 
 
692
704
   geom = xcb_get_geometry_reply(conn, geom_cookie, &err);
693
 
   if (geom) {
 
705
   if (!geom)
 
706
      return VK_ERROR_SURFACE_LOST_KHR;
 
707
   {
694
708
      VkExtent2D extent = { geom->width, geom->height };
695
709
      caps->currentExtent = extent;
696
710
      caps->minImageExtent = extent;
698
712
   }
699
713
   free(err);
700
714
   free(geom);
701
 
   if (!geom)
702
 
       return VK_ERROR_SURFACE_LOST_KHR;
703
715
 
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;
707
719
   } else {
957
969
                        VkSurfaceKHR *pSurface)
958
970
{
959
971
   VK_FROM_HANDLE(vk_instance, instance, _instance);
960
 
   VkIcdSurfaceXcb *surface;
 
972
   struct wsi_x11_vk_surface *surface;
961
973
 
962
974
   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR);
963
975
 
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);
 
979
   if (!visual)
 
980
      return VK_ERROR_OUT_OF_HOST_MEMORY;
 
981
 
 
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;
968
986
 
969
 
   surface->base.platform = VK_ICD_WSI_PLATFORM_XCB;
970
 
   surface->connection = pCreateInfo->connection;
971
 
   surface->window = pCreateInfo->window;
972
 
 
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;
 
990
 
 
991
   surface->has_alpha = visual_has_alpha(visual, visual_depth);
 
992
 
 
993
   *pSurface = VkIcdSurfaceBase_to_handle(&surface->xcb.base);
974
994
   return VK_SUCCESS;
975
995
}
976
996
 
981
1001
                         VkSurfaceKHR *pSurface)
982
1002
{
983
1003
   VK_FROM_HANDLE(vk_instance, instance, _instance);
984
 
   VkIcdSurfaceXlib *surface;
 
1004
   struct wsi_x11_vk_surface *surface;
985
1005
 
986
1006
   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR);
987
1007
 
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);
 
1011
   if (!visual)
 
1012
      return VK_ERROR_OUT_OF_HOST_MEMORY;
 
1013
 
 
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;
992
1018
 
993
 
   surface->base.platform = VK_ICD_WSI_PLATFORM_XLIB;
994
 
   surface->dpy = pCreateInfo->dpy;
995
 
   surface->window = pCreateInfo->window;
996
 
 
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;
 
1022
 
 
1023
   surface->has_alpha = visual_has_alpha(visual, visual_depth);
 
1024
 
 
1025
   *pSurface = VkIcdSurfaceBase_to_handle(&surface->xlib.base);
998
1026
   return VK_SUCCESS;
999
1027
}
1000
1028
 
1020
1048
 
1021
1049
   bool                                         has_dri3_modifiers;
1022
1050
   bool                                         has_mit_shm;
 
1051
   bool                                         has_async_may_tear;
1023
1052
 
1024
1053
   xcb_connection_t *                           conn;
1025
1054
   xcb_window_t                                 window;
1082
1111
static void x11_present_complete(struct x11_swapchain *swapchain,
1083
1112
                                 struct x11_image *image)
1084
1113
{
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;
1578
1607
 
 
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;
 
1611
 
1579
1612
#ifdef HAVE_DRI3_MODIFIERS
1580
1613
   if (chain->has_dri3_modifiers)
1581
1614
      options |= XCB_PRESENT_OPTION_SUBOPTIMAL;
1582
1615
#endif
1583
1616
 
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.
1587
 
    */
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);
1593
 
      free(event);
1594
 
      if (result < 0)
1595
 
         return result;
1596
 
   }
1597
 
 
1598
1617
   xshmfence_reset(image->shm_fence);
1599
1618
 
1600
1619
   ++chain->sent_image_count;
1604
1623
   image->present_queued = true;
1605
1624
   image->serial = (uint32_t) chain->send_sbc;
1606
1625
 
1607
 
   xcb_void_cookie_t cookie =
1608
 
      xcb_present_pixmap_checked(chain->conn,
1609
 
                                 chain->window,
1610
 
                                 image->pixmap,
1611
 
                                 image->serial,
1612
 
                                 0,                            /* valid */
1613
 
                                 image->update_area,           /* update */
1614
 
                                 0,                            /* x_off */
1615
 
                                 0,                            /* y_off */
1616
 
                                 XCB_NONE,                     /* target_crtc */
1617
 
                                 XCB_NONE,
1618
 
                                 image->sync_fence,
1619
 
                                 options,
1620
 
                                 target_msc,
1621
 
                                 divisor,
1622
 
                                 remainder, 0, NULL);
1623
 
   xcb_generic_error_t *error = xcb_request_check(chain->conn, cookie);
1624
 
   if (error) {
1625
 
      free(error);
1626
 
      return x11_swapchain_result(chain, VK_ERROR_SURFACE_LOST_KHR);
1627
 
   }
1628
 
 
 
1626
   xcb_present_pixmap(chain->conn,
 
1627
                      chain->window,
 
1628
                      image->pixmap,
 
1629
                      image->serial,
 
1630
                      0,                            /* valid */
 
1631
                      image->update_area,           /* update */
 
1632
                      0,                            /* x_off */
 
1633
                      0,                            /* y_off */
 
1634
                      XCB_NONE,                     /* target_crtc */
 
1635
                      XCB_NONE,
 
1636
                      image->sync_fence,
 
1637
                      options,
 
1638
                      target_msc,
 
1639
                      divisor,
 
1640
                      remainder, 0, NULL);
 
1641
   xcb_flush(chain->conn);
1629
1642
   return x11_swapchain_result(chain, VK_SUCCESS);
1630
1643
}
1631
1644
 
1680
1693
   return x11_swapchain_result(chain, VK_SUCCESS);
1681
1694
}
1682
1695
 
 
1696
static void
 
1697
x11_capture_trace(struct x11_swapchain *chain)
 
1698
{
 
1699
#ifdef XCB_KEYSYMS_AVAILABLE
 
1700
   VK_FROM_HANDLE(vk_device, device, chain->base.device);
 
1701
   if (!device->physical->instance->trace_mode)
 
1702
      return;
 
1703
 
 
1704
   xcb_query_keymap_cookie_t keys_cookie = xcb_query_keymap(chain->conn);
 
1705
 
 
1706
   xcb_generic_error_t *error = NULL;
 
1707
   xcb_query_keymap_reply_t *keys = xcb_query_keymap_reply(chain->conn, keys_cookie, &error);
 
1708
   if (error) {
 
1709
      free(error);
 
1710
      return;
 
1711
   }
 
1712
 
 
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);
 
1715
   if (keycodes) {
 
1716
      xcb_keycode_t keycode = keycodes[0];
 
1717
      free(keycodes);
 
1718
 
 
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);
 
1724
   }
 
1725
 
 
1726
   xcb_key_symbols_free(key_symbols);
 
1727
   free(keys);
 
1728
#endif
 
1729
}
 
1730
 
1683
1731
/**
1684
1732
 * Send image to the X server for presentation at target_msc.
1685
1733
 */
1687
1735
x11_present_to_x11(struct x11_swapchain *chain, uint32_t image_index,
1688
1736
                   uint64_t target_msc)
1689
1737
{
 
1738
   x11_capture_trace(chain);
 
1739
 
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);
2059
2109
               struct x11_image *image)
2060
2110
{
2061
2111
   xcb_void_cookie_t cookie;
 
2112
   xcb_generic_error_t *error = NULL;
2062
2113
   VkResult result;
2063
2114
   uint32_t bpp = 32;
2064
2115
   int fence_fd;
2153
2204
                                             chain->depth, bpp, fd);
2154
2205
   }
2155
2206
 
2156
 
   xcb_discard_reply(chain->conn, cookie.sequence);
 
2207
   error = xcb_request_check(chain->conn, cookie);
 
2208
   if (error != NULL) {
 
2209
      free(error);
 
2210
      goto fail_image;
 
2211
   }
2157
2212
 
2158
2213
out_fence:
2159
2214
   fence_fd = xshmfence_alloc_shm();
2183
2238
   cookie = xcb_free_pixmap(chain->conn, image->pixmap);
2184
2239
   xcb_discard_reply(chain->conn, cookie.sequence);
2185
2240
 
 
2241
fail_image:
2186
2242
   wsi_destroy_image(&chain->base, &image->base);
2187
2243
 
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;
2682
2738
 
 
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);
 
2746
   }
 
2747
 
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