From: Gustavo Padovan <gustavo.pado...@collabora.com>

Add support to async updates of cursors by using the new atomic
interface for that. Basically what this commit does is do what
intel_legacy_cursor_update() did but through atomic.

v3:
        - set correct vma to new state for cleanup
        - move size checks back to drivers (Ville Syrjälä)

v2:
        - move fb setting to core and use new state (Eric Anholt)

Cc: Daniel Vetter <daniel.vet...@intel.com>
Signed-off-by: Gustavo Padovan <gustavo.pado...@collabora.com>
---
 drivers/gpu/drm/i915/intel_atomic_plane.c |  73 +++++++++++++++
 drivers/gpu/drm/i915/intel_display.c      | 149 +++++-------------------------
 2 files changed, 97 insertions(+), 125 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c 
b/drivers/gpu/drm/i915/intel_atomic_plane.c
index cfb4729..974c91f 100644
--- a/drivers/gpu/drm/i915/intel_atomic_plane.c
+++ b/drivers/gpu/drm/i915/intel_atomic_plane.c
@@ -246,11 +246,84 @@ static void intel_plane_atomic_update(struct drm_plane 
*plane,
        }
 }
 
+static int intel_plane_atomic_async_check(struct drm_plane *plane,
+                                         struct drm_plane_state *state)
+{
+       struct drm_crtc *crtc = plane->state->crtc;
+       struct drm_crtc_state *crtc_state = crtc->state;
+
+       if (plane->type != DRM_PLANE_TYPE_CURSOR)
+               return -EINVAL;
+
+       /*
+        * When crtc is inactive or there is a modeset pending,
+        * wait for it to complete in the slowpath
+        */
+       if (!crtc_state->active || to_intel_crtc_state(crtc_state)->update_pipe)
+               return -EINVAL;
+
+       /*
+        * If any parameters change that may affect watermarks,
+        * take the slowpath. Only changing fb or position should be
+        * in the fastpath.
+        */
+       if (plane->state->crtc != state->crtc ||
+           plane->state->src_w != state->src_w ||
+           plane->state->src_h != state->src_h ||
+           plane->state->crtc_w != state->crtc_w ||
+           plane->state->crtc_h != state->crtc_h ||
+           !plane->state->fb != !state->fb)
+               return -EINVAL;
+
+       return 0;
+}
+
+static void intel_plane_atomic_async_update(struct drm_plane *plane,
+                                           struct drm_plane_state *new_state)
+{
+       struct intel_plane *intel_plane = to_intel_plane(plane);
+       struct drm_crtc *crtc = plane->state->crtc;
+       struct drm_framebuffer *old_fb;
+       struct i915_vma *old_vma;
+
+       old_vma = to_intel_plane_state(plane->state)->vma;
+       old_fb = plane->state->fb;
+
+       i915_gem_track_fb(intel_fb_obj(old_fb), intel_fb_obj(new_state->fb),
+                         intel_plane->frontbuffer_bit);
+
+       plane->state->src_x = new_state->src_x;
+       plane->state->src_y = new_state->src_y;
+       plane->state->crtc_x = new_state->crtc_x;
+       plane->state->crtc_y = new_state->crtc_y;
+       plane->state->fb = new_state->fb;
+       *to_intel_plane_state(plane->state) = *to_intel_plane_state(new_state);
+
+       to_intel_plane_state(new_state)->vma = old_vma;
+       new_state->fb = old_fb;
+
+       if (plane->state->visible) {
+               trace_intel_update_plane(plane, to_intel_crtc(crtc));
+               intel_plane->update_plane(plane,
+                                         to_intel_crtc_state(crtc->state),
+                                         to_intel_plane_state(plane->state));
+       } else {
+               trace_intel_disable_plane(plane, to_intel_crtc(crtc));
+               intel_plane->disable_plane(plane, crtc);
+       }
+
+       mutex_lock(&plane->dev->struct_mutex);
+       intel_cleanup_plane_fb(plane, new_state);
+       mutex_unlock(&plane->dev->struct_mutex);
+}
+
 const struct drm_plane_helper_funcs intel_plane_helper_funcs = {
        .prepare_fb = intel_prepare_plane_fb,
        .cleanup_fb = intel_cleanup_plane_fb,
        .atomic_check = intel_plane_atomic_check,
        .atomic_update = intel_plane_atomic_update,
+       .atomic_async_check = intel_plane_atomic_async_check,
+       .atomic_async_update = intel_plane_atomic_async_update,
 };
 
 /**
diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 207f144..7f4c8d3 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -13010,6 +13010,26 @@ static int intel_atomic_commit(struct drm_device *dev,
        struct drm_i915_private *dev_priv = to_i915(dev);
        int ret = 0;
 
+       /*
+        * The atomic async update fast path takes care
+        * of avoiding the vblank waits for simple cursor
+        * movement and flips. For cursor on/off and size changes,
+        * we want to perform the vblank waits so that watermark
+        * updates happen during the correct frames. Gen9+ have
+        * double buffered watermarks and so shouldn't need this.
+        */
+       if (state->async_update) {
+               ret = mutex_lock_interruptible(&dev->struct_mutex);
+               if (ret)
+                       return ret;
+
+               ret = drm_atomic_helper_prepare_planes(dev, state);
+               mutex_unlock(&dev->struct_mutex);
+
+               drm_atomic_helper_async_commit(dev, state);
+               return 0;
+       }
+
        ret = drm_atomic_helper_setup_commit(state, nonblock);
        if (ret)
                return ret;
@@ -13168,6 +13188,9 @@ intel_prepare_plane_fb(struct drm_plane *plane,
                }
        }
 
