+#if 0 /* debug */
+ t = 0;
+ for (i = 0; i < nbins_y; i++) {
+ for (j = 0; j < nbins_x; j++) {
+ struct fd_tile *tile = &ctx->tile[t++];
+ printf("|p:%u n:%u|", tile->p, tile->n);
+ }
+ printf("\n");
+ }
+#endif
+}
+
+static void
+render_tiles(struct fd_context *ctx)
+{
+ struct fd_gmem_stateobj *gmem = &ctx->gmem;
+ int i;
+
+ ctx->emit_tile_init(ctx);
+
+ if (ctx->restore)
+ ctx->stats.batch_restore++;
+
+ for (i = 0; i < (gmem->nbins_x * gmem->nbins_y); i++) {
+ struct fd_tile *tile = &ctx->tile[i];
+
+ DBG("bin_h=%d, yoff=%d, bin_w=%d, xoff=%d",
+ tile->bin_h, tile->yoff, tile->bin_w, tile->xoff);
+
+ ctx->emit_tile_prep(ctx, tile);
+
+ if (ctx->restore) {
+ fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_MEM2GMEM);
+ ctx->emit_tile_mem2gmem(ctx, tile);
+ fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_NULL);
+ }
+
+ ctx->emit_tile_renderprep(ctx, tile);
+
+ fd_hw_query_prepare_tile(ctx, i, ctx->ring);
+
+ /* emit IB to drawcmds: */
+ OUT_IB(ctx->ring, ctx->draw_start, ctx->draw_end);
+ fd_reset_wfi(ctx);
+
+ /* emit gmem2mem to transfer tile back to system memory: */
+ fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_GMEM2MEM);
+ ctx->emit_tile_gmem2mem(ctx, tile);
+ fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_NULL);
+ }
+}
+
+static void
+render_sysmem(struct fd_context *ctx)
+{
+ ctx->emit_sysmem_prep(ctx);
+
+ fd_hw_query_prepare_tile(ctx, 0, ctx->ring);
+
+ /* emit IB to drawcmds: */
+ OUT_IB(ctx->ring, ctx->draw_start, ctx->draw_end);
+ fd_reset_wfi(ctx);
+}
+
+void
+fd_gmem_render_tiles(struct fd_context *ctx)
+{
+ struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
+ uint32_t timestamp = 0;
+ bool sysmem = false;
+
+ if (ctx->emit_sysmem_prep) {
+ if (ctx->cleared || ctx->gmem_reason || (ctx->num_draws > 5)) {
+ DBG("GMEM: cleared=%x, gmem_reason=%x, num_draws=%u",
+ ctx->cleared, ctx->gmem_reason, ctx->num_draws);
+ } else if (!(fd_mesa_debug & FD_DBG_NOBYPASS)) {
+ sysmem = true;
+ }
+ }
+
+ /* close out the draw cmds by making sure any active queries are
+ * paused:
+ */
+ fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_NULL);
+
+ /* mark the end of the clear/draw cmds before emitting per-tile cmds: */
+ fd_ringmarker_mark(ctx->draw_end);
+ fd_ringmarker_mark(ctx->binning_end);
+
+ fd_reset_wfi(ctx);
+
+ ctx->stats.batch_total++;
+
+ if (sysmem) {
+ DBG("rendering sysmem (%s/%s)",
+ util_format_short_name(pipe_surface_format(pfb->cbufs[0])),
+ util_format_short_name(pipe_surface_format(pfb->zsbuf)));
+ fd_hw_query_prepare(ctx, 1);
+ render_sysmem(ctx);
+ ctx->stats.batch_sysmem++;
+ } else {
+ struct fd_gmem_stateobj *gmem = &ctx->gmem;
+ calculate_tiles(ctx);
+ DBG("rendering %dx%d tiles (%s/%s)", gmem->nbins_x, gmem->nbins_y,
+ util_format_short_name(pipe_surface_format(pfb->cbufs[0])),
+ util_format_short_name(pipe_surface_format(pfb->zsbuf)));
+ fd_hw_query_prepare(ctx, gmem->nbins_x * gmem->nbins_y);
+ render_tiles(ctx);
+ ctx->stats.batch_gmem++;
+ }
+