1 /*
2 * Copyright © 2010-2011 Intel Corporation
3 * Copyright © 2008-2011 Kristian Høgsberg
4 * Copyright © 2012-2018 Collabora, Ltd.
5 * Copyright © 2017, 2018 General Electric Company
6 *
7 * 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:
14 *
15 * 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.
27 */
28
29 #include "config.h"
30
31 #include <fcntl.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include <stdint.h>
36 #include <limits.h>
37 #include <stdarg.h>
38 #include <assert.h>
39 #include <sys/ioctl.h>
40 #include <sys/mman.h>
41 #include <sys/wait.h>
42 #include <sys/socket.h>
43 #include <sys/utsname.h>
44 #include <sys/stat.h>
45 #include <unistd.h>
46 #include <math.h>
47 #include <linux/input.h>
48 #include <dlfcn.h>
49 #include <signal.h>
50 #include <setjmp.h>
51 #include <sys/time.h>
52 #include <time.h>
53 #include <errno.h>
54 #include <inttypes.h>
55
56 // OHOS remove timeline
57 //#include "timeline.h"
58
59 #include <libweston/libweston.h>
60 #include <libweston/weston-log.h>
61 #include "linux-dmabuf.h"
62 #include "viewporter-server-protocol.h"
63 #include "presentation-time-server-protocol.h"
64 #include "xdg-output-unstable-v1-server-protocol.h"
65 #include "linux-explicit-synchronization-unstable-v1-server-protocol.h"
66 #include "linux-explicit-synchronization.h"
67 #include "shared/fd-util.h"
68 #include "shared/helpers.h"
69 #include "shared/os-compatibility.h"
70 #include "shared/string-helpers.h"
71 #include "shared/timespec-util.h"
72 #include "git-version.h"
73 #include <libweston/version.h>
74 #include <libweston/plugin-registry.h>
75 #include "pixel-formats.h"
76 #include "backend.h"
77 #include "libweston-internal.h"
78
79 #include "libweston/trace.h"
80 DEFINE_LOG_LABEL("Compositor");
81
82 // OHOS remove logger
83 //#include "weston-log-internal.h"
84
85 /**
86 * \defgroup head Head
87 * \defgroup output Output
88 * \defgroup compositor Compositor
89 */
90
91 #define DEFAULT_REPAINT_WINDOW 7 /* milliseconds */
92
93 static void
94 weston_output_update_matrix(struct weston_output *output);
95
96 static void
97 weston_output_transform_scale_init(struct weston_output *output,
98 uint32_t transform, uint32_t scale);
99
100 static void
101 weston_compositor_build_view_list(struct weston_compositor *compositor);
102
103 static char *
104 weston_output_create_heads_string(struct weston_output *output);
105
106 /** Send wl_output events for mode and scale changes
107 *
108 * \param head Send on all resources bound to this head.
109 * \param mode_changed If true, send the current mode.
110 * \param scale_changed If true, send the current scale.
111 */
112 static void
weston_mode_switch_send_events(struct weston_head * head,bool mode_changed,bool scale_changed)113 weston_mode_switch_send_events(struct weston_head *head,
114 bool mode_changed, bool scale_changed)
115 {
116 struct weston_output *output = head->output;
117 struct wl_resource *resource;
118 int version;
119
120 wl_resource_for_each(resource, &head->resource_list) {
121 if (mode_changed) {
122 wl_output_send_mode(resource,
123 output->current_mode->flags,
124 output->current_mode->width,
125 output->current_mode->height,
126 output->current_mode->refresh);
127 }
128
129 version = wl_resource_get_version(resource);
130 if (version >= WL_OUTPUT_SCALE_SINCE_VERSION && scale_changed)
131 wl_output_send_scale(resource, output->current_scale);
132
133 if (version >= WL_OUTPUT_DONE_SINCE_VERSION)
134 wl_output_send_done(resource);
135 }
136 wl_resource_for_each(resource, &head->xdg_output_resource_list) {
137 zxdg_output_v1_send_logical_position(resource,
138 output->x,
139 output->y);
140 zxdg_output_v1_send_logical_size(resource,
141 output->width,
142 output->height);
143 zxdg_output_v1_send_done(resource);
144 }
145 }
146
147 static void
weston_mode_switch_finish(struct weston_output * output,int mode_changed,int scale_changed)148 weston_mode_switch_finish(struct weston_output *output,
149 int mode_changed, int scale_changed)
150 {
151 struct weston_seat *seat;
152 struct weston_head *head;
153 pixman_region32_t old_output_region;
154
155 pixman_region32_init(&old_output_region);
156 pixman_region32_copy(&old_output_region, &output->region);
157
158 /* Update output region and transformation matrix */
159 weston_output_transform_scale_init(output, output->transform, output->current_scale);
160
161 pixman_region32_init_rect(&output->region, output->x, output->y,
162 output->width, output->height);
163
164 weston_output_update_matrix(output);
165
166 /* If a pointer falls outside the outputs new geometry, move it to its
167 * lower-right corner */
168 wl_list_for_each(seat, &output->compositor->seat_list, link) {
169 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
170 int32_t x, y;
171
172 if (!pointer)
173 continue;
174
175 x = wl_fixed_to_int(pointer->x);
176 y = wl_fixed_to_int(pointer->y);
177
178 if (!pixman_region32_contains_point(&old_output_region,
179 x, y, NULL) ||
180 pixman_region32_contains_point(&output->region,
181 x, y, NULL))
182 continue;
183
184 if (x >= output->x + output->width)
185 x = output->x + output->width - 1;
186 if (y >= output->y + output->height)
187 y = output->y + output->height - 1;
188
189 pointer->x = wl_fixed_from_int(x);
190 pointer->y = wl_fixed_from_int(y);
191 }
192
193 pixman_region32_fini(&old_output_region);
194
195 if (!mode_changed && !scale_changed)
196 return;
197
198 /* notify clients of the changes */
199 wl_list_for_each(head, &output->head_list, output_link)
200 weston_mode_switch_send_events(head,
201 mode_changed, scale_changed);
202 }
203
204 static void
205 weston_compositor_reflow_outputs(struct weston_compositor *compositor,
206 struct weston_output *resized_output, int delta_width);
207
208 /**
209 * \ingroup output
210 */
211 WL_EXPORT int
weston_output_mode_set_native(struct weston_output * output,struct weston_mode * mode,int32_t scale)212 weston_output_mode_set_native(struct weston_output *output,
213 struct weston_mode *mode,
214 int32_t scale)
215 {
216 int ret;
217 int mode_changed = 0, scale_changed = 0;
218 int32_t old_width;
219
220 if (!output->switch_mode)
221 return -1;
222
223 if (!output->original_mode) {
224 mode_changed = 1;
225 ret = output->switch_mode(output, mode);
226 if (ret < 0)
227 return ret;
228 if (output->current_scale != scale) {
229 scale_changed = 1;
230 output->current_scale = scale;
231 }
232 }
233
234 old_width = output->width;
235 output->native_mode = mode;
236 output->native_scale = scale;
237
238 weston_mode_switch_finish(output, mode_changed, scale_changed);
239
240 if (mode_changed || scale_changed) {
241 weston_compositor_reflow_outputs(output->compositor, output, output->width - old_width);
242
243 wl_signal_emit(&output->compositor->output_resized_signal, output);
244 }
245 return 0;
246 }
247
248 /**
249 * \ingroup output
250 */
251 WL_EXPORT int
weston_output_mode_switch_to_native(struct weston_output * output)252 weston_output_mode_switch_to_native(struct weston_output *output)
253 {
254 int ret;
255 int mode_changed = 0, scale_changed = 0;
256
257 if (!output->switch_mode)
258 return -1;
259
260 if (!output->original_mode) {
261 weston_log("already in the native mode\n");
262 return -1;
263 }
264 /* the non fullscreen clients haven't seen a mode set since we
265 * switched into a temporary, so we need to notify them if the
266 * mode at that time is different from the native mode now.
267 */
268 mode_changed = (output->original_mode != output->native_mode);
269 scale_changed = (output->original_scale != output->native_scale);
270
271 ret = output->switch_mode(output, output->native_mode);
272 if (ret < 0)
273 return ret;
274
275 output->current_scale = output->native_scale;
276
277 output->original_mode = NULL;
278 output->original_scale = 0;
279
280 weston_mode_switch_finish(output, mode_changed, scale_changed);
281
282 return 0;
283 }
284
285 /**
286 * \ingroup output
287 */
288 WL_EXPORT int
weston_output_mode_switch_to_temporary(struct weston_output * output,struct weston_mode * mode,int32_t scale)289 weston_output_mode_switch_to_temporary(struct weston_output *output,
290 struct weston_mode *mode,
291 int32_t scale)
292 {
293 int ret;
294
295 if (!output->switch_mode)
296 return -1;
297
298 /* original_mode is the last mode non full screen clients have seen,
299 * so we shouldn't change it if we already have one set.
300 */
301 if (!output->original_mode) {
302 output->original_mode = output->native_mode;
303 output->original_scale = output->native_scale;
304 }
305 ret = output->switch_mode(output, mode);
306 if (ret < 0)
307 return ret;
308
309 output->current_scale = scale;
310
311 weston_mode_switch_finish(output, 0, 0);
312
313 return 0;
314 }
315
316 static void
region_init_infinite(pixman_region32_t * region)317 region_init_infinite(pixman_region32_t *region)
318 {
319 pixman_region32_init_rect(region, INT32_MIN, INT32_MIN,
320 UINT32_MAX, UINT32_MAX);
321 }
322
323 static struct weston_subsurface *
324 weston_surface_to_subsurface(struct weston_surface *surface);
325
326 WL_EXPORT struct weston_view *
weston_view_create(struct weston_surface * surface)327 weston_view_create(struct weston_surface *surface)
328 {
329 struct weston_view *view;
330
331 view = zalloc(sizeof *view);
332 if (view == NULL)
333 return NULL;
334
335 view->surface = surface;
336 view->plane = &surface->compositor->primary_plane;
337
338 /* Assign to surface */
339 wl_list_insert(&surface->views, &view->surface_link);
340
341 wl_signal_init(&view->destroy_signal);
342 wl_list_init(&view->link);
343 wl_list_init(&view->layer_link.link);
344
345 pixman_region32_init(&view->clip);
346
347 view->alpha = 1.0;
348 pixman_region32_init(&view->transform.opaque);
349
350 wl_list_init(&view->geometry.transformation_list);
351 wl_list_insert(&view->geometry.transformation_list,
352 &view->transform.position.link);
353 weston_matrix_init(&view->transform.position.matrix);
354 wl_list_init(&view->geometry.child_list);
355 pixman_region32_init(&view->geometry.scissor);
356 pixman_region32_init(&view->transform.boundingbox);
357 view->transform.dirty = 1;
358
359 return view;
360 }
361
362 struct weston_frame_callback {
363 struct wl_resource *resource;
364 struct wl_list link;
365 };
366
367 struct weston_presentation_feedback {
368 struct wl_resource *resource;
369
370 /* XXX: could use just wl_resource_get_link() instead */
371 struct wl_list link;
372
373 /* The per-surface feedback flags */
374 uint32_t psf_flags;
375 };
376
377 static void
weston_presentation_feedback_discard(struct weston_presentation_feedback * feedback)378 weston_presentation_feedback_discard(
379 struct weston_presentation_feedback *feedback)
380 {
381 wp_presentation_feedback_send_discarded(feedback->resource);
382 wl_resource_destroy(feedback->resource);
383 }
384
385 static void
weston_presentation_feedback_discard_list(struct wl_list * list)386 weston_presentation_feedback_discard_list(struct wl_list *list)
387 {
388 struct weston_presentation_feedback *feedback, *tmp;
389
390 wl_list_for_each_safe(feedback, tmp, list, link)
391 weston_presentation_feedback_discard(feedback);
392 }
393
394 static void
weston_presentation_feedback_present(struct weston_presentation_feedback * feedback,struct weston_output * output,uint32_t refresh_nsec,const struct timespec * ts,uint64_t seq,uint32_t flags)395 weston_presentation_feedback_present(
396 struct weston_presentation_feedback *feedback,
397 struct weston_output *output,
398 uint32_t refresh_nsec,
399 const struct timespec *ts,
400 uint64_t seq,
401 uint32_t flags)
402 {
403 struct wl_client *client = wl_resource_get_client(feedback->resource);
404 struct weston_head *head;
405 struct wl_resource *o;
406 uint32_t tv_sec_hi;
407 uint32_t tv_sec_lo;
408 uint32_t tv_nsec;
409 bool done = false;
410
411 wl_list_for_each(head, &output->head_list, output_link) {
412 wl_resource_for_each(o, &head->resource_list) {
413 if (wl_resource_get_client(o) != client)
414 continue;
415
416 wp_presentation_feedback_send_sync_output(feedback->resource, o);
417 done = true;
418 }
419
420 /* For clone mode, send it for just one wl_output global,
421 * they are all equivalent anyway.
422 */
423 if (done)
424 break;
425 }
426
427 timespec_to_proto(ts, &tv_sec_hi, &tv_sec_lo, &tv_nsec);
428 wp_presentation_feedback_send_presented(feedback->resource,
429 tv_sec_hi, tv_sec_lo, tv_nsec,
430 refresh_nsec,
431 seq >> 32, seq & 0xffffffff,
432 flags | feedback->psf_flags);
433 wl_resource_destroy(feedback->resource);
434 }
435
436 static void
weston_presentation_feedback_present_list(struct wl_list * list,struct weston_output * output,uint32_t refresh_nsec,const struct timespec * ts,uint64_t seq,uint32_t flags)437 weston_presentation_feedback_present_list(struct wl_list *list,
438 struct weston_output *output,
439 uint32_t refresh_nsec,
440 const struct timespec *ts,
441 uint64_t seq,
442 uint32_t flags)
443 {
444 struct weston_presentation_feedback *feedback, *tmp;
445
446 assert(!(flags & WP_PRESENTATION_FEEDBACK_INVALID) ||
447 wl_list_empty(list));
448
449 wl_list_for_each_safe(feedback, tmp, list, link)
450 weston_presentation_feedback_present(feedback, output,
451 refresh_nsec, ts, seq,
452 flags);
453 }
454
455 static void
surface_state_handle_buffer_destroy(struct wl_listener * listener,void * data)456 surface_state_handle_buffer_destroy(struct wl_listener *listener, void *data)
457 {
458 struct weston_surface_state *state =
459 container_of(listener, struct weston_surface_state,
460 buffer_destroy_listener);
461
462 state->buffer = NULL;
463 }
464
465 static void
weston_surface_state_init(struct weston_surface_state * state)466 weston_surface_state_init(struct weston_surface_state *state)
467 {
468 state->newly_attached = 0;
469 state->buffer = NULL;
470 state->buffer_destroy_listener.notify =
471 surface_state_handle_buffer_destroy;
472 state->sx = 0;
473 state->sy = 0;
474
475 pixman_region32_init(&state->damage_surface);
476 pixman_region32_init(&state->damage_buffer);
477 pixman_region32_init(&state->opaque);
478 region_init_infinite(&state->input);
479
480 wl_list_init(&state->frame_callback_list);
481 wl_list_init(&state->feedback_list);
482
483 state->buffer_viewport.buffer.transform = WL_OUTPUT_TRANSFORM_NORMAL;
484 state->buffer_viewport.buffer.scale = 1;
485 state->buffer_viewport.buffer.src_width = wl_fixed_from_int(-1);
486 state->buffer_viewport.surface.width = -1;
487 state->buffer_viewport.changed = 0;
488
489 state->acquire_fence_fd = -1;
490
491 state->desired_protection = WESTON_HDCP_DISABLE;
492 state->protection_mode = WESTON_SURFACE_PROTECTION_MODE_RELAXED;
493 }
494
495 static void
weston_surface_state_fini(struct weston_surface_state * state)496 weston_surface_state_fini(struct weston_surface_state *state)
497 {
498 struct weston_frame_callback *cb, *next;
499
500 wl_list_for_each_safe(cb, next,
501 &state->frame_callback_list, link)
502 wl_resource_destroy(cb->resource);
503
504 weston_presentation_feedback_discard_list(&state->feedback_list);
505
506 pixman_region32_fini(&state->input);
507 pixman_region32_fini(&state->opaque);
508 pixman_region32_fini(&state->damage_surface);
509 pixman_region32_fini(&state->damage_buffer);
510
511 if (state->buffer)
512 wl_list_remove(&state->buffer_destroy_listener.link);
513 state->buffer = NULL;
514
515 fd_clear(&state->acquire_fence_fd);
516 weston_buffer_release_reference(&state->buffer_release_ref, NULL);
517 }
518
519 static void
weston_surface_state_set_buffer(struct weston_surface_state * state,struct weston_buffer * buffer)520 weston_surface_state_set_buffer(struct weston_surface_state *state,
521 struct weston_buffer *buffer)
522 {
523 if (state->buffer == buffer)
524 return;
525
526 if (state->buffer)
527 wl_list_remove(&state->buffer_destroy_listener.link);
528 state->buffer = buffer;
529 if (state->buffer)
530 wl_signal_add(&state->buffer->destroy_signal,
531 &state->buffer_destroy_listener);
532 }
533
534 WL_EXPORT struct weston_surface *
weston_surface_create(struct weston_compositor * compositor)535 weston_surface_create(struct weston_compositor *compositor)
536 {
537 struct weston_surface *surface;
538
539 surface = zalloc(sizeof *surface);
540 if (surface == NULL)
541 return NULL;
542
543 wl_signal_init(&surface->destroy_signal);
544 wl_signal_init(&surface->commit_signal);
545
546 surface->compositor = compositor;
547 surface->ref_count = 1;
548
549 surface->buffer_viewport.buffer.transform = WL_OUTPUT_TRANSFORM_NORMAL;
550 surface->buffer_viewport.buffer.scale = 1;
551 surface->buffer_viewport.buffer.src_width = wl_fixed_from_int(-1);
552 surface->buffer_viewport.surface.width = -1;
553
554 weston_surface_state_init(&surface->pending);
555
556 pixman_region32_init(&surface->damage);
557 pixman_region32_init(&surface->opaque);
558 region_init_infinite(&surface->input);
559
560 wl_list_init(&surface->views);
561
562 wl_list_init(&surface->frame_callback_list);
563 wl_list_init(&surface->feedback_list);
564
565 wl_list_init(&surface->subsurface_list);
566 wl_list_init(&surface->subsurface_list_pending);
567
568 weston_matrix_init(&surface->buffer_to_surface_matrix);
569 weston_matrix_init(&surface->surface_to_buffer_matrix);
570
571 wl_list_init(&surface->pointer_constraints);
572
573 surface->acquire_fence_fd = -1;
574
575 surface->desired_protection = WESTON_HDCP_DISABLE;
576 surface->current_protection = WESTON_HDCP_DISABLE;
577 surface->protection_mode = WESTON_SURFACE_PROTECTION_MODE_RELAXED;
578
579 return surface;
580 }
581
582 WL_EXPORT void
weston_surface_set_color(struct weston_surface * surface,float red,float green,float blue,float alpha)583 weston_surface_set_color(struct weston_surface *surface,
584 float red, float green, float blue, float alpha)
585 {
586 surface->compositor->renderer->surface_set_color(surface, red, green, blue, alpha);
587 surface->is_opaque = !(alpha < 1.0);
588 }
589
590 WL_EXPORT void
weston_view_to_global_float(struct weston_view * view,float sx,float sy,float * x,float * y)591 weston_view_to_global_float(struct weston_view *view,
592 float sx, float sy, float *x, float *y)
593 {
594 if (view->transform.enabled) {
595 struct weston_vector v = { { sx, sy, 0.0f, 1.0f } };
596
597 weston_matrix_transform(&view->transform.matrix, &v);
598
599 if (fabsf(v.f[3]) < 1e-6) {
600 weston_log("warning: numerical instability in "
601 "%s(), divisor = %g\n", __func__,
602 v.f[3]);
603 *x = 0;
604 *y = 0;
605 return;
606 }
607
608 *x = v.f[0] / v.f[3];
609 *y = v.f[1] / v.f[3];
610 } else {
611 *x = sx + view->geometry.x;
612 *y = sy + view->geometry.y;
613 }
614 }
615
616 /** Transform a point to buffer coordinates
617 *
618 * \param width Surface width.
619 * \param height Surface height.
620 * \param transform Buffer transform.
621 * \param scale Buffer scale.
622 * \param sx Surface x coordinate of a point.
623 * \param sy Surface y coordinate of a point.
624 * \param[out] bx Buffer x coordinate of the point.
625 * \param[out] by Buffer Y coordinate of the point.
626 *
627 * Converts the given surface-local coordinates to buffer coordinates
628 * according to the given buffer transform and scale.
629 * This ignores wp_viewport.
630 *
631 * The given width and height must be the result of inverse scaled and
632 * inverse transformed buffer size.
633 */
634 WL_EXPORT void
weston_transformed_coord(int width,int height,enum wl_output_transform transform,int32_t scale,float sx,float sy,float * bx,float * by)635 weston_transformed_coord(int width, int height,
636 enum wl_output_transform transform,
637 int32_t scale,
638 float sx, float sy, float *bx, float *by)
639 {
640 switch (transform) {
641 case WL_OUTPUT_TRANSFORM_NORMAL:
642 default:
643 *bx = sx;
644 *by = sy;
645 break;
646 case WL_OUTPUT_TRANSFORM_FLIPPED:
647 *bx = width - sx;
648 *by = sy;
649 break;
650 case WL_OUTPUT_TRANSFORM_90:
651 *bx = sy;
652 *by = width - sx;
653 break;
654 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
655 *bx = sy;
656 *by = sx;
657 break;
658 case WL_OUTPUT_TRANSFORM_180:
659 *bx = width - sx;
660 *by = height - sy;
661 break;
662 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
663 *bx = sx;
664 *by = height - sy;
665 break;
666 case WL_OUTPUT_TRANSFORM_270:
667 *bx = height - sy;
668 *by = sx;
669 break;
670 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
671 *bx = height - sy;
672 *by = width - sx;
673 break;
674 }
675
676 *bx *= scale;
677 *by *= scale;
678 }
679
680 /** Transform a rectangle to buffer coordinates
681 *
682 * \param width Surface width.
683 * \param height Surface height.
684 * \param transform Buffer transform.
685 * \param scale Buffer scale.
686 * \param rect Rectangle in surface coordinates.
687 * \return Rectangle in buffer coordinates.
688 *
689 * Converts the given surface-local rectangle to buffer coordinates
690 * according to the given buffer transform and scale. The resulting
691 * rectangle is guaranteed to be well-formed.
692 * This ignores wp_viewport.
693 *
694 * The given width and height must be the result of inverse scaled and
695 * inverse transformed buffer size.
696 */
697 WL_EXPORT pixman_box32_t
weston_transformed_rect(int width,int height,enum wl_output_transform transform,int32_t scale,pixman_box32_t rect)698 weston_transformed_rect(int width, int height,
699 enum wl_output_transform transform,
700 int32_t scale,
701 pixman_box32_t rect)
702 {
703 float x1, x2, y1, y2;
704
705 pixman_box32_t ret;
706
707 weston_transformed_coord(width, height, transform, scale,
708 rect.x1, rect.y1, &x1, &y1);
709 weston_transformed_coord(width, height, transform, scale,
710 rect.x2, rect.y2, &x2, &y2);
711
712 if (x1 <= x2) {
713 ret.x1 = x1;
714 ret.x2 = x2;
715 } else {
716 ret.x1 = x2;
717 ret.x2 = x1;
718 }
719
720 if (y1 <= y2) {
721 ret.y1 = y1;
722 ret.y2 = y2;
723 } else {
724 ret.y1 = y2;
725 ret.y2 = y1;
726 }
727
728 return ret;
729 }
730
731 /** Transform a region by a matrix, restricted to axis-aligned transformations
732 *
733 * Warning: This function does not work for projective, affine, or matrices
734 * that encode arbitrary rotations. Only 90-degree step rotations are
735 * supported.
736 */
737 WL_EXPORT void
weston_matrix_transform_region(pixman_region32_t * dest,struct weston_matrix * matrix,pixman_region32_t * src)738 weston_matrix_transform_region(pixman_region32_t *dest,
739 struct weston_matrix *matrix,
740 pixman_region32_t *src)
741 {
742 pixman_box32_t *src_rects, *dest_rects;
743 int nrects, i;
744
745 src_rects = pixman_region32_rectangles(src, &nrects);
746 dest_rects = malloc(nrects * sizeof(*dest_rects));
747 if (!dest_rects)
748 return;
749
750 for (i = 0; i < nrects; i++) {
751 struct weston_vector vec1 = {{
752 src_rects[i].x1, src_rects[i].y1, 0, 1
753 }};
754 weston_matrix_transform(matrix, &vec1);
755 vec1.f[0] /= vec1.f[3];
756 vec1.f[1] /= vec1.f[3];
757
758 struct weston_vector vec2 = {{
759 src_rects[i].x2, src_rects[i].y2, 0, 1
760 }};
761 weston_matrix_transform(matrix, &vec2);
762 vec2.f[0] /= vec2.f[3];
763 vec2.f[1] /= vec2.f[3];
764
765 if (vec1.f[0] < vec2.f[0]) {
766 dest_rects[i].x1 = floor(vec1.f[0]);
767 dest_rects[i].x2 = ceil(vec2.f[0]);
768 } else {
769 dest_rects[i].x1 = floor(vec2.f[0]);
770 dest_rects[i].x2 = ceil(vec1.f[0]);
771 }
772
773 if (vec1.f[1] < vec2.f[1]) {
774 dest_rects[i].y1 = floor(vec1.f[1]);
775 dest_rects[i].y2 = ceil(vec2.f[1]);
776 } else {
777 dest_rects[i].y1 = floor(vec2.f[1]);
778 dest_rects[i].y2 = ceil(vec1.f[1]);
779 }
780 }
781
782 pixman_region32_clear(dest);
783 pixman_region32_init_rects(dest, dest_rects, nrects);
784 free(dest_rects);
785 }
786
787 /** Transform a region to buffer coordinates
788 *
789 * \param width Surface width.
790 * \param height Surface height.
791 * \param transform Buffer transform.
792 * \param scale Buffer scale.
793 * \param[in] src Region in surface coordinates.
794 * \param[out] dest Resulting region in buffer coordinates.
795 *
796 * Converts the given surface-local region to buffer coordinates
797 * according to the given buffer transform and scale.
798 * This ignores wp_viewport.
799 *
800 * The given width and height must be the result of inverse scaled and
801 * inverse transformed buffer size.
802 *
803 * src and dest are allowed to point to the same memory for in-place conversion.
804 */
805 WL_EXPORT void
weston_transformed_region(int width,int height,enum wl_output_transform transform,int32_t scale,pixman_region32_t * src,pixman_region32_t * dest)806 weston_transformed_region(int width, int height,
807 enum wl_output_transform transform,
808 int32_t scale,
809 pixman_region32_t *src, pixman_region32_t *dest)
810 {
811 pixman_box32_t *src_rects, *dest_rects;
812 int nrects, i;
813
814 if (transform == WL_OUTPUT_TRANSFORM_NORMAL && scale == 1) {
815 if (src != dest)
816 pixman_region32_copy(dest, src);
817 return;
818 }
819
820 src_rects = pixman_region32_rectangles(src, &nrects);
821 dest_rects = malloc(nrects * sizeof(*dest_rects));
822 if (!dest_rects)
823 return;
824
825 if (transform == WL_OUTPUT_TRANSFORM_NORMAL) {
826 memcpy(dest_rects, src_rects, nrects * sizeof(*dest_rects));
827 } else {
828 for (i = 0; i < nrects; i++) {
829 switch (transform) {
830 default:
831 case WL_OUTPUT_TRANSFORM_NORMAL:
832 dest_rects[i].x1 = src_rects[i].x1;
833 dest_rects[i].y1 = src_rects[i].y1;
834 dest_rects[i].x2 = src_rects[i].x2;
835 dest_rects[i].y2 = src_rects[i].y2;
836 break;
837 case WL_OUTPUT_TRANSFORM_90:
838 dest_rects[i].x1 = src_rects[i].y1;
839 dest_rects[i].y1 = width - src_rects[i].x2;
840 dest_rects[i].x2 = src_rects[i].y2;
841 dest_rects[i].y2 = width - src_rects[i].x1;
842 break;
843 case WL_OUTPUT_TRANSFORM_180:
844 dest_rects[i].x1 = width - src_rects[i].x2;
845 dest_rects[i].y1 = height - src_rects[i].y2;
846 dest_rects[i].x2 = width - src_rects[i].x1;
847 dest_rects[i].y2 = height - src_rects[i].y1;
848 break;
849 case WL_OUTPUT_TRANSFORM_270:
850 dest_rects[i].x1 = height - src_rects[i].y2;
851 dest_rects[i].y1 = src_rects[i].x1;
852 dest_rects[i].x2 = height - src_rects[i].y1;
853 dest_rects[i].y2 = src_rects[i].x2;
854 break;
855 case WL_OUTPUT_TRANSFORM_FLIPPED:
856 dest_rects[i].x1 = width - src_rects[i].x2;
857 dest_rects[i].y1 = src_rects[i].y1;
858 dest_rects[i].x2 = width - src_rects[i].x1;
859 dest_rects[i].y2 = src_rects[i].y2;
860 break;
861 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
862 dest_rects[i].x1 = src_rects[i].y1;
863 dest_rects[i].y1 = src_rects[i].x1;
864 dest_rects[i].x2 = src_rects[i].y2;
865 dest_rects[i].y2 = src_rects[i].x2;
866 break;
867 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
868 dest_rects[i].x1 = src_rects[i].x1;
869 dest_rects[i].y1 = height - src_rects[i].y2;
870 dest_rects[i].x2 = src_rects[i].x2;
871 dest_rects[i].y2 = height - src_rects[i].y1;
872 break;
873 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
874 dest_rects[i].x1 = height - src_rects[i].y2;
875 dest_rects[i].y1 = width - src_rects[i].x2;
876 dest_rects[i].x2 = height - src_rects[i].y1;
877 dest_rects[i].y2 = width - src_rects[i].x1;
878 break;
879 }
880 }
881 }
882
883 if (scale != 1) {
884 for (i = 0; i < nrects; i++) {
885 dest_rects[i].x1 *= scale;
886 dest_rects[i].x2 *= scale;
887 dest_rects[i].y1 *= scale;
888 dest_rects[i].y2 *= scale;
889 }
890 }
891
892 pixman_region32_clear(dest);
893 pixman_region32_init_rects(dest, dest_rects, nrects);
894 free(dest_rects);
895 }
896
897 static void
viewport_surface_to_buffer(struct weston_surface * surface,float sx,float sy,float * bx,float * by)898 viewport_surface_to_buffer(struct weston_surface *surface,
899 float sx, float sy, float *bx, float *by)
900 {
901 struct weston_buffer_viewport *vp = &surface->buffer_viewport;
902 double src_width, src_height;
903 double src_x, src_y;
904
905 if (vp->buffer.src_width == wl_fixed_from_int(-1)) {
906 if (vp->surface.width == -1) {
907 *bx = sx;
908 *by = sy;
909 return;
910 }
911
912 src_x = 0.0;
913 src_y = 0.0;
914 src_width = surface->width_from_buffer;
915 src_height = surface->height_from_buffer;
916 } else {
917 src_x = wl_fixed_to_double(vp->buffer.src_x);
918 src_y = wl_fixed_to_double(vp->buffer.src_y);
919 src_width = wl_fixed_to_double(vp->buffer.src_width);
920 src_height = wl_fixed_to_double(vp->buffer.src_height);
921 }
922
923 *bx = sx * src_width / surface->width + src_x;
924 *by = sy * src_height / surface->height + src_y;
925 }
926
927 WL_EXPORT void
weston_surface_to_buffer_float(struct weston_surface * surface,float sx,float sy,float * bx,float * by)928 weston_surface_to_buffer_float(struct weston_surface *surface,
929 float sx, float sy, float *bx, float *by)
930 {
931 struct weston_buffer_viewport *vp = &surface->buffer_viewport;
932
933 /* first transform coordinates if the viewport is set */
934 viewport_surface_to_buffer(surface, sx, sy, bx, by);
935
936 weston_transformed_coord(surface->width_from_buffer,
937 surface->height_from_buffer,
938 vp->buffer.transform, vp->buffer.scale,
939 *bx, *by, bx, by);
940 }
941
942 /** Transform a rectangle from surface coordinates to buffer coordinates
943 *
944 * \param surface The surface to fetch wp_viewport and buffer transformation
945 * from.
946 * \param rect The rectangle to transform.
947 * \return The transformed rectangle.
948 *
949 * Viewport and buffer transformations can only do translation, scaling,
950 * and rotations in 90-degree steps. Therefore the only loss in the
951 * conversion is coordinate rounding.
952 *
953 * However, some coordinate rounding takes place as an intermediate
954 * step before the buffer scale factor is applied, so the rectangle
955 * boundary may not be exactly as expected.
956 *
957 * This is OK for damage tracking since a little extra coverage is
958 * not a problem.
959 */
960 WL_EXPORT pixman_box32_t
weston_surface_to_buffer_rect(struct weston_surface * surface,pixman_box32_t rect)961 weston_surface_to_buffer_rect(struct weston_surface *surface,
962 pixman_box32_t rect)
963 {
964 struct weston_buffer_viewport *vp = &surface->buffer_viewport;
965 float xf, yf;
966
967 /* first transform box coordinates if the viewport is set */
968 viewport_surface_to_buffer(surface, rect.x1, rect.y1, &xf, &yf);
969 rect.x1 = floorf(xf);
970 rect.y1 = floorf(yf);
971
972 viewport_surface_to_buffer(surface, rect.x2, rect.y2, &xf, &yf);
973 rect.x2 = ceilf(xf);
974 rect.y2 = ceilf(yf);
975
976 return weston_transformed_rect(surface->width_from_buffer,
977 surface->height_from_buffer,
978 vp->buffer.transform, vp->buffer.scale,
979 rect);
980 }
981
982 /** Transform a region from surface coordinates to buffer coordinates
983 *
984 * \param surface The surface to fetch wp_viewport and buffer transformation
985 * from.
986 * \param[in] surface_region The region in surface coordinates.
987 * \param[out] buffer_region The region converted to buffer coordinates.
988 *
989 * Buffer_region must be init'd, but will be completely overwritten.
990 *
991 * Viewport and buffer transformations can only do translation, scaling,
992 * and rotations in 90-degree steps. Therefore the only loss in the
993 * conversion is from the coordinate rounding that takes place in
994 * \ref weston_surface_to_buffer_rect.
995 *
996 */
997 WL_EXPORT void
weston_surface_to_buffer_region(struct weston_surface * surface,pixman_region32_t * surface_region,pixman_region32_t * buffer_region)998 weston_surface_to_buffer_region(struct weston_surface *surface,
999 pixman_region32_t *surface_region,
1000 pixman_region32_t *buffer_region)
1001 {
1002 pixman_box32_t *src_rects, *dest_rects;
1003 int nrects, i;
1004
1005 src_rects = pixman_region32_rectangles(surface_region, &nrects);
1006 dest_rects = malloc(nrects * sizeof(*dest_rects));
1007 if (!dest_rects)
1008 return;
1009
1010 for (i = 0; i < nrects; i++) {
1011 dest_rects[i] = weston_surface_to_buffer_rect(surface,
1012 src_rects[i]);
1013 }
1014
1015 pixman_region32_fini(buffer_region);
1016 pixman_region32_init_rects(buffer_region, dest_rects, nrects);
1017 free(dest_rects);
1018 }
1019
1020 WL_EXPORT void
weston_view_move_to_plane(struct weston_view * view,struct weston_plane * plane)1021 weston_view_move_to_plane(struct weston_view *view,
1022 struct weston_plane *plane)
1023 {
1024 if (view->plane == plane)
1025 return;
1026
1027 weston_view_damage_below(view);
1028 view->plane = plane;
1029 weston_surface_damage(view->surface);
1030 }
1031
1032 /** Inflict damage on the plane where the view is visible.
1033 *
1034 * \param view The view that causes the damage.
1035 *
1036 * If the view is currently on a plane (including the primary plane),
1037 * take the view's boundingbox, subtract all the opaque views that cover it,
1038 * and add the remaining region as damage to the plane. This corresponds
1039 * to the damage inflicted to the plane if this view disappeared.
1040 *
1041 * A repaint is scheduled for this view.
1042 *
1043 * The region of all opaque views covering this view is stored in
1044 * weston_view::clip and updated by view_accumulate_damage() during
1045 * weston_output_repaint(). Specifically, that region matches the
1046 * scenegraph as it was last painted.
1047 */
1048 WL_EXPORT void
weston_view_damage_below(struct weston_view * view)1049 weston_view_damage_below(struct weston_view *view)
1050 {
1051 pixman_region32_t damage;
1052
1053 pixman_region32_init(&damage);
1054 pixman_region32_subtract(&damage, &view->transform.boundingbox,
1055 &view->clip);
1056 if (view->plane)
1057 pixman_region32_union(&view->plane->damage,
1058 &view->plane->damage, &damage);
1059 pixman_region32_fini(&damage);
1060 weston_view_schedule_repaint(view);
1061 }
1062
1063 /** Send wl_surface.enter/leave events
1064 *
1065 * \param surface The surface.
1066 * \param head A head of the entered/left output.
1067 * \param enter True if entered.
1068 * \param leave True if left.
1069 *
1070 * Send the enter/leave events for all protocol objects bound to the given
1071 * output by the client owning the surface.
1072 */
1073 static void
weston_surface_send_enter_leave(struct weston_surface * surface,struct weston_head * head,bool enter,bool leave)1074 weston_surface_send_enter_leave(struct weston_surface *surface,
1075 struct weston_head *head,
1076 bool enter,
1077 bool leave)
1078 {
1079 struct wl_resource *wloutput;
1080 struct wl_client *client;
1081
1082 assert(enter != leave);
1083
1084 client = wl_resource_get_client(surface->resource);
1085 wl_resource_for_each(wloutput, &head->resource_list) {
1086 if (wl_resource_get_client(wloutput) != client)
1087 continue;
1088
1089 if (enter)
1090 wl_surface_send_enter(surface->resource, wloutput);
1091 if (leave)
1092 wl_surface_send_leave(surface->resource, wloutput);
1093 }
1094 }
1095
1096 static void
weston_surface_compute_protection(struct protected_surface * psurface)1097 weston_surface_compute_protection(struct protected_surface *psurface)
1098 {
1099 enum weston_hdcp_protection min_protection;
1100 bool min_protection_valid = false;
1101 struct weston_surface *surface = psurface->surface;
1102 struct weston_output *output;
1103
1104 wl_list_for_each(output, &surface->compositor->output_list, link)
1105 if (surface->output_mask & (1u << output->id)) {
1106 /*
1107 * If the content-protection is enabled with protection
1108 * mode as RELAXED for a surface, and if
1109 * content-recording features like: screen-shooter,
1110 * recorder, screen-sharing, etc are on, then notify the
1111 * client, that the protection is disabled.
1112 *
1113 * Note: If the protection mode is ENFORCED then there
1114 * is no need to bother the client as the renderer takes
1115 * care of censoring the visibility of the protected
1116 * content.
1117 */
1118
1119 if (output->disable_planes > 0 &&
1120 surface->protection_mode == WESTON_SURFACE_PROTECTION_MODE_RELAXED) {
1121 min_protection = WESTON_HDCP_DISABLE;
1122 min_protection_valid = true;
1123 break;
1124 }
1125 if (!min_protection_valid) {
1126 min_protection = output->current_protection;
1127 min_protection_valid = true;
1128 }
1129 if (output->current_protection < min_protection)
1130 min_protection = output->current_protection;
1131 }
1132 if (!min_protection_valid)
1133 min_protection = WESTON_HDCP_DISABLE;
1134
1135 surface->current_protection = min_protection;
1136
1137 weston_protected_surface_send_event(psurface, surface->current_protection);
1138 }
1139
1140 static void
notify_surface_protection_change(void * data)1141 notify_surface_protection_change(void *data)
1142 {
1143 struct weston_compositor *compositor = data;
1144 struct content_protection *cp;
1145 struct protected_surface *psurface;
1146
1147 cp = compositor->content_protection;
1148 cp->surface_protection_update = NULL;
1149
1150 /* Notify the clients, whose surfaces are changed */
1151 wl_list_for_each(psurface, &cp->protected_list, link)
1152 if (psurface && psurface->surface)
1153 weston_surface_compute_protection(psurface);
1154 }
1155
1156 /**
1157 * \param compositor weston_compositor
1158 *
1159 * Schedule an idle task to notify surface about the update in protection,
1160 * if not already scheduled.
1161 */
1162 static void
weston_schedule_surface_protection_update(struct weston_compositor * compositor)1163 weston_schedule_surface_protection_update(struct weston_compositor *compositor)
1164 {
1165 struct content_protection *cp = compositor->content_protection;
1166 struct wl_event_loop *loop;
1167
1168 if (!cp || cp->surface_protection_update)
1169 return;
1170 loop = wl_display_get_event_loop(compositor->wl_display);
1171 cp->surface_protection_update = wl_event_loop_add_idle(loop,
1172 notify_surface_protection_change,
1173 compositor);
1174 }
1175
1176 /**
1177 * \param es The surface
1178 * \param mask The new set of outputs for the surface
1179 *
1180 * Sets the surface's set of outputs to the ones specified by
1181 * the new output mask provided. Identifies the outputs that
1182 * have changed, the posts enter and leave events for these
1183 * outputs as appropriate.
1184 */
1185 static void
weston_surface_update_output_mask(struct weston_surface * es,uint32_t mask)1186 weston_surface_update_output_mask(struct weston_surface *es, uint32_t mask)
1187 {
1188 LOG_INFO("update surface %p output mask %x", es, mask);
1189 uint32_t different = es->output_mask ^ mask;
1190 uint32_t entered = mask & different;
1191 uint32_t left = es->output_mask & different;
1192 uint32_t output_bit;
1193 struct weston_output *output;
1194 struct weston_head *head;
1195
1196 es->output_mask = mask;
1197 if (es->resource == NULL)
1198 return;
1199 if (different == 0)
1200 return;
1201
1202 wl_list_for_each(output, &es->compositor->output_list, link) {
1203 output_bit = 1u << output->id;
1204 if (!(output_bit & different))
1205 continue;
1206
1207 wl_list_for_each(head, &output->head_list, output_link) {
1208 weston_surface_send_enter_leave(es, head,
1209 output_bit & entered,
1210 output_bit & left);
1211 }
1212 }
1213 /*
1214 * Change in surfaces' output mask might trigger a change in its
1215 * protection.
1216 */
1217 weston_schedule_surface_protection_update(es->compositor);
1218 }
1219
1220 static void
notify_view_output_destroy(struct wl_listener * listener,void * data)1221 notify_view_output_destroy(struct wl_listener *listener, void *data)
1222 {
1223 struct weston_view *view =
1224 container_of(listener,
1225 struct weston_view, output_destroy_listener);
1226
1227 view->output = NULL;
1228 view->output_destroy_listener.notify = NULL;
1229 }
1230
1231 /** Set the primary output of the view
1232 *
1233 * \param view The view whose primary output to set
1234 * \param output The new primary output for the view
1235 *
1236 * Set \a output to be the primary output of the \a view.
1237 *
1238 * Notice that the assignment may be temporary; the primary output could be
1239 * automatically changed. Hence, one cannot rely on the value persisting.
1240 *
1241 * Passing NULL as /a output will set the primary output to NULL.
1242 */
1243 WL_EXPORT void
weston_view_set_output(struct weston_view * view,struct weston_output * output)1244 weston_view_set_output(struct weston_view *view, struct weston_output *output)
1245 {
1246 if (view->output_destroy_listener.notify) {
1247 wl_list_remove(&view->output_destroy_listener.link);
1248 view->output_destroy_listener.notify = NULL;
1249 }
1250 view->output = output;
1251 if (output) {
1252 view->output_destroy_listener.notify =
1253 notify_view_output_destroy;
1254 wl_signal_add(&output->destroy_signal,
1255 &view->output_destroy_listener);
1256 }
1257 }
1258
1259 /** Recalculate which output(s) the surface has views displayed on
1260 *
1261 * \param es The surface to remap to outputs
1262 *
1263 * Finds the output that is showing the largest amount of one
1264 * of the surface's various views. This output becomes the
1265 * surface's primary output for vsync and frame callback purposes.
1266 *
1267 * Also notes all outputs of all of the surface's views
1268 * in the output_mask for the surface.
1269 */
1270 static void
weston_surface_assign_output(struct weston_surface * es)1271 weston_surface_assign_output(struct weston_surface *es)
1272 {
1273 LOG_ENTER();
1274 struct weston_output *new_output;
1275 struct weston_view *view;
1276 pixman_region32_t region;
1277 uint32_t max, area, mask;
1278 pixman_box32_t *e;
1279
1280 new_output = NULL;
1281 max = 0;
1282 mask = 0;
1283 pixman_region32_init(®ion);
1284 wl_list_for_each(view, &es->views, surface_link) {
1285 if (!view->output)
1286 continue;
1287
1288 pixman_region32_intersect(®ion, &view->transform.boundingbox,
1289 &view->output->region);
1290
1291 e = pixman_region32_extents(®ion);
1292 area = (e->x2 - e->x1) * (e->y2 - e->y1);
1293
1294 mask |= view->output_mask;
1295
1296 if (area >= max) {
1297 new_output = view->output;
1298 max = area;
1299 }
1300 }
1301 pixman_region32_fini(®ion);
1302
1303 es->output = new_output;
1304 weston_surface_update_output_mask(es, mask);
1305 LOG_EXIT();
1306 }
1307
1308 /** Recalculate which output(s) the view is displayed on
1309 *
1310 * \param ev The view to remap to outputs
1311 *
1312 * Identifies the set of outputs that the view is visible on,
1313 * noting them into the output_mask. The output that the view
1314 * is most visible on is set as the view's primary output.
1315 *
1316 * Also does the same for the view's surface. See
1317 * weston_surface_assign_output().
1318 */
1319 static void
weston_view_assign_output(struct weston_view * ev)1320 weston_view_assign_output(struct weston_view *ev)
1321 {
1322 LOG_ENTER();
1323 struct weston_compositor *ec = ev->surface->compositor;
1324 struct weston_output *output, *new_output;
1325 pixman_region32_t region;
1326 uint32_t max, area, mask;
1327 pixman_box32_t *e;
1328
1329 new_output = NULL;
1330 max = 0;
1331 mask = 0;
1332 pixman_region32_init(®ion);
1333 wl_list_for_each(output, &ec->output_list, link) {
1334 if (output->destroying)
1335 continue;
1336
1337 pixman_region32_intersect(®ion, &ev->transform.boundingbox,
1338 &output->region);
1339
1340 e = pixman_region32_extents(®ion);
1341 area = (e->x2 - e->x1) * (e->y2 - e->y1);
1342
1343 if (area > 0)
1344 mask |= 1u << output->id;
1345
1346 if (area >= max) {
1347 new_output = output;
1348 max = area;
1349 }
1350 }
1351 pixman_region32_fini(®ion);
1352
1353 weston_view_set_output(ev, new_output);
1354 ev->output_mask = mask;
1355
1356 weston_surface_assign_output(ev->surface);
1357 LOG_EXIT();
1358 }
1359
1360 static void
weston_view_to_view_map(struct weston_view * from,struct weston_view * to,int from_x,int from_y,int * to_x,int * to_y)1361 weston_view_to_view_map(struct weston_view *from, struct weston_view *to,
1362 int from_x, int from_y, int *to_x, int *to_y)
1363 {
1364 float x, y;
1365
1366 weston_view_to_global_float(from, from_x, from_y, &x, &y);
1367 weston_view_from_global_float(to, x, y, &x, &y);
1368
1369 *to_x = round(x);
1370 *to_y = round(y);
1371 }
1372
1373 static void
weston_view_transfer_scissor(struct weston_view * from,struct weston_view * to)1374 weston_view_transfer_scissor(struct weston_view *from, struct weston_view *to)
1375 {
1376 pixman_box32_t *a;
1377 pixman_box32_t b;
1378
1379 a = pixman_region32_extents(&from->geometry.scissor);
1380
1381 weston_view_to_view_map(from, to, a->x1, a->y1, &b.x1, &b.y1);
1382 weston_view_to_view_map(from, to, a->x2, a->y2, &b.x2, &b.y2);
1383
1384 pixman_region32_fini(&to->geometry.scissor);
1385 pixman_region32_init_with_extents(&to->geometry.scissor, &b);
1386 }
1387
1388 static void
view_compute_bbox(struct weston_view * view,const pixman_box32_t * inbox,pixman_region32_t * bbox)1389 view_compute_bbox(struct weston_view *view, const pixman_box32_t *inbox,
1390 pixman_region32_t *bbox)
1391 {
1392 float min_x = HUGE_VALF, min_y = HUGE_VALF;
1393 float max_x = -HUGE_VALF, max_y = -HUGE_VALF;
1394 int32_t s[4][2] = {
1395 { inbox->x1, inbox->y1 },
1396 { inbox->x1, inbox->y2 },
1397 { inbox->x2, inbox->y1 },
1398 { inbox->x2, inbox->y2 },
1399 };
1400 float int_x, int_y;
1401 int i;
1402
1403 if (inbox->x1 == inbox->x2 || inbox->y1 == inbox->y2) {
1404 /* avoid rounding empty bbox to 1x1 */
1405 pixman_region32_init(bbox);
1406 return;
1407 }
1408
1409 for (i = 0; i < 4; ++i) {
1410 float x, y;
1411 weston_view_to_global_float(view, s[i][0], s[i][1], &x, &y);
1412 if (x < min_x)
1413 min_x = x;
1414 if (x > max_x)
1415 max_x = x;
1416 if (y < min_y)
1417 min_y = y;
1418 if (y > max_y)
1419 max_y = y;
1420 }
1421
1422 int_x = floorf(min_x);
1423 int_y = floorf(min_y);
1424 pixman_region32_init_rect(bbox, int_x, int_y,
1425 ceilf(max_x) - int_x, ceilf(max_y) - int_y);
1426 }
1427
1428 static void
weston_view_update_transform_disable(struct weston_view * view)1429 weston_view_update_transform_disable(struct weston_view *view)
1430 {
1431 view->transform.enabled = 0;
1432
1433 /* round off fractions when not transformed */
1434 view->geometry.x = roundf(view->geometry.x);
1435 view->geometry.y = roundf(view->geometry.y);
1436
1437 /* Otherwise identity matrix, but with x and y translation. */
1438 view->transform.position.matrix.type = WESTON_MATRIX_TRANSFORM_TRANSLATE;
1439 view->transform.position.matrix.d[12] = view->geometry.x;
1440 view->transform.position.matrix.d[13] = view->geometry.y;
1441
1442 view->transform.matrix = view->transform.position.matrix;
1443
1444 view->transform.inverse = view->transform.position.matrix;
1445 view->transform.inverse.d[12] = -view->geometry.x;
1446 view->transform.inverse.d[13] = -view->geometry.y;
1447
1448 pixman_region32_init_rect(&view->transform.boundingbox,
1449 0, 0,
1450 view->surface->width,
1451 view->surface->height);
1452 if (view->geometry.scissor_enabled)
1453 pixman_region32_intersect(&view->transform.boundingbox,
1454 &view->transform.boundingbox,
1455 &view->geometry.scissor);
1456
1457 pixman_region32_translate(&view->transform.boundingbox,
1458 view->geometry.x, view->geometry.y);
1459
1460 if (view->alpha == 1.0) {
1461 pixman_region32_copy(&view->transform.opaque,
1462 &view->surface->opaque);
1463 pixman_region32_translate(&view->transform.opaque,
1464 view->geometry.x,
1465 view->geometry.y);
1466 }
1467 }
1468
1469 static int
weston_view_update_transform_enable(struct weston_view * view)1470 weston_view_update_transform_enable(struct weston_view *view)
1471 {
1472 struct weston_view *parent = view->geometry.parent;
1473 struct weston_matrix *matrix = &view->transform.matrix;
1474 struct weston_matrix *inverse = &view->transform.inverse;
1475 struct weston_transform *tform;
1476 pixman_region32_t surfregion;
1477 const pixman_box32_t *surfbox;
1478
1479 view->transform.enabled = 1;
1480
1481 /* Otherwise identity matrix, but with x and y translation. */
1482 view->transform.position.matrix.type = WESTON_MATRIX_TRANSFORM_TRANSLATE;
1483 view->transform.position.matrix.d[12] = view->geometry.x;
1484 view->transform.position.matrix.d[13] = view->geometry.y;
1485
1486 weston_matrix_init(matrix);
1487 wl_list_for_each(tform, &view->geometry.transformation_list, link)
1488 weston_matrix_multiply(matrix, &tform->matrix);
1489
1490 if (parent)
1491 weston_matrix_multiply(matrix, &parent->transform.matrix);
1492
1493 if (weston_matrix_invert(inverse, matrix) < 0) {
1494 /* Oops, bad total transformation, not invertible */
1495 weston_log("error: weston_view %p"
1496 " transformation not invertible.\n", view);
1497 return -1;
1498 }
1499
1500 if (view->alpha == 1.0 &&
1501 matrix->type == WESTON_MATRIX_TRANSFORM_TRANSLATE) {
1502 pixman_region32_copy(&view->transform.opaque,
1503 &view->surface->opaque);
1504 pixman_region32_translate(&view->transform.opaque,
1505 matrix->d[12],
1506 matrix->d[13]);
1507 }
1508
1509 pixman_region32_init_rect(&surfregion, 0, 0,
1510 view->surface->width, view->surface->height);
1511 if (view->geometry.scissor_enabled)
1512 pixman_region32_intersect(&surfregion, &surfregion,
1513 &view->geometry.scissor);
1514 surfbox = pixman_region32_extents(&surfregion);
1515
1516 view_compute_bbox(view, surfbox, &view->transform.boundingbox);
1517 pixman_region32_fini(&surfregion);
1518
1519 return 0;
1520 }
1521
1522 static struct weston_layer *
get_view_layer(struct weston_view * view)1523 get_view_layer(struct weston_view *view)
1524 {
1525 if (view->parent_view)
1526 return get_view_layer(view->parent_view);
1527 return view->layer_link.layer;
1528 }
1529
1530 WL_EXPORT void
weston_view_update_transform(struct weston_view * view)1531 weston_view_update_transform(struct weston_view *view)
1532 {
1533 LOG_ENTER();
1534 struct weston_view *parent = view->geometry.parent;
1535 struct weston_layer *layer;
1536 pixman_region32_t mask;
1537
1538 if (!view->transform.dirty) {
1539 LOG_EXIT();
1540 return;
1541 }
1542
1543 if (parent)
1544 weston_view_update_transform(parent);
1545
1546 view->transform.dirty = 0;
1547
1548 weston_view_damage_below(view);
1549
1550 pixman_region32_fini(&view->transform.boundingbox);
1551 pixman_region32_fini(&view->transform.opaque);
1552 pixman_region32_init(&view->transform.opaque);
1553
1554 /* transform.position is always in transformation_list */
1555 if (view->geometry.transformation_list.next ==
1556 &view->transform.position.link &&
1557 view->geometry.transformation_list.prev ==
1558 &view->transform.position.link &&
1559 !parent) {
1560 weston_view_update_transform_disable(view);
1561 } else {
1562 if (weston_view_update_transform_enable(view) < 0)
1563 weston_view_update_transform_disable(view);
1564 }
1565
1566 layer = get_view_layer(view);
1567 if (layer) {
1568 pixman_region32_init_with_extents(&mask, &layer->mask);
1569 pixman_region32_intersect(&view->transform.boundingbox,
1570 &view->transform.boundingbox, &mask);
1571 pixman_region32_intersect(&view->transform.opaque,
1572 &view->transform.opaque, &mask);
1573 pixman_region32_fini(&mask);
1574 }
1575
1576 if (parent) {
1577 if (parent->geometry.scissor_enabled) {
1578 view->geometry.scissor_enabled = true;
1579 weston_view_transfer_scissor(parent, view);
1580 } else {
1581 view->geometry.scissor_enabled = false;
1582 }
1583 }
1584
1585 weston_view_damage_below(view);
1586
1587 weston_view_assign_output(view);
1588
1589 wl_signal_emit(&view->surface->compositor->transform_signal,
1590 view->surface);
1591 LOG_EXIT();
1592 }
1593
1594 WL_EXPORT void
weston_view_geometry_dirty(struct weston_view * view)1595 weston_view_geometry_dirty(struct weston_view *view)
1596 {
1597 struct weston_view *child;
1598
1599 /*
1600 * The invariant: if view->geometry.dirty, then all views
1601 * in view->geometry.child_list have geometry.dirty too.
1602 * Corollary: if not parent->geometry.dirty, then all ancestors
1603 * are not dirty.
1604 */
1605
1606 if (view->transform.dirty)
1607 return;
1608
1609 view->transform.dirty = 1;
1610
1611 wl_list_for_each(child, &view->geometry.child_list,
1612 geometry.parent_link)
1613 weston_view_geometry_dirty(child);
1614 }
1615
1616 WL_EXPORT void
weston_view_to_global_fixed(struct weston_view * view,wl_fixed_t vx,wl_fixed_t vy,wl_fixed_t * x,wl_fixed_t * y)1617 weston_view_to_global_fixed(struct weston_view *view,
1618 wl_fixed_t vx, wl_fixed_t vy,
1619 wl_fixed_t *x, wl_fixed_t *y)
1620 {
1621 float xf, yf;
1622
1623 weston_view_to_global_float(view,
1624 wl_fixed_to_double(vx),
1625 wl_fixed_to_double(vy),
1626 &xf, &yf);
1627 *x = wl_fixed_from_double(xf);
1628 *y = wl_fixed_from_double(yf);
1629 }
1630
1631 WL_EXPORT void
weston_view_from_global_float(struct weston_view * view,float x,float y,float * vx,float * vy)1632 weston_view_from_global_float(struct weston_view *view,
1633 float x, float y, float *vx, float *vy)
1634 {
1635 if (view->transform.enabled) {
1636 struct weston_vector v = { { x, y, 0.0f, 1.0f } };
1637
1638 weston_matrix_transform(&view->transform.inverse, &v);
1639
1640 if (fabsf(v.f[3]) < 1e-6) {
1641 weston_log("warning: numerical instability in "
1642 "weston_view_from_global(), divisor = %g\n",
1643 v.f[3]);
1644 *vx = 0;
1645 *vy = 0;
1646 return;
1647 }
1648
1649 *vx = v.f[0] / v.f[3];
1650 *vy = v.f[1] / v.f[3];
1651 } else {
1652 *vx = x - view->geometry.x;
1653 *vy = y - view->geometry.y;
1654 }
1655 }
1656
1657 WL_EXPORT void
weston_view_from_global_fixed(struct weston_view * view,wl_fixed_t x,wl_fixed_t y,wl_fixed_t * vx,wl_fixed_t * vy)1658 weston_view_from_global_fixed(struct weston_view *view,
1659 wl_fixed_t x, wl_fixed_t y,
1660 wl_fixed_t *vx, wl_fixed_t *vy)
1661 {
1662 float vxf, vyf;
1663
1664 weston_view_from_global_float(view,
1665 wl_fixed_to_double(x),
1666 wl_fixed_to_double(y),
1667 &vxf, &vyf);
1668 *vx = wl_fixed_from_double(vxf);
1669 *vy = wl_fixed_from_double(vyf);
1670 }
1671
1672 WL_EXPORT void
weston_view_from_global(struct weston_view * view,int32_t x,int32_t y,int32_t * vx,int32_t * vy)1673 weston_view_from_global(struct weston_view *view,
1674 int32_t x, int32_t y, int32_t *vx, int32_t *vy)
1675 {
1676 float vxf, vyf;
1677
1678 weston_view_from_global_float(view, x, y, &vxf, &vyf);
1679 *vx = floorf(vxf);
1680 *vy = floorf(vyf);
1681 }
1682
1683 /**
1684 * \param surface The surface to be repainted
1685 *
1686 * Marks the output(s) that the surface is shown on as needing to be
1687 * repainted. See weston_output_schedule_repaint().
1688 */
1689 WL_EXPORT void
weston_surface_schedule_repaint(struct weston_surface * surface)1690 weston_surface_schedule_repaint(struct weston_surface *surface)
1691 {
1692 LOG_INFO("surface schedule repaint");
1693 struct weston_output *output;
1694
1695 wl_list_for_each(output, &surface->compositor->output_list, link)
1696 if (surface->output_mask & (1u << output->id))
1697 weston_output_schedule_repaint(output);
1698 }
1699
1700 /**
1701 * \param view The view to be repainted
1702 *
1703 * Marks the output(s) that the view is shown on as needing to be
1704 * repainted. See weston_output_schedule_repaint().
1705 */
1706 WL_EXPORT void
weston_view_schedule_repaint(struct weston_view * view)1707 weston_view_schedule_repaint(struct weston_view *view)
1708 {
1709 LOG_INFO("view schedule repaint");
1710 struct weston_output *output;
1711
1712 wl_list_for_each(output, &view->surface->compositor->output_list, link)
1713 if (view->output_mask & (1u << output->id))
1714 weston_output_schedule_repaint(output);
1715 }
1716
1717 /**
1718 * XXX: This function does it the wrong way.
1719 * surface->damage is the damage from the client, and causes
1720 * surface_flush_damage() to copy pixels. No window management action can
1721 * cause damage to the client-provided content, warranting re-upload!
1722 *
1723 * Instead of surface->damage, this function should record the damage
1724 * with all the views for this surface to avoid extraneous texture
1725 * uploads.
1726 */
1727 WL_EXPORT void
weston_surface_damage(struct weston_surface * surface)1728 weston_surface_damage(struct weston_surface *surface)
1729 {
1730 pixman_region32_union_rect(&surface->damage, &surface->damage,
1731 0, 0, surface->width,
1732 surface->height);
1733
1734 weston_surface_schedule_repaint(surface);
1735 }
1736
1737 WL_EXPORT void
weston_view_set_position(struct weston_view * view,float x,float y)1738 weston_view_set_position(struct weston_view *view, float x, float y)
1739 {
1740 if (view->geometry.x == x && view->geometry.y == y)
1741 return;
1742
1743 view->geometry.x = x;
1744 view->geometry.y = y;
1745 weston_view_geometry_dirty(view);
1746 }
1747
1748 static void
transform_parent_handle_parent_destroy(struct wl_listener * listener,void * data)1749 transform_parent_handle_parent_destroy(struct wl_listener *listener,
1750 void *data)
1751 {
1752 struct weston_view *view =
1753 container_of(listener, struct weston_view,
1754 geometry.parent_destroy_listener);
1755
1756 weston_view_set_transform_parent(view, NULL);
1757 }
1758
1759 WL_EXPORT void
weston_view_set_transform_parent(struct weston_view * view,struct weston_view * parent)1760 weston_view_set_transform_parent(struct weston_view *view,
1761 struct weston_view *parent)
1762 {
1763 if (view->geometry.parent) {
1764 wl_list_remove(&view->geometry.parent_destroy_listener.link);
1765 wl_list_remove(&view->geometry.parent_link);
1766
1767 if (!parent)
1768 view->geometry.scissor_enabled = false;
1769 }
1770
1771 view->geometry.parent = parent;
1772
1773 view->geometry.parent_destroy_listener.notify =
1774 transform_parent_handle_parent_destroy;
1775 if (parent) {
1776 wl_signal_add(&parent->destroy_signal,
1777 &view->geometry.parent_destroy_listener);
1778 wl_list_insert(&parent->geometry.child_list,
1779 &view->geometry.parent_link);
1780 }
1781
1782 weston_view_geometry_dirty(view);
1783 }
1784
1785 /** Set a clip mask rectangle on a view
1786 *
1787 * \param view The view to set the clip mask on.
1788 * \param x Top-left corner X coordinate of the clip rectangle.
1789 * \param y Top-left corner Y coordinate of the clip rectangle.
1790 * \param width Width of the clip rectangle, non-negative.
1791 * \param height Height of the clip rectangle, non-negative.
1792 *
1793 * A shell may set a clip mask rectangle on a view. Everything outside
1794 * the rectangle is cut away for input and output purposes: it is
1795 * not drawn and cannot be hit by hit-test based input like pointer
1796 * motion or touch-downs. Everything inside the rectangle will behave
1797 * normally. Clients are unaware of clipping.
1798 *
1799 * The rectangle is set in surface-local coordinates. Setting a clip
1800 * mask rectangle does not affect the view position, the view is positioned
1801 * as it would be without a clip. The clip also does not change
1802 * weston_surface::width,height.
1803 *
1804 * The clip mask rectangle is part of transformation inheritance
1805 * (weston_view_set_transform_parent()). A clip set in the root of the
1806 * transformation inheritance tree will affect all views in the tree.
1807 * A clip can be set only on the root view. Attempting to set a clip
1808 * on view that has a transformation parent will fail. Assigning a parent
1809 * to a view that has a clip set will cause the clip to be forgotten.
1810 *
1811 * Because the clip mask is an axis-aligned rectangle, it poses restrictions
1812 * on the additional transformations in the child views. These transformations
1813 * may not rotate the coordinate axes, i.e., only translation and scaling
1814 * are allowed. Violating this restriction causes the clipping to malfunction.
1815 * Furthermore, using scaling may cause rounding errors in child clipping.
1816 *
1817 * The clip mask rectangle is not automatically adjusted based on
1818 * wl_surface.attach dx and dy arguments.
1819 *
1820 * A clip mask rectangle can be set only if the compositor capability
1821 * WESTON_CAP_VIEW_CLIP_MASK is present.
1822 *
1823 * This function sets the clip mask rectangle and schedules a repaint for
1824 * the view.
1825 */
1826 WL_EXPORT void
weston_view_set_mask(struct weston_view * view,int x,int y,int width,int height)1827 weston_view_set_mask(struct weston_view *view,
1828 int x, int y, int width, int height)
1829 {
1830 struct weston_compositor *compositor = view->surface->compositor;
1831
1832 if (!(compositor->capabilities & WESTON_CAP_VIEW_CLIP_MASK)) {
1833 weston_log("%s not allowed without capability!\n", __func__);
1834 return;
1835 }
1836
1837 if (view->geometry.parent) {
1838 weston_log("view %p has a parent, clip forbidden!\n", view);
1839 return;
1840 }
1841
1842 if (width < 0 || height < 0) {
1843 weston_log("%s: illegal args %d, %d, %d, %d\n", __func__,
1844 x, y, width, height);
1845 return;
1846 }
1847
1848 pixman_region32_fini(&view->geometry.scissor);
1849 pixman_region32_init_rect(&view->geometry.scissor, x, y, width, height);
1850 view->geometry.scissor_enabled = true;
1851 weston_view_geometry_dirty(view);
1852 weston_view_schedule_repaint(view);
1853 }
1854
1855 /** Remove the clip mask from a view
1856 *
1857 * \param view The view to remove the clip mask from.
1858 *
1859 * Removed the clip mask rectangle and schedules a repaint.
1860 *
1861 * \sa weston_view_set_mask
1862 */
1863 WL_EXPORT void
weston_view_set_mask_infinite(struct weston_view * view)1864 weston_view_set_mask_infinite(struct weston_view *view)
1865 {
1866 view->geometry.scissor_enabled = false;
1867 weston_view_geometry_dirty(view);
1868 weston_view_schedule_repaint(view);
1869 }
1870
1871 /* Check if view should be displayed
1872 *
1873 * The indicator is set manually when assigning
1874 * a view to a surface.
1875 *
1876 * This needs reworking. See the thread starting at:
1877 *
1878 * https://lists.freedesktop.org/archives/wayland-devel/2016-June/029656.html
1879 */
1880 WL_EXPORT bool
weston_view_is_mapped(struct weston_view * view)1881 weston_view_is_mapped(struct weston_view *view)
1882 {
1883 return view->is_mapped;
1884 }
1885
1886 /* Check if view is opaque in specified region
1887 *
1888 * \param view The view to check for opacity.
1889 * \param region The region to check for opacity, in view coordinates.
1890 *
1891 * Returns true if the view is opaque in the specified region, because view
1892 * alpha is 1.0 and either the opaque region set by the client contains the
1893 * specified region, or the buffer pixel format or solid color is opaque.
1894 */
1895 WL_EXPORT bool
weston_view_is_opaque(struct weston_view * ev,pixman_region32_t * region)1896 weston_view_is_opaque(struct weston_view *ev, pixman_region32_t *region)
1897 {
1898 pixman_region32_t r;
1899 bool ret = false;
1900
1901 if (ev->alpha < 1.0)
1902 return false;
1903
1904 if (ev->surface->is_opaque)
1905 return true;
1906
1907 if (ev->transform.dirty)
1908 return false;
1909
1910 pixman_region32_init(&r);
1911 pixman_region32_subtract(&r, region, &ev->transform.opaque);
1912
1913 if (!pixman_region32_not_empty(&r))
1914 ret = true;
1915
1916 pixman_region32_fini(&r);
1917
1918 return ret;
1919 }
1920
1921 /** Check if the view has a valid buffer available
1922 *
1923 * @param ev The view to check if it has a valid buffer.
1924 *
1925 * Returns true if the view has a valid buffer or false otherwise.
1926 */
1927 WL_EXPORT bool
weston_view_has_valid_buffer(struct weston_view * ev)1928 weston_view_has_valid_buffer(struct weston_view *ev)
1929 {
1930 return ev->surface->buffer_ref.buffer != NULL;
1931 }
1932
1933 /** Check if the view matches the entire output
1934 *
1935 * @param ev The view to check.
1936 * @param output The output to check against.
1937 *
1938 * Returns true if the view does indeed matches the entire output.
1939 */
1940 WL_EXPORT bool
weston_view_matches_output_entirely(struct weston_view * ev,struct weston_output * output)1941 weston_view_matches_output_entirely(struct weston_view *ev,
1942 struct weston_output *output)
1943 {
1944 pixman_box32_t *extents =
1945 pixman_region32_extents(&ev->transform.boundingbox);
1946
1947 if (extents->x1 != output->x ||
1948 extents->y1 != output->y ||
1949 extents->x2 != output->x + output->width ||
1950 extents->y2 != output->y + output->height)
1951 return false;
1952
1953 return true;
1954 }
1955
1956 /* Check if a surface has a view assigned to it
1957 *
1958 * The indicator is set manually when mapping
1959 * a surface and creating a view for it.
1960 *
1961 * This needs to go. See the thread starting at:
1962 *
1963 * https://lists.freedesktop.org/archives/wayland-devel/2016-June/029656.html
1964 *
1965 */
1966 WL_EXPORT bool
weston_surface_is_mapped(struct weston_surface * surface)1967 weston_surface_is_mapped(struct weston_surface *surface)
1968 {
1969 return surface->is_mapped;
1970 }
1971
1972 static void
surface_set_size(struct weston_surface * surface,int32_t width,int32_t height)1973 surface_set_size(struct weston_surface *surface, int32_t width, int32_t height)
1974 {
1975 LOG_INFO("set width = %d, height = %d", width, height);
1976 struct weston_view *view;
1977
1978 if (surface->width == width && surface->height == height)
1979 return;
1980
1981 surface->width = width;
1982 surface->height = height;
1983
1984 wl_list_for_each(view, &surface->views, surface_link)
1985 weston_view_geometry_dirty(view);
1986 }
1987
1988 WL_EXPORT void
weston_surface_set_size(struct weston_surface * surface,int32_t width,int32_t height)1989 weston_surface_set_size(struct weston_surface *surface,
1990 int32_t width, int32_t height)
1991 {
1992 assert(!surface->resource);
1993 surface_set_size(surface, width, height);
1994 }
1995
1996 static int
fixed_round_up_to_int(wl_fixed_t f)1997 fixed_round_up_to_int(wl_fixed_t f)
1998 {
1999 return wl_fixed_to_int(wl_fixed_from_int(1) - 1 + f);
2000 }
2001
2002 static void
convert_size_by_transform_scale(int32_t * width_out,int32_t * height_out,int32_t width,int32_t height,uint32_t transform,int32_t scale)2003 convert_size_by_transform_scale(int32_t *width_out, int32_t *height_out,
2004 int32_t width, int32_t height,
2005 uint32_t transform,
2006 int32_t scale)
2007 {
2008 assert(scale > 0);
2009
2010 switch (transform) {
2011 case WL_OUTPUT_TRANSFORM_NORMAL:
2012 case WL_OUTPUT_TRANSFORM_180:
2013 case WL_OUTPUT_TRANSFORM_FLIPPED:
2014 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
2015 *width_out = width / scale;
2016 *height_out = height / scale;
2017 break;
2018 case WL_OUTPUT_TRANSFORM_90:
2019 case WL_OUTPUT_TRANSFORM_270:
2020 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
2021 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
2022 *width_out = height / scale;
2023 *height_out = width / scale;
2024 break;
2025 default:
2026 assert(0 && "invalid transform");
2027 }
2028 }
2029
2030 static void
weston_surface_calculate_size_from_buffer(struct weston_surface * surface)2031 weston_surface_calculate_size_from_buffer(struct weston_surface *surface)
2032 {
2033 struct weston_buffer_viewport *vp = &surface->buffer_viewport;
2034
2035 if (!surface->buffer_ref.buffer) {
2036 surface->width_from_buffer = 0;
2037 surface->height_from_buffer = 0;
2038 return;
2039 }
2040
2041 convert_size_by_transform_scale(&surface->width_from_buffer,
2042 &surface->height_from_buffer,
2043 surface->buffer_ref.buffer->width,
2044 surface->buffer_ref.buffer->height,
2045 vp->buffer.transform,
2046 vp->buffer.scale);
2047 }
2048
2049 static void
weston_surface_update_size(struct weston_surface * surface)2050 weston_surface_update_size(struct weston_surface *surface)
2051 {
2052 struct weston_buffer_viewport *vp = &surface->buffer_viewport;
2053 int32_t width, height;
2054
2055 LOG_INFO("from buffer, width = %d, height = %d",
2056 surface->width_from_buffer, surface->height_from_buffer);
2057
2058 LOG_INFO("vp->surface, width = %d, height = %d",
2059 vp->surface.width, vp->surface.height);
2060
2061 width = surface->width_from_buffer;
2062 height = surface->height_from_buffer;
2063
2064 if (width != 0 && vp->surface.width != -1) {
2065 surface_set_size(surface,
2066 vp->surface.width, vp->surface.height);
2067 return;
2068 }
2069
2070 if (width != 0 && vp->buffer.src_width != wl_fixed_from_int(-1)) {
2071 int32_t w = fixed_round_up_to_int(vp->buffer.src_width);
2072 int32_t h = fixed_round_up_to_int(vp->buffer.src_height);
2073
2074 surface_set_size(surface, w ?: 1, h ?: 1);
2075 return;
2076 }
2077
2078 surface_set_size(surface, width, height);
2079 }
2080
2081 /** weston_compositor_get_time
2082 * \ingroup compositor
2083 */
2084 WL_EXPORT void
weston_compositor_get_time(struct timespec * time)2085 weston_compositor_get_time(struct timespec *time)
2086 {
2087 clock_gettime(CLOCK_REALTIME, time);
2088 }
2089
2090 /** weston_compositor_pick_view
2091 * \ingroup compositor
2092 */
2093 WL_EXPORT struct weston_view *
weston_compositor_pick_view(struct weston_compositor * compositor,wl_fixed_t x,wl_fixed_t y,wl_fixed_t * vx,wl_fixed_t * vy)2094 weston_compositor_pick_view(struct weston_compositor *compositor,
2095 wl_fixed_t x, wl_fixed_t y,
2096 wl_fixed_t *vx, wl_fixed_t *vy)
2097 {
2098 struct weston_view *view;
2099 wl_fixed_t view_x, view_y;
2100 int view_ix, view_iy;
2101 int ix = wl_fixed_to_int(x);
2102 int iy = wl_fixed_to_int(y);
2103
2104 wl_list_for_each(view, &compositor->view_list, link) {
2105 if (!pixman_region32_contains_point(
2106 &view->transform.boundingbox, ix, iy, NULL))
2107 continue;
2108
2109 weston_view_from_global_fixed(view, x, y, &view_x, &view_y);
2110 view_ix = wl_fixed_to_int(view_x);
2111 view_iy = wl_fixed_to_int(view_y);
2112
2113 if (!pixman_region32_contains_point(&view->surface->input,
2114 view_ix, view_iy, NULL))
2115 continue;
2116
2117 if (view->geometry.scissor_enabled &&
2118 !pixman_region32_contains_point(&view->geometry.scissor,
2119 view_ix, view_iy, NULL))
2120 continue;
2121
2122 *vx = view_x;
2123 *vy = view_y;
2124 return view;
2125 }
2126
2127 *vx = wl_fixed_from_int(-1000000);
2128 *vy = wl_fixed_from_int(-1000000);
2129 return NULL;
2130 }
2131
2132 static void
weston_compositor_repick(struct weston_compositor * compositor)2133 weston_compositor_repick(struct weston_compositor *compositor)
2134 {
2135 struct weston_seat *seat;
2136
2137 if (!compositor->session_active)
2138 return;
2139
2140 wl_list_for_each(seat, &compositor->seat_list, link)
2141 weston_seat_repick(seat);
2142 }
2143
2144 WL_EXPORT void
weston_view_unmap(struct weston_view * view)2145 weston_view_unmap(struct weston_view *view)
2146 {
2147 struct weston_seat *seat;
2148
2149 if (!weston_view_is_mapped(view))
2150 return;
2151
2152 weston_view_damage_below(view);
2153 weston_view_set_output(view, NULL);
2154 view->plane = NULL;
2155 view->is_mapped = false;
2156 weston_layer_entry_remove(&view->layer_link);
2157 wl_list_remove(&view->link);
2158 wl_list_init(&view->link);
2159 view->output_mask = 0;
2160 weston_surface_assign_output(view->surface);
2161
2162 if (weston_surface_is_mapped(view->surface))
2163 return;
2164
2165 wl_list_for_each(seat, &view->surface->compositor->seat_list, link) {
2166 struct weston_touch *touch = weston_seat_get_touch(seat);
2167 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
2168 struct weston_keyboard *keyboard =
2169 weston_seat_get_keyboard(seat);
2170
2171 if (keyboard && keyboard->focus == view->surface)
2172 weston_keyboard_set_focus(keyboard, NULL);
2173 if (pointer && pointer->focus == view)
2174 weston_pointer_clear_focus(pointer);
2175 if (touch && touch->focus == view)
2176 weston_touch_set_focus(touch, NULL);
2177 }
2178 }
2179
2180 WL_EXPORT void
weston_surface_unmap(struct weston_surface * surface)2181 weston_surface_unmap(struct weston_surface *surface)
2182 {
2183 struct weston_view *view;
2184
2185 surface->is_mapped = false;
2186 wl_list_for_each(view, &surface->views, surface_link)
2187 weston_view_unmap(view);
2188 surface->output = NULL;
2189 }
2190
2191 static void
weston_surface_reset_pending_buffer(struct weston_surface * surface)2192 weston_surface_reset_pending_buffer(struct weston_surface *surface)
2193 {
2194 weston_surface_state_set_buffer(&surface->pending, NULL);
2195 surface->pending.sx = 0;
2196 surface->pending.sy = 0;
2197 surface->pending.newly_attached = 0;
2198 surface->pending.buffer_viewport.changed = 0;
2199 }
2200
2201 WL_EXPORT void
weston_view_destroy(struct weston_view * view)2202 weston_view_destroy(struct weston_view *view)
2203 {
2204 wl_signal_emit(&view->destroy_signal, view);
2205
2206 assert(wl_list_empty(&view->geometry.child_list));
2207
2208 if (weston_view_is_mapped(view)) {
2209 weston_view_unmap(view);
2210 weston_compositor_build_view_list(view->surface->compositor);
2211 }
2212
2213 wl_list_remove(&view->link);
2214 weston_layer_entry_remove(&view->layer_link);
2215
2216 pixman_region32_fini(&view->clip);
2217 pixman_region32_fini(&view->geometry.scissor);
2218 pixman_region32_fini(&view->transform.boundingbox);
2219 pixman_region32_fini(&view->transform.opaque);
2220
2221 weston_view_set_transform_parent(view, NULL);
2222 weston_view_set_output(view, NULL);
2223
2224 wl_list_remove(&view->surface_link);
2225
2226 free(view);
2227 }
2228
2229 WL_EXPORT void
weston_surface_destroy(struct weston_surface * surface)2230 weston_surface_destroy(struct weston_surface *surface)
2231 {
2232 struct weston_frame_callback *cb, *next;
2233 struct weston_view *ev, *nv;
2234 struct weston_pointer_constraint *constraint, *next_constraint;
2235
2236 if (--surface->ref_count > 0)
2237 return;
2238
2239 assert(surface->resource == NULL);
2240
2241 wl_signal_emit(&surface->destroy_signal, surface);
2242
2243 assert(wl_list_empty(&surface->subsurface_list_pending));
2244 assert(wl_list_empty(&surface->subsurface_list));
2245
2246 wl_list_for_each_safe(ev, nv, &surface->views, surface_link)
2247 weston_view_destroy(ev);
2248
2249 weston_surface_state_fini(&surface->pending);
2250
2251 weston_buffer_reference(&surface->buffer_ref, NULL);
2252 weston_buffer_release_reference(&surface->buffer_release_ref, NULL);
2253
2254 pixman_region32_fini(&surface->damage);
2255 pixman_region32_fini(&surface->opaque);
2256 pixman_region32_fini(&surface->input);
2257
2258 wl_list_for_each_safe(cb, next, &surface->frame_callback_list, link)
2259 wl_resource_destroy(cb->resource);
2260
2261 weston_presentation_feedback_discard_list(&surface->feedback_list);
2262
2263 wl_list_for_each_safe(constraint, next_constraint,
2264 &surface->pointer_constraints,
2265 link)
2266 weston_pointer_constraint_destroy(constraint);
2267
2268 fd_clear(&surface->acquire_fence_fd);
2269
2270 free(surface);
2271 }
2272
2273 static void
destroy_surface(struct wl_resource * resource)2274 destroy_surface(struct wl_resource *resource)
2275 {
2276 struct weston_surface *surface = wl_resource_get_user_data(resource);
2277
2278 assert(surface);
2279
2280 /* Set the resource to NULL, since we don't want to leave a
2281 * dangling pointer if the surface was refcounted and survives
2282 * the weston_surface_destroy() call. */
2283 surface->resource = NULL;
2284
2285 if (surface->viewport_resource)
2286 wl_resource_set_user_data(surface->viewport_resource, NULL);
2287
2288 if (surface->synchronization_resource) {
2289 wl_resource_set_user_data(surface->synchronization_resource,
2290 NULL);
2291 }
2292
2293 weston_surface_destroy(surface);
2294 }
2295
2296 static void
weston_buffer_destroy_handler(struct wl_listener * listener,void * data)2297 weston_buffer_destroy_handler(struct wl_listener *listener, void *data)
2298 {
2299 struct weston_buffer *buffer =
2300 container_of(listener, struct weston_buffer, destroy_listener);
2301
2302 wl_signal_emit(&buffer->destroy_signal, buffer);
2303 free(buffer);
2304 }
2305
2306 WL_EXPORT struct weston_buffer *
weston_buffer_from_resource(struct wl_resource * resource)2307 weston_buffer_from_resource(struct wl_resource *resource)
2308 {
2309 struct weston_buffer *buffer;
2310 struct wl_listener *listener;
2311
2312 listener = wl_resource_get_destroy_listener(resource,
2313 weston_buffer_destroy_handler);
2314
2315 if (listener)
2316 return container_of(listener, struct weston_buffer,
2317 destroy_listener);
2318
2319 buffer = zalloc(sizeof *buffer);
2320 if (buffer == NULL)
2321 return NULL;
2322
2323 buffer->resource = resource;
2324 wl_signal_init(&buffer->destroy_signal);
2325 buffer->destroy_listener.notify = weston_buffer_destroy_handler;
2326 buffer->y_inverted = 1;
2327 wl_resource_add_destroy_listener(resource, &buffer->destroy_listener);
2328
2329 return buffer;
2330 }
2331
2332 static void
weston_buffer_reference_handle_destroy(struct wl_listener * listener,void * data)2333 weston_buffer_reference_handle_destroy(struct wl_listener *listener,
2334 void *data)
2335 {
2336 struct weston_buffer_reference *ref =
2337 container_of(listener, struct weston_buffer_reference,
2338 destroy_listener);
2339
2340 assert((struct weston_buffer *)data == ref->buffer);
2341 ref->buffer = NULL;
2342 }
2343
2344 WL_EXPORT void
weston_buffer_reference(struct weston_buffer_reference * ref,struct weston_buffer * buffer)2345 weston_buffer_reference(struct weston_buffer_reference *ref,
2346 struct weston_buffer *buffer)
2347 {
2348 if (ref->buffer && buffer != ref->buffer) {
2349 ref->buffer->busy_count--;
2350 if (ref->buffer->busy_count == 0) {
2351 assert(wl_resource_get_client(ref->buffer->resource));
2352 wl_buffer_send_release(ref->buffer->resource);
2353 }
2354 wl_list_remove(&ref->destroy_listener.link);
2355 }
2356
2357 if (buffer && buffer != ref->buffer) {
2358 buffer->busy_count++;
2359 wl_signal_add(&buffer->destroy_signal,
2360 &ref->destroy_listener);
2361 }
2362
2363 ref->buffer = buffer;
2364 ref->destroy_listener.notify = weston_buffer_reference_handle_destroy;
2365 }
2366
2367 static void
weston_buffer_release_reference_handle_destroy(struct wl_listener * listener,void * data)2368 weston_buffer_release_reference_handle_destroy(struct wl_listener *listener,
2369 void *data)
2370 {
2371 struct weston_buffer_release_reference *ref =
2372 container_of(listener, struct weston_buffer_release_reference,
2373 destroy_listener);
2374
2375 assert((struct wl_resource *)data == ref->buffer_release->resource);
2376 ref->buffer_release = NULL;
2377 }
2378
2379 static void
weston_buffer_release_destroy(struct weston_buffer_release * buffer_release)2380 weston_buffer_release_destroy(struct weston_buffer_release *buffer_release)
2381 {
2382 struct wl_resource *resource = buffer_release->resource;
2383 int release_fence_fd = buffer_release->fence_fd;
2384
2385 if (release_fence_fd >= 0) {
2386 zwp_linux_buffer_release_v1_send_fenced_release(
2387 resource, release_fence_fd);
2388 } else {
2389 zwp_linux_buffer_release_v1_send_immediate_release(
2390 resource);
2391 }
2392
2393 wl_resource_destroy(resource);
2394 }
2395
2396 WL_EXPORT void
weston_buffer_release_reference(struct weston_buffer_release_reference * ref,struct weston_buffer_release * buffer_release)2397 weston_buffer_release_reference(struct weston_buffer_release_reference *ref,
2398 struct weston_buffer_release *buffer_release)
2399 {
2400 if (buffer_release == ref->buffer_release)
2401 return;
2402
2403 if (ref->buffer_release) {
2404 ref->buffer_release->ref_count--;
2405 wl_list_remove(&ref->destroy_listener.link);
2406 if (ref->buffer_release->ref_count == 0)
2407 weston_buffer_release_destroy(ref->buffer_release);
2408 }
2409
2410 if (buffer_release) {
2411 buffer_release->ref_count++;
2412 wl_resource_add_destroy_listener(buffer_release->resource,
2413 &ref->destroy_listener);
2414 }
2415
2416 ref->buffer_release = buffer_release;
2417 ref->destroy_listener.notify =
2418 weston_buffer_release_reference_handle_destroy;
2419 }
2420
2421 WL_EXPORT void
weston_buffer_release_move(struct weston_buffer_release_reference * dest,struct weston_buffer_release_reference * src)2422 weston_buffer_release_move(struct weston_buffer_release_reference *dest,
2423 struct weston_buffer_release_reference *src)
2424 {
2425 weston_buffer_release_reference(dest, src->buffer_release);
2426 weston_buffer_release_reference(src, NULL);
2427 }
2428
2429 static void
weston_surface_attach(struct weston_surface * surface,struct weston_buffer * buffer)2430 weston_surface_attach(struct weston_surface *surface,
2431 struct weston_buffer *buffer)
2432 {
2433 weston_buffer_reference(&surface->buffer_ref, buffer);
2434
2435 if (!buffer) {
2436 if (weston_surface_is_mapped(surface))
2437 weston_surface_unmap(surface);
2438 }
2439
2440 surface->compositor->renderer->attach(surface, buffer);
2441
2442 weston_surface_calculate_size_from_buffer(surface);
2443 weston_presentation_feedback_discard_list(&surface->feedback_list);
2444 }
2445
2446 /** weston_compositor_damage_all
2447 * \ingroup compositor
2448 */
2449 WL_EXPORT void
weston_compositor_damage_all(struct weston_compositor * compositor)2450 weston_compositor_damage_all(struct weston_compositor *compositor)
2451 {
2452 struct weston_output *output;
2453
2454 wl_list_for_each(output, &compositor->output_list, link)
2455 weston_output_damage(output);
2456 }
2457
2458 /**
2459 * \ingroup output
2460 */
2461 WL_EXPORT void
weston_output_damage(struct weston_output * output)2462 weston_output_damage(struct weston_output *output)
2463 {
2464 struct weston_compositor *compositor = output->compositor;
2465
2466 pixman_region32_union(&compositor->primary_plane.damage,
2467 &compositor->primary_plane.damage,
2468 &output->region);
2469 weston_output_schedule_repaint(output);
2470 }
2471
2472 static void
surface_flush_damage(struct weston_surface * surface)2473 surface_flush_damage(struct weston_surface *surface)
2474 {
2475 if (surface->buffer_ref.buffer &&
2476 wl_shm_buffer_get(surface->buffer_ref.buffer->resource))
2477 surface->compositor->renderer->flush_damage(surface);
2478
2479 // OHOS remove timeline
2480 // if (pixman_region32_not_empty(&surface->damage))
2481 // TL_POINT(surface->compositor, "core_flush_damage", TLP_SURFACE(surface),
2482 // TLP_OUTPUT(surface->output), TLP_END);
2483
2484 pixman_region32_clear(&surface->damage);
2485 }
2486
2487 static void
view_accumulate_damage(struct weston_view * view,pixman_region32_t * opaque)2488 view_accumulate_damage(struct weston_view *view,
2489 pixman_region32_t *opaque)
2490 {
2491 pixman_region32_t damage;
2492
2493 pixman_region32_init(&damage);
2494 if (view->transform.enabled) {
2495 pixman_box32_t *extents;
2496
2497 extents = pixman_region32_extents(&view->surface->damage);
2498 view_compute_bbox(view, extents, &damage);
2499 } else {
2500 pixman_region32_copy(&damage, &view->surface->damage);
2501 pixman_region32_translate(&damage,
2502 view->geometry.x, view->geometry.y);
2503 }
2504
2505 pixman_region32_intersect(&damage, &damage,
2506 &view->transform.boundingbox);
2507 pixman_region32_subtract(&damage, &damage, opaque);
2508 pixman_region32_union(&view->plane->damage,
2509 &view->plane->damage, &damage);
2510 pixman_region32_fini(&damage);
2511 pixman_region32_copy(&view->clip, opaque);
2512 pixman_region32_union(opaque, opaque, &view->transform.opaque);
2513 }
2514
2515 static void
output_accumulate_damage(struct weston_output * output)2516 output_accumulate_damage(struct weston_output *output)
2517 {
2518 struct weston_compositor *ec = output->compositor;
2519 struct weston_plane *plane;
2520 struct weston_view *ev;
2521 pixman_region32_t opaque, clip;
2522
2523 pixman_region32_init(&clip);
2524
2525 wl_list_for_each(plane, &ec->plane_list, link) {
2526 pixman_region32_copy(&plane->clip, &clip);
2527
2528 pixman_region32_init(&opaque);
2529
2530 wl_list_for_each(ev, &ec->view_list, link) {
2531 if (ev->plane != plane)
2532 continue;
2533
2534 view_accumulate_damage(ev, &opaque);
2535 }
2536
2537 pixman_region32_union(&clip, &clip, &opaque);
2538 pixman_region32_fini(&opaque);
2539 }
2540
2541 pixman_region32_fini(&clip);
2542
2543 wl_list_for_each(ev, &ec->view_list, link)
2544 ev->surface->touched = false;
2545
2546 wl_list_for_each(ev, &ec->view_list, link) {
2547 /* Ignore views not visible on the current output */
2548 if (!(ev->output_mask & (1u << output->id)))
2549 continue;
2550 if (ev->surface->touched)
2551 continue;
2552 ev->surface->touched = true;
2553
2554 surface_flush_damage(ev->surface);
2555
2556 /* Both the renderer and the backend have seen the buffer
2557 * by now. If renderer needs the buffer, it has its own
2558 * reference set. If the backend wants to keep the buffer
2559 * around for migrating the surface into a non-primary plane
2560 * later, keep_buffer is true. Otherwise, drop the core
2561 * reference now, and allow early buffer release. This enables
2562 * clients to use single-buffering.
2563 */
2564 if (!ev->surface->keep_buffer) {
2565 weston_buffer_reference(&ev->surface->buffer_ref, NULL);
2566 weston_buffer_release_reference(
2567 &ev->surface->buffer_release_ref, NULL);
2568 }
2569 }
2570 }
2571
2572 static void
surface_stash_subsurface_views(struct weston_surface * surface)2573 surface_stash_subsurface_views(struct weston_surface *surface)
2574 {
2575 struct weston_subsurface *sub;
2576
2577 wl_list_for_each(sub, &surface->subsurface_list, parent_link) {
2578 if (sub->surface == surface)
2579 continue;
2580
2581 wl_list_insert_list(&sub->unused_views, &sub->surface->views);
2582 wl_list_init(&sub->surface->views);
2583
2584 surface_stash_subsurface_views(sub->surface);
2585 }
2586 }
2587
2588 static void
surface_free_unused_subsurface_views(struct weston_surface * surface)2589 surface_free_unused_subsurface_views(struct weston_surface *surface)
2590 {
2591 struct weston_subsurface *sub;
2592 struct weston_view *view, *nv;
2593
2594 wl_list_for_each(sub, &surface->subsurface_list, parent_link) {
2595 if (sub->surface == surface)
2596 continue;
2597
2598 wl_list_for_each_safe(view, nv, &sub->unused_views, surface_link) {
2599 weston_view_unmap (view);
2600 weston_view_destroy(view);
2601 }
2602
2603 surface_free_unused_subsurface_views(sub->surface);
2604 }
2605 }
2606
2607 static void
view_list_add_subsurface_view(struct weston_compositor * compositor,struct weston_subsurface * sub,struct weston_view * parent)2608 view_list_add_subsurface_view(struct weston_compositor *compositor,
2609 struct weston_subsurface *sub,
2610 struct weston_view *parent)
2611 {
2612 struct weston_subsurface *child;
2613 struct weston_view *view = NULL, *iv;
2614
2615 if (!weston_surface_is_mapped(sub->surface))
2616 return;
2617
2618 wl_list_for_each(iv, &sub->unused_views, surface_link) {
2619 if (iv->geometry.parent == parent) {
2620 view = iv;
2621 break;
2622 }
2623 }
2624
2625 if (view) {
2626 /* Put it back in the surface's list of views */
2627 wl_list_remove(&view->surface_link);
2628 wl_list_insert(&sub->surface->views, &view->surface_link);
2629 } else {
2630 view = weston_view_create(sub->surface);
2631 weston_view_set_position(view,
2632 sub->position.x,
2633 sub->position.y);
2634 weston_view_set_transform_parent(view, parent);
2635 }
2636
2637 view->parent_view = parent;
2638 weston_view_update_transform(view);
2639 view->is_mapped = true;
2640
2641 if (wl_list_empty(&sub->surface->subsurface_list)) {
2642 wl_list_insert(compositor->view_list.prev, &view->link);
2643 return;
2644 }
2645
2646 wl_list_for_each(child, &sub->surface->subsurface_list, parent_link) {
2647 if (child->surface == sub->surface)
2648 wl_list_insert(compositor->view_list.prev, &view->link);
2649 else
2650 view_list_add_subsurface_view(compositor, child, view);
2651 }
2652 }
2653
2654 /* This recursively adds the sub-surfaces for a view, relying on the
2655 * sub-surface order. Thus, if a client restacks the sub-surfaces, that
2656 * change first happens to the sub-surface list, and then automatically
2657 * propagates here. See weston_surface_damage_subsurfaces() for how the
2658 * sub-surfaces receive damage when the client changes the state.
2659 */
2660 static void
view_list_add(struct weston_compositor * compositor,struct weston_view * view)2661 view_list_add(struct weston_compositor *compositor,
2662 struct weston_view *view)
2663 {
2664 struct weston_subsurface *sub;
2665
2666 weston_view_update_transform(view);
2667
2668 if (wl_list_empty(&view->surface->subsurface_list)) {
2669 wl_list_insert(compositor->view_list.prev, &view->link);
2670 return;
2671 }
2672
2673 wl_list_for_each(sub, &view->surface->subsurface_list, parent_link) {
2674 if (sub->surface == view->surface)
2675 wl_list_insert(compositor->view_list.prev, &view->link);
2676 else
2677 view_list_add_subsurface_view(compositor, sub, view);
2678 }
2679 }
2680
2681 static void
weston_compositor_build_view_list(struct weston_compositor * compositor)2682 weston_compositor_build_view_list(struct weston_compositor *compositor)
2683 {
2684 LOG_ENTER();
2685 struct weston_view *view, *tmp;
2686 struct weston_layer *layer;
2687
2688 wl_list_for_each(layer, &compositor->layer_list, link)
2689 wl_list_for_each(view, &layer->view_list.link, layer_link.link)
2690 surface_stash_subsurface_views(view->surface);
2691
2692 wl_list_for_each_safe(view, tmp, &compositor->view_list, link)
2693 wl_list_init(&view->link);
2694 wl_list_init(&compositor->view_list);
2695
2696 wl_list_for_each(layer, &compositor->layer_list, link) {
2697 wl_list_for_each(view, &layer->view_list.link, layer_link.link) {
2698 view_list_add(compositor, view);
2699 }
2700 }
2701
2702 wl_list_for_each(layer, &compositor->layer_list, link)
2703 wl_list_for_each(view, &layer->view_list.link, layer_link.link)
2704 surface_free_unused_subsurface_views(view->surface);
2705 LOG_EXIT();
2706 }
2707
2708 static void
weston_output_take_feedback_list(struct weston_output * output,struct weston_surface * surface)2709 weston_output_take_feedback_list(struct weston_output *output,
2710 struct weston_surface *surface)
2711 {
2712 struct weston_view *view;
2713 struct weston_presentation_feedback *feedback;
2714 uint32_t flags = 0xffffffff;
2715
2716 if (wl_list_empty(&surface->feedback_list))
2717 return;
2718
2719 /* All views must have the flag for the flag to survive. */
2720 wl_list_for_each(view, &surface->views, surface_link) {
2721 /* ignore views that are not on this output at all */
2722 if (view->output_mask & (1u << output->id))
2723 flags &= view->psf_flags;
2724 }
2725
2726 wl_list_for_each(feedback, &surface->feedback_list, link)
2727 feedback->psf_flags = flags;
2728
2729 wl_list_insert_list(&output->feedback_list, &surface->feedback_list);
2730 wl_list_init(&surface->feedback_list);
2731 }
2732
2733 static int
weston_output_repaint(struct weston_output * output,void * repaint_data)2734 weston_output_repaint(struct weston_output *output, void *repaint_data)
2735 {
2736 LOG_ENTER();
2737 struct weston_compositor *ec = output->compositor;
2738 struct weston_view *ev;
2739 struct weston_animation *animation, *next;
2740 struct weston_frame_callback *cb, *cnext;
2741 struct wl_list frame_callback_list;
2742 pixman_region32_t output_damage;
2743 int r;
2744 uint32_t frame_time_msec;
2745 enum weston_hdcp_protection highest_requested = WESTON_HDCP_DISABLE;
2746
2747 if (output->destroying) {
2748 LOG_EXIT();
2749 return 0;
2750 }
2751
2752 // OHOS remove timeline
2753 // TL_POINT(ec, "core_repaint_begin", TLP_OUTPUT(output), TLP_END);
2754
2755 /* Rebuild the surface list and update surface transforms up front. */
2756 weston_compositor_build_view_list(ec);
2757
2758 /* Find the highest protection desired for an output */
2759 wl_list_for_each(ev, &ec->view_list, link) {
2760 if (ev->surface->output_mask & (1u << output->id)) {
2761 /*
2762 * The desired_protection of the output should be the
2763 * maximum of the desired_protection of the surfaces,
2764 * that are displayed on that output, to avoid
2765 * reducing the protection for existing surfaces.
2766 */
2767 if (ev->surface->desired_protection > highest_requested)
2768 highest_requested =
2769 ev->surface->desired_protection;
2770 }
2771 }
2772
2773 output->desired_protection = highest_requested;
2774
2775 if (output->assign_planes && !output->disable_planes) {
2776 output->assign_planes(output, repaint_data);
2777 } else {
2778 wl_list_for_each(ev, &ec->view_list, link) {
2779 weston_view_move_to_plane(ev, &ec->primary_plane);
2780 ev->psf_flags = 0;
2781 }
2782 }
2783
2784 wl_list_init(&frame_callback_list);
2785 wl_list_for_each(ev, &ec->view_list, link) {
2786 /* Note: This operation is safe to do multiple times on the
2787 * same surface.
2788 */
2789 if (ev->surface->output == output) {
2790 wl_list_insert_list(&frame_callback_list,
2791 &ev->surface->frame_callback_list);
2792 wl_list_init(&ev->surface->frame_callback_list);
2793
2794 weston_output_take_feedback_list(output, ev->surface);
2795 }
2796 }
2797
2798 output_accumulate_damage(output);
2799
2800 pixman_region32_init(&output_damage);
2801 pixman_region32_intersect(&output_damage,
2802 &ec->primary_plane.damage, &output->region);
2803 pixman_region32_subtract(&output_damage,
2804 &output_damage, &ec->primary_plane.clip);
2805
2806 if (output->dirty)
2807 weston_output_update_matrix(output);
2808
2809 r = output->repaint(output, &output_damage, repaint_data);
2810
2811 pixman_region32_fini(&output_damage);
2812
2813 output->repaint_needed = false;
2814 if (r == 0)
2815 output->repaint_status = REPAINT_AWAITING_COMPLETION;
2816
2817 weston_compositor_repick(ec);
2818
2819 frame_time_msec = timespec_to_msec(&output->frame_time);
2820
2821 wl_list_for_each_safe(cb, cnext, &frame_callback_list, link) {
2822 wl_callback_send_done(cb->resource, frame_time_msec);
2823 wl_resource_destroy(cb->resource);
2824 }
2825
2826 wl_list_for_each_safe(animation, next, &output->animation_list, link) {
2827 animation->frame_counter++;
2828 animation->frame(animation, output, &output->frame_time);
2829 }
2830
2831 // OHOS remove timeline
2832 // TL_POINT(ec, "core_repaint_posted", TLP_OUTPUT(output), TLP_END);
2833
2834 LOG_EXIT();
2835 return r;
2836 }
2837
2838 static void
weston_output_schedule_repaint_reset(struct weston_output * output)2839 weston_output_schedule_repaint_reset(struct weston_output *output)
2840 {
2841 output->repaint_status = REPAINT_NOT_SCHEDULED;
2842 // OHOS remove timeline
2843 // TL_POINT(output->compositor, "core_repaint_exit_loop",
2844 // TLP_OUTPUT(output), TLP_END);
2845 }
2846
2847 static int
weston_output_maybe_repaint(struct weston_output * output,struct timespec * now,void * repaint_data)2848 weston_output_maybe_repaint(struct weston_output *output, struct timespec *now,
2849 void *repaint_data)
2850 {
2851 struct weston_compositor *compositor = output->compositor;
2852 int ret = 0;
2853 int64_t msec_to_repaint;
2854
2855 /* We're not ready yet; come back to make a decision later. */
2856 if (output->repaint_status != REPAINT_SCHEDULED) {
2857 LOG_EXIT();
2858 return ret;
2859 }
2860
2861 msec_to_repaint = timespec_sub_to_msec(&output->next_repaint, now);
2862 if (msec_to_repaint > 1) {
2863 LOG_EXIT();
2864 return ret;
2865 }
2866
2867 LOG_INFO("1");
2868 /* If we're sleeping, drop the repaint machinery entirely; we will
2869 * explicitly repaint all outputs when we come back. */
2870 if (compositor->state == WESTON_COMPOSITOR_SLEEPING ||
2871 compositor->state == WESTON_COMPOSITOR_OFFSCREEN)
2872 goto err;
2873
2874 LOG_INFO("2");
2875 /* We don't actually need to repaint this output; drop it from
2876 * repaint until something causes damage. */
2877 if (!output->repaint_needed)
2878 goto err;
2879
2880 LOG_INFO("3");
2881 /* If repaint fails, we aren't going to get weston_output_finish_frame
2882 * to trigger a new repaint, so drop it from repaint and hope
2883 * something schedules a successful repaint later. As repainting may
2884 * take some time, re-read our clock as a courtesy to the next
2885 * output. */
2886 ret = weston_output_repaint(output, repaint_data);
2887 weston_compositor_read_presentation_clock(compositor, now);
2888 if (ret != 0)
2889 goto err;
2890
2891 output->repainted = true;
2892 return ret;
2893
2894 err:
2895 weston_output_schedule_repaint_reset(output);
2896 return ret;
2897 }
2898
2899 static void
output_repaint_timer_arm(struct weston_compositor * compositor)2900 output_repaint_timer_arm(struct weston_compositor *compositor)
2901 {
2902 struct weston_output *output;
2903 bool any_should_repaint = false;
2904 struct timespec now;
2905 int64_t msec_to_next = INT64_MAX;
2906
2907 weston_compositor_read_presentation_clock(compositor, &now);
2908
2909 wl_list_for_each(output, &compositor->output_list, link) {
2910 int64_t msec_to_this;
2911
2912 if (output->repaint_status != REPAINT_SCHEDULED)
2913 continue;
2914
2915 msec_to_this = timespec_sub_to_msec(&output->next_repaint,
2916 &now);
2917 if (!any_should_repaint || msec_to_this < msec_to_next)
2918 msec_to_next = msec_to_this;
2919
2920 any_should_repaint = true;
2921 }
2922
2923 if (!any_should_repaint)
2924 return;
2925
2926 /* Even if we should repaint immediately, add the minimum 1 ms delay.
2927 * This is a workaround to allow coalescing multiple output repaints
2928 * particularly from weston_output_finish_frame()
2929 * into the same call, which would not happen if we called
2930 * output_repaint_timer_handler() directly.
2931 */
2932 if (msec_to_next < 1)
2933 msec_to_next = 1;
2934
2935 wl_event_source_timer_update(compositor->repaint_timer, msec_to_next);
2936 }
2937
2938 static int
output_repaint_timer_handler(void * data)2939 output_repaint_timer_handler(void *data)
2940 {
2941 LOG_ENTERS("core: repaint");
2942 struct weston_compositor *compositor = data;
2943 struct weston_output *output;
2944 struct timespec now;
2945 void *repaint_data = NULL;
2946 int ret = 0;
2947
2948 weston_compositor_read_presentation_clock(compositor, &now);
2949
2950 if (compositor->backend->repaint_begin)
2951 repaint_data = compositor->backend->repaint_begin(compositor);
2952
2953 wl_list_for_each(output, &compositor->output_list, link) {
2954 ret = weston_output_maybe_repaint(output, &now, repaint_data);
2955 if (ret)
2956 break;
2957 }
2958
2959 if (ret == 0) {
2960 if (compositor->backend->repaint_flush)
2961 ret = compositor->backend->repaint_flush(compositor,
2962 repaint_data);
2963 } else {
2964 if (compositor->backend->repaint_cancel)
2965 compositor->backend->repaint_cancel(compositor,
2966 repaint_data);
2967 }
2968
2969 if (ret != 0) {
2970 wl_list_for_each(output, &compositor->output_list, link) {
2971 if (output->repainted)
2972 weston_output_schedule_repaint_reset(output);
2973 }
2974 }
2975
2976 wl_list_for_each(output, &compositor->output_list, link)
2977 output->repainted = false;
2978
2979 output_repaint_timer_arm(compositor);
2980
2981 LOG_EXITS("end core: repaint");
2982 return 0;
2983 }
2984
2985 /** Convert a presentation timestamp to another clock domain
2986 *
2987 * \param compositor The compositor defines the presentation clock domain.
2988 * \param presentation_stamp The timestamp in presentation clock domain.
2989 * \param presentation_now Current time in presentation clock domain.
2990 * \param target_clock Defines the target clock domain.
2991 *
2992 * This approximation relies on presentation_stamp to be close to current time.
2993 * The further it is from current time and the bigger the speed difference
2994 * between the two clock domains, the bigger the conversion error.
2995 *
2996 * Conversion error due to system load is biased and unbounded.
2997 */
2998 static struct timespec
convert_presentation_time_now(struct weston_compositor * compositor,const struct timespec * presentation_stamp,const struct timespec * presentation_now,clockid_t target_clock)2999 convert_presentation_time_now(struct weston_compositor *compositor,
3000 const struct timespec *presentation_stamp,
3001 const struct timespec *presentation_now,
3002 clockid_t target_clock)
3003 {
3004 struct timespec target_now = {};
3005 struct timespec target_stamp;
3006 int64_t delta_ns;
3007
3008 if (compositor->presentation_clock == target_clock)
3009 return *presentation_stamp;
3010
3011 clock_gettime(target_clock, &target_now);
3012 delta_ns = timespec_sub_to_nsec(presentation_stamp, presentation_now);
3013 timespec_add_nsec(&target_stamp, &target_now, delta_ns);
3014
3015 return target_stamp;
3016 }
3017
3018 /**
3019 * \ingroup output
3020 */
3021 WL_EXPORT void
weston_output_finish_frame(struct weston_output * output,const struct timespec * stamp,uint32_t presented_flags)3022 weston_output_finish_frame(struct weston_output *output,
3023 const struct timespec *stamp,
3024 uint32_t presented_flags)
3025 {
3026 struct weston_compositor *compositor = output->compositor;
3027 int32_t refresh_nsec;
3028 struct timespec now;
3029 struct timespec vblank_monotonic;
3030 int64_t msec_rel;
3031
3032 assert(output->repaint_status == REPAINT_AWAITING_COMPLETION);
3033 assert(stamp || (presented_flags & WP_PRESENTATION_FEEDBACK_INVALID));
3034
3035 weston_compositor_read_presentation_clock(compositor, &now);
3036
3037 /* If we haven't been supplied any timestamp at all, we don't have a
3038 * timebase to work against, so any delay just wastes time. Push a
3039 * repaint as soon as possible so we can get on with it. */
3040 if (!stamp) {
3041 output->next_repaint = now;
3042 goto out;
3043 }
3044
3045 vblank_monotonic = convert_presentation_time_now(compositor,
3046 stamp, &now,
3047 CLOCK_MONOTONIC);
3048 // OHOS remove timeline
3049 // TL_POINT(compositor, "core_repaint_finished", TLP_OUTPUT(output),
3050 // TLP_VBLANK(&vblank_monotonic), TLP_END);
3051
3052 refresh_nsec = millihz_to_nsec(output->current_mode->refresh);
3053 weston_presentation_feedback_present_list(&output->feedback_list,
3054 output, refresh_nsec, stamp,
3055 output->msc,
3056 presented_flags);
3057
3058 output->frame_time = *stamp;
3059
3060 timespec_add_nsec(&output->next_repaint, stamp, refresh_nsec);
3061 timespec_add_msec(&output->next_repaint, &output->next_repaint,
3062 -compositor->repaint_msec);
3063 msec_rel = timespec_sub_to_msec(&output->next_repaint, &now);
3064
3065 if (msec_rel < -1000 || msec_rel > 1000) {
3066 static bool warned;
3067
3068 if (!warned)
3069 weston_log("Warning: computed repaint delay is "
3070 "insane: %lld msec\n", (long long) msec_rel);
3071 warned = true;
3072
3073 output->next_repaint = now;
3074 }
3075
3076 /* Called from restart_repaint_loop and restart happens already after
3077 * the deadline given by repaint_msec? In that case we delay until
3078 * the deadline of the next frame, to give clients a more predictable
3079 * timing of the repaint cycle to lock on. */
3080 if (presented_flags == WP_PRESENTATION_FEEDBACK_INVALID &&
3081 msec_rel < 0) {
3082 while (timespec_sub_to_nsec(&output->next_repaint, &now) < 0) {
3083 timespec_add_nsec(&output->next_repaint,
3084 &output->next_repaint,
3085 refresh_nsec);
3086 }
3087 }
3088
3089 out:
3090 output->repaint_status = REPAINT_SCHEDULED;
3091 LOG_INFO("arm");
3092 output_repaint_timer_arm(compositor);
3093 }
3094
3095 static void
idle_repaint(void * data)3096 idle_repaint(void *data)
3097 {
3098 LOG_ENTERS("core: idle_repaint");
3099 struct weston_output *output = data;
3100 int ret;
3101
3102 assert(output->repaint_status == REPAINT_BEGIN_FROM_IDLE);
3103 output->repaint_status = REPAINT_AWAITING_COMPLETION;
3104 output->idle_repaint_source = NULL;
3105 ret = output->start_repaint_loop(output);
3106 if (ret != 0)
3107 weston_output_schedule_repaint_reset(output);
3108 LOG_EXITS("end core: idle_repaint");
3109 }
3110
3111 WL_EXPORT void
weston_layer_entry_insert(struct weston_layer_entry * list,struct weston_layer_entry * entry)3112 weston_layer_entry_insert(struct weston_layer_entry *list,
3113 struct weston_layer_entry *entry)
3114 {
3115 wl_list_insert(&list->link, &entry->link);
3116 entry->layer = list->layer;
3117 }
3118
3119 WL_EXPORT void
weston_layer_entry_remove(struct weston_layer_entry * entry)3120 weston_layer_entry_remove(struct weston_layer_entry *entry)
3121 {
3122 wl_list_remove(&entry->link);
3123 wl_list_init(&entry->link);
3124 entry->layer = NULL;
3125 }
3126
3127
3128 /** Initialize the weston_layer struct.
3129 *
3130 * \param compositor The compositor instance
3131 * \param layer The layer to initialize
3132 */
3133 WL_EXPORT void
weston_layer_init(struct weston_layer * layer,struct weston_compositor * compositor)3134 weston_layer_init(struct weston_layer *layer,
3135 struct weston_compositor *compositor)
3136 {
3137 layer->compositor = compositor;
3138 wl_list_init(&layer->link);
3139 wl_list_init(&layer->view_list.link);
3140 layer->view_list.layer = layer;
3141 weston_layer_set_mask_infinite(layer);
3142 }
3143
3144 /** Sets the position of the layer in the layer list. The layer will be placed
3145 * below any layer with the same position value, if any.
3146 * This function is safe to call if the layer is already on the list, but the
3147 * layer may be moved below other layers at the same position, if any.
3148 *
3149 * \param layer The layer to modify
3150 * \param position The position the layer will be placed at
3151 */
3152 WL_EXPORT void
weston_layer_set_position(struct weston_layer * layer,enum weston_layer_position position)3153 weston_layer_set_position(struct weston_layer *layer,
3154 enum weston_layer_position position)
3155 {
3156 struct weston_layer *below;
3157
3158 wl_list_remove(&layer->link);
3159
3160 /* layer_list is ordered from top to bottom, the last layer being the
3161 * background with the smallest position value */
3162
3163 layer->position = position;
3164 wl_list_for_each_reverse(below, &layer->compositor->layer_list, link) {
3165 if (below->position >= layer->position) {
3166 wl_list_insert(&below->link, &layer->link);
3167 return;
3168 }
3169 }
3170 wl_list_insert(&layer->compositor->layer_list, &layer->link);
3171 }
3172
3173 /** Hide a layer by taking it off the layer list.
3174 * This function is safe to call if the layer is not on the list.
3175 *
3176 * \param layer The layer to hide
3177 */
3178 WL_EXPORT void
weston_layer_unset_position(struct weston_layer * layer)3179 weston_layer_unset_position(struct weston_layer *layer)
3180 {
3181 wl_list_remove(&layer->link);
3182 wl_list_init(&layer->link);
3183 }
3184
3185 WL_EXPORT void
weston_layer_set_mask(struct weston_layer * layer,int x,int y,int width,int height)3186 weston_layer_set_mask(struct weston_layer *layer,
3187 int x, int y, int width, int height)
3188 {
3189 struct weston_view *view;
3190
3191 layer->mask.x1 = x;
3192 layer->mask.x2 = x + width;
3193 layer->mask.y1 = y;
3194 layer->mask.y2 = y + height;
3195
3196 wl_list_for_each(view, &layer->view_list.link, layer_link.link) {
3197 weston_view_geometry_dirty(view);
3198 }
3199 }
3200
3201 WL_EXPORT void
weston_layer_set_mask_infinite(struct weston_layer * layer)3202 weston_layer_set_mask_infinite(struct weston_layer *layer)
3203 {
3204 struct weston_view *view;
3205
3206 layer->mask.x1 = INT32_MIN;
3207 layer->mask.x2 = INT32_MAX;
3208 layer->mask.y1 = INT32_MIN;
3209 layer->mask.y2 = INT32_MAX;
3210
3211 wl_list_for_each(view, &layer->view_list.link, layer_link.link) {
3212 weston_view_geometry_dirty(view);
3213 }
3214 }
3215
3216 WL_EXPORT bool
weston_layer_mask_is_infinite(struct weston_layer * layer)3217 weston_layer_mask_is_infinite(struct weston_layer *layer)
3218 {
3219 return layer->mask.x1 == INT32_MIN &&
3220 layer->mask.y1 == INT32_MIN &&
3221 layer->mask.x2 == INT32_MAX &&
3222 layer->mask.y2 == INT32_MAX;
3223 }
3224
3225 /**
3226 * \ingroup output
3227 */
3228 WL_EXPORT void
weston_output_schedule_repaint(struct weston_output * output)3229 weston_output_schedule_repaint(struct weston_output *output)
3230 {
3231 LOG_INFO("output schedule repaint");
3232 struct weston_compositor *compositor = output->compositor;
3233 struct wl_event_loop *loop;
3234
3235 if (compositor->state == WESTON_COMPOSITOR_SLEEPING ||
3236 compositor->state == WESTON_COMPOSITOR_OFFSCREEN) {
3237 LOG_ERROR("no need idle_repaint");
3238 return;
3239 }
3240
3241 // OHOS remove timeline
3242 // if (!output->repaint_needed)
3243 // TL_POINT(compositor, "core_repaint_req", TLP_OUTPUT(output), TLP_END);
3244
3245 loop = wl_display_get_event_loop(compositor->wl_display);
3246 output->repaint_needed = true;
3247
3248 /* If we already have a repaint scheduled for our idle handler,
3249 * no need to set it again. If the repaint has been called but
3250 * not finished, then weston_output_finish_frame() will notice
3251 * that a repaint is needed and schedule one. */
3252 if (output->repaint_status != REPAINT_NOT_SCHEDULED) {
3253 LOG_ERROR("no need idle_repaint");
3254 return;
3255 }
3256
3257 output->repaint_status = REPAINT_BEGIN_FROM_IDLE;
3258 assert(!output->idle_repaint_source);
3259 output->idle_repaint_source = wl_event_loop_add_idle(loop, idle_repaint,
3260 output);
3261 LOG_INFO("core: add idle_repaint source");
3262 // OHOS remove timeline
3263 // TL_POINT(compositor, "core_repaint_enter_loop", TLP_OUTPUT(output), TLP_END);
3264 }
3265
3266 /** weston_compositor_schedule_repaint
3267 * \ingroup compositor
3268 */
3269 WL_EXPORT void
weston_compositor_schedule_repaint(struct weston_compositor * compositor)3270 weston_compositor_schedule_repaint(struct weston_compositor *compositor)
3271 {
3272 LOG_INFO("compositor schedule repaint");
3273 struct weston_output *output;
3274
3275 wl_list_for_each(output, &compositor->output_list, link)
3276 weston_output_schedule_repaint(output);
3277 }
3278
3279 static void
surface_destroy(struct wl_client * client,struct wl_resource * resource)3280 surface_destroy(struct wl_client *client, struct wl_resource *resource)
3281 {
3282 wl_resource_destroy(resource);
3283 }
3284
3285 static void
surface_attach(struct wl_client * client,struct wl_resource * resource,struct wl_resource * buffer_resource,int32_t sx,int32_t sy)3286 surface_attach(struct wl_client *client,
3287 struct wl_resource *resource,
3288 struct wl_resource *buffer_resource, int32_t sx, int32_t sy)
3289 {
3290 LOG_ENTER();
3291 struct weston_surface *surface = wl_resource_get_user_data(resource);
3292 struct weston_buffer *buffer = NULL;
3293
3294 if (buffer_resource) {
3295 buffer = weston_buffer_from_resource(buffer_resource);
3296 if (buffer == NULL) {
3297 wl_client_post_no_memory(client);
3298 LOG_EXIT();
3299 return;
3300 }
3301 }
3302
3303 /* Attach, attach, without commit in between does not send
3304 * wl_buffer.release. */
3305 weston_surface_state_set_buffer(&surface->pending, buffer);
3306
3307 surface->pending.sx = sx;
3308 surface->pending.sy = sy;
3309 surface->pending.newly_attached = 1;
3310 LOG_EXIT();
3311 }
3312
3313 static void
surface_damage(struct wl_client * client,struct wl_resource * resource,int32_t x,int32_t y,int32_t width,int32_t height)3314 surface_damage(struct wl_client *client,
3315 struct wl_resource *resource,
3316 int32_t x, int32_t y, int32_t width, int32_t height)
3317 {
3318 struct weston_surface *surface = wl_resource_get_user_data(resource);
3319
3320 if (width <= 0 || height <= 0)
3321 return;
3322
3323 pixman_region32_union_rect(&surface->pending.damage_surface,
3324 &surface->pending.damage_surface,
3325 x, y, width, height);
3326 }
3327
3328 static void
surface_damage_buffer(struct wl_client * client,struct wl_resource * resource,int32_t x,int32_t y,int32_t width,int32_t height)3329 surface_damage_buffer(struct wl_client *client,
3330 struct wl_resource *resource,
3331 int32_t x, int32_t y, int32_t width, int32_t height)
3332 {
3333 struct weston_surface *surface = wl_resource_get_user_data(resource);
3334
3335 if (width <= 0 || height <= 0)
3336 return;
3337
3338 pixman_region32_union_rect(&surface->pending.damage_buffer,
3339 &surface->pending.damage_buffer,
3340 x, y, width, height);
3341 }
3342
3343 // OHOS surface type
3344 static void
surface_set_surface_type(struct wl_client * client,struct wl_resource * resource,int32_t type)3345 surface_set_surface_type(struct wl_client *client,
3346 struct wl_resource *resource, int32_t type)
3347 {
3348 struct weston_surface *surface = wl_resource_get_user_data(resource);
3349 surface->type = type;
3350 }
3351
3352 static void
destroy_frame_callback(struct wl_resource * resource)3353 destroy_frame_callback(struct wl_resource *resource)
3354 {
3355 struct weston_frame_callback *cb = wl_resource_get_user_data(resource);
3356
3357 wl_list_remove(&cb->link);
3358 free(cb);
3359 }
3360
3361 static void
surface_frame(struct wl_client * client,struct wl_resource * resource,uint32_t callback)3362 surface_frame(struct wl_client *client,
3363 struct wl_resource *resource, uint32_t callback)
3364 {
3365 struct weston_frame_callback *cb;
3366 struct weston_surface *surface = wl_resource_get_user_data(resource);
3367
3368 cb = malloc(sizeof *cb);
3369 if (cb == NULL) {
3370 wl_resource_post_no_memory(resource);
3371 return;
3372 }
3373
3374 cb->resource = wl_resource_create(client, &wl_callback_interface, 1,
3375 callback);
3376 if (cb->resource == NULL) {
3377 free(cb);
3378 wl_resource_post_no_memory(resource);
3379 return;
3380 }
3381
3382 wl_resource_set_implementation(cb->resource, NULL, cb,
3383 destroy_frame_callback);
3384
3385 wl_list_insert(surface->pending.frame_callback_list.prev, &cb->link);
3386 }
3387
3388 static void
surface_set_opaque_region(struct wl_client * client,struct wl_resource * resource,struct wl_resource * region_resource)3389 surface_set_opaque_region(struct wl_client *client,
3390 struct wl_resource *resource,
3391 struct wl_resource *region_resource)
3392 {
3393 struct weston_surface *surface = wl_resource_get_user_data(resource);
3394 struct weston_region *region;
3395
3396 if (region_resource) {
3397 region = wl_resource_get_user_data(region_resource);
3398 pixman_region32_copy(&surface->pending.opaque,
3399 ®ion->region);
3400 } else {
3401 pixman_region32_clear(&surface->pending.opaque);
3402 }
3403 }
3404
3405 static void
surface_set_input_region(struct wl_client * client,struct wl_resource * resource,struct wl_resource * region_resource)3406 surface_set_input_region(struct wl_client *client,
3407 struct wl_resource *resource,
3408 struct wl_resource *region_resource)
3409 {
3410 struct weston_surface *surface = wl_resource_get_user_data(resource);
3411 struct weston_region *region;
3412
3413 if (region_resource) {
3414 region = wl_resource_get_user_data(region_resource);
3415 pixman_region32_copy(&surface->pending.input,
3416 ®ion->region);
3417 } else {
3418 pixman_region32_fini(&surface->pending.input);
3419 region_init_infinite(&surface->pending.input);
3420 }
3421 }
3422
3423 /* Cause damage to this sub-surface and all its children.
3424 *
3425 * This is useful when there are state changes that need an implicit
3426 * damage, e.g. a z-order change.
3427 */
3428 static void
weston_surface_damage_subsurfaces(struct weston_subsurface * sub)3429 weston_surface_damage_subsurfaces(struct weston_subsurface *sub)
3430 {
3431 struct weston_subsurface *child;
3432
3433 weston_surface_damage(sub->surface);
3434 sub->reordered = false;
3435
3436 wl_list_for_each(child, &sub->surface->subsurface_list, parent_link)
3437 if (child != sub)
3438 weston_surface_damage_subsurfaces(child);
3439 }
3440
3441 static void
weston_surface_commit_subsurface_order(struct weston_surface * surface)3442 weston_surface_commit_subsurface_order(struct weston_surface *surface)
3443 {
3444 struct weston_subsurface *sub;
3445
3446 wl_list_for_each_reverse(sub, &surface->subsurface_list_pending,
3447 parent_link_pending) {
3448 wl_list_remove(&sub->parent_link);
3449 wl_list_insert(&surface->subsurface_list, &sub->parent_link);
3450
3451 if (sub->reordered)
3452 weston_surface_damage_subsurfaces(sub);
3453 }
3454 }
3455
3456 static void
weston_surface_build_buffer_matrix(const struct weston_surface * surface,struct weston_matrix * matrix)3457 weston_surface_build_buffer_matrix(const struct weston_surface *surface,
3458 struct weston_matrix *matrix)
3459 {
3460 const struct weston_buffer_viewport *vp = &surface->buffer_viewport;
3461 double src_width, src_height, dest_width, dest_height;
3462
3463 weston_matrix_init(matrix);
3464
3465 if (vp->buffer.src_width == wl_fixed_from_int(-1)) {
3466 src_width = surface->width_from_buffer;
3467 src_height = surface->height_from_buffer;
3468 } else {
3469 src_width = wl_fixed_to_double(vp->buffer.src_width);
3470 src_height = wl_fixed_to_double(vp->buffer.src_height);
3471 }
3472
3473 if (vp->surface.width == -1) {
3474 dest_width = src_width;
3475 dest_height = src_height;
3476 } else {
3477 dest_width = vp->surface.width;
3478 dest_height = vp->surface.height;
3479 }
3480
3481 if (src_width != dest_width || src_height != dest_height)
3482 weston_matrix_scale(matrix,
3483 src_width / dest_width,
3484 src_height / dest_height, 1);
3485
3486 if (vp->buffer.src_width != wl_fixed_from_int(-1))
3487 weston_matrix_translate(matrix,
3488 wl_fixed_to_double(vp->buffer.src_x),
3489 wl_fixed_to_double(vp->buffer.src_y),
3490 0);
3491
3492 switch (vp->buffer.transform) {
3493 case WL_OUTPUT_TRANSFORM_FLIPPED:
3494 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
3495 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
3496 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
3497 weston_matrix_scale(matrix, -1, 1, 1);
3498 weston_matrix_translate(matrix,
3499 surface->width_from_buffer, 0, 0);
3500 break;
3501 }
3502
3503 switch (vp->buffer.transform) {
3504 default:
3505 case WL_OUTPUT_TRANSFORM_NORMAL:
3506 case WL_OUTPUT_TRANSFORM_FLIPPED:
3507 break;
3508 case WL_OUTPUT_TRANSFORM_90:
3509 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
3510 weston_matrix_rotate_xy(matrix, 0, -1);
3511 weston_matrix_translate(matrix,
3512 0, surface->width_from_buffer, 0);
3513 break;
3514 case WL_OUTPUT_TRANSFORM_180:
3515 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
3516 weston_matrix_rotate_xy(matrix, -1, 0);
3517 weston_matrix_translate(matrix,
3518 surface->width_from_buffer,
3519 surface->height_from_buffer, 0);
3520 break;
3521 case WL_OUTPUT_TRANSFORM_270:
3522 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
3523 weston_matrix_rotate_xy(matrix, 0, 1);
3524 weston_matrix_translate(matrix,
3525 surface->height_from_buffer, 0, 0);
3526 break;
3527 }
3528
3529 weston_matrix_scale(matrix, vp->buffer.scale, vp->buffer.scale, 1);
3530 }
3531
3532 /**
3533 * Compute a + b > c while being safe to overflows.
3534 */
3535 static bool
fixed_sum_gt(wl_fixed_t a,wl_fixed_t b,wl_fixed_t c)3536 fixed_sum_gt(wl_fixed_t a, wl_fixed_t b, wl_fixed_t c)
3537 {
3538 return (int64_t)a + (int64_t)b > (int64_t)c;
3539 }
3540
3541 static bool
weston_surface_is_pending_viewport_source_valid(const struct weston_surface * surface)3542 weston_surface_is_pending_viewport_source_valid(
3543 const struct weston_surface *surface)
3544 {
3545 const struct weston_surface_state *pend = &surface->pending;
3546 const struct weston_buffer_viewport *vp = &pend->buffer_viewport;
3547 int width_from_buffer = 0;
3548 int height_from_buffer = 0;
3549 wl_fixed_t w;
3550 wl_fixed_t h;
3551
3552 /* If viewport source rect is not set, it is always ok. */
3553 if (vp->buffer.src_width == wl_fixed_from_int(-1))
3554 return true;
3555
3556 if (pend->newly_attached) {
3557 if (pend->buffer) {
3558 convert_size_by_transform_scale(&width_from_buffer,
3559 &height_from_buffer,
3560 pend->buffer->width,
3561 pend->buffer->height,
3562 vp->buffer.transform,
3563 vp->buffer.scale);
3564 } else {
3565 /* No buffer: viewport is irrelevant. */
3566 return true;
3567 }
3568 } else {
3569 width_from_buffer = surface->width_from_buffer;
3570 height_from_buffer = surface->height_from_buffer;
3571 }
3572
3573 assert((width_from_buffer == 0) == (height_from_buffer == 0));
3574 assert(width_from_buffer >= 0 && height_from_buffer >= 0);
3575
3576 /* No buffer: viewport is irrelevant. */
3577 if (width_from_buffer == 0 || height_from_buffer == 0)
3578 return true;
3579
3580 /* overflow checks for wl_fixed_from_int() */
3581 if (width_from_buffer > wl_fixed_to_int(INT32_MAX))
3582 return false;
3583 if (height_from_buffer > wl_fixed_to_int(INT32_MAX))
3584 return false;
3585
3586 w = wl_fixed_from_int(width_from_buffer);
3587 h = wl_fixed_from_int(height_from_buffer);
3588
3589 if (fixed_sum_gt(vp->buffer.src_x, vp->buffer.src_width, w))
3590 return false;
3591 if (fixed_sum_gt(vp->buffer.src_y, vp->buffer.src_height, h))
3592 return false;
3593
3594 return true;
3595 }
3596
3597 static bool
fixed_is_integer(wl_fixed_t v)3598 fixed_is_integer(wl_fixed_t v)
3599 {
3600 return (v & 0xff) == 0;
3601 }
3602
3603 static bool
weston_surface_is_pending_viewport_dst_size_int(const struct weston_surface * surface)3604 weston_surface_is_pending_viewport_dst_size_int(
3605 const struct weston_surface *surface)
3606 {
3607 const struct weston_buffer_viewport *vp =
3608 &surface->pending.buffer_viewport;
3609
3610 if (vp->surface.width != -1) {
3611 assert(vp->surface.width > 0 && vp->surface.height > 0);
3612 return true;
3613 }
3614
3615 return fixed_is_integer(vp->buffer.src_width) &&
3616 fixed_is_integer(vp->buffer.src_height);
3617 }
3618
3619 /* Translate pending damage in buffer co-ordinates to surface
3620 * co-ordinates and union it with a pixman_region32_t.
3621 * This should only be called after the buffer is attached.
3622 */
3623 static void
apply_damage_buffer(pixman_region32_t * dest,struct weston_surface * surface,struct weston_surface_state * state)3624 apply_damage_buffer(pixman_region32_t *dest,
3625 struct weston_surface *surface,
3626 struct weston_surface_state *state)
3627 {
3628 struct weston_buffer *buffer = surface->buffer_ref.buffer;
3629
3630 /* wl_surface.damage_buffer needs to be clipped to the buffer,
3631 * translated into surface co-ordinates and unioned with
3632 * any other surface damage.
3633 * None of this makes sense if there is no buffer though.
3634 */
3635 if (buffer && pixman_region32_not_empty(&state->damage_buffer)) {
3636 pixman_region32_t buffer_damage;
3637
3638 pixman_region32_intersect_rect(&state->damage_buffer,
3639 &state->damage_buffer,
3640 0, 0, buffer->width,
3641 buffer->height);
3642 pixman_region32_init(&buffer_damage);
3643 weston_matrix_transform_region(&buffer_damage,
3644 &surface->buffer_to_surface_matrix,
3645 &state->damage_buffer);
3646 pixman_region32_union(dest, dest, &buffer_damage);
3647 pixman_region32_fini(&buffer_damage);
3648 }
3649 /* We should clear this on commit even if there was no buffer */
3650 pixman_region32_clear(&state->damage_buffer);
3651 }
3652
3653 static void
weston_surface_set_desired_protection(struct weston_surface * surface,enum weston_hdcp_protection protection)3654 weston_surface_set_desired_protection(struct weston_surface *surface,
3655 enum weston_hdcp_protection protection)
3656 {
3657 if (surface->desired_protection == protection)
3658 return;
3659 surface->desired_protection = protection;
3660 weston_surface_damage(surface);
3661 }
3662
3663 static void
weston_surface_set_protection_mode(struct weston_surface * surface,enum weston_surface_protection_mode p_mode)3664 weston_surface_set_protection_mode(struct weston_surface *surface,
3665 enum weston_surface_protection_mode p_mode)
3666 {
3667 struct content_protection *cp = surface->compositor->content_protection;
3668 struct protected_surface *psurface;
3669
3670 surface->protection_mode = p_mode;
3671 wl_list_for_each(psurface, &cp->protected_list, link) {
3672 if (!psurface || psurface->surface != surface)
3673 continue;
3674 weston_protected_surface_send_event(psurface,
3675 surface->current_protection);
3676 }
3677 }
3678
3679 static void
weston_surface_commit_state(struct weston_surface * surface,struct weston_surface_state * state)3680 weston_surface_commit_state(struct weston_surface *surface,
3681 struct weston_surface_state *state)
3682 {
3683 struct weston_view *view;
3684 pixman_region32_t opaque;
3685
3686 /* wl_surface.set_buffer_transform */
3687 /* wl_surface.set_buffer_scale */
3688 /* wp_viewport.set_source */
3689 /* wp_viewport.set_destination */
3690 surface->buffer_viewport = state->buffer_viewport;
3691
3692 /* wl_surface.attach */
3693 if (state->newly_attached) {
3694 /* zwp_surface_synchronization_v1.set_acquire_fence */
3695 fd_move(&surface->acquire_fence_fd,
3696 &state->acquire_fence_fd);
3697 /* zwp_surface_synchronization_v1.get_release */
3698 weston_buffer_release_move(&surface->buffer_release_ref,
3699 &state->buffer_release_ref);
3700 weston_surface_attach(surface, state->buffer);
3701 }
3702 weston_surface_state_set_buffer(state, NULL);
3703 assert(state->acquire_fence_fd == -1);
3704 assert(state->buffer_release_ref.buffer_release == NULL);
3705
3706 weston_surface_build_buffer_matrix(surface,
3707 &surface->surface_to_buffer_matrix);
3708 weston_matrix_invert(&surface->buffer_to_surface_matrix,
3709 &surface->surface_to_buffer_matrix);
3710
3711 if (state->newly_attached || state->buffer_viewport.changed) {
3712 weston_surface_update_size(surface);
3713 LOG_INFO("surface->committed: %p", surface->committed);
3714 LOG_ENTERS("surface->committed");
3715 if (surface->committed)
3716 surface->committed(surface, state->sx, state->sy);
3717 LOG_EXITS("surface->committed");
3718 }
3719
3720 state->sx = 0;
3721 state->sy = 0;
3722 state->newly_attached = 0;
3723 state->buffer_viewport.changed = 0;
3724
3725 // OHOS remove timeline
3726 // /* wl_surface.damage and wl_surface.damage_buffer */
3727 // if (pixman_region32_not_empty(&state->damage_surface) ||
3728 // pixman_region32_not_empty(&state->damage_buffer))
3729 // TL_POINT(surface->compositor, "core_commit_damage", TLP_SURFACE(surface), TLP_END);
3730
3731 pixman_region32_union(&surface->damage, &surface->damage,
3732 &state->damage_surface);
3733
3734 apply_damage_buffer(&surface->damage, surface, state);
3735
3736 pixman_region32_intersect_rect(&surface->damage, &surface->damage,
3737 0, 0, surface->width, surface->height);
3738 pixman_region32_clear(&state->damage_surface);
3739
3740 /* wl_surface.set_opaque_region */
3741 pixman_region32_init(&opaque);
3742 pixman_region32_intersect_rect(&opaque, &state->opaque,
3743 0, 0, surface->width, surface->height);
3744
3745 if (!pixman_region32_equal(&opaque, &surface->opaque)) {
3746 pixman_region32_copy(&surface->opaque, &opaque);
3747 wl_list_for_each(view, &surface->views, surface_link)
3748 weston_view_geometry_dirty(view);
3749 }
3750
3751 pixman_region32_fini(&opaque);
3752
3753 /* wl_surface.set_input_region */
3754 pixman_region32_intersect_rect(&surface->input, &state->input,
3755 0, 0, surface->width, surface->height);
3756
3757 /* wl_surface.frame */
3758 wl_list_insert_list(&surface->frame_callback_list,
3759 &state->frame_callback_list);
3760 wl_list_init(&state->frame_callback_list);
3761
3762 /* XXX:
3763 * What should happen with a feedback request, if there
3764 * is no wl_buffer attached for this commit?
3765 */
3766
3767 /* presentation.feedback */
3768 wl_list_insert_list(&surface->feedback_list,
3769 &state->feedback_list);
3770 wl_list_init(&state->feedback_list);
3771
3772 /* weston_protected_surface.enforced/relaxed */
3773 if (surface->protection_mode != state->protection_mode)
3774 weston_surface_set_protection_mode(surface,
3775 state->protection_mode);
3776
3777 /* weston_protected_surface.set_type */
3778 weston_surface_set_desired_protection(surface, state->desired_protection);
3779
3780 wl_signal_emit(&surface->commit_signal, surface);
3781 }
3782
3783 static void
weston_surface_commit(struct weston_surface * surface)3784 weston_surface_commit(struct weston_surface *surface)
3785 {
3786 LOG_ENTER();
3787 weston_surface_commit_state(surface, &surface->pending);
3788
3789 weston_surface_commit_subsurface_order(surface);
3790
3791 weston_surface_schedule_repaint(surface);
3792 LOG_EXIT();
3793 }
3794
3795 static void
3796 weston_subsurface_commit(struct weston_subsurface *sub);
3797
3798 static void
3799 weston_subsurface_parent_commit(struct weston_subsurface *sub,
3800 int parent_is_synchronized);
3801
3802 static void
surface_commit(struct wl_client * client,struct wl_resource * resource)3803 surface_commit(struct wl_client *client, struct wl_resource *resource)
3804 {
3805 LOG_ENTER();
3806 struct weston_surface *surface = wl_resource_get_user_data(resource);
3807 struct weston_subsurface *sub = weston_surface_to_subsurface(surface);
3808
3809 if (!weston_surface_is_pending_viewport_source_valid(surface)) {
3810 assert(surface->viewport_resource);
3811
3812 wl_resource_post_error(surface->viewport_resource,
3813 WP_VIEWPORT_ERROR_OUT_OF_BUFFER,
3814 "wl_surface@%d has viewport source outside buffer",
3815 wl_resource_get_id(resource));
3816 LOG_EXIT();
3817 return;
3818 }
3819
3820 if (!weston_surface_is_pending_viewport_dst_size_int(surface)) {
3821 assert(surface->viewport_resource);
3822
3823 wl_resource_post_error(surface->viewport_resource,
3824 WP_VIEWPORT_ERROR_BAD_SIZE,
3825 "wl_surface@%d viewport dst size not integer",
3826 wl_resource_get_id(resource));
3827 LOG_EXIT();
3828 return;
3829 }
3830
3831 if (surface->pending.acquire_fence_fd >= 0) {
3832 assert(surface->synchronization_resource);
3833
3834 if (!surface->pending.buffer) {
3835 fd_clear(&surface->pending.acquire_fence_fd);
3836 wl_resource_post_error(surface->synchronization_resource,
3837 ZWP_LINUX_SURFACE_SYNCHRONIZATION_V1_ERROR_NO_BUFFER,
3838 "wl_surface@%"PRIu32" no buffer for synchronization",
3839 wl_resource_get_id(resource));
3840 LOG_EXIT();
3841 return;
3842 }
3843
3844 /* We support fences for both wp_linux_dmabuf and opaque EGL
3845 * buffers, as mandated by minor version 2 of the
3846 * zwp_linux_explicit_synchronization_v1 protocol. Since
3847 * renderers that support fences currently only support these
3848 * two buffer types plus SHM buffers, we can just check for the
3849 * SHM buffer case here.
3850 */
3851 if (wl_shm_buffer_get(surface->pending.buffer->resource)) {
3852 fd_clear(&surface->pending.acquire_fence_fd);
3853 wl_resource_post_error(surface->synchronization_resource,
3854 ZWP_LINUX_SURFACE_SYNCHRONIZATION_V1_ERROR_UNSUPPORTED_BUFFER,
3855 "wl_surface@%"PRIu32" unsupported buffer for synchronization",
3856 wl_resource_get_id(resource));
3857 LOG_EXIT();
3858 return;
3859 }
3860 }
3861
3862 if (surface->pending.buffer_release_ref.buffer_release &&
3863 !surface->pending.buffer) {
3864 assert(surface->synchronization_resource);
3865
3866 wl_resource_post_error(surface->synchronization_resource,
3867 ZWP_LINUX_SURFACE_SYNCHRONIZATION_V1_ERROR_NO_BUFFER,
3868 "wl_surface@%"PRIu32" no buffer for synchronization",
3869 wl_resource_get_id(resource));
3870 LOG_EXIT();
3871 return;
3872 }
3873
3874 if (sub) {
3875 weston_subsurface_commit(sub);
3876 LOG_EXIT();
3877 return;
3878 }
3879
3880 weston_surface_commit(surface);
3881
3882 wl_list_for_each(sub, &surface->subsurface_list, parent_link) {
3883 if (sub->surface != surface)
3884 weston_subsurface_parent_commit(sub, 0);
3885 }
3886 LOG_EXIT();
3887 }
3888
3889 static void
surface_set_buffer_transform(struct wl_client * client,struct wl_resource * resource,int transform)3890 surface_set_buffer_transform(struct wl_client *client,
3891 struct wl_resource *resource, int transform)
3892 {
3893 struct weston_surface *surface = wl_resource_get_user_data(resource);
3894
3895 /* if wl_output.transform grows more members this will need to be updated. */
3896 if (transform < 0 ||
3897 transform > WL_OUTPUT_TRANSFORM_FLIPPED_270) {
3898 wl_resource_post_error(resource,
3899 WL_SURFACE_ERROR_INVALID_TRANSFORM,
3900 "buffer transform must be a valid transform "
3901 "('%d' specified)", transform);
3902 return;
3903 }
3904
3905 surface->pending.buffer_viewport.buffer.transform = transform;
3906 surface->pending.buffer_viewport.changed = 1;
3907 }
3908
3909 static void
surface_set_buffer_scale(struct wl_client * client,struct wl_resource * resource,int32_t scale)3910 surface_set_buffer_scale(struct wl_client *client,
3911 struct wl_resource *resource,
3912 int32_t scale)
3913 {
3914 struct weston_surface *surface = wl_resource_get_user_data(resource);
3915
3916 if (scale < 1) {
3917 wl_resource_post_error(resource,
3918 WL_SURFACE_ERROR_INVALID_SCALE,
3919 "buffer scale must be at least one "
3920 "('%d' specified)", scale);
3921 return;
3922 }
3923
3924 surface->pending.buffer_viewport.buffer.scale = scale;
3925 surface->pending.buffer_viewport.changed = 1;
3926 }
3927
3928 static const struct wl_surface_interface surface_interface = {
3929 surface_destroy,
3930 surface_attach,
3931 surface_damage,
3932 surface_frame,
3933 surface_set_opaque_region,
3934 surface_set_input_region,
3935 surface_commit,
3936 surface_set_buffer_transform,
3937 surface_set_buffer_scale,
3938 surface_damage_buffer,
3939 surface_set_surface_type // OHOS surface type
3940 };
3941
3942 static void
compositor_create_surface(struct wl_client * client,struct wl_resource * resource,uint32_t id)3943 compositor_create_surface(struct wl_client *client,
3944 struct wl_resource *resource, uint32_t id)
3945 {
3946 struct weston_compositor *ec = wl_resource_get_user_data(resource);
3947 struct weston_surface *surface;
3948
3949 surface = weston_surface_create(ec);
3950 if (surface == NULL) {
3951 wl_resource_post_no_memory(resource);
3952 return;
3953 }
3954
3955 surface->resource =
3956 wl_resource_create(client, &wl_surface_interface,
3957 wl_resource_get_version(resource), id);
3958 if (surface->resource == NULL) {
3959 weston_surface_destroy(surface);
3960 wl_resource_post_no_memory(resource);
3961 return;
3962 }
3963 wl_resource_set_implementation(surface->resource, &surface_interface,
3964 surface, destroy_surface);
3965
3966 wl_signal_emit(&ec->create_surface_signal, surface);
3967 }
3968
3969 static void
destroy_region(struct wl_resource * resource)3970 destroy_region(struct wl_resource *resource)
3971 {
3972 struct weston_region *region = wl_resource_get_user_data(resource);
3973
3974 pixman_region32_fini(®ion->region);
3975 free(region);
3976 }
3977
3978 static void
region_destroy(struct wl_client * client,struct wl_resource * resource)3979 region_destroy(struct wl_client *client, struct wl_resource *resource)
3980 {
3981 wl_resource_destroy(resource);
3982 }
3983
3984 static void
region_add(struct wl_client * client,struct wl_resource * resource,int32_t x,int32_t y,int32_t width,int32_t height)3985 region_add(struct wl_client *client, struct wl_resource *resource,
3986 int32_t x, int32_t y, int32_t width, int32_t height)
3987 {
3988 struct weston_region *region = wl_resource_get_user_data(resource);
3989
3990 pixman_region32_union_rect(®ion->region, ®ion->region,
3991 x, y, width, height);
3992 }
3993
3994 static void
region_subtract(struct wl_client * client,struct wl_resource * resource,int32_t x,int32_t y,int32_t width,int32_t height)3995 region_subtract(struct wl_client *client, struct wl_resource *resource,
3996 int32_t x, int32_t y, int32_t width, int32_t height)
3997 {
3998 struct weston_region *region = wl_resource_get_user_data(resource);
3999 pixman_region32_t rect;
4000
4001 pixman_region32_init_rect(&rect, x, y, width, height);
4002 pixman_region32_subtract(®ion->region, ®ion->region, &rect);
4003 pixman_region32_fini(&rect);
4004 }
4005
4006 static const struct wl_region_interface region_interface = {
4007 region_destroy,
4008 region_add,
4009 region_subtract
4010 };
4011
4012 static void
compositor_create_region(struct wl_client * client,struct wl_resource * resource,uint32_t id)4013 compositor_create_region(struct wl_client *client,
4014 struct wl_resource *resource, uint32_t id)
4015 {
4016 struct weston_region *region;
4017
4018 region = malloc(sizeof *region);
4019 if (region == NULL) {
4020 wl_resource_post_no_memory(resource);
4021 return;
4022 }
4023
4024 pixman_region32_init(®ion->region);
4025
4026 region->resource =
4027 wl_resource_create(client, &wl_region_interface, 1, id);
4028 if (region->resource == NULL) {
4029 free(region);
4030 wl_resource_post_no_memory(resource);
4031 return;
4032 }
4033 wl_resource_set_implementation(region->resource, ®ion_interface,
4034 region, destroy_region);
4035 }
4036
4037 static const struct wl_compositor_interface compositor_interface = {
4038 compositor_create_surface,
4039 compositor_create_region
4040 };
4041
4042 static void
weston_subsurface_commit_from_cache(struct weston_subsurface * sub)4043 weston_subsurface_commit_from_cache(struct weston_subsurface *sub)
4044 {
4045 struct weston_surface *surface = sub->surface;
4046
4047 weston_surface_commit_state(surface, &sub->cached);
4048 weston_buffer_reference(&sub->cached_buffer_ref, NULL);
4049
4050 weston_surface_commit_subsurface_order(surface);
4051
4052 weston_surface_schedule_repaint(surface);
4053
4054 sub->has_cached_data = 0;
4055 }
4056
4057 static void
weston_subsurface_commit_to_cache(struct weston_subsurface * sub)4058 weston_subsurface_commit_to_cache(struct weston_subsurface *sub)
4059 {
4060 struct weston_surface *surface = sub->surface;
4061
4062 /*
4063 * If this commit would cause the surface to move by the
4064 * attach(dx, dy) parameters, the old damage region must be
4065 * translated to correspond to the new surface coordinate system
4066 * origin.
4067 */
4068 pixman_region32_translate(&sub->cached.damage_surface,
4069 -surface->pending.sx, -surface->pending.sy);
4070 pixman_region32_union(&sub->cached.damage_surface,
4071 &sub->cached.damage_surface,
4072 &surface->pending.damage_surface);
4073 pixman_region32_clear(&surface->pending.damage_surface);
4074
4075 if (surface->pending.newly_attached) {
4076 sub->cached.newly_attached = 1;
4077 weston_surface_state_set_buffer(&sub->cached,
4078 surface->pending.buffer);
4079 weston_buffer_reference(&sub->cached_buffer_ref,
4080 surface->pending.buffer);
4081 weston_presentation_feedback_discard_list(
4082 &sub->cached.feedback_list);
4083 /* zwp_surface_synchronization_v1.set_acquire_fence */
4084 fd_move(&sub->cached.acquire_fence_fd,
4085 &surface->pending.acquire_fence_fd);
4086 /* zwp_surface_synchronization_v1.get_release */
4087 weston_buffer_release_move(&sub->cached.buffer_release_ref,
4088 &surface->pending.buffer_release_ref);
4089 }
4090 sub->cached.desired_protection = surface->pending.desired_protection;
4091 sub->cached.protection_mode = surface->pending.protection_mode;
4092 assert(surface->pending.acquire_fence_fd == -1);
4093 assert(surface->pending.buffer_release_ref.buffer_release == NULL);
4094 sub->cached.sx += surface->pending.sx;
4095 sub->cached.sy += surface->pending.sy;
4096
4097 apply_damage_buffer(&sub->cached.damage_surface, surface, &surface->pending);
4098
4099 sub->cached.buffer_viewport.changed |=
4100 surface->pending.buffer_viewport.changed;
4101 sub->cached.buffer_viewport.buffer =
4102 surface->pending.buffer_viewport.buffer;
4103 sub->cached.buffer_viewport.surface =
4104 surface->pending.buffer_viewport.surface;
4105
4106 weston_surface_reset_pending_buffer(surface);
4107
4108 pixman_region32_copy(&sub->cached.opaque, &surface->pending.opaque);
4109
4110 pixman_region32_copy(&sub->cached.input, &surface->pending.input);
4111
4112 wl_list_insert_list(&sub->cached.frame_callback_list,
4113 &surface->pending.frame_callback_list);
4114 wl_list_init(&surface->pending.frame_callback_list);
4115
4116 wl_list_insert_list(&sub->cached.feedback_list,
4117 &surface->pending.feedback_list);
4118 wl_list_init(&surface->pending.feedback_list);
4119
4120 sub->has_cached_data = 1;
4121 }
4122
4123 static bool
weston_subsurface_is_synchronized(struct weston_subsurface * sub)4124 weston_subsurface_is_synchronized(struct weston_subsurface *sub)
4125 {
4126 while (sub) {
4127 if (sub->synchronized)
4128 return true;
4129
4130 if (!sub->parent)
4131 return false;
4132
4133 sub = weston_surface_to_subsurface(sub->parent);
4134 }
4135
4136 return false;
4137 }
4138
4139 static void
weston_subsurface_commit(struct weston_subsurface * sub)4140 weston_subsurface_commit(struct weston_subsurface *sub)
4141 {
4142 struct weston_surface *surface = sub->surface;
4143 struct weston_subsurface *tmp;
4144
4145 /* Recursive check for effectively synchronized. */
4146 if (weston_subsurface_is_synchronized(sub)) {
4147 weston_subsurface_commit_to_cache(sub);
4148 } else {
4149 if (sub->has_cached_data) {
4150 /* flush accumulated state from cache */
4151 weston_subsurface_commit_to_cache(sub);
4152 weston_subsurface_commit_from_cache(sub);
4153 } else {
4154 weston_surface_commit(surface);
4155 }
4156
4157 wl_list_for_each(tmp, &surface->subsurface_list, parent_link) {
4158 if (tmp->surface != surface)
4159 weston_subsurface_parent_commit(tmp, 0);
4160 }
4161 }
4162 }
4163
4164 static void
weston_subsurface_synchronized_commit(struct weston_subsurface * sub)4165 weston_subsurface_synchronized_commit(struct weston_subsurface *sub)
4166 {
4167 struct weston_surface *surface = sub->surface;
4168 struct weston_subsurface *tmp;
4169
4170 /* From now on, commit_from_cache the whole sub-tree, regardless of
4171 * the synchronized mode of each child. This sub-surface or some
4172 * of its ancestors were synchronized, so we are synchronized
4173 * all the way down.
4174 */
4175
4176 if (sub->has_cached_data)
4177 weston_subsurface_commit_from_cache(sub);
4178
4179 wl_list_for_each(tmp, &surface->subsurface_list, parent_link) {
4180 if (tmp->surface != surface)
4181 weston_subsurface_parent_commit(tmp, 1);
4182 }
4183 }
4184
4185 static void
weston_subsurface_parent_commit(struct weston_subsurface * sub,int parent_is_synchronized)4186 weston_subsurface_parent_commit(struct weston_subsurface *sub,
4187 int parent_is_synchronized)
4188 {
4189 struct weston_view *view;
4190 if (sub->position.set) {
4191 wl_list_for_each(view, &sub->surface->views, surface_link)
4192 weston_view_set_position(view,
4193 sub->position.x,
4194 sub->position.y);
4195
4196 sub->position.set = 0;
4197 }
4198
4199 if (parent_is_synchronized || sub->synchronized)
4200 weston_subsurface_synchronized_commit(sub);
4201 }
4202
4203 static int
subsurface_get_label(struct weston_surface * surface,char * buf,size_t len)4204 subsurface_get_label(struct weston_surface *surface, char *buf, size_t len)
4205 {
4206 return snprintf(buf, len, "sub-surface");
4207 }
4208
4209 static void
subsurface_committed(struct weston_surface * surface,int32_t dx,int32_t dy)4210 subsurface_committed(struct weston_surface *surface, int32_t dx, int32_t dy)
4211 {
4212 struct weston_view *view;
4213
4214 wl_list_for_each(view, &surface->views, surface_link)
4215 weston_view_set_position(view,
4216 view->geometry.x + dx,
4217 view->geometry.y + dy);
4218
4219 /* No need to check parent mappedness, because if parent is not
4220 * mapped, parent is not in a visible layer, so this sub-surface
4221 * will not be drawn either.
4222 */
4223
4224 if (!weston_surface_is_mapped(surface)) {
4225 surface->is_mapped = true;
4226
4227 /* Cannot call weston_view_update_transform(),
4228 * because that would call it also for the parent surface,
4229 * which might not be mapped yet. That would lead to
4230 * inconsistent state, where the window could never be
4231 * mapped.
4232 *
4233 * Instead just force the is_mapped flag on, to make
4234 * weston_surface_is_mapped() return true, so that when the
4235 * parent surface does get mapped, this one will get
4236 * included, too. See view_list_add().
4237 */
4238 }
4239 }
4240
4241 static struct weston_subsurface *
weston_surface_to_subsurface(struct weston_surface * surface)4242 weston_surface_to_subsurface(struct weston_surface *surface)
4243 {
4244 if (surface->committed == subsurface_committed)
4245 return surface->committed_private;
4246
4247 return NULL;
4248 }
4249
4250 WL_EXPORT struct weston_surface *
weston_surface_get_main_surface(struct weston_surface * surface)4251 weston_surface_get_main_surface(struct weston_surface *surface)
4252 {
4253 struct weston_subsurface *sub;
4254
4255 while (surface && (sub = weston_surface_to_subsurface(surface)))
4256 surface = sub->parent;
4257
4258 return surface;
4259 }
4260
4261 WL_EXPORT int
weston_surface_set_role(struct weston_surface * surface,const char * role_name,struct wl_resource * error_resource,uint32_t error_code)4262 weston_surface_set_role(struct weston_surface *surface,
4263 const char *role_name,
4264 struct wl_resource *error_resource,
4265 uint32_t error_code)
4266 {
4267 assert(role_name);
4268
4269 if (surface->role_name == NULL ||
4270 surface->role_name == role_name ||
4271 strcmp(surface->role_name, role_name) == 0) {
4272 surface->role_name = role_name;
4273
4274 return 0;
4275 }
4276
4277 wl_resource_post_error(error_resource, error_code,
4278 "Cannot assign role %s to wl_surface@%d,"
4279 " already has role %s\n",
4280 role_name,
4281 wl_resource_get_id(surface->resource),
4282 surface->role_name);
4283 return -1;
4284 }
4285
4286 WL_EXPORT const char *
weston_surface_get_role(struct weston_surface * surface)4287 weston_surface_get_role(struct weston_surface *surface)
4288 {
4289 return surface->role_name;
4290 }
4291
4292 WL_EXPORT void
weston_surface_set_label_func(struct weston_surface * surface,int (* desc)(struct weston_surface *,char *,size_t))4293 weston_surface_set_label_func(struct weston_surface *surface,
4294 int (*desc)(struct weston_surface *,
4295 char *, size_t))
4296 {
4297 surface->get_label = desc;
4298 // OHOS remove timeline
4299 // weston_timeline_refresh_subscription_objects(surface->compositor,
4300 // surface);
4301 }
4302
4303 /** Get the size of surface contents
4304 *
4305 * \param surface The surface to query.
4306 * \param width Returns the width of raw contents.
4307 * \param height Returns the height of raw contents.
4308 *
4309 * Retrieves the raw surface content size in pixels for the given surface.
4310 * This is the whole content size in buffer pixels. If the surface
4311 * has no content or the renderer does not implement this feature,
4312 * zeroes are returned.
4313 *
4314 * This function is used to determine the buffer size needed for
4315 * a weston_surface_copy_content() call.
4316 */
4317 WL_EXPORT void
weston_surface_get_content_size(struct weston_surface * surface,int * width,int * height)4318 weston_surface_get_content_size(struct weston_surface *surface,
4319 int *width, int *height)
4320 {
4321 struct weston_renderer *rer = surface->compositor->renderer;
4322
4323 if (!rer->surface_get_content_size) {
4324 *width = 0;
4325 *height = 0;
4326 return;
4327 }
4328
4329 rer->surface_get_content_size(surface, width, height);
4330 }
4331
4332 /** Get the bounding box of a surface and its subsurfaces
4333 *
4334 * \param surface The surface to query.
4335 * \return The bounding box relative to the surface origin.
4336 *
4337 */
4338 WL_EXPORT struct weston_geometry
weston_surface_get_bounding_box(struct weston_surface * surface)4339 weston_surface_get_bounding_box(struct weston_surface *surface)
4340 {
4341 pixman_region32_t region;
4342 pixman_box32_t *box;
4343 struct weston_subsurface *subsurface;
4344
4345 pixman_region32_init_rect(®ion,
4346 0, 0,
4347 surface->width, surface->height);
4348
4349 wl_list_for_each(subsurface, &surface->subsurface_list, parent_link)
4350 pixman_region32_union_rect(®ion, ®ion,
4351 subsurface->position.x,
4352 subsurface->position.y,
4353 subsurface->surface->width,
4354 subsurface->surface->height);
4355
4356 box = pixman_region32_extents(®ion);
4357 struct weston_geometry geometry = {
4358 .x = box->x1,
4359 .y = box->y1,
4360 .width = box->x2 - box->x1,
4361 .height = box->y2 - box->y1,
4362 };
4363
4364 pixman_region32_fini(®ion);
4365
4366 return geometry;
4367 }
4368
4369 /** Copy surface contents to system memory.
4370 *
4371 * \param surface The surface to copy from.
4372 * \param target Pointer to the target memory buffer.
4373 * \param size Size of the target buffer in bytes.
4374 * \param src_x X location on contents to copy from.
4375 * \param src_y Y location on contents to copy from.
4376 * \param width Width in pixels of the area to copy.
4377 * \param height Height in pixels of the area to copy.
4378 * \return 0 for success, -1 for failure.
4379 *
4380 * Surface contents are maintained by the renderer. They can be in a
4381 * reserved weston_buffer or as a copy, e.g. a GL texture, or something
4382 * else.
4383 *
4384 * Surface contents are copied into memory pointed to by target,
4385 * which has size bytes of space available. The target memory
4386 * may be larger than needed, but being smaller returns an error.
4387 * The extra bytes in target may or may not be written; their content is
4388 * unspecified. Size must be large enough to hold the image.
4389 *
4390 * The image in the target memory will be arranged in rows from
4391 * top to bottom, and pixels on a row from left to right. The pixel
4392 * format is PIXMAN_a8b8g8r8, 4 bytes per pixel, and stride is exactly
4393 * width * 4.
4394 *
4395 * Parameters src_x and src_y define the upper-left corner in buffer
4396 * coordinates (pixels) to copy from. Parameters width and height
4397 * define the size of the area to copy in pixels.
4398 *
4399 * The rectangle defined by src_x, src_y, width, height must fit in
4400 * the surface contents. Otherwise an error is returned.
4401 *
4402 * Use weston_surface_get_content_size to determine the content size; the
4403 * needed target buffer size and rectangle limits.
4404 *
4405 * CURRENT IMPLEMENTATION RESTRICTIONS:
4406 * - the machine must be little-endian due to Pixman formats.
4407 *
4408 * NOTE: Pixman formats are premultiplied.
4409 */
4410 WL_EXPORT int
weston_surface_copy_content(struct weston_surface * surface,void * target,size_t size,int src_x,int src_y,int width,int height)4411 weston_surface_copy_content(struct weston_surface *surface,
4412 void *target, size_t size,
4413 int src_x, int src_y,
4414 int width, int height)
4415 {
4416 struct weston_renderer *rer = surface->compositor->renderer;
4417 int cw, ch;
4418 const size_t bytespp = 4; /* PIXMAN_a8b8g8r8 */
4419
4420 if (!rer->surface_copy_content)
4421 return -1;
4422
4423 weston_surface_get_content_size(surface, &cw, &ch);
4424
4425 if (src_x < 0 || src_y < 0)
4426 return -1;
4427
4428 if (width <= 0 || height <= 0)
4429 return -1;
4430
4431 if (src_x + width > cw || src_y + height > ch)
4432 return -1;
4433
4434 if (width * bytespp * height > size)
4435 return -1;
4436
4437 return rer->surface_copy_content(surface, target, size,
4438 src_x, src_y, width, height);
4439 }
4440
4441 static void
subsurface_set_position(struct wl_client * client,struct wl_resource * resource,int32_t x,int32_t y)4442 subsurface_set_position(struct wl_client *client,
4443 struct wl_resource *resource, int32_t x, int32_t y)
4444 {
4445 struct weston_subsurface *sub = wl_resource_get_user_data(resource);
4446
4447 if (!sub)
4448 return;
4449
4450 sub->position.x = x;
4451 sub->position.y = y;
4452 sub->position.set = 1;
4453 }
4454
4455 static struct weston_subsurface *
subsurface_find_sibling(struct weston_subsurface * sub,struct weston_surface * surface)4456 subsurface_find_sibling(struct weston_subsurface *sub,
4457 struct weston_surface *surface)
4458 {
4459 struct weston_surface *parent = sub->parent;
4460 struct weston_subsurface *sibling;
4461
4462 wl_list_for_each(sibling, &parent->subsurface_list, parent_link) {
4463 if (sibling->surface == surface && sibling != sub)
4464 return sibling;
4465 }
4466
4467 return NULL;
4468 }
4469
4470 static struct weston_subsurface *
subsurface_sibling_check(struct weston_subsurface * sub,struct weston_surface * surface,const char * request)4471 subsurface_sibling_check(struct weston_subsurface *sub,
4472 struct weston_surface *surface,
4473 const char *request)
4474 {
4475 struct weston_subsurface *sibling;
4476
4477 sibling = subsurface_find_sibling(sub, surface);
4478 if (!sibling) {
4479 wl_resource_post_error(sub->resource,
4480 WL_SUBSURFACE_ERROR_BAD_SURFACE,
4481 "%s: wl_surface@%d is not a parent or sibling",
4482 request, wl_resource_get_id(surface->resource));
4483 return NULL;
4484 }
4485
4486 assert(sibling->parent == sub->parent);
4487
4488 return sibling;
4489 }
4490
4491 static void
subsurface_place_above(struct wl_client * client,struct wl_resource * resource,struct wl_resource * sibling_resource)4492 subsurface_place_above(struct wl_client *client,
4493 struct wl_resource *resource,
4494 struct wl_resource *sibling_resource)
4495 {
4496 struct weston_subsurface *sub = wl_resource_get_user_data(resource);
4497 struct weston_surface *surface =
4498 wl_resource_get_user_data(sibling_resource);
4499 struct weston_subsurface *sibling;
4500
4501 if (!sub)
4502 return;
4503
4504 sibling = subsurface_sibling_check(sub, surface, "place_above");
4505 if (!sibling)
4506 return;
4507
4508 wl_list_remove(&sub->parent_link_pending);
4509 wl_list_insert(sibling->parent_link_pending.prev,
4510 &sub->parent_link_pending);
4511
4512 sub->reordered = true;
4513 }
4514
4515 static void
subsurface_place_below(struct wl_client * client,struct wl_resource * resource,struct wl_resource * sibling_resource)4516 subsurface_place_below(struct wl_client *client,
4517 struct wl_resource *resource,
4518 struct wl_resource *sibling_resource)
4519 {
4520 struct weston_subsurface *sub = wl_resource_get_user_data(resource);
4521 struct weston_surface *surface =
4522 wl_resource_get_user_data(sibling_resource);
4523 struct weston_subsurface *sibling;
4524
4525 if (!sub)
4526 return;
4527
4528 sibling = subsurface_sibling_check(sub, surface, "place_below");
4529 if (!sibling)
4530 return;
4531
4532 wl_list_remove(&sub->parent_link_pending);
4533 wl_list_insert(&sibling->parent_link_pending,
4534 &sub->parent_link_pending);
4535
4536 sub->reordered = true;
4537 }
4538
4539 static void
subsurface_set_sync(struct wl_client * client,struct wl_resource * resource)4540 subsurface_set_sync(struct wl_client *client, struct wl_resource *resource)
4541 {
4542 struct weston_subsurface *sub = wl_resource_get_user_data(resource);
4543
4544 if (sub)
4545 sub->synchronized = 1;
4546 }
4547
4548 static void
subsurface_set_desync(struct wl_client * client,struct wl_resource * resource)4549 subsurface_set_desync(struct wl_client *client, struct wl_resource *resource)
4550 {
4551 struct weston_subsurface *sub = wl_resource_get_user_data(resource);
4552
4553 if (sub && sub->synchronized) {
4554 sub->synchronized = 0;
4555
4556 /* If sub became effectively desynchronized, flush. */
4557 if (!weston_subsurface_is_synchronized(sub))
4558 weston_subsurface_synchronized_commit(sub);
4559 }
4560 }
4561
4562 static void
weston_subsurface_unlink_parent(struct weston_subsurface * sub)4563 weston_subsurface_unlink_parent(struct weston_subsurface *sub)
4564 {
4565 wl_list_remove(&sub->parent_link);
4566 wl_list_remove(&sub->parent_link_pending);
4567 wl_list_remove(&sub->parent_destroy_listener.link);
4568 sub->parent = NULL;
4569 }
4570
4571 static void
4572 weston_subsurface_destroy(struct weston_subsurface *sub);
4573
4574 static void
subsurface_handle_surface_destroy(struct wl_listener * listener,void * data)4575 subsurface_handle_surface_destroy(struct wl_listener *listener, void *data)
4576 {
4577 struct weston_subsurface *sub =
4578 container_of(listener, struct weston_subsurface,
4579 surface_destroy_listener);
4580 assert(data == sub->surface);
4581
4582 /* The protocol object (wl_resource) is left inert. */
4583 if (sub->resource)
4584 wl_resource_set_user_data(sub->resource, NULL);
4585
4586 weston_subsurface_destroy(sub);
4587 }
4588
4589 static void
subsurface_handle_parent_destroy(struct wl_listener * listener,void * data)4590 subsurface_handle_parent_destroy(struct wl_listener *listener, void *data)
4591 {
4592 struct weston_subsurface *sub =
4593 container_of(listener, struct weston_subsurface,
4594 parent_destroy_listener);
4595 assert(data == sub->parent);
4596 assert(sub->surface != sub->parent);
4597
4598 if (weston_surface_is_mapped(sub->surface))
4599 weston_surface_unmap(sub->surface);
4600
4601 weston_subsurface_unlink_parent(sub);
4602 }
4603
4604 static void
subsurface_resource_destroy(struct wl_resource * resource)4605 subsurface_resource_destroy(struct wl_resource *resource)
4606 {
4607 struct weston_subsurface *sub = wl_resource_get_user_data(resource);
4608
4609 if (sub)
4610 weston_subsurface_destroy(sub);
4611 }
4612
4613 static void
subsurface_destroy(struct wl_client * client,struct wl_resource * resource)4614 subsurface_destroy(struct wl_client *client, struct wl_resource *resource)
4615 {
4616 wl_resource_destroy(resource);
4617 }
4618
4619 static void
weston_subsurface_link_parent(struct weston_subsurface * sub,struct weston_surface * parent)4620 weston_subsurface_link_parent(struct weston_subsurface *sub,
4621 struct weston_surface *parent)
4622 {
4623 sub->parent = parent;
4624 sub->parent_destroy_listener.notify = subsurface_handle_parent_destroy;
4625 wl_signal_add(&parent->destroy_signal,
4626 &sub->parent_destroy_listener);
4627
4628 wl_list_insert(&parent->subsurface_list, &sub->parent_link);
4629 wl_list_insert(&parent->subsurface_list_pending,
4630 &sub->parent_link_pending);
4631 }
4632
4633 static void
weston_subsurface_link_surface(struct weston_subsurface * sub,struct weston_surface * surface)4634 weston_subsurface_link_surface(struct weston_subsurface *sub,
4635 struct weston_surface *surface)
4636 {
4637 sub->surface = surface;
4638 sub->surface_destroy_listener.notify =
4639 subsurface_handle_surface_destroy;
4640 wl_signal_add(&surface->destroy_signal,
4641 &sub->surface_destroy_listener);
4642 }
4643
4644 static void
weston_subsurface_destroy(struct weston_subsurface * sub)4645 weston_subsurface_destroy(struct weston_subsurface *sub)
4646 {
4647 struct weston_view *view, *next;
4648
4649 assert(sub->surface);
4650
4651 if (sub->resource) {
4652 assert(weston_surface_to_subsurface(sub->surface) == sub);
4653 assert(sub->parent_destroy_listener.notify ==
4654 subsurface_handle_parent_destroy);
4655
4656 wl_list_for_each_safe(view, next, &sub->surface->views, surface_link) {
4657 weston_view_unmap(view);
4658 weston_view_destroy(view);
4659 }
4660
4661 if (sub->parent)
4662 weston_subsurface_unlink_parent(sub);
4663
4664 weston_surface_state_fini(&sub->cached);
4665 weston_buffer_reference(&sub->cached_buffer_ref, NULL);
4666
4667 sub->surface->committed = NULL;
4668 sub->surface->committed_private = NULL;
4669 weston_surface_set_label_func(sub->surface, NULL);
4670 } else {
4671 /* the dummy weston_subsurface for the parent itself */
4672 assert(sub->parent_destroy_listener.notify == NULL);
4673 wl_list_remove(&sub->parent_link);
4674 wl_list_remove(&sub->parent_link_pending);
4675 }
4676
4677 wl_list_remove(&sub->surface_destroy_listener.link);
4678 free(sub);
4679 }
4680
4681 static const struct wl_subsurface_interface subsurface_implementation = {
4682 subsurface_destroy,
4683 subsurface_set_position,
4684 subsurface_place_above,
4685 subsurface_place_below,
4686 subsurface_set_sync,
4687 subsurface_set_desync
4688 };
4689
4690 static struct weston_subsurface *
weston_subsurface_create(uint32_t id,struct weston_surface * surface,struct weston_surface * parent)4691 weston_subsurface_create(uint32_t id, struct weston_surface *surface,
4692 struct weston_surface *parent)
4693 {
4694 struct weston_subsurface *sub;
4695 struct wl_client *client = wl_resource_get_client(surface->resource);
4696
4697 sub = zalloc(sizeof *sub);
4698 if (sub == NULL)
4699 return NULL;
4700
4701 wl_list_init(&sub->unused_views);
4702
4703 sub->resource =
4704 wl_resource_create(client, &wl_subsurface_interface, 1, id);
4705 if (!sub->resource) {
4706 free(sub);
4707 return NULL;
4708 }
4709
4710 wl_resource_set_implementation(sub->resource,
4711 &subsurface_implementation,
4712 sub, subsurface_resource_destroy);
4713 weston_subsurface_link_surface(sub, surface);
4714 weston_subsurface_link_parent(sub, parent);
4715 weston_surface_state_init(&sub->cached);
4716 sub->cached_buffer_ref.buffer = NULL;
4717 sub->synchronized = 1;
4718
4719 return sub;
4720 }
4721
4722 /* Create a dummy subsurface for having the parent itself in its
4723 * sub-surface lists. Makes stacking order manipulation easy.
4724 */
4725 static struct weston_subsurface *
weston_subsurface_create_for_parent(struct weston_surface * parent)4726 weston_subsurface_create_for_parent(struct weston_surface *parent)
4727 {
4728 struct weston_subsurface *sub;
4729
4730 sub = zalloc(sizeof *sub);
4731 if (sub == NULL)
4732 return NULL;
4733
4734 weston_subsurface_link_surface(sub, parent);
4735 sub->parent = parent;
4736 wl_list_insert(&parent->subsurface_list, &sub->parent_link);
4737 wl_list_insert(&parent->subsurface_list_pending,
4738 &sub->parent_link_pending);
4739
4740 return sub;
4741 }
4742
4743 static void
subcompositor_get_subsurface(struct wl_client * client,struct wl_resource * resource,uint32_t id,struct wl_resource * surface_resource,struct wl_resource * parent_resource)4744 subcompositor_get_subsurface(struct wl_client *client,
4745 struct wl_resource *resource,
4746 uint32_t id,
4747 struct wl_resource *surface_resource,
4748 struct wl_resource *parent_resource)
4749 {
4750 struct weston_surface *surface =
4751 wl_resource_get_user_data(surface_resource);
4752 struct weston_surface *parent =
4753 wl_resource_get_user_data(parent_resource);
4754 struct weston_subsurface *sub;
4755 static const char where[] = "get_subsurface: wl_subsurface@";
4756
4757 if (surface == parent) {
4758 wl_resource_post_error(resource,
4759 WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
4760 "%s%d: wl_surface@%d cannot be its own parent",
4761 where, id, wl_resource_get_id(surface_resource));
4762 return;
4763 }
4764
4765 if (weston_surface_to_subsurface(surface)) {
4766 wl_resource_post_error(resource,
4767 WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
4768 "%s%d: wl_surface@%d is already a sub-surface",
4769 where, id, wl_resource_get_id(surface_resource));
4770 return;
4771 }
4772
4773 if (weston_surface_set_role(surface, "wl_subsurface", resource,
4774 WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE) < 0)
4775 return;
4776
4777 if (weston_surface_get_main_surface(parent) == surface) {
4778 wl_resource_post_error(resource,
4779 WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
4780 "%s%d: wl_surface@%d is an ancestor of parent",
4781 where, id, wl_resource_get_id(surface_resource));
4782 return;
4783 }
4784
4785 /* make sure the parent is in its own list */
4786 if (wl_list_empty(&parent->subsurface_list)) {
4787 if (!weston_subsurface_create_for_parent(parent)) {
4788 wl_resource_post_no_memory(resource);
4789 return;
4790 }
4791 }
4792
4793 sub = weston_subsurface_create(id, surface, parent);
4794 if (!sub) {
4795 wl_resource_post_no_memory(resource);
4796 return;
4797 }
4798
4799 surface->committed = subsurface_committed;
4800 surface->committed_private = sub;
4801 weston_surface_set_label_func(surface, subsurface_get_label);
4802 }
4803
4804 static void
subcompositor_destroy(struct wl_client * client,struct wl_resource * resource)4805 subcompositor_destroy(struct wl_client *client, struct wl_resource *resource)
4806 {
4807 wl_resource_destroy(resource);
4808 }
4809
4810 static const struct wl_subcompositor_interface subcompositor_interface = {
4811 subcompositor_destroy,
4812 subcompositor_get_subsurface
4813 };
4814
4815 static void
bind_subcompositor(struct wl_client * client,void * data,uint32_t version,uint32_t id)4816 bind_subcompositor(struct wl_client *client,
4817 void *data, uint32_t version, uint32_t id)
4818 {
4819 struct weston_compositor *compositor = data;
4820 struct wl_resource *resource;
4821
4822 resource =
4823 wl_resource_create(client, &wl_subcompositor_interface, 1, id);
4824 if (resource == NULL) {
4825 wl_client_post_no_memory(client);
4826 return;
4827 }
4828 wl_resource_set_implementation(resource, &subcompositor_interface,
4829 compositor, NULL);
4830 }
4831
4832 /** Set a DPMS mode on all of the compositor's outputs
4833 *
4834 * \param compositor The compositor instance
4835 * \param state The DPMS state the outputs will be set to
4836 */
4837 static void
weston_compositor_dpms(struct weston_compositor * compositor,enum dpms_enum state)4838 weston_compositor_dpms(struct weston_compositor *compositor,
4839 enum dpms_enum state)
4840 {
4841 struct weston_output *output;
4842
4843 wl_list_for_each(output, &compositor->output_list, link)
4844 if (output->set_dpms)
4845 output->set_dpms(output, state);
4846 }
4847
4848 /** Restores the compositor to active status
4849 *
4850 * \param compositor The compositor instance
4851 *
4852 * If the compositor was in a sleeping mode, all outputs are powered
4853 * back on via DPMS. Otherwise if the compositor was inactive
4854 * (idle/locked, offscreen, or sleeping) then the compositor's wake
4855 * signal will fire.
4856 *
4857 * Restarts the idle timer.
4858 * \ingroup compositor
4859 */
4860 WL_EXPORT void
weston_compositor_wake(struct weston_compositor * compositor)4861 weston_compositor_wake(struct weston_compositor *compositor)
4862 {
4863 uint32_t old_state = compositor->state;
4864
4865 /* The state needs to be changed before emitting the wake
4866 * signal because that may try to schedule a repaint which
4867 * will not work if the compositor is still sleeping */
4868 compositor->state = WESTON_COMPOSITOR_ACTIVE;
4869
4870 switch (old_state) {
4871 case WESTON_COMPOSITOR_SLEEPING:
4872 case WESTON_COMPOSITOR_IDLE:
4873 case WESTON_COMPOSITOR_OFFSCREEN:
4874 weston_compositor_dpms(compositor, WESTON_DPMS_ON);
4875 wl_signal_emit(&compositor->wake_signal, compositor);
4876 /* fall through */
4877 default:
4878 wl_event_source_timer_update(compositor->idle_source,
4879 compositor->idle_time * 1000);
4880 }
4881 }
4882
4883 /** Turns off rendering and frame events for the compositor.
4884 *
4885 * \param compositor The compositor instance
4886 *
4887 * This is used for example to prevent further rendering while the
4888 * compositor is shutting down.
4889 *
4890 * Stops the idle timer.
4891 *
4892 * \ingroup compositor
4893 */
4894 WL_EXPORT void
weston_compositor_offscreen(struct weston_compositor * compositor)4895 weston_compositor_offscreen(struct weston_compositor *compositor)
4896 {
4897 switch (compositor->state) {
4898 case WESTON_COMPOSITOR_OFFSCREEN:
4899 return;
4900 case WESTON_COMPOSITOR_SLEEPING:
4901 default:
4902 compositor->state = WESTON_COMPOSITOR_OFFSCREEN;
4903 wl_event_source_timer_update(compositor->idle_source, 0);
4904 }
4905 }
4906
4907 /** Powers down all attached output devices
4908 *
4909 * \param compositor The compositor instance
4910 *
4911 * Causes rendering to the outputs to cease, and no frame events to be
4912 * sent. Only powers down the outputs if the compositor is not already
4913 * in sleep mode.
4914 *
4915 * Stops the idle timer.
4916 *
4917 * \ingroup compositor
4918 */
4919 WL_EXPORT void
weston_compositor_sleep(struct weston_compositor * compositor)4920 weston_compositor_sleep(struct weston_compositor *compositor)
4921 {
4922 if (compositor->state == WESTON_COMPOSITOR_SLEEPING)
4923 return;
4924
4925 wl_event_source_timer_update(compositor->idle_source, 0);
4926 compositor->state = WESTON_COMPOSITOR_SLEEPING;
4927 weston_compositor_dpms(compositor, WESTON_DPMS_OFF);
4928 }
4929
4930 /** Sets compositor to idle mode
4931 *
4932 * \param data The compositor instance
4933 *
4934 * This is called when the idle timer fires. Once the compositor is in
4935 * idle mode it requires a wake action (e.g. via
4936 * weston_compositor_wake()) to restore it. The compositor's
4937 * idle_signal will be triggered when the idle event occurs.
4938 *
4939 * Idleness can be inhibited by setting the compositor's idle_inhibit
4940 * property.
4941 */
4942 static int
idle_handler(void * data)4943 idle_handler(void *data)
4944 {
4945 struct weston_compositor *compositor = data;
4946
4947 if (compositor->idle_inhibit)
4948 return 1;
4949
4950 compositor->state = WESTON_COMPOSITOR_IDLE;
4951 wl_signal_emit(&compositor->idle_signal, compositor);
4952
4953 return 1;
4954 }
4955
4956 WL_EXPORT void
weston_plane_init(struct weston_plane * plane,struct weston_compositor * ec,int32_t x,int32_t y)4957 weston_plane_init(struct weston_plane *plane,
4958 struct weston_compositor *ec,
4959 int32_t x, int32_t y)
4960 {
4961 pixman_region32_init(&plane->damage);
4962 pixman_region32_init(&plane->clip);
4963 plane->x = x;
4964 plane->y = y;
4965 plane->compositor = ec;
4966
4967 /* Init the link so that the call to wl_list_remove() when releasing
4968 * the plane without ever stacking doesn't lead to a crash */
4969 wl_list_init(&plane->link);
4970 }
4971
4972 WL_EXPORT void
weston_plane_release(struct weston_plane * plane)4973 weston_plane_release(struct weston_plane *plane)
4974 {
4975 struct weston_view *view;
4976
4977 pixman_region32_fini(&plane->damage);
4978 pixman_region32_fini(&plane->clip);
4979
4980 wl_list_for_each(view, &plane->compositor->view_list, link) {
4981 if (view->plane == plane)
4982 view->plane = NULL;
4983 }
4984
4985 wl_list_remove(&plane->link);
4986 }
4987
4988 /** weston_compositor_stack_plane
4989 * \ingroup compositor
4990 */
4991 WL_EXPORT void
weston_compositor_stack_plane(struct weston_compositor * ec,struct weston_plane * plane,struct weston_plane * above)4992 weston_compositor_stack_plane(struct weston_compositor *ec,
4993 struct weston_plane *plane,
4994 struct weston_plane *above)
4995 {
4996 if (above)
4997 wl_list_insert(above->link.prev, &plane->link);
4998 else
4999 wl_list_insert(&ec->plane_list, &plane->link);
5000 }
5001
5002 static void
output_release(struct wl_client * client,struct wl_resource * resource)5003 output_release(struct wl_client *client, struct wl_resource *resource)
5004 {
5005 wl_resource_destroy(resource);
5006 }
5007
5008 static const struct wl_output_interface output_interface = {
5009 output_release,
5010 };
5011
5012
unbind_resource(struct wl_resource * resource)5013 static void unbind_resource(struct wl_resource *resource)
5014 {
5015 wl_list_remove(wl_resource_get_link(resource));
5016 }
5017
5018 static void
bind_output(struct wl_client * client,void * data,uint32_t version,uint32_t id)5019 bind_output(struct wl_client *client,
5020 void *data, uint32_t version, uint32_t id)
5021 {
5022 struct weston_head *head = data;
5023 struct weston_output *output = head->output;
5024 struct weston_mode *mode;
5025 struct wl_resource *resource;
5026
5027 resource = wl_resource_create(client, &wl_output_interface,
5028 version, id);
5029 if (resource == NULL) {
5030 wl_client_post_no_memory(client);
5031 return;
5032 }
5033
5034 wl_list_insert(&head->resource_list, wl_resource_get_link(resource));
5035 wl_resource_set_implementation(resource, &output_interface, head,
5036 unbind_resource);
5037
5038 assert(output);
5039 wl_output_send_geometry(resource,
5040 output->x,
5041 output->y,
5042 head->mm_width,
5043 head->mm_height,
5044 head->subpixel,
5045 head->make, head->model,
5046 output->transform);
5047 if (version >= WL_OUTPUT_SCALE_SINCE_VERSION)
5048 wl_output_send_scale(resource,
5049 output->current_scale);
5050
5051 wl_list_for_each (mode, &output->mode_list, link) {
5052 wl_output_send_mode(resource,
5053 mode->flags,
5054 mode->width,
5055 mode->height,
5056 mode->refresh);
5057 }
5058
5059 if (version >= WL_OUTPUT_DONE_SINCE_VERSION)
5060 wl_output_send_done(resource);
5061 }
5062
5063 static void
weston_head_add_global(struct weston_head * head)5064 weston_head_add_global(struct weston_head *head)
5065 {
5066 head->global = wl_global_create(head->compositor->wl_display,
5067 &wl_output_interface, 3,
5068 head, bind_output);
5069 }
5070
5071 /** Remove the global wl_output protocol object
5072 *
5073 * \param head The head whose global to remove.
5074 *
5075 * Also orphans the wl_resources for this head (wl_output).
5076 */
5077 static void
weston_head_remove_global(struct weston_head * head)5078 weston_head_remove_global(struct weston_head *head)
5079 {
5080 struct wl_resource *resource, *tmp;
5081
5082 if (head->global)
5083 wl_global_destroy(head->global);
5084 head->global = NULL;
5085
5086 wl_resource_for_each_safe(resource, tmp, &head->resource_list) {
5087 unbind_resource(resource);
5088 wl_resource_set_destructor(resource, NULL);
5089 wl_resource_set_user_data(resource, NULL);
5090 }
5091
5092 wl_resource_for_each(resource, &head->xdg_output_resource_list) {
5093 /* It's sufficient to unset the destructor, then the list elements
5094 * won't be accessed.
5095 */
5096 wl_resource_set_destructor(resource, NULL);
5097 }
5098 wl_list_init(&head->xdg_output_resource_list);
5099 }
5100
5101 /** Get the backing object of wl_output
5102 *
5103 * \param resource A wl_output protocol object.
5104 * \return The backing object (user data) of a wl_resource representing a
5105 * wl_output protocol object.
5106 *
5107 * \ingroup head
5108 */
5109 WL_EXPORT struct weston_head *
weston_head_from_resource(struct wl_resource * resource)5110 weston_head_from_resource(struct wl_resource *resource)
5111 {
5112 assert(wl_resource_instance_of(resource, &wl_output_interface,
5113 &output_interface));
5114
5115 return wl_resource_get_user_data(resource);
5116 }
5117
5118 /** Initialize a pre-allocated weston_head
5119 *
5120 * \param head The head to initialize.
5121 * \param name The head name, e.g. the connector name or equivalent.
5122 *
5123 * The head will be safe to attach, detach and release.
5124 *
5125 * The name is used in logs, and can be used by compositors as a configuration
5126 * identifier.
5127 *
5128 * \ingroup head
5129 * \internal
5130 */
5131 WL_EXPORT void
weston_head_init(struct weston_head * head,const char * name)5132 weston_head_init(struct weston_head *head, const char *name)
5133 {
5134 /* Add some (in)sane defaults which can be used
5135 * for checking if an output was properly configured
5136 */
5137 memset(head, 0, sizeof *head);
5138
5139 wl_list_init(&head->compositor_link);
5140 wl_signal_init(&head->destroy_signal);
5141 wl_list_init(&head->output_link);
5142 wl_list_init(&head->resource_list);
5143 wl_list_init(&head->xdg_output_resource_list);
5144 head->name = strdup(name);
5145 head->current_protection = WESTON_HDCP_DISABLE;
5146 }
5147
5148 /** Send output heads changed signal
5149 *
5150 * \param output The output that changed.
5151 *
5152 * Notify that the enabled output gained and/or lost heads, or that the
5153 * associated heads may have changed their connection status. This does not
5154 * include cases where the output becomes enabled or disabled. The registered
5155 * callbacks are called after the change has successfully happened.
5156 *
5157 * If connection status change causes the compositor to attach or detach a head
5158 * to an enabled output, the registered callbacks may be called multiple times.
5159 *
5160 * \ingroup output
5161 */
5162 static void
weston_output_emit_heads_changed(struct weston_output * output)5163 weston_output_emit_heads_changed(struct weston_output *output)
5164 {
5165 wl_signal_emit(&output->compositor->output_heads_changed_signal,
5166 output);
5167 }
5168
5169 /** Idle task for emitting heads_changed_signal */
5170 static void
weston_compositor_call_heads_changed(void * data)5171 weston_compositor_call_heads_changed(void *data)
5172 {
5173 struct weston_compositor *compositor = data;
5174 struct weston_head *head;
5175
5176 compositor->heads_changed_source = NULL;
5177
5178 wl_signal_emit(&compositor->heads_changed_signal, compositor);
5179
5180 wl_list_for_each(head, &compositor->head_list, compositor_link) {
5181 if (head->output && head->output->enabled)
5182 weston_output_emit_heads_changed(head->output);
5183 }
5184 }
5185
5186 /** Schedule a call on idle to heads_changed callback
5187 *
5188 * \param compositor The Compositor.
5189 *
5190 * \ingroup compositor
5191 * \internal
5192 */
5193 static void
weston_compositor_schedule_heads_changed(struct weston_compositor * compositor)5194 weston_compositor_schedule_heads_changed(struct weston_compositor *compositor)
5195 {
5196 struct wl_event_loop *loop;
5197
5198 if (compositor->heads_changed_source)
5199 return;
5200
5201 loop = wl_display_get_event_loop(compositor->wl_display);
5202 compositor->heads_changed_source = wl_event_loop_add_idle(loop,
5203 weston_compositor_call_heads_changed, compositor);
5204 }
5205
5206 /** Register a new head
5207 *
5208 * \param compositor The compositor.
5209 * \param head The head to register, must not be already registered.
5210 *
5211 * This signals the core that a new head has become available, leading to
5212 * heads_changed hook being called later.
5213 *
5214 * \ingroup compositor
5215 * \internal
5216 */
5217 WL_EXPORT void
weston_compositor_add_head(struct weston_compositor * compositor,struct weston_head * head)5218 weston_compositor_add_head(struct weston_compositor *compositor,
5219 struct weston_head *head)
5220 {
5221 assert(wl_list_empty(&head->compositor_link));
5222 assert(head->name);
5223
5224 wl_list_insert(compositor->head_list.prev, &head->compositor_link);
5225 head->compositor = compositor;
5226 weston_compositor_schedule_heads_changed(compositor);
5227 }
5228
5229 /** Adds a listener to be called when heads change
5230 *
5231 * \param compositor The compositor.
5232 * \param listener The listener to add.
5233 *
5234 * The listener notify function argument is weston_compositor.
5235 *
5236 * The listener function will be called after heads are added or their
5237 * connection status has changed. Several changes may be accumulated into a
5238 * single call. The user is expected to iterate over the existing heads and
5239 * check their statuses to find out what changed.
5240 *
5241 * \sa weston_compositor_iterate_heads, weston_head_is_connected,
5242 * weston_head_is_enabled
5243 * \ingroup compositor
5244 */
5245 WL_EXPORT void
weston_compositor_add_heads_changed_listener(struct weston_compositor * compositor,struct wl_listener * listener)5246 weston_compositor_add_heads_changed_listener(struct weston_compositor *compositor,
5247 struct wl_listener *listener)
5248 {
5249 wl_signal_add(&compositor->heads_changed_signal, listener);
5250 }
5251
5252 /** Iterate over available heads
5253 *
5254 * \param compositor The compositor.
5255 * \param iter The iterator, or NULL for start.
5256 * \return The next available head in the list.
5257 *
5258 * Returns all available heads, regardless of being connected or enabled.
5259 *
5260 * You can iterate over all heads as follows:
5261 * \code
5262 * struct weston_head *head = NULL;
5263 *
5264 * while ((head = weston_compositor_iterate_heads(compositor, head))) {
5265 * ...
5266 * }
5267 * \endcode
5268 *
5269 * If you cause \c iter to be removed from the list, you cannot use it to
5270 * continue iterating. Removing any other item is safe.
5271 *
5272 * \ingroup compositor
5273 */
5274 WL_EXPORT struct weston_head *
weston_compositor_iterate_heads(struct weston_compositor * compositor,struct weston_head * iter)5275 weston_compositor_iterate_heads(struct weston_compositor *compositor,
5276 struct weston_head *iter)
5277 {
5278 struct wl_list *list = &compositor->head_list;
5279 struct wl_list *node;
5280
5281 assert(compositor);
5282 assert(!iter || iter->compositor == compositor);
5283
5284 if (iter)
5285 node = iter->compositor_link.next;
5286 else
5287 node = list->next;
5288
5289 assert(node);
5290 assert(!iter || node != &iter->compositor_link);
5291
5292 if (node == list)
5293 return NULL;
5294
5295 return container_of(node, struct weston_head, compositor_link);
5296 }
5297
5298 /** Iterate over attached heads
5299 *
5300 * \param output The output whose heads to iterate.
5301 * \param iter The iterator, or NULL for start.
5302 * \return The next attached head in the list.
5303 *
5304 * Returns all heads currently attached to the output.
5305 *
5306 * You can iterate over all heads as follows:
5307 * \code
5308 * struct weston_head *head = NULL;
5309 *
5310 * while ((head = weston_output_iterate_heads(output, head))) {
5311 * ...
5312 * }
5313 * \endcode
5314 *
5315 * If you cause \c iter to be removed from the list, you cannot use it to
5316 * continue iterating. Removing any other item is safe.
5317 *
5318 * \ingroup ouput
5319 */
5320 WL_EXPORT struct weston_head *
weston_output_iterate_heads(struct weston_output * output,struct weston_head * iter)5321 weston_output_iterate_heads(struct weston_output *output,
5322 struct weston_head *iter)
5323 {
5324 struct wl_list *list = &output->head_list;
5325 struct wl_list *node;
5326
5327 assert(output);
5328 assert(!iter || iter->output == output);
5329
5330 if (iter)
5331 node = iter->output_link.next;
5332 else
5333 node = list->next;
5334
5335 assert(node);
5336 assert(!iter || node != &iter->output_link);
5337
5338 if (node == list)
5339 return NULL;
5340
5341 return container_of(node, struct weston_head, output_link);
5342 }
5343
5344 /** Attach a head to an output
5345 *
5346 * \param output The output to attach to.
5347 * \param head The head that is not yet attached.
5348 * \return 0 on success, -1 on failure.
5349 *
5350 * Attaches the given head to the output. All heads of an output are clones
5351 * and share the resolution and timings.
5352 *
5353 * Cloning heads this way uses less resources than creating an output for
5354 * each head, but is not always possible due to environment, driver and hardware
5355 * limitations.
5356 *
5357 * On failure, the head remains unattached. Success of this function does not
5358 * guarantee the output configuration is actually valid. The final checks are
5359 * made on weston_output_enable() unless the output was already enabled.
5360 *
5361 * \ingroup output
5362 */
5363 WL_EXPORT int
weston_output_attach_head(struct weston_output * output,struct weston_head * head)5364 weston_output_attach_head(struct weston_output *output,
5365 struct weston_head *head)
5366 {
5367 LOG_ENTER();
5368 char *head_names;
5369
5370 if (!wl_list_empty(&head->output_link)) {
5371 LOG_ERROR("head already have output");
5372 LOG_EXIT();
5373 return -1;
5374 }
5375
5376 if (output->attach_head) {
5377 if (output->attach_head(output, head) < 0) {
5378 LOG_ERROR("this->attach_head(head) failed");
5379 LOG_EXIT();
5380 return -1;
5381 }
5382 } else if (!wl_list_empty(&output->head_list)) {
5383 /* No support for clones in the legacy path. */
5384 LOG_ERROR("output already have head");
5385 LOG_EXIT();
5386 return -1;
5387 }
5388
5389 head->output = output;
5390 LOG_INFO("this->head_list.push_back(head)");
5391 wl_list_insert(output->head_list.prev, &head->output_link);
5392
5393 if (output->enabled) {
5394 weston_head_add_global(head);
5395
5396 head_names = weston_output_create_heads_string(output);
5397 weston_log("Output '%s' updated to have head(s) %s\n",
5398 output->name, head_names);
5399 free(head_names);
5400
5401 weston_output_emit_heads_changed(output);
5402 }
5403
5404 LOG_EXIT();
5405 return 0;
5406 }
5407
5408 /** Detach a head from its output
5409 *
5410 * \param head The head to detach.
5411 *
5412 * It is safe to detach a non-attached head.
5413 *
5414 * If the head is attached to an enabled output and the output will be left
5415 * with no heads, the output will be disabled.
5416 *
5417 * \ingroup head
5418 * \sa weston_output_disable
5419 */
5420 WL_EXPORT void
weston_head_detach(struct weston_head * head)5421 weston_head_detach(struct weston_head *head)
5422 {
5423 struct weston_output *output = head->output;
5424 char *head_names;
5425
5426 wl_list_remove(&head->output_link);
5427 wl_list_init(&head->output_link);
5428 head->output = NULL;
5429
5430 if (!output)
5431 return;
5432
5433 if (output->detach_head)
5434 output->detach_head(output, head);
5435
5436 if (output->enabled) {
5437 weston_head_remove_global(head);
5438
5439 if (wl_list_empty(&output->head_list)) {
5440 weston_log("Output '%s' no heads left, disabling.\n",
5441 output->name);
5442 weston_output_disable(output);
5443 } else {
5444 head_names = weston_output_create_heads_string(output);
5445 weston_log("Output '%s' updated to have head(s) %s\n",
5446 output->name, head_names);
5447 free(head_names);
5448
5449 weston_output_emit_heads_changed(output);
5450 }
5451 }
5452 }
5453
5454 /** Destroy a head
5455 *
5456 * \param head The head to be released.
5457 *
5458 * Destroys the head. The caller is responsible for freeing the memory pointed
5459 * to by \c head.
5460 *
5461 * \ingroup head
5462 * \internal
5463 */
5464 WL_EXPORT void
weston_head_release(struct weston_head * head)5465 weston_head_release(struct weston_head *head)
5466 {
5467 wl_signal_emit(&head->destroy_signal, head);
5468
5469 weston_head_detach(head);
5470
5471 free(head->make);
5472 free(head->model);
5473 free(head->serial_number);
5474 free(head->name);
5475
5476 wl_list_remove(&head->compositor_link);
5477 }
5478
5479 static void
weston_head_set_device_changed(struct weston_head * head)5480 weston_head_set_device_changed(struct weston_head *head)
5481 {
5482 head->device_changed = true;
5483
5484 if (head->compositor)
5485 weston_compositor_schedule_heads_changed(head->compositor);
5486 }
5487
5488 /** String equal comparison with NULLs being equal */
5489 static bool
str_null_eq(const char * a,const char * b)5490 str_null_eq(const char *a, const char *b)
5491 {
5492 if (!a && !b)
5493 return true;
5494
5495 if (!!a != !!b)
5496 return false;
5497
5498 return strcmp(a, b) == 0;
5499 }
5500
5501 /** Store monitor make, model and serial number
5502 *
5503 * \param head The head to modify.
5504 * \param make The monitor make. If EDID is available, the PNP ID. Otherwise
5505 * any string, or NULL for none.
5506 * \param model The monitor model or name, or a made-up string, or NULL for
5507 * none.
5508 * \param serialno The monitor serial number, a made-up string, or NULL for
5509 * none.
5510 *
5511 * This may set the device_changed flag.
5512 *
5513 * \ingroup head
5514 * \internal
5515 */
5516 WL_EXPORT void
weston_head_set_monitor_strings(struct weston_head * head,const char * make,const char * model,const char * serialno)5517 weston_head_set_monitor_strings(struct weston_head *head,
5518 const char *make,
5519 const char *model,
5520 const char *serialno)
5521 {
5522 if (str_null_eq(head->make, make) &&
5523 str_null_eq(head->model, model) &&
5524 str_null_eq(head->serial_number, serialno))
5525 return;
5526
5527 free(head->make);
5528 free(head->model);
5529 free(head->serial_number);
5530
5531 head->make = make ? strdup(make) : NULL;
5532 head->model = model ? strdup(model) : NULL;
5533 head->serial_number = serialno ? strdup(serialno) : NULL;
5534
5535 weston_head_set_device_changed(head);
5536 }
5537
5538 /** Store display non-desktop status
5539 *
5540 * \param head The head to modify.
5541 * \param non_desktop Whether the head connects to a non-desktop display.
5542 *
5543 * \ingroup head
5544 * \internal
5545 */
5546 WL_EXPORT void
weston_head_set_non_desktop(struct weston_head * head,bool non_desktop)5547 weston_head_set_non_desktop(struct weston_head *head, bool non_desktop)
5548 {
5549 if (head->non_desktop == non_desktop)
5550 return;
5551
5552 head->non_desktop = non_desktop;
5553
5554 weston_head_set_device_changed(head);
5555 }
5556
5557 /** Store display transformation
5558 *
5559 * \param head The head to modify.
5560 * \param transform The transformation to apply for this head
5561 *
5562 * This may set the device_changed flag.
5563 *
5564 * \ingroup head
5565 * \internal
5566 */
5567 WL_EXPORT void
weston_head_set_transform(struct weston_head * head,uint32_t transform)5568 weston_head_set_transform(struct weston_head *head, uint32_t transform)
5569 {
5570 if (head->transform == transform)
5571 return;
5572
5573 head->transform = transform;
5574
5575 weston_head_set_device_changed(head);
5576 }
5577
5578
5579 /** Store physical image size
5580 *
5581 * \param head The head to modify.
5582 * \param mm_width Image area width in millimeters.
5583 * \param mm_height Image area height in millimeters.
5584 *
5585 * This may set the device_changed flag.
5586 *
5587 * \ingroup head
5588 * \internal
5589 */
5590 WL_EXPORT void
weston_head_set_physical_size(struct weston_head * head,int32_t mm_width,int32_t mm_height)5591 weston_head_set_physical_size(struct weston_head *head,
5592 int32_t mm_width, int32_t mm_height)
5593 {
5594 if (head->mm_width == mm_width &&
5595 head->mm_height == mm_height)
5596 return;
5597
5598 head->mm_width = mm_width;
5599 head->mm_height = mm_height;
5600
5601 weston_head_set_device_changed(head);
5602 }
5603
5604 /** Store monitor sub-pixel layout
5605 *
5606 * \param head The head to modify.
5607 * \param sp Sub-pixel layout. The possible values are:
5608 * - WL_OUTPUT_SUBPIXEL_UNKNOWN,
5609 * - WL_OUTPUT_SUBPIXEL_NONE,
5610 * - WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB,
5611 * - WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR,
5612 * - WL_OUTPUT_SUBPIXEL_VERTICAL_RGB,
5613 * - WL_OUTPUT_SUBPIXEL_VERTICAL_BGR
5614 *
5615 * This may set the device_changed flag.
5616 *
5617 * \ingroup head
5618 * \internal
5619 */
5620 WL_EXPORT void
weston_head_set_subpixel(struct weston_head * head,enum wl_output_subpixel sp)5621 weston_head_set_subpixel(struct weston_head *head,
5622 enum wl_output_subpixel sp)
5623 {
5624 if (head->subpixel == sp)
5625 return;
5626
5627 head->subpixel = sp;
5628
5629 weston_head_set_device_changed(head);
5630 }
5631
5632 /** Mark the monitor as internal
5633 *
5634 * This is used for embedded screens, like laptop panels.
5635 *
5636 * \param head The head to mark as internal.
5637 *
5638 * By default a head is external. The type is often inferred from the physical
5639 * connector type.
5640 *
5641 * \ingroup head
5642 * \internal
5643 */
5644 WL_EXPORT void
weston_head_set_internal(struct weston_head * head)5645 weston_head_set_internal(struct weston_head *head)
5646 {
5647 head->connection_internal = true;
5648 }
5649
5650 /** Store connector status
5651 *
5652 * \param head The head to modify.
5653 * \param connected Whether the head is connected.
5654 *
5655 * Connectors are created as disconnected. This function can be used to
5656 * set the connector status.
5657 *
5658 * The status should be set to true when a physical connector is connected to
5659 * a video sink device like a monitor and to false when the connector is
5660 * disconnected. For nested backends, the connection status should reflect the
5661 * connection to the parent display server.
5662 *
5663 * When the connection status changes, it schedules a call to the heads_changed
5664 * hook and sets the device_changed flag.
5665 *
5666 * \sa weston_compositor_set_heads_changed_cb
5667 * \ingroup head
5668 * \internal
5669 */
5670 WL_EXPORT void
weston_head_set_connection_status(struct weston_head * head,bool connected)5671 weston_head_set_connection_status(struct weston_head *head, bool connected)
5672 {
5673 if (head->connected == connected)
5674 return;
5675
5676 head->connected = connected;
5677
5678 weston_head_set_device_changed(head);
5679 }
5680
5681 static void
weston_output_compute_protection(struct weston_output * output)5682 weston_output_compute_protection(struct weston_output *output)
5683 {
5684 struct weston_head *head;
5685 enum weston_hdcp_protection op_protection;
5686 bool op_protection_valid = false;
5687 struct weston_compositor *wc = output->compositor;
5688
5689 wl_list_for_each(head, &output->head_list, output_link) {
5690 if (!op_protection_valid) {
5691 op_protection = head->current_protection;
5692 op_protection_valid = true;
5693 }
5694 if (head->current_protection < op_protection)
5695 op_protection = head->current_protection;
5696 }
5697
5698 if (!op_protection_valid)
5699 op_protection = WESTON_HDCP_DISABLE;
5700
5701 if (output->current_protection != op_protection) {
5702 output->current_protection = op_protection;
5703 weston_output_damage(output);
5704 weston_schedule_surface_protection_update(wc);
5705 }
5706 }
5707
5708 WL_EXPORT void
weston_head_set_content_protection_status(struct weston_head * head,enum weston_hdcp_protection status)5709 weston_head_set_content_protection_status(struct weston_head *head,
5710 enum weston_hdcp_protection status)
5711 {
5712 head->current_protection = status;
5713 if (head->output)
5714 weston_output_compute_protection(head->output);
5715 }
5716
5717 /** Is the head currently connected?
5718 *
5719 * \param head The head to query.
5720 * \return Connection status.
5721 *
5722 * Returns true if the head is physically connected to a monitor, or in
5723 * case of a nested backend returns true when there is a connection to the
5724 * parent display server.
5725 *
5726 * This is independent from the head being enabled.
5727 *
5728 * \sa weston_head_is_enabled
5729 * \ingroup head
5730 */
5731 WL_EXPORT bool
weston_head_is_connected(struct weston_head * head)5732 weston_head_is_connected(struct weston_head *head)
5733 {
5734 return head->connected;
5735 }
5736
5737 /** Is the head currently enabled?
5738 *
5739 * \param head The head to query.
5740 * \return Video status.
5741 *
5742 * Returns true if the head is currently transmitting a video stream.
5743 *
5744 * This is independent of the head being connected.
5745 *
5746 * \sa weston_head_is_connected
5747 * \ingroup head
5748 */
5749 WL_EXPORT bool
weston_head_is_enabled(struct weston_head * head)5750 weston_head_is_enabled(struct weston_head *head)
5751 {
5752 if (!head->output)
5753 return false;
5754
5755 return head->output->enabled;
5756 }
5757
5758 /** Has the device information changed?
5759 *
5760 * \param head The head to query.
5761 * \return True if the device information has changed since last reset.
5762 *
5763 * The information about the connected display device, e.g. a monitor, may
5764 * change without being disconnected in between. Changing information
5765 * causes a call to the heads_changed hook.
5766 *
5767 * The information includes make, model, serial number, physical size,
5768 * and sub-pixel type. The connection status is also included.
5769 *
5770 * \sa weston_head_reset_device_changed, weston_compositor_set_heads_changed_cb
5771 * \ingroup head
5772 */
5773 WL_EXPORT bool
weston_head_is_device_changed(struct weston_head * head)5774 weston_head_is_device_changed(struct weston_head *head)
5775 {
5776 return head->device_changed;
5777 }
5778
5779 /** Does the head represent a non-desktop display?
5780 *
5781 * \param head The head to query.
5782 * \return True if the device is a non-desktop display.
5783 *
5784 * Non-desktop heads are not attached to outputs by default.
5785 * This stops weston from extending the desktop onto head mounted displays.
5786 *
5787 * \ingroup head
5788 */
5789 WL_EXPORT bool
weston_head_is_non_desktop(struct weston_head * head)5790 weston_head_is_non_desktop(struct weston_head *head)
5791 {
5792 return head->non_desktop;
5793 }
5794
5795 /** Acknowledge device information change
5796 *
5797 * \param head The head to acknowledge.
5798 *
5799 * Clears the device changed flag on this head. When a compositor has processed
5800 * device information, it should call this to be able to notice further
5801 * changes.
5802 *
5803 * \sa weston_head_is_device_changed
5804 * \ingroup head
5805 */
5806 WL_EXPORT void
weston_head_reset_device_changed(struct weston_head * head)5807 weston_head_reset_device_changed(struct weston_head *head)
5808 {
5809 head->device_changed = false;
5810 }
5811
5812 /** Get the name of a head
5813 *
5814 * \param head The head to query.
5815 * \return The head's name, not NULL.
5816 *
5817 * The name depends on the backend. The DRM backend uses connector names,
5818 * other backends may use hardcoded names or user-given names.
5819 *
5820 * \ingroup head
5821 */
5822 WL_EXPORT const char *
weston_head_get_name(struct weston_head * head)5823 weston_head_get_name(struct weston_head *head)
5824 {
5825 return head->name;
5826 }
5827
5828 /** Get the output the head is attached to
5829 *
5830 * \param head The head to query.
5831 * \return The output the head is attached to, or NULL if detached.
5832 * \ingroup head
5833 */
5834 WL_EXPORT struct weston_output *
weston_head_get_output(struct weston_head * head)5835 weston_head_get_output(struct weston_head *head)
5836 {
5837 return head->output;
5838 }
5839
5840 /** Get the head's native transformation
5841 *
5842 * \param head The head to query.
5843 * \return The head's native transform, as a WL_OUTPUT_TRANSFORM_* value
5844 *
5845 * A weston_head may have a 'native' transform provided by the backend.
5846 * Examples include panels which are physically rotated, where the rotation
5847 * is recorded and described as part of the system configuration. This call
5848 * will return any known native transform for the head.
5849 *
5850 * \ingroup head
5851 */
5852 WL_EXPORT uint32_t
weston_head_get_transform(struct weston_head * head)5853 weston_head_get_transform(struct weston_head *head)
5854 {
5855 return head->transform;
5856 }
5857
5858 /** Add destroy callback for a head
5859 *
5860 * \param head The head to watch for.
5861 * \param listener The listener to add. The \c notify member must be set.
5862 *
5863 * Heads may get destroyed for various reasons by the backends. If a head is
5864 * attached to an output, the compositor should listen for head destruction
5865 * and reconfigure or destroy the output if necessary.
5866 *
5867 * The destroy callbacks will be called on weston_head destruction before any
5868 * automatic detaching from an associated weston_output and before any
5869 * weston_head information is lost.
5870 *
5871 * The \c data argument to the notify callback is the weston_head being
5872 * destroyed.
5873 *
5874 * \ingroup head
5875 */
5876 WL_EXPORT void
weston_head_add_destroy_listener(struct weston_head * head,struct wl_listener * listener)5877 weston_head_add_destroy_listener(struct weston_head *head,
5878 struct wl_listener *listener)
5879 {
5880 wl_signal_add(&head->destroy_signal, listener);
5881 }
5882
5883 /** Look up destroy listener for a head
5884 *
5885 * \param head The head to query.
5886 * \param notify The notify function used used for the added destroy listener.
5887 * \return The listener, or NULL if not found.
5888 *
5889 * This looks up the previously added destroy listener struct based on the
5890 * notify function it has. The listener can be used to access user data
5891 * through \c container_of().
5892 *
5893 * \sa wl_signal_get()
5894 * \ingroup head
5895 */
5896 WL_EXPORT struct wl_listener *
weston_head_get_destroy_listener(struct weston_head * head,wl_notify_func_t notify)5897 weston_head_get_destroy_listener(struct weston_head *head,
5898 wl_notify_func_t notify)
5899 {
5900 return wl_signal_get(&head->destroy_signal, notify);
5901 }
5902
5903 /* Move other outputs when one is resized so the space remains contiguous. */
5904 static void
weston_compositor_reflow_outputs(struct weston_compositor * compositor,struct weston_output * resized_output,int delta_width)5905 weston_compositor_reflow_outputs(struct weston_compositor *compositor,
5906 struct weston_output *resized_output, int delta_width)
5907 {
5908 struct weston_output *output;
5909 bool start_resizing = false;
5910
5911 if (!delta_width)
5912 return;
5913
5914 wl_list_for_each(output, &compositor->output_list, link) {
5915 if (output == resized_output) {
5916 start_resizing = true;
5917 continue;
5918 }
5919
5920 if (start_resizing) {
5921 weston_output_move(output, output->x + delta_width, output->y);
5922 output->dirty = 1;
5923 }
5924 }
5925 }
5926
5927 static void
weston_output_update_matrix(struct weston_output * output)5928 weston_output_update_matrix(struct weston_output *output)
5929 {
5930 float magnification;
5931
5932 weston_matrix_init(&output->matrix);
5933 weston_matrix_translate(&output->matrix, -output->x, -output->y, 0);
5934
5935 if (output->zoom.active) {
5936 magnification = 1 / (1 - output->zoom.spring_z.current);
5937 weston_output_update_zoom(output);
5938 weston_matrix_translate(&output->matrix, -output->zoom.trans_x,
5939 -output->zoom.trans_y, 0);
5940 weston_matrix_scale(&output->matrix, magnification,
5941 magnification, 1.0);
5942 }
5943
5944 switch (output->transform) {
5945 case WL_OUTPUT_TRANSFORM_FLIPPED:
5946 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
5947 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
5948 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
5949 weston_matrix_translate(&output->matrix, -output->width, 0, 0);
5950 weston_matrix_scale(&output->matrix, -1, 1, 1);
5951 break;
5952 }
5953
5954 switch (output->transform) {
5955 default:
5956 case WL_OUTPUT_TRANSFORM_NORMAL:
5957 case WL_OUTPUT_TRANSFORM_FLIPPED:
5958 break;
5959 case WL_OUTPUT_TRANSFORM_90:
5960 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
5961 weston_matrix_translate(&output->matrix, -output->width, 0, 0);
5962 weston_matrix_rotate_xy(&output->matrix, 0, -1);
5963 break;
5964 case WL_OUTPUT_TRANSFORM_180:
5965 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
5966 weston_matrix_translate(&output->matrix,
5967 -output->width, -output->height, 0);
5968 weston_matrix_rotate_xy(&output->matrix, -1, 0);
5969 break;
5970 case WL_OUTPUT_TRANSFORM_270:
5971 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
5972 weston_matrix_translate(&output->matrix, 0, -output->height, 0);
5973 weston_matrix_rotate_xy(&output->matrix, 0, 1);
5974 break;
5975 }
5976
5977 if (output->current_scale != 1)
5978 weston_matrix_scale(&output->matrix,
5979 output->current_scale,
5980 output->current_scale, 1);
5981
5982 output->dirty = 0;
5983
5984 weston_matrix_invert(&output->inverse_matrix, &output->matrix);
5985 }
5986
5987 static void
weston_output_transform_scale_init(struct weston_output * output,uint32_t transform,uint32_t scale)5988 weston_output_transform_scale_init(struct weston_output *output, uint32_t transform, uint32_t scale)
5989 {
5990 output->transform = transform;
5991 output->native_scale = scale;
5992 output->current_scale = scale;
5993
5994 convert_size_by_transform_scale(&output->width, &output->height,
5995 output->current_mode->width,
5996 output->current_mode->height,
5997 transform, scale);
5998 }
5999
6000 static void
weston_output_init_geometry(struct weston_output * output,int x,int y)6001 weston_output_init_geometry(struct weston_output *output, int x, int y)
6002 {
6003 output->x = x;
6004 output->y = y;
6005
6006 pixman_region32_fini(&output->region);
6007 pixman_region32_init_rect(&output->region, x, y,
6008 output->width,
6009 output->height);
6010 }
6011
6012 /**
6013 * \ingroup output
6014 */
6015 WL_EXPORT void
weston_output_move(struct weston_output * output,int x,int y)6016 weston_output_move(struct weston_output *output, int x, int y)
6017 {
6018 struct weston_head *head;
6019 struct wl_resource *resource;
6020 int ver;
6021
6022 output->move_x = x - output->x;
6023 output->move_y = y - output->y;
6024
6025 if (output->move_x == 0 && output->move_y == 0)
6026 return;
6027
6028 weston_output_init_geometry(output, x, y);
6029
6030 output->dirty = 1;
6031
6032 /* Move views on this output. */
6033 wl_signal_emit(&output->compositor->output_moved_signal, output);
6034
6035 /* Notify clients of the change for output position. */
6036 wl_list_for_each(head, &output->head_list, output_link) {
6037 wl_resource_for_each(resource, &head->resource_list) {
6038 wl_output_send_geometry(resource,
6039 output->x,
6040 output->y,
6041 head->mm_width,
6042 head->mm_height,
6043 head->subpixel,
6044 head->make,
6045 head->model,
6046 output->transform);
6047
6048 ver = wl_resource_get_version(resource);
6049 if (ver >= WL_OUTPUT_DONE_SINCE_VERSION)
6050 wl_output_send_done(resource);
6051 }
6052
6053 wl_resource_for_each(resource, &head->xdg_output_resource_list) {
6054 zxdg_output_v1_send_logical_position(resource,
6055 output->x,
6056 output->y);
6057 zxdg_output_v1_send_done(resource);
6058 }
6059 }
6060 }
6061
6062 /** Signal that a pending output is taken into use.
6063 *
6064 * Removes the output from the pending list and adds it to the compositor's
6065 * list of enabled outputs. The output created signal is emitted.
6066 *
6067 * The output gets an internal ID assigned, and the wl_output global is
6068 * created.
6069 *
6070 * \param compositor The compositor instance.
6071 * \param output The output to be added.
6072 *
6073 * \internal
6074 * \ingroup compositor
6075 */
6076 static void
weston_compositor_add_output(struct weston_compositor * compositor,struct weston_output * output)6077 weston_compositor_add_output(struct weston_compositor *compositor,
6078 struct weston_output *output)
6079 {
6080 struct weston_view *view, *next;
6081 struct weston_head *head;
6082
6083 assert(!output->enabled);
6084
6085 /* Verify we haven't reached the limit of 32 available output IDs */
6086 assert(ffs(~compositor->output_id_pool) > 0);
6087
6088 /* Invert the output id pool and look for the lowest numbered
6089 * switch (the least significant bit). Take that bit's position
6090 * as our ID, and mark it used in the compositor's output_id_pool.
6091 */
6092 output->id = ffs(~compositor->output_id_pool) - 1;
6093 compositor->output_id_pool |= 1u << output->id;
6094
6095 wl_list_remove(&output->link);
6096 wl_list_insert(compositor->output_list.prev, &output->link);
6097 output->enabled = true;
6098
6099 wl_list_for_each(head, &output->head_list, output_link)
6100 weston_head_add_global(head);
6101
6102 wl_signal_emit(&compositor->output_created_signal, output);
6103
6104 wl_list_for_each_safe(view, next, &compositor->view_list, link)
6105 weston_view_geometry_dirty(view);
6106 }
6107
6108 /** Transform device coordinates into global coordinates
6109 *
6110 * \param output the weston_output object
6111 * \param[in] device_x X coordinate in device units.
6112 * \param[in] device_y Y coordinate in device units.
6113 * \param[out] x X coordinate in the global space.
6114 * \param[out] y Y coordinate in the global space.
6115 *
6116 * Transforms coordinates from the device coordinate space (physical pixel
6117 * units) to the global coordinate space (logical pixel units). This takes
6118 * into account output transform and scale.
6119 *
6120 * \ingroup output
6121 * \internal
6122 */
6123 WL_EXPORT void
weston_output_transform_coordinate(struct weston_output * output,double device_x,double device_y,double * x,double * y)6124 weston_output_transform_coordinate(struct weston_output *output,
6125 double device_x, double device_y,
6126 double *x, double *y)
6127 {
6128 struct weston_vector p = { {
6129 device_x,
6130 device_y,
6131 0.0,
6132 1.0 } };
6133
6134 weston_matrix_transform(&output->inverse_matrix, &p);
6135
6136 *x = p.f[0] / p.f[3];
6137 *y = p.f[1] / p.f[3];
6138 }
6139
6140 /** Removes output from compositor's list of enabled outputs
6141 *
6142 * \param output The weston_output object that is being removed.
6143 *
6144 * The following happens:
6145 *
6146 * - The output assignments of all views in the current scenegraph are
6147 * recomputed.
6148 *
6149 * - Presentation feedback is discarded.
6150 *
6151 * - Compositor is notified that outputs were changed and
6152 * applies the necessary changes to re-layout outputs.
6153 *
6154 * - The output is put back in the pending outputs list.
6155 *
6156 * - Signal is emitted to notify all users of the weston_output
6157 * object that the output is being destroyed.
6158 *
6159 * - wl_output protocol objects referencing this weston_output
6160 * are made inert, and the wl_output global is removed.
6161 *
6162 * - The output's internal ID is released.
6163 *
6164 * \ingroup compositor
6165 * \internal
6166 */
6167 static void
weston_compositor_remove_output(struct weston_output * output)6168 weston_compositor_remove_output(struct weston_output *output)
6169 {
6170 struct weston_compositor *compositor = output->compositor;
6171 struct weston_view *view;
6172 struct weston_head *head;
6173
6174 assert(output->destroying);
6175 assert(output->enabled);
6176
6177 wl_list_for_each(view, &compositor->view_list, link) {
6178 if (view->output_mask & (1u << output->id))
6179 weston_view_assign_output(view);
6180 }
6181
6182 weston_presentation_feedback_discard_list(&output->feedback_list);
6183
6184 weston_compositor_reflow_outputs(compositor, output, -output->width);
6185
6186 wl_list_remove(&output->link);
6187 wl_list_insert(compositor->pending_output_list.prev, &output->link);
6188 output->enabled = false;
6189
6190 wl_signal_emit(&compositor->output_destroyed_signal, output);
6191 wl_signal_emit(&output->destroy_signal, output);
6192
6193 wl_list_for_each(head, &output->head_list, output_link)
6194 weston_head_remove_global(head);
6195
6196 compositor->output_id_pool &= ~(1u << output->id);
6197 output->id = 0xffffffff; /* invalid */
6198 }
6199
6200 /** Sets the output scale for a given output.
6201 *
6202 * \param output The weston_output object that the scale is set for.
6203 * \param scale Scale factor for the given output.
6204 *
6205 * It only supports setting scale for an output that
6206 * is not enabled and it can only be ran once.
6207 *
6208 * \ingroup ouput
6209 */
6210 WL_EXPORT void
weston_output_set_scale(struct weston_output * output,int32_t scale)6211 weston_output_set_scale(struct weston_output *output,
6212 int32_t scale)
6213 {
6214 /* We can only set scale on a disabled output */
6215 assert(!output->enabled);
6216
6217 /* We only want to set scale once */
6218 assert(!output->scale);
6219
6220 output->scale = scale;
6221 }
6222
6223 /** Sets the output transform for a given output.
6224 *
6225 * \param output The weston_output object that the transform is set for.
6226 * \param transform Transform value for the given output.
6227 *
6228 * Refer to wl_output::transform section located at
6229 * https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_output
6230 * for list of values that can be passed to this function.
6231 *
6232 * \ingroup output
6233 */
6234 WL_EXPORT void
weston_output_set_transform(struct weston_output * output,uint32_t transform)6235 weston_output_set_transform(struct weston_output *output,
6236 uint32_t transform)
6237 {
6238 struct weston_pointer_motion_event ev;
6239 struct wl_resource *resource;
6240 struct weston_seat *seat;
6241 pixman_region32_t old_region;
6242 int mid_x, mid_y;
6243 struct weston_head *head;
6244 int ver;
6245
6246 if (!output->enabled && output->transform == UINT32_MAX) {
6247 output->transform = transform;
6248 return;
6249 }
6250
6251 weston_output_transform_scale_init(output, transform, output->scale);
6252
6253 pixman_region32_init(&old_region);
6254 pixman_region32_copy(&old_region, &output->region);
6255
6256 weston_output_init_geometry(output, output->x, output->y);
6257
6258 output->dirty = 1;
6259
6260 /* Notify clients of the change for output transform. */
6261 wl_list_for_each(head, &output->head_list, output_link) {
6262 wl_resource_for_each(resource, &head->resource_list) {
6263 wl_output_send_geometry(resource,
6264 output->x,
6265 output->y,
6266 head->mm_width,
6267 head->mm_height,
6268 head->subpixel,
6269 head->make,
6270 head->model,
6271 output->transform);
6272
6273 ver = wl_resource_get_version(resource);
6274 if (ver >= WL_OUTPUT_DONE_SINCE_VERSION)
6275 wl_output_send_done(resource);
6276 }
6277 wl_resource_for_each(resource, &head->xdg_output_resource_list) {
6278 zxdg_output_v1_send_logical_position(resource,
6279 output->x,
6280 output->y);
6281 zxdg_output_v1_send_logical_size(resource,
6282 output->width,
6283 output->height);
6284 zxdg_output_v1_send_done(resource);
6285 }
6286 }
6287
6288 /* we must ensure that pointers are inside output, otherwise they disappear */
6289 mid_x = output->x + output->width / 2;
6290 mid_y = output->y + output->height / 2;
6291
6292 ev.mask = WESTON_POINTER_MOTION_ABS;
6293 ev.x = wl_fixed_to_double(wl_fixed_from_int(mid_x));
6294 ev.y = wl_fixed_to_double(wl_fixed_from_int(mid_y));
6295
6296 wl_list_for_each(seat, &output->compositor->seat_list, link) {
6297 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
6298
6299 if (pointer && pixman_region32_contains_point(&old_region,
6300 wl_fixed_to_int(pointer->x),
6301 wl_fixed_to_int(pointer->y),
6302 NULL))
6303 weston_pointer_move(pointer, &ev);
6304 }
6305 }
6306
6307 /** Initializes a weston_output object with enough data so
6308 ** an output can be configured.
6309 *
6310 * \param output The weston_output object to initialize
6311 * \param compositor The compositor instance.
6312 * \param name Name for the output (the string is copied).
6313 *
6314 * Sets initial values for fields that are expected to be
6315 * configured either by compositors or backends.
6316 *
6317 * The name is used in logs, and can be used by compositors as a configuration
6318 * identifier.
6319 *
6320 * \ingroup output
6321 * \internal
6322 */
6323 WL_EXPORT void
weston_output_init(struct weston_output * output,struct weston_compositor * compositor,const char * name)6324 weston_output_init(struct weston_output *output,
6325 struct weston_compositor *compositor,
6326 const char *name)
6327 {
6328 output->compositor = compositor;
6329 output->destroying = 0;
6330 output->name = strdup(name);
6331 wl_list_init(&output->link);
6332 wl_signal_init(&output->user_destroy_signal);
6333 output->enabled = false;
6334 output->desired_protection = WESTON_HDCP_DISABLE;
6335 output->allow_protection = true;
6336
6337 LOG_INFO("this->head_list.clear()");
6338 wl_list_init(&output->head_list);
6339
6340 /* Add some (in)sane defaults which can be used
6341 * for checking if an output was properly configured
6342 */
6343 output->scale = 0;
6344 /* Can't use -1 on uint32_t and 0 is valid enum value */
6345 output->transform = UINT32_MAX;
6346
6347 pixman_region32_init(&output->region);
6348 wl_list_init(&output->mode_list);
6349 }
6350
6351 /** Adds weston_output object to pending output list.
6352 *
6353 * \param output The weston_output object to add
6354 * \param compositor The compositor instance.
6355 *
6356 * The opposite of this operation is built into weston_output_release().
6357 *
6358 * \ingroup compositor
6359 * \internal
6360 */
6361 WL_EXPORT void
weston_compositor_add_pending_output(struct weston_output * output,struct weston_compositor * compositor)6362 weston_compositor_add_pending_output(struct weston_output *output,
6363 struct weston_compositor *compositor)
6364 {
6365 assert(output->disable);
6366 assert(output->enable);
6367
6368 wl_list_remove(&output->link);
6369 wl_list_insert(compositor->pending_output_list.prev, &output->link);
6370 }
6371
6372 /** Create a string with the attached heads' names.
6373 *
6374 * The string must be free()'d.
6375 *
6376 * \ingroup output
6377 */
6378 static char *
weston_output_create_heads_string(struct weston_output * output)6379 weston_output_create_heads_string(struct weston_output *output)
6380 {
6381 FILE *fp;
6382 char *str = NULL;
6383 size_t size = 0;
6384 struct weston_head *head;
6385 const char *sep = "";
6386
6387 fp = open_memstream(&str, &size);
6388 if (!fp)
6389 return NULL;
6390
6391 wl_list_for_each(head, &output->head_list, output_link) {
6392 fprintf(fp, "%s%s", sep, head->name);
6393 sep = ", ";
6394 }
6395 fclose(fp);
6396
6397 return str;
6398 }
6399
6400 /** Constructs a weston_output object that can be used by the compositor.
6401 *
6402 * \param output The weston_output object that needs to be enabled. Must not
6403 * be enabled already. Must have at least one head attached.
6404 *
6405 * Output coordinates are calculated and each new output is by default
6406 * assigned to the right of previous one.
6407 *
6408 * Sets up the transformation, zoom, and geometry of the output using
6409 * the properties that need to be configured by the compositor.
6410 *
6411 * Establishes a repaint timer for the output with the relevant display
6412 * object's event loop. See output_repaint_timer_handler().
6413 *
6414 * The output is assigned an ID. Weston can support up to 32 distinct
6415 * outputs, with IDs numbered from 0-31; the compositor's output_id_pool
6416 * is referred to and used to find the first available ID number, and
6417 * then this ID is marked as used in output_id_pool.
6418 *
6419 * The output is also assigned a Wayland global with the wl_output
6420 * external interface.
6421 *
6422 * Backend specific function is called to set up the output output.
6423 *
6424 * Output is added to the compositor's output list
6425 *
6426 * If the backend specific function fails, the weston_output object
6427 * is returned to a state it was before calling this function and
6428 * is added to the compositor's pending_output_list in case it needs
6429 * to be reconfigured or just so it can be destroyed at shutdown.
6430 *
6431 * 0 is returned on success, -1 on failure.
6432 *
6433 * \ingroup output
6434 */
6435 WL_EXPORT int
weston_output_enable(struct weston_output * output)6436 weston_output_enable(struct weston_output *output)
6437 {
6438 struct weston_compositor *c = output->compositor;
6439 struct weston_output *iterator;
6440 struct weston_head *head;
6441 char *head_names;
6442 int x = 0, y = 0;
6443
6444 if (output->enabled) {
6445 weston_log("Error: attempt to enable an enabled output '%s'\n",
6446 output->name);
6447 return -1;
6448 }
6449
6450 if (wl_list_empty(&output->head_list)) {
6451 weston_log("Error: cannot enable output '%s' without heads.\n",
6452 output->name);
6453 return -1;
6454 }
6455
6456 if (wl_list_empty(&output->mode_list) || !output->current_mode) {
6457 weston_log("Error: no video mode for output '%s'.\n",
6458 output->name);
6459 return -1;
6460 }
6461
6462 wl_list_for_each(head, &output->head_list, output_link) {
6463 assert(head->make);
6464 assert(head->model);
6465 }
6466
6467 iterator = container_of(c->output_list.prev,
6468 struct weston_output, link);
6469
6470 if (!wl_list_empty(&c->output_list))
6471 x = iterator->x + iterator->width;
6472
6473 /* Make sure the scale is set up */
6474 assert(output->scale);
6475
6476 /* Make sure we have a transform set */
6477 assert(output->transform != UINT32_MAX);
6478
6479 output->x = x;
6480 output->y = y;
6481 output->dirty = 1;
6482 output->original_scale = output->scale;
6483
6484 wl_signal_init(&output->frame_signal);
6485 wl_signal_init(&output->destroy_signal);
6486
6487 weston_output_transform_scale_init(output, output->transform, output->scale);
6488 weston_output_init_zoom(output);
6489
6490 weston_output_init_geometry(output, x, y);
6491 weston_output_damage(output);
6492
6493 wl_list_init(&output->animation_list);
6494 wl_list_init(&output->feedback_list);
6495
6496 /* Enable the output (set up the crtc or create a
6497 * window representing the output, set up the
6498 * renderer, etc)
6499 */
6500 if (output->enable(output) < 0) {
6501 weston_log("Enabling output \"%{public}s\" failed.\n", output->name);
6502 return -1;
6503 }
6504
6505 weston_compositor_add_output(output->compositor, output);
6506
6507 head_names = weston_output_create_heads_string(output);
6508 weston_log("Output '%s' enabled with head(s) %s\n",
6509 output->name, head_names);
6510 free(head_names);
6511
6512 return 0;
6513 }
6514
6515 /** Converts a weston_output object to a pending output state, so it
6516 ** can be configured again or destroyed.
6517 *
6518 * \param output The weston_output object that needs to be disabled.
6519 *
6520 * Calls a backend specific function to disable an output, in case
6521 * such function exists.
6522 *
6523 * The backend specific disable function may choose to postpone the disabling
6524 * by returning a negative value, in which case this function returns early.
6525 * In that case the backend will guarantee the output will be disabled soon
6526 * by the backend calling this function again. One must not attempt to re-enable
6527 * the output until that happens.
6528 *
6529 * Otherwise, if the output is being used by the compositor, it is removed
6530 * from weston's output_list (see weston_compositor_remove_output())
6531 * and is returned to a state it was before weston_output_enable()
6532 * was ran (see weston_output_enable_undo()).
6533 *
6534 * See weston_output_init() for more information on the
6535 * state output is returned to.
6536 *
6537 * If the output has never been enabled yet, this function can still be
6538 * called to ensure that the output is actually turned off rather than left
6539 * in the state it was discovered in.
6540 *
6541 * \ingroup output
6542 */
6543 WL_EXPORT void
weston_output_disable(struct weston_output * output)6544 weston_output_disable(struct weston_output *output)
6545 {
6546 /* Should we rename this? */
6547 output->destroying = 1;
6548
6549 /* Disable is called unconditionally also for not-enabled outputs,
6550 * because at compositor start-up, if there is an output that is
6551 * already on but the compositor wants to turn it off, we have to
6552 * forward the turn-off to the backend so it knows to do it.
6553 * The backend cannot initially turn off everything, because it
6554 * would cause unnecessary mode-sets for all outputs the compositor
6555 * wants to be on.
6556 */
6557 if (output->disable(output) < 0)
6558 return;
6559
6560 if (output->enabled)
6561 weston_compositor_remove_output(output);
6562
6563 output->destroying = 0;
6564 }
6565
6566 /** Forces a synchronous call to heads_changed hook
6567 *
6568 * \param compositor The compositor instance
6569 *
6570 * If there are new or changed heads, calls the heads_changed hook and
6571 * returns after the hook returns.
6572 *
6573 * \ingroup compositor
6574 */
6575 WL_EXPORT void
weston_compositor_flush_heads_changed(struct weston_compositor * compositor)6576 weston_compositor_flush_heads_changed(struct weston_compositor *compositor)
6577 {
6578 if (compositor->heads_changed_source) {
6579 wl_event_source_remove(compositor->heads_changed_source);
6580 weston_compositor_call_heads_changed(compositor);
6581 }
6582 }
6583
6584 /** Add destroy callback for an output
6585 *
6586 * \param output The output to watch.
6587 * \param listener The listener to add. The \c notify member must be set.
6588 *
6589 * The listener callback will be called when user destroys an output. This
6590 * may be delayed by a backend in some cases. The main purpose of the
6591 * listener is to allow hooking up custom data to the output. The custom data
6592 * can be fetched via weston_output_get_destroy_listener() followed by
6593 * container_of().
6594 *
6595 * The \c data argument to the notify callback is the weston_output being
6596 * destroyed.
6597 *
6598 * @note This is for the final destruction of an output, not when it gets
6599 * disabled. If you want to keep track of enabled outputs, this is not it.
6600 *
6601 * \ingroup ouput
6602 */
6603 WL_EXPORT void
weston_output_add_destroy_listener(struct weston_output * output,struct wl_listener * listener)6604 weston_output_add_destroy_listener(struct weston_output *output,
6605 struct wl_listener *listener)
6606 {
6607 wl_signal_add(&output->user_destroy_signal, listener);
6608 }
6609
6610 /** Look up destroy listener for an output
6611 *
6612 * \param output The output to query.
6613 * \param notify The notify function used used for the added destroy listener.
6614 * \return The listener, or NULL if not found.
6615 *
6616 * This looks up the previously added destroy listener struct based on the
6617 * notify function it has. The listener can be used to access user data
6618 * through \c container_of().
6619 *
6620 * \sa wl_signal_get() weston_output_add_destroy_listener()
6621 * \ingroup output
6622 */
6623 WL_EXPORT struct wl_listener *
weston_output_get_destroy_listener(struct weston_output * output,wl_notify_func_t notify)6624 weston_output_get_destroy_listener(struct weston_output *output,
6625 wl_notify_func_t notify)
6626 {
6627 return wl_signal_get(&output->user_destroy_signal, notify);
6628 }
6629
6630 /** Uninitialize an output
6631 *
6632 * Removes the output from the list of enabled outputs if necessary, but
6633 * does not call the backend's output disable function. The output will no
6634 * longer be in the list of pending outputs either.
6635 *
6636 * All fields of weston_output become uninitialized, i.e. should not be used
6637 * anymore. The caller can free the memory after this.
6638 *
6639 * \ingroup ouput
6640 * \internal
6641 */
6642 WL_EXPORT void
weston_output_release(struct weston_output * output)6643 weston_output_release(struct weston_output *output)
6644 {
6645 struct weston_head *head, *tmp;
6646
6647 output->destroying = 1;
6648
6649 wl_signal_emit(&output->user_destroy_signal, output);
6650
6651 if (output->idle_repaint_source)
6652 wl_event_source_remove(output->idle_repaint_source);
6653
6654 if (output->enabled)
6655 weston_compositor_remove_output(output);
6656
6657 pixman_region32_fini(&output->region);
6658 wl_list_remove(&output->link);
6659
6660 wl_list_for_each_safe(head, tmp, &output->head_list, output_link)
6661 weston_head_detach(head);
6662
6663 free(output->name);
6664 }
6665
6666 /** Find an output by its given name
6667 *
6668 * \param compositor The compositor to search in.
6669 * \param name The output name to search for.
6670 * \return An existing output with the given name, or NULL if not found.
6671 *
6672 * \ingroup compositor
6673 */
6674 WL_EXPORT struct weston_output *
weston_compositor_find_output_by_name(struct weston_compositor * compositor,const char * name)6675 weston_compositor_find_output_by_name(struct weston_compositor *compositor,
6676 const char *name)
6677 {
6678 struct weston_output *output;
6679
6680 wl_list_for_each(output, &compositor->output_list, link)
6681 if (strcmp(output->name, name) == 0)
6682 return output;
6683
6684 wl_list_for_each(output, &compositor->pending_output_list, link)
6685 if (strcmp(output->name, name) == 0)
6686 return output;
6687
6688 return NULL;
6689 }
6690
6691 /** Create a named output
6692 *
6693 * \param compositor The compositor.
6694 * \param name The name for the output.
6695 * \return A new \c weston_output, or NULL on failure.
6696 *
6697 * This creates a new weston_output that starts with no heads attached.
6698 *
6699 * An output must be configured and it must have at least one head before
6700 * it can be enabled.
6701 *
6702 * \ingroup compositor
6703 */
6704 WL_EXPORT struct weston_output *
weston_compositor_create_output(struct weston_compositor * compositor,const char * name)6705 weston_compositor_create_output(struct weston_compositor *compositor,
6706 const char *name)
6707 {
6708 assert(compositor->backend->create_output);
6709
6710 if (weston_compositor_find_output_by_name(compositor, name)) {
6711 weston_log("Warning: attempted to create an output with a "
6712 "duplicate name '%s'.\n", name);
6713 return NULL;
6714 }
6715
6716 return compositor->backend->create_output(compositor, name);
6717 }
6718
6719 /** Create an output for an unused head
6720 *
6721 * \param compositor The compositor.
6722 * \param head The head to attach to the output.
6723 * \return A new \c weston_output, or NULL on failure.
6724 *
6725 * This creates a new weston_output that starts with the given head attached.
6726 * The output inherits the name of the head. The head must not be already
6727 * attached to another output.
6728 *
6729 * An output must be configured before it can be enabled.
6730 *
6731 * \ingroup compositor
6732 */
6733 WL_EXPORT struct weston_output *
weston_compositor_create_output_with_head(struct weston_compositor * compositor,struct weston_head * head)6734 weston_compositor_create_output_with_head(struct weston_compositor *compositor,
6735 struct weston_head *head)
6736 {
6737 struct weston_output *output;
6738
6739 output = weston_compositor_create_output(compositor, head->name);
6740 if (!output)
6741 return NULL;
6742
6743 if (weston_output_attach_head(output, head) < 0) {
6744 weston_output_destroy(output);
6745 return NULL;
6746 }
6747
6748 return output;
6749 }
6750
6751 /** Destroy an output
6752 *
6753 * \param output The output to destroy.
6754 *
6755 * The heads attached to the given output are detached and become unused again.
6756 *
6757 * It is not necessary to explicitly destroy all outputs at compositor exit.
6758 * weston_compositor_destroy() will automatically destroy any remaining
6759 * outputs.
6760 *
6761 * \ingroup ouput
6762 */
6763 WL_EXPORT void
weston_output_destroy(struct weston_output * output)6764 weston_output_destroy(struct weston_output *output)
6765 {
6766 output->destroy(output);
6767 }
6768
6769 /** When you need a head...
6770 *
6771 * This function is a hack, used until all code has been converted to become
6772 * multi-head aware.
6773 *
6774 * \param output The weston_output whose head to get.
6775 * \return The first head in the output's list.
6776 *
6777 * \ingroup ouput
6778 */
6779 WL_EXPORT struct weston_head *
weston_output_get_first_head(struct weston_output * output)6780 weston_output_get_first_head(struct weston_output *output)
6781 {
6782 if (wl_list_empty(&output->head_list))
6783 return NULL;
6784
6785 return container_of(output->head_list.next,
6786 struct weston_head, output_link);
6787 }
6788
6789 /** Allow/Disallow content-protection support for an output
6790 *
6791 * This function sets the allow_protection member for an output. Setting of
6792 * this field will allow the compositor to attempt content-protection for this
6793 * output, for a backend that supports the content-protection protocol.
6794 *
6795 * \param output The weston_output for whom the content-protection is to be
6796 * allowed.
6797 * \param allow_protection The bool value which is to be set.
6798 */
6799 WL_EXPORT void
weston_output_allow_protection(struct weston_output * output,bool allow_protection)6800 weston_output_allow_protection(struct weston_output *output,
6801 bool allow_protection)
6802 {
6803 output->allow_protection = allow_protection;
6804 }
6805
6806 static void
xdg_output_unlist(struct wl_resource * resource)6807 xdg_output_unlist(struct wl_resource *resource)
6808 {
6809 wl_list_remove(wl_resource_get_link(resource));
6810 }
6811
6812 static void
xdg_output_destroy(struct wl_client * client,struct wl_resource * resource)6813 xdg_output_destroy(struct wl_client *client, struct wl_resource *resource)
6814 {
6815 wl_resource_destroy(resource);
6816 }
6817
6818 static const struct zxdg_output_v1_interface xdg_output_interface = {
6819 xdg_output_destroy
6820 };
6821
6822 static void
xdg_output_manager_destroy(struct wl_client * client,struct wl_resource * resource)6823 xdg_output_manager_destroy(struct wl_client *client,
6824 struct wl_resource *resource)
6825 {
6826 wl_resource_destroy(resource);
6827 }
6828
6829 static void
xdg_output_manager_get_xdg_output(struct wl_client * client,struct wl_resource * manager,uint32_t id,struct wl_resource * output_resource)6830 xdg_output_manager_get_xdg_output(struct wl_client *client,
6831 struct wl_resource *manager,
6832 uint32_t id,
6833 struct wl_resource *output_resource)
6834 {
6835 int version = wl_resource_get_version(manager);
6836 struct weston_head *head = wl_resource_get_user_data(output_resource);
6837 struct weston_output *output = head->output;
6838 struct wl_resource *resource;
6839
6840 resource = wl_resource_create(client, &zxdg_output_v1_interface,
6841 version, id);
6842 if (resource == NULL) {
6843 wl_client_post_no_memory(client);
6844 return;
6845 }
6846
6847 wl_list_insert(&head->xdg_output_resource_list,
6848 wl_resource_get_link(resource));
6849
6850 wl_resource_set_implementation(resource, &xdg_output_interface,
6851 NULL, xdg_output_unlist);
6852
6853 zxdg_output_v1_send_logical_position(resource, output->x, output->y);
6854 zxdg_output_v1_send_logical_size(resource,
6855 output->width,
6856 output->height);
6857 if (version >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION)
6858 zxdg_output_v1_send_name(resource, head->name);
6859
6860 zxdg_output_v1_send_done(resource);
6861 }
6862
6863 static const struct zxdg_output_manager_v1_interface xdg_output_manager_interface = {
6864 xdg_output_manager_destroy,
6865 xdg_output_manager_get_xdg_output
6866 };
6867
6868 static void
bind_xdg_output_manager(struct wl_client * client,void * data,uint32_t version,uint32_t id)6869 bind_xdg_output_manager(struct wl_client *client,
6870 void *data, uint32_t version, uint32_t id)
6871 {
6872 struct wl_resource *resource;
6873
6874 resource = wl_resource_create(client, &zxdg_output_manager_v1_interface,
6875 version, id);
6876 if (resource == NULL) {
6877 wl_client_post_no_memory(client);
6878 return;
6879 }
6880
6881 wl_resource_set_implementation(resource, &xdg_output_manager_interface,
6882 NULL, NULL);
6883 }
6884
6885 static void
destroy_viewport(struct wl_resource * resource)6886 destroy_viewport(struct wl_resource *resource)
6887 {
6888 struct weston_surface *surface =
6889 wl_resource_get_user_data(resource);
6890
6891 if (!surface)
6892 return;
6893
6894 surface->viewport_resource = NULL;
6895 surface->pending.buffer_viewport.buffer.src_width =
6896 wl_fixed_from_int(-1);
6897 surface->pending.buffer_viewport.surface.width = -1;
6898 surface->pending.buffer_viewport.changed = 1;
6899 }
6900
6901 static void
viewport_destroy(struct wl_client * client,struct wl_resource * resource)6902 viewport_destroy(struct wl_client *client,
6903 struct wl_resource *resource)
6904 {
6905 wl_resource_destroy(resource);
6906 }
6907
6908 static void
viewport_set_source(struct wl_client * client,struct wl_resource * resource,wl_fixed_t src_x,wl_fixed_t src_y,wl_fixed_t src_width,wl_fixed_t src_height)6909 viewport_set_source(struct wl_client *client,
6910 struct wl_resource *resource,
6911 wl_fixed_t src_x,
6912 wl_fixed_t src_y,
6913 wl_fixed_t src_width,
6914 wl_fixed_t src_height)
6915 {
6916 struct weston_surface *surface =
6917 wl_resource_get_user_data(resource);
6918
6919 if (!surface) {
6920 wl_resource_post_error(resource,
6921 WP_VIEWPORT_ERROR_NO_SURFACE,
6922 "wl_surface for this viewport is no longer exists");
6923 return;
6924 }
6925
6926 assert(surface->viewport_resource == resource);
6927 assert(surface->resource);
6928
6929 if (src_width == wl_fixed_from_int(-1) &&
6930 src_height == wl_fixed_from_int(-1) &&
6931 src_x == wl_fixed_from_int(-1) &&
6932 src_y == wl_fixed_from_int(-1)) {
6933 /* unset source rect */
6934 surface->pending.buffer_viewport.buffer.src_width =
6935 wl_fixed_from_int(-1);
6936 surface->pending.buffer_viewport.changed = 1;
6937 return;
6938 }
6939
6940 if (src_width <= 0 || src_height <= 0 || src_x < 0 || src_y < 0) {
6941 wl_resource_post_error(resource,
6942 WP_VIEWPORT_ERROR_BAD_VALUE,
6943 "wl_surface@%d viewport source "
6944 "w=%f <= 0, h=%f <= 0, x=%f < 0, or y=%f < 0",
6945 wl_resource_get_id(surface->resource),
6946 wl_fixed_to_double(src_width),
6947 wl_fixed_to_double(src_height),
6948 wl_fixed_to_double(src_x),
6949 wl_fixed_to_double(src_y));
6950 return;
6951 }
6952
6953 surface->pending.buffer_viewport.buffer.src_x = src_x;
6954 surface->pending.buffer_viewport.buffer.src_y = src_y;
6955 surface->pending.buffer_viewport.buffer.src_width = src_width;
6956 surface->pending.buffer_viewport.buffer.src_height = src_height;
6957 surface->pending.buffer_viewport.changed = 1;
6958 }
6959
6960 static void
viewport_set_destination(struct wl_client * client,struct wl_resource * resource,int32_t dst_width,int32_t dst_height)6961 viewport_set_destination(struct wl_client *client,
6962 struct wl_resource *resource,
6963 int32_t dst_width,
6964 int32_t dst_height)
6965 {
6966 struct weston_surface *surface =
6967 wl_resource_get_user_data(resource);
6968
6969 if (!surface) {
6970 wl_resource_post_error(resource,
6971 WP_VIEWPORT_ERROR_NO_SURFACE,
6972 "wl_surface for this viewport no longer exists");
6973 return;
6974 }
6975
6976 assert(surface->viewport_resource == resource);
6977
6978 if (dst_width == -1 && dst_height == -1) {
6979 /* unset destination size */
6980 surface->pending.buffer_viewport.surface.width = -1;
6981 surface->pending.buffer_viewport.changed = 1;
6982 return;
6983 }
6984
6985 if (dst_width <= 0 || dst_height <= 0) {
6986 wl_resource_post_error(resource,
6987 WP_VIEWPORT_ERROR_BAD_VALUE,
6988 "destination size must be positive (%dx%d)",
6989 dst_width, dst_height);
6990 return;
6991 }
6992
6993 surface->pending.buffer_viewport.surface.width = dst_width;
6994 surface->pending.buffer_viewport.surface.height = dst_height;
6995 surface->pending.buffer_viewport.changed = 1;
6996 }
6997
6998 static const struct wp_viewport_interface viewport_interface = {
6999 viewport_destroy,
7000 viewport_set_source,
7001 viewport_set_destination
7002 };
7003
7004 static void
viewporter_destroy(struct wl_client * client,struct wl_resource * resource)7005 viewporter_destroy(struct wl_client *client,
7006 struct wl_resource *resource)
7007 {
7008 wl_resource_destroy(resource);
7009 }
7010
7011 static void
viewporter_get_viewport(struct wl_client * client,struct wl_resource * viewporter,uint32_t id,struct wl_resource * surface_resource)7012 viewporter_get_viewport(struct wl_client *client,
7013 struct wl_resource *viewporter,
7014 uint32_t id,
7015 struct wl_resource *surface_resource)
7016 {
7017 int version = wl_resource_get_version(viewporter);
7018 struct weston_surface *surface =
7019 wl_resource_get_user_data(surface_resource);
7020 struct wl_resource *resource;
7021
7022 if (surface->viewport_resource) {
7023 wl_resource_post_error(viewporter,
7024 WP_VIEWPORTER_ERROR_VIEWPORT_EXISTS,
7025 "a viewport for that surface already exists");
7026 return;
7027 }
7028
7029 resource = wl_resource_create(client, &wp_viewport_interface,
7030 version, id);
7031 if (resource == NULL) {
7032 wl_client_post_no_memory(client);
7033 return;
7034 }
7035
7036 wl_resource_set_implementation(resource, &viewport_interface,
7037 surface, destroy_viewport);
7038
7039 surface->viewport_resource = resource;
7040 }
7041
7042 static const struct wp_viewporter_interface viewporter_interface = {
7043 viewporter_destroy,
7044 viewporter_get_viewport
7045 };
7046
7047 static void
bind_viewporter(struct wl_client * client,void * data,uint32_t version,uint32_t id)7048 bind_viewporter(struct wl_client *client,
7049 void *data, uint32_t version, uint32_t id)
7050 {
7051 struct wl_resource *resource;
7052
7053 resource = wl_resource_create(client, &wp_viewporter_interface,
7054 version, id);
7055 if (resource == NULL) {
7056 wl_client_post_no_memory(client);
7057 return;
7058 }
7059
7060 wl_resource_set_implementation(resource, &viewporter_interface,
7061 NULL, NULL);
7062 }
7063
7064 static void
destroy_presentation_feedback(struct wl_resource * feedback_resource)7065 destroy_presentation_feedback(struct wl_resource *feedback_resource)
7066 {
7067 struct weston_presentation_feedback *feedback;
7068
7069 feedback = wl_resource_get_user_data(feedback_resource);
7070
7071 wl_list_remove(&feedback->link);
7072 free(feedback);
7073 }
7074
7075 static void
presentation_destroy(struct wl_client * client,struct wl_resource * resource)7076 presentation_destroy(struct wl_client *client, struct wl_resource *resource)
7077 {
7078 wl_resource_destroy(resource);
7079 }
7080
7081 static void
presentation_feedback(struct wl_client * client,struct wl_resource * presentation_resource,struct wl_resource * surface_resource,uint32_t callback)7082 presentation_feedback(struct wl_client *client,
7083 struct wl_resource *presentation_resource,
7084 struct wl_resource *surface_resource,
7085 uint32_t callback)
7086 {
7087 struct weston_surface *surface;
7088 struct weston_presentation_feedback *feedback;
7089
7090 surface = wl_resource_get_user_data(surface_resource);
7091
7092 feedback = zalloc(sizeof *feedback);
7093 if (feedback == NULL)
7094 goto err_calloc;
7095
7096 feedback->resource = wl_resource_create(client,
7097 &wp_presentation_feedback_interface,
7098 1, callback);
7099 if (!feedback->resource)
7100 goto err_create;
7101
7102 wl_resource_set_implementation(feedback->resource, NULL, feedback,
7103 destroy_presentation_feedback);
7104
7105 wl_list_insert(&surface->pending.feedback_list, &feedback->link);
7106
7107 return;
7108
7109 err_create:
7110 free(feedback);
7111
7112 err_calloc:
7113 wl_client_post_no_memory(client);
7114 }
7115
7116 static const struct wp_presentation_interface presentation_implementation = {
7117 presentation_destroy,
7118 presentation_feedback
7119 };
7120
7121 static void
bind_presentation(struct wl_client * client,void * data,uint32_t version,uint32_t id)7122 bind_presentation(struct wl_client *client,
7123 void *data, uint32_t version, uint32_t id)
7124 {
7125 struct weston_compositor *compositor = data;
7126 struct wl_resource *resource;
7127
7128 resource = wl_resource_create(client, &wp_presentation_interface,
7129 version, id);
7130 if (resource == NULL) {
7131 wl_client_post_no_memory(client);
7132 return;
7133 }
7134
7135 wl_resource_set_implementation(resource, &presentation_implementation,
7136 compositor, NULL);
7137 wp_presentation_send_clock_id(resource, compositor->presentation_clock);
7138 }
7139
7140 static void
compositor_bind(struct wl_client * client,void * data,uint32_t version,uint32_t id)7141 compositor_bind(struct wl_client *client,
7142 void *data, uint32_t version, uint32_t id)
7143 {
7144 struct weston_compositor *compositor = data;
7145 struct wl_resource *resource;
7146
7147 resource = wl_resource_create(client, &wl_compositor_interface,
7148 version, id);
7149 if (resource == NULL) {
7150 wl_client_post_no_memory(client);
7151 return;
7152 }
7153
7154 wl_resource_set_implementation(resource, &compositor_interface,
7155 compositor, NULL);
7156 }
7157
7158 // OHOS remove logger
7159 //static const char *
7160 //output_repaint_status_text(struct weston_output *output)
7161 //{
7162 // switch (output->repaint_status) {
7163 // case REPAINT_NOT_SCHEDULED:
7164 // return "no repaint";
7165 // case REPAINT_BEGIN_FROM_IDLE:
7166 // return "start_repaint_loop scheduled";
7167 // case REPAINT_SCHEDULED:
7168 // return "repaint scheduled";
7169 // case REPAINT_AWAITING_COMPLETION:
7170 // return "awaiting completion";
7171 // }
7172 //
7173 // assert(!"output_repaint_status_text missing enum");
7174 // return NULL;
7175 //}
7176 //
7177 //static void
7178 //debug_scene_view_print_buffer(FILE *fp, struct weston_view *view)
7179 //{
7180 // struct weston_buffer *buffer = view->surface->buffer_ref.buffer;
7181 // struct wl_shm_buffer *shm;
7182 // struct linux_dmabuf_buffer *dmabuf;
7183 // const struct pixel_format_info *pixel_info = NULL;
7184 //
7185 // if (!buffer) {
7186 // fprintf(fp, "\t\t[buffer not available]\n");
7187 // return;
7188 // }
7189 //
7190 // shm = wl_shm_buffer_get(buffer->resource);
7191 // if (shm) {
7192 // uint32_t _format = wl_shm_buffer_get_format(shm);
7193 // pixel_info = pixel_format_get_info_shm(_format);
7194 // fprintf(fp, "\t\tSHM buffer\n");
7195 // fprintf(fp, "\t\t\tformat: 0x%lx %s\n",
7196 // (unsigned long) _format,
7197 // pixel_info ? pixel_info->drm_format_name : "UNKNOWN");
7198 // return;
7199 // }
7200 //
7201 // dmabuf = linux_dmabuf_buffer_get(buffer->resource);
7202 // if (dmabuf) {
7203 // pixel_info = pixel_format_get_info(dmabuf->attributes.format);
7204 // fprintf(fp, "\t\tdmabuf buffer\n");
7205 // fprintf(fp, "\t\t\tformat: 0x%lx %s\n",
7206 // (unsigned long) dmabuf->attributes.format,
7207 // pixel_info ? pixel_info->drm_format_name : "UNKNOWN");
7208 // fprintf(fp, "\t\t\tmodifier: 0x%llx\n",
7209 // (unsigned long long) dmabuf->attributes.modifier[0]);
7210 // return;
7211 // }
7212 //
7213 // fprintf(fp, "\t\tEGL buffer\n");
7214 //}
7215 //
7216 //static void
7217 //debug_scene_view_print(FILE *fp, struct weston_view *view, int view_idx)
7218 //{
7219 // struct weston_compositor *ec = view->surface->compositor;
7220 // struct weston_output *output;
7221 // char desc[512];
7222 // pixman_box32_t *box;
7223 // uint32_t surface_id = 0;
7224 // pid_t pid = 0;
7225 //
7226 // if (view->surface->resource) {
7227 // struct wl_resource *resource = view->surface->resource;
7228 // wl_client_get_credentials(wl_resource_get_client(resource),
7229 // &pid, NULL, NULL);
7230 // surface_id = wl_resource_get_id(view->surface->resource);
7231 // }
7232 //
7233 // if (!view->surface->get_label ||
7234 // view->surface->get_label(view->surface, desc, sizeof(desc)) < 0) {
7235 // strcpy(desc, "[no description available]");
7236 // }
7237 // fprintf(fp, "\tView %d (role %s, PID %d, surface ID %u, %s, %p):\n",
7238 // view_idx, view->surface->role_name, pid, surface_id,
7239 // desc, view);
7240 //
7241 // box = pixman_region32_extents(&view->transform.boundingbox);
7242 // fprintf(fp, "\t\tposition: (%d, %d) -> (%d, %d)\n",
7243 // box->x1, box->y1, box->x2, box->y2);
7244 // box = pixman_region32_extents(&view->transform.opaque);
7245 //
7246 // if (weston_view_is_opaque(view, &view->transform.boundingbox)) {
7247 // fprintf(fp, "\t\t[fully opaque]\n");
7248 // } else if (!pixman_region32_not_empty(&view->transform.opaque)) {
7249 // fprintf(fp, "\t\t[not opaque]\n");
7250 // } else {
7251 // fprintf(fp, "\t\t[opaque: (%d, %d) -> (%d, %d)]\n",
7252 // box->x1, box->y1, box->x2, box->y2);
7253 // }
7254 //
7255 // if (view->alpha < 1.0)
7256 // fprintf(fp, "\t\talpha: %f\n", view->alpha);
7257 //
7258 // if (view->output_mask != 0) {
7259 // bool first_output = true;
7260 // fprintf(fp, "\t\toutputs: ");
7261 // wl_list_for_each(output, &ec->output_list, link) {
7262 // if (!(view->output_mask & (1 << output->id)))
7263 // continue;
7264 // fprintf(fp, "%s%d (%s)%s",
7265 // (first_output) ? "" : ", ",
7266 // output->id, output->name,
7267 // (view->output == output) ? " (primary)" : "");
7268 // first_output = false;
7269 // }
7270 // } else {
7271 // fprintf(fp, "\t\t[no outputs]");
7272 // }
7273 //
7274 // fprintf(fp, "\n");
7275 //
7276 // debug_scene_view_print_buffer(fp, view);
7277 //}
7278 //
7279 //static void
7280 //debug_scene_view_print_tree(struct weston_view *view,
7281 // FILE *fp, int *view_idx)
7282 //{
7283 // struct weston_subsurface *sub;
7284 // struct weston_view *ev;
7285 //
7286 // /*
7287 // * print the view first, then we recursively go on printing
7288 // * sub-surfaces. We bail out once no more sub-surfaces are available.
7289 // */
7290 // debug_scene_view_print(fp, view, *view_idx);
7291 //
7292 // /* no more sub-surfaces */
7293 // if (wl_list_empty(&view->surface->subsurface_list))
7294 // return;
7295 //
7296 // wl_list_for_each(sub, &view->surface->subsurface_list, parent_link) {
7297 // wl_list_for_each(ev, &sub->surface->views, surface_link) {
7298 // /* only print the child views of the current view */
7299 // if (ev->parent_view != view)
7300 // continue;
7301 //
7302 // (*view_idx)++;
7303 // debug_scene_view_print_tree(ev, fp, view_idx);
7304 // }
7305 // }
7306 //}
7307
7308 /**
7309 * Output information on how libweston is currently composing the scene
7310 * graph.
7311 *
7312 * \ingroup compositor
7313 */
7314 // OHOS remove logger
7315 //WL_EXPORT char *
7316 //weston_compositor_print_scene_graph(struct weston_compositor *ec)
7317 //{
7318 // struct weston_output *output;
7319 // struct weston_layer *layer;
7320 // struct timespec now;
7321 // int layer_idx = 0;
7322 // FILE *fp;
7323 // char *ret;
7324 // size_t len;
7325 // int err;
7326 //
7327 // fp = open_memstream(&ret, &len);
7328 // assert(fp);
7329 //
7330 // weston_compositor_read_presentation_clock(ec, &now);
7331 // fprintf(fp, "Weston scene graph at %ld.%09ld:\n\n",
7332 // now.tv_sec, now.tv_nsec);
7333 //
7334 // wl_list_for_each(output, &ec->output_list, link) {
7335 // struct weston_head *head;
7336 // int head_idx = 0;
7337 //
7338 // fprintf(fp, "Output %d (%s):\n", output->id, output->name);
7339 // assert(output->enabled);
7340 //
7341 // fprintf(fp, "\tposition: (%d, %d) -> (%d, %d)\n",
7342 // output->x, output->y,
7343 // output->x + output->width,
7344 // output->y + output->height);
7345 // fprintf(fp, "\tmode: %dx%d@%.3fHz\n",
7346 // output->current_mode->width,
7347 // output->current_mode->height,
7348 // output->current_mode->refresh / 1000.0);
7349 // fprintf(fp, "\tscale: %d\n", output->scale);
7350 //
7351 // fprintf(fp, "\trepaint status: %s\n",
7352 // output_repaint_status_text(output));
7353 // if (output->repaint_status == REPAINT_SCHEDULED)
7354 // fprintf(fp, "\tnext repaint: %ld.%09ld\n",
7355 // output->next_repaint.tv_sec,
7356 // output->next_repaint.tv_nsec);
7357 //
7358 // wl_list_for_each(head, &output->head_list, output_link) {
7359 // fprintf(fp, "\tHead %d (%s): %sconnected\n",
7360 // head_idx++, head->name,
7361 // (head->connected) ? "" : "not ");
7362 // }
7363 // }
7364 //
7365 // fprintf(fp, "\n");
7366 //
7367 // wl_list_for_each(layer, &ec->layer_list, link) {
7368 // struct weston_view *view;
7369 // int view_idx = 0;
7370 //
7371 // fprintf(fp, "Layer %d (pos 0x%lx):\n", layer_idx++,
7372 // (unsigned long) layer->position);
7373 //
7374 // if (!weston_layer_mask_is_infinite(layer)) {
7375 // fprintf(fp, "\t[mask: (%d, %d) -> (%d,%d)]\n\n",
7376 // layer->mask.x1, layer->mask.y1,
7377 // layer->mask.x2, layer->mask.y2);
7378 // }
7379 //
7380 // wl_list_for_each(view, &layer->view_list.link, layer_link.link) {
7381 // debug_scene_view_print_tree(view, fp, &view_idx);
7382 // view_idx++;
7383 // }
7384 //
7385 // if (wl_list_empty(&layer->view_list.link))
7386 // fprintf(fp, "\t[no views]\n");
7387 //
7388 // fprintf(fp, "\n");
7389 // }
7390 //
7391 // err = fclose(fp);
7392 // assert(err == 0);
7393 //
7394 // return ret;
7395 //}
7396
7397 /**
7398 * Called when the 'scene-graph' debug scope is bound by a client. This
7399 * one-shot weston-debug scope prints the current scene graph when bound,
7400 * and then terminates the stream.
7401 */
7402 // OHOS remove logger
7403 //static void
7404 //debug_scene_graph_cb(struct weston_log_subscription *sub, void *data)
7405 //{
7406 // struct weston_compositor *ec = data;
7407 // char *str = weston_compositor_print_scene_graph(ec);
7408 //
7409 // weston_log_subscription_printf(sub, "%s", str);
7410 // free(str);
7411 // weston_log_subscription_complete(sub);
7412 //}
7413
7414 /** Create the compositor.
7415 *
7416 * This functions creates and initializes a compositor instance.
7417 *
7418 * \param display The Wayland display to be used.
7419 * \param user_data A pointer to an object that can later be retrieved
7420 * \param log_ctx A pointer to weston_debug_compositor
7421 * using the \ref weston_compositor_get_user_data function.
7422 * \return The compositor instance on success or NULL on failure.
7423 *
7424 * \ingroup compositor
7425 */
7426 WL_EXPORT struct weston_compositor *
weston_compositor_create(struct wl_display * display,void * user_data)7427 weston_compositor_create(struct wl_display *display,
7428 // OHOS remove logger
7429 // struct weston_log_context *log_ctx,
7430 void *user_data)
7431 {
7432 LOG_ENTER();
7433 struct weston_compositor *ec;
7434 struct wl_event_loop *loop;
7435
7436 // OHOS remove logger
7437 // if (!log_ctx)
7438 // return NULL;
7439
7440 ec = zalloc(sizeof *ec);
7441 if (!ec) {
7442 LOG_EXIT();
7443 return NULL;
7444 }
7445
7446 // OHOS remove logger
7447 // ec->weston_log_ctx = log_ctx;
7448 ec->wl_display = display;
7449 ec->user_data = user_data;
7450 wl_signal_init(&ec->destroy_signal);
7451 wl_signal_init(&ec->create_surface_signal);
7452 wl_signal_init(&ec->activate_signal);
7453 wl_signal_init(&ec->transform_signal);
7454 wl_signal_init(&ec->kill_signal);
7455 wl_signal_init(&ec->idle_signal);
7456 wl_signal_init(&ec->wake_signal);
7457 wl_signal_init(&ec->show_input_panel_signal);
7458 wl_signal_init(&ec->hide_input_panel_signal);
7459 wl_signal_init(&ec->update_input_panel_signal);
7460 wl_signal_init(&ec->seat_created_signal);
7461 wl_signal_init(&ec->output_created_signal);
7462 wl_signal_init(&ec->output_destroyed_signal);
7463 wl_signal_init(&ec->output_moved_signal);
7464 wl_signal_init(&ec->output_resized_signal);
7465 wl_signal_init(&ec->heads_changed_signal);
7466 wl_signal_init(&ec->output_heads_changed_signal);
7467 wl_signal_init(&ec->session_signal);
7468 ec->session_active = true;
7469
7470 ec->output_id_pool = 0;
7471 ec->repaint_msec = DEFAULT_REPAINT_WINDOW;
7472
7473 ec->activate_serial = 1;
7474
7475 ec->touch_mode = WESTON_TOUCH_MODE_NORMAL;
7476
7477 ec->content_protection = NULL;
7478
7479 if (!wl_global_create(ec->wl_display, &wl_compositor_interface, 4,
7480 ec, compositor_bind))
7481 goto fail;
7482
7483 if (!wl_global_create(ec->wl_display, &wl_subcompositor_interface, 1,
7484 ec, bind_subcompositor))
7485 goto fail;
7486
7487 if (!wl_global_create(ec->wl_display, &wp_viewporter_interface, 1,
7488 ec, bind_viewporter))
7489 goto fail;
7490
7491 if (!wl_global_create(ec->wl_display, &zxdg_output_manager_v1_interface, 2,
7492 ec, bind_xdg_output_manager))
7493 goto fail;
7494
7495 if (!wl_global_create(ec->wl_display, &wp_presentation_interface, 1,
7496 ec, bind_presentation))
7497 goto fail;
7498
7499 if (weston_input_init(ec) != 0)
7500 goto fail;
7501
7502 wl_list_init(&ec->view_list);
7503 wl_list_init(&ec->plane_list);
7504 wl_list_init(&ec->layer_list);
7505 wl_list_init(&ec->seat_list);
7506 wl_list_init(&ec->pending_output_list);
7507 wl_list_init(&ec->output_list);
7508 wl_list_init(&ec->head_list);
7509 wl_list_init(&ec->key_binding_list);
7510 wl_list_init(&ec->modifier_binding_list);
7511 wl_list_init(&ec->button_binding_list);
7512 wl_list_init(&ec->touch_binding_list);
7513 wl_list_init(&ec->axis_binding_list);
7514 wl_list_init(&ec->debug_binding_list);
7515
7516 wl_list_init(&ec->plugin_api_list);
7517
7518 weston_plane_init(&ec->primary_plane, ec, 0, 0);
7519 weston_compositor_stack_plane(ec, &ec->primary_plane, NULL);
7520
7521 wl_data_device_manager_init(ec->wl_display);
7522
7523 wl_display_init_shm(ec->wl_display);
7524
7525 loop = wl_display_get_event_loop(ec->wl_display);
7526 ec->idle_source = wl_event_loop_add_timer(loop, idle_handler, ec);
7527 ec->repaint_timer =
7528 wl_event_loop_add_timer(loop, output_repaint_timer_handler,
7529 ec);
7530
7531 weston_layer_init(&ec->fade_layer, ec);
7532 weston_layer_init(&ec->cursor_layer, ec);
7533
7534 weston_layer_set_position(&ec->fade_layer, WESTON_LAYER_POSITION_FADE);
7535 weston_layer_set_position(&ec->cursor_layer,
7536 WESTON_LAYER_POSITION_CURSOR);
7537
7538 // OHOS remove debugger
7539 // ec->debug_scene =
7540 // weston_compositor_add_log_scope(ec, "scene-graph",
7541 // "Scene graph details\n",
7542 // debug_scene_graph_cb, NULL,
7543 // ec);
7544 //
7545 // ec->timeline =
7546 // weston_compositor_add_log_scope(ec, "timeline",
7547 // "Timeline event points\n",
7548 // weston_timeline_create_subscription,
7549 // weston_timeline_destroy_subscription,
7550 // ec);
7551 LOG_EXIT();
7552 return ec;
7553
7554 fail:
7555 free(ec);
7556 LOG_EXIT();
7557 return NULL;
7558 }
7559
7560 /** weston_compositor_shutdown
7561 * \ingroup compositor
7562 */
7563 WL_EXPORT void
weston_compositor_shutdown(struct weston_compositor * ec)7564 weston_compositor_shutdown(struct weston_compositor *ec)
7565 {
7566 struct weston_output *output, *next;
7567
7568 wl_event_source_remove(ec->idle_source);
7569
7570 /* Destroy all outputs associated with this compositor */
7571 wl_list_for_each_safe(output, next, &ec->output_list, link)
7572 output->destroy(output);
7573
7574 /* Destroy all pending outputs associated with this compositor */
7575 wl_list_for_each_safe(output, next, &ec->pending_output_list, link)
7576 output->destroy(output);
7577
7578 if (ec->renderer)
7579 ec->renderer->destroy(ec);
7580
7581 weston_binding_list_destroy_all(&ec->key_binding_list);
7582 weston_binding_list_destroy_all(&ec->modifier_binding_list);
7583 weston_binding_list_destroy_all(&ec->button_binding_list);
7584 weston_binding_list_destroy_all(&ec->touch_binding_list);
7585 weston_binding_list_destroy_all(&ec->axis_binding_list);
7586 weston_binding_list_destroy_all(&ec->debug_binding_list);
7587
7588 weston_plane_release(&ec->primary_plane);
7589 }
7590
7591 /** weston_compositor_exit_with_code
7592 * \ingroup compositor
7593 */
7594 WL_EXPORT void
weston_compositor_exit_with_code(struct weston_compositor * compositor,int exit_code)7595 weston_compositor_exit_with_code(struct weston_compositor *compositor,
7596 int exit_code)
7597 {
7598 if (compositor->exit_code == EXIT_SUCCESS)
7599 compositor->exit_code = exit_code;
7600
7601 weston_compositor_exit(compositor);
7602 }
7603
7604 /** weston_compositor_set_default_pointer_grab
7605 * \ingroup compositor
7606 */
7607 WL_EXPORT void
weston_compositor_set_default_pointer_grab(struct weston_compositor * ec,const struct weston_pointer_grab_interface * interface)7608 weston_compositor_set_default_pointer_grab(struct weston_compositor *ec,
7609 const struct weston_pointer_grab_interface *interface)
7610 {
7611 struct weston_seat *seat;
7612
7613 ec->default_pointer_grab = interface;
7614 wl_list_for_each(seat, &ec->seat_list, link) {
7615 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
7616
7617 if (pointer)
7618 weston_pointer_set_default_grab(pointer, interface);
7619 }
7620 }
7621
7622 /** weston_compositor_set_presentation_clock
7623 * \ingroup compositor
7624 */
7625 WL_EXPORT int
weston_compositor_set_presentation_clock(struct weston_compositor * compositor,clockid_t clk_id)7626 weston_compositor_set_presentation_clock(struct weston_compositor *compositor,
7627 clockid_t clk_id)
7628 {
7629 struct timespec ts;
7630
7631 if (clock_gettime(clk_id, &ts) < 0)
7632 return -1;
7633
7634 compositor->presentation_clock = clk_id;
7635
7636 return 0;
7637 }
7638
7639 /** For choosing the software clock, when the display hardware or API
7640 * does not expose a compatible presentation timestamp.
7641 *
7642 * \ingroup compositor
7643 */
7644 WL_EXPORT int
weston_compositor_set_presentation_clock_software(struct weston_compositor * compositor)7645 weston_compositor_set_presentation_clock_software(
7646 struct weston_compositor *compositor)
7647 {
7648 /* In order of preference */
7649 static const clockid_t clocks[] = {
7650 CLOCK_MONOTONIC_RAW, /* no jumps, no crawling */
7651 CLOCK_MONOTONIC_COARSE, /* no jumps, may crawl, fast & coarse */
7652 CLOCK_MONOTONIC, /* no jumps, may crawl */
7653 CLOCK_REALTIME_COARSE, /* may jump and crawl, fast & coarse */
7654 CLOCK_REALTIME /* may jump and crawl */
7655 };
7656 unsigned i;
7657
7658 for (i = 0; i < ARRAY_LENGTH(clocks); i++)
7659 if (weston_compositor_set_presentation_clock(compositor,
7660 clocks[i]) == 0)
7661 return 0;
7662
7663 weston_log("Error: no suitable presentation clock available.\n");
7664
7665 return -1;
7666 }
7667
7668 /** Read the current time from the Presentation clock
7669 *
7670 * \param compositor
7671 * \param[out] ts The current time.
7672 *
7673 * \note Reading the current time in user space is always imprecise to some
7674 * degree.
7675 *
7676 * This function is never meant to fail. If reading the clock does fail,
7677 * an error message is logged and a zero time is returned. Callers are not
7678 * supposed to detect or react to failures.
7679 *
7680 * \ingroup compositor
7681 */
7682 WL_EXPORT void
weston_compositor_read_presentation_clock(const struct weston_compositor * compositor,struct timespec * ts)7683 weston_compositor_read_presentation_clock(
7684 const struct weston_compositor *compositor,
7685 struct timespec *ts)
7686 {
7687 static bool warned;
7688 int ret;
7689
7690 ret = clock_gettime(compositor->presentation_clock, ts);
7691 if (ret < 0) {
7692 ts->tv_sec = 0;
7693 ts->tv_nsec = 0;
7694
7695 if (!warned)
7696 weston_log("Error: failure to read "
7697 "the presentation clock %#x: '%s' (%d)\n",
7698 compositor->presentation_clock,
7699 strerror(errno), errno);
7700 warned = true;
7701 }
7702 }
7703
7704 /** Import dmabuf buffer into current renderer
7705 *
7706 * \param compositor
7707 * \param buffer the dmabuf buffer to import
7708 * \return true on usable buffers, false otherwise
7709 *
7710 * This function tests that the linux_dmabuf_buffer is usable
7711 * for the current renderer. Returns false on unusable buffers. Usually
7712 * usability is tested by importing the dmabufs for composition.
7713 *
7714 * This hook is also used for detecting if the renderer supports
7715 * dmabufs at all. If the renderer hook is NULL, dmabufs are not
7716 * supported.
7717 *
7718 * \ingroup compositor
7719 */
7720 WL_EXPORT bool
weston_compositor_import_dmabuf(struct weston_compositor * compositor,struct linux_dmabuf_buffer * buffer)7721 weston_compositor_import_dmabuf(struct weston_compositor *compositor,
7722 struct linux_dmabuf_buffer *buffer)
7723 {
7724 struct weston_renderer *renderer;
7725
7726 renderer = compositor->renderer;
7727
7728 if (renderer->import_dmabuf == NULL)
7729 return false;
7730
7731 return renderer->import_dmabuf(compositor, buffer);
7732 }
7733
7734 WL_EXPORT bool
weston_compositor_dmabuf_can_scanout(struct weston_compositor * compositor,struct linux_dmabuf_buffer * buffer)7735 weston_compositor_dmabuf_can_scanout(struct weston_compositor *compositor,
7736 struct linux_dmabuf_buffer *buffer)
7737 {
7738 struct weston_backend *backend = compositor->backend;
7739
7740 if (backend->can_scanout_dmabuf == NULL)
7741 return false;
7742
7743 return backend->can_scanout_dmabuf(compositor, buffer);
7744 }
7745
7746 WL_EXPORT void
weston_version(int * major,int * minor,int * micro)7747 weston_version(int *major, int *minor, int *micro)
7748 {
7749 *major = WESTON_VERSION_MAJOR;
7750 *minor = WESTON_VERSION_MINOR;
7751 *micro = WESTON_VERSION_MICRO;
7752 }
7753
7754 /**
7755 * Attempts to find a module path from the module map specified in the
7756 * environment. If found, writes the full path into the path variable.
7757 *
7758 * The module map is a string in environment variable WESTON_MODULE_MAP, where
7759 * each entry is of the form "name=path" and entries are separated by
7760 * semicolons. Whitespace is significant.
7761 *
7762 * \param name The name to search for.
7763 * \param path Where the path is written to if found.
7764 * \param path_len Allocated bytes at \c path .
7765 * \returns The length of the string written to path on success, or 0 if the
7766 * module was not specified in the environment map or path_len was too small.
7767 */
7768 WL_EXPORT size_t
weston_module_path_from_env(const char * name,char * path,size_t path_len)7769 weston_module_path_from_env(const char *name, char *path, size_t path_len)
7770 {
7771 const char *mapping = getenv("WESTON_MODULE_MAP");
7772 const char *end;
7773 const int name_len = strlen(name);
7774
7775 if (!mapping)
7776 return 0;
7777
7778 end = mapping + strlen(mapping);
7779 while (mapping < end && *mapping) {
7780 const char *filename, *next;
7781
7782 /* early out: impossibly short string */
7783 if (end - mapping < name_len + 1)
7784 return 0;
7785
7786 filename = &mapping[name_len + 1];
7787 next = strchrnul(mapping, ';');
7788
7789 if (strncmp(mapping, name, name_len) == 0 &&
7790 mapping[name_len] == '=') {
7791 size_t file_len = next - filename; /* no trailing NUL */
7792 if (file_len >= path_len)
7793 return 0;
7794 strncpy(path, filename, file_len);
7795 path[file_len] = '\0';
7796 return file_len;
7797 }
7798
7799 mapping = next + 1;
7800 }
7801
7802 return 0;
7803 }
7804
7805 WL_EXPORT void *
weston_load_module(const char * name,const char * entrypoint)7806 weston_load_module(const char *name, const char *entrypoint)
7807 {
7808 char path[PATH_MAX];
7809 void *module, *init;
7810 size_t len;
7811
7812 if (name == NULL)
7813 return NULL;
7814
7815 if (name[0] != '/') {
7816 len = weston_module_path_from_env(name, path, sizeof path);
7817 if (len == 0)
7818 len = snprintf(path, sizeof path, "%s/%s",
7819 LIBWESTON_MODULEDIR, name);
7820 } else {
7821 len = snprintf(path, sizeof path, "%s", name);
7822 }
7823
7824 /* snprintf returns the length of the string it would've written,
7825 * _excluding_ the NUL byte. So even being equal to the size of
7826 * our buffer is an error here. */
7827 if (len >= sizeof path)
7828 return NULL;
7829
7830 module = dlopen(path, RTLD_NOW | RTLD_NOLOAD);
7831 if (module) {
7832 weston_log("Module '%s' already loaded\n", path);
7833 } else {
7834 weston_log("Loading module '%{public}s'\n", path);
7835 module = dlopen(path, RTLD_NOW);
7836 if (!module) {
7837 weston_log("Failed to load module: %{public}s\n", dlerror());
7838 return NULL;
7839 }
7840 }
7841
7842 init = dlsym(module, entrypoint);
7843 if (!init) {
7844 weston_log("Failed to lookup init function: %s\n", dlerror());
7845 dlclose(module);
7846 return NULL;
7847 }
7848
7849 return init;
7850 }
7851
7852 /** Add a compositor destroy listener only once
7853 *
7854 * \param compositor The compositor whose destroy to watch for.
7855 * \param listener The listener struct to initialize.
7856 * \param destroy_handler The callback when compositor is destroyed.
7857 * \return True if listener is added, or false if there already is a listener
7858 * with the given \c destroy_handler.
7859 *
7860 * This function does nothing and returns false if the given callback function
7861 * is already present in the weston_compositor destroy callbacks list.
7862 * Otherwise, this function initializes the given listener with the given
7863 * callback pointer and adds it to the compositor's destroy callbacks list.
7864 *
7865 * This can be used to ensure that plugin initialization is done only once
7866 * in case the same plugin is loaded multiple times. If this function returns
7867 * false, the plugin should be already initialized successfully.
7868 *
7869 * All plugins should register a destroy listener for cleaning up. Note, that
7870 * the plugin destruction order is not guaranteed: plugins that depend on other
7871 * plugins must be able to be torn down in arbitrary order.
7872 *
7873 * \sa weston_compositor_destroy
7874 */
7875 WL_EXPORT bool
weston_compositor_add_destroy_listener_once(struct weston_compositor * compositor,struct wl_listener * listener,wl_notify_func_t destroy_handler)7876 weston_compositor_add_destroy_listener_once(struct weston_compositor *compositor,
7877 struct wl_listener *listener,
7878 wl_notify_func_t destroy_handler)
7879 {
7880 if (wl_signal_get(&compositor->destroy_signal, destroy_handler))
7881 return false;
7882
7883 listener->notify = destroy_handler;
7884 wl_signal_add(&compositor->destroy_signal, listener);
7885 return true;
7886 }
7887
7888 /** Destroys the compositor.
7889 *
7890 * This function cleans up the compositor state and then destroys it.
7891 *
7892 * @param compositor The compositor to be destroyed.
7893 *
7894 * @ingroup compositor
7895 */
7896 WL_EXPORT void
weston_compositor_destroy(struct weston_compositor * compositor)7897 weston_compositor_destroy(struct weston_compositor *compositor)
7898 {
7899 /* prevent further rendering while shutting down */
7900 compositor->state = WESTON_COMPOSITOR_OFFSCREEN;
7901
7902 wl_signal_emit(&compositor->destroy_signal, compositor);
7903
7904 weston_compositor_xkb_destroy(compositor);
7905
7906 if (compositor->backend)
7907 compositor->backend->destroy(compositor);
7908
7909 /* The backend is responsible for destroying the heads. */
7910 assert(wl_list_empty(&compositor->head_list));
7911
7912 weston_plugin_api_destroy_list(compositor);
7913
7914 if (compositor->heads_changed_source)
7915 wl_event_source_remove(compositor->heads_changed_source);
7916
7917 // OHOS remove logger
7918 // weston_log_scope_destroy(compositor->debug_scene);
7919 // compositor->debug_scene = NULL;
7920 //
7921 // weston_log_scope_destroy(compositor->timeline);
7922 // compositor->timeline = NULL;
7923
7924 free(compositor);
7925 }
7926
7927 /** Instruct the compositor to exit.
7928 *
7929 * This functions does not directly destroy the compositor object, it merely
7930 * command it to start the tear down process. It is not guaranteed that the
7931 * tear down will happen immediately.
7932 *
7933 * \param compositor The compositor to tear down.
7934 *
7935 * \ingroup compositor
7936 */
7937 WL_EXPORT void
weston_compositor_exit(struct weston_compositor * compositor)7938 weston_compositor_exit(struct weston_compositor *compositor)
7939 {
7940 compositor->exit(compositor);
7941 }
7942
7943 /** Return the user data stored in the compositor.
7944 *
7945 * This function returns the user data pointer set with user_data parameter
7946 * to the \ref weston_compositor_create function.
7947 *
7948 * \ingroup compositor
7949 */
7950 WL_EXPORT void *
weston_compositor_get_user_data(struct weston_compositor * compositor)7951 weston_compositor_get_user_data(struct weston_compositor *compositor)
7952 {
7953 return compositor->user_data;
7954 }
7955
7956 static const char * const backend_map[] = {
7957 [WESTON_BACKEND_DRM] = "drm-backend.so",
7958 [WESTON_BACKEND_FBDEV] = "fbdev-backend.so",
7959 [WESTON_BACKEND_HEADLESS] = "headless-backend.so",
7960 [WESTON_BACKEND_RDP] = "rdp-backend.so",
7961 [WESTON_BACKEND_WAYLAND] = "wayland-backend.so",
7962 [WESTON_BACKEND_X11] = "x11-backend.so",
7963 [WESTON_BACKEND_HDI] = "hdi-backend.so",
7964 };
7965
7966 /** Load a backend into a weston_compositor
7967 *
7968 * A backend must be loaded to make a weston_compositor work. A backend
7969 * provides input and output capabilities, and determines the renderer to use.
7970 *
7971 * \param compositor A compositor that has not had a backend loaded yet.
7972 * \param backend Name of the backend file.
7973 * \param config_base A pointer to a backend-specific configuration
7974 * structure's 'base' member.
7975 *
7976 * \return 0 on success, or -1 on error.
7977 *
7978 * \ingroup compositor
7979 */
7980 WL_EXPORT int
weston_compositor_load_backend(struct weston_compositor * compositor,enum weston_compositor_backend backend,struct weston_backend_config * config_base)7981 weston_compositor_load_backend(struct weston_compositor *compositor,
7982 enum weston_compositor_backend backend,
7983 struct weston_backend_config *config_base)
7984 {
7985 int (*backend_init)(struct weston_compositor *c,
7986 struct weston_backend_config *config_base);
7987
7988 if (compositor->backend) {
7989 weston_log("Error: attempt to load a backend when one is already loaded\n");
7990 return -1;
7991 }
7992
7993 if (backend >= ARRAY_LENGTH(backend_map))
7994 return -1;
7995
7996 backend_init = weston_load_module(backend_map[backend], "weston_backend_init");
7997 if (!backend_init)
7998 return -1;
7999
8000 if (backend_init(compositor, config_base) < 0) {
8001 compositor->backend = NULL;
8002 return -1;
8003 }
8004
8005 return 0;
8006 }
8007
8008 /** weston_compositor_load_xwayland
8009 * \ingroup compositor
8010 */
8011 WL_EXPORT int
weston_compositor_load_xwayland(struct weston_compositor * compositor)8012 weston_compositor_load_xwayland(struct weston_compositor *compositor)
8013 {
8014 int (*module_init)(struct weston_compositor *ec);
8015
8016 module_init = weston_load_module("xwayland.so", "weston_module_init");
8017 if (!module_init)
8018 return -1;
8019 if (module_init(compositor) < 0)
8020 return -1;
8021 return 0;
8022 }
8023
8024 /** Resolve an internal compositor error by disconnecting the client.
8025 *
8026 * This function is used in cases when the wl_buffer turns out
8027 * unusable and there is no fallback path.
8028 *
8029 * It is possible the fault is caused by a compositor bug, the underlying
8030 * graphics stack bug or normal behaviour, or perhaps a client mistake.
8031 * In any case, the options are to either composite garbage or nothing,
8032 * or disconnect the client. This is a helper function for the latter.
8033 *
8034 * The error is sent as an INVALID_OBJECT error on the client's wl_display.
8035 *
8036 * \param buffer The weston buffer that is unusable.
8037 * \param msg A custom error message attached to the protocol error.
8038 */
8039 WL_EXPORT void
weston_buffer_send_server_error(struct weston_buffer * buffer,const char * msg)8040 weston_buffer_send_server_error(struct weston_buffer *buffer,
8041 const char *msg)
8042 {
8043 struct wl_client *client;
8044 struct wl_resource *display_resource;
8045 uint32_t id;
8046
8047 assert(buffer->resource);
8048 id = wl_resource_get_id(buffer->resource);
8049 client = wl_resource_get_client(buffer->resource);
8050 display_resource = wl_client_get_object(client, 1);
8051
8052 assert(display_resource);
8053 wl_resource_post_error(display_resource,
8054 WL_DISPLAY_ERROR_INVALID_OBJECT,
8055 "server error with "
8056 "wl_buffer@%u: %s", id, msg);
8057 }
8058
8059 WL_EXPORT void
weston_output_disable_planes_incr(struct weston_output * output)8060 weston_output_disable_planes_incr(struct weston_output *output)
8061 {
8062 output->disable_planes++;
8063 /*
8064 * If disable_planes changes from 0 to non-zero, it means some type of
8065 * recording of content has started, and therefore protection level of
8066 * the protected surfaces must be updated to avoid the recording of
8067 * the protected content.
8068 */
8069 if (output->disable_planes == 1)
8070 weston_schedule_surface_protection_update(output->compositor);
8071 }
8072
8073 WL_EXPORT void
weston_output_disable_planes_decr(struct weston_output * output)8074 weston_output_disable_planes_decr(struct weston_output *output)
8075 {
8076 output->disable_planes--;
8077 /*
8078 * If disable_planes changes from non-zero to 0, it means no content
8079 * recording is going on any more, and the protected and surfaces can be
8080 * shown without any apprehensions about content being recorded.
8081 */
8082 if (output->disable_planes == 0)
8083 weston_schedule_surface_protection_update(output->compositor);
8084
8085 }
8086