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