From ed5f6a0074133ac8f5ec65d0436d97ebdb4414d3 Mon Sep 17 00:00:00 2001 From: Jeffy Chen Date: Tue, 7 Jul 2020 17:00:40 +0800 Subject: [PATCH 10/74] HACK: gl-renderer: Support making hole for surface Signed-off-by: Jeffy Chen --- include/libweston/libweston.h | 3 ++ libweston/compositor.c | 29 ++++++++++++ libweston/renderer-gl/gl-renderer.c | 71 +++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+) diff --git a/include/libweston/libweston.h b/include/libweston/libweston.h index bfa7e36..be2514a 100644 --- a/include/libweston/libweston.h +++ b/include/libweston/libweston.h @@ -1551,6 +1551,9 @@ struct weston_surface { enum weston_hdcp_protection desired_protection; enum weston_hdcp_protection current_protection; enum weston_surface_protection_mode protection_mode; + + /* Transparent hole region(excluding it's lower subsurface area) */ + pixman_region32_t hole; }; struct weston_subsurface { diff --git a/libweston/compositor.c b/libweston/compositor.c index 2e38c1b..9579493 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -605,6 +605,7 @@ weston_surface_create(struct weston_compositor *compositor) pixman_region32_init(&surface->damage); pixman_region32_init(&surface->opaque); region_init_infinite(&surface->input); + pixman_region32_init(&surface->hole); wl_list_init(&surface->views); wl_list_init(&surface->paint_node_list); @@ -2341,6 +2342,7 @@ weston_surface_destroy(struct weston_surface *surface) pixman_region32_fini(&surface->damage); pixman_region32_fini(&surface->opaque); pixman_region32_fini(&surface->input); + pixman_region32_fini(&surface->hole); wl_resource_for_each_safe(cb, next, &surface->frame_callback_list) wl_resource_destroy(cb); @@ -3519,6 +3521,33 @@ surface_set_opaque_region(struct wl_client *client, if (region_resource) { region = wl_resource_get_user_data(region_resource); + + /** + * HACK: Make a hole for this surface + * Usage: + * 1/ Set the hole region + * wl_region_add(region, [hole region]); + * 2/ Add a special rect to mark the region as a hole + * wl_region_add(region, -1, -1, 1, 1); + * wl_surface_set_opaque_region(surface, region); + */ + if (pixman_region32_contains_point(®ion->region, -1, -1, + NULL)) { + pixman_region32_t hole; + + // Subtract the special rect + pixman_region32_init_rect(&hole, -1, -1, 1, 1); + pixman_region32_subtract(&hole, ®ion->region, + &hole); + + pixman_region32_copy(&surface->hole, &hole); + pixman_region32_fini(&hole); + + // Trigger repaint to apply the hole + weston_surface_damage(surface); + return; + } + pixman_region32_copy(&surface->pending.opaque, ®ion->region); } else { diff --git a/libweston/renderer-gl/gl-renderer.c b/libweston/renderer-gl/gl-renderer.c index 053fd52..6e04baa 100644 --- a/libweston/renderer-gl/gl-renderer.c +++ b/libweston/renderer-gl/gl-renderer.c @@ -1034,6 +1034,46 @@ gl_shader_config_init_for_paint_node(struct gl_shader_config *sconf, return true; } +static void +clear_region(struct weston_view *ev, pixman_region32_t *region) +{ + pixman_box32_t *rects; + int i, n, h = ev->output->height; + + if (ev->alpha < 0.5f) + return; + + rects = pixman_region32_rectangles(region, &n); + for (i = 0; i < n; i++) { + pixman_box32_t r = rects[i]; + glScissor(r.x1, h - r.y2, r.x2 - r.x1, r.y2 - r.y1); + glEnable(GL_SCISSOR_TEST); + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glDisable(GL_SCISSOR_TEST); + } +} + +static void +weston_view_to_global_region(struct weston_view *ev, pixman_region32_t *region, + pixman_region32_t *global_region) +{ + pixman_box32_t *rects; + int i, n; + float x1, y1, x2, y2; + + pixman_region32_clear(global_region); + + rects = pixman_region32_rectangles(region, &n); + for (i = 0; i < n; i++) { + pixman_box32_t r = rects[i]; + weston_view_to_global_float(ev, r.x1, r.y1, &x1, &y1); + weston_view_to_global_float(ev, r.x2, r.y2, &x2, &y2); + pixman_region32_union_rect(global_region, global_region, + x1, y1, x2 - x1, y2 - y1); + } +} + static void draw_paint_node(struct weston_paint_node *pnode, pixman_region32_t *damage /* in global coordinates */) @@ -1077,6 +1117,37 @@ draw_paint_node(struct weston_paint_node *pnode, if (!gl_shader_config_init_for_paint_node(&sconf, pnode, filter)) goto out; + // HACK: Make hole for the surface(excluding it's lower subsurface area) + if (pixman_region32_not_empty(&pnode->surface->hole)) { + struct weston_subsurface *child; + pixman_region32_t hole, region; + + pixman_region32_init(®ion); + wl_list_for_each_reverse(child, &pnode->surface->subsurface_list, + parent_link) { + if (child->surface == pnode->surface) + break; + + pixman_region32_union_rect(®ion, ®ion, + child->position.x, + child->position.y, + child->surface->width, + child->surface->height); + } + + pixman_region32_subtract(®ion, &pnode->surface->hole, ®ion); + pixman_region32_init(&hole); + weston_view_to_global_region(pnode->view, ®ion, &hole); + + pixman_region32_intersect(&hole, &hole, &repaint); + + weston_output_region_from_global(pnode->output, &hole); + clear_region(pnode->view, &hole); + + pixman_region32_fini(&hole); + pixman_region32_fini(®ion); + } + /* blended region is whole surface minus opaque region: */ pixman_region32_init_rect(&surface_blend, 0, 0, pnode->surface->width, pnode->surface->height); -- 2.20.1