drm/atomic: Integrate fence support
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Wed, 29 Oct 2014 10:34:56 +0000 (11:34 +0100)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Thu, 6 Nov 2014 20:02:22 +0000 (21:02 +0100)
This patch is for enabling async commits. It replaces an earlier
approach which added an async boolean paramter to the ->prepare_fb
callbacks. The idea is that prepare_fb picks up the right fence to
synchronize against, which is then used by the synchronous commit
helper. For async commits drivers can either register a callback to
the fence or simply do the synchronous wait in their async work queue.

v2: Remove unused variable.

v3: Only wait for fences after the point of no return in the part
of the commit function which can be run asynchronously. This is after
the atomic state has been swapped in, hence now check
plane->state->fence.

Also add a WARN_ON to make sure we don't try to wait on a fence when
there's no fb, just as a sanity check.

Reviewed-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
drivers/gpu/drm/drm_atomic_helper.c
include/drm/drm_crtc.h

index 077c792c46e09c7b0ecca1c2068295f9feba1ed7..4808e71dedb08e1afc5b57c27cc41f577d71fd43 100644 (file)
@@ -30,6 +30,7 @@
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_atomic_helper.h>
+#include <linux/fence.h>
 
 static void
 drm_atomic_helper_plane_changed(struct drm_atomic_state *state,
@@ -712,6 +713,26 @@ void drm_atomic_helper_commit_post_planes(struct drm_device *dev,
 }
 EXPORT_SYMBOL(drm_atomic_helper_commit_post_planes);
 
+static void wait_for_fences(struct drm_device *dev,
+                           struct drm_atomic_state *state)
+{
+       int nplanes = dev->mode_config.num_total_plane;
+       int i;
+
+       for (i = 0; i < nplanes; i++) {
+               struct drm_plane *plane = state->planes[i];
+
+               if (!plane || !plane->state->fence)
+                       continue;
+
+               WARN_ON(!plane->state->fb);
+
+               fence_wait(plane->state->fence, false);
+               fence_put(plane->state->fence);
+               plane->state->fence = NULL;
+       }
+}
+
 static void
 wait_for_vblanks(struct drm_device *dev, struct drm_atomic_state *old_state)
 {
@@ -809,6 +830,8 @@ int drm_atomic_helper_commit(struct drm_device *dev,
         * current layout.
         */
 
+       wait_for_fences(dev, state);
+
        drm_atomic_helper_commit_pre_planes(dev, state);
 
        drm_atomic_helper_commit_planes(dev, state);
index bc47d11cb126b4e8da265f1517f51644035ed8e8..bc1cc3ce05c44fef38c6bfb0802dd08c6c592fa3 100644 (file)
@@ -42,6 +42,7 @@ struct drm_object_properties;
 struct drm_file;
 struct drm_clip_rect;
 struct device_node;
+struct fence;
 
 #define DRM_MODE_OBJECT_CRTC 0xcccccccc
 #define DRM_MODE_OBJECT_CONNECTOR 0xc0c0c0c0
@@ -658,6 +659,7 @@ struct drm_connector {
  * struct drm_plane_state - mutable plane state
  * @crtc: currently bound CRTC, NULL if disabled
  * @fb: currently bound framebuffer
+ * @fence: optional fence to wait for before scanning out @fb
  * @crtc_x: left position of visible portion of plane on crtc
  * @crtc_y: upper position of visible portion of plane on crtc
  * @crtc_w: width of visible portion of plane on crtc
@@ -673,6 +675,7 @@ struct drm_connector {
 struct drm_plane_state {
        struct drm_crtc *crtc;
        struct drm_framebuffer *fb;
+       struct fence *fence;
 
        /* Signed dest location allows it to be partially off screen */
        int32_t crtc_x, crtc_y;