<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Mon, Jun 11, 2018 at 10:39 PM, Keith Packard <span dir="ltr"><<a href="mailto:keithp@keithp.com" target="_blank">keithp@keithp.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">This extension adds the ability to borrow an X RandR output for<br>
temporary use directly by a Vulkan application. For DRM, we use the<br>
Linux resource leasing mechanism.<br>
<br>
v2:<br>
        Clean up xlib_lease detection<br>
<br>
        * Use separate temporary '_xlib_lease' variable to hold the<br>
          option value to avoid changin the type of a variable.<br>
<br>
        * Use boolean expressions instead of additional if statements<br>
          to compute resulting with_xlib_lease value.<br>
<br>
        * Simplify addition of VK_USE_PLATFORM_XLIB_XRANDR_KH<wbr>R to<br>
          vulkan_wsi_args<br>
<br>
          Suggested-by: Eric Engestrom <<a href="mailto:eric.engestrom@imgtec.com" target="_blank">eric.engestrom@imgtec.com</a>><br>
<br>
        Move mode list from wsi_display to wsi_display_connector<br>
<br>
        Fix scope for wsi_display_mode and wsi_display_connector allocs<br>
<br>
          Suggested-by: Jason Ekstrand <<a href="mailto:jason@jlekstrand.net" target="_blank">jason@jlekstrand.net</a>><br>
<br>
v3:<br>
        Adopt Jason Ekstrand's coding conventions<br>
<br>
        Declare variables at first use, eliminate extra whitespace<br>
        between types and names. Wrap lines to 80 columns.<br>
<br>
        Explicitly forbid multiple DRM leases. Making the code support<br>
        this looks tricky and will require additional thought.<br>
<br>
        Use xcb_randr_output_t throughout the internals of the<br>
        implementation. Convert at the public API<br>
        (wsi_get_randr_output_display)<wbr>.<br>
<br>
        Clean up check for usable active_crtc (possible when only the<br>
        desired output is connected to the crtc).<br>
<br>
        Suggested-by: Jason Ekstrand <<a href="mailto:jason.ekstrand@intel.com" target="_blank">jason.ekstrand@intel.com</a>><br>
<br>
Signed-off-by: Keith Packard <<a href="mailto:keithp@keithp.com" target="_blank">keithp@keithp.com</a>><br>
<br>
fixup for acquire<br>
<br>
fixup for RROutput type<br>
<br>
Signed-off-by: Keith Packard <<a href="mailto:keithp@keithp.com" target="_blank">keithp@keithp.com</a>><br>
<br>
fixup<br></blockquote><div><br></div><div>Lots of "fixup".  Did you mean to actually comment on what that was?<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
---<br>
 <a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a>                        |  32 ++<br>
 meson.build                         |  11 +<br>
 meson_options.txt                   |   7 +<br>
 src/vulkan/Makefile.am              |   5 +<br>
 src/vulkan/wsi/meson.build          |   5 +<br>
 src/vulkan/wsi/wsi_common_dis<wbr>play.c | 493 ++++++++++++++++++++++++++++<br>
 src/vulkan/wsi/wsi_common_dis<wbr>play.h |  17 +<br>
 7 files changed, 570 insertions(+)<br></blockquote><div> </div><div>[...]<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+static bool<br>
