Skip to content

Commit dbef0f1

Browse files
pzanoni-inteldanvet
authored andcommitted
drm/i915: add frontbuffer tracking to FBC
Kill the blt/render tracking we currently have and use the frontbuffer tracking infrastructure. Don't enable things by default yet. v2: (Rodrigo) Fix small conflict on rebase and typo at subject. v3: (Paulo) Rebase on RENDER_CS change. v4: (Paulo) Rebase. v5: (Paulo) Simplify: flushes don't have origin (Daniel). Also rebase due to patch order changes. Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com> Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
1 parent 3954e73 commit dbef0f1

File tree

6 files changed

+65
-98
lines changed

6 files changed

+65
-98
lines changed

drivers/gpu/drm/i915/i915_drv.h

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -805,6 +805,8 @@ struct i915_fbc {
805805
unsigned long uncompressed_size;
806806
unsigned threshold;
807807
unsigned int fb_id;
808+
unsigned int possible_framebuffer_bits;
809+
unsigned int busy_bits;
808810
struct intel_crtc *crtc;
809811
int y;
810812

@@ -817,14 +819,6 @@ struct i915_fbc {
817819
* possible. */
818820
bool enabled;
819821

820-
/* On gen8 some rings cannont perform fbc clean operation so for now
821-
* we are doing this on SW with mmio.
822-
* This variable works in the opposite information direction
823-
* of ring->fbc_dirty telling software on frontbuffer tracking
824-
* to perform the cache clean on sw side.
825-
*/
826-
bool need_sw_cache_clean;
827-
828822
struct intel_fbc_work {
829823
struct delayed_work work;
830824
struct drm_crtc *crtc;

drivers/gpu/drm/i915/intel_drv.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1115,7 +1115,11 @@ bool intel_fbc_enabled(struct drm_device *dev);
11151115
void intel_fbc_update(struct drm_device *dev);
11161116
void intel_fbc_init(struct drm_i915_private *dev_priv);
11171117
void intel_fbc_disable(struct drm_device *dev);
1118-
void bdw_fbc_sw_flush(struct drm_device *dev, u32 value);
1118+
void intel_fbc_invalidate(struct drm_i915_private *dev_priv,
1119+
unsigned int frontbuffer_bits,
1120+
enum fb_op_origin origin);
1121+
void intel_fbc_flush(struct drm_i915_private *dev_priv,
1122+
unsigned int frontbuffer_bits);
11191123

11201124
/* intel_hdmi.c */
11211125
void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port);

drivers/gpu/drm/i915/intel_fbc.c

Lines changed: 54 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -174,29 +174,10 @@ static bool g4x_fbc_enabled(struct drm_device *dev)
174174
return I915_READ(DPFC_CONTROL) & DPFC_CTL_EN;
175175
}
176176

177-
static void snb_fbc_blit_update(struct drm_device *dev)
177+
static void intel_fbc_nuke(struct drm_i915_private *dev_priv)
178178
{
179-
struct drm_i915_private *dev_priv = dev->dev_private;
180-
u32 blt_ecoskpd;
181-
182-
/* Make sure blitter notifies FBC of writes */
183-
184-
/* Blitter is part of Media powerwell on VLV. No impact of
185-
* his param in other platforms for now */
186-
intel_uncore_forcewake_get(dev_priv, FORCEWAKE_MEDIA);
187-
188-
blt_ecoskpd = I915_READ(GEN6_BLITTER_ECOSKPD);
189-
blt_ecoskpd |= GEN6_BLITTER_FBC_NOTIFY <<
190-
GEN6_BLITTER_LOCK_SHIFT;
191-
I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd);
192-
blt_ecoskpd |= GEN6_BLITTER_FBC_NOTIFY;
193-
I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd);
194-
blt_ecoskpd &= ~(GEN6_BLITTER_FBC_NOTIFY <<
195-
GEN6_BLITTER_LOCK_SHIFT);
196-
I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd);
197-
POSTING_READ(GEN6_BLITTER_ECOSKPD);
198-
199-
intel_uncore_forcewake_put(dev_priv, FORCEWAKE_MEDIA);
179+
I915_WRITE(MSG_FBC_REND_STATE, FBC_REND_NUKE);
180+
POSTING_READ(MSG_FBC_REND_STATE);
200181
}
201182

202183
static void ilk_fbc_enable(struct drm_crtc *crtc)
@@ -239,9 +220,10 @@ static void ilk_fbc_enable(struct drm_crtc *crtc)
239220
I915_WRITE(SNB_DPFC_CTL_SA,
240221
SNB_CPU_FENCE_ENABLE | obj->fence_reg);
241222
I915_WRITE(DPFC_CPU_FENCE_OFFSET, crtc->y);
242-
snb_fbc_blit_update(dev);
243223
}
244224

225+
intel_fbc_nuke(dev_priv);
226+
245227
DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(intel_crtc->plane));
246228
}
247229

