1From b65972a63cf04dd9a4cf0bc992fde885d9543ec7 Mon Sep 17 00:00:00 2001 2From: Jeffy Chen <jeffy.chen@rock-chips.com> 3Date: Thu, 12 Nov 2020 16:59:50 +0800 4Subject: [PATCH 31/93] backend-drm: Add dummy output when no screens connected 5 6Some clients are not expecting no screens, add a dummy output for them. 7 8Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> 9--- 10 compositor/main.c | 3 + 11 desktop-shell/shell.c | 7 +- 12 libweston/backend-drm/drm-internal.h | 6 + 13 libweston/backend-drm/drm.c | 210 ++++++++++++++++++++++++++- 14 libweston/backend-drm/kms.c | 2 +- 15 libweston/compositor.c | 3 + 16 6 files changed, 224 insertions(+), 7 deletions(-) 17 18diff --git a/compositor/main.c b/compositor/main.c 19index 987c8f9..f151a77 100644 20--- a/compositor/main.c 21+++ b/compositor/main.c 22@@ -2595,6 +2595,9 @@ drm_heads_changed(struct wl_listener *listener, void *arg) 23 * output. 24 */ 25 while ((head = weston_compositor_iterate_heads(compositor, head))) { 26+ if (!strcasecmp(weston_head_get_name(head), "dummy")) 27+ continue; 28+ 29 drm_head_update_output_section(head); 30 31 connected = weston_head_is_connected(head); 32diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c 33index 463c64e..e48db31 100644 34--- a/desktop-shell/shell.c 35+++ b/desktop-shell/shell.c 36@@ -4317,10 +4317,6 @@ shell_reposition_view_on_output_change(struct weston_view *view) 37 shsurf = get_shell_surface(view->surface); 38 if (!shsurf) 39 return; 40- 41- shsurf->saved_position_valid = false; 42- set_maximized(shsurf, false); 43- set_fullscreen(shsurf, false, NULL); 44 } 45 46 void 47@@ -4447,6 +4443,9 @@ handle_output_resized(struct wl_listener *listener, void *data) 48 struct weston_output *output = (struct weston_output *)data; 49 struct shell_output *sh_output = find_shell_output_from_weston_output(shell, output); 50 51+ if (!sh_output) 52+ return; 53+ 54 if (shell->lock_surface) 55 shell->lock_surface->committed(shell->lock_surface, 0, 0); 56 57diff --git a/libweston/backend-drm/drm-internal.h b/libweston/backend-drm/drm-internal.h 58index 532593e..e175f16 100644 59--- a/libweston/backend-drm/drm-internal.h 60+++ b/libweston/backend-drm/drm-internal.h 61@@ -370,6 +370,9 @@ struct drm_backend { 62 63 struct wl_event_source *config_timer; 64 struct stat config_stat; 65+ 66+ struct weston_output *dummy_output; 67+ struct drm_head *dummy_head; 68 }; 69 70 struct drm_mode { 71@@ -667,6 +670,8 @@ void 72 drm_output_destroy(struct weston_output *output_base); 73 void 74 drm_virtual_output_destroy(struct weston_output *output_base); 75+void 76+drm_dummy_output_destroy(struct weston_output *output_base); 77 78 static inline struct drm_output * 79 to_drm_output(struct weston_output *base) 80@@ -675,6 +680,7 @@ to_drm_output(struct weston_output *base) 81 #ifdef BUILD_DRM_VIRTUAL 82 base->destroy != drm_virtual_output_destroy && 83 #endif 84+ base->destroy != drm_dummy_output_destroy && 85 base->destroy != drm_output_destroy) 86 return NULL; 87 return container_of(base, struct drm_output, base); 88diff --git a/libweston/backend-drm/drm.c b/libweston/backend-drm/drm.c 89index a7c57f7..2b3e90b 100644 90--- a/libweston/backend-drm/drm.c 91+++ b/libweston/backend-drm/drm.c 92@@ -211,8 +211,14 @@ drm_backend_update_outputs(struct drm_backend *b) 93 { 94 struct weston_output *primary; 95 96- if (!b->primary_head) 97+ if (!b->primary_head) { 98+ if (!b->dummy_output->enabled) 99+ weston_output_enable(b->dummy_output); 100 return; 101+ } else { 102+ if (b->dummy_output->enabled) 103+ weston_output_disable(b->dummy_output); 104+ } 105 106 primary = b->primary_head->base.output; 107 108@@ -1268,6 +1274,10 @@ drm_output_find_special_plane(struct drm_device *device, 109 struct weston_output *base; 110 bool found_elsewhere = false; 111 112+ /* Ignore non-real planes */ 113+ if (!plane->plane_id) 114+ continue; 115+ 116 if (plane->type != type) 117 continue; 118 if (!drm_plane_is_available(plane, output)) 119@@ -2703,11 +2713,15 @@ drm_head_destroy(struct weston_head *base) 120 121 weston_head_release(&head->base); 122 123+ if (!head->connector.connector_id) 124+ goto out; 125+ 126 drm_connector_fini(&head->connector); 127 128 if (head->backlight) 129 backlight_destroy(head->backlight); 130 131+out: 132 free(head); 133 } 134 135@@ -2944,8 +2958,9 @@ drm_backend_update_connectors(struct drm_device *device, 136 wl_list_for_each_safe(base, base_next, 137 &b->compositor->head_list, compositor_link) { 138 head = to_drm_head(base); 139- if (!head) 140+ if (!head || !head->connector.connector_id) 141 continue; 142+ 143 connector_id = head->connector.connector_id; 144 145 if (head->connector.device != device) 146@@ -2993,6 +3008,9 @@ drm_backend_update_connectors(struct drm_device *device, 147 continue; 148 149 head = to_drm_head(base); 150+ if (!head || !head->connector.connector_id) 151+ continue; 152+ 153 conn = head->connector.conn; 154 155 if (conn->connection != DRM_MODE_CONNECTED || 156@@ -3022,6 +3040,8 @@ drm_backend_update_connectors(struct drm_device *device, 157 } 158 match_done: 159 160+ weston_head_set_connection_status(&b->dummy_head->base, 161+ !b->primary_head); 162 drm_backend_update_outputs(b); 163 164 weston_compositor_read_presentation_clock(b->compositor, &now); 165@@ -3197,6 +3217,11 @@ drm_destroy(struct weston_compositor *ec) 166 struct drm_crtc *crtc, *crtc_tmp; 167 struct drm_writeback *writeback, *writeback_tmp; 168 169+ weston_output_destroy(b->dummy_output); 170+ 171+ if (b->dummy_head) 172+ drm_head_destroy(&b->dummy_head->base); 173+ 174 udev_input_destroy(&b->input); 175 176 wl_event_source_remove(b->config_timer); 177@@ -3903,6 +3928,182 @@ config_timer_handler(void *data) 178 return 0; 179 } 180 181+static int 182+drm_dummy_output_start_repaint_loop(struct weston_output *output_base) 183+{ 184+ weston_output_finish_frame(output_base, NULL, 185+ WP_PRESENTATION_FEEDBACK_INVALID); 186+ 187+ return 0; 188+} 189+ 190+static int 191+drm_dummy_output_repaint(struct weston_output *output_base, 192+ pixman_region32_t *damage) 193+{ 194+ struct drm_backend *b = to_drm_backend(output_base->compositor); 195+ 196+ wl_signal_emit(&output_base->frame_signal, damage); 197+ 198+ if (b->use_pixman) 199+ return -1; 200+ 201+ /* Switch GL output context to avoid corruption */ 202+ output_base->compositor->renderer->repaint_output(output_base, damage); 203+ return -1; 204+} 205+ 206+static int 207+drm_dummy_output_enable(struct weston_output *output_base) 208+{ 209+ struct drm_backend *b = to_drm_backend(output_base->compositor); 210+ struct drm_output *output = to_drm_output(output_base); 211+ 212+ if (b->use_pixman) 213+ return 0; 214+ 215+ return drm_output_init_egl(output, b); 216+} 217+ 218+static int 219+drm_dummy_output_disable(struct weston_output *output_base) 220+{ 221+ struct drm_backend *b = to_drm_backend(output_base->compositor); 222+ struct drm_output *output = to_drm_output(output_base); 223+ 224+ if (!b->use_pixman) 225+ drm_output_fini_egl(output); 226+ 227+ return 0; 228+} 229+ 230+void 231+drm_dummy_output_destroy(struct weston_output *output_base) 232+{ 233+ struct drm_output *output = to_drm_output(output_base); 234+ struct drm_plane *plane = output->scanout_plane; 235+ struct weston_mode *mode, *next; 236+ 237+ if (output->base.enabled) 238+ drm_dummy_output_disable(&output->base); 239+ 240+ wl_list_for_each_safe(mode, next, &output_base->mode_list, link) { 241+ wl_list_remove(&mode->link); 242+ free(mode); 243+ } 244+ 245+ drm_plane_state_free(plane->state_cur, true); 246+ weston_plane_release(&plane->base); 247+ wl_list_remove(&plane->link); 248+ weston_drm_format_array_fini(&plane->formats); 249+ free(plane); 250+ 251+ weston_output_release(output_base); 252+ free(output); 253+} 254+ 255+static struct weston_output * 256+drm_dummy_output_create(struct drm_device *device) 257+{ 258+ struct drm_backend *b = device->backend; 259+ struct drm_output *output; 260+ struct drm_plane *plane; 261+ struct weston_drm_format *fmt; 262+ 263+ output = zalloc(sizeof *output); 264+ if (!output) 265+ return NULL; 266+ 267+ output->device = device; 268+ output->crtc = NULL; 269+ 270+#ifdef BUILD_DRM_GBM 271+ output->gbm_bo_flags = GBM_BO_USE_LINEAR | GBM_BO_USE_RENDERING; 272+ output->gbm_format = DRM_FORMAT_XRGB8888; 273+#endif 274+ 275+ weston_output_init(&output->base, b->compositor, "DUMMY"); 276+ 277+ output->base.enable = drm_dummy_output_enable; 278+ output->base.destroy = drm_dummy_output_destroy; 279+ output->base.disable = drm_dummy_output_disable; 280+ 281+ output->base.start_repaint_loop = drm_dummy_output_start_repaint_loop; 282+ output->base.repaint = drm_dummy_output_repaint; 283+ output->base.unavailable = true; 284+ 285+ weston_compositor_add_pending_output(&output->base, b->compositor); 286+ 287+ plane = zalloc(sizeof(*plane)); 288+ if (!plane) { 289+ weston_output_release(&output->base); 290+ free(output); 291+ return NULL; 292+ } 293+ 294+ plane->type = WDRM_PLANE_TYPE_PRIMARY; 295+ plane->device = device; 296+ plane->state_cur = drm_plane_state_alloc(NULL, plane); 297+ plane->state_cur->complete = true; 298+ 299+ weston_drm_format_array_init(&plane->formats); 300+ fmt = weston_drm_format_array_add_format(&plane->formats, 301+ output->gbm_format); 302+ weston_drm_format_add_modifier(fmt, DRM_FORMAT_MOD_LINEAR); 303+ 304+ weston_plane_init(&plane->base, b->compositor, 0, 0); 305+ wl_list_insert(&device->plane_list, &plane->link); 306+ 307+ output->scanout_plane = plane; 308+ 309+ return &output->base; 310+} 311+ 312+static int drm_backend_init_dummy(struct drm_backend *b) 313+{ 314+ struct weston_mode *mode; 315+ 316+ b->dummy_output = drm_dummy_output_create(b->drm); 317+ if (!b->dummy_output) 318+ return -1; 319+ 320+ mode = zalloc(sizeof *mode); 321+ if (!mode) 322+ goto err; 323+ 324+ mode->flags = WL_OUTPUT_MODE_CURRENT; 325+ mode->width = 1920; 326+ mode->height = 1080; 327+ mode->refresh = 60 * 1000LL; 328+ 329+ wl_list_insert(b->dummy_output->mode_list.prev, &mode->link); 330+ 331+ b->dummy_output->current_mode = mode; 332+ 333+ weston_output_set_scale(b->dummy_output, 1); 334+ weston_output_set_transform(b->dummy_output, 335+ WL_OUTPUT_TRANSFORM_NORMAL); 336+ 337+ b->dummy_head = zalloc(sizeof *b->dummy_head); 338+ if (!b->dummy_head) 339+ goto err; 340+ 341+ weston_head_init(&b->dummy_head->base, "DUMMY"); 342+ 343+ b->dummy_head->base.backend_id = drm_head_destroy; 344+ 345+ weston_head_set_monitor_strings(&b->dummy_head->base, 346+ "DUMMY", "DUMMY", "DUMMY"); 347+ weston_compositor_add_head(b->compositor, &b->dummy_head->base); 348+ weston_output_attach_head(b->dummy_output, &b->dummy_head->base); 349+ 350+ return 0; 351+err: 352+ drm_dummy_output_destroy(b->dummy_output); 353+ b->dummy_output = NULL; 354+ return -1; 355+} 356+ 357 enum drm_head_mode { 358 DRM_HEAD_MODE_DEFAULT, 359 DRM_HEAD_MODE_PRIMARY, 360@@ -4140,6 +4341,11 @@ drm_backend_create(struct weston_compositor *compositor, 361 goto err_sprite; 362 } 363 364+ if (drm_backend_init_dummy(b) < 0) { 365+ weston_log("Failed to init dummy output\n"); 366+ goto err_udev_input; 367+ } 368+ 369 wl_list_init(&b->drm->writeback_connector_list); 370 if (drm_backend_update_connectors(b->drm, drm_device) < 0) { 371 weston_log("Failed to create heads for %s\n", b->drm->drm.filename); 372diff --git a/libweston/backend-drm/kms.c b/libweston/backend-drm/kms.c 373index 0008e83..fb43c43 100644 374--- a/libweston/backend-drm/kms.c 375+++ b/libweston/backend-drm/kms.c 376@@ -1196,7 +1196,7 @@ drm_pending_state_apply_atomic(struct drm_pending_state *pending_state, 377 &b->compositor->head_list, compositor_link) { 378 struct drm_property_info *info; 379 head = to_drm_head(head_base); 380- if (!head) 381+ if (!head || head == b->dummy_head) 382 continue; 383 384 if (weston_head_is_enabled(head_base)) 385diff --git a/libweston/compositor.c b/libweston/compositor.c 386index 8ca0c27..fa211bd 100644 387--- a/libweston/compositor.c 388+++ b/libweston/compositor.c 389@@ -6932,6 +6932,9 @@ weston_output_set_color_outcome(struct weston_output *output) 390 struct weston_color_manager *cm = output->compositor->color_manager; 391 struct weston_output_color_outcome *colorout; 392 393+ if (!cm) 394+ return false; 395+ 396 colorout = cm->create_output_color_outcome(cm, output); 397 if (!colorout) { 398 weston_log("Creating color transformation for output \"%s\" failed.\n", 399-- 4002.20.1 401 402