drm-lease: Add weston DRM lease integration 12/26112/4
authorDamian Hobson-Garcia <dhobsong@igel.co.jp>
Thu, 4 Feb 2021 07:13:41 +0000 (16:13 +0900)
committerDamian Hobson-Garcia <dhobsong@igel.co.jp>
Tue, 9 Mar 2021 08:25:21 +0000 (17:25 +0900)
Allow option for weston to use a DRM lease instead of the primary DRM
device node when using the DRM backend.

EGL clients will require a wayland EGL driver than can does not
need DRM authentication. e.g. an implementation based on DRM render
nodes.

Bug-AGL: SPEC-3730

Change-Id: I12f6d5b5df62a90702431010ab685e3b0654912b
Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
meta-agl-drm-lease/README.md
meta-agl-drm-lease/recipes-graphics/weston/weston/0001-backend-drm-Add-method-to-import-DRM-fd.patch [new file with mode: 0644]
meta-agl-drm-lease/recipes-graphics/weston/weston/0002-Add-DRM-lease-support.patch [new file with mode: 0644]
meta-agl-drm-lease/recipes-graphics/weston/weston_8.0.0.bbappend [new file with mode: 0644]

index e397e6a..2c5ba05 100644 (file)
@@ -14,9 +14,10 @@ Enable the  `agl-drm-lease` AGL feature when setting up your build environment
 with aglsetup.sh.
 
 This will add the `drm-lease-manager` package to the image, and will add DRM
-lease support to some packages.
+lease support to the following packages:
+ * weston
+ * kmscube
 
-Currently, only the `kmscube` sample application has support for DRM lease.  
 `kmscube` is not included in the image by default. To add the package to the
 image, add the following to your local.conf
 
@@ -37,6 +38,14 @@ This will create 1 lease for each output connection on the platform.
 The name of each lease will be in the form of `card0-<output name>`
 (eg. `card0-LVDS-1` or `card0-HDMI-A-1`)
 
+## Running weston
+
+weston can be started on any available DRM lease by running with the
+`--drm-lease=<lease name>` option. Eg:
+```
+  # weston --drm-lease=card0-HDMI-A-1
+```
+
 ## Running kmscube sample
 
 With the `drm-lease-manager` running `kmscube` can display on any available
