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

Pekka Paalanen ppaalanen at gmail.com
Wed Jan 17 10:43:01 UTC 2018


On Wed, 20 Dec 2017 12:26:27 +0000
Daniel Stone <daniels at collabora.com> wrote:

> 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.

Hi Daniel,

I have a recollection of having a rationale that the state_invalid flag
should stay per-output, but it seems those ideas were just optimization
that's probably moot anyway. I suppose with atomic, the per-output flag
would not make any difference to a global flag, since the atomic commit
would be modeset-or-not as a whole?

I wonder, could the following happen:
- have outputs A and B at different timing phase such that they usually
  don't coalesce to the same atomic update
- output A needs a modeset
- output B repaints first, does modeset, and clears the flag
- output A does not get a modeset

Would we actually need per-output flags and a flag for the unused CRTCs?

Clone mode will bring new causes for "needs a modeset": attaching or
detaching a head from a running output.

If we were good with just a global flag, then this patch would be good.


Thanks,
pq


> 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);

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <https://lists.freedesktop.org/archives/wayland-devel/attachments/20180117/b6ad00b6/attachment.sig>


More information about the wayland-devel mailing list