@@ -320,7 +302,7 @@ static void gen7_fbc_enable(struct drm_crtc *crtc)
320302
SNB_CPU_FENCE_ENABLE | obj->fence_reg);
321303
I915_WRITE(DPFC_CPU_FENCE_OFFSET, crtc->y);
322304

323-
snb_fbc_blit_update(dev);
305+
intel_fbc_nuke(dev_priv);
324306

325307
DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(intel_crtc->plane));
326308
}
@@ -340,19 +322,6 @@ bool intel_fbc_enabled(struct drm_device *dev)
340322
return dev_priv->fbc.enabled;
341323
}
342324

343-
void bdw_fbc_sw_flush(struct drm_device *dev, u32 value)
344-
{
345-
struct drm_i915_private *dev_priv = dev->dev_private;
346-
347-
if (!IS_GEN8(dev))
348-
return;
349-
350-
if (!intel_fbc_enabled(dev))
351-
return;
352-
353-
I915_WRITE(MSG_FBC_REND_STATE, value);
354-
}
355-
356325
static void intel_fbc_work_fn(struct work_struct *__work)
357326
{
358327
struct intel_fbc_work *work =
@@ -685,6 +654,44 @@ void intel_fbc_update(struct drm_device *dev)
685654
i915_gem_stolen_cleanup_compression(dev);
686655
}
687656

657+
void intel_fbc_invalidate(struct drm_i915_private *dev_priv,
658+
unsigned int frontbuffer_bits,
659+
enum fb_op_origin origin)
660+
{
661+
struct drm_device *dev = dev_priv->dev;
662+
unsigned int fbc_bits;
663+
664+
if (origin == ORIGIN_GTT)
665+
return;
666+
667+
if (dev_priv->fbc.enabled)
668+
fbc_bits = INTEL_FRONTBUFFER_PRIMARY(dev_priv->fbc.crtc->pipe);
669+
else if (dev_priv->fbc.fbc_work)
670+
fbc_bits = INTEL_FRONTBUFFER_PRIMARY(
671+
to_intel_crtc(dev_priv->fbc.fbc_work->crtc)->pipe);
672+
else
673+
fbc_bits = dev_priv->fbc.possible_framebuffer_bits;
674+
675+
dev_priv->fbc.busy_bits |= (fbc_bits & frontbuffer_bits);
676+
677+
if (dev_priv->fbc.busy_bits)
678+
intel_fbc_disable(dev);
679+
}
680+
681+
void intel_fbc_flush(struct drm_i915_private *dev_priv,
682+
unsigned int frontbuffer_bits)
683+
{
684+
struct drm_device *dev = dev_priv->dev;
685+
686+
if (!dev_priv->fbc.busy_bits)
687+
return;
688+
689+
dev_priv->fbc.busy_bits &= ~frontbuffer_bits;
690+
691+
if (!dev_priv->fbc.busy_bits)
692+
intel_fbc_update(dev);
693+
}
694+
688695
/**
689696
* intel_fbc_init - Initialize FBC
690697
* @dev_priv: the i915 device
@@ -693,12 +700,22 @@ void intel_fbc_update(struct drm_device *dev)
693700
*/
694701
void intel_fbc_init(struct drm_i915_private *dev_priv)
695702
{
703+
enum pipe pipe;
704+
696705
if (!HAS_FBC(dev_priv)) {
697706
dev_priv->fbc.enabled = false;
698707
dev_priv->fbc.no_fbc_reason = FBC_UNSUPPORTED;
699708
return;
700709
}
701710

711+
for_each_pipe(dev_priv, pipe) {
712+
dev_priv->fbc.possible_framebuffer_bits |=
713+
INTEL_FRONTBUFFER_PRIMARY(pipe);
714+
715+
if (IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8)
716+
break;
717+
}
718+
702719
if (INTEL_INFO(dev_priv)->gen >= 7) {
703720
dev_priv->display.fbc_enabled = ilk_fbc_enabled;
704721
dev_priv->display.enable_fbc = gen7_fbc_enable;

drivers/gpu/drm/i915/intel_frontbuffer.c

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,6 @@ static void intel_mark_fb_busy(struct drm_device *dev,
118118
continue;
119119

120120
intel_increase_pllclock(dev, pipe);
121-
if (ring && intel_fbc_enabled(dev))
122-
ring->fbc_dirty = true;
123121
}
124122
}
125123

@@ -160,6 +158,7 @@ void intel_fb_obj_invalidate(struct drm_i915_gem_object *obj,
160158

161159
intel_psr_invalidate(dev, obj->frontbuffer_bits);
162160
intel_edp_drrs_invalidate(dev, obj->frontbuffer_bits);
161+
intel_fbc_invalidate(dev_priv, obj->frontbuffer_bits, origin);
163162
}
164163

165164
/**
@@ -187,16 +186,7 @@ void intel_frontbuffer_flush(struct drm_device *dev,
187186

188187
intel_edp_drrs_flush(dev, frontbuffer_bits);
189188
intel_psr_flush(dev, frontbuffer_bits);
190-
191-
/*
192-
* FIXME: Unconditional fbc flushing here is a rather gross hack and
193-
* needs to be reworked into a proper frontbuffer tracking scheme like
194-
* psr employs.
195-
*/
196-
if (dev_priv->fbc.need_sw_cache_clean) {
197-
dev_priv->fbc.need_sw_cache_clean = false;
198-
bdw_fbc_sw_flush(dev, FBC_REND_CACHE_CLEAN);
199-
}
189+
intel_fbc_flush(dev_priv, frontbuffer_bits);
200190
}
201191

