1From 15243cd3aec009b59b4b6aa4698b56ed3506c304 Mon Sep 17 00:00:00 2001 2From: Jeffy Chen <jeffy.chen@rock-chips.com> 3Date: Thu, 19 Nov 2020 09:41:47 +0800 4Subject: [PATCH 15/79] backend-drm: Support mirror mode 5 6Set env "WESTON_DRM_MIRROR" to enable mirror mode, and set env 7"WESTON_DRM_KEEP_RATIO" to keep the aspect ratio. 8 9Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> 10--- 11 clients/desktop-shell.c | 9 +- 12 desktop-shell/shell.c | 3 + 13 include/libweston/libweston.h | 4 + 14 libweston/backend-drm/drm-gbm.c | 4 +- 15 libweston/backend-drm/drm-internal.h | 10 + 16 libweston/backend-drm/drm.c | 328 +++++++++++++++++++++++++- 17 libweston/backend-drm/meson.build | 3 +- 18 libweston/backend-drm/state-propose.c | 22 +- 19 libweston/compositor.c | 24 +- 20 libweston/input.c | 7 + 21 meson.build | 5 + 22 11 files changed, 398 insertions(+), 21 deletions(-) 23 24diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c 25index 56c3976..8711399 100644 26--- a/clients/desktop-shell.c 27+++ b/clients/desktop-shell.c 28@@ -1062,9 +1062,14 @@ desktop_shell_configure(void *data, 29 struct wl_surface *surface, 30 int32_t width, int32_t height) 31 { 32- struct window *window = wl_surface_get_user_data(surface); 33- struct surface *s = window_get_user_data(window); 34+ struct window *window; 35+ struct surface *s; 36+ 37+ if (!surface) 38+ return; 39 40+ window = wl_surface_get_user_data(surface); 41+ s = window_get_user_data(window); 42 s->configure(data, desktop_shell, edges, window, width, height); 43 } 44 45diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c 46index 515c57f..18bec12 100644 47--- a/desktop-shell/shell.c 48+++ b/desktop-shell/shell.c 49@@ -4280,6 +4280,9 @@ weston_view_set_initial_position(struct weston_view *view, 50 } 51 52 wl_list_for_each(output, &compositor->output_list, link) { 53+ if (output->unavailable) 54+ continue; 55+ 56 if (pixman_region32_contains_point(&output->region, ix, iy, NULL)) { 57 target_output = output; 58 break; 59diff --git a/include/libweston/libweston.h b/include/libweston/libweston.h 60index bdecc19..8868622 100644 61--- a/include/libweston/libweston.h 62+++ b/include/libweston/libweston.h 63@@ -411,7 +411,11 @@ struct weston_output { 64 */ 65 void (*detach_head)(struct weston_output *output, 66 struct weston_head *head); 67+ 68+ bool unavailable; 69 }; 70+#define weston_output_valid(o) \ 71+ ((o) && !(o)->destroying && !(o)->unavailable) 72 73 enum weston_pointer_motion_mask { 74 WESTON_POINTER_MOTION_ABS = 1 << 0, 75diff --git a/libweston/backend-drm/drm-gbm.c b/libweston/backend-drm/drm-gbm.c 76index d0a4c6c..d7bd05f 100644 77--- a/libweston/backend-drm/drm-gbm.c 78+++ b/libweston/backend-drm/drm-gbm.c 79@@ -265,8 +265,8 @@ drm_output_fini_egl(struct drm_output *output) 80 /* Destroying the GBM surface will destroy all our GBM buffers, 81 * regardless of refcount. Ensure we destroy them here. */ 82 if (!b->shutting_down && 83- output->scanout_plane->state_cur->fb && 84- output->scanout_plane->state_cur->fb->type == BUFFER_GBM_SURFACE) { 85+ output->scanout_plane->state_cur->fb && (output->is_mirror || 86+ output->scanout_plane->state_cur->fb->type == BUFFER_GBM_SURFACE)) { 87 drm_plane_reset_state(output->scanout_plane); 88 } 89 90diff --git a/libweston/backend-drm/drm-internal.h b/libweston/backend-drm/drm-internal.h 91index 996f587..1625be2 100644 92--- a/libweston/backend-drm/drm-internal.h 93+++ b/libweston/backend-drm/drm-internal.h 94@@ -346,6 +346,8 @@ struct drm_backend { 95 96 int virtual_width; 97 int virtual_height; 98+ 99+ bool mirror_mode; 100 }; 101 102 struct drm_mode { 103@@ -603,6 +605,10 @@ struct drm_output { 104 int current_image; 105 pixman_region32_t previous_damage; 106 107+ /* Wrap fb for scale/rotate usage */ 108+ struct drm_fb *wrap[2]; 109+ int next_wrap; 110+ 111 struct vaapi_recorder *recorder; 112 struct wl_listener recorder_frame_listener; 113 114@@ -616,6 +622,10 @@ struct drm_output { 115 116 /* The dummy framebuffer for SET_CRTC. */ 117 struct drm_fb *fb_dummy; 118+ 119+ bool is_mirror; 120+ 121+ pixman_box32_t plane_bounds; 122 }; 123 124 static inline struct drm_head * 125diff --git a/libweston/backend-drm/drm.c b/libweston/backend-drm/drm.c 126index 1c839c5..696df68 100644 127--- a/libweston/backend-drm/drm.c 128+++ b/libweston/backend-drm/drm.c 129@@ -67,6 +67,11 @@ 130 #include "linux-dmabuf-unstable-v1-server-protocol.h" 131 #include "linux-explicit-synchronization.h" 132 133+#ifdef HAVE_RGA 134+#include <rga/rga.h> 135+#include <rga/RgaApi.h> 136+#endif 137+ 138 static const char default_seat[] = "seat0"; 139 140 static inline bool 141@@ -85,6 +90,118 @@ drm_head_is_external(struct drm_head *head) 142 } 143 }; 144 145+static int 146+drm_output_get_rotation(struct drm_output *output) 147+{ 148+ switch (output->base.transform) { 149+ case WL_OUTPUT_TRANSFORM_90: 150+ case WL_OUTPUT_TRANSFORM_FLIPPED_90: 151+ return 90; 152+ case WL_OUTPUT_TRANSFORM_180: 153+ case WL_OUTPUT_TRANSFORM_FLIPPED_180: 154+ return 180; 155+ case WL_OUTPUT_TRANSFORM_270: 156+ case WL_OUTPUT_TRANSFORM_FLIPPED_270: 157+ return 270; 158+ default: 159+ return 0; 160+ } 161+} 162+ 163+#ifdef HAVE_RGA 164+static inline RgaSURF_FORMAT 165+rga_get_format(const struct pixel_format_info *format) 166+{ 167+ switch (format->bpp) { 168+ case 32: 169+ return RK_FORMAT_BGRX_8888; 170+ case 16: 171+ return RK_FORMAT_RGB_565; 172+ default: 173+ return RK_FORMAT_UNKNOWN; 174+ } 175+} 176+#endif 177+ 178+static int 179+drm_copy_fb(struct drm_fb *src, struct drm_fb *dst, int rotation, 180+ int src_width, int src_height) 181+{ 182+#ifndef HAVE_RGA 183+ /* TODO: Use pixman to do the copy */ 184+ weston_log("rga not supported\n"); 185+ return -1; 186+#else 187+ RgaSURF_FORMAT src_format, dst_format; 188+ rga_info_t src_info = {0}; 189+ rga_info_t dst_info = {0}; 190+ int src_fd, dst_fd; 191+ int ret; 192+ 193+ static bool rga_supported = true; 194+ static bool rga_inited = false; 195+ 196+ if (!rga_supported) 197+ return -1; 198+ 199+ if (!rga_inited) { 200+ ret = c_RkRgaInit(); 201+ if (ret < 0) { 202+ weston_log("rga not supported\n"); 203+ rga_supported = false; 204+ return ret; 205+ } 206+ rga_inited = true; 207+ } 208+ 209+ src_format = rga_get_format(src->format); 210+ dst_format = rga_get_format(dst->format); 211+ 212+ if (src_format == RK_FORMAT_UNKNOWN || 213+ dst_format == RK_FORMAT_UNKNOWN) { 214+ weston_log("unsupported fb format\n"); 215+ return -1; 216+ } 217+ 218+ ret = drmPrimeHandleToFD(src->fd, src->handles[0], 219+ DRM_CLOEXEC, &src_fd); 220+ if (ret < 0) 221+ return ret; 222+ 223+ ret = drmPrimeHandleToFD(dst->fd, dst->handles[0], 224+ DRM_CLOEXEC, &dst_fd); 225+ if (ret < 0) 226+ goto close_src; 227+ 228+ src_info.fd = src_fd; 229+ src_info.mmuFlag = 1; 230+ 231+ rga_set_rect(&src_info.rect, 0, 0, src_width, src_height, 232+ src->strides[0] * 8 / src->format->bpp, src->height, 233+ src_format); 234+ 235+ if (rotation == 90) 236+ src_info.rotation = HAL_TRANSFORM_ROT_90; 237+ else if (rotation == 180) 238+ src_info.rotation = HAL_TRANSFORM_ROT_180; 239+ else if (rotation == 270) 240+ src_info.rotation = HAL_TRANSFORM_ROT_270; 241+ 242+ dst_info.fd = dst_fd; 243+ dst_info.mmuFlag = 1; 244+ 245+ rga_set_rect(&dst_info.rect, 0, 0, dst->width, dst->height, 246+ dst->strides[0] * 8 / dst->format->bpp, dst->height, 247+ dst_format); 248+ 249+ ret = c_RkRgaBlit(&src_info, &dst_info, NULL); 250+ close(dst_fd); 251+close_src: 252+ close(src_fd); 253+ return ret; 254+#endif 255+} 256+ 257 static void 258 drm_backend_update_outputs(struct drm_backend *b) 259 { 260@@ -94,6 +211,26 @@ drm_backend_update_outputs(struct drm_backend *b) 261 return; 262 263 primary = b->primary_head->base.output; 264+ 265+ if (b->mirror_mode) { 266+ wl_list_for_each(base, &b->compositor->output_list, link) { 267+ struct drm_output *output = to_drm_output(base); 268+ bool is_mirror = base != primary; 269+ 270+ if (output->is_mirror == is_mirror) 271+ continue; 272+ 273+ /* Make mirrors unavailable for normal views */ 274+ output->base.unavailable = is_mirror; 275+ 276+ output->is_mirror = is_mirror; 277+ output->state_invalid = true; 278+ 279+ weston_log("Output %s changed to %s output\n", 280+ base->name, is_mirror ? "mirror" : "main"); 281+ } 282+ } 283+ 284 if (!primary) 285 return; 286 287@@ -392,6 +529,69 @@ drm_output_render_pixman(struct drm_output_state *state, 288 return drm_fb_ref(output->dumb[output->current_image]); 289 } 290 291+static struct drm_fb * 292+drm_output_get_fb(struct drm_pending_state *pending_state, 293+ struct weston_output *output_base) 294+{ 295+ struct drm_output *output = to_drm_output(output_base); 296+ struct drm_plane_state *scanout_state; 297+ struct drm_output_state *state; 298+ struct drm_fb *fb = output->scanout_plane->state_cur->fb; 299+ 300+ state = drm_pending_state_get_output(pending_state, output); 301+ if (!state) 302+ return fb; 303+ 304+ scanout_state = 305+ drm_output_state_get_existing_plane(state, 306+ output->scanout_plane); 307+ if (!scanout_state || !scanout_state->fb) 308+ return fb; 309+ 310+ return scanout_state->fb; 311+} 312+ 313+static void 314+drm_output_try_destroy_wrap_fb(struct drm_output *output) 315+{ 316+ if (output->wrap[0]) { 317+ drm_fb_unref(output->wrap[0]); 318+ output->wrap[0] = NULL; 319+ } 320+ 321+ if (output->wrap[1]) { 322+ drm_fb_unref(output->wrap[1]); 323+ output->wrap[1] = NULL; 324+ } 325+ 326+ output->next_wrap = 0; 327+} 328+ 329+static struct drm_fb * 330+drm_output_get_wrap_fb(struct drm_backend *b, struct drm_output *output, 331+ int width, int height) 332+{ 333+ struct drm_fb *fb = output->wrap[output->next_wrap]; 334+ 335+ if (fb) { 336+ if (fb->width == width && fb->height == height) 337+ goto out; 338+ 339+ drm_fb_unref(fb); 340+ } 341+ 342+ fb = drm_fb_create_dumb(b, width, height, output->gbm_format); 343+ if (!fb) { 344+ weston_log("failed to create wrap fb\n"); 345+ return NULL; 346+ } 347+ 348+ output->wrap[output->next_wrap] = fb; 349+out: 350+ output->next_wrap ^= 1; 351+ return drm_fb_ref(fb); 352+} 353+ 354 void 355 drm_output_render(struct drm_output_state *state, pixman_region32_t *damage) 356 { 357@@ -403,10 +603,13 @@ drm_output_render(struct drm_output_state *state, pixman_region32_t *damage) 358 &scanout_plane->props[WDRM_PLANE_FB_DAMAGE_CLIPS]; 359 struct drm_backend *b = to_drm_backend(c); 360 struct drm_mode *mode; 361- struct drm_fb *fb; 362+ struct drm_fb *fb = NULL; 363 pixman_region32_t scanout_damage; 364 pixman_box32_t *rects; 365 int n_rects; 366+ int sw, sh, dx, dy, dw, dh; 367+ int rotation = 0; 368+ bool scaling; 369 370 /* If we already have a client buffer promoted to scanout, then we don't 371 * want to render. */ 372@@ -414,6 +617,35 @@ drm_output_render(struct drm_output_state *state, pixman_region32_t *damage) 373 if (scanout_state->fb) 374 return; 375 376+ if (!output->is_mirror) { 377+ struct drm_output *tmp; 378+ 379+ /* Repaint all mirrors when updating main output */ 380+ wl_list_for_each(tmp, &b->compositor->output_list, base.link) 381+ if (tmp->is_mirror) 382+ weston_output_schedule_repaint(&tmp->base); 383+ } else { 384+ if (!b->primary_head) 385+ goto out; 386+ 387+ rotation = drm_output_get_rotation(output); 388+ 389+ fb = drm_output_get_fb(state->pending_state, 390+ b->primary_head->base.output); 391+ if (fb) { 392+ drm_fb_ref(fb); 393+ 394+ pixman_region32_init(&scanout_damage); 395+ wl_signal_emit(&output->base.frame_signal, 396+ &scanout_damage); 397+ pixman_region32_fini(&scanout_damage); 398+ } else { 399+ weston_compositor_damage_all(b->compositor); 400+ } 401+ 402+ goto out; 403+ } 404+ 405 /* 406 * If we don't have any damage on the primary plane, and we already 407 * have a renderer buffer active, we can reuse it; else we pass 408@@ -433,24 +665,86 @@ drm_output_render(struct drm_output_state *state, pixman_region32_t *damage) 409 fb = drm_output_render_gl(state, damage); 410 } 411 412+out: 413 if (!fb) { 414 drm_plane_state_put_back(scanout_state); 415 return; 416 } 417 418+ sw = fb->width; 419+ sh = fb->height; 420+ 421+ dx = output->plane_bounds.x1; 422+ dy = output->plane_bounds.y1; 423+ dw = output->plane_bounds.x2 - output->plane_bounds.x1; 424+ dh = output->plane_bounds.y2 - output->plane_bounds.y1; 425+ 426+ if (!dw || !dh) { 427+ mode = to_drm_mode(output->base.current_mode); 428+ dw = mode->mode_info.hdisplay; 429+ dh = mode->mode_info.vdisplay; 430+ } 431+ 432+ if (output->is_mirror && getenv("WESTON_DRM_KEEP_RATIO")) { 433+ float src_ratio = (float) sw / sh; 434+ float dst_ratio = (float) dw / dh; 435+ int offset; 436+ 437+ if (rotation % 180) 438+ src_ratio = 1 / src_ratio; 439+ 440+ if (src_ratio > dst_ratio) { 441+ offset = dh - dw / src_ratio; 442+ dy = offset / 2; 443+ dh -= offset; 444+ } else { 445+ offset = dw - dh * src_ratio; 446+ dx = offset / 2; 447+ dw -= offset; 448+ } 449+ } 450+ 451+ scaling = sw != dw || sh != dh; 452+ 453+ if (rotation || (scaling && !output->scanout_plane->can_scale)) { 454+ struct drm_fb *wrap_fb = 455+ drm_output_get_wrap_fb(b, output, dw, dh); 456+ if (!wrap_fb) { 457+ weston_log("failed to get wrap fb\n"); 458+ goto err; 459+ } 460+ 461+ if (drm_copy_fb(fb, wrap_fb, rotation, sw, sh) < 0) { 462+ weston_log("failed to copy fb\n"); 463+ goto err; 464+ } 465+ 466+ sw = dw; 467+ sh = dh; 468+ 469+ drm_fb_unref(fb); 470+ fb = wrap_fb; 471+ } else { 472+ drm_output_try_destroy_wrap_fb(output); 473+ } 474+ 475 scanout_state->fb = fb; 476+ fb = NULL; 477+ 478 scanout_state->output = output; 479 480 scanout_state->src_x = 0; 481 scanout_state->src_y = 0; 482- scanout_state->src_w = fb->width << 16; 483- scanout_state->src_h = fb->height << 16; 484+ scanout_state->src_w = sw << 16; 485+ scanout_state->src_h = sh << 16; 486 487- mode = to_drm_mode(output->base.current_mode); 488- scanout_state->dest_x = 0; 489- scanout_state->dest_y = 0; 490- scanout_state->dest_w = mode->mode_info.hdisplay; 491- scanout_state->dest_h = mode->mode_info.vdisplay; 492+ scanout_state->dest_x = dx; 493+ scanout_state->dest_y = dy; 494+ scanout_state->dest_w = dw; 495+ scanout_state->dest_h = dh; 496+ 497+ if (output->is_mirror) 498+ return; 499 500 pixman_region32_subtract(&c->primary_plane.damage, 501 &c->primary_plane.damage, damage); 502@@ -499,6 +793,12 @@ drm_output_render(struct drm_output_state *state, pixman_region32_t *damage) 503 &scanout_state->damage_blob_id); 504 505 pixman_region32_fini(&scanout_damage); 506+ return; 507+err: 508+ if (fb) 509+ drm_fb_unref(fb); 510+ 511+ drm_plane_state_put_back(scanout_state); 512 } 513 514 static int 515@@ -1296,8 +1596,8 @@ drm_output_fini_pixman(struct drm_output *output) 516 /* Destroying the Pixman surface will destroy all our buffers, 517 * regardless of refcount. Ensure we destroy them here. */ 518 if (!b->shutting_down && 519- output->scanout_plane->state_cur->fb && 520- output->scanout_plane->state_cur->fb->type == BUFFER_PIXMAN_DUMB) { 521+ output->scanout_plane->state_cur->fb && (output->is_mirror || 522+ output->scanout_plane->state_cur->fb->type == BUFFER_PIXMAN_DUMB)) { 523 drm_plane_reset_state(output->scanout_plane); 524 } 525 526@@ -1975,6 +2275,8 @@ drm_output_destroy(struct weston_output *base) 527 assert(!output->state_last); 528 drm_output_state_free(output->state_cur); 529 530+ drm_output_try_destroy_wrap_fb(output); 531+ 532 free(output); 533 } 534 535@@ -3320,6 +3622,12 @@ drm_backend_create(struct weston_compositor *compositor, 536 else 537 b->resize_freeze_ms = DRM_RESIZE_FREEZE_MS; 538 539+ buf = getenv("WESTON_DRM_MIRROR"); 540+ if (buf && buf[0] == '1') { 541+ b->mirror_mode = true; 542+ weston_log("Entering mirror mode.\n"); 543+ } 544+ 545 b->state_invalid = true; 546 b->drm.fd = -1; 547 548diff --git a/libweston/backend-drm/meson.build b/libweston/backend-drm/meson.build 549index 23db912..6dbd05d 100644 550--- a/libweston/backend-drm/meson.build 551+++ b/libweston/backend-drm/meson.build 552@@ -38,7 +38,8 @@ deps_drm = [ 553 dep_libdrm, 554 dep_libinput_backend, 555 dependency('libudev', version: '>= 136'), 556- dep_backlight 557+ dep_backlight, 558+ dep_rga 559 ] 560 561 if get_option('renderer-gl') 562diff --git a/libweston/backend-drm/state-propose.c b/libweston/backend-drm/state-propose.c 563index 7b350aa..48e6de2 100644 564--- a/libweston/backend-drm/state-propose.c 565+++ b/libweston/backend-drm/state-propose.c 566@@ -54,6 +54,21 @@ static const char *const drm_output_propose_state_mode_as_string[] = { 567 [DRM_OUTPUT_PROPOSE_STATE_PLANES_ONLY] = "plane-only state" 568 }; 569 570+static bool 571+drm_is_mirroring(struct drm_backend *b) 572+{ 573+ struct drm_output *tmp; 574+ 575+ if (!b->mirror_mode) 576+ return false; 577+ 578+ wl_list_for_each(tmp, &b->compositor->output_list, base.link) 579+ if (tmp->is_mirror) 580+ return true; 581+ 582+ return false; 583+} 584+ 585 static const char * 586 drm_propose_state_mode_to_string(enum drm_output_propose_state_mode mode) 587 { 588@@ -466,7 +481,7 @@ drm_output_try_view_on_plane(struct drm_plane *plane, 589 590 switch (plane->type) { 591 case WDRM_PLANE_TYPE_CURSOR: 592- if (b->cursors_are_broken) { 593+ if (b->cursors_are_broken || drm_is_mirroring(b)) { 594 availability = NO_PLANES_ACCEPTED; 595 goto out; 596 } 597@@ -1102,7 +1117,10 @@ drm_assign_planes(struct weston_output *output_base, void *repaint_data) 598 drm_debug(b, "\t[repaint] preparing state for output %s (%lu)\n", 599 output_base->name, (unsigned long) output_base->id); 600 601- if (!b->sprites_are_broken && !output->virtual) { 602+ /* Force single plane in mirror mode */ 603+ if (drm_is_mirroring(b)) { 604+ drm_debug(b, "\t[state] no overlay plane in mirror mode\n"); 605+ } else if (!b->sprites_are_broken && !output->virtual) { 606 drm_debug(b, "\t[repaint] trying planes-only build state\n"); 607 state = drm_output_propose_state(output_base, pending_state, mode); 608 if (!state) { 609diff --git a/libweston/compositor.c b/libweston/compositor.c 610index 22a8593..7680445 100644 611--- a/libweston/compositor.c 612+++ b/libweston/compositor.c 613@@ -1407,7 +1407,7 @@ weston_view_assign_output(struct weston_view *ev) 614 mask = 0; 615 pixman_region32_init(®ion); 616 wl_list_for_each(output, &ec->output_list, link) { 617- if (output->destroying) 618+ if (!weston_output_valid(output)) 619 continue; 620 621 pixman_region32_intersect(®ion, &ev->transform.boundingbox, 622@@ -5249,6 +5249,9 @@ bind_output(struct wl_client *client, 623 static void 624 weston_head_add_global(struct weston_head *head) 625 { 626+ if (head->global || !weston_output_valid(head->output)) 627+ return; 628+ 629 head->global = wl_global_create(head->compositor->wl_display, 630 &wl_output_interface, 3, 631 head, bind_output); 632@@ -5284,6 +5287,15 @@ weston_head_remove_global(struct weston_head *head) 633 wl_list_init(&head->xdg_output_resource_list); 634 } 635 636+static void 637+weston_head_update_global(struct weston_head *head) 638+{ 639+ if (weston_output_valid(head->output)) 640+ weston_head_add_global(head); 641+ else 642+ weston_head_remove_global(head); 643+} 644+ 645 /** Get the backing object of wl_output 646 * 647 * \param resource A wl_output protocol object. 648@@ -6079,11 +6091,15 @@ WL_EXPORT void 649 weston_compositor_reflow_outputs(struct weston_compositor *compositor) 650 { 651 struct weston_output *output; 652+ struct weston_head *head; 653 int x, y, next_x, next_y; 654 655 next_x = next_y = 0; 656 wl_list_for_each(output, &compositor->output_list, link) { 657- if (output->destroying) 658+ wl_list_for_each(head, &output->head_list, output_link) 659+ weston_head_update_global(head); 660+ 661+ if (!weston_output_valid(output)) 662 continue; 663 664 x = next_x; 665@@ -6300,11 +6316,11 @@ weston_compositor_add_output(struct weston_compositor *compositor, 666 wl_list_insert(compositor->output_list.prev, &output->link); 667 output->enabled = true; 668 669+ wl_signal_emit(&compositor->output_created_signal, output); 670+ 671 wl_list_for_each(head, &output->head_list, output_link) 672 weston_head_add_global(head); 673 674- wl_signal_emit(&compositor->output_created_signal, output); 675- 676 /* 677 * Use view_list, as paint nodes have not been created for this 678 * output yet. Any existing view might touch this new output. 679diff --git a/libweston/input.c b/libweston/input.c 680index 6fb4bed..ec7e416 100644 681--- a/libweston/input.c 682+++ b/libweston/input.c 683@@ -1688,6 +1688,10 @@ weston_pointer_clamp(struct weston_pointer *pointer, wl_fixed_t *fx, wl_fixed_t 684 wl_list_for_each(output, &ec->output_list, link) { 685 if (pointer->seat->output && pointer->seat->output != output) 686 continue; 687+ 688+ if (output->unavailable) 689+ continue; 690+ 691 if (pixman_region32_contains_point(&output->region, 692 x, y, NULL)) 693 valid = 1; 694@@ -1757,6 +1761,9 @@ weston_pointer_handle_output_destroy(struct wl_listener *listener, void *data) 695 y = wl_fixed_to_int(pointer->y); 696 697 wl_list_for_each(output, &ec->output_list, link) { 698+ if (output->unavailable) 699+ continue; 700+ 701 if (pixman_region32_contains_point(&output->region, 702 x, y, NULL)) 703 return; 704diff --git a/meson.build b/meson.build 705index f5aa460..feecd45 100644 706--- a/meson.build 707+++ b/meson.build 708@@ -145,6 +145,11 @@ if get_option('deprecated-wl-shell') 709 config_h.set('HAVE_DEPRECATED_WL_SHELL', '1') 710 endif 711 712+dep_rga = dependency('librga', required: false) 713+if dep_rga.found() 714+ config_h.set('HAVE_RGA', '1') 715+endif 716+ 717 dep_wayland_server = dependency('wayland-server', version: '>= 1.18.0') 718 dep_wayland_client = dependency('wayland-client', version: '>= 1.18.0') 719 dep_pixman = dependency('pixman-1', version: '>= 0.25.2') 720-- 7212.20.1 722 723