blob: b60f35def670ae3d3c4e9378eca2b9d3f63138dd [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>
Kristian Høgsberg890bc052008-12-30 14:31:33 -050054
Pekka Paalanenb5026542014-11-12 15:09:24 +020055#include "timeline.h"
56
Kristian Høgsberg82863022010-06-04 21:52:02 -040057#include "compositor.h"
Daniel Stonece62cb32018-07-20 09:46:24 +010058#include "weston-debug.h"
59#include "linux-dmabuf.h"
Pekka Paalanene95ad5c2016-04-15 14:47:08 +030060#include "viewporter-server-protocol.h"
Pekka Paalanenb00c79b2016-02-18 16:53:27 +020061#include "presentation-time-server-protocol.h"
Jon Cruz35b2eaa2015-06-15 15:37:08 -070062#include "shared/helpers.h"
Jon Cruz4678bab2015-06-15 15:37:07 -070063#include "shared/os-compatibility.h"
Bryce Harrington25a2bdd2016-08-03 17:40:52 -070064#include "shared/string-helpers.h"
Pekka Paalanenaa21f622015-07-03 15:44:50 +030065#include "shared/timespec-util.h"
Kristian Høgsberga411c8b2012-06-08 16:16:52 -040066#include "git-version.h"
Kristian Høgsbergaf4f2aa2013-02-15 20:53:20 -050067#include "version.h"
Pekka Paalanen827b5d22016-06-29 11:54:26 +020068#include "plugin-registry.h"
Kristian Høgsberg5ee1a602008-12-11 23:18:45 -050069
Pekka Paalanen0513a952014-05-21 16:17:27 +030070#define DEFAULT_REPAINT_WINDOW 7 /* milliseconds */
71
Ander Conselvan de Oliveira5c38ef42012-12-14 13:37:25 -020072static void
Pekka Paalanend72bad22017-03-29 17:01:41 +030073weston_output_update_matrix(struct weston_output *output);
74
75static void
Alexander Larsson0b135062013-05-28 16:23:36 +020076weston_output_transform_scale_init(struct weston_output *output,
77 uint32_t transform, uint32_t scale);
Ander Conselvan de Oliveira5c38ef42012-12-14 13:37:25 -020078
Rob Bradford27b17932013-06-26 18:08:46 +010079static void
Jason Ekstranda7af7042013-10-12 22:38:11 -050080weston_compositor_build_view_list(struct weston_compositor *compositor);
Rob Bradford27b17932013-06-26 18:08:46 +010081
Pekka Paalanendcac3512017-12-08 14:13:34 +020082static char *
83weston_output_create_heads_string(struct weston_output *output);
84
Pekka Paalanen6528c032017-03-28 15:27:10 +030085/** Send wl_output events for mode and scale changes
86 *
87 * \param head Send on all resources bound to this head.
88 * \param mode_changed If true, send the current mode.
89 * \param scale_changed If true, send the current scale.
90 */
91static void
92weston_mode_switch_send_events(struct weston_head *head,
93 bool mode_changed, bool scale_changed)
94{
95 struct weston_output *output = head->output;
96 struct wl_resource *resource;
97 int version;
98
99 wl_resource_for_each(resource, &head->resource_list) {
100 if (mode_changed) {
101 wl_output_send_mode(resource,
102 output->current_mode->flags,
103 output->current_mode->width,
104 output->current_mode->height,
105 output->current_mode->refresh);
106 }
107
108 version = wl_resource_get_version(resource);
109 if (version >= WL_OUTPUT_SCALE_SINCE_VERSION && scale_changed)
110 wl_output_send_scale(resource, output->current_scale);
111
112 if (version >= WL_OUTPUT_DONE_SINCE_VERSION)
113 wl_output_send_done(resource);
114 }
115}
116
117static void
118weston_mode_switch_finish(struct weston_output *output,
119 int mode_changed, int scale_changed)
Alex Wu2dda6042012-04-17 17:20:47 +0800120{
Ander Conselvan de Oliveira2bbb2b82012-12-14 13:37:26 -0200121 struct weston_seat *seat;
Pekka Paalanen1b9bf592017-03-27 12:15:38 +0300122 struct weston_head *head;
Ander Conselvan de Oliveira2bbb2b82012-12-14 13:37:26 -0200123 pixman_region32_t old_output_region;
Alexander Larsson355748e2013-05-28 16:23:38 +0200124
Ander Conselvan de Oliveira2bbb2b82012-12-14 13:37:26 -0200125 pixman_region32_init(&old_output_region);
126 pixman_region32_copy(&old_output_region, &output->region);
127
Ander Conselvan de Oliveira5c38ef42012-12-14 13:37:25 -0200128 /* Update output region and transformation matrix */
Hardeningff39efa2013-09-18 23:56:35 +0200129 weston_output_transform_scale_init(output, output->transform, output->current_scale);
Ander Conselvan de Oliveira5c38ef42012-12-14 13:37:25 -0200130
131 pixman_region32_init(&output->previous_damage);
132 pixman_region32_init_rect(&output->region, output->x, output->y,
133 output->width, output->height);
134
135 weston_output_update_matrix(output);
136
Ander Conselvan de Oliveira2bbb2b82012-12-14 13:37:26 -0200137 /* If a pointer falls outside the outputs new geometry, move it to its
138 * lower-right corner */
139 wl_list_for_each(seat, &output->compositor->seat_list, link) {
Derek Foreman1281a362015-07-31 16:55:32 -0500140 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
Ander Conselvan de Oliveira2bbb2b82012-12-14 13:37:26 -0200141 int32_t x, y;
142
143 if (!pointer)
144 continue;
145
146 x = wl_fixed_to_int(pointer->x);
147 y = wl_fixed_to_int(pointer->y);
148
149 if (!pixman_region32_contains_point(&old_output_region,
150 x, y, NULL) ||
151 pixman_region32_contains_point(&output->region,
152 x, y, NULL))
153 continue;
154
155 if (x >= output->x + output->width)
156 x = output->x + output->width - 1;
157 if (y >= output->y + output->height)
158 y = output->y + output->height - 1;
159
160 pointer->x = wl_fixed_from_int(x);
161 pointer->y = wl_fixed_from_int(y);
162 }
163
164 pixman_region32_fini(&old_output_region);
165
Derek Foremandd4cd332014-11-10 10:29:59 -0600166 if (!mode_changed && !scale_changed)
167 return;
168
Hardening57388e42013-09-18 23:56:36 +0200169 /* notify clients of the changes */
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +0300170 wl_list_for_each(head, &output->head_list, output_link)
171 weston_mode_switch_send_events(head,
172 mode_changed, scale_changed);
Derek Foreman6ae7bc92014-11-04 10:47:33 -0600173}
174
David Fort0de859e2016-05-27 23:22:57 +0200175static void
176weston_compositor_reflow_outputs(struct weston_compositor *compositor,
177 struct weston_output *resized_output, int delta_width);
178
Derek Foreman6ae7bc92014-11-04 10:47:33 -0600179WL_EXPORT int
180weston_output_mode_set_native(struct weston_output *output,
181 struct weston_mode *mode,
182 int32_t scale)
183{
184 int ret;
185 int mode_changed = 0, scale_changed = 0;
David Fort0de859e2016-05-27 23:22:57 +0200186 int32_t old_width;
Derek Foreman6ae7bc92014-11-04 10:47:33 -0600187
188 if (!output->switch_mode)
189 return -1;
190
191 if (!output->original_mode) {
192 mode_changed = 1;
193 ret = output->switch_mode(output, mode);
194 if (ret < 0)
195 return ret;
196 if (output->current_scale != scale) {
197 scale_changed = 1;
198 output->current_scale = scale;
Hardening57388e42013-09-18 23:56:36 +0200199 }
200 }
201
David Fort0de859e2016-05-27 23:22:57 +0200202 old_width = output->width;
Derek Foreman6ae7bc92014-11-04 10:47:33 -0600203 output->native_mode = mode;
204 output->native_scale = scale;
205
206 weston_mode_switch_finish(output, mode_changed, scale_changed);
207
David Fort0de859e2016-05-27 23:22:57 +0200208 if (mode_changed || scale_changed) {
209 weston_compositor_reflow_outputs(output->compositor, output, output->width - old_width);
210
211 wl_signal_emit(&output->compositor->output_resized_signal, output);
212 }
Derek Foreman6ae7bc92014-11-04 10:47:33 -0600213 return 0;
214}
215
216WL_EXPORT int
217weston_output_mode_switch_to_native(struct weston_output *output)
218{
219 int ret;
220 int mode_changed = 0, scale_changed = 0;
221
222 if (!output->switch_mode)
223 return -1;
224
225 if (!output->original_mode) {
226 weston_log("already in the native mode\n");
227 return -1;
228 }
229 /* the non fullscreen clients haven't seen a mode set since we
230 * switched into a temporary, so we need to notify them if the
231 * mode at that time is different from the native mode now.
232 */
233 mode_changed = (output->original_mode != output->native_mode);
234 scale_changed = (output->original_scale != output->native_scale);
235
236 ret = output->switch_mode(output, output->native_mode);
237 if (ret < 0)
238 return ret;
239
240 output->current_scale = output->native_scale;
241
242 output->original_mode = NULL;
243 output->original_scale = 0;
244
245 weston_mode_switch_finish(output, mode_changed, scale_changed);
246
247 return 0;
248}
249
250WL_EXPORT int
251weston_output_mode_switch_to_temporary(struct weston_output *output,
252 struct weston_mode *mode,
253 int32_t scale)
254{
255 int ret;
256
257 if (!output->switch_mode)
258 return -1;
259
260 /* original_mode is the last mode non full screen clients have seen,
261 * so we shouldn't change it if we already have one set.
262 */
263 if (!output->original_mode) {
264 output->original_mode = output->native_mode;
265 output->original_scale = output->native_scale;
266 }
267 ret = output->switch_mode(output, mode);
268 if (ret < 0)
269 return ret;
270
271 output->current_scale = scale;
272
273 weston_mode_switch_finish(output, 0, 0);
274
275 return 0;
Alex Wu2dda6042012-04-17 17:20:47 +0800276}
277
Benjamin Franzke06286262011-05-06 19:12:33 +0200278static void
Pekka Paalanen0cbd3b52012-10-10 12:49:28 +0300279region_init_infinite(pixman_region32_t *region)
280{
281 pixman_region32_init_rect(region, INT32_MIN, INT32_MIN,
282 UINT32_MAX, UINT32_MAX);
283}
284
Pekka Paalanene67858b2013-04-25 13:57:42 +0300285static struct weston_subsurface *
286weston_surface_to_subsurface(struct weston_surface *surface);
287
Jason Ekstranda7af7042013-10-12 22:38:11 -0500288WL_EXPORT struct weston_view *
289weston_view_create(struct weston_surface *surface)
290{
291 struct weston_view *view;
292
Bryce Harringtonde16d892014-11-20 22:21:57 -0800293 view = zalloc(sizeof *view);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500294 if (view == NULL)
295 return NULL;
296
297 view->surface = surface;
Daniel Stonefb4869d2016-12-09 16:27:54 +0000298 view->plane = &surface->compositor->primary_plane;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500299
Jason Ekstranda7af7042013-10-12 22:38:11 -0500300 /* Assign to surface */
301 wl_list_insert(&surface->views, &view->surface_link);
302
303 wl_signal_init(&view->destroy_signal);
304 wl_list_init(&view->link);
Giulio Camuffo412e6a52014-07-09 22:12:56 +0300305 wl_list_init(&view->layer_link.link);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500306
Jason Ekstranda7af7042013-10-12 22:38:11 -0500307 pixman_region32_init(&view->clip);
308
309 view->alpha = 1.0;
310 pixman_region32_init(&view->transform.opaque);
311
312 wl_list_init(&view->geometry.transformation_list);
313 wl_list_insert(&view->geometry.transformation_list,
314 &view->transform.position.link);
315 weston_matrix_init(&view->transform.position.matrix);
316 wl_list_init(&view->geometry.child_list);
Pekka Paalanen380adf52015-02-16 14:39:11 +0200317 pixman_region32_init(&view->geometry.scissor);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500318 pixman_region32_init(&view->transform.boundingbox);
319 view->transform.dirty = 1;
320
Jason Ekstranda7af7042013-10-12 22:38:11 -0500321 return view;
322}
323
Jason Ekstrand108865d2014-06-26 10:04:49 -0700324struct weston_frame_callback {
325 struct wl_resource *resource;
326 struct wl_list link;
327};
328
Pekka Paalanen133e4392014-09-23 22:08:46 -0400329struct weston_presentation_feedback {
330 struct wl_resource *resource;
331
332 /* XXX: could use just wl_resource_get_link() instead */
333 struct wl_list link;
Pekka Paalanenbf0e0312014-12-17 16:20:41 +0200334
335 /* The per-surface feedback flags */
336 uint32_t psf_flags;
Pekka Paalanen133e4392014-09-23 22:08:46 -0400337};
338
339static void
340weston_presentation_feedback_discard(
341 struct weston_presentation_feedback *feedback)
342{
Pekka Paalanenb00c79b2016-02-18 16:53:27 +0200343 wp_presentation_feedback_send_discarded(feedback->resource);
Pekka Paalanen133e4392014-09-23 22:08:46 -0400344 wl_resource_destroy(feedback->resource);
345}
346
347static void
348weston_presentation_feedback_discard_list(struct wl_list *list)
349{
350 struct weston_presentation_feedback *feedback, *tmp;
351
352 wl_list_for_each_safe(feedback, tmp, list, link)
353 weston_presentation_feedback_discard(feedback);
354}
355
356static void
357weston_presentation_feedback_present(
358 struct weston_presentation_feedback *feedback,
359 struct weston_output *output,
360 uint32_t refresh_nsec,
361 const struct timespec *ts,
Pekka Paalanen363aa7b2014-12-17 16:20:40 +0200362 uint64_t seq,
363 uint32_t flags)
Pekka Paalanen133e4392014-09-23 22:08:46 -0400364{
365 struct wl_client *client = wl_resource_get_client(feedback->resource);
Pekka Paalanen1b9bf592017-03-27 12:15:38 +0300366 struct weston_head *head;
Pekka Paalanen133e4392014-09-23 22:08:46 -0400367 struct wl_resource *o;
Alexandros Frantzis10d708d2017-12-13 13:27:54 +0200368 uint32_t tv_sec_hi;
369 uint32_t tv_sec_lo;
370 uint32_t tv_nsec;
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +0300371 bool done = false;
Pekka Paalanen133e4392014-09-23 22:08:46 -0400372
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +0300373 wl_list_for_each(head, &output->head_list, output_link) {
374 wl_resource_for_each(o, &head->resource_list) {
375 if (wl_resource_get_client(o) != client)
376 continue;
Pekka Paalanen133e4392014-09-23 22:08:46 -0400377
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +0300378 wp_presentation_feedback_send_sync_output(feedback->resource, o);
379 done = true;
380 }
381
382 /* For clone mode, send it for just one wl_output global,
383 * they are all equivalent anyway.
384 */
385 if (done)
386 break;
Pekka Paalanen133e4392014-09-23 22:08:46 -0400387 }
388
Alexandros Frantzis10d708d2017-12-13 13:27:54 +0200389 timespec_to_proto(ts, &tv_sec_hi, &tv_sec_lo, &tv_nsec);
Pekka Paalanenb00c79b2016-02-18 16:53:27 +0200390 wp_presentation_feedback_send_presented(feedback->resource,
Alexandros Frantzis10d708d2017-12-13 13:27:54 +0200391 tv_sec_hi, tv_sec_lo, tv_nsec,
Pekka Paalanenb00c79b2016-02-18 16:53:27 +0200392 refresh_nsec,
393 seq >> 32, seq & 0xffffffff,
394 flags | feedback->psf_flags);
Pekka Paalanen133e4392014-09-23 22:08:46 -0400395 wl_resource_destroy(feedback->resource);
396}
397
398static void
399weston_presentation_feedback_present_list(struct wl_list *list,
400 struct weston_output *output,
401 uint32_t refresh_nsec,
402 const struct timespec *ts,
Pekka Paalanen363aa7b2014-12-17 16:20:40 +0200403 uint64_t seq,
404 uint32_t flags)
Pekka Paalanen133e4392014-09-23 22:08:46 -0400405{
406 struct weston_presentation_feedback *feedback, *tmp;
407
Pekka Paalanenb00c79b2016-02-18 16:53:27 +0200408 assert(!(flags & WP_PRESENTATION_FEEDBACK_INVALID) ||
Pekka Paalanen363aa7b2014-12-17 16:20:40 +0200409 wl_list_empty(list));
410
Pekka Paalanen133e4392014-09-23 22:08:46 -0400411 wl_list_for_each_safe(feedback, tmp, list, link)
412 weston_presentation_feedback_present(feedback, output,
Pekka Paalanen363aa7b2014-12-17 16:20:40 +0200413 refresh_nsec, ts, seq,
414 flags);
Pekka Paalanen133e4392014-09-23 22:08:46 -0400415}
416
Jason Ekstrand7b982072014-05-20 14:33:03 -0500417static void
418surface_state_handle_buffer_destroy(struct wl_listener *listener, void *data)
419{
420 struct weston_surface_state *state =
421 container_of(listener, struct weston_surface_state,
422 buffer_destroy_listener);
423
424 state->buffer = NULL;
425}
426
427static void
428weston_surface_state_init(struct weston_surface_state *state)
429{
430 state->newly_attached = 0;
431 state->buffer = NULL;
432 state->buffer_destroy_listener.notify =
433 surface_state_handle_buffer_destroy;
434 state->sx = 0;
435 state->sy = 0;
436
Derek Foreman152254b2015-11-26 14:17:48 -0600437 pixman_region32_init(&state->damage_surface);
438 pixman_region32_init(&state->damage_buffer);
Jason Ekstrand7b982072014-05-20 14:33:03 -0500439 pixman_region32_init(&state->opaque);
440 region_init_infinite(&state->input);
441
442 wl_list_init(&state->frame_callback_list);
Pekka Paalanen133e4392014-09-23 22:08:46 -0400443 wl_list_init(&state->feedback_list);
Jason Ekstrand7b982072014-05-20 14:33:03 -0500444
445 state->buffer_viewport.buffer.transform = WL_OUTPUT_TRANSFORM_NORMAL;
446 state->buffer_viewport.buffer.scale = 1;
447 state->buffer_viewport.buffer.src_width = wl_fixed_from_int(-1);
448 state->buffer_viewport.surface.width = -1;
449 state->buffer_viewport.changed = 0;
450}
451
452static void
453weston_surface_state_fini(struct weston_surface_state *state)
454{
455 struct weston_frame_callback *cb, *next;
456
457 wl_list_for_each_safe(cb, next,
458 &state->frame_callback_list, link)
459 wl_resource_destroy(cb->resource);
460
Pekka Paalanen133e4392014-09-23 22:08:46 -0400461 weston_presentation_feedback_discard_list(&state->feedback_list);
462
Jason Ekstrand7b982072014-05-20 14:33:03 -0500463 pixman_region32_fini(&state->input);
464 pixman_region32_fini(&state->opaque);
Derek Foreman152254b2015-11-26 14:17:48 -0600465 pixman_region32_fini(&state->damage_surface);
466 pixman_region32_fini(&state->damage_buffer);
Jason Ekstrand7b982072014-05-20 14:33:03 -0500467
468 if (state->buffer)
469 wl_list_remove(&state->buffer_destroy_listener.link);
470 state->buffer = NULL;
471}
472
473static void
474weston_surface_state_set_buffer(struct weston_surface_state *state,
475 struct weston_buffer *buffer)
476{
477 if (state->buffer == buffer)
478 return;
479
480 if (state->buffer)
481 wl_list_remove(&state->buffer_destroy_listener.link);
482 state->buffer = buffer;
483 if (state->buffer)
484 wl_signal_add(&state->buffer->destroy_signal,
485 &state->buffer_destroy_listener);
486}
487
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500488WL_EXPORT struct weston_surface *
Kristian Høgsberg18c93002012-01-27 11:58:31 -0500489weston_surface_create(struct weston_compositor *compositor)
Kristian Høgsberg1a208d52009-02-10 14:20:26 -0500490{
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500491 struct weston_surface *surface;
Kristian Høgsberg77fb1672010-08-16 10:38:29 -0400492
Bryce Harringtonde16d892014-11-20 22:21:57 -0800493 surface = zalloc(sizeof *surface);
Kristian Høgsberg77fb1672010-08-16 10:38:29 -0400494 if (surface == NULL)
495 return NULL;
496
Jason Ekstrand26ed73c2013-06-06 22:34:41 -0500497 wl_signal_init(&surface->destroy_signal);
Jonas Ådahl5d9ca272016-07-22 17:48:03 +0800498 wl_signal_init(&surface->commit_signal);
Jason Ekstrand26ed73c2013-06-06 22:34:41 -0500499
Kristian Høgsberg1a208d52009-02-10 14:20:26 -0500500 surface->compositor = compositor;
Giulio Camuffo13b85bd2013-08-13 23:10:14 +0200501 surface->ref_count = 1;
Kristian Høgsberg27803c62010-06-06 22:23:21 -0400502
Pekka Paalanen952b6c82014-03-14 14:38:15 +0200503 surface->buffer_viewport.buffer.transform = WL_OUTPUT_TRANSFORM_NORMAL;
504 surface->buffer_viewport.buffer.scale = 1;
Pekka Paalanenf0cad482014-03-14 14:38:16 +0200505 surface->buffer_viewport.buffer.src_width = wl_fixed_from_int(-1);
506 surface->buffer_viewport.surface.width = -1;
Jason Ekstrand7b982072014-05-20 14:33:03 -0500507
508 weston_surface_state_init(&surface->pending);
509
Kristian Høgsberg20300ba2011-06-23 20:29:12 -0400510 pixman_region32_init(&surface->damage);
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -0500511 pixman_region32_init(&surface->opaque);
Pekka Paalanen8ec4ab62012-10-10 12:49:32 +0300512 region_init_infinite(&surface->input);
Kristian Høgsberg20300ba2011-06-23 20:29:12 -0400513
Jason Ekstranda7af7042013-10-12 22:38:11 -0500514 wl_list_init(&surface->views);
515
516 wl_list_init(&surface->frame_callback_list);
Pekka Paalanen133e4392014-09-23 22:08:46 -0400517 wl_list_init(&surface->feedback_list);
Kristian Høgsberg1e4b86a2008-11-23 23:41:08 -0500518
Pekka Paalanene67858b2013-04-25 13:57:42 +0300519 wl_list_init(&surface->subsurface_list);
520 wl_list_init(&surface->subsurface_list_pending);
521
Jason Ekstrand1e059042014-10-16 10:55:19 -0500522 weston_matrix_init(&surface->buffer_to_surface_matrix);
523 weston_matrix_init(&surface->surface_to_buffer_matrix);
524
Jonas Ådahld3414f22016-07-22 17:56:31 +0800525 wl_list_init(&surface->pointer_constraints);
526
Kristian Høgsberg77fb1672010-08-16 10:38:29 -0400527 return surface;
Kristian Høgsberg54879822008-11-23 17:07:32 -0500528}
529
Alex Wu8811bf92012-02-28 18:07:54 +0800530WL_EXPORT void
Kristian Høgsbergbbeefb02012-01-26 10:00:23 -0500531weston_surface_set_color(struct weston_surface *surface,
John Kåre Alsaker490d02a2012-09-30 02:57:21 +0200532 float red, float green, float blue, float alpha)
Kristian Høgsbergbbeefb02012-01-26 10:00:23 -0500533{
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100534 surface->compositor->renderer->surface_set_color(surface, red, green, blue, alpha);
Philipp Zabel195dade2018-09-03 19:44:59 +0200535 surface->is_opaque = !(alpha < 1.0);
Kristian Høgsbergbbeefb02012-01-26 10:00:23 -0500536}
537
Kristian Høgsberge4c1a5f2012-06-18 13:17:32 -0400538WL_EXPORT void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500539weston_view_to_global_float(struct weston_view *view,
540 float sx, float sy, float *x, float *y)
Pekka Paalanenece8a012012-02-08 15:23:15 +0200541{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500542 if (view->transform.enabled) {
Pekka Paalanenece8a012012-02-08 15:23:15 +0200543 struct weston_vector v = { { sx, sy, 0.0f, 1.0f } };
544
Jason Ekstranda7af7042013-10-12 22:38:11 -0500545 weston_matrix_transform(&view->transform.matrix, &v);
Pekka Paalanenece8a012012-02-08 15:23:15 +0200546
547 if (fabsf(v.f[3]) < 1e-6) {
Martin Minarik6d118362012-06-07 18:01:59 +0200548 weston_log("warning: numerical instability in "
Scott Moreau088c62e2013-02-11 04:45:38 -0700549 "%s(), divisor = %g\n", __func__,
Pekka Paalanenece8a012012-02-08 15:23:15 +0200550 v.f[3]);
551 *x = 0;
552 *y = 0;
553 return;
554 }
555
556 *x = v.f[0] / v.f[3];
557 *y = v.f[1] / v.f[3];
558 } else {
Jason Ekstranda7af7042013-10-12 22:38:11 -0500559 *x = sx + view->geometry.x;
560 *y = sy + view->geometry.y;
Pekka Paalanenece8a012012-02-08 15:23:15 +0200561 }
562}
563
Kristian Høgsbergd8bf90c2012-02-23 23:03:14 -0500564WL_EXPORT void
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200565weston_transformed_coord(int width, int height,
566 enum wl_output_transform transform,
Alexander Larssonedddbd12013-05-24 13:09:43 +0200567 int32_t scale,
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200568 float sx, float sy, float *bx, float *by)
569{
570 switch (transform) {
571 case WL_OUTPUT_TRANSFORM_NORMAL:
572 default:
573 *bx = sx;
574 *by = sy;
575 break;
576 case WL_OUTPUT_TRANSFORM_FLIPPED:
577 *bx = width - sx;
578 *by = sy;
579 break;
580 case WL_OUTPUT_TRANSFORM_90:
581 *bx = height - sy;
582 *by = sx;
583 break;
584 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
585 *bx = height - sy;
586 *by = width - sx;
587 break;
588 case WL_OUTPUT_TRANSFORM_180:
589 *bx = width - sx;
590 *by = height - sy;
591 break;
592 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
593 *bx = sx;
594 *by = height - sy;
595 break;
596 case WL_OUTPUT_TRANSFORM_270:
597 *bx = sy;
598 *by = width - sx;
599 break;
600 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
601 *bx = sy;
602 *by = sx;
603 break;
604 }
Alexander Larsson4ea95522013-05-22 14:41:37 +0200605
606 *bx *= scale;
607 *by *= scale;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200608}
609
610WL_EXPORT pixman_box32_t
611weston_transformed_rect(int width, int height,
612 enum wl_output_transform transform,
Alexander Larssonedddbd12013-05-24 13:09:43 +0200613 int32_t scale,
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200614 pixman_box32_t rect)
615{
616 float x1, x2, y1, y2;
617
618 pixman_box32_t ret;
619
Alexander Larsson4ea95522013-05-22 14:41:37 +0200620 weston_transformed_coord(width, height, transform, scale,
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200621 rect.x1, rect.y1, &x1, &y1);
Alexander Larsson4ea95522013-05-22 14:41:37 +0200622 weston_transformed_coord(width, height, transform, scale,
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200623 rect.x2, rect.y2, &x2, &y2);
624
625 if (x1 <= x2) {
626 ret.x1 = x1;
627 ret.x2 = x2;
628 } else {
629 ret.x1 = x2;
630 ret.x2 = x1;
631 }
632
633 if (y1 <= y2) {
634 ret.y1 = y1;
635 ret.y2 = y2;
636 } else {
637 ret.y1 = y2;
638 ret.y2 = y1;
639 }
640
641 return ret;
642}
643
Derek Foremanbc9a61c2015-11-18 16:32:30 -0600644/** Transform a region by a matrix, restricted to axis-aligned transformations
645 *
646 * Warning: This function does not work for projective, affine, or matrices
647 * that encode arbitrary rotations. Only 90-degree step rotations are
648 * supported.
649 */
650WL_EXPORT void
651weston_matrix_transform_region(pixman_region32_t *dest,
652 struct weston_matrix *matrix,
653 pixman_region32_t *src)
654{
655 pixman_box32_t *src_rects, *dest_rects;
656 int nrects, i;
657
658 src_rects = pixman_region32_rectangles(src, &nrects);
659 dest_rects = malloc(nrects * sizeof(*dest_rects));
660 if (!dest_rects)
661 return;
662
663 for (i = 0; i < nrects; i++) {
664 struct weston_vector vec1 = {{
665 src_rects[i].x1, src_rects[i].y1, 0, 1
666 }};
667 weston_matrix_transform(matrix, &vec1);
668 vec1.f[0] /= vec1.f[3];
669 vec1.f[1] /= vec1.f[3];
670
671 struct weston_vector vec2 = {{
672 src_rects[i].x2, src_rects[i].y2, 0, 1
673 }};
674 weston_matrix_transform(matrix, &vec2);
675 vec2.f[0] /= vec2.f[3];
676 vec2.f[1] /= vec2.f[3];
677
678 if (vec1.f[0] < vec2.f[0]) {
679 dest_rects[i].x1 = floor(vec1.f[0]);
680 dest_rects[i].x2 = ceil(vec2.f[0]);
681 } else {
682 dest_rects[i].x1 = floor(vec2.f[0]);
683 dest_rects[i].x2 = ceil(vec1.f[0]);
684 }
685
Derek Foremanbc9a61c2015-11-18 16:32:30 -0600686 if (vec1.f[1] < vec2.f[1]) {
687 dest_rects[i].y1 = floor(vec1.f[1]);
688 dest_rects[i].y2 = ceil(vec2.f[1]);
689 } else {
690 dest_rects[i].y1 = floor(vec2.f[1]);
691 dest_rects[i].y2 = ceil(vec1.f[1]);
692 }
693 }
694
695 pixman_region32_clear(dest);
696 pixman_region32_init_rects(dest, dest_rects, nrects);
697 free(dest_rects);
698}
699
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +0200700WL_EXPORT void
Jason Ekstrand33ff6362013-10-27 22:25:01 -0500701weston_transformed_region(int width, int height,
702 enum wl_output_transform transform,
703 int32_t scale,
704 pixman_region32_t *src, pixman_region32_t *dest)
705{
706 pixman_box32_t *src_rects, *dest_rects;
707 int nrects, i;
708
709 if (transform == WL_OUTPUT_TRANSFORM_NORMAL && scale == 1) {
710 if (src != dest)
711 pixman_region32_copy(dest, src);
712 return;
713 }
714
715 src_rects = pixman_region32_rectangles(src, &nrects);
716 dest_rects = malloc(nrects * sizeof(*dest_rects));
717 if (!dest_rects)
718 return;
719
720 if (transform == WL_OUTPUT_TRANSFORM_NORMAL) {
721 memcpy(dest_rects, src_rects, nrects * sizeof(*dest_rects));
722 } else {
723 for (i = 0; i < nrects; i++) {
724 switch (transform) {
725 default:
726 case WL_OUTPUT_TRANSFORM_NORMAL:
727 dest_rects[i].x1 = src_rects[i].x1;
728 dest_rects[i].y1 = src_rects[i].y1;
729 dest_rects[i].x2 = src_rects[i].x2;
730 dest_rects[i].y2 = src_rects[i].y2;
731 break;
732 case WL_OUTPUT_TRANSFORM_90:
733 dest_rects[i].x1 = height - src_rects[i].y2;
734 dest_rects[i].y1 = src_rects[i].x1;
735 dest_rects[i].x2 = height - src_rects[i].y1;
736 dest_rects[i].y2 = src_rects[i].x2;
737 break;
738 case WL_OUTPUT_TRANSFORM_180:
739 dest_rects[i].x1 = width - src_rects[i].x2;
740 dest_rects[i].y1 = height - src_rects[i].y2;
741 dest_rects[i].x2 = width - src_rects[i].x1;
742 dest_rects[i].y2 = height - src_rects[i].y1;
743 break;
744 case WL_OUTPUT_TRANSFORM_270:
745 dest_rects[i].x1 = src_rects[i].y1;
746 dest_rects[i].y1 = width - src_rects[i].x2;
747 dest_rects[i].x2 = src_rects[i].y2;
748 dest_rects[i].y2 = width - src_rects[i].x1;
749 break;
750 case WL_OUTPUT_TRANSFORM_FLIPPED:
751 dest_rects[i].x1 = width - src_rects[i].x2;
752 dest_rects[i].y1 = src_rects[i].y1;
753 dest_rects[i].x2 = width - src_rects[i].x1;
754 dest_rects[i].y2 = src_rects[i].y2;
755 break;
756 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
757 dest_rects[i].x1 = height - src_rects[i].y2;
758 dest_rects[i].y1 = width - src_rects[i].x2;
759 dest_rects[i].x2 = height - src_rects[i].y1;
760 dest_rects[i].y2 = width - src_rects[i].x1;
761 break;
762 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
763 dest_rects[i].x1 = src_rects[i].x1;
764 dest_rects[i].y1 = height - src_rects[i].y2;
765 dest_rects[i].x2 = src_rects[i].x2;
766 dest_rects[i].y2 = height - src_rects[i].y1;
767 break;
768 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
769 dest_rects[i].x1 = src_rects[i].y1;
770 dest_rects[i].y1 = src_rects[i].x1;
771 dest_rects[i].x2 = src_rects[i].y2;
772 dest_rects[i].y2 = src_rects[i].x2;
773 break;
774 }
775 }
776 }
777
778 if (scale != 1) {
779 for (i = 0; i < nrects; i++) {
780 dest_rects[i].x1 *= scale;
781 dest_rects[i].x2 *= scale;
782 dest_rects[i].y1 *= scale;
783 dest_rects[i].y2 *= scale;
784 }
785 }
786
787 pixman_region32_clear(dest);
788 pixman_region32_init_rects(dest, dest_rects, nrects);
789 free(dest_rects);
790}
791
Jonny Lamb74130762013-11-26 18:19:46 +0100792static void
Pekka Paalanen9c5a0d92016-04-15 16:42:49 +0300793viewport_surface_to_buffer(struct weston_surface *surface,
794 float sx, float sy, float *bx, float *by)
Jonny Lamb74130762013-11-26 18:19:46 +0100795{
Pekka Paalanen952b6c82014-03-14 14:38:15 +0200796 struct weston_buffer_viewport *vp = &surface->buffer_viewport;
Pekka Paalanen0b4c5352014-03-14 14:38:17 +0200797 double src_width, src_height;
798 double src_x, src_y;
Pekka Paalanen952b6c82014-03-14 14:38:15 +0200799
Pekka Paalanen0b4c5352014-03-14 14:38:17 +0200800 if (vp->buffer.src_width == wl_fixed_from_int(-1)) {
801 if (vp->surface.width == -1) {
802 *bx = sx;
803 *by = sy;
804 return;
805 }
Jonny Lamb74130762013-11-26 18:19:46 +0100806
Pekka Paalanen0b4c5352014-03-14 14:38:17 +0200807 src_x = 0.0;
808 src_y = 0.0;
809 src_width = surface->width_from_buffer;
810 src_height = surface->height_from_buffer;
Jonny Lamb74130762013-11-26 18:19:46 +0100811 } else {
Pekka Paalanen0b4c5352014-03-14 14:38:17 +0200812 src_x = wl_fixed_to_double(vp->buffer.src_x);
813 src_y = wl_fixed_to_double(vp->buffer.src_y);
814 src_width = wl_fixed_to_double(vp->buffer.src_width);
815 src_height = wl_fixed_to_double(vp->buffer.src_height);
Jonny Lamb74130762013-11-26 18:19:46 +0100816 }
Pekka Paalanen0b4c5352014-03-14 14:38:17 +0200817
818 *bx = sx * src_width / surface->width + src_x;
819 *by = sy * src_height / surface->height + src_y;
Jonny Lamb74130762013-11-26 18:19:46 +0100820}
821
Jason Ekstrand33ff6362013-10-27 22:25:01 -0500822WL_EXPORT void
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +0200823weston_surface_to_buffer_float(struct weston_surface *surface,
824 float sx, float sy, float *bx, float *by)
825{
Pekka Paalanen952b6c82014-03-14 14:38:15 +0200826 struct weston_buffer_viewport *vp = &surface->buffer_viewport;
827
Pekka Paalanen9c5a0d92016-04-15 16:42:49 +0300828 /* first transform coordinates if the viewport is set */
829 viewport_surface_to_buffer(surface, sx, sy, bx, by);
Jonny Lamb74130762013-11-26 18:19:46 +0100830
Jason Ekstrandd0cebc32014-04-21 20:56:46 -0500831 weston_transformed_coord(surface->width_from_buffer,
832 surface->height_from_buffer,
Pekka Paalanen952b6c82014-03-14 14:38:15 +0200833 vp->buffer.transform, vp->buffer.scale,
Jonny Lamb74130762013-11-26 18:19:46 +0100834 *bx, *by, bx, by);
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +0200835}
836
Derek Foreman99739672015-12-03 16:38:11 -0600837/** Transform a rectangle from surface coordinates to buffer coordinates
838 *
Pekka Paalanene95ad5c2016-04-15 14:47:08 +0300839 * \param surface The surface to fetch wp_viewport and buffer transformation
Derek Foreman99739672015-12-03 16:38:11 -0600840 * from.
841 * \param rect The rectangle to transform.
842 * \return The transformed rectangle.
843 *
844 * Viewport and buffer transformations can only do translation, scaling,
845 * and rotations in 90-degree steps. Therefore the only loss in the
846 * conversion is coordinate rounding.
847 *
848 * However, some coordinate rounding takes place as an intermediate
849 * step before the buffer scale factor is applied, so the rectangle
850 * boundary may not be exactly as expected.
851 *
852 * This is OK for damage tracking since a little extra coverage is
853 * not a problem.
854 */
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +0200855WL_EXPORT pixman_box32_t
856weston_surface_to_buffer_rect(struct weston_surface *surface,
857 pixman_box32_t rect)
858{
Pekka Paalanen952b6c82014-03-14 14:38:15 +0200859 struct weston_buffer_viewport *vp = &surface->buffer_viewport;
Jonny Lamb74130762013-11-26 18:19:46 +0100860 float xf, yf;
861
Pekka Paalanen9c5a0d92016-04-15 16:42:49 +0300862 /* first transform box coordinates if the viewport is set */
863 viewport_surface_to_buffer(surface, rect.x1, rect.y1, &xf, &yf);
Jonny Lamb74130762013-11-26 18:19:46 +0100864 rect.x1 = floorf(xf);
865 rect.y1 = floorf(yf);
866
Pekka Paalanen9c5a0d92016-04-15 16:42:49 +0300867 viewport_surface_to_buffer(surface, rect.x2, rect.y2, &xf, &yf);
Derek Foremane2e15ac2015-12-01 13:00:43 -0600868 rect.x2 = ceilf(xf);
869 rect.y2 = ceilf(yf);
Jonny Lamb74130762013-11-26 18:19:46 +0100870
Jason Ekstrandd0cebc32014-04-21 20:56:46 -0500871 return weston_transformed_rect(surface->width_from_buffer,
872 surface->height_from_buffer,
Pekka Paalanen952b6c82014-03-14 14:38:15 +0200873 vp->buffer.transform, vp->buffer.scale,
Alexander Larsson4ea95522013-05-22 14:41:37 +0200874 rect);
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +0200875}
876
Pekka Paalanene54e31c2015-03-04 14:23:28 +0200877/** Transform a region from surface coordinates to buffer coordinates
878 *
Pekka Paalanene95ad5c2016-04-15 14:47:08 +0300879 * \param surface The surface to fetch wp_viewport and buffer transformation
Pekka Paalanene54e31c2015-03-04 14:23:28 +0200880 * from.
881 * \param surface_region[in] The region in surface coordinates.
882 * \param buffer_region[out] The region converted to buffer coordinates.
883 *
884 * Buffer_region must be init'd, but will be completely overwritten.
885 *
886 * Viewport and buffer transformations can only do translation, scaling,
887 * and rotations in 90-degree steps. Therefore the only loss in the
Derek Foreman99739672015-12-03 16:38:11 -0600888 * conversion is from the coordinate rounding that takes place in
889 * \ref weston_surface_to_buffer_rect.
Pekka Paalanene54e31c2015-03-04 14:23:28 +0200890 */
891WL_EXPORT void
892weston_surface_to_buffer_region(struct weston_surface *surface,
893 pixman_region32_t *surface_region,
894 pixman_region32_t *buffer_region)
895{
896 pixman_box32_t *src_rects, *dest_rects;
897 int nrects, i;
898
899 src_rects = pixman_region32_rectangles(surface_region, &nrects);
900 dest_rects = malloc(nrects * sizeof(*dest_rects));
901 if (!dest_rects)
902 return;
903
904 for (i = 0; i < nrects; i++) {
905 dest_rects[i] = weston_surface_to_buffer_rect(surface,
906 src_rects[i]);
907 }
908
909 pixman_region32_fini(buffer_region);
910 pixman_region32_init_rects(buffer_region, dest_rects, nrects);
911 free(dest_rects);
912}
913
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +0200914WL_EXPORT void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500915weston_view_move_to_plane(struct weston_view *view,
Kristian Høgsberg65a11e12012-08-03 11:30:18 -0400916 struct weston_plane *plane)
917{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500918 if (view->plane == plane)
Kristian Høgsberg65a11e12012-08-03 11:30:18 -0400919 return;
920
Jason Ekstranda7af7042013-10-12 22:38:11 -0500921 weston_view_damage_below(view);
922 view->plane = plane;
923 weston_surface_damage(view->surface);
Kristian Høgsberg65a11e12012-08-03 11:30:18 -0400924}
925
Pekka Paalanen51723d52015-02-17 13:10:01 +0200926/** Inflict damage on the plane where the view is visible.
927 *
928 * \param view The view that causes the damage.
929 *
930 * If the view is currently on a plane (including the primary plane),
931 * take the view's boundingbox, subtract all the opaque views that cover it,
932 * and add the remaining region as damage to the plane. This corresponds
933 * to the damage inflicted to the plane if this view disappeared.
934 *
935 * A repaint is scheduled for this view.
936 *
937 * The region of all opaque views covering this view is stored in
938 * weston_view::clip and updated by view_accumulate_damage() during
939 * weston_output_repaint(). Specifically, that region matches the
940 * scenegraph as it was last painted.
941 */
Kristian Høgsberg65a11e12012-08-03 11:30:18 -0400942WL_EXPORT void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500943weston_view_damage_below(struct weston_view *view)
Pekka Paalanen9abf3932012-02-08 14:49:37 +0200944{
Kristian Høgsberg1e832122012-02-28 22:47:14 -0500945 pixman_region32_t damage;
Pekka Paalanen9abf3932012-02-08 14:49:37 +0200946
Kristian Høgsberg1e832122012-02-28 22:47:14 -0500947 pixman_region32_init(&damage);
Pekka Paalanen25c0ca52015-02-19 11:15:33 +0200948 pixman_region32_subtract(&damage, &view->transform.boundingbox,
Jason Ekstranda7af7042013-10-12 22:38:11 -0500949 &view->clip);
Xiong Zhang97116532013-10-23 13:58:31 +0800950 if (view->plane)
951 pixman_region32_union(&view->plane->damage,
952 &view->plane->damage, &damage);
Kristian Høgsberg1e832122012-02-28 22:47:14 -0500953 pixman_region32_fini(&damage);
Kristian Høgsberga3a784a2013-11-13 21:33:43 -0800954 weston_view_schedule_repaint(view);
Pekka Paalanen9abf3932012-02-08 14:49:37 +0200955}
956
Pekka Paalanen01e00682017-03-24 16:21:06 +0200957/** Send wl_surface.enter/leave events
958 *
959 * \param surface The surface.
Pekka Paalanen1b9bf592017-03-27 12:15:38 +0300960 * \param head A head of the entered/left output.
Pekka Paalanen01e00682017-03-24 16:21:06 +0200961 * \param enter True if entered.
962 * \param left True if left.
963 *
964 * Send the enter/leave events for all protocol objects bound to the given
965 * output by the client owning the surface.
966 */
967static void
968weston_surface_send_enter_leave(struct weston_surface *surface,
Pekka Paalanen1b9bf592017-03-27 12:15:38 +0300969 struct weston_head *head,
Pekka Paalanen01e00682017-03-24 16:21:06 +0200970 bool enter,
971 bool leave)
972{
973 struct wl_resource *wloutput;
974 struct wl_client *client;
975
976 assert(enter != leave);
977
978 client = wl_resource_get_client(surface->resource);
Pekka Paalanen1b9bf592017-03-27 12:15:38 +0300979 wl_resource_for_each(wloutput, &head->resource_list) {
Pekka Paalanen01e00682017-03-24 16:21:06 +0200980 if (wl_resource_get_client(wloutput) != client)
981 continue;
982
983 if (enter)
984 wl_surface_send_enter(surface->resource, wloutput);
985 if (leave)
986 wl_surface_send_leave(surface->resource, wloutput);
987 }
988}
989
Bryce Harrington3f650b82015-12-23 11:01:58 -0800990/**
991 * \param es The surface
992 * \param mask The new set of outputs for the surface
993 *
994 * Sets the surface's set of outputs to the ones specified by
995 * the new output mask provided. Identifies the outputs that
996 * have changed, the posts enter and leave events for these
997 * outputs as appropriate.
998 */
Kristian Høgsbergb9af4792012-09-25 14:48:04 -0400999static void
1000weston_surface_update_output_mask(struct weston_surface *es, uint32_t mask)
1001{
1002 uint32_t different = es->output_mask ^ mask;
1003 uint32_t entered = mask & different;
1004 uint32_t left = es->output_mask & different;
Pekka Paalanen01e00682017-03-24 16:21:06 +02001005 uint32_t output_bit;
Kristian Høgsbergb9af4792012-09-25 14:48:04 -04001006 struct weston_output *output;
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03001007 struct weston_head *head;
Kristian Høgsbergb9af4792012-09-25 14:48:04 -04001008
1009 es->output_mask = mask;
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05001010 if (es->resource == NULL)
Kristian Høgsbergb9af4792012-09-25 14:48:04 -04001011 return;
1012 if (different == 0)
1013 return;
1014
1015 wl_list_for_each(output, &es->compositor->output_list, link) {
Pekka Paalanen01e00682017-03-24 16:21:06 +02001016 output_bit = 1u << output->id;
1017 if (!(output_bit & different))
Kristian Høgsbergb9af4792012-09-25 14:48:04 -04001018 continue;
Pekka Paalanen01e00682017-03-24 16:21:06 +02001019
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03001020 wl_list_for_each(head, &output->head_list, output_link) {
1021 weston_surface_send_enter_leave(es, head,
1022 output_bit & entered,
1023 output_bit & left);
1024 }
Kristian Høgsbergb9af4792012-09-25 14:48:04 -04001025 }
1026}
1027
Semi Malinene7a52fb2018-04-26 11:08:10 +02001028static void
1029notify_view_output_destroy(struct wl_listener *listener, void *data)
1030{
1031 struct weston_view *view =
1032 container_of(listener,
1033 struct weston_view, output_destroy_listener);
1034
1035 view->output = NULL;
1036 view->output_destroy_listener.notify = NULL;
1037}
1038
1039/** Set the primary output of the view
1040 *
1041 * \param view The view whose primary output to set
1042 * \param output The new primary output for the view
1043 *
1044 * Set \a output to be the primary output of the \a view.
1045 *
1046 * Notice that the assignment may be temporary; the primary output could be
1047 * automatically changed. Hence, one cannot rely on the value persisting.
1048 *
1049 * Passing NULL as /a output will set the primary output to NULL.
1050 */
1051WL_EXPORT void
1052weston_view_set_output(struct weston_view *view, struct weston_output *output)
1053{
1054 if (view->output_destroy_listener.notify) {
1055 wl_list_remove(&view->output_destroy_listener.link);
1056 view->output_destroy_listener.notify = NULL;
1057 }
1058 view->output = output;
1059 if (output) {
1060 view->output_destroy_listener.notify =
1061 notify_view_output_destroy;
1062 wl_signal_add(&output->destroy_signal,
1063 &view->output_destroy_listener);
1064 }
1065}
1066
Bryce Harrington3f650b82015-12-23 11:01:58 -08001067/** Recalculate which output(s) the surface has views displayed on
1068 *
1069 * \param es The surface to remap to outputs
1070 *
1071 * Finds the output that is showing the largest amount of one
1072 * of the surface's various views. This output becomes the
Pekka Paalanen130ae6e2016-03-30 14:33:33 +03001073 * surface's primary output for vsync and frame callback purposes.
Bryce Harrington3f650b82015-12-23 11:01:58 -08001074 *
Pekka Paalanen130ae6e2016-03-30 14:33:33 +03001075 * Also notes all outputs of all of the surface's views
Bryce Harrington3f650b82015-12-23 11:01:58 -08001076 * in the output_mask for the surface.
1077 */
Kristian Høgsbergb9af4792012-09-25 14:48:04 -04001078static void
1079weston_surface_assign_output(struct weston_surface *es)
1080{
Jason Ekstranda7af7042013-10-12 22:38:11 -05001081 struct weston_output *new_output;
1082 struct weston_view *view;
1083 pixman_region32_t region;
1084 uint32_t max, area, mask;
1085 pixman_box32_t *e;
1086
1087 new_output = NULL;
1088 max = 0;
1089 mask = 0;
1090 pixman_region32_init(&region);
1091 wl_list_for_each(view, &es->views, surface_link) {
1092 if (!view->output)
1093 continue;
1094
1095 pixman_region32_intersect(&region, &view->transform.boundingbox,
1096 &view->output->region);
1097
1098 e = pixman_region32_extents(&region);
1099 area = (e->x2 - e->x1) * (e->y2 - e->y1);
1100
1101 mask |= view->output_mask;
1102
1103 if (area >= max) {
1104 new_output = view->output;
1105 max = area;
1106 }
1107 }
1108 pixman_region32_fini(&region);
1109
1110 es->output = new_output;
1111 weston_surface_update_output_mask(es, mask);
1112}
1113
Bryce Harrington3f650b82015-12-23 11:01:58 -08001114/** Recalculate which output(s) the view is displayed on
1115 *
1116 * \param ev The view to remap to outputs
1117 *
1118 * Identifies the set of outputs that the view is visible on,
1119 * noting them into the output_mask. The output that the view
Pekka Paalanen130ae6e2016-03-30 14:33:33 +03001120 * is most visible on is set as the view's primary output.
Bryce Harrington3f650b82015-12-23 11:01:58 -08001121 *
1122 * Also does the same for the view's surface. See
1123 * weston_surface_assign_output().
1124 */
Jason Ekstranda7af7042013-10-12 22:38:11 -05001125static void
1126weston_view_assign_output(struct weston_view *ev)
1127{
1128 struct weston_compositor *ec = ev->surface->compositor;
Kristian Høgsbergb9af4792012-09-25 14:48:04 -04001129 struct weston_output *output, *new_output;
1130 pixman_region32_t region;
1131 uint32_t max, area, mask;
1132 pixman_box32_t *e;
1133
1134 new_output = NULL;
1135 max = 0;
1136 mask = 0;
1137 pixman_region32_init(&region);
1138 wl_list_for_each(output, &ec->output_list, link) {
Giulio Camuffo2f2a70c2015-07-12 10:52:32 +03001139 if (output->destroying)
1140 continue;
1141
Jason Ekstranda7af7042013-10-12 22:38:11 -05001142 pixman_region32_intersect(&region, &ev->transform.boundingbox,
Kristian Høgsbergb9af4792012-09-25 14:48:04 -04001143 &output->region);
1144
1145 e = pixman_region32_extents(&region);
1146 area = (e->x2 - e->x1) * (e->y2 - e->y1);
1147
1148 if (area > 0)
Bryce Harrington89324ce2015-12-23 18:38:07 -08001149 mask |= 1u << output->id;
Kristian Høgsbergb9af4792012-09-25 14:48:04 -04001150
1151 if (area >= max) {
1152 new_output = output;
1153 max = area;
1154 }
1155 }
1156 pixman_region32_fini(&region);
1157
Semi Malinene7a52fb2018-04-26 11:08:10 +02001158 weston_view_set_output(ev, new_output);
Jason Ekstranda7af7042013-10-12 22:38:11 -05001159 ev->output_mask = mask;
1160
1161 weston_surface_assign_output(ev->surface);
Kristian Høgsbergb9af4792012-09-25 14:48:04 -04001162}
1163
Pekka Paalanen9abf3932012-02-08 14:49:37 +02001164static void
Pekka Paalanen380adf52015-02-16 14:39:11 +02001165weston_view_to_view_map(struct weston_view *from, struct weston_view *to,
1166 int from_x, int from_y, int *to_x, int *to_y)
1167{
1168 float x, y;
1169
1170 weston_view_to_global_float(from, from_x, from_y, &x, &y);
1171 weston_view_from_global_float(to, x, y, &x, &y);
1172
1173 *to_x = round(x);
1174 *to_y = round(y);
1175}
1176
1177static void
1178weston_view_transfer_scissor(struct weston_view *from, struct weston_view *to)
1179{
1180 pixman_box32_t *a;
1181 pixman_box32_t b;
1182
1183 a = pixman_region32_extents(&from->geometry.scissor);
1184
1185 weston_view_to_view_map(from, to, a->x1, a->y1, &b.x1, &b.y1);
1186 weston_view_to_view_map(from, to, a->x2, a->y2, &b.x2, &b.y2);
1187
1188 pixman_region32_fini(&to->geometry.scissor);
1189 pixman_region32_init_with_extents(&to->geometry.scissor, &b);
1190}
1191
1192static void
Pekka Paalanenc7d7fdf2015-02-23 12:27:00 +02001193view_compute_bbox(struct weston_view *view, const pixman_box32_t *inbox,
Jason Ekstranda7af7042013-10-12 22:38:11 -05001194 pixman_region32_t *bbox)
Pekka Paalanen6720d8f2012-01-25 15:17:40 +02001195{
John Kåre Alsaker490d02a2012-09-30 02:57:21 +02001196 float min_x = HUGE_VALF, min_y = HUGE_VALF;
1197 float max_x = -HUGE_VALF, max_y = -HUGE_VALF;
Pekka Paalanen6720d8f2012-01-25 15:17:40 +02001198 int32_t s[4][2] = {
Pekka Paalanenc7d7fdf2015-02-23 12:27:00 +02001199 { inbox->x1, inbox->y1 },
1200 { inbox->x1, inbox->y2 },
1201 { inbox->x2, inbox->y1 },
1202 { inbox->x2, inbox->y2 },
Pekka Paalanen6720d8f2012-01-25 15:17:40 +02001203 };
John Kåre Alsaker490d02a2012-09-30 02:57:21 +02001204 float int_x, int_y;
Pekka Paalanen6720d8f2012-01-25 15:17:40 +02001205 int i;
1206
Pekka Paalanenc7d7fdf2015-02-23 12:27:00 +02001207 if (inbox->x1 == inbox->x2 || inbox->y1 == inbox->y2) {
Pekka Paalanen7c7d4642012-09-04 13:55:44 +03001208 /* avoid rounding empty bbox to 1x1 */
1209 pixman_region32_init(bbox);
1210 return;
1211 }
1212
Pekka Paalanen6720d8f2012-01-25 15:17:40 +02001213 for (i = 0; i < 4; ++i) {
John Kåre Alsaker490d02a2012-09-30 02:57:21 +02001214 float x, y;
Jason Ekstranda7af7042013-10-12 22:38:11 -05001215 weston_view_to_global_float(view, s[i][0], s[i][1], &x, &y);
Pekka Paalanen6720d8f2012-01-25 15:17:40 +02001216 if (x < min_x)
1217 min_x = x;
1218 if (x > max_x)
1219 max_x = x;
1220 if (y < min_y)
1221 min_y = y;
1222 if (y > max_y)
1223 max_y = y;
1224 }
1225
Pekka Paalanen219b9822012-02-08 15:38:37 +02001226 int_x = floorf(min_x);
1227 int_y = floorf(min_y);
1228 pixman_region32_init_rect(bbox, int_x, int_y,
1229 ceilf(max_x) - int_x, ceilf(max_y) - int_y);
Pekka Paalanen6720d8f2012-01-25 15:17:40 +02001230}
1231
Pekka Paalanen80fb08d2012-02-08 15:14:17 +02001232static void
Jason Ekstranda7af7042013-10-12 22:38:11 -05001233weston_view_update_transform_disable(struct weston_view *view)
Pekka Paalanen80fb08d2012-02-08 15:14:17 +02001234{
Jason Ekstranda7af7042013-10-12 22:38:11 -05001235 view->transform.enabled = 0;
Pekka Paalanen80fb08d2012-02-08 15:14:17 +02001236
Pekka Paalanencc2f8682012-02-13 10:34:04 +02001237 /* round off fractions when not transformed */
Jason Ekstranda7af7042013-10-12 22:38:11 -05001238 view->geometry.x = roundf(view->geometry.x);
1239 view->geometry.y = roundf(view->geometry.y);
Pekka Paalanencc2f8682012-02-13 10:34:04 +02001240
Kristian Høgsbergc1e6c8a2013-02-19 17:04:50 -05001241 /* Otherwise identity matrix, but with x and y translation. */
Jason Ekstranda7af7042013-10-12 22:38:11 -05001242 view->transform.position.matrix.type = WESTON_MATRIX_TRANSFORM_TRANSLATE;
1243 view->transform.position.matrix.d[12] = view->geometry.x;
1244 view->transform.position.matrix.d[13] = view->geometry.y;
Kristian Høgsbergc1e6c8a2013-02-19 17:04:50 -05001245
Jason Ekstranda7af7042013-10-12 22:38:11 -05001246 view->transform.matrix = view->transform.position.matrix;
Kristian Høgsbergc1e6c8a2013-02-19 17:04:50 -05001247
Jason Ekstranda7af7042013-10-12 22:38:11 -05001248 view->transform.inverse = view->transform.position.matrix;
1249 view->transform.inverse.d[12] = -view->geometry.x;
1250 view->transform.inverse.d[13] = -view->geometry.y;
Kristian Høgsbergc1e6c8a2013-02-19 17:04:50 -05001251
Jason Ekstranda7af7042013-10-12 22:38:11 -05001252 pixman_region32_init_rect(&view->transform.boundingbox,
Pekka Paalanen380adf52015-02-16 14:39:11 +02001253 0, 0,
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06001254 view->surface->width,
1255 view->surface->height);
Pekka Paalanen380adf52015-02-16 14:39:11 +02001256 if (view->geometry.scissor_enabled)
1257 pixman_region32_intersect(&view->transform.boundingbox,
1258 &view->transform.boundingbox,
1259 &view->geometry.scissor);
1260
1261 pixman_region32_translate(&view->transform.boundingbox,
1262 view->geometry.x, view->geometry.y);
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05001263
Jason Ekstranda7af7042013-10-12 22:38:11 -05001264 if (view->alpha == 1.0) {
1265 pixman_region32_copy(&view->transform.opaque,
1266 &view->surface->opaque);
1267 pixman_region32_translate(&view->transform.opaque,
1268 view->geometry.x,
1269 view->geometry.y);
Kristian Høgsberg3b4af202012-02-28 09:19:39 -05001270 }
Pekka Paalanen80fb08d2012-02-08 15:14:17 +02001271}
1272
1273static int
Jason Ekstranda7af7042013-10-12 22:38:11 -05001274weston_view_update_transform_enable(struct weston_view *view)
Pekka Paalanen2a5cecc2012-01-20 14:24:25 +02001275{
Jason Ekstranda7af7042013-10-12 22:38:11 -05001276 struct weston_view *parent = view->geometry.parent;
1277 struct weston_matrix *matrix = &view->transform.matrix;
1278 struct weston_matrix *inverse = &view->transform.inverse;
Pekka Paalanen2a5cecc2012-01-20 14:24:25 +02001279 struct weston_transform *tform;
Pekka Paalanen380adf52015-02-16 14:39:11 +02001280 pixman_region32_t surfregion;
1281 const pixman_box32_t *surfbox;
Pekka Paalanen2a5cecc2012-01-20 14:24:25 +02001282
Jason Ekstranda7af7042013-10-12 22:38:11 -05001283 view->transform.enabled = 1;
Pekka Paalanen80fb08d2012-02-08 15:14:17 +02001284
1285 /* Otherwise identity matrix, but with x and y translation. */
Jason Ekstranda7af7042013-10-12 22:38:11 -05001286 view->transform.position.matrix.type = WESTON_MATRIX_TRANSFORM_TRANSLATE;
1287 view->transform.position.matrix.d[12] = view->geometry.x;
1288 view->transform.position.matrix.d[13] = view->geometry.y;
Pekka Paalanen80fb08d2012-02-08 15:14:17 +02001289
1290 weston_matrix_init(matrix);
Jason Ekstranda7af7042013-10-12 22:38:11 -05001291 wl_list_for_each(tform, &view->geometry.transformation_list, link)
Pekka Paalanen80fb08d2012-02-08 15:14:17 +02001292 weston_matrix_multiply(matrix, &tform->matrix);
1293
Pekka Paalanen483243f2013-03-08 14:56:50 +02001294 if (parent)
1295 weston_matrix_multiply(matrix, &parent->transform.matrix);
1296
Pekka Paalanen80fb08d2012-02-08 15:14:17 +02001297 if (weston_matrix_invert(inverse, matrix) < 0) {
1298 /* Oops, bad total transformation, not invertible */
Jason Ekstranda7af7042013-10-12 22:38:11 -05001299 weston_log("error: weston_view %p"
1300 " transformation not invertible.\n", view);
Pekka Paalanen80fb08d2012-02-08 15:14:17 +02001301 return -1;
1302 }
1303
Giulio Camuffo148c1992016-09-04 18:50:46 +03001304 if (view->alpha == 1.0 &&
1305 matrix->type == WESTON_MATRIX_TRANSFORM_TRANSLATE) {
1306 pixman_region32_copy(&view->transform.opaque,
1307 &view->surface->opaque);
1308 pixman_region32_translate(&view->transform.opaque,
1309 matrix->d[12],
1310 matrix->d[13]);
1311 }
1312
Pekka Paalanen380adf52015-02-16 14:39:11 +02001313 pixman_region32_init_rect(&surfregion, 0, 0,
1314 view->surface->width, view->surface->height);
1315 if (view->geometry.scissor_enabled)
1316 pixman_region32_intersect(&surfregion, &surfregion,
1317 &view->geometry.scissor);
1318 surfbox = pixman_region32_extents(&surfregion);
1319
1320 view_compute_bbox(view, surfbox, &view->transform.boundingbox);
1321 pixman_region32_fini(&surfregion);
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05001322
Pekka Paalanen80fb08d2012-02-08 15:14:17 +02001323 return 0;
1324}
1325
Giulio Camuffo95ec0f92014-07-09 22:12:57 +03001326static struct weston_layer *
1327get_view_layer(struct weston_view *view)
1328{
1329 if (view->parent_view)
1330 return get_view_layer(view->parent_view);
1331 return view->layer_link.layer;
1332}
1333
Pekka Paalanen80fb08d2012-02-08 15:14:17 +02001334WL_EXPORT void
Jason Ekstranda7af7042013-10-12 22:38:11 -05001335weston_view_update_transform(struct weston_view *view)
Pekka Paalanen80fb08d2012-02-08 15:14:17 +02001336{
Jason Ekstranda7af7042013-10-12 22:38:11 -05001337 struct weston_view *parent = view->geometry.parent;
Giulio Camuffo95ec0f92014-07-09 22:12:57 +03001338 struct weston_layer *layer;
1339 pixman_region32_t mask;
Pekka Paalanen483243f2013-03-08 14:56:50 +02001340
Jason Ekstranda7af7042013-10-12 22:38:11 -05001341 if (!view->transform.dirty)
Pekka Paalanen2a5cecc2012-01-20 14:24:25 +02001342 return;
1343
Pekka Paalanen483243f2013-03-08 14:56:50 +02001344 if (parent)
Jason Ekstranda7af7042013-10-12 22:38:11 -05001345 weston_view_update_transform(parent);
Pekka Paalanen483243f2013-03-08 14:56:50 +02001346
Jason Ekstranda7af7042013-10-12 22:38:11 -05001347 view->transform.dirty = 0;
Pekka Paalanen2a5cecc2012-01-20 14:24:25 +02001348
Jason Ekstranda7af7042013-10-12 22:38:11 -05001349 weston_view_damage_below(view);
Pekka Paalanen96516782012-02-09 15:32:15 +02001350
Jason Ekstranda7af7042013-10-12 22:38:11 -05001351 pixman_region32_fini(&view->transform.boundingbox);
1352 pixman_region32_fini(&view->transform.opaque);
1353 pixman_region32_init(&view->transform.opaque);
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05001354
Pekka Paalanencd403622012-01-25 13:37:39 +02001355 /* transform.position is always in transformation_list */
Jason Ekstranda7af7042013-10-12 22:38:11 -05001356 if (view->geometry.transformation_list.next ==
1357 &view->transform.position.link &&
1358 view->geometry.transformation_list.prev ==
1359 &view->transform.position.link &&
Pekka Paalanen483243f2013-03-08 14:56:50 +02001360 !parent) {
Jason Ekstranda7af7042013-10-12 22:38:11 -05001361 weston_view_update_transform_disable(view);
Pekka Paalanen80fb08d2012-02-08 15:14:17 +02001362 } else {
Jason Ekstranda7af7042013-10-12 22:38:11 -05001363 if (weston_view_update_transform_enable(view) < 0)
1364 weston_view_update_transform_disable(view);
Pekka Paalanen2a5cecc2012-01-20 14:24:25 +02001365 }
Pekka Paalanen96516782012-02-09 15:32:15 +02001366
Giulio Camuffo95ec0f92014-07-09 22:12:57 +03001367 layer = get_view_layer(view);
1368 if (layer) {
1369 pixman_region32_init_with_extents(&mask, &layer->mask);
Pekka Paalanen25c0ca52015-02-19 11:15:33 +02001370 pixman_region32_intersect(&view->transform.boundingbox,
1371 &view->transform.boundingbox, &mask);
Pekka Paalanen8844bf22015-02-18 16:30:47 +02001372 pixman_region32_intersect(&view->transform.opaque,
1373 &view->transform.opaque, &mask);
Giulio Camuffo95ec0f92014-07-09 22:12:57 +03001374 pixman_region32_fini(&mask);
1375 }
1376
Pekka Paalanen380adf52015-02-16 14:39:11 +02001377 if (parent) {
1378 if (parent->geometry.scissor_enabled) {
1379 view->geometry.scissor_enabled = true;
1380 weston_view_transfer_scissor(parent, view);
1381 } else {
1382 view->geometry.scissor_enabled = false;
1383 }
1384 }
1385
Jason Ekstranda7af7042013-10-12 22:38:11 -05001386 weston_view_damage_below(view);
Pekka Paalanen96516782012-02-09 15:32:15 +02001387
Jason Ekstranda7af7042013-10-12 22:38:11 -05001388 weston_view_assign_output(view);
Tiago Vignattifb2adba2013-06-12 15:43:21 -03001389
Jason Ekstranda7af7042013-10-12 22:38:11 -05001390 wl_signal_emit(&view->surface->compositor->transform_signal,
1391 view->surface);
Pekka Paalanen2a5cecc2012-01-20 14:24:25 +02001392}
1393
Pekka Paalanenddae03c2012-02-06 14:54:20 +02001394WL_EXPORT void
Jason Ekstranda7af7042013-10-12 22:38:11 -05001395weston_view_geometry_dirty(struct weston_view *view)
Pekka Paalanenc3ce7382013-03-08 14:56:49 +02001396{
Jason Ekstranda7af7042013-10-12 22:38:11 -05001397 struct weston_view *child;
Pekka Paalanen483243f2013-03-08 14:56:50 +02001398
1399 /*
Jason Ekstranda7af7042013-10-12 22:38:11 -05001400 * The invariant: if view->geometry.dirty, then all views
1401 * in view->geometry.child_list have geometry.dirty too.
Pekka Paalanen483243f2013-03-08 14:56:50 +02001402 * Corollary: if not parent->geometry.dirty, then all ancestors
1403 * are not dirty.
1404 */
1405
Jason Ekstranda7af7042013-10-12 22:38:11 -05001406 if (view->transform.dirty)
Pekka Paalanen483243f2013-03-08 14:56:50 +02001407 return;
1408
Jason Ekstranda7af7042013-10-12 22:38:11 -05001409 view->transform.dirty = 1;
Pekka Paalanen483243f2013-03-08 14:56:50 +02001410
Jason Ekstranda7af7042013-10-12 22:38:11 -05001411 wl_list_for_each(child, &view->geometry.child_list,
Pekka Paalanen483243f2013-03-08 14:56:50 +02001412 geometry.parent_link)
Jason Ekstranda7af7042013-10-12 22:38:11 -05001413 weston_view_geometry_dirty(child);
Pekka Paalanenc3ce7382013-03-08 14:56:49 +02001414}
1415
1416WL_EXPORT void
Jason Ekstranda7af7042013-10-12 22:38:11 -05001417weston_view_to_global_fixed(struct weston_view *view,
1418 wl_fixed_t vx, wl_fixed_t vy,
1419 wl_fixed_t *x, wl_fixed_t *y)
Daniel Stonebd3489b2012-05-08 17:17:53 +01001420{
John Kåre Alsaker490d02a2012-09-30 02:57:21 +02001421 float xf, yf;
Daniel Stonebd3489b2012-05-08 17:17:53 +01001422
Jason Ekstranda7af7042013-10-12 22:38:11 -05001423 weston_view_to_global_float(view,
1424 wl_fixed_to_double(vx),
1425 wl_fixed_to_double(vy),
1426 &xf, &yf);
Daniel Stonebd3489b2012-05-08 17:17:53 +01001427 *x = wl_fixed_from_double(xf);
1428 *y = wl_fixed_from_double(yf);
1429}
1430
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -04001431WL_EXPORT void
Jason Ekstranda7af7042013-10-12 22:38:11 -05001432weston_view_from_global_float(struct weston_view *view,
1433 float x, float y, float *vx, float *vy)
Pekka Paalanene0f3cb22012-01-24 09:59:29 +02001434{
Jason Ekstranda7af7042013-10-12 22:38:11 -05001435 if (view->transform.enabled) {
Pekka Paalanene0f3cb22012-01-24 09:59:29 +02001436 struct weston_vector v = { { x, y, 0.0f, 1.0f } };
1437
Jason Ekstranda7af7042013-10-12 22:38:11 -05001438 weston_matrix_transform(&view->transform.inverse, &v);
Pekka Paalanene0f3cb22012-01-24 09:59:29 +02001439
1440 if (fabsf(v.f[3]) < 1e-6) {
Martin Minarik6d118362012-06-07 18:01:59 +02001441 weston_log("warning: numerical instability in "
Jason Ekstranda7af7042013-10-12 22:38:11 -05001442 "weston_view_from_global(), divisor = %g\n",
Pekka Paalanene0f3cb22012-01-24 09:59:29 +02001443 v.f[3]);
Jason Ekstranda7af7042013-10-12 22:38:11 -05001444 *vx = 0;
1445 *vy = 0;
Pekka Paalanene0f3cb22012-01-24 09:59:29 +02001446 return;
1447 }
1448
Jason Ekstranda7af7042013-10-12 22:38:11 -05001449 *vx = v.f[0] / v.f[3];
1450 *vy = v.f[1] / v.f[3];
Pekka Paalanene0f3cb22012-01-24 09:59:29 +02001451 } else {
Jason Ekstranda7af7042013-10-12 22:38:11 -05001452 *vx = x - view->geometry.x;
1453 *vy = y - view->geometry.y;
Pekka Paalanene0f3cb22012-01-24 09:59:29 +02001454 }
1455}
1456
1457WL_EXPORT void
Jason Ekstranda7af7042013-10-12 22:38:11 -05001458weston_view_from_global_fixed(struct weston_view *view,
1459 wl_fixed_t x, wl_fixed_t y,
1460 wl_fixed_t *vx, wl_fixed_t *vy)
Daniel Stonebd3489b2012-05-08 17:17:53 +01001461{
Jason Ekstranda7af7042013-10-12 22:38:11 -05001462 float vxf, vyf;
Daniel Stonebd3489b2012-05-08 17:17:53 +01001463
Jason Ekstranda7af7042013-10-12 22:38:11 -05001464 weston_view_from_global_float(view,
1465 wl_fixed_to_double(x),
1466 wl_fixed_to_double(y),
1467 &vxf, &vyf);
1468 *vx = wl_fixed_from_double(vxf);
1469 *vy = wl_fixed_from_double(vyf);
Daniel Stonebd3489b2012-05-08 17:17:53 +01001470}
1471
1472WL_EXPORT void
Jason Ekstranda7af7042013-10-12 22:38:11 -05001473weston_view_from_global(struct weston_view *view,
1474 int32_t x, int32_t y, int32_t *vx, int32_t *vy)
Pekka Paalanen0e151bb2012-01-24 14:47:37 +02001475{
Jason Ekstranda7af7042013-10-12 22:38:11 -05001476 float vxf, vyf;
Pekka Paalanen0e151bb2012-01-24 14:47:37 +02001477
Jason Ekstranda7af7042013-10-12 22:38:11 -05001478 weston_view_from_global_float(view, x, y, &vxf, &vyf);
1479 *vx = floorf(vxf);
1480 *vy = floorf(vyf);
Pekka Paalanen0e151bb2012-01-24 14:47:37 +02001481}
1482
Bryce Harrington3f650b82015-12-23 11:01:58 -08001483/**
1484 * \param surface The surface to be repainted
1485 *
1486 * Marks the output(s) that the surface is shown on as needing to be
1487 * repainted. See weston_output_schedule_repaint().
1488 */
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -04001489WL_EXPORT void
Kristian Høgsberg98238702012-08-03 16:29:12 -04001490weston_surface_schedule_repaint(struct weston_surface *surface)
1491{
1492 struct weston_output *output;
1493
1494 wl_list_for_each(output, &surface->compositor->output_list, link)
Bryce Harrington89324ce2015-12-23 18:38:07 -08001495 if (surface->output_mask & (1u << output->id))
Kristian Høgsberg98238702012-08-03 16:29:12 -04001496 weston_output_schedule_repaint(output);
1497}
1498
Bryce Harrington3f650b82015-12-23 11:01:58 -08001499/**
1500 * \param view The view to be repainted
1501 *
1502 * Marks the output(s) that the view is shown on as needing to be
1503 * repainted. See weston_output_schedule_repaint().
1504 */
Kristian Høgsberg98238702012-08-03 16:29:12 -04001505WL_EXPORT void
Jason Ekstranda7af7042013-10-12 22:38:11 -05001506weston_view_schedule_repaint(struct weston_view *view)
1507{
1508 struct weston_output *output;
1509
1510 wl_list_for_each(output, &view->surface->compositor->output_list, link)
Bryce Harrington89324ce2015-12-23 18:38:07 -08001511 if (view->output_mask & (1u << output->id))
Jason Ekstranda7af7042013-10-12 22:38:11 -05001512 weston_output_schedule_repaint(output);
1513}
1514
Pekka Paalanene508ce62015-02-19 13:59:55 +02001515/**
1516 * XXX: This function does it the wrong way.
1517 * surface->damage is the damage from the client, and causes
1518 * surface_flush_damage() to copy pixels. No window management action can
1519 * cause damage to the client-provided content, warranting re-upload!
1520 *
1521 * Instead of surface->damage, this function should record the damage
1522 * with all the views for this surface to avoid extraneous texture
1523 * uploads.
1524 */
Jason Ekstranda7af7042013-10-12 22:38:11 -05001525WL_EXPORT void
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05001526weston_surface_damage(struct weston_surface *surface)
Kristian Høgsberg31bd6c72011-02-13 13:00:51 -05001527{
Kristian Høgsberg460a79b2012-06-18 15:09:11 -04001528 pixman_region32_union_rect(&surface->damage, &surface->damage,
Jason Ekstranda7af7042013-10-12 22:38:11 -05001529 0, 0, surface->width,
1530 surface->height);
Pekka Paalanen2267d452012-01-26 13:12:45 +02001531
Kristian Høgsberg98238702012-08-03 16:29:12 -04001532 weston_surface_schedule_repaint(surface);
Kristian Høgsberg31bd6c72011-02-13 13:00:51 -05001533}
1534
Kristian Høgsberga691aee2011-06-23 21:43:50 -04001535WL_EXPORT void
Jason Ekstranda7af7042013-10-12 22:38:11 -05001536weston_view_set_position(struct weston_view *view, float x, float y)
Pekka Paalanen8fb8d3b2012-02-13 13:03:59 +02001537{
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06001538 if (view->geometry.x == x && view->geometry.y == y)
1539 return;
1540
Jason Ekstranda7af7042013-10-12 22:38:11 -05001541 view->geometry.x = x;
1542 view->geometry.y = y;
1543 weston_view_geometry_dirty(view);
Pekka Paalanen8fb8d3b2012-02-13 13:03:59 +02001544}
1545
Pekka Paalanen483243f2013-03-08 14:56:50 +02001546static void
1547transform_parent_handle_parent_destroy(struct wl_listener *listener,
1548 void *data)
1549{
Jason Ekstranda7af7042013-10-12 22:38:11 -05001550 struct weston_view *view =
1551 container_of(listener, struct weston_view,
Pekka Paalanen483243f2013-03-08 14:56:50 +02001552 geometry.parent_destroy_listener);
1553
Jason Ekstranda7af7042013-10-12 22:38:11 -05001554 weston_view_set_transform_parent(view, NULL);
Pekka Paalanen483243f2013-03-08 14:56:50 +02001555}
1556
1557WL_EXPORT void
Jason Ekstranda7af7042013-10-12 22:38:11 -05001558weston_view_set_transform_parent(struct weston_view *view,
Pekka Paalanen380adf52015-02-16 14:39:11 +02001559 struct weston_view *parent)
Pekka Paalanen483243f2013-03-08 14:56:50 +02001560{
Jason Ekstranda7af7042013-10-12 22:38:11 -05001561 if (view->geometry.parent) {
1562 wl_list_remove(&view->geometry.parent_destroy_listener.link);
1563 wl_list_remove(&view->geometry.parent_link);
Pekka Paalanen380adf52015-02-16 14:39:11 +02001564
1565 if (!parent)
1566 view->geometry.scissor_enabled = false;
Pekka Paalanen483243f2013-03-08 14:56:50 +02001567 }
1568
Jason Ekstranda7af7042013-10-12 22:38:11 -05001569 view->geometry.parent = parent;
Pekka Paalanen483243f2013-03-08 14:56:50 +02001570
Jason Ekstranda7af7042013-10-12 22:38:11 -05001571 view->geometry.parent_destroy_listener.notify =
Pekka Paalanen483243f2013-03-08 14:56:50 +02001572 transform_parent_handle_parent_destroy;
1573 if (parent) {
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05001574 wl_signal_add(&parent->destroy_signal,
Jason Ekstranda7af7042013-10-12 22:38:11 -05001575 &view->geometry.parent_destroy_listener);
Pekka Paalanen483243f2013-03-08 14:56:50 +02001576 wl_list_insert(&parent->geometry.child_list,
Jason Ekstranda7af7042013-10-12 22:38:11 -05001577 &view->geometry.parent_link);
Pekka Paalanen483243f2013-03-08 14:56:50 +02001578 }
1579
Jason Ekstranda7af7042013-10-12 22:38:11 -05001580 weston_view_geometry_dirty(view);
1581}
1582
Pekka Paalanen380adf52015-02-16 14:39:11 +02001583/** Set a clip mask rectangle on a view
1584 *
1585 * \param view The view to set the clip mask on.
1586 * \param x Top-left corner X coordinate of the clip rectangle.
1587 * \param y Top-left corner Y coordinate of the clip rectangle.
1588 * \param width Width of the clip rectangle, non-negative.
1589 * \param height Height of the clip rectangle, non-negative.
1590 *
1591 * A shell may set a clip mask rectangle on a view. Everything outside
1592 * the rectangle is cut away for input and output purposes: it is
1593 * not drawn and cannot be hit by hit-test based input like pointer
1594 * motion or touch-downs. Everything inside the rectangle will behave
1595 * normally. Clients are unaware of clipping.
1596 *
Yong Bakos4c72e292016-04-28 11:59:10 -05001597 * The rectangle is set in surface-local coordinates. Setting a clip
Pekka Paalanen380adf52015-02-16 14:39:11 +02001598 * mask rectangle does not affect the view position, the view is positioned
1599 * as it would be without a clip. The clip also does not change
1600 * weston_surface::width,height.
1601 *
1602 * The clip mask rectangle is part of transformation inheritance
1603 * (weston_view_set_transform_parent()). A clip set in the root of the
1604 * transformation inheritance tree will affect all views in the tree.
1605 * A clip can be set only on the root view. Attempting to set a clip
1606 * on view that has a transformation parent will fail. Assigning a parent
1607 * to a view that has a clip set will cause the clip to be forgotten.
1608 *
1609 * Because the clip mask is an axis-aligned rectangle, it poses restrictions
1610 * on the additional transformations in the child views. These transformations
1611 * may not rotate the coordinate axes, i.e., only translation and scaling
1612 * are allowed. Violating this restriction causes the clipping to malfunction.
1613 * Furthermore, using scaling may cause rounding errors in child clipping.
1614 *
1615 * The clip mask rectangle is not automatically adjusted based on
1616 * wl_surface.attach dx and dy arguments.
1617 *
1618 * A clip mask rectangle can be set only if the compositor capability
1619 * WESTON_CAP_VIEW_CLIP_MASK is present.
1620 *
1621 * This function sets the clip mask rectangle and schedules a repaint for
1622 * the view.
1623 */
1624WL_EXPORT void
1625weston_view_set_mask(struct weston_view *view,
1626 int x, int y, int width, int height)
1627{
1628 struct weston_compositor *compositor = view->surface->compositor;
1629
1630 if (!(compositor->capabilities & WESTON_CAP_VIEW_CLIP_MASK)) {
1631 weston_log("%s not allowed without capability!\n", __func__);
1632 return;
1633 }
1634
1635 if (view->geometry.parent) {
1636 weston_log("view %p has a parent, clip forbidden!\n", view);
1637 return;
1638 }
1639
1640 if (width < 0 || height < 0) {
1641 weston_log("%s: illegal args %d, %d, %d, %d\n", __func__,
1642 x, y, width, height);
1643 return;
1644 }
1645
1646 pixman_region32_fini(&view->geometry.scissor);
1647 pixman_region32_init_rect(&view->geometry.scissor, x, y, width, height);
1648 view->geometry.scissor_enabled = true;
1649 weston_view_geometry_dirty(view);
1650 weston_view_schedule_repaint(view);
1651}
1652
1653/** Remove the clip mask from a view
1654 *
1655 * \param view The view to remove the clip mask from.
1656 *
1657 * Removed the clip mask rectangle and schedules a repaint.
1658 *
1659 * \sa weston_view_set_mask
1660 */
1661WL_EXPORT void
1662weston_view_set_mask_infinite(struct weston_view *view)
1663{
1664 view->geometry.scissor_enabled = false;
1665 weston_view_geometry_dirty(view);
1666 weston_view_schedule_repaint(view);
1667}
1668
Armin Krezović0da12b82016-06-30 06:04:33 +02001669/* Check if view should be displayed
1670 *
1671 * The indicator is set manually when assigning
1672 * a view to a surface.
1673 *
1674 * This needs reworking. See the thread starting at:
1675 *
1676 * https://lists.freedesktop.org/archives/wayland-devel/2016-June/029656.html
1677 */
Derek Foreman280e7dd2014-10-03 13:13:42 -05001678WL_EXPORT bool
Jason Ekstranda7af7042013-10-12 22:38:11 -05001679weston_view_is_mapped(struct weston_view *view)
1680{
Armin Krezović0da12b82016-06-30 06:04:33 +02001681 return view->is_mapped;
Pekka Paalanen483243f2013-03-08 14:56:50 +02001682}
1683
Philipp Zabel70decd52018-09-03 20:11:15 +02001684/* Check if view is opaque in specified region
1685 *
1686 * \param view The view to check for opacity.
1687 * \param region The region to check for opacity, in view coordinates.
1688 *
1689 * Returns true if the view is opaque in the specified region, because view
1690 * alpha is 1.0 and either the opaque region set by the client contains the
1691 * specified region, or the buffer pixel format or solid color is opaque.
1692 */
1693WL_EXPORT bool
1694weston_view_is_opaque(struct weston_view *ev, pixman_region32_t *region)
1695{
1696 pixman_region32_t r;
1697 bool ret = false;
1698
1699 if (ev->alpha < 1.0)
1700 return false;
1701
1702 if (ev->surface->is_opaque)
1703 return true;
1704
1705 if (ev->transform.dirty) {
1706 weston_log("%s: transform dirty", __func__);
1707 return false;
1708 }
1709
1710 pixman_region32_init(&r);
1711 pixman_region32_subtract(&r, region, &ev->transform.opaque);
1712
1713 if (!pixman_region32_not_empty(&r))
1714 ret = true;
1715
1716 pixman_region32_fini(&r);
1717
1718 return ret;
1719}
1720
Armin Krezović0da12b82016-06-30 06:04:33 +02001721/* Check if a surface has a view assigned to it
1722 *
1723 * The indicator is set manually when mapping
1724 * a surface and creating a view for it.
1725 *
1726 * This needs to go. See the thread starting at:
1727 *
1728 * https://lists.freedesktop.org/archives/wayland-devel/2016-June/029656.html
1729 *
1730 */
Derek Foreman280e7dd2014-10-03 13:13:42 -05001731WL_EXPORT bool
Ander Conselvan de Oliveirab8ab14f2012-03-27 17:36:36 +03001732weston_surface_is_mapped(struct weston_surface *surface)
1733{
Armin Krezović0da12b82016-06-30 06:04:33 +02001734 return surface->is_mapped;
Ander Conselvan de Oliveirab8ab14f2012-03-27 17:36:36 +03001735}
1736
Pekka Paalanenda75ee12013-11-26 18:19:43 +01001737static void
Jason Ekstrand5c11a332013-12-04 20:32:03 -06001738surface_set_size(struct weston_surface *surface, int32_t width, int32_t height)
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06001739{
1740 struct weston_view *view;
1741
1742 if (surface->width == width && surface->height == height)
1743 return;
1744
1745 surface->width = width;
1746 surface->height = height;
1747
1748 wl_list_for_each(view, &surface->views, surface_link)
1749 weston_view_geometry_dirty(view);
1750}
1751
Jason Ekstrand5c11a332013-12-04 20:32:03 -06001752WL_EXPORT void
1753weston_surface_set_size(struct weston_surface *surface,
1754 int32_t width, int32_t height)
1755{
1756 assert(!surface->resource);
1757 surface_set_size(surface, width, height);
1758}
1759
Pekka Paalanen0b4c5352014-03-14 14:38:17 +02001760static int
1761fixed_round_up_to_int(wl_fixed_t f)
1762{
1763 return wl_fixed_to_int(wl_fixed_from_int(1) - 1 + f);
1764}
1765
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06001766static void
Pekka Paalanen59987fa2016-04-26 15:50:59 +03001767convert_size_by_transform_scale(int32_t *width_out, int32_t *height_out,
1768 int32_t width, int32_t height,
1769 uint32_t transform,
1770 int32_t scale)
1771{
1772 assert(scale > 0);
1773
1774 switch (transform) {
1775 case WL_OUTPUT_TRANSFORM_NORMAL:
1776 case WL_OUTPUT_TRANSFORM_180:
1777 case WL_OUTPUT_TRANSFORM_FLIPPED:
1778 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
1779 *width_out = width / scale;
1780 *height_out = height / scale;
1781 break;
1782 case WL_OUTPUT_TRANSFORM_90:
1783 case WL_OUTPUT_TRANSFORM_270:
1784 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
1785 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
1786 *width_out = height / scale;
1787 *height_out = width / scale;
1788 break;
1789 default:
1790 assert(0 && "invalid transform");
1791 }
1792}
1793
1794static void
George Kiagiadakis8f9e87f2014-06-13 18:14:20 +02001795weston_surface_calculate_size_from_buffer(struct weston_surface *surface)
Ander Conselvan de Oliveira012b4c72012-11-27 17:03:42 +02001796{
Pekka Paalanen952b6c82014-03-14 14:38:15 +02001797 struct weston_buffer_viewport *vp = &surface->buffer_viewport;
Pekka Paalanenda75ee12013-11-26 18:19:43 +01001798
1799 if (!surface->buffer_ref.buffer) {
Pekka Paalanen0b4c5352014-03-14 14:38:17 +02001800 surface->width_from_buffer = 0;
1801 surface->height_from_buffer = 0;
Jonny Lamb74130762013-11-26 18:19:46 +01001802 return;
1803 }
1804
Pekka Paalanen59987fa2016-04-26 15:50:59 +03001805 convert_size_by_transform_scale(&surface->width_from_buffer,
1806 &surface->height_from_buffer,
1807 surface->buffer_ref.buffer->width,
1808 surface->buffer_ref.buffer->height,
1809 vp->buffer.transform,
1810 vp->buffer.scale);
George Kiagiadakis8f9e87f2014-06-13 18:14:20 +02001811}
Pekka Paalanen0b4c5352014-03-14 14:38:17 +02001812
George Kiagiadakis8f9e87f2014-06-13 18:14:20 +02001813static void
1814weston_surface_update_size(struct weston_surface *surface)
1815{
1816 struct weston_buffer_viewport *vp = &surface->buffer_viewport;
1817 int32_t width, height;
1818
1819 width = surface->width_from_buffer;
1820 height = surface->height_from_buffer;
1821
1822 if (width != 0 && vp->surface.width != -1) {
Pekka Paalanen0b4c5352014-03-14 14:38:17 +02001823 surface_set_size(surface,
1824 vp->surface.width, vp->surface.height);
1825 return;
1826 }
1827
George Kiagiadakis8f9e87f2014-06-13 18:14:20 +02001828 if (width != 0 && vp->buffer.src_width != wl_fixed_from_int(-1)) {
Pekka Paalanene9317212014-04-04 14:22:13 +03001829 int32_t w = fixed_round_up_to_int(vp->buffer.src_width);
1830 int32_t h = fixed_round_up_to_int(vp->buffer.src_height);
1831
1832 surface_set_size(surface, w ?: 1, h ?: 1);
Pekka Paalanen0b4c5352014-03-14 14:38:17 +02001833 return;
1834 }
1835
Jason Ekstrand5c11a332013-12-04 20:32:03 -06001836 surface_set_size(surface, width, height);
Ander Conselvan de Oliveira012b4c72012-11-27 17:03:42 +02001837}
1838
Alexandros Frantzis409b01f2017-11-16 18:21:01 +02001839WL_EXPORT void
1840weston_compositor_get_time(struct timespec *time)
Kristian Høgsberg7132a9a2010-12-06 21:41:10 -05001841{
Alexandros Frantzis409b01f2017-11-16 18:21:01 +02001842 clock_gettime(CLOCK_REALTIME, time);
Kristian Høgsberg7132a9a2010-12-06 21:41:10 -05001843}
1844
Jason Ekstranda7af7042013-10-12 22:38:11 -05001845WL_EXPORT struct weston_view *
1846weston_compositor_pick_view(struct weston_compositor *compositor,
1847 wl_fixed_t x, wl_fixed_t y,
1848 wl_fixed_t *vx, wl_fixed_t *vy)
Tiago Vignatti9d393522012-02-10 16:26:19 +02001849{
Jason Ekstranda7af7042013-10-12 22:38:11 -05001850 struct weston_view *view;
Pekka Paalanenfc22a522015-02-18 15:08:29 +02001851 wl_fixed_t view_x, view_y;
1852 int view_ix, view_iy;
1853 int ix = wl_fixed_to_int(x);
1854 int iy = wl_fixed_to_int(y);
Tiago Vignatti9d393522012-02-10 16:26:19 +02001855
Jason Ekstranda7af7042013-10-12 22:38:11 -05001856 wl_list_for_each(view, &compositor->view_list, link) {
Pekka Paalanenfc22a522015-02-18 15:08:29 +02001857 if (!pixman_region32_contains_point(
1858 &view->transform.boundingbox, ix, iy, NULL))
1859 continue;
1860
1861 weston_view_from_global_fixed(view, x, y, &view_x, &view_y);
1862 view_ix = wl_fixed_to_int(view_x);
1863 view_iy = wl_fixed_to_int(view_y);
1864
1865 if (!pixman_region32_contains_point(&view->surface->input,
1866 view_ix, view_iy, NULL))
1867 continue;
1868
Pekka Paalanen380adf52015-02-16 14:39:11 +02001869 if (view->geometry.scissor_enabled &&
1870 !pixman_region32_contains_point(&view->geometry.scissor,
1871 view_ix, view_iy, NULL))
1872 continue;
1873
Pekka Paalanenfc22a522015-02-18 15:08:29 +02001874 *vx = view_x;
1875 *vy = view_y;
1876 return view;
Tiago Vignatti9d393522012-02-10 16:26:19 +02001877 }
1878
Derek Foremanf9318d12015-05-11 15:40:11 -05001879 *vx = wl_fixed_from_int(-1000000);
1880 *vy = wl_fixed_from_int(-1000000);
Tiago Vignatti9d393522012-02-10 16:26:19 +02001881 return NULL;
1882}
1883
1884static void
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05001885weston_compositor_repick(struct weston_compositor *compositor)
Kristian Høgsbergd2baf1f2011-10-11 22:20:37 -04001886{
Daniel Stone37816df2012-05-16 18:45:18 +01001887 struct weston_seat *seat;
Kristian Høgsbergd2baf1f2011-10-11 22:20:37 -04001888
Kristian Høgsberg10ddd972013-10-22 12:40:54 -07001889 if (!compositor->session_active)
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -05001890 return;
1891
Daniel Stone37816df2012-05-16 18:45:18 +01001892 wl_list_for_each(seat, &compositor->seat_list, link)
Kristian Høgsberga71e8b22013-05-06 21:51:21 -04001893 weston_seat_repick(seat);
Kristian Høgsbergd2baf1f2011-10-11 22:20:37 -04001894}
1895
Kristian Høgsbergaf7b1ff2012-06-26 21:19:23 -04001896WL_EXPORT void
Jason Ekstranda7af7042013-10-12 22:38:11 -05001897weston_view_unmap(struct weston_view *view)
Kristian Høgsberg3b5ea3b2012-02-17 12:43:56 -05001898{
Daniel Stone4dab5db2012-05-30 16:31:53 +01001899 struct weston_seat *seat;
Kristian Høgsberg867dec72012-03-01 17:09:37 -05001900
Jason Ekstranda7af7042013-10-12 22:38:11 -05001901 if (!weston_view_is_mapped(view))
1902 return;
Kristian Høgsberg867dec72012-03-01 17:09:37 -05001903
Jason Ekstranda7af7042013-10-12 22:38:11 -05001904 weston_view_damage_below(view);
Semi Malinene7a52fb2018-04-26 11:08:10 +02001905 weston_view_set_output(view, NULL);
Xiong Zhang97116532013-10-23 13:58:31 +08001906 view->plane = NULL;
Armin Krezovićf8486c32016-06-30 06:04:28 +02001907 view->is_mapped = false;
Giulio Camuffo412e6a52014-07-09 22:12:56 +03001908 weston_layer_entry_remove(&view->layer_link);
Jason Ekstranda7af7042013-10-12 22:38:11 -05001909 wl_list_remove(&view->link);
1910 wl_list_init(&view->link);
Jason Ekstranda7af7042013-10-12 22:38:11 -05001911 view->output_mask = 0;
1912 weston_surface_assign_output(view->surface);
1913
1914 if (weston_surface_is_mapped(view->surface))
1915 return;
1916
1917 wl_list_for_each(seat, &view->surface->compositor->seat_list, link) {
Derek Foreman1281a362015-07-31 16:55:32 -05001918 struct weston_touch *touch = weston_seat_get_touch(seat);
1919 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
1920 struct weston_keyboard *keyboard =
1921 weston_seat_get_keyboard(seat);
1922
1923 if (keyboard && keyboard->focus == view->surface)
1924 weston_keyboard_set_focus(keyboard, NULL);
1925 if (pointer && pointer->focus == view)
Derek Foremanf9318d12015-05-11 15:40:11 -05001926 weston_pointer_clear_focus(pointer);
Derek Foreman1281a362015-07-31 16:55:32 -05001927 if (touch && touch->focus == view)
1928 weston_touch_set_focus(touch, NULL);
Daniel Stone4dab5db2012-05-30 16:31:53 +01001929 }
Jason Ekstranda7af7042013-10-12 22:38:11 -05001930}
Kristian Høgsberg867dec72012-03-01 17:09:37 -05001931
Jason Ekstranda7af7042013-10-12 22:38:11 -05001932WL_EXPORT void
1933weston_surface_unmap(struct weston_surface *surface)
1934{
1935 struct weston_view *view;
1936
Armin Krezovićf8486c32016-06-30 06:04:28 +02001937 surface->is_mapped = false;
Jason Ekstranda7af7042013-10-12 22:38:11 -05001938 wl_list_for_each(view, &surface->views, surface_link)
1939 weston_view_unmap(view);
1940 surface->output = NULL;
Kristian Høgsberg3b5ea3b2012-02-17 12:43:56 -05001941}
1942
Pekka Paalanen3c9b8022014-03-14 14:38:13 +02001943static void
1944weston_surface_reset_pending_buffer(struct weston_surface *surface)
1945{
Jason Ekstrand7b982072014-05-20 14:33:03 -05001946 weston_surface_state_set_buffer(&surface->pending, NULL);
Pekka Paalanen3c9b8022014-03-14 14:38:13 +02001947 surface->pending.sx = 0;
1948 surface->pending.sy = 0;
1949 surface->pending.newly_attached = 0;
George Kiagiadakis8f9e87f2014-06-13 18:14:20 +02001950 surface->pending.buffer_viewport.changed = 0;
Pekka Paalanen3c9b8022014-03-14 14:38:13 +02001951}
1952
Jason Ekstranda7af7042013-10-12 22:38:11 -05001953WL_EXPORT void
1954weston_view_destroy(struct weston_view *view)
1955{
1956 wl_signal_emit(&view->destroy_signal, view);
1957
1958 assert(wl_list_empty(&view->geometry.child_list));
1959
1960 if (weston_view_is_mapped(view)) {
1961 weston_view_unmap(view);
1962 weston_compositor_build_view_list(view->surface->compositor);
1963 }
1964
1965 wl_list_remove(&view->link);
Giulio Camuffo412e6a52014-07-09 22:12:56 +03001966 weston_layer_entry_remove(&view->layer_link);
Jason Ekstranda7af7042013-10-12 22:38:11 -05001967
1968 pixman_region32_fini(&view->clip);
Pekka Paalanen380adf52015-02-16 14:39:11 +02001969 pixman_region32_fini(&view->geometry.scissor);
Jason Ekstranda7af7042013-10-12 22:38:11 -05001970 pixman_region32_fini(&view->transform.boundingbox);
Pekka Paalanen8844bf22015-02-18 16:30:47 +02001971 pixman_region32_fini(&view->transform.opaque);
Jason Ekstranda7af7042013-10-12 22:38:11 -05001972
1973 weston_view_set_transform_parent(view, NULL);
Pekka Paalanen944fae82018-05-22 13:15:58 +03001974 weston_view_set_output(view, NULL);
Jason Ekstranda7af7042013-10-12 22:38:11 -05001975
Jason Ekstranda7af7042013-10-12 22:38:11 -05001976 wl_list_remove(&view->surface_link);
1977
1978 free(view);
1979}
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05001980
1981WL_EXPORT void
1982weston_surface_destroy(struct weston_surface *surface)
Kristian Høgsberg54879822008-11-23 17:07:32 -05001983{
Kristian Høgsberg1e51fec2012-07-22 11:33:14 -04001984 struct weston_frame_callback *cb, *next;
Jason Ekstranda7af7042013-10-12 22:38:11 -05001985 struct weston_view *ev, *nv;
Jonas Ådahld3414f22016-07-22 17:56:31 +08001986 struct weston_pointer_constraint *constraint, *next_constraint;
Kristian Høgsberg4fa48732009-03-10 23:17:00 -04001987
Giulio Camuffo13b85bd2013-08-13 23:10:14 +02001988 if (--surface->ref_count > 0)
1989 return;
1990
Pekka Paalanen08d3fb72015-04-17 14:00:24 +03001991 assert(surface->resource == NULL);
1992
Pekka Paalanenca790762015-04-17 14:23:38 +03001993 wl_signal_emit(&surface->destroy_signal, surface);
Giulio Camuffo13b85bd2013-08-13 23:10:14 +02001994
Pekka Paalanene67858b2013-04-25 13:57:42 +03001995 assert(wl_list_empty(&surface->subsurface_list_pending));
1996 assert(wl_list_empty(&surface->subsurface_list));
Pekka Paalanen483243f2013-03-08 14:56:50 +02001997
Jason Ekstranda7af7042013-10-12 22:38:11 -05001998 wl_list_for_each_safe(ev, nv, &surface->views, surface_link)
1999 weston_view_destroy(ev);
Kristian Høgsbergd2baf1f2011-10-11 22:20:37 -04002000
Jason Ekstrand7b982072014-05-20 14:33:03 -05002001 weston_surface_state_fini(&surface->pending);
Pekka Paalanen5df44de2012-10-10 12:49:23 +03002002
Pekka Paalanende685b82012-12-04 15:58:12 +02002003 weston_buffer_reference(&surface->buffer_ref, NULL);
Kristian Høgsberg3f8f39c2009-09-18 17:05:13 -04002004
Pekka Paalanen402ae6d2012-01-03 10:23:24 +02002005 pixman_region32_fini(&surface->damage);
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05002006 pixman_region32_fini(&surface->opaque);
Pekka Paalanen0cbd3b52012-10-10 12:49:28 +03002007 pixman_region32_fini(&surface->input);
Pekka Paalanen402ae6d2012-01-03 10:23:24 +02002008
Kristian Høgsberg1e51fec2012-07-22 11:33:14 -04002009 wl_list_for_each_safe(cb, next, &surface->frame_callback_list, link)
Jason Ekstrandfbbbec82013-06-14 10:07:57 -05002010 wl_resource_destroy(cb->resource);
Kristian Høgsberg1e51fec2012-07-22 11:33:14 -04002011
Pekka Paalanen133e4392014-09-23 22:08:46 -04002012 weston_presentation_feedback_discard_list(&surface->feedback_list);
2013
Jonas Ådahld3414f22016-07-22 17:56:31 +08002014 wl_list_for_each_safe(constraint, next_constraint,
2015 &surface->pointer_constraints,
2016 link)
2017 weston_pointer_constraint_destroy(constraint);
2018
Kristian Høgsberg4fa48732009-03-10 23:17:00 -04002019 free(surface);
Kristian Høgsberg54879822008-11-23 17:07:32 -05002020}
2021
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05002022static void
2023destroy_surface(struct wl_resource *resource)
Alex Wu8811bf92012-02-28 18:07:54 +08002024{
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05002025 struct weston_surface *surface = wl_resource_get_user_data(resource);
Alex Wu8811bf92012-02-28 18:07:54 +08002026
Pekka Paalanen08d3fb72015-04-17 14:00:24 +03002027 assert(surface);
2028
Giulio Camuffo0d379742013-11-15 22:06:15 +01002029 /* Set the resource to NULL, since we don't want to leave a
2030 * dangling pointer if the surface was refcounted and survives
2031 * the weston_surface_destroy() call. */
2032 surface->resource = NULL;
Pekka Paalanen4826f872016-04-22 14:14:38 +03002033
2034 if (surface->viewport_resource)
2035 wl_resource_set_user_data(surface->viewport_resource, NULL);
2036
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05002037 weston_surface_destroy(surface);
Alex Wu8811bf92012-02-28 18:07:54 +08002038}
2039
Benjamin Franzkefaa0a9d2011-02-21 16:24:53 +01002040static void
Jason Ekstrand6bd62942013-06-20 20:38:23 -05002041weston_buffer_destroy_handler(struct wl_listener *listener, void *data)
2042{
2043 struct weston_buffer *buffer =
2044 container_of(listener, struct weston_buffer, destroy_listener);
2045
2046 wl_signal_emit(&buffer->destroy_signal, buffer);
2047 free(buffer);
2048}
2049
Giulio Camuffoe058cd12013-12-12 14:14:29 +01002050WL_EXPORT struct weston_buffer *
Jason Ekstrand6bd62942013-06-20 20:38:23 -05002051weston_buffer_from_resource(struct wl_resource *resource)
2052{
2053 struct weston_buffer *buffer;
2054 struct wl_listener *listener;
U. Artie Eoff2e2384a2014-01-17 13:19:01 -08002055
Jason Ekstrand6bd62942013-06-20 20:38:23 -05002056 listener = wl_resource_get_destroy_listener(resource,
2057 weston_buffer_destroy_handler);
2058
Kristian Høgsberg08b58c72013-08-15 12:26:42 -07002059 if (listener)
2060 return container_of(listener, struct weston_buffer,
2061 destroy_listener);
2062
2063 buffer = zalloc(sizeof *buffer);
2064 if (buffer == NULL)
2065 return NULL;
2066
2067 buffer->resource = resource;
2068 wl_signal_init(&buffer->destroy_signal);
2069 buffer->destroy_listener.notify = weston_buffer_destroy_handler;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04002070 buffer->y_inverted = 1;
Kristian Høgsberg08b58c72013-08-15 12:26:42 -07002071 wl_resource_add_destroy_listener(resource, &buffer->destroy_listener);
U. Artie Eoff2e2384a2014-01-17 13:19:01 -08002072
Jason Ekstrand6bd62942013-06-20 20:38:23 -05002073 return buffer;
2074}
2075
2076static void
Pekka Paalanende685b82012-12-04 15:58:12 +02002077weston_buffer_reference_handle_destroy(struct wl_listener *listener,
2078 void *data)
Benjamin Franzkefaa0a9d2011-02-21 16:24:53 +01002079{
Pekka Paalanende685b82012-12-04 15:58:12 +02002080 struct weston_buffer_reference *ref =
2081 container_of(listener, struct weston_buffer_reference,
2082 destroy_listener);
2083
Jason Ekstrand6bd62942013-06-20 20:38:23 -05002084 assert((struct weston_buffer *)data == ref->buffer);
Pekka Paalanende685b82012-12-04 15:58:12 +02002085 ref->buffer = NULL;
2086}
2087
2088WL_EXPORT void
2089weston_buffer_reference(struct weston_buffer_reference *ref,
Jason Ekstrand6bd62942013-06-20 20:38:23 -05002090 struct weston_buffer *buffer)
Pekka Paalanende685b82012-12-04 15:58:12 +02002091{
2092 if (ref->buffer && buffer != ref->buffer) {
Kristian Høgsberg20347802013-03-04 12:07:46 -05002093 ref->buffer->busy_count--;
2094 if (ref->buffer->busy_count == 0) {
Jason Ekstrand6bd62942013-06-20 20:38:23 -05002095 assert(wl_resource_get_client(ref->buffer->resource));
Matt Hoosier3052bc72017-09-26 08:09:40 -05002096 wl_buffer_send_release(ref->buffer->resource);
Kristian Høgsberg20347802013-03-04 12:07:46 -05002097 }
Pekka Paalanende685b82012-12-04 15:58:12 +02002098 wl_list_remove(&ref->destroy_listener.link);
Ander Conselvan de Oliveirae11683a2012-03-27 17:36:40 +03002099 }
2100
Pekka Paalanende685b82012-12-04 15:58:12 +02002101 if (buffer && buffer != ref->buffer) {
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04002102 buffer->busy_count++;
Jason Ekstrand6bd62942013-06-20 20:38:23 -05002103 wl_signal_add(&buffer->destroy_signal,
Pekka Paalanende685b82012-12-04 15:58:12 +02002104 &ref->destroy_listener);
Pekka Paalanena6421c42012-12-04 15:58:10 +02002105 }
2106
Pekka Paalanende685b82012-12-04 15:58:12 +02002107 ref->buffer = buffer;
2108 ref->destroy_listener.notify = weston_buffer_reference_handle_destroy;
2109}
2110
2111static void
Jason Ekstrand6bd62942013-06-20 20:38:23 -05002112weston_surface_attach(struct weston_surface *surface,
2113 struct weston_buffer *buffer)
Pekka Paalanende685b82012-12-04 15:58:12 +02002114{
2115 weston_buffer_reference(&surface->buffer_ref, buffer);
2116
Pekka Paalanena6421c42012-12-04 15:58:10 +02002117 if (!buffer) {
Pekka Paalanen5df44de2012-10-10 12:49:23 +03002118 if (weston_surface_is_mapped(surface))
2119 weston_surface_unmap(surface);
Ander Conselvan de Oliveirae11683a2012-03-27 17:36:40 +03002120 }
2121
Pekka Paalanen5df44de2012-10-10 12:49:23 +03002122 surface->compositor->renderer->attach(surface, buffer);
Pekka Paalanenbb2f3f22014-03-14 14:38:11 +02002123
George Kiagiadakis8f9e87f2014-06-13 18:14:20 +02002124 weston_surface_calculate_size_from_buffer(surface);
Pekka Paalanen133e4392014-09-23 22:08:46 -04002125 weston_presentation_feedback_discard_list(&surface->feedback_list);
Benjamin Franzkefaa0a9d2011-02-21 16:24:53 +01002126}
2127
Kristian Høgsberg3be2ce92012-02-29 12:42:35 -05002128WL_EXPORT void
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05002129weston_compositor_damage_all(struct weston_compositor *compositor)
Kristian Høgsberge10a5d92011-04-22 14:01:18 -04002130{
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05002131 struct weston_output *output;
Kristian Høgsberge10a5d92011-04-22 14:01:18 -04002132
2133 wl_list_for_each(output, &compositor->output_list, link)
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05002134 weston_output_damage(output);
Kristian Høgsberge10a5d92011-04-22 14:01:18 -04002135}
2136
Kristian Høgsberg9f404b72012-01-26 00:11:01 -05002137WL_EXPORT void
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05002138weston_output_damage(struct weston_output *output)
Kristian Høgsberge10a5d92011-04-22 14:01:18 -04002139{
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05002140 struct weston_compositor *compositor = output->compositor;
Kristian Høgsberge10a5d92011-04-22 14:01:18 -04002141
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04002142 pixman_region32_union(&compositor->primary_plane.damage,
2143 &compositor->primary_plane.damage,
2144 &output->region);
Kristian Høgsberg49952d12012-06-20 00:35:59 -04002145 weston_output_schedule_repaint(output);
Kristian Høgsberge10a5d92011-04-22 14:01:18 -04002146}
2147
Kristian Høgsberg01f941b2009-05-27 17:47:15 -04002148static void
Jason Ekstranda7af7042013-10-12 22:38:11 -05002149surface_flush_damage(struct weston_surface *surface)
Kristian Høgsberg460a79b2012-06-18 15:09:11 -04002150{
Pekka Paalanende685b82012-12-04 15:58:12 +02002151 if (surface->buffer_ref.buffer &&
Jason Ekstrand6bd62942013-06-20 20:38:23 -05002152 wl_shm_buffer_get(surface->buffer_ref.buffer->resource))
Kristian Høgsbergfa1be022012-09-05 22:49:55 -04002153 surface->compositor->renderer->flush_damage(surface);
Kristian Høgsberg460a79b2012-06-18 15:09:11 -04002154
Pekka Paalanenb5026542014-11-12 15:09:24 +02002155 if (weston_timeline_enabled_ &&
2156 pixman_region32_not_empty(&surface->damage))
2157 TL_POINT("core_flush_damage", TLP_SURFACE(surface),
2158 TLP_OUTPUT(surface->output), TLP_END);
2159
Jason Ekstrandef540082014-06-26 10:37:36 -07002160 pixman_region32_clear(&surface->damage);
Jason Ekstranda7af7042013-10-12 22:38:11 -05002161}
2162
2163static void
2164view_accumulate_damage(struct weston_view *view,
2165 pixman_region32_t *opaque)
2166{
2167 pixman_region32_t damage;
2168
2169 pixman_region32_init(&damage);
2170 if (view->transform.enabled) {
Kristian Høgsberg460a79b2012-06-18 15:09:11 -04002171 pixman_box32_t *extents;
2172
Jason Ekstranda7af7042013-10-12 22:38:11 -05002173 extents = pixman_region32_extents(&view->surface->damage);
Pekka Paalanenc7d7fdf2015-02-23 12:27:00 +02002174 view_compute_bbox(view, extents, &damage);
Kristian Høgsberg460a79b2012-06-18 15:09:11 -04002175 } else {
Jason Ekstranda7af7042013-10-12 22:38:11 -05002176 pixman_region32_copy(&damage, &view->surface->damage);
2177 pixman_region32_translate(&damage,
Pekka Paalanen502f5e02015-02-23 14:08:25 +02002178 view->geometry.x, view->geometry.y);
Kristian Høgsberg460a79b2012-06-18 15:09:11 -04002179 }
2180
Pekka Paalanen380adf52015-02-16 14:39:11 +02002181 pixman_region32_intersect(&damage, &damage,
2182 &view->transform.boundingbox);
Jason Ekstranda7af7042013-10-12 22:38:11 -05002183 pixman_region32_subtract(&damage, &damage, opaque);
2184 pixman_region32_union(&view->plane->damage,
2185 &view->plane->damage, &damage);
2186 pixman_region32_fini(&damage);
2187 pixman_region32_copy(&view->clip, opaque);
Pekka Paalanen8844bf22015-02-18 16:30:47 +02002188 pixman_region32_union(opaque, opaque, &view->transform.opaque);
Kristian Høgsberg460a79b2012-06-18 15:09:11 -04002189}
2190
Kristian Høgsbergcce1aec2011-04-22 15:38:14 -04002191static void
Ander Conselvan de Oliveira8ad19822013-03-05 17:30:27 +02002192compositor_accumulate_damage(struct weston_compositor *ec)
2193{
2194 struct weston_plane *plane;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002195 struct weston_view *ev;
Ander Conselvan de Oliveirae1bd5a02013-03-05 17:30:29 +02002196 pixman_region32_t opaque, clip;
Ander Conselvan de Oliveira8ad19822013-03-05 17:30:27 +02002197
Ander Conselvan de Oliveirae1bd5a02013-03-05 17:30:29 +02002198 pixman_region32_init(&clip);
Ander Conselvan de Oliveira8ad19822013-03-05 17:30:27 +02002199
2200 wl_list_for_each(plane, &ec->plane_list, link) {
Ander Conselvan de Oliveirae1bd5a02013-03-05 17:30:29 +02002201 pixman_region32_copy(&plane->clip, &clip);
2202
2203 pixman_region32_init(&opaque);
2204
Jason Ekstranda7af7042013-10-12 22:38:11 -05002205 wl_list_for_each(ev, &ec->view_list, link) {
2206 if (ev->plane != plane)
Ander Conselvan de Oliveirae1bd5a02013-03-05 17:30:29 +02002207 continue;
2208
Jason Ekstranda7af7042013-10-12 22:38:11 -05002209 view_accumulate_damage(ev, &opaque);
Ander Conselvan de Oliveirae1bd5a02013-03-05 17:30:29 +02002210 }
2211
2212 pixman_region32_union(&clip, &clip, &opaque);
2213 pixman_region32_fini(&opaque);
Ander Conselvan de Oliveira8ad19822013-03-05 17:30:27 +02002214 }
2215
Ander Conselvan de Oliveirae1bd5a02013-03-05 17:30:29 +02002216 pixman_region32_fini(&clip);
Ander Conselvan de Oliveira8ad19822013-03-05 17:30:27 +02002217
Jason Ekstranda7af7042013-10-12 22:38:11 -05002218 wl_list_for_each(ev, &ec->view_list, link)
Derek Foreman060cf112015-11-18 16:32:26 -06002219 ev->surface->touched = false;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002220
2221 wl_list_for_each(ev, &ec->view_list, link) {
2222 if (ev->surface->touched)
2223 continue;
Derek Foreman060cf112015-11-18 16:32:26 -06002224 ev->surface->touched = true;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002225
2226 surface_flush_damage(ev->surface);
2227
Ander Conselvan de Oliveira8ad19822013-03-05 17:30:27 +02002228 /* Both the renderer and the backend have seen the buffer
2229 * by now. If renderer needs the buffer, it has its own
2230 * reference set. If the backend wants to keep the buffer
2231 * around for migrating the surface into a non-primary plane
2232 * later, keep_buffer is true. Otherwise, drop the core
2233 * reference now, and allow early buffer release. This enables
2234 * clients to use single-buffering.
2235 */
Jason Ekstranda7af7042013-10-12 22:38:11 -05002236 if (!ev->surface->keep_buffer)
2237 weston_buffer_reference(&ev->surface->buffer_ref, NULL);
Ander Conselvan de Oliveira8ad19822013-03-05 17:30:27 +02002238 }
Ander Conselvan de Oliveira8ad19822013-03-05 17:30:27 +02002239}
2240
2241static void
Jason Ekstranda7af7042013-10-12 22:38:11 -05002242surface_stash_subsurface_views(struct weston_surface *surface)
Pekka Paalanene67858b2013-04-25 13:57:42 +03002243{
2244 struct weston_subsurface *sub;
2245
Pekka Paalanene67858b2013-04-25 13:57:42 +03002246 wl_list_for_each(sub, &surface->subsurface_list, parent_link) {
Jason Ekstranda7af7042013-10-12 22:38:11 -05002247 if (sub->surface == surface)
Pekka Paalanene67858b2013-04-25 13:57:42 +03002248 continue;
2249
Jason Ekstranda7af7042013-10-12 22:38:11 -05002250 wl_list_insert_list(&sub->unused_views, &sub->surface->views);
2251 wl_list_init(&sub->surface->views);
2252
2253 surface_stash_subsurface_views(sub->surface);
Pekka Paalanene67858b2013-04-25 13:57:42 +03002254 }
2255}
2256
2257static void
Jason Ekstranda7af7042013-10-12 22:38:11 -05002258surface_free_unused_subsurface_views(struct weston_surface *surface)
Pekka Paalanene67858b2013-04-25 13:57:42 +03002259{
Jason Ekstranda7af7042013-10-12 22:38:11 -05002260 struct weston_subsurface *sub;
2261 struct weston_view *view, *nv;
Pekka Paalanene67858b2013-04-25 13:57:42 +03002262
Jason Ekstranda7af7042013-10-12 22:38:11 -05002263 wl_list_for_each(sub, &surface->subsurface_list, parent_link) {
2264 if (sub->surface == surface)
2265 continue;
2266
George Kiagiadakised04d382014-06-13 18:10:26 +02002267 wl_list_for_each_safe(view, nv, &sub->unused_views, surface_link) {
2268 weston_view_unmap (view);
Jason Ekstranda7af7042013-10-12 22:38:11 -05002269 weston_view_destroy(view);
George Kiagiadakised04d382014-06-13 18:10:26 +02002270 }
Jason Ekstranda7af7042013-10-12 22:38:11 -05002271
2272 surface_free_unused_subsurface_views(sub->surface);
2273 }
2274}
2275
2276static void
2277view_list_add_subsurface_view(struct weston_compositor *compositor,
2278 struct weston_subsurface *sub,
2279 struct weston_view *parent)
2280{
2281 struct weston_subsurface *child;
2282 struct weston_view *view = NULL, *iv;
2283
Pekka Paalanen661de3a2014-07-28 12:49:24 +03002284 if (!weston_surface_is_mapped(sub->surface))
2285 return;
2286
Jason Ekstranda7af7042013-10-12 22:38:11 -05002287 wl_list_for_each(iv, &sub->unused_views, surface_link) {
2288 if (iv->geometry.parent == parent) {
2289 view = iv;
2290 break;
Pekka Paalanene67858b2013-04-25 13:57:42 +03002291 }
2292 }
Jason Ekstranda7af7042013-10-12 22:38:11 -05002293
2294 if (view) {
2295 /* Put it back in the surface's list of views */
2296 wl_list_remove(&view->surface_link);
2297 wl_list_insert(&sub->surface->views, &view->surface_link);
2298 } else {
2299 view = weston_view_create(sub->surface);
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06002300 weston_view_set_position(view,
2301 sub->position.x,
2302 sub->position.y);
Jason Ekstranda7af7042013-10-12 22:38:11 -05002303 weston_view_set_transform_parent(view, parent);
2304 }
2305
Giulio Camuffo95ec0f92014-07-09 22:12:57 +03002306 view->parent_view = parent;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002307 weston_view_update_transform(view);
Armin Krezovićf8486c32016-06-30 06:04:28 +02002308 view->is_mapped = true;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002309
Pekka Paalanenb188e912013-11-19 14:03:35 +02002310 if (wl_list_empty(&sub->surface->subsurface_list)) {
2311 wl_list_insert(compositor->view_list.prev, &view->link);
2312 return;
2313 }
2314
2315 wl_list_for_each(child, &sub->surface->subsurface_list, parent_link) {
2316 if (child->surface == sub->surface)
2317 wl_list_insert(compositor->view_list.prev, &view->link);
2318 else
Jason Ekstranda7af7042013-10-12 22:38:11 -05002319 view_list_add_subsurface_view(compositor, child, view);
Pekka Paalanenb188e912013-11-19 14:03:35 +02002320 }
Jason Ekstranda7af7042013-10-12 22:38:11 -05002321}
2322
Emilio Pozuelo Monfort4f3cad72017-01-27 17:30:29 +01002323/* This recursively adds the sub-surfaces for a view, relying on the
2324 * sub-surface order. Thus, if a client restacks the sub-surfaces, that
2325 * change first happens to the sub-surface list, and then automatically
2326 * propagates here. See weston_surface_damage_subsurfaces() for how the
2327 * sub-surfaces receive damage when the client changes the state.
2328 */
Jason Ekstranda7af7042013-10-12 22:38:11 -05002329static void
2330view_list_add(struct weston_compositor *compositor,
2331 struct weston_view *view)
2332{
2333 struct weston_subsurface *sub;
2334
2335 weston_view_update_transform(view);
Jason Ekstranda7af7042013-10-12 22:38:11 -05002336
Pekka Paalanenb188e912013-11-19 14:03:35 +02002337 if (wl_list_empty(&view->surface->subsurface_list)) {
2338 wl_list_insert(compositor->view_list.prev, &view->link);
2339 return;
2340 }
2341
2342 wl_list_for_each(sub, &view->surface->subsurface_list, parent_link) {
2343 if (sub->surface == view->surface)
2344 wl_list_insert(compositor->view_list.prev, &view->link);
2345 else
Jason Ekstranda7af7042013-10-12 22:38:11 -05002346 view_list_add_subsurface_view(compositor, sub, view);
Pekka Paalanenb188e912013-11-19 14:03:35 +02002347 }
Jason Ekstranda7af7042013-10-12 22:38:11 -05002348}
2349
2350static void
2351weston_compositor_build_view_list(struct weston_compositor *compositor)
2352{
2353 struct weston_view *view;
2354 struct weston_layer *layer;
2355
2356 wl_list_for_each(layer, &compositor->layer_list, link)
Giulio Camuffo412e6a52014-07-09 22:12:56 +03002357 wl_list_for_each(view, &layer->view_list.link, layer_link.link)
Jason Ekstranda7af7042013-10-12 22:38:11 -05002358 surface_stash_subsurface_views(view->surface);
2359
2360 wl_list_init(&compositor->view_list);
2361 wl_list_for_each(layer, &compositor->layer_list, link) {
Giulio Camuffo412e6a52014-07-09 22:12:56 +03002362 wl_list_for_each(view, &layer->view_list.link, layer_link.link) {
Jason Ekstranda7af7042013-10-12 22:38:11 -05002363 view_list_add(compositor, view);
2364 }
2365 }
2366
2367 wl_list_for_each(layer, &compositor->layer_list, link)
Giulio Camuffo412e6a52014-07-09 22:12:56 +03002368 wl_list_for_each(view, &layer->view_list.link, layer_link.link)
Jason Ekstranda7af7042013-10-12 22:38:11 -05002369 surface_free_unused_subsurface_views(view->surface);
Pekka Paalanene67858b2013-04-25 13:57:42 +03002370}
2371
Pekka Paalanenbf0e0312014-12-17 16:20:41 +02002372static void
2373weston_output_take_feedback_list(struct weston_output *output,
2374 struct weston_surface *surface)
2375{
2376 struct weston_view *view;
2377 struct weston_presentation_feedback *feedback;
2378 uint32_t flags = 0xffffffff;
2379
2380 if (wl_list_empty(&surface->feedback_list))
2381 return;
2382
2383 /* All views must have the flag for the flag to survive. */
2384 wl_list_for_each(view, &surface->views, surface_link) {
2385 /* ignore views that are not on this output at all */
2386 if (view->output_mask & (1u << output->id))
2387 flags &= view->psf_flags;
2388 }
2389
2390 wl_list_for_each(feedback, &surface->feedback_list, link)
2391 feedback->psf_flags = flags;
2392
2393 wl_list_insert_list(&output->feedback_list, &surface->feedback_list);
2394 wl_list_init(&surface->feedback_list);
2395}
2396
David Herrmann1edf44c2013-10-22 17:11:26 +02002397static int
Daniel Stoneb1f166d2017-03-01 11:34:10 +00002398weston_output_repaint(struct weston_output *output, void *repaint_data)
Kristian Høgsbergef7a9ca2008-10-11 21:21:39 -04002399{
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05002400 struct weston_compositor *ec = output->compositor;
Jason Ekstranda7af7042013-10-12 22:38:11 -05002401 struct weston_view *ev;
Kristian Høgsberg30c018b2012-01-26 08:40:37 -05002402 struct weston_animation *animation, *next;
2403 struct weston_frame_callback *cb, *cnext;
Jonas Ådahldb773762012-06-13 00:01:21 +02002404 struct wl_list frame_callback_list;
Ander Conselvan de Oliveira8ad19822013-03-05 17:30:27 +02002405 pixman_region32_t output_damage;
David Herrmann1edf44c2013-10-22 17:11:26 +02002406 int r;
Alexandros Frantzise6ac2af2017-11-16 18:20:53 +02002407 uint32_t frame_time_msec;
Kristian Høgsbergfbdbbdc2008-11-28 17:06:06 -05002408
Ander Conselvan de Oliveirae1e23522013-12-13 22:10:55 +02002409 if (output->destroying)
2410 return 0;
2411
Pekka Paalanenb5026542014-11-12 15:09:24 +02002412 TL_POINT("core_repaint_begin", TLP_OUTPUT(output), TLP_END);
2413
Kristian Høgsberg3be2ce92012-02-29 12:42:35 -05002414 /* Rebuild the surface list and update surface transforms up front. */
Jason Ekstranda7af7042013-10-12 22:38:11 -05002415 weston_compositor_build_view_list(ec);
Pekka Paalanen15d60ef2012-01-27 14:38:33 +02002416
Pekka Paalanenbf0e0312014-12-17 16:20:41 +02002417 if (output->assign_planes && !output->disable_planes) {
Daniel Stoneb1f166d2017-03-01 11:34:10 +00002418 output->assign_planes(output, repaint_data);
Pekka Paalanenbf0e0312014-12-17 16:20:41 +02002419 } else {
2420 wl_list_for_each(ev, &ec->view_list, link) {
Jason Ekstranda7af7042013-10-12 22:38:11 -05002421 weston_view_move_to_plane(ev, &ec->primary_plane);
Pekka Paalanenbf0e0312014-12-17 16:20:41 +02002422 ev->psf_flags = 0;
2423 }
2424 }
Kristian Høgsberg79af73e2012-08-03 15:45:23 -04002425
Pekka Paalanene67858b2013-04-25 13:57:42 +03002426 wl_list_init(&frame_callback_list);
Jason Ekstranda7af7042013-10-12 22:38:11 -05002427 wl_list_for_each(ev, &ec->view_list, link) {
2428 /* Note: This operation is safe to do multiple times on the
2429 * same surface.
2430 */
2431 if (ev->surface->output == output) {
Pekka Paalanene67858b2013-04-25 13:57:42 +03002432 wl_list_insert_list(&frame_callback_list,
Jason Ekstranda7af7042013-10-12 22:38:11 -05002433 &ev->surface->frame_callback_list);
2434 wl_list_init(&ev->surface->frame_callback_list);
Pekka Paalanen133e4392014-09-23 22:08:46 -04002435
Pekka Paalanenbf0e0312014-12-17 16:20:41 +02002436 weston_output_take_feedback_list(output, ev->surface);
Pekka Paalanene67858b2013-04-25 13:57:42 +03002437 }
2438 }
2439
Ander Conselvan de Oliveira8ad19822013-03-05 17:30:27 +02002440 compositor_accumulate_damage(ec);
Kristian Høgsberg53df1d82011-06-23 21:11:19 -04002441
Ander Conselvan de Oliveira4f521732012-08-15 14:02:05 -04002442 pixman_region32_init(&output_damage);
Ander Conselvan de Oliveira4f521732012-08-15 14:02:05 -04002443 pixman_region32_intersect(&output_damage,
2444 &ec->primary_plane.damage, &output->region);
Ander Conselvan de Oliveirae1bd5a02013-03-05 17:30:29 +02002445 pixman_region32_subtract(&output_damage,
2446 &output_damage, &ec->primary_plane.clip);
Ander Conselvan de Oliveira4f521732012-08-15 14:02:05 -04002447
Scott Moreauccbf29d2012-02-22 14:21:41 -07002448 if (output->dirty)
2449 weston_output_update_matrix(output);
2450
Daniel Stoneb1f166d2017-03-01 11:34:10 +00002451 r = output->repaint(output, &output_damage, repaint_data);
Kristian Høgsbergef7a9ca2008-10-11 21:21:39 -04002452
Kristian Høgsberg6ddcdae2012-02-28 22:31:58 -05002453 pixman_region32_fini(&output_damage);
Kristian Høgsberg81ce09a2008-12-31 16:18:42 -05002454
Daniel Stone09a97e22017-03-01 11:34:06 +00002455 output->repaint_needed = false;
Daniel Stone05df8c12017-03-03 16:59:42 +00002456 if (r == 0)
2457 output->repaint_status = REPAINT_AWAITING_COMPLETION;
Benjamin Franzkeec4d3422011-03-14 12:07:26 +01002458
Kristian Høgsbergaa6019e2012-03-11 16:35:16 -04002459 weston_compositor_repick(ec);
Kristian Høgsbergaa6019e2012-03-11 16:35:16 -04002460
Alexandros Frantzise6ac2af2017-11-16 18:20:53 +02002461 frame_time_msec = timespec_to_msec(&output->frame_time);
2462
Jonas Ådahldb773762012-06-13 00:01:21 +02002463 wl_list_for_each_safe(cb, cnext, &frame_callback_list, link) {
Alexandros Frantzise6ac2af2017-11-16 18:20:53 +02002464 wl_callback_send_done(cb->resource, frame_time_msec);
Jason Ekstrandfbbbec82013-06-14 10:07:57 -05002465 wl_resource_destroy(cb->resource);
Kristian Høgsberg81ce09a2008-12-31 16:18:42 -05002466 }
2467
Scott Moreaud64cf212012-06-08 19:40:54 -06002468 wl_list_for_each_safe(animation, next, &output->animation_list, link) {
Scott Moreaud64cf212012-06-08 19:40:54 -06002469 animation->frame_counter++;
Alexandros Frantzise6ac2af2017-11-16 18:20:53 +02002470 animation->frame(animation, output, &output->frame_time);
Scott Moreaud64cf212012-06-08 19:40:54 -06002471 }
David Herrmann1edf44c2013-10-22 17:11:26 +02002472
Pekka Paalanenb5026542014-11-12 15:09:24 +02002473 TL_POINT("core_repaint_posted", TLP_OUTPUT(output), TLP_END);
2474
David Herrmann1edf44c2013-10-22 17:11:26 +02002475 return r;
Kristian Høgsbergef044142011-06-21 15:02:12 -04002476}
Kristian Høgsbergb1868472011-04-22 12:27:57 -04002477
Pekka Paalanen82919792014-05-21 13:51:49 +03002478static void
2479weston_output_schedule_repaint_reset(struct weston_output *output)
2480{
Daniel Stone05df8c12017-03-03 16:59:42 +00002481 output->repaint_status = REPAINT_NOT_SCHEDULED;
Pekka Paalanen82919792014-05-21 13:51:49 +03002482 TL_POINT("core_repaint_exit_loop", TLP_OUTPUT(output), TLP_END);
Pekka Paalanen82919792014-05-21 13:51:49 +03002483}
2484
Daniel Stoneb1f166d2017-03-01 11:34:10 +00002485static int
2486weston_output_maybe_repaint(struct weston_output *output, struct timespec *now,
2487 void *repaint_data)
Pekka Paalanen0513a952014-05-21 16:17:27 +03002488{
Pekka Paalanen0513a952014-05-21 16:17:27 +03002489 struct weston_compositor *compositor = output->compositor;
Daniel Stoneb1f166d2017-03-01 11:34:10 +00002490 int ret = 0;
Daniel Stone6847b852017-03-01 11:34:08 +00002491 int64_t msec_to_repaint;
Pekka Paalanen0513a952014-05-21 16:17:27 +03002492
Daniel Stone6847b852017-03-01 11:34:08 +00002493 /* We're not ready yet; come back to make a decision later. */
2494 if (output->repaint_status != REPAINT_SCHEDULED)
Daniel Stoneb1f166d2017-03-01 11:34:10 +00002495 return ret;
Daniel Stone6847b852017-03-01 11:34:08 +00002496
2497 msec_to_repaint = timespec_sub_to_msec(&output->next_repaint, now);
2498 if (msec_to_repaint > 1)
Daniel Stoneb1f166d2017-03-01 11:34:10 +00002499 return ret;
Daniel Stone05df8c12017-03-03 16:59:42 +00002500
Daniel Stonecd1a1c32017-01-16 15:38:54 +00002501 /* If we're sleeping, drop the repaint machinery entirely; we will
2502 * explicitly repaint all outputs when we come back. */
2503 if (compositor->state == WESTON_COMPOSITOR_SLEEPING ||
2504 compositor->state == WESTON_COMPOSITOR_OFFSCREEN)
2505 goto err;
Pekka Paalanen0513a952014-05-21 16:17:27 +03002506
Daniel Stonecd1a1c32017-01-16 15:38:54 +00002507 /* We don't actually need to repaint this output; drop it from
2508 * repaint until something causes damage. */
2509 if (!output->repaint_needed)
2510 goto err;
2511
2512 /* If repaint fails, we aren't going to get weston_output_finish_frame
2513 * to trigger a new repaint, so drop it from repaint and hope
Daniel Stone6847b852017-03-01 11:34:08 +00002514 * something schedules a successful repaint later. As repainting may
2515 * take some time, re-read our clock as a courtesy to the next
2516 * output. */
Daniel Stoneb1f166d2017-03-01 11:34:10 +00002517 ret = weston_output_repaint(output, repaint_data);
Daniel Stone6847b852017-03-01 11:34:08 +00002518 weston_compositor_read_presentation_clock(compositor, now);
Daniel Stonecd1a1c32017-01-16 15:38:54 +00002519 if (ret != 0)
2520 goto err;
2521
Tomohito Esaki7f4d9ff2018-06-05 10:37:06 +09002522 output->repainted = true;
Daniel Stoneb1f166d2017-03-01 11:34:10 +00002523 return ret;
Daniel Stonecd1a1c32017-01-16 15:38:54 +00002524
2525err:
Pekka Paalanen0513a952014-05-21 16:17:27 +03002526 weston_output_schedule_repaint_reset(output);
Daniel Stoneb1f166d2017-03-01 11:34:10 +00002527 return ret;
Daniel Stone6847b852017-03-01 11:34:08 +00002528}
2529
2530static void
2531output_repaint_timer_arm(struct weston_compositor *compositor)
2532{
2533 struct weston_output *output;
2534 bool any_should_repaint = false;
2535 struct timespec now;
Sergi Granellb4c08862017-03-18 13:01:15 +01002536 int64_t msec_to_next = INT64_MAX;
Daniel Stone6847b852017-03-01 11:34:08 +00002537
2538 weston_compositor_read_presentation_clock(compositor, &now);
2539
2540 wl_list_for_each(output, &compositor->output_list, link) {
2541 int64_t msec_to_this;
2542
2543 if (output->repaint_status != REPAINT_SCHEDULED)
2544 continue;
2545
2546 msec_to_this = timespec_sub_to_msec(&output->next_repaint,
2547 &now);
2548 if (!any_should_repaint || msec_to_this < msec_to_next)
2549 msec_to_next = msec_to_this;
2550
2551 any_should_repaint = true;
2552 }
2553
2554 if (!any_should_repaint)
2555 return;
2556
2557 /* Even if we should repaint immediately, add the minimum 1 ms delay.
2558 * This is a workaround to allow coalescing multiple output repaints
2559 * particularly from weston_output_finish_frame()
2560 * into the same call, which would not happen if we called
2561 * output_repaint_timer_handler() directly.
2562 */
2563 if (msec_to_next < 1)
2564 msec_to_next = 1;
2565
2566 wl_event_source_timer_update(compositor->repaint_timer, msec_to_next);
2567}
2568
2569static int
2570output_repaint_timer_handler(void *data)
2571{
2572 struct weston_compositor *compositor = data;
2573 struct weston_output *output;
2574 struct timespec now;
Daniel Stoneb1f166d2017-03-01 11:34:10 +00002575 void *repaint_data = NULL;
Emre Ucane479ed82018-03-20 15:29:40 +01002576 int ret = 0;
Daniel Stone6847b852017-03-01 11:34:08 +00002577
2578 weston_compositor_read_presentation_clock(compositor, &now);
Daniel Stoneb1f166d2017-03-01 11:34:10 +00002579
2580 if (compositor->backend->repaint_begin)
2581 repaint_data = compositor->backend->repaint_begin(compositor);
2582
2583 wl_list_for_each(output, &compositor->output_list, link) {
2584 ret = weston_output_maybe_repaint(output, &now, repaint_data);
2585 if (ret)
2586 break;
2587 }
2588
2589 if (ret == 0) {
Tomohito Esaki09bfcd62018-06-05 10:37:05 +09002590 if (compositor->backend->repaint_flush)
2591 compositor->backend->repaint_flush(compositor,
2592 repaint_data);
Daniel Stoneb1f166d2017-03-01 11:34:10 +00002593 } else {
Tomohito Esaki7f4d9ff2018-06-05 10:37:06 +09002594 wl_list_for_each(output, &compositor->output_list, link) {
2595 if (output->repainted)
2596 weston_output_schedule_repaint_reset(output);
2597 }
2598
Tomohito Esaki09bfcd62018-06-05 10:37:05 +09002599 if (compositor->backend->repaint_cancel)
2600 compositor->backend->repaint_cancel(compositor,
2601 repaint_data);
Daniel Stoneb1f166d2017-03-01 11:34:10 +00002602 }
Daniel Stone6847b852017-03-01 11:34:08 +00002603
Tomohito Esakiddaf95c2018-07-10 11:47:15 +09002604 wl_list_for_each(output, &compositor->output_list, link)
2605 output->repainted = false;
2606
Daniel Stone6847b852017-03-01 11:34:08 +00002607 output_repaint_timer_arm(compositor);
2608
Pekka Paalanen0513a952014-05-21 16:17:27 +03002609 return 0;
2610}
2611
Kristian Høgsbergef044142011-06-21 15:02:12 -04002612WL_EXPORT void
Pekka Paalanenb5eedad2014-09-23 22:08:45 -04002613weston_output_finish_frame(struct weston_output *output,
Pekka Paalanen363aa7b2014-12-17 16:20:40 +02002614 const struct timespec *stamp,
2615 uint32_t presented_flags)
Kristian Høgsbergef044142011-06-21 15:02:12 -04002616{
Kristian Høgsberg7dbf5e22012-03-05 19:50:08 -05002617 struct weston_compositor *compositor = output->compositor;
Pekka Paalanen0513a952014-05-21 16:17:27 +03002618 int32_t refresh_nsec;
2619 struct timespec now;
Daniel Stone6847b852017-03-01 11:34:08 +00002620 int64_t msec_rel;
Pekka Paalanen133e4392014-09-23 22:08:46 -04002621
Pekka Paalanenb5026542014-11-12 15:09:24 +02002622
Daniel Stone05df8c12017-03-03 16:59:42 +00002623 assert(output->repaint_status == REPAINT_AWAITING_COMPLETION);
Daniel Stone3615ce12017-03-01 11:34:05 +00002624 assert(stamp || (presented_flags & WP_PRESENTATION_FEEDBACK_INVALID));
2625
Daniel Stone6847b852017-03-01 11:34:08 +00002626 weston_compositor_read_presentation_clock(compositor, &now);
2627
Daniel Stone3615ce12017-03-01 11:34:05 +00002628 /* If we haven't been supplied any timestamp at all, we don't have a
2629 * timebase to work against, so any delay just wastes time. Push a
2630 * repaint as soon as possible so we can get on with it. */
Daniel Stone6847b852017-03-01 11:34:08 +00002631 if (!stamp) {
2632 output->next_repaint = now;
Daniel Stone3615ce12017-03-01 11:34:05 +00002633 goto out;
Daniel Stone6847b852017-03-01 11:34:08 +00002634 }
Daniel Stone3615ce12017-03-01 11:34:05 +00002635
Marius Vladdf9278a2018-03-06 18:56:23 +02002636 TL_POINT("core_repaint_finished", TLP_OUTPUT(output),
2637 TLP_VBLANK(stamp), TLP_END);
2638
Pekka Paalanend7894d02015-07-03 15:08:53 +03002639 refresh_nsec = millihz_to_nsec(output->current_mode->refresh);
Pekka Paalanen133e4392014-09-23 22:08:46 -04002640 weston_presentation_feedback_present_list(&output->feedback_list,
2641 output, refresh_nsec, stamp,
Pekka Paalanen363aa7b2014-12-17 16:20:40 +02002642 output->msc,
2643 presented_flags);
Kristian Høgsberg7dbf5e22012-03-05 19:50:08 -05002644
Alexandros Frantzise6ac2af2017-11-16 18:20:53 +02002645 output->frame_time = *stamp;
Kristian Høgsberg7dbf5e22012-03-05 19:50:08 -05002646
Daniel Stone6847b852017-03-01 11:34:08 +00002647 timespec_add_nsec(&output->next_repaint, stamp, refresh_nsec);
2648 timespec_add_msec(&output->next_repaint, &output->next_repaint,
2649 -compositor->repaint_msec);
2650 msec_rel = timespec_sub_to_msec(&output->next_repaint, &now);
Daniel Stone84aff5c2017-03-01 11:34:04 +00002651
2652 if (msec_rel < -1000 || msec_rel > 1000) {
Pekka Paalanen8fd4de42015-03-19 12:27:29 +02002653 static bool warned;
2654
2655 if (!warned)
2656 weston_log("Warning: computed repaint delay is "
Daniel Stone6847b852017-03-01 11:34:08 +00002657 "insane: %lld msec\n", (long long) msec_rel);
Pekka Paalanen8fd4de42015-03-19 12:27:29 +02002658 warned = true;
2659
Daniel Stone6847b852017-03-01 11:34:08 +00002660 output->next_repaint = now;
Pekka Paalanen8fd4de42015-03-19 12:27:29 +02002661 }
2662
Mario Kleinerb7df04e2015-06-21 21:25:15 +02002663 /* Called from restart_repaint_loop and restart happens already after
2664 * the deadline given by repaint_msec? In that case we delay until
2665 * the deadline of the next frame, to give clients a more predictable
2666 * timing of the repaint cycle to lock on. */
Daniel Stoneeca5cca2017-02-28 21:53:51 +00002667 if (presented_flags == WP_PRESENTATION_FEEDBACK_INVALID &&
2668 msec_rel < 0) {
2669 while (timespec_sub_to_nsec(&output->next_repaint, &now) < 0) {
2670 timespec_add_nsec(&output->next_repaint,
2671 &output->next_repaint,
2672 refresh_nsec);
2673 }
2674 }
Mario Kleinerb7df04e2015-06-21 21:25:15 +02002675
Daniel Stone3615ce12017-03-01 11:34:05 +00002676out:
Daniel Stone05df8c12017-03-03 16:59:42 +00002677 output->repaint_status = REPAINT_SCHEDULED;
Daniel Stone6847b852017-03-01 11:34:08 +00002678 output_repaint_timer_arm(compositor);
Kristian Høgsberg7dbf5e22012-03-05 19:50:08 -05002679}
2680
2681static void
2682idle_repaint(void *data)
2683{
2684 struct weston_output *output = data;
2685
Daniel Stone05df8c12017-03-03 16:59:42 +00002686 assert(output->repaint_status == REPAINT_BEGIN_FROM_IDLE);
2687 output->repaint_status = REPAINT_AWAITING_COMPLETION;
Pekka Paalanendcbcfc72017-10-26 14:33:59 +03002688 output->idle_repaint_source = NULL;
Jonas Ådahle5a12252013-04-05 23:07:11 +02002689 output->start_repaint_loop(output);
Kristian Høgsbergef7a9ca2008-10-11 21:21:39 -04002690}
2691
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -04002692WL_EXPORT void
Giulio Camuffo412e6a52014-07-09 22:12:56 +03002693weston_layer_entry_insert(struct weston_layer_entry *list,
2694 struct weston_layer_entry *entry)
2695{
2696 wl_list_insert(&list->link, &entry->link);
2697 entry->layer = list->layer;
2698}
2699
2700WL_EXPORT void
2701weston_layer_entry_remove(struct weston_layer_entry *entry)
2702{
2703 wl_list_remove(&entry->link);
2704 wl_list_init(&entry->link);
2705 entry->layer = NULL;
2706}
2707
Quentin Glidic82681572016-12-17 13:40:51 +01002708
2709/** Initialize the weston_layer struct.
2710 *
2711 * \param compositor The compositor instance
2712 * \param layer The layer to initialize
2713 */
Giulio Camuffo412e6a52014-07-09 22:12:56 +03002714WL_EXPORT void
Quentin Glidic82681572016-12-17 13:40:51 +01002715weston_layer_init(struct weston_layer *layer,
2716 struct weston_compositor *compositor)
Kristian Høgsberg3be2ce92012-02-29 12:42:35 -05002717{
Quentin Glidic82681572016-12-17 13:40:51 +01002718 layer->compositor = compositor;
2719 wl_list_init(&layer->link);
Giulio Camuffo412e6a52014-07-09 22:12:56 +03002720 wl_list_init(&layer->view_list.link);
2721 layer->view_list.layer = layer;
Giulio Camuffo95ec0f92014-07-09 22:12:57 +03002722 weston_layer_set_mask_infinite(layer);
Quentin Glidic82681572016-12-17 13:40:51 +01002723}
2724
2725/** Sets the position of the layer in the layer list. The layer will be placed
2726 * below any layer with the same position value, if any.
2727 * This function is safe to call if the layer is already on the list, but the
2728 * layer may be moved below other layers at the same position, if any.
2729 *
2730 * \param layer The layer to modify
2731 * \param position The position the layer will be placed at
2732 */
2733WL_EXPORT void
2734weston_layer_set_position(struct weston_layer *layer,
2735 enum weston_layer_position position)
2736{
2737 struct weston_layer *below;
2738
2739 wl_list_remove(&layer->link);
2740
2741 /* layer_list is ordered from top to bottom, the last layer being the
2742 * background with the smallest position value */
2743
2744 layer->position = position;
2745 wl_list_for_each_reverse(below, &layer->compositor->layer_list, link) {
2746 if (below->position >= layer->position) {
2747 wl_list_insert(&below->link, &layer->link);
2748 return;
2749 }
2750 }
2751 wl_list_insert(&layer->compositor->layer_list, &layer->link);
2752}
2753
2754/** Hide a layer by taking it off the layer list.
2755 * This function is safe to call if the layer is not on the list.
2756 *
2757 * \param layer The layer to hide
2758 */
2759WL_EXPORT void
2760weston_layer_unset_position(struct weston_layer *layer)
2761{
2762 wl_list_remove(&layer->link);
2763 wl_list_init(&layer->link);
Kristian Høgsberg3be2ce92012-02-29 12:42:35 -05002764}
2765
2766WL_EXPORT void
Giulio Camuffo95ec0f92014-07-09 22:12:57 +03002767weston_layer_set_mask(struct weston_layer *layer,
2768 int x, int y, int width, int height)
2769{
2770 struct weston_view *view;
2771
2772 layer->mask.x1 = x;
2773 layer->mask.x2 = x + width;
2774 layer->mask.y1 = y;
2775 layer->mask.y2 = y + height;
2776
2777 wl_list_for_each(view, &layer->view_list.link, layer_link.link) {
2778 weston_view_geometry_dirty(view);
2779 }
2780}
2781
2782WL_EXPORT void
2783weston_layer_set_mask_infinite(struct weston_layer *layer)
2784{
2785 weston_layer_set_mask(layer, INT32_MIN, INT32_MIN,
2786 UINT32_MAX, UINT32_MAX);
2787}
2788
Daniel Stone3b775632018-07-20 08:38:25 +01002789WL_EXPORT bool
2790weston_layer_mask_is_infinite(struct weston_layer *layer)
2791{
2792 return layer->mask.x1 == INT32_MIN &&
2793 layer->mask.y1 == INT32_MIN &&
2794 layer->mask.x2 == INT32_MIN + UINT32_MAX &&
2795 layer->mask.y2 == INT32_MIN + UINT32_MAX;
2796}
2797
Giulio Camuffo95ec0f92014-07-09 22:12:57 +03002798WL_EXPORT void
Kristian Høgsberg49952d12012-06-20 00:35:59 -04002799weston_output_schedule_repaint(struct weston_output *output)
Kristian Høgsbergef7a9ca2008-10-11 21:21:39 -04002800{
Kristian Høgsberg49952d12012-06-20 00:35:59 -04002801 struct weston_compositor *compositor = output->compositor;
Kristian Høgsbergef044142011-06-21 15:02:12 -04002802 struct wl_event_loop *loop;
Benjamin Franzkeec4d3422011-03-14 12:07:26 +01002803
Bryce Harrington08976ac2016-08-30 12:05:16 -07002804 if (compositor->state == WESTON_COMPOSITOR_SLEEPING ||
2805 compositor->state == WESTON_COMPOSITOR_OFFSCREEN)
Kristian Høgsberge10a5d92011-04-22 14:01:18 -04002806 return;
2807
Pekka Paalanenb5026542014-11-12 15:09:24 +02002808 if (!output->repaint_needed)
2809 TL_POINT("core_repaint_req", TLP_OUTPUT(output), TLP_END);
2810
Kristian Høgsbergef044142011-06-21 15:02:12 -04002811 loop = wl_display_get_event_loop(compositor->wl_display);
Daniel Stone09a97e22017-03-01 11:34:06 +00002812 output->repaint_needed = true;
Daniel Stone05df8c12017-03-03 16:59:42 +00002813
2814 /* If we already have a repaint scheduled for our idle handler,
2815 * no need to set it again. If the repaint has been called but
2816 * not finished, then weston_output_finish_frame() will notice
2817 * that a repaint is needed and schedule one. */
2818 if (output->repaint_status != REPAINT_NOT_SCHEDULED)
Kristian Høgsberg49952d12012-06-20 00:35:59 -04002819 return;
Benjamin Franzkeec4d3422011-03-14 12:07:26 +01002820
Daniel Stone05df8c12017-03-03 16:59:42 +00002821 output->repaint_status = REPAINT_BEGIN_FROM_IDLE;
Pekka Paalanendcbcfc72017-10-26 14:33:59 +03002822 assert(!output->idle_repaint_source);
2823 output->idle_repaint_source = wl_event_loop_add_idle(loop, idle_repaint,
2824 output);
Pekka Paalanenb5026542014-11-12 15:09:24 +02002825 TL_POINT("core_repaint_enter_loop", TLP_OUTPUT(output), TLP_END);
Kristian Høgsbergef7a9ca2008-10-11 21:21:39 -04002826}
Kristian Høgsberg5c8c3282009-02-09 15:17:46 -05002827
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -04002828WL_EXPORT void
Kristian Høgsberg49952d12012-06-20 00:35:59 -04002829weston_compositor_schedule_repaint(struct weston_compositor *compositor)
2830{
2831 struct weston_output *output;
2832
2833 wl_list_for_each(output, &compositor->output_list, link)
2834 weston_output_schedule_repaint(output);
2835}
2836
Kristian Høgsberg5503bf82008-11-06 10:38:17 -05002837static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -04002838surface_destroy(struct wl_client *client, struct wl_resource *resource)
Kristian Høgsberg16eb6752008-10-08 22:51:32 -04002839{
Kristian Høgsbergeae5de72012-04-11 22:42:15 -04002840 wl_resource_destroy(resource);
Kristian Høgsberg16eb6752008-10-08 22:51:32 -04002841}
2842
Kristian Høgsberg5503bf82008-11-06 10:38:17 -05002843static void
Ander Conselvan de Oliveirae11683a2012-03-27 17:36:40 +03002844surface_attach(struct wl_client *client,
2845 struct wl_resource *resource,
2846 struct wl_resource *buffer_resource, int32_t sx, int32_t sy)
2847{
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -05002848 struct weston_surface *surface = wl_resource_get_user_data(resource);
Jason Ekstrand6bd62942013-06-20 20:38:23 -05002849 struct weston_buffer *buffer = NULL;
Ander Conselvan de Oliveirae11683a2012-03-27 17:36:40 +03002850
Kristian Høgsbergab19f932013-08-20 11:30:54 -07002851 if (buffer_resource) {
Jason Ekstrand6bd62942013-06-20 20:38:23 -05002852 buffer = weston_buffer_from_resource(buffer_resource);
Kristian Høgsbergab19f932013-08-20 11:30:54 -07002853 if (buffer == NULL) {
2854 wl_client_post_no_memory(client);
2855 return;
2856 }
Kristian Høgsberg08b58c72013-08-15 12:26:42 -07002857 }
Kristian Høgsberga691aee2011-06-23 21:43:50 -04002858
Pekka Paalanende685b82012-12-04 15:58:12 +02002859 /* Attach, attach, without commit in between does not send
2860 * wl_buffer.release. */
Jason Ekstrand7b982072014-05-20 14:33:03 -05002861 weston_surface_state_set_buffer(&surface->pending, buffer);
Ander Conselvan de Oliveirae11683a2012-03-27 17:36:40 +03002862
Pekka Paalanen5df44de2012-10-10 12:49:23 +03002863 surface->pending.sx = sx;
2864 surface->pending.sy = sy;
Giulio Camuffo184df502013-02-21 11:29:21 +01002865 surface->pending.newly_attached = 1;
Kristian Høgsbergf9212892008-10-11 18:40:23 -04002866}
2867
Kristian Høgsberg5503bf82008-11-06 10:38:17 -05002868static void
Kristian Høgsbergd2412e22008-12-15 20:35:24 -05002869surface_damage(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -04002870 struct wl_resource *resource,
Kristian Høgsbergd2412e22008-12-15 20:35:24 -05002871 int32_t x, int32_t y, int32_t width, int32_t height)
Kristian Høgsberg7f77bd82008-11-07 08:39:37 -05002872{
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -05002873 struct weston_surface *surface = wl_resource_get_user_data(resource);
Kristian Høgsberg9d69f8e2010-09-03 14:46:38 -04002874
Derek Foreman57e92ed2015-11-17 14:11:35 -06002875 if (width <= 0 || height <= 0)
2876 return;
2877
Derek Foreman152254b2015-11-26 14:17:48 -06002878 pixman_region32_union_rect(&surface->pending.damage_surface,
2879 &surface->pending.damage_surface,
2880 x, y, width, height);
2881}
2882
2883static void
2884surface_damage_buffer(struct wl_client *client,
2885 struct wl_resource *resource,
2886 int32_t x, int32_t y, int32_t width, int32_t height)
2887{
2888 struct weston_surface *surface = wl_resource_get_user_data(resource);
2889
2890 if (width <= 0 || height <= 0)
2891 return;
2892
2893 pixman_region32_union_rect(&surface->pending.damage_buffer,
2894 &surface->pending.damage_buffer,
Kristian Høgsberg460a79b2012-06-18 15:09:11 -04002895 x, y, width, height);
Kristian Høgsbergfbdbbdc2008-11-28 17:06:06 -05002896}
2897
Kristian Høgsberg33418202011-08-16 23:01:28 -04002898static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -04002899destroy_frame_callback(struct wl_resource *resource)
Kristian Høgsberg33418202011-08-16 23:01:28 -04002900{
Jason Ekstrandfbbbec82013-06-14 10:07:57 -05002901 struct weston_frame_callback *cb = wl_resource_get_user_data(resource);
Kristian Høgsberg904055a2011-08-18 17:55:30 -04002902
2903 wl_list_remove(&cb->link);
Pekka Paalanen8c196452011-11-15 11:45:42 +02002904 free(cb);
Kristian Høgsberg33418202011-08-16 23:01:28 -04002905}
2906
2907static void
2908surface_frame(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -04002909 struct wl_resource *resource, uint32_t callback)
Kristian Høgsberg33418202011-08-16 23:01:28 -04002910{
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05002911 struct weston_frame_callback *cb;
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -05002912 struct weston_surface *surface = wl_resource_get_user_data(resource);
Kristian Høgsberg33418202011-08-16 23:01:28 -04002913
2914 cb = malloc(sizeof *cb);
2915 if (cb == NULL) {
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -04002916 wl_resource_post_no_memory(resource);
Kristian Høgsberg33418202011-08-16 23:01:28 -04002917 return;
2918 }
Pekka Paalanenbc106382012-10-10 12:49:31 +03002919
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07002920 cb->resource = wl_resource_create(client, &wl_callback_interface, 1,
2921 callback);
2922 if (cb->resource == NULL) {
2923 free(cb);
2924 wl_resource_post_no_memory(resource);
2925 return;
2926 }
2927
Jason Ekstranda85118c2013-06-27 20:17:02 -05002928 wl_resource_set_implementation(cb->resource, NULL, cb,
2929 destroy_frame_callback);
Kristian Høgsberg33418202011-08-16 23:01:28 -04002930
Pekka Paalanenbc106382012-10-10 12:49:31 +03002931 wl_list_insert(surface->pending.frame_callback_list.prev, &cb->link);
Kristian Høgsberg33418202011-08-16 23:01:28 -04002932}
2933
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05002934static void
2935surface_set_opaque_region(struct wl_client *client,
2936 struct wl_resource *resource,
2937 struct wl_resource *region_resource)
2938{
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -05002939 struct weston_surface *surface = wl_resource_get_user_data(resource);
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05002940 struct weston_region *region;
2941
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05002942 if (region_resource) {
Jason Ekstrand8895efc2013-06-14 10:07:56 -05002943 region = wl_resource_get_user_data(region_resource);
Pekka Paalanen512dde82012-10-10 12:49:27 +03002944 pixman_region32_copy(&surface->pending.opaque,
2945 &region->region);
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05002946 } else {
Jason Ekstrandef540082014-06-26 10:37:36 -07002947 pixman_region32_clear(&surface->pending.opaque);
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05002948 }
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05002949}
2950
2951static void
2952surface_set_input_region(struct wl_client *client,
2953 struct wl_resource *resource,
2954 struct wl_resource *region_resource)
2955{
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -05002956 struct weston_surface *surface = wl_resource_get_user_data(resource);
Kristian Høgsberg010f98b2012-02-23 17:30:45 -05002957 struct weston_region *region;
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05002958
2959 if (region_resource) {
Jason Ekstrand8895efc2013-06-14 10:07:56 -05002960 region = wl_resource_get_user_data(region_resource);
Pekka Paalanen0cbd3b52012-10-10 12:49:28 +03002961 pixman_region32_copy(&surface->pending.input,
2962 &region->region);
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05002963 } else {
Pekka Paalanen0cbd3b52012-10-10 12:49:28 +03002964 pixman_region32_fini(&surface->pending.input);
2965 region_init_infinite(&surface->pending.input);
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05002966 }
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05002967}
2968
Emilio Pozuelo Monfort4f3cad72017-01-27 17:30:29 +01002969/* Cause damage to this sub-surface and all its children.
2970 *
2971 * This is useful when there are state changes that need an implicit
2972 * damage, e.g. a z-order change.
2973 */
2974static void
2975weston_surface_damage_subsurfaces(struct weston_subsurface *sub)
2976{
2977 struct weston_subsurface *child;
2978
2979 weston_surface_damage(sub->surface);
2980 sub->reordered = false;
2981
2982 wl_list_for_each(child, &sub->surface->subsurface_list, parent_link)
2983 if (child != sub)
2984 weston_surface_damage_subsurfaces(child);
2985}
2986
Pekka Paalanen5df44de2012-10-10 12:49:23 +03002987static void
Pekka Paalanene67858b2013-04-25 13:57:42 +03002988weston_surface_commit_subsurface_order(struct weston_surface *surface)
Pekka Paalanen5df44de2012-10-10 12:49:23 +03002989{
Pekka Paalanene67858b2013-04-25 13:57:42 +03002990 struct weston_subsurface *sub;
2991
2992 wl_list_for_each_reverse(sub, &surface->subsurface_list_pending,
2993 parent_link_pending) {
2994 wl_list_remove(&sub->parent_link);
2995 wl_list_insert(&surface->subsurface_list, &sub->parent_link);
Emilio Pozuelo Monfort4f3cad72017-01-27 17:30:29 +01002996
2997 if (sub->reordered)
2998 weston_surface_damage_subsurfaces(sub);
Pekka Paalanene67858b2013-04-25 13:57:42 +03002999 }
3000}
3001
3002static void
Pekka Paalanen04baea52016-04-26 15:50:58 +03003003weston_surface_build_buffer_matrix(const struct weston_surface *surface,
Jason Ekstrand1e059042014-10-16 10:55:19 -05003004 struct weston_matrix *matrix)
3005{
Pekka Paalanen04baea52016-04-26 15:50:58 +03003006 const struct weston_buffer_viewport *vp = &surface->buffer_viewport;
Jason Ekstrand1e059042014-10-16 10:55:19 -05003007 double src_width, src_height, dest_width, dest_height;
3008
3009 weston_matrix_init(matrix);
3010
3011 if (vp->buffer.src_width == wl_fixed_from_int(-1)) {
3012 src_width = surface->width_from_buffer;
3013 src_height = surface->height_from_buffer;
3014 } else {
3015 src_width = wl_fixed_to_double(vp->buffer.src_width);
3016 src_height = wl_fixed_to_double(vp->buffer.src_height);
3017 }
3018
3019 if (vp->surface.width == -1) {
3020 dest_width = src_width;
3021 dest_height = src_height;
3022 } else {
3023 dest_width = vp->surface.width;
3024 dest_height = vp->surface.height;
3025 }
3026
3027 if (src_width != dest_width || src_height != dest_height)
3028 weston_matrix_scale(matrix,
3029 src_width / dest_width,
3030 src_height / dest_height, 1);
3031
3032 if (vp->buffer.src_width != wl_fixed_from_int(-1))
3033 weston_matrix_translate(matrix,
3034 wl_fixed_to_double(vp->buffer.src_x),
3035 wl_fixed_to_double(vp->buffer.src_y),
3036 0);
3037
3038 switch (vp->buffer.transform) {
3039 case WL_OUTPUT_TRANSFORM_FLIPPED:
3040 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
3041 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
3042 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
3043 weston_matrix_scale(matrix, -1, 1, 1);
3044 weston_matrix_translate(matrix,
3045 surface->width_from_buffer, 0, 0);
3046 break;
3047 }
3048
3049 switch (vp->buffer.transform) {
3050 default:
3051 case WL_OUTPUT_TRANSFORM_NORMAL:
3052 case WL_OUTPUT_TRANSFORM_FLIPPED:
3053 break;
3054 case WL_OUTPUT_TRANSFORM_90:
3055 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
3056 weston_matrix_rotate_xy(matrix, 0, 1);
3057 weston_matrix_translate(matrix,
3058 surface->height_from_buffer, 0, 0);
3059 break;
3060 case WL_OUTPUT_TRANSFORM_180:
3061 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
3062 weston_matrix_rotate_xy(matrix, -1, 0);
3063 weston_matrix_translate(matrix,
3064 surface->width_from_buffer,
3065 surface->height_from_buffer, 0);
3066 break;
3067 case WL_OUTPUT_TRANSFORM_270:
3068 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
3069 weston_matrix_rotate_xy(matrix, 0, -1);
3070 weston_matrix_translate(matrix,
3071 0, surface->width_from_buffer, 0);
3072 break;
3073 }
3074
3075 weston_matrix_scale(matrix, vp->buffer.scale, vp->buffer.scale, 1);
3076}
3077
Pekka Paalanend9aae9c2016-04-26 13:46:38 +03003078/**
3079 * Compute a + b > c while being safe to overflows.
3080 */
3081static bool
3082fixed_sum_gt(wl_fixed_t a, wl_fixed_t b, wl_fixed_t c)
3083{
3084 return (int64_t)a + (int64_t)b > (int64_t)c;
3085}
3086
3087static bool
3088weston_surface_is_pending_viewport_source_valid(
3089 const struct weston_surface *surface)
3090{
3091 const struct weston_surface_state *pend = &surface->pending;
3092 const struct weston_buffer_viewport *vp = &pend->buffer_viewport;
3093 int width_from_buffer = 0;
3094 int height_from_buffer = 0;
3095 wl_fixed_t w;
3096 wl_fixed_t h;
3097
3098 /* If viewport source rect is not set, it is always ok. */
3099 if (vp->buffer.src_width == wl_fixed_from_int(-1))
3100 return true;
3101
3102 if (pend->newly_attached) {
3103 if (pend->buffer) {
3104 convert_size_by_transform_scale(&width_from_buffer,
3105 &height_from_buffer,
3106 pend->buffer->width,
3107 pend->buffer->height,
3108 vp->buffer.transform,
3109 vp->buffer.scale);
3110 } else {
3111 /* No buffer: viewport is irrelevant. */
3112 return true;
3113 }
3114 } else {
3115 width_from_buffer = surface->width_from_buffer;
3116 height_from_buffer = surface->height_from_buffer;
3117 }
3118
3119 assert((width_from_buffer == 0) == (height_from_buffer == 0));
3120 assert(width_from_buffer >= 0 && height_from_buffer >= 0);
3121
3122 /* No buffer: viewport is irrelevant. */
3123 if (width_from_buffer == 0 || height_from_buffer == 0)
3124 return true;
3125
3126 /* overflow checks for wl_fixed_from_int() */
3127 if (width_from_buffer > wl_fixed_to_int(INT32_MAX))
3128 return false;
3129 if (height_from_buffer > wl_fixed_to_int(INT32_MAX))
3130 return false;
3131
3132 w = wl_fixed_from_int(width_from_buffer);
3133 h = wl_fixed_from_int(height_from_buffer);
3134
3135 if (fixed_sum_gt(vp->buffer.src_x, vp->buffer.src_width, w))
3136 return false;
3137 if (fixed_sum_gt(vp->buffer.src_y, vp->buffer.src_height, h))
3138 return false;
3139
3140 return true;
3141}
3142
Pekka Paalanenbb32ccc2016-04-26 14:28:28 +03003143static bool
3144fixed_is_integer(wl_fixed_t v)
3145{
3146 return (v & 0xff) == 0;
3147}
3148
3149static bool
3150weston_surface_is_pending_viewport_dst_size_int(
3151 const struct weston_surface *surface)
3152{
3153 const struct weston_buffer_viewport *vp =
3154 &surface->pending.buffer_viewport;
3155
3156 if (vp->surface.width != -1) {
3157 assert(vp->surface.width > 0 && vp->surface.height > 0);
3158 return true;
3159 }
3160
3161 return fixed_is_integer(vp->buffer.src_width) &&
3162 fixed_is_integer(vp->buffer.src_height);
3163}
3164
Derek Foreman152254b2015-11-26 14:17:48 -06003165/* Translate pending damage in buffer co-ordinates to surface
3166 * co-ordinates and union it with a pixman_region32_t.
3167 * This should only be called after the buffer is attached.
3168 */
3169static void
3170apply_damage_buffer(pixman_region32_t *dest,
3171 struct weston_surface *surface,
3172 struct weston_surface_state *state)
3173{
3174 struct weston_buffer *buffer = surface->buffer_ref.buffer;
3175
3176 /* wl_surface.damage_buffer needs to be clipped to the buffer,
3177 * translated into surface co-ordinates and unioned with
3178 * any other surface damage.
3179 * None of this makes sense if there is no buffer though.
3180 */
3181 if (buffer && pixman_region32_not_empty(&state->damage_buffer)) {
3182 pixman_region32_t buffer_damage;
3183
3184 pixman_region32_intersect_rect(&state->damage_buffer,
3185 &state->damage_buffer,
3186 0, 0, buffer->width,
3187 buffer->height);
3188 pixman_region32_init(&buffer_damage);
3189 weston_matrix_transform_region(&buffer_damage,
3190 &surface->buffer_to_surface_matrix,
3191 &state->damage_buffer);
3192 pixman_region32_union(dest, dest, &buffer_damage);
3193 pixman_region32_fini(&buffer_damage);
3194 }
3195 /* We should clear this on commit even if there was no buffer */
3196 pixman_region32_clear(&state->damage_buffer);
3197}
3198
Jason Ekstrand1e059042014-10-16 10:55:19 -05003199static void
Jason Ekstrand7b982072014-05-20 14:33:03 -05003200weston_surface_commit_state(struct weston_surface *surface,
3201 struct weston_surface_state *state)
Pekka Paalanene67858b2013-04-25 13:57:42 +03003202{
Jason Ekstranda7af7042013-10-12 22:38:11 -05003203 struct weston_view *view;
Ander Conselvan de Oliveira5df8eca2012-10-30 17:44:01 +02003204 pixman_region32_t opaque;
3205
Alexander Larsson4ea95522013-05-22 14:41:37 +02003206 /* wl_surface.set_buffer_transform */
Alexander Larsson4ea95522013-05-22 14:41:37 +02003207 /* wl_surface.set_buffer_scale */
Pekka Paalanene95ad5c2016-04-15 14:47:08 +03003208 /* wp_viewport.set_source */
3209 /* wp_viewport.set_destination */
Jason Ekstrand7b982072014-05-20 14:33:03 -05003210 surface->buffer_viewport = state->buffer_viewport;
Alexander Larsson4ea95522013-05-22 14:41:37 +02003211
Pekka Paalanen5df44de2012-10-10 12:49:23 +03003212 /* wl_surface.attach */
Jason Ekstrand7b982072014-05-20 14:33:03 -05003213 if (state->newly_attached)
3214 weston_surface_attach(surface, state->buffer);
3215 weston_surface_state_set_buffer(state, NULL);
Giulio Camuffo184df502013-02-21 11:29:21 +01003216
Jason Ekstrand1e059042014-10-16 10:55:19 -05003217 weston_surface_build_buffer_matrix(surface,
3218 &surface->surface_to_buffer_matrix);
3219 weston_matrix_invert(&surface->buffer_to_surface_matrix,
3220 &surface->surface_to_buffer_matrix);
3221
Jason Ekstrand7b982072014-05-20 14:33:03 -05003222 if (state->newly_attached || state->buffer_viewport.changed) {
George Kiagiadakis8f9e87f2014-06-13 18:14:20 +02003223 weston_surface_update_size(surface);
Quentin Glidic2edc3d52016-08-12 10:41:33 +02003224 if (surface->committed)
3225 surface->committed(surface, state->sx, state->sy);
George Kiagiadakis8f9e87f2014-06-13 18:14:20 +02003226 }
Giulio Camuffo184df502013-02-21 11:29:21 +01003227
Jason Ekstrand7b982072014-05-20 14:33:03 -05003228 state->sx = 0;
3229 state->sy = 0;
3230 state->newly_attached = 0;
3231 state->buffer_viewport.changed = 0;
Pekka Paalanen8e159182012-10-10 12:49:25 +03003232
Derek Foreman152254b2015-11-26 14:17:48 -06003233 /* wl_surface.damage and wl_surface.damage_buffer */
Pekka Paalanenb5026542014-11-12 15:09:24 +02003234 if (weston_timeline_enabled_ &&
Derek Foreman152254b2015-11-26 14:17:48 -06003235 (pixman_region32_not_empty(&state->damage_surface) ||
3236 pixman_region32_not_empty(&state->damage_buffer)))
Pekka Paalanenb5026542014-11-12 15:09:24 +02003237 TL_POINT("core_commit_damage", TLP_SURFACE(surface), TLP_END);
Derek Foreman152254b2015-11-26 14:17:48 -06003238
Pekka Paalanen8e159182012-10-10 12:49:25 +03003239 pixman_region32_union(&surface->damage, &surface->damage,
Derek Foreman152254b2015-11-26 14:17:48 -06003240 &state->damage_surface);
3241
3242 apply_damage_buffer(&surface->damage, surface, state);
3243
Kristian Høgsberg4d0214c2012-11-08 11:36:02 -05003244 pixman_region32_intersect_rect(&surface->damage, &surface->damage,
Jason Ekstrandef540082014-06-26 10:37:36 -07003245 0, 0, surface->width, surface->height);
Derek Foreman152254b2015-11-26 14:17:48 -06003246 pixman_region32_clear(&state->damage_surface);
Pekka Paalanen512dde82012-10-10 12:49:27 +03003247
3248 /* wl_surface.set_opaque_region */
Jason Ekstrand7b982072014-05-20 14:33:03 -05003249 pixman_region32_init(&opaque);
3250 pixman_region32_intersect_rect(&opaque, &state->opaque,
3251 0, 0, surface->width, surface->height);
Ander Conselvan de Oliveira5df8eca2012-10-30 17:44:01 +02003252
3253 if (!pixman_region32_equal(&opaque, &surface->opaque)) {
3254 pixman_region32_copy(&surface->opaque, &opaque);
Jason Ekstranda7af7042013-10-12 22:38:11 -05003255 wl_list_for_each(view, &surface->views, surface_link)
3256 weston_view_geometry_dirty(view);
Ander Conselvan de Oliveira5df8eca2012-10-30 17:44:01 +02003257 }
3258
3259 pixman_region32_fini(&opaque);
Pekka Paalanen0cbd3b52012-10-10 12:49:28 +03003260
3261 /* wl_surface.set_input_region */
Jason Ekstrand7b982072014-05-20 14:33:03 -05003262 pixman_region32_intersect_rect(&surface->input, &state->input,
3263 0, 0, surface->width, surface->height);
Pekka Paalanen0cbd3b52012-10-10 12:49:28 +03003264
Pekka Paalanenbc106382012-10-10 12:49:31 +03003265 /* wl_surface.frame */
3266 wl_list_insert_list(&surface->frame_callback_list,
Jason Ekstrand7b982072014-05-20 14:33:03 -05003267 &state->frame_callback_list);
3268 wl_list_init(&state->frame_callback_list);
Pekka Paalanen133e4392014-09-23 22:08:46 -04003269
3270 /* XXX:
3271 * What should happen with a feedback request, if there
3272 * is no wl_buffer attached for this commit?
3273 */
3274
3275 /* presentation.feedback */
3276 wl_list_insert_list(&surface->feedback_list,
3277 &state->feedback_list);
3278 wl_list_init(&state->feedback_list);
Jonas Ådahl5d9ca272016-07-22 17:48:03 +08003279
3280 wl_signal_emit(&surface->commit_signal, surface);
Jason Ekstrand7b982072014-05-20 14:33:03 -05003281}
3282
3283static void
3284weston_surface_commit(struct weston_surface *surface)
3285{
3286 weston_surface_commit_state(surface, &surface->pending);
Pekka Paalanenbc106382012-10-10 12:49:31 +03003287
Pekka Paalanene67858b2013-04-25 13:57:42 +03003288 weston_surface_commit_subsurface_order(surface);
3289
Pekka Paalanen0cbd3b52012-10-10 12:49:28 +03003290 weston_surface_schedule_repaint(surface);
Pekka Paalanen5df44de2012-10-10 12:49:23 +03003291}
3292
Ander Conselvan de Oliveira012b4c72012-11-27 17:03:42 +02003293static void
Pekka Paalanene67858b2013-04-25 13:57:42 +03003294weston_subsurface_commit(struct weston_subsurface *sub);
3295
3296static void
3297weston_subsurface_parent_commit(struct weston_subsurface *sub,
3298 int parent_is_synchronized);
3299
3300static void
3301surface_commit(struct wl_client *client, struct wl_resource *resource)
3302{
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -05003303 struct weston_surface *surface = wl_resource_get_user_data(resource);
Pekka Paalanene67858b2013-04-25 13:57:42 +03003304 struct weston_subsurface *sub = weston_surface_to_subsurface(surface);
3305
Pekka Paalanend9aae9c2016-04-26 13:46:38 +03003306 if (!weston_surface_is_pending_viewport_source_valid(surface)) {
3307 assert(surface->viewport_resource);
3308
3309 wl_resource_post_error(surface->viewport_resource,
3310 WP_VIEWPORT_ERROR_OUT_OF_BUFFER,
3311 "wl_surface@%d has viewport source outside buffer",
3312 wl_resource_get_id(resource));
3313 return;
3314 }
3315
Pekka Paalanenbb32ccc2016-04-26 14:28:28 +03003316 if (!weston_surface_is_pending_viewport_dst_size_int(surface)) {
3317 assert(surface->viewport_resource);
3318
3319 wl_resource_post_error(surface->viewport_resource,
3320 WP_VIEWPORT_ERROR_BAD_SIZE,
3321 "wl_surface@%d viewport dst size not integer",
3322 wl_resource_get_id(resource));
3323 return;
3324 }
3325
Pekka Paalanene67858b2013-04-25 13:57:42 +03003326 if (sub) {
3327 weston_subsurface_commit(sub);
3328 return;
3329 }
3330
3331 weston_surface_commit(surface);
3332
3333 wl_list_for_each(sub, &surface->subsurface_list, parent_link) {
3334 if (sub->surface != surface)
3335 weston_subsurface_parent_commit(sub, 0);
3336 }
3337}
3338
3339static void
Ander Conselvan de Oliveira012b4c72012-11-27 17:03:42 +02003340surface_set_buffer_transform(struct wl_client *client,
3341 struct wl_resource *resource, int transform)
3342{
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -05003343 struct weston_surface *surface = wl_resource_get_user_data(resource);
Ander Conselvan de Oliveira012b4c72012-11-27 17:03:42 +02003344
Jonny Lamba55f1392014-05-30 12:07:15 +02003345 /* if wl_output.transform grows more members this will need to be updated. */
3346 if (transform < 0 ||
3347 transform > WL_OUTPUT_TRANSFORM_FLIPPED_270) {
3348 wl_resource_post_error(resource,
3349 WL_SURFACE_ERROR_INVALID_TRANSFORM,
3350 "buffer transform must be a valid transform "
3351 "('%d' specified)", transform);
3352 return;
3353 }
3354
Pekka Paalanen952b6c82014-03-14 14:38:15 +02003355 surface->pending.buffer_viewport.buffer.transform = transform;
George Kiagiadakis8f9e87f2014-06-13 18:14:20 +02003356 surface->pending.buffer_viewport.changed = 1;
Ander Conselvan de Oliveira012b4c72012-11-27 17:03:42 +02003357}
3358
Alexander Larsson4ea95522013-05-22 14:41:37 +02003359static void
3360surface_set_buffer_scale(struct wl_client *client,
3361 struct wl_resource *resource,
Alexander Larssonedddbd12013-05-24 13:09:43 +02003362 int32_t scale)
Alexander Larsson4ea95522013-05-22 14:41:37 +02003363{
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -05003364 struct weston_surface *surface = wl_resource_get_user_data(resource);
Alexander Larsson4ea95522013-05-22 14:41:37 +02003365
Jonny Lamba55f1392014-05-30 12:07:15 +02003366 if (scale < 1) {
3367 wl_resource_post_error(resource,
3368 WL_SURFACE_ERROR_INVALID_SCALE,
3369 "buffer scale must be at least one "
3370 "('%d' specified)", scale);
3371 return;
3372 }
3373
Pekka Paalanen952b6c82014-03-14 14:38:15 +02003374 surface->pending.buffer_viewport.buffer.scale = scale;
George Kiagiadakis8f9e87f2014-06-13 18:14:20 +02003375 surface->pending.buffer_viewport.changed = 1;
Alexander Larsson4ea95522013-05-22 14:41:37 +02003376}
3377
Kristian Høgsberg875ab9e2012-03-30 11:52:39 -04003378static const struct wl_surface_interface surface_interface = {
Kristian Høgsbergd2412e22008-12-15 20:35:24 -05003379 surface_destroy,
3380 surface_attach,
Kristian Høgsberg33418202011-08-16 23:01:28 -04003381 surface_damage,
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05003382 surface_frame,
3383 surface_set_opaque_region,
Pekka Paalanen5df44de2012-10-10 12:49:23 +03003384 surface_set_input_region,
Ander Conselvan de Oliveira012b4c72012-11-27 17:03:42 +02003385 surface_commit,
Alexander Larsson4ea95522013-05-22 14:41:37 +02003386 surface_set_buffer_transform,
Derek Foreman152254b2015-11-26 14:17:48 -06003387 surface_set_buffer_scale,
3388 surface_damage_buffer
Kristian Høgsbergd2412e22008-12-15 20:35:24 -05003389};
3390
3391static void
3392compositor_create_surface(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -04003393 struct wl_resource *resource, uint32_t id)
Kristian Høgsbergd2412e22008-12-15 20:35:24 -05003394{
Kristian Høgsbergc2d70422013-06-25 15:34:33 -04003395 struct weston_compositor *ec = wl_resource_get_user_data(resource);
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05003396 struct weston_surface *surface;
Kristian Høgsbergd2412e22008-12-15 20:35:24 -05003397
Kristian Høgsberg18c93002012-01-27 11:58:31 -05003398 surface = weston_surface_create(ec);
Kristian Høgsberg5fcd0aa2010-08-09 14:43:33 -04003399 if (surface == NULL) {
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -04003400 wl_resource_post_no_memory(resource);
Kristian Høgsbergd2412e22008-12-15 20:35:24 -05003401 return;
Kristian Høgsberg5fcd0aa2010-08-09 14:43:33 -04003402 }
Kristian Høgsbergd2412e22008-12-15 20:35:24 -05003403
Jason Ekstranda85118c2013-06-27 20:17:02 -05003404 surface->resource =
3405 wl_resource_create(client, &wl_surface_interface,
3406 wl_resource_get_version(resource), id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07003407 if (surface->resource == NULL) {
3408 weston_surface_destroy(surface);
3409 wl_resource_post_no_memory(resource);
3410 return;
3411 }
Jason Ekstranda85118c2013-06-27 20:17:02 -05003412 wl_resource_set_implementation(surface->resource, &surface_interface,
3413 surface, destroy_surface);
Kristian Høgsbergf03a04a2014-04-06 22:04:50 -07003414
3415 wl_signal_emit(&ec->create_surface_signal, surface);
Kristian Høgsbergd2412e22008-12-15 20:35:24 -05003416}
3417
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05003418static void
3419destroy_region(struct wl_resource *resource)
3420{
Jason Ekstrand8895efc2013-06-14 10:07:56 -05003421 struct weston_region *region = wl_resource_get_user_data(resource);
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05003422
3423 pixman_region32_fini(&region->region);
3424 free(region);
3425}
3426
3427static void
3428region_destroy(struct wl_client *client, struct wl_resource *resource)
3429{
Kristian Høgsbergeae5de72012-04-11 22:42:15 -04003430 wl_resource_destroy(resource);
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05003431}
3432
3433static void
3434region_add(struct wl_client *client, struct wl_resource *resource,
3435 int32_t x, int32_t y, int32_t width, int32_t height)
3436{
Jason Ekstrand8895efc2013-06-14 10:07:56 -05003437 struct weston_region *region = wl_resource_get_user_data(resource);
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05003438
3439 pixman_region32_union_rect(&region->region, &region->region,
3440 x, y, width, height);
3441}
3442
3443static void
3444region_subtract(struct wl_client *client, struct wl_resource *resource,
3445 int32_t x, int32_t y, int32_t width, int32_t height)
3446{
Jason Ekstrand8895efc2013-06-14 10:07:56 -05003447 struct weston_region *region = wl_resource_get_user_data(resource);
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05003448 pixman_region32_t rect;
3449
3450 pixman_region32_init_rect(&rect, x, y, width, height);
3451 pixman_region32_subtract(&region->region, &region->region, &rect);
3452 pixman_region32_fini(&rect);
3453}
3454
3455static const struct wl_region_interface region_interface = {
3456 region_destroy,
3457 region_add,
3458 region_subtract
3459};
3460
3461static void
3462compositor_create_region(struct wl_client *client,
3463 struct wl_resource *resource, uint32_t id)
3464{
3465 struct weston_region *region;
3466
3467 region = malloc(sizeof *region);
3468 if (region == NULL) {
3469 wl_resource_post_no_memory(resource);
3470 return;
3471 }
3472
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05003473 pixman_region32_init(&region->region);
3474
Jason Ekstranda85118c2013-06-27 20:17:02 -05003475 region->resource =
3476 wl_resource_create(client, &wl_region_interface, 1, id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07003477 if (region->resource == NULL) {
3478 free(region);
3479 wl_resource_post_no_memory(resource);
3480 return;
3481 }
Jason Ekstranda85118c2013-06-27 20:17:02 -05003482 wl_resource_set_implementation(region->resource, &region_interface,
3483 region, destroy_region);
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05003484}
3485
Kristian Høgsberg875ab9e2012-03-30 11:52:39 -04003486static const struct wl_compositor_interface compositor_interface = {
Kristian Høgsbergd2412e22008-12-15 20:35:24 -05003487 compositor_create_surface,
Kristian Høgsberg5e7e6f22012-02-23 16:11:59 -05003488 compositor_create_region
Kristian Høgsbergd2412e22008-12-15 20:35:24 -05003489};
3490
Tiago Vignatti8e53c7f2012-02-29 19:53:50 +02003491static void
Pekka Paalanene67858b2013-04-25 13:57:42 +03003492weston_subsurface_commit_from_cache(struct weston_subsurface *sub)
3493{
3494 struct weston_surface *surface = sub->surface;
Pekka Paalanene67858b2013-04-25 13:57:42 +03003495
Jason Ekstrand7b982072014-05-20 14:33:03 -05003496 weston_surface_commit_state(surface, &sub->cached);
3497 weston_buffer_reference(&sub->cached_buffer_ref, NULL);
Pekka Paalanene67858b2013-04-25 13:57:42 +03003498
3499 weston_surface_commit_subsurface_order(surface);
3500
3501 weston_surface_schedule_repaint(surface);
3502
Jason Ekstrand7b982072014-05-20 14:33:03 -05003503 sub->has_cached_data = 0;
Pekka Paalanene67858b2013-04-25 13:57:42 +03003504}
3505
3506static void
3507weston_subsurface_commit_to_cache(struct weston_subsurface *sub)
3508{
3509 struct weston_surface *surface = sub->surface;
3510
3511 /*
3512 * If this commit would cause the surface to move by the
3513 * attach(dx, dy) parameters, the old damage region must be
3514 * translated to correspond to the new surface coordinate system
Chris Michael062edf22015-11-26 11:30:00 -05003515 * origin.
Pekka Paalanene67858b2013-04-25 13:57:42 +03003516 */
Derek Foreman152254b2015-11-26 14:17:48 -06003517 pixman_region32_translate(&sub->cached.damage_surface,
Pekka Paalanene67858b2013-04-25 13:57:42 +03003518 -surface->pending.sx, -surface->pending.sy);
Derek Foreman152254b2015-11-26 14:17:48 -06003519 pixman_region32_union(&sub->cached.damage_surface,
3520 &sub->cached.damage_surface,
3521 &surface->pending.damage_surface);
3522 pixman_region32_clear(&surface->pending.damage_surface);
Pekka Paalanene67858b2013-04-25 13:57:42 +03003523
3524 if (surface->pending.newly_attached) {
3525 sub->cached.newly_attached = 1;
Jason Ekstrand7b982072014-05-20 14:33:03 -05003526 weston_surface_state_set_buffer(&sub->cached,
3527 surface->pending.buffer);
3528 weston_buffer_reference(&sub->cached_buffer_ref,
Pekka Paalanene67858b2013-04-25 13:57:42 +03003529 surface->pending.buffer);
Pekka Paalanen133e4392014-09-23 22:08:46 -04003530 weston_presentation_feedback_discard_list(
3531 &sub->cached.feedback_list);
Pekka Paalanene67858b2013-04-25 13:57:42 +03003532 }
3533 sub->cached.sx += surface->pending.sx;
3534 sub->cached.sy += surface->pending.sy;
Pekka Paalanen260ba382014-03-14 14:38:12 +02003535
Derek Foreman152254b2015-11-26 14:17:48 -06003536 apply_damage_buffer(&sub->cached.damage_surface, surface, &surface->pending);
3537
George Kiagiadakis8f9e87f2014-06-13 18:14:20 +02003538 sub->cached.buffer_viewport.changed |=
3539 surface->pending.buffer_viewport.changed;
3540 sub->cached.buffer_viewport.buffer =
3541 surface->pending.buffer_viewport.buffer;
3542 sub->cached.buffer_viewport.surface =
3543 surface->pending.buffer_viewport.surface;
Pekka Paalanene67858b2013-04-25 13:57:42 +03003544
George Kiagiadakis8f9e87f2014-06-13 18:14:20 +02003545 weston_surface_reset_pending_buffer(surface);
Pekka Paalanene67858b2013-04-25 13:57:42 +03003546
3547 pixman_region32_copy(&sub->cached.opaque, &surface->pending.opaque);
3548
3549 pixman_region32_copy(&sub->cached.input, &surface->pending.input);
3550
3551 wl_list_insert_list(&sub->cached.frame_callback_list,
3552 &surface->pending.frame_callback_list);
3553 wl_list_init(&surface->pending.frame_callback_list);
3554
Pekka Paalanen133e4392014-09-23 22:08:46 -04003555 wl_list_insert_list(&sub->cached.feedback_list,
3556 &surface->pending.feedback_list);
3557 wl_list_init(&surface->pending.feedback_list);
3558
Jason Ekstrand7b982072014-05-20 14:33:03 -05003559 sub->has_cached_data = 1;
Pekka Paalanene67858b2013-04-25 13:57:42 +03003560}
3561
Derek Foreman280e7dd2014-10-03 13:13:42 -05003562static bool
Pekka Paalanene67858b2013-04-25 13:57:42 +03003563weston_subsurface_is_synchronized(struct weston_subsurface *sub)
3564{
3565 while (sub) {
3566 if (sub->synchronized)
Derek Foreman280e7dd2014-10-03 13:13:42 -05003567 return true;
Pekka Paalanene67858b2013-04-25 13:57:42 +03003568
3569 if (!sub->parent)
Derek Foreman280e7dd2014-10-03 13:13:42 -05003570 return false;
Pekka Paalanene67858b2013-04-25 13:57:42 +03003571
3572 sub = weston_surface_to_subsurface(sub->parent);
3573 }
3574
Carlos Olmedo Escobar61a9bf52014-11-04 14:38:39 +01003575 return false;
Pekka Paalanene67858b2013-04-25 13:57:42 +03003576}
3577
3578static void
3579weston_subsurface_commit(struct weston_subsurface *sub)
3580{
3581 struct weston_surface *surface = sub->surface;
3582 struct weston_subsurface *tmp;
3583
3584 /* Recursive check for effectively synchronized. */
3585 if (weston_subsurface_is_synchronized(sub)) {
3586 weston_subsurface_commit_to_cache(sub);
3587 } else {
Jason Ekstrand7b982072014-05-20 14:33:03 -05003588 if (sub->has_cached_data) {
Pekka Paalanene67858b2013-04-25 13:57:42 +03003589 /* flush accumulated state from cache */
3590 weston_subsurface_commit_to_cache(sub);
3591 weston_subsurface_commit_from_cache(sub);
3592 } else {
3593 weston_surface_commit(surface);
3594 }
3595
3596 wl_list_for_each(tmp, &surface->subsurface_list, parent_link) {
3597 if (tmp->surface != surface)
3598 weston_subsurface_parent_commit(tmp, 0);
3599 }
3600 }
3601}
3602
3603static void
Pekka Paalanen16abf6a2013-05-17 16:46:05 +03003604weston_subsurface_synchronized_commit(struct weston_subsurface *sub)
Pekka Paalanene67858b2013-04-25 13:57:42 +03003605{
3606 struct weston_surface *surface = sub->surface;
3607 struct weston_subsurface *tmp;
3608
Pekka Paalanene67858b2013-04-25 13:57:42 +03003609 /* From now on, commit_from_cache the whole sub-tree, regardless of
3610 * the synchronized mode of each child. This sub-surface or some
3611 * of its ancestors were synchronized, so we are synchronized
3612 * all the way down.
3613 */
3614
Jason Ekstrand7b982072014-05-20 14:33:03 -05003615 if (sub->has_cached_data)
Pekka Paalanene67858b2013-04-25 13:57:42 +03003616 weston_subsurface_commit_from_cache(sub);
3617
3618 wl_list_for_each(tmp, &surface->subsurface_list, parent_link) {
3619 if (tmp->surface != surface)
3620 weston_subsurface_parent_commit(tmp, 1);
3621 }
3622}
3623
3624static void
Pekka Paalanen16abf6a2013-05-17 16:46:05 +03003625weston_subsurface_parent_commit(struct weston_subsurface *sub,
3626 int parent_is_synchronized)
3627{
Jason Ekstranda7af7042013-10-12 22:38:11 -05003628 struct weston_view *view;
Pekka Paalanen16abf6a2013-05-17 16:46:05 +03003629 if (sub->position.set) {
Jason Ekstranda7af7042013-10-12 22:38:11 -05003630 wl_list_for_each(view, &sub->surface->views, surface_link)
3631 weston_view_set_position(view,
3632 sub->position.x,
3633 sub->position.y);
3634
Pekka Paalanen16abf6a2013-05-17 16:46:05 +03003635 sub->position.set = 0;
3636 }
3637
3638 if (parent_is_synchronized || sub->synchronized)
3639 weston_subsurface_synchronized_commit(sub);
3640}
3641
Pekka Paalanen8274d902014-08-06 19:36:51 +03003642static int
3643subsurface_get_label(struct weston_surface *surface, char *buf, size_t len)
3644{
3645 return snprintf(buf, len, "sub-surface");
3646}
3647
Pekka Paalanen16abf6a2013-05-17 16:46:05 +03003648static void
Quentin Glidic2edc3d52016-08-12 10:41:33 +02003649subsurface_committed(struct weston_surface *surface, int32_t dx, int32_t dy)
Pekka Paalanene67858b2013-04-25 13:57:42 +03003650{
Jason Ekstranda7af7042013-10-12 22:38:11 -05003651 struct weston_view *view;
Pekka Paalanene67858b2013-04-25 13:57:42 +03003652
Jason Ekstranda7af7042013-10-12 22:38:11 -05003653 wl_list_for_each(view, &surface->views, surface_link)
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06003654 weston_view_set_position(view,
3655 view->geometry.x + dx,
3656 view->geometry.y + dy);
Pekka Paalanene67858b2013-04-25 13:57:42 +03003657
3658 /* No need to check parent mappedness, because if parent is not
3659 * mapped, parent is not in a visible layer, so this sub-surface
3660 * will not be drawn either.
3661 */
Armin Krezovićf8486c32016-06-30 06:04:28 +02003662
Pekka Paalanene67858b2013-04-25 13:57:42 +03003663 if (!weston_surface_is_mapped(surface)) {
Armin Krezovićf8486c32016-06-30 06:04:28 +02003664 surface->is_mapped = true;
Pekka Paalaneneb3cf222014-06-30 11:52:07 +03003665
Derek Foreman4b1a0a12014-09-10 15:37:33 -05003666 /* Cannot call weston_view_update_transform(),
Pekka Paalanene67858b2013-04-25 13:57:42 +03003667 * because that would call it also for the parent surface,
3668 * which might not be mapped yet. That would lead to
3669 * inconsistent state, where the window could never be
3670 * mapped.
3671 *
Armin Krezovićf8486c32016-06-30 06:04:28 +02003672 * Instead just force the is_mapped flag on, to make
Pekka Paalanene67858b2013-04-25 13:57:42 +03003673 * weston_surface_is_mapped() return true, so that when the
3674 * parent surface does get mapped, this one will get
Pekka Paalaneneb3cf222014-06-30 11:52:07 +03003675 * included, too. See view_list_add().
Pekka Paalanene67858b2013-04-25 13:57:42 +03003676 */
Pekka Paalanene67858b2013-04-25 13:57:42 +03003677 }
3678}
3679
3680static struct weston_subsurface *
3681weston_surface_to_subsurface(struct weston_surface *surface)
3682{
Quentin Glidic2edc3d52016-08-12 10:41:33 +02003683 if (surface->committed == subsurface_committed)
3684 return surface->committed_private;
Pekka Paalanene67858b2013-04-25 13:57:42 +03003685
3686 return NULL;
3687}
3688
Pekka Paalanen01388e22013-04-25 13:57:44 +03003689WL_EXPORT struct weston_surface *
3690weston_surface_get_main_surface(struct weston_surface *surface)
3691{
3692 struct weston_subsurface *sub;
3693
3694 while (surface && (sub = weston_surface_to_subsurface(surface)))
3695 surface = sub->parent;
3696
3697 return surface;
3698}
3699
Pekka Paalanen50b67472014-10-01 15:02:41 +03003700WL_EXPORT int
3701weston_surface_set_role(struct weston_surface *surface,
3702 const char *role_name,
3703 struct wl_resource *error_resource,
3704 uint32_t error_code)
3705{
3706 assert(role_name);
3707
3708 if (surface->role_name == NULL ||
3709 surface->role_name == role_name ||
3710 strcmp(surface->role_name, role_name) == 0) {
3711 surface->role_name = role_name;
3712
3713 return 0;
3714 }
3715
3716 wl_resource_post_error(error_resource, error_code,
3717 "Cannot assign role %s to wl_surface@%d,"
3718 " already has role %s\n",
3719 role_name,
3720 wl_resource_get_id(surface->resource),
3721 surface->role_name);
3722 return -1;
3723}
3724
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +02003725WL_EXPORT const char *
3726weston_surface_get_role(struct weston_surface *surface)
3727{
3728 return surface->role_name;
3729}
3730
Pekka Paalanen8274d902014-08-06 19:36:51 +03003731WL_EXPORT void
3732weston_surface_set_label_func(struct weston_surface *surface,
3733 int (*desc)(struct weston_surface *,
3734 char *, size_t))
3735{
3736 surface->get_label = desc;
Pekka Paalanenb5026542014-11-12 15:09:24 +02003737 surface->timeline.force_refresh = 1;
Pekka Paalanen8274d902014-08-06 19:36:51 +03003738}
3739
Pekka Paalanenc647ed72015-02-09 13:16:57 +02003740/** Get the size of surface contents
3741 *
3742 * \param surface The surface to query.
3743 * \param width Returns the width of raw contents.
3744 * \param height Returns the height of raw contents.
3745 *
3746 * Retrieves the raw surface content size in pixels for the given surface.
3747 * This is the whole content size in buffer pixels. If the surface
3748 * has no content or the renderer does not implement this feature,
3749 * zeroes are returned.
3750 *
3751 * This function is used to determine the buffer size needed for
3752 * a weston_surface_copy_content() call.
3753 */
3754WL_EXPORT void
3755weston_surface_get_content_size(struct weston_surface *surface,
3756 int *width, int *height)
3757{
3758 struct weston_renderer *rer = surface->compositor->renderer;
3759
3760 if (!rer->surface_get_content_size) {
3761 *width = 0;
3762 *height = 0;
3763 return;
3764 }
3765
3766 rer->surface_get_content_size(surface, width, height);
3767}
3768
Quentin Glidic248dd102016-08-12 10:41:34 +02003769/** Get the bounding box of a surface and its subsurfaces
3770 *
3771 * \param surface The surface to query.
3772 * \return The bounding box relative to the surface origin.
3773 *
3774 */
3775WL_EXPORT struct weston_geometry
3776weston_surface_get_bounding_box(struct weston_surface *surface)
3777{
3778 pixman_region32_t region;
3779 pixman_box32_t *box;
3780 struct weston_subsurface *subsurface;
3781
3782 pixman_region32_init_rect(&region,
3783 0, 0,
3784 surface->width, surface->height);
3785
3786 wl_list_for_each(subsurface, &surface->subsurface_list, parent_link)
3787 pixman_region32_union_rect(&region, &region,
3788 subsurface->position.x,
3789 subsurface->position.y,
3790 subsurface->surface->width,
3791 subsurface->surface->height);
3792
3793 box = pixman_region32_extents(&region);
3794 struct weston_geometry geometry = {
3795 .x = box->x1,
3796 .y = box->y1,
3797 .width = box->x2 - box->x1,
3798 .height = box->y2 - box->y1,
3799 };
3800
3801 pixman_region32_fini(&region);
3802
3803 return geometry;
3804}
3805
Pekka Paalanenc647ed72015-02-09 13:16:57 +02003806/** Copy surface contents to system memory.
3807 *
3808 * \param surface The surface to copy from.
3809 * \param target Pointer to the target memory buffer.
3810 * \param size Size of the target buffer in bytes.
3811 * \param src_x X location on contents to copy from.
3812 * \param src_y Y location on contents to copy from.
3813 * \param width Width in pixels of the area to copy.
3814 * \param height Height in pixels of the area to copy.
3815 * \return 0 for success, -1 for failure.
3816 *
3817 * Surface contents are maintained by the renderer. They can be in a
3818 * reserved weston_buffer or as a copy, e.g. a GL texture, or something
3819 * else.
3820 *
3821 * Surface contents are copied into memory pointed to by target,
3822 * which has size bytes of space available. The target memory
3823 * may be larger than needed, but being smaller returns an error.
3824 * The extra bytes in target may or may not be written; their content is
3825 * unspecified. Size must be large enough to hold the image.
3826 *
3827 * The image in the target memory will be arranged in rows from
3828 * top to bottom, and pixels on a row from left to right. The pixel
3829 * format is PIXMAN_a8b8g8r8, 4 bytes per pixel, and stride is exactly
3830 * width * 4.
3831 *
3832 * Parameters src_x and src_y define the upper-left corner in buffer
3833 * coordinates (pixels) to copy from. Parameters width and height
3834 * define the size of the area to copy in pixels.
3835 *
3836 * The rectangle defined by src_x, src_y, width, height must fit in
3837 * the surface contents. Otherwise an error is returned.
3838 *
Changwoo Chof97d2502017-08-05 00:30:47 +09003839 * Use weston_surface_get_content_size to determine the content size; the
Pekka Paalanenc647ed72015-02-09 13:16:57 +02003840 * needed target buffer size and rectangle limits.
3841 *
3842 * CURRENT IMPLEMENTATION RESTRICTIONS:
3843 * - the machine must be little-endian due to Pixman formats.
3844 *
3845 * NOTE: Pixman formats are premultiplied.
3846 */
3847WL_EXPORT int
3848weston_surface_copy_content(struct weston_surface *surface,
3849 void *target, size_t size,
3850 int src_x, int src_y,
3851 int width, int height)
3852{
3853 struct weston_renderer *rer = surface->compositor->renderer;
3854 int cw, ch;
3855 const size_t bytespp = 4; /* PIXMAN_a8b8g8r8 */
3856
3857 if (!rer->surface_copy_content)
3858 return -1;
3859
3860 weston_surface_get_content_size(surface, &cw, &ch);
3861
3862 if (src_x < 0 || src_y < 0)
3863 return -1;
3864
3865 if (width <= 0 || height <= 0)
3866 return -1;
3867
3868 if (src_x + width > cw || src_y + height > ch)
3869 return -1;
3870
3871 if (width * bytespp * height > size)
3872 return -1;
3873
3874 return rer->surface_copy_content(surface, target, size,
3875 src_x, src_y, width, height);
3876}
3877
Pekka Paalanene67858b2013-04-25 13:57:42 +03003878static void
3879subsurface_set_position(struct wl_client *client,
3880 struct wl_resource *resource, int32_t x, int32_t y)
3881{
Jason Ekstrand0bd587e2013-06-14 10:08:02 -05003882 struct weston_subsurface *sub = wl_resource_get_user_data(resource);
Pekka Paalanene67858b2013-04-25 13:57:42 +03003883
3884 if (!sub)
3885 return;
3886
3887 sub->position.x = x;
3888 sub->position.y = y;
3889 sub->position.set = 1;
3890}
3891
3892static struct weston_subsurface *
Arnaud Vracb8c16c92016-06-08 18:37:57 +02003893subsurface_find_sibling(struct weston_subsurface *sub,
3894 struct weston_surface *surface)
Pekka Paalanene67858b2013-04-25 13:57:42 +03003895{
Arnaud Vracb8c16c92016-06-08 18:37:57 +02003896 struct weston_surface *parent = sub->parent;
3897 struct weston_subsurface *sibling;
Pekka Paalanene67858b2013-04-25 13:57:42 +03003898
Arnaud Vracb8c16c92016-06-08 18:37:57 +02003899 wl_list_for_each(sibling, &parent->subsurface_list, parent_link) {
3900 if (sibling->surface == surface && sibling != sub)
3901 return sibling;
3902 }
Pekka Paalanene67858b2013-04-25 13:57:42 +03003903
3904 return NULL;
3905}
3906
3907static struct weston_subsurface *
3908subsurface_sibling_check(struct weston_subsurface *sub,
3909 struct weston_surface *surface,
3910 const char *request)
3911{
3912 struct weston_subsurface *sibling;
3913
Arnaud Vracb8c16c92016-06-08 18:37:57 +02003914 sibling = subsurface_find_sibling(sub, surface);
Pekka Paalanene67858b2013-04-25 13:57:42 +03003915 if (!sibling) {
3916 wl_resource_post_error(sub->resource,
3917 WL_SUBSURFACE_ERROR_BAD_SURFACE,
3918 "%s: wl_surface@%d is not a parent or sibling",
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05003919 request, wl_resource_get_id(surface->resource));
Pekka Paalanene67858b2013-04-25 13:57:42 +03003920 return NULL;
3921 }
3922
Arnaud Vracb8c16c92016-06-08 18:37:57 +02003923 assert(sibling->parent == sub->parent);
Pekka Paalanene67858b2013-04-25 13:57:42 +03003924
3925 return sibling;
3926}
3927
3928static void
3929subsurface_place_above(struct wl_client *client,
3930 struct wl_resource *resource,
3931 struct wl_resource *sibling_resource)
3932{
Jason Ekstrand0bd587e2013-06-14 10:08:02 -05003933 struct weston_subsurface *sub = wl_resource_get_user_data(resource);
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -05003934 struct weston_surface *surface =
3935 wl_resource_get_user_data(sibling_resource);
Pekka Paalanene67858b2013-04-25 13:57:42 +03003936 struct weston_subsurface *sibling;
3937
3938 if (!sub)
3939 return;
3940
3941 sibling = subsurface_sibling_check(sub, surface, "place_above");
3942 if (!sibling)
3943 return;
3944
3945 wl_list_remove(&sub->parent_link_pending);
3946 wl_list_insert(sibling->parent_link_pending.prev,
3947 &sub->parent_link_pending);
Emilio Pozuelo Monfort4f3cad72017-01-27 17:30:29 +01003948
3949 sub->reordered = true;
Pekka Paalanene67858b2013-04-25 13:57:42 +03003950}
3951
3952static void
3953subsurface_place_below(struct wl_client *client,
3954 struct wl_resource *resource,
3955 struct wl_resource *sibling_resource)
3956{
Jason Ekstrand0bd587e2013-06-14 10:08:02 -05003957 struct weston_subsurface *sub = wl_resource_get_user_data(resource);
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -05003958 struct weston_surface *surface =
3959 wl_resource_get_user_data(sibling_resource);
Pekka Paalanene67858b2013-04-25 13:57:42 +03003960 struct weston_subsurface *sibling;
3961
3962 if (!sub)
3963 return;
3964
3965 sibling = subsurface_sibling_check(sub, surface, "place_below");
3966 if (!sibling)
3967 return;
3968
3969 wl_list_remove(&sub->parent_link_pending);
3970 wl_list_insert(&sibling->parent_link_pending,
3971 &sub->parent_link_pending);
Emilio Pozuelo Monfort4f3cad72017-01-27 17:30:29 +01003972
3973 sub->reordered = true;
Pekka Paalanene67858b2013-04-25 13:57:42 +03003974}
3975
3976static void
3977subsurface_set_sync(struct wl_client *client, struct wl_resource *resource)
3978{
Jason Ekstrand0bd587e2013-06-14 10:08:02 -05003979 struct weston_subsurface *sub = wl_resource_get_user_data(resource);
Pekka Paalanene67858b2013-04-25 13:57:42 +03003980
3981 if (sub)
3982 sub->synchronized = 1;
3983}
3984
3985static void
3986subsurface_set_desync(struct wl_client *client, struct wl_resource *resource)
3987{
Jason Ekstrand0bd587e2013-06-14 10:08:02 -05003988 struct weston_subsurface *sub = wl_resource_get_user_data(resource);
Pekka Paalanene67858b2013-04-25 13:57:42 +03003989
Pekka Paalanen16abf6a2013-05-17 16:46:05 +03003990 if (sub && sub->synchronized) {
Pekka Paalanene67858b2013-04-25 13:57:42 +03003991 sub->synchronized = 0;
Pekka Paalanen16abf6a2013-05-17 16:46:05 +03003992
3993 /* If sub became effectively desynchronized, flush. */
3994 if (!weston_subsurface_is_synchronized(sub))
3995 weston_subsurface_synchronized_commit(sub);
3996 }
Pekka Paalanene67858b2013-04-25 13:57:42 +03003997}
3998
3999static void
Pekka Paalanene67858b2013-04-25 13:57:42 +03004000weston_subsurface_unlink_parent(struct weston_subsurface *sub)
4001{
4002 wl_list_remove(&sub->parent_link);
4003 wl_list_remove(&sub->parent_link_pending);
4004 wl_list_remove(&sub->parent_destroy_listener.link);
4005 sub->parent = NULL;
4006}
4007
4008static void
4009weston_subsurface_destroy(struct weston_subsurface *sub);
4010
4011static void
4012subsurface_handle_surface_destroy(struct wl_listener *listener, void *data)
4013{
4014 struct weston_subsurface *sub =
4015 container_of(listener, struct weston_subsurface,
4016 surface_destroy_listener);
Pekka Paalanenca790762015-04-17 14:23:38 +03004017 assert(data == sub->surface);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004018
4019 /* The protocol object (wl_resource) is left inert. */
4020 if (sub->resource)
Jason Ekstrand0bd587e2013-06-14 10:08:02 -05004021 wl_resource_set_user_data(sub->resource, NULL);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004022
4023 weston_subsurface_destroy(sub);
4024}
4025
4026static void
4027subsurface_handle_parent_destroy(struct wl_listener *listener, void *data)
4028{
4029 struct weston_subsurface *sub =
4030 container_of(listener, struct weston_subsurface,
4031 parent_destroy_listener);
Pekka Paalanenca790762015-04-17 14:23:38 +03004032 assert(data == sub->parent);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004033 assert(sub->surface != sub->parent);
4034
4035 if (weston_surface_is_mapped(sub->surface))
4036 weston_surface_unmap(sub->surface);
4037
4038 weston_subsurface_unlink_parent(sub);
4039}
4040
4041static void
4042subsurface_resource_destroy(struct wl_resource *resource)
4043{
Jason Ekstrand0bd587e2013-06-14 10:08:02 -05004044 struct weston_subsurface *sub = wl_resource_get_user_data(resource);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004045
4046 if (sub)
4047 weston_subsurface_destroy(sub);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004048}
4049
4050static void
4051subsurface_destroy(struct wl_client *client, struct wl_resource *resource)
4052{
4053 wl_resource_destroy(resource);
4054}
4055
4056static void
4057weston_subsurface_link_parent(struct weston_subsurface *sub,
4058 struct weston_surface *parent)
4059{
4060 sub->parent = parent;
4061 sub->parent_destroy_listener.notify = subsurface_handle_parent_destroy;
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05004062 wl_signal_add(&parent->destroy_signal,
Pekka Paalanene67858b2013-04-25 13:57:42 +03004063 &sub->parent_destroy_listener);
4064
4065 wl_list_insert(&parent->subsurface_list, &sub->parent_link);
4066 wl_list_insert(&parent->subsurface_list_pending,
4067 &sub->parent_link_pending);
4068}
4069
4070static void
4071weston_subsurface_link_surface(struct weston_subsurface *sub,
4072 struct weston_surface *surface)
4073{
4074 sub->surface = surface;
4075 sub->surface_destroy_listener.notify =
4076 subsurface_handle_surface_destroy;
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05004077 wl_signal_add(&surface->destroy_signal,
Pekka Paalanene67858b2013-04-25 13:57:42 +03004078 &sub->surface_destroy_listener);
4079}
4080
4081static void
4082weston_subsurface_destroy(struct weston_subsurface *sub)
4083{
Jason Ekstranda7af7042013-10-12 22:38:11 -05004084 struct weston_view *view, *next;
4085
Pekka Paalanene67858b2013-04-25 13:57:42 +03004086 assert(sub->surface);
4087
4088 if (sub->resource) {
4089 assert(weston_surface_to_subsurface(sub->surface) == sub);
4090 assert(sub->parent_destroy_listener.notify ==
4091 subsurface_handle_parent_destroy);
4092
George Kiagiadakised04d382014-06-13 18:10:26 +02004093 wl_list_for_each_safe(view, next, &sub->surface->views, surface_link) {
4094 weston_view_unmap(view);
Jason Ekstranda7af7042013-10-12 22:38:11 -05004095 weston_view_destroy(view);
George Kiagiadakised04d382014-06-13 18:10:26 +02004096 }
Jason Ekstranda7af7042013-10-12 22:38:11 -05004097
Pekka Paalanene67858b2013-04-25 13:57:42 +03004098 if (sub->parent)
4099 weston_subsurface_unlink_parent(sub);
4100
Jason Ekstrand7b982072014-05-20 14:33:03 -05004101 weston_surface_state_fini(&sub->cached);
4102 weston_buffer_reference(&sub->cached_buffer_ref, NULL);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004103
Quentin Glidic2edc3d52016-08-12 10:41:33 +02004104 sub->surface->committed = NULL;
4105 sub->surface->committed_private = NULL;
Pekka Paalanen8274d902014-08-06 19:36:51 +03004106 weston_surface_set_label_func(sub->surface, NULL);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004107 } else {
4108 /* the dummy weston_subsurface for the parent itself */
4109 assert(sub->parent_destroy_listener.notify == NULL);
4110 wl_list_remove(&sub->parent_link);
4111 wl_list_remove(&sub->parent_link_pending);
4112 }
4113
4114 wl_list_remove(&sub->surface_destroy_listener.link);
4115 free(sub);
4116}
4117
4118static const struct wl_subsurface_interface subsurface_implementation = {
4119 subsurface_destroy,
4120 subsurface_set_position,
4121 subsurface_place_above,
4122 subsurface_place_below,
4123 subsurface_set_sync,
4124 subsurface_set_desync
4125};
4126
4127static struct weston_subsurface *
4128weston_subsurface_create(uint32_t id, struct weston_surface *surface,
4129 struct weston_surface *parent)
4130{
4131 struct weston_subsurface *sub;
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05004132 struct wl_client *client = wl_resource_get_client(surface->resource);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004133
Bryce Harringtonde16d892014-11-20 22:21:57 -08004134 sub = zalloc(sizeof *sub);
4135 if (sub == NULL)
Pekka Paalanene67858b2013-04-25 13:57:42 +03004136 return NULL;
4137
Jason Ekstranda7af7042013-10-12 22:38:11 -05004138 wl_list_init(&sub->unused_views);
4139
Jason Ekstranda85118c2013-06-27 20:17:02 -05004140 sub->resource =
4141 wl_resource_create(client, &wl_subsurface_interface, 1, id);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004142 if (!sub->resource) {
4143 free(sub);
4144 return NULL;
4145 }
4146
Jason Ekstranda85118c2013-06-27 20:17:02 -05004147 wl_resource_set_implementation(sub->resource,
4148 &subsurface_implementation,
4149 sub, subsurface_resource_destroy);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004150 weston_subsurface_link_surface(sub, surface);
4151 weston_subsurface_link_parent(sub, parent);
Jason Ekstrand7b982072014-05-20 14:33:03 -05004152 weston_surface_state_init(&sub->cached);
4153 sub->cached_buffer_ref.buffer = NULL;
Pekka Paalanene67858b2013-04-25 13:57:42 +03004154 sub->synchronized = 1;
Pekka Paalanene67858b2013-04-25 13:57:42 +03004155
4156 return sub;
4157}
4158
4159/* Create a dummy subsurface for having the parent itself in its
4160 * sub-surface lists. Makes stacking order manipulation easy.
4161 */
4162static struct weston_subsurface *
4163weston_subsurface_create_for_parent(struct weston_surface *parent)
4164{
4165 struct weston_subsurface *sub;
4166
Bryce Harringtonde16d892014-11-20 22:21:57 -08004167 sub = zalloc(sizeof *sub);
4168 if (sub == NULL)
Pekka Paalanene67858b2013-04-25 13:57:42 +03004169 return NULL;
4170
4171 weston_subsurface_link_surface(sub, parent);
4172 sub->parent = parent;
4173 wl_list_insert(&parent->subsurface_list, &sub->parent_link);
4174 wl_list_insert(&parent->subsurface_list_pending,
4175 &sub->parent_link_pending);
4176
4177 return sub;
4178}
4179
4180static void
4181subcompositor_get_subsurface(struct wl_client *client,
4182 struct wl_resource *resource,
4183 uint32_t id,
4184 struct wl_resource *surface_resource,
4185 struct wl_resource *parent_resource)
4186{
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -05004187 struct weston_surface *surface =
4188 wl_resource_get_user_data(surface_resource);
4189 struct weston_surface *parent =
4190 wl_resource_get_user_data(parent_resource);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004191 struct weston_subsurface *sub;
4192 static const char where[] = "get_subsurface: wl_subsurface@";
4193
4194 if (surface == parent) {
4195 wl_resource_post_error(resource,
4196 WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
4197 "%s%d: wl_surface@%d cannot be its own parent",
Jason Ekstrand0bd587e2013-06-14 10:08:02 -05004198 where, id, wl_resource_get_id(surface_resource));
Pekka Paalanene67858b2013-04-25 13:57:42 +03004199 return;
4200 }
4201
4202 if (weston_surface_to_subsurface(surface)) {
4203 wl_resource_post_error(resource,
4204 WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
4205 "%s%d: wl_surface@%d is already a sub-surface",
Jason Ekstrand0bd587e2013-06-14 10:08:02 -05004206 where, id, wl_resource_get_id(surface_resource));
Pekka Paalanene67858b2013-04-25 13:57:42 +03004207 return;
4208 }
4209
Pekka Paalanen50b67472014-10-01 15:02:41 +03004210 if (weston_surface_set_role(surface, "wl_subsurface", resource,
4211 WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE) < 0)
Pekka Paalanene67858b2013-04-25 13:57:42 +03004212 return;
Pekka Paalanene67858b2013-04-25 13:57:42 +03004213
Pekka Paalanen86c8ca02013-05-17 16:46:07 +03004214 if (weston_surface_get_main_surface(parent) == surface) {
4215 wl_resource_post_error(resource,
4216 WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
4217 "%s%d: wl_surface@%d is an ancestor of parent",
Jason Ekstrand0bd587e2013-06-14 10:08:02 -05004218 where, id, wl_resource_get_id(surface_resource));
Pekka Paalanen86c8ca02013-05-17 16:46:07 +03004219 return;
4220 }
4221
Pekka Paalanene67858b2013-04-25 13:57:42 +03004222 /* make sure the parent is in its own list */
4223 if (wl_list_empty(&parent->subsurface_list)) {
4224 if (!weston_subsurface_create_for_parent(parent)) {
4225 wl_resource_post_no_memory(resource);
4226 return;
4227 }
4228 }
4229
4230 sub = weston_subsurface_create(id, surface, parent);
4231 if (!sub) {
4232 wl_resource_post_no_memory(resource);
4233 return;
4234 }
4235
Quentin Glidic2edc3d52016-08-12 10:41:33 +02004236 surface->committed = subsurface_committed;
4237 surface->committed_private = sub;
Pekka Paalanen8274d902014-08-06 19:36:51 +03004238 weston_surface_set_label_func(surface, subsurface_get_label);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004239}
4240
4241static void
4242subcompositor_destroy(struct wl_client *client, struct wl_resource *resource)
4243{
4244 wl_resource_destroy(resource);
4245}
4246
4247static const struct wl_subcompositor_interface subcompositor_interface = {
4248 subcompositor_destroy,
4249 subcompositor_get_subsurface
4250};
4251
4252static void
4253bind_subcompositor(struct wl_client *client,
4254 void *data, uint32_t version, uint32_t id)
4255{
4256 struct weston_compositor *compositor = data;
Jason Ekstranda85118c2013-06-27 20:17:02 -05004257 struct wl_resource *resource;
Pekka Paalanene67858b2013-04-25 13:57:42 +03004258
Jason Ekstranda85118c2013-06-27 20:17:02 -05004259 resource =
4260 wl_resource_create(client, &wl_subcompositor_interface, 1, id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07004261 if (resource == NULL) {
4262 wl_client_post_no_memory(client);
4263 return;
4264 }
4265 wl_resource_set_implementation(resource, &subcompositor_interface,
4266 compositor, NULL);
Pekka Paalanene67858b2013-04-25 13:57:42 +03004267}
4268
Bryce Harrington0795ece2016-08-30 12:04:26 -07004269/** Set a DPMS mode on all of the compositor's outputs
Bryce Harringtonc9626a32015-12-11 13:11:38 -08004270 *
4271 * \param compositor The compositor instance
4272 * \param state The DPMS state the outputs will be set to
4273 */
Pekka Paalanene67858b2013-04-25 13:57:42 +03004274static void
Ander Conselvan de Oliveira87524b62013-02-21 18:35:22 +02004275weston_compositor_dpms(struct weston_compositor *compositor,
4276 enum dpms_enum state)
Tiago Vignatti8e53c7f2012-02-29 19:53:50 +02004277{
4278 struct weston_output *output;
4279
Bryce Harrington08976ac2016-08-30 12:05:16 -07004280 wl_list_for_each(output, &compositor->output_list, link)
4281 if (output->set_dpms)
4282 output->set_dpms(output, state);
Tiago Vignatti8e53c7f2012-02-29 19:53:50 +02004283}
4284
Bryce Harringtonc9626a32015-12-11 13:11:38 -08004285/** Restores the compositor to active status
4286 *
4287 * \param compositor The compositor instance
4288 *
4289 * If the compositor was in a sleeping mode, all outputs are powered
4290 * back on via DPMS. Otherwise if the compositor was inactive
4291 * (idle/locked, offscreen, or sleeping) then the compositor's wake
4292 * signal will fire.
4293 *
4294 * Restarts the idle timer.
4295 */
Kristian Høgsbergaf867cc2011-11-15 13:34:49 +02004296WL_EXPORT void
Ander Conselvan de Oliveira87524b62013-02-21 18:35:22 +02004297weston_compositor_wake(struct weston_compositor *compositor)
Kristian Høgsbergaf867cc2011-11-15 13:34:49 +02004298{
Neil Roberts8b62e202013-09-30 13:14:47 +01004299 uint32_t old_state = compositor->state;
4300
4301 /* The state needs to be changed before emitting the wake
4302 * signal because that may try to schedule a repaint which
4303 * will not work if the compositor is still sleeping */
4304 compositor->state = WESTON_COMPOSITOR_ACTIVE;
4305
4306 switch (old_state) {
Ander Conselvan de Oliveira87524b62013-02-21 18:35:22 +02004307 case WESTON_COMPOSITOR_SLEEPING:
Ander Conselvan de Oliveira87524b62013-02-21 18:35:22 +02004308 case WESTON_COMPOSITOR_IDLE:
Philipp Brüschweiler57edf7f2013-03-29 13:01:56 +01004309 case WESTON_COMPOSITOR_OFFSCREEN:
Daniel Stone893b9362016-11-08 15:47:09 +00004310 weston_compositor_dpms(compositor, WESTON_DPMS_ON);
Ander Conselvan de Oliveiraa4575632013-02-21 18:35:23 +02004311 wl_signal_emit(&compositor->wake_signal, compositor);
Ander Conselvan de Oliveira87524b62013-02-21 18:35:22 +02004312 /* fall through */
4313 default:
Ander Conselvan de Oliveira87524b62013-02-21 18:35:22 +02004314 wl_event_source_timer_update(compositor->idle_source,
4315 compositor->idle_time * 1000);
Kristian Høgsbergaf867cc2011-11-15 13:34:49 +02004316 }
4317}
4318
Bryce Harringtonc9626a32015-12-11 13:11:38 -08004319/** Turns off rendering and frame events for the compositor.
4320 *
4321 * \param compositor The compositor instance
4322 *
4323 * This is used for example to prevent further rendering while the
4324 * compositor is shutting down.
4325 *
Bryce Harringtonc9626a32015-12-11 13:11:38 -08004326 * Stops the idle timer.
4327 */
Ander Conselvan de Oliveira87524b62013-02-21 18:35:22 +02004328WL_EXPORT void
Philipp Brüschweiler57edf7f2013-03-29 13:01:56 +01004329weston_compositor_offscreen(struct weston_compositor *compositor)
4330{
4331 switch (compositor->state) {
4332 case WESTON_COMPOSITOR_OFFSCREEN:
4333 return;
4334 case WESTON_COMPOSITOR_SLEEPING:
Philipp Brüschweiler57edf7f2013-03-29 13:01:56 +01004335 default:
4336 compositor->state = WESTON_COMPOSITOR_OFFSCREEN;
4337 wl_event_source_timer_update(compositor->idle_source, 0);
4338 }
4339}
4340
Bryce Harringtonc9626a32015-12-11 13:11:38 -08004341/** Powers down all attached output devices
4342 *
4343 * \param compositor The compositor instance
4344 *
4345 * Causes rendering to the outputs to cease, and no frame events to be
4346 * sent. Only powers down the outputs if the compositor is not already
4347 * in sleep mode.
4348 *
4349 * Stops the idle timer.
4350 */
Philipp Brüschweiler57edf7f2013-03-29 13:01:56 +01004351WL_EXPORT void
Ander Conselvan de Oliveira87524b62013-02-21 18:35:22 +02004352weston_compositor_sleep(struct weston_compositor *compositor)
4353{
4354 if (compositor->state == WESTON_COMPOSITOR_SLEEPING)
4355 return;
4356
Philipp Brüschweiler57edf7f2013-03-29 13:01:56 +01004357 wl_event_source_timer_update(compositor->idle_source, 0);
Ander Conselvan de Oliveira87524b62013-02-21 18:35:22 +02004358 compositor->state = WESTON_COMPOSITOR_SLEEPING;
4359 weston_compositor_dpms(compositor, WESTON_DPMS_OFF);
4360}
4361
Bryce Harringtonc9626a32015-12-11 13:11:38 -08004362/** Sets compositor to idle mode
4363 *
4364 * \param data The compositor instance
4365 *
4366 * This is called when the idle timer fires. Once the compositor is in
4367 * idle mode it requires a wake action (e.g. via
4368 * weston_compositor_wake()) to restore it. The compositor's
4369 * idle_signal will be triggered when the idle event occurs.
4370 *
4371 * Idleness can be inhibited by setting the compositor's idle_inhibit
4372 * property.
4373 */
Kristian Høgsberge10a5d92011-04-22 14:01:18 -04004374static int
4375idle_handler(void *data)
4376{
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05004377 struct weston_compositor *compositor = data;
Kristian Høgsberge10a5d92011-04-22 14:01:18 -04004378
4379 if (compositor->idle_inhibit)
4380 return 1;
4381
Ander Conselvan de Oliveira19d10ef2013-02-21 18:35:20 +02004382 compositor->state = WESTON_COMPOSITOR_IDLE;
Ander Conselvan de Oliveiraa4575632013-02-21 18:35:23 +02004383 wl_signal_emit(&compositor->idle_signal, compositor);
Kristian Høgsberge10a5d92011-04-22 14:01:18 -04004384
4385 return 1;
4386}
4387
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04004388WL_EXPORT void
Xiong Zhang97116532013-10-23 13:58:31 +08004389weston_plane_init(struct weston_plane *plane,
4390 struct weston_compositor *ec,
4391 int32_t x, int32_t y)
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04004392{
4393 pixman_region32_init(&plane->damage);
Ander Conselvan de Oliveirae1bd5a02013-03-05 17:30:29 +02004394 pixman_region32_init(&plane->clip);
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04004395 plane->x = x;
4396 plane->y = y;
Xiong Zhang97116532013-10-23 13:58:31 +08004397 plane->compositor = ec;
Ander Conselvan de Oliveira3c36bf32013-07-05 16:05:26 +03004398
4399 /* Init the link so that the call to wl_list_remove() when releasing
4400 * the plane without ever stacking doesn't lead to a crash */
4401 wl_list_init(&plane->link);
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04004402}
4403
4404WL_EXPORT void
4405weston_plane_release(struct weston_plane *plane)
4406{
Xiong Zhang97116532013-10-23 13:58:31 +08004407 struct weston_view *view;
4408
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04004409 pixman_region32_fini(&plane->damage);
Ander Conselvan de Oliveirae1bd5a02013-03-05 17:30:29 +02004410 pixman_region32_fini(&plane->clip);
Ander Conselvan de Oliveira3c36bf32013-07-05 16:05:26 +03004411
Xiong Zhang97116532013-10-23 13:58:31 +08004412 wl_list_for_each(view, &plane->compositor->view_list, link) {
4413 if (view->plane == plane)
4414 view->plane = NULL;
4415 }
4416
Ander Conselvan de Oliveira3c36bf32013-07-05 16:05:26 +03004417 wl_list_remove(&plane->link);
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04004418}
4419
Ander Conselvan de Oliveira8ad19822013-03-05 17:30:27 +02004420WL_EXPORT void
4421weston_compositor_stack_plane(struct weston_compositor *ec,
4422 struct weston_plane *plane,
4423 struct weston_plane *above)
4424{
4425 if (above)
4426 wl_list_insert(above->link.prev, &plane->link);
4427 else
4428 wl_list_insert(&ec->plane_list, &plane->link);
4429}
4430
Quentin Glidic4ef719c2016-07-05 20:44:33 +02004431static void
4432output_release(struct wl_client *client, struct wl_resource *resource)
4433{
4434 wl_resource_destroy(resource);
4435}
4436
4437static const struct wl_output_interface output_interface = {
4438 output_release,
4439};
4440
4441
Casey Dahlin9074db52012-04-19 22:50:09 -04004442static void unbind_resource(struct wl_resource *resource)
Kristian Høgsbergd2baf1f2011-10-11 22:20:37 -04004443{
Jason Ekstranda0d2dde2013-06-14 10:08:01 -05004444 wl_list_remove(wl_resource_get_link(resource));
Kristian Høgsbergd2baf1f2011-10-11 22:20:37 -04004445}
4446
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -04004447static void
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -04004448bind_output(struct wl_client *client,
4449 void *data, uint32_t version, uint32_t id)
Kristian Høgsbergbf9541f2008-11-25 12:10:09 -05004450{
Pekka Paalanen05347622017-03-27 12:24:34 +03004451 struct weston_head *head = data;
4452 struct weston_output *output = head->output;
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05004453 struct weston_mode *mode;
Kristian Høgsbergfd07fb72011-08-29 15:03:09 -04004454 struct wl_resource *resource;
Kristian Høgsberg81ce09a2008-12-31 16:18:42 -05004455
Jason Ekstranda85118c2013-06-27 20:17:02 -05004456 resource = wl_resource_create(client, &wl_output_interface,
Derek Foreman1909c102015-11-26 14:17:47 -06004457 version, id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07004458 if (resource == NULL) {
4459 wl_client_post_no_memory(client);
4460 return;
4461 }
Kristian Høgsbergfd07fb72011-08-29 15:03:09 -04004462
Pekka Paalanen1b9bf592017-03-27 12:15:38 +03004463 wl_list_insert(&head->resource_list, wl_resource_get_link(resource));
Pekka Paalanen055c1132017-03-27 16:31:25 +03004464 wl_resource_set_implementation(resource, &output_interface, head,
Pekka Paalanen05347622017-03-27 12:24:34 +03004465 unbind_resource);
Casey Dahlin9074db52012-04-19 22:50:09 -04004466
Pekka Paalanen05347622017-03-27 12:24:34 +03004467 assert(output);
Kristian Høgsberg0b5cd0c2012-03-04 21:57:37 -05004468 wl_output_send_geometry(resource,
4469 output->x,
4470 output->y,
Pekka Paalanen01f60212017-03-24 15:39:24 +02004471 head->mm_width,
4472 head->mm_height,
4473 head->subpixel,
4474 head->make, head->model,
Kristian Høgsberg05890dc2012-08-10 10:09:20 -04004475 output->transform);
Jasper St. Pierre0013a292014-08-07 16:43:11 -04004476 if (version >= WL_OUTPUT_SCALE_SINCE_VERSION)
Alexander Larsson4ea95522013-05-22 14:41:37 +02004477 wl_output_send_scale(resource,
Hardeningff39efa2013-09-18 23:56:35 +02004478 output->current_scale);
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -04004479
4480 wl_list_for_each (mode, &output->mode_list, link) {
Kristian Høgsberg0b5cd0c2012-03-04 21:57:37 -05004481 wl_output_send_mode(resource,
4482 mode->flags,
4483 mode->width,
4484 mode->height,
4485 mode->refresh);
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -04004486 }
Alexander Larsson4ea95522013-05-22 14:41:37 +02004487
Jasper St. Pierre0013a292014-08-07 16:43:11 -04004488 if (version >= WL_OUTPUT_DONE_SINCE_VERSION)
Alexander Larsson4ea95522013-05-22 14:41:37 +02004489 wl_output_send_done(resource);
Kristian Høgsberg81ce09a2008-12-31 16:18:42 -05004490}
4491
Pekka Paalanendcac3512017-12-08 14:13:34 +02004492static void
4493weston_head_add_global(struct weston_head *head)
4494{
4495 head->global = wl_global_create(head->compositor->wl_display,
4496 &wl_output_interface, 3,
4497 head, bind_output);
4498}
4499
Pekka Paalanend9dcc6d2017-12-04 15:28:13 +02004500/** Remove the global wl_output protocol object
4501 *
4502 * \param head The head whose global to remove.
4503 *
4504 * Also orphans the wl_resources for this head (wl_output).
4505 */
4506static void
4507weston_head_remove_global(struct weston_head *head)
4508{
4509 struct wl_resource *resource, *tmp;
4510
4511 if (head->global)
4512 wl_global_destroy(head->global);
4513 head->global = NULL;
4514
4515 wl_resource_for_each_safe(resource, tmp, &head->resource_list) {
4516 unbind_resource(resource);
4517 wl_resource_set_destructor(resource, NULL);
4518 wl_resource_set_user_data(resource, NULL);
4519 }
4520}
4521
Pekka Paalanen9ffb2502017-03-27 15:14:32 +03004522/** Get the backing object of wl_output
4523 *
4524 * \param resource A wl_output protocol object.
4525 * \return The backing object (user data) of a wl_resource representing a
4526 * wl_output protocol object.
4527 */
Pekka Paalanen055c1132017-03-27 16:31:25 +03004528WL_EXPORT struct weston_head *
4529weston_head_from_resource(struct wl_resource *resource)
Pekka Paalanen9ffb2502017-03-27 15:14:32 +03004530{
4531 assert(wl_resource_instance_of(resource, &wl_output_interface,
4532 &output_interface));
4533
4534 return wl_resource_get_user_data(resource);
4535}
4536
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03004537/** Initialize a pre-allocated weston_head
4538 *
4539 * \param head The head to initialize.
Pekka Paalanen9b02e472017-08-14 14:43:13 +03004540 * \param name The head name, e.g. the connector name or equivalent.
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03004541 *
4542 * The head will be safe to attach, detach and release.
4543 *
Pekka Paalanen9b02e472017-08-14 14:43:13 +03004544 * The name is used in logs, and can be used by compositors as a configuration
4545 * identifier.
4546 *
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03004547 * \memberof weston_head
4548 * \internal
4549 */
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03004550WL_EXPORT void
Pekka Paalanen9b02e472017-08-14 14:43:13 +03004551weston_head_init(struct weston_head *head, const char *name)
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03004552{
4553 /* Add some (in)sane defaults which can be used
4554 * for checking if an output was properly configured
4555 */
4556 memset(head, 0, sizeof *head);
4557
Pekka Paalanen1adcbac2017-08-14 16:05:35 +03004558 wl_list_init(&head->compositor_link);
Pekka Paalanen2e1bedb2017-10-10 11:21:58 +03004559 wl_signal_init(&head->destroy_signal);
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03004560 wl_list_init(&head->output_link);
4561 wl_list_init(&head->resource_list);
Pekka Paalanen9b02e472017-08-14 14:43:13 +03004562 head->name = strdup(name);
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03004563}
4564
Pekka Paalanen8dc6db82018-03-20 13:29:40 +02004565/** Send output heads changed signal
4566 *
4567 * \param output The output that changed.
4568 *
4569 * Notify that the enabled output gained and/or lost heads, or that the
4570 * associated heads may have changed their connection status. This does not
4571 * include cases where the output becomes enabled or disabled. The registered
4572 * callbacks are called after the change has successfully happened.
4573 *
4574 * If connection status change causes the compositor to attach or detach a head
4575 * to an enabled output, the registered callbacks may be called multiple times.
4576 */
4577static void
4578weston_output_emit_heads_changed(struct weston_output *output)
4579{
4580 wl_signal_emit(&output->compositor->output_heads_changed_signal,
4581 output);
4582}
4583
Pekka Paalanen37e6c9e2017-08-15 13:00:02 +03004584/** Idle task for emitting heads_changed_signal */
4585static void
4586weston_compositor_call_heads_changed(void *data)
4587{
4588 struct weston_compositor *compositor = data;
Pekka Paalanen8dc6db82018-03-20 13:29:40 +02004589 struct weston_head *head;
Pekka Paalanen37e6c9e2017-08-15 13:00:02 +03004590
4591 compositor->heads_changed_source = NULL;
4592
4593 wl_signal_emit(&compositor->heads_changed_signal, compositor);
Pekka Paalanen8dc6db82018-03-20 13:29:40 +02004594
4595 wl_list_for_each(head, &compositor->head_list, compositor_link) {
4596 if (head->output && head->output->enabled)
4597 weston_output_emit_heads_changed(head->output);
4598 }
Pekka Paalanen37e6c9e2017-08-15 13:00:02 +03004599}
4600
4601/** Schedule a call on idle to heads_changed callback
4602 *
4603 * \param compositor The Compositor.
4604 *
4605 * \memberof weston_compositor
4606 * \internal
4607 */
4608static void
4609weston_compositor_schedule_heads_changed(struct weston_compositor *compositor)
4610{
4611 struct wl_event_loop *loop;
4612
4613 if (compositor->heads_changed_source)
4614 return;
4615
4616 loop = wl_display_get_event_loop(compositor->wl_display);
4617 compositor->heads_changed_source = wl_event_loop_add_idle(loop,
4618 weston_compositor_call_heads_changed, compositor);
4619}
4620
Pekka Paalanen1adcbac2017-08-14 16:05:35 +03004621/** Register a new head
4622 *
4623 * \param compositor The compositor.
4624 * \param head The head to register, must not be already registered.
4625 *
Pekka Paalanen37e6c9e2017-08-15 13:00:02 +03004626 * This signals the core that a new head has become available, leading to
4627 * heads_changed hook being called later.
Pekka Paalanen1adcbac2017-08-14 16:05:35 +03004628 *
4629 * \memberof weston_compositor
4630 * \internal
4631 */
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03004632WL_EXPORT void
Pekka Paalanen1adcbac2017-08-14 16:05:35 +03004633weston_compositor_add_head(struct weston_compositor *compositor,
4634 struct weston_head *head)
4635{
4636 assert(wl_list_empty(&head->compositor_link));
4637 assert(head->name);
4638
4639 wl_list_insert(compositor->head_list.prev, &head->compositor_link);
4640 head->compositor = compositor;
Pekka Paalanen37e6c9e2017-08-15 13:00:02 +03004641 weston_compositor_schedule_heads_changed(compositor);
4642}
4643
4644/** Adds a listener to be called when heads change
4645 *
4646 * \param compositor The compositor.
4647 * \param listener The listener to add.
4648 *
4649 * The listener notify function argument is the \var compositor.
4650 *
4651 * The listener function will be called after heads are added or their
4652 * connection status has changed. Several changes may be accumulated into a
4653 * single call. The user is expected to iterate over the existing heads and
4654 * check their statuses to find out what changed.
4655 *
4656 * \sa weston_compositor_iterate_heads, weston_head_is_connected,
4657 * weston_head_is_enabled
4658 * \memberof weston_compositor
4659 */
4660WL_EXPORT void
4661weston_compositor_add_heads_changed_listener(struct weston_compositor *compositor,
4662 struct wl_listener *listener)
4663{
4664 wl_signal_add(&compositor->heads_changed_signal, listener);
Pekka Paalanen1adcbac2017-08-14 16:05:35 +03004665}
4666
4667/** Iterate over available heads
4668 *
4669 * \param compositor The compositor.
4670 * \param item The iterator, or NULL for start.
4671 * \return The next available head in the list.
4672 *
4673 * Returns all available heads, regardless of being connected or enabled.
4674 *
4675 * You can iterate over all heads as follows:
4676 * \code
4677 * struct weston_head *head = NULL;
4678 *
4679 * while ((head = weston_compositor_iterate_heads(compositor, head))) {
4680 * ...
4681 * }
4682 * \endcode
4683 *
4684 * If you cause \c iter to be removed from the list, you cannot use it to
4685 * continue iterating. Removing any other item is safe.
4686 *
4687 * \memberof weston_compositor
4688 */
4689WL_EXPORT struct weston_head *
4690weston_compositor_iterate_heads(struct weston_compositor *compositor,
4691 struct weston_head *iter)
4692{
4693 struct wl_list *list = &compositor->head_list;
4694 struct wl_list *node;
4695
4696 assert(compositor);
4697 assert(!iter || iter->compositor == compositor);
4698
4699 if (iter)
4700 node = iter->compositor_link.next;
4701 else
4702 node = list->next;
4703
4704 assert(node);
4705 assert(!iter || node != &iter->compositor_link);
4706
4707 if (node == list)
4708 return NULL;
4709
4710 return container_of(node, struct weston_head, compositor_link);
4711}
4712
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03004713/** Iterate over attached heads
4714 *
4715 * \param output The output whose heads to iterate.
4716 * \param item The iterator, or NULL for start.
4717 * \return The next attached head in the list.
4718 *
4719 * Returns all heads currently attached to the output.
4720 *
4721 * You can iterate over all heads as follows:
4722 * \code
4723 * struct weston_head *head = NULL;
4724 *
4725 * while ((head = weston_output_iterate_heads(output, head))) {
4726 * ...
4727 * }
4728 * \endcode
4729 *
4730 * If you cause \c iter to be removed from the list, you cannot use it to
4731 * continue iterating. Removing any other item is safe.
4732 *
4733 * \memberof weston_compositor
4734 */
4735WL_EXPORT struct weston_head *
4736weston_output_iterate_heads(struct weston_output *output,
4737 struct weston_head *iter)
4738{
4739 struct wl_list *list = &output->head_list;
4740 struct wl_list *node;
4741
4742 assert(output);
4743 assert(!iter || iter->output == output);
4744
4745 if (iter)
4746 node = iter->output_link.next;
4747 else
4748 node = list->next;
4749
4750 assert(node);
4751 assert(!iter || node != &iter->output_link);
4752
4753 if (node == list)
4754 return NULL;
4755
4756 return container_of(node, struct weston_head, output_link);
4757}
4758
Pekka Paalanendcac3512017-12-08 14:13:34 +02004759/** Attach a head to an output
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03004760 *
4761 * \param output The output to attach to.
4762 * \param head The head that is not yet attached.
4763 * \return 0 on success, -1 on failure.
4764 *
4765 * Attaches the given head to the output. All heads of an output are clones
4766 * and share the resolution and timings.
4767 *
4768 * Cloning heads this way uses less resources than creating an output for
4769 * each head, but is not always possible due to environment, driver and hardware
4770 * limitations.
4771 *
4772 * On failure, the head remains unattached. Success of this function does not
4773 * guarantee the output configuration is actually valid. The final checks are
Pekka Paalanendcac3512017-12-08 14:13:34 +02004774 * made on weston_output_enable() unless the output was already enabled.
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03004775 *
4776 * \memberof weston_output
4777 */
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03004778WL_EXPORT int
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03004779weston_output_attach_head(struct weston_output *output,
4780 struct weston_head *head)
4781{
Pekka Paalanendcac3512017-12-08 14:13:34 +02004782 char *head_names;
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03004783
4784 if (!wl_list_empty(&head->output_link))
4785 return -1;
4786
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03004787 if (output->attach_head) {
4788 if (output->attach_head(output, head) < 0)
4789 return -1;
4790 } else if (!wl_list_empty(&output->head_list)) {
4791 /* No support for clones in the legacy path. */
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03004792 return -1;
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03004793 }
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03004794
4795 head->output = output;
4796 wl_list_insert(output->head_list.prev, &head->output_link);
4797
Pekka Paalanendcac3512017-12-08 14:13:34 +02004798 if (output->enabled) {
4799 weston_head_add_global(head);
4800
4801 head_names = weston_output_create_heads_string(output);
4802 weston_log("Output '%s' updated to have head(s) %s\n",
4803 output->name, head_names);
4804 free(head_names);
Pekka Paalanen8dc6db82018-03-20 13:29:40 +02004805
4806 weston_output_emit_heads_changed(output);
Pekka Paalanendcac3512017-12-08 14:13:34 +02004807 }
4808
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03004809 return 0;
4810}
4811
4812/** Detach a head from its output
4813 *
4814 * \param head The head to detach.
4815 *
4816 * It is safe to detach a non-attached head.
4817 *
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03004818 * If the head is attached to an enabled output and the output will be left
4819 * with no heads, the output will be disabled.
4820 *
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03004821 * \memberof weston_head
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03004822 * \sa weston_output_disable
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03004823 */
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03004824WL_EXPORT void
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03004825weston_head_detach(struct weston_head *head)
4826{
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03004827 struct weston_output *output = head->output;
Pekka Paalanena0106992017-12-08 16:11:17 +02004828 char *head_names;
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03004829
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03004830 wl_list_remove(&head->output_link);
4831 wl_list_init(&head->output_link);
4832 head->output = NULL;
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03004833
4834 if (!output)
4835 return;
4836
4837 if (output->detach_head)
4838 output->detach_head(output, head);
4839
4840 if (output->enabled) {
4841 weston_head_remove_global(head);
4842
Pekka Paalanena0106992017-12-08 16:11:17 +02004843 if (wl_list_empty(&output->head_list)) {
4844 weston_log("Output '%s' no heads left, disabling.\n",
4845 output->name);
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03004846 weston_output_disable(output);
Pekka Paalanena0106992017-12-08 16:11:17 +02004847 } else {
4848 head_names = weston_output_create_heads_string(output);
4849 weston_log("Output '%s' updated to have head(s) %s\n",
4850 output->name, head_names);
4851 free(head_names);
Pekka Paalanen8dc6db82018-03-20 13:29:40 +02004852
4853 weston_output_emit_heads_changed(output);
Pekka Paalanena0106992017-12-08 16:11:17 +02004854 }
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03004855 }
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03004856}
4857
4858/** Destroy a head
4859 *
4860 * \param head The head to be released.
4861 *
4862 * Destroys the head. The caller is responsible for freeing the memory pointed
4863 * to by \c head.
4864 *
4865 * \memberof weston_head
4866 * \internal
4867 */
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03004868WL_EXPORT void
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03004869weston_head_release(struct weston_head *head)
4870{
Pekka Paalanen2e1bedb2017-10-10 11:21:58 +03004871 wl_signal_emit(&head->destroy_signal, head);
4872
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03004873 weston_head_detach(head);
Pekka Paalanen06f99ef2017-04-04 16:26:23 +03004874
4875 free(head->make);
4876 free(head->model);
4877 free(head->serial_number);
Pekka Paalanen9b02e472017-08-14 14:43:13 +03004878 free(head->name);
Pekka Paalanen1adcbac2017-08-14 16:05:35 +03004879
4880 wl_list_remove(&head->compositor_link);
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03004881}
4882
Pekka Paalanene19970f2017-08-28 14:11:02 +03004883static void
4884weston_head_set_device_changed(struct weston_head *head)
4885{
4886 head->device_changed = true;
4887
4888 if (head->compositor)
4889 weston_compositor_schedule_heads_changed(head->compositor);
4890}
4891
4892/** String equal comparison with NULLs being equal */
4893static bool
4894str_null_eq(const char *a, const char *b)
4895{
4896 if (!a && !b)
4897 return true;
4898
4899 if (!!a != !!b)
4900 return false;
4901
4902 return strcmp(a, b) == 0;
4903}
4904
Pekka Paalanen01f60212017-03-24 15:39:24 +02004905/** Store monitor make, model and serial number
4906 *
4907 * \param head The head to modify.
4908 * \param make The monitor make. If EDID is available, the PNP ID. Otherwise
4909 * any string, or NULL for none.
4910 * \param model The monitor model or name, or a made-up string, or NULL for
4911 * none.
4912 * \param serialno The monitor serial number, a made-up string, or NULL for
4913 * none.
4914 *
Pekka Paalanene19970f2017-08-28 14:11:02 +03004915 * This may set the device_changed flag.
4916 *
Pekka Paalanen01f60212017-03-24 15:39:24 +02004917 * \memberof weston_head
4918 * \internal
4919 */
4920WL_EXPORT void
4921weston_head_set_monitor_strings(struct weston_head *head,
4922 const char *make,
4923 const char *model,
4924 const char *serialno)
4925{
Pekka Paalanene19970f2017-08-28 14:11:02 +03004926 if (str_null_eq(head->make, make) &&
4927 str_null_eq(head->model, model) &&
4928 str_null_eq(head->serial_number, serialno))
4929 return;
4930
Pekka Paalanen06f99ef2017-04-04 16:26:23 +03004931 free(head->make);
4932 free(head->model);
4933 free(head->serial_number);
4934
4935 head->make = make ? strdup(make) : NULL;
4936 head->model = model ? strdup(model) : NULL;
4937 head->serial_number = serialno ? strdup(serialno) : NULL;
Pekka Paalanene19970f2017-08-28 14:11:02 +03004938
4939 weston_head_set_device_changed(head);
Pekka Paalanen01f60212017-03-24 15:39:24 +02004940}
4941
Philipp Zabelc18ffd32018-08-30 17:38:03 +02004942/** Store display non-desktop status
4943 *
4944 * \param head The head to modify.
4945 * \param non_desktop Whether the head connects to a non-desktop display.
4946 *
4947 * \memberof weston_head
4948 * \internal
4949 */
4950WL_EXPORT void
4951weston_head_set_non_desktop(struct weston_head *head, bool non_desktop)
4952{
4953 if (head->non_desktop == non_desktop)
4954 return;
4955
4956 head->non_desktop = non_desktop;
4957
4958 weston_head_set_device_changed(head);
4959}
4960
Pekka Paalanen01f60212017-03-24 15:39:24 +02004961/** Store physical image size
4962 *
4963 * \param head The head to modify.
4964 * \param mm_width Image area width in millimeters.
4965 * \param mm_height Image area height in millimeters.
4966 *
Pekka Paalanene19970f2017-08-28 14:11:02 +03004967 * This may set the device_changed flag.
4968 *
Pekka Paalanen01f60212017-03-24 15:39:24 +02004969 * \memberof weston_head
4970 * \internal
4971 */
4972WL_EXPORT void
4973weston_head_set_physical_size(struct weston_head *head,
4974 int32_t mm_width, int32_t mm_height)
4975{
Pekka Paalanene19970f2017-08-28 14:11:02 +03004976 if (head->mm_width == mm_width &&
4977 head->mm_height == mm_height)
4978 return;
4979
Pekka Paalanen01f60212017-03-24 15:39:24 +02004980 head->mm_width = mm_width;
4981 head->mm_height = mm_height;
Pekka Paalanene19970f2017-08-28 14:11:02 +03004982
4983 weston_head_set_device_changed(head);
Pekka Paalanen01f60212017-03-24 15:39:24 +02004984}
4985
4986/** Store monitor sub-pixel layout
4987 *
4988 * \param head The head to modify.
4989 * \param sp Sub-pixel layout. The possible values are:
4990 * - WL_OUTPUT_SUBPIXEL_UNKNOWN,
4991 * - WL_OUTPUT_SUBPIXEL_NONE,
4992 * - WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB,
4993 * - WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR,
4994 * - WL_OUTPUT_SUBPIXEL_VERTICAL_RGB,
4995 * - WL_OUTPUT_SUBPIXEL_VERTICAL_BGR
4996 *
Pekka Paalanene19970f2017-08-28 14:11:02 +03004997 * This may set the device_changed flag.
4998 *
Pekka Paalanen01f60212017-03-24 15:39:24 +02004999 * \memberof weston_head
5000 * \internal
5001 */
5002WL_EXPORT void
5003weston_head_set_subpixel(struct weston_head *head,
5004 enum wl_output_subpixel sp)
5005{
Pekka Paalanene19970f2017-08-28 14:11:02 +03005006 if (head->subpixel == sp)
5007 return;
5008
Pekka Paalanen01f60212017-03-24 15:39:24 +02005009 head->subpixel = sp;
Pekka Paalanene19970f2017-08-28 14:11:02 +03005010
5011 weston_head_set_device_changed(head);
Pekka Paalanen01f60212017-03-24 15:39:24 +02005012}
5013
5014/** Mark the monitor as internal
5015 *
5016 * This is used for embedded screens, like laptop panels.
5017 *
5018 * \param head The head to mark as internal.
5019 *
5020 * By default a head is external. The type is often inferred from the physical
5021 * connector type.
5022 *
5023 * \memberof weston_head
5024 * \internal
5025 */
5026WL_EXPORT void
5027weston_head_set_internal(struct weston_head *head)
5028{
5029 head->connection_internal = true;
5030}
Pekka Paalanen9ffb2502017-03-27 15:14:32 +03005031
Pekka Paalanen7fe858b2017-08-14 15:45:14 +03005032/** Store connector status
5033 *
5034 * \param head The head to modify.
5035 * \param connected Whether the head is connected.
5036 *
5037 * Connectors are created as disconnected. This function can be used to
5038 * set the connector status.
5039 *
5040 * The status should be set to true when a physical connector is connected to
5041 * a video sink device like a monitor and to false when the connector is
5042 * disconnected. For nested backends, the connection status should reflect the
5043 * connection to the parent display server.
5044 *
Pekka Paalanen37e6c9e2017-08-15 13:00:02 +03005045 * When the connection status changes, it schedules a call to the heads_changed
Pekka Paalanene19970f2017-08-28 14:11:02 +03005046 * hook and sets the device_changed flag.
Pekka Paalanen37e6c9e2017-08-15 13:00:02 +03005047 *
5048 * \sa weston_compositor_set_heads_changed_cb
Pekka Paalanen7fe858b2017-08-14 15:45:14 +03005049 * \memberof weston_head
5050 * \internal
5051 */
5052WL_EXPORT void
5053weston_head_set_connection_status(struct weston_head *head, bool connected)
5054{
Pekka Paalanen37e6c9e2017-08-15 13:00:02 +03005055 if (head->connected == connected)
5056 return;
5057
Pekka Paalanen7fe858b2017-08-14 15:45:14 +03005058 head->connected = connected;
Pekka Paalanen37e6c9e2017-08-15 13:00:02 +03005059
Pekka Paalanene19970f2017-08-28 14:11:02 +03005060 weston_head_set_device_changed(head);
Pekka Paalanen7fe858b2017-08-14 15:45:14 +03005061}
5062
5063/** Is the head currently connected?
5064 *
5065 * \param head The head to query.
5066 * \return Connection status.
5067 *
5068 * Returns true if the head is physically connected to a monitor, or in
5069 * case of a nested backend returns true when there is a connection to the
5070 * parent display server.
5071 *
5072 * This is independent from the head being enabled.
5073 *
5074 * \sa weston_head_is_enabled
5075 * \memberof weston_head
5076 */
5077WL_EXPORT bool
5078weston_head_is_connected(struct weston_head *head)
5079{
5080 return head->connected;
5081}
5082
Pekka Paalanen8e552fd2018-02-15 15:18:20 +02005083/** Is the head currently enabled?
5084 *
5085 * \param head The head to query.
5086 * \return Video status.
5087 *
5088 * Returns true if the head is currently transmitting a video stream.
5089 *
5090 * This is independent of the head being connected.
5091 *
5092 * \sa weston_head_is_connected
5093 * \memberof weston_head
5094 */
5095WL_EXPORT bool
5096weston_head_is_enabled(struct weston_head *head)
5097{
5098 if (!head->output)
5099 return false;
5100
5101 return head->output->enabled;
5102}
5103
Pekka Paalanene19970f2017-08-28 14:11:02 +03005104/** Has the device information changed?
5105 *
5106 * \param head The head to query.
5107 * \return True if the device information has changed since last reset.
5108 *
5109 * The information about the connected display device, e.g. a monitor, may
5110 * change without being disconnected in between. Changing information
5111 * causes a call to the heads_changed hook.
5112 *
5113 * The information includes make, model, serial number, physical size,
5114 * and sub-pixel type. The connection status is also included.
5115 *
5116 * \sa weston_head_reset_device_changed, weston_compositor_set_heads_changed_cb
5117 * \memberof weston_head
5118 */
5119WL_EXPORT bool
5120weston_head_is_device_changed(struct weston_head *head)
5121{
5122 return head->device_changed;
5123}
5124
Philipp Zabelc18ffd32018-08-30 17:38:03 +02005125/** Does the head represent a non-desktop display?
5126 *
5127 * \param head The head to query.
5128 * \return True if the device is a non-desktop display.
5129 *
5130 * Non-desktop heads are not attached to outputs by default.
5131 * This stops weston from extending the desktop onto head mounted displays.
5132 *
5133 * \memberof weston_head
5134 */
5135WL_EXPORT bool
5136weston_head_is_non_desktop(struct weston_head *head)
5137{
5138 return head->non_desktop;
5139}
5140
Pekka Paalanene19970f2017-08-28 14:11:02 +03005141/** Acknowledge device information change
5142 *
5143 * \param head The head to acknowledge.
5144 *
5145 * Clears the device changed flag on this head. When a compositor has processed
5146 * device information, it should call this to be able to notice further
5147 * changes.
5148 *
5149 * \sa weston_head_is_device_changed
5150 * \memberof weston_head
5151 */
5152WL_EXPORT void
5153weston_head_reset_device_changed(struct weston_head *head)
5154{
5155 head->device_changed = false;
5156}
5157
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03005158/** Get the name of a head
5159 *
5160 * \param head The head to query.
5161 * \return The head's name, not NULL.
5162 *
5163 * The name depends on the backend. The DRM backend uses connector names,
5164 * other backends may use hardcoded names or user-given names.
5165 */
5166WL_EXPORT const char *
5167weston_head_get_name(struct weston_head *head)
5168{
5169 return head->name;
5170}
5171
5172/** Get the output the head is attached to
5173 *
5174 * \param head The head to query.
5175 * \return The output the head is attached to, or NULL if detached.
5176 */
5177WL_EXPORT struct weston_output *
5178weston_head_get_output(struct weston_head *head)
5179{
5180 return head->output;
5181}
5182
Pekka Paalanen2e1bedb2017-10-10 11:21:58 +03005183/** Add destroy callback for a head
5184 *
5185 * \param head The head to watch for.
5186 * \param listener The listener to add. The \c notify member must be set.
5187 *
5188 * Heads may get destroyed for various reasons by the backends. If a head is
5189 * attached to an output, the compositor should listen for head destruction
5190 * and reconfigure or destroy the output if necessary.
5191 *
5192 * The destroy callbacks will be called on weston_head destruction before any
5193 * automatic detaching from an associated weston_output and before any
5194 * weston_head information is lost.
5195 *
5196 * The \c data argument to the notify callback is the weston_head being
5197 * destroyed.
5198 */
5199WL_EXPORT void
5200weston_head_add_destroy_listener(struct weston_head *head,
5201 struct wl_listener *listener)
5202{
5203 wl_signal_add(&head->destroy_signal, listener);
5204}
5205
5206/** Look up destroy listener for a head
5207 *
5208 * \param head The head to query.
5209 * \param notify The notify function used used for the added destroy listener.
5210 * \return The listener, or NULL if not found.
5211 *
5212 * This looks up the previously added destroy listener struct based on the
5213 * notify function it has. The listener can be used to access user data
5214 * through \c container_of().
5215 *
5216 * \sa wl_signal_get()
5217 */
5218WL_EXPORT struct wl_listener *
5219weston_head_get_destroy_listener(struct weston_head *head,
5220 wl_notify_func_t notify)
5221{
5222 return wl_signal_get(&head->destroy_signal, notify);
5223}
5224
David Fort0de859e2016-05-27 23:22:57 +02005225/* Move other outputs when one is resized so the space remains contiguous. */
Zhang, Xiong Ya4b54c02013-12-13 22:10:51 +02005226static void
David Fort0de859e2016-05-27 23:22:57 +02005227weston_compositor_reflow_outputs(struct weston_compositor *compositor,
5228 struct weston_output *resized_output, int delta_width)
Zhang, Xiong Ya4b54c02013-12-13 22:10:51 +02005229{
5230 struct weston_output *output;
David Fort0de859e2016-05-27 23:22:57 +02005231 bool start_resizing = false;
5232
5233 if (!delta_width)
5234 return;
Zhang, Xiong Ya4b54c02013-12-13 22:10:51 +02005235
5236 wl_list_for_each(output, &compositor->output_list, link) {
David Fort0de859e2016-05-27 23:22:57 +02005237 if (output == resized_output) {
5238 start_resizing = true;
Zhang, Xiong Ya4b54c02013-12-13 22:10:51 +02005239 continue;
5240 }
5241
David Fort0de859e2016-05-27 23:22:57 +02005242 if (start_resizing) {
5243 weston_output_move(output, output->x + delta_width, output->y);
Zhang, Xiong Ya4b54c02013-12-13 22:10:51 +02005244 output->dirty = 1;
5245 }
5246 }
5247}
5248
Pekka Paalanend72bad22017-03-29 17:01:41 +03005249static void
Scott Moreauccbf29d2012-02-22 14:21:41 -07005250weston_output_update_matrix(struct weston_output *output)
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01005251{
Scott Moreau850ca422012-05-21 15:21:25 -06005252 float magnification;
Kristian Høgsberg31bd6c72011-02-13 13:00:51 -05005253
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05005254 weston_matrix_init(&output->matrix);
Jason Ekstrandfb23df72014-10-16 10:55:21 -05005255 weston_matrix_translate(&output->matrix, -output->x, -output->y, 0);
Scott Moreau1bad5db2012-08-18 01:04:05 -06005256
Scott Moreauccbf29d2012-02-22 14:21:41 -07005257 if (output->zoom.active) {
Scott Moreaue6603982012-06-11 13:07:51 -06005258 magnification = 1 / (1 - output->zoom.spring_z.current);
Jason Ekstranda7af7042013-10-12 22:38:11 -05005259 weston_output_update_zoom(output);
Neil Roberts1e40a7e2014-04-25 13:19:37 +01005260 weston_matrix_translate(&output->matrix, -output->zoom.trans_x,
Jason Ekstrandfb23df72014-10-16 10:55:21 -05005261 -output->zoom.trans_y, 0);
Neil Roberts1e40a7e2014-04-25 13:19:37 +01005262 weston_matrix_scale(&output->matrix, magnification,
5263 magnification, 1.0);
Scott Moreauccbf29d2012-02-22 14:21:41 -07005264 }
Kristian Høgsbergce5325d2010-06-14 11:54:00 -04005265
Jason Ekstrandfb23df72014-10-16 10:55:21 -05005266 switch (output->transform) {
5267 case WL_OUTPUT_TRANSFORM_FLIPPED:
5268 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
5269 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
5270 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
5271 weston_matrix_translate(&output->matrix, -output->width, 0, 0);
5272 weston_matrix_scale(&output->matrix, -1, 1, 1);
5273 break;
5274 }
5275
5276 switch (output->transform) {
5277 default:
5278 case WL_OUTPUT_TRANSFORM_NORMAL:
5279 case WL_OUTPUT_TRANSFORM_FLIPPED:
5280 break;
5281 case WL_OUTPUT_TRANSFORM_90:
5282 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
5283 weston_matrix_translate(&output->matrix, 0, -output->height, 0);
5284 weston_matrix_rotate_xy(&output->matrix, 0, 1);
5285 break;
5286 case WL_OUTPUT_TRANSFORM_180:
5287 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
5288 weston_matrix_translate(&output->matrix,
5289 -output->width, -output->height, 0);
5290 weston_matrix_rotate_xy(&output->matrix, -1, 0);
5291 break;
5292 case WL_OUTPUT_TRANSFORM_270:
5293 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
5294 weston_matrix_translate(&output->matrix, -output->width, 0, 0);
5295 weston_matrix_rotate_xy(&output->matrix, 0, -1);
5296 break;
5297 }
5298
5299 if (output->current_scale != 1)
5300 weston_matrix_scale(&output->matrix,
5301 output->current_scale,
5302 output->current_scale, 1);
Neil Roberts6c3b01f2014-05-06 19:04:15 +01005303
Scott Moreauccbf29d2012-02-22 14:21:41 -07005304 output->dirty = 0;
Derek Foremanc0023212015-03-24 11:36:13 -05005305
5306 weston_matrix_invert(&output->inverse_matrix, &output->matrix);
Scott Moreauccbf29d2012-02-22 14:21:41 -07005307}
5308
Scott Moreau1bad5db2012-08-18 01:04:05 -06005309static void
Alexander Larsson0b135062013-05-28 16:23:36 +02005310weston_output_transform_scale_init(struct weston_output *output, uint32_t transform, uint32_t scale)
Scott Moreau1bad5db2012-08-18 01:04:05 -06005311{
5312 output->transform = transform;
Pekka Paalanen59987fa2016-04-26 15:50:59 +03005313 output->native_scale = scale;
5314 output->current_scale = scale;
Scott Moreau1bad5db2012-08-18 01:04:05 -06005315
Pekka Paalanen59987fa2016-04-26 15:50:59 +03005316 convert_size_by_transform_scale(&output->width, &output->height,
5317 output->current_mode->width,
5318 output->current_mode->height,
5319 transform, scale);
Alexander Larsson4ea95522013-05-22 14:41:37 +02005320}
5321
Zhang, Xiong Yf3012412013-12-13 22:10:53 +02005322static void
5323weston_output_init_geometry(struct weston_output *output, int x, int y)
Scott Moreauccbf29d2012-02-22 14:21:41 -07005324{
5325 output->x = x;
5326 output->y = y;
5327
Pekka Paalanen4b582c72017-03-30 16:04:58 +03005328 pixman_region32_fini(&output->previous_damage);
Ander Conselvan de Oliveirab8fcca92012-11-16 17:23:52 +02005329 pixman_region32_init(&output->previous_damage);
Pekka Paalanen4b582c72017-03-30 16:04:58 +03005330
5331 pixman_region32_fini(&output->region);
Scott Moreauccbf29d2012-02-22 14:21:41 -07005332 pixman_region32_init_rect(&output->region, x, y,
Scott Moreau1bad5db2012-08-18 01:04:05 -06005333 output->width,
5334 output->height);
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01005335}
5336
Kristian Høgsberg1c562182011-05-02 22:09:20 -04005337WL_EXPORT void
Zhang, Xiong Yf3012412013-12-13 22:10:53 +02005338weston_output_move(struct weston_output *output, int x, int y)
5339{
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005340 struct weston_head *head;
Zhang, Xiong Yf3012412013-12-13 22:10:53 +02005341 struct wl_resource *resource;
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005342 int ver;
Zhang, Xiong Yf3012412013-12-13 22:10:53 +02005343
5344 output->move_x = x - output->x;
5345 output->move_y = y - output->y;
5346
5347 if (output->move_x == 0 && output->move_y == 0)
5348 return;
5349
Zhang, Xiong Yf3012412013-12-13 22:10:53 +02005350 weston_output_init_geometry(output, x, y);
5351
5352 output->dirty = 1;
5353
5354 /* Move views on this output. */
Ander Conselvan de Oliveiraa8a9baf2014-01-29 18:47:52 +02005355 wl_signal_emit(&output->compositor->output_moved_signal, output);
Zhang, Xiong Yf3012412013-12-13 22:10:53 +02005356
5357 /* Notify clients of the change for output position. */
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005358 wl_list_for_each(head, &output->head_list, output_link) {
5359 wl_resource_for_each(resource, &head->resource_list) {
5360 wl_output_send_geometry(resource,
5361 output->x,
5362 output->y,
5363 head->mm_width,
5364 head->mm_height,
5365 head->subpixel,
5366 head->make,
5367 head->model,
5368 output->transform);
Quanxian Wangb2c86362014-03-14 09:16:25 +08005369
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005370 ver = wl_resource_get_version(resource);
5371 if (ver >= WL_OUTPUT_DONE_SINCE_VERSION)
5372 wl_output_send_done(resource);
5373 }
Quanxian Wangb2c86362014-03-14 09:16:25 +08005374 }
Zhang, Xiong Yf3012412013-12-13 22:10:53 +02005375}
5376
Pekka Paalanenf0ca7962017-03-29 16:20:19 +03005377/** Signal that a pending output is taken into use.
5378 *
5379 * Removes the output from the pending list and adds it to the compositor's
5380 * list of enabled outputs. The output created signal is emitted.
Giulio Camuffob1147152015-05-06 21:41:57 +03005381 *
Pekka Paalanen2210ad02017-03-30 15:48:06 +03005382 * The output gets an internal ID assigned, and the wl_output global is
5383 * created.
Pekka Paalanen3d2d4972017-03-30 15:19:45 +03005384 *
Giulio Camuffob1147152015-05-06 21:41:57 +03005385 * \param compositor The compositor instance.
5386 * \param output The output to be added.
Pekka Paalanenee16ea92017-03-29 16:53:50 +03005387 *
5388 * \internal
Giulio Camuffob1147152015-05-06 21:41:57 +03005389 */
Pekka Paalanenf9681b52017-03-29 16:58:48 +03005390static void
Giulio Camuffob1147152015-05-06 21:41:57 +03005391weston_compositor_add_output(struct weston_compositor *compositor,
5392 struct weston_output *output)
5393{
Armin Krezoviće5403842016-08-05 15:28:29 +02005394 struct weston_view *view, *next;
Pekka Paalanen1b9bf592017-03-27 12:15:38 +03005395 struct weston_head *head;
Armin Krezoviće5403842016-08-05 15:28:29 +02005396
Pekka Paalanen7f340ff2017-03-30 14:56:22 +03005397 assert(!output->enabled);
Pekka Paalanen3d2d4972017-03-30 15:19:45 +03005398
5399 /* Verify we haven't reached the limit of 32 available output IDs */
5400 assert(ffs(~compositor->output_id_pool) > 0);
5401
5402 /* Invert the output id pool and look for the lowest numbered
5403 * switch (the least significant bit). Take that bit's position
5404 * as our ID, and mark it used in the compositor's output_id_pool.
5405 */
5406 output->id = ffs(~compositor->output_id_pool) - 1;
5407 compositor->output_id_pool |= 1u << output->id;
5408
Pekka Paalanenf0ca7962017-03-29 16:20:19 +03005409 wl_list_remove(&output->link);
Giulio Camuffob1147152015-05-06 21:41:57 +03005410 wl_list_insert(compositor->output_list.prev, &output->link);
Pekka Paalanen7f340ff2017-03-30 14:56:22 +03005411 output->enabled = true;
Pekka Paalanenf0ca7962017-03-29 16:20:19 +03005412
Pekka Paalanendcac3512017-12-08 14:13:34 +02005413 wl_list_for_each(head, &output->head_list, output_link)
5414 weston_head_add_global(head);
Pekka Paalanen2210ad02017-03-30 15:48:06 +03005415
Giulio Camuffob1147152015-05-06 21:41:57 +03005416 wl_signal_emit(&compositor->output_created_signal, output);
Armin Krezoviće5403842016-08-05 15:28:29 +02005417
5418 wl_list_for_each_safe(view, next, &compositor->view_list, link)
5419 weston_view_geometry_dirty(view);
Kristian Høgsbergce5325d2010-06-14 11:54:00 -04005420}
5421
Pekka Paalanenee16ea92017-03-29 16:53:50 +03005422/** Transform device coordinates into global coordinates
5423 *
5424 * \param device_x[in] X coordinate in device units.
5425 * \param device_y[in] Y coordinate in device units.
5426 * \param x[out] X coordinate in the global space.
5427 * \param y[out] Y coordinate in the global space.
5428 *
5429 * Transforms coordinates from the device coordinate space
5430 * (physical pixel units) to the global coordinate space (logical pixel units).
5431 * This takes into account output transform and scale.
5432 *
5433 * \memberof weston_output
5434 * \internal
5435 */
Kristian Høgsberg98c774f2013-07-22 14:33:42 -07005436WL_EXPORT void
5437weston_output_transform_coordinate(struct weston_output *output,
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02005438 double device_x, double device_y,
5439 double *x, double *y)
Kristian Høgsberg98c774f2013-07-22 14:33:42 -07005440{
Derek Foreman0f679412014-10-02 13:41:17 -05005441 struct weston_vector p = { {
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02005442 device_x,
5443 device_y,
Derek Foreman0f679412014-10-02 13:41:17 -05005444 0.0,
5445 1.0 } };
Kristian Høgsberg98c774f2013-07-22 14:33:42 -07005446
Derek Foreman67a18b92015-03-24 11:36:14 -05005447 weston_matrix_transform(&output->inverse_matrix, &p);
Kristian Høgsberg98c774f2013-07-22 14:33:42 -07005448
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02005449 *x = p.f[0] / p.f[3];
5450 *y = p.f[1] / p.f[3];
Kristian Høgsberg98c774f2013-07-22 14:33:42 -07005451}
5452
Pekka Paalanene6ac4fc2017-03-29 16:07:34 +03005453/** Removes output from compositor's list of enabled outputs
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005454 *
5455 * \param output The weston_output object that is being removed.
5456 *
Pekka Paalanene6ac4fc2017-03-29 16:07:34 +03005457 * The following happens:
5458 *
5459 * - The output assignments of all views in the current scenegraph are
5460 * recomputed.
5461 *
5462 * - Presentation feedback is discarded.
5463 *
5464 * - Compositor is notified that outputs were changed and
5465 * applies the necessary changes to re-layout outputs.
5466 *
Pekka Paalanenf0ca7962017-03-29 16:20:19 +03005467 * - The output is put back in the pending outputs list.
5468 *
Pekka Paalanene6ac4fc2017-03-29 16:07:34 +03005469 * - Signal is emitted to notify all users of the weston_output
5470 * object that the output is being destroyed.
5471 *
5472 * - wl_output protocol objects referencing this weston_output
Pekka Paalanen2210ad02017-03-30 15:48:06 +03005473 * are made inert, and the wl_output global is removed.
Pekka Paalanenee16ea92017-03-29 16:53:50 +03005474 *
Pekka Paalanen3d2d4972017-03-30 15:19:45 +03005475 * - The output's internal ID is released.
5476 *
Pekka Paalanenee16ea92017-03-29 16:53:50 +03005477 * \memberof weston_output
5478 * \internal
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005479 */
5480static void
5481weston_compositor_remove_output(struct weston_output *output)
5482{
Pekka Paalanenbccda712017-03-29 16:16:04 +03005483 struct weston_compositor *compositor = output->compositor;
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005484 struct weston_view *view;
Pekka Paalanen1b9bf592017-03-27 12:15:38 +03005485 struct weston_head *head;
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005486
5487 assert(output->destroying);
Pekka Paalanen7f340ff2017-03-30 14:56:22 +03005488 assert(output->enabled);
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005489
Pekka Paalanenbccda712017-03-29 16:16:04 +03005490 wl_list_for_each(view, &compositor->view_list, link) {
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005491 if (view->output_mask & (1u << output->id))
5492 weston_view_assign_output(view);
5493 }
5494
5495 weston_presentation_feedback_discard_list(&output->feedback_list);
5496
Pekka Paalanen9711fd92018-06-21 14:26:18 +03005497 weston_compositor_reflow_outputs(compositor, output, -output->width);
Pekka Paalanenf0ca7962017-03-29 16:20:19 +03005498
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005499 wl_list_remove(&output->link);
Pekka Paalanenf0ca7962017-03-29 16:20:19 +03005500 wl_list_insert(compositor->pending_output_list.prev, &output->link);
Pekka Paalanen7f340ff2017-03-30 14:56:22 +03005501 output->enabled = false;
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005502
Pekka Paalanenbccda712017-03-29 16:16:04 +03005503 wl_signal_emit(&compositor->output_destroyed_signal, output);
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005504 wl_signal_emit(&output->destroy_signal, output);
5505
Pekka Paalanend9dcc6d2017-12-04 15:28:13 +02005506 wl_list_for_each(head, &output->head_list, output_link)
5507 weston_head_remove_global(head);
Pekka Paalanen3d2d4972017-03-30 15:19:45 +03005508
5509 compositor->output_id_pool &= ~(1u << output->id);
5510 output->id = 0xffffffff; /* invalid */
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005511}
5512
5513/** Sets the output scale for a given output.
5514 *
5515 * \param output The weston_output object that the scale is set for.
5516 * \param scale Scale factor for the given output.
5517 *
5518 * It only supports setting scale for an output that
5519 * is not enabled and it can only be ran once.
Pekka Paalanenee16ea92017-03-29 16:53:50 +03005520 *
5521 * \memberof weston_output
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005522 */
5523WL_EXPORT void
5524weston_output_set_scale(struct weston_output *output,
5525 int32_t scale)
5526{
5527 /* We can only set scale on a disabled output */
5528 assert(!output->enabled);
5529
5530 /* We only want to set scale once */
5531 assert(!output->scale);
5532
5533 output->scale = scale;
5534}
5535
5536/** Sets the output transform for a given output.
5537 *
5538 * \param output The weston_output object that the transform is set for.
5539 * \param transform Transform value for the given output.
5540 *
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005541 * Refer to wl_output::transform section located at
5542 * https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_output
5543 * for list of values that can be passed to this function.
Pekka Paalanenee16ea92017-03-29 16:53:50 +03005544 *
5545 * \memberof weston_output
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005546 */
5547WL_EXPORT void
5548weston_output_set_transform(struct weston_output *output,
5549 uint32_t transform)
5550{
Ilia Bozhinov8564a0d2017-06-25 12:21:39 +00005551 struct weston_pointer_motion_event ev;
5552 struct wl_resource *resource;
5553 struct weston_seat *seat;
5554 pixman_region32_t old_region;
5555 int mid_x, mid_y;
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005556 struct weston_head *head;
5557 int ver;
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005558
Ilia Bozhinov8564a0d2017-06-25 12:21:39 +00005559 if (!output->enabled && output->transform == UINT32_MAX) {
5560 output->transform = transform;
5561 return;
5562 }
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005563
Ilia Bozhinov8564a0d2017-06-25 12:21:39 +00005564 weston_output_transform_scale_init(output, transform, output->scale);
5565
5566 pixman_region32_init(&old_region);
5567 pixman_region32_copy(&old_region, &output->region);
5568
Ilia Bozhinov8564a0d2017-06-25 12:21:39 +00005569 weston_output_init_geometry(output, output->x, output->y);
5570
5571 output->dirty = 1;
5572
5573 /* Notify clients of the change for output transform. */
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005574 wl_list_for_each(head, &output->head_list, output_link) {
5575 wl_resource_for_each(resource, &head->resource_list) {
5576 wl_output_send_geometry(resource,
5577 output->x,
5578 output->y,
5579 head->mm_width,
5580 head->mm_height,
5581 head->subpixel,
5582 head->make,
5583 head->model,
5584 output->transform);
Ilia Bozhinov8564a0d2017-06-25 12:21:39 +00005585
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005586 ver = wl_resource_get_version(resource);
5587 if (ver >= WL_OUTPUT_DONE_SINCE_VERSION)
5588 wl_output_send_done(resource);
5589 }
Ilia Bozhinov8564a0d2017-06-25 12:21:39 +00005590 }
5591
5592 /* we must ensure that pointers are inside output, otherwise they disappear */
5593 mid_x = output->x + output->width / 2;
5594 mid_y = output->y + output->height / 2;
5595
5596 ev.mask = WESTON_POINTER_MOTION_ABS;
5597 ev.x = wl_fixed_to_double(wl_fixed_from_int(mid_x));
5598 ev.y = wl_fixed_to_double(wl_fixed_from_int(mid_y));
5599
5600 wl_list_for_each(seat, &output->compositor->seat_list, link) {
5601 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
5602
5603 if (pointer && pixman_region32_contains_point(&old_region,
5604 wl_fixed_to_int(pointer->x),
5605 wl_fixed_to_int(pointer->y),
5606 NULL))
5607 weston_pointer_move(pointer, &ev);
5608 }
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005609}
5610
5611/** Initializes a weston_output object with enough data so
5612 ** an output can be configured.
5613 *
5614 * \param output The weston_output object to initialize
5615 * \param compositor The compositor instance.
Pekka Paalanen26ac2e12017-04-03 13:18:13 +03005616 * \param name Name for the output (the string is copied).
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005617 *
5618 * Sets initial values for fields that are expected to be
5619 * configured either by compositors or backends.
Pekka Paalanenee16ea92017-03-29 16:53:50 +03005620 *
Pekka Paalanen26ac2e12017-04-03 13:18:13 +03005621 * The name is used in logs, and can be used by compositors as a configuration
5622 * identifier.
5623 *
Pekka Paalanenee16ea92017-03-29 16:53:50 +03005624 * \memberof weston_output
5625 * \internal
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005626 */
5627WL_EXPORT void
Armin Krezović40087402016-09-30 14:11:12 +02005628weston_output_init(struct weston_output *output,
Pekka Paalanen26ac2e12017-04-03 13:18:13 +03005629 struct weston_compositor *compositor,
5630 const char *name)
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005631{
5632 output->compositor = compositor;
5633 output->destroying = 0;
Pekka Paalanen26ac2e12017-04-03 13:18:13 +03005634 output->name = strdup(name);
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005635 wl_list_init(&output->link);
Pekka Paalanen37b7c6e2017-11-07 10:15:01 +02005636 wl_signal_init(&output->user_destroy_signal);
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005637 output->enabled = false;
5638
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005639 wl_list_init(&output->head_list);
5640
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005641 /* Add some (in)sane defaults which can be used
5642 * for checking if an output was properly configured
5643 */
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005644 output->scale = 0;
5645 /* Can't use -1 on uint32_t and 0 is valid enum value */
5646 output->transform = UINT32_MAX;
Pekka Paalanen4b582c72017-03-30 16:04:58 +03005647
5648 pixman_region32_init(&output->previous_damage);
5649 pixman_region32_init(&output->region);
Pekka Paalanen42704142017-09-06 16:47:52 +03005650 wl_list_init(&output->mode_list);
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005651}
5652
5653/** Adds weston_output object to pending output list.
5654 *
5655 * \param output The weston_output object to add
5656 * \param compositor The compositor instance.
5657 *
Pekka Paalanenae6d35d2017-08-16 12:07:14 +03005658 * The opposite of this operation is built into weston_output_release().
Pekka Paalanenee16ea92017-03-29 16:53:50 +03005659 *
5660 * \memberof weston_output
5661 * \internal
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005662 */
5663WL_EXPORT void
5664weston_compositor_add_pending_output(struct weston_output *output,
5665 struct weston_compositor *compositor)
5666{
Pekka Paalanene952a012017-03-29 17:14:00 +03005667 assert(output->disable);
5668 assert(output->enable);
5669
Pekka Paalanenf0ca7962017-03-29 16:20:19 +03005670 wl_list_remove(&output->link);
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005671 wl_list_insert(compositor->pending_output_list.prev, &output->link);
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005672}
5673
Pekka Paalanen3e8f2012017-11-02 14:03:11 +02005674/** Create a string with the attached heads' names.
5675 *
5676 * The string must be free()'d.
5677 */
5678static char *
5679weston_output_create_heads_string(struct weston_output *output)
5680{
5681 FILE *fp;
5682 char *str = NULL;
5683 size_t size = 0;
5684 struct weston_head *head;
5685 const char *sep = "";
5686
5687 fp = open_memstream(&str, &size);
5688 if (!fp)
5689 return NULL;
5690
5691 wl_list_for_each(head, &output->head_list, output_link) {
5692 fprintf(fp, "%s%s", sep, head->name);
5693 sep = ", ";
5694 }
5695 fclose(fp);
5696
5697 return str;
5698}
5699
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005700/** Constructs a weston_output object that can be used by the compositor.
5701 *
Pekka Paalanencc201e42017-03-30 15:11:25 +03005702 * \param output The weston_output object that needs to be enabled. Must not
Pekka Paalanenddce54d2017-08-23 16:00:21 +03005703 * be enabled already. Must have at least one head attached.
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005704 *
5705 * Output coordinates are calculated and each new output is by default
5706 * assigned to the right of previous one.
5707 *
5708 * Sets up the transformation, zoom, and geometry of the output using
5709 * the properties that need to be configured by the compositor.
5710 *
5711 * Establishes a repaint timer for the output with the relevant display
5712 * object's event loop. See output_repaint_timer_handler().
5713 *
5714 * The output is assigned an ID. Weston can support up to 32 distinct
5715 * outputs, with IDs numbered from 0-31; the compositor's output_id_pool
5716 * is referred to and used to find the first available ID number, and
5717 * then this ID is marked as used in output_id_pool.
5718 *
5719 * The output is also assigned a Wayland global with the wl_output
5720 * external interface.
5721 *
5722 * Backend specific function is called to set up the output output.
5723 *
5724 * Output is added to the compositor's output list
5725 *
5726 * If the backend specific function fails, the weston_output object
5727 * is returned to a state it was before calling this function and
5728 * is added to the compositor's pending_output_list in case it needs
5729 * to be reconfigured or just so it can be destroyed at shutdown.
5730 *
5731 * 0 is returned on success, -1 on failure.
5732 */
5733WL_EXPORT int
5734weston_output_enable(struct weston_output *output)
5735{
Armin Krezović782f5df2016-09-30 14:11:11 +02005736 struct weston_compositor *c = output->compositor;
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005737 struct weston_output *iterator;
Pekka Paalanenec25b0a2017-08-24 16:08:49 +03005738 struct weston_head *head;
Pekka Paalanen3e8f2012017-11-02 14:03:11 +02005739 char *head_names;
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005740 int x = 0, y = 0;
5741
Pekka Paalanencc201e42017-03-30 15:11:25 +03005742 if (output->enabled) {
5743 weston_log("Error: attempt to enable an enabled output '%s'\n",
5744 output->name);
5745 return -1;
5746 }
5747
Pekka Paalanenddce54d2017-08-23 16:00:21 +03005748 if (wl_list_empty(&output->head_list)) {
5749 weston_log("Error: cannot enable output '%s' without heads.\n",
5750 output->name);
5751 return -1;
5752 }
5753
Pekka Paalanen586e1ac2017-09-14 16:17:59 +03005754 if (wl_list_empty(&output->mode_list) || !output->current_mode) {
5755 weston_log("Error: no video mode for output '%s'.\n",
5756 output->name);
5757 return -1;
5758 }
5759
Pekka Paalanenec25b0a2017-08-24 16:08:49 +03005760 wl_list_for_each(head, &output->head_list, output_link) {
5761 assert(head->make);
5762 assert(head->model);
5763 }
5764
Armin Krezović782f5df2016-09-30 14:11:11 +02005765 iterator = container_of(c->output_list.prev,
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005766 struct weston_output, link);
5767
Armin Krezović782f5df2016-09-30 14:11:11 +02005768 if (!wl_list_empty(&c->output_list))
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005769 x = iterator->x + iterator->width;
5770
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005771 /* Make sure the scale is set up */
5772 assert(output->scale);
5773
5774 /* Make sure we have a transform set */
5775 assert(output->transform != UINT32_MAX);
5776
Armin Krezović782f5df2016-09-30 14:11:11 +02005777 output->x = x;
5778 output->y = y;
5779 output->dirty = 1;
5780 output->original_scale = output->scale;
5781
5782 weston_output_transform_scale_init(output, output->transform, output->scale);
5783 weston_output_init_zoom(output);
5784
5785 weston_output_init_geometry(output, x, y);
5786 weston_output_damage(output);
5787
5788 wl_signal_init(&output->frame_signal);
5789 wl_signal_init(&output->destroy_signal);
5790 wl_list_init(&output->animation_list);
Armin Krezović782f5df2016-09-30 14:11:11 +02005791 wl_list_init(&output->feedback_list);
Armin Krezović782f5df2016-09-30 14:11:11 +02005792
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005793 /* Enable the output (set up the crtc or create a
5794 * window representing the output, set up the
5795 * renderer, etc)
5796 */
5797 if (output->enable(output) < 0) {
5798 weston_log("Enabling output \"%s\" failed.\n", output->name);
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005799 return -1;
5800 }
5801
5802 weston_compositor_add_output(output->compositor, output);
5803
Pekka Paalanen3e8f2012017-11-02 14:03:11 +02005804 head_names = weston_output_create_heads_string(output);
5805 weston_log("Output '%s' enabled with head(s) %s\n",
5806 output->name, head_names);
5807 free(head_names);
5808
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005809 return 0;
5810}
5811
5812/** Converts a weston_output object to a pending output state, so it
5813 ** can be configured again or destroyed.
5814 *
5815 * \param output The weston_output object that needs to be disabled.
5816 *
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005817 * Calls a backend specific function to disable an output, in case
5818 * such function exists.
5819 *
Pekka Paalanenc65df642017-03-29 15:45:46 +03005820 * The backend specific disable function may choose to postpone the disabling
5821 * by returning a negative value, in which case this function returns early.
5822 * In that case the backend will guarantee the output will be disabled soon
5823 * by the backend calling this function again. One must not attempt to re-enable
5824 * the output until that happens.
5825 *
5826 * Otherwise, if the output is being used by the compositor, it is removed
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005827 * from weston's output_list (see weston_compositor_remove_output())
5828 * and is returned to a state it was before weston_output_enable()
5829 * was ran (see weston_output_enable_undo()).
5830 *
Pekka Paalanenc65df642017-03-29 15:45:46 +03005831 * See weston_output_init() for more information on the
5832 * state output is returned to.
Pekka Paalanencc201e42017-03-30 15:11:25 +03005833 *
5834 * If the output has never been enabled yet, this function can still be
5835 * called to ensure that the output is actually turned off rather than left
5836 * in the state it was discovered in.
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005837 */
5838WL_EXPORT void
5839weston_output_disable(struct weston_output *output)
5840{
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005841 /* Should we rename this? */
5842 output->destroying = 1;
5843
Pekka Paalanenc65df642017-03-29 15:45:46 +03005844 /* Disable is called unconditionally also for not-enabled outputs,
5845 * because at compositor start-up, if there is an output that is
5846 * already on but the compositor wants to turn it off, we have to
5847 * forward the turn-off to the backend so it knows to do it.
5848 * The backend cannot initially turn off everything, because it
5849 * would cause unnecessary mode-sets for all outputs the compositor
5850 * wants to be on.
5851 */
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005852 if (output->disable(output) < 0)
5853 return;
5854
Pekka Paalanen4b582c72017-03-30 16:04:58 +03005855 if (output->enabled)
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005856 weston_compositor_remove_output(output);
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005857
5858 output->destroying = 0;
5859}
5860
Pekka Paalanen8a8dcac2017-08-17 17:29:36 +03005861/** Forces a synchronous call to heads_changed hook
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005862 *
5863 * \param compositor The compositor instance
Pekka Paalanen8a8dcac2017-08-17 17:29:36 +03005864 *
5865 * If there are new or changed heads, calls the heads_changed hook and
5866 * returns after the hook returns.
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005867 */
5868WL_EXPORT void
Pekka Paalanen8a8dcac2017-08-17 17:29:36 +03005869weston_compositor_flush_heads_changed(struct weston_compositor *compositor)
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005870{
Pekka Paalanen37e6c9e2017-08-15 13:00:02 +03005871 if (compositor->heads_changed_source) {
5872 wl_event_source_remove(compositor->heads_changed_source);
5873 weston_compositor_call_heads_changed(compositor);
5874 }
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005875}
5876
Pekka Paalanen37b7c6e2017-11-07 10:15:01 +02005877/** Add destroy callback for an output
5878 *
5879 * \param output The output to watch.
5880 * \param listener The listener to add. The \c notify member must be set.
5881 *
5882 * The listener callback will be called when user destroys an output. This
5883 * may be delayed by a backend in some cases. The main purpose of the
5884 * listener is to allow hooking up custom data to the output. The custom data
5885 * can be fetched via weston_output_get_destroy_listener() followed by
5886 * container_of().
5887 *
5888 * The \c data argument to the notify callback is the weston_output being
5889 * destroyed.
5890 *
5891 * @note This is for the final destruction of an output, not when it gets
5892 * disabled. If you want to keep track of enabled outputs, this is not it.
5893 */
5894WL_EXPORT void
5895weston_output_add_destroy_listener(struct weston_output *output,
5896 struct wl_listener *listener)
5897{
5898 wl_signal_add(&output->user_destroy_signal, listener);
5899}
5900
5901/** Look up destroy listener for an output
5902 *
5903 * \param output The output to query.
5904 * \param notify The notify function used used for the added destroy listener.
5905 * \return The listener, or NULL if not found.
5906 *
5907 * This looks up the previously added destroy listener struct based on the
5908 * notify function it has. The listener can be used to access user data
5909 * through \c container_of().
5910 *
5911 * \sa wl_signal_get() weston_output_add_destroy_listener()
5912 */
5913WL_EXPORT struct wl_listener *
5914weston_output_get_destroy_listener(struct weston_output *output,
5915 wl_notify_func_t notify)
5916{
5917 return wl_signal_get(&output->user_destroy_signal, notify);
5918}
5919
Pekka Paalanenee16ea92017-03-29 16:53:50 +03005920/** Uninitialize an output
5921 *
5922 * Removes the output from the list of enabled outputs if necessary, but
5923 * does not call the backend's output disable function. The output will no
5924 * longer be in the list of pending outputs either.
5925 *
5926 * All fields of weston_output become uninitialized, i.e. should not be used
5927 * anymore. The caller can free the memory after this.
5928 *
5929 * \memberof weston_output
5930 * \internal
5931 */
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005932WL_EXPORT void
Pekka Paalanenae6d35d2017-08-16 12:07:14 +03005933weston_output_release(struct weston_output *output)
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005934{
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005935 struct weston_head *head, *tmp;
5936
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005937 output->destroying = 1;
5938
Pekka Paalanen37b7c6e2017-11-07 10:15:01 +02005939 wl_signal_emit(&output->user_destroy_signal, output);
5940
Pekka Paalanendcbcfc72017-10-26 14:33:59 +03005941 if (output->idle_repaint_source)
5942 wl_event_source_remove(output->idle_repaint_source);
5943
Pekka Paalanen4b582c72017-03-30 16:04:58 +03005944 if (output->enabled)
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005945 weston_compositor_remove_output(output);
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005946
Pekka Paalanen4b582c72017-03-30 16:04:58 +03005947 pixman_region32_fini(&output->region);
5948 pixman_region32_fini(&output->previous_damage);
Pekka Paalanenf0ca7962017-03-29 16:20:19 +03005949 wl_list_remove(&output->link);
Pekka Paalanen7cdbabe2017-03-28 16:27:25 +03005950
5951 wl_list_for_each_safe(head, tmp, &output->head_list, output_link)
5952 weston_head_detach(head);
5953
Armin Krezovića01ab6d2016-09-30 14:11:02 +02005954 free(output->name);
5955}
5956
Pekka Paalanen1ae9d082017-11-02 14:11:53 +02005957/** Find an output by its given name
5958 *
5959 * \param compositor The compositor to search in.
5960 * \param name The output name to search for.
5961 * \return An existing output with the given name, or NULL if not found.
5962 *
5963 * \memberof weston_compositor
5964 */
5965WL_EXPORT struct weston_output *
5966weston_compositor_find_output_by_name(struct weston_compositor *compositor,
5967 const char *name)
5968{
5969 struct weston_output *output;
5970
5971 wl_list_for_each(output, &compositor->output_list, link)
5972 if (strcmp(output->name, name) == 0)
5973 return output;
5974
5975 wl_list_for_each(output, &compositor->pending_output_list, link)
5976 if (strcmp(output->name, name) == 0)
5977 return output;
5978
5979 return NULL;
5980}
5981
5982/** Create a named output
5983 *
5984 * \param compositor The compositor.
5985 * \param name The name for the output.
5986 * \return A new \c weston_output, or NULL on failure.
5987 *
5988 * This creates a new weston_output that starts with no heads attached.
5989 *
5990 * An output must be configured and it must have at least one head before
5991 * it can be enabled.
5992 *
5993 * \memberof weston_compositor
5994 */
5995WL_EXPORT struct weston_output *
5996weston_compositor_create_output(struct weston_compositor *compositor,
5997 const char *name)
5998{
5999 assert(compositor->backend->create_output);
6000
6001 if (weston_compositor_find_output_by_name(compositor, name)) {
6002 weston_log("Warning: attempted to create an output with a "
6003 "duplicate name '%s'.\n", name);
6004 return NULL;
6005 }
6006
6007 return compositor->backend->create_output(compositor, name);
6008}
6009
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03006010/** Create an output for an unused head
6011 *
6012 * \param compositor The compositor.
6013 * \param head The head to attach to the output.
6014 * \return A new \c weston_output, or NULL on failure.
6015 *
6016 * This creates a new weston_output that starts with the given head attached.
6017 * The output inherits the name of the head. The head must not be already
6018 * attached to another output.
6019 *
6020 * An output must be configured before it can be enabled.
6021 *
6022 * \memberof weston_compositor
6023 */
6024WL_EXPORT struct weston_output *
6025weston_compositor_create_output_with_head(struct weston_compositor *compositor,
6026 struct weston_head *head)
6027{
6028 struct weston_output *output;
6029
Pekka Paalanen1ae9d082017-11-02 14:11:53 +02006030 output = weston_compositor_create_output(compositor, head->name);
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03006031 if (!output)
6032 return NULL;
6033
6034 if (weston_output_attach_head(output, head) < 0) {
Pekka Paalanen42c0e142017-10-27 12:07:49 +03006035 weston_output_destroy(output);
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03006036 return NULL;
6037 }
6038
6039 return output;
6040}
6041
6042/** Destroy an output
6043 *
6044 * \param output The output to destroy.
6045 *
6046 * The heads attached to the given output are detached and become unused again.
6047 *
6048 * It is not necessary to explicitly destroy all outputs at compositor exit.
6049 * weston_compositor_destroy() will automatically destroy any remaining
6050 * outputs.
6051 *
6052 * \memberof weston_output
6053 */
6054WL_EXPORT void
6055weston_output_destroy(struct weston_output *output)
6056{
Pekka Paalanen992a8cb2017-08-16 10:39:17 +03006057 output->destroy(output);
6058}
6059
Pekka Paalanencf0a4762017-04-04 16:36:07 +03006060/** When you need a head...
6061 *
6062 * This function is a hack, used until all code has been converted to become
6063 * multi-head aware.
6064 *
6065 * \param output The weston_output whose head to get.
6066 * \return The first head in the output's list.
6067 */
6068WL_EXPORT struct weston_head *
6069weston_output_get_first_head(struct weston_output *output)
6070{
6071 if (wl_list_empty(&output->head_list))
6072 return NULL;
6073
6074 return container_of(output->head_list.next,
6075 struct weston_head, output_link);
6076}
6077
Benjamin Franzke315b3dc2011-03-08 11:32:57 +01006078static void
Pekka Paalanenb0420ae2014-01-08 15:39:17 +02006079destroy_viewport(struct wl_resource *resource)
Jonny Lamb8ae35902013-11-26 18:19:45 +01006080{
Jonny Lamb74130762013-11-26 18:19:46 +01006081 struct weston_surface *surface =
6082 wl_resource_get_user_data(resource);
6083
Pekka Paalanen4826f872016-04-22 14:14:38 +03006084 if (!surface)
6085 return;
6086
Pekka Paalanenb0420ae2014-01-08 15:39:17 +02006087 surface->viewport_resource = NULL;
Pekka Paalanenf0cad482014-03-14 14:38:16 +02006088 surface->pending.buffer_viewport.buffer.src_width =
6089 wl_fixed_from_int(-1);
6090 surface->pending.buffer_viewport.surface.width = -1;
George Kiagiadakis8f9e87f2014-06-13 18:14:20 +02006091 surface->pending.buffer_viewport.changed = 1;
Jonny Lamb8ae35902013-11-26 18:19:45 +01006092}
6093
6094static void
Pekka Paalanenb0420ae2014-01-08 15:39:17 +02006095viewport_destroy(struct wl_client *client,
6096 struct wl_resource *resource)
Jonny Lamb8ae35902013-11-26 18:19:45 +01006097{
6098 wl_resource_destroy(resource);
6099}
6100
6101static void
Pekka Paalanen0b4c5352014-03-14 14:38:17 +02006102viewport_set_source(struct wl_client *client,
6103 struct wl_resource *resource,
6104 wl_fixed_t src_x,
6105 wl_fixed_t src_y,
6106 wl_fixed_t src_width,
6107 wl_fixed_t src_height)
6108{
6109 struct weston_surface *surface =
6110 wl_resource_get_user_data(resource);
6111
Pekka Paalanen4826f872016-04-22 14:14:38 +03006112 if (!surface) {
6113 wl_resource_post_error(resource,
6114 WP_VIEWPORT_ERROR_NO_SURFACE,
6115 "wl_surface for this viewport is no longer exists");
6116 return;
6117 }
6118
6119 assert(surface->viewport_resource == resource);
Pekka Paalanen201769a2016-04-26 14:42:11 +03006120 assert(surface->resource);
Pekka Paalanen0b4c5352014-03-14 14:38:17 +02006121
Pekka Paalanen2c8b5f52014-04-04 14:22:12 +03006122 if (src_width == wl_fixed_from_int(-1) &&
Pekka Paalanen201769a2016-04-26 14:42:11 +03006123 src_height == wl_fixed_from_int(-1) &&
6124 src_x == wl_fixed_from_int(-1) &&
6125 src_y == wl_fixed_from_int(-1)) {
6126 /* unset source rect */
Pekka Paalanen0b4c5352014-03-14 14:38:17 +02006127 surface->pending.buffer_viewport.buffer.src_width =
6128 wl_fixed_from_int(-1);
George Kiagiadakis8f9e87f2014-06-13 18:14:20 +02006129 surface->pending.buffer_viewport.changed = 1;
Pekka Paalanen2c8b5f52014-04-04 14:22:12 +03006130 return;
Pekka Paalanen0b4c5352014-03-14 14:38:17 +02006131 }
Pekka Paalanen2c8b5f52014-04-04 14:22:12 +03006132
Pekka Paalanen201769a2016-04-26 14:42:11 +03006133 if (src_width <= 0 || src_height <= 0 || src_x < 0 || src_y < 0) {
Pekka Paalanen2c8b5f52014-04-04 14:22:12 +03006134 wl_resource_post_error(resource,
Pekka Paalanene95ad5c2016-04-15 14:47:08 +03006135 WP_VIEWPORT_ERROR_BAD_VALUE,
Pekka Paalanen201769a2016-04-26 14:42:11 +03006136 "wl_surface@%d viewport source "
6137 "w=%f <= 0, h=%f <= 0, x=%f < 0, or y=%f < 0",
6138 wl_resource_get_id(surface->resource),
Pekka Paalanen2c8b5f52014-04-04 14:22:12 +03006139 wl_fixed_to_double(src_width),
Pekka Paalanen201769a2016-04-26 14:42:11 +03006140 wl_fixed_to_double(src_height),
6141 wl_fixed_to_double(src_x),
6142 wl_fixed_to_double(src_y));
Pekka Paalanen2c8b5f52014-04-04 14:22:12 +03006143 return;
6144 }
6145
6146 surface->pending.buffer_viewport.buffer.src_x = src_x;
6147 surface->pending.buffer_viewport.buffer.src_y = src_y;
6148 surface->pending.buffer_viewport.buffer.src_width = src_width;
6149 surface->pending.buffer_viewport.buffer.src_height = src_height;
George Kiagiadakis8f9e87f2014-06-13 18:14:20 +02006150 surface->pending.buffer_viewport.changed = 1;
Pekka Paalanen0b4c5352014-03-14 14:38:17 +02006151}
6152
6153static void
6154viewport_set_destination(struct wl_client *client,
6155 struct wl_resource *resource,
6156 int32_t dst_width,
6157 int32_t dst_height)
6158{
6159 struct weston_surface *surface =
6160 wl_resource_get_user_data(resource);
6161
Pekka Paalanen4826f872016-04-22 14:14:38 +03006162 if (!surface) {
6163 wl_resource_post_error(resource,
6164 WP_VIEWPORT_ERROR_NO_SURFACE,
6165 "wl_surface for this viewport no longer exists");
6166 return;
6167 }
6168
6169 assert(surface->viewport_resource == resource);
Pekka Paalanen0b4c5352014-03-14 14:38:17 +02006170
Pekka Paalanen2c8b5f52014-04-04 14:22:12 +03006171 if (dst_width == -1 && dst_height == -1) {
6172 /* unset destination size */
Pekka Paalanen0b4c5352014-03-14 14:38:17 +02006173 surface->pending.buffer_viewport.surface.width = -1;
George Kiagiadakis8f9e87f2014-06-13 18:14:20 +02006174 surface->pending.buffer_viewport.changed = 1;
Pekka Paalanen2c8b5f52014-04-04 14:22:12 +03006175 return;
Pekka Paalanen0b4c5352014-03-14 14:38:17 +02006176 }
Pekka Paalanen2c8b5f52014-04-04 14:22:12 +03006177
6178 if (dst_width <= 0 || dst_height <= 0) {
6179 wl_resource_post_error(resource,
Pekka Paalanene95ad5c2016-04-15 14:47:08 +03006180 WP_VIEWPORT_ERROR_BAD_VALUE,
Pekka Paalanen2c8b5f52014-04-04 14:22:12 +03006181 "destination size must be positive (%dx%d)",
6182 dst_width, dst_height);
6183 return;
6184 }
6185
6186 surface->pending.buffer_viewport.surface.width = dst_width;
6187 surface->pending.buffer_viewport.surface.height = dst_height;
George Kiagiadakis8f9e87f2014-06-13 18:14:20 +02006188 surface->pending.buffer_viewport.changed = 1;
Pekka Paalanen0b4c5352014-03-14 14:38:17 +02006189}
6190
Pekka Paalanene95ad5c2016-04-15 14:47:08 +03006191static const struct wp_viewport_interface viewport_interface = {
Pekka Paalanenb0420ae2014-01-08 15:39:17 +02006192 viewport_destroy,
Pekka Paalanen0b4c5352014-03-14 14:38:17 +02006193 viewport_set_source,
6194 viewport_set_destination
Jonny Lamb8ae35902013-11-26 18:19:45 +01006195};
6196
6197static void
Pekka Paalanen9c5a0d92016-04-15 16:42:49 +03006198viewporter_destroy(struct wl_client *client,
6199 struct wl_resource *resource)
Jonny Lamb8ae35902013-11-26 18:19:45 +01006200{
6201 wl_resource_destroy(resource);
6202}
6203
6204static void
Pekka Paalanen9c5a0d92016-04-15 16:42:49 +03006205viewporter_get_viewport(struct wl_client *client,
6206 struct wl_resource *viewporter,
6207 uint32_t id,
6208 struct wl_resource *surface_resource)
Jonny Lamb8ae35902013-11-26 18:19:45 +01006209{
Pekka Paalanen9c5a0d92016-04-15 16:42:49 +03006210 int version = wl_resource_get_version(viewporter);
Pekka Paalanen0b4c5352014-03-14 14:38:17 +02006211 struct weston_surface *surface =
6212 wl_resource_get_user_data(surface_resource);
Jonny Lamb8ae35902013-11-26 18:19:45 +01006213 struct wl_resource *resource;
6214
Pekka Paalanenb0420ae2014-01-08 15:39:17 +02006215 if (surface->viewport_resource) {
Pekka Paalanen9c5a0d92016-04-15 16:42:49 +03006216 wl_resource_post_error(viewporter,
Pekka Paalanene95ad5c2016-04-15 14:47:08 +03006217 WP_VIEWPORTER_ERROR_VIEWPORT_EXISTS,
Pekka Paalanenb0420ae2014-01-08 15:39:17 +02006218 "a viewport for that surface already exists");
Jonny Lamb74130762013-11-26 18:19:46 +01006219 return;
6220 }
6221
Pekka Paalanene95ad5c2016-04-15 14:47:08 +03006222 resource = wl_resource_create(client, &wp_viewport_interface,
Pekka Paalanen0b4c5352014-03-14 14:38:17 +02006223 version, id);
Jonny Lamb8ae35902013-11-26 18:19:45 +01006224 if (resource == NULL) {
6225 wl_client_post_no_memory(client);
6226 return;
6227 }
6228
Pekka Paalanenb0420ae2014-01-08 15:39:17 +02006229 wl_resource_set_implementation(resource, &viewport_interface,
6230 surface, destroy_viewport);
Jonny Lamb74130762013-11-26 18:19:46 +01006231
Pekka Paalanenb0420ae2014-01-08 15:39:17 +02006232 surface->viewport_resource = resource;
Jonny Lamb8ae35902013-11-26 18:19:45 +01006233}
6234
Pekka Paalanen9c5a0d92016-04-15 16:42:49 +03006235static const struct wp_viewporter_interface viewporter_interface = {
6236 viewporter_destroy,
6237 viewporter_get_viewport
Jonny Lamb8ae35902013-11-26 18:19:45 +01006238};
6239
6240static void
Pekka Paalanen9c5a0d92016-04-15 16:42:49 +03006241bind_viewporter(struct wl_client *client,
6242 void *data, uint32_t version, uint32_t id)
Jonny Lamb8ae35902013-11-26 18:19:45 +01006243{
6244 struct wl_resource *resource;
6245
Pekka Paalanene95ad5c2016-04-15 14:47:08 +03006246 resource = wl_resource_create(client, &wp_viewporter_interface,
Derek Foreman1909c102015-11-26 14:17:47 -06006247 version, id);
Jonny Lamb8ae35902013-11-26 18:19:45 +01006248 if (resource == NULL) {
6249 wl_client_post_no_memory(client);
6250 return;
6251 }
6252
Pekka Paalanen9c5a0d92016-04-15 16:42:49 +03006253 wl_resource_set_implementation(resource, &viewporter_interface,
Jonny Lamb8ae35902013-11-26 18:19:45 +01006254 NULL, NULL);
6255}
6256
6257static void
Pekka Paalanen133e4392014-09-23 22:08:46 -04006258destroy_presentation_feedback(struct wl_resource *feedback_resource)
6259{
6260 struct weston_presentation_feedback *feedback;
6261
6262 feedback = wl_resource_get_user_data(feedback_resource);
6263
6264 wl_list_remove(&feedback->link);
6265 free(feedback);
6266}
6267
6268static void
Pekka Paalanen31f7d782014-09-23 22:08:43 -04006269presentation_destroy(struct wl_client *client, struct wl_resource *resource)
6270{
6271 wl_resource_destroy(resource);
6272}
6273
6274static void
6275presentation_feedback(struct wl_client *client,
Pekka Paalanen133e4392014-09-23 22:08:46 -04006276 struct wl_resource *presentation_resource,
6277 struct wl_resource *surface_resource,
Pekka Paalanen31f7d782014-09-23 22:08:43 -04006278 uint32_t callback)
6279{
Pekka Paalanen133e4392014-09-23 22:08:46 -04006280 struct weston_surface *surface;
6281 struct weston_presentation_feedback *feedback;
6282
6283 surface = wl_resource_get_user_data(surface_resource);
6284
Bryce Harringtonde16d892014-11-20 22:21:57 -08006285 feedback = zalloc(sizeof *feedback);
6286 if (feedback == NULL)
Pekka Paalanen133e4392014-09-23 22:08:46 -04006287 goto err_calloc;
6288
6289 feedback->resource = wl_resource_create(client,
Pekka Paalanenb00c79b2016-02-18 16:53:27 +02006290 &wp_presentation_feedback_interface,
Pekka Paalanen133e4392014-09-23 22:08:46 -04006291 1, callback);
6292 if (!feedback->resource)
6293 goto err_create;
6294
6295 wl_resource_set_implementation(feedback->resource, NULL, feedback,
6296 destroy_presentation_feedback);
6297
6298 wl_list_insert(&surface->pending.feedback_list, &feedback->link);
6299
6300 return;
6301
6302err_create:
6303 free(feedback);
6304
6305err_calloc:
6306 wl_client_post_no_memory(client);
Pekka Paalanen31f7d782014-09-23 22:08:43 -04006307}
6308
Pekka Paalanenb00c79b2016-02-18 16:53:27 +02006309static const struct wp_presentation_interface presentation_implementation = {
Pekka Paalanen31f7d782014-09-23 22:08:43 -04006310 presentation_destroy,
6311 presentation_feedback
6312};
6313
6314static void
6315bind_presentation(struct wl_client *client,
6316 void *data, uint32_t version, uint32_t id)
6317{
6318 struct weston_compositor *compositor = data;
6319 struct wl_resource *resource;
6320
Pekka Paalanenb00c79b2016-02-18 16:53:27 +02006321 resource = wl_resource_create(client, &wp_presentation_interface,
Derek Foreman1909c102015-11-26 14:17:47 -06006322 version, id);
Pekka Paalanen31f7d782014-09-23 22:08:43 -04006323 if (resource == NULL) {
6324 wl_client_post_no_memory(client);
6325 return;
6326 }
6327
6328 wl_resource_set_implementation(resource, &presentation_implementation,
6329 compositor, NULL);
Pekka Paalanenb00c79b2016-02-18 16:53:27 +02006330 wp_presentation_send_clock_id(resource, compositor->presentation_clock);
Pekka Paalanen31f7d782014-09-23 22:08:43 -04006331}
6332
6333static void
Kristian Høgsberga8873122011-11-23 10:39:34 -05006334compositor_bind(struct wl_client *client,
6335 void *data, uint32_t version, uint32_t id)
6336{
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05006337 struct weston_compositor *compositor = data;
Jason Ekstranda85118c2013-06-27 20:17:02 -05006338 struct wl_resource *resource;
Kristian Høgsberga8873122011-11-23 10:39:34 -05006339
Jason Ekstranda85118c2013-06-27 20:17:02 -05006340 resource = wl_resource_create(client, &wl_compositor_interface,
Derek Foreman1909c102015-11-26 14:17:47 -06006341 version, id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07006342 if (resource == NULL) {
6343 wl_client_post_no_memory(client);
6344 return;
6345 }
6346
6347 wl_resource_set_implementation(resource, &compositor_interface,
6348 compositor, NULL);
Kristian Høgsberga8873122011-11-23 10:39:34 -05006349}
6350
Kristian Høgsberg1c562182011-05-02 22:09:20 -04006351WL_EXPORT int
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +02006352weston_environment_get_fd(const char *env)
6353{
Bryce Harrington25a2bdd2016-08-03 17:40:52 -07006354 char *e;
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +02006355 int fd, flags;
6356
6357 e = getenv(env);
Bryce Harrington25a2bdd2016-08-03 17:40:52 -07006358 if (!e || !safe_strtoint(e, &fd))
Ander Conselvan de Oliveiracbdebc22013-02-21 18:35:16 +02006359 return -1;
6360
6361 flags = fcntl(fd, F_GETFD);
6362 if (flags == -1)
6363 return -1;
6364
6365 fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
6366 unsetenv(env);
6367
6368 return fd;
6369}
6370
Pekka Paalanenb5026542014-11-12 15:09:24 +02006371static void
Alexandros Frantzis47e79c82017-11-16 18:20:57 +02006372timeline_key_binding_handler(struct weston_keyboard *keyboard,
6373 const struct timespec *time, uint32_t key,
6374 void *data)
Pekka Paalanenb5026542014-11-12 15:09:24 +02006375{
6376 struct weston_compositor *compositor = data;
6377
6378 if (weston_timeline_enabled_)
6379 weston_timeline_close();
6380 else
6381 weston_timeline_open(compositor);
6382}
6383
Daniel Stonece62cb32018-07-20 09:46:24 +01006384static const char *
6385output_repaint_status_text(struct weston_output *output)
6386{
6387 switch (output->repaint_status) {
6388 case REPAINT_NOT_SCHEDULED:
6389 return "no repaint";
6390 case REPAINT_BEGIN_FROM_IDLE:
6391 return "start_repaint_loop scheduled";
6392 case REPAINT_SCHEDULED:
6393 return "repaint scheduled";
6394 case REPAINT_AWAITING_COMPLETION:
6395 return "awaiting completion";
6396 }
6397
6398 assert(!"output_repaint_status_text missing enum");
6399 return NULL;
6400}
6401
6402static void
6403debug_scene_view_print_buffer(FILE *fp, struct weston_view *view)
6404{
6405 struct weston_buffer *buffer = view->surface->buffer_ref.buffer;
6406 struct wl_shm_buffer *shm;
6407 struct linux_dmabuf_buffer *dmabuf;
6408
6409 if (!buffer) {
6410 fprintf(fp, "\t\t[buffer not available]\n");
6411 return;
6412 }
6413
6414 shm = wl_shm_buffer_get(buffer->resource);
6415 if (shm) {
6416 fprintf(fp, "\t\tSHM buffer\n");
6417 fprintf(fp, "\t\t\tformat: 0x%lx\n",
6418 (unsigned long) wl_shm_buffer_get_format(shm));
6419 return;
6420 }
6421
6422 dmabuf = linux_dmabuf_buffer_get(buffer->resource);
6423 if (dmabuf) {
6424 fprintf(fp, "\t\tdmabuf buffer\n");
6425 fprintf(fp, "\t\t\tformat: 0x%lx\n",
6426 (unsigned long) dmabuf->attributes.format);
6427 fprintf(fp, "\t\t\tmodifier: 0x%llx\n",
6428 (unsigned long long) dmabuf->attributes.modifier[0]);
6429 return;
6430 }
6431
6432 fprintf(fp, "\t\tEGL buffer");
6433}
6434
6435static void
6436debug_scene_view_print(FILE *fp, struct weston_view *view, int view_idx)
6437{
6438 struct weston_compositor *ec = view->surface->compositor;
6439 struct weston_output *output;
6440 char desc[512];
6441 pixman_box32_t *box;
6442 uint32_t surface_id = 0;
6443 pid_t pid = 0;
6444
6445 if (view->surface->resource) {
6446 struct wl_resource *resource = view->surface->resource;
6447 wl_client_get_credentials(wl_resource_get_client(resource),
6448 &pid, NULL, NULL);
6449 surface_id = wl_resource_get_id(view->surface->resource);
6450 }
6451
6452 if (!view->surface->get_label ||
6453 view->surface->get_label(view->surface, desc, sizeof(desc)) < 0) {
6454 strcpy(desc, "[no description available]");
6455 }
6456 fprintf(fp, "\tView %d (role %s, PID %d, surface ID %u, %s, %p):\n",
6457 view_idx, view->surface->role_name, pid, surface_id,
6458 desc, view);
6459
6460 box = pixman_region32_extents(&view->transform.boundingbox);
6461 fprintf(fp, "\t\tposition: (%d, %d) -> (%d, %d)\n",
6462 box->x1, box->y1, box->x2, box->y2);
6463 box = pixman_region32_extents(&view->transform.opaque);
6464
6465 if (pixman_region32_equal(&view->transform.opaque,
6466 &view->transform.boundingbox)) {
6467 fprintf(fp, "\t\t[fully opaque]\n");
6468 } else if (!pixman_region32_not_empty(&view->transform.opaque)) {
6469 fprintf(fp, "\t\t[not opaque]\n");
6470 } else {
6471 fprintf(fp, "\t\t[opaque: (%d, %d) -> (%d, %d)]\n",
6472 box->x1, box->y1, box->x2, box->y2);
6473 }
6474
6475 if (view->alpha < 1.0)
6476 fprintf(fp, "\t\talpha: %f\n", view->alpha);
6477
6478 if (view->output_mask != 0) {
6479 bool first_output = true;
6480 fprintf(fp, "\t\toutputs: ");
6481 wl_list_for_each(output, &ec->output_list, link) {
6482 if (!(view->output_mask & (1 << output->id)))
6483 continue;
6484 fprintf(fp, "%s%d (%s)%s",
6485 (first_output) ? "" : ", ",
6486 output->id, output->name,
6487 (view->output == output) ? " (primary)" : "");
6488 first_output = false;
6489 }
6490 } else {
6491 fprintf(fp, "\t\t[no outputs]");
6492 }
6493
6494 fprintf(fp, "\n");
6495
6496 debug_scene_view_print_buffer(fp, view);
6497}
6498
6499/**
6500 * Output information on how libweston is currently composing the scene
6501 * graph.
6502 */
6503WL_EXPORT char *
6504weston_compositor_print_scene_graph(struct weston_compositor *ec)
6505{
6506 struct weston_output *output;
6507 struct weston_layer *layer;
6508 struct timespec now;
6509 int layer_idx = 0;
6510 FILE *fp;
6511 char *ret;
6512 size_t len;
6513 int err;
6514
6515 fp = open_memstream(&ret, &len);
6516 assert(fp);
6517
6518 weston_compositor_read_presentation_clock(ec, &now);
6519 fprintf(fp, "Weston scene graph at %ld.%09ld:\n\n",
6520 now.tv_sec, now.tv_nsec);
6521
6522 wl_list_for_each(output, &ec->output_list, link) {
6523 struct weston_head *head;
6524 int head_idx = 0;
6525
6526 fprintf(fp, "Output %d (%s):\n", output->id, output->name);
6527 assert(output->enabled);
6528
6529 fprintf(fp, "\tposition: (%d, %d) -> (%d, %d)\n",
6530 output->x, output->y,
6531 output->x + output->width,
6532 output->y + output->height);
6533 fprintf(fp, "\tmode: %dx%d@%.3fHz\n",
6534 output->current_mode->width,
6535 output->current_mode->height,
6536 output->current_mode->refresh / 1000.0);
6537 fprintf(fp, "\tscale: %d\n", output->scale);
6538
6539 fprintf(fp, "\trepaint status: %s\n",
6540 output_repaint_status_text(output));
6541 if (output->repaint_status == REPAINT_SCHEDULED)
6542 fprintf(fp, "\tnext repaint: %ld.%09ld\n",
6543 output->next_repaint.tv_sec,
6544 output->next_repaint.tv_nsec);
6545
6546 wl_list_for_each(head, &output->head_list, output_link) {
6547 fprintf(fp, "\tHead %d (%s): %sconnected\n",
6548 head_idx++, head->name,
6549 (head->connected) ? "" : "not ");
6550 }
6551 }
6552
6553 fprintf(fp, "\n");
6554
6555 wl_list_for_each(layer, &ec->layer_list, link) {
6556 struct weston_view *view;
6557 int view_idx = 0;
6558
6559 fprintf(fp, "Layer %d (pos 0x%lx):\n", layer_idx++,
6560 (unsigned long) layer->position);
6561
6562 if (!weston_layer_mask_is_infinite(layer)) {
6563 fprintf(fp, "\t[mask: (%d, %d) -> (%d,%d)]\n\n",
6564 layer->mask.x1, layer->mask.y1,
6565 layer->mask.x2, layer->mask.y2);
6566 }
6567
6568 wl_list_for_each(view, &layer->view_list.link, layer_link.link)
6569 debug_scene_view_print(fp, view, view_idx++);
6570
6571 if (wl_list_empty(&layer->view_list.link))
6572 fprintf(fp, "\t[no views]\n");
6573
6574 fprintf(fp, "\n");
6575 }
6576
6577 err = fclose(fp);
6578 assert(err == 0);
6579
6580 return ret;
6581}
6582
6583/**
6584 * Called when the 'scene-graph' debug scope is bound by a client. This
6585 * one-shot weston-debug scope prints the current scene graph when bound,
6586 * and then terminates the stream.
6587 */
6588static void
6589debug_scene_graph_cb(struct weston_debug_stream *stream, void *data)
6590{
6591 struct weston_compositor *ec = data;
6592 char *str = weston_compositor_print_scene_graph(ec);
6593
6594 weston_debug_stream_printf(stream, "%s", str);
6595 free(str);
6596 weston_debug_stream_complete(stream);
6597}
6598
Giulio Camuffo459137b2014-10-11 23:56:24 +03006599/** Create the compositor.
6600 *
6601 * This functions creates and initializes a compositor instance.
6602 *
6603 * \param display The Wayland display to be used.
6604 * \param user_data A pointer to an object that can later be retrieved
6605 * using the \ref weston_compositor_get_user_data function.
6606 * \return The compositor instance on success or NULL on failure.
6607 */
6608WL_EXPORT struct weston_compositor *
6609weston_compositor_create(struct wl_display *display, void *user_data)
Kristian Høgsbergce5325d2010-06-14 11:54:00 -04006610{
Giulio Camuffo459137b2014-10-11 23:56:24 +03006611 struct weston_compositor *ec;
Kristian Høgsbergfbdbbdc2008-11-28 17:06:06 -05006612 struct wl_event_loop *loop;
Ossama Othmana50e6e42013-05-14 09:48:26 -07006613
Giulio Camuffo459137b2014-10-11 23:56:24 +03006614 ec = zalloc(sizeof *ec);
6615 if (!ec)
6616 return NULL;
6617
6618 ec->wl_display = display;
6619 ec->user_data = user_data;
Kristian Høgsberg02e79dc2012-04-12 09:55:26 -04006620 wl_signal_init(&ec->destroy_signal);
Kristian Høgsbergf03a04a2014-04-06 22:04:50 -07006621 wl_signal_init(&ec->create_surface_signal);
Kristian Høgsberg02e79dc2012-04-12 09:55:26 -04006622 wl_signal_init(&ec->activate_signal);
Tiago Vignattifb2adba2013-06-12 15:43:21 -03006623 wl_signal_init(&ec->transform_signal);
Tiago Vignatti1d01b012012-09-27 17:48:36 +03006624 wl_signal_init(&ec->kill_signal);
Ander Conselvan de Oliveiraa4575632013-02-21 18:35:23 +02006625 wl_signal_init(&ec->idle_signal);
6626 wl_signal_init(&ec->wake_signal);
Jan Arne Petersen42feced2012-06-21 21:52:17 +02006627 wl_signal_init(&ec->show_input_panel_signal);
6628 wl_signal_init(&ec->hide_input_panel_signal);
Jan Arne Petersen14da96b2013-04-18 16:47:28 +02006629 wl_signal_init(&ec->update_input_panel_signal);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01006630 wl_signal_init(&ec->seat_created_signal);
Richard Hughes59d5da72013-05-01 21:52:11 +01006631 wl_signal_init(&ec->output_created_signal);
Ander Conselvan de Oliveiraf84327a2014-01-29 18:47:51 +02006632 wl_signal_init(&ec->output_destroyed_signal);
Ander Conselvan de Oliveiraa8a9baf2014-01-29 18:47:52 +02006633 wl_signal_init(&ec->output_moved_signal);
David Fort0de859e2016-05-27 23:22:57 +02006634 wl_signal_init(&ec->output_resized_signal);
Pekka Paalanen37e6c9e2017-08-15 13:00:02 +03006635 wl_signal_init(&ec->heads_changed_signal);
Pekka Paalanen8dc6db82018-03-20 13:29:40 +02006636 wl_signal_init(&ec->output_heads_changed_signal);
Kristian Høgsberg61741a22013-09-17 16:02:57 -07006637 wl_signal_init(&ec->session_signal);
6638 ec->session_active = 1;
Kristian Høgsberg16eb6752008-10-08 22:51:32 -04006639
Casey Dahlin58ba1372012-04-19 22:50:08 -04006640 ec->output_id_pool = 0;
Giulio Camuffobab996e2014-10-12 00:24:25 +03006641 ec->repaint_msec = DEFAULT_REPAINT_WINDOW;
Casey Dahlin58ba1372012-04-19 22:50:08 -04006642
Jonas Ådahl94e2e2d2014-10-18 18:42:19 +02006643 ec->activate_serial = 1;
6644
Louis-Francis Ratté-Bouliannec4689ff2017-11-28 20:42:47 -05006645 ec->touch_mode = WESTON_TOUCH_MODE_NORMAL;
6646
Derek Foreman152254b2015-11-26 14:17:48 -06006647 if (!wl_global_create(ec->wl_display, &wl_compositor_interface, 4,
Kristian Høgsberg919cddb2013-07-08 19:03:57 -04006648 ec, compositor_bind))
Giulio Camuffo459137b2014-10-11 23:56:24 +03006649 goto fail;
Kristian Høgsbergee02ca62008-12-21 23:37:12 -05006650
Giulio Camuffo954f1832014-10-11 18:27:30 +03006651 if (!wl_global_create(ec->wl_display, &wl_subcompositor_interface, 1,
Kristian Høgsberg919cddb2013-07-08 19:03:57 -04006652 ec, bind_subcompositor))
Giulio Camuffo459137b2014-10-11 23:56:24 +03006653 goto fail;
Pekka Paalanene67858b2013-04-25 13:57:42 +03006654
Pekka Paalanene95ad5c2016-04-15 14:47:08 +03006655 if (!wl_global_create(ec->wl_display, &wp_viewporter_interface, 1,
Pekka Paalanen9c5a0d92016-04-15 16:42:49 +03006656 ec, bind_viewporter))
Giulio Camuffo459137b2014-10-11 23:56:24 +03006657 goto fail;
Jonny Lamb8ae35902013-11-26 18:19:45 +01006658
Pekka Paalanenb00c79b2016-02-18 16:53:27 +02006659 if (!wl_global_create(ec->wl_display, &wp_presentation_interface, 1,
Pekka Paalanen31f7d782014-09-23 22:08:43 -04006660 ec, bind_presentation))
Giulio Camuffo459137b2014-10-11 23:56:24 +03006661 goto fail;
Pekka Paalanen31f7d782014-09-23 22:08:43 -04006662
Pekka Paalanena5630ea2017-10-12 13:13:42 +02006663 if (weston_debug_compositor_create(ec) < 0)
6664 goto fail;
6665
Jonas Ådahl30d61d82014-10-22 21:21:17 +02006666 if (weston_input_init(ec) != 0)
6667 goto fail;
6668
Jason Ekstranda7af7042013-10-12 22:38:11 -05006669 wl_list_init(&ec->view_list);
Ander Conselvan de Oliveira8ad19822013-03-05 17:30:27 +02006670 wl_list_init(&ec->plane_list);
Daniel Stone725c2c32012-06-22 14:04:36 +01006671 wl_list_init(&ec->layer_list);
6672 wl_list_init(&ec->seat_list);
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006673 wl_list_init(&ec->pending_output_list);
Daniel Stone725c2c32012-06-22 14:04:36 +01006674 wl_list_init(&ec->output_list);
Pekka Paalanen1adcbac2017-08-14 16:05:35 +03006675 wl_list_init(&ec->head_list);
Daniel Stone725c2c32012-06-22 14:04:36 +01006676 wl_list_init(&ec->key_binding_list);
Daniel Stone96d47c02013-11-19 11:37:12 +01006677 wl_list_init(&ec->modifier_binding_list);
Daniel Stone725c2c32012-06-22 14:04:36 +01006678 wl_list_init(&ec->button_binding_list);
Neil Robertsa28c6932013-10-03 16:43:04 +01006679 wl_list_init(&ec->touch_binding_list);
Daniel Stone725c2c32012-06-22 14:04:36 +01006680 wl_list_init(&ec->axis_binding_list);
Ander Conselvan de Oliveirac509d2b2012-11-08 17:20:45 +02006681 wl_list_init(&ec->debug_binding_list);
Daniel Stone725c2c32012-06-22 14:04:36 +01006682
Pekka Paalanen827b5d22016-06-29 11:54:26 +02006683 wl_list_init(&ec->plugin_api_list);
6684
Xiong Zhang97116532013-10-23 13:58:31 +08006685 weston_plane_init(&ec->primary_plane, ec, 0, 0);
Ander Conselvan de Oliveira8ad19822013-03-05 17:30:27 +02006686 weston_compositor_stack_plane(ec, &ec->primary_plane, NULL);
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04006687
Giulio Camuffo459137b2014-10-11 23:56:24 +03006688 wl_data_device_manager_init(ec->wl_display);
6689
6690 wl_display_init_shm(ec->wl_display);
6691
6692 loop = wl_display_get_event_loop(ec->wl_display);
6693 ec->idle_source = wl_event_loop_add_timer(loop, idle_handler, ec);
Daniel Stone6847b852017-03-01 11:34:08 +00006694 ec->repaint_timer =
6695 wl_event_loop_add_timer(loop, output_repaint_timer_handler,
6696 ec);
Giulio Camuffo459137b2014-10-11 23:56:24 +03006697
Quentin Glidic82681572016-12-17 13:40:51 +01006698 weston_layer_init(&ec->fade_layer, ec);
6699 weston_layer_init(&ec->cursor_layer, ec);
6700
6701 weston_layer_set_position(&ec->fade_layer, WESTON_LAYER_POSITION_FADE);
6702 weston_layer_set_position(&ec->cursor_layer,
6703 WESTON_LAYER_POSITION_CURSOR);
Giulio Camuffo459137b2014-10-11 23:56:24 +03006704
6705 weston_compositor_add_debug_binding(ec, KEY_T,
6706 timeline_key_binding_handler, ec);
6707
Daniel Stonece62cb32018-07-20 09:46:24 +01006708 ec->debug_scene =
6709 weston_compositor_add_debug_scope(ec, "scene-graph",
6710 "Scene graph details\n",
6711 debug_scene_graph_cb,
6712 ec);
6713
Giulio Camuffo459137b2014-10-11 23:56:24 +03006714 return ec;
6715
6716fail:
6717 free(ec);
6718 return NULL;
6719}
6720
Benjamin Franzkeb8263022011-08-30 11:32:47 +02006721WL_EXPORT void
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05006722weston_compositor_shutdown(struct weston_compositor *ec)
Matt Roper361d2ad2011-08-29 13:52:23 -07006723{
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05006724 struct weston_output *output, *next;
Matt Roper361d2ad2011-08-29 13:52:23 -07006725
Pekka Paalanend1591ae2012-01-02 16:06:56 +02006726 wl_event_source_remove(ec->idle_source);
6727
Matt Roper361d2ad2011-08-29 13:52:23 -07006728 /* Destroy all outputs associated with this compositor */
Tiago Vignattib303a1d2011-12-18 22:27:40 +02006729 wl_list_for_each_safe(output, next, &ec->output_list, link)
Matt Roper361d2ad2011-08-29 13:52:23 -07006730 output->destroy(output);
Pekka Paalanen4738f3b2012-01-02 15:47:07 +02006731
Armin Krezovića01ab6d2016-09-30 14:11:02 +02006732 /* Destroy all pending outputs associated with this compositor */
6733 wl_list_for_each_safe(output, next, &ec->pending_output_list, link)
6734 output->destroy(output);
6735
Ander Conselvan de Oliveira18536762013-12-20 21:07:00 +02006736 if (ec->renderer)
6737 ec->renderer->destroy(ec);
6738
Daniel Stone325fc2d2012-05-30 16:31:58 +01006739 weston_binding_list_destroy_all(&ec->key_binding_list);
Ryo Munakata27135af2015-07-17 13:07:42 +09006740 weston_binding_list_destroy_all(&ec->modifier_binding_list);
Daniel Stone325fc2d2012-05-30 16:31:58 +01006741 weston_binding_list_destroy_all(&ec->button_binding_list);
Neil Robertsa28c6932013-10-03 16:43:04 +01006742 weston_binding_list_destroy_all(&ec->touch_binding_list);
Daniel Stone325fc2d2012-05-30 16:31:58 +01006743 weston_binding_list_destroy_all(&ec->axis_binding_list);
Ander Conselvan de Oliveirac509d2b2012-11-08 17:20:45 +02006744 weston_binding_list_destroy_all(&ec->debug_binding_list);
Pekka Paalanend1591ae2012-01-02 16:06:56 +02006745
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04006746 weston_plane_release(&ec->primary_plane);
Matt Roper361d2ad2011-08-29 13:52:23 -07006747}
6748
Kristian Høgsbergaf4f2aa2013-02-15 20:53:20 -05006749WL_EXPORT void
Frederic Plourdec336f062014-10-29 14:44:33 -04006750weston_compositor_exit_with_code(struct weston_compositor *compositor,
6751 int exit_code)
6752{
Pekka Paalanenf5ef88f2014-11-18 15:57:04 +02006753 if (compositor->exit_code == EXIT_SUCCESS)
6754 compositor->exit_code = exit_code;
6755
Giulio Camuffo459137b2014-10-11 23:56:24 +03006756 weston_compositor_exit(compositor);
Frederic Plourdec336f062014-10-29 14:44:33 -04006757}
6758
6759WL_EXPORT void
Giulio Camuffocdb4d292013-11-14 23:42:53 +01006760weston_compositor_set_default_pointer_grab(struct weston_compositor *ec,
6761 const struct weston_pointer_grab_interface *interface)
6762{
6763 struct weston_seat *seat;
6764
6765 ec->default_pointer_grab = interface;
6766 wl_list_for_each(seat, &ec->seat_list, link) {
Derek Foreman1281a362015-07-31 16:55:32 -05006767 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
6768
6769 if (pointer)
6770 weston_pointer_set_default_grab(pointer, interface);
Giulio Camuffocdb4d292013-11-14 23:42:53 +01006771 }
6772}
6773
Pekka Paalanenb5eedad2014-09-23 22:08:45 -04006774WL_EXPORT int
6775weston_compositor_set_presentation_clock(struct weston_compositor *compositor,
6776 clockid_t clk_id)
6777{
6778 struct timespec ts;
6779
6780 if (clock_gettime(clk_id, &ts) < 0)
6781 return -1;
6782
6783 compositor->presentation_clock = clk_id;
6784
6785 return 0;
6786}
6787
6788/*
6789 * For choosing the software clock, when the display hardware or API
6790 * does not expose a compatible presentation timestamp.
6791 */
6792WL_EXPORT int
6793weston_compositor_set_presentation_clock_software(
6794 struct weston_compositor *compositor)
6795{
6796 /* In order of preference */
6797 static const clockid_t clocks[] = {
6798 CLOCK_MONOTONIC_RAW, /* no jumps, no crawling */
6799 CLOCK_MONOTONIC_COARSE, /* no jumps, may crawl, fast & coarse */
6800 CLOCK_MONOTONIC, /* no jumps, may crawl */
6801 CLOCK_REALTIME_COARSE, /* may jump and crawl, fast & coarse */
6802 CLOCK_REALTIME /* may jump and crawl */
6803 };
6804 unsigned i;
6805
6806 for (i = 0; i < ARRAY_LENGTH(clocks); i++)
6807 if (weston_compositor_set_presentation_clock(compositor,
6808 clocks[i]) == 0)
6809 return 0;
6810
6811 weston_log("Error: no suitable presentation clock available.\n");
6812
6813 return -1;
6814}
6815
Pekka Paalanen662f3842015-03-18 12:17:26 +02006816/** Read the current time from the Presentation clock
6817 *
6818 * \param compositor
6819 * \param ts[out] The current time.
6820 *
6821 * \note Reading the current time in user space is always imprecise to some
6822 * degree.
6823 *
6824 * This function is never meant to fail. If reading the clock does fail,
6825 * an error message is logged and a zero time is returned. Callers are not
6826 * supposed to detect or react to failures.
6827 */
6828WL_EXPORT void
6829weston_compositor_read_presentation_clock(
6830 const struct weston_compositor *compositor,
6831 struct timespec *ts)
6832{
6833 static bool warned;
6834 int ret;
6835
6836 ret = clock_gettime(compositor->presentation_clock, ts);
6837 if (ret < 0) {
6838 ts->tv_sec = 0;
6839 ts->tv_nsec = 0;
6840
6841 if (!warned)
6842 weston_log("Error: failure to read "
6843 "the presentation clock %#x: '%m' (%d)\n",
6844 compositor->presentation_clock, errno);
6845 warned = true;
6846 }
6847}
6848
Pekka Paalanen230f3b12014-09-29 14:18:40 -04006849/** Import dmabuf buffer into current renderer
6850 *
6851 * \param compositor
6852 * \param buffer the dmabuf buffer to import
6853 * \return true on usable buffers, false otherwise
6854 *
6855 * This function tests that the linux_dmabuf_buffer is usable
6856 * for the current renderer. Returns false on unusable buffers. Usually
6857 * usability is tested by importing the dmabufs for composition.
6858 *
6859 * This hook is also used for detecting if the renderer supports
6860 * dmabufs at all. If the renderer hook is NULL, dmabufs are not
6861 * supported.
6862 * */
6863WL_EXPORT bool
6864weston_compositor_import_dmabuf(struct weston_compositor *compositor,
6865 struct linux_dmabuf_buffer *buffer)
6866{
6867 struct weston_renderer *renderer;
6868
6869 renderer = compositor->renderer;
6870
6871 if (renderer->import_dmabuf == NULL)
6872 return false;
6873
6874 return renderer->import_dmabuf(compositor, buffer);
6875}
6876
Giulio Camuffocdb4d292013-11-14 23:42:53 +01006877WL_EXPORT void
Kristian Høgsbergaf4f2aa2013-02-15 20:53:20 -05006878weston_version(int *major, int *minor, int *micro)
6879{
6880 *major = WESTON_VERSION_MAJOR;
6881 *minor = WESTON_VERSION_MINOR;
6882 *micro = WESTON_VERSION_MICRO;
6883}
6884
Daniel Stonee03c1112016-11-24 20:45:45 +00006885/**
6886 * Attempts to find a module path from the module map specified in the
6887 * environment. If found, writes the full path into the path variable.
6888 *
6889 * The module map is a string in environment variable WESTON_MODULE_MAP, where
6890 * each entry is of the form "name=path" and entries are separated by
6891 * semicolons. Whitespace is significant.
6892 *
6893 * \param name The name to search for.
6894 * \param path Where the path is written to if found.
6895 * \param path_len Allocated bytes at \c path .
6896 * \returns The length of the string written to path on success, or 0 if the
6897 * module was not specified in the environment map or path_len was too small.
6898 */
6899WL_EXPORT size_t
6900weston_module_path_from_env(const char *name, char *path, size_t path_len)
6901{
6902 const char *mapping = getenv("WESTON_MODULE_MAP");
6903 const char *end;
6904 const int name_len = strlen(name);
6905
6906 if (!mapping)
6907 return 0;
6908
6909 end = mapping + strlen(mapping);
6910 while (mapping < end && *mapping) {
6911 const char *filename, *next;
6912
6913 /* early out: impossibly short string */
6914 if (end - mapping < name_len + 1)
6915 return 0;
6916
6917 filename = &mapping[name_len + 1];
6918 next = strchrnul(mapping, ';');
6919
6920 if (strncmp(mapping, name, name_len) == 0 &&
6921 mapping[name_len] == '=') {
6922 size_t file_len = next - filename; /* no trailing NUL */
6923 if (file_len >= path_len)
6924 return 0;
6925 strncpy(path, filename, file_len);
6926 path[file_len] = '\0';
6927 return file_len;
6928 }
6929
6930 mapping = next + 1;
6931 }
6932
6933 return 0;
6934}
6935
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03006936WL_EXPORT void *
6937weston_load_module(const char *name, const char *entrypoint)
Kristian Høgsberg1c562182011-05-02 22:09:20 -04006938{
6939 char path[PATH_MAX];
6940 void *module, *init;
Daniel Stonebeb97e52016-11-28 12:13:54 +00006941 size_t len;
Kristian Høgsberg1c562182011-05-02 22:09:20 -04006942
U. Artie Eoff2e2384a2014-01-17 13:19:01 -08006943 if (name == NULL)
6944 return NULL;
6945
Derek Foreman3f86e502015-06-08 11:46:54 -05006946 if (name[0] != '/') {
Daniel Stonee03c1112016-11-24 20:45:45 +00006947 len = weston_module_path_from_env(name, path, sizeof path);
6948 if (len == 0)
Daniel Stonebeb97e52016-11-28 12:13:54 +00006949 len = snprintf(path, sizeof path, "%s/%s",
6950 LIBWESTON_MODULEDIR, name);
Derek Foreman3f86e502015-06-08 11:46:54 -05006951 } else {
Daniel Stonebeb97e52016-11-28 12:13:54 +00006952 len = snprintf(path, sizeof path, "%s", name);
Derek Foreman3f86e502015-06-08 11:46:54 -05006953 }
Kristian Høgsberg1c562182011-05-02 22:09:20 -04006954
Daniel Stonebeb97e52016-11-28 12:13:54 +00006955 /* snprintf returns the length of the string it would've written,
6956 * _excluding_ the NUL byte. So even being equal to the size of
6957 * our buffer is an error here. */
6958 if (len >= sizeof path)
6959 return NULL;
6960
Kristian Høgsberga6813d22012-09-12 12:21:01 -04006961 module = dlopen(path, RTLD_NOW | RTLD_NOLOAD);
6962 if (module) {
6963 weston_log("Module '%s' already loaded\n", path);
6964 dlclose(module);
6965 return NULL;
6966 }
6967
Pekka Paalanen1b3c1ea2012-06-11 14:06:04 +03006968 weston_log("Loading module '%s'\n", path);
Kristian Høgsberg1acd9f82012-07-26 11:39:26 -04006969 module = dlopen(path, RTLD_NOW);
Kristian Høgsberg1c562182011-05-02 22:09:20 -04006970 if (!module) {
Pekka Paalanen1b3c1ea2012-06-11 14:06:04 +03006971 weston_log("Failed to load module: %s\n", dlerror());
Kristian Høgsberg1c562182011-05-02 22:09:20 -04006972 return NULL;
6973 }
6974
6975 init = dlsym(module, entrypoint);
6976 if (!init) {
Pekka Paalanen1b3c1ea2012-06-11 14:06:04 +03006977 weston_log("Failed to lookup init function: %s\n", dlerror());
Rob Bradfordc9e64ab2012-12-05 18:47:10 +00006978 dlclose(module);
Kristian Høgsberg1c562182011-05-02 22:09:20 -04006979 return NULL;
6980 }
6981
6982 return init;
6983}
6984
Giulio Camuffo459137b2014-10-11 23:56:24 +03006985
6986/** Destroys the compositor.
6987 *
6988 * This function cleans up the compositor state and destroys it.
6989 *
6990 * \param compositor The compositor to be destroyed.
6991 */
6992WL_EXPORT void
6993weston_compositor_destroy(struct weston_compositor *compositor)
6994{
6995 /* prevent further rendering while shutting down */
6996 compositor->state = WESTON_COMPOSITOR_OFFSCREEN;
6997
6998 wl_signal_emit(&compositor->destroy_signal, compositor);
6999
7000 weston_compositor_xkb_destroy(compositor);
7001
Giulio Camuffo2d24e642015-10-03 16:25:15 +03007002 if (compositor->backend)
7003 compositor->backend->destroy(compositor);
Pekka Paalanen827b5d22016-06-29 11:54:26 +02007004
Pekka Paalanen1adcbac2017-08-14 16:05:35 +03007005 /* The backend is responsible for destroying the heads. */
7006 assert(wl_list_empty(&compositor->head_list));
7007
Pekka Paalanen827b5d22016-06-29 11:54:26 +02007008 weston_plugin_api_destroy_list(compositor);
7009
Pekka Paalanen37e6c9e2017-08-15 13:00:02 +03007010 if (compositor->heads_changed_source)
7011 wl_event_source_remove(compositor->heads_changed_source);
7012
Daniel Stonece62cb32018-07-20 09:46:24 +01007013 weston_debug_scope_destroy(compositor->debug_scene);
7014 compositor->debug_scene = NULL;
Pekka Paalanena5630ea2017-10-12 13:13:42 +02007015 weston_debug_compositor_destroy(compositor);
7016
Giulio Camuffo459137b2014-10-11 23:56:24 +03007017 free(compositor);
7018}
7019
7020/** Instruct the compositor to exit.
7021 *
7022 * This functions does not directly destroy the compositor object, it merely
7023 * command it to start the tear down process. It is not guaranteed that the
7024 * tear down will happen immediately.
7025 *
7026 * \param compositor The compositor to tear down.
7027 */
7028WL_EXPORT void
7029weston_compositor_exit(struct weston_compositor *compositor)
7030{
7031 compositor->exit(compositor);
7032}
7033
7034/** Return the user data stored in the compositor.
7035 *
7036 * This function returns the user data pointer set with user_data parameter
7037 * to the \ref weston_compositor_create function.
7038 */
7039WL_EXPORT void *
7040weston_compositor_get_user_data(struct weston_compositor *compositor)
7041{
7042 return compositor->user_data;
7043}
Pekka Paalanendd186732016-06-03 14:49:54 +03007044
Pekka Paalanen50dbf382016-06-03 15:23:46 +03007045static const char * const backend_map[] = {
7046 [WESTON_BACKEND_DRM] = "drm-backend.so",
7047 [WESTON_BACKEND_FBDEV] = "fbdev-backend.so",
7048 [WESTON_BACKEND_HEADLESS] = "headless-backend.so",
7049 [WESTON_BACKEND_RDP] = "rdp-backend.so",
7050 [WESTON_BACKEND_WAYLAND] = "wayland-backend.so",
7051 [WESTON_BACKEND_X11] = "x11-backend.so",
7052};
7053
Pekka Paalanendd186732016-06-03 14:49:54 +03007054/** Load a backend into a weston_compositor
7055 *
7056 * A backend must be loaded to make a weston_compositor work. A backend
7057 * provides input and output capabilities, and determines the renderer to use.
7058 *
7059 * \param compositor A compositor that has not had a backend loaded yet.
7060 * \param backend Name of the backend file.
7061 * \param config_base A pointer to a backend-specific configuration
7062 * structure's 'base' member.
7063 *
7064 * \return 0 on success, or -1 on error.
7065 */
7066WL_EXPORT int
7067weston_compositor_load_backend(struct weston_compositor *compositor,
Pekka Paalanen50dbf382016-06-03 15:23:46 +03007068 enum weston_compositor_backend backend,
Pekka Paalanendd186732016-06-03 14:49:54 +03007069 struct weston_backend_config *config_base)
7070{
7071 int (*backend_init)(struct weston_compositor *c,
Pekka Paalanendd186732016-06-03 14:49:54 +03007072 struct weston_backend_config *config_base);
7073
Pekka Paalanend7e35112017-08-29 17:04:12 +03007074 if (compositor->backend) {
7075 weston_log("Error: attempt to load a backend when one is already loaded\n");
7076 return -1;
7077 }
7078
Quentin Glidic887c0182016-07-10 11:00:53 +02007079 if (backend >= ARRAY_LENGTH(backend_map))
Pekka Paalanen50dbf382016-06-03 15:23:46 +03007080 return -1;
7081
Quentin Glidic23e1d6f2016-12-02 14:08:44 +01007082 backend_init = weston_load_module(backend_map[backend], "weston_backend_init");
Pekka Paalanendd186732016-06-03 14:49:54 +03007083 if (!backend_init)
7084 return -1;
7085
Pekka Paalanend7e35112017-08-29 17:04:12 +03007086 if (backend_init(compositor, config_base) < 0) {
7087 compositor->backend = NULL;
7088 return -1;
7089 }
7090
7091 return 0;
Pekka Paalanendd186732016-06-03 14:49:54 +03007092}
Giulio Camuffo9c764df2016-06-29 11:54:27 +02007093
7094WL_EXPORT int
7095weston_compositor_load_xwayland(struct weston_compositor *compositor)
7096{
Quentin Glidic3d7ca3b2016-12-02 14:20:35 +01007097 int (*module_init)(struct weston_compositor *ec);
Giulio Camuffo9c764df2016-06-29 11:54:27 +02007098
Quentin Glidic3d7ca3b2016-12-02 14:20:35 +01007099 module_init = weston_load_module("xwayland.so", "weston_module_init");
Giulio Camuffo9c764df2016-06-29 11:54:27 +02007100 if (!module_init)
7101 return -1;
Quentin Glidic3d7ca3b2016-12-02 14:20:35 +01007102 if (module_init(compositor) < 0)
Giulio Camuffo9c764df2016-06-29 11:54:27 +02007103 return -1;
7104 return 0;
7105}
Vasilis Liaskovitis486b4632018-10-10 16:14:55 +02007106
7107/** Resolve an internal compositor error by disconnecting the client.
7108 *
7109 * This function is used in cases when the wl_buffer turns out
7110 * unusable and there is no fallback path.
7111 *
7112 * It is possible the fault is caused by a compositor bug, the underlying
7113 * graphics stack bug or normal behaviour, or perhaps a client mistake.
7114 * In any case, the options are to either composite garbage or nothing,
7115 * or disconnect the client. This is a helper function for the latter.
7116 *
7117 * The error is sent as an INVALID_OBJECT error on the client's wl_display.
7118 *
7119 * \param buffer The weston buffer that is unusable.
7120 * \param msg A custom error message attached to the protocol error.
7121 */
7122WL_EXPORT void
7123weston_buffer_send_server_error(struct weston_buffer *buffer,
7124 const char *msg)
7125{
7126 struct wl_client *client;
7127 struct wl_resource *display_resource;
7128 uint32_t id;
7129
7130 assert(buffer->resource);
7131 id = wl_resource_get_id(buffer->resource);
7132 client = wl_resource_get_client(buffer->resource);
7133 display_resource = wl_client_get_object(client, 1);
7134
7135 assert(display_resource);
7136 wl_resource_post_error(display_resource,
7137 WL_DISPLAY_ERROR_INVALID_OBJECT,
7138 "server error with "
7139 "wl_buffer@%u: %s", id, msg);
7140}