Queue the unpinning of the current plane object to after the next
vblank. For special case benchmarks and others apps that may call
set_plane at a high frequency, we can unpin their objects directly
unless they are "live".

Signed-off-by: Jesse Barnes <[email protected]>
Signed-off-by: Chris Wilson <[email protected]>
---
 drivers/gpu/drm/i915/i915_reg.h      |  2 ++
 drivers/gpu/drm/i915/intel_display.c |  2 +-
 drivers/gpu/drm/i915/intel_drv.h     |  3 ++
 drivers/gpu/drm/i915/intel_sprite.c  | 69 ++++++++++++++++++++++++------------
 4 files changed, 53 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 72e5693..74a3f01 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3411,6 +3411,7 @@
 #define DVSSTRIDE(pipe) _PIPE(pipe, _DVSASTRIDE, _DVSBSTRIDE)
 #define DVSPOS(pipe) _PIPE(pipe, _DVSAPOS, _DVSBPOS)
 #define DVSSURF(pipe) _PIPE(pipe, _DVSASURF, _DVSBSURF)
+#define DVSSURFLIVE(pipe) _PIPE(pipe, _DVSASURFLIVE, _DVSBSURFLIVE)
 #define DVSKEYMAX(pipe) _PIPE(pipe, _DVSAKEYMAXVAL, _DVSBKEYMAXVAL)
 #define DVSSIZE(pipe) _PIPE(pipe, _DVSASIZE, _DVSBSIZE)
 #define DVSSCALE(pipe) _PIPE(pipe, _DVSASCALE, _DVSBSCALE)
@@ -3487,6 +3488,7 @@
 #define SPRKEYVAL(pipe) _PIPE(pipe, _SPRA_KEYVAL, _SPRB_KEYVAL)
 #define SPRKEYMSK(pipe) _PIPE(pipe, _SPRA_KEYMSK, _SPRB_KEYMSK)
 #define SPRSURF(pipe) _PIPE(pipe, _SPRA_SURF, _SPRB_SURF)
+#define SPRSURFLIVE(pipe) _PIPE(pipe, _SPRA_SURFLIVE, _SPRB_SURFLIVE)
 #define SPRKEYMAX(pipe) _PIPE(pipe, _SPRA_KEYMAX, _SPRB_KEYMAX)
 #define SPRTILEOFF(pipe) _PIPE(pipe, _SPRA_TILEOFF, _SPRB_TILEOFF)
 #define SPROFFSET(pipe) _PIPE(pipe, _SPRA_OFFSET, _SPRB_OFFSET)
diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 4b50d5f..dc4bf49 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2270,7 +2270,7 @@ static void intel_crtc_unpin_work_fn(struct intel_crtc 
*crtc, void *obj)
        mutex_unlock(&dev->struct_mutex);
 }
 
-static void
+void
 intel_crtc_queue_unpin(struct intel_crtc *crtc,
                       struct drm_i915_gem_object *obj)
 {
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 19df4ec..e6dda01 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -383,6 +383,7 @@ struct intel_plane {
                               struct drm_intel_sprite_colorkey *key);
        void (*get_colorkey)(struct drm_plane *plane,
                             struct drm_intel_sprite_colorkey *key);
+       u32 (*current_surface)(struct drm_plane *plane);
 };
 
 struct intel_watermark_params {
@@ -648,6 +649,8 @@ extern int intel_set_mode(struct drm_crtc *crtc, struct 
drm_display_mode *mode,
                          int x, int y, struct drm_framebuffer *old_fb);
 extern void intel_modeset_disable(struct drm_device *dev);
 extern void intel_crtc_restore_mode(struct drm_crtc *crtc);
+extern void intel_crtc_queue_unpin(struct intel_crtc *crtc,
+                                  struct drm_i915_gem_object *obj);
 extern void intel_crtc_load_lut(struct drm_crtc *crtc);
 extern void intel_crtc_update_dpms(struct drm_crtc *crtc);
 extern void intel_encoder_destroy(struct drm_encoder *encoder);
diff --git a/drivers/gpu/drm/i915/intel_sprite.c 
b/drivers/gpu/drm/i915/intel_sprite.c
index 9d95589..d129282 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -397,6 +397,16 @@ ivb_get_colorkey(struct drm_plane *plane, struct 
drm_intel_sprite_colorkey *key)
                key->flags = I915_SET_COLORKEY_NONE;
 }
 
