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