If the driver supports it, allow user-space to supply the
DRM_MODE_PAGE_FLIP_ASYNC flag to request an async page-flip.
Set drm_crtc_state.async_flip accordingly.

Document that drivers will reject atomic commits if an async
flip isn't possible. This allows user-space to fall back to
something else. For instance, Xorg falls back to a blit.
Another option is to wait as close to the next vblank as
possible before performing the page-flip to reduce latency.

v2: document new uAPI

Signed-off-by: Simon Ser <cont...@emersion.fr>
Co-developed-by: André Almeida <andrealm...@igalia.com>
Signed-off-by: André Almeida <andrealm...@igalia.com>
Cc: Daniel Vetter <daniel.vet...@ffwll.ch>
Cc: Joshua Ashton <jos...@froggi.es>
Cc: Melissa Wen <m...@igalia.com>
Cc: Alex Deucher <alexander.deuc...@amd.com>
Cc: Harry Wentland <hwent...@amd.com>
Cc: Nicholas Kazlauskas <nicholas.kazlaus...@amd.com>
Cc: Ville Syrjälä <ville.syrj...@linux.intel.com>
---
 drivers/gpu/drm/drm_atomic_uapi.c | 28 +++++++++++++++++++++++++---
 include/uapi/drm/drm_mode.h       |  4 ++++
 2 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic_uapi.c 
b/drivers/gpu/drm/drm_atomic_uapi.c
index 79730fa1dd8e..ee24ed7e2edb 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -1278,6 +1278,18 @@ static void complete_signaling(struct drm_device *dev,
        kfree(fence_state);
 }
 
+static void
+set_async_flip(struct drm_atomic_state *state)
+{
+       struct drm_crtc *crtc;
+       struct drm_crtc_state *crtc_state;
+       int i;
+
+       for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
+               crtc_state->async_flip = true;
+       }
+}
+
 int drm_mode_atomic_ioctl(struct drm_device *dev,
                          void *data, struct drm_file *file_priv)
 {
@@ -1318,9 +1330,16 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
        }
 
        if (arg->flags & DRM_MODE_PAGE_FLIP_ASYNC) {
-               drm_dbg_atomic(dev,
-                              "commit failed: invalid flag 
DRM_MODE_PAGE_FLIP_ASYNC\n");
-               return -EINVAL;
+               if (!dev->mode_config.async_page_flip) {
+                       drm_dbg_atomic(dev,
+                                      "commit failed: DRM_MODE_PAGE_FLIP_ASYNC 
not supported\n");
+                       return -EINVAL;
+               }
+               if (dev->mode_config.atomic_async_page_flip_not_supported) {
+                       drm_dbg_atomic(dev,
+                                      "commit failed: DRM_MODE_PAGE_FLIP_ASYNC 
not supported with atomic\n");
+                       return -EINVAL;
+               }
        }
 
        /* can't test and expect an event at the same time. */
@@ -1418,6 +1437,9 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
        if (ret)
                goto out;
 
+       if (arg->flags & DRM_MODE_PAGE_FLIP_ASYNC)
+               set_async_flip(state);
+
        if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) {
                ret = drm_atomic_check_only(state);
        } else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) {
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index 86a292c3185a..cce1a1bea645 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -942,6 +942,10 @@ struct hdr_output_metadata {
  * Request that the page-flip is performed as soon as possible, ie. with no
  * delay due to waiting for vblank. This may cause tearing to be visible on
  * the screen.
+ *
+ * When used with atomic uAPI, the driver will return an error if the hardware
+ * doesn't support performing an asynchronous page-flip for this update.
+ * User-space should handle this, e.g. by falling back to a regular page-flip.
  */
 #define DRM_MODE_PAGE_FLIP_ASYNC 0x02
 #define DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE 0x4
-- 
2.37.2


Reply via email to