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