Treat the overlay as another wait-source, just like other rendering to
the fb, and asynchronously wait upon it before doing an atomic modeset.

Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk>
---
This is half the solution, it should prevent the wait before disabling
the overlay, but we still need to remove the wait from inside
intel_overlay_off() itself, preferably by switching to mmio instead of
CS here.
---
 drivers/gpu/drm/i915/intel_display.c |  9 +++++++++
 drivers/gpu/drm/i915/intel_drv.h     |  2 ++
 drivers/gpu/drm/i915/intel_overlay.c | 19 +++++++++++++++++++
 3 files changed, 30 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index bfcd368ebf6f..6c51b0f2a96e 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -14183,9 +14183,18 @@ intel_prepare_plane_fb(struct drm_plane *plane,
        int ret;
 
        if (plane->state->fb && old_plane_needs_modeset(plane, new_state)) {
+               struct intel_crtc *crtc = to_intel_crtc(plane->state->crtc);
                struct drm_i915_gem_object *old_obj =
                        intel_fb_obj(plane->state->fb);
 
+               /* Queue this update after a previous old-school overlay flip */
+               if (crtc->overlay) {
+                       ret = intel_overlay_await(crtc->overlay,
+                                                 &intel_state->commit_ready);
+                       if (ret)
+                               return ret;
+               }
+
                /* Big Hammer, we also need to ensure that any pending
                 * MI_WAIT_FOR_EVENT inside a user batch buffer on the
                 * current scanout is retired before unpinning the old
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 5c521065dc3b..87fd544339d9 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1566,6 +1566,8 @@ void intel_attach_aspect_ratio_property(struct 
drm_connector *connector);
 /* intel_overlay.c */
 void intel_setup_overlay(struct drm_i915_private *dev_priv);
 void intel_cleanup_overlay(struct drm_i915_private *dev_priv);
+int intel_overlay_await(struct intel_overlay *overlay,
+                       struct i915_sw_fence *fence);
 int intel_overlay_switch_off(struct intel_overlay *overlay);
 int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
                                  struct drm_file *file_priv);
diff --git a/drivers/gpu/drm/i915/intel_overlay.c 
b/drivers/gpu/drm/i915/intel_overlay.c
index 79f93e7d699d..476a25961f34 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -855,6 +855,25 @@ static int intel_overlay_do_put_image(struct intel_overlay 
*overlay,
        return ret;
 }
 
+int intel_overlay_await(struct intel_overlay *overlay,
+                       struct i915_sw_fence *fence)
+{
+       struct drm_i915_gem_request *request;
+       int err;
+
+       request = i915_gem_active_peek(&overlay->last_flip,
+                                      &overlay->i915->drm.struct_mutex);
+       if (!request)
+               return 0;
+
+       err = i915_sw_fence_await_dma_fence(fence,
+                                           &request->fence, 0, GFP_KERNEL);
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
 int intel_overlay_switch_off(struct intel_overlay *overlay)
 {
        struct drm_i915_private *dev_priv = overlay->i915;
-- 
2.11.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to