The patch relies on previous drm-lease-unstable-v1 extension protocol posted previously [1].
Changes since v2: - accommodate changes due to protocol changes - use enable/disabled for the output instead of destroy/update_outputs (Daniel Stone) - split into a series, added a client example - forcing a repaint when giving the lease and not doing a modeset if the output has been leased avoids blank switching between the lesor and lessee Signed-off-by: Marius Vlad <marius-cristian.v...@nxp.com> --- Makefile.am | 2 + compositor/main.c | 9 ++ configure.ac | 4 + libweston/compositor-drm.c | 244 +++++++++++++++++++++++++++++++++++++++++++++ libweston/compositor.c | 1 + libweston/compositor.h | 2 + 6 files changed, 262 insertions(+) diff --git a/Makefile.am b/Makefile.am index e224d60..4580d24 100644 --- a/Makefile.am +++ b/Makefile.am @@ -178,6 +178,8 @@ nodist_libweston_@LIBWESTON_MAJOR@_la_SOURCES = \ protocol/viewporter-server-protocol.h \ protocol/linux-dmabuf-unstable-v1-protocol.c \ protocol/linux-dmabuf-unstable-v1-server-protocol.h \ + protocol/drm-lease-unstable-v1-protocol.c \ + protocol/drm-lease-unstable-v1-server-protocol.h \ protocol/relative-pointer-unstable-v1-protocol.c \ protocol/relative-pointer-unstable-v1-server-protocol.h \ protocol/pointer-constraints-unstable-v1-protocol.c \ diff --git a/compositor/main.c b/compositor/main.c index 7feb4cb..779a4dd 100644 --- a/compositor/main.c +++ b/compositor/main.c @@ -1209,6 +1209,15 @@ drm_backend_output_configure(struct wl_listener *listener, void *data) api->set_seat(output, seat); free(seat); + char *lease; + weston_config_section_get_string(section, "lease", &lease, "off"); + if (!strncmp(lease, "on", 2)) { + output->lease = true; + weston_log("Enabling lease on output %s\n", output->name); + } + free(lease); + + weston_output_enable(output); } diff --git a/configure.ac b/configure.ac index 6f295dc..e1aa0cd 100644 --- a/configure.ac +++ b/configure.ac @@ -209,6 +209,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 fe59bf5..253d0f7 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -62,6 +62,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 @@ -202,6 +203,21 @@ struct drm_backend { uint32_t pageflip_timeout; bool shutting_down; + struct wl_list leases; +}; + +struct lease { + int leased_fd; + uint32_t leased_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 { @@ -380,6 +396,9 @@ struct drm_output { struct wl_listener recorder_frame_listener; struct wl_event_source *pageflip_timer; + + /** this output has been leased */ + int leased; }; static struct gl_renderer_interface *gl_renderer; @@ -4837,6 +4856,225 @@ 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_clear_objects(struct lease *lease) +{ + memset(lease->objects, 0, sizeof(uint32_t) * lease->tnobjects); + lease->tnobjects = 0; +} + +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); + int drm_fd = lease->drm_backend->drm.fd; + struct weston_compositor *compositor = lease->drm_backend->compositor; + struct drm_output *output, *leased_output = NULL; + + wl_list_for_each(output, &compositor->output_list, base.link) { + struct weston_output *wet_output = &output->base; + + /* verify if this output is allow to be leased */ + if (wet_output->lease) { + int conn_found = 0; + + /* determine which connector to disable */ + for (int i = 0; i < lease->tnobjects; i++) { + if (lease->objects[i] == output->connector_id) { + conn_found = 1; + break; + } + } + + if (!conn_found) { + break; + } + + leased_output = output; + break; + } + } + + if (!leased_output) { + zwp_kms_lease_request_v1_send_failed(resource); + drm_lease_clear_objects(lease); + return; + } + + lease->leased_fd = drmModeCreateLease(drm_fd, lease->objects, + lease->tnobjects, 0, + &lease->leased_id); + if (lease->leased_fd < 0) { + drm_lease_clear_objects(lease); + zwp_kms_lease_request_v1_send_failed(resource); + return; + } + + lease->leased_output = leased_output; + lease->leased_output->leased = true; + wl_list_insert(&lease->drm_backend->leases, &lease->link); + + weston_output_disable(&lease->leased_output->base); + + zwp_kms_lease_request_v1_send_created(resource, + lease->leased_fd, lease->leased_id); +} + + +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->leased_id == id) { + struct weston_output *wet_output = &old->leased_output->base; + if (drmModeRevokeLease(drm_fd, id) < 0) { + goto out_err; + } + + old->leased_output->leased = false; + /* + * 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); + + /* + * Not arbitrary, normal we should lease connector/crtc/plane. User + * might be want to share additional overlay plane(s) + */ + lease->nobjects = 3; + lease->objects = calloc(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) @@ -4945,6 +5183,12 @@ drm_backend_create(struct weston_compositor *compositor, weston_log("failed to create output 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. */ diff --git a/libweston/compositor.c b/libweston/compositor.c index aec937b..529a61c 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -4773,6 +4773,7 @@ weston_output_init(struct weston_output *output, output->name = strdup(name); wl_list_init(&output->link); output->enabled = false; + output->lease = false; /* Add some (in)sane defaults which can be used * for checking if an output was properly configured diff --git a/libweston/compositor.h b/libweston/compositor.h index dffcba8..900b67d 100644 --- a/libweston/compositor.h +++ b/libweston/compositor.h @@ -239,6 +239,8 @@ struct weston_output { int (*enable)(struct weston_output *output); int (*disable)(struct weston_output *output); + /**< this output can be leased */ + bool lease; }; enum weston_pointer_motion_mask { -- 2.9.3 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel