From f74c35b1f4a62543e559de3455c60c82dc468ade Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Wed, 3 Apr 2019 19:21:58 +0530 Subject: [PATCH] libweston: Notify client for change in content-protection status The change in an output's content-protection may trigger a change in the surface's content-protection status, and inturn the content-protection available for the client. This patch recomputes the content-protection level for a surface, in case there is a change in content-protection level of an output, showing the surface. In case of a change in the surface's content-protection, the client associated with that surface is notified. Signed-off-by: Ankit Nautiyal --- include/libweston/libweston.h | 1 + libweston/compositor.c | 71 +++++++++++++++++++++++++++++++++- libweston/content-protection.c | 1 + 3 files changed, 72 insertions(+), 1 deletion(-) diff --git a/include/libweston/libweston.h b/include/libweston/libweston.h index 04a17918..7d3307e1 100644 --- a/include/libweston/libweston.h +++ b/include/libweston/libweston.h @@ -1630,6 +1630,7 @@ struct content_protection { struct wl_listener destroy_listener; struct weston_log_scope *debug; struct wl_list protected_list; + struct wl_event_source *surface_protection_update; }; diff --git a/libweston/compositor.c b/libweston/compositor.c index fc11ae5c..d417d7ac 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -1032,6 +1032,47 @@ weston_surface_send_enter_leave(struct weston_surface *surface, } } +static void +weston_surface_compute_protection(struct protected_surface *psurface) +{ + enum weston_hdcp_protection min_protection; + bool min_protection_valid = false; + struct weston_surface *surface = psurface->surface; + struct weston_output *output; + + wl_list_for_each(output, &surface->compositor->output_list, link) + if (surface->output_mask & (1u << output->id)) { + if (!min_protection_valid) { + min_protection = output->current_protection; + min_protection_valid = true; + } + if (output->current_protection < min_protection) + min_protection = output->current_protection; + } + if (!min_protection_valid) + min_protection = WESTON_HDCP_DISABLE; + + surface->current_protection = min_protection; + weston_protected_surface_send_event(psurface, + surface->current_protection); +} + +static void +notify_surface_protection_change(void *data) +{ + struct weston_compositor *compositor = data; + struct content_protection *cp; + struct protected_surface *psurface; + + cp = compositor->content_protection; + cp->surface_protection_update = NULL; + + /* Notify the clients, whose surfaces are changed */ + wl_list_for_each(psurface, &cp->protected_list, link) + if (psurface && psurface->surface) + weston_surface_compute_protection(psurface); +} + /** * \param es The surface * \param mask The new set of outputs for the surface @@ -1050,6 +1091,8 @@ weston_surface_update_output_mask(struct weston_surface *es, uint32_t mask) uint32_t output_bit; struct weston_output *output; struct weston_head *head; + struct content_protection *cp; + struct wl_event_loop *loop; es->output_mask = mask; if (es->resource == NULL) @@ -1068,6 +1111,17 @@ weston_surface_update_output_mask(struct weston_surface *es, uint32_t mask) output_bit & left); } } + /* + * Change in surfaces' output mask might trigger a change in its + * protection. + */ + loop = wl_display_get_event_loop(es->compositor->wl_display); + cp = es->compositor->content_protection; + if (!cp || cp->surface_protection_update) + return; + cp->surface_protection_update = wl_event_loop_add_idle(loop, + notify_surface_protection_change, + es->compositor); } static void @@ -5338,6 +5392,11 @@ weston_output_compute_protection(struct weston_output *output) struct weston_head *head; enum weston_hdcp_protection op_protection; bool op_protection_valid = false; + struct weston_compositor *wc = output->compositor; + struct content_protection *cp = wc->content_protection; + + if (!cp) + return; wl_list_for_each(head, &output->head_list, output_link) { if (!op_protection_valid) { @@ -5351,8 +5410,18 @@ weston_output_compute_protection(struct weston_output *output) if (!op_protection_valid) op_protection = WESTON_HDCP_DISABLE; - if (output->current_protection != op_protection) + if (output->current_protection != op_protection) { + struct wl_event_loop *loop; + output->current_protection = op_protection; + weston_output_damage(output); + if (cp->surface_protection_update) + return; + loop = wl_display_get_event_loop(wc->wl_display); + cp->surface_protection_update = wl_event_loop_add_idle(loop, + notify_surface_protection_change, + wc); + } } WL_EXPORT void diff --git a/libweston/content-protection.c b/libweston/content-protection.c index 72865a51..689a2ec8 100644 --- a/libweston/content-protection.c +++ b/libweston/content-protection.c @@ -189,6 +189,7 @@ cp_destroy_listener(struct wl_listener *listener, void *data) wl_list_remove(&cp->protected_list); weston_compositor_log_scope_destroy(cp->debug); cp->debug = NULL; + cp->surface_protection_update = NULL; free(cp); }