diff mbox

[2/2] drm/i915: add async flip support on gen7

Message ID 1351622029-2276-3-git-send-email-jbarnes@virtuousgeek.org (mailing list archive)
State New, archived
Headers show

Commit Message

Jesse Barnes Oct. 30, 2012, 6:33 p.m. UTC
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/i915/i915_drv.h      |    3 ++-
 drivers/gpu/drm/i915/i915_reg.h      |    2 ++
 drivers/gpu/drm/i915/intel_display.c |   30 +++++++++++++++++++++---------
 3 files changed, 25 insertions(+), 10 deletions(-)

Comments

Eric Anholt Oct. 31, 2012, 5:47 p.m. UTC | #1
Jesse Barnes <jbarnes@virtuousgeek.org> writes:

> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>

So, these days if you go to render to a buffer that's been flipped from,
your rendering gets stalled (since the buffer may still be scanned out
when the rendering starts happening), which is the thing we need to
avoid.  I don't see this patch series avoiding that in the async case.
Jesse Barnes Oct. 31, 2012, 7:24 p.m. UTC | #2
On Wed, 31 Oct 2012 10:47:03 -0700
Eric Anholt <eric@anholt.net> wrote:

> Jesse Barnes <jbarnes@virtuousgeek.org> writes:
> 
> > Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
> 
> So, these days if you go to render to a buffer that's been flipped from,
> your rendering gets stalled (since the buffer may still be scanned out
> when the rendering starts happening), which is the thing we need to
> avoid.  I don't see this patch series avoiding that in the async case.

The currently displayed buffer should be marked idle shortly (i.e.
when the parser gets to your new flip command) after you queue your
async flip.  So the delay should be much shorter than with today's
sync'd flips, but may still be an issue if you have rendering queued up
before the flip.  We can certainly get rid of that...

Or we could just fix our triple buffering to do what you want and get
the best of both worlds.
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index f5120d0..af9db2b 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -273,7 +273,8 @@  struct drm_i915_display_funcs {
 	void (*init_pch_clock_gating)(struct drm_device *dev);
 	int (*queue_flip)(struct drm_device *dev, struct drm_crtc *crtc,
 			  struct drm_framebuffer *fb,
-			  struct drm_i915_gem_object *obj);
+			  struct drm_i915_gem_object *obj,
+			  u32 flags);
 	int (*update_plane)(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 			    int x, int y);
 	/* clock updates for mode set */
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 2dd880f..c9b49b7 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -211,6 +211,7 @@ 
 #define MI_LOAD_SCAN_LINES_INCL MI_INSTR(0x12, 0)
 #define MI_DISPLAY_FLIP		MI_INSTR(0x14, 2)
 #define MI_DISPLAY_FLIP_I915	MI_INSTR(0x14, 1)
+#define   MI_DISPLAY_FLIP_ASYNC_IND    (1 << 22)
 #define   MI_DISPLAY_FLIP_PLANE(n) ((n) << 20)
 /* IVB has funny definitions for which plane to flip. */
 #define   MI_DISPLAY_FLIP_IVB_PLANE_A  (0 << 19)
@@ -219,6 +220,7 @@ 
 #define   MI_DISPLAY_FLIP_IVB_SPRITE_B (3 << 19)
 #define   MI_DISPLAY_FLIP_IVB_PLANE_C  (4 << 19)
 #define   MI_DISPLAY_FLIP_IVB_SPRITE_C (5 << 19)
+#define   MI_DISPLAY_FLIP_ASYNC	       (1 << 0) /* in DW2 of the command */
 #define MI_ARB_ON_OFF		MI_INSTR(0x08, 0)
 #define   MI_ARB_ENABLE			(1<<0)
 #define   MI_ARB_DISABLE		(0<<0)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 2c0c174..ed79892 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6878,7 +6878,8 @@  void intel_prepare_page_flip(struct drm_device *dev, int plane)
 static int intel_gen2_queue_flip(struct drm_device *dev,
 				 struct drm_crtc *crtc,
 				 struct drm_framebuffer *fb,
-				 struct drm_i915_gem_object *obj)
+				 struct drm_i915_gem_object *obj,
+				 u32 flags)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -6920,7 +6921,8 @@  err:
 static int intel_gen3_queue_flip(struct drm_device *dev,
 				 struct drm_crtc *crtc,
 				 struct drm_framebuffer *fb,
-				 struct drm_i915_gem_object *obj)
+				 struct drm_i915_gem_object *obj,
+				 u32 flags)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -6960,7 +6962,8 @@  err:
 static int intel_gen4_queue_flip(struct drm_device *dev,
 				 struct drm_crtc *crtc,
 				 struct drm_framebuffer *fb,
-				 struct drm_i915_gem_object *obj)
+				 struct drm_i915_gem_object *obj,
+				 u32 flags)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -7006,7 +7009,8 @@  err:
 static int intel_gen6_queue_flip(struct drm_device *dev,
 				 struct drm_crtc *crtc,
 				 struct drm_framebuffer *fb,
-				 struct drm_i915_gem_object *obj)
+				 struct drm_i915_gem_object *obj,
+				 u32 flags)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -7054,12 +7058,13 @@  err:
 static int intel_gen7_queue_flip(struct drm_device *dev,
 				 struct drm_crtc *crtc,
 				 struct drm_framebuffer *fb,
-				 struct drm_i915_gem_object *obj)
+				 struct drm_i915_gem_object *obj,
+				 u32 flags)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_ring_buffer *ring = &dev_priv->ring[BCS];
-	uint32_t plane_bit = 0;
+	uint32_t plane_bit = 0, addr_bits = 0;
 	int ret;
 
 	ret = intel_pin_and_fence_fb_obj(dev, obj, ring);
@@ -7082,13 +7087,19 @@  static int intel_gen7_queue_flip(struct drm_device *dev,
 		goto err_unpin;
 	}
 
+	if (flags & DRM_MODE_PAGE_FLIP_ASYNC) {
+		plane_bit |= MI_DISPLAY_FLIP_ASYNC_IND;
+		addr_bits |= MI_DISPLAY_FLIP_ASYNC;
+	}
+
 	ret = intel_ring_begin(ring, 4);
 	if (ret)
 		goto err_unpin;
 
 	intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane_bit);
 	intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode));
-	intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset);
+	intel_ring_emit(ring, (obj->gtt_offset + intel_crtc->dspaddr_offset) |
+			addr_bits);
 	intel_ring_emit(ring, (MI_NOOP));
 	intel_ring_advance(ring);
 	return 0;
@@ -7102,7 +7113,8 @@  err:
 static int intel_default_queue_flip(struct drm_device *dev,
 				    struct drm_crtc *crtc,
 				    struct drm_framebuffer *fb,
-				    struct drm_i915_gem_object *obj)
+				    struct drm_i915_gem_object *obj,
+				    u32 flags)
 {
 	return -ENODEV;
 }
@@ -7183,7 +7195,7 @@  static int intel_crtc_page_flip(struct drm_crtc *crtc,
 	 */
 	atomic_add(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip);
 
-	ret = dev_priv->display.queue_flip(dev, crtc, fb, obj);
+	ret = dev_priv->display.queue_flip(dev, crtc, fb, obj, flags);
 	if (ret)
 		goto cleanup_pending;