[PATCH weston 1/2 v5] compositor-drm: Add support for DRM lease
Marius Vlad
marius-cristian.vlad at nxp.com
Tue May 29 10:04:05 UTC 2018
Signed-off-by: Marius Vlad <marius-cristian.vlad at nxp.com>
---
Makefile.am | 8 +-
compositor/main.c | 6 +
configure.ac | 4 +
libweston/compositor-drm.c | 279 ++++++++++++++++++++++++++++++++++++++++++++-
libweston/compositor.c | 1 +
libweston/compositor.h | 1 +
6 files changed, 296 insertions(+), 3 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 69ca6cb..00a49d9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -168,7 +168,9 @@ nodist_libweston_ at LIBWESTON_MAJOR@_la_SOURCES = \
protocol/pointer-constraints-unstable-v1-protocol.c \
protocol/pointer-constraints-unstable-v1-server-protocol.h \
protocol/input-timestamps-unstable-v1-protocol.c \
- protocol/input-timestamps-unstable-v1-server-protocol.h
+ protocol/input-timestamps-unstable-v1-server-protocol.h \
+ protocol/drm-lease-unstable-v1-protocol.c \
+ protocol/drm-lease-unstable-v1-server-protocol.h
BUILT_SOURCES += $(nodist_libweston_ at LIBWESTON_MAJOR@_la_SOURCES)
@@ -889,7 +891,9 @@ BUILT_SOURCES += \
protocol/linux-dmabuf-unstable-v1-protocol.c \
protocol/linux-dmabuf-unstable-v1-client-protocol.h \
protocol/input-timestamps-unstable-v1-protocol.c \
- protocol/input-timestamps-unstable-v1-client-protocol.h
+ protocol/input-timestamps-unstable-v1-client-protocol.h \
+ protocol/drm-lease-unstable-v1-protocol.c \
+ protocol/drm-lease-unstable-v1-client-protocol.h
westondatadir = $(datadir)/weston
dist_westondata_DATA = \
diff --git a/compositor/main.c b/compositor/main.c
index 1092204..8fda259 100644
--- a/compositor/main.c
+++ b/compositor/main.c
@@ -1234,6 +1234,7 @@ drm_backend_output_configure(struct weston_output *output)
char *modeline = NULL;
char *gbm_format = NULL;
char *seat = NULL;
+ char *lease = NULL;
if (!api) {
weston_log("Cannot use weston_drm_output_api.\n");
@@ -1276,6 +1277,11 @@ drm_backend_output_configure(struct weston_output *output)
api->set_seat(output, seat);
free(seat);
+ weston_config_section_get_string(section, "lease", &lease, "off");
+ if (!strncmp(lease, "on", 2))
+ output->leasable = true;
+ free(lease);
+
return 0;
}
diff --git a/configure.ac b/configure.ac
index da3f734..a81b137 100644
--- a/configure.ac
+++ b/configure.ac
@@ -212,6 +212,10 @@ if test x$enable_drm_compositor = xyes; then
PKG_CHECK_MODULES(DRM_COMPOSITOR_GBM, [gbm >= 10.2],
[AC_DEFINE([HAVE_GBM_FD_IMPORT], 1, [gbm supports dmabuf import])],
[AC_MSG_WARN([gbm does not support dmabuf import, will omit that capability])])
+ PKG_CHECK_MODULES(DRM_LEASE, [libdrm >= 2.4.89],
+ [AC_DEFINE([HAVE_DRM_LEASE], 1, [libdrm support lease capability])],
+ [AC_MSG_WARN([libdrm doesn't have leases support, will omit that capability])])
+
fi
diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c
index 8b1ea66..4b7b470 100644
--- a/libweston/compositor-drm.c
+++ b/libweston/compositor-drm.c
@@ -64,6 +64,7 @@
#include "presentation-time-server-protocol.h"
#include "linux-dmabuf.h"
#include "linux-dmabuf-unstable-v1-server-protocol.h"
+#include "drm-lease-unstable-v1-server-protocol.h"
#ifndef DRM_CAP_TIMESTAMP_MONOTONIC
#define DRM_CAP_TIMESTAMP_MONOTONIC 0x6
@@ -273,6 +274,21 @@ struct drm_backend {
uint32_t pageflip_timeout;
bool shutting_down;
+ struct wl_list leases;
+};
+
+struct lease {
+ int leased_fd;
+ uint32_t lessee_id;
+
+ int nobjects;
+ int tnobjects;
+ uint32_t *objects;
+
+ struct drm_output *leased_output;
+ struct wl_resource *lease_resource;
+ struct drm_backend *drm_backend;
+ struct wl_list link;
};
struct drm_mode {
@@ -436,6 +452,7 @@ struct drm_output {
int destroy_pending;
int disable_pending;
int dpms_off_pending;
+ int lease_pending;
struct drm_fb *gbm_cursor_fb[2];
struct drm_plane *cursor_plane;
@@ -463,6 +480,7 @@ struct drm_output {
struct wl_listener recorder_frame_listener;
struct wl_event_source *pageflip_timer;
+ struct lease *lease;
};
static struct gl_renderer_interface *gl_renderer;
@@ -1392,6 +1410,38 @@ drm_pending_state_get_output(struct drm_pending_state *pending_state,
static int drm_pending_state_apply_sync(struct drm_pending_state *state);
+#ifdef HAVE_DRM_LEASE
+static void
+drm_lease_clear_objects(struct lease *lease)
+{
+ memset(lease->objects, 0, sizeof(uint32_t) * lease->tnobjects);
+ lease->tnobjects = 0;
+}
+
+static void
+drm_output_send_lease(struct drm_output *output)
+{
+ struct lease *lease = output->lease;
+ struct wl_resource *resource = lease->lease_resource;
+ int drm_fd = lease->drm_backend->drm.fd;
+
+ lease->leased_fd = drmModeCreateLease(drm_fd, lease->objects,
+ lease->tnobjects, 0,
+ &lease->lessee_id);
+ if (lease->leased_fd < 0) {
+ drm_lease_clear_objects(lease);
+ zwp_kms_lease_request_v1_send_failed(resource);
+ return;
+ }
+
+ wl_list_insert(&lease->drm_backend->leases, &lease->link);
+ zwp_kms_lease_request_v1_send_created(resource,
+ lease->leased_fd,
+ lease->lessee_id);
+}
+#endif
+
+
/**
* Mark a drm_output_state (the output's last state) as complete. This handles
* any post-completion actions such as updating the repaint timer, disabling the
@@ -1425,6 +1475,12 @@ drm_output_update_complete(struct drm_output *output, uint32_t flags,
output->disable_pending = 0;
output->dpms_off_pending = 0;
weston_output_disable(&output->base);
+#ifdef HAVE_DRM_LEASE
+ if (output->lease_pending) {
+ output->lease_pending = 0;
+ drm_output_send_lease(output);
+ }
+#endif
return;
} else if (output->dpms_off_pending) {
struct drm_pending_state *pending = drm_pending_state_alloc(b);
@@ -6021,6 +6077,222 @@ static const struct weston_drm_output_api api = {
drm_output_set_seat,
};
+
+#ifdef HAVE_DRM_LEASE
+static void
+destroy_lease_req(struct wl_resource *params_resource)
+{
+ struct lease *lease = wl_resource_get_user_data(params_resource);
+ free(lease->objects);
+ free(lease);
+}
+
+static void
+drm_lease_add_objects(struct lease *lease, uint32_t id)
+{
+ if (lease->tnobjects > lease->nobjects) {
+ lease->nobjects *= 2;
+ lease->objects = realloc(lease->objects,
+ lease->nobjects * sizeof(uint32_t));
+ }
+
+ lease->objects[lease->tnobjects++] = id;
+}
+
+static void
+drm_lease_add_connector(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t id)
+{
+ (void) client;
+
+ struct lease *lease = wl_resource_get_user_data(resource);
+ drm_lease_add_objects(lease, id);
+}
+
+static void
+drm_lease_add_crtc(struct wl_client *client,
+ struct wl_resource *resource, uint32_t id)
+{
+ (void) client;
+ struct lease *lease = wl_resource_get_user_data(resource);
+ drm_lease_add_objects(lease, id);
+}
+
+static void
+drm_lease_add_plane(struct wl_client *client, struct wl_resource *resource,
+ uint32_t id)
+{
+ (void) client;
+ struct lease *lease = wl_resource_get_user_data(resource);
+ drm_lease_add_objects(lease, id);
+}
+
+static void
+drm_lease_create(struct wl_client *client, struct wl_resource *resource)
+{
+ (void) client;
+ struct lease *lease = wl_resource_get_user_data(resource);
+ struct weston_compositor *compositor = lease->drm_backend->compositor;
+
+ struct weston_head *head;
+ struct drm_head *drm_head;
+ struct drm_output *leased_output = NULL;
+
+ wl_list_for_each(head, &compositor->head_list, compositor_link) {
+ struct weston_output *wet_output = head->output;
+
+ /* verify if this output is allow to be leased */
+ if (wet_output->leasable) {
+ int conn_found = 0;
+
+ drm_head = to_drm_head(head);
+ /* determine which connector to disable */
+ for (int i = 0; i < lease->tnobjects; i++) {
+ if (lease->objects[i] == drm_head->connector_id) {
+ conn_found = 1;
+ break;
+ }
+ }
+
+ if (!conn_found) {
+ break;
+ }
+
+ leased_output = to_drm_output(wet_output);
+ break;
+ }
+ }
+
+ if (!leased_output) {
+ zwp_kms_lease_request_v1_send_failed(resource);
+ drm_lease_clear_objects(lease);
+ return;
+ }
+
+ leased_output->lease = lease;
+ lease->leased_output = leased_output;
+
+ /*
+ * If we are just in the middle of a flip disabling the output will be
+ * deferred so we rely on drm_output_update_complete() to disable it and
+ * send the event back to the client. Otherwise we disable and send the
+ * event directly.
+ */
+ if (leased_output->page_flip_pending || leased_output->vblank_pending ||
+ leased_output->atomic_complete_pending) {
+ leased_output->lease_pending = 1;
+ leased_output->disable_pending = 1;
+ } else {
+ weston_output_disable(&leased_output->base);
+ drm_output_send_lease(leased_output);
+ }
+}
+
+static void
+drm_lease_revoke(struct wl_client *client,
+ struct wl_resource *resource, uint32_t id)
+{
+ (void) client;
+ struct lease *lease = wl_resource_get_user_data(resource);
+ int drm_fd = lease->drm_backend->drm.fd;
+ struct lease *old, *tmp;
+
+ wl_list_for_each_safe(old, tmp, &lease->drm_backend->leases, link) {
+ if (old->lessee_id == id) {
+ struct weston_output *wet_output = &old->leased_output->base;
+ if (drmModeRevokeLease(drm_fd, id) < 0) {
+ goto out_err;
+ }
+
+ /*
+ * calling directly weston_output_schedule_repaint()
+ * would not help. Also, weston_output_enable() will
+ * eventuall schedule a repaint but without the
+ * REPAINT_SCHEDULED repaint status set we will continue
+ * to see the last fb frame of the leased app on the
+ * screen, hence forcibly the repaint status solves this
+ * issue.
+ */
+ wet_output->repaint_status = REPAINT_SCHEDULED;
+ weston_output_enable(wet_output);
+
+ wl_list_remove(&old->link);
+ zwp_kms_lease_request_v1_send_revoked(resource);
+ return;
+ }
+ }
+out_err:
+ zwp_kms_lease_request_v1_send_failed(resource);
+}
+
+static const struct zwp_kms_lease_request_v1_interface
+ zwp_kms_lease_request_v1_implementation = {
+ drm_lease_add_connector,
+ drm_lease_add_crtc,
+ drm_lease_add_plane,
+
+ drm_lease_create,
+ drm_lease_revoke,
+};
+
+static void
+drm_lease_manager_create_lease_req(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t params_id)
+{
+ struct lease *lease = zalloc(sizeof(*lease));
+ uint32_t version = wl_resource_get_version(resource);
+
+ lease->nobjects = 3;
+ lease->objects = zalloc(lease->nobjects * sizeof(uint32_t));
+
+ lease->lease_resource = wl_resource_create(client,
+ &zwp_kms_lease_request_v1_interface,
+ version, params_id);
+ if (!lease->lease_resource) {
+ free(lease);
+ free(lease->objects);
+ return;
+ }
+
+ lease->drm_backend = wl_resource_get_user_data(resource);
+ wl_resource_set_implementation(lease->lease_resource,
+ &zwp_kms_lease_request_v1_implementation,
+ lease, destroy_lease_req);
+}
+
+static void drm_lease_manager_destroy(struct wl_client *client,
+ struct wl_resource *resource)
+{
+ (void) client;
+ (void) resource;
+}
+
+static const struct zwp_kms_lease_manager_v1_interface drm_lease_manager_interface = {
+ drm_lease_manager_destroy,
+ drm_lease_manager_create_lease_req,
+};
+
+static void
+drm_lease_setup(struct wl_client *client, void *data, uint32_t ver, uint32_t id)
+{
+ struct drm_backend *drm_backend = (struct drm_backend *) data;
+ struct wl_resource *resource;
+
+ resource = wl_resource_create(client,
+ &zwp_kms_lease_manager_v1_interface,
+ ver, id);
+ if (resource == NULL) {
+ wl_client_post_no_memory(client);
+ return;
+ }
+
+ wl_resource_set_implementation(resource, &drm_lease_manager_interface,
+ drm_backend, NULL);
+}
+#endif
+
static struct drm_backend *
drm_backend_create(struct weston_compositor *compositor,
struct weston_drm_backend_config *config)
@@ -6132,7 +6404,12 @@ drm_backend_create(struct weston_compositor *compositor,
weston_log("Failed to create heads for %s\n", b->drm.filename);
goto err_udev_input;
}
-
+#ifdef HAVE_DRM_LEASE
+ wl_list_init(&b->leases);
+ wl_global_create(compositor->wl_display,
+ &zwp_kms_lease_manager_v1_interface, 1, b,
+ drm_lease_setup);
+#endif
/* A this point we have some idea of whether or not we have a working
* cursor plane. */
if (!b->cursors_are_broken)
diff --git a/libweston/compositor.c b/libweston/compositor.c
index 619e88b..5609cca 100644
--- a/libweston/compositor.c
+++ b/libweston/compositor.c
@@ -5542,6 +5542,7 @@ weston_output_init(struct weston_output *output,
wl_list_init(&output->link);
wl_signal_init(&output->user_destroy_signal);
output->enabled = false;
+ output->leasable = false;
wl_list_init(&output->head_list);
diff --git a/libweston/compositor.h b/libweston/compositor.h
index 47337d8..fd67216 100644
--- a/libweston/compositor.h
+++ b/libweston/compositor.h
@@ -267,6 +267,7 @@ struct weston_output {
struct weston_timeline_object timeline;
bool enabled; /**< is in the output_list, not pending list */
+ bool leasable; /**< this output can be leased */
int scale;
int (*enable)(struct weston_output *output);
--
2.9.3
More information about the wayland-devel
mailing list