[Intel-gfx] [PATCH 5/5] drm/i915: Defer the FBC w/a invalidation
Chris Wilson
chris at chris-wilson.co.uk
Thu Jun 20 19:18:32 CEST 2013
Hook into the frontbuffer write and delayed flush mechanism to avoid
having to send the FBC w/a on every batch, and instead just send the
w/a whenever we update the scanout.
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
drivers/gpu/drm/i915/i915_drv.h | 1 +
drivers/gpu/drm/i915/i915_gem.c | 2 +-
drivers/gpu/drm/i915/i915_gem_execbuffer.c | 2 +-
drivers/gpu/drm/i915/intel_display.c | 30 ++++++++++++++++++------------
drivers/gpu/drm/i915/intel_drv.h | 4 ++--
drivers/gpu/drm/i915/intel_pm.c | 2 ++
drivers/gpu/drm/i915/intel_ringbuffer.c | 9 +++------
drivers/gpu/drm/i915/intel_ringbuffer.h | 2 +-
8 files changed, 29 insertions(+), 23 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 1257e0e..7dc76bf 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1070,6 +1070,7 @@ typedef struct drm_i915_private {
unsigned long cfb_size;
unsigned int cfb_fb;
+ bool cfb_enabled;
enum plane cfb_plane;
int cfb_y;
struct intel_fbc_work *fbc_work;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 6661adb..707a55e 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -3323,7 +3323,7 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
obj->dirty = 1;
if (obj->pin_count && !list_empty(&obj->fb_list))
- intel_mark_fb_busy(obj, NULL);
+ intel_mark_fb_busy(obj);
}
trace_i915_gem_object_change_domain(obj,
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index dabd9af..c6a02d7 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -786,7 +786,7 @@ i915_gem_execbuffer_move_to_active(struct list_head *objects,
obj->dirty = 1;
obj->last_write_seqno = intel_ring_get_seqno(ring);
if (obj->pin_count && !list_empty(&obj->fb_list))
- intel_mark_fb_busy(obj, ring);
+ intel_mark_fb_busy(obj);
}
trace_i915_gem_object_change_domain(obj, old_read, old_write);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index be60f12..9a90aa5 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -7108,6 +7108,14 @@ static void intel_display_refresh(struct work_struct *work)
if (!fb->refresh_pending)
continue;
+ if (fb->fbc_dirty) {
+ flush |= RING_FBC;
+ if (fb->obj->ring)
+ rings |= 1 << fb->obj->ring->id;
+ intel_update_fbc(dev);
+ fb->fbc_dirty = false;
+ }
+
if (fb->refresh_mode == REFRESH_NONE)
i915_gem_release_mmap(fb->obj);
fb->obj->base.write_domain &= ~I915_GEM_DOMAIN_GTT;
@@ -7129,10 +7137,10 @@ static void intel_display_refresh(struct work_struct *work)
mutex_unlock(&dev->struct_mutex);
}
-static void __intel_mark_fb_busy(struct intel_framebuffer *fb,
- struct intel_ring_buffer *ring)
+static void __intel_mark_fb_busy(struct intel_framebuffer *fb)
{
struct drm_device *dev = fb->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_crtc *crtc;
bool refresh = false;
@@ -7149,14 +7157,13 @@ static void __intel_mark_fb_busy(struct intel_framebuffer *fb,
refresh = false;
- if (ring && intel_fbc_enabled(dev)) {
- ring->fbc_dirty = true;
+ if (dev_priv->cfb_enabled) {
+ intel_disable_fbc(dev);
+ fb->fbc_dirty = true;
refresh = true;
}
if (refresh) {
- struct drm_i915_private *dev_priv = dev->dev_private;
-
fb->refresh_pending = true;
queue_delayed_work(dev_priv->wq,
&dev_priv->display_refresh_work,
@@ -7164,8 +7171,7 @@ static void __intel_mark_fb_busy(struct intel_framebuffer *fb,
}
}
-void intel_mark_fb_busy(struct drm_i915_gem_object *obj,
- struct intel_ring_buffer *ring)
+void intel_mark_fb_busy(struct drm_i915_gem_object *obj)
{
struct intel_framebuffer *fb;
@@ -7173,7 +7179,7 @@ void intel_mark_fb_busy(struct drm_i915_gem_object *obj,
if (fb->refresh_mode == REFRESH_USER)
continue;
- __intel_mark_fb_busy(fb, NULL);
+ __intel_mark_fb_busy(fb);
}
}
@@ -7622,8 +7628,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
if (ret)
goto cleanup_pending;
- intel_disable_fbc(dev);
- intel_mark_fb_busy(obj, NULL);
+ intel_mark_fb_busy(obj);
mutex_unlock(&dev->struct_mutex);
trace_i915_flip_request(intel_crtc->plane, obj);
@@ -9151,7 +9156,7 @@ static int intel_user_framebuffer_dirty(struct drm_framebuffer *fb,
struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
if (intel_fb->refresh_mode == REFRESH_USER)
- __intel_mark_fb_busy(intel_fb, NULL);
+ __intel_mark_fb_busy(intel_fb);
return 0;
}
@@ -9267,6 +9272,7 @@ int intel_framebuffer_init(struct drm_device *dev,
intel_fb->powersave = true;
intel_fb->refresh_mode = REFRESH_NONE;
intel_fb->refresh_pending = false;
+ intel_fb->fbc_dirty = false;
ret = drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs);
if (ret) {
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 9f32949..01957bf 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -107,6 +107,7 @@ struct intel_framebuffer {
#define REFRESH_NONE 0
#define REFRESH_USER 1
unsigned refresh_pending:1;
+ unsigned fbc_dirty:1;
struct list_head obj_list;
};
@@ -585,8 +586,7 @@ extern bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg,
extern void intel_dvo_init(struct drm_device *dev);
extern void intel_tv_init(struct drm_device *dev);
extern void intel_mark_busy(struct drm_device *dev);
-extern void intel_mark_fb_busy(struct drm_i915_gem_object *obj,
- struct intel_ring_buffer *ring);
+extern void intel_mark_fb_busy(struct drm_i915_gem_object *obj);
extern void intel_mark_idle(struct drm_device *dev);
extern void intel_lvds_init(struct drm_device *dev);
extern bool intel_is_dual_link_lvds(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 2f6150b..711cdd0 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -347,6 +347,7 @@ static void intel_fbc_work_fn(struct work_struct *__work)
static void intel_cancel_fbc_work(struct drm_i915_private *dev_priv)
{
+ dev_priv->cfb_enabled = false;
if (dev_priv->fbc_work == NULL)
return;
@@ -379,6 +380,7 @@ void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
intel_cancel_fbc_work(dev_priv);
+ dev_priv->cfb_enabled = true;
work = kzalloc(sizeof *work, GFP_KERNEL);
if (work == NULL) {
DRM_ERROR("Failed to allocate FBC work structure\n");
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 601e1eb..1383267 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -278,12 +278,10 @@ static int gen7_ring_fbc_flush(struct intel_ring_buffer *ring, u32 value)
{
int ret;
- if (!ring->fbc_dirty)
- return 0;
-
ret = intel_ring_begin(ring, 4);
if (ret)
return ret;
+
intel_ring_emit(ring, MI_NOOP);
/* WaFbcNukeOn3DBlt:ivb/hsw */
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
@@ -291,7 +289,6 @@ static int gen7_ring_fbc_flush(struct intel_ring_buffer *ring, u32 value)
intel_ring_emit(ring, value);
intel_ring_advance(ring);
- ring->fbc_dirty = false;
return 0;
}
@@ -353,7 +350,7 @@ gen7_render_ring_flush(struct intel_ring_buffer *ring, u32 action)
intel_ring_advance(ring);
}
- if (action & RING_FLUSH)
+ if (action & RING_FBC)
return gen7_ring_fbc_flush(ring, FBC_REND_NUKE);
return 0;
@@ -1737,7 +1734,7 @@ static int gen6_ring_flush(struct intel_ring_buffer *ring, u32 action)
intel_ring_advance(ring);
}
- if (IS_GEN7(dev) && action & RING_FLUSH)
+ if (IS_GEN7(dev) && action & RING_FBC)
return gen7_ring_fbc_flush(ring, FBC_REND_CACHE_CLEAN);
return 0;
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 5066b3b..c91a4b1 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -96,6 +96,7 @@ struct intel_ring_buffer {
u32 action);
#define RING_FLUSH 0x1
#define RING_INVALIDATE 0x2
+#define RING_FBC 0x4
int (*add_request)(struct intel_ring_buffer *ring);
/* Some chipsets are not quite as coherent as advertised and need
@@ -146,7 +147,6 @@ struct intel_ring_buffer {
*/
u32 outstanding_lazy_request;
bool gpu_caches_dirty;
- bool fbc_dirty;
wait_queue_head_t irq_queue;
--
1.8.3.1
More information about the Intel-gfx
mailing list