[PATCH v14 10/41] compositor-drm: Disable unused CRTCs/connectors

Daniel Stone daniels at collabora.com
Wed Dec 20 12:26:27 UTC 2017


If we have an unused CRTC or connector, explicitly disable it during the
end of the repaint cycle, or when we get VT-switched back in.

This commit moves state_invalid from an output property to a backend
property, as the unused CRTCs or connectors are likely not tracked by
drm_outputs. This matches the mechanics of later commits, where we move
to a global repaint-flush hook, applying the state for all outputs in
one go.

Signed-off-by: Daniel Stone <daniels at collabora.com>
---
 libweston/compositor-drm.c | 35 +++++++++++++++++++++--------------
 1 file changed, 21 insertions(+), 14 deletions(-)

diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c
index 9c7564383..87c2603c7 100644
--- a/libweston/compositor-drm.c
+++ b/libweston/compositor-drm.c
@@ -188,6 +188,7 @@ struct drm_backend {
 
 	void *repaint_data;
 
+	bool state_invalid;
 	struct wl_array unused_connectors;
 	struct wl_array unused_crtcs;
 
@@ -350,8 +351,6 @@ struct drm_output {
 	enum dpms_enum dpms;
 	struct backlight *backlight;
 
-	bool state_invalid;
-
 	int vblank_pending;
 	int page_flip_pending;
 	int destroy_pending;
@@ -1748,7 +1747,7 @@ drm_output_repaint(struct weston_output *output_base,
 	assert(scanout_state->dest_h == scanout_state->src_h >> 16);
 
 	mode = container_of(output->base.current_mode, struct drm_mode, base);
-	if (output->state_invalid || !scanout_plane->state_cur->fb ||
+	if (backend->state_invalid || !scanout_plane->state_cur->fb ||
 	    scanout_plane->state_cur->fb->stride != scanout_state->fb->stride) {
 		ret = drmModeSetCrtc(backend->drm.fd, output->crtc_id,
 				     scanout_state->fb->fb_id,
@@ -1760,9 +1759,7 @@ drm_output_repaint(struct weston_output *output_base,
 			goto err;
 		}
 		output_base->set_dpms(output_base, WESTON_DPMS_ON);
-
-		output->state_invalid = false;
-	}
+        }
 
 	if (drmModePageFlip(backend->drm.fd, output->crtc_id,
 			    scanout_state->fb->fb_id,
@@ -1869,7 +1866,7 @@ drm_output_start_repaint_loop(struct weston_output *output_base)
 	/* Need to smash all state in from scratch; current timings might not
 	 * be what we want, page flip might not work, etc.
 	 */
-	if (output->state_invalid)
+	if (backend->state_invalid)
 		goto finish_frame;
 
 	assert(scanout_plane->state_cur->output == output);
@@ -2033,12 +2030,26 @@ drm_repaint_flush(struct weston_compositor *compositor, void *repaint_data)
 	struct drm_backend *b = to_drm_backend(compositor);
 	struct drm_pending_state *pending_state = repaint_data;
 	struct drm_output_state *output_state, *tmp;
+	uint32_t *unused;
+
+	if (b->state_invalid) {
+		/* If we need to reset all our state (e.g. because we've
+		 * just started, or just been VT-switched in), explicitly
+		 * disable all the CRTCs we aren't using. This also disables
+		 * all connectors on these CRTCs, so we don't need to do that
+		 * separately with the pre-atomic API. */
+		wl_array_for_each(unused, &b->unused_crtcs)
+			drmModeSetCrtc(b->drm.fd, *unused, 0, 0, 0, NULL, 0,
+				       NULL);
+	}
 
 	wl_list_for_each_safe(output_state, tmp, &pending_state->output_list,
 			      link) {
 		drm_output_assign_state(output_state, DRM_STATE_APPLY_ASYNC);
 	}
 
+	b->state_invalid = false;
+
 	drm_pending_state_free(pending_state);
 	b->repaint_data = NULL;
 }
@@ -2659,7 +2670,7 @@ drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mo
 	 *      sledgehammer modeswitch first, and only later showing new
 	 *      content.
 	 */
-	output->state_invalid = true;
+	b->state_invalid = true;
 
 	if (b->use_pixman) {
 		drm_output_fini_pixman(output);
@@ -4000,8 +4011,6 @@ drm_output_enable(struct weston_output *base)
 				    output->connector->count_modes == 0 ?
 				    ", built-in" : "");
 
-	output->state_invalid = true;
-
 	return 0;
 
 err:
@@ -4516,10 +4525,7 @@ session_notify(struct wl_listener *listener, void *data)
 		weston_log("activating session\n");
 		weston_compositor_wake(compositor);
 		weston_compositor_damage_all(compositor);
-
-		wl_list_for_each(output, &compositor->output_list, base.link)
-			output->state_invalid = true;
-
+		b->state_invalid = true;
 		udev_input_enable(&b->input);
 	} else {
 		weston_log("deactivating session\n");
@@ -4931,6 +4937,7 @@ drm_backend_create(struct weston_compositor *compositor,
 	if (b == NULL)
 		return NULL;
 
+	b->state_invalid = true;
 	b->drm.fd = -1;
 	wl_array_init(&b->unused_crtcs);
 	wl_array_init(&b->unused_connectors);
-- 
2.14.3



More information about the wayland-devel mailing list