xserver: Branch 'master' - 4 commits

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Dec 7 10:45:43 UTC 2021


 .gitlab-ci.yml                   |    2 
 .gitlab-ci/debian-install.sh     |    4 
 hw/xfree86/common/xf86Module.h   |    2 
 hw/xwayland/meson.build          |    9 
 hw/xwayland/xwayland-drm-lease.c |  439 +++++++++++++++++++++++++++++++++++++++
 hw/xwayland/xwayland-drm-lease.h |   67 +++++
 hw/xwayland/xwayland-output.c    |   32 +-
 hw/xwayland/xwayland-output.h    |   23 +-
 hw/xwayland/xwayland-screen.c    |   46 ++++
 hw/xwayland/xwayland-screen.h    |    4 
 hw/xwayland/xwayland-types.h     |    1 
 meson.build                      |    2 
 randr/randrstr.h                 |   12 +
 randr/rrlease.c                  |   27 ++
 14 files changed, 648 insertions(+), 22 deletions(-)

New commits:
commit 089e7f98f86836fdd09fd231bff8004c0fc45381
Author: Drew DeVault <sir at cmpwn.com>
Date:   Thu Jul 25 15:51:33 2019 -0400

    Xwayland: implement drm-lease-v1
    
    This commit allows X11 clients running through Xwayland to lease
    non-desktop connectors from the Wayland compositor by implementing
    support for drm-lease-v1.
    In order to not deadlock with the Wayland compositor if its response
    to a lease request is delayed, the new interface in _rrScrPriv
    introduced in the last commit is used, which makes it possible to
    block the X11 client while a response is pending.
    Leasing normal outputs is not yet supported, all connectors offered
    for lease will be advertised as non-desktop.
    
    Co-authored-by: Xaver Hugl <xaver.hugl at gmail.com>
    Reviewed-by: Simon Ser <contact at emersion.fr>
    Acked-by: Olivier Fourdan <ofourdan at redhat.com>
    Acked-by: Michel Dänzer <mdaenzer at redhat.com>

