blob: 39ab48076071a6db9c7dd2a3fd31fa7d36ccf5fc [file] [log] [blame]
Kristian Høgsbergffd710e2008-12-02 15:15:01 -05001/*
Kristian Høgsberg96aa7da2011-09-15 15:43:14 -04002 * Copyright © 2010-2011 Intel Corporation
3 * Copyright © 2008-2011 Kristian Høgsberg
Pekka Paalanen925788f2018-04-19 14:20:01 +03004 * Copyright © 2012-2018 Collabora, Ltd.
5 * Copyright © 2017, 2018 General Electric Company
Kristian Høgsbergffd710e2008-12-02 15:15:01 -05006 *
Bryce Harringtona0bbfea2015-06-11 15:35:43 -07007 * Permission is hereby granted, free of charge, to any person obtaining
8 * a copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sublicense, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
Kristian Høgsbergffd710e2008-12-02 15:15:01 -050014 *
Bryce Harringtona0bbfea2015-06-11 15:35:43 -070015 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial
17 * portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
23 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
24 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 * SOFTWARE.
Kristian Høgsbergffd710e2008-12-02 15:15:01 -050027 */
28
Kristian Høgsberga9410222011-01-14 17:22:35 -050029#include "config.h"
30
Daniel Stoneb7452fe2012-06-01 12:14:06 +010031#include <fcntl.h>
Kristian Høgsberg16eb6752008-10-08 22:51:32 -040032#include <stdio.h>
33#include <string.h>
34#include <stdlib.h>
35#include <stdint.h>
Benjamin Franzkeeefc36c2011-03-11 16:39:20 +010036#include <limits.h>
Kristian Høgsberg8d7ca6b2008-11-09 00:22:51 -050037#include <stdarg.h>
Benjamin Franzke6f5fc692011-06-21 19:34:19 +020038#include <assert.h>
Kristian Høgsberg16eb6752008-10-08 22:51:32 -040039#include <sys/ioctl.h>
Daniel Stoneb7452fe2012-06-01 12:14:06 +010040#include <sys/mman.h>
Kristian Høgsberg27da5382011-06-21 17:32:25 -040041#include <sys/wait.h>
Pekka Paalanen409ef0a2011-12-02 15:30:21 +020042#include <sys/socket.h>
Martin Minarikf12c2872012-06-11 00:57:39 +020043#include <sys/utsname.h>
Martin Minarik37032f82012-06-18 20:15:18 +020044#include <sys/stat.h>
Kristian Høgsberg16eb6752008-10-08 22:51:32 -040045#include <unistd.h>
Kristian Høgsberg54879822008-11-23 17:07:32 -050046#include <math.h>
Kristian Høgsbergfc783d42010-06-11 12:56:24 -040047#include <linux/input.h>
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -040048#include <dlfcn.h>
Kristian Høgsberg85449032011-05-02 12:11:07 -040049#include <signal.h>
Kristian Høgsberg0690da62012-01-16 11:53:54 -050050#include <setjmp.h>
Kristian Høgsberga411c8b2012-06-08 16:16:52 -040051#include <sys/time.h>
52#include <time.h>
Pekka Paalanen23ade622014-08-27 13:31:26 +030053#include <errno.h>
Alexandros Frantzisacff29b2018-10-19 12:14:11 +030054#include <inttypes.h>
Kristian Høgsberg890bc052008-12-30 14:31:33 -050055
Pekka Paalanenb5026542014-11-12 15:09:24 +020056#include "timeline.h"
57
Pekka Paalanen3d5d9472019-03-28 16:28:47 +020058#include <libweston/libweston.h>
Marius Vladc901e892019-06-21 22:49:18 +030059#include <libweston/weston-log.h>
Daniel Stonece62cb32018-07-20 09:46:24 +010060#include "linux-dmabuf.h"
Pekka Paalanene95ad5c2016-04-15 14:47:08 +030061#include "viewporter-server-protocol.h"
Pekka Paalanenb00c79b2016-02-18 16:53:27 +020062#include "presentation-time-server-protocol.h"
Roman Gilge97391c2019-03-29 13:01:06 +010063#include "xdg-output-unstable-v1-server-protocol.h"
Alexandros Frantzisacff29b2018-10-19 12:14:11 +030064#include "linux-explicit-synchronization-unstable-v1-server-protocol.h"
Alexandros Frantzis67629672018-10-19 12:14:11 +030065#include "linux-explicit-synchronization.h"
Alexandros Frantzisacff29b2018-10-19 12:14:11 +030066#include "shared/fd-util.h"
Jon Cruz35b2eaa2015-06-15 15:37:08 -070067#include "shared/helpers.h"
Jon Cruz4678bab2015-06-15 15:37:07 -070068#include "shared/os-compatibility.h"
Bryce Harrington25a2bdd2016-08-03 17:40:52 -070069#include "shared/string-helpers.h"
Pekka Paalanenaa21f622015-07-03 15:44:50 +030070#include "shared/timespec-util.h"
Kristian Høgsberga411c8b2012-06-08 16:16:52 -040071#include "git-version.h"
Pekka Paalanencda14882019-04-04 15:41:02 +030072#include <libweston/version.h>
Pekka Paalanen27b377f2019-03-29 17:07:34 +020073#include <libweston/plugin-registry.h>
Marius Vlad00a6e012018-11-20 17:52:31 +020074#include "pixel-formats.h"
Marius Vlad63ef0782019-07-16 23:34:14 +030075#include "backend.h"
Marius Vlada72e3712019-07-10 13:46:39 +030076#include "libweston-internal.h"
Kristian Høgsberg5ee1a602008-12-11 23:18:45 -050077
Marius Vlad4e036292019-07-09 00:36:20 +030078#include "weston-log-internal.h"
79
Marius Vlad78984ee2019-06-11 00:05:08 +030080/**
81 * \defgroup head Head
82 * \defgroup output Output
83 * \defgroup compositor Compositor
84 */
85
Pekka Paalanen0513a952014-05-21 16:17:27 +030086#define DEFAULT_REPAINT_WINDOW 7 /* milliseconds */
87
Ander Conselvan de Oliveira5c38ef42012-12-14 13:37:25 -020088static void
Pekka Paalanend72bad22017-03-29 17:01:41 +030089weston_output_update_matrix(struct weston_output *output);
90
91static void
Alexander Larsson0b135062013-05-28 16:23:36 +020092weston_output_transform_scale_init(struct weston_output *output,
93 uint32_t transform, uint32_t scale);
Ander Conselvan de Oliveira5c38ef42012-12-14 13:37:25 -020094
Rob Bradford27b17932013-06-26 18:08:46 +010095static void
Jason Ekstranda7af7042013-10-12 22:38:11 -050096weston_compositor_build_view_list(struct weston_compositor *compositor);
Rob Bradford27b17932013-06-26 18:08:46 +010097
Pekka Paalanendcac3512017-12-08 14:13:34 +020098static char *
99weston_output_create_heads_string(struct weston_output *output);
100
Pekka Paalanen6528c032017-03-28 15:27:10 +0300101/** Send wl_output events for mode and scale changes
102 *
103 * \param head Send on all resources bound to this head.
104 * \param mode_changed If true, send the current mode.
105 * \param scale_changed If true, send the current scale.
106 */
107static void
108weston_mode_switch_send_events(struct weston_head *head,
109 bool mode_changed, bool scale_changed)
110{
111 struct weston_output *output = head->output;
112 struct wl_resource *resource;
113 int version;
114
115 wl_resource_for_each(resource, &head->resource_list) {
116 if (mode_changed) {
117 wl_output_send_mode(resource,
118 output->current_mode->flags,
119 output->current_mode->width,
120 output->current_mode->height,
121 output->current_mode->refresh);
122 }
123
124 version = wl_resource_get_version(resource);
125 if (version >= WL_OUTPUT_SCALE_SINCE_VERSION && scale_changed)
126 wl_output_send_scale(resource, output->current_scale);
127
128 if (version >= WL_OUTPUT_DONE_SINCE_VERSION)
129 wl_output_send_done(resource);
130 }
Roman Gilge97391c2019-03-29 13:01:06 +0100131 wl_resource_for_each(resource, &head->xdg_output_resource_list) {
132 zxdg_output_v1_send_logical_position(resource,
133 output->x,
134 output->y);
135 zxdg_output_v1_send_logical_size(resource,
136 output->width,
137 output->height);
138 zxdg_output_v1_send_done(resource);
139 }
Pekka Paalanen6528c032017-03-28 15:27:10 +0300140}
141
142static void
143weston_mode_switch_finish(struct weston_output *output,
144 int mode_changed, int scale_changed)
Alex Wu2dda6042012-04-17 17:20:47 +0800145{
Ander Conselvan de Oliveira2bbb2b82012-12-14 13:37:26 -0200146 struct weston_seat *seat;
Pekka Paalanen1b9bf592017-03-27 12:15:38 +0300147 struct weston_head *head;
Ander Conselvan de Oliveira2bbb2b82012-12-14 13:37:26 -0200148 pixman_region32_t old_output_region;
Alexander Larsson355748e2013-05-28 16:23:38 +0200149
Ander Conselvan de Oliveira2bbb2b82012-12-14 13:37:26 -0200150 pixman_region32_init(&old_output_region);
151 pixman_region32_copy(&old_output_region, &output->region);
152
Ander Conselvan de Oliveira5c38ef42012-12-14 13:37:25 -0200153 /* Update output region and transformation matrix */
Hardeningff39efa2013-09-18 23:56:35 +0200154 weston_output_transform_scale_init(output, output->transform, output->current_scale);
Ander Conselvan de Oliveira5c38ef42012-12-14 13:37:25 -0200155
Ander Conselvan de Oliveira5c38ef42012-12-14 13:37:25 -0200156 pixman_region32_init_rect(&output->region, output->x, output->y,
157 output->width, output->height);
158
159 weston_output_update_matrix(output);
160
Ander Conselvan de Oliveira2bbb2b82012-12-14 13:37:26 -0200161 /* If a pointer falls outside the outputs new geometry, move it to its
162 * lower-right corner */
163 wl_list_for_each(seat, &output->compositor->seat_list, link) {
Derek Foreman1281a362015-07-31 16:55:32 -0500164 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Ander Conselvan de Oliveira2bbb2b82012-12-14 13:37:26 -0200165 int32_t x, y;
166
167 if (!pointer)
168 continue;
169
170 x = wl_fixed_to_int(pointer->x);
171 y = wl_fixed_to_int(pointer->y);
172
173 if (!pixman_region32_contains_point(&old_output_region,
174 x, y, NULL) ||
175 pixman_region32_contains_point(&output->region,
176 x, y, NULL))
177 continue;
178
179 if (x >= output->x + output->width)
180 x = output->x + output->width - 1;
181 if (y >= output->y + output->height)
182 y = output->y + output->height - 1;
183
184 pointer->x = wl_fixed_from_int(x);
185 pointer->y = wl_fixed_from_int(y);
186 }
187
188 pixman_region32_fini(&old_output_region);
189
Derek Foremandd4cd332014-11-10 10:29:59 -0600190 if (!mode_changed && !scale_changed)
191 return;
192
Hardening57388e42013-09-18 23:56:36 +0200193 /* notify clients of the changes */
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +0300194 wl_list_for_each(head, &output->head_list, output_link)
195 weston_mode_switch_send_events(head,
196 mode_changed, scale_changed);
Derek Foreman6ae7bc92014-11-04 10:47:33 -0600197}
198
David Fort0de859e2016-05-27 23:22:57 +0200199static void
200weston_compositor_reflow_outputs(struct weston_compositor *compositor,
201 struct weston_output *resized_output, int delta_width);
202
Marius Vlad55d87362019-06-11 01:15:35 +0300203/**
204 * \ingroup output
205 */
Derek Foreman6ae7bc92014-11-04 10:47:33 -0600206WL_EXPORT int
207weston_output_mode_set_native(struct weston_output *output,
208 struct weston_mode *mode,
209 int32_t scale)
210{
211 int ret;
212 int mode_changed = 0, scale_changed = 0;
David Fort0de859e2016-05-27 23:22:57 +0200213 int32_t old_width;
Derek Foreman6ae7bc92014-11-04 10:47:33 -0600214
215 if (!output->switch_mode)
216 return -1;
217
218 if (!output->original_mode) {
219 mode_changed = 1;
220 ret = output->switch_mode(output, mode);
221 if (ret < 0)
222 return ret;
223 if (output->current_scale != scale) {
224 scale_changed = 1;
225 output->current_scale = scale;
Hardening57388e42013-09-18 23:56:36 +0200226 }
227 }
228
David Fort0de859e2016-05-27 23:22:57 +0200229 old_width = output->width;
Derek Foreman6ae7bc92014-11-04 10:47:33 -0600230 output->native_mode = mode;
231 output->native_scale = scale;
232
233 weston_mode_switch_finish(output, mode_changed, scale_changed);
234
David Fort0de859e2016-05-27 23:22:57 +0200235 if (mode_changed || scale_changed) {
236 weston_compositor_reflow_outputs(output->compositor, output, output->width - old_width);
237
238 wl_signal_emit(&output->compositor->output_resized_signal, output);
239 }
Derek Foreman6ae7bc92014-11-04 10:47:33 -0600240 return 0;
241}
242
Marius Vlad55d87362019-06-11 01:15:35 +0300243/**
244 * \ingroup output
245 */
Derek Foreman6ae7bc92014-11-04 10:47:33 -0600246WL_EXPORT int
247weston_output_mode_switch_to_native(struct weston_output *output)
248{
249 int ret;
250 int mode_changed = 0, scale_changed = 0;
251
252 if (!output->switch_mode)
253 return -1;
254
255 if (!output->original_mode) {
256 weston_log("already in the native mode\n");
257 return -1;
258 }
259 /* the non fullscreen clients haven't seen a mode set since we
260 * switched into a temporary, so we need to notify them if the
261 * mode at that time is different from the native mode now.
262 */
263 mode_changed = (output->original_mode != output->native_mode);
264 scale_changed = (output->original_scale != output->native_scale);
265
266 ret = output->switch_mode(output, output->native_mode);
267 if (ret < 0)
268 return ret;
269
270 output->current_scale = output->native_scale;
271
272 output->original_mode = NULL;
273 output->original_scale = 0;
274
275 weston_mode_switch_finish(output, mode_changed, scale_changed);
276
277 return 0;
278}
279
Marius Vlad55d87362019-06-11 01:15:35 +0300280/**
281 * \ingroup output
282 */
Derek Foreman6ae7bc92014-11-04 10:47:33 -0600283WL_EXPORT int
284weston_output_mode_switch_to_temporary(struct weston_output *output,
285 struct weston_mode *mode,
286 int32_t scale)
287{
288 int ret;
289
290 if (!output->switch_mode)
291 return -1;
292
293 /* original_mode is the last mode non full screen clients have seen,
294 * so we shouldn't change it if we already have one set.
295 */
296 if (!output->original_mode) {
297 output->original_mode = output->native_mode;
298 output->original_scale = output->native_scale;
299 }
300 ret = output->switch_mode(output, mode);
301 if (ret < 0)
302 return ret;
303
304 output->current_scale = scale;
305
306 weston_mode_switch_finish(output, 0, 0);
307
308 return 0;
Alex Wu2dda6042012-04-17 17:20:47 +0800309}
310
Benjamin Franzke06286262011-05-06 19:12:33 +0200311static void
Pekka Paalanen0cbd3b52012-10-10 12:49:28 +0300312region_init_infinite(pixman_region32_t *region)
313{
314 pixman_region32_init_rect(region, INT32_MIN, INT32_MIN,
315 UINT32_MAX, UINT32_MAX);
316}
317
Pekka Paalanene67858b2013-04-25 13:57:42 +0300318static struct weston_subsurface *
319weston_surface_to_subsurface(struct weston_surface *surface);
320
Jason Ekstranda7af7042013-10-12 22:38:11 -0500321WL_EXPORT struct weston_view *
322weston_view_create(struct weston_surface *surface)
323{
324 struct weston_view *view;
325
Bryce Harringtonde16d892014-11-20 22:21:57 -0800326 view = zalloc(sizeof *view);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500327 if (view == NULL)
328 return NULL;
329
330 view->surface = surface;
Daniel Stonefb4869d2016-12-09 16:27:54 +0000331 view->plane = &surface->compositor->primary_plane;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500332
Jason Ekstranda7af7042013-10-12 22:38:11 -0500333 /* Assign to surface */
334 wl_list_insert(&surface->views, &view->surface_link);
335
336 wl_signal_init(&view->destroy_signal);
337 wl_list_init(&view->link);
Giulio Camuffo412e6a52014-07-09 22:12:56 +0300338 wl_list_init(&view->layer_link.link);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500339
Jason Ekstranda7af7042013-10-12 22:38:11 -0500340 pixman_region32_init(&view->clip);
341
342 view->alpha = 1.0;
343 pixman_region32_init(&view->transform.opaque);
344
345 wl_list_init(&view->geometry.transformation_list);
346 wl_list_insert(&view->geometry.transformation_list,
347 &view->transform.position.link);
348 weston_matrix_init(&view->transform.position.matrix);
349 wl_list_init(&view->geometry.child_list);
Pekka Paalanen380adf52015-02-16 14:39:11 +0200350 pixman_region32_init(&view->geometry.scissor);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500351 pixman_region32_init(&view->transform.boundingbox);
352 view->transform.dirty = 1;
353
Jason Ekstranda7af7042013-10-12 22:38:11 -0500354 return view;
355}
356
Jason Ekstrand108865d2014-06-26 10:04:49 -0700357struct weston_frame_callback {
358 struct wl_resource *resource;
359 struct wl_list link;
360};
361
Pekka Paalanen133e4392014-09-23 22:08:46 -0400362struct weston_presentation_feedback {
363 struct wl_resource *resource;
364
365 /* XXX: could use just wl_resource_get_link() instead */
366 struct wl_list link;
Pekka Paalanenbf0e0312014-12-17 16:20:41 +0200367
368 /* The per-surface feedback flags */
369 uint32_t psf_flags;
Pekka Paalanen133e4392014-09-23 22:08:46 -0400370};
371
372static void
373weston_presentation_feedback_discard(
374 struct weston_presentation_feedback *feedback)
375{
Pekka Paalanenb00c79b2016-02-18 16:53:27 +0200376 wp_presentation_feedback_send_discarded(feedback->resource);
Pekka Paalanen133e4392014-09-23 22:08:46 -0400377 wl_resource_destroy(feedback->resource);
378}
379
380static void
381weston_presentation_feedback_discard_list(struct wl_list *list)
382{
383 struct weston_presentation_feedback *feedback, *tmp;
384
385 wl_list_for_each_safe(feedback, tmp, list, link)
386 weston_presentation_feedback_discard(feedback);
387}
388
389static void
390weston_presentation_feedback_present(
391 struct weston_presentation_feedback *feedback,
392 struct weston_output *output,
393 uint32_t refresh_nsec,
394 const struct timespec *ts,
Pekka Paalanen363aa7b2014-12-17 16:20:40 +0200395 uint64_t seq,
396 uint32_t flags)
Pekka Paalanen133e4392014-09-23 22:08:46 -0400397{
398 struct wl_client *client = wl_resource_get_client(feedback->resource);
Pekka Paalanen1b9bf592017-03-27 12:15:38 +0300399 struct weston_head *head;
Pekka Paalanen133e4392014-09-23 22:08:46 -0400400 struct wl_resource *o;
Alexandros Frantzis10d708d2017-12-13 13:27:54 +0200401 uint32_t tv_sec_hi;
402 uint32_t tv_sec_lo;
403 uint32_t tv_nsec;
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +0300404 bool done = false;
Pekka Paalanen133e4392014-09-23 22:08:46 -0400405
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +0300406 wl_list_for_each(head, &output->head_list, output_link) {
407 wl_resource_for_each(o, &head->resource_list) {
408 if (wl_resource_get_client(o) != client)
409 continue;
Pekka Paalanen133e4392014-09-23 22:08:46 -0400410
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +0300411 wp_presentation_feedback_send_sync_output(feedback->resource, o);
412 done = true;
413 }
414
415 /* For clone mode, send it for just one wl_output global,
416 * they are all equivalent anyway.
417 */
418 if (done)
419 break;
Pekka Paalanen133e4392014-09-23 22:08:46 -0400420 }
421
Alexandros Frantzis10d708d2017-12-13 13:27:54 +0200422 timespec_to_proto(ts, &tv_sec_hi, &tv_sec_lo, &tv_nsec);
Pekka Paalanenb00c79b2016-02-18 16:53:27 +0200423 wp_presentation_feedback_send_presented(feedback->resource,
Alexandros Frantzis10d708d2017-12-13 13:27:54 +0200424 tv_sec_hi, tv_sec_lo, tv_nsec,
Pekka Paalanenb00c79b2016-02-18 16:53:27 +0200425 refresh_nsec,
426 seq >> 32, seq & 0xffffffff,
427 flags | feedback->psf_flags);
Pekka Paalanen133e4392014-09-23 22:08:46 -0400428 wl_resource_destroy(feedback->resource);
429}
430
431static void
432weston_presentation_feedback_present_list(struct wl_list *list,
433 struct weston_output *output,
434 uint32_t refresh_nsec,
435 const struct timespec *ts,
Pekka Paalanen363aa7b2014-12-17 16:20:40 +0200436 uint64_t seq,
437 uint32_t flags)
Pekka Paalanen133e4392014-09-23 22:08:46 -0400438{
439 struct weston_presentation_feedback *feedback, *tmp;
440
Pekka Paalanenb00c79b2016-02-18 16:53:27 +0200441 assert(!(flags & WP_PRESENTATION_FEEDBACK_INVALID) ||
Pekka Paalanen363aa7b2014-12-17 16:20:40 +0200442 wl_list_empty(list));
443
Pekka Paalanen133e4392014-09-23 22:08:46 -0400444 wl_list_for_each_safe(feedback, tmp, list, link)
445 weston_presentation_feedback_present(feedback, output,
Pekka Paalanen363aa7b2014-12-17 16:20:40 +0200446 refresh_nsec, ts, seq,
447 flags);
Pekka Paalanen133e4392014-09-23 22:08:46 -0400448}
449
Jason Ekstrand7b982072014-05-20 14:33:03 -0500450static void
451surface_state_handle_buffer_destroy(struct wl_listener *listener, void *data)
452{
453 struct weston_surface_state *state =
454 container_of(listener, struct weston_surface_state,
455 buffer_destroy_listener);
456
457 state->buffer = NULL;
458}
459
460static void
461weston_surface_state_init(struct weston_surface_state *state)
462{
463 state->newly_attached = 0;
464 state->buffer = NULL;
465 state->buffer_destroy_listener.notify =
466 surface_state_handle_buffer_destroy;
467 state->sx = 0;
468 state->sy = 0;
469
Derek Foreman152254b2015-11-26 14:17:48 -0600470 pixman_region32_init(&state->damage_surface);
471 pixman_region32_init(&state->damage_buffer);
Jason Ekstrand7b982072014-05-20 14:33:03 -0500472 pixman_region32_init(&state->opaque);
473 region_init_infinite(&state->input);
474
475 wl_list_init(&state->frame_callback_list);
Pekka Paalanen133e4392014-09-23 22:08:46 -0400476 wl_list_init(&state->feedback_list);
Jason Ekstrand7b982072014-05-20 14:33:03 -0500477
478 state->buffer_viewport.buffer.transform = WL_OUTPUT_TRANSFORM_NORMAL;
479 state->buffer_viewport.buffer.scale = 1;
480 state->buffer_viewport.buffer.src_width = wl_fixed_from_int(-1);
481 state->buffer_viewport.surface.width = -1;
482 state->buffer_viewport.changed = 0;
Alexandros Frantzisacff29b2018-10-19 12:14:11 +0300483
484 state->acquire_fence_fd = -1;
Ankit Nautiyal4b6e73d2019-03-26 13:37:12 +0530485
486 state->desired_protection = WESTON_HDCP_DISABLE;
Ankit Nautiyal5cfe03c2019-03-28 15:05:42 +0530487 state->protection_mode = WESTON_SURFACE_PROTECTION_MODE_RELAXED;
Jason Ekstrand7b982072014-05-20 14:33:03 -0500488}
489
490static void
491weston_surface_state_fini(struct weston_surface_state *state)
492{
493 struct weston_frame_callback *cb, *next;
494
495 wl_list_for_each_safe(cb, next,
496 &state->frame_callback_list, link)
497 wl_resource_destroy(cb->resource);
498
Pekka Paalanen133e4392014-09-23 22:08:46 -0400499 weston_presentation_feedback_discard_list(&state->feedback_list);
500
Jason Ekstrand7b982072014-05-20 14:33:03 -0500501 pixman_region32_fini(&state->input);
502 pixman_region32_fini(&state->opaque);
Derek Foreman152254b2015-11-26 14:17:48 -0600503 pixman_region32_fini(&state->damage_surface);
504 pixman_region32_fini(&state->damage_buffer);
Jason Ekstrand7b982072014-05-20 14:33:03 -0500505
506 if (state->buffer)
507 wl_list_remove(&state->buffer_destroy_listener.link);
508 state->buffer = NULL;
Alexandros Frantzisacff29b2018-10-19 12:14:11 +0300509
510 fd_clear(&state->acquire_fence_fd);
Alexandros Frantzis67629672018-10-19 12:14:11 +0300511 weston_buffer_release_reference(&state->buffer_release_ref, NULL);
Jason Ekstrand7b982072014-05-20 14:33:03 -0500512}
513
514static void
515weston_surface_state_set_buffer(struct weston_surface_state *state,
516 struct weston_buffer *buffer)
517{
518 if (state->buffer == buffer)
519 return;
520
521 if (state->buffer)
522 wl_list_remove(&state->buffer_destroy_listener.link);
523 state->buffer = buffer;
524 if (state->buffer)
525 wl_signal_add(&state->buffer->destroy_signal,
526 &state->buffer_destroy_listener);
527}
528
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500529WL_EXPORT struct weston_surface *
Kristian Høgsberg18c93002012-01-27 11:58:31 -0500530weston_surface_create(struct weston_compositor *compositor)
Kristian Høgsberg1a208d52009-02-10 14:20:26 -0500531{
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500532 struct weston_surface *surface;
Kristian Høgsberg77fb1672010-08-16 10:38:29 -0400533
Bryce Harringtonde16d892014-11-20 22:21:57 -0800534 surface = zalloc(sizeof *surface);
Kristian Høgsberg77fb1672010-08-16 10:38:29 -0400535 if (surface == NULL)
536 return NULL;
537
Jason Ekstrand26ed73c2013-06-06 22:34:41 -0500538 wl_signal_init(&surface->destroy_signal);
Jonas Ådahl5d9ca272016-07-22 17:48:03 +0800539 wl_signal_init(&surface->commit_signal);
Jason Ekstrand26ed73c2013-06-06 22:34:41 -0500540
Kristian Høgsberg1a208d52009-02-10 14:20:26 -0500541 surface->compositor = compositor;
Giulio Camuffo13b85bd2013-08-13 23:10:14 +0200542 surface->ref_count = 1;
Kristian Høgsberg27803c62010-06-06 22:23:21 -0400543
Pekka Paalanen952b6c82014-03-14 14:38:15 +0200544 surface->buffer_viewport.buffer.transform = WL_OUTPUT_TRANSFORM_NORMAL;
545 surface->buffer_viewport.buffer.scale = 1;
Pekka Paalanenf0cad482014-03-14 14:38:16 +0200546 surface->buffer_viewport.buffer.src_width = wl_fixed_from_int(-1);
547 surface->buffer_viewport.surface.width = -1;
Jason Ekstrand7b982072014-05-20 14:33:03 -0500548
549 weston_surface_state_init(&surface->pending);
550
Kristian Høgsberg20300ba2011-06-23 20:29:12 -0400551 pixman_region32_init(&surface->damage);
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -0500552 pixman_region32_init(&surface->opaque);
Pekka Paalanen8ec4ab62012-10-10 12:49:32 +0300553 region_init_infinite(&surface->input);
Kristian Høgsberg20300ba2011-06-23 20:29:12 -0400554
Jason Ekstranda7af7042013-10-12 22:38:11 -0500555 wl_list_init(&surface->views);
556
557 wl_list_init(&surface->frame_callback_list);
Pekka Paalanen133e4392014-09-23 22:08:46 -0400558 wl_list_init(&surface->feedback_list);
Kristian Høgsberg1e4b86a2008-11-23 23:41:08 -0500559
Pekka Paalanene67858b2013-04-25 13:57:42 +0300560 wl_list_init(&surface->subsurface_list);
561 wl_list_init(&surface->subsurface_list_pending);
562
Jason Ekstrand1e059042014-10-16 10:55:19 -0500563 weston_matrix_init(&surface->buffer_to_surface_matrix);
564 weston_matrix_init(&surface->surface_to_buffer_matrix);
565
Jonas Ådahld3414f22016-07-22 17:56:31 +0800566 wl_list_init(&surface->pointer_constraints);
567
Alexandros Frantzisacff29b2018-10-19 12:14:11 +0300568 surface->acquire_fence_fd = -1;
569
Ankit Nautiyal4b6e73d2019-03-26 13:37:12 +0530570 surface->desired_protection = WESTON_HDCP_DISABLE;
Ankit Nautiyal5cfe03c2019-03-28 15:05:42 +0530571 surface->current_protection = WESTON_HDCP_DISABLE;
572 surface->protection_mode = WESTON_SURFACE_PROTECTION_MODE_RELAXED;
Ankit Nautiyal4b6e73d2019-03-26 13:37:12 +0530573
Kristian Høgsberg77fb1672010-08-16 10:38:29 -0400574 return surface;
Kristian Høgsberg54879822008-11-23 17:07:32 -0500575}
576
Alex Wu8811bf92012-02-28 18:07:54 +0800577WL_EXPORT void
Kristian Høgsbergbbeefb02012-01-26 10:00:23 -0500578weston_surface_set_color(struct weston_surface *surface,
John Kåre Alsaker490d02a2012-09-30 02:57:21 +0200579 float red, float green, float blue, float alpha)
Kristian Høgsbergbbeefb02012-01-26 10:00:23 -0500580{
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100581 surface->compositor->renderer->surface_set_color(surface, red, green, blue, alpha);
Philipp Zabel195dade2018-09-03 19:44:59 +0200582 surface->is_opaque = !(alpha < 1.0);
Kristian Høgsbergbbeefb02012-01-26 10:00:23 -0500583}
584
Kristian Høgsberge4c1a5f2012-06-18 13:17:32 -0400585WL_EXPORT void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500586weston_view_to_global_float(struct weston_view *view,
587 float sx, float sy, float *x, float *y)
Pekka Paalanenece8a012012-02-08 15:23:15 +0200588{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500589 if (view->transform.enabled) {
Pekka Paalanenece8a012012-02-08 15:23:15 +0200590 struct weston_vector v = { { sx, sy, 0.0f, 1.0f } };
591
Jason Ekstranda7af7042013-10-12 22:38:11 -0500592 weston_matrix_transform(&view->transform.matrix, &v);
Pekka Paalanenece8a012012-02-08 15:23:15 +0200593
594 if (fabsf(v.f[3]) < 1e-6) {
Martin Minarik6d118362012-06-07 18:01:59 +0200595 weston_log("warning: numerical instability in "
Scott Moreau088c62e2013-02-11 04:45:38 -0700596 "%s(), divisor = %g\n", __func__,
Pekka Paalanenece8a012012-02-08 15:23:15 +0200597 v.f[3]);
598 *x = 0;
599 *y = 0;
600 return;
601 }
602
603 *x = v.f[0] / v.f[3];
604 *y = v.f[1] / v.f[3];
605 } else {
Jason Ekstranda7af7042013-10-12 22:38:11 -0500606 *x = sx + view->geometry.x;
607 *y = sy + view->geometry.y;
Pekka Paalanenece8a012012-02-08 15:23:15 +0200608 }
609}
610
Pekka Paalanen0df44772020-02-14 14:50:03 +0200611/** Transform a point to buffer coordinates
612 *
613 * \param width Surface width.
614 * \param height Surface height.
615 * \param transform Buffer transform.
616 * \param scale Buffer scale.
617 * \param sx Surface x coordinate of a point.
618 * \param sy Surface y coordinate of a point.
619 * \param[out] bx Buffer x coordinate of the point.
620 * \param[out] by Buffer Y coordinate of the point.
621 *
622 * Converts the given surface-local coordinates to buffer coordinates
623 * according to the given buffer transform and scale.
624 * This ignores wp_viewport.
625 *
626 * The given width and height must be the result of inverse scaled and
627 * inverse transformed buffer size.
628 */
Kristian Høgsbergd8bf90c2012-02-23 23:03:14 -0500629WL_EXPORT void
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200630weston_transformed_coord(int width, int height,
631 enum wl_output_transform transform,
Alexander Larssonedddbd12013-05-24 13:09:43 +0200632 int32_t scale,
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200633 float sx, float sy, float *bx, float *by)
634{
635 switch (transform) {
636 case WL_OUTPUT_TRANSFORM_NORMAL:
637 default:
638 *bx = sx;
639 *by = sy;
640 break;
641 case WL_OUTPUT_TRANSFORM_FLIPPED:
642 *bx = width - sx;
643 *by = sy;
644 break;
645 case WL_OUTPUT_TRANSFORM_90:
Pekka Paalanen8060d822020-02-06 15:27:54 +0200646 *bx = sy;
647 *by = width - sx;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200648 break;
649 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
Pekka Paalanen8060d822020-02-06 15:27:54 +0200650 *bx = sy;
651 *by = sx;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200652 break;
653 case WL_OUTPUT_TRANSFORM_180:
654 *bx = width - sx;
655 *by = height - sy;
656 break;
657 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
658 *bx = sx;
659 *by = height - sy;
660 break;
661 case WL_OUTPUT_TRANSFORM_270:
Pekka Paalanen8060d822020-02-06 15:27:54 +0200662 *bx = height - sy;
663 *by = sx;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200664 break;
665 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
Pekka Paalanen8060d822020-02-06 15:27:54 +0200666 *bx = height - sy;
667 *by = width - sx;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200668 break;
669 }
Alexander Larsson4ea95522013-05-22 14:41:37 +0200670
671 *bx *= scale;
672 *by *= scale;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200673}
674
Pekka Paalanen0df44772020-02-14 14:50:03 +0200675/** Transform a rectangle to buffer coordinates
676 *
677 * \param width Surface width.
678 * \param height Surface height.
679 * \param transform Buffer transform.
680 * \param scale Buffer scale.
681 * \param rect Rectangle in surface coordinates.
682 * \return Rectangle in buffer coordinates.
683 *
684 * Converts the given surface-local rectangle to buffer coordinates
685 * according to the given buffer transform and scale. The resulting
686 * rectangle is guaranteed to be well-formed.
687 * This ignores wp_viewport.
688 *
689 * The given width and height must be the result of inverse scaled and
690 * inverse transformed buffer size.
691 */
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200692WL_EXPORT pixman_box32_t
693weston_transformed_rect(int width, int height,
694 enum wl_output_transform transform,
Alexander Larssonedddbd12013-05-24 13:09:43 +0200695 int32_t scale,
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200696 pixman_box32_t rect)
697{
698 float x1, x2, y1, y2;
699
700 pixman_box32_t ret;
701
Alexander Larsson4ea95522013-05-22 14:41:37 +0200702 weston_transformed_coord(width, height, transform, scale,
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200703 rect.x1, rect.y1, &x1, &y1);
Alexander Larsson4ea95522013-05-22 14:41:37 +0200704 weston_transformed_coord(width, height, transform, scale,
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200705 rect.x2, rect.y2, &x2, &y2);
706
707 if (x1 <= x2) {
708 ret.x1 = x1;
709 ret.x2 = x2;
710 } else {
711 ret.x1 = x2;
712 ret.x2 = x1;
713 }
714
715 if (y1 <= y2) {
716 ret.y1 = y1;
717 ret.y2 = y2;
718 } else {
719 ret.y1 = y2;
720 ret.y2 = y1;
721 }
722
723 return ret;
724}
725
Derek Foremanbc9a61c2015-11-18 16:32:30 -0600726/** Transform a region by a matrix, restricted to axis-aligned transformations
727 *
728 * Warning: This function does not work for projective, affine, or matrices
729 * that encode arbitrary rotations. Only 90-degree step rotations are
730 * supported.
731 */
732WL_EXPORT void
733weston_matrix_transform_region(pixman_region32_t *dest,
734 struct weston_matrix *matrix,
735 pixman_region32_t *src)
736{
737 pixman_box32_t *src_rects, *dest_rects;
738 int nrects, i;
739
740 src_rects = pixman_region32_rectangles(src, &nrects);
741 dest_rects = malloc(nrects * sizeof(*dest_rects));
742 if (!dest_rects)
743 return;
744
745 for (i = 0; i < nrects; i++) {
746 struct weston_vector vec1 = {{
747 src_rects[i].x1, src_rects[i].y1, 0, 1
748 }};
749 weston_matrix_transform(matrix, &vec1);
750 vec1.f[0] /= vec1.f[3];
751 vec1.f[1] /= vec1.f[3];
752
753 struct weston_vector vec2 = {{
754 src_rects[i].x2, src_rects[i].y2, 0, 1
755 }};
756 weston_matrix_transform(matrix, &vec2);
757 vec2.f[0] /= vec2.f[3];
758 vec2.f[1] /= vec2.f[3];
759
760 if (vec1.f[0] < vec2.f[0]) {
761 dest_rects[i].x1 = floor(vec1.f[0]);
762 dest_rects[i].x2 = ceil(vec2.f[0]);
763 } else {
764 dest_rects[i].x1 = floor(vec2.f[0]);
765 dest_rects[i].x2 = ceil(vec1.f[0]);
766 }
767
Derek Foremanbc9a61c2015-11-18 16:32:30 -0600768 if (vec1.f[1] < vec2.f[1]) {
769 dest_rects[i].y1 = floor(vec1.f[1]);
770 dest_rects[i].y2 = ceil(vec2.f[1]);
771 } else {
772 dest_rects[i].y1 = floor(vec2.f[1]);
773 dest_rects[i].y2 = ceil(vec1.f[1]);
774 }
775 }
776
777 pixman_region32_clear(dest);
778 pixman_region32_init_rects(dest, dest_rects, nrects);
779 free(dest_rects);
780}
781
Pekka Paalanen0df44772020-02-14 14:50:03 +0200782/** Transform a region to buffer coordinates
783 *
784 * \param width Surface width.
785 * \param height Surface height.
786 * \param transform Buffer transform.
787 * \param scale Buffer scale.
788 * \param[in] src Region in surface coordinates.
789 * \param[out] dest Resulting region in buffer coordinates.
790 *
791 * Converts the given surface-local region to buffer coordinates
792 * according to the given buffer transform and scale.
793 * This ignores wp_viewport.
794 *
795 * The given width and height must be the result of inverse scaled and
796 * inverse transformed buffer size.
797 *
798 * src and dest are allowed to point to the same memory for in-place conversion.
799 */
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200800WL_EXPORT void
Jason Ekstrand33ff6362013-10-27 22:25:01 -0500801weston_transformed_region(int width, int height,
802 enum wl_output_transform transform,
803 int32_t scale,
804 pixman_region32_t *src, pixman_region32_t *dest)
805{
806 pixman_box32_t *src_rects, *dest_rects;
807 int nrects, i;
808
809 if (transform == WL_OUTPUT_TRANSFORM_NORMAL && scale == 1) {
810 if (src != dest)
811 pixman_region32_copy(dest, src);
812 return;
813 }
814
815 src_rects = pixman_region32_rectangles(src, &nrects);
816 dest_rects = malloc(nrects * sizeof(*dest_rects));
817 if (!dest_rects)
818 return;
819
820 if (transform == WL_OUTPUT_TRANSFORM_NORMAL) {
821 memcpy(dest_rects, src_rects, nrects * sizeof(*dest_rects));
822 } else {
823 for (i = 0; i < nrects; i++) {
824 switch (transform) {
825 default:
826 case WL_OUTPUT_TRANSFORM_NORMAL:
827 dest_rects[i].x1 = src_rects[i].x1;
828 dest_rects[i].y1 = src_rects[i].y1;
829 dest_rects[i].x2 = src_rects[i].x2;
830 dest_rects[i].y2 = src_rects[i].y2;
831 break;
832 case WL_OUTPUT_TRANSFORM_90:
Pekka Paalanen8060d822020-02-06 15:27:54 +0200833 dest_rects[i].x1 = src_rects[i].y1;
834 dest_rects[i].y1 = width - src_rects[i].x2;
835 dest_rects[i].x2 = src_rects[i].y2;
836 dest_rects[i].y2 = width - src_rects[i].x1;
Jason Ekstrand33ff6362013-10-27 22:25:01 -0500837 break;
838 case WL_OUTPUT_TRANSFORM_180:
839 dest_rects[i].x1 = width - src_rects[i].x2;
840 dest_rects[i].y1 = height - src_rects[i].y2;
841 dest_rects[i].x2 = width - src_rects[i].x1;
842 dest_rects[i].y2 = height - src_rects[i].y1;
843 break;
844 case WL_OUTPUT_TRANSFORM_270:
Pekka Paalanen8060d822020-02-06 15:27:54 +0200845 dest_rects[i].x1 = height - src_rects[i].y2;
846 dest_rects[i].y1 = src_rects[i].x1;
847 dest_rects[i].x2 = height - src_rects[i].y1;
848 dest_rects[i].y2 = src_rects[i].x2;
Jason Ekstrand33ff6362013-10-27 22:25:01 -0500849 break;
850 case WL_OUTPUT_TRANSFORM_FLIPPED:
851 dest_rects[i].x1 = width - src_rects[i].x2;
852 dest_rects[i].y1 = src_rects[i].y1;
853 dest_rects[i].x2 = width - src_rects[i].x1;
854 dest_rects[i].y2 = src_rects[i].y2;
855 break;
856 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
Pekka Paalanen8060d822020-02-06 15:27:54 +0200857 dest_rects[i].x1 = src_rects[i].y1;
858 dest_rects[i].y1 = src_rects[i].x1;
859 dest_rects[i].x2 = src_rects[i].y2;
860 dest_rects[i].y2 = src_rects[i].x2;
Jason Ekstrand33ff6362013-10-27 22:25:01 -0500861 break;
862 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
863 dest_rects[i].x1 = src_rects[i].x1;
864 dest_rects[i].y1 = height - src_rects[i].y2;
865 dest_rects[i].x2 = src_rects[i].x2;
866 dest_rects[i].y2 = height - src_rects[i].y1;
867 break;
868 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
Pekka Paalanen8060d822020-02-06 15:27:54 +0200869 dest_rects[i].x1 = height - src_rects[i].y2;
870 dest_rects[i].y1 = width - src_rects[i].x2;
871 dest_rects[i].x2 = height - src_rects[i].y1;
872 dest_rects[i].y2 = width - src_rects[i].x1;
Jason Ekstrand33ff6362013-10-27 22:25:01 -0500873 break;
874 }
875 }
876 }
877
878 if (scale != 1) {
879 for (i = 0; i < nrects; i++) {
880 dest_rects[i].x1 *= scale;
881 dest_rects[i].x2 *= scale;
882 dest_rects[i].y1 *= scale;
883 dest_rects[i].y2 *= scale;
884 }
885 }
886
887 pixman_region32_clear(dest);
888 pixman_region32_init_rects(dest, dest_rects, nrects);
889 free(dest_rects);
890}
891
Jonny Lamb74130762013-11-26 18:19:46 +0100892static void
Pekka Paalanen9c5a0d92016-04-15 16:42:49 +0300893viewport_surface_to_buffer(struct weston_surface *surface,
894 float sx, float sy, float *bx, float *by)
Jonny Lamb74130762013-11-26 18:19:46 +0100895{
Pekka Paalanen952b6c82014-03-14 14:38:15 +0200896 struct weston_buffer_viewport *vp = &surface->buffer_viewport;
Pekka Paalanen0b4c5352014-03-14 14:38:17 +0200897 double src_width, src_height;
898 double src_x, src_y;
Pekka Paalanen952b6c82014-03-14 14:38:15 +0200899
Pekka Paalanen0b4c5352014-03-14 14:38:17 +0200900 if (vp->buffer.src_width == wl_fixed_from_int(-1)) {
901 if (vp->surface.width == -1) {
902 *bx = sx;
903 *by = sy;
904 return;
905 }
Jonny Lamb74130762013-11-26 18:19:46 +0100906
Pekka Paalanen0b4c5352014-03-14 14:38:17 +0200907 src_x = 0.0;
908 src_y = 0.0;
909 src_width = surface->width_from_buffer;
910 src_height = surface->height_from_buffer;
Jonny Lamb74130762013-11-26 18:19:46 +0100911 } else {
Pekka Paalanen0b4c5352014-03-14 14:38:17 +0200912 src_x = wl_fixed_to_double(vp->buffer.src_x);
913 src_y = wl_fixed_to_double(vp->buffer.src_y);
914 src_width = wl_fixed_to_double(vp->buffer.src_width);
915 src_height = wl_fixed_to_double(vp->buffer.src_height);
Jonny Lamb74130762013-11-26 18:19:46 +0100916 }
Pekka Paalanen0b4c5352014-03-14 14:38:17 +0200917
918 *bx = sx * src_width / surface->width + src_x;
919 *by = sy * src_height / surface->height + src_y;
Jonny Lamb74130762013-11-26 18:19:46 +0100920}
921
Jason Ekstrand33ff6362013-10-27 22:25:01 -0500922WL_EXPORT void
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +0200923weston_surface_to_buffer_float(struct weston_surface *surface,
924 float sx, float sy, float *bx, float *by)
925{
Pekka Paalanen952b6c82014-03-14 14:38:15 +0200926 struct weston_buffer_viewport *vp = &surface->buffer_viewport;
927
Pekka Paalanen9c5a0d92016-04-15 16:42:49 +0300928 /* first transform coordinates if the viewport is set */
929 viewport_surface_to_buffer(surface, sx, sy, bx, by);
Jonny Lamb74130762013-11-26 18:19:46 +0100930
Jason Ekstrandd0cebc32014-04-21 20:56:46 -0500931 weston_transformed_coord(surface->width_from_buffer,
932 surface->height_from_buffer,
Pekka Paalanen952b6c82014-03-14 14:38:15 +0200933 vp->buffer.transform, vp->buffer.scale,
Jonny Lamb74130762013-11-26 18:19:46 +0100934 *bx, *by, bx, by);
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +0200935}
936
Derek Foreman99739672015-12-03 16:38:11 -0600937/** Transform a rectangle from surface coordinates to buffer coordinates
938 *
Pekka Paalanene95ad5c2016-04-15 14:47:08 +0300939 * \param surface The surface to fetch wp_viewport and buffer transformation
Derek Foreman99739672015-12-03 16:38:11 -0600940 * from.
941 * \param rect The rectangle to transform.
942 * \return The transformed rectangle.
943 *
944 * Viewport and buffer transformations can only do translation, scaling,
945 * and rotations in 90-degree steps. Therefore the only loss in the
946 * conversion is coordinate rounding.
947 *
948 * However, some coordinate rounding takes place as an intermediate
949 * step before the buffer scale factor is applied, so the rectangle
950 * boundary may not be exactly as expected.
951 *
952 * This is OK for damage tracking since a little extra coverage is
953 * not a problem.
954 */
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +0200955WL_EXPORT pixman_box32_t
956weston_surface_to_buffer_rect(struct weston_surface *surface,
957 pixman_box32_t rect)
958{
Pekka Paalanen952b6c82014-03-14 14:38:15 +0200959 struct weston_buffer_viewport *vp = &surface->buffer_viewport;
Jonny Lamb74130762013-11-26 18:19:46 +0100960 float xf, yf;
961
Pekka Paalanen9c5a0d92016-04-15 16:42:49 +0300962 /* first transform box coordinates if the viewport is set */
963 viewport_surface_to_buffer(surface, rect.x1, rect.y1, &xf, &yf);
Jonny Lamb74130762013-11-26 18:19:46 +0100964 rect.x1 = floorf(xf);
965 rect.y1 = floorf(yf);
966
Pekka Paalanen9c5a0d92016-04-15 16:42:49 +0300967 viewport_surface_to_buffer(surface, rect.x2, rect.y2, &xf, &yf);
Derek Foremane2e15ac2015-12-01 13:00:43 -0600968 rect.x2 = ceilf(xf);
969 rect.y2 = ceilf(yf);
Jonny Lamb74130762013-11-26 18:19:46 +0100970
Jason Ekstrandd0cebc32014-04-21 20:56:46 -0500971 return weston_transformed_rect(surface->width_from_buffer,
972 surface->height_from_buffer,
Pekka Paalanen952b6c82014-03-14 14:38:15 +0200973 vp->buffer.transform, vp->buffer.scale,
Alexander Larsson4ea95522013-05-22 14:41:37 +0200974 rect);
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +0200975}
976
Pekka Paalanene54e31c2015-03-04 14:23:28 +0200977/** Transform a region from surface coordinates to buffer coordinates
978 *
Pekka Paalanene95ad5c2016-04-15 14:47:08 +0300979 * \param surface The surface to fetch wp_viewport and buffer transformation
Pekka Paalanene54e31c2015-03-04 14:23:28 +0200980 * from.
Marius Vlada2dace22019-06-12 16:05:44 +0300981 * \param[in] surface_region The region in surface coordinates.
982 * \param[out] buffer_region The region converted to buffer coordinates.
Pekka Paalanene54e31c2015-03-04 14:23:28 +0200983 *
984 * Buffer_region must be init'd, but will be completely overwritten.
985 *
986 * Viewport and buffer transformations can only do translation, scaling,
987 * and rotations in 90-degree steps. Therefore the only loss in the
Derek Foreman99739672015-12-03 16:38:11 -0600988 * conversion is from the coordinate rounding that takes place in
989 * \ref weston_surface_to_buffer_rect.
Marius Vlada2dace22019-06-12 16:05:44 +0300990 *
Pekka Paalanene54e31c2015-03-04 14:23:28 +0200991 */
992WL_EXPORT void
993weston_surface_to_buffer_region(struct weston_surface *surface,
994 pixman_region32_t *surface_region,
995 pixman_region32_t *buffer_region)
996{
997 pixman_box32_t *src_rects, *dest_rects;
998 int nrects, i;
999
1000 src_rects = pixman_region32_rectangles(surface_region, &nrects);
1001 dest_rects = malloc(nrects * sizeof(*dest_rects));
1002 if (!dest_rects)
1003 return;
1004
1005 for (i = 0; i < nrects; i++) {
1006 dest_rects[i] = weston_surface_to_buffer_rect(surface,
1007 src_rects[i]);
1008 }
1009
1010 pixman_region32_fini(buffer_region);
1011 pixman_region32_init_rects(buffer_region, dest_rects, nrects);
1012 free(dest_rects);
1013}
1014
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +02001015WL_EXPORT void
Jason Ekstranda7af7042013-10-12 22:38:11 -05001016weston_view_move_to_plane(struct weston_view *view,
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04001017 struct weston_plane *plane)
1018{
Jason Ekstranda7af7042013-10-12 22:38:11 -05001019 if (view->plane == plane)
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04001020 return;
1021
Jason Ekstranda7af7042013-10-12 22:38:11 -05001022 weston_view_damage_below(view);
1023 view->plane = plane;
1024 weston_surface_damage(view->surface);
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04001025}
1026
Pekka Paalanen51723d52015-02-17 13:10:01 +02001027/** Inflict damage on the plane where the view is visible.
1028 *
1029 * \param view The view that causes the damage.
1030 *
1031 * If the view is currently on a plane (including the primary plane),
1032 * take the view's boundingbox, subtract all the opaque views that cover it,
1033 * and add the remaining region as damage to the plane. This corresponds
1034 * to the damage inflicted to the plane if this view disappeared.
1035 *
1036 * A repaint is scheduled for this view.
1037 *
1038 * The region of all opaque views covering this view is stored in
1039 * weston_view::clip and updated by view_accumulate_damage() during
1040 * weston_output_repaint(). Specifically, that region matches the
1041 * scenegraph as it was last painted.
1042 */
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04001043WL_EXPORT void
Jason Ekstranda7af7042013-10-12 22:38:11 -05001044weston_view_damage_below(struct weston_view *view)
Pekka Paalanen9abf3932012-02-08 14:49:37 +02001045{
Kristian Høgsberg1e832122012-02-28 22:47:14 -05001046 pixman_region32_t damage;
Pekka Paalanen9abf3932012-02-08 14:49:37 +02001047
Kristian Høgsberg1e832122012-02-28 22:47:14 -05001048 pixman_region32_init(&damage);
Pekka Paalanen25c0ca52015-02-19 11:15:33 +02001049 pixman_region32_subtract(&damage, &view->transform.boundingbox,
Jason Ekstranda7af7042013-10-12 22:38:11 -05001050 &view->clip);
Xiong Zhang97116532013-10-23 13:58:31 +08001051 if (view->plane)
1052 pixman_region32_union(&view->plane->damage,
1053 &view->plane->damage, &damage);
Kristian Høgsberg1e832122012-02-28 22:47:14 -05001054 pixman_region32_fini(&damage);
Kristian Høgsberga3a784a2013-11-13 21:33:43 -08001055 weston_view_schedule_repaint(view);
Pekka Paalanen9abf3932012-02-08 14:49:37 +02001056}
1057
Pekka Paalanen01e00682017-03-24 16:21:06 +02001058/** Send wl_surface.enter/leave events
1059 *
1060 * \param surface The surface.
Pekka Paalanen1b9bf592017-03-27 12:15:38 +03001061 * \param head A head of the entered/left output.
Pekka Paalanen01e00682017-03-24 16:21:06 +02001062 * \param enter True if entered.
Marius Vlada2dace22019-06-12 16:05:44 +03001063 * \param leave True if left.
Pekka Paalanen01e00682017-03-24 16:21:06 +02001064 *
1065 * Send the enter/leave events for all protocol objects bound to the given
1066 * output by the client owning the surface.
1067 */
1068static void
1069weston_surface_send_enter_leave(struct weston_surface *surface,
Pekka Paalanen1b9bf592017-03-27 12:15:38 +03001070 struct weston_head *head,
Pekka Paalanen01e00682017-03-24 16:21:06 +02001071 bool enter,
1072 bool leave)
1073{
1074 struct wl_resource *wloutput;
1075 struct wl_client *client;
1076
1077 assert(enter != leave);
1078
1079 client = wl_resource_get_client(surface->resource);
Pekka Paalanen1b9bf592017-03-27 12:15:38 +03001080 wl_resource_for_each(wloutput, &head->resource_list) {
Pekka Paalanen01e00682017-03-24 16:21:06 +02001081 if (wl_resource_get_client(wloutput) != client)
1082 continue;
1083
1084 if (enter)
1085 wl_surface_send_enter(surface->resource, wloutput);
1086 if (leave)
1087 wl_surface_send_leave(surface->resource, wloutput);
1088 }
1089}
1090
Ankit Nautiyalf74c35b2019-04-03 19:21:58 +05301091static void
1092weston_surface_compute_protection(struct protected_surface *psurface)
1093{
1094 enum weston_hdcp_protection min_protection;
1095 bool min_protection_valid = false;
1096 struct weston_surface *surface = psurface->surface;
1097 struct weston_output *output;
1098
1099 wl_list_for_each(output, &surface->compositor->output_list, link)
1100 if (surface->output_mask & (1u << output->id)) {
Ankit Nautiyal4fd38132019-07-08 15:12:19 +05301101 /*
1102 * If the content-protection is enabled with protection
1103 * mode as RELAXED for a surface, and if
1104 * content-recording features like: screen-shooter,
1105 * recorder, screen-sharing, etc are on, then notify the
1106 * client, that the protection is disabled.
1107 *
1108 * Note: If the protection mode is ENFORCED then there
1109 * is no need to bother the client as the renderer takes
1110 * care of censoring the visibility of the protected
1111 * content.
1112 */
1113
1114 if (output->disable_planes > 0 &&
1115 surface->protection_mode == WESTON_SURFACE_PROTECTION_MODE_RELAXED) {
1116 min_protection = WESTON_HDCP_DISABLE;
1117 min_protection_valid = true;
1118 break;
1119 }
Ankit Nautiyalf74c35b2019-04-03 19:21:58 +05301120 if (!min_protection_valid) {
1121 min_protection = output->current_protection;
1122 min_protection_valid = true;
1123 }
1124 if (output->current_protection < min_protection)
1125 min_protection = output->current_protection;
1126 }
1127 if (!min_protection_valid)
1128 min_protection = WESTON_HDCP_DISABLE;
1129
1130 surface->current_protection = min_protection;
Ankit Nautiyal4fd38132019-07-08 15:12:19 +05301131
1132 weston_protected_surface_send_event(psurface, surface->current_protection);
Ankit Nautiyalf74c35b2019-04-03 19:21:58 +05301133}
1134
1135static void
1136notify_surface_protection_change(void *data)
1137{
1138 struct weston_compositor *compositor = data;
1139 struct content_protection *cp;
1140 struct protected_surface *psurface;
1141
1142 cp = compositor->content_protection;
1143 cp->surface_protection_update = NULL;
1144
1145 /* Notify the clients, whose surfaces are changed */
1146 wl_list_for_each(psurface, &cp->protected_list, link)
1147 if (psurface && psurface->surface)
1148 weston_surface_compute_protection(psurface);
1149}
1150
Bryce Harrington3f650b82015-12-23 11:01:58 -08001151/**
Ankit Nautiyalfaa5ab42019-07-08 13:23:24 +05301152 * \param compositor weston_compositor
1153 *
1154 * Schedule an idle task to notify surface about the update in protection,
1155 * if not already scheduled.
1156 */
1157static void
1158weston_schedule_surface_protection_update(struct weston_compositor *compositor)
1159{
1160 struct content_protection *cp = compositor->content_protection;
1161 struct wl_event_loop *loop;
1162
1163 if (!cp || cp->surface_protection_update)
1164 return;
1165 loop = wl_display_get_event_loop(compositor->wl_display);
1166 cp->surface_protection_update = wl_event_loop_add_idle(loop,
1167 notify_surface_protection_change,
1168 compositor);
1169}
1170
1171/**
Bryce Harrington3f650b82015-12-23 11:01:58 -08001172 * \param es The surface
1173 * \param mask The new set of outputs for the surface
1174 *
1175 * Sets the surface's set of outputs to the ones specified by
1176 * the new output mask provided. Identifies the outputs that
1177 * have changed, the posts enter and leave events for these
1178 * outputs as appropriate.
1179 */
Kristian Høgsbergb9af4792012-09-25 14:48:04 -04001180static void
1181weston_surface_update_output_mask(struct weston_surface *es, uint32_t mask)
1182{
1183 uint32_t different = es->output_mask ^ mask;
1184 uint32_t entered = mask & different;
1185 uint32_t left = es->output_mask & different;
Pekka Paalanen01e00682017-03-24 16:21:06 +02001186 uint32_t output_bit;
Kristian Høgsbergb9af4792012-09-25 14:48:04 -04001187 struct weston_output *output;
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03001188 struct weston_head *head;
Kristian Høgsbergb9af4792012-09-25 14:48:04 -04001189
1190 es->output_mask = mask;
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05001191 if (es->resource == NULL)
Kristian Høgsbergb9af4792012-09-25 14:48:04 -04001192 return;
1193 if (different == 0)
1194 return;
1195
1196 wl_list_for_each(output, &es->compositor->output_list, link) {
Pekka Paalanen01e00682017-03-24 16:21:06 +02001197 output_bit = 1u << output->id;
1198 if (!(output_bit & different))
Kristian Høgsbergb9af4792012-09-25 14:48:04 -04001199 continue;
Pekka Paalanen01e00682017-03-24 16:21:06 +02001200
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03001201 wl_list_for_each(head, &output->head_list, output_link) {
1202 weston_surface_send_enter_leave(es, head,
1203 output_bit & entered,
1204 output_bit & left);
1205 }
Kristian Høgsbergb9af4792012-09-25 14:48:04 -04001206 }
Ankit Nautiyalf74c35b2019-04-03 19:21:58 +05301207 /*
1208 * Change in surfaces' output mask might trigger a change in its
1209 * protection.
1210 */
Ankit Nautiyalfaa5ab42019-07-08 13:23:24 +05301211 weston_schedule_surface_protection_update(es->compositor);
Kristian Høgsbergb9af4792012-09-25 14:48:04 -04001212}
1213
Semi Malinene7a52fb2018-04-26 11:08:10 +02001214static void
1215notify_view_output_destroy(struct wl_listener *listener, void *data)
1216{
1217 struct weston_view *view =
1218 container_of(listener,
1219 struct weston_view, output_destroy_listener);
1220
1221 view->output = NULL;
1222 view->output_destroy_listener.notify = NULL;
1223}
1224
1225/** Set the primary output of the view
1226 *
1227 * \param view The view whose primary output to set
1228 * \param output The new primary output for the view
1229 *
1230 * Set \a output to be the primary output of the \a view.
1231 *
1232 * Notice that the assignment may be temporary; the primary output could be
1233 * automatically changed. Hence, one cannot rely on the value persisting.
1234 *
1235 * Passing NULL as /a output will set the primary output to NULL.
1236 */
1237WL_EXPORT void
1238weston_view_set_output(struct weston_view *view, struct weston_output *output)
1239{
1240 if (view->output_destroy_listener.notify) {
1241 wl_list_remove(&view->output_destroy_listener.link);
1242 view->output_destroy_listener.notify = NULL;
1243 }
1244 view->output = output;
1245 if (output) {
1246 view->output_destroy_listener.notify =
1247 notify_view_output_destroy;
1248 wl_signal_add(&output->destroy_signal,
1249 &view->output_destroy_listener);
1250 }
1251}
1252
Bryce Harrington3f650b82015-12-23 11:01:58 -08001253/** Recalculate which output(s) the surface has views displayed on
1254 *
1255 * \param es The surface to remap to outputs
1256 *
1257 * Finds the output that is showing the largest amount of one
1258 * of the surface's various views. This output becomes the
Pekka Paalanen130ae6e2016-03-30 14:33:33 +03001259 * surface's primary output for vsync and frame callback purposes.
Bryce Harrington3f650b82015-12-23 11:01:58 -08001260 *
Pekka Paalanen130ae6e2016-03-30 14:33:33 +03001261 * Also notes all outputs of all of the surface's views
Bryce Harrington3f650b82015-12-23 11:01:58 -08001262 * in the output_mask for the surface.
1263 */
Kristian Høgsbergb9af4792012-09-25 14:48:04 -04001264static void
1265weston_surface_assign_output(struct weston_surface *es)
1266{
Jason Ekstranda7af7042013-10-12 22:38:11 -05001267 struct weston_output *new_output;
1268 struct weston_view *view;
1269 pixman_region32_t region;
1270 uint32_t max, area, mask;
1271 pixman_box32_t *e;
1272
1273 new_output = NULL;
1274 max = 0;
1275 mask = 0;
1276 pixman_region32_init(&region);
1277 wl_list_for_each(view, &es->views, surface_link) {
1278 if (!view->output)
1279 continue;
1280
1281 pixman_region32_intersect(&region, &view->transform.boundingbox,
1282 &view->output->region);
1283
1284 e = pixman_region32_extents(&region);
1285 area = (e->x2 - e->x1) * (e->y2 - e->y1);
1286
1287 mask |= view->output_mask;
1288
1289 if (area >= max) {
1290 new_output = view->output;
1291 max = area;
1292 }
1293 }
1294 pixman_region32_fini(&region);
1295
1296 es->output = new_output;
1297 weston_surface_update_output_mask(es, mask);
1298}
1299
Bryce Harrington3f650b82015-12-23 11:01:58 -08001300/** Recalculate which output(s) the view is displayed on
1301 *
1302 * \param ev The view to remap to outputs
1303 *
1304 * Identifies the set of outputs that the view is visible on,
1305 * noting them into the output_mask. The output that the view
Pekka Paalanen130ae6e2016-03-30 14:33:33 +03001306 * is most visible on is set as the view's primary output.
Bryce Harrington3f650b82015-12-23 11:01:58 -08001307 *
1308 * Also does the same for the view's surface. See
1309 * weston_surface_assign_output().
1310 */
Jason Ekstranda7af7042013-10-12 22:38:11 -05001311static void
1312weston_view_assign_output(struct weston_view *ev)
1313{
1314 struct weston_compositor *ec = ev->surface->compositor;
Kristian Høgsbergb9af4792012-09-25 14:48:04 -04001315 struct weston_output *output, *new_output;
1316 pixman_region32_t region;
1317 uint32_t max, area, mask;
1318 pixman_box32_t *e;
1319
1320 new_output = NULL;
1321 max = 0;
1322 mask = 0;
1323 pixman_region32_init(&region);
1324 wl_list_for_each(output, &ec->output_list, link) {
Giulio Camuffo2f2a70c2015-07-12 10:52:32 +03001325 if (output->destroying)
1326 continue;
1327
Jason Ekstranda7af7042013-10-12 22:38:11 -05001328 pixman_region32_intersect(&region, &ev->transform.boundingbox,
Kristian Høgsbergb9af4792012-09-25 14:48:04 -04001329 &output->region);
1330
1331 e = pixman_region32_extents(&region);
1332 area = (e->x2 - e->x1) * (e->y2 - e->y1);
1333
1334 if (area > 0)
Bryce Harrington89324ce2015-12-23 18:38:07 -08001335 mask |= 1u << output->id;
Kristian Høgsbergb9af4792012-09-25 14:48:04 -04001336
1337 if (area >= max) {
1338 new_output = output;
1339 max = area;
1340 }
1341 }
1342 pixman_region32_fini(&region);
1343
Semi Malinene7a52fb2018-04-26 11:08:10 +02001344 weston_view_set_output(ev, new_output);
Jason Ekstranda7af7042013-10-12 22:38:11 -05001345 ev->output_mask = mask;
1346
1347 weston_surface_assign_output(ev->surface);
Kristian Høgsbergb9af4792012-09-25 14:48:04 -04001348}
1349
Pekka Paalanen9abf3932012-02-08 14:49:37 +02001350static void
Pekka Paalanen380adf52015-02-16 14:39:11 +02001351weston_view_to_view_map(struct weston_view *from, struct weston_view *to,
1352 int from_x, int from_y, int *to_x, int *to_y)
1353{
1354 float x, y;
1355
1356 weston_view_to_global_float(from, from_x, from_y, &x, &y);
1357 weston_view_from_global_float(to, x, y, &x, &y);
1358
1359 *to_x = round(x);
1360 *to_y = round(y);
1361}
1362
1363static void
1364weston_view_transfer_scissor(struct weston_view *from, struct weston_view *to)
1365{
1366 pixman_box32_t *a;
1367 pixman_box32_t b;
1368
1369 a = pixman_region32_extents(&from->geometry.scissor);
1370
1371 weston_view_to_view_map(from, to, a->x1, a->y1, &b.x1, &b.y1);
1372 weston_view_to_view_map(from, to, a->x2, a->y2, &b.x2, &b.y2);
1373
1374 pixman_region32_fini(&to->geometry.scissor);
1375 pixman_region32_init_with_extents(&to->geometry.scissor, &b);
1376}
1377
1378static void
Pekka Paalanenc7d7fdf2015-02-23 12:27:00 +02001379view_compute_bbox(struct weston_view *view, const pixman_box32_t *inbox,
Jason Ekstranda7af7042013-10-12 22:38:11 -05001380 pixman_region32_t *bbox)
Pekka Paalanen6720d8f2012-01-25 15:17:40 +02001381{
John Kåre Alsaker490d02a2012-09-30 02:57:21 +02001382 float min_x = HUGE_VALF, min_y = HUGE_VALF;
1383 float max_x = -HUGE_VALF, max_y = -HUGE_VALF;
Pekka Paalanen6720d8f2012-01-25 15:17:40 +02001384 int32_t s[4][2] = {
Pekka Paalanenc7d7fdf2015-02-23 12:27:00 +02001385 { inbox->x1, inbox->y1 },
1386 { inbox->x1, inbox->y2 },
1387 { inbox->x2, inbox->y1 },
1388 { inbox->x2, inbox->y2 },
Pekka Paalanen6720d8f2012-01-25 15:17:40 +02001389 };
John Kåre Alsaker490d02a2012-09-30 02:57:21 +02001390 float int_x, int_y;
Pekka Paalanen6720d8f2012-01-25 15:17:40 +02001391 int i;
1392
Pekka Paalanenc7d7fdf2015-02-23 12:27:00 +02001393 if (inbox->x1 == inbox->x2 || inbox->y1 == inbox->y2) {
Pekka Paalanen7c7d4642012-09-04 13:55:44 +03001394 /* avoid rounding empty bbox to 1x1 */
1395 pixman_region32_init(bbox);
1396 return;
1397 }
1398
Pekka Paalanen6720d8f2012-01-25 15:17:40 +02001399 for (i = 0; i < 4; ++i) {
John Kåre Alsaker490d02a2012-09-30 02:57:21 +02001400 float x, y;
Jason Ekstranda7af7042013-10-12 22:38:11 -05001401 weston_view_to_global_float(view, s[i][0], s[i][1], &x, &y);
Pekka Paalanen6720d8f2012-01-25 15:17:40 +02001402 if (x < min_x)
1403 min_x = x;
1404 if (x > max_x)
1405 max_x = x;
1406 if (y < min_y)
1407 min_y = y;
1408 if (y > max_y)
1409 max_y = y;
1410 }
1411
Pekka Paalanen219b9822012-02-08 15:38:37 +02001412 int_x = floorf(min_x);
1413 int_y = floorf(min_y);
1414 pixman_region32_init_rect(bbox, int_x, int_y,
1415 ceilf(max_x) - int_x, ceilf(max_y) - int_y);
Pekka Paalanen6720d8f2012-01-25 15:17:40 +02001416}
1417
Pekka Paalanen80fb08d2012-02-08 15:14:17 +02001418static void
Michael Olbrichcb04f982020-06-08 10:22:32 +02001419weston_view_update_transform_scissor(struct weston_view *view,
1420 pixman_region32_t *region)
1421{
1422 struct weston_view *parent = view->geometry.parent;
1423
1424 if (parent) {
1425 if (parent->geometry.scissor_enabled) {
1426 view->geometry.scissor_enabled = true;
1427 weston_view_transfer_scissor(parent, view);
1428 } else {
1429 view->geometry.scissor_enabled = false;
1430 }
1431 }
1432
1433 if (view->geometry.scissor_enabled)
1434 pixman_region32_intersect(region, region,
1435 &view->geometry.scissor);
1436}
1437static void
Jason Ekstranda7af7042013-10-12 22:38:11 -05001438weston_view_update_transform_disable(struct weston_view *view)
Pekka Paalanen80fb08d2012-02-08 15:14:17 +02001439{
Jason Ekstranda7af7042013-10-12 22:38:11 -05001440 view->transform.enabled = 0;
Pekka Paalanen80fb08d2012-02-08 15:14:17 +02001441
Pekka Paalanencc2f8682012-02-13 10:34:04 +02001442 /* round off fractions when not transformed */
Jason Ekstranda7af7042013-10-12 22:38:11 -05001443 view->geometry.x = roundf(view->geometry.x);
1444 view->geometry.y = roundf(view->geometry.y);
Pekka Paalanencc2f8682012-02-13 10:34:04 +02001445
Kristian Høgsbergc1e6c8a2013-02-19 17:04:50 -05001446 /* Otherwise identity matrix, but with x and y translation. */
Jason Ekstranda7af7042013-10-12 22:38:11 -05001447 view->transform.position.matrix.type = WESTON_MATRIX_TRANSFORM_TRANSLATE;
1448 view->transform.position.matrix.d[12] = view->geometry.x;
1449 view->transform.position.matrix.d[13] = view->geometry.y;
Kristian Høgsbergc1e6c8a2013-02-19 17:04:50 -05001450
Jason Ekstranda7af7042013-10-12 22:38:11 -05001451 view->transform.matrix = view->transform.position.matrix;
Kristian Høgsbergc1e6c8a2013-02-19 17:04:50 -05001452
Jason Ekstranda7af7042013-10-12 22:38:11 -05001453 view->transform.inverse = view->transform.position.matrix;
1454 view->transform.inverse.d[12] = -view->geometry.x;
1455 view->transform.inverse.d[13] = -view->geometry.y;
Kristian Høgsbergc1e6c8a2013-02-19 17:04:50 -05001456
Jason Ekstranda7af7042013-10-12 22:38:11 -05001457 pixman_region32_init_rect(&view->transform.boundingbox,
Pekka Paalanen380adf52015-02-16 14:39:11 +02001458 0, 0,
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06001459 view->surface->width,
1460 view->surface->height);
Michael Olbrichcb04f982020-06-08 10:22:32 +02001461
1462 weston_view_update_transform_scissor(view, &view->transform.boundingbox);
Pekka Paalanen380adf52015-02-16 14:39:11 +02001463
1464 pixman_region32_translate(&view->transform.boundingbox,
1465 view->geometry.x, view->geometry.y);
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05001466
Jason Ekstranda7af7042013-10-12 22:38:11 -05001467 if (view->alpha == 1.0) {
1468 pixman_region32_copy(&view->transform.opaque,
1469 &view->surface->opaque);
1470 pixman_region32_translate(&view->transform.opaque,
1471 view->geometry.x,
1472 view->geometry.y);
Kristian Høgsberg3b4af202012-02-28 09:19:39 -05001473 }
Pekka Paalanen80fb08d2012-02-08 15:14:17 +02001474}
1475
1476static int
Jason Ekstranda7af7042013-10-12 22:38:11 -05001477weston_view_update_transform_enable(struct weston_view *view)
Pekka Paalanen2a5cecc2012-01-20 14:24:25 +02001478{
Jason Ekstranda7af7042013-10-12 22:38:11 -05001479 struct weston_view *parent = view->geometry.parent;
1480 struct weston_matrix *matrix = &view->transform.matrix;
1481 struct weston_matrix *inverse = &view->transform.inverse;
Pekka Paalanen2a5cecc2012-01-20 14:24:25 +02001482 struct weston_transform *tform;
Pekka Paalanen380adf52015-02-16 14:39:11 +02001483 pixman_region32_t surfregion;
1484 const pixman_box32_t *surfbox;
Pekka Paalanen2a5cecc2012-01-20 14:24:25 +02001485
Jason Ekstranda7af7042013-10-12 22:38:11 -05001486 view->transform.enabled = 1;
Pekka Paalanen80fb08d2012-02-08 15:14:17 +02001487
1488 /* Otherwise identity matrix, but with x and y translation. */
Jason Ekstranda7af7042013-10-12 22:38:11 -05001489 view->transform.position.matrix.type = WESTON_MATRIX_TRANSFORM_TRANSLATE;
1490 view->transform.position.matrix.d[12] = view->geometry.x;
1491 view->transform.position.matrix.d[13] = view->geometry.y;
Pekka Paalanen80fb08d2012-02-08 15:14:17 +02001492
1493 weston_matrix_init(matrix);
Jason Ekstranda7af7042013-10-12 22:38:11 -05001494 wl_list_for_each(tform, &view->geometry.transformation_list, link)
Pekka Paalanen80fb08d2012-02-08 15:14:17 +02001495 weston_matrix_multiply(matrix, &tform->matrix);
1496
Pekka Paalanen483243f2013-03-08 14:56:50 +02001497 if (parent)
1498 weston_matrix_multiply(matrix, &parent->transform.matrix);
1499
Pekka Paalanen80fb08d2012-02-08 15:14:17 +02001500 if (weston_matrix_invert(inverse, matrix) < 0) {
1501 /* Oops, bad total transformation, not invertible */
Jason Ekstranda7af7042013-10-12 22:38:11 -05001502 weston_log("error: weston_view %p"
1503 " transformation not invertible.\n", view);
Pekka Paalanen80fb08d2012-02-08 15:14:17 +02001504 return -1;
1505 }
1506
Giulio Camuffo148c1992016-09-04 18:50:46 +03001507 if (view->alpha == 1.0 &&
1508 matrix->type == WESTON_MATRIX_TRANSFORM_TRANSLATE) {
1509 pixman_region32_copy(&view->transform.opaque,
1510 &view->surface->opaque);
1511 pixman_region32_translate(&view->transform.opaque,
1512 matrix->d[12],
1513 matrix->d[13]);
1514 }
1515
Pekka Paalanen380adf52015-02-16 14:39:11 +02001516 pixman_region32_init_rect(&surfregion, 0, 0,
1517 view->surface->width, view->surface->height);
Michael Olbrichcb04f982020-06-08 10:22:32 +02001518
1519 weston_view_update_transform_scissor(view, &surfregion);
1520
Pekka Paalanen380adf52015-02-16 14:39:11 +02001521 surfbox = pixman_region32_extents(&surfregion);
1522
1523 view_compute_bbox(view, surfbox, &view->transform.boundingbox);
1524 pixman_region32_fini(&surfregion);
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05001525
Pekka Paalanen80fb08d2012-02-08 15:14:17 +02001526 return 0;
1527}
1528
Giulio Camuffo95ec0f92014-07-09 22:12:57 +03001529static struct weston_layer *
1530get_view_layer(struct weston_view *view)
1531{
1532 if (view->parent_view)
1533 return get_view_layer(view->parent_view);
1534 return view->layer_link.layer;
1535}
1536
Pekka Paalanen80fb08d2012-02-08 15:14:17 +02001537WL_EXPORT void
Jason Ekstranda7af7042013-10-12 22:38:11 -05001538weston_view_update_transform(struct weston_view *view)
Pekka Paalanen80fb08d2012-02-08 15:14:17 +02001539{
Jason Ekstranda7af7042013-10-12 22:38:11 -05001540 struct weston_view *parent = view->geometry.parent;
Giulio Camuffo95ec0f92014-07-09 22:12:57 +03001541 struct weston_layer *layer;
1542 pixman_region32_t mask;
Pekka Paalanen483243f2013-03-08 14:56:50 +02001543
Jason Ekstranda7af7042013-10-12 22:38:11 -05001544 if (!view->transform.dirty)
Pekka Paalanen2a5cecc2012-01-20 14:24:25 +02001545 return;
1546
Pekka Paalanen483243f2013-03-08 14:56:50 +02001547 if (parent)
Jason Ekstranda7af7042013-10-12 22:38:11 -05001548 weston_view_update_transform(parent);
Pekka Paalanen483243f2013-03-08 14:56:50 +02001549
Jason Ekstranda7af7042013-10-12 22:38:11 -05001550 view->transform.dirty = 0;
Pekka Paalanen2a5cecc2012-01-20 14:24:25 +02001551
Jason Ekstranda7af7042013-10-12 22:38:11 -05001552 weston_view_damage_below(view);
Pekka Paalanen96516782012-02-09 15:32:15 +02001553
Jason Ekstranda7af7042013-10-12 22:38:11 -05001554 pixman_region32_fini(&view->transform.boundingbox);
1555 pixman_region32_fini(&view->transform.opaque);
1556 pixman_region32_init(&view->transform.opaque);
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05001557
Pekka Paalanencd403622012-01-25 13:37:39 +02001558 /* transform.position is always in transformation_list */
Jason Ekstranda7af7042013-10-12 22:38:11 -05001559 if (view->geometry.transformation_list.next ==
1560 &view->transform.position.link &&
1561 view->geometry.transformation_list.prev ==
1562 &view->transform.position.link &&
Pekka Paalanen483243f2013-03-08 14:56:50 +02001563 !parent) {
Jason Ekstranda7af7042013-10-12 22:38:11 -05001564 weston_view_update_transform_disable(view);
Pekka Paalanen80fb08d2012-02-08 15:14:17 +02001565 } else {
Jason Ekstranda7af7042013-10-12 22:38:11 -05001566 if (weston_view_update_transform_enable(view) < 0)
1567 weston_view_update_transform_disable(view);
Pekka Paalanen2a5cecc2012-01-20 14:24:25 +02001568 }
Pekka Paalanen96516782012-02-09 15:32:15 +02001569
Giulio Camuffo95ec0f92014-07-09 22:12:57 +03001570 layer = get_view_layer(view);
1571 if (layer) {
1572 pixman_region32_init_with_extents(&mask, &layer->mask);
Pekka Paalanen25c0ca52015-02-19 11:15:33 +02001573 pixman_region32_intersect(&view->transform.boundingbox,
1574 &view->transform.boundingbox, &mask);
Pekka Paalanen8844bf22015-02-18 16:30:47 +02001575 pixman_region32_intersect(&view->transform.opaque,
1576 &view->transform.opaque, &mask);
Giulio Camuffo95ec0f92014-07-09 22:12:57 +03001577 pixman_region32_fini(&mask);
1578 }
1579
Jason Ekstranda7af7042013-10-12 22:38:11 -05001580 weston_view_damage_below(view);
Pekka Paalanen96516782012-02-09 15:32:15 +02001581
Jason Ekstranda7af7042013-10-12 22:38:11 -05001582 weston_view_assign_output(view);
Tiago Vignattifb2adba2013-06-12 15:43:21 -03001583
Jason Ekstranda7af7042013-10-12 22:38:11 -05001584 wl_signal_emit(&view->surface->compositor->transform_signal,
1585 view->surface);
Pekka Paalanen2a5cecc2012-01-20 14:24:25 +02001586}
1587
Pekka Paalanenddae03c2012-02-06 14:54:20 +02001588WL_EXPORT void
Jason Ekstranda7af7042013-10-12 22:38:11 -05001589weston_view_geometry_dirty(struct weston_view *view)
Pekka Paalanenc3ce7382013-03-08 14:56:49 +02001590{
Jason Ekstranda7af7042013-10-12 22:38:11 -05001591 struct weston_view *child;
Pekka Paalanen483243f2013-03-08 14:56:50 +02001592
1593 /*
Jason Ekstranda7af7042013-10-12 22:38:11 -05001594 * The invariant: if view->geometry.dirty, then all views
1595 * in view->geometry.child_list have geometry.dirty too.
Pekka Paalanen483243f2013-03-08 14:56:50 +02001596 * Corollary: if not parent->geometry.dirty, then all ancestors
1597 * are not dirty.
1598 */
1599
Jason Ekstranda7af7042013-10-12 22:38:11 -05001600 if (view->transform.dirty)
Pekka Paalanen483243f2013-03-08 14:56:50 +02001601 return;
1602
Jason Ekstranda7af7042013-10-12 22:38:11 -05001603 view->transform.dirty = 1;
Pekka Paalanen483243f2013-03-08 14:56:50 +02001604
Jason Ekstranda7af7042013-10-12 22:38:11 -05001605 wl_list_for_each(child, &view->geometry.child_list,
Pekka Paalanen483243f2013-03-08 14:56:50 +02001606 geometry.parent_link)
Jason Ekstranda7af7042013-10-12 22:38:11 -05001607 weston_view_geometry_dirty(child);
Pekka Paalanenc3ce7382013-03-08 14:56:49 +02001608}
1609
1610WL_EXPORT void
Jason Ekstranda7af7042013-10-12 22:38:11 -05001611weston_view_to_global_fixed(struct weston_view *view,
1612 wl_fixed_t vx, wl_fixed_t vy,
1613 wl_fixed_t *x, wl_fixed_t *y)
Daniel Stonebd3489b2012-05-08 17:17:53 +01001614{
John Kåre Alsaker490d02a2012-09-30 02:57:21 +02001615 float xf, yf;
Daniel Stonebd3489b2012-05-08 17:17:53 +01001616
Jason Ekstranda7af7042013-10-12 22:38:11 -05001617 weston_view_to_global_float(view,
1618 wl_fixed_to_double(vx),
1619 wl_fixed_to_double(vy),
1620 &xf, &yf);
Daniel Stonebd3489b2012-05-08 17:17:53 +01001621 *x = wl_fixed_from_double(xf);
1622 *y = wl_fixed_from_double(yf);
1623}
1624
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -04001625WL_EXPORT void
Jason Ekstranda7af7042013-10-12 22:38:11 -05001626weston_view_from_global_float(struct weston_view *view,
1627 float x, float y, float *vx, float *vy)
Pekka Paalanene0f3cb22012-01-24 09:59:29 +02001628{
Jason Ekstranda7af7042013-10-12 22:38:11 -05001629 if (view->transform.enabled) {
Pekka Paalanene0f3cb22012-01-24 09:59:29 +02001630 struct weston_vector v = { { x, y, 0.0f, 1.0f } };
1631
Jason Ekstranda7af7042013-10-12 22:38:11 -05001632 weston_matrix_transform(&view->transform.inverse, &v);
Pekka Paalanene0f3cb22012-01-24 09:59:29 +02001633
1634 if (fabsf(v.f[3]) < 1e-6) {
Martin Minarik6d118362012-06-07 18:01:59 +02001635 weston_log("warning: numerical instability in "
Jason Ekstranda7af7042013-10-12 22:38:11 -05001636 "weston_view_from_global(), divisor = %g\n",
Pekka Paalanene0f3cb22012-01-24 09:59:29 +02001637 v.f[3]);
Jason Ekstranda7af7042013-10-12 22:38:11 -05001638 *vx = 0;
1639 *vy = 0;
Pekka Paalanene0f3cb22012-01-24 09:59:29 +02001640 return;
1641 }
1642
Jason Ekstranda7af7042013-10-12 22:38:11 -05001643 *vx = v.f[0] / v.f[3];
1644 *vy = v.f[1] / v.f[3];
Pekka Paalanene0f3cb22012-01-24 09:59:29 +02001645 } else {
Jason Ekstranda7af7042013-10-12 22:38:11 -05001646 *vx = x - view->geometry.x;
1647 *vy = y - view->geometry.y;
Pekka Paalanene0f3cb22012-01-24 09:59:29 +02001648 }
1649}
1650
1651WL_EXPORT void
Jason Ekstranda7af7042013-10-12 22:38:11 -05001652weston_view_from_global_fixed(struct weston_view *view,
1653 wl_fixed_t x, wl_fixed_t y,
1654 wl_fixed_t *vx, wl_fixed_t *vy)
Daniel Stonebd3489b2012-05-08 17:17:53 +01001655{
Jason Ekstranda7af7042013-10-12 22:38:11 -05001656 float vxf, vyf;
Daniel Stonebd3489b2012-05-08 17:17:53 +01001657
Jason Ekstranda7af7042013-10-12 22:38:11 -05001658 weston_view_from_global_float(view,
1659 wl_fixed_to_double(x),
1660 wl_fixed_to_double(y),
1661 &vxf, &vyf);
1662 *vx = wl_fixed_from_double(vxf);
1663 *vy = wl_fixed_from_double(vyf);
Daniel Stonebd3489b2012-05-08 17:17:53 +01001664}
1665
1666WL_EXPORT void
Jason Ekstranda7af7042013-10-12 22:38:11 -05001667weston_view_from_global(struct weston_view *view,
1668 int32_t x, int32_t y, int32_t *vx, int32_t *vy)
Pekka Paalanen0e151bb2012-01-24 14:47:37 +02001669{
Jason Ekstranda7af7042013-10-12 22:38:11 -05001670 float vxf, vyf;
Pekka Paalanen0e151bb2012-01-24 14:47:37 +02001671
Jason Ekstranda7af7042013-10-12 22:38:11 -05001672 weston_view_from_global_float(view, x, y, &vxf, &vyf);
1673 *vx = floorf(vxf);
1674 *vy = floorf(vyf);
Pekka Paalanen0e151bb2012-01-24 14:47:37 +02001675}
1676
Bryce Harrington3f650b82015-12-23 11:01:58 -08001677/**
1678 * \param surface The surface to be repainted
1679 *
1680 * Marks the output(s) that the surface is shown on as needing to be
1681 * repainted. See weston_output_schedule_repaint().
1682 */
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -04001683WL_EXPORT void
Kristian Høgsberg98238702012-08-03 16:29:12 -04001684weston_surface_schedule_repaint(struct weston_surface *surface)
1685{
1686 struct weston_output *output;
1687
1688 wl_list_for_each(output, &surface->compositor->output_list, link)
Bryce Harrington89324ce2015-12-23 18:38:07 -08001689 if (surface->output_mask & (1u << output->id))
Kristian Høgsberg98238702012-08-03 16:29:12 -04001690 weston_output_schedule_repaint(output);
1691}
1692
Bryce Harrington3f650b82015-12-23 11:01:58 -08001693/**
1694 * \param view The view to be repainted
1695 *
1696 * Marks the output(s) that the view is shown on as needing to be
1697 * repainted. See weston_output_schedule_repaint().
1698 */
Kristian Høgsberg98238702012-08-03 16:29:12 -04001699WL_EXPORT void
Jason Ekstranda7af7042013-10-12 22:38:11 -05001700weston_view_schedule_repaint(struct weston_view *view)
1701{
1702 struct weston_output *output;
1703
1704 wl_list_for_each(output, &view->surface->compositor->output_list, link)
Bryce Harrington89324ce2015-12-23 18:38:07 -08001705 if (view->output_mask & (1u << output->id))
Jason Ekstranda7af7042013-10-12 22:38:11 -05001706 weston_output_schedule_repaint(output);
1707}
1708
Pekka Paalanene508ce62015-02-19 13:59:55 +02001709/**
1710 * XXX: This function does it the wrong way.
1711 * surface->damage is the damage from the client, and causes
1712 * surface_flush_damage() to copy pixels. No window management action can
1713 * cause damage to the client-provided content, warranting re-upload!
1714 *
1715 * Instead of surface->damage, this function should record the damage
1716 * with all the views for this surface to avoid extraneous texture
1717 * uploads.
1718 */
Jason Ekstranda7af7042013-10-12 22:38:11 -05001719WL_EXPORT void
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05001720weston_surface_damage(struct weston_surface *surface)
Kristian Høgsberg31bd6c72011-02-13 13:00:51 -05001721{
Kristian Høgsberg460a79b2012-06-18 15:09:11 -04001722 pixman_region32_union_rect(&surface->damage, &surface->damage,
Jason Ekstranda7af7042013-10-12 22:38:11 -05001723 0, 0, surface->width,
1724 surface->height);
Pekka Paalanen2267d452012-01-26 13:12:45 +02001725
Kristian Høgsberg98238702012-08-03 16:29:12 -04001726 weston_surface_schedule_repaint(surface);
Kristian Høgsberg31bd6c72011-02-13 13:00:51 -05001727}
1728
Kristian Høgsberga691aee2011-06-23 21:43:50 -04001729WL_EXPORT void
Jason Ekstranda7af7042013-10-12 22:38:11 -05001730weston_view_set_position(struct weston_view *view, float x, float y)
Pekka Paalanen8fb8d3b2012-02-13 13:03:59 +02001731{
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06001732 if (view->geometry.x == x && view->geometry.y == y)
1733 return;
1734
Jason Ekstranda7af7042013-10-12 22:38:11 -05001735 view->geometry.x = x;
1736 view->geometry.y = y;
1737 weston_view_geometry_dirty(view);
Pekka Paalanen8fb8d3b2012-02-13 13:03:59 +02001738}
1739
Pekka Paalanen483243f2013-03-08 14:56:50 +02001740static void
1741transform_parent_handle_parent_destroy(struct wl_listener *listener,
1742 void *data)
1743{
Jason Ekstranda7af7042013-10-12 22:38:11 -05001744 struct weston_view *view =
1745 container_of(listener, struct weston_view,
Pekka Paalanen483243f2013-03-08 14:56:50 +02001746 geometry.parent_destroy_listener);
1747
Jason Ekstranda7af7042013-10-12 22:38:11 -05001748 weston_view_set_transform_parent(view, NULL);
Pekka Paalanen483243f2013-03-08 14:56:50 +02001749}
1750
1751WL_EXPORT void
Jason Ekstranda7af7042013-10-12 22:38:11 -05001752weston_view_set_transform_parent(struct weston_view *view,
Pekka Paalanen380adf52015-02-16 14:39:11 +02001753 struct weston_view *parent)
Pekka Paalanen483243f2013-03-08 14:56:50 +02001754{
Jason Ekstranda7af7042013-10-12 22:38:11 -05001755 if (view->geometry.parent) {
1756 wl_list_remove(&view->geometry.parent_destroy_listener.link);
1757 wl_list_remove(&view->geometry.parent_link);
Pekka Paalanen380adf52015-02-16 14:39:11 +02001758
1759 if (!parent)
1760 view->geometry.scissor_enabled = false;
Pekka Paalanen483243f2013-03-08 14:56:50 +02001761 }
1762
Jason Ekstranda7af7042013-10-12 22:38:11 -05001763 view->geometry.parent = parent;
Pekka Paalanen483243f2013-03-08 14:56:50 +02001764
Jason Ekstranda7af7042013-10-12 22:38:11 -05001765 view->geometry.parent_destroy_listener.notify =
Pekka Paalanen483243f2013-03-08 14:56:50 +02001766 transform_parent_handle_parent_destroy;
1767 if (parent) {
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05001768 wl_signal_add(&parent->destroy_signal,
Jason Ekstranda7af7042013-10-12 22:38:11 -05001769 &view->geometry.parent_destroy_listener);
Pekka Paalanen483243f2013-03-08 14:56:50 +02001770 wl_list_insert(&parent->geometry.child_list,
Jason Ekstranda7af7042013-10-12 22:38:11 -05001771 &view->geometry.parent_link);
Pekka Paalanen483243f2013-03-08 14:56:50 +02001772 }
1773
Jason Ekstranda7af7042013-10-12 22:38:11 -05001774 weston_view_geometry_dirty(view);
1775}
1776
Pekka Paalanen380adf52015-02-16 14:39:11 +02001777/** Set a clip mask rectangle on a view
1778 *
1779 * \param view The view to set the clip mask on.
1780 * \param x Top-left corner X coordinate of the clip rectangle.
1781 * \param y Top-left corner Y coordinate of the clip rectangle.
1782 * \param width Width of the clip rectangle, non-negative.
1783 * \param height Height of the clip rectangle, non-negative.
1784 *
1785 * A shell may set a clip mask rectangle on a view. Everything outside
1786 * the rectangle is cut away for input and output purposes: it is
1787 * not drawn and cannot be hit by hit-test based input like pointer
1788 * motion or touch-downs. Everything inside the rectangle will behave
1789 * normally. Clients are unaware of clipping.
1790 *
Yong Bakos4c72e292016-04-28 11:59:10 -05001791 * The rectangle is set in surface-local coordinates. Setting a clip
Pekka Paalanen380adf52015-02-16 14:39:11 +02001792 * mask rectangle does not affect the view position, the view is positioned
1793 * as it would be without a clip. The clip also does not change
1794 * weston_surface::width,height.
1795 *
1796 * The clip mask rectangle is part of transformation inheritance
1797 * (weston_view_set_transform_parent()). A clip set in the root of the
1798 * transformation inheritance tree will affect all views in the tree.
1799 * A clip can be set only on the root view. Attempting to set a clip
1800 * on view that has a transformation parent will fail. Assigning a parent
1801 * to a view that has a clip set will cause the clip to be forgotten.
1802 *
1803 * Because the clip mask is an axis-aligned rectangle, it poses restrictions
1804 * on the additional transformations in the child views. These transformations
1805 * may not rotate the coordinate axes, i.e., only translation and scaling
1806 * are allowed. Violating this restriction causes the clipping to malfunction.
1807 * Furthermore, using scaling may cause rounding errors in child clipping.
1808 *
1809 * The clip mask rectangle is not automatically adjusted based on
1810 * wl_surface.attach dx and dy arguments.
1811 *
1812 * A clip mask rectangle can be set only if the compositor capability
1813 * WESTON_CAP_VIEW_CLIP_MASK is present.
1814 *
1815 * This function sets the clip mask rectangle and schedules a repaint for
1816 * the view.
1817 */
1818WL_EXPORT void
1819weston_view_set_mask(struct weston_view *view,
1820 int x, int y, int width, int height)
1821{
1822 struct weston_compositor *compositor = view->surface->compositor;
1823
1824 if (!(compositor->capabilities & WESTON_CAP_VIEW_CLIP_MASK)) {
1825 weston_log("%s not allowed without capability!\n", __func__);
1826 return;
1827 }
1828
1829 if (view->geometry.parent) {
1830 weston_log("view %p has a parent, clip forbidden!\n", view);
1831 return;
1832 }
1833
1834 if (width < 0 || height < 0) {
1835 weston_log("%s: illegal args %d, %d, %d, %d\n", __func__,
1836 x, y, width, height);
1837 return;
1838 }
1839
1840 pixman_region32_fini(&view->geometry.scissor);
1841 pixman_region32_init_rect(&view->geometry.scissor, x, y, width, height);
1842 view->geometry.scissor_enabled = true;
1843 weston_view_geometry_dirty(view);
1844 weston_view_schedule_repaint(view);
1845}
1846
1847/** Remove the clip mask from a view
1848 *
1849 * \param view The view to remove the clip mask from.
1850 *
1851 * Removed the clip mask rectangle and schedules a repaint.
1852 *
1853 * \sa weston_view_set_mask
1854 */
1855WL_EXPORT void
1856weston_view_set_mask_infinite(struct weston_view *view)
1857{
1858 view->geometry.scissor_enabled = false;
1859 weston_view_geometry_dirty(view);
1860 weston_view_schedule_repaint(view);
1861}
1862
Armin Krezović0da12b82016-06-30 06:04:33 +02001863/* Check if view should be displayed
1864 *
1865 * The indicator is set manually when assigning
1866 * a view to a surface.
1867 *
1868 * This needs reworking. See the thread starting at:
1869 *
1870 * https://lists.freedesktop.org/archives/wayland-devel/2016-June/029656.html
1871 */
Derek Foreman280e7dd2014-10-03 13:13:42 -05001872WL_EXPORT bool
Jason Ekstranda7af7042013-10-12 22:38:11 -05001873weston_view_is_mapped(struct weston_view *view)
1874{
Armin Krezović0da12b82016-06-30 06:04:33 +02001875 return view->is_mapped;
Pekka Paalanen483243f2013-03-08 14:56:50 +02001876}
1877
Philipp Zabel70decd52018-09-03 20:11:15 +02001878/* Check if view is opaque in specified region
1879 *
1880 * \param view The view to check for opacity.
1881 * \param region The region to check for opacity, in view coordinates.
1882 *
1883 * Returns true if the view is opaque in the specified region, because view
1884 * alpha is 1.0 and either the opaque region set by the client contains the
1885 * specified region, or the buffer pixel format or solid color is opaque.
1886 */
1887WL_EXPORT bool
1888weston_view_is_opaque(struct weston_view *ev, pixman_region32_t *region)
1889{
1890 pixman_region32_t r;
1891 bool ret = false;
1892
1893 if (ev->alpha < 1.0)
1894 return false;
1895
1896 if (ev->surface->is_opaque)
1897 return true;
1898
Marius Vlad67b382c2020-08-21 13:57:54 +03001899 if (ev->transform.dirty)
Philipp Zabel70decd52018-09-03 20:11:15 +02001900 return false;
Philipp Zabel70decd52018-09-03 20:11:15 +02001901
1902 pixman_region32_init(&r);
1903 pixman_region32_subtract(&r, region, &ev->transform.opaque);
1904
1905 if (!pixman_region32_not_empty(&r))
1906 ret = true;
1907
1908 pixman_region32_fini(&r);
1909
1910 return ret;
1911}
1912
Marius Vlad5f6bee42019-09-11 16:41:04 +03001913/** Check if the view has a valid buffer available
1914 *
1915 * @param ev The view to check if it has a valid buffer.
1916 *
1917 * Returns true if the view has a valid buffer or false otherwise.
1918 */
1919WL_EXPORT bool
1920weston_view_has_valid_buffer(struct weston_view *ev)
1921{
1922 return ev->surface->buffer_ref.buffer != NULL;
1923}
1924
Marius Vlad47e3d1e2019-09-11 16:53:08 +03001925/** Check if the view matches the entire output
1926 *
1927 * @param ev The view to check.
1928 * @param output The output to check against.
1929 *
1930 * Returns true if the view does indeed matches the entire output.
1931 */
1932WL_EXPORT bool
1933weston_view_matches_output_entirely(struct weston_view *ev,
1934 struct weston_output *output)
1935{
1936 pixman_box32_t *extents =
1937 pixman_region32_extents(&ev->transform.boundingbox);
1938
1939 if (extents->x1 != output->x ||
1940 extents->y1 != output->y ||
1941 extents->x2 != output->x + output->width ||
1942 extents->y2 != output->y + output->height)
1943 return false;
1944
1945 return true;
1946}
1947
Armin Krezović0da12b82016-06-30 06:04:33 +02001948/* Check if a surface has a view assigned to it
1949 *
1950 * The indicator is set manually when mapping
1951 * a surface and creating a view for it.
1952 *
1953 * This needs to go. See the thread starting at:
1954 *
1955 * https://lists.freedesktop.org/archives/wayland-devel/2016-June/029656.html
1956 *
1957 */
Derek Foreman280e7dd2014-10-03 13:13:42 -05001958WL_EXPORT bool
Ander Conselvan de Oliveirab8ab14f2012-03-27 17:36:36 +03001959weston_surface_is_mapped(struct weston_surface *surface)
1960{
Armin Krezović0da12b82016-06-30 06:04:33 +02001961 return surface->is_mapped;
Ander Conselvan de Oliveirab8ab14f2012-03-27 17:36:36 +03001962}
1963
Pekka Paalanenda75ee12013-11-26 18:19:43 +01001964static void
Jason Ekstrand5c11a332013-12-04 20:32:03 -06001965surface_set_size(struct weston_surface *surface, int32_t width, int32_t height)
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06001966{
1967 struct weston_view *view;
1968
1969 if (surface->width == width && surface->height == height)
1970 return;
1971
1972 surface->width = width;
1973 surface->height = height;
1974
1975 wl_list_for_each(view, &surface->views, surface_link)
1976 weston_view_geometry_dirty(view);
1977}
1978
Jason Ekstrand5c11a332013-12-04 20:32:03 -06001979WL_EXPORT void
1980weston_surface_set_size(struct weston_surface *surface,
1981 int32_t width, int32_t height)
1982{
1983 assert(!surface->resource);
1984 surface_set_size(surface, width, height);
1985}
1986
Pekka Paalanen0b4c5352014-03-14 14:38:17 +02001987static int
1988fixed_round_up_to_int(wl_fixed_t f)
1989{
1990 return wl_fixed_to_int(wl_fixed_from_int(1) - 1 + f);
1991}
1992
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06001993static void
Pekka Paalanen59987fa2016-04-26 15:50:59 +03001994convert_size_by_transform_scale(int32_t *width_out, int32_t *height_out,
1995 int32_t width, int32_t height,
1996 uint32_t transform,
1997 int32_t scale)
1998{
1999 assert(scale > 0);
2000
2001 switch (transform) {
2002 case WL_OUTPUT_TRANSFORM_NORMAL:
2003 case WL_OUTPUT_TRANSFORM_180:
2004 case WL_OUTPUT_TRANSFORM_FLIPPED:
2005 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
2006 *width_out = width / scale;
2007 *height_out = height / scale;
2008 break;
2009 case WL_OUTPUT_TRANSFORM_90:
2010 case WL_OUTPUT_TRANSFORM_270:
2011 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
2012 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
2013 *width_out = height / scale;
2014 *height_out = width / scale;
2015 break;
2016 default:
2017 assert(0 && "invalid transform");
2018 }
2019}
2020
2021static void
George Kiagiadakis8f9e87f2014-06-13 18:14:20 +02002022weston_surface_calculate_size_from_buffer(struct weston_surface *surface)
Ander Conselvan de Oliveira012b4c72012-11-27 17:03:42 +02002023{
Pekka Paalanen952b6c82014-03-14 14:38:15 +02002024 struct weston_buffer_viewport *vp = &surface->buffer_viewport;
Pekka Paalanenda75ee12013-11-26 18:19:43 +01002025
2026 if (!surface->buffer_ref.buffer) {
Pekka Paalanen0b4c5352014-03-14 14:38:17 +02002027 surface->width_from_buffer = 0;
2028 surface->height_from_buffer = 0;
Jonny Lamb74130762013-11-26 18:19:46 +01002029 return;
2030 }
2031
Pekka Paalanen59987fa2016-04-26 15:50:59 +03002032 convert_size_by_transform_scale(&surface->width_from_buffer,
2033 &surface->height_from_buffer,
2034 surface->buffer_ref.buffer->width,
2035 surface->buffer_ref.buffer->height,
2036 vp->buffer.transform,
2037 vp->buffer.scale);
George Kiagiadakis8f9e87f2014-06-13 18:14:20 +02002038}
Pekka Paalanen0b4c5352014-03-14 14:38:17 +02002039
George Kiagiadakis8f9e87f2014-06-13 18:14:20 +02002040static void
2041weston_surface_update_size(struct weston_surface *surface)
2042{
2043 struct weston_buffer_viewport *vp = &surface->buffer_viewport;
2044 int32_t width, height;
2045
2046 width = surface->width_from_buffer;
2047 height = surface->height_from_buffer;
2048
2049 if (width != 0 && vp->surface.width != -1) {
Pekka Paalanen0b4c5352014-03-14 14:38:17 +02002050 surface_set_size(surface,
2051 vp->surface.width, vp->surface.height);
2052 return;
2053 }
2054
George Kiagiadakis8f9e87f2014-06-13 18:14:20 +02002055 if (width != 0 && vp->buffer.src_width != wl_fixed_from_int(-1)) {
Pekka Paalanene9317212014-04-04 14:22:13 +03002056 int32_t w = fixed_round_up_to_int(vp->buffer.src_width);
2057 int32_t h = fixed_round_up_to_int(vp->buffer.src_height);
2058
2059 surface_set_size(surface, w ?: 1, h ?: 1);
Pekka Paalanen0b4c5352014-03-14 14:38:17 +02002060 return;
2061 }
2062
Jason Ekstrand5c11a332013-12-04 20:32:03 -06002063 surface_set_size(surface, width, height);
Ander Conselvan de Oliveira012b4c72012-11-27 17:03:42 +02002064}
2065
Marius Vlad9fdda7f2019-06-11 16:08:55 +03002066/** weston_compositor_get_time
2067 * \ingroup compositor
2068 */
Alexandros Frantzis409b01f2017-11-16 18:21:01 +02002069WL_EXPORT void
2070weston_compositor_get_time(struct timespec *time)
Kristian Høgsberg7132a9a2010-12-06 21:41:10 -05002071{
Alexandros Frantzis409b01f2017-11-16 18:21:01 +02002072 clock_gettime(CLOCK_REALTIME, time);
Kristian Høgsberg7132a9a2010-12-06 21:41:10 -05002073}
2074
Marius Vlad9fdda7f2019-06-11 16:08:55 +03002075/** weston_compositor_pick_view
2076 * \ingroup compositor
2077 */
Jason Ekstranda7af7042013-10-12 22:38:11 -05002078WL_EXPORT struct weston_view *
2079weston_compositor_pick_view(struct weston_compositor *compositor,
2080 wl_fixed_t x, wl_fixed_t y,
2081 wl_fixed_t *vx, wl_fixed_t *vy)
Tiago Vignatti9d393522012-02-10 16:26:19 +02002082{
Jason Ekstranda7af7042013-10-12 22:38:11 -05002083 struct weston_view *view;
Pekka Paalanenfc22a522015-02-18 15:08:29 +02002084 wl_fixed_t view_x, view_y;
2085 int view_ix, view_iy;
2086 int ix = wl_fixed_to_int(x);
2087 int iy = wl_fixed_to_int(y);
Tiago Vignatti9d393522012-02-10 16:26:19 +02002088
Jason Ekstranda7af7042013-10-12 22:38:11 -05002089 wl_list_for_each(view, &compositor->view_list, link) {
Pekka Paalanenfc22a522015-02-18 15:08:29 +02002090 if (!pixman_region32_contains_point(
2091 &view->transform.boundingbox, ix, iy, NULL))
2092 continue;
2093
2094 weston_view_from_global_fixed(view, x, y, &view_x, &view_y);
2095 view_ix = wl_fixed_to_int(view_x);
2096 view_iy = wl_fixed_to_int(view_y);
2097
2098 if (!pixman_region32_contains_point(&view->surface->input,
2099 view_ix, view_iy, NULL))
2100 continue;
2101
Pekka Paalanen380adf52015-02-16 14:39:11 +02002102 if (view->geometry.scissor_enabled &&
2103 !pixman_region32_contains_point(&view->geometry.scissor,
2104 view_ix, view_iy, NULL))
2105 continue;
2106
Pekka Paalanenfc22a522015-02-18 15:08:29 +02002107 *vx = view_x;
2108 *vy = view_y;
2109 return view;
Tiago Vignatti9d393522012-02-10 16:26:19 +02002110 }
2111
Derek Foremanf9318d12015-05-11 15:40:11 -05002112 *vx = wl_fixed_from_int(-1000000);
2113 *vy = wl_fixed_from_int(-1000000);
Tiago Vignatti9d393522012-02-10 16:26:19 +02002114 return NULL;
2115}
2116
2117static void
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05002118weston_compositor_repick(struct weston_compositor *compositor)
Kristian Høgsbergd2baf1f2011-10-11 22:20:37 -04002119{
Daniel Stone37816df2012-05-16 18:45:18 +01002120 struct weston_seat *seat;
Kristian Høgsbergd2baf1f2011-10-11 22:20:37 -04002121
Kristian Høgsberg10ddd972013-10-22 12:40:54 -07002122 if (!compositor->session_active)
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -05002123 return;
2124
Daniel Stone37816df2012-05-16 18:45:18 +01002125 wl_list_for_each(seat, &compositor->seat_list, link)
Kristian Høgsberga71e8b22013-05-06 21:51:21 -04002126 weston_seat_repick(seat);
Kristian Høgsbergd2baf1f2011-10-11 22:20:37 -04002127}
2128
Kristian Høgsbergaf7b1ff2012-06-26 21:19:23 -04002129WL_EXPORT void
Jason Ekstranda7af7042013-10-12 22:38:11 -05002130weston_view_unmap(struct weston_view *view)
Kristian Høgsberg3b5ea3b2012-02-17 12:43:56 -05002131{
Daniel Stone4dab5db2012-05-30 16:31:53 +01002132 struct weston_seat *seat;
Kristian Høgsberg867dec72012-03-01 17:09:37 -05002133
Jason Ekstranda7af7042013-10-12 22:38:11 -05002134 if (!weston_view_is_mapped(view))
2135 return;
Kristian Høgsberg867dec72012-03-01 17:09:37 -05002136
Jason Ekstranda7af7042013-10-12 22:38:11 -05002137 weston_view_damage_below(view);
Semi Malinene7a52fb2018-04-26 11:08:10 +02002138 weston_view_set_output(view, NULL);
Xiong Zhang97116532013-10-23 13:58:31 +08002139 view->plane = NULL;
Armin Krezovićf8486c32016-06-30 06:04:28 +02002140 view->is_mapped = false;
Giulio Camuffo412e6a52014-07-09 22:12:56 +03002141 weston_layer_entry_remove(&view->layer_link);
Jason Ekstranda7af7042013-10-12 22:38:11 -05002142 wl_list_remove(&view->link);
2143 wl_list_init(&view->link);
Jason Ekstranda7af7042013-10-12 22:38:11 -05002144 view->output_mask = 0;
2145 weston_surface_assign_output(view->surface);
2146
2147 if (weston_surface_is_mapped(view->surface))
2148 return;
2149
2150 wl_list_for_each(seat, &view->surface->compositor->seat_list, link) {
Derek Foreman1281a362015-07-31 16:55:32 -05002151 struct weston_touch *touch = weston_seat_get_touch(seat);
2152 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
2153 struct weston_keyboard *keyboard =
2154 weston_seat_get_keyboard(seat);
2155
2156 if (keyboard && keyboard->focus == view->surface)
2157 weston_keyboard_set_focus(keyboard, NULL);
2158 if (pointer && pointer->focus == view)
Derek Foremanf9318d12015-05-11 15:40:11 -05002159 weston_pointer_clear_focus(pointer);
Derek Foreman1281a362015-07-31 16:55:32 -05002160 if (touch && touch->focus == view)
2161 weston_touch_set_focus(touch, NULL);
Daniel Stone4dab5db2012-05-30 16:31:53 +01002162 }
Jason Ekstranda7af7042013-10-12 22:38:11 -05002163}
Kristian Høgsberg867dec72012-03-01 17:09:37 -05002164
Jason Ekstranda7af7042013-10-12 22:38:11 -05002165WL_EXPORT void
2166weston_surface_unmap(struct weston_surface *surface)
2167{
2168 struct weston_view *view;
2169
Armin Krezovićf8486c32016-06-30 06:04:28 +02002170 surface->is_mapped = false;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002171 wl_list_for_each(view, &surface->views, surface_link)
2172 weston_view_unmap(view);
2173 surface->output = NULL;
Kristian Høgsberg3b5ea3b2012-02-17 12:43:56 -05002174}
2175
Pekka Paalanen3c9b8022014-03-14 14:38:13 +02002176static void
2177weston_surface_reset_pending_buffer(struct weston_surface *surface)
2178{
Jason Ekstrand7b982072014-05-20 14:33:03 -05002179 weston_surface_state_set_buffer(&surface->pending, NULL);
Pekka Paalanen3c9b8022014-03-14 14:38:13 +02002180 surface->pending.sx = 0;
2181 surface->pending.sy = 0;
2182 surface->pending.newly_attached = 0;
George Kiagiadakis8f9e87f2014-06-13 18:14:20 +02002183 surface->pending.buffer_viewport.changed = 0;
Pekka Paalanen3c9b8022014-03-14 14:38:13 +02002184}
2185
Jason Ekstranda7af7042013-10-12 22:38:11 -05002186WL_EXPORT void
2187weston_view_destroy(struct weston_view *view)
2188{
2189 wl_signal_emit(&view->destroy_signal, view);
2190
2191 assert(wl_list_empty(&view->geometry.child_list));
2192
2193 if (weston_view_is_mapped(view)) {
2194 weston_view_unmap(view);
2195 weston_compositor_build_view_list(view->surface->compositor);
2196 }
2197
2198 wl_list_remove(&view->link);
Giulio Camuffo412e6a52014-07-09 22:12:56 +03002199 weston_layer_entry_remove(&view->layer_link);
Jason Ekstranda7af7042013-10-12 22:38:11 -05002200
2201 pixman_region32_fini(&view->clip);
Pekka Paalanen380adf52015-02-16 14:39:11 +02002202 pixman_region32_fini(&view->geometry.scissor);
Jason Ekstranda7af7042013-10-12 22:38:11 -05002203 pixman_region32_fini(&view->transform.boundingbox);
Pekka Paalanen8844bf22015-02-18 16:30:47 +02002204 pixman_region32_fini(&view->transform.opaque);
Jason Ekstranda7af7042013-10-12 22:38:11 -05002205
2206 weston_view_set_transform_parent(view, NULL);
Pekka Paalanen944fae82018-05-22 13:15:58 +03002207 weston_view_set_output(view, NULL);
Jason Ekstranda7af7042013-10-12 22:38:11 -05002208
Jason Ekstranda7af7042013-10-12 22:38:11 -05002209 wl_list_remove(&view->surface_link);
2210
2211 free(view);
2212}
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05002213
2214WL_EXPORT void
2215weston_surface_destroy(struct weston_surface *surface)
Kristian Høgsberg54879822008-11-23 17:07:32 -05002216{
Kristian Høgsberg1e51fec2012-07-22 11:33:14 -04002217 struct weston_frame_callback *cb, *next;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002218 struct weston_view *ev, *nv;
Jonas Ådahld3414f22016-07-22 17:56:31 +08002219 struct weston_pointer_constraint *constraint, *next_constraint;
Kristian Høgsberg4fa48732009-03-10 23:17:00 -04002220
Giulio Camuffo13b85bd2013-08-13 23:10:14 +02002221 if (--surface->ref_count > 0)
2222 return;
2223
Pekka Paalanen08d3fb72015-04-17 14:00:24 +03002224 assert(surface->resource == NULL);
2225
Pekka Paalanenca790762015-04-17 14:23:38 +03002226 wl_signal_emit(&surface->destroy_signal, surface);
Giulio Camuffo13b85bd2013-08-13 23:10:14 +02002227
Pekka Paalanene67858b2013-04-25 13:57:42 +03002228 assert(wl_list_empty(&surface->subsurface_list_pending));
2229 assert(wl_list_empty(&surface->subsurface_list));
Pekka Paalanen483243f2013-03-08 14:56:50 +02002230
Jason Ekstranda7af7042013-10-12 22:38:11 -05002231 wl_list_for_each_safe(ev, nv, &surface->views, surface_link)
2232 weston_view_destroy(ev);
Kristian Høgsbergd2baf1f2011-10-11 22:20:37 -04002233
Jason Ekstrand7b982072014-05-20 14:33:03 -05002234 weston_surface_state_fini(&surface->pending);
Pekka Paalanen5df44de2012-10-10 12:49:23 +03002235
Pekka Paalanende685b82012-12-04 15:58:12 +02002236 weston_buffer_reference(&surface->buffer_ref, NULL);
Alexandros Frantzis67629672018-10-19 12:14:11 +03002237 weston_buffer_release_reference(&surface->buffer_release_ref, NULL);
Kristian Høgsberg3f8f39c2009-09-18 17:05:13 -04002238
Pekka Paalanen402ae6d2012-01-03 10:23:24 +02002239 pixman_region32_fini(&surface->damage);
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05002240 pixman_region32_fini(&surface->opaque);
Pekka Paalanen0cbd3b52012-10-10 12:49:28 +03002241 pixman_region32_fini(&surface->input);
Pekka Paalanen402ae6d2012-01-03 10:23:24 +02002242
Kristian Høgsberg1e51fec2012-07-22 11:33:14 -04002243 wl_list_for_each_safe(cb, next, &surface->frame_callback_list, link)
Jason Ekstrandfbbbec82013-06-14 10:07:57 -05002244 wl_resource_destroy(cb->resource);
Kristian Høgsberg1e51fec2012-07-22 11:33:14 -04002245
Pekka Paalanen133e4392014-09-23 22:08:46 -04002246 weston_presentation_feedback_discard_list(&surface->feedback_list);
2247
Jonas Ådahld3414f22016-07-22 17:56:31 +08002248 wl_list_for_each_safe(constraint, next_constraint,
2249 &surface->pointer_constraints,
2250 link)
2251 weston_pointer_constraint_destroy(constraint);
2252
Alexandros Frantzisacff29b2018-10-19 12:14:11 +03002253 fd_clear(&surface->acquire_fence_fd);
2254
Kristian Høgsberg4fa48732009-03-10 23:17:00 -04002255 free(surface);
Kristian Høgsberg54879822008-11-23 17:07:32 -05002256}
2257
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05002258static void
2259destroy_surface(struct wl_resource *resource)
Alex Wu8811bf92012-02-28 18:07:54 +08002260{
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05002261 struct weston_surface *surface = wl_resource_get_user_data(resource);
Alex Wu8811bf92012-02-28 18:07:54 +08002262
Pekka Paalanen08d3fb72015-04-17 14:00:24 +03002263 assert(surface);
2264
Giulio Camuffo0d379742013-11-15 22:06:15 +01002265 /* Set the resource to NULL, since we don't want to leave a
2266 * dangling pointer if the surface was refcounted and survives
2267 * the weston_surface_destroy() call. */
2268 surface->resource = NULL;
Pekka Paalanen4826f872016-04-22 14:14:38 +03002269
2270 if (surface->viewport_resource)
2271 wl_resource_set_user_data(surface->viewport_resource, NULL);
2272
Alexandros Frantzis27d7c392018-10-19 12:14:11 +03002273 if (surface->synchronization_resource) {
2274 wl_resource_set_user_data(surface->synchronization_resource,
2275 NULL);
2276 }
2277
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05002278 weston_surface_destroy(surface);
Alex Wu8811bf92012-02-28 18:07:54 +08002279}
2280
Benjamin Franzkefaa0a9d2011-02-21 16:24:53 +01002281static void
Jason Ekstrand6bd62942013-06-20 20:38:23 -05002282weston_buffer_destroy_handler(struct wl_listener *listener, void *data)
2283{
2284 struct weston_buffer *buffer =
2285 container_of(listener, struct weston_buffer, destroy_listener);
2286
2287 wl_signal_emit(&buffer->destroy_signal, buffer);
2288 free(buffer);
2289}
2290
Giulio Camuffoe058cd12013-12-12 14:14:29 +01002291WL_EXPORT struct weston_buffer *
Jason Ekstrand6bd62942013-06-20 20:38:23 -05002292weston_buffer_from_resource(struct wl_resource *resource)
2293{
2294 struct weston_buffer *buffer;
2295 struct wl_listener *listener;
U. Artie Eoff2e2384a2014-01-17 13:19:01 -08002296
Jason Ekstrand6bd62942013-06-20 20:38:23 -05002297 listener = wl_resource_get_destroy_listener(resource,
2298 weston_buffer_destroy_handler);
2299
Kristian Høgsberg08b58c72013-08-15 12:26:42 -07002300 if (listener)
2301 return container_of(listener, struct weston_buffer,
2302 destroy_listener);
2303
2304 buffer = zalloc(sizeof *buffer);
2305 if (buffer == NULL)
2306 return NULL;
2307
2308 buffer->resource = resource;
2309 wl_signal_init(&buffer->destroy_signal);
2310 buffer->destroy_listener.notify = weston_buffer_destroy_handler;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04002311 buffer->y_inverted = 1;
Kristian Høgsberg08b58c72013-08-15 12:26:42 -07002312 wl_resource_add_destroy_listener(resource, &buffer->destroy_listener);
U. Artie Eoff2e2384a2014-01-17 13:19:01 -08002313
Jason Ekstrand6bd62942013-06-20 20:38:23 -05002314 return buffer;
2315}
2316
2317static void
Pekka Paalanende685b82012-12-04 15:58:12 +02002318weston_buffer_reference_handle_destroy(struct wl_listener *listener,
2319 void *data)
Benjamin Franzkefaa0a9d2011-02-21 16:24:53 +01002320{
Pekka Paalanende685b82012-12-04 15:58:12 +02002321 struct weston_buffer_reference *ref =
2322 container_of(listener, struct weston_buffer_reference,
2323 destroy_listener);
2324
Jason Ekstrand6bd62942013-06-20 20:38:23 -05002325 assert((struct weston_buffer *)data == ref->buffer);
Pekka Paalanende685b82012-12-04 15:58:12 +02002326 ref->buffer = NULL;
2327}
2328
2329WL_EXPORT void
2330weston_buffer_reference(struct weston_buffer_reference *ref,
Jason Ekstrand6bd62942013-06-20 20:38:23 -05002331 struct weston_buffer *buffer)
Pekka Paalanende685b82012-12-04 15:58:12 +02002332{
2333 if (ref->buffer && buffer != ref->buffer) {
Kristian Høgsberg20347802013-03-04 12:07:46 -05002334 ref->buffer->busy_count--;
2335 if (ref->buffer->busy_count == 0) {
Jason Ekstrand6bd62942013-06-20 20:38:23 -05002336 assert(wl_resource_get_client(ref->buffer->resource));
Matt Hoosier3052bc72017-09-26 08:09:40 -05002337 wl_buffer_send_release(ref->buffer->resource);
Kristian Høgsberg20347802013-03-04 12:07:46 -05002338 }
Pekka Paalanende685b82012-12-04 15:58:12 +02002339 wl_list_remove(&ref->destroy_listener.link);
Ander Conselvan de Oliveirae11683a2012-03-27 17:36:40 +03002340 }
2341
Pekka Paalanende685b82012-12-04 15:58:12 +02002342 if (buffer && buffer != ref->buffer) {
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04002343 buffer->busy_count++;
Jason Ekstrand6bd62942013-06-20 20:38:23 -05002344 wl_signal_add(&buffer->destroy_signal,
Pekka Paalanende685b82012-12-04 15:58:12 +02002345 &ref->destroy_listener);
Pekka Paalanena6421c42012-12-04 15:58:10 +02002346 }
2347
Pekka Paalanende685b82012-12-04 15:58:12 +02002348 ref->buffer = buffer;
2349 ref->destroy_listener.notify = weston_buffer_reference_handle_destroy;
2350}
2351
2352static void
Alexandros Frantzis67629672018-10-19 12:14:11 +03002353weston_buffer_release_reference_handle_destroy(struct wl_listener *listener,
2354 void *data)
2355{
2356 struct weston_buffer_release_reference *ref =
2357 container_of(listener, struct weston_buffer_release_reference,
2358 destroy_listener);
2359
2360 assert((struct wl_resource *)data == ref->buffer_release->resource);
2361 ref->buffer_release = NULL;
2362}
2363
2364static void
2365weston_buffer_release_destroy(struct weston_buffer_release *buffer_release)
2366{
2367 struct wl_resource *resource = buffer_release->resource;
2368 int release_fence_fd = buffer_release->fence_fd;
2369
2370 if (release_fence_fd >= 0) {
2371 zwp_linux_buffer_release_v1_send_fenced_release(
2372 resource, release_fence_fd);
2373 } else {
2374 zwp_linux_buffer_release_v1_send_immediate_release(
2375 resource);
2376 }
2377
2378 wl_resource_destroy(resource);
2379}
2380
2381WL_EXPORT void
2382weston_buffer_release_reference(struct weston_buffer_release_reference *ref,
2383 struct weston_buffer_release *buffer_release)
2384{
2385 if (buffer_release == ref->buffer_release)
2386 return;
2387
2388 if (ref->buffer_release) {
2389 ref->buffer_release->ref_count--;
2390 wl_list_remove(&ref->destroy_listener.link);
2391 if (ref->buffer_release->ref_count == 0)
2392 weston_buffer_release_destroy(ref->buffer_release);
2393 }
2394
2395 if (buffer_release) {
2396 buffer_release->ref_count++;
2397 wl_resource_add_destroy_listener(buffer_release->resource,
2398 &ref->destroy_listener);
2399 }
2400
2401 ref->buffer_release = buffer_release;
2402 ref->destroy_listener.notify =
2403 weston_buffer_release_reference_handle_destroy;
2404}
2405
2406WL_EXPORT void
2407weston_buffer_release_move(struct weston_buffer_release_reference *dest,
2408 struct weston_buffer_release_reference *src)
2409{
2410 weston_buffer_release_reference(dest, src->buffer_release);
2411 weston_buffer_release_reference(src, NULL);
2412}
2413
2414static void
Jason Ekstrand6bd62942013-06-20 20:38:23 -05002415weston_surface_attach(struct weston_surface *surface,
2416 struct weston_buffer *buffer)
Pekka Paalanende685b82012-12-04 15:58:12 +02002417{
2418 weston_buffer_reference(&surface->buffer_ref, buffer);
2419
Pekka Paalanena6421c42012-12-04 15:58:10 +02002420 if (!buffer) {
Pekka Paalanen5df44de2012-10-10 12:49:23 +03002421 if (weston_surface_is_mapped(surface))
2422 weston_surface_unmap(surface);
Ander Conselvan de Oliveirae11683a2012-03-27 17:36:40 +03002423 }
2424
Pekka Paalanen5df44de2012-10-10 12:49:23 +03002425 surface->compositor->renderer->attach(surface, buffer);
Pekka Paalanenbb2f3f22014-03-14 14:38:11 +02002426
George Kiagiadakis8f9e87f2014-06-13 18:14:20 +02002427 weston_surface_calculate_size_from_buffer(surface);
Pekka Paalanen133e4392014-09-23 22:08:46 -04002428 weston_presentation_feedback_discard_list(&surface->feedback_list);
Benjamin Franzkefaa0a9d2011-02-21 16:24:53 +01002429}
2430
Marius Vlad9fdda7f2019-06-11 16:08:55 +03002431/** weston_compositor_damage_all
2432 * \ingroup compositor
2433 */
Kristian Høgsberg3be2ce92012-02-29 12:42:35 -05002434WL_EXPORT void
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05002435weston_compositor_damage_all(struct weston_compositor *compositor)
Kristian Høgsberge10a5d92011-04-22 14:01:18 -04002436{
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05002437 struct weston_output *output;
Kristian Høgsberge10a5d92011-04-22 14:01:18 -04002438
2439 wl_list_for_each(output, &compositor->output_list, link)
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05002440 weston_output_damage(output);
Kristian Høgsberge10a5d92011-04-22 14:01:18 -04002441}
2442
Marius Vlad55d87362019-06-11 01:15:35 +03002443/**
2444 * \ingroup output
2445 */
Kristian Høgsberg9f404b72012-01-26 00:11:01 -05002446WL_EXPORT void
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05002447weston_output_damage(struct weston_output *output)
Kristian Høgsberge10a5d92011-04-22 14:01:18 -04002448{
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05002449 struct weston_compositor *compositor = output->compositor;
Kristian Høgsberge10a5d92011-04-22 14:01:18 -04002450
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04002451 pixman_region32_union(&compositor->primary_plane.damage,
2452 &compositor->primary_plane.damage,
2453 &output->region);
Kristian Høgsberg49952d12012-06-20 00:35:59 -04002454 weston_output_schedule_repaint(output);
Kristian Høgsberge10a5d92011-04-22 14:01:18 -04002455}
2456
Kristian Høgsberg01f941b2009-05-27 17:47:15 -04002457static void
Jason Ekstranda7af7042013-10-12 22:38:11 -05002458surface_flush_damage(struct weston_surface *surface)
Kristian Høgsberg460a79b2012-06-18 15:09:11 -04002459{
Pekka Paalanende685b82012-12-04 15:58:12 +02002460 if (surface->buffer_ref.buffer &&
Jason Ekstrand6bd62942013-06-20 20:38:23 -05002461 wl_shm_buffer_get(surface->buffer_ref.buffer->resource))
Kristian Høgsbergfa1be022012-09-05 22:49:55 -04002462 surface->compositor->renderer->flush_damage(surface);
Kristian Høgsberg460a79b2012-06-18 15:09:11 -04002463
Marius Vlad2a1b7862019-09-05 13:12:18 +03002464 if (pixman_region32_not_empty(&surface->damage))
Marius Vlad3203ff62019-09-05 14:56:12 +03002465 TL_POINT(surface->compositor, "core_flush_damage", TLP_SURFACE(surface),
Pekka Paalanenb5026542014-11-12 15:09:24 +02002466 TLP_OUTPUT(surface->output), TLP_END);
2467
Jason Ekstrandef540082014-06-26 10:37:36 -07002468 pixman_region32_clear(&surface->damage);
Jason Ekstranda7af7042013-10-12 22:38:11 -05002469}
2470
2471static void
2472view_accumulate_damage(struct weston_view *view,
2473 pixman_region32_t *opaque)
2474{
2475 pixman_region32_t damage;
2476
2477 pixman_region32_init(&damage);
2478 if (view->transform.enabled) {
Kristian Høgsberg460a79b2012-06-18 15:09:11 -04002479 pixman_box32_t *extents;
2480
Jason Ekstranda7af7042013-10-12 22:38:11 -05002481 extents = pixman_region32_extents(&view->surface->damage);
Pekka Paalanenc7d7fdf2015-02-23 12:27:00 +02002482 view_compute_bbox(view, extents, &damage);
Kristian Høgsberg460a79b2012-06-18 15:09:11 -04002483 } else {
Jason Ekstranda7af7042013-10-12 22:38:11 -05002484 pixman_region32_copy(&damage, &view->surface->damage);
2485 pixman_region32_translate(&damage,
Pekka Paalanen502f5e02015-02-23 14:08:25 +02002486 view->geometry.x, view->geometry.y);
Kristian Høgsberg460a79b2012-06-18 15:09:11 -04002487 }
2488
Pekka Paalanen380adf52015-02-16 14:39:11 +02002489 pixman_region32_intersect(&damage, &damage,
2490 &view->transform.boundingbox);
Jason Ekstranda7af7042013-10-12 22:38:11 -05002491 pixman_region32_subtract(&damage, &damage, opaque);
2492 pixman_region32_union(&view->plane->damage,
2493 &view->plane->damage, &damage);
2494 pixman_region32_fini(&damage);
2495 pixman_region32_copy(&view->clip, opaque);
Pekka Paalanen8844bf22015-02-18 16:30:47 +02002496 pixman_region32_union(opaque, opaque, &view->transform.opaque);
Kristian Høgsberg460a79b2012-06-18 15:09:11 -04002497}
2498
Kristian Høgsbergcce1aec2011-04-22 15:38:14 -04002499static void
Michael Olbrichc5ea4952020-08-11 12:42:35 +02002500output_accumulate_damage(struct weston_output *output)
Ander Conselvan de Oliveira8ad19822013-03-05 17:30:27 +02002501{
Michael Olbrichc5ea4952020-08-11 12:42:35 +02002502 struct weston_compositor *ec = output->compositor;
Ander Conselvan de Oliveira8ad19822013-03-05 17:30:27 +02002503 struct weston_plane *plane;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002504 struct weston_view *ev;
Ander Conselvan de Oliveirae1bd5a02013-03-05 17:30:29 +02002505 pixman_region32_t opaque, clip;
Ander Conselvan de Oliveira8ad19822013-03-05 17:30:27 +02002506
Ander Conselvan de Oliveirae1bd5a02013-03-05 17:30:29 +02002507 pixman_region32_init(&clip);
Ander Conselvan de Oliveira8ad19822013-03-05 17:30:27 +02002508
2509 wl_list_for_each(plane, &ec->plane_list, link) {
Ander Conselvan de Oliveirae1bd5a02013-03-05 17:30:29 +02002510 pixman_region32_copy(&plane->clip, &clip);
2511
2512 pixman_region32_init(&opaque);
2513
Jason Ekstranda7af7042013-10-12 22:38:11 -05002514 wl_list_for_each(ev, &ec->view_list, link) {
2515 if (ev->plane != plane)
Ander Conselvan de Oliveirae1bd5a02013-03-05 17:30:29 +02002516 continue;
2517
Jason Ekstranda7af7042013-10-12 22:38:11 -05002518 view_accumulate_damage(ev, &opaque);
Ander Conselvan de Oliveirae1bd5a02013-03-05 17:30:29 +02002519 }
2520
2521 pixman_region32_union(&clip, &clip, &opaque);
2522 pixman_region32_fini(&opaque);
Ander Conselvan de Oliveira8ad19822013-03-05 17:30:27 +02002523 }
2524
Ander Conselvan de Oliveirae1bd5a02013-03-05 17:30:29 +02002525 pixman_region32_fini(&clip);
Ander Conselvan de Oliveira8ad19822013-03-05 17:30:27 +02002526
Jason Ekstranda7af7042013-10-12 22:38:11 -05002527 wl_list_for_each(ev, &ec->view_list, link)
Derek Foreman060cf112015-11-18 16:32:26 -06002528 ev->surface->touched = false;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002529
2530 wl_list_for_each(ev, &ec->view_list, link) {
Michael Olbrichc5ea4952020-08-11 12:42:35 +02002531 /* Ignore views not visible on the current output */
2532 if (!(ev->output_mask & (1u << output->id)))
2533 continue;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002534 if (ev->surface->touched)
2535 continue;
Derek Foreman060cf112015-11-18 16:32:26 -06002536 ev->surface->touched = true;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002537
2538 surface_flush_damage(ev->surface);
2539
Ander Conselvan de Oliveira8ad19822013-03-05 17:30:27 +02002540 /* Both the renderer and the backend have seen the buffer
2541 * by now. If renderer needs the buffer, it has its own
2542 * reference set. If the backend wants to keep the buffer
2543 * around for migrating the surface into a non-primary plane
2544 * later, keep_buffer is true. Otherwise, drop the core
2545 * reference now, and allow early buffer release. This enables
2546 * clients to use single-buffering.
2547 */
Alexandros Frantzis67629672018-10-19 12:14:11 +03002548 if (!ev->surface->keep_buffer) {
Jason Ekstranda7af7042013-10-12 22:38:11 -05002549 weston_buffer_reference(&ev->surface->buffer_ref, NULL);
Alexandros Frantzis67629672018-10-19 12:14:11 +03002550 weston_buffer_release_reference(
2551 &ev->surface->buffer_release_ref, NULL);
2552 }
Ander Conselvan de Oliveira8ad19822013-03-05 17:30:27 +02002553 }
Ander Conselvan de Oliveira8ad19822013-03-05 17:30:27 +02002554}
2555
2556static void
Jason Ekstranda7af7042013-10-12 22:38:11 -05002557surface_stash_subsurface_views(struct weston_surface *surface)
Pekka Paalanene67858b2013-04-25 13:57:42 +03002558{
2559 struct weston_subsurface *sub;
2560
Pekka Paalanene67858b2013-04-25 13:57:42 +03002561 wl_list_for_each(sub, &surface->subsurface_list, parent_link) {
Jason Ekstranda7af7042013-10-12 22:38:11 -05002562 if (sub->surface == surface)
Pekka Paalanene67858b2013-04-25 13:57:42 +03002563 continue;
2564
Jason Ekstranda7af7042013-10-12 22:38:11 -05002565 wl_list_insert_list(&sub->unused_views, &sub->surface->views);
2566 wl_list_init(&sub->surface->views);
2567
2568 surface_stash_subsurface_views(sub->surface);
Pekka Paalanene67858b2013-04-25 13:57:42 +03002569 }
2570}
2571
2572static void
Jason Ekstranda7af7042013-10-12 22:38:11 -05002573surface_free_unused_subsurface_views(struct weston_surface *surface)
Pekka Paalanene67858b2013-04-25 13:57:42 +03002574{
Jason Ekstranda7af7042013-10-12 22:38:11 -05002575 struct weston_subsurface *sub;
2576 struct weston_view *view, *nv;
Pekka Paalanene67858b2013-04-25 13:57:42 +03002577
Jason Ekstranda7af7042013-10-12 22:38:11 -05002578 wl_list_for_each(sub, &surface->subsurface_list, parent_link) {
2579 if (sub->surface == surface)
2580 continue;
2581
George Kiagiadakised04d382014-06-13 18:10:26 +02002582 wl_list_for_each_safe(view, nv, &sub->unused_views, surface_link) {
2583 weston_view_unmap (view);
Jason Ekstranda7af7042013-10-12 22:38:11 -05002584 weston_view_destroy(view);
George Kiagiadakised04d382014-06-13 18:10:26 +02002585 }
Jason Ekstranda7af7042013-10-12 22:38:11 -05002586
2587 surface_free_unused_subsurface_views(sub->surface);
2588 }
2589}
2590
2591static void
2592view_list_add_subsurface_view(struct weston_compositor *compositor,
2593 struct weston_subsurface *sub,
2594 struct weston_view *parent)
2595{
2596 struct weston_subsurface *child;
2597 struct weston_view *view = NULL, *iv;
2598
Pekka Paalanen661de3a2014-07-28 12:49:24 +03002599 if (!weston_surface_is_mapped(sub->surface))
2600 return;
2601
Jason Ekstranda7af7042013-10-12 22:38:11 -05002602 wl_list_for_each(iv, &sub->unused_views, surface_link) {
2603 if (iv->geometry.parent == parent) {
2604 view = iv;
2605 break;
Pekka Paalanene67858b2013-04-25 13:57:42 +03002606 }
2607 }
Jason Ekstranda7af7042013-10-12 22:38:11 -05002608
2609 if (view) {
2610 /* Put it back in the surface's list of views */
2611 wl_list_remove(&view->surface_link);
2612 wl_list_insert(&sub->surface->views, &view->surface_link);
2613 } else {
2614 view = weston_view_create(sub->surface);
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06002615 weston_view_set_position(view,
2616 sub->position.x,
2617 sub->position.y);
Jason Ekstranda7af7042013-10-12 22:38:11 -05002618 weston_view_set_transform_parent(view, parent);
2619 }
2620
Giulio Camuffo95ec0f92014-07-09 22:12:57 +03002621 view->parent_view = parent;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002622 weston_view_update_transform(view);
Armin Krezovićf8486c32016-06-30 06:04:28 +02002623 view->is_mapped = true;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002624
Pekka Paalanenb188e912013-11-19 14:03:35 +02002625 if (wl_list_empty(&sub->surface->subsurface_list)) {
2626 wl_list_insert(compositor->view_list.prev, &view->link);
2627 return;
2628 }
2629
2630 wl_list_for_each(child, &sub->surface->subsurface_list, parent_link) {
2631 if (child->surface == sub->surface)
2632 wl_list_insert(compositor->view_list.prev, &view->link);
2633 else
Jason Ekstranda7af7042013-10-12 22:38:11 -05002634 view_list_add_subsurface_view(compositor, child, view);
Pekka Paalanenb188e912013-11-19 14:03:35 +02002635 }
Jason Ekstranda7af7042013-10-12 22:38:11 -05002636}
2637
Emilio Pozuelo Monfort4f3cad72017-01-27 17:30:29 +01002638/* This recursively adds the sub-surfaces for a view, relying on the
2639 * sub-surface order. Thus, if a client restacks the sub-surfaces, that
2640 * change first happens to the sub-surface list, and then automatically
2641 * propagates here. See weston_surface_damage_subsurfaces() for how the
2642 * sub-surfaces receive damage when the client changes the state.
2643 */
Jason Ekstranda7af7042013-10-12 22:38:11 -05002644static void
2645view_list_add(struct weston_compositor *compositor,
2646 struct weston_view *view)
2647{
2648 struct weston_subsurface *sub;
2649
2650 weston_view_update_transform(view);
Jason Ekstranda7af7042013-10-12 22:38:11 -05002651
Pekka Paalanenb188e912013-11-19 14:03:35 +02002652 if (wl_list_empty(&view->surface->subsurface_list)) {
2653 wl_list_insert(compositor->view_list.prev, &view->link);
2654 return;
2655 }
2656
2657 wl_list_for_each(sub, &view->surface->subsurface_list, parent_link) {
2658 if (sub->surface == view->surface)
2659 wl_list_insert(compositor->view_list.prev, &view->link);
2660 else
Jason Ekstranda7af7042013-10-12 22:38:11 -05002661 view_list_add_subsurface_view(compositor, sub, view);
Pekka Paalanenb188e912013-11-19 14:03:35 +02002662 }
Jason Ekstranda7af7042013-10-12 22:38:11 -05002663}
2664
2665static void
2666weston_compositor_build_view_list(struct weston_compositor *compositor)
2667{
Loïc Yhuel267b16e2019-09-17 20:14:56 +02002668 struct weston_view *view, *tmp;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002669 struct weston_layer *layer;
2670
2671 wl_list_for_each(layer, &compositor->layer_list, link)
Giulio Camuffo412e6a52014-07-09 22:12:56 +03002672 wl_list_for_each(view, &layer->view_list.link, layer_link.link)
Jason Ekstranda7af7042013-10-12 22:38:11 -05002673 surface_stash_subsurface_views(view->surface);
2674
Loïc Yhuel267b16e2019-09-17 20:14:56 +02002675 wl_list_for_each_safe(view, tmp, &compositor->view_list, link)
2676 wl_list_init(&view->link);
Jason Ekstranda7af7042013-10-12 22:38:11 -05002677 wl_list_init(&compositor->view_list);
Loïc Yhuel267b16e2019-09-17 20:14:56 +02002678
Jason Ekstranda7af7042013-10-12 22:38:11 -05002679 wl_list_for_each(layer, &compositor->layer_list, link) {
Giulio Camuffo412e6a52014-07-09 22:12:56 +03002680 wl_list_for_each(view, &layer->view_list.link, layer_link.link) {
Jason Ekstranda7af7042013-10-12 22:38:11 -05002681 view_list_add(compositor, view);
2682 }
2683 }
2684
2685 wl_list_for_each(layer, &compositor->layer_list, link)
Giulio Camuffo412e6a52014-07-09 22:12:56 +03002686 wl_list_for_each(view, &layer->view_list.link, layer_link.link)
Jason Ekstranda7af7042013-10-12 22:38:11 -05002687 surface_free_unused_subsurface_views(view->surface);
Pekka Paalanene67858b2013-04-25 13:57:42 +03002688}
2689
Pekka Paalanenbf0e0312014-12-17 16:20:41 +02002690static void
2691weston_output_take_feedback_list(struct weston_output *output,
2692 struct weston_surface *surface)
2693{
2694 struct weston_view *view;
2695 struct weston_presentation_feedback *feedback;
2696 uint32_t flags = 0xffffffff;
2697
2698 if (wl_list_empty(&surface->feedback_list))
2699 return;
2700
2701 /* All views must have the flag for the flag to survive. */
2702 wl_list_for_each(view, &surface->views, surface_link) {
2703 /* ignore views that are not on this output at all */
2704 if (view->output_mask & (1u << output->id))
2705 flags &= view->psf_flags;
2706 }
2707
2708 wl_list_for_each(feedback, &surface->feedback_list, link)
2709 feedback->psf_flags = flags;
2710
2711 wl_list_insert_list(&output->feedback_list, &surface->feedback_list);
2712 wl_list_init(&surface->feedback_list);
2713}
2714
David Herrmann1edf44c2013-10-22 17:11:26 +02002715static int
Daniel Stoneb1f166d2017-03-01 11:34:10 +00002716weston_output_repaint(struct weston_output *output, void *repaint_data)
Kristian Høgsbergef7a9ca2008-10-11 21:21:39 -04002717{
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05002718 struct weston_compositor *ec = output->compositor;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002719 struct weston_view *ev;
Kristian Høgsberg30c018b2012-01-26 08:40:37 -05002720 struct weston_animation *animation, *next;
2721 struct weston_frame_callback *cb, *cnext;
Jonas Ådahldb773762012-06-13 00:01:21 +02002722 struct wl_list frame_callback_list;
Ander Conselvan de Oliveira8ad19822013-03-05 17:30:27 +02002723 pixman_region32_t output_damage;
David Herrmann1edf44c2013-10-22 17:11:26 +02002724 int r;
Alexandros Frantzise6ac2af2017-11-16 18:20:53 +02002725 uint32_t frame_time_msec;
Ankit Nautiyal4b6e73d2019-03-26 13:37:12 +05302726 enum weston_hdcp_protection highest_requested = WESTON_HDCP_DISABLE;
Kristian Høgsbergfbdbbdc2008-11-28 17:06:06 -05002727
Ander Conselvan de Oliveirae1e23522013-12-13 22:10:55 +02002728 if (output->destroying)
2729 return 0;
2730
Marius Vlad3203ff62019-09-05 14:56:12 +03002731 TL_POINT(ec, "core_repaint_begin", TLP_OUTPUT(output), TLP_END);
Pekka Paalanenb5026542014-11-12 15:09:24 +02002732
Kristian Høgsberg3be2ce92012-02-29 12:42:35 -05002733 /* Rebuild the surface list and update surface transforms up front. */
Jason Ekstranda7af7042013-10-12 22:38:11 -05002734 weston_compositor_build_view_list(ec);
Pekka Paalanen15d60ef2012-01-27 14:38:33 +02002735
Ankit Nautiyal4b6e73d2019-03-26 13:37:12 +05302736 /* Find the highest protection desired for an output */
2737 wl_list_for_each(ev, &ec->view_list, link) {
2738 if (ev->surface->output_mask & (1u << output->id)) {
2739 /*
2740 * The desired_protection of the output should be the
2741 * maximum of the desired_protection of the surfaces,
2742 * that are displayed on that output, to avoid
2743 * reducing the protection for existing surfaces.
2744 */
2745 if (ev->surface->desired_protection > highest_requested)
2746 highest_requested =
2747 ev->surface->desired_protection;
2748 }
2749 }
2750
2751 output->desired_protection = highest_requested;
2752
Pekka Paalanenbf0e0312014-12-17 16:20:41 +02002753 if (output->assign_planes && !output->disable_planes) {
Daniel Stoneb1f166d2017-03-01 11:34:10 +00002754 output->assign_planes(output, repaint_data);
Pekka Paalanenbf0e0312014-12-17 16:20:41 +02002755 } else {
2756 wl_list_for_each(ev, &ec->view_list, link) {
Jason Ekstranda7af7042013-10-12 22:38:11 -05002757 weston_view_move_to_plane(ev, &ec->primary_plane);
Pekka Paalanenbf0e0312014-12-17 16:20:41 +02002758 ev->psf_flags = 0;
2759 }
2760 }
Kristian Høgsberg79af73e2012-08-03 15:45:23 -04002761
Pekka Paalanene67858b2013-04-25 13:57:42 +03002762 wl_list_init(&frame_callback_list);
Jason Ekstranda7af7042013-10-12 22:38:11 -05002763 wl_list_for_each(ev, &ec->view_list, link) {
2764 /* Note: This operation is safe to do multiple times on the
2765 * same surface.
2766 */
2767 if (ev->surface->output == output) {
Pekka Paalanene67858b2013-04-25 13:57:42 +03002768 wl_list_insert_list(&frame_callback_list,
Jason Ekstranda7af7042013-10-12 22:38:11 -05002769 &ev->surface->frame_callback_list);
2770 wl_list_init(&ev->surface->frame_callback_list);
Pekka Paalanen133e4392014-09-23 22:08:46 -04002771
Pekka Paalanenbf0e0312014-12-17 16:20:41 +02002772 weston_output_take_feedback_list(output, ev->surface);
Pekka Paalanene67858b2013-04-25 13:57:42 +03002773 }
2774 }
2775
Michael Olbrichc5ea4952020-08-11 12:42:35 +02002776 output_accumulate_damage(output);
Kristian Høgsberg53df1d82011-06-23 21:11:19 -04002777
Ander Conselvan de Oliveira4f521732012-08-15 14:02:05 -04002778 pixman_region32_init(&output_damage);
Ander Conselvan de Oliveira4f521732012-08-15 14:02:05 -04002779 pixman_region32_intersect(&output_damage,
2780 &ec->primary_plane.damage, &output->region);
Ander Conselvan de Oliveirae1bd5a02013-03-05 17:30:29 +02002781 pixman_region32_subtract(&output_damage,
2782 &output_damage, &ec->primary_plane.clip);
Ander Conselvan de Oliveira4f521732012-08-15 14:02:05 -04002783
Scott Moreauccbf29d2012-02-22 14:21:41 -07002784 if (output->dirty)
2785 weston_output_update_matrix(output);
2786
Daniel Stoneb1f166d2017-03-01 11:34:10 +00002787 r = output->repaint(output, &output_damage, repaint_data);
Kristian Høgsbergef7a9ca2008-10-11 21:21:39 -04002788
Kristian Høgsberg6ddcdae2012-02-28 22:31:58 -05002789 pixman_region32_fini(&output_damage);
Kristian Høgsberg81ce09a2008-12-31 16:18:42 -05002790
Daniel Stone09a97e22017-03-01 11:34:06 +00002791 output->repaint_needed = false;
Daniel Stone05df8c12017-03-03 16:59:42 +00002792 if (r == 0)
2793 output->repaint_status = REPAINT_AWAITING_COMPLETION;
Benjamin Franzkeec4d3422011-03-14 12:07:26 +01002794
Kristian Høgsbergaa6019e2012-03-11 16:35:16 -04002795 weston_compositor_repick(ec);
Kristian Høgsbergaa6019e2012-03-11 16:35:16 -04002796
Alexandros Frantzise6ac2af2017-11-16 18:20:53 +02002797 frame_time_msec = timespec_to_msec(&output->frame_time);
2798
Jonas Ådahldb773762012-06-13 00:01:21 +02002799 wl_list_for_each_safe(cb, cnext, &frame_callback_list, link) {
Alexandros Frantzise6ac2af2017-11-16 18:20:53 +02002800 wl_callback_send_done(cb->resource, frame_time_msec);
Jason Ekstrandfbbbec82013-06-14 10:07:57 -05002801 wl_resource_destroy(cb->resource);
Kristian Høgsberg81ce09a2008-12-31 16:18:42 -05002802 }
2803
Scott Moreaud64cf212012-06-08 19:40:54 -06002804 wl_list_for_each_safe(animation, next, &output->animation_list, link) {
Scott Moreaud64cf212012-06-08 19:40:54 -06002805 animation->frame_counter++;
Alexandros Frantzise6ac2af2017-11-16 18:20:53 +02002806 animation->frame(animation, output, &output->frame_time);
Scott Moreaud64cf212012-06-08 19:40:54 -06002807 }
David Herrmann1edf44c2013-10-22 17:11:26 +02002808
Marius Vlad3203ff62019-09-05 14:56:12 +03002809 TL_POINT(ec, "core_repaint_posted", TLP_OUTPUT(output), TLP_END);
Pekka Paalanenb5026542014-11-12 15:09:24 +02002810
David Herrmann1edf44c2013-10-22 17:11:26 +02002811 return r;
Kristian Høgsbergef044142011-06-21 15:02:12 -04002812}
Kristian Høgsbergb1868472011-04-22 12:27:57 -04002813
Pekka Paalanen82919792014-05-21 13:51:49 +03002814static void
2815weston_output_schedule_repaint_reset(struct weston_output *output)
2816{
Daniel Stone05df8c12017-03-03 16:59:42 +00002817 output->repaint_status = REPAINT_NOT_SCHEDULED;
Marius Vlad3203ff62019-09-05 14:56:12 +03002818 TL_POINT(output->compositor, "core_repaint_exit_loop",
2819 TLP_OUTPUT(output), TLP_END);
Pekka Paalanen82919792014-05-21 13:51:49 +03002820}
2821
Daniel Stoneb1f166d2017-03-01 11:34:10 +00002822static int
2823weston_output_maybe_repaint(struct weston_output *output, struct timespec *now,
2824 void *repaint_data)
Pekka Paalanen0513a952014-05-21 16:17:27 +03002825{
Pekka Paalanen0513a952014-05-21 16:17:27 +03002826 struct weston_compositor *compositor = output->compositor;
Daniel Stoneb1f166d2017-03-01 11:34:10 +00002827 int ret = 0;
Daniel Stone6847b852017-03-01 11:34:08 +00002828 int64_t msec_to_repaint;
Pekka Paalanen0513a952014-05-21 16:17:27 +03002829
Daniel Stone6847b852017-03-01 11:34:08 +00002830 /* We're not ready yet; come back to make a decision later. */
2831 if (output->repaint_status != REPAINT_SCHEDULED)
Daniel Stoneb1f166d2017-03-01 11:34:10 +00002832 return ret;
Daniel Stone6847b852017-03-01 11:34:08 +00002833
2834 msec_to_repaint = timespec_sub_to_msec(&output->next_repaint, now);
2835 if (msec_to_repaint > 1)
Daniel Stoneb1f166d2017-03-01 11:34:10 +00002836 return ret;
Daniel Stone05df8c12017-03-03 16:59:42 +00002837
Daniel Stonecd1a1c32017-01-16 15:38:54 +00002838 /* If we're sleeping, drop the repaint machinery entirely; we will
2839 * explicitly repaint all outputs when we come back. */
2840 if (compositor->state == WESTON_COMPOSITOR_SLEEPING ||
2841 compositor->state == WESTON_COMPOSITOR_OFFSCREEN)
2842 goto err;
Pekka Paalanen0513a952014-05-21 16:17:27 +03002843
Daniel Stonecd1a1c32017-01-16 15:38:54 +00002844 /* We don't actually need to repaint this output; drop it from
2845 * repaint until something causes damage. */
2846 if (!output->repaint_needed)
2847 goto err;
2848
2849 /* If repaint fails, we aren't going to get weston_output_finish_frame
2850 * to trigger a new repaint, so drop it from repaint and hope
Daniel Stone6847b852017-03-01 11:34:08 +00002851 * something schedules a successful repaint later. As repainting may
2852 * take some time, re-read our clock as a courtesy to the next
2853 * output. */
Daniel Stoneb1f166d2017-03-01 11:34:10 +00002854 ret = weston_output_repaint(output, repaint_data);
Daniel Stone6847b852017-03-01 11:34:08 +00002855 weston_compositor_read_presentation_clock(compositor, now);
Daniel Stonecd1a1c32017-01-16 15:38:54 +00002856 if (ret != 0)
2857 goto err;
2858
Tomohito Esaki7f4d9ff2018-06-05 10:37:06 +09002859 output->repainted = true;
Daniel Stoneb1f166d2017-03-01 11:34:10 +00002860 return ret;
Daniel Stonecd1a1c32017-01-16 15:38:54 +00002861
2862err:
Pekka Paalanen0513a952014-05-21 16:17:27 +03002863 weston_output_schedule_repaint_reset(output);
Daniel Stoneb1f166d2017-03-01 11:34:10 +00002864 return ret;
Daniel Stone6847b852017-03-01 11:34:08 +00002865}
2866
2867static void
2868output_repaint_timer_arm(struct weston_compositor *compositor)
2869{
2870 struct weston_output *output;
2871 bool any_should_repaint = false;
2872 struct timespec now;
Sergi Granellb4c08862017-03-18 13:01:15 +01002873 int64_t msec_to_next = INT64_MAX;
Daniel Stone6847b852017-03-01 11:34:08 +00002874
2875 weston_compositor_read_presentation_clock(compositor, &now);
2876
2877 wl_list_for_each(output, &compositor->output_list, link) {
2878 int64_t msec_to_this;
2879
2880 if (output->repaint_status != REPAINT_SCHEDULED)
2881 continue;
2882
2883 msec_to_this = timespec_sub_to_msec(&output->next_repaint,
2884 &now);
2885 if (!any_should_repaint || msec_to_this < msec_to_next)
2886 msec_to_next = msec_to_this;
2887
2888 any_should_repaint = true;
2889 }
2890
2891 if (!any_should_repaint)
2892 return;
2893
2894 /* Even if we should repaint immediately, add the minimum 1 ms delay.
2895 * This is a workaround to allow coalescing multiple output repaints
2896 * particularly from weston_output_finish_frame()
2897 * into the same call, which would not happen if we called
2898 * output_repaint_timer_handler() directly.
2899 */
2900 if (msec_to_next < 1)
2901 msec_to_next = 1;
2902
2903 wl_event_source_timer_update(compositor->repaint_timer, msec_to_next);
2904}
2905
2906static int
2907output_repaint_timer_handler(void *data)
2908{
2909 struct weston_compositor *compositor = data;
2910 struct weston_output *output;
2911 struct timespec now;
Daniel Stoneb1f166d2017-03-01 11:34:10 +00002912 void *repaint_data = NULL;
Emre Ucane479ed82018-03-20 15:29:40 +01002913 int ret = 0;
Daniel Stone6847b852017-03-01 11:34:08 +00002914
2915 weston_compositor_read_presentation_clock(compositor, &now);
Daniel Stoneb1f166d2017-03-01 11:34:10 +00002916
2917 if (compositor->backend->repaint_begin)
2918 repaint_data = compositor->backend->repaint_begin(compositor);
2919
2920 wl_list_for_each(output, &compositor->output_list, link) {
2921 ret = weston_output_maybe_repaint(output, &now, repaint_data);
2922 if (ret)
2923 break;
2924 }
2925
2926 if (ret == 0) {
Tomohito Esaki09bfcd62018-06-05 10:37:05 +09002927 if (compositor->backend->repaint_flush)
Antonio Borneoc90fccc2019-06-30 15:51:10 +02002928 ret = compositor->backend->repaint_flush(compositor,
2929 repaint_data);
Daniel Stoneb1f166d2017-03-01 11:34:10 +00002930 } else {
Antonio Borneoc90fccc2019-06-30 15:51:10 +02002931 if (compositor->backend->repaint_cancel)
2932 compositor->backend->repaint_cancel(compositor,
2933 repaint_data);
2934 }
2935
2936 if (ret != 0) {
Tomohito Esaki7f4d9ff2018-06-05 10:37:06 +09002937 wl_list_for_each(output, &compositor->output_list, link) {
2938 if (output->repainted)
2939 weston_output_schedule_repaint_reset(output);
2940 }
Daniel Stoneb1f166d2017-03-01 11:34:10 +00002941 }
Daniel Stone6847b852017-03-01 11:34:08 +00002942
Tomohito Esakiddaf95c2018-07-10 11:47:15 +09002943 wl_list_for_each(output, &compositor->output_list, link)
2944 output->repainted = false;
2945
Daniel Stone6847b852017-03-01 11:34:08 +00002946 output_repaint_timer_arm(compositor);
2947
Pekka Paalanen0513a952014-05-21 16:17:27 +03002948 return 0;
2949}
2950
Pekka Paalanen50aa3a72020-05-28 11:34:04 +03002951/** Convert a presentation timestamp to another clock domain
2952 *
2953 * \param compositor The compositor defines the presentation clock domain.
2954 * \param presentation_stamp The timestamp in presentation clock domain.
2955 * \param presentation_now Current time in presentation clock domain.
2956 * \param target_clock Defines the target clock domain.
2957 *
2958 * This approximation relies on presentation_stamp to be close to current time.
2959 * The further it is from current time and the bigger the speed difference
2960 * between the two clock domains, the bigger the conversion error.
2961 *
2962 * Conversion error due to system load is biased and unbounded.
2963 */
2964static struct timespec
2965convert_presentation_time_now(struct weston_compositor *compositor,
2966 const struct timespec *presentation_stamp,
2967 const struct timespec *presentation_now,
2968 clockid_t target_clock)
2969{
2970 struct timespec target_now = {};
2971 struct timespec target_stamp;
2972 int64_t delta_ns;
2973
2974 if (compositor->presentation_clock == target_clock)
2975 return *presentation_stamp;
2976
2977 clock_gettime(target_clock, &target_now);
2978 delta_ns = timespec_sub_to_nsec(presentation_stamp, presentation_now);
2979 timespec_add_nsec(&target_stamp, &target_now, delta_ns);
2980
2981 return target_stamp;
2982}
2983
Marius Vlad55d87362019-06-11 01:15:35 +03002984/**
2985 * \ingroup output
2986 */
Kristian Høgsbergef044142011-06-21 15:02:12 -04002987WL_EXPORT void
Pekka Paalanenb5eedad2014-09-23 22:08:45 -04002988weston_output_finish_frame(struct weston_output *output,
Pekka Paalanen363aa7b2014-12-17 16:20:40 +02002989 const struct timespec *stamp,
2990 uint32_t presented_flags)
Kristian Høgsbergef044142011-06-21 15:02:12 -04002991{
Kristian Høgsberg7dbf5e22012-03-05 19:50:08 -05002992 struct weston_compositor *compositor = output->compositor;
Pekka Paalanen0513a952014-05-21 16:17:27 +03002993 int32_t refresh_nsec;
2994 struct timespec now;
Pekka Paalanen50aa3a72020-05-28 11:34:04 +03002995 struct timespec vblank_monotonic;
Daniel Stone6847b852017-03-01 11:34:08 +00002996 int64_t msec_rel;
Pekka Paalanen133e4392014-09-23 22:08:46 -04002997
Daniel Stone05df8c12017-03-03 16:59:42 +00002998 assert(output->repaint_status == REPAINT_AWAITING_COMPLETION);
Daniel Stone3615ce12017-03-01 11:34:05 +00002999 assert(stamp || (presented_flags & WP_PRESENTATION_FEEDBACK_INVALID));
3000
Daniel Stone6847b852017-03-01 11:34:08 +00003001 weston_compositor_read_presentation_clock(compositor, &now);
3002
Daniel Stone3615ce12017-03-01 11:34:05 +00003003 /* If we haven't been supplied any timestamp at all, we don't have a
3004 * timebase to work against, so any delay just wastes time. Push a
3005 * repaint as soon as possible so we can get on with it. */
Daniel Stone6847b852017-03-01 11:34:08 +00003006 if (!stamp) {
3007 output->next_repaint = now;
Daniel Stone3615ce12017-03-01 11:34:05 +00003008 goto out;
Daniel Stone6847b852017-03-01 11:34:08 +00003009 }
Daniel Stone3615ce12017-03-01 11:34:05 +00003010
Pekka Paalanen50aa3a72020-05-28 11:34:04 +03003011 vblank_monotonic = convert_presentation_time_now(compositor,
3012 stamp, &now,
3013 CLOCK_MONOTONIC);
Marius Vlad3203ff62019-09-05 14:56:12 +03003014 TL_POINT(compositor, "core_repaint_finished", TLP_OUTPUT(output),
Pekka Paalanen50aa3a72020-05-28 11:34:04 +03003015 TLP_VBLANK(&vblank_monotonic), TLP_END);
Marius Vladdf9278a2018-03-06 18:56:23 +02003016
Pekka Paalanend7894d02015-07-03 15:08:53 +03003017 refresh_nsec = millihz_to_nsec(output->current_mode->refresh);
Pekka Paalanen133e4392014-09-23 22:08:46 -04003018 weston_presentation_feedback_present_list(&output->feedback_list,
3019 output, refresh_nsec, stamp,
Pekka Paalanen363aa7b2014-12-17 16:20:40 +02003020 output->msc,
3021 presented_flags);
Kristian Høgsberg7dbf5e22012-03-05 19:50:08 -05003022
Alexandros Frantzise6ac2af2017-11-16 18:20:53 +02003023 output->frame_time = *stamp;
Kristian Høgsberg7dbf5e22012-03-05 19:50:08 -05003024
Daniel Stone6847b852017-03-01 11:34:08 +00003025 timespec_add_nsec(&output->next_repaint, stamp, refresh_nsec);
3026 timespec_add_msec(&output->next_repaint, &output->next_repaint,
3027 -compositor->repaint_msec);
3028 msec_rel = timespec_sub_to_msec(&output->next_repaint, &now);
Daniel Stone84aff5c2017-03-01 11:34:04 +00003029
3030 if (msec_rel < -1000 || msec_rel > 1000) {
Pekka Paalanen8fd4de42015-03-19 12:27:29 +02003031 static bool warned;
3032
3033 if (!warned)
3034 weston_log("Warning: computed repaint delay is "
Daniel Stone6847b852017-03-01 11:34:08 +00003035 "insane: %lld msec\n", (long long) msec_rel);
Pekka Paalanen8fd4de42015-03-19 12:27:29 +02003036 warned = true;
3037
Daniel Stone6847b852017-03-01 11:34:08 +00003038 output->next_repaint = now;
Pekka Paalanen8fd4de42015-03-19 12:27:29 +02003039 }
3040
Mario Kleinerb7df04e2015-06-21 21:25:15 +02003041 /* Called from restart_repaint_loop and restart happens already after
3042 * the deadline given by repaint_msec? In that case we delay until
3043 * the deadline of the next frame, to give clients a more predictable
3044 * timing of the repaint cycle to lock on. */
Daniel Stoneeca5cca2017-02-28 21:53:51 +00003045 if (presented_flags == WP_PRESENTATION_FEEDBACK_INVALID &&
3046 msec_rel < 0) {
3047 while (timespec_sub_to_nsec(&output->next_repaint, &now) < 0) {
3048 timespec_add_nsec(&output->next_repaint,
3049 &output->next_repaint,
3050 refresh_nsec);
3051 }
3052 }
Mario Kleinerb7df04e2015-06-21 21:25:15 +02003053
Daniel Stone3615ce12017-03-01 11:34:05 +00003054out:
Daniel Stone05df8c12017-03-03 16:59:42 +00003055 output->repaint_status = REPAINT_SCHEDULED;
Daniel Stone6847b852017-03-01 11:34:08 +00003056 output_repaint_timer_arm(compositor);
Kristian Høgsberg7dbf5e22012-03-05 19:50:08 -05003057}
3058
3059static void
3060idle_repaint(void *data)
3061{
3062 struct weston_output *output = data;
Antonio Borneoc90fccc2019-06-30 15:51:10 +02003063 int ret;
Kristian Høgsberg7dbf5e22012-03-05 19:50:08 -05003064
Daniel Stone05df8c12017-03-03 16:59:42 +00003065 assert(output->repaint_status == REPAINT_BEGIN_FROM_IDLE);
3066 output->repaint_status = REPAINT_AWAITING_COMPLETION;
Pekka Paalanendcbcfc72017-10-26 14:33:59 +03003067 output->idle_repaint_source = NULL;
Antonio Borneoc90fccc2019-06-30 15:51:10 +02003068 ret = output->start_repaint_loop(output);
3069 if (ret != 0)
3070 weston_output_schedule_repaint_reset(output);
Kristian Høgsbergef7a9ca2008-10-11 21:21:39 -04003071}
3072
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -04003073WL_EXPORT void
Giulio Camuffo412e6a52014-07-09 22:12:56 +03003074weston_layer_entry_insert(struct weston_layer_entry *list,
3075 struct weston_layer_entry *entry)
3076{
3077 wl_list_insert(&list->link, &entry->link);
3078 entry->layer = list->layer;
3079}
3080
3081WL_EXPORT void
3082weston_layer_entry_remove(struct weston_layer_entry *entry)
3083{
3084 wl_list_remove(&entry->link);
3085 wl_list_init(&entry->link);
3086 entry->layer = NULL;
3087}
3088
Quentin Glidic82681572016-12-17 13:40:51 +01003089
3090/** Initialize the weston_layer struct.
3091 *
3092 * \param compositor The compositor instance
3093 * \param layer The layer to initialize
3094 */
Giulio Camuffo412e6a52014-07-09 22:12:56 +03003095WL_EXPORT void
Quentin Glidic82681572016-12-17 13:40:51 +01003096weston_layer_init(struct weston_layer *layer,
3097 struct weston_compositor *compositor)
Kristian Høgsberg3be2ce92012-02-29 12:42:35 -05003098{
Quentin Glidic82681572016-12-17 13:40:51 +01003099 layer->compositor = compositor;
3100 wl_list_init(&layer->link);
Giulio Camuffo412e6a52014-07-09 22:12:56 +03003101 wl_list_init(&layer->view_list.link);
3102 layer->view_list.layer = layer;
Giulio Camuffo95ec0f92014-07-09 22:12:57 +03003103 weston_layer_set_mask_infinite(layer);
Quentin Glidic82681572016-12-17 13:40:51 +01003104}
3105
3106/** Sets the position of the layer in the layer list. The layer will be placed
3107 * below any layer with the same position value, if any.
3108 * This function is safe to call if the layer is already on the list, but the
3109 * layer may be moved below other layers at the same position, if any.
3110 *
3111 * \param layer The layer to modify
3112 * \param position The position the layer will be placed at
3113 */
3114WL_EXPORT void
3115weston_layer_set_position(struct weston_layer *layer,
3116 enum weston_layer_position position)
3117{
3118 struct weston_layer *below;
3119
3120 wl_list_remove(&layer->link);
3121
3122 /* layer_list is ordered from top to bottom, the last layer being the
3123 * background with the smallest position value */
3124
3125 layer->position = position;
3126 wl_list_for_each_reverse(below, &layer->compositor->layer_list, link) {
3127 if (below->position >= layer->position) {
3128 wl_list_insert(&below->link, &layer->link);
3129 return;
3130 }
3131 }
3132 wl_list_insert(&layer->compositor->layer_list, &layer->link);
3133}
3134
3135/** Hide a layer by taking it off the layer list.
3136 * This function is safe to call if the layer is not on the list.
3137 *
3138 * \param layer The layer to hide
3139 */
3140WL_EXPORT void
3141weston_layer_unset_position(struct weston_layer *layer)
3142{
3143 wl_list_remove(&layer->link);
3144 wl_list_init(&layer->link);
Kristian Høgsberg3be2ce92012-02-29 12:42:35 -05003145}
3146
3147WL_EXPORT void
Giulio Camuffo95ec0f92014-07-09 22:12:57 +03003148weston_layer_set_mask(struct weston_layer *layer,
3149 int x, int y, int width, int height)
3150{
3151 struct weston_view *view;
3152
3153 layer->mask.x1 = x;
3154 layer->mask.x2 = x + width;
3155 layer->mask.y1 = y;
3156 layer->mask.y2 = y + height;
3157
3158 wl_list_for_each(view, &layer->view_list.link, layer_link.link) {
3159 weston_view_geometry_dirty(view);
3160 }
3161}
3162
3163WL_EXPORT void
3164weston_layer_set_mask_infinite(struct weston_layer *layer)
3165{
Adam Jackson3c3f3b12019-10-16 16:02:59 -04003166 struct weston_view *view;
3167
3168 layer->mask.x1 = INT32_MIN;
3169 layer->mask.x2 = INT32_MAX;
3170 layer->mask.y1 = INT32_MIN;
3171 layer->mask.y2 = INT32_MAX;
3172
3173 wl_list_for_each(view, &layer->view_list.link, layer_link.link) {
3174 weston_view_geometry_dirty(view);
3175 }
Giulio Camuffo95ec0f92014-07-09 22:12:57 +03003176}
3177
Daniel Stone3b775632018-07-20 08:38:25 +01003178WL_EXPORT bool
3179weston_layer_mask_is_infinite(struct weston_layer *layer)
3180{
3181 return layer->mask.x1 == INT32_MIN &&
3182 layer->mask.y1 == INT32_MIN &&
Adam Jackson3c3f3b12019-10-16 16:02:59 -04003183 layer->mask.x2 == INT32_MAX &&
3184 layer->mask.y2 == INT32_MAX;
Daniel Stone3b775632018-07-20 08:38:25 +01003185}
3186
Marius Vlad55d87362019-06-11 01:15:35 +03003187/**
3188 * \ingroup output
3189 */
Giulio Camuffo95ec0f92014-07-09 22:12:57 +03003190WL_EXPORT void
Kristian Høgsberg49952d12012-06-20 00:35:59 -04003191weston_output_schedule_repaint(struct weston_output *output)
Kristian Høgsbergef7a9ca2008-10-11 21:21:39 -04003192{
Kristian Høgsberg49952d12012-06-20 00:35:59 -04003193 struct weston_compositor *compositor = output->compositor;
Kristian Høgsbergef044142011-06-21 15:02:12 -04003194 struct wl_event_loop *loop;
Benjamin Franzkeec4d3422011-03-14 12:07:26 +01003195
Bryce Harrington08976ac2016-08-30 12:05:16 -07003196 if (compositor->state == WESTON_COMPOSITOR_SLEEPING ||
3197 compositor->state == WESTON_COMPOSITOR_OFFSCREEN)
Kristian Høgsberge10a5d92011-04-22 14:01:18 -04003198 return;
3199
Pekka Paalanenb5026542014-11-12 15:09:24 +02003200 if (!output->repaint_needed)
Marius Vlad3203ff62019-09-05 14:56:12 +03003201 TL_POINT(compositor, "core_repaint_req", TLP_OUTPUT(output), TLP_END);
Pekka Paalanenb5026542014-11-12 15:09:24 +02003202
Kristian Høgsbergef044142011-06-21 15:02:12 -04003203 loop = wl_display_get_event_loop(compositor->wl_display);
Daniel Stone09a97e22017-03-01 11:34:06 +00003204 output->repaint_needed = true;
Daniel Stone05df8c12017-03-03 16:59:42 +00003205
3206 /* If we already have a repaint scheduled for our idle handler,
3207 * no need to set it again. If the repaint has been called but
3208 * not finished, then weston_output_finish_frame() will notice
3209 * that a repaint is needed and schedule one. */
3210 if (output->repaint_status != REPAINT_NOT_SCHEDULED)
Kristian Høgsberg49952d12012-06-20 00:35:59 -04003211 return;
Benjamin Franzkeec4d3422011-03-14 12:07:26 +01003212
Daniel Stone05df8c12017-03-03 16:59:42 +00003213 output->repaint_status = REPAINT_BEGIN_FROM_IDLE;
Pekka Paalanendcbcfc72017-10-26 14:33:59 +03003214 assert(!output->idle_repaint_source);
3215 output->idle_repaint_source = wl_event_loop_add_idle(loop, idle_repaint,
3216 output);
Marius Vlad3203ff62019-09-05 14:56:12 +03003217 TL_POINT(compositor, "core_repaint_enter_loop", TLP_OUTPUT(output), TLP_END);
Kristian Høgsbergef7a9ca2008-10-11 21:21:39 -04003218}
Kristian Høgsberg5c8c3282009-02-09 15:17:46 -05003219
Marius Vlad9fdda7f2019-06-11 16:08:55 +03003220/** weston_compositor_schedule_repaint
3221 * \ingroup compositor
3222 */
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -04003223WL_EXPORT void
Kristian Høgsberg49952d12012-06-20 00:35:59 -04003224weston_compositor_schedule_repaint(struct weston_compositor *compositor)
3225{
3226 struct weston_output *output;
3227
3228 wl_list_for_each(output, &compositor->output_list, link)
3229 weston_output_schedule_repaint(output);
3230}
3231
Kristian Høgsberg5503bf82008-11-06 10:38:17 -05003232static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -04003233surface_destroy(struct wl_client *client, struct wl_resource *resource)
Kristian Høgsberg16eb6752008-10-08 22:51:32 -04003234{
Kristian Høgsbergeae5de72012-04-11 22:42:15 -04003235 wl_resource_destroy(resource);
Kristian Høgsberg16eb6752008-10-08 22:51:32 -04003236}
3237
Kristian Høgsberg5503bf82008-11-06 10:38:17 -05003238static void
Ander Conselvan de Oliveirae11683a2012-03-27 17:36:40 +03003239surface_attach(struct wl_client *client,
3240 struct wl_resource *resource,
3241 struct wl_resource *buffer_resource, int32_t sx, int32_t sy)
3242{
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -05003243 struct weston_surface *surface = wl_resource_get_user_data(resource);
Jason Ekstrand6bd62942013-06-20 20:38:23 -05003244 struct weston_buffer *buffer = NULL;
Ander Conselvan de Oliveirae11683a2012-03-27 17:36:40 +03003245
Kristian Høgsbergab19f932013-08-20 11:30:54 -07003246 if (buffer_resource) {
Jason Ekstrand6bd62942013-06-20 20:38:23 -05003247 buffer = weston_buffer_from_resource(buffer_resource);
Kristian Høgsbergab19f932013-08-20 11:30:54 -07003248 if (buffer == NULL) {
3249 wl_client_post_no_memory(client);
3250 return;
3251 }
Kristian Høgsberg08b58c72013-08-15 12:26:42 -07003252 }
Kristian Høgsberga691aee2011-06-23 21:43:50 -04003253
Pekka Paalanende685b82012-12-04 15:58:12 +02003254 /* Attach, attach, without commit in between does not send
3255 * wl_buffer.release. */
Jason Ekstrand7b982072014-05-20 14:33:03 -05003256 weston_surface_state_set_buffer(&surface->pending, buffer);
Ander Conselvan de Oliveirae11683a2012-03-27 17:36:40 +03003257
Pekka Paalanen5df44de2012-10-10 12:49:23 +03003258 surface->pending.sx = sx;
3259 surface->pending.sy = sy;
Giulio Camuffo184df502013-02-21 11:29:21 +01003260 surface->pending.newly_attached = 1;
Kristian Høgsbergf9212892008-10-11 18:40:23 -04003261}
3262
Kristian Høgsberg5503bf82008-11-06 10:38:17 -05003263static void
Kristian Høgsbergd2412e22008-12-15 20:35:24 -05003264surface_damage(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -04003265 struct wl_resource *resource,
Kristian Høgsbergd2412e22008-12-15 20:35:24 -05003266 int32_t x, int32_t y, int32_t width, int32_t height)
Kristian Høgsberg7f77bd82008-11-07 08:39:37 -05003267{
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -05003268 struct weston_surface *surface = wl_resource_get_user_data(resource);
Kristian Høgsberg9d69f8e2010-09-03 14:46:38 -04003269
Derek Foreman57e92ed2015-11-17 14:11:35 -06003270 if (width <= 0 || height <= 0)
3271 return;
3272
Derek Foreman152254b2015-11-26 14:17:48 -06003273 pixman_region32_union_rect(&surface->pending.damage_surface,
3274 &surface->pending.damage_surface,
3275 x, y, width, height);
3276}
3277
3278static void
3279surface_damage_buffer(struct wl_client *client,
3280 struct wl_resource *resource,
3281 int32_t x, int32_t y, int32_t width, int32_t height)
3282{
3283 struct weston_surface *surface = wl_resource_get_user_data(resource);
3284
3285 if (width <= 0 || height <= 0)
3286 return;
3287
3288 pixman_region32_union_rect(&surface->pending.damage_buffer,
3289 &surface->pending.damage_buffer,
Kristian Høgsberg460a79b2012-06-18 15:09:11 -04003290 x, y, width, height);
Kristian Høgsbergfbdbbdc2008-11-28 17:06:06 -05003291}
3292
Kristian Høgsberg33418202011-08-16 23:01:28 -04003293static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -04003294destroy_frame_callback(struct wl_resource *resource)
Kristian Høgsberg33418202011-08-16 23:01:28 -04003295{
Jason Ekstrandfbbbec82013-06-14 10:07:57 -05003296 struct weston_frame_callback *cb = wl_resource_get_user_data(resource);
Kristian Høgsberg904055a2011-08-18 17:55:30 -04003297
3298 wl_list_remove(&cb->link);
Pekka Paalanen8c196452011-11-15 11:45:42 +02003299 free(cb);
Kristian Høgsberg33418202011-08-16 23:01:28 -04003300}
3301
3302static void
3303surface_frame(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -04003304 struct wl_resource *resource, uint32_t callback)
Kristian Høgsberg33418202011-08-16 23:01:28 -04003305{
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05003306 struct weston_frame_callback *cb;
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -05003307 struct weston_surface *surface = wl_resource_get_user_data(resource);
Kristian Høgsberg33418202011-08-16 23:01:28 -04003308
3309 cb = malloc(sizeof *cb);
3310 if (cb == NULL) {
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -04003311 wl_resource_post_no_memory(resource);
Kristian Høgsberg33418202011-08-16 23:01:28 -04003312 return;
3313 }
Pekka Paalanenbc106382012-10-10 12:49:31 +03003314
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07003315 cb->resource = wl_resource_create(client, &wl_callback_interface, 1,
3316 callback);
3317 if (cb->resource == NULL) {
3318 free(cb);
3319 wl_resource_post_no_memory(resource);
3320 return;
3321 }
3322
Jason Ekstranda85118c2013-06-27 20:17:02 -05003323 wl_resource_set_implementation(cb->resource, NULL, cb,
3324 destroy_frame_callback);
Kristian Høgsberg33418202011-08-16 23:01:28 -04003325
Pekka Paalanenbc106382012-10-10 12:49:31 +03003326 wl_list_insert(surface->pending.frame_callback_list.prev, &cb->link);
Kristian Høgsberg33418202011-08-16 23:01:28 -04003327}
3328
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05003329static void
3330surface_set_opaque_region(struct wl_client *client,
3331 struct wl_resource *resource,
3332 struct wl_resource *region_resource)
3333{
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -05003334 struct weston_surface *surface = wl_resource_get_user_data(resource);
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05003335 struct weston_region *region;
3336
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05003337 if (region_resource) {
Jason Ekstrand8895efc2013-06-14 10:07:56 -05003338 region = wl_resource_get_user_data(region_resource);
Pekka Paalanen512dde82012-10-10 12:49:27 +03003339 pixman_region32_copy(&surface->pending.opaque,
3340 &region->region);
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05003341 } else {
Jason Ekstrandef540082014-06-26 10:37:36 -07003342 pixman_region32_clear(&surface->pending.opaque);
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05003343 }
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05003344}
3345
3346static void
3347surface_set_input_region(struct wl_client *client,
3348 struct wl_resource *resource,
3349 struct wl_resource *region_resource)
3350{
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -05003351 struct weston_surface *surface = wl_resource_get_user_data(resource);
Kristian Høgsberg010f98b2012-02-23 17:30:45 -05003352 struct weston_region *region;
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05003353
3354 if (region_resource) {
Jason Ekstrand8895efc2013-06-14 10:07:56 -05003355 region = wl_resource_get_user_data(region_resource);
Pekka Paalanen0cbd3b52012-10-10 12:49:28 +03003356 pixman_region32_copy(&surface->pending.input,
3357 &region->region);
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05003358 } else {
Pekka Paalanen0cbd3b52012-10-10 12:49:28 +03003359 pixman_region32_fini(&surface->pending.input);
3360 region_init_infinite(&surface->pending.input);
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05003361 }
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05003362}
3363
Emilio Pozuelo Monfort4f3cad72017-01-27 17:30:29 +01003364/* Cause damage to this sub-surface and all its children.
3365 *
3366 * This is useful when there are state changes that need an implicit
3367 * damage, e.g. a z-order change.
3368 */
3369static void
3370weston_surface_damage_subsurfaces(struct weston_subsurface *sub)
3371{
3372 struct weston_subsurface *child;
3373
3374 weston_surface_damage(sub->surface);
3375 sub->reordered = false;
3376
3377 wl_list_for_each(child, &sub->surface->subsurface_list, parent_link)
3378 if (child != sub)
3379 weston_surface_damage_subsurfaces(child);
3380}
3381
Pekka Paalanen5df44de2012-10-10 12:49:23 +03003382static void
Pekka Paalanene67858b2013-04-25 13:57:42 +03003383weston_surface_commit_subsurface_order(struct weston_surface *surface)
Pekka Paalanen5df44de2012-10-10 12:49:23 +03003384{
Pekka Paalanene67858b2013-04-25 13:57:42 +03003385 struct weston_subsurface *sub;
3386
3387 wl_list_for_each_reverse(sub, &surface->subsurface_list_pending,
3388 parent_link_pending) {
3389 wl_list_remove(&sub->parent_link);
3390 wl_list_insert(&surface->subsurface_list, &sub->parent_link);
Emilio Pozuelo Monfort4f3cad72017-01-27 17:30:29 +01003391
3392 if (sub->reordered)
3393 weston_surface_damage_subsurfaces(sub);
Pekka Paalanene67858b2013-04-25 13:57:42 +03003394 }
3395}
3396
3397static void
Pekka Paalanen04baea52016-04-26 15:50:58 +03003398weston_surface_build_buffer_matrix(const struct weston_surface *surface,
Jason Ekstrand1e059042014-10-16 10:55:19 -05003399 struct weston_matrix *matrix)
3400{
Pekka Paalanen04baea52016-04-26 15:50:58 +03003401 const struct weston_buffer_viewport *vp = &surface->buffer_viewport;
Jason Ekstrand1e059042014-10-16 10:55:19 -05003402 double src_width, src_height, dest_width, dest_height;
3403
3404 weston_matrix_init(matrix);
3405
3406 if (vp->buffer.src_width == wl_fixed_from_int(-1)) {
3407 src_width = surface->width_from_buffer;
3408 src_height = surface->height_from_buffer;
3409 } else {
3410 src_width = wl_fixed_to_double(vp->buffer.src_width);
3411 src_height = wl_fixed_to_double(vp->buffer.src_height);
3412 }
3413
3414 if (vp->surface.width == -1) {
3415 dest_width = src_width;
3416 dest_height = src_height;
3417 } else {
3418 dest_width = vp->surface.width;
3419 dest_height = vp->surface.height;
3420 }
3421
3422 if (src_width != dest_width || src_height != dest_height)
3423 weston_matrix_scale(matrix,
3424 src_width / dest_width,
3425 src_height / dest_height, 1);
3426
3427 if (vp->buffer.src_width != wl_fixed_from_int(-1))
3428 weston_matrix_translate(matrix,
3429 wl_fixed_to_double(vp->buffer.src_x),
3430 wl_fixed_to_double(vp->buffer.src_y),
3431 0);
3432
3433 switch (vp->buffer.transform) {
3434 case WL_OUTPUT_TRANSFORM_FLIPPED:
3435 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
3436 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
3437 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
3438 weston_matrix_scale(matrix, -1, 1, 1);
3439 weston_matrix_translate(matrix,
3440 surface->width_from_buffer, 0, 0);
3441 break;
3442 }
3443
3444 switch (vp->buffer.transform) {
3445 default:
3446 case WL_OUTPUT_TRANSFORM_NORMAL:
3447 case WL_OUTPUT_TRANSFORM_FLIPPED:
3448 break;
3449 case WL_OUTPUT_TRANSFORM_90:
3450 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
Pekka Paalanen8060d822020-02-06 15:27:54 +02003451 weston_matrix_rotate_xy(matrix, 0, -1);
Jason Ekstrand1e059042014-10-16 10:55:19 -05003452 weston_matrix_translate(matrix,
Pekka Paalanen8060d822020-02-06 15:27:54 +02003453 0, surface->width_from_buffer, 0);
Jason Ekstrand1e059042014-10-16 10:55:19 -05003454 break;
3455 case WL_OUTPUT_TRANSFORM_180:
3456 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
3457 weston_matrix_rotate_xy(matrix, -1, 0);
3458 weston_matrix_translate(matrix,
3459 surface->width_from_buffer,
3460 surface->height_from_buffer, 0);
3461 break;
3462 case WL_OUTPUT_TRANSFORM_270:
3463 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
Pekka Paalanen8060d822020-02-06 15:27:54 +02003464 weston_matrix_rotate_xy(matrix, 0, 1);
Jason Ekstrand1e059042014-10-16 10:55:19 -05003465 weston_matrix_translate(matrix,
Pekka Paalanen8060d822020-02-06 15:27:54 +02003466 surface->height_from_buffer, 0, 0);
Jason Ekstrand1e059042014-10-16 10:55:19 -05003467 break;
3468 }
3469
3470 weston_matrix_scale(matrix, vp->buffer.scale, vp->buffer.scale, 1);
3471}
3472
Pekka Paalanend9aae9c2016-04-26 13:46:38 +03003473/**
3474 * Compute a + b > c while being safe to overflows.
3475 */
3476static bool
3477fixed_sum_gt(wl_fixed_t a, wl_fixed_t b, wl_fixed_t c)
3478{
3479 return (int64_t)a + (int64_t)b > (int64_t)c;
3480}
3481
3482static bool
3483weston_surface_is_pending_viewport_source_valid(
3484 const struct weston_surface *surface)
3485{
3486 const struct weston_surface_state *pend = &surface->pending;
3487 const struct weston_buffer_viewport *vp = &pend->buffer_viewport;
3488 int width_from_buffer = 0;
3489 int height_from_buffer = 0;
3490 wl_fixed_t w;
3491 wl_fixed_t h;
3492
3493 /* If viewport source rect is not set, it is always ok. */
3494 if (vp->buffer.src_width == wl_fixed_from_int(-1))
3495 return true;
3496
3497 if (pend->newly_attached) {
3498 if (pend->buffer) {
3499 convert_size_by_transform_scale(&width_from_buffer,
3500 &height_from_buffer,
3501 pend->buffer->width,
3502 pend->buffer->height,
3503 vp->buffer.transform,
3504 vp->buffer.scale);
3505 } else {
3506 /* No buffer: viewport is irrelevant. */
3507 return true;
3508 }
3509 } else {
3510 width_from_buffer = surface->width_from_buffer;
3511 height_from_buffer = surface->height_from_buffer;
3512 }
3513
3514 assert((width_from_buffer == 0) == (height_from_buffer == 0));
3515 assert(width_from_buffer >= 0 && height_from_buffer >= 0);
3516
3517 /* No buffer: viewport is irrelevant. */
3518 if (width_from_buffer == 0 || height_from_buffer == 0)
3519 return true;
3520
3521 /* overflow checks for wl_fixed_from_int() */
3522 if (width_from_buffer > wl_fixed_to_int(INT32_MAX))
3523 return false;
3524 if (height_from_buffer > wl_fixed_to_int(INT32_MAX))
3525 return false;
3526
3527 w = wl_fixed_from_int(width_from_buffer);
3528 h = wl_fixed_from_int(height_from_buffer);
3529
3530 if (fixed_sum_gt(vp->buffer.src_x, vp->buffer.src_width, w))
3531 return false;
3532 if (fixed_sum_gt(vp->buffer.src_y, vp->buffer.src_height, h))
3533 return false;
3534
3535 return true;
3536}
3537
Pekka Paalanenbb32ccc2016-04-26 14:28:28 +03003538static bool
3539fixed_is_integer(wl_fixed_t v)
3540{
3541 return (v & 0xff) == 0;
3542}
3543
3544static bool
3545weston_surface_is_pending_viewport_dst_size_int(
3546 const struct weston_surface *surface)
3547{
3548 const struct weston_buffer_viewport *vp =
3549 &surface->pending.buffer_viewport;
3550
3551 if (vp->surface.width != -1) {
3552 assert(vp->surface.width > 0 && vp->surface.height > 0);
3553 return true;
3554 }
3555
3556 return fixed_is_integer(vp->buffer.src_width) &&
3557 fixed_is_integer(vp->buffer.src_height);
3558}
3559
Derek Foreman152254b2015-11-26 14:17:48 -06003560/* Translate pending damage in buffer co-ordinates to surface
3561 * co-ordinates and union it with a pixman_region32_t.
3562 * This should only be called after the buffer is attached.
3563 */
3564static void
3565apply_damage_buffer(pixman_region32_t *dest,
3566 struct weston_surface *surface,
3567 struct weston_surface_state *state)
3568{
3569 struct weston_buffer *buffer = surface->buffer_ref.buffer;
3570
3571 /* wl_surface.damage_buffer needs to be clipped to the buffer,
3572 * translated into surface co-ordinates and unioned with
3573 * any other surface damage.
3574 * None of this makes sense if there is no buffer though.
3575 */
3576 if (buffer && pixman_region32_not_empty(&state->damage_buffer)) {
3577 pixman_region32_t buffer_damage;
3578
3579 pixman_region32_intersect_rect(&state->damage_buffer,
3580 &state->damage_buffer,
3581 0, 0, buffer->width,
3582 buffer->height);
3583 pixman_region32_init(&buffer_damage);
3584 weston_matrix_transform_region(&buffer_damage,
3585 &surface->buffer_to_surface_matrix,
3586 &state->damage_buffer);
3587 pixman_region32_union(dest, dest, &buffer_damage);
3588 pixman_region32_fini(&buffer_damage);
3589 }
3590 /* We should clear this on commit even if there was no buffer */
3591 pixman_region32_clear(&state->damage_buffer);
3592}
3593
Jason Ekstrand1e059042014-10-16 10:55:19 -05003594static void
Ankit Nautiyal4b6e73d2019-03-26 13:37:12 +05303595weston_surface_set_desired_protection(struct weston_surface *surface,
3596 enum weston_hdcp_protection protection)
3597{
3598 if (surface->desired_protection == protection)
3599 return;
3600 surface->desired_protection = protection;
3601 weston_surface_damage(surface);
3602}
3603
3604static void
Ankit Nautiyal5cfe03c2019-03-28 15:05:42 +05303605weston_surface_set_protection_mode(struct weston_surface *surface,
3606 enum weston_surface_protection_mode p_mode)
3607{
3608 struct content_protection *cp = surface->compositor->content_protection;
3609 struct protected_surface *psurface;
3610
3611 surface->protection_mode = p_mode;
3612 wl_list_for_each(psurface, &cp->protected_list, link) {
3613 if (!psurface || psurface->surface != surface)
3614 continue;
3615 weston_protected_surface_send_event(psurface,
3616 surface->current_protection);
3617 }
3618}
3619
3620static void
Jason Ekstrand7b982072014-05-20 14:33:03 -05003621weston_surface_commit_state(struct weston_surface *surface,
3622 struct weston_surface_state *state)
Pekka Paalanene67858b2013-04-25 13:57:42 +03003623{
Jason Ekstranda7af7042013-10-12 22:38:11 -05003624 struct weston_view *view;
Ander Conselvan de Oliveira5df8eca2012-10-30 17:44:01 +02003625 pixman_region32_t opaque;
3626
Alexander Larsson4ea95522013-05-22 14:41:37 +02003627 /* wl_surface.set_buffer_transform */
Alexander Larsson4ea95522013-05-22 14:41:37 +02003628 /* wl_surface.set_buffer_scale */
Pekka Paalanene95ad5c2016-04-15 14:47:08 +03003629 /* wp_viewport.set_source */
3630 /* wp_viewport.set_destination */
Jason Ekstrand7b982072014-05-20 14:33:03 -05003631 surface->buffer_viewport = state->buffer_viewport;
Alexander Larsson4ea95522013-05-22 14:41:37 +02003632
Pekka Paalanen5df44de2012-10-10 12:49:23 +03003633 /* wl_surface.attach */
Alexandros Frantzisacff29b2018-10-19 12:14:11 +03003634 if (state->newly_attached) {
3635 /* zwp_surface_synchronization_v1.set_acquire_fence */
3636 fd_move(&surface->acquire_fence_fd,
3637 &state->acquire_fence_fd);
Alexandros Frantzis67629672018-10-19 12:14:11 +03003638 /* zwp_surface_synchronization_v1.get_release */
3639 weston_buffer_release_move(&surface->buffer_release_ref,
3640 &state->buffer_release_ref);
Jason Ekstrand7b982072014-05-20 14:33:03 -05003641 weston_surface_attach(surface, state->buffer);
Alexandros Frantzisacff29b2018-10-19 12:14:11 +03003642 }
Jason Ekstrand7b982072014-05-20 14:33:03 -05003643 weston_surface_state_set_buffer(state, NULL);
Alexandros Frantzisacff29b2018-10-19 12:14:11 +03003644 assert(state->acquire_fence_fd == -1);
Alexandros Frantzis67629672018-10-19 12:14:11 +03003645 assert(state->buffer_release_ref.buffer_release == NULL);
Giulio Camuffo184df502013-02-21 11:29:21 +01003646
Jason Ekstrand1e059042014-10-16 10:55:19 -05003647 weston_surface_build_buffer_matrix(surface,
3648 &surface->surface_to_buffer_matrix);
3649 weston_matrix_invert(&surface->buffer_to_surface_matrix,
3650 &surface->surface_to_buffer_matrix);
3651
Jason Ekstrand7b982072014-05-20 14:33:03 -05003652 if (state->newly_attached || state->buffer_viewport.changed) {
George Kiagiadakis8f9e87f2014-06-13 18:14:20 +02003653 weston_surface_update_size(surface);
Quentin Glidic2edc3d52016-08-12 10:41:33 +02003654 if (surface->committed)
3655 surface->committed(surface, state->sx, state->sy);
George Kiagiadakis8f9e87f2014-06-13 18:14:20 +02003656 }
Giulio Camuffo184df502013-02-21 11:29:21 +01003657
Jason Ekstrand7b982072014-05-20 14:33:03 -05003658 state->sx = 0;
3659 state->sy = 0;
3660 state->newly_attached = 0;
3661 state->buffer_viewport.changed = 0;
Pekka Paalanen8e159182012-10-10 12:49:25 +03003662
Derek Foreman152254b2015-11-26 14:17:48 -06003663 /* wl_surface.damage and wl_surface.damage_buffer */
Marius Vlad2a1b7862019-09-05 13:12:18 +03003664 if (pixman_region32_not_empty(&state->damage_surface) ||
3665 pixman_region32_not_empty(&state->damage_buffer))
Marius Vlad3203ff62019-09-05 14:56:12 +03003666 TL_POINT(surface->compositor, "core_commit_damage", TLP_SURFACE(surface), TLP_END);
Derek Foreman152254b2015-11-26 14:17:48 -06003667
Pekka Paalanen8e159182012-10-10 12:49:25 +03003668 pixman_region32_union(&surface->damage, &surface->damage,
Derek Foreman152254b2015-11-26 14:17:48 -06003669 &state->damage_surface);
3670
3671 apply_damage_buffer(&surface->damage, surface, state);
3672
Kristian Høgsberg4d0214c2012-11-08 11:36:02 -05003673 pixman_region32_intersect_rect(&surface->damage, &surface->damage,
Jason Ekstrandef540082014-06-26 10:37:36 -07003674 0, 0, surface->width, surface->height);
Derek Foreman152254b2015-11-26 14:17:48 -06003675 pixman_region32_clear(&state->damage_surface);
Pekka Paalanen512dde82012-10-10 12:49:27 +03003676
3677 /* wl_surface.set_opaque_region */
Jason Ekstrand7b982072014-05-20 14:33:03 -05003678 pixman_region32_init(&opaque);
3679 pixman_region32_intersect_rect(&opaque, &state->opaque,
3680 0, 0, surface->width, surface->height);
Ander Conselvan de Oliveira5df8eca2012-10-30 17:44:01 +02003681
3682 if (!pixman_region32_equal(&opaque, &surface->opaque)) {
3683 pixman_region32_copy(&surface->opaque, &opaque);
Jason Ekstranda7af7042013-10-12 22:38:11 -05003684 wl_list_for_each(view, &surface->views, surface_link)
3685 weston_view_geometry_dirty(view);
Ander Conselvan de Oliveira5df8eca2012-10-30 17:44:01 +02003686 }
3687
3688 pixman_region32_fini(&opaque);
Pekka Paalanen0cbd3b52012-10-10 12:49:28 +03003689
3690 /* wl_surface.set_input_region */
Jason Ekstrand7b982072014-05-20 14:33:03 -05003691 pixman_region32_intersect_rect(&surface->input, &state->input,
3692 0, 0, surface->width, surface->height);
Pekka Paalanen0cbd3b52012-10-10 12:49:28 +03003693
Pekka Paalanenbc106382012-10-10 12:49:31 +03003694 /* wl_surface.frame */
3695 wl_list_insert_list(&surface->frame_callback_list,
Jason Ekstrand7b982072014-05-20 14:33:03 -05003696 &state->frame_callback_list);
3697 wl_list_init(&state->frame_callback_list);
Pekka Paalanen133e4392014-09-23 22:08:46 -04003698
3699 /* XXX:
3700 * What should happen with a feedback request, if there
3701 * is no wl_buffer attached for this commit?
3702 */
3703
3704 /* presentation.feedback */
3705 wl_list_insert_list(&surface->feedback_list,
3706 &state->feedback_list);
3707 wl_list_init(&state->feedback_list);
Jonas Ådahl5d9ca272016-07-22 17:48:03 +08003708
Ankit Nautiyal5cfe03c2019-03-28 15:05:42 +05303709 /* weston_protected_surface.enforced/relaxed */
3710 if (surface->protection_mode != state->protection_mode)
3711 weston_surface_set_protection_mode(surface,
3712 state->protection_mode);
3713
Ankit Nautiyal4b6e73d2019-03-26 13:37:12 +05303714 /* weston_protected_surface.set_type */
3715 weston_surface_set_desired_protection(surface, state->desired_protection);
3716
Jonas Ådahl5d9ca272016-07-22 17:48:03 +08003717 wl_signal_emit(&surface->commit_signal, surface);
Jason Ekstrand7b982072014-05-20 14:33:03 -05003718}
3719
3720static void
3721weston_surface_commit(struct weston_surface *surface)
3722{
3723 weston_surface_commit_state(surface, &surface->pending);
Pekka Paalanenbc106382012-10-10 12:49:31 +03003724
Pekka Paalanene67858b2013-04-25 13:57:42 +03003725 weston_surface_commit_subsurface_order(surface);
3726
Pekka Paalanen0cbd3b52012-10-10 12:49:28 +03003727 weston_surface_schedule_repaint(surface);
Pekka Paalanen5df44de2012-10-10 12:49:23 +03003728}
3729
Ander Conselvan de Oliveira012b4c72012-11-27 17:03:42 +02003730static void
Pekka Paalanene67858b2013-04-25 13:57:42 +03003731weston_subsurface_commit(struct weston_subsurface *sub);
3732
3733static void
3734weston_subsurface_parent_commit(struct weston_subsurface *sub,
3735 int parent_is_synchronized);
3736
3737static void
3738surface_commit(struct wl_client *client, struct wl_resource *resource)
3739{
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -05003740 struct weston_surface *surface = wl_resource_get_user_data(resource);
Pekka Paalanene67858b2013-04-25 13:57:42 +03003741 struct weston_subsurface *sub = weston_surface_to_subsurface(surface);
3742
Pekka Paalanend9aae9c2016-04-26 13:46:38 +03003743 if (!weston_surface_is_pending_viewport_source_valid(surface)) {
3744 assert(surface->viewport_resource);
3745
3746 wl_resource_post_error(surface->viewport_resource,
3747 WP_VIEWPORT_ERROR_OUT_OF_BUFFER,
3748 "wl_surface@%d has viewport source outside buffer",
3749 wl_resource_get_id(resource));
3750 return;
3751 }
3752
Pekka Paalanenbb32ccc2016-04-26 14:28:28 +03003753 if (!weston_surface_is_pending_viewport_dst_size_int(surface)) {
3754 assert(surface->viewport_resource);
3755
3756 wl_resource_post_error(surface->viewport_resource,
3757 WP_VIEWPORT_ERROR_BAD_SIZE,
3758 "wl_surface@%d viewport dst size not integer",
3759 wl_resource_get_id(resource));
3760 return;
3761 }
3762
Alexandros Frantzisacff29b2018-10-19 12:14:11 +03003763 if (surface->pending.acquire_fence_fd >= 0) {
3764 assert(surface->synchronization_resource);
3765
3766 if (!surface->pending.buffer) {
3767 fd_clear(&surface->pending.acquire_fence_fd);
3768 wl_resource_post_error(surface->synchronization_resource,
3769 ZWP_LINUX_SURFACE_SYNCHRONIZATION_V1_ERROR_NO_BUFFER,
3770 "wl_surface@%"PRIu32" no buffer for synchronization",
3771 wl_resource_get_id(resource));
3772 return;
3773 }
3774
3775 /* We support fences for both wp_linux_dmabuf and opaque EGL
3776 * buffers, as mandated by minor version 2 of the
3777 * zwp_linux_explicit_synchronization_v1 protocol. Since
3778 * renderers that support fences currently only support these
3779 * two buffer types plus SHM buffers, we can just check for the
3780 * SHM buffer case here.
3781 */
3782 if (wl_shm_buffer_get(surface->pending.buffer->resource)) {
3783 fd_clear(&surface->pending.acquire_fence_fd);
3784 wl_resource_post_error(surface->synchronization_resource,
3785 ZWP_LINUX_SURFACE_SYNCHRONIZATION_V1_ERROR_UNSUPPORTED_BUFFER,
3786 "wl_surface@%"PRIu32" unsupported buffer for synchronization",
3787 wl_resource_get_id(resource));
3788 return;
3789 }
3790 }
3791
Alexandros Frantzis67629672018-10-19 12:14:11 +03003792 if (surface->pending.buffer_release_ref.buffer_release &&
3793 !surface->pending.buffer) {
3794 assert(surface->synchronization_resource);
3795
3796 wl_resource_post_error(surface->synchronization_resource,
3797 ZWP_LINUX_SURFACE_SYNCHRONIZATION_V1_ERROR_NO_BUFFER,
3798 "wl_surface@%"PRIu32" no buffer for synchronization",
3799 wl_resource_get_id(resource));
3800 return;
3801 }
3802
Pekka Paalanene67858b2013-04-25 13:57:42 +03003803 if (sub) {
3804 weston_subsurface_commit(sub);
3805 return;
3806 }
3807
3808 weston_surface_commit(surface);
3809
3810 wl_list_for_each(sub, &surface->subsurface_list, parent_link) {
3811 if (sub->surface != surface)
3812 weston_subsurface_parent_commit(sub, 0);
3813 }
3814}
3815
3816static void
Ander Conselvan de Oliveira012b4c72012-11-27 17:03:42 +02003817surface_set_buffer_transform(struct wl_client *client,
3818 struct wl_resource *resource, int transform)
3819{
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -05003820 struct weston_surface *surface = wl_resource_get_user_data(resource);
Ander Conselvan de Oliveira012b4c72012-11-27 17:03:42 +02003821
Jonny Lamba55f1392014-05-30 12:07:15 +02003822 /* if wl_output.transform grows more members this will need to be updated. */
3823 if (transform < 0 ||
3824 transform > WL_OUTPUT_TRANSFORM_FLIPPED_270) {
3825 wl_resource_post_error(resource,
3826 WL_SURFACE_ERROR_INVALID_TRANSFORM,
3827 "buffer transform must be a valid transform "
3828 "('%d' specified)", transform);
3829 return;
3830 }
3831
Pekka Paalanen952b6c82014-03-14 14:38:15 +02003832 surface->pending.buffer_viewport.buffer.transform = transform;
George Kiagiadakis8f9e87f2014-06-13 18:14:20 +02003833 surface->pending.buffer_viewport.changed = 1;
Ander Conselvan de Oliveira012b4c72012-11-27 17:03:42 +02003834}
3835
Alexander Larsson4ea95522013-05-22 14:41:37 +02003836static void
3837surface_set_buffer_scale(struct wl_client *client,
3838 struct wl_resource *resource,
Alexander Larssonedddbd12013-05-24 13:09:43 +02003839 int32_t scale)
Alexander Larsson4ea95522013-05-22 14:41:37 +02003840{
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -05003841 struct weston_surface *surface = wl_resource_get_user_data(resource);
Alexander Larsson4ea95522013-05-22 14:41:37 +02003842
Jonny Lamba55f1392014-05-30 12:07:15 +02003843 if (scale < 1) {
3844 wl_resource_post_error(resource,
3845 WL_SURFACE_ERROR_INVALID_SCALE,
3846 "buffer scale must be at least one "
3847 "('%d' specified)", scale);
3848 return;
3849 }
3850
Pekka Paalanen952b6c82014-03-14 14:38:15 +02003851 surface->pending.buffer_viewport.buffer.scale = scale;
George Kiagiadakis8f9e87f2014-06-13 18:14:20 +02003852 surface->pending.buffer_viewport.changed = 1;
Alexander Larsson4ea95522013-05-22 14:41:37 +02003853}
3854
Kristian Høgsberg875ab9e2012-03-30 11:52:39 -04003855static const struct wl_surface_interface surface_interface = {
Kristian Høgsbergd2412e22008-12-15 20:35:24 -05003856 surface_destroy,
3857 surface_attach,
Kristian Høgsberg33418202011-08-16 23:01:28 -04003858 surface_damage,
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05003859 surface_frame,
3860 surface_set_opaque_region,
Pekka Paalanen5df44de2012-10-10 12:49:23 +03003861 surface_set_input_region,
Ander Conselvan de Oliveira012b4c72012-11-27 17:03:42 +02003862 surface_commit,
Alexander Larsson4ea95522013-05-22 14:41:37 +02003863 surface_set_buffer_transform,
Derek Foreman152254b2015-11-26 14:17:48 -06003864 surface_set_buffer_scale,
3865 surface_damage_buffer
Kristian Høgsbergd2412e22008-12-15 20:35:24 -05003866};
3867
3868static void
3869compositor_create_surface(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -04003870 struct wl_resource *resource, uint32_t id)
Kristian Høgsbergd2412e22008-12-15 20:35:24 -05003871{
Kristian Høgsbergc2d70422013-06-25 15:34:33 -04003872 struct weston_compositor *ec = wl_resource_get_user_data(resource);
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05003873 struct weston_surface *surface;
Kristian Høgsbergd2412e22008-12-15 20:35:24 -05003874
Kristian Høgsberg18c93002012-01-27 11:58:31 -05003875 surface = weston_surface_create(ec);
Kristian Høgsberg5fcd0aa2010-08-09 14:43:33 -04003876 if (surface == NULL) {
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -04003877 wl_resource_post_no_memory(resource);
Kristian Høgsbergd2412e22008-12-15 20:35:24 -05003878 return;
Kristian Høgsberg5fcd0aa2010-08-09 14:43:33 -04003879 }
Kristian Høgsbergd2412e22008-12-15 20:35:24 -05003880
Jason Ekstranda85118c2013-06-27 20:17:02 -05003881 surface->resource =
3882 wl_resource_create(client, &wl_surface_interface,
3883 wl_resource_get_version(resource), id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07003884 if (surface->resource == NULL) {
3885 weston_surface_destroy(surface);
3886 wl_resource_post_no_memory(resource);
3887 return;
3888 }
Jason Ekstranda85118c2013-06-27 20:17:02 -05003889 wl_resource_set_implementation(surface->resource, &surface_interface,
3890 surface, destroy_surface);
Kristian Høgsbergf03a04a2014-04-06 22:04:50 -07003891
3892 wl_signal_emit(&ec->create_surface_signal, surface);
Kristian Høgsbergd2412e22008-12-15 20:35:24 -05003893}
3894
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05003895static void
3896destroy_region(struct wl_resource *resource)
3897{
Jason Ekstrand8895efc2013-06-14 10:07:56 -05003898 struct weston_region *region = wl_resource_get_user_data(resource);
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05003899
3900 pixman_region32_fini(&region->region);
3901 free(region);
3902}
3903
3904static void
3905region_destroy(struct wl_client *client, struct wl_resource *resource)
3906{
Kristian Høgsbergeae5de72012-04-11 22:42:15 -04003907 wl_resource_destroy(resource);
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05003908}
3909
3910static void
3911region_add(struct wl_client *client, struct wl_resource *resource,
3912 int32_t x, int32_t y, int32_t width, int32_t height)
3913{
Jason Ekstrand8895efc2013-06-14 10:07:56 -05003914 struct weston_region *region = wl_resource_get_user_data(resource);
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05003915
3916 pixman_region32_union_rect(&region->region, &region->region,
3917 x, y, width, height);
3918}
3919
3920static void
3921region_subtract(struct wl_client *client, struct wl_resource *resource,
3922 int32_t x, int32_t y, int32_t width, int32_t height)
3923{
Jason Ekstrand8895efc2013-06-14 10:07:56 -05003924 struct weston_region *region = wl_resource_get_user_data(resource);
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05003925 pixman_region32_t rect;
3926
3927 pixman_region32_init_rect(&rect, x, y, width, height);
3928 pixman_region32_subtract(&region->region, &region->region, &rect);
3929 pixman_region32_fini(&rect);
3930}
3931
3932static const struct wl_region_interface region_interface = {
3933 region_destroy,
3934 region_add,
3935 region_subtract
3936};
3937
3938static void
3939compositor_create_region(struct wl_client *client,
3940 struct wl_resource *resource, uint32_t id)
3941{
3942 struct weston_region *region;
3943
3944 region = malloc(sizeof *region);
3945 if (region == NULL) {
3946 wl_resource_post_no_memory(resource);
3947 return;
3948 }
3949
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05003950 pixman_region32_init(&region->region);
3951
Jason Ekstranda85118c2013-06-27 20:17:02 -05003952 region->resource =
3953 wl_resource_create(client, &wl_region_interface, 1, id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07003954 if (region->resource == NULL) {
3955 free(region);
3956 wl_resource_post_no_memory(resource);
3957 return;
3958 }
Jason Ekstranda85118c2013-06-27 20:17:02 -05003959 wl_resource_set_implementation(region->resource, &region_interface,
3960 region, destroy_region);
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05003961}
3962
Kristian Høgsberg875ab9e2012-03-30 11:52:39 -04003963static const struct wl_compositor_interface compositor_interface = {
Kristian Høgsbergd2412e22008-12-15 20:35:24 -05003964 compositor_create_surface,
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05003965 compositor_create_region
Kristian Høgsbergd2412e22008-12-15 20:35:24 -05003966};
3967
Tiago Vignatti8e53c7f2012-02-29 19:53:50 +02003968static void
Pekka Paalanene67858b2013-04-25 13:57:42 +03003969weston_subsurface_commit_from_cache(struct weston_subsurface *sub)
3970{
3971 struct weston_surface *surface = sub->surface;
Pekka Paalanene67858b2013-04-25 13:57:42 +03003972
Jason Ekstrand7b982072014-05-20 14:33:03 -05003973 weston_surface_commit_state(surface, &sub->cached);
3974 weston_buffer_reference(&sub->cached_buffer_ref, NULL);
Pekka Paalanene67858b2013-04-25 13:57:42 +03003975
3976 weston_surface_commit_subsurface_order(surface);
3977
3978 weston_surface_schedule_repaint(surface);
3979
Jason Ekstrand7b982072014-05-20 14:33:03 -05003980 sub->has_cached_data = 0;
Pekka Paalanene67858b2013-04-25 13:57:42 +03003981}
3982
3983static void
3984weston_subsurface_commit_to_cache(struct weston_subsurface *sub)
3985{
3986 struct weston_surface *surface = sub->surface;
3987
3988 /*
3989 * If this commit would cause the surface to move by the
3990 * attach(dx, dy) parameters, the old damage region must be
3991 * translated to correspond to the new surface coordinate system
Chris Michael062edf22015-11-26 11:30:00 -05003992 * origin.
Pekka Paalanene67858b2013-04-25 13:57:42 +03003993 */
Derek Foreman152254b2015-11-26 14:17:48 -06003994 pixman_region32_translate(&sub->cached.damage_surface,
Pekka Paalanene67858b2013-04-25 13:57:42 +03003995 -surface->pending.sx, -surface->pending.sy);
Derek Foreman152254b2015-11-26 14:17:48 -06003996 pixman_region32_union(&sub->cached.damage_surface,
3997 &sub->cached.damage_surface,
3998 &surface->pending.damage_surface);
3999 pixman_region32_clear(&surface->pending.damage_surface);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004000
4001 if (surface->pending.newly_attached) {
4002 sub->cached.newly_attached = 1;
Jason Ekstrand7b982072014-05-20 14:33:03 -05004003 weston_surface_state_set_buffer(&sub->cached,
4004 surface->pending.buffer);
4005 weston_buffer_reference(&sub->cached_buffer_ref,
Pekka Paalanene67858b2013-04-25 13:57:42 +03004006 surface->pending.buffer);
Pekka Paalanen133e4392014-09-23 22:08:46 -04004007 weston_presentation_feedback_discard_list(
4008 &sub->cached.feedback_list);
Alexandros Frantzisacff29b2018-10-19 12:14:11 +03004009 /* zwp_surface_synchronization_v1.set_acquire_fence */
4010 fd_move(&sub->cached.acquire_fence_fd,
4011 &surface->pending.acquire_fence_fd);
Alexandros Frantzis67629672018-10-19 12:14:11 +03004012 /* zwp_surface_synchronization_v1.get_release */
4013 weston_buffer_release_move(&sub->cached.buffer_release_ref,
4014 &surface->pending.buffer_release_ref);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004015 }
Ankit Nautiyal4b6e73d2019-03-26 13:37:12 +05304016 sub->cached.desired_protection = surface->pending.desired_protection;
Ankit Nautiyal5cfe03c2019-03-28 15:05:42 +05304017 sub->cached.protection_mode = surface->pending.protection_mode;
Alexandros Frantzisacff29b2018-10-19 12:14:11 +03004018 assert(surface->pending.acquire_fence_fd == -1);
Alexandros Frantzis67629672018-10-19 12:14:11 +03004019 assert(surface->pending.buffer_release_ref.buffer_release == NULL);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004020 sub->cached.sx += surface->pending.sx;
4021 sub->cached.sy += surface->pending.sy;
Pekka Paalanen260ba382014-03-14 14:38:12 +02004022
Derek Foreman152254b2015-11-26 14:17:48 -06004023 apply_damage_buffer(&sub->cached.damage_surface, surface, &surface->pending);
4024
George Kiagiadakis8f9e87f2014-06-13 18:14:20 +02004025 sub->cached.buffer_viewport.changed |=
4026 surface->pending.buffer_viewport.changed;
4027 sub->cached.buffer_viewport.buffer =
4028 surface->pending.buffer_viewport.buffer;
4029 sub->cached.buffer_viewport.surface =
4030 surface->pending.buffer_viewport.surface;
Pekka Paalanene67858b2013-04-25 13:57:42 +03004031
George Kiagiadakis8f9e87f2014-06-13 18:14:20 +02004032 weston_surface_reset_pending_buffer(surface);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004033
4034 pixman_region32_copy(&sub->cached.opaque, &surface->pending.opaque);
4035
4036 pixman_region32_copy(&sub->cached.input, &surface->pending.input);
4037
4038 wl_list_insert_list(&sub->cached.frame_callback_list,
4039 &surface->pending.frame_callback_list);
4040 wl_list_init(&surface->pending.frame_callback_list);
4041
Pekka Paalanen133e4392014-09-23 22:08:46 -04004042 wl_list_insert_list(&sub->cached.feedback_list,
4043 &surface->pending.feedback_list);
4044 wl_list_init(&surface->pending.feedback_list);
4045
Jason Ekstrand7b982072014-05-20 14:33:03 -05004046 sub->has_cached_data = 1;
Pekka Paalanene67858b2013-04-25 13:57:42 +03004047}
4048
Derek Foreman280e7dd2014-10-03 13:13:42 -05004049static bool
Pekka Paalanene67858b2013-04-25 13:57:42 +03004050weston_subsurface_is_synchronized(struct weston_subsurface *sub)
4051{
4052 while (sub) {
4053 if (sub->synchronized)
Derek Foreman280e7dd2014-10-03 13:13:42 -05004054 return true;
Pekka Paalanene67858b2013-04-25 13:57:42 +03004055
4056 if (!sub->parent)
Derek Foreman280e7dd2014-10-03 13:13:42 -05004057 return false;
Pekka Paalanene67858b2013-04-25 13:57:42 +03004058
4059 sub = weston_surface_to_subsurface(sub->parent);
4060 }
4061
Carlos Olmedo Escobar61a9bf52014-11-04 14:38:39 +01004062 return false;
Pekka Paalanene67858b2013-04-25 13:57:42 +03004063}
4064
4065static void
4066weston_subsurface_commit(struct weston_subsurface *sub)
4067{
4068 struct weston_surface *surface = sub->surface;
4069 struct weston_subsurface *tmp;
4070
4071 /* Recursive check for effectively synchronized. */
4072 if (weston_subsurface_is_synchronized(sub)) {
4073 weston_subsurface_commit_to_cache(sub);
4074 } else {
Jason Ekstrand7b982072014-05-20 14:33:03 -05004075 if (sub->has_cached_data) {
Pekka Paalanene67858b2013-04-25 13:57:42 +03004076 /* flush accumulated state from cache */
4077 weston_subsurface_commit_to_cache(sub);
4078 weston_subsurface_commit_from_cache(sub);
4079 } else {
4080 weston_surface_commit(surface);
4081 }
4082
4083 wl_list_for_each(tmp, &surface->subsurface_list, parent_link) {
4084 if (tmp->surface != surface)
4085 weston_subsurface_parent_commit(tmp, 0);
4086 }
4087 }
4088}
4089
4090static void
Pekka Paalanen16abf6a2013-05-17 16:46:05 +03004091weston_subsurface_synchronized_commit(struct weston_subsurface *sub)
Pekka Paalanene67858b2013-04-25 13:57:42 +03004092{
4093 struct weston_surface *surface = sub->surface;
4094 struct weston_subsurface *tmp;
4095
Pekka Paalanene67858b2013-04-25 13:57:42 +03004096 /* From now on, commit_from_cache the whole sub-tree, regardless of
4097 * the synchronized mode of each child. This sub-surface or some
4098 * of its ancestors were synchronized, so we are synchronized
4099 * all the way down.
4100 */
4101
Jason Ekstrand7b982072014-05-20 14:33:03 -05004102 if (sub->has_cached_data)
Pekka Paalanene67858b2013-04-25 13:57:42 +03004103 weston_subsurface_commit_from_cache(sub);
4104
4105 wl_list_for_each(tmp, &surface->subsurface_list, parent_link) {
4106 if (tmp->surface != surface)
4107 weston_subsurface_parent_commit(tmp, 1);
4108 }
4109}
4110
4111static void
Pekka Paalanen16abf6a2013-05-17 16:46:05 +03004112weston_subsurface_parent_commit(struct weston_subsurface *sub,
4113 int parent_is_synchronized)
4114{
Jason Ekstranda7af7042013-10-12 22:38:11 -05004115 struct weston_view *view;
Pekka Paalanen16abf6a2013-05-17 16:46:05 +03004116 if (sub->position.set) {
Jason Ekstranda7af7042013-10-12 22:38:11 -05004117 wl_list_for_each(view, &sub->surface->views, surface_link)
4118 weston_view_set_position(view,
4119 sub->position.x,
4120 sub->position.y);
4121
Pekka Paalanen16abf6a2013-05-17 16:46:05 +03004122 sub->position.set = 0;
4123 }
4124
4125 if (parent_is_synchronized || sub->synchronized)
4126 weston_subsurface_synchronized_commit(sub);
4127}
4128
Pekka Paalanen8274d902014-08-06 19:36:51 +03004129static int
4130subsurface_get_label(struct weston_surface *surface, char *buf, size_t len)
4131{
4132 return snprintf(buf, len, "sub-surface");
4133}
4134
Pekka Paalanen16abf6a2013-05-17 16:46:05 +03004135static void
Quentin Glidic2edc3d52016-08-12 10:41:33 +02004136subsurface_committed(struct weston_surface *surface, int32_t dx, int32_t dy)
Pekka Paalanene67858b2013-04-25 13:57:42 +03004137{
Jason Ekstranda7af7042013-10-12 22:38:11 -05004138 struct weston_view *view;
Pekka Paalanene67858b2013-04-25 13:57:42 +03004139
Jason Ekstranda7af7042013-10-12 22:38:11 -05004140 wl_list_for_each(view, &surface->views, surface_link)
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06004141 weston_view_set_position(view,
4142 view->geometry.x + dx,
4143 view->geometry.y + dy);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004144
4145 /* No need to check parent mappedness, because if parent is not
4146 * mapped, parent is not in a visible layer, so this sub-surface
4147 * will not be drawn either.
4148 */
Armin Krezovićf8486c32016-06-30 06:04:28 +02004149
Pekka Paalanene67858b2013-04-25 13:57:42 +03004150 if (!weston_surface_is_mapped(surface)) {
Armin Krezovićf8486c32016-06-30 06:04:28 +02004151 surface->is_mapped = true;
Pekka Paalaneneb3cf222014-06-30 11:52:07 +03004152
Derek Foreman4b1a0a12014-09-10 15:37:33 -05004153 /* Cannot call weston_view_update_transform(),
Pekka Paalanene67858b2013-04-25 13:57:42 +03004154 * because that would call it also for the parent surface,
4155 * which might not be mapped yet. That would lead to
4156 * inconsistent state, where the window could never be
4157 * mapped.
4158 *
Armin Krezovićf8486c32016-06-30 06:04:28 +02004159 * Instead just force the is_mapped flag on, to make
Pekka Paalanene67858b2013-04-25 13:57:42 +03004160 * weston_surface_is_mapped() return true, so that when the
4161 * parent surface does get mapped, this one will get
Pekka Paalaneneb3cf222014-06-30 11:52:07 +03004162 * included, too. See view_list_add().
Pekka Paalanene67858b2013-04-25 13:57:42 +03004163 */
Pekka Paalanene67858b2013-04-25 13:57:42 +03004164 }
4165}
4166
4167static struct weston_subsurface *
4168weston_surface_to_subsurface(struct weston_surface *surface)
4169{
Quentin Glidic2edc3d52016-08-12 10:41:33 +02004170 if (surface->committed == subsurface_committed)
4171 return surface->committed_private;
Pekka Paalanene67858b2013-04-25 13:57:42 +03004172
4173 return NULL;
4174}
4175
Pekka Paalanen01388e22013-04-25 13:57:44 +03004176WL_EXPORT struct weston_surface *
4177weston_surface_get_main_surface(struct weston_surface *surface)
4178{
4179 struct weston_subsurface *sub;
4180
4181 while (surface && (sub = weston_surface_to_subsurface(surface)))
4182 surface = sub->parent;
4183
4184 return surface;
4185}
4186
Pekka Paalanen50b67472014-10-01 15:02:41 +03004187WL_EXPORT int
4188weston_surface_set_role(struct weston_surface *surface,
4189 const char *role_name,
4190 struct wl_resource *error_resource,
4191 uint32_t error_code)
4192{
4193 assert(role_name);
4194
4195 if (surface->role_name == NULL ||
4196 surface->role_name == role_name ||
4197 strcmp(surface->role_name, role_name) == 0) {
4198 surface->role_name = role_name;
4199
4200 return 0;
4201 }
4202
4203 wl_resource_post_error(error_resource, error_code,
4204 "Cannot assign role %s to wl_surface@%d,"
4205 " already has role %s\n",
4206 role_name,
4207 wl_resource_get_id(surface->resource),
4208 surface->role_name);
4209 return -1;
4210}
4211
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +02004212WL_EXPORT const char *
4213weston_surface_get_role(struct weston_surface *surface)
4214{
4215 return surface->role_name;
4216}
4217
Pekka Paalanen8274d902014-08-06 19:36:51 +03004218WL_EXPORT void
4219weston_surface_set_label_func(struct weston_surface *surface,
4220 int (*desc)(struct weston_surface *,
4221 char *, size_t))
4222{
4223 surface->get_label = desc;
Marius Vlad5de92972019-10-15 13:25:41 +03004224 weston_timeline_refresh_subscription_objects(surface->compositor,
4225 surface);
Pekka Paalanen8274d902014-08-06 19:36:51 +03004226}
4227
Pekka Paalanenc647ed72015-02-09 13:16:57 +02004228/** Get the size of surface contents
4229 *
4230 * \param surface The surface to query.
4231 * \param width Returns the width of raw contents.
4232 * \param height Returns the height of raw contents.
4233 *
4234 * Retrieves the raw surface content size in pixels for the given surface.
4235 * This is the whole content size in buffer pixels. If the surface
4236 * has no content or the renderer does not implement this feature,
4237 * zeroes are returned.
4238 *
4239 * This function is used to determine the buffer size needed for
4240 * a weston_surface_copy_content() call.
4241 */
4242WL_EXPORT void
4243weston_surface_get_content_size(struct weston_surface *surface,
4244 int *width, int *height)
4245{
4246 struct weston_renderer *rer = surface->compositor->renderer;
4247
4248 if (!rer->surface_get_content_size) {
4249 *width = 0;
4250 *height = 0;
4251 return;
4252 }
4253
4254 rer->surface_get_content_size(surface, width, height);
4255}
4256
Quentin Glidic248dd102016-08-12 10:41:34 +02004257/** Get the bounding box of a surface and its subsurfaces
4258 *
4259 * \param surface The surface to query.
4260 * \return The bounding box relative to the surface origin.
4261 *
4262 */
4263WL_EXPORT struct weston_geometry
4264weston_surface_get_bounding_box(struct weston_surface *surface)
4265{
4266 pixman_region32_t region;
4267 pixman_box32_t *box;
4268 struct weston_subsurface *subsurface;
4269
4270 pixman_region32_init_rect(&region,
4271 0, 0,
4272 surface->width, surface->height);
4273
4274 wl_list_for_each(subsurface, &surface->subsurface_list, parent_link)
4275 pixman_region32_union_rect(&region, &region,
4276 subsurface->position.x,
4277 subsurface->position.y,
4278 subsurface->surface->width,
4279 subsurface->surface->height);
4280
4281 box = pixman_region32_extents(&region);
4282 struct weston_geometry geometry = {
4283 .x = box->x1,
4284 .y = box->y1,
4285 .width = box->x2 - box->x1,
4286 .height = box->y2 - box->y1,
4287 };
4288
4289 pixman_region32_fini(&region);
4290
4291 return geometry;
4292}
4293
Pekka Paalanenc647ed72015-02-09 13:16:57 +02004294/** Copy surface contents to system memory.
4295 *
4296 * \param surface The surface to copy from.
4297 * \param target Pointer to the target memory buffer.
4298 * \param size Size of the target buffer in bytes.
4299 * \param src_x X location on contents to copy from.
4300 * \param src_y Y location on contents to copy from.
4301 * \param width Width in pixels of the area to copy.
4302 * \param height Height in pixels of the area to copy.
4303 * \return 0 for success, -1 for failure.
4304 *
4305 * Surface contents are maintained by the renderer. They can be in a
4306 * reserved weston_buffer or as a copy, e.g. a GL texture, or something
4307 * else.
4308 *
4309 * Surface contents are copied into memory pointed to by target,
4310 * which has size bytes of space available. The target memory
4311 * may be larger than needed, but being smaller returns an error.
4312 * The extra bytes in target may or may not be written; their content is
4313 * unspecified. Size must be large enough to hold the image.
4314 *
4315 * The image in the target memory will be arranged in rows from
4316 * top to bottom, and pixels on a row from left to right. The pixel
4317 * format is PIXMAN_a8b8g8r8, 4 bytes per pixel, and stride is exactly
4318 * width * 4.
4319 *
4320 * Parameters src_x and src_y define the upper-left corner in buffer
4321 * coordinates (pixels) to copy from. Parameters width and height
4322 * define the size of the area to copy in pixels.
4323 *
4324 * The rectangle defined by src_x, src_y, width, height must fit in
4325 * the surface contents. Otherwise an error is returned.
4326 *
Changwoo Chof97d2502017-08-05 00:30:47 +09004327 * Use weston_surface_get_content_size to determine the content size; the
Pekka Paalanenc647ed72015-02-09 13:16:57 +02004328 * needed target buffer size and rectangle limits.
4329 *
4330 * CURRENT IMPLEMENTATION RESTRICTIONS:
4331 * - the machine must be little-endian due to Pixman formats.
4332 *
4333 * NOTE: Pixman formats are premultiplied.
4334 */
4335WL_EXPORT int
4336weston_surface_copy_content(struct weston_surface *surface,
4337 void *target, size_t size,
4338 int src_x, int src_y,
4339 int width, int height)
4340{
4341 struct weston_renderer *rer = surface->compositor->renderer;
4342 int cw, ch;
4343 const size_t bytespp = 4; /* PIXMAN_a8b8g8r8 */
4344
4345 if (!rer->surface_copy_content)
4346 return -1;
4347
4348 weston_surface_get_content_size(surface, &cw, &ch);
4349
4350 if (src_x < 0 || src_y < 0)
4351 return -1;
4352
4353 if (width <= 0 || height <= 0)
4354 return -1;
4355
4356 if (src_x + width > cw || src_y + height > ch)
4357 return -1;
4358
4359 if (width * bytespp * height > size)
4360 return -1;
4361
4362 return rer->surface_copy_content(surface, target, size,
4363 src_x, src_y, width, height);
4364}
4365
Pekka Paalanene67858b2013-04-25 13:57:42 +03004366static void
4367subsurface_set_position(struct wl_client *client,
4368 struct wl_resource *resource, int32_t x, int32_t y)
4369{
Jason Ekstrand0bd587e2013-06-14 10:08:02 -05004370 struct weston_subsurface *sub = wl_resource_get_user_data(resource);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004371
4372 if (!sub)
4373 return;
4374
4375 sub->position.x = x;
4376 sub->position.y = y;
4377 sub->position.set = 1;
4378}
4379
4380static struct weston_subsurface *
Arnaud Vracb8c16c92016-06-08 18:37:57 +02004381subsurface_find_sibling(struct weston_subsurface *sub,
4382 struct weston_surface *surface)
Pekka Paalanene67858b2013-04-25 13:57:42 +03004383{
Arnaud Vracb8c16c92016-06-08 18:37:57 +02004384 struct weston_surface *parent = sub->parent;
4385 struct weston_subsurface *sibling;
Pekka Paalanene67858b2013-04-25 13:57:42 +03004386
Arnaud Vracb8c16c92016-06-08 18:37:57 +02004387 wl_list_for_each(sibling, &parent->subsurface_list, parent_link) {
4388 if (sibling->surface == surface && sibling != sub)
4389 return sibling;
4390 }
Pekka Paalanene67858b2013-04-25 13:57:42 +03004391
4392 return NULL;
4393}
4394
4395static struct weston_subsurface *
4396subsurface_sibling_check(struct weston_subsurface *sub,
4397 struct weston_surface *surface,
4398 const char *request)
4399{
4400 struct weston_subsurface *sibling;
4401
Arnaud Vracb8c16c92016-06-08 18:37:57 +02004402 sibling = subsurface_find_sibling(sub, surface);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004403 if (!sibling) {
4404 wl_resource_post_error(sub->resource,
4405 WL_SUBSURFACE_ERROR_BAD_SURFACE,
4406 "%s: wl_surface@%d is not a parent or sibling",
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05004407 request, wl_resource_get_id(surface->resource));
Pekka Paalanene67858b2013-04-25 13:57:42 +03004408 return NULL;
4409 }
4410
Arnaud Vracb8c16c92016-06-08 18:37:57 +02004411 assert(sibling->parent == sub->parent);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004412
4413 return sibling;
4414}
4415
4416static void
4417subsurface_place_above(struct wl_client *client,
4418 struct wl_resource *resource,
4419 struct wl_resource *sibling_resource)
4420{
Jason Ekstrand0bd587e2013-06-14 10:08:02 -05004421 struct weston_subsurface *sub = wl_resource_get_user_data(resource);
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -05004422 struct weston_surface *surface =
4423 wl_resource_get_user_data(sibling_resource);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004424 struct weston_subsurface *sibling;
4425
4426 if (!sub)
4427 return;
4428
4429 sibling = subsurface_sibling_check(sub, surface, "place_above");
4430 if (!sibling)
4431 return;
4432
4433 wl_list_remove(&sub->parent_link_pending);
4434 wl_list_insert(sibling->parent_link_pending.prev,
4435 &sub->parent_link_pending);
Emilio Pozuelo Monfort4f3cad72017-01-27 17:30:29 +01004436
4437 sub->reordered = true;
Pekka Paalanene67858b2013-04-25 13:57:42 +03004438}
4439
4440static void
4441subsurface_place_below(struct wl_client *client,
4442 struct wl_resource *resource,
4443 struct wl_resource *sibling_resource)
4444{
Jason Ekstrand0bd587e2013-06-14 10:08:02 -05004445 struct weston_subsurface *sub = wl_resource_get_user_data(resource);
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -05004446 struct weston_surface *surface =
4447 wl_resource_get_user_data(sibling_resource);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004448 struct weston_subsurface *sibling;
4449
4450 if (!sub)
4451 return;
4452
4453 sibling = subsurface_sibling_check(sub, surface, "place_below");
4454 if (!sibling)
4455 return;
4456
4457 wl_list_remove(&sub->parent_link_pending);
4458 wl_list_insert(&sibling->parent_link_pending,
4459 &sub->parent_link_pending);
Emilio Pozuelo Monfort4f3cad72017-01-27 17:30:29 +01004460
4461 sub->reordered = true;
Pekka Paalanene67858b2013-04-25 13:57:42 +03004462}
4463
4464static void
4465subsurface_set_sync(struct wl_client *client, struct wl_resource *resource)
4466{
Jason Ekstrand0bd587e2013-06-14 10:08:02 -05004467 struct weston_subsurface *sub = wl_resource_get_user_data(resource);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004468
4469 if (sub)
4470 sub->synchronized = 1;
4471}
4472
4473static void
4474subsurface_set_desync(struct wl_client *client, struct wl_resource *resource)
4475{
Jason Ekstrand0bd587e2013-06-14 10:08:02 -05004476 struct weston_subsurface *sub = wl_resource_get_user_data(resource);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004477
Pekka Paalanen16abf6a2013-05-17 16:46:05 +03004478 if (sub && sub->synchronized) {
Pekka Paalanene67858b2013-04-25 13:57:42 +03004479 sub->synchronized = 0;
Pekka Paalanen16abf6a2013-05-17 16:46:05 +03004480
4481 /* If sub became effectively desynchronized, flush. */
4482 if (!weston_subsurface_is_synchronized(sub))
4483 weston_subsurface_synchronized_commit(sub);
4484 }
Pekka Paalanene67858b2013-04-25 13:57:42 +03004485}
4486
4487static void
Pekka Paalanene67858b2013-04-25 13:57:42 +03004488weston_subsurface_unlink_parent(struct weston_subsurface *sub)
4489{
4490 wl_list_remove(&sub->parent_link);
4491 wl_list_remove(&sub->parent_link_pending);
4492 wl_list_remove(&sub->parent_destroy_listener.link);
4493 sub->parent = NULL;
4494}
4495
4496static void
4497weston_subsurface_destroy(struct weston_subsurface *sub);
4498
4499static void
4500subsurface_handle_surface_destroy(struct wl_listener *listener, void *data)
4501{
4502 struct weston_subsurface *sub =
4503 container_of(listener, struct weston_subsurface,
4504 surface_destroy_listener);
Pekka Paalanenca790762015-04-17 14:23:38 +03004505 assert(data == sub->surface);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004506
4507 /* The protocol object (wl_resource) is left inert. */
4508 if (sub->resource)
Jason Ekstrand0bd587e2013-06-14 10:08:02 -05004509 wl_resource_set_user_data(sub->resource, NULL);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004510
4511 weston_subsurface_destroy(sub);
4512}
4513
4514static void
4515subsurface_handle_parent_destroy(struct wl_listener *listener, void *data)
4516{
4517 struct weston_subsurface *sub =
4518 container_of(listener, struct weston_subsurface,
4519 parent_destroy_listener);
Pekka Paalanenca790762015-04-17 14:23:38 +03004520 assert(data == sub->parent);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004521 assert(sub->surface != sub->parent);
4522
4523 if (weston_surface_is_mapped(sub->surface))
4524 weston_surface_unmap(sub->surface);
4525
4526 weston_subsurface_unlink_parent(sub);
4527}
4528
4529static void
4530subsurface_resource_destroy(struct wl_resource *resource)
4531{
Jason Ekstrand0bd587e2013-06-14 10:08:02 -05004532 struct weston_subsurface *sub = wl_resource_get_user_data(resource);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004533
4534 if (sub)
4535 weston_subsurface_destroy(sub);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004536}
4537
4538static void
4539subsurface_destroy(struct wl_client *client, struct wl_resource *resource)
4540{
4541 wl_resource_destroy(resource);
4542}
4543
4544static void
4545weston_subsurface_link_parent(struct weston_subsurface *sub,
4546 struct weston_surface *parent)
4547{
4548 sub->parent = parent;
4549 sub->parent_destroy_listener.notify = subsurface_handle_parent_destroy;
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05004550 wl_signal_add(&parent->destroy_signal,
Pekka Paalanene67858b2013-04-25 13:57:42 +03004551 &sub->parent_destroy_listener);
4552
4553 wl_list_insert(&parent->subsurface_list, &sub->parent_link);
4554 wl_list_insert(&parent->subsurface_list_pending,
4555 &sub->parent_link_pending);
4556}
4557
4558static void
4559weston_subsurface_link_surface(struct weston_subsurface *sub,
4560 struct weston_surface *surface)
4561{
4562 sub->surface = surface;
4563 sub->surface_destroy_listener.notify =
4564 subsurface_handle_surface_destroy;
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05004565 wl_signal_add(&surface->destroy_signal,
Pekka Paalanene67858b2013-04-25 13:57:42 +03004566 &sub->surface_destroy_listener);
4567}
4568
4569static void
4570weston_subsurface_destroy(struct weston_subsurface *sub)
4571{
Jason Ekstranda7af7042013-10-12 22:38:11 -05004572 struct weston_view *view, *next;
4573
Pekka Paalanene67858b2013-04-25 13:57:42 +03004574 assert(sub->surface);
4575
4576 if (sub->resource) {
4577 assert(weston_surface_to_subsurface(sub->surface) == sub);
4578 assert(sub->parent_destroy_listener.notify ==
4579 subsurface_handle_parent_destroy);
4580
George Kiagiadakised04d382014-06-13 18:10:26 +02004581 wl_list_for_each_safe(view, next, &sub->surface->views, surface_link) {
4582 weston_view_unmap(view);
Jason Ekstranda7af7042013-10-12 22:38:11 -05004583 weston_view_destroy(view);
George Kiagiadakised04d382014-06-13 18:10:26 +02004584 }
Jason Ekstranda7af7042013-10-12 22:38:11 -05004585
Pekka Paalanene67858b2013-04-25 13:57:42 +03004586 if (sub->parent)
4587 weston_subsurface_unlink_parent(sub);
4588
Jason Ekstrand7b982072014-05-20 14:33:03 -05004589 weston_surface_state_fini(&sub->cached);
4590 weston_buffer_reference(&sub->cached_buffer_ref, NULL);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004591
Quentin Glidic2edc3d52016-08-12 10:41:33 +02004592 sub->surface->committed = NULL;
4593 sub->surface->committed_private = NULL;
Pekka Paalanen8274d902014-08-06 19:36:51 +03004594 weston_surface_set_label_func(sub->surface, NULL);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004595 } else {
4596 /* the dummy weston_subsurface for the parent itself */
4597 assert(sub->parent_destroy_listener.notify == NULL);
4598 wl_list_remove(&sub->parent_link);
4599 wl_list_remove(&sub->parent_link_pending);
4600 }
4601
4602 wl_list_remove(&sub->surface_destroy_listener.link);
4603 free(sub);
4604}
4605
4606static const struct wl_subsurface_interface subsurface_implementation = {
4607 subsurface_destroy,
4608 subsurface_set_position,
4609 subsurface_place_above,
4610 subsurface_place_below,
4611 subsurface_set_sync,
4612 subsurface_set_desync
4613};
4614
4615static struct weston_subsurface *
4616weston_subsurface_create(uint32_t id, struct weston_surface *surface,
4617 struct weston_surface *parent)
4618{
4619 struct weston_subsurface *sub;
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05004620 struct wl_client *client = wl_resource_get_client(surface->resource);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004621
Bryce Harringtonde16d892014-11-20 22:21:57 -08004622 sub = zalloc(sizeof *sub);
4623 if (sub == NULL)
Pekka Paalanene67858b2013-04-25 13:57:42 +03004624 return NULL;
4625
Jason Ekstranda7af7042013-10-12 22:38:11 -05004626 wl_list_init(&sub->unused_views);
4627
Jason Ekstranda85118c2013-06-27 20:17:02 -05004628 sub->resource =
4629 wl_resource_create(client, &wl_subsurface_interface, 1, id);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004630 if (!sub->resource) {
4631 free(sub);
4632 return NULL;
4633 }
4634
Jason Ekstranda85118c2013-06-27 20:17:02 -05004635 wl_resource_set_implementation(sub->resource,
4636 &subsurface_implementation,
4637 sub, subsurface_resource_destroy);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004638 weston_subsurface_link_surface(sub, surface);
4639 weston_subsurface_link_parent(sub, parent);
Jason Ekstrand7b982072014-05-20 14:33:03 -05004640 weston_surface_state_init(&sub->cached);
4641 sub->cached_buffer_ref.buffer = NULL;
Pekka Paalanene67858b2013-04-25 13:57:42 +03004642 sub->synchronized = 1;
Pekka Paalanene67858b2013-04-25 13:57:42 +03004643
4644 return sub;
4645}
4646
4647/* Create a dummy subsurface for having the parent itself in its
4648 * sub-surface lists. Makes stacking order manipulation easy.
4649 */
4650static struct weston_subsurface *
4651weston_subsurface_create_for_parent(struct weston_surface *parent)
4652{
4653 struct weston_subsurface *sub;
4654
Bryce Harringtonde16d892014-11-20 22:21:57 -08004655 sub = zalloc(sizeof *sub);
4656 if (sub == NULL)
Pekka Paalanene67858b2013-04-25 13:57:42 +03004657 return NULL;
4658
4659 weston_subsurface_link_surface(sub, parent);
4660 sub->parent = parent;
4661 wl_list_insert(&parent->subsurface_list, &sub->parent_link);
4662 wl_list_insert(&parent->subsurface_list_pending,
4663 &sub->parent_link_pending);
4664
4665 return sub;
4666}
4667
4668static void
4669subcompositor_get_subsurface(struct wl_client *client,
4670 struct wl_resource *resource,
4671 uint32_t id,
4672 struct wl_resource *surface_resource,
4673 struct wl_resource *parent_resource)
4674{
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -05004675 struct weston_surface *surface =
4676 wl_resource_get_user_data(surface_resource);
4677 struct weston_surface *parent =
4678 wl_resource_get_user_data(parent_resource);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004679 struct weston_subsurface *sub;
4680 static const char where[] = "get_subsurface: wl_subsurface@";
4681
4682 if (surface == parent) {
4683 wl_resource_post_error(resource,
4684 WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
4685 "%s%d: wl_surface@%d cannot be its own parent",
Jason Ekstrand0bd587e2013-06-14 10:08:02 -05004686 where, id, wl_resource_get_id(surface_resource));
Pekka Paalanene67858b2013-04-25 13:57:42 +03004687 return;
4688 }
4689
4690 if (weston_surface_to_subsurface(surface)) {
4691 wl_resource_post_error(resource,
4692 WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
4693 "%s%d: wl_surface@%d is already a sub-surface",
Jason Ekstrand0bd587e2013-06-14 10:08:02 -05004694 where, id, wl_resource_get_id(surface_resource));
Pekka Paalanene67858b2013-04-25 13:57:42 +03004695 return;
4696 }
4697
Pekka Paalanen50b67472014-10-01 15:02:41 +03004698 if (weston_surface_set_role(surface, "wl_subsurface", resource,
4699 WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE) < 0)
Pekka Paalanene67858b2013-04-25 13:57:42 +03004700 return;
Pekka Paalanene67858b2013-04-25 13:57:42 +03004701
Pekka Paalanen86c8ca02013-05-17 16:46:07 +03004702 if (weston_surface_get_main_surface(parent) == surface) {
4703 wl_resource_post_error(resource,
4704 WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
4705 "%s%d: wl_surface@%d is an ancestor of parent",
Jason Ekstrand0bd587e2013-06-14 10:08:02 -05004706 where, id, wl_resource_get_id(surface_resource));
Pekka Paalanen86c8ca02013-05-17 16:46:07 +03004707 return;
4708 }
4709
Pekka Paalanene67858b2013-04-25 13:57:42 +03004710 /* make sure the parent is in its own list */
4711 if (wl_list_empty(&parent->subsurface_list)) {
4712 if (!weston_subsurface_create_for_parent(parent)) {
4713 wl_resource_post_no_memory(resource);
4714 return;
4715 }
4716 }
4717
4718 sub = weston_subsurface_create(id, surface, parent);
4719 if (!sub) {
4720 wl_resource_post_no_memory(resource);
4721 return;
4722 }
4723
Quentin Glidic2edc3d52016-08-12 10:41:33 +02004724 surface->committed = subsurface_committed;
4725 surface->committed_private = sub;
Pekka Paalanen8274d902014-08-06 19:36:51 +03004726 weston_surface_set_label_func(surface, subsurface_get_label);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004727}
4728
4729static void
4730subcompositor_destroy(struct wl_client *client, struct wl_resource *resource)
4731{
4732 wl_resource_destroy(resource);
4733}
4734
4735static const struct wl_subcompositor_interface subcompositor_interface = {
4736 subcompositor_destroy,
4737 subcompositor_get_subsurface
4738};
4739
4740static void
4741bind_subcompositor(struct wl_client *client,
4742 void *data, uint32_t version, uint32_t id)
4743{
4744 struct weston_compositor *compositor = data;
Jason Ekstranda85118c2013-06-27 20:17:02 -05004745 struct wl_resource *resource;
Pekka Paalanene67858b2013-04-25 13:57:42 +03004746
Jason Ekstranda85118c2013-06-27 20:17:02 -05004747 resource =
4748 wl_resource_create(client, &wl_subcompositor_interface, 1, id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07004749 if (resource == NULL) {
4750 wl_client_post_no_memory(client);
4751 return;
4752 }
4753 wl_resource_set_implementation(resource, &subcompositor_interface,
4754 compositor, NULL);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004755}
4756
Bryce Harrington0795ece2016-08-30 12:04:26 -07004757/** Set a DPMS mode on all of the compositor's outputs
Bryce Harringtonc9626a32015-12-11 13:11:38 -08004758 *
4759 * \param compositor The compositor instance
4760 * \param state The DPMS state the outputs will be set to
4761 */
Pekka Paalanene67858b2013-04-25 13:57:42 +03004762static void
Ander Conselvan de Oliveira87524b62013-02-21 18:35:22 +02004763weston_compositor_dpms(struct weston_compositor *compositor,
4764 enum dpms_enum state)
Tiago Vignatti8e53c7f2012-02-29 19:53:50 +02004765{
4766 struct weston_output *output;
4767
Bryce Harrington08976ac2016-08-30 12:05:16 -07004768 wl_list_for_each(output, &compositor->output_list, link)
4769 if (output->set_dpms)
4770 output->set_dpms(output, state);
Tiago Vignatti8e53c7f2012-02-29 19:53:50 +02004771}
4772
Bryce Harringtonc9626a32015-12-11 13:11:38 -08004773/** Restores the compositor to active status
4774 *
4775 * \param compositor The compositor instance
4776 *
4777 * If the compositor was in a sleeping mode, all outputs are powered
4778 * back on via DPMS. Otherwise if the compositor was inactive
4779 * (idle/locked, offscreen, or sleeping) then the compositor's wake
4780 * signal will fire.
4781 *
4782 * Restarts the idle timer.
Marius Vlad9fdda7f2019-06-11 16:08:55 +03004783 * \ingroup compositor
Bryce Harringtonc9626a32015-12-11 13:11:38 -08004784 */
Kristian Høgsbergaf867cc2011-11-15 13:34:49 +02004785WL_EXPORT void
Ander Conselvan de Oliveira87524b62013-02-21 18:35:22 +02004786weston_compositor_wake(struct weston_compositor *compositor)
Kristian Høgsbergaf867cc2011-11-15 13:34:49 +02004787{
Neil Roberts8b62e202013-09-30 13:14:47 +01004788 uint32_t old_state = compositor->state;
4789
4790 /* The state needs to be changed before emitting the wake
4791 * signal because that may try to schedule a repaint which
4792 * will not work if the compositor is still sleeping */
4793 compositor->state = WESTON_COMPOSITOR_ACTIVE;
4794
4795 switch (old_state) {
Ander Conselvan de Oliveira87524b62013-02-21 18:35:22 +02004796 case WESTON_COMPOSITOR_SLEEPING:
Ander Conselvan de Oliveira87524b62013-02-21 18:35:22 +02004797 case WESTON_COMPOSITOR_IDLE:
Philipp Brüschweiler57edf7f2013-03-29 13:01:56 +01004798 case WESTON_COMPOSITOR_OFFSCREEN:
Daniel Stone893b9362016-11-08 15:47:09 +00004799 weston_compositor_dpms(compositor, WESTON_DPMS_ON);
Ander Conselvan de Oliveiraa4575632013-02-21 18:35:23 +02004800 wl_signal_emit(&compositor->wake_signal, compositor);
Ander Conselvan de Oliveira87524b62013-02-21 18:35:22 +02004801 /* fall through */
4802 default:
Ander Conselvan de Oliveira87524b62013-02-21 18:35:22 +02004803 wl_event_source_timer_update(compositor->idle_source,
4804 compositor->idle_time * 1000);
Kristian Høgsbergaf867cc2011-11-15 13:34:49 +02004805 }
4806}
4807
Bryce Harringtonc9626a32015-12-11 13:11:38 -08004808/** Turns off rendering and frame events for the compositor.
4809 *
4810 * \param compositor The compositor instance
4811 *
4812 * This is used for example to prevent further rendering while the
4813 * compositor is shutting down.
4814 *
Bryce Harringtonc9626a32015-12-11 13:11:38 -08004815 * Stops the idle timer.
Marius Vlad9fdda7f2019-06-11 16:08:55 +03004816 *
4817 * \ingroup compositor
Bryce Harringtonc9626a32015-12-11 13:11:38 -08004818 */
Ander Conselvan de Oliveira87524b62013-02-21 18:35:22 +02004819WL_EXPORT void
Philipp Brüschweiler57edf7f2013-03-29 13:01:56 +01004820weston_compositor_offscreen(struct weston_compositor *compositor)
4821{
4822 switch (compositor->state) {
4823 case WESTON_COMPOSITOR_OFFSCREEN:
4824 return;
4825 case WESTON_COMPOSITOR_SLEEPING:
Philipp Brüschweiler57edf7f2013-03-29 13:01:56 +01004826 default:
4827 compositor->state = WESTON_COMPOSITOR_OFFSCREEN;
4828 wl_event_source_timer_update(compositor->idle_source, 0);
4829 }
4830}
4831
Bryce Harringtonc9626a32015-12-11 13:11:38 -08004832/** Powers down all attached output devices
4833 *
4834 * \param compositor The compositor instance
4835 *
4836 * Causes rendering to the outputs to cease, and no frame events to be
4837 * sent. Only powers down the outputs if the compositor is not already
4838 * in sleep mode.
4839 *
4840 * Stops the idle timer.
Marius Vlad9fdda7f2019-06-11 16:08:55 +03004841 *
4842 * \ingroup compositor
Bryce Harringtonc9626a32015-12-11 13:11:38 -08004843 */
Philipp Brüschweiler57edf7f2013-03-29 13:01:56 +01004844WL_EXPORT void
Ander Conselvan de Oliveira87524b62013-02-21 18:35:22 +02004845weston_compositor_sleep(struct weston_compositor *compositor)
4846{
4847 if (compositor->state == WESTON_COMPOSITOR_SLEEPING)
4848 return;
4849
Philipp Brüschweiler57edf7f2013-03-29 13:01:56 +01004850 wl_event_source_timer_update(compositor->idle_source, 0);
Ander Conselvan de Oliveira87524b62013-02-21 18:35:22 +02004851 compositor->state = WESTON_COMPOSITOR_SLEEPING;
4852 weston_compositor_dpms(compositor, WESTON_DPMS_OFF);
4853}
4854
Bryce Harringtonc9626a32015-12-11 13:11:38 -08004855/** Sets compositor to idle mode
4856 *
4857 * \param data The compositor instance
4858 *
4859 * This is called when the idle timer fires. Once the compositor is in
4860 * idle mode it requires a wake action (e.g. via
4861 * weston_compositor_wake()) to restore it. The compositor's
4862 * idle_signal will be triggered when the idle event occurs.
4863 *
4864 * Idleness can be inhibited by setting the compositor's idle_inhibit
4865 * property.
4866 */
Kristian Høgsberge10a5d92011-04-22 14:01:18 -04004867static int
4868idle_handler(void *data)
4869{
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05004870 struct weston_compositor *compositor = data;
Kristian Høgsberge10a5d92011-04-22 14:01:18 -04004871
4872 if (compositor->idle_inhibit)
4873 return 1;
4874
Ander Conselvan de Oliveira19d10ef2013-02-21 18:35:20 +02004875 compositor->state = WESTON_COMPOSITOR_IDLE;
Ander Conselvan de Oliveiraa4575632013-02-21 18:35:23 +02004876 wl_signal_emit(&compositor->idle_signal, compositor);
Kristian Høgsberge10a5d92011-04-22 14:01:18 -04004877
4878 return 1;
4879}
4880
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04004881WL_EXPORT void
Xiong Zhang97116532013-10-23 13:58:31 +08004882weston_plane_init(struct weston_plane *plane,
4883 struct weston_compositor *ec,
4884 int32_t x, int32_t y)
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04004885{
4886 pixman_region32_init(&plane->damage);
Ander Conselvan de Oliveirae1bd5a02013-03-05 17:30:29 +02004887 pixman_region32_init(&plane->clip);
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04004888 plane->x = x;
4889 plane->y = y;
Xiong Zhang97116532013-10-23 13:58:31 +08004890 plane->compositor = ec;
Ander Conselvan de Oliveira3c36bf32013-07-05 16:05:26 +03004891
4892 /* Init the link so that the call to wl_list_remove() when releasing
4893 * the plane without ever stacking doesn't lead to a crash */
4894 wl_list_init(&plane->link);
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04004895}
4896
4897WL_EXPORT void
4898weston_plane_release(struct weston_plane *plane)
4899{
Xiong Zhang97116532013-10-23 13:58:31 +08004900 struct weston_view *view;
4901
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04004902 pixman_region32_fini(&plane->damage);
Ander Conselvan de Oliveirae1bd5a02013-03-05 17:30:29 +02004903 pixman_region32_fini(&plane->clip);
Ander Conselvan de Oliveira3c36bf32013-07-05 16:05:26 +03004904
Xiong Zhang97116532013-10-23 13:58:31 +08004905 wl_list_for_each(view, &plane->compositor->view_list, link) {
4906 if (view->plane == plane)
4907 view->plane = NULL;
4908 }
4909
Ander Conselvan de Oliveira3c36bf32013-07-05 16:05:26 +03004910 wl_list_remove(&plane->link);
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04004911}
4912
Marius Vlad9fdda7f2019-06-11 16:08:55 +03004913/** weston_compositor_stack_plane
4914 * \ingroup compositor
4915 */
Ander Conselvan de Oliveira8ad19822013-03-05 17:30:27 +02004916WL_EXPORT void
4917weston_compositor_stack_plane(struct weston_compositor *ec,
4918 struct weston_plane *plane,
4919 struct weston_plane *above)
4920{
4921 if (above)
4922 wl_list_insert(above->link.prev, &plane->link);
4923 else
4924 wl_list_insert(&ec->plane_list, &plane->link);
4925}
4926
Quentin Glidic4ef719c2016-07-05 20:44:33 +02004927static void
4928output_release(struct wl_client *client, struct wl_resource *resource)
4929{
4930 wl_resource_destroy(resource);
4931}
4932
4933static const struct wl_output_interface output_interface = {
4934 output_release,
4935};
4936
4937
Casey Dahlin9074db52012-04-19 22:50:09 -04004938static void unbind_resource(struct wl_resource *resource)
Kristian Høgsbergd2baf1f2011-10-11 22:20:37 -04004939{
Jason Ekstranda0d2dde2013-06-14 10:08:01 -05004940 wl_list_remove(wl_resource_get_link(resource));
Kristian Høgsbergd2baf1f2011-10-11 22:20:37 -04004941}
4942
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -04004943static void
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -04004944bind_output(struct wl_client *client,
4945 void *data, uint32_t version, uint32_t id)
Kristian Høgsbergbf9541f2008-11-25 12:10:09 -05004946{
Pekka Paalanen05347622017-03-27 12:24:34 +03004947 struct weston_head *head = data;
4948 struct weston_output *output = head->output;
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05004949 struct weston_mode *mode;
Kristian Høgsbergfd07fb72011-08-29 15:03:09 -04004950 struct wl_resource *resource;
Kristian Høgsberg81ce09a2008-12-31 16:18:42 -05004951
Jason Ekstranda85118c2013-06-27 20:17:02 -05004952 resource = wl_resource_create(client, &wl_output_interface,
Derek Foreman1909c102015-11-26 14:17:47 -06004953 version, id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07004954 if (resource == NULL) {
4955 wl_client_post_no_memory(client);
4956 return;
4957 }
Kristian Høgsbergfd07fb72011-08-29 15:03:09 -04004958
Pekka Paalanen1b9bf592017-03-27 12:15:38 +03004959 wl_list_insert(&head->resource_list, wl_resource_get_link(resource));
Pekka Paalanen055c1132017-03-27 16:31:25 +03004960 wl_resource_set_implementation(resource, &output_interface, head,
Pekka Paalanen05347622017-03-27 12:24:34 +03004961 unbind_resource);
Casey Dahlin9074db52012-04-19 22:50:09 -04004962
Pekka Paalanen05347622017-03-27 12:24:34 +03004963 assert(output);
Kristian Høgsberg0b5cd0c2012-03-04 21:57:37 -05004964 wl_output_send_geometry(resource,
4965 output->x,
4966 output->y,
Pekka Paalanen01f60212017-03-24 15:39:24 +02004967 head->mm_width,
4968 head->mm_height,
4969 head->subpixel,
4970 head->make, head->model,
Kristian Høgsberg05890dc2012-08-10 10:09:20 -04004971 output->transform);
Jasper St. Pierre0013a292014-08-07 16:43:11 -04004972 if (version >= WL_OUTPUT_SCALE_SINCE_VERSION)
Alexander Larsson4ea95522013-05-22 14:41:37 +02004973 wl_output_send_scale(resource,
Hardeningff39efa2013-09-18 23:56:35 +02004974 output->current_scale);
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -04004975
4976 wl_list_for_each (mode, &output->mode_list, link) {
Kristian Høgsberg0b5cd0c2012-03-04 21:57:37 -05004977 wl_output_send_mode(resource,
4978 mode->flags,
4979 mode->width,
4980 mode->height,
4981 mode->refresh);
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -04004982 }
Alexander Larsson4ea95522013-05-22 14:41:37 +02004983
Jasper St. Pierre0013a292014-08-07 16:43:11 -04004984 if (version >= WL_OUTPUT_DONE_SINCE_VERSION)
Alexander Larsson4ea95522013-05-22 14:41:37 +02004985 wl_output_send_done(resource);
Kristian Høgsberg81ce09a2008-12-31 16:18:42 -05004986}
4987
Pekka Paalanendcac3512017-12-08 14:13:34 +02004988static void
4989weston_head_add_global(struct weston_head *head)
4990{
4991 head->global = wl_global_create(head->compositor->wl_display,
4992 &wl_output_interface, 3,
4993 head, bind_output);
4994}
4995
Pekka Paalanend9dcc6d2017-12-04 15:28:13 +02004996/** Remove the global wl_output protocol object
4997 *
4998 * \param head The head whose global to remove.
4999 *
5000 * Also orphans the wl_resources for this head (wl_output).
5001 */
5002static void
5003weston_head_remove_global(struct weston_head *head)
5004{
5005 struct wl_resource *resource, *tmp;
5006
5007 if (head->global)
5008 wl_global_destroy(head->global);
5009 head->global = NULL;
5010
5011 wl_resource_for_each_safe(resource, tmp, &head->resource_list) {
5012 unbind_resource(resource);
5013 wl_resource_set_destructor(resource, NULL);
5014 wl_resource_set_user_data(resource, NULL);
5015 }
Roman Gilge97391c2019-03-29 13:01:06 +01005016
5017 wl_resource_for_each(resource, &head->xdg_output_resource_list) {
5018 /* It's sufficient to unset the destructor, then the list elements
5019 * won't be accessed.
5020 */
5021 wl_resource_set_destructor(resource, NULL);
5022 }
5023 wl_list_init(&head->xdg_output_resource_list);
Pekka Paalanend9dcc6d2017-12-04 15:28:13 +02005024}
5025
Pekka Paalanen9ffb2502017-03-27 15:14:32 +03005026/** Get the backing object of wl_output
5027 *
5028 * \param resource A wl_output protocol object.
5029 * \return The backing object (user data) of a wl_resource representing a
5030 * wl_output protocol object.
Marius Vlad78984ee2019-06-11 00:05:08 +03005031 *
5032 * \ingroup head
Pekka Paalanen9ffb2502017-03-27 15:14:32 +03005033 */
Pekka Paalanen055c1132017-03-27 16:31:25 +03005034WL_EXPORT struct weston_head *
5035weston_head_from_resource(struct wl_resource *resource)
Pekka Paalanen9ffb2502017-03-27 15:14:32 +03005036{
5037 assert(wl_resource_instance_of(resource, &wl_output_interface,
5038 &output_interface));
5039
5040 return wl_resource_get_user_data(resource);
5041}
5042
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005043/** Initialize a pre-allocated weston_head
5044 *
5045 * \param head The head to initialize.
Pekka Paalanen9b02e472017-08-14 14:43:13 +03005046 * \param name The head name, e.g. the connector name or equivalent.
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005047 *
5048 * The head will be safe to attach, detach and release.
5049 *
Pekka Paalanen9b02e472017-08-14 14:43:13 +03005050 * The name is used in logs, and can be used by compositors as a configuration
5051 * identifier.
5052 *
Marius Vlad78984ee2019-06-11 00:05:08 +03005053 * \ingroup head
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005054 * \internal
5055 */
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03005056WL_EXPORT void
Pekka Paalanen9b02e472017-08-14 14:43:13 +03005057weston_head_init(struct weston_head *head, const char *name)
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005058{
5059 /* Add some (in)sane defaults which can be used
5060 * for checking if an output was properly configured
5061 */
5062 memset(head, 0, sizeof *head);
5063
Pekka Paalanen1adcbac2017-08-14 16:05:35 +03005064 wl_list_init(&head->compositor_link);
Pekka Paalanen2e1bedb2017-10-10 11:21:58 +03005065 wl_signal_init(&head->destroy_signal);
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005066 wl_list_init(&head->output_link);
5067 wl_list_init(&head->resource_list);
Roman Gilge97391c2019-03-29 13:01:06 +01005068 wl_list_init(&head->xdg_output_resource_list);
Pekka Paalanen9b02e472017-08-14 14:43:13 +03005069 head->name = strdup(name);
Ankit Nautiyal4f64ff82019-04-03 18:44:35 +05305070 head->current_protection = WESTON_HDCP_DISABLE;
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005071}
5072
Pekka Paalanen8dc6db82018-03-20 13:29:40 +02005073/** Send output heads changed signal
5074 *
5075 * \param output The output that changed.
5076 *
5077 * Notify that the enabled output gained and/or lost heads, or that the
5078 * associated heads may have changed their connection status. This does not
5079 * include cases where the output becomes enabled or disabled. The registered
5080 * callbacks are called after the change has successfully happened.
5081 *
5082 * If connection status change causes the compositor to attach or detach a head
5083 * to an enabled output, the registered callbacks may be called multiple times.
Marius Vlad55d87362019-06-11 01:15:35 +03005084 *
5085 * \ingroup output
Pekka Paalanen8dc6db82018-03-20 13:29:40 +02005086 */
5087static void
5088weston_output_emit_heads_changed(struct weston_output *output)
5089{
5090 wl_signal_emit(&output->compositor->output_heads_changed_signal,
5091 output);
5092}
5093
Pekka Paalanen37e6c9e2017-08-15 13:00:02 +03005094/** Idle task for emitting heads_changed_signal */
5095static void
5096weston_compositor_call_heads_changed(void *data)
5097{
5098 struct weston_compositor *compositor = data;
Pekka Paalanen8dc6db82018-03-20 13:29:40 +02005099 struct weston_head *head;
Pekka Paalanen37e6c9e2017-08-15 13:00:02 +03005100
5101 compositor->heads_changed_source = NULL;
5102
5103 wl_signal_emit(&compositor->heads_changed_signal, compositor);
Pekka Paalanen8dc6db82018-03-20 13:29:40 +02005104
5105 wl_list_for_each(head, &compositor->head_list, compositor_link) {
5106 if (head->output && head->output->enabled)
5107 weston_output_emit_heads_changed(head->output);
5108 }
Pekka Paalanen37e6c9e2017-08-15 13:00:02 +03005109}
5110
5111/** Schedule a call on idle to heads_changed callback
5112 *
5113 * \param compositor The Compositor.
5114 *
Marius Vlad9fdda7f2019-06-11 16:08:55 +03005115 * \ingroup compositor
Pekka Paalanen37e6c9e2017-08-15 13:00:02 +03005116 * \internal
5117 */
5118static void
5119weston_compositor_schedule_heads_changed(struct weston_compositor *compositor)
5120{
5121 struct wl_event_loop *loop;
5122
5123 if (compositor->heads_changed_source)
5124 return;
5125
5126 loop = wl_display_get_event_loop(compositor->wl_display);
5127 compositor->heads_changed_source = wl_event_loop_add_idle(loop,
5128 weston_compositor_call_heads_changed, compositor);
5129}
5130
Pekka Paalanen1adcbac2017-08-14 16:05:35 +03005131/** Register a new head
5132 *
5133 * \param compositor The compositor.
5134 * \param head The head to register, must not be already registered.
5135 *
Pekka Paalanen37e6c9e2017-08-15 13:00:02 +03005136 * This signals the core that a new head has become available, leading to
5137 * heads_changed hook being called later.
Pekka Paalanen1adcbac2017-08-14 16:05:35 +03005138 *
Marius Vlad9fdda7f2019-06-11 16:08:55 +03005139 * \ingroup compositor
Pekka Paalanen1adcbac2017-08-14 16:05:35 +03005140 * \internal
5141 */
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03005142WL_EXPORT void
Pekka Paalanen1adcbac2017-08-14 16:05:35 +03005143weston_compositor_add_head(struct weston_compositor *compositor,
5144 struct weston_head *head)
5145{
5146 assert(wl_list_empty(&head->compositor_link));
5147 assert(head->name);
5148
5149 wl_list_insert(compositor->head_list.prev, &head->compositor_link);
5150 head->compositor = compositor;
Pekka Paalanen37e6c9e2017-08-15 13:00:02 +03005151 weston_compositor_schedule_heads_changed(compositor);
5152}
5153
5154/** Adds a listener to be called when heads change
5155 *
5156 * \param compositor The compositor.
5157 * \param listener The listener to add.
5158 *
Marius Vlada2dace22019-06-12 16:05:44 +03005159 * The listener notify function argument is weston_compositor.
Pekka Paalanen37e6c9e2017-08-15 13:00:02 +03005160 *
5161 * The listener function will be called after heads are added or their
5162 * connection status has changed. Several changes may be accumulated into a
5163 * single call. The user is expected to iterate over the existing heads and
5164 * check their statuses to find out what changed.
5165 *
5166 * \sa weston_compositor_iterate_heads, weston_head_is_connected,
5167 * weston_head_is_enabled
Marius Vlad9fdda7f2019-06-11 16:08:55 +03005168 * \ingroup compositor
Pekka Paalanen37e6c9e2017-08-15 13:00:02 +03005169 */
5170WL_EXPORT void
5171weston_compositor_add_heads_changed_listener(struct weston_compositor *compositor,
5172 struct wl_listener *listener)
5173{
5174 wl_signal_add(&compositor->heads_changed_signal, listener);
Pekka Paalanen1adcbac2017-08-14 16:05:35 +03005175}
5176
5177/** Iterate over available heads
5178 *
5179 * \param compositor The compositor.
Marius Vlada2dace22019-06-12 16:05:44 +03005180 * \param iter The iterator, or NULL for start.
Pekka Paalanen1adcbac2017-08-14 16:05:35 +03005181 * \return The next available head in the list.
5182 *
5183 * Returns all available heads, regardless of being connected or enabled.
5184 *
5185 * You can iterate over all heads as follows:
5186 * \code
5187 * struct weston_head *head = NULL;
5188 *
5189 * while ((head = weston_compositor_iterate_heads(compositor, head))) {
5190 * ...
5191 * }
5192 * \endcode
5193 *
5194 * If you cause \c iter to be removed from the list, you cannot use it to
5195 * continue iterating. Removing any other item is safe.
5196 *
Marius Vlad9fdda7f2019-06-11 16:08:55 +03005197 * \ingroup compositor
Pekka Paalanen1adcbac2017-08-14 16:05:35 +03005198 */
5199WL_EXPORT struct weston_head *
5200weston_compositor_iterate_heads(struct weston_compositor *compositor,
5201 struct weston_head *iter)
5202{
5203 struct wl_list *list = &compositor->head_list;
5204 struct wl_list *node;
5205
5206 assert(compositor);
5207 assert(!iter || iter->compositor == compositor);
5208
5209 if (iter)
5210 node = iter->compositor_link.next;
5211 else
5212 node = list->next;
5213
5214 assert(node);
5215 assert(!iter || node != &iter->compositor_link);
5216
5217 if (node == list)
5218 return NULL;
5219
5220 return container_of(node, struct weston_head, compositor_link);
5221}
5222
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03005223/** Iterate over attached heads
5224 *
5225 * \param output The output whose heads to iterate.
Marius Vlada2dace22019-06-12 16:05:44 +03005226 * \param iter The iterator, or NULL for start.
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03005227 * \return The next attached head in the list.
5228 *
5229 * Returns all heads currently attached to the output.
5230 *
5231 * You can iterate over all heads as follows:
5232 * \code
5233 * struct weston_head *head = NULL;
5234 *
5235 * while ((head = weston_output_iterate_heads(output, head))) {
5236 * ...
5237 * }
5238 * \endcode
5239 *
5240 * If you cause \c iter to be removed from the list, you cannot use it to
5241 * continue iterating. Removing any other item is safe.
5242 *
Marius Vlad55d87362019-06-11 01:15:35 +03005243 * \ingroup ouput
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03005244 */
5245WL_EXPORT struct weston_head *
5246weston_output_iterate_heads(struct weston_output *output,
5247 struct weston_head *iter)
5248{
5249 struct wl_list *list = &output->head_list;
5250 struct wl_list *node;
5251
5252 assert(output);
5253 assert(!iter || iter->output == output);
5254
5255 if (iter)
5256 node = iter->output_link.next;
5257 else
5258 node = list->next;
5259
5260 assert(node);
5261 assert(!iter || node != &iter->output_link);
5262
5263 if (node == list)
5264 return NULL;
5265
5266 return container_of(node, struct weston_head, output_link);
5267}
5268
Pekka Paalanendcac3512017-12-08 14:13:34 +02005269/** Attach a head to an output
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005270 *
5271 * \param output The output to attach to.
5272 * \param head The head that is not yet attached.
5273 * \return 0 on success, -1 on failure.
5274 *
5275 * Attaches the given head to the output. All heads of an output are clones
5276 * and share the resolution and timings.
5277 *
5278 * Cloning heads this way uses less resources than creating an output for
5279 * each head, but is not always possible due to environment, driver and hardware
5280 * limitations.
5281 *
5282 * On failure, the head remains unattached. Success of this function does not
5283 * guarantee the output configuration is actually valid. The final checks are
Pekka Paalanendcac3512017-12-08 14:13:34 +02005284 * made on weston_output_enable() unless the output was already enabled.
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005285 *
Marius Vlad55d87362019-06-11 01:15:35 +03005286 * \ingroup output
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005287 */
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03005288WL_EXPORT int
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005289weston_output_attach_head(struct weston_output *output,
5290 struct weston_head *head)
5291{
Pekka Paalanendcac3512017-12-08 14:13:34 +02005292 char *head_names;
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005293
5294 if (!wl_list_empty(&head->output_link))
5295 return -1;
5296
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03005297 if (output->attach_head) {
5298 if (output->attach_head(output, head) < 0)
5299 return -1;
5300 } else if (!wl_list_empty(&output->head_list)) {
5301 /* No support for clones in the legacy path. */
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005302 return -1;
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03005303 }
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005304
5305 head->output = output;
5306 wl_list_insert(output->head_list.prev, &head->output_link);
5307
Pekka Paalanendcac3512017-12-08 14:13:34 +02005308 if (output->enabled) {
5309 weston_head_add_global(head);
5310
5311 head_names = weston_output_create_heads_string(output);
5312 weston_log("Output '%s' updated to have head(s) %s\n",
5313 output->name, head_names);
5314 free(head_names);
Pekka Paalanen8dc6db82018-03-20 13:29:40 +02005315
5316 weston_output_emit_heads_changed(output);
Pekka Paalanendcac3512017-12-08 14:13:34 +02005317 }
5318
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005319 return 0;
5320}
5321
5322/** Detach a head from its output
5323 *
5324 * \param head The head to detach.
5325 *
5326 * It is safe to detach a non-attached head.
5327 *
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03005328 * If the head is attached to an enabled output and the output will be left
5329 * with no heads, the output will be disabled.
5330 *
Marius Vlad78984ee2019-06-11 00:05:08 +03005331 * \ingroup head
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03005332 * \sa weston_output_disable
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005333 */
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03005334WL_EXPORT void
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005335weston_head_detach(struct weston_head *head)
5336{
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03005337 struct weston_output *output = head->output;
Pekka Paalanena0106992017-12-08 16:11:17 +02005338 char *head_names;
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03005339
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005340 wl_list_remove(&head->output_link);
5341 wl_list_init(&head->output_link);
5342 head->output = NULL;
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03005343
5344 if (!output)
5345 return;
5346
5347 if (output->detach_head)
5348 output->detach_head(output, head);
5349
5350 if (output->enabled) {
5351 weston_head_remove_global(head);
5352
Pekka Paalanena0106992017-12-08 16:11:17 +02005353 if (wl_list_empty(&output->head_list)) {
5354 weston_log("Output '%s' no heads left, disabling.\n",
5355 output->name);
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03005356 weston_output_disable(output);
Pekka Paalanena0106992017-12-08 16:11:17 +02005357 } else {
5358 head_names = weston_output_create_heads_string(output);
5359 weston_log("Output '%s' updated to have head(s) %s\n",
5360 output->name, head_names);
5361 free(head_names);
Pekka Paalanen8dc6db82018-03-20 13:29:40 +02005362
5363 weston_output_emit_heads_changed(output);
Pekka Paalanena0106992017-12-08 16:11:17 +02005364 }
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03005365 }
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005366}
5367
5368/** Destroy a head
5369 *
5370 * \param head The head to be released.
5371 *
5372 * Destroys the head. The caller is responsible for freeing the memory pointed
5373 * to by \c head.
5374 *
Marius Vlad78984ee2019-06-11 00:05:08 +03005375 * \ingroup head
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005376 * \internal
5377 */
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03005378WL_EXPORT void
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005379weston_head_release(struct weston_head *head)
5380{
Pekka Paalanen2e1bedb2017-10-10 11:21:58 +03005381 wl_signal_emit(&head->destroy_signal, head);
5382
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005383 weston_head_detach(head);
Pekka Paalanen06f99ef2017-04-04 16:26:23 +03005384
5385 free(head->make);
5386 free(head->model);
5387 free(head->serial_number);
Pekka Paalanen9b02e472017-08-14 14:43:13 +03005388 free(head->name);
Pekka Paalanen1adcbac2017-08-14 16:05:35 +03005389
5390 wl_list_remove(&head->compositor_link);
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005391}
5392
Pekka Paalanene19970f2017-08-28 14:11:02 +03005393static void
5394weston_head_set_device_changed(struct weston_head *head)
5395{
5396 head->device_changed = true;
5397
5398 if (head->compositor)
5399 weston_compositor_schedule_heads_changed(head->compositor);
5400}
5401
5402/** String equal comparison with NULLs being equal */
5403static bool
5404str_null_eq(const char *a, const char *b)
5405{
5406 if (!a && !b)
5407 return true;
5408
5409 if (!!a != !!b)
5410 return false;
5411
5412 return strcmp(a, b) == 0;
5413}
5414
Pekka Paalanen01f60212017-03-24 15:39:24 +02005415/** Store monitor make, model and serial number
5416 *
5417 * \param head The head to modify.
5418 * \param make The monitor make. If EDID is available, the PNP ID. Otherwise
5419 * any string, or NULL for none.
5420 * \param model The monitor model or name, or a made-up string, or NULL for
5421 * none.
5422 * \param serialno The monitor serial number, a made-up string, or NULL for
5423 * none.
5424 *
Pekka Paalanene19970f2017-08-28 14:11:02 +03005425 * This may set the device_changed flag.
5426 *
Marius Vlad78984ee2019-06-11 00:05:08 +03005427 * \ingroup head
Pekka Paalanen01f60212017-03-24 15:39:24 +02005428 * \internal
5429 */
5430WL_EXPORT void
5431weston_head_set_monitor_strings(struct weston_head *head,
5432 const char *make,
5433 const char *model,
5434 const char *serialno)
5435{
Pekka Paalanene19970f2017-08-28 14:11:02 +03005436 if (str_null_eq(head->make, make) &&
5437 str_null_eq(head->model, model) &&
5438 str_null_eq(head->serial_number, serialno))
5439 return;
5440
Pekka Paalanen06f99ef2017-04-04 16:26:23 +03005441 free(head->make);
5442 free(head->model);
5443 free(head->serial_number);
5444
5445 head->make = make ? strdup(make) : NULL;
5446 head->model = model ? strdup(model) : NULL;
5447 head->serial_number = serialno ? strdup(serialno) : NULL;
Pekka Paalanene19970f2017-08-28 14:11:02 +03005448
5449 weston_head_set_device_changed(head);
Pekka Paalanen01f60212017-03-24 15:39:24 +02005450}
5451
Philipp Zabelc18ffd32018-08-30 17:38:03 +02005452/** Store display non-desktop status
5453 *
5454 * \param head The head to modify.
5455 * \param non_desktop Whether the head connects to a non-desktop display.
5456 *
Marius Vlad78984ee2019-06-11 00:05:08 +03005457 * \ingroup head
Philipp Zabelc18ffd32018-08-30 17:38:03 +02005458 * \internal
5459 */
5460WL_EXPORT void
5461weston_head_set_non_desktop(struct weston_head *head, bool non_desktop)
5462{
5463 if (head->non_desktop == non_desktop)
5464 return;
5465
5466 head->non_desktop = non_desktop;
5467
5468 weston_head_set_device_changed(head);
5469}
5470
Lucas Stacha69cb712019-11-25 23:29:31 +00005471/** Store display transformation
5472 *
5473 * \param head The head to modify.
5474 * \param transform The transformation to apply for this head
5475 *
5476 * This may set the device_changed flag.
5477 *
5478 * \ingroup head
5479 * \internal
5480 */
5481WL_EXPORT void
5482weston_head_set_transform(struct weston_head *head, uint32_t transform)
5483{
5484 if (head->transform == transform)
5485 return;
5486
5487 head->transform = transform;
5488
5489 weston_head_set_device_changed(head);
5490}
5491
5492
Pekka Paalanen01f60212017-03-24 15:39:24 +02005493/** Store physical image size
5494 *
5495 * \param head The head to modify.
5496 * \param mm_width Image area width in millimeters.
5497 * \param mm_height Image area height in millimeters.
5498 *
Pekka Paalanene19970f2017-08-28 14:11:02 +03005499 * This may set the device_changed flag.
5500 *
Marius Vlad78984ee2019-06-11 00:05:08 +03005501 * \ingroup head
Pekka Paalanen01f60212017-03-24 15:39:24 +02005502 * \internal
5503 */
5504WL_EXPORT void
5505weston_head_set_physical_size(struct weston_head *head,
5506 int32_t mm_width, int32_t mm_height)
5507{
Pekka Paalanene19970f2017-08-28 14:11:02 +03005508 if (head->mm_width == mm_width &&
5509 head->mm_height == mm_height)
5510 return;
5511
Pekka Paalanen01f60212017-03-24 15:39:24 +02005512 head->mm_width = mm_width;
5513 head->mm_height = mm_height;
Pekka Paalanene19970f2017-08-28 14:11:02 +03005514
5515 weston_head_set_device_changed(head);
Pekka Paalanen01f60212017-03-24 15:39:24 +02005516}
5517
5518/** Store monitor sub-pixel layout
5519 *
5520 * \param head The head to modify.
5521 * \param sp Sub-pixel layout. The possible values are:
5522 * - WL_OUTPUT_SUBPIXEL_UNKNOWN,
5523 * - WL_OUTPUT_SUBPIXEL_NONE,
5524 * - WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB,
5525 * - WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR,
5526 * - WL_OUTPUT_SUBPIXEL_VERTICAL_RGB,
5527 * - WL_OUTPUT_SUBPIXEL_VERTICAL_BGR
5528 *
Pekka Paalanene19970f2017-08-28 14:11:02 +03005529 * This may set the device_changed flag.
5530 *
Marius Vlad78984ee2019-06-11 00:05:08 +03005531 * \ingroup head
Pekka Paalanen01f60212017-03-24 15:39:24 +02005532 * \internal
5533 */
5534WL_EXPORT void
5535weston_head_set_subpixel(struct weston_head *head,
5536 enum wl_output_subpixel sp)
5537{
Pekka Paalanene19970f2017-08-28 14:11:02 +03005538 if (head->subpixel == sp)
5539 return;
5540
Pekka Paalanen01f60212017-03-24 15:39:24 +02005541 head->subpixel = sp;
Pekka Paalanene19970f2017-08-28 14:11:02 +03005542
5543 weston_head_set_device_changed(head);
Pekka Paalanen01f60212017-03-24 15:39:24 +02005544}
5545
5546/** Mark the monitor as internal
5547 *
5548 * This is used for embedded screens, like laptop panels.
5549 *
5550 * \param head The head to mark as internal.
5551 *
5552 * By default a head is external. The type is often inferred from the physical
5553 * connector type.
5554 *
Marius Vlad78984ee2019-06-11 00:05:08 +03005555 * \ingroup head
Pekka Paalanen01f60212017-03-24 15:39:24 +02005556 * \internal
5557 */
5558WL_EXPORT void
5559weston_head_set_internal(struct weston_head *head)
5560{
5561 head->connection_internal = true;
5562}
Pekka Paalanen9ffb2502017-03-27 15:14:32 +03005563
Pekka Paalanen7fe858b2017-08-14 15:45:14 +03005564/** Store connector status
5565 *
5566 * \param head The head to modify.
5567 * \param connected Whether the head is connected.
5568 *
5569 * Connectors are created as disconnected. This function can be used to
5570 * set the connector status.
5571 *
5572 * The status should be set to true when a physical connector is connected to
5573 * a video sink device like a monitor and to false when the connector is
5574 * disconnected. For nested backends, the connection status should reflect the
5575 * connection to the parent display server.
5576 *
Pekka Paalanen37e6c9e2017-08-15 13:00:02 +03005577 * When the connection status changes, it schedules a call to the heads_changed
Pekka Paalanene19970f2017-08-28 14:11:02 +03005578 * hook and sets the device_changed flag.
Pekka Paalanen37e6c9e2017-08-15 13:00:02 +03005579 *
5580 * \sa weston_compositor_set_heads_changed_cb
Marius Vlad78984ee2019-06-11 00:05:08 +03005581 * \ingroup head
Pekka Paalanen7fe858b2017-08-14 15:45:14 +03005582 * \internal
5583 */
5584WL_EXPORT void
5585weston_head_set_connection_status(struct weston_head *head, bool connected)
5586{
Pekka Paalanen37e6c9e2017-08-15 13:00:02 +03005587 if (head->connected == connected)
5588 return;
5589
Pekka Paalanen7fe858b2017-08-14 15:45:14 +03005590 head->connected = connected;
Pekka Paalanen37e6c9e2017-08-15 13:00:02 +03005591
Pekka Paalanene19970f2017-08-28 14:11:02 +03005592 weston_head_set_device_changed(head);
Pekka Paalanen7fe858b2017-08-14 15:45:14 +03005593}
5594
Ankit Nautiyal4f64ff82019-04-03 18:44:35 +05305595static void
5596weston_output_compute_protection(struct weston_output *output)
5597{
5598 struct weston_head *head;
5599 enum weston_hdcp_protection op_protection;
5600 bool op_protection_valid = false;
Ankit Nautiyalf74c35b2019-04-03 19:21:58 +05305601 struct weston_compositor *wc = output->compositor;
Ankit Nautiyal4f64ff82019-04-03 18:44:35 +05305602
5603 wl_list_for_each(head, &output->head_list, output_link) {
5604 if (!op_protection_valid) {
5605 op_protection = head->current_protection;
5606 op_protection_valid = true;
5607 }
5608 if (head->current_protection < op_protection)
5609 op_protection = head->current_protection;
5610 }
5611
5612 if (!op_protection_valid)
5613 op_protection = WESTON_HDCP_DISABLE;
5614
Ankit Nautiyalf74c35b2019-04-03 19:21:58 +05305615 if (output->current_protection != op_protection) {
Ankit Nautiyal4f64ff82019-04-03 18:44:35 +05305616 output->current_protection = op_protection;
Ankit Nautiyalf74c35b2019-04-03 19:21:58 +05305617 weston_output_damage(output);
Ankit Nautiyalfaa5ab42019-07-08 13:23:24 +05305618 weston_schedule_surface_protection_update(wc);
Ankit Nautiyalf74c35b2019-04-03 19:21:58 +05305619 }
Ankit Nautiyal4f64ff82019-04-03 18:44:35 +05305620}
5621
5622WL_EXPORT void
5623weston_head_set_content_protection_status(struct weston_head *head,
5624 enum weston_hdcp_protection status)
5625{
5626 head->current_protection = status;
5627 if (head->output)
5628 weston_output_compute_protection(head->output);
5629}
5630
Pekka Paalanen7fe858b2017-08-14 15:45:14 +03005631/** Is the head currently connected?
5632 *
5633 * \param head The head to query.
5634 * \return Connection status.
5635 *
5636 * Returns true if the head is physically connected to a monitor, or in
5637 * case of a nested backend returns true when there is a connection to the
5638 * parent display server.
5639 *
5640 * This is independent from the head being enabled.
5641 *
5642 * \sa weston_head_is_enabled
Marius Vlad78984ee2019-06-11 00:05:08 +03005643 * \ingroup head
Pekka Paalanen7fe858b2017-08-14 15:45:14 +03005644 */
5645WL_EXPORT bool
5646weston_head_is_connected(struct weston_head *head)
5647{
5648 return head->connected;
5649}
5650
Pekka Paalanen8e552fd2018-02-15 15:18:20 +02005651/** Is the head currently enabled?
5652 *
5653 * \param head The head to query.
5654 * \return Video status.
5655 *
5656 * Returns true if the head is currently transmitting a video stream.
5657 *
5658 * This is independent of the head being connected.
5659 *
5660 * \sa weston_head_is_connected
Marius Vlad78984ee2019-06-11 00:05:08 +03005661 * \ingroup head
Pekka Paalanen8e552fd2018-02-15 15:18:20 +02005662 */
5663WL_EXPORT bool
5664weston_head_is_enabled(struct weston_head *head)
5665{
5666 if (!head->output)
5667 return false;
5668
5669 return head->output->enabled;
5670}
5671
Pekka Paalanene19970f2017-08-28 14:11:02 +03005672/** Has the device information changed?
5673 *
5674 * \param head The head to query.
5675 * \return True if the device information has changed since last reset.
5676 *
5677 * The information about the connected display device, e.g. a monitor, may
5678 * change without being disconnected in between. Changing information
5679 * causes a call to the heads_changed hook.
5680 *
5681 * The information includes make, model, serial number, physical size,
5682 * and sub-pixel type. The connection status is also included.
5683 *
5684 * \sa weston_head_reset_device_changed, weston_compositor_set_heads_changed_cb
Marius Vlad78984ee2019-06-11 00:05:08 +03005685 * \ingroup head
Pekka Paalanene19970f2017-08-28 14:11:02 +03005686 */
5687WL_EXPORT bool
5688weston_head_is_device_changed(struct weston_head *head)
5689{
5690 return head->device_changed;
5691}
5692
Philipp Zabelc18ffd32018-08-30 17:38:03 +02005693/** Does the head represent a non-desktop display?
5694 *
5695 * \param head The head to query.
5696 * \return True if the device is a non-desktop display.
5697 *
5698 * Non-desktop heads are not attached to outputs by default.
5699 * This stops weston from extending the desktop onto head mounted displays.
5700 *
Marius Vlad78984ee2019-06-11 00:05:08 +03005701 * \ingroup head
Philipp Zabelc18ffd32018-08-30 17:38:03 +02005702 */
5703WL_EXPORT bool
5704weston_head_is_non_desktop(struct weston_head *head)
5705{
5706 return head->non_desktop;
5707}
5708
Pekka Paalanene19970f2017-08-28 14:11:02 +03005709/** Acknowledge device information change
5710 *
5711 * \param head The head to acknowledge.
5712 *
5713 * Clears the device changed flag on this head. When a compositor has processed
5714 * device information, it should call this to be able to notice further
5715 * changes.
5716 *
5717 * \sa weston_head_is_device_changed
Marius Vlad78984ee2019-06-11 00:05:08 +03005718 * \ingroup head
Pekka Paalanene19970f2017-08-28 14:11:02 +03005719 */
5720WL_EXPORT void
5721weston_head_reset_device_changed(struct weston_head *head)
5722{
5723 head->device_changed = false;
5724}
5725
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03005726/** Get the name of a head
5727 *
5728 * \param head The head to query.
5729 * \return The head's name, not NULL.
5730 *
5731 * The name depends on the backend. The DRM backend uses connector names,
5732 * other backends may use hardcoded names or user-given names.
Marius Vlad78984ee2019-06-11 00:05:08 +03005733 *
5734 * \ingroup head
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03005735 */
5736WL_EXPORT const char *
5737weston_head_get_name(struct weston_head *head)
5738{
5739 return head->name;
5740}
5741
5742/** Get the output the head is attached to
5743 *
5744 * \param head The head to query.
5745 * \return The output the head is attached to, or NULL if detached.
Marius Vlad78984ee2019-06-11 00:05:08 +03005746 * \ingroup head
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03005747 */
5748WL_EXPORT struct weston_output *
5749weston_head_get_output(struct weston_head *head)
5750{
5751 return head->output;
5752}
5753
Lucas Stacha69cb712019-11-25 23:29:31 +00005754/** Get the head's native transformation
5755 *
5756 * \param head The head to query.
5757 * \return The head's native transform, as a WL_OUTPUT_TRANSFORM_* value
5758 *
5759 * A weston_head may have a 'native' transform provided by the backend.
5760 * Examples include panels which are physically rotated, where the rotation
5761 * is recorded and described as part of the system configuration. This call
5762 * will return any known native transform for the head.
5763 *
5764 * \ingroup head
5765 */
5766WL_EXPORT uint32_t
5767weston_head_get_transform(struct weston_head *head)
5768{
5769 return head->transform;
5770}
5771
Pekka Paalanen2e1bedb2017-10-10 11:21:58 +03005772/** Add destroy callback for a head
5773 *
5774 * \param head The head to watch for.
5775 * \param listener The listener to add. The \c notify member must be set.
5776 *
5777 * Heads may get destroyed for various reasons by the backends. If a head is
5778 * attached to an output, the compositor should listen for head destruction
5779 * and reconfigure or destroy the output if necessary.
5780 *
5781 * The destroy callbacks will be called on weston_head destruction before any
5782 * automatic detaching from an associated weston_output and before any
5783 * weston_head information is lost.
5784 *
5785 * The \c data argument to the notify callback is the weston_head being
5786 * destroyed.
Marius Vlad78984ee2019-06-11 00:05:08 +03005787 *
5788 * \ingroup head
Pekka Paalanen2e1bedb2017-10-10 11:21:58 +03005789 */
5790WL_EXPORT void
5791weston_head_add_destroy_listener(struct weston_head *head,
5792 struct wl_listener *listener)
5793{
5794 wl_signal_add(&head->destroy_signal, listener);
5795}
5796
5797/** Look up destroy listener for a head
5798 *
5799 * \param head The head to query.
5800 * \param notify The notify function used used for the added destroy listener.
5801 * \return The listener, or NULL if not found.
5802 *
5803 * This looks up the previously added destroy listener struct based on the
5804 * notify function it has. The listener can be used to access user data
5805 * through \c container_of().
5806 *
5807 * \sa wl_signal_get()
Marius Vlad78984ee2019-06-11 00:05:08 +03005808 * \ingroup head
Pekka Paalanen2e1bedb2017-10-10 11:21:58 +03005809 */
5810WL_EXPORT struct wl_listener *
5811weston_head_get_destroy_listener(struct weston_head *head,
5812 wl_notify_func_t notify)
5813{
5814 return wl_signal_get(&head->destroy_signal, notify);
5815}
5816
David Fort0de859e2016-05-27 23:22:57 +02005817/* Move other outputs when one is resized so the space remains contiguous. */
Zhang, Xiong Ya4b54c02013-12-13 22:10:51 +02005818static void
David Fort0de859e2016-05-27 23:22:57 +02005819weston_compositor_reflow_outputs(struct weston_compositor *compositor,
5820 struct weston_output *resized_output, int delta_width)
Zhang, Xiong Ya4b54c02013-12-13 22:10:51 +02005821{
5822 struct weston_output *output;
David Fort0de859e2016-05-27 23:22:57 +02005823 bool start_resizing = false;
5824
5825 if (!delta_width)
5826 return;
Zhang, Xiong Ya4b54c02013-12-13 22:10:51 +02005827
5828 wl_list_for_each(output, &compositor->output_list, link) {
David Fort0de859e2016-05-27 23:22:57 +02005829 if (output == resized_output) {
5830 start_resizing = true;
Zhang, Xiong Ya4b54c02013-12-13 22:10:51 +02005831 continue;
5832 }
5833
David Fort0de859e2016-05-27 23:22:57 +02005834 if (start_resizing) {
5835 weston_output_move(output, output->x + delta_width, output->y);
Zhang, Xiong Ya4b54c02013-12-13 22:10:51 +02005836 output->dirty = 1;
5837 }
5838 }
5839}
5840
Pekka Paalanend72bad22017-03-29 17:01:41 +03005841static void
Scott Moreauccbf29d2012-02-22 14:21:41 -07005842weston_output_update_matrix(struct weston_output *output)
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01005843{
Scott Moreau850ca422012-05-21 15:21:25 -06005844 float magnification;
Kristian Høgsberg31bd6c72011-02-13 13:00:51 -05005845
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05005846 weston_matrix_init(&output->matrix);
Jason Ekstrandfb23df72014-10-16 10:55:21 -05005847 weston_matrix_translate(&output->matrix, -output->x, -output->y, 0);
Scott Moreau1bad5db2012-08-18 01:04:05 -06005848
Scott Moreauccbf29d2012-02-22 14:21:41 -07005849 if (output->zoom.active) {
Scott Moreaue6603982012-06-11 13:07:51 -06005850 magnification = 1 / (1 - output->zoom.spring_z.current);
Jason Ekstranda7af7042013-10-12 22:38:11 -05005851 weston_output_update_zoom(output);
Neil Roberts1e40a7e2014-04-25 13:19:37 +01005852 weston_matrix_translate(&output->matrix, -output->zoom.trans_x,
Jason Ekstrandfb23df72014-10-16 10:55:21 -05005853 -output->zoom.trans_y, 0);
Neil Roberts1e40a7e2014-04-25 13:19:37 +01005854 weston_matrix_scale(&output->matrix, magnification,
5855 magnification, 1.0);
Scott Moreauccbf29d2012-02-22 14:21:41 -07005856 }
Kristian Høgsbergce5325d2010-06-14 11:54:00 -04005857
Jason Ekstrandfb23df72014-10-16 10:55:21 -05005858 switch (output->transform) {
5859 case WL_OUTPUT_TRANSFORM_FLIPPED:
5860 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
5861 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
5862 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
5863 weston_matrix_translate(&output->matrix, -output->width, 0, 0);
5864 weston_matrix_scale(&output->matrix, -1, 1, 1);
5865 break;
5866 }
5867
5868 switch (output->transform) {
5869 default:
5870 case WL_OUTPUT_TRANSFORM_NORMAL:
5871 case WL_OUTPUT_TRANSFORM_FLIPPED:
5872 break;
5873 case WL_OUTPUT_TRANSFORM_90:
5874 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
Pekka Paalanen8060d822020-02-06 15:27:54 +02005875 weston_matrix_translate(&output->matrix, -output->width, 0, 0);
5876 weston_matrix_rotate_xy(&output->matrix, 0, -1);
Jason Ekstrandfb23df72014-10-16 10:55:21 -05005877 break;
5878 case WL_OUTPUT_TRANSFORM_180:
5879 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
5880 weston_matrix_translate(&output->matrix,
5881 -output->width, -output->height, 0);
5882 weston_matrix_rotate_xy(&output->matrix, -1, 0);
5883 break;
5884 case WL_OUTPUT_TRANSFORM_270:
5885 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
Pekka Paalanen8060d822020-02-06 15:27:54 +02005886 weston_matrix_translate(&output->matrix, 0, -output->height, 0);
5887 weston_matrix_rotate_xy(&output->matrix, 0, 1);
Jason Ekstrandfb23df72014-10-16 10:55:21 -05005888 break;
5889 }
5890
5891 if (output->current_scale != 1)
5892 weston_matrix_scale(&output->matrix,
5893 output->current_scale,
5894 output->current_scale, 1);
Neil Roberts6c3b01f2014-05-06 19:04:15 +01005895
Scott Moreauccbf29d2012-02-22 14:21:41 -07005896 output->dirty = 0;
Derek Foremanc0023212015-03-24 11:36:13 -05005897
5898 weston_matrix_invert(&output->inverse_matrix, &output->matrix);
Scott Moreauccbf29d2012-02-22 14:21:41 -07005899}
5900
Scott Moreau1bad5db2012-08-18 01:04:05 -06005901static void
Alexander Larsson0b135062013-05-28 16:23:36 +02005902weston_output_transform_scale_init(struct weston_output *output, uint32_t transform, uint32_t scale)
Scott Moreau1bad5db2012-08-18 01:04:05 -06005903{
5904 output->transform = transform;
Pekka Paalanen59987fa2016-04-26 15:50:59 +03005905 output->native_scale = scale;
5906 output->current_scale = scale;
Scott Moreau1bad5db2012-08-18 01:04:05 -06005907
Pekka Paalanen59987fa2016-04-26 15:50:59 +03005908 convert_size_by_transform_scale(&output->width, &output->height,
5909 output->current_mode->width,
5910 output->current_mode->height,
5911 transform, scale);
Alexander Larsson4ea95522013-05-22 14:41:37 +02005912}
5913
Zhang, Xiong Yf3012412013-12-13 22:10:53 +02005914static void
5915weston_output_init_geometry(struct weston_output *output, int x, int y)
Scott Moreauccbf29d2012-02-22 14:21:41 -07005916{
5917 output->x = x;
5918 output->y = y;
5919
Pekka Paalanen4b582c72017-03-30 16:04:58 +03005920 pixman_region32_fini(&output->region);
Scott Moreauccbf29d2012-02-22 14:21:41 -07005921 pixman_region32_init_rect(&output->region, x, y,
Scott Moreau1bad5db2012-08-18 01:04:05 -06005922 output->width,
5923 output->height);
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01005924}
5925
Marius Vlad55d87362019-06-11 01:15:35 +03005926/**
5927 * \ingroup output
5928 */
Kristian Høgsberg1c562182011-05-02 22:09:20 -04005929WL_EXPORT void
Zhang, Xiong Yf3012412013-12-13 22:10:53 +02005930weston_output_move(struct weston_output *output, int x, int y)
5931{
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005932 struct weston_head *head;
Zhang, Xiong Yf3012412013-12-13 22:10:53 +02005933 struct wl_resource *resource;
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005934 int ver;
Zhang, Xiong Yf3012412013-12-13 22:10:53 +02005935
5936 output->move_x = x - output->x;
5937 output->move_y = y - output->y;
5938
5939 if (output->move_x == 0 && output->move_y == 0)
5940 return;
5941
Zhang, Xiong Yf3012412013-12-13 22:10:53 +02005942 weston_output_init_geometry(output, x, y);
5943
5944 output->dirty = 1;
5945
5946 /* Move views on this output. */
Ander Conselvan de Oliveiraa8a9baf2014-01-29 18:47:52 +02005947 wl_signal_emit(&output->compositor->output_moved_signal, output);
Zhang, Xiong Yf3012412013-12-13 22:10:53 +02005948
5949 /* Notify clients of the change for output position. */
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005950 wl_list_for_each(head, &output->head_list, output_link) {
5951 wl_resource_for_each(resource, &head->resource_list) {
5952 wl_output_send_geometry(resource,
5953 output->x,
5954 output->y,
5955 head->mm_width,
5956 head->mm_height,
5957 head->subpixel,
5958 head->make,
5959 head->model,
5960 output->transform);
Quanxian Wangb2c86362014-03-14 09:16:25 +08005961
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005962 ver = wl_resource_get_version(resource);
5963 if (ver >= WL_OUTPUT_DONE_SINCE_VERSION)
5964 wl_output_send_done(resource);
5965 }
Roman Gilge97391c2019-03-29 13:01:06 +01005966
5967 wl_resource_for_each(resource, &head->xdg_output_resource_list) {
5968 zxdg_output_v1_send_logical_position(resource,
5969 output->x,
5970 output->y);
5971 zxdg_output_v1_send_done(resource);
5972 }
Quanxian Wangb2c86362014-03-14 09:16:25 +08005973 }
Zhang, Xiong Yf3012412013-12-13 22:10:53 +02005974}
5975
Pekka Paalanenf0ca7962017-03-29 16:20:19 +03005976/** Signal that a pending output is taken into use.
5977 *
5978 * Removes the output from the pending list and adds it to the compositor's
5979 * list of enabled outputs. The output created signal is emitted.
Giulio Camuffob1147152015-05-06 21:41:57 +03005980 *
Pekka Paalanen2210ad02017-03-30 15:48:06 +03005981 * The output gets an internal ID assigned, and the wl_output global is
5982 * created.
Pekka Paalanen3d2d4972017-03-30 15:19:45 +03005983 *
Giulio Camuffob1147152015-05-06 21:41:57 +03005984 * \param compositor The compositor instance.
5985 * \param output The output to be added.
Pekka Paalanenee16ea92017-03-29 16:53:50 +03005986 *
5987 * \internal
Marius Vlad9fdda7f2019-06-11 16:08:55 +03005988 * \ingroup compositor
Giulio Camuffob1147152015-05-06 21:41:57 +03005989 */
Pekka Paalanenf9681b52017-03-29 16:58:48 +03005990static void
Giulio Camuffob1147152015-05-06 21:41:57 +03005991weston_compositor_add_output(struct weston_compositor *compositor,
5992 struct weston_output *output)
5993{
Armin Krezoviće5403842016-08-05 15:28:29 +02005994 struct weston_view *view, *next;
Pekka Paalanen1b9bf592017-03-27 12:15:38 +03005995 struct weston_head *head;
Armin Krezoviće5403842016-08-05 15:28:29 +02005996
Pekka Paalanen7f340ff2017-03-30 14:56:22 +03005997 assert(!output->enabled);
Pekka Paalanen3d2d4972017-03-30 15:19:45 +03005998
5999 /* Verify we haven't reached the limit of 32 available output IDs */
6000 assert(ffs(~compositor->output_id_pool) > 0);
6001
6002 /* Invert the output id pool and look for the lowest numbered
6003 * switch (the least significant bit). Take that bit's position
6004 * as our ID, and mark it used in the compositor's output_id_pool.
6005 */
6006 output->id = ffs(~compositor->output_id_pool) - 1;
6007 compositor->output_id_pool |= 1u << output->id;
6008
Pekka Paalanenf0ca7962017-03-29 16:20:19 +03006009 wl_list_remove(&output->link);
Giulio Camuffob1147152015-05-06 21:41:57 +03006010 wl_list_insert(compositor->output_list.prev, &output->link);
Pekka Paalanen7f340ff2017-03-30 14:56:22 +03006011 output->enabled = true;
Pekka Paalanenf0ca7962017-03-29 16:20:19 +03006012
Pekka Paalanendcac3512017-12-08 14:13:34 +02006013 wl_list_for_each(head, &output->head_list, output_link)
6014 weston_head_add_global(head);
Pekka Paalanen2210ad02017-03-30 15:48:06 +03006015
Giulio Camuffob1147152015-05-06 21:41:57 +03006016 wl_signal_emit(&compositor->output_created_signal, output);
Armin Krezoviće5403842016-08-05 15:28:29 +02006017
6018 wl_list_for_each_safe(view, next, &compositor->view_list, link)
6019 weston_view_geometry_dirty(view);
Kristian Høgsbergce5325d2010-06-14 11:54:00 -04006020}
6021
Pekka Paalanenee16ea92017-03-29 16:53:50 +03006022/** Transform device coordinates into global coordinates
6023 *
Marius Vlada2dace22019-06-12 16:05:44 +03006024 * \param output the weston_output object
6025 * \param[in] device_x X coordinate in device units.
6026 * \param[in] device_y Y coordinate in device units.
6027 * \param[out] x X coordinate in the global space.
6028 * \param[out] y Y coordinate in the global space.
Pekka Paalanenee16ea92017-03-29 16:53:50 +03006029 *
Marius Vlada2dace22019-06-12 16:05:44 +03006030 * Transforms coordinates from the device coordinate space (physical pixel
6031 * units) to the global coordinate space (logical pixel units). This takes
6032 * into account output transform and scale.
Pekka Paalanenee16ea92017-03-29 16:53:50 +03006033 *
Marius Vlad55d87362019-06-11 01:15:35 +03006034 * \ingroup output
Pekka Paalanenee16ea92017-03-29 16:53:50 +03006035 * \internal
6036 */
Kristian Høgsberg98c774f2013-07-22 14:33:42 -07006037WL_EXPORT void
6038weston_output_transform_coordinate(struct weston_output *output,
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02006039 double device_x, double device_y,
6040 double *x, double *y)
Kristian Høgsberg98c774f2013-07-22 14:33:42 -07006041{
Derek Foreman0f679412014-10-02 13:41:17 -05006042 struct weston_vector p = { {
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02006043 device_x,
6044 device_y,
Derek Foreman0f679412014-10-02 13:41:17 -05006045 0.0,
6046 1.0 } };
Kristian Høgsberg98c774f2013-07-22 14:33:42 -07006047
Derek Foreman67a18b92015-03-24 11:36:14 -05006048 weston_matrix_transform(&output->inverse_matrix, &p);
Kristian Høgsberg98c774f2013-07-22 14:33:42 -07006049
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02006050 *x = p.f[0] / p.f[3];
6051 *y = p.f[1] / p.f[3];
Kristian Høgsberg98c774f2013-07-22 14:33:42 -07006052}
6053
Pekka Paalanene6ac4fc2017-03-29 16:07:34 +03006054/** Removes output from compositor's list of enabled outputs
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006055 *
6056 * \param output The weston_output object that is being removed.
6057 *
Pekka Paalanene6ac4fc2017-03-29 16:07:34 +03006058 * The following happens:
6059 *
6060 * - The output assignments of all views in the current scenegraph are
6061 * recomputed.
6062 *
6063 * - Presentation feedback is discarded.
6064 *
6065 * - Compositor is notified that outputs were changed and
6066 * applies the necessary changes to re-layout outputs.
6067 *
Pekka Paalanenf0ca7962017-03-29 16:20:19 +03006068 * - The output is put back in the pending outputs list.
6069 *
Pekka Paalanene6ac4fc2017-03-29 16:07:34 +03006070 * - Signal is emitted to notify all users of the weston_output
6071 * object that the output is being destroyed.
6072 *
6073 * - wl_output protocol objects referencing this weston_output
Pekka Paalanen2210ad02017-03-30 15:48:06 +03006074 * are made inert, and the wl_output global is removed.
Pekka Paalanenee16ea92017-03-29 16:53:50 +03006075 *
Pekka Paalanen3d2d4972017-03-30 15:19:45 +03006076 * - The output's internal ID is released.
6077 *
Marius Vlad9fdda7f2019-06-11 16:08:55 +03006078 * \ingroup compositor
Pekka Paalanenee16ea92017-03-29 16:53:50 +03006079 * \internal
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006080 */
6081static void
6082weston_compositor_remove_output(struct weston_output *output)
6083{
Pekka Paalanenbccda712017-03-29 16:16:04 +03006084 struct weston_compositor *compositor = output->compositor;
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006085 struct weston_view *view;
Pekka Paalanen1b9bf592017-03-27 12:15:38 +03006086 struct weston_head *head;
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006087
6088 assert(output->destroying);
Pekka Paalanen7f340ff2017-03-30 14:56:22 +03006089 assert(output->enabled);
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006090
Pekka Paalanenbccda712017-03-29 16:16:04 +03006091 wl_list_for_each(view, &compositor->view_list, link) {
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006092 if (view->output_mask & (1u << output->id))
6093 weston_view_assign_output(view);
6094 }
6095
6096 weston_presentation_feedback_discard_list(&output->feedback_list);
6097
Pekka Paalanen9711fd92018-06-21 14:26:18 +03006098 weston_compositor_reflow_outputs(compositor, output, -output->width);
Pekka Paalanenf0ca7962017-03-29 16:20:19 +03006099
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006100 wl_list_remove(&output->link);
Pekka Paalanenf0ca7962017-03-29 16:20:19 +03006101 wl_list_insert(compositor->pending_output_list.prev, &output->link);
Pekka Paalanen7f340ff2017-03-30 14:56:22 +03006102 output->enabled = false;
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006103
Pekka Paalanenbccda712017-03-29 16:16:04 +03006104 wl_signal_emit(&compositor->output_destroyed_signal, output);
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006105 wl_signal_emit(&output->destroy_signal, output);
6106
Pekka Paalanend9dcc6d2017-12-04 15:28:13 +02006107 wl_list_for_each(head, &output->head_list, output_link)
6108 weston_head_remove_global(head);
Pekka Paalanen3d2d4972017-03-30 15:19:45 +03006109
6110 compositor->output_id_pool &= ~(1u << output->id);
6111 output->id = 0xffffffff; /* invalid */
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006112}
6113
6114/** Sets the output scale for a given output.
6115 *
6116 * \param output The weston_output object that the scale is set for.
6117 * \param scale Scale factor for the given output.
6118 *
6119 * It only supports setting scale for an output that
6120 * is not enabled and it can only be ran once.
Pekka Paalanenee16ea92017-03-29 16:53:50 +03006121 *
Marius Vlad55d87362019-06-11 01:15:35 +03006122 * \ingroup ouput
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006123 */
6124WL_EXPORT void
6125weston_output_set_scale(struct weston_output *output,
6126 int32_t scale)
6127{
6128 /* We can only set scale on a disabled output */
6129 assert(!output->enabled);
6130
6131 /* We only want to set scale once */
6132 assert(!output->scale);
6133
6134 output->scale = scale;
6135}
6136
6137/** Sets the output transform for a given output.
6138 *
6139 * \param output The weston_output object that the transform is set for.
6140 * \param transform Transform value for the given output.
6141 *
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006142 * Refer to wl_output::transform section located at
6143 * https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_output
6144 * for list of values that can be passed to this function.
Pekka Paalanenee16ea92017-03-29 16:53:50 +03006145 *
Marius Vlad55d87362019-06-11 01:15:35 +03006146 * \ingroup output
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006147 */
6148WL_EXPORT void
6149weston_output_set_transform(struct weston_output *output,
6150 uint32_t transform)
6151{
Ilia Bozhinov8564a0d2017-06-25 12:21:39 +00006152 struct weston_pointer_motion_event ev;
6153 struct wl_resource *resource;
6154 struct weston_seat *seat;
6155 pixman_region32_t old_region;
6156 int mid_x, mid_y;
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03006157 struct weston_head *head;
6158 int ver;
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006159
Ilia Bozhinov8564a0d2017-06-25 12:21:39 +00006160 if (!output->enabled && output->transform == UINT32_MAX) {
6161 output->transform = transform;
6162 return;
6163 }
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006164
Ilia Bozhinov8564a0d2017-06-25 12:21:39 +00006165 weston_output_transform_scale_init(output, transform, output->scale);
6166
6167 pixman_region32_init(&old_region);
6168 pixman_region32_copy(&old_region, &output->region);
6169
Ilia Bozhinov8564a0d2017-06-25 12:21:39 +00006170 weston_output_init_geometry(output, output->x, output->y);
6171
6172 output->dirty = 1;
6173
6174 /* Notify clients of the change for output transform. */
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03006175 wl_list_for_each(head, &output->head_list, output_link) {
6176 wl_resource_for_each(resource, &head->resource_list) {
6177 wl_output_send_geometry(resource,
6178 output->x,
6179 output->y,
6180 head->mm_width,
6181 head->mm_height,
6182 head->subpixel,
6183 head->make,
6184 head->model,
6185 output->transform);
Ilia Bozhinov8564a0d2017-06-25 12:21:39 +00006186
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03006187 ver = wl_resource_get_version(resource);
6188 if (ver >= WL_OUTPUT_DONE_SINCE_VERSION)
6189 wl_output_send_done(resource);
6190 }
Roman Gilge97391c2019-03-29 13:01:06 +01006191 wl_resource_for_each(resource, &head->xdg_output_resource_list) {
6192 zxdg_output_v1_send_logical_position(resource,
6193 output->x,
6194 output->y);
6195 zxdg_output_v1_send_logical_size(resource,
6196 output->width,
6197 output->height);
6198 zxdg_output_v1_send_done(resource);
6199 }
Ilia Bozhinov8564a0d2017-06-25 12:21:39 +00006200 }
6201
6202 /* we must ensure that pointers are inside output, otherwise they disappear */
6203 mid_x = output->x + output->width / 2;
6204 mid_y = output->y + output->height / 2;
6205
6206 ev.mask = WESTON_POINTER_MOTION_ABS;
6207 ev.x = wl_fixed_to_double(wl_fixed_from_int(mid_x));
6208 ev.y = wl_fixed_to_double(wl_fixed_from_int(mid_y));
6209
6210 wl_list_for_each(seat, &output->compositor->seat_list, link) {
6211 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
6212
6213 if (pointer && pixman_region32_contains_point(&old_region,
6214 wl_fixed_to_int(pointer->x),
6215 wl_fixed_to_int(pointer->y),
6216 NULL))
6217 weston_pointer_move(pointer, &ev);
6218 }
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006219}
6220
6221/** Initializes a weston_output object with enough data so
6222 ** an output can be configured.
6223 *
6224 * \param output The weston_output object to initialize
6225 * \param compositor The compositor instance.
Pekka Paalanen26ac2e12017-04-03 13:18:13 +03006226 * \param name Name for the output (the string is copied).
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006227 *
6228 * Sets initial values for fields that are expected to be
6229 * configured either by compositors or backends.
Pekka Paalanenee16ea92017-03-29 16:53:50 +03006230 *
Pekka Paalanen26ac2e12017-04-03 13:18:13 +03006231 * The name is used in logs, and can be used by compositors as a configuration
6232 * identifier.
6233 *
Marius Vlad55d87362019-06-11 01:15:35 +03006234 * \ingroup output
Pekka Paalanenee16ea92017-03-29 16:53:50 +03006235 * \internal
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006236 */
6237WL_EXPORT void
Armin Krezović40087402016-09-30 14:11:12 +02006238weston_output_init(struct weston_output *output,
Pekka Paalanen26ac2e12017-04-03 13:18:13 +03006239 struct weston_compositor *compositor,
6240 const char *name)
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006241{
6242 output->compositor = compositor;
6243 output->destroying = 0;
Pekka Paalanen26ac2e12017-04-03 13:18:13 +03006244 output->name = strdup(name);
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006245 wl_list_init(&output->link);
Pekka Paalanen37b7c6e2017-11-07 10:15:01 +02006246 wl_signal_init(&output->user_destroy_signal);
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006247 output->enabled = false;
Ankit Nautiyal2690a772019-03-25 17:57:59 +05306248 output->desired_protection = WESTON_HDCP_DISABLE;
Ankit Nautiyal2844f8e2019-04-03 10:14:59 +05306249 output->allow_protection = true;
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006250
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03006251 wl_list_init(&output->head_list);
6252
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006253 /* Add some (in)sane defaults which can be used
6254 * for checking if an output was properly configured
6255 */
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006256 output->scale = 0;
6257 /* Can't use -1 on uint32_t and 0 is valid enum value */
6258 output->transform = UINT32_MAX;
Pekka Paalanen4b582c72017-03-30 16:04:58 +03006259
Pekka Paalanen4b582c72017-03-30 16:04:58 +03006260 pixman_region32_init(&output->region);
Pekka Paalanen42704142017-09-06 16:47:52 +03006261 wl_list_init(&output->mode_list);
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006262}
6263
6264/** Adds weston_output object to pending output list.
6265 *
6266 * \param output The weston_output object to add
6267 * \param compositor The compositor instance.
6268 *
Pekka Paalanenae6d35d2017-08-16 12:07:14 +03006269 * The opposite of this operation is built into weston_output_release().
Pekka Paalanenee16ea92017-03-29 16:53:50 +03006270 *
Marius Vlad9fdda7f2019-06-11 16:08:55 +03006271 * \ingroup compositor
Pekka Paalanenee16ea92017-03-29 16:53:50 +03006272 * \internal
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006273 */
6274WL_EXPORT void
6275weston_compositor_add_pending_output(struct weston_output *output,
6276 struct weston_compositor *compositor)
6277{
Pekka Paalanene952a012017-03-29 17:14:00 +03006278 assert(output->disable);
6279 assert(output->enable);
6280
Pekka Paalanenf0ca7962017-03-29 16:20:19 +03006281 wl_list_remove(&output->link);
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006282 wl_list_insert(compositor->pending_output_list.prev, &output->link);
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006283}
6284
Pekka Paalanen3e8f2012017-11-02 14:03:11 +02006285/** Create a string with the attached heads' names.
6286 *
6287 * The string must be free()'d.
Marius Vlad55d87362019-06-11 01:15:35 +03006288 *
6289 * \ingroup output
Pekka Paalanen3e8f2012017-11-02 14:03:11 +02006290 */
6291static char *
6292weston_output_create_heads_string(struct weston_output *output)
6293{
6294 FILE *fp;
6295 char *str = NULL;
6296 size_t size = 0;
6297 struct weston_head *head;
6298 const char *sep = "";
6299
6300 fp = open_memstream(&str, &size);
6301 if (!fp)
6302 return NULL;
6303
6304 wl_list_for_each(head, &output->head_list, output_link) {
6305 fprintf(fp, "%s%s", sep, head->name);
6306 sep = ", ";
6307 }
6308 fclose(fp);
6309
6310 return str;
6311}
6312
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006313/** Constructs a weston_output object that can be used by the compositor.
6314 *
Pekka Paalanencc201e42017-03-30 15:11:25 +03006315 * \param output The weston_output object that needs to be enabled. Must not
Pekka Paalanenddce54d2017-08-23 16:00:21 +03006316 * be enabled already. Must have at least one head attached.
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006317 *
6318 * Output coordinates are calculated and each new output is by default
6319 * assigned to the right of previous one.
6320 *
6321 * Sets up the transformation, zoom, and geometry of the output using
6322 * the properties that need to be configured by the compositor.
6323 *
6324 * Establishes a repaint timer for the output with the relevant display
6325 * object's event loop. See output_repaint_timer_handler().
6326 *
6327 * The output is assigned an ID. Weston can support up to 32 distinct
6328 * outputs, with IDs numbered from 0-31; the compositor's output_id_pool
6329 * is referred to and used to find the first available ID number, and
6330 * then this ID is marked as used in output_id_pool.
6331 *
6332 * The output is also assigned a Wayland global with the wl_output
6333 * external interface.
6334 *
6335 * Backend specific function is called to set up the output output.
6336 *
6337 * Output is added to the compositor's output list
6338 *
6339 * If the backend specific function fails, the weston_output object
6340 * is returned to a state it was before calling this function and
6341 * is added to the compositor's pending_output_list in case it needs
6342 * to be reconfigured or just so it can be destroyed at shutdown.
6343 *
6344 * 0 is returned on success, -1 on failure.
Marius Vlad55d87362019-06-11 01:15:35 +03006345 *
6346 * \ingroup output
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006347 */
6348WL_EXPORT int
6349weston_output_enable(struct weston_output *output)
6350{
Armin Krezović782f5df2016-09-30 14:11:11 +02006351 struct weston_compositor *c = output->compositor;
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006352 struct weston_output *iterator;
Pekka Paalanenec25b0a2017-08-24 16:08:49 +03006353 struct weston_head *head;
Pekka Paalanen3e8f2012017-11-02 14:03:11 +02006354 char *head_names;
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006355 int x = 0, y = 0;
6356
Pekka Paalanencc201e42017-03-30 15:11:25 +03006357 if (output->enabled) {
6358 weston_log("Error: attempt to enable an enabled output '%s'\n",
6359 output->name);
6360 return -1;
6361 }
6362
Pekka Paalanenddce54d2017-08-23 16:00:21 +03006363 if (wl_list_empty(&output->head_list)) {
6364 weston_log("Error: cannot enable output '%s' without heads.\n",
6365 output->name);
6366 return -1;
6367 }
6368
Pekka Paalanen586e1ac2017-09-14 16:17:59 +03006369 if (wl_list_empty(&output->mode_list) || !output->current_mode) {
6370 weston_log("Error: no video mode for output '%s'.\n",
6371 output->name);
6372 return -1;
6373 }
6374
Pekka Paalanenec25b0a2017-08-24 16:08:49 +03006375 wl_list_for_each(head, &output->head_list, output_link) {
6376 assert(head->make);
6377 assert(head->model);
6378 }
6379
Armin Krezović782f5df2016-09-30 14:11:11 +02006380 iterator = container_of(c->output_list.prev,
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006381 struct weston_output, link);
6382
Armin Krezović782f5df2016-09-30 14:11:11 +02006383 if (!wl_list_empty(&c->output_list))
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006384 x = iterator->x + iterator->width;
6385
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006386 /* Make sure the scale is set up */
6387 assert(output->scale);
6388
6389 /* Make sure we have a transform set */
6390 assert(output->transform != UINT32_MAX);
6391
Armin Krezović782f5df2016-09-30 14:11:11 +02006392 output->x = x;
6393 output->y = y;
6394 output->dirty = 1;
6395 output->original_scale = output->scale;
6396
Marius Vlad3a2f8292019-11-04 17:53:46 +02006397 wl_signal_init(&output->frame_signal);
6398 wl_signal_init(&output->destroy_signal);
6399
Armin Krezović782f5df2016-09-30 14:11:11 +02006400 weston_output_transform_scale_init(output, output->transform, output->scale);
6401 weston_output_init_zoom(output);
6402
6403 weston_output_init_geometry(output, x, y);
6404 weston_output_damage(output);
6405
Armin Krezović782f5df2016-09-30 14:11:11 +02006406 wl_list_init(&output->animation_list);
Armin Krezović782f5df2016-09-30 14:11:11 +02006407 wl_list_init(&output->feedback_list);
Armin Krezović782f5df2016-09-30 14:11:11 +02006408
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006409 /* Enable the output (set up the crtc or create a
6410 * window representing the output, set up the
6411 * renderer, etc)
6412 */
6413 if (output->enable(output) < 0) {
6414 weston_log("Enabling output \"%s\" failed.\n", output->name);
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006415 return -1;
6416 }
6417
6418 weston_compositor_add_output(output->compositor, output);
6419
Pekka Paalanen3e8f2012017-11-02 14:03:11 +02006420 head_names = weston_output_create_heads_string(output);
6421 weston_log("Output '%s' enabled with head(s) %s\n",
6422 output->name, head_names);
6423 free(head_names);
6424
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006425 return 0;
6426}
6427
6428/** Converts a weston_output object to a pending output state, so it
6429 ** can be configured again or destroyed.
6430 *
6431 * \param output The weston_output object that needs to be disabled.
6432 *
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006433 * Calls a backend specific function to disable an output, in case
6434 * such function exists.
6435 *
Pekka Paalanenc65df642017-03-29 15:45:46 +03006436 * The backend specific disable function may choose to postpone the disabling
6437 * by returning a negative value, in which case this function returns early.
6438 * In that case the backend will guarantee the output will be disabled soon
6439 * by the backend calling this function again. One must not attempt to re-enable
6440 * the output until that happens.
6441 *
6442 * Otherwise, if the output is being used by the compositor, it is removed
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006443 * from weston's output_list (see weston_compositor_remove_output())
6444 * and is returned to a state it was before weston_output_enable()
6445 * was ran (see weston_output_enable_undo()).
6446 *
Pekka Paalanenc65df642017-03-29 15:45:46 +03006447 * See weston_output_init() for more information on the
6448 * state output is returned to.
Pekka Paalanencc201e42017-03-30 15:11:25 +03006449 *
6450 * If the output has never been enabled yet, this function can still be
6451 * called to ensure that the output is actually turned off rather than left
6452 * in the state it was discovered in.
Marius Vlad55d87362019-06-11 01:15:35 +03006453 *
6454 * \ingroup output
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006455 */
6456WL_EXPORT void
6457weston_output_disable(struct weston_output *output)
6458{
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006459 /* Should we rename this? */
6460 output->destroying = 1;
6461
Pekka Paalanenc65df642017-03-29 15:45:46 +03006462 /* Disable is called unconditionally also for not-enabled outputs,
6463 * because at compositor start-up, if there is an output that is
6464 * already on but the compositor wants to turn it off, we have to
6465 * forward the turn-off to the backend so it knows to do it.
6466 * The backend cannot initially turn off everything, because it
6467 * would cause unnecessary mode-sets for all outputs the compositor
6468 * wants to be on.
6469 */
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006470 if (output->disable(output) < 0)
6471 return;
6472
Pekka Paalanen4b582c72017-03-30 16:04:58 +03006473 if (output->enabled)
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006474 weston_compositor_remove_output(output);
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006475
6476 output->destroying = 0;
6477}
6478
Pekka Paalanen8a8dcac2017-08-17 17:29:36 +03006479/** Forces a synchronous call to heads_changed hook
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006480 *
6481 * \param compositor The compositor instance
Pekka Paalanen8a8dcac2017-08-17 17:29:36 +03006482 *
6483 * If there are new or changed heads, calls the heads_changed hook and
6484 * returns after the hook returns.
Marius Vlad9fdda7f2019-06-11 16:08:55 +03006485 *
6486 * \ingroup compositor
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006487 */
6488WL_EXPORT void
Pekka Paalanen8a8dcac2017-08-17 17:29:36 +03006489weston_compositor_flush_heads_changed(struct weston_compositor *compositor)
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006490{
Pekka Paalanen37e6c9e2017-08-15 13:00:02 +03006491 if (compositor->heads_changed_source) {
6492 wl_event_source_remove(compositor->heads_changed_source);
6493 weston_compositor_call_heads_changed(compositor);
6494 }
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006495}
6496
Pekka Paalanen37b7c6e2017-11-07 10:15:01 +02006497/** Add destroy callback for an output
6498 *
6499 * \param output The output to watch.
6500 * \param listener The listener to add. The \c notify member must be set.
6501 *
6502 * The listener callback will be called when user destroys an output. This
6503 * may be delayed by a backend in some cases. The main purpose of the
6504 * listener is to allow hooking up custom data to the output. The custom data
6505 * can be fetched via weston_output_get_destroy_listener() followed by
6506 * container_of().
6507 *
6508 * The \c data argument to the notify callback is the weston_output being
6509 * destroyed.
6510 *
6511 * @note This is for the final destruction of an output, not when it gets
6512 * disabled. If you want to keep track of enabled outputs, this is not it.
Marius Vlad55d87362019-06-11 01:15:35 +03006513 *
6514 * \ingroup ouput
Pekka Paalanen37b7c6e2017-11-07 10:15:01 +02006515 */
6516WL_EXPORT void
6517weston_output_add_destroy_listener(struct weston_output *output,
6518 struct wl_listener *listener)
6519{
6520 wl_signal_add(&output->user_destroy_signal, listener);
6521}
6522
6523/** Look up destroy listener for an output
6524 *
6525 * \param output The output to query.
6526 * \param notify The notify function used used for the added destroy listener.
6527 * \return The listener, or NULL if not found.
6528 *
6529 * This looks up the previously added destroy listener struct based on the
6530 * notify function it has. The listener can be used to access user data
6531 * through \c container_of().
6532 *
6533 * \sa wl_signal_get() weston_output_add_destroy_listener()
Marius Vlad55d87362019-06-11 01:15:35 +03006534 * \ingroup output
Pekka Paalanen37b7c6e2017-11-07 10:15:01 +02006535 */
6536WL_EXPORT struct wl_listener *
6537weston_output_get_destroy_listener(struct weston_output *output,
6538 wl_notify_func_t notify)
6539{
6540 return wl_signal_get(&output->user_destroy_signal, notify);
6541}
6542
Pekka Paalanenee16ea92017-03-29 16:53:50 +03006543/** Uninitialize an output
6544 *
6545 * Removes the output from the list of enabled outputs if necessary, but
6546 * does not call the backend's output disable function. The output will no
6547 * longer be in the list of pending outputs either.
6548 *
6549 * All fields of weston_output become uninitialized, i.e. should not be used
6550 * anymore. The caller can free the memory after this.
6551 *
Marius Vlad55d87362019-06-11 01:15:35 +03006552 * \ingroup ouput
Pekka Paalanenee16ea92017-03-29 16:53:50 +03006553 * \internal
6554 */
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006555WL_EXPORT void
Pekka Paalanenae6d35d2017-08-16 12:07:14 +03006556weston_output_release(struct weston_output *output)
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006557{
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03006558 struct weston_head *head, *tmp;
6559
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006560 output->destroying = 1;
6561
Pekka Paalanen37b7c6e2017-11-07 10:15:01 +02006562 wl_signal_emit(&output->user_destroy_signal, output);
6563
Pekka Paalanendcbcfc72017-10-26 14:33:59 +03006564 if (output->idle_repaint_source)
6565 wl_event_source_remove(output->idle_repaint_source);
6566
Pekka Paalanen4b582c72017-03-30 16:04:58 +03006567 if (output->enabled)
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006568 weston_compositor_remove_output(output);
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006569
Pekka Paalanen4b582c72017-03-30 16:04:58 +03006570 pixman_region32_fini(&output->region);
Pekka Paalanenf0ca7962017-03-29 16:20:19 +03006571 wl_list_remove(&output->link);
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03006572
6573 wl_list_for_each_safe(head, tmp, &output->head_list, output_link)
6574 weston_head_detach(head);
6575
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006576 free(output->name);
6577}
6578
Pekka Paalanen1ae9d082017-11-02 14:11:53 +02006579/** Find an output by its given name
6580 *
6581 * \param compositor The compositor to search in.
6582 * \param name The output name to search for.
6583 * \return An existing output with the given name, or NULL if not found.
6584 *
Marius Vlad9fdda7f2019-06-11 16:08:55 +03006585 * \ingroup compositor
Pekka Paalanen1ae9d082017-11-02 14:11:53 +02006586 */
6587WL_EXPORT struct weston_output *
6588weston_compositor_find_output_by_name(struct weston_compositor *compositor,
6589 const char *name)
6590{
6591 struct weston_output *output;
6592
6593 wl_list_for_each(output, &compositor->output_list, link)
6594 if (strcmp(output->name, name) == 0)
6595 return output;
6596
6597 wl_list_for_each(output, &compositor->pending_output_list, link)
6598 if (strcmp(output->name, name) == 0)
6599 return output;
6600
6601 return NULL;
6602}
6603
6604/** Create a named output
6605 *
6606 * \param compositor The compositor.
6607 * \param name The name for the output.
6608 * \return A new \c weston_output, or NULL on failure.
6609 *
6610 * This creates a new weston_output that starts with no heads attached.
6611 *
6612 * An output must be configured and it must have at least one head before
6613 * it can be enabled.
6614 *
Marius Vlad9fdda7f2019-06-11 16:08:55 +03006615 * \ingroup compositor
Pekka Paalanen1ae9d082017-11-02 14:11:53 +02006616 */
6617WL_EXPORT struct weston_output *
6618weston_compositor_create_output(struct weston_compositor *compositor,
6619 const char *name)
6620{
6621 assert(compositor->backend->create_output);
6622
6623 if (weston_compositor_find_output_by_name(compositor, name)) {
6624 weston_log("Warning: attempted to create an output with a "
6625 "duplicate name '%s'.\n", name);
6626 return NULL;
6627 }
6628
6629 return compositor->backend->create_output(compositor, name);
6630}
6631
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03006632/** Create an output for an unused head
6633 *
6634 * \param compositor The compositor.
6635 * \param head The head to attach to the output.
6636 * \return A new \c weston_output, or NULL on failure.
6637 *
6638 * This creates a new weston_output that starts with the given head attached.
6639 * The output inherits the name of the head. The head must not be already
6640 * attached to another output.
6641 *
6642 * An output must be configured before it can be enabled.
6643 *
Marius Vlad9fdda7f2019-06-11 16:08:55 +03006644 * \ingroup compositor
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03006645 */
6646WL_EXPORT struct weston_output *
6647weston_compositor_create_output_with_head(struct weston_compositor *compositor,
6648 struct weston_head *head)
6649{
6650 struct weston_output *output;
6651
Pekka Paalanen1ae9d082017-11-02 14:11:53 +02006652 output = weston_compositor_create_output(compositor, head->name);
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03006653 if (!output)
6654 return NULL;
6655
6656 if (weston_output_attach_head(output, head) < 0) {
Pekka Paalanen42c0e142017-10-27 12:07:49 +03006657 weston_output_destroy(output);
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03006658 return NULL;
6659 }
6660
6661 return output;
6662}
6663
6664/** Destroy an output
6665 *
6666 * \param output The output to destroy.
6667 *
6668 * The heads attached to the given output are detached and become unused again.
6669 *
6670 * It is not necessary to explicitly destroy all outputs at compositor exit.
Leandro Ribeiroca640d52020-01-27 19:12:01 -03006671 * weston_compositor_destroy() will automatically destroy any remaining
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03006672 * outputs.
6673 *
Marius Vlad55d87362019-06-11 01:15:35 +03006674 * \ingroup ouput
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03006675 */
6676WL_EXPORT void
6677weston_output_destroy(struct weston_output *output)
6678{
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03006679 output->destroy(output);
6680}
6681
Pekka Paalanencf0a4762017-04-04 16:36:07 +03006682/** When you need a head...
6683 *
6684 * This function is a hack, used until all code has been converted to become
6685 * multi-head aware.
6686 *
6687 * \param output The weston_output whose head to get.
6688 * \return The first head in the output's list.
Marius Vlad55d87362019-06-11 01:15:35 +03006689 *
6690 * \ingroup ouput
Pekka Paalanencf0a4762017-04-04 16:36:07 +03006691 */
6692WL_EXPORT struct weston_head *
6693weston_output_get_first_head(struct weston_output *output)
6694{
6695 if (wl_list_empty(&output->head_list))
6696 return NULL;
6697
6698 return container_of(output->head_list.next,
6699 struct weston_head, output_link);
6700}
6701
Ankit Nautiyal2844f8e2019-04-03 10:14:59 +05306702/** Allow/Disallow content-protection support for an output
6703 *
6704 * This function sets the allow_protection member for an output. Setting of
6705 * this field will allow the compositor to attempt content-protection for this
6706 * output, for a backend that supports the content-protection protocol.
6707 *
6708 * \param output The weston_output for whom the content-protection is to be
6709 * allowed.
6710 * \param allow_protection The bool value which is to be set.
6711 */
6712WL_EXPORT void
6713weston_output_allow_protection(struct weston_output *output,
6714 bool allow_protection)
6715{
6716 output->allow_protection = allow_protection;
6717}
6718
Benjamin Franzke315b3dc2011-03-08 11:32:57 +01006719static void
Roman Gilge97391c2019-03-29 13:01:06 +01006720xdg_output_unlist(struct wl_resource *resource)
6721{
6722 wl_list_remove(wl_resource_get_link(resource));
6723}
6724
6725static void
6726xdg_output_destroy(struct wl_client *client, struct wl_resource *resource)
6727{
6728 wl_resource_destroy(resource);
6729}
6730
6731static const struct zxdg_output_v1_interface xdg_output_interface = {
6732 xdg_output_destroy
6733};
6734
6735static void
6736xdg_output_manager_destroy(struct wl_client *client,
6737 struct wl_resource *resource)
6738{
6739 wl_resource_destroy(resource);
6740}
6741
6742static void
6743xdg_output_manager_get_xdg_output(struct wl_client *client,
6744 struct wl_resource *manager,
6745 uint32_t id,
6746 struct wl_resource *output_resource)
6747{
6748 int version = wl_resource_get_version(manager);
6749 struct weston_head *head = wl_resource_get_user_data(output_resource);
6750 struct weston_output *output = head->output;
6751 struct wl_resource *resource;
6752
6753 resource = wl_resource_create(client, &zxdg_output_v1_interface,
6754 version, id);
6755 if (resource == NULL) {
6756 wl_client_post_no_memory(client);
6757 return;
6758 }
6759
6760 wl_list_insert(&head->xdg_output_resource_list,
6761 wl_resource_get_link(resource));
6762
6763 wl_resource_set_implementation(resource, &xdg_output_interface,
6764 NULL, xdg_output_unlist);
6765
6766 zxdg_output_v1_send_logical_position(resource, output->x, output->y);
6767 zxdg_output_v1_send_logical_size(resource,
6768 output->width,
6769 output->height);
6770 if (version >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION)
6771 zxdg_output_v1_send_name(resource, head->name);
6772
6773 zxdg_output_v1_send_done(resource);
6774}
6775
6776static const struct zxdg_output_manager_v1_interface xdg_output_manager_interface = {
6777 xdg_output_manager_destroy,
6778 xdg_output_manager_get_xdg_output
6779};
6780
6781static void
6782bind_xdg_output_manager(struct wl_client *client,
6783 void *data, uint32_t version, uint32_t id)
6784{
6785 struct wl_resource *resource;
6786
6787 resource = wl_resource_create(client, &zxdg_output_manager_v1_interface,
6788 version, id);
6789 if (resource == NULL) {
6790 wl_client_post_no_memory(client);
6791 return;
6792 }
6793
6794 wl_resource_set_implementation(resource, &xdg_output_manager_interface,
6795 NULL, NULL);
6796}
6797
6798static void
Pekka Paalanenb0420ae2014-01-08 15:39:17 +02006799destroy_viewport(struct wl_resource *resource)
Jonny Lamb8ae35902013-11-26 18:19:45 +01006800{
Jonny Lamb74130762013-11-26 18:19:46 +01006801 struct weston_surface *surface =
6802 wl_resource_get_user_data(resource);
6803
Pekka Paalanen4826f872016-04-22 14:14:38 +03006804 if (!surface)
6805 return;
6806
Pekka Paalanenb0420ae2014-01-08 15:39:17 +02006807 surface->viewport_resource = NULL;
Pekka Paalanenf0cad482014-03-14 14:38:16 +02006808 surface->pending.buffer_viewport.buffer.src_width =
6809 wl_fixed_from_int(-1);
6810 surface->pending.buffer_viewport.surface.width = -1;
George Kiagiadakis8f9e87f2014-06-13 18:14:20 +02006811 surface->pending.buffer_viewport.changed = 1;
Jonny Lamb8ae35902013-11-26 18:19:45 +01006812}
6813
6814static void
Pekka Paalanenb0420ae2014-01-08 15:39:17 +02006815viewport_destroy(struct wl_client *client,
6816 struct wl_resource *resource)
Jonny Lamb8ae35902013-11-26 18:19:45 +01006817{
6818 wl_resource_destroy(resource);
6819}
6820
6821static void
Pekka Paalanen0b4c5352014-03-14 14:38:17 +02006822viewport_set_source(struct wl_client *client,
6823 struct wl_resource *resource,
6824 wl_fixed_t src_x,
6825 wl_fixed_t src_y,
6826 wl_fixed_t src_width,
6827 wl_fixed_t src_height)
6828{
6829 struct weston_surface *surface =
6830 wl_resource_get_user_data(resource);
6831
Pekka Paalanen4826f872016-04-22 14:14:38 +03006832 if (!surface) {
6833 wl_resource_post_error(resource,
6834 WP_VIEWPORT_ERROR_NO_SURFACE,
6835 "wl_surface for this viewport is no longer exists");
6836 return;
6837 }
6838
6839 assert(surface->viewport_resource == resource);
Pekka Paalanen201769a2016-04-26 14:42:11 +03006840 assert(surface->resource);
Pekka Paalanen0b4c5352014-03-14 14:38:17 +02006841
Pekka Paalanen2c8b5f52014-04-04 14:22:12 +03006842 if (src_width == wl_fixed_from_int(-1) &&
Pekka Paalanen201769a2016-04-26 14:42:11 +03006843 src_height == wl_fixed_from_int(-1) &&
6844 src_x == wl_fixed_from_int(-1) &&
6845 src_y == wl_fixed_from_int(-1)) {
6846 /* unset source rect */
Pekka Paalanen0b4c5352014-03-14 14:38:17 +02006847 surface->pending.buffer_viewport.buffer.src_width =
6848 wl_fixed_from_int(-1);
George Kiagiadakis8f9e87f2014-06-13 18:14:20 +02006849 surface->pending.buffer_viewport.changed = 1;
Pekka Paalanen2c8b5f52014-04-04 14:22:12 +03006850 return;
Pekka Paalanen0b4c5352014-03-14 14:38:17 +02006851 }
Pekka Paalanen2c8b5f52014-04-04 14:22:12 +03006852
Pekka Paalanen201769a2016-04-26 14:42:11 +03006853 if (src_width <= 0 || src_height <= 0 || src_x < 0 || src_y < 0) {
Pekka Paalanen2c8b5f52014-04-04 14:22:12 +03006854 wl_resource_post_error(resource,
Pekka Paalanene95ad5c2016-04-15 14:47:08 +03006855 WP_VIEWPORT_ERROR_BAD_VALUE,
Pekka Paalanen201769a2016-04-26 14:42:11 +03006856 "wl_surface@%d viewport source "
6857 "w=%f <= 0, h=%f <= 0, x=%f < 0, or y=%f < 0",
6858 wl_resource_get_id(surface->resource),
Pekka Paalanen2c8b5f52014-04-04 14:22:12 +03006859 wl_fixed_to_double(src_width),
Pekka Paalanen201769a2016-04-26 14:42:11 +03006860 wl_fixed_to_double(src_height),
6861 wl_fixed_to_double(src_x),
6862 wl_fixed_to_double(src_y));
Pekka Paalanen2c8b5f52014-04-04 14:22:12 +03006863 return;
6864 }
6865
6866 surface->pending.buffer_viewport.buffer.src_x = src_x;
6867 surface->pending.buffer_viewport.buffer.src_y = src_y;
6868 surface->pending.buffer_viewport.buffer.src_width = src_width;
6869 surface->pending.buffer_viewport.buffer.src_height = src_height;
George Kiagiadakis8f9e87f2014-06-13 18:14:20 +02006870 surface->pending.buffer_viewport.changed = 1;
Pekka Paalanen0b4c5352014-03-14 14:38:17 +02006871}
6872
6873static void
6874viewport_set_destination(struct wl_client *client,
6875 struct wl_resource *resource,
6876 int32_t dst_width,
6877 int32_t dst_height)
6878{
6879 struct weston_surface *surface =
6880 wl_resource_get_user_data(resource);
6881
Pekka Paalanen4826f872016-04-22 14:14:38 +03006882 if (!surface) {
6883 wl_resource_post_error(resource,
6884 WP_VIEWPORT_ERROR_NO_SURFACE,
6885 "wl_surface for this viewport no longer exists");
6886 return;
6887 }
6888
6889 assert(surface->viewport_resource == resource);
Pekka Paalanen0b4c5352014-03-14 14:38:17 +02006890
Pekka Paalanen2c8b5f52014-04-04 14:22:12 +03006891 if (dst_width == -1 && dst_height == -1) {
6892 /* unset destination size */
Pekka Paalanen0b4c5352014-03-14 14:38:17 +02006893 surface->pending.buffer_viewport.surface.width = -1;
George Kiagiadakis8f9e87f2014-06-13 18:14:20 +02006894 surface->pending.buffer_viewport.changed = 1;
Pekka Paalanen2c8b5f52014-04-04 14:22:12 +03006895 return;
Pekka Paalanen0b4c5352014-03-14 14:38:17 +02006896 }
Pekka Paalanen2c8b5f52014-04-04 14:22:12 +03006897
6898 if (dst_width <= 0 || dst_height <= 0) {
6899 wl_resource_post_error(resource,
Pekka Paalanene95ad5c2016-04-15 14:47:08 +03006900 WP_VIEWPORT_ERROR_BAD_VALUE,
Pekka Paalanen2c8b5f52014-04-04 14:22:12 +03006901 "destination size must be positive (%dx%d)",
6902 dst_width, dst_height);
6903 return;
6904 }
6905
6906 surface->pending.buffer_viewport.surface.width = dst_width;
6907 surface->pending.buffer_viewport.surface.height = dst_height;
George Kiagiadakis8f9e87f2014-06-13 18:14:20 +02006908 surface->pending.buffer_viewport.changed = 1;
Pekka Paalanen0b4c5352014-03-14 14:38:17 +02006909}
6910
Pekka Paalanene95ad5c2016-04-15 14:47:08 +03006911static const struct wp_viewport_interface viewport_interface = {
Pekka Paalanenb0420ae2014-01-08 15:39:17 +02006912 viewport_destroy,
Pekka Paalanen0b4c5352014-03-14 14:38:17 +02006913 viewport_set_source,
6914 viewport_set_destination
Jonny Lamb8ae35902013-11-26 18:19:45 +01006915};
6916
6917static void
Pekka Paalanen9c5a0d92016-04-15 16:42:49 +03006918viewporter_destroy(struct wl_client *client,
6919 struct wl_resource *resource)
Jonny Lamb8ae35902013-11-26 18:19:45 +01006920{
6921 wl_resource_destroy(resource);
6922}
6923
6924static void
Pekka Paalanen9c5a0d92016-04-15 16:42:49 +03006925viewporter_get_viewport(struct wl_client *client,
6926 struct wl_resource *viewporter,
6927 uint32_t id,
6928 struct wl_resource *surface_resource)
Jonny Lamb8ae35902013-11-26 18:19:45 +01006929{
Pekka Paalanen9c5a0d92016-04-15 16:42:49 +03006930 int version = wl_resource_get_version(viewporter);
Pekka Paalanen0b4c5352014-03-14 14:38:17 +02006931 struct weston_surface *surface =
6932 wl_resource_get_user_data(surface_resource);
Jonny Lamb8ae35902013-11-26 18:19:45 +01006933 struct wl_resource *resource;
6934
Pekka Paalanenb0420ae2014-01-08 15:39:17 +02006935 if (surface->viewport_resource) {
Pekka Paalanen9c5a0d92016-04-15 16:42:49 +03006936 wl_resource_post_error(viewporter,
Pekka Paalanene95ad5c2016-04-15 14:47:08 +03006937 WP_VIEWPORTER_ERROR_VIEWPORT_EXISTS,
Pekka Paalanenb0420ae2014-01-08 15:39:17 +02006938 "a viewport for that surface already exists");
Jonny Lamb74130762013-11-26 18:19:46 +01006939 return;
6940 }
6941
Pekka Paalanene95ad5c2016-04-15 14:47:08 +03006942 resource = wl_resource_create(client, &wp_viewport_interface,
Pekka Paalanen0b4c5352014-03-14 14:38:17 +02006943 version, id);
Jonny Lamb8ae35902013-11-26 18:19:45 +01006944 if (resource == NULL) {
6945 wl_client_post_no_memory(client);
6946 return;
6947 }
6948
Pekka Paalanenb0420ae2014-01-08 15:39:17 +02006949 wl_resource_set_implementation(resource, &viewport_interface,
6950 surface, destroy_viewport);
Jonny Lamb74130762013-11-26 18:19:46 +01006951
Pekka Paalanenb0420ae2014-01-08 15:39:17 +02006952 surface->viewport_resource = resource;
Jonny Lamb8ae35902013-11-26 18:19:45 +01006953}
6954
Pekka Paalanen9c5a0d92016-04-15 16:42:49 +03006955static const struct wp_viewporter_interface viewporter_interface = {
6956 viewporter_destroy,
6957 viewporter_get_viewport
Jonny Lamb8ae35902013-11-26 18:19:45 +01006958};
6959
6960static void
Pekka Paalanen9c5a0d92016-04-15 16:42:49 +03006961bind_viewporter(struct wl_client *client,
6962 void *data, uint32_t version, uint32_t id)
Jonny Lamb8ae35902013-11-26 18:19:45 +01006963{
6964 struct wl_resource *resource;
6965
Pekka Paalanene95ad5c2016-04-15 14:47:08 +03006966 resource = wl_resource_create(client, &wp_viewporter_interface,
Derek Foreman1909c102015-11-26 14:17:47 -06006967 version, id);
Jonny Lamb8ae35902013-11-26 18:19:45 +01006968 if (resource == NULL) {
6969 wl_client_post_no_memory(client);
6970 return;
6971 }
6972
Pekka Paalanen9c5a0d92016-04-15 16:42:49 +03006973 wl_resource_set_implementation(resource, &viewporter_interface,
Jonny Lamb8ae35902013-11-26 18:19:45 +01006974 NULL, NULL);
6975}
6976
6977static void
Pekka Paalanen133e4392014-09-23 22:08:46 -04006978destroy_presentation_feedback(struct wl_resource *feedback_resource)
6979{
6980 struct weston_presentation_feedback *feedback;
6981
6982 feedback = wl_resource_get_user_data(feedback_resource);
6983
6984 wl_list_remove(&feedback->link);
6985 free(feedback);
6986}
6987
6988static void
Pekka Paalanen31f7d782014-09-23 22:08:43 -04006989presentation_destroy(struct wl_client *client, struct wl_resource *resource)
6990{
6991 wl_resource_destroy(resource);
6992}
6993
6994static void
6995presentation_feedback(struct wl_client *client,
Pekka Paalanen133e4392014-09-23 22:08:46 -04006996 struct wl_resource *presentation_resource,
6997 struct wl_resource *surface_resource,
Pekka Paalanen31f7d782014-09-23 22:08:43 -04006998 uint32_t callback)
6999{
Pekka Paalanen133e4392014-09-23 22:08:46 -04007000 struct weston_surface *surface;
7001 struct weston_presentation_feedback *feedback;
7002
7003 surface = wl_resource_get_user_data(surface_resource);
7004
Bryce Harringtonde16d892014-11-20 22:21:57 -08007005 feedback = zalloc(sizeof *feedback);
7006 if (feedback == NULL)
Pekka Paalanen133e4392014-09-23 22:08:46 -04007007 goto err_calloc;
7008
7009 feedback->resource = wl_resource_create(client,
Pekka Paalanenb00c79b2016-02-18 16:53:27 +02007010 &wp_presentation_feedback_interface,
Pekka Paalanen133e4392014-09-23 22:08:46 -04007011 1, callback);
7012 if (!feedback->resource)
7013 goto err_create;
7014
7015 wl_resource_set_implementation(feedback->resource, NULL, feedback,
7016 destroy_presentation_feedback);
7017
7018 wl_list_insert(&surface->pending.feedback_list, &feedback->link);
7019
7020 return;
7021
7022err_create:
7023 free(feedback);
7024
7025err_calloc:
7026 wl_client_post_no_memory(client);
Pekka Paalanen31f7d782014-09-23 22:08:43 -04007027}
7028
Pekka Paalanenb00c79b2016-02-18 16:53:27 +02007029static const struct wp_presentation_interface presentation_implementation = {
Pekka Paalanen31f7d782014-09-23 22:08:43 -04007030 presentation_destroy,
7031 presentation_feedback
7032};
7033
7034static void
7035bind_presentation(struct wl_client *client,
7036 void *data, uint32_t version, uint32_t id)
7037{
7038 struct weston_compositor *compositor = data;
7039 struct wl_resource *resource;
7040
Pekka Paalanenb00c79b2016-02-18 16:53:27 +02007041 resource = wl_resource_create(client, &wp_presentation_interface,
Derek Foreman1909c102015-11-26 14:17:47 -06007042 version, id);
Pekka Paalanen31f7d782014-09-23 22:08:43 -04007043 if (resource == NULL) {
7044 wl_client_post_no_memory(client);
7045 return;
7046 }
7047
7048 wl_resource_set_implementation(resource, &presentation_implementation,
7049 compositor, NULL);
Pekka Paalanenb00c79b2016-02-18 16:53:27 +02007050 wp_presentation_send_clock_id(resource, compositor->presentation_clock);
Pekka Paalanen31f7d782014-09-23 22:08:43 -04007051}
7052
7053static void
Kristian Høgsberga8873122011-11-23 10:39:34 -05007054compositor_bind(struct wl_client *client,
7055 void *data, uint32_t version, uint32_t id)
7056{
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05007057 struct weston_compositor *compositor = data;
Jason Ekstranda85118c2013-06-27 20:17:02 -05007058 struct wl_resource *resource;
Kristian Høgsberga8873122011-11-23 10:39:34 -05007059
Jason Ekstranda85118c2013-06-27 20:17:02 -05007060 resource = wl_resource_create(client, &wl_compositor_interface,
Derek Foreman1909c102015-11-26 14:17:47 -06007061 version, id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07007062 if (resource == NULL) {
7063 wl_client_post_no_memory(client);
7064 return;
7065 }
7066
7067 wl_resource_set_implementation(resource, &compositor_interface,
7068 compositor, NULL);
Kristian Høgsberga8873122011-11-23 10:39:34 -05007069}
7070
Daniel Stonece62cb32018-07-20 09:46:24 +01007071static const char *
7072output_repaint_status_text(struct weston_output *output)
7073{
7074 switch (output->repaint_status) {
7075 case REPAINT_NOT_SCHEDULED:
7076 return "no repaint";
7077 case REPAINT_BEGIN_FROM_IDLE:
7078 return "start_repaint_loop scheduled";
7079 case REPAINT_SCHEDULED:
7080 return "repaint scheduled";
7081 case REPAINT_AWAITING_COMPLETION:
7082 return "awaiting completion";
7083 }
7084
7085 assert(!"output_repaint_status_text missing enum");
7086 return NULL;
7087}
7088
7089static void
7090debug_scene_view_print_buffer(FILE *fp, struct weston_view *view)
7091{
7092 struct weston_buffer *buffer = view->surface->buffer_ref.buffer;
7093 struct wl_shm_buffer *shm;
7094 struct linux_dmabuf_buffer *dmabuf;
Marius Vlad00a6e012018-11-20 17:52:31 +02007095 const struct pixel_format_info *pixel_info = NULL;
Daniel Stonece62cb32018-07-20 09:46:24 +01007096
7097 if (!buffer) {
7098 fprintf(fp, "\t\t[buffer not available]\n");
7099 return;
7100 }
7101
7102 shm = wl_shm_buffer_get(buffer->resource);
7103 if (shm) {
Marius Vlad00a6e012018-11-20 17:52:31 +02007104 uint32_t _format = wl_shm_buffer_get_format(shm);
7105 pixel_info = pixel_format_get_info_shm(_format);
Daniel Stonece62cb32018-07-20 09:46:24 +01007106 fprintf(fp, "\t\tSHM buffer\n");
Marius Vlad00a6e012018-11-20 17:52:31 +02007107 fprintf(fp, "\t\t\tformat: 0x%lx %s\n",
7108 (unsigned long) _format,
7109 pixel_info ? pixel_info->drm_format_name : "UNKNOWN");
Daniel Stonece62cb32018-07-20 09:46:24 +01007110 return;
7111 }
7112
7113 dmabuf = linux_dmabuf_buffer_get(buffer->resource);
7114 if (dmabuf) {
Marius Vlad00a6e012018-11-20 17:52:31 +02007115 pixel_info = pixel_format_get_info(dmabuf->attributes.format);
Daniel Stonece62cb32018-07-20 09:46:24 +01007116 fprintf(fp, "\t\tdmabuf buffer\n");
Marius Vlad00a6e012018-11-20 17:52:31 +02007117 fprintf(fp, "\t\t\tformat: 0x%lx %s\n",
7118 (unsigned long) dmabuf->attributes.format,
7119 pixel_info ? pixel_info->drm_format_name : "UNKNOWN");
Daniel Stonece62cb32018-07-20 09:46:24 +01007120 fprintf(fp, "\t\t\tmodifier: 0x%llx\n",
7121 (unsigned long long) dmabuf->attributes.modifier[0]);
7122 return;
7123 }
7124
Marius Vlad253ba9a2019-03-17 18:22:21 +02007125 fprintf(fp, "\t\tEGL buffer\n");
Daniel Stonece62cb32018-07-20 09:46:24 +01007126}
7127
7128static void
7129debug_scene_view_print(FILE *fp, struct weston_view *view, int view_idx)
7130{
7131 struct weston_compositor *ec = view->surface->compositor;
7132 struct weston_output *output;
7133 char desc[512];
7134 pixman_box32_t *box;
7135 uint32_t surface_id = 0;
7136 pid_t pid = 0;
7137
7138 if (view->surface->resource) {
7139 struct wl_resource *resource = view->surface->resource;
7140 wl_client_get_credentials(wl_resource_get_client(resource),
7141 &pid, NULL, NULL);
7142 surface_id = wl_resource_get_id(view->surface->resource);
7143 }
7144
7145 if (!view->surface->get_label ||
7146 view->surface->get_label(view->surface, desc, sizeof(desc)) < 0) {
7147 strcpy(desc, "[no description available]");
7148 }
7149 fprintf(fp, "\tView %d (role %s, PID %d, surface ID %u, %s, %p):\n",
7150 view_idx, view->surface->role_name, pid, surface_id,
7151 desc, view);
7152
7153 box = pixman_region32_extents(&view->transform.boundingbox);
7154 fprintf(fp, "\t\tposition: (%d, %d) -> (%d, %d)\n",
7155 box->x1, box->y1, box->x2, box->y2);
7156 box = pixman_region32_extents(&view->transform.opaque);
7157
Michael Olbrichb7e5f102020-08-11 16:33:35 +02007158 if (weston_view_is_opaque(view, &view->transform.boundingbox)) {
Daniel Stonece62cb32018-07-20 09:46:24 +01007159 fprintf(fp, "\t\t[fully opaque]\n");
7160 } else if (!pixman_region32_not_empty(&view->transform.opaque)) {
7161 fprintf(fp, "\t\t[not opaque]\n");
7162 } else {
7163 fprintf(fp, "\t\t[opaque: (%d, %d) -> (%d, %d)]\n",
7164 box->x1, box->y1, box->x2, box->y2);
7165 }
7166
7167 if (view->alpha < 1.0)
7168 fprintf(fp, "\t\talpha: %f\n", view->alpha);
7169
7170 if (view->output_mask != 0) {
7171 bool first_output = true;
7172 fprintf(fp, "\t\toutputs: ");
7173 wl_list_for_each(output, &ec->output_list, link) {
7174 if (!(view->output_mask & (1 << output->id)))
7175 continue;
7176 fprintf(fp, "%s%d (%s)%s",
7177 (first_output) ? "" : ", ",
7178 output->id, output->name,
7179 (view->output == output) ? " (primary)" : "");
7180 first_output = false;
7181 }
7182 } else {
7183 fprintf(fp, "\t\t[no outputs]");
7184 }
7185
7186 fprintf(fp, "\n");
7187
7188 debug_scene_view_print_buffer(fp, view);
7189}
7190
Marius Vlad433f4e72019-02-17 22:14:23 +02007191static void
7192debug_scene_view_print_tree(struct weston_view *view,
Marius Vlada6acfa82019-03-17 18:10:09 +02007193 FILE *fp, int *view_idx)
Marius Vlad433f4e72019-02-17 22:14:23 +02007194{
7195 struct weston_subsurface *sub;
7196 struct weston_view *ev;
7197
7198 /*
7199 * print the view first, then we recursively go on printing
7200 * sub-surfaces. We bail out once no more sub-surfaces are available.
7201 */
Marius Vlada6acfa82019-03-17 18:10:09 +02007202 debug_scene_view_print(fp, view, *view_idx);
Marius Vlad433f4e72019-02-17 22:14:23 +02007203
7204 /* no more sub-surfaces */
7205 if (wl_list_empty(&view->surface->subsurface_list))
7206 return;
7207
7208 wl_list_for_each(sub, &view->surface->subsurface_list, parent_link) {
7209 wl_list_for_each(ev, &sub->surface->views, surface_link) {
Michael Olbrichef5f3232020-04-29 09:03:15 +02007210 /* only print the child views of the current view */
7211 if (ev->parent_view != view)
Marius Vlad433f4e72019-02-17 22:14:23 +02007212 continue;
Marius Vlada6acfa82019-03-17 18:10:09 +02007213
7214 (*view_idx)++;
Marius Vlad433f4e72019-02-17 22:14:23 +02007215 debug_scene_view_print_tree(ev, fp, view_idx);
7216 }
7217 }
7218}
7219
Daniel Stonece62cb32018-07-20 09:46:24 +01007220/**
7221 * Output information on how libweston is currently composing the scene
7222 * graph.
Marius Vlad9fdda7f2019-06-11 16:08:55 +03007223 *
7224 * \ingroup compositor
Daniel Stonece62cb32018-07-20 09:46:24 +01007225 */
7226WL_EXPORT char *
7227weston_compositor_print_scene_graph(struct weston_compositor *ec)
7228{
7229 struct weston_output *output;
7230 struct weston_layer *layer;
7231 struct timespec now;
7232 int layer_idx = 0;
7233 FILE *fp;
7234 char *ret;
7235 size_t len;
7236 int err;
7237
7238 fp = open_memstream(&ret, &len);
7239 assert(fp);
7240
7241 weston_compositor_read_presentation_clock(ec, &now);
7242 fprintf(fp, "Weston scene graph at %ld.%09ld:\n\n",
7243 now.tv_sec, now.tv_nsec);
7244
7245 wl_list_for_each(output, &ec->output_list, link) {
7246 struct weston_head *head;
7247 int head_idx = 0;
7248
7249 fprintf(fp, "Output %d (%s):\n", output->id, output->name);
7250 assert(output->enabled);
7251
7252 fprintf(fp, "\tposition: (%d, %d) -> (%d, %d)\n",
7253 output->x, output->y,
7254 output->x + output->width,
7255 output->y + output->height);
7256 fprintf(fp, "\tmode: %dx%d@%.3fHz\n",
7257 output->current_mode->width,
7258 output->current_mode->height,
7259 output->current_mode->refresh / 1000.0);
7260 fprintf(fp, "\tscale: %d\n", output->scale);
7261
7262 fprintf(fp, "\trepaint status: %s\n",
7263 output_repaint_status_text(output));
7264 if (output->repaint_status == REPAINT_SCHEDULED)
7265 fprintf(fp, "\tnext repaint: %ld.%09ld\n",
7266 output->next_repaint.tv_sec,
7267 output->next_repaint.tv_nsec);
7268
7269 wl_list_for_each(head, &output->head_list, output_link) {
7270 fprintf(fp, "\tHead %d (%s): %sconnected\n",
7271 head_idx++, head->name,
7272 (head->connected) ? "" : "not ");
7273 }
7274 }
7275
7276 fprintf(fp, "\n");
7277
7278 wl_list_for_each(layer, &ec->layer_list, link) {
7279 struct weston_view *view;
7280 int view_idx = 0;
7281
7282 fprintf(fp, "Layer %d (pos 0x%lx):\n", layer_idx++,
7283 (unsigned long) layer->position);
7284
7285 if (!weston_layer_mask_is_infinite(layer)) {
7286 fprintf(fp, "\t[mask: (%d, %d) -> (%d,%d)]\n\n",
7287 layer->mask.x1, layer->mask.y1,
7288 layer->mask.x2, layer->mask.y2);
7289 }
7290
Marius Vlada6acfa82019-03-17 18:10:09 +02007291 wl_list_for_each(view, &layer->view_list.link, layer_link.link) {
7292 debug_scene_view_print_tree(view, fp, &view_idx);
7293 view_idx++;
7294 }
Daniel Stonece62cb32018-07-20 09:46:24 +01007295
7296 if (wl_list_empty(&layer->view_list.link))
7297 fprintf(fp, "\t[no views]\n");
7298
7299 fprintf(fp, "\n");
7300 }
7301
7302 err = fclose(fp);
7303 assert(err == 0);
7304
7305 return ret;
7306}
7307
7308/**
7309 * Called when the 'scene-graph' debug scope is bound by a client. This
7310 * one-shot weston-debug scope prints the current scene graph when bound,
7311 * and then terminates the stream.
7312 */
7313static void
Marius Vladdad882a2019-07-17 15:43:53 +03007314debug_scene_graph_cb(struct weston_log_subscription *sub, void *data)
Daniel Stonece62cb32018-07-20 09:46:24 +01007315{
7316 struct weston_compositor *ec = data;
7317 char *str = weston_compositor_print_scene_graph(ec);
7318
Marius Vladdad882a2019-07-17 15:43:53 +03007319 weston_log_subscription_printf(sub, "%s", str);
Daniel Stonece62cb32018-07-20 09:46:24 +01007320 free(str);
Marius Vladdad882a2019-07-17 15:43:53 +03007321 weston_log_subscription_complete(sub);
Daniel Stonece62cb32018-07-20 09:46:24 +01007322}
7323
Giulio Camuffo459137b2014-10-11 23:56:24 +03007324/** Create the compositor.
7325 *
7326 * This functions creates and initializes a compositor instance.
7327 *
7328 * \param display The Wayland display to be used.
7329 * \param user_data A pointer to an object that can later be retrieved
Marius Vlada2dace22019-06-12 16:05:44 +03007330 * \param log_ctx A pointer to weston_debug_compositor
Giulio Camuffo459137b2014-10-11 23:56:24 +03007331 * using the \ref weston_compositor_get_user_data function.
7332 * \return The compositor instance on success or NULL on failure.
Marius Vlad9fdda7f2019-06-11 16:08:55 +03007333 *
7334 * \ingroup compositor
Giulio Camuffo459137b2014-10-11 23:56:24 +03007335 */
7336WL_EXPORT struct weston_compositor *
Marius Vlad880b4852019-04-07 17:07:58 +03007337weston_compositor_create(struct wl_display *display,
Marius Vlad3d7d9782019-04-17 12:35:38 +03007338 struct weston_log_context *log_ctx,
Marius Vlad880b4852019-04-07 17:07:58 +03007339 void *user_data)
Kristian Høgsbergce5325d2010-06-14 11:54:00 -04007340{
Giulio Camuffo459137b2014-10-11 23:56:24 +03007341 struct weston_compositor *ec;
Kristian Høgsbergfbdbbdc2008-11-28 17:06:06 -05007342 struct wl_event_loop *loop;
Ossama Othmana50e6e42013-05-14 09:48:26 -07007343
Leandro Ribeirobd9c0a62020-01-17 10:47:49 -03007344 if (!log_ctx)
7345 return NULL;
7346
Giulio Camuffo459137b2014-10-11 23:56:24 +03007347 ec = zalloc(sizeof *ec);
7348 if (!ec)
7349 return NULL;
7350
Leandro Ribeirobd9c0a62020-01-17 10:47:49 -03007351 ec->weston_log_ctx = log_ctx;
Giulio Camuffo459137b2014-10-11 23:56:24 +03007352 ec->wl_display = display;
7353 ec->user_data = user_data;
Kristian Høgsberg02e79dc2012-04-12 09:55:26 -04007354 wl_signal_init(&ec->destroy_signal);
Kristian Høgsbergf03a04a2014-04-06 22:04:50 -07007355 wl_signal_init(&ec->create_surface_signal);
Kristian Høgsberg02e79dc2012-04-12 09:55:26 -04007356 wl_signal_init(&ec->activate_signal);
Tiago Vignattifb2adba2013-06-12 15:43:21 -03007357 wl_signal_init(&ec->transform_signal);
Tiago Vignatti1d01b012012-09-27 17:48:36 +03007358 wl_signal_init(&ec->kill_signal);
Ander Conselvan de Oliveiraa4575632013-02-21 18:35:23 +02007359 wl_signal_init(&ec->idle_signal);
7360 wl_signal_init(&ec->wake_signal);
Jan Arne Petersen42feced2012-06-21 21:52:17 +02007361 wl_signal_init(&ec->show_input_panel_signal);
7362 wl_signal_init(&ec->hide_input_panel_signal);
Jan Arne Petersen14da96b2013-04-18 16:47:28 +02007363 wl_signal_init(&ec->update_input_panel_signal);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01007364 wl_signal_init(&ec->seat_created_signal);
Richard Hughes59d5da72013-05-01 21:52:11 +01007365 wl_signal_init(&ec->output_created_signal);
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +02007366 wl_signal_init(&ec->output_destroyed_signal);
Ander Conselvan de Oliveiraa8a9baf2014-01-29 18:47:52 +02007367 wl_signal_init(&ec->output_moved_signal);
David Fort0de859e2016-05-27 23:22:57 +02007368 wl_signal_init(&ec->output_resized_signal);
Pekka Paalanen37e6c9e2017-08-15 13:00:02 +03007369 wl_signal_init(&ec->heads_changed_signal);
Pekka Paalanen8dc6db82018-03-20 13:29:40 +02007370 wl_signal_init(&ec->output_heads_changed_signal);
Kristian Høgsberg61741a22013-09-17 16:02:57 -07007371 wl_signal_init(&ec->session_signal);
Robert Beckettc569bdc2019-07-10 16:40:12 +01007372 ec->session_active = true;
Kristian Høgsberg16eb6752008-10-08 22:51:32 -04007373
Casey Dahlin58ba1372012-04-19 22:50:08 -04007374 ec->output_id_pool = 0;
Giulio Camuffobab996e2014-10-12 00:24:25 +03007375 ec->repaint_msec = DEFAULT_REPAINT_WINDOW;
Casey Dahlin58ba1372012-04-19 22:50:08 -04007376
Jonas Ådahl94e2e2d2014-10-18 18:42:19 +02007377 ec->activate_serial = 1;
7378
Louis-Francis Ratté-Bouliannec4689ff2017-11-28 20:42:47 -05007379 ec->touch_mode = WESTON_TOUCH_MODE_NORMAL;
7380
Ankit Nautiyal5cfe03c2019-03-28 15:05:42 +05307381 ec->content_protection = NULL;
7382
Derek Foreman152254b2015-11-26 14:17:48 -06007383 if (!wl_global_create(ec->wl_display, &wl_compositor_interface, 4,
Kristian Høgsberg919cddb2013-07-08 19:03:57 -04007384 ec, compositor_bind))
Giulio Camuffo459137b2014-10-11 23:56:24 +03007385 goto fail;
Kristian Høgsbergee02ca62008-12-21 23:37:12 -05007386
Giulio Camuffo954f1832014-10-11 18:27:30 +03007387 if (!wl_global_create(ec->wl_display, &wl_subcompositor_interface, 1,
Kristian Høgsberg919cddb2013-07-08 19:03:57 -04007388 ec, bind_subcompositor))
Giulio Camuffo459137b2014-10-11 23:56:24 +03007389 goto fail;
Pekka Paalanene67858b2013-04-25 13:57:42 +03007390
Pekka Paalanene95ad5c2016-04-15 14:47:08 +03007391 if (!wl_global_create(ec->wl_display, &wp_viewporter_interface, 1,
Pekka Paalanen9c5a0d92016-04-15 16:42:49 +03007392 ec, bind_viewporter))
Giulio Camuffo459137b2014-10-11 23:56:24 +03007393 goto fail;
Jonny Lamb8ae35902013-11-26 18:19:45 +01007394
Roman Gilge97391c2019-03-29 13:01:06 +01007395 if (!wl_global_create(ec->wl_display, &zxdg_output_manager_v1_interface, 2,
7396 ec, bind_xdg_output_manager))
7397 goto fail;
7398
Pekka Paalanenb00c79b2016-02-18 16:53:27 +02007399 if (!wl_global_create(ec->wl_display, &wp_presentation_interface, 1,
Pekka Paalanen31f7d782014-09-23 22:08:43 -04007400 ec, bind_presentation))
Giulio Camuffo459137b2014-10-11 23:56:24 +03007401 goto fail;
Pekka Paalanen31f7d782014-09-23 22:08:43 -04007402
Jonas Ådahl30d61d82014-10-22 21:21:17 +02007403 if (weston_input_init(ec) != 0)
7404 goto fail;
7405
Jason Ekstranda7af7042013-10-12 22:38:11 -05007406 wl_list_init(&ec->view_list);
Ander Conselvan de Oliveira8ad19822013-03-05 17:30:27 +02007407 wl_list_init(&ec->plane_list);
Daniel Stone725c2c32012-06-22 14:04:36 +01007408 wl_list_init(&ec->layer_list);
7409 wl_list_init(&ec->seat_list);
Armin Krezovića01ab6d2016-09-30 14:11:02 +02007410 wl_list_init(&ec->pending_output_list);
Daniel Stone725c2c32012-06-22 14:04:36 +01007411 wl_list_init(&ec->output_list);
Pekka Paalanen1adcbac2017-08-14 16:05:35 +03007412 wl_list_init(&ec->head_list);
Daniel Stone725c2c32012-06-22 14:04:36 +01007413 wl_list_init(&ec->key_binding_list);
Daniel Stone96d47c02013-11-19 11:37:12 +01007414 wl_list_init(&ec->modifier_binding_list);
Daniel Stone725c2c32012-06-22 14:04:36 +01007415 wl_list_init(&ec->button_binding_list);
Neil Robertsa28c6932013-10-03 16:43:04 +01007416 wl_list_init(&ec->touch_binding_list);
Daniel Stone725c2c32012-06-22 14:04:36 +01007417 wl_list_init(&ec->axis_binding_list);
Ander Conselvan de Oliveirac509d2b2012-11-08 17:20:45 +02007418 wl_list_init(&ec->debug_binding_list);
Daniel Stone725c2c32012-06-22 14:04:36 +01007419
Pekka Paalanen827b5d22016-06-29 11:54:26 +02007420 wl_list_init(&ec->plugin_api_list);
7421
Xiong Zhang97116532013-10-23 13:58:31 +08007422 weston_plane_init(&ec->primary_plane, ec, 0, 0);
Ander Conselvan de Oliveira8ad19822013-03-05 17:30:27 +02007423 weston_compositor_stack_plane(ec, &ec->primary_plane, NULL);
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04007424
Giulio Camuffo459137b2014-10-11 23:56:24 +03007425 wl_data_device_manager_init(ec->wl_display);
7426
7427 wl_display_init_shm(ec->wl_display);
7428
7429 loop = wl_display_get_event_loop(ec->wl_display);
7430 ec->idle_source = wl_event_loop_add_timer(loop, idle_handler, ec);
Daniel Stone6847b852017-03-01 11:34:08 +00007431 ec->repaint_timer =
7432 wl_event_loop_add_timer(loop, output_repaint_timer_handler,
7433 ec);
Giulio Camuffo459137b2014-10-11 23:56:24 +03007434
Quentin Glidic82681572016-12-17 13:40:51 +01007435 weston_layer_init(&ec->fade_layer, ec);
7436 weston_layer_init(&ec->cursor_layer, ec);
7437
7438 weston_layer_set_position(&ec->fade_layer, WESTON_LAYER_POSITION_FADE);
7439 weston_layer_set_position(&ec->cursor_layer,
7440 WESTON_LAYER_POSITION_CURSOR);
Giulio Camuffo459137b2014-10-11 23:56:24 +03007441
Daniel Stonece62cb32018-07-20 09:46:24 +01007442 ec->debug_scene =
Leandro Ribeiroce100192019-12-26 16:35:49 -03007443 weston_compositor_add_log_scope(ec, "scene-graph",
7444 "Scene graph details\n",
7445 debug_scene_graph_cb, NULL,
7446 ec);
Daniel Stonece62cb32018-07-20 09:46:24 +01007447
Marius Vladda104eb2019-09-05 14:31:01 +03007448 ec->timeline =
Leandro Ribeiroce100192019-12-26 16:35:49 -03007449 weston_compositor_add_log_scope(ec, "timeline",
7450 "Timeline event points\n",
7451 weston_timeline_create_subscription,
7452 weston_timeline_destroy_subscription,
7453 ec);
Giulio Camuffo459137b2014-10-11 23:56:24 +03007454 return ec;
7455
7456fail:
7457 free(ec);
7458 return NULL;
7459}
7460
Marius Vlad9fdda7f2019-06-11 16:08:55 +03007461/** weston_compositor_shutdown
7462 * \ingroup compositor
7463 */
Benjamin Franzkeb8263022011-08-30 11:32:47 +02007464WL_EXPORT void
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05007465weston_compositor_shutdown(struct weston_compositor *ec)
Matt Roper361d2ad2011-08-29 13:52:23 -07007466{
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05007467 struct weston_output *output, *next;
Matt Roper361d2ad2011-08-29 13:52:23 -07007468
Pekka Paalanend1591ae2012-01-02 16:06:56 +02007469 wl_event_source_remove(ec->idle_source);
7470
Matt Roper361d2ad2011-08-29 13:52:23 -07007471 /* Destroy all outputs associated with this compositor */
Tiago Vignattib303a1d2011-12-18 22:27:40 +02007472 wl_list_for_each_safe(output, next, &ec->output_list, link)
Matt Roper361d2ad2011-08-29 13:52:23 -07007473 output->destroy(output);
Pekka Paalanen4738f3b2012-01-02 15:47:07 +02007474
Armin Krezovića01ab6d2016-09-30 14:11:02 +02007475 /* Destroy all pending outputs associated with this compositor */
7476 wl_list_for_each_safe(output, next, &ec->pending_output_list, link)
7477 output->destroy(output);
7478
Ander Conselvan de Oliveira18536762013-12-20 21:07:00 +02007479 if (ec->renderer)
7480 ec->renderer->destroy(ec);
7481
Daniel Stone325fc2d2012-05-30 16:31:58 +01007482 weston_binding_list_destroy_all(&ec->key_binding_list);
Ryo Munakata27135af2015-07-17 13:07:42 +09007483 weston_binding_list_destroy_all(&ec->modifier_binding_list);
Daniel Stone325fc2d2012-05-30 16:31:58 +01007484 weston_binding_list_destroy_all(&ec->button_binding_list);
Neil Robertsa28c6932013-10-03 16:43:04 +01007485 weston_binding_list_destroy_all(&ec->touch_binding_list);
Daniel Stone325fc2d2012-05-30 16:31:58 +01007486 weston_binding_list_destroy_all(&ec->axis_binding_list);
Ander Conselvan de Oliveirac509d2b2012-11-08 17:20:45 +02007487 weston_binding_list_destroy_all(&ec->debug_binding_list);
Pekka Paalanend1591ae2012-01-02 16:06:56 +02007488
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04007489 weston_plane_release(&ec->primary_plane);
Matt Roper361d2ad2011-08-29 13:52:23 -07007490}
7491
Marius Vlad9fdda7f2019-06-11 16:08:55 +03007492/** weston_compositor_exit_with_code
7493 * \ingroup compositor
7494 */
Kristian Høgsbergaf4f2aa2013-02-15 20:53:20 -05007495WL_EXPORT void
Adam Jackson3c3f3b12019-10-16 16:02:59 -04007496weston_compositor_exit_with_code(struct weston_compositor *compositor,
Frederic Plourdec336f062014-10-29 14:44:33 -04007497 int exit_code)
7498{
Pekka Paalanenf5ef88f2014-11-18 15:57:04 +02007499 if (compositor->exit_code == EXIT_SUCCESS)
7500 compositor->exit_code = exit_code;
7501
Giulio Camuffo459137b2014-10-11 23:56:24 +03007502 weston_compositor_exit(compositor);
Frederic Plourdec336f062014-10-29 14:44:33 -04007503}
7504
Marius Vlad9fdda7f2019-06-11 16:08:55 +03007505/** weston_compositor_set_default_pointer_grab
7506 * \ingroup compositor
7507 */
Frederic Plourdec336f062014-10-29 14:44:33 -04007508WL_EXPORT void
Giulio Camuffocdb4d292013-11-14 23:42:53 +01007509weston_compositor_set_default_pointer_grab(struct weston_compositor *ec,
7510 const struct weston_pointer_grab_interface *interface)
7511{
7512 struct weston_seat *seat;
7513
7514 ec->default_pointer_grab = interface;
7515 wl_list_for_each(seat, &ec->seat_list, link) {
Derek Foreman1281a362015-07-31 16:55:32 -05007516 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
7517
7518 if (pointer)
7519 weston_pointer_set_default_grab(pointer, interface);
Giulio Camuffocdb4d292013-11-14 23:42:53 +01007520 }
7521}
7522
Marius Vlad9fdda7f2019-06-11 16:08:55 +03007523/** weston_compositor_set_presentation_clock
7524 * \ingroup compositor
7525 */
Pekka Paalanenb5eedad2014-09-23 22:08:45 -04007526WL_EXPORT int
7527weston_compositor_set_presentation_clock(struct weston_compositor *compositor,
7528 clockid_t clk_id)
7529{
7530 struct timespec ts;
7531
7532 if (clock_gettime(clk_id, &ts) < 0)
7533 return -1;
7534
7535 compositor->presentation_clock = clk_id;
7536
7537 return 0;
7538}
7539
Marius Vlad9fdda7f2019-06-11 16:08:55 +03007540/** For choosing the software clock, when the display hardware or API
Pekka Paalanenb5eedad2014-09-23 22:08:45 -04007541 * does not expose a compatible presentation timestamp.
Marius Vlad9fdda7f2019-06-11 16:08:55 +03007542 *
7543 * \ingroup compositor
Pekka Paalanenb5eedad2014-09-23 22:08:45 -04007544 */
7545WL_EXPORT int
7546weston_compositor_set_presentation_clock_software(
7547 struct weston_compositor *compositor)
7548{
7549 /* In order of preference */
7550 static const clockid_t clocks[] = {
7551 CLOCK_MONOTONIC_RAW, /* no jumps, no crawling */
7552 CLOCK_MONOTONIC_COARSE, /* no jumps, may crawl, fast & coarse */
7553 CLOCK_MONOTONIC, /* no jumps, may crawl */
7554 CLOCK_REALTIME_COARSE, /* may jump and crawl, fast & coarse */
7555 CLOCK_REALTIME /* may jump and crawl */
7556 };
7557 unsigned i;
7558
7559 for (i = 0; i < ARRAY_LENGTH(clocks); i++)
7560 if (weston_compositor_set_presentation_clock(compositor,
7561 clocks[i]) == 0)
7562 return 0;
7563
7564 weston_log("Error: no suitable presentation clock available.\n");
7565
7566 return -1;
7567}
7568
Pekka Paalanen662f3842015-03-18 12:17:26 +02007569/** Read the current time from the Presentation clock
7570 *
7571 * \param compositor
Marius Vlada2dace22019-06-12 16:05:44 +03007572 * \param[out] ts The current time.
Pekka Paalanen662f3842015-03-18 12:17:26 +02007573 *
7574 * \note Reading the current time in user space is always imprecise to some
7575 * degree.
7576 *
7577 * This function is never meant to fail. If reading the clock does fail,
7578 * an error message is logged and a zero time is returned. Callers are not
7579 * supposed to detect or react to failures.
Marius Vlad9fdda7f2019-06-11 16:08:55 +03007580 *
7581 * \ingroup compositor
Pekka Paalanen662f3842015-03-18 12:17:26 +02007582 */
7583WL_EXPORT void
7584weston_compositor_read_presentation_clock(
7585 const struct weston_compositor *compositor,
7586 struct timespec *ts)
7587{
7588 static bool warned;
7589 int ret;
7590
7591 ret = clock_gettime(compositor->presentation_clock, ts);
7592 if (ret < 0) {
7593 ts->tv_sec = 0;
7594 ts->tv_nsec = 0;
7595
7596 if (!warned)
7597 weston_log("Error: failure to read "
Antonio Borneo39578632019-04-26 23:57:31 +02007598 "the presentation clock %#x: '%s' (%d)\n",
7599 compositor->presentation_clock,
7600 strerror(errno), errno);
Pekka Paalanen662f3842015-03-18 12:17:26 +02007601 warned = true;
7602 }
7603}
7604
Pekka Paalanen230f3b12014-09-29 14:18:40 -04007605/** Import dmabuf buffer into current renderer
7606 *
7607 * \param compositor
7608 * \param buffer the dmabuf buffer to import
7609 * \return true on usable buffers, false otherwise
7610 *
7611 * This function tests that the linux_dmabuf_buffer is usable
7612 * for the current renderer. Returns false on unusable buffers. Usually
7613 * usability is tested by importing the dmabufs for composition.
7614 *
7615 * This hook is also used for detecting if the renderer supports
7616 * dmabufs at all. If the renderer hook is NULL, dmabufs are not
7617 * supported.
Marius Vlad9fdda7f2019-06-11 16:08:55 +03007618 *
7619 * \ingroup compositor
7620 */
Pekka Paalanen230f3b12014-09-29 14:18:40 -04007621WL_EXPORT bool
7622weston_compositor_import_dmabuf(struct weston_compositor *compositor,
7623 struct linux_dmabuf_buffer *buffer)
7624{
7625 struct weston_renderer *renderer;
7626
7627 renderer = compositor->renderer;
7628
7629 if (renderer->import_dmabuf == NULL)
7630 return false;
7631
7632 return renderer->import_dmabuf(compositor, buffer);
7633}
7634
Marius Vlad5a701542019-11-16 20:26:52 +02007635WL_EXPORT bool
7636weston_compositor_dmabuf_can_scanout(struct weston_compositor *compositor,
7637 struct linux_dmabuf_buffer *buffer)
7638{
7639 struct weston_backend *backend = compositor->backend;
7640
7641 if (backend->can_scanout_dmabuf == NULL)
7642 return false;
7643
7644 return backend->can_scanout_dmabuf(compositor, buffer);
7645}
7646
Giulio Camuffocdb4d292013-11-14 23:42:53 +01007647WL_EXPORT void
Kristian Høgsbergaf4f2aa2013-02-15 20:53:20 -05007648weston_version(int *major, int *minor, int *micro)
7649{
7650 *major = WESTON_VERSION_MAJOR;
7651 *minor = WESTON_VERSION_MINOR;
7652 *micro = WESTON_VERSION_MICRO;
7653}
7654
Daniel Stonee03c1112016-11-24 20:45:45 +00007655/**
7656 * Attempts to find a module path from the module map specified in the
7657 * environment. If found, writes the full path into the path variable.
7658 *
7659 * The module map is a string in environment variable WESTON_MODULE_MAP, where
7660 * each entry is of the form "name=path" and entries are separated by
7661 * semicolons. Whitespace is significant.
7662 *
7663 * \param name The name to search for.
7664 * \param path Where the path is written to if found.
7665 * \param path_len Allocated bytes at \c path .
7666 * \returns The length of the string written to path on success, or 0 if the
7667 * module was not specified in the environment map or path_len was too small.
7668 */
7669WL_EXPORT size_t
7670weston_module_path_from_env(const char *name, char *path, size_t path_len)
7671{
7672 const char *mapping = getenv("WESTON_MODULE_MAP");
7673 const char *end;
7674 const int name_len = strlen(name);
7675
7676 if (!mapping)
7677 return 0;
7678
7679 end = mapping + strlen(mapping);
7680 while (mapping < end && *mapping) {
7681 const char *filename, *next;
7682
7683 /* early out: impossibly short string */
7684 if (end - mapping < name_len + 1)
7685 return 0;
7686
7687 filename = &mapping[name_len + 1];
7688 next = strchrnul(mapping, ';');
7689
7690 if (strncmp(mapping, name, name_len) == 0 &&
7691 mapping[name_len] == '=') {
7692 size_t file_len = next - filename; /* no trailing NUL */
7693 if (file_len >= path_len)
7694 return 0;
7695 strncpy(path, filename, file_len);
7696 path[file_len] = '\0';
7697 return file_len;
7698 }
7699
7700 mapping = next + 1;
7701 }
7702
7703 return 0;
7704}
7705
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03007706WL_EXPORT void *
7707weston_load_module(const char *name, const char *entrypoint)
Kristian Høgsberg1c562182011-05-02 22:09:20 -04007708{
7709 char path[PATH_MAX];
7710 void *module, *init;
Daniel Stonebeb97e52016-11-28 12:13:54 +00007711 size_t len;
Kristian Høgsberg1c562182011-05-02 22:09:20 -04007712
U. Artie Eoff2e2384a2014-01-17 13:19:01 -08007713 if (name == NULL)
7714 return NULL;
7715
Derek Foreman3f86e502015-06-08 11:46:54 -05007716 if (name[0] != '/') {
Daniel Stonee03c1112016-11-24 20:45:45 +00007717 len = weston_module_path_from_env(name, path, sizeof path);
7718 if (len == 0)
Daniel Stonebeb97e52016-11-28 12:13:54 +00007719 len = snprintf(path, sizeof path, "%s/%s",
7720 LIBWESTON_MODULEDIR, name);
Derek Foreman3f86e502015-06-08 11:46:54 -05007721 } else {
Daniel Stonebeb97e52016-11-28 12:13:54 +00007722 len = snprintf(path, sizeof path, "%s", name);
Derek Foreman3f86e502015-06-08 11:46:54 -05007723 }
Kristian Høgsberg1c562182011-05-02 22:09:20 -04007724
Daniel Stonebeb97e52016-11-28 12:13:54 +00007725 /* snprintf returns the length of the string it would've written,
7726 * _excluding_ the NUL byte. So even being equal to the size of
7727 * our buffer is an error here. */
7728 if (len >= sizeof path)
7729 return NULL;
7730
Kristian Høgsberga6813d22012-09-12 12:21:01 -04007731 module = dlopen(path, RTLD_NOW | RTLD_NOLOAD);
7732 if (module) {
7733 weston_log("Module '%s' already loaded\n", path);
Pekka Paalanenf696ee92019-11-04 14:07:51 +02007734 } else {
7735 weston_log("Loading module '%s'\n", path);
7736 module = dlopen(path, RTLD_NOW);
7737 if (!module) {
7738 weston_log("Failed to load module: %s\n", dlerror());
7739 return NULL;
7740 }
Kristian Høgsberg1c562182011-05-02 22:09:20 -04007741 }
7742
7743 init = dlsym(module, entrypoint);
7744 if (!init) {
Pekka Paalanen1b3c1ea2012-06-11 14:06:04 +03007745 weston_log("Failed to lookup init function: %s\n", dlerror());
Rob Bradfordc9e64ab2012-12-05 18:47:10 +00007746 dlclose(module);
Kristian Høgsberg1c562182011-05-02 22:09:20 -04007747 return NULL;
7748 }
7749
7750 return init;
7751}
7752
Pekka Paalanen6ffbba32019-11-06 12:59:32 +02007753/** Add a compositor destroy listener only once
7754 *
7755 * \param compositor The compositor whose destroy to watch for.
7756 * \param listener The listener struct to initialize.
7757 * \param destroy_handler The callback when compositor is destroyed.
7758 * \return True if listener is added, or false if there already is a listener
7759 * with the given \c destroy_handler.
7760 *
7761 * This function does nothing and returns false if the given callback function
7762 * is already present in the weston_compositor destroy callbacks list.
7763 * Otherwise, this function initializes the given listener with the given
7764 * callback pointer and adds it to the compositor's destroy callbacks list.
7765 *
7766 * This can be used to ensure that plugin initialization is done only once
7767 * in case the same plugin is loaded multiple times. If this function returns
7768 * false, the plugin should be already initialized successfully.
7769 *
7770 * All plugins should register a destroy listener for cleaning up. Note, that
7771 * the plugin destruction order is not guaranteed: plugins that depend on other
7772 * plugins must be able to be torn down in arbitrary order.
7773 *
Leandro Ribeiroca640d52020-01-27 19:12:01 -03007774 * \sa weston_compositor_destroy
Pekka Paalanen6ffbba32019-11-06 12:59:32 +02007775 */
7776WL_EXPORT bool
7777weston_compositor_add_destroy_listener_once(struct weston_compositor *compositor,
7778 struct wl_listener *listener,
7779 wl_notify_func_t destroy_handler)
7780{
7781 if (wl_signal_get(&compositor->destroy_signal, destroy_handler))
7782 return false;
7783
7784 listener->notify = destroy_handler;
7785 wl_signal_add(&compositor->destroy_signal, listener);
7786 return true;
7787}
Giulio Camuffo459137b2014-10-11 23:56:24 +03007788
Leandro Ribeiroca640d52020-01-27 19:12:01 -03007789/** Destroys the compositor.
Giulio Camuffo459137b2014-10-11 23:56:24 +03007790 *
Leandro Ribeiroca640d52020-01-27 19:12:01 -03007791 * This function cleans up the compositor state and then destroys it.
Giulio Camuffo459137b2014-10-11 23:56:24 +03007792 *
Leandro Ribeiroca640d52020-01-27 19:12:01 -03007793 * @param compositor The compositor to be destroyed.
Marius Vlad9fdda7f2019-06-11 16:08:55 +03007794 *
Marius Vlad284d5342019-06-24 12:00:47 +03007795 * @ingroup compositor
Giulio Camuffo459137b2014-10-11 23:56:24 +03007796 */
7797WL_EXPORT void
Leandro Ribeiroca640d52020-01-27 19:12:01 -03007798weston_compositor_destroy(struct weston_compositor *compositor)
Giulio Camuffo459137b2014-10-11 23:56:24 +03007799{
7800 /* prevent further rendering while shutting down */
7801 compositor->state = WESTON_COMPOSITOR_OFFSCREEN;
7802
7803 wl_signal_emit(&compositor->destroy_signal, compositor);
7804
7805 weston_compositor_xkb_destroy(compositor);
7806
Giulio Camuffo2d24e642015-10-03 16:25:15 +03007807 if (compositor->backend)
7808 compositor->backend->destroy(compositor);
Pekka Paalanen827b5d22016-06-29 11:54:26 +02007809
Pekka Paalanen1adcbac2017-08-14 16:05:35 +03007810 /* The backend is responsible for destroying the heads. */
7811 assert(wl_list_empty(&compositor->head_list));
7812
Pekka Paalanen827b5d22016-06-29 11:54:26 +02007813 weston_plugin_api_destroy_list(compositor);
7814
Pekka Paalanen37e6c9e2017-08-15 13:00:02 +03007815 if (compositor->heads_changed_source)
7816 wl_event_source_remove(compositor->heads_changed_source);
7817
Leandro Ribeirof0149642019-12-18 15:52:18 -03007818 weston_log_scope_destroy(compositor->debug_scene);
Daniel Stonece62cb32018-07-20 09:46:24 +01007819 compositor->debug_scene = NULL;
Marius Vladda104eb2019-09-05 14:31:01 +03007820
Leandro Ribeirof0149642019-12-18 15:52:18 -03007821 weston_log_scope_destroy(compositor->timeline);
Marius Vladda104eb2019-09-05 14:31:01 +03007822 compositor->timeline = NULL;
Pekka Paalanena5630ea2017-10-12 13:13:42 +02007823
Giulio Camuffo459137b2014-10-11 23:56:24 +03007824 free(compositor);
7825}
7826
7827/** Instruct the compositor to exit.
7828 *
7829 * This functions does not directly destroy the compositor object, it merely
7830 * command it to start the tear down process. It is not guaranteed that the
7831 * tear down will happen immediately.
7832 *
7833 * \param compositor The compositor to tear down.
Marius Vlad9fdda7f2019-06-11 16:08:55 +03007834 *
7835 * \ingroup compositor
Giulio Camuffo459137b2014-10-11 23:56:24 +03007836 */
7837WL_EXPORT void
7838weston_compositor_exit(struct weston_compositor *compositor)
7839{
7840 compositor->exit(compositor);
7841}
7842
7843/** Return the user data stored in the compositor.
7844 *
7845 * This function returns the user data pointer set with user_data parameter
7846 * to the \ref weston_compositor_create function.
Marius Vlad9fdda7f2019-06-11 16:08:55 +03007847 *
7848 * \ingroup compositor
Giulio Camuffo459137b2014-10-11 23:56:24 +03007849 */
7850WL_EXPORT void *
7851weston_compositor_get_user_data(struct weston_compositor *compositor)
7852{
7853 return compositor->user_data;
7854}
Pekka Paalanendd186732016-06-03 14:49:54 +03007855
Pekka Paalanen50dbf382016-06-03 15:23:46 +03007856static const char * const backend_map[] = {
7857 [WESTON_BACKEND_DRM] = "drm-backend.so",
7858 [WESTON_BACKEND_FBDEV] = "fbdev-backend.so",
7859 [WESTON_BACKEND_HEADLESS] = "headless-backend.so",
7860 [WESTON_BACKEND_RDP] = "rdp-backend.so",
7861 [WESTON_BACKEND_WAYLAND] = "wayland-backend.so",
7862 [WESTON_BACKEND_X11] = "x11-backend.so",
7863};
7864
Pekka Paalanendd186732016-06-03 14:49:54 +03007865/** Load a backend into a weston_compositor
7866 *
7867 * A backend must be loaded to make a weston_compositor work. A backend
7868 * provides input and output capabilities, and determines the renderer to use.
7869 *
7870 * \param compositor A compositor that has not had a backend loaded yet.
7871 * \param backend Name of the backend file.
7872 * \param config_base A pointer to a backend-specific configuration
7873 * structure's 'base' member.
7874 *
7875 * \return 0 on success, or -1 on error.
Marius Vlad9fdda7f2019-06-11 16:08:55 +03007876 *
7877 * \ingroup compositor
Pekka Paalanendd186732016-06-03 14:49:54 +03007878 */
7879WL_EXPORT int
7880weston_compositor_load_backend(struct weston_compositor *compositor,
Pekka Paalanen50dbf382016-06-03 15:23:46 +03007881 enum weston_compositor_backend backend,
Pekka Paalanendd186732016-06-03 14:49:54 +03007882 struct weston_backend_config *config_base)
7883{
7884 int (*backend_init)(struct weston_compositor *c,
Pekka Paalanendd186732016-06-03 14:49:54 +03007885 struct weston_backend_config *config_base);
7886
Pekka Paalanend7e35112017-08-29 17:04:12 +03007887 if (compositor->backend) {
7888 weston_log("Error: attempt to load a backend when one is already loaded\n");
7889 return -1;
7890 }
7891
Quentin Glidic887c0182016-07-10 11:00:53 +02007892 if (backend >= ARRAY_LENGTH(backend_map))
Pekka Paalanen50dbf382016-06-03 15:23:46 +03007893 return -1;
7894
Quentin Glidic23e1d6f2016-12-02 14:08:44 +01007895 backend_init = weston_load_module(backend_map[backend], "weston_backend_init");
Pekka Paalanendd186732016-06-03 14:49:54 +03007896 if (!backend_init)
7897 return -1;
7898
Pekka Paalanend7e35112017-08-29 17:04:12 +03007899 if (backend_init(compositor, config_base) < 0) {
7900 compositor->backend = NULL;
7901 return -1;
7902 }
7903
7904 return 0;
Pekka Paalanendd186732016-06-03 14:49:54 +03007905}
Giulio Camuffo9c764df2016-06-29 11:54:27 +02007906
Marius Vlad9fdda7f2019-06-11 16:08:55 +03007907/** weston_compositor_load_xwayland
7908 * \ingroup compositor
7909 */
Giulio Camuffo9c764df2016-06-29 11:54:27 +02007910WL_EXPORT int
7911weston_compositor_load_xwayland(struct weston_compositor *compositor)
7912{
Quentin Glidic3d7ca3b2016-12-02 14:20:35 +01007913 int (*module_init)(struct weston_compositor *ec);
Giulio Camuffo9c764df2016-06-29 11:54:27 +02007914
Quentin Glidic3d7ca3b2016-12-02 14:20:35 +01007915 module_init = weston_load_module("xwayland.so", "weston_module_init");
Giulio Camuffo9c764df2016-06-29 11:54:27 +02007916 if (!module_init)
7917 return -1;
Quentin Glidic3d7ca3b2016-12-02 14:20:35 +01007918 if (module_init(compositor) < 0)
Giulio Camuffo9c764df2016-06-29 11:54:27 +02007919 return -1;
7920 return 0;
7921}
Vasilis Liaskovitis486b4632018-10-10 16:14:55 +02007922
7923/** Resolve an internal compositor error by disconnecting the client.
7924 *
7925 * This function is used in cases when the wl_buffer turns out
7926 * unusable and there is no fallback path.
7927 *
7928 * It is possible the fault is caused by a compositor bug, the underlying
7929 * graphics stack bug or normal behaviour, or perhaps a client mistake.
7930 * In any case, the options are to either composite garbage or nothing,
7931 * or disconnect the client. This is a helper function for the latter.
7932 *
7933 * The error is sent as an INVALID_OBJECT error on the client's wl_display.
7934 *
7935 * \param buffer The weston buffer that is unusable.
7936 * \param msg A custom error message attached to the protocol error.
7937 */
7938WL_EXPORT void
7939weston_buffer_send_server_error(struct weston_buffer *buffer,
7940 const char *msg)
7941{
7942 struct wl_client *client;
7943 struct wl_resource *display_resource;
7944 uint32_t id;
7945
7946 assert(buffer->resource);
7947 id = wl_resource_get_id(buffer->resource);
7948 client = wl_resource_get_client(buffer->resource);
7949 display_resource = wl_client_get_object(client, 1);
7950
7951 assert(display_resource);
7952 wl_resource_post_error(display_resource,
7953 WL_DISPLAY_ERROR_INVALID_OBJECT,
7954 "server error with "
7955 "wl_buffer@%u: %s", id, msg);
7956}
Ankit Nautiyal93dde242019-07-08 11:46:42 +05307957
7958WL_EXPORT void
7959weston_output_disable_planes_incr(struct weston_output *output)
7960{
7961 output->disable_planes++;
Ankit Nautiyal4fd38132019-07-08 15:12:19 +05307962 /*
7963 * If disable_planes changes from 0 to non-zero, it means some type of
7964 * recording of content has started, and therefore protection level of
7965 * the protected surfaces must be updated to avoid the recording of
7966 * the protected content.
7967 */
7968 if (output->disable_planes == 1)
7969 weston_schedule_surface_protection_update(output->compositor);
Ankit Nautiyal93dde242019-07-08 11:46:42 +05307970}
7971
7972WL_EXPORT void
7973weston_output_disable_planes_decr(struct weston_output *output)
7974{
7975 output->disable_planes--;
Ankit Nautiyal4fd38132019-07-08 15:12:19 +05307976 /*
7977 * If disable_planes changes from non-zero to 0, it means no content
7978 * recording is going on any more, and the protected and surfaces can be
7979 * shown without any apprehensions about content being recorded.
7980 */
7981 if (output->disable_planes == 0)
7982 weston_schedule_surface_protection_update(output->compositor);
7983
Ankit Nautiyal93dde242019-07-08 11:46:42 +05307984}