<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>