diff --git a/hw/xwayland/meson.build b/hw/xwayland/meson.build
index 093d7552b..37c39497c 100644
--- a/hw/xwayland/meson.build
+++ b/hw/xwayland/meson.build
@@ -4,6 +4,8 @@ srcs = [
     'xwayland-input.h',
     'xwayland-cursor.c',
     'xwayland-cursor.h',
+    'xwayland-drm-lease.h',
+    'xwayland-drm-lease.c',
     'xwayland-glamor.h',
     'xwayland-glx.h',
     'xwayland-pixmap.c',
@@ -43,6 +45,7 @@ xdg_output_xml = join_paths(protodir, 'unstable', 'xdg-output', 'xdg-output-unst
 dmabuf_xml = join_paths(protodir, 'unstable', 'linux-dmabuf', 'linux-dmabuf-unstable-v1.xml')
 viewporter_xml = join_paths(protodir, 'stable', 'viewporter', 'viewporter.xml')
 xdg_shell_xml = join_paths(protodir, 'stable', 'xdg-shell', 'xdg-shell.xml')
+drm_lease_xml = join_paths(protodir, 'staging', 'drm-lease', 'drm-lease-v1.xml')
 
 client_header = generator(scanner,
     output : '@BASENAME at -client-protocol.h',
@@ -68,6 +71,7 @@ srcs += client_header.process(xdg_output_xml)
 srcs += client_header.process(dmabuf_xml)
 srcs += client_header.process(viewporter_xml)
 srcs += client_header.process(xdg_shell_xml)
+srcs += client_header.process(drm_lease_xml)
 srcs += code.process(relative_xml)
 srcs += code.process(pointer_xml)
 srcs += code.process(gestures_xml)
@@ -77,6 +81,7 @@ srcs += code.process(xdg_output_xml)
 srcs += code.process(dmabuf_xml)
 srcs += code.process(viewporter_xml)
 srcs += code.process(xdg_shell_xml)
+srcs += code.process(drm_lease_xml)
 
 xwayland_glamor = []
 eglstream_srcs = []
@@ -116,6 +121,10 @@ if build_glx
     wayland_inc += glx_inc
 endif
 
+if libdrm_dep.found()
+    xwayland_dep += libdrm_dep
+endif
+
 xwayland_server = executable(
     'Xwayland',
     srcs,
diff --git a/hw/xwayland/xwayland-drm-lease.c b/hw/xwayland/xwayland-drm-lease.c
new file mode 100644
index 000000000..656e6a62d
--- /dev/null
+++ b/hw/xwayland/xwayland-drm-lease.c
@@ -0,0 +1,439 @@
+/*
+ * Copyright © 2020 Drew Devault
+ * Copyright © 2021 Xaver Hugl
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of the
+ * copyright holders not be used in advertising or publicity
+ * pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#include <xwayland-config.h>
+
+#ifdef WITH_LIBDRM
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+#endif
+
+#include "xwayland-drm-lease.h"
+#include "xwayland-screen.h"
+#include "xwayland-output.h"
+
+static void
+drm_lease_handle_lease_fd(void *data,
+                          struct wp_drm_lease_v1 *wp_drm_lease_v1,
+                          int32_t lease_fd)
+{
+    struct xwl_drm_lease *lease = (struct xwl_drm_lease *)data;
+
+    lease->fd = lease_fd;
+    AttendClient(lease->client);
+}
+
+static void
+drm_lease_handle_finished(void *data,
+                          struct wp_drm_lease_v1 *wp_drm_lease_v1)
+{
+    struct xwl_drm_lease *lease = (struct xwl_drm_lease *)data;
+    struct xwl_output *output;
+    int i;
+
+    if (lease->fd >= 0) {
+        RRTerminateLease(lease->rrLease);
+    } else {
+        AttendClient(lease->client);
+        for (i = 0; i < lease->rrLease->numOutputs; ++i) {
+            output = lease->rrLease->outputs[i]->devPrivate;
+            output->lease = NULL;
+        }
+    }
+}
+
+static struct wp_drm_lease_v1_listener drm_lease_listener = {
+    .lease_fd = drm_lease_handle_lease_fd,
+    .finished = drm_lease_handle_finished,
+};
+
+void
+xwl_randr_get_lease(ClientPtr client, ScreenPtr screen, RRLeasePtr *rrLease, int *fd)
+{
+    struct xwl_screen *xwl_screen;
+    struct xwl_drm_lease *lease;
+    xwl_screen = xwl_screen_get(screen);
+
+    xorg_list_for_each_entry(lease, &xwl_screen->drm_leases, link) {
+        if (lease->client == client) {
+            *rrLease = lease->rrLease;
+            *fd = lease->fd;
+            if (lease->fd < 0)
+                xorg_list_del(&lease->link);
+            return;
+        }
+    }
+    *rrLease = NULL;
+    *fd = -1;
+}
+
+int
+xwl_randr_request_lease(ClientPtr client, ScreenPtr screen, RRLeasePtr rrLease)
+{
+    struct xwl_screen *xwl_screen;
+    struct wp_drm_lease_request_v1 *req;
+    struct xwl_drm_lease *lease_private;
+    struct xwl_drm_lease_device *lease_device = NULL;
+    struct xwl_drm_lease_device *device_data;
+    struct xwl_output *output;
+    int i;
+
+    xwl_screen = xwl_screen_get(screen);
+
+    if (xorg_list_is_empty(&xwl_screen->drm_lease_devices)) {
+        ErrorF("Attempted to create DRM lease without wp_drm_lease_device_v1\n");
+        return BadMatch;
+    }
+
+    xorg_list_for_each_entry(device_data, &xwl_screen->drm_lease_devices, link) {
+        Bool connectors_of_device = FALSE;
+        for (i = 0; i < rrLease->numOutputs; ++i) {
+            output = rrLease->outputs[i]->devPrivate;
+            if (output->lease_device == device_data) {
+                connectors_of_device = TRUE;
+                break;
+            }
+        }
+        if (connectors_of_device) {
+            if (lease_device != NULL) {
+                ErrorF("Attempted to create DRM lease from multiple devices\n");
+                return BadValue;
+            }
+            lease_device = device_data;
+        }
+    }
+
+    for (i = 0; i < rrLease->numOutputs; ++i) {
+        output = rrLease->outputs[i]->devPrivate;
+        if (!output || !output->lease_connector || output->lease) {
+            return BadValue;
+        }
+    }
+
+    req = wp_drm_lease_device_v1_create_lease_request(
+            lease_device->drm_lease_device);
+    lease_private = calloc(1, sizeof(struct xwl_drm_lease));
+    for (i = 0; i < rrLease->numOutputs; ++i) {
+        output = rrLease->outputs[i]->devPrivate;
+        output->lease = lease_private;
+        wp_drm_lease_request_v1_request_connector(req, output->lease_connector);
+    }
+    lease_private->fd = -1;
+    lease_private->lease = wp_drm_lease_request_v1_submit(req);
+    lease_private->rrLease = rrLease;
+    lease_private->client = client;
+    rrLease->devPrivate = lease_private;
+
+    wp_drm_lease_v1_add_listener(lease_private->lease,
+                                  &drm_lease_listener, lease_private);
+    xorg_list_add(&lease_private->link, &xwl_screen->drm_leases);
+
+    ResetCurrentRequest(client);
+    client->sequence--;
+    IgnoreClient(client);
+
+    return Success;
+}
+
+void
+xwl_randr_terminate_lease(ScreenPtr screen, RRLeasePtr lease)
+{
+    struct xwl_drm_lease *lease_private = lease->devPrivate;
+
+    if (lease_private) {
+        xorg_list_del(&lease_private->link);
+        if (lease_private->fd >= 0)
+            close(lease_private->fd);
+        wp_drm_lease_v1_destroy(lease_private->lease);
+        free(lease_private);
+        lease->devPrivate = NULL;
+    }
+
+    RRLeaseTerminated(lease);
+}
+
+static void
+lease_connector_handle_name(void *data,
+                            struct wp_drm_lease_connector_v1 *wp_drm_lease_connector_v1,
+                            const char *name)
+{
+    /* This space is deliberately left blank */
+}
+
+static void
+lease_connector_handle_description(void *data,
+                                   struct wp_drm_lease_connector_v1 *wp_drm_lease_connector_v1,
+                                   const char *description)
+{
+    /* This space is deliberately left blank */
+}
+
+static RRModePtr *
+xwl_get_rrmodes_from_connector_id(int drm, int32_t connector_id, int *nmode, int *npref)
+{
+#ifdef WITH_LIBDRM
+    drmModeConnectorPtr conn;
+    drmModeModeInfoPtr kmode;
+    RRModePtr *rrmodes;
+    int pref, i;
+
+    *nmode = *npref = 0;
+
+    conn = drmModeGetConnectorCurrent(drm, connector_id);
+    if (!conn) {
+        ErrorF("drmModeGetConnector for connector %d failed\n", connector_id);
+        return NULL;
+    }
+    rrmodes = xallocarray(conn->count_modes, sizeof(RRModePtr));
+    if (!rrmodes) {
+        ErrorF("Failed to allocate connector modes\n");
+        drmModeFreeConnector(conn);
+        return NULL;
+    }
+
+    /* This spaghetti brought to you courtesey of xf86RandrR12.c
+     * It adds preferred modes first, then non-preferred modes */
+    for (pref = 1; pref >= 0; pref--) {
+        for (i = 0; i < conn->count_modes; ++i) {
+            kmode = &conn->modes[i];
+            if ((pref != 0) == ((kmode->type & DRM_MODE_TYPE_PREFERRED) != 0)) {
+                xRRModeInfo modeInfo;
+                RRModePtr rrmode;
+
+                modeInfo.nameLength = strlen(kmode->name);
+
+                modeInfo.width = kmode->hdisplay;
+                modeInfo.dotClock = kmode->clock * 1000;
+                modeInfo.hSyncStart = kmode->hsync_start;
+                modeInfo.hSyncEnd = kmode->hsync_end;
+                modeInfo.hTotal = kmode->htotal;
+                modeInfo.hSkew = kmode->hskew;
+
+                modeInfo.height = kmode->vdisplay;
+                modeInfo.vSyncStart = kmode->vsync_start;
+                modeInfo.vSyncEnd = kmode->vsync_end;
+                modeInfo.vTotal = kmode->vtotal;
+                modeInfo.modeFlags = kmode->flags;
+
+                rrmode = RRModeGet(&modeInfo, kmode->name);
+                if (rrmode) {
+                    rrmodes[*nmode] = rrmode;
+                    *nmode = *nmode + 1;
+                    *npref = *npref + pref;
+                }
+            }
+        }
+    }
+    /* workaround: there could be no preferred mode that got added */
+    if (*nmode > 0 && *npref == 0)
+        *npref = 1;
+
+    drmModeFreeConnector(conn);
+    return rrmodes;
+#else
+    *nmode = *npref = 0;
+    return NULL;
+#endif
+}
+
+static void
+lease_connector_handle_connector_id(void *data,
+                                    struct wp_drm_lease_connector_v1 *wp_drm_lease_connector_v1,
+                                    uint32_t connector_id)
+{
+    struct xwl_output *output;
+    Atom name;
+    INT32 value;
+    int err;
+    int nmode, npref;
+    RRModePtr *rrmodes;
+
+    value = connector_id;
+    output = (struct xwl_output *)data;
+    name = MakeAtom("CONNECTOR_ID", 12, TRUE);
+
+    if (name != BAD_RESOURCE) {
+        err = RRConfigureOutputProperty(output->randr_output, name,
+                                        FALSE, FALSE, TRUE,
+                                        1, &value);
+        if (err != 0) {
+            ErrorF("RRConfigureOutputProperty error, %d\n", err);
+            return;
+        }
+        err = RRChangeOutputProperty(output->randr_output, name,
+                                     XA_INTEGER, 32, PropModeReplace, 1,
+                                     &value, FALSE, FALSE);
+        if (err != 0) {
+            ErrorF("RRChangeOutputProperty error, %d\n", err);
+            return;
+        }
+    }
+    rrmodes = xwl_get_rrmodes_from_connector_id(output->lease_device->drm_read_only_fd,
+                                                connector_id, &nmode, &npref);
+
+    if (rrmodes != NULL)
+        RROutputSetModes(output->randr_output, rrmodes, nmode, npref);
+
+    free(rrmodes);
+}
+
+static void
+lease_connector_handle_done(void *data,
+                            struct wp_drm_lease_connector_v1 *wp_drm_lease_connector_v1)
+{
+    /* This space is deliberately left blank */
+}
+
+static void
+lease_connector_handle_withdrawn(void *data,
+                                 struct wp_drm_lease_connector_v1 *wp_drm_lease_connector_v1)
+{
+    xwl_output_remove(data);
+}
+
+static const struct wp_drm_lease_connector_v1_listener lease_connector_listener = {
+    .name = lease_connector_handle_name,
+    .description = lease_connector_handle_description,
+    .connector_id = lease_connector_handle_connector_id,
+    .withdrawn = lease_connector_handle_withdrawn,
+    .done = lease_connector_handle_done,
+};
+
+static void
+drm_lease_device_handle_drm_fd(void *data,
+                               struct wp_drm_lease_device_v1 *wp_drm_lease_device_v1,
+                               int fd)
+{
+    ((struct xwl_drm_lease_device *)data)->drm_read_only_fd = fd;
+}
+
+static void
+drm_lease_device_handle_connector(void *data,
+                                  struct wp_drm_lease_device_v1 *wp_drm_lease_device_v1,
+                                  struct wp_drm_lease_connector_v1 *connector)
+{
+    struct xwl_drm_lease_device *lease_device = data;
+    struct xwl_output *xwl_output;
+    char name[256];
+
+    xwl_output = calloc(1, sizeof *xwl_output);
+    if (xwl_output == NULL) {
+        ErrorF("%s ENOMEM\n", __func__);
+        return;
+    }
+
+    snprintf(name, sizeof name, "XWAYLAND%d", xwl_get_next_output_serial());
+
+    xwl_output->lease_device = lease_device;
+    xwl_output->xwl_screen = lease_device->xwl_screen;
+    xwl_output->lease_connector = connector;
+    xwl_output->randr_crtc = RRCrtcCreate(lease_device->xwl_screen->screen, xwl_output);
+    if (!xwl_output->randr_crtc) {
+        ErrorF("Failed creating RandR CRTC\n");
+        goto err;
+    }
+    RRCrtcSetRotations(xwl_output->randr_crtc, ALL_ROTATIONS);
+    xwl_output->randr_output = RROutputCreate(lease_device->xwl_screen->screen,
+                                              name, strlen(name), xwl_output);
+    if (!xwl_output->randr_output) {
+        ErrorF("Failed creating RandR Output\n");
+        goto err;
+    }
+
+    RRCrtcGammaSetSize(xwl_output->randr_crtc, 256);
+    RROutputSetCrtcs(xwl_output->randr_output, &xwl_output->randr_crtc, 1);
+    RROutputSetConnection(xwl_output->randr_output, RR_Connected);
+    RROutputSetNonDesktop(xwl_output->randr_output, TRUE);
+    xwl_output->randr_output->devPrivate = xwl_output;
+
+    wp_drm_lease_connector_v1_add_listener(connector,
+                                            &lease_connector_listener,
+                                            xwl_output);
+
+    xorg_list_append(&xwl_output->link, &lease_device->xwl_screen->output_list);
+    return;
+
+err:
+    if (xwl_output->randr_crtc)
+        RRCrtcDestroy(xwl_output->randr_crtc);
+    free(xwl_output);
+}
+
+static void
+drm_lease_device_handle_released(void *data,
+                                 struct wp_drm_lease_device_v1 *wp_drm_lease_device_v1)
+{
+    xwl_screen_destroy_drm_lease_device(data, wp_drm_lease_device_v1);
+}
+
+static void
+drm_lease_device_handle_done(void *data,
+                             struct wp_drm_lease_device_v1 *wp_drm_lease_device_v1)
+{
+    /* This space is deliberately left blank */
+}
+
+static const struct wp_drm_lease_device_v1_listener drm_lease_device_listener = {
+    .drm_fd = drm_lease_device_handle_drm_fd,
+    .connector = drm_lease_device_handle_connector,
+    .released = drm_lease_device_handle_released,
+    .done = drm_lease_device_handle_done,
+};
+
+void
+xwl_screen_add_drm_lease_device(struct xwl_screen *xwl_screen, uint32_t id)
+{
+    struct wp_drm_lease_device_v1 *lease_device = wl_registry_bind(
+        xwl_screen->registry, id, &wp_drm_lease_device_v1_interface, 1);
+    struct xwl_drm_lease_device *device_data = malloc(sizeof(struct xwl_drm_lease_device));
+
+    device_data->drm_lease_device = lease_device;
+    device_data->xwl_screen = xwl_screen;
+    device_data->drm_read_only_fd = -1;
+    device_data->id = id;
+    xorg_list_add(&device_data->link, &xwl_screen->drm_lease_devices);
+    wp_drm_lease_device_v1_add_listener(lease_device,
+                                         &drm_lease_device_listener,
+                                         device_data);
+}
+
+void
+xwl_screen_destroy_drm_lease_device(struct xwl_screen *xwl_screen,
+                                    struct wp_drm_lease_device_v1 *wp_drm_lease_device_v1)
+{
+    struct xwl_drm_lease_device *device_data;
+
+    xorg_list_for_each_entry(device_data, &xwl_screen->drm_lease_devices, link) {
+        if (device_data->drm_lease_device == wp_drm_lease_device_v1) {
+            wp_drm_lease_device_v1_destroy(wp_drm_lease_device_v1);
+            xorg_list_del(&device_data->link);
+            if (device_data->drm_read_only_fd >= 0)
+                close(device_data->drm_read_only_fd);
+            free(device_data);
+            return;
+        }
+    }
+}
diff --git a/hw/xwayland/xwayland-drm-lease.h b/hw/xwayland/xwayland-drm-lease.h
new file mode 100644
index 000000000..aa5aed63c
--- /dev/null
+++ b/hw/xwayland/xwayland-drm-lease.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright © 2020 Drew Devault
+ * Copyright © 2021 Xaver Hugl
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of the
+ * copyright holders not be used in advertising or publicity
+ * pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#ifndef XWAYLAND_DRM_LEASE_H
+#define XWAYLAND_DRM_LEASE_H
+
+#include <X11/Xatom.h>
+#include <randrstr.h>
+
+#include "xwayland-types.h"
+#include "list.h"
+
+#include "drm-lease-v1-client-protocol.h"
+
+struct xwl_drm_lease_device {
+    struct xorg_list link;
+    struct wp_drm_lease_device_v1 *drm_lease_device;
+    int drm_read_only_fd;
+    struct xwl_screen *xwl_screen;
+    uint32_t id;
+};
+
+struct xwl_queued_drm_lease_device {
+    struct xorg_list link;
+    uint32_t id;
+};
+
+struct xwl_drm_lease {
+    struct xorg_list link;
+    struct wp_drm_lease_v1 *lease;
+    RRLeasePtr rrLease;
+    ClientPtr client;
+    int fd;
+};
+
+int xwl_randr_request_lease(ClientPtr client, ScreenPtr screen, RRLeasePtr rrLease);
+void xwl_randr_get_lease(ClientPtr client, ScreenPtr screen, RRLeasePtr *rrLease, int *fd);
+void xwl_randr_terminate_lease(ScreenPtr screen, RRLeasePtr lease);
+
+void xwl_screen_add_drm_lease_device(struct xwl_screen *xwl_screen, uint32_t id);
+void xwl_screen_destroy_drm_lease_device(struct xwl_screen *xwl_screen,
+                                         struct wp_drm_lease_device_v1 *wp_drm_lease_device_v1);
+
+#endif /* XWAYLAND_DRM_LEASE_H */
diff --git a/hw/xwayland/xwayland-output.c b/hw/xwayland/xwayland-output.c
index 1f22c4cf6..d2fa4e0bb 100644
--- a/hw/xwayland/xwayland-output.c
+++ b/hw/xwayland/xwayland-output.c
@@ -35,13 +35,6 @@
 
 #include "xdg-output-unstable-v1-client-protocol.h"
 
-#define ALL_ROTATIONS (RR_Rotate_0   | \
-                       RR_Rotate_90  | \
-                       RR_Rotate_180 | \
-                       RR_Rotate_270 | \
-                       RR_Reflect_X  | \
-                       RR_Reflect_Y)
-
 static void xwl_output_get_xdg_output(struct xwl_output *xwl_output);
 
 static Rotation
@@ -731,7 +724,6 @@ struct xwl_output *
 xwl_output_create(struct xwl_screen *xwl_screen, uint32_t id)
 {
     struct xwl_output *xwl_output;
-    static int serial;
     char name[256];
 
     xwl_output = calloc(1, sizeof *xwl_output);
@@ -750,7 +742,7 @@ xwl_output_create(struct xwl_screen *xwl_screen, uint32_t id)
     xwl_output->server_output_id = id;
     wl_output_add_listener(xwl_output->output, &output_listener, xwl_output);
 
-    snprintf(name, sizeof name, "XWAYLAND%d", serial++);
+    snprintf(name, sizeof name, "XWAYLAND%d", xwl_get_next_output_serial());
 
     xwl_output->xwl_screen = xwl_screen;
     xwl_output->randr_crtc = RRCrtcCreate(xwl_screen->screen, xwl_output);
@@ -795,9 +787,12 @@ err:
 void
 xwl_output_destroy(struct xwl_output *xwl_output)
 {
+    if (xwl_output->lease_connector)
+        wp_drm_lease_connector_v1_destroy(xwl_output->lease_connector);
     if (xwl_output->xdg_output)
         zxdg_output_v1_destroy(xwl_output->xdg_output);
-    wl_output_destroy(xwl_output->output);
+    if (xwl_output->output)
+        wl_output_destroy(xwl_output->output);
     free(xwl_output);
 }
 
@@ -946,6 +941,10 @@ xwl_screen_init_output(struct xwl_screen *xwl_screen)
     rp->rrModeDestroy = xwl_randr_mode_destroy;
 #endif
 
+    rp->rrRequestLease = xwl_randr_request_lease;
+    rp->rrGetLease = xwl_randr_get_lease;
+    rp->rrTerminateLease = xwl_randr_terminate_lease;
+
     return TRUE;
 }
 
@@ -954,6 +953,12 @@ xwl_output_get_xdg_output(struct xwl_output *xwl_output)
 {
     struct xwl_screen *xwl_screen = xwl_output->xwl_screen;
 
+    if (!xwl_output->output) {
+        /* This can happen when an output is created from a leasable DRM
+         * connector */
+        return;
+    }
+
     xwl_output->xdg_output =
         zxdg_output_manager_v1_get_xdg_output (xwl_screen->xdg_output_manager,
                                                xwl_output->output);
@@ -973,3 +978,10 @@ xwl_screen_init_xdg_output(struct xwl_screen *xwl_screen)
     xorg_list_for_each_entry(it, &xwl_screen->output_list, link)
         xwl_output_get_xdg_output(it);
 }
+
+int
+xwl_get_next_output_serial(void)
+{
+    static int output_name_serial = 0;
+    return output_name_serial++;
+}
diff --git a/hw/xwayland/xwayland-output.h b/hw/xwayland/xwayland-output.h
index 02b983108..74a46994f 100644
--- a/hw/xwayland/xwayland-output.h
+++ b/hw/xwayland/xwayland-output.h
@@ -34,19 +34,34 @@
 #include <randrstr.h>
 
 #include "xwayland-types.h"
+#include "xwayland-drm-lease.h"
+
+#define ALL_ROTATIONS (RR_Rotate_0   | \
+                       RR_Rotate_90  | \
+                       RR_Rotate_180 | \
+                       RR_Rotate_270 | \
+                       RR_Reflect_X  | \
+                       RR_Reflect_Y)
 
 struct xwl_output {
     struct xorg_list link;
-    struct wl_output *output;
-    struct zxdg_output_v1 *xdg_output;
-    uint32_t server_output_id;
     struct xwl_screen *xwl_screen;
     RROutputPtr randr_output;
     RRCrtcPtr randr_crtc;
+
+    /* only for regular outputs */
+    struct wl_output *output;
+    struct zxdg_output_v1 *xdg_output;
+    uint32_t server_output_id;
     int32_t x, y, width, height, refresh;
     Rotation rotation;
     Bool wl_output_done;
     Bool xdg_output_done;
+
+    /* only for lease-able DRM connectors */
+    struct wp_drm_lease_connector_v1 *lease_connector;
+    struct xwl_drm_lease *lease;
+    struct xwl_drm_lease_device *lease_device;
 };
 
 /* Per client per output emulated randr/vidmode resolution info. */
@@ -79,4 +94,6 @@ void xwl_output_set_window_randr_emu_props(struct xwl_screen *xwl_screen,
 
 void xwl_screen_init_xdg_output(struct xwl_screen *xwl_screen);
 
+int xwl_get_next_output_serial(void);
+
 #endif /* XWAYLAND_OUTPUT_H */
diff --git a/hw/xwayland/xwayland-screen.c b/hw/xwayland/xwayland-screen.c
index b39a3d2fd..b249dbb08 100644
--- a/hw/xwayland/xwayland-screen.c
+++ b/hw/xwayland/xwayland-screen.c
@@ -149,6 +149,24 @@ xwl_property_callback(CallbackListPtr *pcbl, void *closure,
         xwl_window_update_property(xwl_window, rec);
 }
 
+static void
+xwl_root_window_finalized_callback(CallbackListPtr *pcbl,
+                                   void *closure,
+                                   void *calldata)
+{
+    ScreenPtr screen = closure;
+    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+    struct xwl_queued_drm_lease_device *queued_device, *next;
+
+    xorg_list_for_each_entry_safe(queued_device, next,
+                                  &xwl_screen->queued_drm_lease_devices, link) {
+        xwl_screen_add_drm_lease_device(xwl_screen, queued_device->id);
+        xorg_list_del(&queued_device->link);
+        free(queued_device);
+    }
+    DeleteCallback(&RootWindowFinalizeCallback, xwl_root_window_finalized_callback, screen);
+}
+
 Bool
 xwl_close_screen(ScreenPtr screen)
 {
@@ -168,6 +186,12 @@ xwl_close_screen(ScreenPtr screen)
 
     xwl_screen_release_tablet_manager(xwl_screen);
 
+    struct xwl_drm_lease_device *device_data, *next;
+    xorg_list_for_each_entry_safe(device_data, next,
+                                  &xwl_screen->drm_lease_devices, link)
+        xwl_screen_destroy_drm_lease_device(xwl_screen,
+                                            device_data->drm_lease_device);
+
     RemoveNotifyFd(xwl_screen->wayland_fd);
 
     wl_display_disconnect(xwl_screen->display);
@@ -392,6 +416,15 @@ registry_global(void *data, struct wl_registry *registry, uint32_t id,
             wl_registry_bind(registry, id, &zxdg_output_manager_v1_interface, version);
         xwl_screen_init_xdg_output(xwl_screen);
     }
+    else if (strcmp(interface, "wp_drm_lease_device_v1") == 0) {
+        if (xwl_screen->screen->root == NULL) {
+            struct xwl_queued_drm_lease_device *queued = malloc(sizeof(struct xwl_queued_drm_lease_device));
+            queued->id = id;
+            xorg_list_append(&queued->link, &xwl_screen->queued_drm_lease_devices);
+        } else {
+            xwl_screen_add_drm_lease_device(xwl_screen, id);
+        }
+    }
     else if (strcmp(interface, "wp_viewporter") == 0) {
         xwl_screen->viewporter = wl_registry_bind(registry, id, &wp_viewporter_interface, 1);
     }
@@ -408,6 +441,7 @@ global_remove(void *data, struct wl_registry *registry, uint32_t name)
 {
     struct xwl_screen *xwl_screen = data;
     struct xwl_output *xwl_output, *tmp_xwl_output;
+    struct xwl_drm_lease_device *lease_device, *tmp_lease_device;
 
     xorg_list_for_each_entry_safe(xwl_output, tmp_xwl_output,
                                   &xwl_screen->output_list, link) {
@@ -416,6 +450,14 @@ global_remove(void *data, struct wl_registry *registry, uint32_t name)
             break;
         }
     }
+
+    xorg_list_for_each_entry_safe(lease_device, tmp_lease_device,
+                                  &xwl_screen->drm_lease_devices, link) {
+        if (lease_device->id == name) {
+            wp_drm_lease_device_v1_release(lease_device->drm_lease_device);
+            break;
+        }
+    }
 }
 
 static const struct wl_registry_listener registry_listener = {
@@ -619,6 +661,9 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
     xorg_list_init(&xwl_screen->seat_list);
     xorg_list_init(&xwl_screen->damage_window_list);
     xorg_list_init(&xwl_screen->window_list);
+    xorg_list_init(&xwl_screen->drm_lease_devices);
+    xorg_list_init(&xwl_screen->queued_drm_lease_devices);
+    xorg_list_init(&xwl_screen->drm_leases);
     xwl_screen->depth = 24;
 
     if (!monitorResolution)
@@ -744,6 +789,7 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
         return FALSE;
 
     AddCallback(&PropertyStateCallback, xwl_property_callback, pScreen);
+    AddCallback(&RootWindowFinalizeCallback, xwl_root_window_finalized_callback, pScreen);
 
     xwl_screen_roundtrip(xwl_screen);
 
diff --git a/hw/xwayland/xwayland-screen.h b/hw/xwayland/xwayland-screen.h
index 137e94b55..f04d431c7 100644
--- a/hw/xwayland/xwayland-screen.h
+++ b/hw/xwayland/xwayland-screen.h
@@ -36,6 +36,7 @@
 #include "xwayland-types.h"
 #include "xwayland-output.h"
 #include "xwayland-glamor.h"
+#include "xwayland-drm-lease.h"
 
 struct xwl_format {
     uint32_t format;
@@ -87,6 +88,9 @@ struct xwl_screen {
     struct zwp_linux_dmabuf_v1 *dmabuf;
     struct zxdg_output_manager_v1 *xdg_output_manager;
     struct wp_viewporter *viewporter;
+    struct xorg_list drm_lease_devices;
+    struct xorg_list queued_drm_lease_devices;
+    struct xorg_list drm_leases;
     uint32_t serial;
 
 #define XWL_FORMAT_ARGB8888 (1 << 0)
diff --git a/hw/xwayland/xwayland-types.h b/hw/xwayland/xwayland-types.h
index da80ff98e..e70e56320 100644
--- a/hw/xwayland/xwayland-types.h
+++ b/hw/xwayland/xwayland-types.h
@@ -30,5 +30,6 @@ struct xwl_pixmap;
 struct xwl_window;
 struct xwl_screen;
 struct xwl_egl_backend;
+struct xwl_drm_lease;
 
 #endif /* XWAYLAND_TYPES_H */
commit 7759743c6387f72faa9eb8602ea3f2777c0e0d17
Author: Xaver Hugl <xaver.hugl at gmail.com>
Date:   Thu Dec 2 13:22:53 2021 +0100

    randr: add new interface to allow delaying lease responses
    
    Add a new interface to _rrScrPriv to make it possible for the server to
    delay answering a lease request, at the cost of blocking the client. This
    is needed for implementing drm-lease-v1, as the Wayland protocol has no
    defined time table for responding to lease requests.
    
    Signed-off-by: Xaver Hugl <xaver.hugl at gmail.com>
    Acked-by: Michel Dänzer <mdaenzer at redhat.com>

diff --git a/hw/xfree86/common/xf86Module.h b/hw/xfree86/common/xf86Module.h
index 1eb09bca3..33cf0e56a 100644
--- a/hw/xfree86/common/xf86Module.h
+++ b/hw/xfree86/common/xf86Module.h
@@ -74,7 +74,7 @@
  * mask is 0xFFFF0000.
  */
 #define ABI_ANSIC_VERSION	SET_ABI_VERSION(0, 4)
-#define ABI_VIDEODRV_VERSION	SET_ABI_VERSION(25, 2)
+#define ABI_VIDEODRV_VERSION	SET_ABI_VERSION(25, 3)
 #define ABI_XINPUT_VERSION	SET_ABI_VERSION(24, 4)
 #define ABI_EXTENSION_VERSION	SET_ABI_VERSION(10, 0)
 
diff --git a/randr/randrstr.h b/randr/randrstr.h
index b23390575..173ecdf4e 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -280,6 +280,15 @@ typedef int (*RRCreateLeaseProcPtr)(ScreenPtr screen,
 typedef void (*RRTerminateLeaseProcPtr)(ScreenPtr screen,
                                         RRLeasePtr lease);
 
+typedef int (*RRRequestLeaseProcPtr)(ClientPtr client,
+                                     ScreenPtr screen,
+                                     RRLeasePtr lease);
+
+typedef void (*RRGetLeaseProcPtr)(ClientPtr client,
+                                 ScreenPtr screen,
+                                 RRLeasePtr *lease,
+                                 int *fd);
+
 /* These are for 1.0 compatibility */
 
 typedef struct _rrRefresh {
@@ -408,6 +417,9 @@ typedef struct _rrScrPriv {
     RRMonitorPtr *monitors;
 
     struct xorg_list leases;
+
+    RRRequestLeaseProcPtr rrRequestLease;
+    RRGetLeaseProcPtr rrGetLease;
 } rrScrPrivRec, *rrScrPrivPtr;
 
 extern _X_EXPORT DevPrivateKeyRec rrPrivKeyRec;
diff --git a/randr/rrlease.c b/randr/rrlease.c
index 11ba96f24..cb366e767 100644
--- a/randr/rrlease.c
+++ b/randr/rrlease.c
@@ -239,9 +239,19 @@ ProcRRCreateLease(ClientPtr client)
     if (!scr_priv)
         return BadMatch;
 
-    if (!scr_priv->rrCreateLease)
+    if (!scr_priv->rrCreateLease && !scr_priv->rrRequestLease)
         return BadMatch;
 
+    if (scr_priv->rrGetLease) {
+        scr_priv->rrGetLease(client, screen, &lease, &fd);
+        if (lease) {
+            if (fd >= 0)
+                goto leaseReturned;
+            else
+                goto bail_lease;
+        }
+    }
+
     /* Allocate a structure to hold all of the lease information */
 
     lease = RRLeaseAlloc(screen, stuff->lid, stuff->nCrtcs, stuff->nOutputs);
@@ -291,10 +301,19 @@ ProcRRCreateLease(ClientPtr client)
         lease->outputs[o] = output;
     }
 
-    rc = scr_priv->rrCreateLease(screen, lease, &fd);
-    if (rc != Success)
-        goto bail_lease;
+    if (scr_priv->rrRequestLease) {
+        rc = scr_priv->rrRequestLease(client, screen, lease);
+        if (rc == Success)
+            return Success;
+        else
+            goto bail_lease;
+    } else {
+        rc = scr_priv->rrCreateLease(screen, lease, &fd);
+        if (rc != Success)
+            goto bail_lease;
+    }
 
+leaseReturned:
     xorg_list_add(&lease->list, &scr_priv->leases);
 
     if (!AddResource(stuff->lid, RRLeaseType, lease)) {
commit f34ffdd9a92afc6cb2b319c49d4e06e56cf8f70e
Author: Xaver Hugl <xaver.hugl at gmail.com>
Date:   Fri Oct 22 00:30:16 2021 +0200

    require wayland-protocols 1.22
    
    This is needed for implementing drm-lease-v1
    
    Signed-off-by: Xaver Hugl <xaver.hugl at gmail.com>
    Acked-by: Michel Dänzer <mdaenzer at redhat.com>

diff --git a/meson.build b/meson.build
index a4f59aeda..db1d63f3e 100644
--- a/meson.build
+++ b/meson.build
@@ -64,7 +64,7 @@ libdrm_req = '>= 2.4.89'
 libselinux_req = '>= 2.0.86'
 xext_req = '>= 1.0.99.4'
 wayland_req = '>= 1.5.0'
-wayland_protocols_req = '>= 1.18'
+wayland_protocols_req = '>= 1.22'
 gbm_req = '>= 10.2'
 xf86dgaproto_req = '>= 2.0.99.1'
 
commit fabd6a7c6504469f062d41d92b4701502ad82a3b
Author: Xaver Hugl <xaver.hugl at gmail.com>
Date:   Fri Oct 22 00:26:43 2021 +0200

    Update the CI to provide wayland-protocols 1.22
    
    This is needed for implementing drm-lease-v1
    
    Signed-off-by: Xaver Hugl <xaver.hugl at gmail.com>
    Acked-by: Michel Dänzer <mdaenzer at redhat.com>

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index ed4c7da7c..c7851fbf7 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -11,7 +11,7 @@ variables:
     FDO_UPSTREAM_REPO: xorg/xserver
     FDO_DISTRIBUTION_VERSION: buster-slim
     FDO_DISTRIBUTION_EXEC: 'env FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} bash .gitlab-ci/debian-install.sh'
-    FDO_DISTRIBUTION_TAG: "2021-07-09"
+    FDO_DISTRIBUTION_TAG: "2021-10-22"
 
 include:
   - project: 'freedesktop/ci-templates'
diff --git a/.gitlab-ci/debian-install.sh b/.gitlab-ci/debian-install.sh
index 16003e8a4..89ca49e14 100644
--- a/.gitlab-ci/debian-install.sh
+++ b/.gitlab-ci/debian-install.sh
@@ -131,8 +131,8 @@ ninja -C _build -j${FDO_CI_CONCURRENT:-4} install
 cd ..
 rm -rf wayland
 
-# Xwayland requires wayland-protocols >= 1.18, but Debian buster has 1.17 only
-git clone https://gitlab.freedesktop.org/wayland/wayland-protocols.git --depth 1 --branch=1.18
+# Xwayland requires wayland-protocols >= 1.22, but Debian buster has 1.17 only
+git clone https://gitlab.freedesktop.org/wayland/wayland-protocols.git --depth 1 --branch=1.22
 cd wayland-protocols
 ./autogen.sh
 make -j${FDO_CI_CONCURRENT:-4} install


More information about the xorg-commit mailing list