diff --git a/meta-agl-drm-lease/recipes-graphics/weston/weston/0001-backend-drm-Add-method-to-import-DRM-fd.patch b/meta-agl-drm-lease/recipes-graphics/weston/weston/0001-backend-drm-Add-method-to-import-DRM-fd.patch
new file mode 100644 (file)
index 0000000..da3a0c6
--- /dev/null
@@ -0,0 +1,205 @@
+From e7d843e3a2af9ed04569f4ec94d3f558ab2aeede Mon Sep 17 00:00:00 2001
+From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
+Date: Wed, 20 Jan 2021 16:25:39 +0900
+Subject: [PATCH 1/2] backend-drm: Add method to import DRM fd
+
+Allow the compositor to provide a file descriptor for a
+DRM device.
+
+This allows the compositor to bypass the launcher backends
+and to get a DRM file descriptor from an external
+resource manager, such as one that can create DRM leases,
+and pass it to the DRM backend for use.
+
+Having the DRM device management in the compositor allows for
+integrating a platform specific resource manager without having
+to add extra dependencies to the generic libweston code.
+---
+ compositor/main.c               |  1 +
+ include/libweston/backend-drm.h |  7 +++
+ libweston/backend-drm/drm.c     | 76 ++++++++++++++++++++++++---------
+ 3 files changed, 65 insertions(+), 19 deletions(-)
+
+diff --git a/compositor/main.c b/compositor/main.c
+index 8eb8a470..7d5373f7 100644
+--- a/compositor/main.c
++++ b/compositor/main.c
+@@ -2510,6 +2510,7 @@ load_drm_backend(struct weston_compositor *c,
+       config.base.struct_version = WESTON_DRM_BACKEND_CONFIG_VERSION;
+       config.base.struct_size = sizeof(struct weston_drm_backend_config);
+       config.configure_device = configure_input_device;
++      config.device_fd = -1;
+       wet->heads_changed_listener.notify = drm_heads_changed;
+       weston_compositor_add_heads_changed_listener(c,
+diff --git a/include/libweston/backend-drm.h b/include/libweston/backend-drm.h
+index f6647e28..a62c8996 100644
+--- a/include/libweston/backend-drm.h
++++ b/include/libweston/backend-drm.h
+@@ -223,6 +223,13 @@ struct weston_drm_backend_config {
+       /** Use shadow buffer if using Pixman-renderer. */
+       bool use_pixman_shadow;
++
++      /** DRM device file descriptor to use
++         *
++         * An openeded DRM device file descriptor.  If <0, open a DRM
++         * device in the backend using `specific_device` or heuristics.
++         */
++      int device_fd;
+ };
+ #ifdef  __cplusplus
+diff --git a/libweston/backend-drm/drm.c b/libweston/backend-drm/drm.c
+index e3169b6e..300c9ff6 100644
+--- a/libweston/backend-drm/drm.c
++++ b/libweston/backend-drm/drm.c
+@@ -40,6 +40,7 @@
+ #include <linux/vt.h>
+ #include <assert.h>
+ #include <sys/mman.h>
++#include <sys/stat.h>
+ #include <time.h>
+ #include <xf86drm.h>
+@@ -2486,29 +2487,22 @@ drm_device_changed(struct weston_compositor *compositor,
+       wl_signal_emit(&compositor->session_signal, compositor);
+ }
+-/**
+- * Determines whether or not a device is capable of modesetting. If successful,
+- * sets b->drm.fd and b->drm.filename to the opened device.
+- */
+ static bool
+-drm_device_is_kms(struct drm_backend *b, struct udev_device *device)
++drm_backend_update_kms_device(struct drm_backend *b, struct udev_device *device,
++                const char *name, int drm_fd)
+ {
+-      const char *filename = udev_device_get_devnode(device);
+       const char *sysnum = udev_device_get_sysnum(device);
+       dev_t devnum = udev_device_get_devnum(device);
+       drmModeRes *res;
+-      int id = -1, fd;
++      int id = -1;
+-      if (!filename)
++      if (!name)
+               return false;
+-      fd = weston_launcher_open(b->compositor->launcher, filename, O_RDWR);
+-      if (fd < 0)
+-              return false;
+-      res = drmModeGetResources(fd);
++      res = drmModeGetResources(drm_fd);
+       if (!res)
+-              goto out_fd;
++              return false;
+       if (res->count_crtcs <= 0 || res->count_connectors <= 0 ||
+           res->count_encoders <= 0)
+@@ -2517,7 +2511,7 @@ drm_device_is_kms(struct drm_backend *b, struct udev_device *device)
+       if (sysnum)
+               id = atoi(sysnum);
+       if (!sysnum || id < 0) {
+-              weston_log("couldn't get sysnum for device %s\n", filename);
++              weston_log("couldn't get sysnum for device %s\n", name);
+               goto out_res;
+       }
+@@ -2527,9 +2521,9 @@ drm_device_is_kms(struct drm_backend *b, struct udev_device *device)
+               weston_launcher_close(b->compositor->launcher, b->drm.fd);
+       free(b->drm.filename);
+-      b->drm.fd = fd;
++      b->drm.fd = drm_fd;
+       b->drm.id = id;
+-      b->drm.filename = strdup(filename);
++      b->drm.filename = strdup(name);
+       b->drm.devnum = devnum;
+       drmModeFreeResources(res);
+@@ -2538,11 +2532,33 @@ drm_device_is_kms(struct drm_backend *b, struct udev_device *device)
+ out_res:
+       drmModeFreeResources(res);
+-out_fd:
+-      weston_launcher_close(b->compositor->launcher, fd);
+       return false;
+ }
++/**
++ * Determines whether or not a device is capable of modesetting. If successful,
++ * sets b->drm.fd and b->drm.filename to the opened device.
++ */
++static bool
++drm_device_is_kms(struct drm_backend *b, struct udev_device *device)
++{
++      int fd;
++      const char *filename = udev_device_get_devnode(device);
++      if (!filename)
++              return false;
++
++      fd = weston_launcher_open(b->compositor->launcher, filename, O_RDWR);
++      if (fd < 0)
++              return false;
++
++      if (!drm_backend_update_kms_device(b, device, filename, fd)) {
++              weston_launcher_close(b->compositor->launcher, fd);
++              return false;
++      }
++
++      return true;
++}
++
+ /*
+  * Find primary GPU
+  * Some systems may have multiple DRM devices attached to a single seat. This
+@@ -2630,6 +2646,25 @@ find_primary_gpu(struct drm_backend *b, const char *seat)
+       return drm_device;
+ }
++static struct udev_device *
++import_drm_device_fd(struct drm_backend *b, int fd)
++{
++      struct udev_device *device;
++      struct stat s;
++
++      if (fstat(fd, &s) < 0 || !S_ISCHR(s.st_mode))
++              return NULL;
++
++      device = udev_device_new_from_devnum(b->udev, 'c', s.st_rdev);
++      if (!device)
++              return NULL;
++
++      if (!drm_backend_update_kms_device(b, device, "imported DRM device fd", fd))
++              return NULL;
++
++      return device;
++}
++
+ static struct udev_device *
+ open_specific_drm_device(struct drm_backend *b, const char *name)
+ {
+@@ -2854,7 +2889,9 @@ drm_backend_create(struct weston_compositor *compositor,
+       b->session_listener.notify = session_notify;
+       wl_signal_add(&compositor->session_signal, &b->session_listener);
+-      if (config->specific_device)
++      if (config->device_fd >= 0)
++              drm_device = import_drm_device_fd(b, config->device_fd);
++      else if (config->specific_device)
+               drm_device = open_specific_drm_device(b, config->specific_device);
+       else
+               drm_device = find_primary_gpu(b, seat_id);
+@@ -3013,6 +3050,7 @@ static void
+ config_init_to_defaults(struct weston_drm_backend_config *config)
+ {
+       config->use_pixman_shadow = true;
++      config->device_fd = -1;
+ }
+ WL_EXPORT int
+-- 
+2.25.1
+
diff --git a/meta-agl-drm-lease/recipes-graphics/weston/weston/0002-Add-DRM-lease-support.patch b/meta-agl-drm-lease/recipes-graphics/weston/weston/0002-Add-DRM-lease-support.patch
new file mode 100644 (file)
index 0000000..5b2d69a
--- /dev/null
@@ -0,0 +1,230 @@
+From 24ece5f73b7c9377e14d74c2b14c9ae3504edcc3 Mon Sep 17 00:00:00 2001
+From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
+Date: Fri, 5 Mar 2021 19:24:35 +0900
+Subject: [PATCH 2/2] Add DRM lease support
+
+Add a command line option to use a DRM lease instead of a primary node for
+output when using the DRM backend.
+---
+ compositor/drm-lease.c | 53 ++++++++++++++++++++++++++++++++++++++++++
+ compositor/drm-lease.h | 40 +++++++++++++++++++++++++++++++
+ compositor/main.c      | 11 ++++++++-
+ compositor/meson.build |  5 ++++
+ meson_options.txt      |  7 ++++++
+ 5 files changed, 115 insertions(+), 1 deletion(-)
+ create mode 100644 compositor/drm-lease.c
+ create mode 100644 compositor/drm-lease.h
+
+diff --git a/compositor/drm-lease.c b/compositor/drm-lease.c
+new file mode 100644
+index 00000000..fdb1f5e2
+--- /dev/null
++++ b/compositor/drm-lease.c
+@@ -0,0 +1,53 @@
++/*
++ * Copyright © 2021 IGEL Co., Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include "drm-lease.h"
++
++#include <libweston/libweston.h>
++
++int get_drm_lease(struct dlm_lease **drm_lease, const char *drm_lease_name) {
++      if (!drm_lease_name)
++              return -1;
++
++      int drm_fd;
++      struct dlm_lease *lease = dlm_get_lease(drm_lease_name);
++      if (lease) {
++              drm_fd = dlm_lease_fd(lease);
++              if (drm_fd < 0)
++                      dlm_release_lease(lease);
++      }
++      if (drm_fd < 0)
++          weston_log("Could not get DRM lease %s\n", drm_lease_name);
++
++        *drm_lease = lease;
++      return drm_fd;
++}
++
++void release_drm_lease(struct dlm_lease *lease) {
++      if (lease)
++              dlm_release_lease(lease);
++}
++
++
+diff --git a/compositor/drm-lease.h b/compositor/drm-lease.h
+new file mode 100644
+index 00000000..a102e4cb
+--- /dev/null
++++ b/compositor/drm-lease.h
+@@ -0,0 +1,40 @@
++/*
++ * Copyright © 2021 IGEL Co., Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include "config.h"
++
++#ifdef BUILD_DRM_LEASE_CLIENT
++#include <dlmclient.h>
++int get_drm_lease(struct dlm_lease **drm_lease, const char *drm_lease_name);
++void release_drm_lease(struct dlm_lease *drm_lease);
++#else
++struct dlm_lease;
++int get_drm_lease(struct dlm_lease **drm_lease, const char *drm_lease_name) {
++      return -1;
++}
++void release_drm_lease(struct dlm_lease *drm_lease) {
++}
++
++#endif
+diff --git a/compositor/main.c b/compositor/main.c
+index 7d5373f7..dae754aa 100644
+--- a/compositor/main.c
++++ b/compositor/main.c
+@@ -65,6 +65,7 @@
+ #include <libweston/weston-log.h>
+ #include "../remoting/remoting-plugin.h"
+ #include "../pipewire/pipewire-plugin.h"
++#include "drm-lease.h"
+ #define WINDOW_TITLE "Weston Compositor"
+ /* flight recorder size (in bytes) */
+@@ -122,6 +123,7 @@ struct wet_compositor {
+       int (*simple_output_configure)(struct weston_output *output);
+       bool init_failed;
+       struct wl_list layoutput_list;  /**< wet_layoutput::compositor_link */
++      struct dlm_lease *drm_lease;
+ };
+ static FILE *weston_logfile = NULL;
+@@ -669,6 +671,9 @@ usage(int error_code)
+               "  --seat=SEAT\t\tThe seat that weston should run on, instead of the seat defined in XDG_SEAT\n"
+               "  --tty=TTY\t\tThe tty to use\n"
+               "  --drm-device=CARD\tThe DRM device to use, e.g. \"card0\".\n"
++#ifdef BUILD_DRM_LEASE_CLIENT
++              "  --drm-lease=lease\tUse the specified DRM lease. e.g \"card0-HDMI-A-1\"\n"
++#endif
+               "  --use-pixman\t\tUse the pixman (CPU) renderer\n"
+               "  --current-mode\tPrefer current KMS mode over EDID preferred mode\n\n");
+ #endif
+@@ -2481,6 +2486,7 @@ load_drm_backend(struct weston_compositor *c,
+       struct weston_config_section *section;
+       struct wet_compositor *wet = to_wet_compositor(c);
+       int ret = 0;
++      char *drm_lease_name = NULL;
+       wet->drm_use_current_mode = false;
+@@ -2492,6 +2498,7 @@ load_drm_backend(struct weston_compositor *c,
+               { WESTON_OPTION_STRING, "seat", 0, &config.seat_id },
+               { WESTON_OPTION_INTEGER, "tty", 0, &config.tty },
+               { WESTON_OPTION_STRING, "drm-device", 0, &config.specific_device },
++              { WESTON_OPTION_STRING, "drm-lease", 0, &drm_lease_name },
+               { WESTON_OPTION_BOOLEAN, "current-mode", 0, &wet->drm_use_current_mode },
+               { WESTON_OPTION_BOOLEAN, "use-pixman", 0, &config.use_pixman },
+       };
+@@ -2510,7 +2517,7 @@ load_drm_backend(struct weston_compositor *c,
+       config.base.struct_version = WESTON_DRM_BACKEND_CONFIG_VERSION;
+       config.base.struct_size = sizeof(struct weston_drm_backend_config);
+       config.configure_device = configure_input_device;
+-      config.device_fd = -1;
++      config.device_fd = get_drm_lease(&wet->drm_lease, drm_lease_name);
+       wet->heads_changed_listener.notify = drm_heads_changed;
+       weston_compositor_add_heads_changed_listener(c,
+@@ -2527,6 +2534,7 @@ load_drm_backend(struct weston_compositor *c,
+       free(config.gbm_format);
+       free(config.seat_id);
++      free(drm_lease_name);
+       return ret;
+ }
+@@ -3373,6 +3381,7 @@ out:
+       /* free(NULL) is valid, and it won't be NULL if it's used */
+       free(wet.parsed_options);
++      release_drm_lease(wet.drm_lease);
+       if (protologger)
+               wl_protocol_logger_destroy(protologger);
+diff --git a/compositor/meson.build b/compositor/meson.build
+index e1334d6a..e5b82a88 100644
+--- a/compositor/meson.build
++++ b/compositor/meson.build
+@@ -25,6 +25,11 @@ if get_option('xwayland')
+       srcs_weston += 'xwayland.c'
+       config_h.set_quoted('XSERVER_PATH', get_option('xwayland-path'))
+ endif
++if get_option('drm-lease')
++      deps_weston += dependency('libdlmclient')
++      srcs_weston += 'drm-lease.c'
++      config_h.set('BUILD_DRM_LEASE_CLIENT', '1')
++endif
+ libexec_weston = shared_library(
+       'exec_weston',
+diff --git a/meson_options.txt b/meson_options.txt
+index 73ef2c34..9cb27536 100644
+--- a/meson_options.txt
++++ b/meson_options.txt
+@@ -113,6 +113,13 @@ option(
+       description: 'Virtual remote output with Pipewire on DRM backend'
+ )
++option(
++        'drm-lease',
++        type: 'boolean',
++        value: false,
++        description: 'Support for running weston with a leased DRM Master'
++)
++
+ option(
+       'shell-desktop',
+       type: 'boolean',
+-- 
+2.25.1
+
diff --git a/meta-agl-drm-lease/recipes-graphics/weston/weston_8.0.0.bbappend b/meta-agl-drm-lease/recipes-graphics/weston/weston_8.0.0.bbappend
new file mode 100644 (file)
index 0000000..97de8c6
--- /dev/null
@@ -0,0 +1,8 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI += "file://0001-backend-drm-Add-method-to-import-DRM-fd.patch \
+            file://0002-Add-DRM-lease-support.patch \
+            "
+
+PACKAGECONFIG[drm-lease] = "-Ddrm-lease=true,-Ddrm-lease=false,drm-lease-manager"
+PACKAGECONFIG_append = " drm-lease"