+       if (new_state->state->async_update)
+               return 0;
+
        if (!obj && !old_obj)
                return 0;
 
@@ -13395,132 +13418,8 @@ const struct drm_plane_funcs intel_plane_funcs = {
        .atomic_destroy_state = intel_plane_destroy_state,
 };
 
-static int
-intel_legacy_cursor_update(struct drm_plane *plane,
-                          struct drm_crtc *crtc,
-                          struct drm_framebuffer *fb,
-                          int crtc_x, int crtc_y,
-                          unsigned int crtc_w, unsigned int crtc_h,
-                          uint32_t src_x, uint32_t src_y,
-                          uint32_t src_w, uint32_t src_h,
-                          struct drm_modeset_acquire_ctx *ctx)
-{
-       struct drm_i915_private *dev_priv = to_i915(crtc->dev);
-       int ret;
-       struct drm_plane_state *old_plane_state, *new_plane_state;
-       struct intel_plane *intel_plane = to_intel_plane(plane);
-       struct drm_framebuffer *old_fb;
-       struct drm_crtc_state *crtc_state = crtc->state;
-       struct i915_vma *old_vma;
-
-       /*
-        * When crtc is inactive or there is a modeset pending,
-        * wait for it to complete in the slowpath
-        */
-       if (!crtc_state->active || needs_modeset(crtc_state) ||
-           to_intel_crtc_state(crtc_state)->update_pipe)
-               goto slow;
-
-       old_plane_state = plane->state;
-
-       /*
-        * If any parameters change that may affect watermarks,
-        * take the slowpath. Only changing fb or position should be
-        * in the fastpath.
-        */
-       if (old_plane_state->crtc != crtc ||
-           old_plane_state->src_w != src_w ||
-           old_plane_state->src_h != src_h ||
-           old_plane_state->crtc_w != crtc_w ||
-           old_plane_state->crtc_h != crtc_h ||
-           !old_plane_state->fb != !fb)
-               goto slow;
-
-       new_plane_state = intel_plane_duplicate_state(plane);
-       if (!new_plane_state)
-               return -ENOMEM;
-
-       drm_atomic_set_fb_for_plane(new_plane_state, fb);
-
-       new_plane_state->src_x = src_x;
-       new_plane_state->src_y = src_y;
-       new_plane_state->src_w = src_w;
-       new_plane_state->src_h = src_h;
-       new_plane_state->crtc_x = crtc_x;
-       new_plane_state->crtc_y = crtc_y;
-       new_plane_state->crtc_w = crtc_w;
-       new_plane_state->crtc_h = crtc_h;
-
-       ret = 
intel_plane_atomic_check_with_state(to_intel_crtc_state(crtc->state),
-                                                 
to_intel_plane_state(new_plane_state));
-       if (ret)
-               goto out_free;
-
-       ret = mutex_lock_interruptible(&dev_priv->drm.struct_mutex);
-       if (ret)
-               goto out_free;
-
-       if (INTEL_INFO(dev_priv)->cursor_needs_physical) {
-               int align = IS_I830(dev_priv) ? 16 * 1024 : 256;
-
-               ret = i915_gem_object_attach_phys(intel_fb_obj(fb), align);
-               if (ret) {
-                       DRM_DEBUG_KMS("failed to attach phys object\n");
-                       goto out_unlock;
-               }
-       } else {
-               struct i915_vma *vma;
-
-               vma = intel_pin_and_fence_fb_obj(fb, new_plane_state->rotation);
-               if (IS_ERR(vma)) {
-                       DRM_DEBUG_KMS("failed to pin object\n");
-
-                       ret = PTR_ERR(vma);
-                       goto out_unlock;
-               }
-
-               to_intel_plane_state(new_plane_state)->vma = vma;
-       }
-
-       old_fb = old_plane_state->fb;
-       old_vma = to_intel_plane_state(old_plane_state)->vma;
-
-       i915_gem_track_fb(intel_fb_obj(old_fb), intel_fb_obj(fb),
-                         intel_plane->frontbuffer_bit);
-
-       /* Swap plane state */
-       new_plane_state->fence = old_plane_state->fence;
-       *to_intel_plane_state(old_plane_state) = 
*to_intel_plane_state(new_plane_state);
-       new_plane_state->fence = NULL;
-       new_plane_state->fb = old_fb;
-       to_intel_plane_state(new_plane_state)->vma = old_vma;
-
-       if (plane->state->visible) {
-               trace_intel_update_plane(plane, to_intel_crtc(crtc));
-               intel_plane->update_plane(plane,
-                                         to_intel_crtc_state(crtc->state),
-                                         to_intel_plane_state(plane->state));
-       } else {
-               trace_intel_disable_plane(plane, to_intel_crtc(crtc));
-               intel_plane->disable_plane(plane, crtc);
-       }
-
-       intel_cleanup_plane_fb(plane, new_plane_state);
-
-out_unlock:
-       mutex_unlock(&dev_priv->drm.struct_mutex);
-out_free:
-       intel_plane_destroy_state(plane, new_plane_state);
-       return ret;
-
-slow:
-       return drm_atomic_helper_update_plane(plane, crtc, fb,
-                                             crtc_x, crtc_y, crtc_w, crtc_h,
-                                             src_x, src_y, src_w, src_h, ctx);
-}
-
 static const struct drm_plane_funcs intel_cursor_plane_funcs = {
-       .update_plane = intel_legacy_cursor_update,
+       .update_plane = drm_atomic_helper_update_plane,
        .disable_plane = drm_atomic_helper_disable_plane,
        .destroy = intel_plane_destroy,
        .set_property = drm_atomic_helper_plane_set_property,
-- 
2.9.3

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to