+wsi_display_mode_matches_x(st<wbr>ruct wsi_display_mode *wsi,<br>
+                           xcb_randr_mode_info_t *xcb)<br>
+{<br>
+   return wsi->clock == (xcb->dot_clock + 500) / 1000 &&<br>
+      wsi->hdisplay == xcb->width &&<br>
+      wsi->hsync_start == xcb->hsync_start &&<br>
+      wsi->hsync_end == xcb->hsync_end &&<br>
+      wsi->htotal == xcb->htotal &&<br>
+      wsi->hskew == xcb->hskew &&<br>
+      wsi->vdisplay == xcb->height &&<br>
+      wsi->vsync_start == xcb->vsync_start &&<br>
+      wsi->vsync_end == xcb->vsync_end &&<br>
+      wsi->vtotal == xcb->vtotal &&<br></blockquote><div><br></div><div>You're not checking vscan here.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+      wsi->flags == xcb->mode_flags;<br>
+}<br></blockquote><div><br></div><div>[...]<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+static struct wsi_display_connector *<br>
+wsi_display_get_output(struct wsi_device *wsi_device,<br>
+                       xcb_connection_t *connection,<br>
+                       xcb_randr_output_t output)<br>
+{<br>
+   struct wsi_display *wsi =<br>
+      (struct wsi_display *) wsi_device->wsi[VK_ICD_WSI_PLA<wbr>TFORM_DISPLAY];<br>
+   struct wsi_display_connector *connector;<br>
+   uint32_t connector_id;<br>
+<br>
+   xcb_window_t root = wsi_display_output_to_root(con<wbr>nection, output);<br>
+   if (!root)<br>
+      return NULL;<br>
+<br>
+   xcb_randr_get_screen_resource<wbr>s_cookie_t src =<br>
+      xcb_randr_get_screen_resources<wbr>(connection, root);<br>
+   xcb_randr_get_output_info_coo<wbr>kie_t oic =<br>
+      xcb_randr_get_output_info(conn<wbr>ection, output, XCB_CURRENT_TIME);<br>
+   xcb_randr_get_screen_resource<wbr>s_reply_t *srr =<br>
+      xcb_randr_get_screen_resources<wbr>_reply(connection, src, NULL);<br>
+   xcb_randr_get_output_info_rep<wbr>ly_t *oir =<br>
+      xcb_randr_get_output_info_repl<wbr>y(connection, oic, NULL);<br></blockquote><div><br></div><div>Why are you fetching these here and not lower down?  The only uses of them inside the "if (!connector)" is to free them.  Seems to be a bit of a waste.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
+   /* See if we already have a connector for this output */<br>
+   connector = wsi_display_find_output(wsi_de<wbr>vice, output);<br>
+<br>
+   if (!connector) {<br>
+      xcb_atom_t connector_id_atom = 0;<br>
+<br>
+      /*<br>
+       * Go get the kernel connector ID for this X output<br>
+       */<br>
+      connector_id = wsi_display_output_to_connecto<wbr>r_id(connection,<br>
+                                                        &connector_id_atom,<br>
+                                                        output);<br>
+<br>
+      /* Any X server with lease support will have this atom */<br>
+      if (!connector_id) {<br>
+         free(oir);<br>
+         free(srr);<br>
+         return NULL;<br>
+      }<br>
+<br>
+      /* See if we already have a connector for this id */<br>
+      connector = wsi_display_find_connector(wsi<wbr>_device, connector_id);<br>
+<br>
+      if (connector == NULL) {<br>
+         connector = wsi_display_alloc_connector(ws<wbr>i, connector_id);<br>
+         if (!connector) {<br>
+            free(oir);<br>
+            free(srr);<br>
+            return NULL;<br>
+         }<br>
+         list_addtail(&connector-><wbr>list, &wsi->connectors);<br>
+      }<br>
+      connector->output = output;<br>
+   }<br>
+<br>
+   if (oir && srr) {<br>
+      /* Get X modes and add them */<br>
+<br>
+      connector->connected =<br>
+         oir->connection != XCB_RANDR_CONNECTION_DISCONNEC<wbr>TED;<br>
+<br>
+      wsi_display_invalidate_connect<wbr>or_modes(wsi_device, connector);<br>
+<br>
+      xcb_randr_mode_t *x_modes = xcb_randr_get_output_info_mode<wbr>s(oir);<br>
+      for (int m = 0; m < oir->num_modes; m++) {<br>
+         xcb_randr_mode_info_iterator_<wbr>t i =<br>
+            xcb_randr_get_screen_resources<wbr>_modes_iterator(srr);<br>
+         while (i.rem) {<br>
+            xcb_randr_mode_info_t *mi = i.data;<br>
+            if (mi->id == x_modes[m]) {<br>
+               VkResult result = wsi_display_register_x_mode(<br>
+                  wsi_device, connector, mi, m < oir->num_preferred);<br>
+               if (result != VK_SUCCESS) {<br>
+                  free(oir);<br>
+                  free(srr);<br>
+                  return NULL;<br>
+               }<br>
+               break;<br>
+            }<br>
+            xcb_randr_mode_info_next(&i);<br>
+         }<br>
+      }<br>
+   }<br>
+<br>
+   free(oir);<br>
+   free(srr);<br>
+   return connector;<br>
+}<br></blockquote><div><br></div><div>[...]<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+VkResult<br>
+wsi_acquire_xlib_display(VkPh<wbr>ysicalDevice physical_device,<br>
+                         struct wsi_device *wsi_device,<br>
+                         Display *dpy,<br>
+                         VkDisplayKHR display)<br>
+{<br>
+   struct wsi_display *wsi =<br>
+      (struct wsi_display *) wsi_device->wsi[VK_ICD_WSI_PLA<wbr>TFORM_DISPLAY];<br>
+   xcb_connection_t *connection = XGetXCBConnection(dpy);<br>
+   struct wsi_display_connector *connector =<br>
+      wsi_display_connector_from_han<wbr>dle(display);<br>
+   xcb_window_t root;<br>
+<br>
+   /* XXX no support for multiple leases yet */<br>
+   if (wsi->fd >= 0)<br>
+      return VK_ERROR_OUT_OF_DATE_KHR;<br></blockquote><div><br></div><div>This function is supposed to return either VK_SUCCESS or VK_ERROR_INITIALIZATION_FAILED.  The errors here and below should probably all be VK_ERROR_INITIALIZATION_FAILED.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
+   if (!connector->output) {<br>
+      connector->output = wsi_display_connector_id_to_ou<wbr>tput(connection,<br>
+                                                             connector->id);<br>
+<br>
+      /* Check and see if we found the output */<br>
+      if (!connector->output)<br>
+         return VK_ERROR_OUT_OF_DATE_KHR;<br>
+   }<br>
+<br>
+   root = wsi_display_output_to_root(con<wbr>nection, connector->output);<br>
+   if (!root)<br>
+      return VK_ERROR_OUT_OF_DATE_KHR;<br>
+<br>
+   xcb_randr_crtc_t crtc = wsi_display_find_crtc_for_outp<wbr>ut(connection,<br>
+                                                            root,<br>
+                                                            connector->output);<br>
+<br>
+   if (!crtc)<br>
+      return VK_ERROR_OUT_OF_DATE_KHR;<br>
+<br>
+   xcb_randr_lease_t lease = xcb_generate_id(connection);<br>
+   xcb_randr_create_lease_<wbr>cookie_t cl_c =<br>
+      xcb_randr_create_lease(connect<wbr>ion, root, lease, 1, 1,<br>
+                             &crtc, &connector->output);<br>
+   xcb_randr_create_lease_reply_<wbr>t *cl_r =<br>
+      xcb_randr_create_lease_reply(c<wbr>onnection, cl_c, NULL);<br>
+   if (!cl_r)<br>
+      return VK_ERROR_OUT_OF_DATE_KHR;<br>
+<br>
+   int fd = -1;<br>
+   if (cl_r->nfd > 0) {<br>
+      int *rcl_f = xcb_randr_create_lease_reply_f<wbr>ds(connection, cl_r);<br>
+<br>
+      fd = rcl_f[0];<br>
+   }<br>
+   free (cl_r);<br>
+   if (fd < 0)<br>
+      return VK_ERROR_OUT_OF_DATE_KHR;<br>
+<br>
+   wsi->fd = fd;<br>
+<br>
+   return VK_SUCCESS;<br>
+}<span class="m_6153633376319927332HOEnZb"><font color="#888888"><br></font></span></blockquote><div><br></div><div>Everything else looks good to me.</div><div><br></div><div>--Jason<br></div></div><br></div></div>