diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2013-06-23 09:00:17 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2013-06-23 09:00:17 +0100 |
commit | 16fb786bd0791986fcac8b11a7e182090c5b6249 (patch) | |
tree | 2402baa973b1e985c00c48dac0aa13d59c7ac4aa /src/sna/gen5_render.c | |
parent | 9eabe28a4046b33772bcfe109346179b81294420 (diff) |
sna/gen5: Force a write flush when changing blend modes
Otherwise it appears that the hardware will readback from memory
bypassing its render cache after a change of modes. There is probably a
lot more subtly to it than this, but this appears to be a good first
approximation.
Reported-by: Clemens Eisserer <linuxhippy@gmail.com>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=51422
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src/sna/gen5_render.c')
-rw-r--r-- | src/sna/gen5_render.c | 32 |
1 files changed, 20 insertions, 12 deletions
diff --git a/src/sna/gen5_render.c b/src/sna/gen5_render.c index 11b90692..918c4f28 100644 --- a/src/sna/gen5_render.c +++ b/src/sna/gen5_render.c @@ -1009,9 +1009,20 @@ gen5_emit_state(struct sna *sna, const struct sna_composite_op *op, uint16_t offset) { + bool flush = false; + assert(op->dst.bo->exec); - if (kgem_bo_is_dirty(op->src.bo) || kgem_bo_is_dirty(op->mask.bo)) { + /* drawrect must be first for Ironlake BLT workaround */ + gen5_emit_drawing_rectangle(sna, op); + gen5_emit_binding_table(sna, offset & ~1); + if (gen5_emit_pipelined_pointers(sna, op, op->op, op->u.gen5.wm_kernel)){ + gen5_emit_urb(sna); + flush = (offset & 1) && op->op > PictOpSrc; + } + gen5_emit_vertex_elements(sna, op); + + if (flush || kgem_bo_is_dirty(op->src.bo) || kgem_bo_is_dirty(op->mask.bo)) { DBG(("%s: flushing dirty (%d, %d)\n", __FUNCTION__, kgem_bo_is_dirty(op->src.bo), kgem_bo_is_dirty(op->mask.bo))); @@ -1019,18 +1030,12 @@ gen5_emit_state(struct sna *sna, kgem_clear_dirty(&sna->kgem); kgem_bo_mark_dirty(op->dst.bo); } - - /* drawrect must be first for Ironlake BLT workaround */ - gen5_emit_drawing_rectangle(sna, op); - gen5_emit_binding_table(sna, offset); - if (gen5_emit_pipelined_pointers(sna, op, op->op, op->u.gen5.wm_kernel)) - gen5_emit_urb(sna); - gen5_emit_vertex_elements(sna, op); } static void gen5_bind_surfaces(struct sna *sna, const struct sna_composite_op *op) { + bool dirty = kgem_bo_is_dirty(op->dst.bo); uint32_t *binding_table; uint16_t offset; @@ -1067,7 +1072,7 @@ static void gen5_bind_surfaces(struct sna *sna, offset = sna->render_state.gen5.surface_table; } - gen5_emit_state(sna, op, offset); + gen5_emit_state(sna, op, offset | dirty); } fastcall static void @@ -1239,6 +1244,7 @@ static uint32_t gen5_bind_video_source(struct sna *sna, static void gen5_video_bind_surfaces(struct sna *sna, const struct sna_composite_op *op) { + bool dirty = kgem_bo_is_dirty(op->dst.bo); struct sna_video_frame *frame = op->priv; uint32_t src_surf_format; uint32_t src_surf_base[6]; @@ -1299,7 +1305,7 @@ static void gen5_video_bind_surfaces(struct sna *sna, src_surf_format); } - gen5_emit_state(sna, op, offset); + gen5_emit_state(sna, op, offset | dirty); } static bool @@ -2201,6 +2207,7 @@ static void gen5_copy_bind_surfaces(struct sna *sna, const struct sna_composite_op *op) { + bool dirty = kgem_bo_is_dirty(op->dst.bo); uint32_t *binding_table; uint16_t offset; @@ -2225,7 +2232,7 @@ gen5_copy_bind_surfaces(struct sna *sna, offset = sna->render_state.gen5.surface_table; } - gen5_emit_state(sna, op, offset); + gen5_emit_state(sna, op, offset | dirty); } static bool @@ -2537,6 +2544,7 @@ static void gen5_fill_bind_surfaces(struct sna *sna, const struct sna_composite_op *op) { + bool dirty = kgem_bo_is_dirty(op->dst.bo); uint32_t *binding_table; uint16_t offset; @@ -2562,7 +2570,7 @@ gen5_fill_bind_surfaces(struct sna *sna, offset = sna->render_state.gen5.surface_table; } - gen5_emit_state(sna, op, offset); + gen5_emit_state(sna, op, offset | dirty); } static inline bool prefer_blt_fill(struct sna *sna) |