1From 5840de5c959343d8f367c4e191cb7221c2d77289 Mon Sep 17 00:00:00 2001
2From: Pekka Paalanen <pekka.paalanen@collabora.com>
3Date: Fri, 22 Jul 2022 11:30:04 +0300
4Subject: [PATCH 82/95] libweston: add weston_renderer::resize_output()
5
6Previously renderers were not told when the output (framebuffer they
7need to draw) size changed. Renderers just pulled that information out
8from weston_output::current_mode when they happened to need it. This
9makes some things awkward, like resizing the shadow or intermediate
10buffers. In fact, Pixman-renderer does not even support resizing its
11shadow buffer, nor does GL-renderer. DRM-backend has to destroy and
12re-create the renderer output state anyway, but rdp, x11 and wayland
13backends would be natural users of resizing API.
14
15This commit adds an API for resizing with empty implementations. Actual
16implementations will be added in following patches for each renderer
17while moving parts of resizing code from backends into the renderers.
18No-op renderer needs no implementation.
19
20Only wayland-backend has actual resizing code already, and that is made
21to call the new API. Unfortunately, Pixman and GL renderers differ: one
22does not blit them while the other does. In order to assert the
23functionality of each renderer to keep the API consistent,
24wayland-backend needs to lie to pixman-renderer. That's not new, it
25already does so in wayland_output_get_shm_buffer() where the 'pm_image'
26addresses only the interior area instead of the whole buffer.
27
28Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
29(cherry picked from commit 8636422309462226436bc52f35e53e422bfd7e67)
30Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
31---
32 libweston/backend-wayland/wayland.c | 14 ++++++++++++-
33 libweston/compositor.c              | 27 ++++++++++++++++++++++++
34 libweston/libweston-internal.h      | 32 +++++++++++++++++++++++++++++
35 libweston/noop-renderer.c           | 10 +++++++++
36 libweston/pixman-renderer.c         | 20 ++++++++++++++++++
37 libweston/renderer-gl/gl-renderer.c | 10 +++++++++
38 6 files changed, 112 insertions(+), 1 deletion(-)
39
40diff --git a/libweston/backend-wayland/wayland.c b/libweston/backend-wayland/wayland.c
41index bb5648d..7f27264 100644
42--- a/libweston/backend-wayland/wayland.c
43+++ b/libweston/backend-wayland/wayland.c
44@@ -886,6 +886,7 @@ wayland_output_resize_surface(struct wayland_output *output)
45 	if (output->gl.egl_window) {
46 		wl_egl_window_resize(output->gl.egl_window,
47 				     fb_size.width, fb_size.height, 0, 0);
48+		weston_renderer_resize_output(&output->base, &fb_size, &area);
49
50 		/* These will need to be re-created due to the resize */
51 		gl_renderer->output_set_border(&output->base,
52@@ -908,8 +909,19 @@ wayland_output_resize_surface(struct wayland_output *output)
53 					       0, 0, 0, NULL);
54 		cairo_surface_destroy(output->gl.border.bottom);
55 		output->gl.border.bottom = NULL;
56-	}
57+	} else
58 #endif
59+	{
60+		/*
61+		 * Pixman-renderer never knows about decorations, we blit them
62+		 * ourselves.
63+		 */
64+		struct weston_size pm_size = {
65+			.width = area.width,
66+			.height = area.height
67+		};
68+		weston_renderer_resize_output(&output->base, &pm_size, NULL);
69+	}
70
71 	wayland_output_destroy_shm_buffers(output);
72 }
73diff --git a/libweston/compositor.c b/libweston/compositor.c
74index d51a0bd..cd5c48d 100644
75--- a/libweston/compositor.c
76+++ b/libweston/compositor.c
77@@ -9273,3 +9273,30 @@ weston_output_disable_planes_decr(struct weston_output *output)
78 		weston_schedule_surface_protection_update(output->compositor);
79
80 }
81+
82+/** Tell the renderer that the target framebuffer size has changed
83+ *
84+ * \param output The output that was resized.
85+ * \param fb_size The framebuffer size, including output decorations.
86+ * \param area The composited area inside the framebuffer, excluding
87+ * decorations. This can also be NULL, which means the whole fb_size is
88+ * the composited area.
89+ */
90+WL_EXPORT void
91+weston_renderer_resize_output(struct weston_output *output,
92+			      const struct weston_size *fb_size,
93+			      const struct weston_geometry *area)
94+{
95+	struct weston_renderer *r = output->compositor->renderer;
96+	struct weston_geometry def = {
97+		.x = 0,
98+		.y = 0,
99+		.width = fb_size->width,
100+		.height = fb_size->height
101+	};
102+
103+	if (!r->resize_output(output, fb_size, area ?: &def)) {
104+		weston_log("Error: Resizing output '%s' failed.\n",
105+			   output->name);
106+	}
107+}
108diff --git a/libweston/libweston-internal.h b/libweston/libweston-internal.h
109index 39d9e85..bcfb153 100644
110--- a/libweston/libweston-internal.h
111+++ b/libweston/libweston-internal.h
112@@ -41,6 +41,7 @@
113  */
114
115 #include <libweston/libweston.h>
116+#include <assert.h>
117 #include "color.h"
118
119 /* compositor <-> renderer interface */
120@@ -52,6 +53,15 @@ struct weston_renderer {
121 			   uint32_t width, uint32_t height);
122 	void (*repaint_output)(struct weston_output *output,
123 			       pixman_region32_t *output_damage);
124+
125+	/** See weston_renderer_resize_output()
126+	 *
127+	 * \return True for success, false for leaving the output in a mess.
128+	 */
129+	bool (*resize_output)(struct weston_output *output,
130+			      const struct weston_size *fb_size,
131+			      const struct weston_geometry *area);
132+
133 	void (*flush_damage)(struct weston_surface *surface,
134 			     struct weston_buffer *buffer);
135 	void (*attach)(struct weston_surface *es, struct weston_buffer *buffer);
136@@ -74,6 +84,28 @@ struct weston_renderer {
137 				 struct weston_buffer *buffer);
138 };
139
140+void
141+weston_renderer_resize_output(struct weston_output *output,
142+			      const struct weston_size *fb_size,
143+			      const struct weston_geometry *area);
144+
145+static inline void
146+check_compositing_area(const struct weston_size *fb_size,
147+		       const struct weston_geometry *area)
148+{
149+	assert(fb_size);
150+	assert(fb_size->width > 0);
151+	assert(fb_size->height > 0);
152+
153+	assert(area);
154+	assert(area->x >= 0);
155+	assert(area->width > 0);
156+	assert(area->x <= fb_size->width - area->width);
157+	assert(area->y >= 0);
158+	assert(area->height > 0);
159+	assert(area->y <= fb_size->height - area->height);
160+}
161+
162 /* weston_buffer */
163
164 void
165diff --git a/libweston/noop-renderer.c b/libweston/noop-renderer.c
166index f99a313..35f180e 100644
167--- a/libweston/noop-renderer.c
168+++ b/libweston/noop-renderer.c
169@@ -51,6 +51,15 @@ noop_renderer_repaint_output(struct weston_output *output,
170 {
171 }
172
173+static bool
174+noop_renderer_resize_output(struct weston_output *output,
175+			    const struct weston_size *fb_size,
176+			    const struct weston_geometry *area)
177+{
178+	check_compositing_area(fb_size, area);
179+	return true;
180+}
181+
182 static void
183 noop_renderer_flush_damage(struct weston_surface *surface,
184 			   struct weston_buffer *buffer)
185@@ -124,6 +133,7 @@ noop_renderer_init(struct weston_compositor *ec)
186
187 	renderer->base.read_pixels = noop_renderer_read_pixels;
188 	renderer->base.repaint_output = noop_renderer_repaint_output;
189+	renderer->base.resize_output = noop_renderer_resize_output;
190 	renderer->base.flush_damage = noop_renderer_flush_damage;
191 	renderer->base.attach = noop_renderer_attach;
192 	renderer->base.destroy = noop_renderer_destroy;
193diff --git a/libweston/pixman-renderer.c b/libweston/pixman-renderer.c
194index 4e9e704..7678587 100644
195--- a/libweston/pixman-renderer.c
196+++ b/libweston/pixman-renderer.c
197@@ -1191,6 +1191,25 @@ pixman_renderer_surface_copy_content(struct weston_surface *surface,
198 	return 0;
199 }
200
201+static bool
202+pixman_renderer_resize_output(struct weston_output *output,
203+			      const struct weston_size *fb_size,
204+			      const struct weston_geometry *area)
205+{
206+	check_compositing_area(fb_size, area);
207+
208+	/*
209+	 * Pixman-renderer does not implement output decorations blitting,
210+	 * wayland-backend does it on its own.
211+	 */
212+	assert(area->x == 0);
213+	assert(area->y == 0);
214+	assert(fb_size->width == area->width);
215+	assert(fb_size->height == area->height);
216+
217+	return true;
218+}
219+
220 static void
221 debug_binding(struct weston_keyboard *keyboard, const struct timespec *time,
222 	      uint32_t key, void *data)
223@@ -1371,6 +1390,7 @@ pixman_renderer_init(struct weston_compositor *ec)
224 	renderer->debug_color = NULL;
225 	renderer->base.read_pixels = pixman_renderer_read_pixels;
226 	renderer->base.repaint_output = pixman_renderer_repaint_output;
227+	renderer->base.resize_output = pixman_renderer_resize_output;
228 	renderer->base.flush_damage = pixman_renderer_flush_damage;
229 	renderer->base.attach = pixman_renderer_attach;
230 	renderer->base.destroy = pixman_renderer_destroy;
231diff --git a/libweston/renderer-gl/gl-renderer.c b/libweston/renderer-gl/gl-renderer.c
232index 9b63c24..28fc4ae 100644
233--- a/libweston/renderer-gl/gl-renderer.c
234+++ b/libweston/renderer-gl/gl-renderer.c
235@@ -3427,6 +3427,15 @@ gl_renderer_output_set_border(struct weston_output *output,
236 	go->border_status |= 1 << side;
237 }
238
239+static bool
240+gl_renderer_resize_output(struct weston_output *output,
241+			  const struct weston_size *fb_size,
242+			  const struct weston_geometry *area)
243+{
244+	check_compositing_area(fb_size, area);
245+	return true;
246+}
247+
248 static int
249 gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface);
250
251@@ -3780,6 +3789,7 @@ gl_renderer_display_create(struct weston_compositor *ec,
252
253 	gr->base.read_pixels = gl_renderer_read_pixels;
254 	gr->base.repaint_output = gl_renderer_repaint_output;
255+	gr->base.resize_output = gl_renderer_resize_output;
256 	gr->base.flush_damage = gl_renderer_flush_damage;
257 	gr->base.attach = gl_renderer_attach;
258 	gr->base.destroy = gl_renderer_destroy;
259--
2602.20.1
261
262