1From 54619af12a927bbef47382587f977e8ca6062625 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 28/79] 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 | 3 + 13 libweston/backend-drm/drm.c | 203 ++++++++++++++++++++++++++- 14 libweston/backend-drm/kms.c | 3 + 15 libweston/compositor.c | 3 + 16 6 files changed, 216 insertions(+), 6 deletions(-) 17 18diff --git a/compositor/main.c b/compositor/main.c 19index 128016b..3824404 100644 20--- a/compositor/main.c 21+++ b/compositor/main.c 22@@ -2337,6 +2337,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 4cb29dd..a8b8f35 100644 34--- a/desktop-shell/shell.c 35+++ b/desktop-shell/shell.c 36@@ -4820,10 +4820,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@@ -4955,6 +4951,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 9d24017..67e6dd2 100644 59--- a/libweston/backend-drm/drm-internal.h 60+++ b/libweston/backend-drm/drm-internal.h 61@@ -354,6 +354,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 { 71diff --git a/libweston/backend-drm/drm.c b/libweston/backend-drm/drm.c 72index 53a3d49..e829d77 100644 73--- a/libweston/backend-drm/drm.c 74+++ b/libweston/backend-drm/drm.c 75@@ -210,8 +210,14 @@ drm_backend_update_outputs(struct drm_backend *b) 76 { 77 struct weston_output *base, *primary; 78 79- if (!b->primary_head) 80+ if (!b->primary_head) { 81+ if (!b->dummy_output->enabled) 82+ weston_output_enable(b->dummy_output); 83 return; 84+ } else { 85+ if (b->dummy_output->enabled) 86+ weston_output_disable(b->dummy_output); 87+ } 88 89 primary = b->primary_head->base.output; 90 91@@ -1245,7 +1251,7 @@ drm_output_find_special_plane(struct drm_backend *b, struct drm_output *output, 92 num_primary - 1 != output->crtc->pipe) 93 continue; 94 95- if (plane->type != type) 96+ if (!plane->plane_id || plane->type != type) 97 continue; 98 if (!drm_plane_is_available(plane, output)) 99 continue; 100@@ -2591,11 +2597,15 @@ drm_head_destroy(struct drm_head *head) 101 { 102 weston_head_release(&head->base); 103 104+ if (!head->connector.connector_id) 105+ goto out; 106+ 107 drm_connector_fini(&head->connector); 108 109 if (head->backlight) 110 backlight_destroy(head->backlight); 111 112+out: 113 free(head); 114 } 115 116@@ -2827,6 +2837,9 @@ drm_backend_update_connectors(struct drm_backend *b, struct udev_device *drm_dev 117 wl_list_for_each_safe(base, base_next, 118 &b->compositor->head_list, compositor_link) { 119 head = to_drm_head(base); 120+ if (!head->connector.connector_id) 121+ continue; 122+ 123 connector_id = head->connector.connector_id; 124 125 if (resources_has_connector(resources, connector_id)) 126@@ -2871,6 +2884,9 @@ drm_backend_update_connectors(struct drm_backend *b, struct udev_device *drm_dev 127 continue; 128 129 head = to_drm_head(base); 130+ if (!head->connector.connector_id) 131+ continue; 132+ 133 conn = head->connector.conn; 134 135 if (conn->connection != DRM_MODE_CONNECTED || 136@@ -2900,6 +2916,8 @@ drm_backend_update_connectors(struct drm_backend *b, struct udev_device *drm_dev 137 } 138 match_done: 139 140+ weston_head_set_connection_status(&b->dummy_head->base, 141+ !b->primary_head); 142 drm_backend_update_outputs(b); 143 144 weston_compositor_read_presentation_clock(b->compositor, &now); 145@@ -3072,6 +3090,8 @@ drm_destroy(struct weston_compositor *ec) 146 struct drm_crtc *crtc, *crtc_tmp; 147 struct drm_writeback *writeback, *writeback_tmp; 148 149+ weston_output_destroy(b->dummy_output); 150+ 151 udev_input_destroy(&b->input); 152 153 wl_event_source_remove(b->config_timer); 154@@ -3776,6 +3796,180 @@ config_timer_handler(void *data) 155 return 0; 156 } 157 158+static int 159+drm_dummy_output_start_repaint_loop(struct weston_output *output_base) 160+{ 161+ weston_output_finish_frame(output_base, NULL, 162+ WP_PRESENTATION_FEEDBACK_INVALID); 163+ 164+ return 0; 165+} 166+ 167+static int 168+drm_dummy_output_repaint(struct weston_output *output_base, 169+ pixman_region32_t *damage, 170+ void *repaint_data) 171+{ 172+ struct drm_backend *b = to_drm_backend(output_base->compositor); 173+ 174+ wl_signal_emit(&output_base->frame_signal, damage); 175+ 176+ if (b->use_pixman) 177+ return -1; 178+ 179+ /* Switch GL output context to avoid corruption */ 180+ output_base->compositor->renderer->repaint_output(output_base, damage); 181+ return -1; 182+} 183+ 184+static int 185+drm_dummy_output_enable(struct weston_output *output_base) 186+{ 187+ struct drm_backend *b = to_drm_backend(output_base->compositor); 188+ struct drm_output *output = to_drm_output(output_base); 189+ 190+ if (b->use_pixman) 191+ return 0; 192+ 193+ return drm_output_init_egl(output, b); 194+} 195+ 196+static int 197+drm_dummy_output_disable(struct weston_output *output_base) 198+{ 199+ struct drm_backend *b = to_drm_backend(output_base->compositor); 200+ struct drm_output *output = to_drm_output(output_base); 201+ 202+ if (!b->use_pixman) 203+ drm_output_fini_egl(output); 204+ 205+ return 0; 206+} 207+ 208+static void 209+drm_dummy_output_destroy(struct weston_output *output_base) 210+{ 211+ struct drm_output *output = to_drm_output(output_base); 212+ struct drm_plane *plane = output->scanout_plane; 213+ struct weston_mode *mode, *next; 214+ 215+ if (output->base.enabled) 216+ drm_dummy_output_disable(&output->base); 217+ 218+ wl_list_for_each_safe(mode, next, &output_base->mode_list, link) { 219+ wl_list_remove(&mode->link); 220+ free(mode); 221+ } 222+ 223+ drm_plane_state_free(plane->state_cur, true); 224+ weston_plane_release(&plane->base); 225+ wl_list_remove(&plane->link); 226+ weston_drm_format_array_fini(&plane->formats); 227+ free(plane); 228+ 229+ weston_output_release(output_base); 230+ free(output); 231+} 232+ 233+static struct weston_output * 234+drm_dummy_output_create(struct drm_backend *b) 235+{ 236+ struct drm_output *output; 237+ struct drm_plane *plane; 238+ struct weston_drm_format *fmt; 239+ 240+ output = zalloc(sizeof *output); 241+ if (!output) 242+ return NULL; 243+ 244+ weston_output_init(&output->base, b->compositor, "DUMMY"); 245+ 246+ output->base.enable = drm_dummy_output_enable; 247+ output->base.destroy = drm_dummy_output_destroy; 248+ output->base.disable = drm_dummy_output_disable; 249+ 250+ output->base.start_repaint_loop = drm_dummy_output_start_repaint_loop; 251+ output->base.repaint = drm_dummy_output_repaint; 252+ output->base.set_dpms = NULL; 253+ output->base.switch_mode = NULL; 254+ output->base.gamma_size = 0; 255+ output->base.set_gamma = NULL; 256+ output->base.unavailable = true; 257+ 258+ weston_compositor_add_pending_output(&output->base, b->compositor); 259+ 260+#ifdef BUILD_DRM_GBM 261+ output->gbm_bo_flags = GBM_BO_USE_LINEAR | GBM_BO_USE_RENDERING; 262+ output->gbm_format = DRM_FORMAT_XRGB8888; 263+#endif 264+ 265+ plane = zalloc(sizeof(*plane)); 266+ if (!plane) { 267+ weston_output_release(&output->base); 268+ free(output); 269+ return NULL; 270+ } 271+ 272+ plane->type = WDRM_PLANE_TYPE_PRIMARY; 273+ plane->backend = b; 274+ plane->state_cur = drm_plane_state_alloc(NULL, plane); 275+ plane->state_cur->complete = true; 276+ 277+ weston_drm_format_array_init(&plane->formats); 278+ fmt = weston_drm_format_array_add_format(&plane->formats, 279+ output->gbm_format); 280+ weston_drm_format_add_modifier(fmt, DRM_FORMAT_MOD_LINEAR); 281+ 282+ weston_plane_init(&plane->base, b->compositor, 0, 0); 283+ wl_list_insert(&b->plane_list, &plane->link); 284+ 285+ output->scanout_plane = plane; 286+ 287+ return &output->base; 288+} 289+ 290+static int drm_backend_init_dummy(struct drm_backend *b) 291+{ 292+ struct weston_mode *mode; 293+ 294+ b->dummy_output = drm_dummy_output_create(b); 295+ if (!b->dummy_output) 296+ return -1; 297+ 298+ mode = zalloc(sizeof *mode); 299+ if (!mode) 300+ goto err; 301+ 302+ mode->flags = WL_OUTPUT_MODE_CURRENT; 303+ mode->width = 1920; 304+ mode->height = 1080; 305+ mode->refresh = 60 * 1000LL; 306+ 307+ wl_list_insert(b->dummy_output->mode_list.prev, &mode->link); 308+ 309+ b->dummy_output->current_mode = mode; 310+ 311+ weston_output_set_scale(b->dummy_output, 1); 312+ weston_output_set_transform(b->dummy_output, 313+ WL_OUTPUT_TRANSFORM_NORMAL); 314+ 315+ b->dummy_head = zalloc(sizeof *b->dummy_head); 316+ if (!b->dummy_head) 317+ goto err; 318+ 319+ weston_head_init(&b->dummy_head->base, "DUMMY"); 320+ weston_head_set_monitor_strings(&b->dummy_head->base, 321+ "DUMMY", "DUMMY", "DUMMY"); 322+ weston_compositor_add_head(b->compositor, &b->dummy_head->base); 323+ weston_output_attach_head(b->dummy_output, &b->dummy_head->base); 324+ 325+ return 0; 326+err: 327+ drm_dummy_output_destroy(b->dummy_output); 328+ b->dummy_output = NULL; 329+ return -1; 330+} 331+ 332 enum drm_head_mode { 333 DRM_HEAD_MODE_DEFAULT, 334 DRM_HEAD_MODE_PRIMARY, 335@@ -4007,6 +4201,11 @@ drm_backend_create(struct weston_compositor *compositor, 336 goto err_sprite; 337 } 338 339+ if (drm_backend_init_dummy(b) < 0) { 340+ weston_log("Failed to init dummy output\n"); 341+ goto err_udev_input; 342+ } 343+ 344 wl_list_init(&b->writeback_connector_list); 345 if (drm_backend_update_connectors(b, drm_device) < 0) { 346 weston_log("Failed to create heads for %s\n", b->drm.filename); 347diff --git a/libweston/backend-drm/kms.c b/libweston/backend-drm/kms.c 348index 4b5ba42..a3c55bd 100644 349--- a/libweston/backend-drm/kms.c 350+++ b/libweston/backend-drm/kms.c 351@@ -1170,6 +1170,9 @@ drm_pending_state_apply_atomic(struct drm_pending_state *pending_state, 352 continue; 353 354 head = to_drm_head(head_base); 355+ if (head == b->dummy_head) 356+ continue; 357+ 358 connector_id = head->connector.connector_id; 359 360 drm_debug(b, "\t\t[atomic] disabling inactive head %s\n", 361diff --git a/libweston/compositor.c b/libweston/compositor.c 362index 121871c..67766df 100644 363--- a/libweston/compositor.c 364+++ b/libweston/compositor.c 365@@ -6436,6 +6436,9 @@ weston_output_set_color_transforms(struct weston_output *output) 366 struct weston_color_transform *sRGB_to_blend = NULL; 367 bool ok; 368 369+ if (!cm) 370+ return false; 371+ 372 ok = cm->get_output_color_transform(cm, output, &blend_to_output); 373 ok = ok && cm->get_sRGB_to_output_color_transform(cm, output, 374 &sRGB_to_output); 375-- 3762.20.1 377 378