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