202192
/**

drivers/gpu/drm/i915/intel_ringbuffer.c

Lines changed: 2 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -317,29 +317,6 @@ gen7_render_ring_cs_stall_wa(struct intel_engine_cs *ring)
317317
return 0;
318318
}
319319

320-
static int gen7_ring_fbc_flush(struct intel_engine_cs *ring, u32 value)
321-
{
322-
int ret;
323-
324-
if (!ring->fbc_dirty)
325-
return 0;
326-
327-
ret = intel_ring_begin(ring, 6);
328-
if (ret)
329-
return ret;
330-
/* WaFbcNukeOn3DBlt:ivb/hsw */
331-
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
332-
intel_ring_emit(ring, MSG_FBC_REND_STATE);
333-
intel_ring_emit(ring, value);
334-
intel_ring_emit(ring, MI_STORE_REGISTER_MEM(1) | MI_SRM_LRM_GLOBAL_GTT);
335-
intel_ring_emit(ring, MSG_FBC_REND_STATE);
336-
intel_ring_emit(ring, ring->scratch.gtt_offset + 256);
337-
intel_ring_advance(ring);
338-
339-
ring->fbc_dirty = false;
340-
return 0;
341-
}
342-
343320
static int
344321
gen7_render_ring_flush(struct intel_engine_cs *ring,
345322
u32 invalidate_domains, u32 flush_domains)
@@ -398,9 +375,6 @@ gen7_render_ring_flush(struct intel_engine_cs *ring,
398375
intel_ring_emit(ring, 0);
399376
intel_ring_advance(ring);
400377

401-
if (!invalidate_domains && flush_domains)
402-
return gen7_ring_fbc_flush(ring, FBC_REND_NUKE);
403-
404378
return 0;
405379
}
406380

@@ -462,9 +436,6 @@ gen8_render_ring_flush(struct intel_engine_cs *ring,
462436
if (ret)
463437
return ret;
464438

465-
if (!invalidate_domains && flush_domains)
466-
return gen7_ring_fbc_flush(ring, FBC_REND_NUKE);
467-
468439
return 0;
469440
}
470441

@@ -2477,7 +2448,6 @@ static int gen6_ring_flush(struct intel_engine_cs *ring,
24772448
u32 invalidate, u32 flush)
24782449
{
24792450
struct drm_device *dev = ring->dev;
2480-
struct drm_i915_private *dev_priv = dev->dev_private;
24812451
uint32_t cmd;
24822452
int ret;
24832453

@@ -2486,7 +2456,7 @@ static int gen6_ring_flush(struct intel_engine_cs *ring,
24862456
return ret;
24872457

24882458
cmd = MI_FLUSH_DW;
2489-
if (INTEL_INFO(ring->dev)->gen >= 8)
2459+
if (INTEL_INFO(dev)->gen >= 8)
24902460
cmd += 1;
24912461

24922462
/* We always require a command barrier so that subsequent
@@ -2506,7 +2476,7 @@ static int gen6_ring_flush(struct intel_engine_cs *ring,
25062476
cmd |= MI_INVALIDATE_TLB;
25072477
intel_ring_emit(ring, cmd);
25082478
intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT);
2509-
if (INTEL_INFO(ring->dev)->gen >= 8) {
2479+
if (INTEL_INFO(dev)->gen >= 8) {
25102480
intel_ring_emit(ring, 0); /* upper addr */
25112481
intel_ring_emit(ring, 0); /* value */
25122482
} else {
@@ -2515,13 +2485,6 @@ static int gen6_ring_flush(struct intel_engine_cs *ring,
25152485
}
25162486
intel_ring_advance(ring);
25172487

2518-
if (!invalidate && flush) {
2519-
if (IS_GEN7(dev))
2520-
return gen7_ring_fbc_flush(ring, FBC_REND_CACHE_CLEAN);
2521-
else if (IS_BROADWELL(dev))
2522-
dev_priv->fbc.need_sw_cache_clean = true;
2523-
}
2524-
25252488
return 0;
25262489
}
25272490

drivers/gpu/drm/i915/intel_ringbuffer.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,6 @@ struct intel_engine_cs {
267267
*/
268268
struct drm_i915_gem_request *outstanding_lazy_request;
269269
bool gpu_caches_dirty;
270-
bool fbc_dirty;
271270

272271
wait_queue_head_t irq_queue;
273272

0 commit comments

Comments
 (0)