Re: [PATCH 1/2] drm: Fix dirtyfb stalls

Daniel Vetter
2021-05-10T16:15:01Z

On Sat, May 08, 2021 at 12:56:38PM -0700, Rob Clark wrote:
> From: Rob Clark <robdclark@chromium.org>
>
> drm_atomic_helper_dirtyfb() will end up stalling for vblank on "video
> mode" type displays, which is pointless and unnecessary. Add an
> optional helper vfunc to determine if a plane is attached to a CRTC
> that actually needs dirtyfb, and skip over them.
>
> Signed-off-by: Rob Clark <robdclark@chromium.org>

So this is a bit annoying because the idea of all these "remap legacy uapi
to atomic constructs" helpers is that they shouldn't need/use anything
beyond what userspace also has available. So adding hacks for them feels
really bad.

Also I feel like it's not entirely the right thing to do here either.
We've had this problem already on the fbcon emulation side (which also
shouldn't be able to peek behind the atomic kms uapi curtain), and the fix
there was to have a worker which batches up all the updates and avoids any
stalls in bad places.

Since this is for frontbuffer rendering userspace only we can probably get
away with assuming there's only a single fb, so the implementation becomes
pretty simple:

- 1 worker, and we keep track of a single pending fb
- if there's already a dirty fb pending on a different fb, we stall for
the worker to start processing that one already (i.e. the fb we track is
reset to NULL)
- if it's pending on the same fb we just toss away all the updates and go
with a full update, since merging the clip rects is too much work :-) I
think there's helpers so you could be slightly more clever and just have
an overall bounding box

Could probably steal most of the implementation.

This approach here feels a tad too much in the hacky area ...

Thoughts?
-Daniel

> ---
> drivers/gpu/drm/drm_damage_helper.c | 8 ++++++++
> include/drm/drm_modeset_helper_vtables.h | 14 ++++++++++++++
> 2 files changed, 22 insertions(+)
>
> diff --git a/drivers/gpu/drm/drm_damage_helper.c b/drivers/gpu/drm/drm_damage_helper.c
> index 3a4126dc2520..a0bed1a2c2dc 100644
> --- a/drivers/gpu/drm/drm_damage_helper.c
> +++ b/drivers/gpu/drm/drm_damage_helper.c
> @@ -211,6 +211,7 @@ int drm_atomic_helper_dirtyfb(struct drm_framebuffer *fb,
> retry:
> drm_for_each_plane(plane, fb->dev) {
> struct drm_plane_state *plane_state;
> + struct drm_crtc *crtc;
>
> ret = drm_modeset_lock(&plane->mutex, state->acquire_ctx);
> if (ret)
> @@ -221,6 +222,13 @@ int drm_atomic_helper_dirtyfb(struct drm_framebuffer *fb,
> continue;
> }
>
> + crtc = plane->state->crtc;
> + if (crtc->helper_private->needs_dirtyfb &&
> + !crtc->helper_private->needs_dirtyfb(crtc)) {
> + drm_modeset_unlock(&plane->mutex);
> + continue;
> + }
> +
> plane_state = drm_atomic_get_plane_state(state, plane);
> if (IS_ERR(plane_state)) {
> ret = PTR_ERR(plane_state);
> diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
> index eb706342861d..afa8ec5754e7 100644
> --- a/include/drm/drm_modeset_helper_vtables.h
> +++ b/include/drm/drm_modeset_helper_vtables.h
> @@ -487,6 +487,20 @@ struct drm_crtc_helper_funcs {
> bool in_vblank_irq, int *vpos, int *hpos,
> ktime_t *stime, ktime_t *etime,
> const struct drm_display_mode *mode);
> +
> + /**
> + * @needs_dirtyfb
> + *
> + * Optional callback used by damage helpers to determine if fb_damage_clips
> + * update is needed.
> + *
> + * Returns:
> + *
> + * True if fb_damage_clips update is needed to handle DIRTYFB, False
> + * otherwise. If this callback is not implemented, then True is
> + * assumed.
> + */
> + bool (*needs_dirtyfb)(struct drm_crtc *crtc);
> };
>
> /**
> --
> 2.30.2
>

--
Daniel Vetter
Software Engineer, Intel Corporation