1From c6a4bb348b8964dc1f4114562e9db4e95f2ad6de Mon Sep 17 00:00:00 2001
2From: Jeffy Chen <jeffy.chen@rock-chips.com>
3Date: Tue, 7 Jul 2020 17:00:40 +0800
4Subject: [PATCH 10/79] HACK: gl-renderer: Support making hole for surface
5
6Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
7---
8 include/libweston/libweston.h       |  3 ++
9 libweston/compositor.c              | 29 ++++++++++++
10 libweston/renderer-gl/gl-renderer.c | 71 +++++++++++++++++++++++++++++
11 3 files changed, 103 insertions(+)
12
13diff --git a/include/libweston/libweston.h b/include/libweston/libweston.h
14index bfa7e36..be2514a 100644
15--- a/include/libweston/libweston.h
16+++ b/include/libweston/libweston.h
17@@ -1551,6 +1551,9 @@ struct weston_surface {
18 	enum weston_hdcp_protection desired_protection;
19 	enum weston_hdcp_protection current_protection;
20 	enum weston_surface_protection_mode protection_mode;
21+
22+	/* Transparent hole region(excluding it's lower subsurface area) */
23+	pixman_region32_t hole;
24 };
25
26 struct weston_subsurface {
27diff --git a/libweston/compositor.c b/libweston/compositor.c
28index 2e38c1b..9579493 100644
29--- a/libweston/compositor.c
30+++ b/libweston/compositor.c
31@@ -605,6 +605,7 @@ weston_surface_create(struct weston_compositor *compositor)
32 	pixman_region32_init(&surface->damage);
33 	pixman_region32_init(&surface->opaque);
34 	region_init_infinite(&surface->input);
35+	pixman_region32_init(&surface->hole);
36
37 	wl_list_init(&surface->views);
38 	wl_list_init(&surface->paint_node_list);
39@@ -2341,6 +2342,7 @@ weston_surface_destroy(struct weston_surface *surface)
40 	pixman_region32_fini(&surface->damage);
41 	pixman_region32_fini(&surface->opaque);
42 	pixman_region32_fini(&surface->input);
43+	pixman_region32_fini(&surface->hole);
44
45 	wl_resource_for_each_safe(cb, next, &surface->frame_callback_list)
46 		wl_resource_destroy(cb);
47@@ -3519,6 +3521,33 @@ surface_set_opaque_region(struct wl_client *client,
48
49 	if (region_resource) {
50 		region = wl_resource_get_user_data(region_resource);
51+
52+		/**
53+		 * HACK: Make a hole for this surface
54+		 * Usage:
55+		 * 1/ Set the hole region
56+		 *  wl_region_add(region, [hole region]);
57+		 * 2/ Add a special rect to mark the region as a hole
58+		 *  wl_region_add(region, -1, -1, 1, 1);
59+		 *  wl_surface_set_opaque_region(surface, region);
60+		 */
61+		if (pixman_region32_contains_point(&region->region, -1, -1,
62+						   NULL)) {
63+			pixman_region32_t hole;
64+
65+			// Subtract the special rect
66+			pixman_region32_init_rect(&hole, -1, -1, 1, 1);
67+			pixman_region32_subtract(&hole, &region->region,
68+						 &hole);
69+
70+			pixman_region32_copy(&surface->hole, &hole);
71+			pixman_region32_fini(&hole);
72+
73+			// Trigger repaint to apply the hole
74+			weston_surface_damage(surface);
75+			return;
76+		}
77+
78 		pixman_region32_copy(&surface->pending.opaque,
79 				     &region->region);
80 	} else {
81diff --git a/libweston/renderer-gl/gl-renderer.c b/libweston/renderer-gl/gl-renderer.c
82index 053fd52..6e04baa 100644
83--- a/libweston/renderer-gl/gl-renderer.c
84+++ b/libweston/renderer-gl/gl-renderer.c
85@@ -1034,6 +1034,46 @@ gl_shader_config_init_for_paint_node(struct gl_shader_config *sconf,
86 	return true;
87 }
88
89+static void
90+clear_region(struct weston_view *ev, pixman_region32_t *region)
91+{
92+	pixman_box32_t *rects;
93+	int i, n, h = ev->output->height;
94+
95+	if (ev->alpha < 0.5f)
96+		return;
97+
98+	rects = pixman_region32_rectangles(region, &n);
99+	for (i = 0; i < n; i++) {
100+		pixman_box32_t r = rects[i];
101+		glScissor(r.x1, h - r.y2, r.x2 - r.x1, r.y2 - r.y1);
102+		glEnable(GL_SCISSOR_TEST);
103+		glClearColor(0, 0, 0, 0);
104+		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
105+		glDisable(GL_SCISSOR_TEST);
106+	}
107+}
108+
109+static void
110+weston_view_to_global_region(struct weston_view *ev, pixman_region32_t *region,
111+			     pixman_region32_t *global_region)
112+{
113+	pixman_box32_t *rects;
114+	int i, n;
115+	float x1, y1, x2, y2;
116+
117+	pixman_region32_clear(global_region);
118+
119+	rects = pixman_region32_rectangles(region, &n);
120+	for (i = 0; i < n; i++) {
121+		pixman_box32_t r = rects[i];
122+		weston_view_to_global_float(ev, r.x1, r.y1, &x1, &y1);
123+		weston_view_to_global_float(ev, r.x2, r.y2, &x2, &y2);
124+		pixman_region32_union_rect(global_region, global_region,
125+					   x1, y1, x2 - x1, y2 - y1);
126+	}
127+}
128+
129 static void
130 draw_paint_node(struct weston_paint_node *pnode,
131 		pixman_region32_t *damage /* in global coordinates */)
132@@ -1077,6 +1117,37 @@ draw_paint_node(struct weston_paint_node *pnode,
133 	if (!gl_shader_config_init_for_paint_node(&sconf, pnode, filter))
134 		goto out;
135
136+	// HACK: Make hole for the surface(excluding it's lower subsurface area)
137+	if (pixman_region32_not_empty(&pnode->surface->hole)) {
138+		struct weston_subsurface *child;
139+		pixman_region32_t hole, region;
140+
141+		pixman_region32_init(&region);
142+		wl_list_for_each_reverse(child, &pnode->surface->subsurface_list,
143+				 parent_link) {
144+			if (child->surface == pnode->surface)
145+				break;
146+
147+			pixman_region32_union_rect(&region, &region,
148+						   child->position.x,
149+						   child->position.y,
150+						   child->surface->width,
151+						   child->surface->height);
152+		}
153+
154+		pixman_region32_subtract(&region, &pnode->surface->hole, &region);
155+		pixman_region32_init(&hole);
156+		weston_view_to_global_region(pnode->view, &region, &hole);
157+
158+		pixman_region32_intersect(&hole, &hole, &repaint);
159+
160+		weston_output_region_from_global(pnode->output, &hole);
161+		clear_region(pnode->view, &hole);
162+
163+		pixman_region32_fini(&hole);
164+		pixman_region32_fini(&region);
165+	}
166+
167 	/* blended region is whole surface minus opaque region: */
168 	pixman_region32_init_rect(&surface_blend, 0, 0,
169 				  pnode->surface->width, pnode->surface->height);
170--
1712.20.1
172
173