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