summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2017-09-18 15:17:31 -0700
committerJuan A. Suarez Romero <jasuarez@igalia.com>2017-09-20 22:54:11 +0200
commitf6469ac143a7ebff31fb5c5490d0cfa646cd1e22 (patch)
treebf50856aff629fe31be88feebfe055109c92ea7d
parent727a6a8cddaf31ab422dde649752c9cbee54c7c6 (diff)
broadcom/vc4: Fix use-after-free trying to mix a quad and tile clear.
The blitter will bind just the depth buffer, which flushes the current job if we had both a color and depth/stencil. If the clear was doing partial depth/stencil (quad-based) and color (tile-based), we'd go on to try to set up the rest of the tile clear in the now flushed job. Instead, move the partial clear up before we start setting up the job for the current FBO state, and re-fetch the job if we're continuing on to a tile-based clear. Fixes valgrind failures in fbo-depthtex. Fixes: 9421a6065c4e ("vc4: Fix fallback to quad clears of depth in GLX.") (cherry picked from commit 9940fb42058e0b0815e0edb202ca69b7853aead5)
-rw-r--r--src/gallium/drivers/vc4/vc4_draw.c56
1 files changed, 32 insertions, 24 deletions
diff --git a/src/gallium/drivers/vc4/vc4_draw.c b/src/gallium/drivers/vc4/vc4_draw.c
index ebd080298a4..a6248239680 100644
--- a/src/gallium/drivers/vc4/vc4_draw.c
+++ b/src/gallium/drivers/vc4/vc4_draw.c
@@ -495,6 +495,37 @@ vc4_clear(struct pipe_context *pctx, unsigned buffers,
struct vc4_context *vc4 = vc4_context(pctx);
struct vc4_job *job = vc4_get_job_for_fbo(vc4);
+ if (buffers & PIPE_CLEAR_DEPTHSTENCIL) {
+ struct vc4_resource *rsc =
+ vc4_resource(vc4->framebuffer.zsbuf->texture);
+ unsigned zsclear = buffers & PIPE_CLEAR_DEPTHSTENCIL;
+
+ /* Clearing ZS will clear both Z and stencil, so if we're
+ * trying to clear just one then we need to draw a quad to do
+ * it instead. We need to do this before setting up
+ * tile-based clears in vc4->job, because the blitter may
+ * submit the current job.
+ */
+ if ((zsclear == PIPE_CLEAR_DEPTH ||
+ zsclear == PIPE_CLEAR_STENCIL) &&
+ (rsc->initialized_buffers & ~(zsclear | job->cleared)) &&
+ util_format_is_depth_and_stencil(vc4->framebuffer.zsbuf->format)) {
+ perf_debug("Partial clear of Z+stencil buffer, "
+ "drawing a quad instead of fast clearing\n");
+ vc4_blitter_save(vc4);
+ util_blitter_clear(vc4->blitter,
+ vc4->framebuffer.width,
+ vc4->framebuffer.height,
+ 1,
+ zsclear,
+ NULL, depth, stencil);
+ buffers &= ~zsclear;
+ if (!buffers)
+ return;
+ job = vc4_get_job_for_fbo(vc4);
+ }
+ }
+
/* We can't flag new buffers for clearing once we've queued draws. We
* could avoid this by using the 3d engine to clear.
*/
@@ -530,29 +561,6 @@ vc4_clear(struct pipe_context *pctx, unsigned buffers,
if (buffers & PIPE_CLEAR_DEPTHSTENCIL) {
struct vc4_resource *rsc =
vc4_resource(vc4->framebuffer.zsbuf->texture);
- unsigned zsclear = buffers & PIPE_CLEAR_DEPTHSTENCIL;
-
- /* Clearing ZS will clear both Z and stencil, so if we're
- * trying to clear just one then we need to draw a quad to do
- * it instead.
- */
- if ((zsclear == PIPE_CLEAR_DEPTH ||
- zsclear == PIPE_CLEAR_STENCIL) &&
- (rsc->initialized_buffers & ~(zsclear | job->cleared)) &&
- util_format_is_depth_and_stencil(vc4->framebuffer.zsbuf->format)) {
- perf_debug("Partial clear of Z+stencil buffer, "
- "drawing a quad instead of fast clearing\n");
- vc4_blitter_save(vc4);
- util_blitter_clear(vc4->blitter,
- vc4->framebuffer.width,
- vc4->framebuffer.height,
- 1,
- zsclear,
- NULL, depth, stencil);
- buffers &= ~zsclear;
- if (!buffers)
- return;
- }
/* Though the depth buffer is stored with Z in the high 24,
* for this field we just need to store it in the low 24.
@@ -564,7 +572,7 @@ vc4_clear(struct pipe_context *pctx, unsigned buffers,
if (buffers & PIPE_CLEAR_STENCIL)
job->clear_stencil = stencil;
- rsc->initialized_buffers |= zsclear;
+ rsc->initialized_buffers |= (buffers & PIPE_CLEAR_DEPTHSTENCIL);
}
job->draw_min_x = 0;