aboutsummaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/freedreno/freedreno_gmem.c
diff options
context:
space:
mode:
authorRob Clark <[email protected]>2014-10-21 10:30:49 -0400
committerRob Clark <[email protected]>2014-10-21 20:08:49 -0400
commit01b757e2b0fb97a146b0ef278b449cecab0d15e8 (patch)
treea2b0089ba5f796a23ecb558f88ab72ba17daaede /src/gallium/drivers/freedreno/freedreno_gmem.c
parent1ab6543431b5a4eaf589cdabf2227088dd62ce6f (diff)
freedreno: clear vs scissor
The optimization of avoiding restore (mem2gmem) if there was a clear falls down a bit if you don't have a fullscreen scissor. We need to make the decision logic a bit more clever to keep track of *what* was cleared, so that we can (a) completely skip mem2gmem if entire buffer was cleared, or (b) skip mem2gmem on a per-tile basis for tiles that were completely cleared. Signed-off-by: Rob Clark <[email protected]>
Diffstat (limited to 'src/gallium/drivers/freedreno/freedreno_gmem.c')
-rw-r--r--src/gallium/drivers/freedreno/freedreno_gmem.c48
1 files changed, 46 insertions, 2 deletions
diff --git a/src/gallium/drivers/freedreno/freedreno_gmem.c b/src/gallium/drivers/freedreno/freedreno_gmem.c
index 7e43c2e74ce..7f6c8476cdb 100644
--- a/src/gallium/drivers/freedreno/freedreno_gmem.c
+++ b/src/gallium/drivers/freedreno/freedreno_gmem.c
@@ -314,9 +314,8 @@ render_sysmem(struct fd_context *ctx)
}
void
-fd_gmem_render_tiles(struct pipe_context *pctx)
+fd_gmem_render_tiles(struct fd_context *ctx)
{
- struct fd_context *ctx = fd_context(pctx);
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
uint32_t timestamp = 0;
bool sysmem = false;
@@ -383,3 +382,48 @@ fd_gmem_render_tiles(struct pipe_context *pctx)
ctx->dirty = ~0;
}
+
+/* tile needs restore if it isn't completely contained within the
+ * cleared scissor:
+ */
+static bool
+skip_restore(struct pipe_scissor_state *scissor, struct fd_tile *tile)
+{
+ unsigned minx = tile->xoff;
+ unsigned maxx = tile->xoff + tile->bin_w;
+ unsigned miny = tile->yoff;
+ unsigned maxy = tile->yoff + tile->bin_h;
+ return (minx >= scissor->minx) && (maxx <= scissor->maxx) &&
+ (miny >= scissor->miny) && (maxy <= scissor->maxy);
+}
+
+/* When deciding whether a tile needs mem2gmem, we need to take into
+ * account the scissor rect(s) that were cleared. To simplify we only
+ * consider the last scissor rect for each buffer, since the common
+ * case would be a single clear.
+ */
+bool
+fd_gmem_needs_restore(struct fd_context *ctx, struct fd_tile *tile,
+ uint32_t buffers)
+{
+ if (!(ctx->restore & buffers))
+ return false;
+
+ /* if buffers partially cleared, then slow-path to figure out
+ * if this particular tile needs restoring:
+ */
+ if ((buffers & FD_BUFFER_COLOR) &&
+ (ctx->partial_cleared & FD_BUFFER_COLOR) &&
+ skip_restore(&ctx->cleared_scissor.color, tile))
+ return false;
+ if ((buffers & FD_BUFFER_DEPTH) &&
+ (ctx->partial_cleared & FD_BUFFER_DEPTH) &&
+ skip_restore(&ctx->cleared_scissor.depth, tile))
+ return false;
+ if ((buffers & FD_BUFFER_STENCIL) &&
+ (ctx->partial_cleared & FD_BUFFER_STENCIL) &&
+ skip_restore(&ctx->cleared_scissor.stencil, tile))
+ return false;
+
+ return true;
+}