On Sat, 30 May 2026 17:14:44 +0000
Simon Ser <[email protected]> wrote:

> Currently user-space can only request page-flip events for all CRTCs included
> in an atomic commit. This is cumbersome with multi-CRTC commits: when moving a
> plane from a different CRTC, or when disabling a plane, user-space has no way
> to opt-out of the page-flip events.
> 
> Additionally, page-flip events are invalid for already-disable planes, so

Hi Simon,

do you mean CRTCs? I find "already disabled" to be not really clear
that you mean off->off transition.

> user-space needs to add special cases [1]. Libraries cannot add planes to the
> commit without risking causing unexpected page-flip events for the
> compositor [2].

If a library adds a plane that is currently associated with another
CRTC, would it not be a logic error in userspace if it didn't expect
that CRTC to be involved? Mostly likely if it succeeds, the plane
would disappear from its old CRTC unintended.

If a CRTC is unexpectedly involved, userspace risks EBUSY when it wants
to update that CRTC for real.

> Figuring out what CRTCs get implicitly included in a commit is
> non-trivial [3].

Yes, but is this actually helpful rather than making the failures more
rare and harder to debug?

> Introduce a new PAGE_FLIP_EVENT CRTC property so that user-space can select
> explicitly which CRTCs will get page-flip events. The property is very
> similar to IN_FENCE_FD/OUT_FENCE_PTR: it always reads as zero, and 1 can
> be written to request an event.
> 
> A user-space implementation is available at [4].
> 
> [1]: 
> https://github.com/ValveSoftware/gamescope/blob/67fcb3aebae0ae1eb2d1cff60f29e6d9fe1d128f/src/Backends/DRMBackend.cpp#L2897
> [2]: https://gitlab.freedesktop.org/emersion/libliftoff/-/merge_requests/85
> [3]: 
> https://lore.kernel.org/dri-devel/[email protected]/
> [4]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5387
> 
> Signed-off-by: Simon Ser <[email protected]>
> Cc: Daniel Stone <[email protected]>
> Cc: Michel Dänzer <[email protected]>
> Cc: Pekka Paalanen <[email protected]>
> Cc: Christian König <[email protected]>
> Cc: Simona Vetter <[email protected]>
> ---
>  drivers/gpu/drm/drm_atomic_uapi.c | 17 +++++++++++++++--
>  drivers/gpu/drm/drm_crtc.c        |  7 +++++++
>  drivers/gpu/drm/drm_mode_config.c |  6 ++++++
>  include/drm/drm_crtc.h            |  6 ++++++
>  include/drm/drm_mode_config.h     |  4 ++++
>  5 files changed, 38 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_atomic_uapi.c 
> b/drivers/gpu/drm/drm_atomic_uapi.c
> index 6441b55cc274..21f2b0df4f63 100644
> --- a/drivers/gpu/drm/drm_atomic_uapi.c
> +++ b/drivers/gpu/drm/drm_atomic_uapi.c
> @@ -466,6 +466,14 @@ static int drm_atomic_crtc_set_property(struct drm_crtc 
> *crtc,
>                       return -EFAULT;
>  
>               set_out_fence_for_crtc(state->state, crtc, fence_ptr);
> +     } else if (property == config->prop_page_flip_event) {
> +             if (val != 1) {
> +                     drm_dbg_atomic(crtc->dev,
> +                                    "[CRTC:%d:%s] PAGE_FLIP_EVENT can only 
> be set to 1",
> +                                    crtc->base.id, crtc->name);
> +                     return -EINVAL;
> +             }
> +             state->page_flip_event_requested = val;
>       } else if (property == crtc->scaling_filter_property) {
>               state->scaling_filter = val;
>       } else if (property == crtc->sharpness_strength_property) {
> @@ -507,6 +515,8 @@ drm_atomic_crtc_get_property(struct drm_crtc *crtc,
>               *val = state->background_color;
>       else if (property == config->prop_out_fence_ptr)
>               *val = 0;
> +     else if (property == config->prop_page_flip_event)
> +             *val = 0;
>       else if (property == crtc->scaling_filter_property)
>               *val = state->scaling_filter;
>       else if (property == crtc->sharpness_strength_property)
> @@ -1385,6 +1395,7 @@ static int prepare_signaling(struct drm_device *dev,
>       struct drm_connector *conn;
>       struct drm_connector_state *conn_state;
>       int i, c = 0, ret;
> +     bool page_flip_event_requested;
>  
>       if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY)
>               return 0;
> @@ -1392,9 +1403,11 @@ static int prepare_signaling(struct drm_device *dev,
>       for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
>               s32 __user *fence_ptr;
>  
> +             page_flip_event_requested = arg->flags & 
> DRM_MODE_PAGE_FLIP_EVENT ||
> +                                         
> crtc_state->page_flip_event_requested;
>               fence_ptr = get_out_fence_for_crtc(crtc_state->state, crtc);
>  
> -             if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT || fence_ptr) {
> +             if (page_flip_event_requested || fence_ptr) {
>                       struct drm_pending_vblank_event *e;
>  
>                       e = create_vblank_event(crtc, arg->user_data);
> @@ -1404,7 +1417,7 @@ static int prepare_signaling(struct drm_device *dev,
>                       crtc_state->event = e;
>               }
>  
> -             if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
> +             if (page_flip_event_requested) {
>                       struct drm_pending_vblank_event *e = crtc_state->event;
>  
>                       if (!file_priv)
> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> index 63ead8ba6756..5ad6681bd47c 100644
> --- a/drivers/gpu/drm/drm_crtc.c
> +++ b/drivers/gpu/drm/drm_crtc.c
> @@ -248,6 +248,11 @@ struct dma_fence *drm_crtc_create_fence(struct drm_crtc 
> *crtc)
>   *   The sharpness effect takes place post blending on the final composed 
> output.
>   *   If the feature is disabled, the content remains same without any 
> sharpening effect
>   *   and when this feature is applied, it enhances the clarity of the 
> content.
> + * PAGE_FLIP_EVENT:
> + *   Atomic property for requesting a page-flip event on this CRTC.
> + *
> + *   The value of this property is an integer value which always reads as
> + *   zero and can be written with 1 to request the event.

It took me a while to realise; should probably explain here that if one
uses this, then they would not use DRM_MODE_PAGE_FLIP_EVENT at the same
time.

Does this allow asking for an event for a CRTC off->off
transition?


Thanks,
pq

>   */
>  
>  __printf(6, 0)
> @@ -322,6 +327,8 @@ static int __drm_crtc_init_with_planes(struct drm_device 
> *dev, struct drm_crtc *
>                                          config->prop_out_fence_ptr, 0);
>               drm_object_attach_property(&crtc->base,
>                                          config->prop_vrr_enabled, 0);
> +             drm_object_attach_property(&crtc->base,
> +                                        config->prop_page_flip_event, 0);
>       }
>  
>       return 0;
> diff --git a/drivers/gpu/drm/drm_mode_config.c 
> b/drivers/gpu/drm/drm_mode_config.c
> index f432f485a914..688937d2e1ec 100644
> --- a/drivers/gpu/drm/drm_mode_config.c
> +++ b/drivers/gpu/drm/drm_mode_config.c
> @@ -496,6 +496,12 @@ static int drm_mode_create_standard_properties(struct 
> drm_device *dev)
>               return -ENOMEM;
>       dev->mode_config.prop_out_fence_ptr = prop;
>  
> +     prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
> +                     "PAGE_FLIP_EVENT", 0, 1);
> +     if (!prop)
> +             return -ENOMEM;
> +     dev->mode_config.prop_page_flip_event = prop;
> +
>       prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
>                       "CRTC_ID", DRM_MODE_OBJECT_CRTC);
>       if (!prop)
> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index 152349f973e3..b0f9130d263a 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -311,6 +311,12 @@ struct drm_crtc_state {
>        */
>       bool vrr_enabled;
>  
> +     /**
> +      * @page_flip_event_requested: indicates whether a page-flip event has
> +      * been requested on this CRTC.
> +      */
> +     bool page_flip_event_requested;
> +
>       /**
>        * @self_refresh_active:
>        *
> diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
> index d8f5b7e9673e..13f39677c32f 100644
> --- a/include/drm/drm_mode_config.h
> +++ b/include/drm/drm_mode_config.h
> @@ -670,6 +670,10 @@ struct drm_mode_config {
>        * value of type s32, and then cast that pointer to u64.
>        */
>       struct drm_property *prop_out_fence_ptr;
> +     /**
> +      * @page_flip_event_property: property to request page-flip events.
> +      */
> +     struct drm_property *prop_page_flip_event;
>       /**
>        * @prop_crtc_id: Default atomic plane property to specify the
>        * &drm_crtc.

Attachment: pgpdPKVhAJIiA.pgp
Description: OpenPGP digital signature

Reply via email to