FD_BUFFER_ALL = FD_BUFFER_COLOR | FD_BUFFER_DEPTH | FD_BUFFER_STENCIL,
} cleared, partial_cleared, restore, resolve;
- bool needs_flush;
+ bool needs_flush : 1;
+ bool blit : 1;
+ bool back_blit : 1; /* only blit so far is resource shadowing back-blit */
/* To decide whether to render to system memory, keep track of the
* number of draws, and whether any of them require multisample,
*/
struct fd_batch *batch;
+ /* Are we in process of shadowing a resource? Used to detect recursion
+ * in transfer_map, and skip unneeded synchronization.
+ */
+ bool in_shadow : 1;
+
+ /* Ie. in blit situation where we no longer care about previous framebuffer
+ * contents. Main point is to eliminate blits from fd_try_shadow_resource().
+ * For example, in case of texture upload + gen-mipmaps.
+ */
+ bool in_blit : 1;
+
/* Keep track if WAIT_FOR_IDLE is needed for registers we need
* to update via RMW:
*/
- bool needs_wfi;
+ bool needs_wfi : 1;
/* Do we need to re-emit RB_FRAME_BUFFER_DIMENSION? At least on a3xx
* it is not a banked context register, so it needs a WFI to update.
* Keep track if it has actually changed, to avoid unneeded WFI.
* */
- bool needs_rb_fbd;
+ bool needs_rb_fbd : 1;
struct pipe_scissor_state scissor;
bool cond_cond; /* inverted rendering condition */
uint cond_mode;
- /* Are we in process of shadowing a resource? Used to detect recursion
- * in transfer_map, and skip unneeded synchronization.
- */
- bool in_shadow;
-
- /* Ie. in blit situation where we no longer care about previous framebuffer
- * contents. Main point is to eliminate blits from fd_try_shadow_resource().
- * For example, in case of texture upload + gen-mipmaps.
- */
- bool discard;
-
struct pipe_debug_callback debug;
/* GMEM/tile handling fxns: */
return;
}
- if (ctx->discard) {
- fd_batch_reset(ctx->batch);
- ctx->discard = false;
+ if (ctx->in_blit) {
+ fd_batch_reset(batch);
+ ctx->dirty = ~0;
}
+ batch->blit = ctx->in_blit;
+ batch->back_blit = ctx->in_shadow;
+
/* NOTE: needs to be before resource_written(batch->query_buf), otherwise
* query_buf may not be created yet.
*/
fd_hw_query_set_stage(batch, batch->draw, FD_STAGE_DRAW);
+
/*
* Figure out the buffers/features we need:
*/
if (!fd_render_condition_check(pctx))
return;
- if (ctx->discard) {
- fd_batch_reset(ctx->batch);
- ctx->discard = false;
+ if (ctx->in_blit) {
+ fd_batch_reset(batch);
+ ctx->dirty = ~0;
}
/* for bookkeeping about which buffers have been cleared (and thus
* to wait.
*/
} else if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
+ if ((usage & PIPE_TRANSFER_WRITE) && rsc->write_batch &&
+ rsc->write_batch->back_blit) {
+ /* if only thing pending is a back-blit, we can discard it: */
+ fd_batch_reset(rsc->write_batch);
+ }
+
/* If the GPU is writing to the resource, or if it is reading from the
* resource and we're trying to write to it, flush the renders.
*/
if (ctx->batch)
fd_hw_query_set_stage(ctx->batch, ctx->batch->draw, FD_STAGE_BLIT);
- ctx->discard = discard;
+ ctx->in_blit = discard;
}
static void
{
if (ctx->batch)
fd_hw_query_set_stage(ctx->batch, ctx->batch->draw, FD_STAGE_NULL);
+ ctx->in_blit = false;
}
static void
struct pipe_framebuffer_state *cso;
if (ctx->screen->reorder) {
- struct fd_batch *batch;
- if (likely(ctx->batch))
- fd_hw_query_set_stage(ctx->batch, ctx->batch->draw, FD_STAGE_NULL);
+ struct fd_batch *batch, *old_batch = NULL;
+
+ fd_batch_reference(&old_batch, ctx->batch);
+
+ if (likely(old_batch))
+ fd_hw_query_set_stage(old_batch, old_batch->draw, FD_STAGE_NULL);
+
batch = fd_batch_from_fb(&ctx->screen->batch_cache, ctx, framebuffer);
fd_batch_reference(&ctx->batch, NULL);
ctx->batch = batch;
ctx->dirty = ~0;
+
+ if (old_batch && old_batch->blit && !old_batch->back_blit) {
+ /* for blits, there is not really much point in hanging on
+ * to the uncommitted batch (ie. you probably don't blit
+ * multiple times to the same surface), so we might as
+ * well go ahead and flush this one:
+ */
+ fd_batch_flush(old_batch);
+ }
+
+ fd_batch_reference(&old_batch, NULL);
} else {
DBG("%d: cbufs[0]=%p, zsbuf=%p", ctx->batch->needs_flush,
framebuffer->cbufs[0], framebuffer->zsbuf);