+static u32
+ivb_current_surface(struct drm_plane *plane)
+{
+       struct intel_plane *intel_plane;
+
+       intel_plane = to_intel_plane(plane);
+
+       return SPRSURFLIVE(intel_plane->pipe);
+}
+
 static void
 ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
                 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
@@ -602,6 +612,35 @@ format_is_yuv(uint32_t format)
        }
 }
 
+static u32
+ilk_current_surface(struct drm_plane *plane)
+{
+       struct intel_plane *intel_plane;
+
+       intel_plane = to_intel_plane(plane);
+
+       return DVSSURFLIVE(intel_plane->pipe);
+}
+
+static void
+intel_plane_queue_unpin(struct intel_plane *plane,
+                       struct drm_i915_gem_object *obj)
+{
+       /*
+        * If the surface is currently being scanned out, we need to
+        * wait until the next vblank event latches in the new base address
+        * before we unpin it, or we may end up displaying the wrong data.
+        * However, if the old object isn't currently 'live', we can just
+        * unpin right away.
+        */
+       if (plane->current_surface(&plane->base) != 
i915_gem_obj_ggtt_offset(obj)) {
+               intel_unpin_fb_obj(obj);
+               return;
+       }
+
+       intel_crtc_queue_unpin(to_intel_crtc(plane->base.crtc), obj);
+}
+
 static int
 intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
                   struct drm_framebuffer *fb, int crtc_x, int crtc_y,
@@ -830,20 +869,8 @@ intel_update_plane(struct drm_plane *plane, struct 
drm_crtc *crtc,
                intel_disable_primary(crtc);
 
        /* Unpin old obj after new one is active to avoid ugliness */
-       if (old_obj) {
-               /*
-                * It's fairly common to simply update the position of
-                * an existing object.  In that case, we don't need to
-                * wait for vblank to avoid ugliness, we only need to
-                * do the pin & ref bookkeeping.
-                */
-               if (old_obj != obj) {
-                       mutex_unlock(&dev->struct_mutex);
-                       intel_wait_for_vblank(dev, to_intel_crtc(crtc)->pipe);
-                       mutex_lock(&dev->struct_mutex);
-               }
-               intel_unpin_fb_obj(old_obj);
-       }
+       if (old_obj)
+               intel_plane_queue_unpin(intel_plane, old_obj);
 
 out_unlock:
        mutex_unlock(&dev->struct_mutex);
@@ -861,16 +888,12 @@ intel_disable_plane(struct drm_plane *plane)
                intel_enable_primary(plane->crtc);
        intel_plane->disable_plane(plane);
 
-       if (!intel_plane->obj)
-               goto out;
-
-       intel_wait_for_vblank(dev, intel_plane->pipe);
-
        mutex_lock(&dev->struct_mutex);
-       intel_unpin_fb_obj(intel_plane->obj);
-       intel_plane->obj = NULL;
+       if (intel_plane->obj) {
+               intel_plane_queue_unpin(intel_plane, intel_plane->obj);
+               intel_plane->obj = NULL;
+       }
        mutex_unlock(&dev->struct_mutex);
-out:
 
        return ret;
 }
@@ -1029,6 +1052,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, 
int plane)
                intel_plane->disable_plane = ilk_disable_plane;
                intel_plane->update_colorkey = ilk_update_colorkey;
                intel_plane->get_colorkey = ilk_get_colorkey;
+               intel_plane->current_surface = ilk_current_surface;
 
                if (IS_GEN6(dev)) {
                        plane_formats = snb_plane_formats;
@@ -1061,6 +1085,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, 
int plane)
                        intel_plane->disable_plane = ivb_disable_plane;
                        intel_plane->update_colorkey = ivb_update_colorkey;
                        intel_plane->get_colorkey = ivb_get_colorkey;
+                       intel_plane->current_surface = ivb_current_surface;
 
                        plane_formats = snb_plane_formats;
                        num_plane_formats = ARRAY_SIZE(snb_plane_formats);
-- 
1.8.3.2

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to