aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2014-11-24 14:42:42 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2014-11-25 07:12:42 -0500
commitab58e3384b9f9863bfd029b458ff337d381bf6d2 (patch)
tree8a8408b443c8765f06217099540849f7a39cbe9e
parentb0ff4b93f646c39900ead9f6f7b6da78b5978273 (diff)
drm/atomic-helper: Skip vblank waits for unchanged fbs
Especially with legacy cursor ioctls existing userspace assumes that you can pile up lots of updates in one go. The super-proper way to support this would be a special commit mode which overwrites the last update. But getting there will be quite a bit of work. Meanwhile do what pretty much all the drivers have done for the plane update functions: Simply skip the vblank wait for the buffer cleanup if the buffer is the same. Since the universal cursor plane code will not recreate framebuffers needlessly this allows us to not slow down legacy pageflip events while someone moves the cursor around. v2: Drop the async plane update hunk from a previous attempt at this issue. v3: Fix up kerneldoc. v4: Don't oops so badly. Reported by Jasper. Cc: Rob Clark <robdclark@gmail.com> Cc: "Jasper St. Pierre" <jstpierre@mecheye.net> Reviewed-by: Rob Clark <robdclark@gmail.com> Reviewed-by: Jasper St. Pierre <jstpierre@mecheye.net> Tested-by: Jasper St. Pierre <jstpierre@mecheye.net> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
-rw-r--r--drivers/gpu/drm/drm_atomic_helper.c34
1 files changed, 33 insertions, 1 deletions
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index a17b8e9c0a81..4368581ac1eb 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -751,6 +751,33 @@ static void wait_for_fences(struct drm_device *dev,
751 } 751 }
752} 752}
753 753
754static bool framebuffer_changed(struct drm_device *dev,
755 struct drm_atomic_state *old_state,
756 struct drm_crtc *crtc)
757{
758 struct drm_plane *plane;
759 struct drm_plane_state *old_plane_state;
760 int nplanes = old_state->dev->mode_config.num_total_plane;
761 int i;
762
763 for (i = 0; i < nplanes; i++) {
764 plane = old_state->planes[i];
765 old_plane_state = old_state->plane_states[i];
766
767 if (!plane)
768 continue;
769
770 if (plane->state->crtc != crtc &&
771 old_plane_state->crtc != crtc)
772 continue;
773
774 if (plane->state->fb != old_plane_state->fb)
775 return true;
776 }
777
778 return false;
779}
780
754/** 781/**
755 * drm_atomic_helper_wait_for_vblanks - wait for vblank on crtcs 782 * drm_atomic_helper_wait_for_vblanks - wait for vblank on crtcs
756 * @dev: DRM device 783 * @dev: DRM device
@@ -758,7 +785,9 @@ static void wait_for_fences(struct drm_device *dev,
758 * 785 *
759 * Helper to, after atomic commit, wait for vblanks on all effected 786 * Helper to, after atomic commit, wait for vblanks on all effected
760 * crtcs (ie. before cleaning up old framebuffers using 787 * crtcs (ie. before cleaning up old framebuffers using
761 * drm_atomic_helper_cleanup_planes()) 788 * drm_atomic_helper_cleanup_planes()). It will only wait on crtcs where the
789 * framebuffers have actually changed to optimize for the legacy cursor and
790 * plane update use-case.
762 */ 791 */
763void 792void
764drm_atomic_helper_wait_for_vblanks(struct drm_device *dev, 793drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,
@@ -784,6 +813,9 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,
784 if (!crtc->state->enable) 813 if (!crtc->state->enable)
785 continue; 814 continue;
786 815
816 if (!framebuffer_changed(dev, old_state, crtc))
817 continue;
818
787 ret = drm_crtc_vblank_get(crtc); 819 ret = drm_crtc_vblank_get(crtc);
788 if (ret != 0) 820 if (ret != 0)
789 continue; 821 continue;