From 732b0b5ebc5a30b6e87f67aabfb0e25d3e662d41 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 6 Mar 2013 10:45:58 -0500 Subject: [PATCH] freedreno: track maximal scissor bounds Optimize out parts of the render target that are scissored out by taking into account maximal scissor bounds in fd_gmem_render_tiles(). This is a big win on things like gnome-shell which frequently do partial screen updates. Signed-off-by: Rob Clark --- .../drivers/freedreno/freedreno_clear.c | 7 +- .../drivers/freedreno/freedreno_context.c | 8 +- .../drivers/freedreno/freedreno_context.h | 21 +- .../drivers/freedreno/freedreno_gmem.c | 208 +++++++++++------- .../drivers/freedreno/freedreno_gmem.h | 1 - .../drivers/freedreno/freedreno_resource.c | 2 +- .../drivers/freedreno/freedreno_state.c | 41 +--- .../drivers/freedreno/freedreno_state.h | 2 - src/gallium/drivers/freedreno/freedreno_vbo.c | 8 +- 9 files changed, 162 insertions(+), 136 deletions(-) diff --git a/src/gallium/drivers/freedreno/freedreno_clear.c b/src/gallium/drivers/freedreno/freedreno_clear.c index 545e8ad3125..f3fd1a256dd 100644 --- a/src/gallium/drivers/freedreno/freedreno_clear.c +++ b/src/gallium/drivers/freedreno/freedreno_clear.c @@ -54,7 +54,7 @@ fd_clear(struct pipe_context *pctx, unsigned buffers, { struct fd_context *ctx = fd_context(pctx); struct fd_ringbuffer *ring = ctx->ring; - struct pipe_framebuffer_state *fb = &ctx->framebuffer.base; + struct pipe_framebuffer_state *fb = &ctx->framebuffer; uint32_t reg, colr = 0; ctx->cleared |= buffers; @@ -171,11 +171,6 @@ fd_clear(struct pipe_context *pctx, unsigned buffers, OUT_RING(ring, xy2d(fb->width, /* PA_SC_WINDOW_SCISSOR_BR */ fb->height)); - OUT_PKT3(ring, CP_SET_CONSTANT, 2); - OUT_RING(ring, CP_REG(REG_RB_COLOR_INFO)); - OUT_RING(ring, RB_COLOR_INFO_COLOR_SWAP(1) | - RB_COLOR_INFO_COLOR_FORMAT(fd_pipe2color(fb->cbufs[0]->format))); - OUT_PKT3(ring, CP_SET_CONSTANT, 2); OUT_RING(ring, CP_REG(REG_RB_COLOR_MASK)); if (buffers & PIPE_CLEAR_COLOR) { diff --git a/src/gallium/drivers/freedreno/freedreno_context.c b/src/gallium/drivers/freedreno/freedreno_context.c index cac10b70c9c..4753f58d12d 100644 --- a/src/gallium/drivers/freedreno/freedreno_context.c +++ b/src/gallium/drivers/freedreno/freedreno_context.c @@ -69,7 +69,7 @@ void fd_context_render(struct pipe_context *pctx) { struct fd_context *ctx = fd_context(pctx); - struct pipe_framebuffer_state *fb = &ctx->framebuffer.base; + struct pipe_framebuffer_state *pfb = &ctx->framebuffer; DBG("needs_flush: %d", ctx->needs_flush); @@ -89,9 +89,9 @@ fd_context_render(struct pipe_context *pctx) ctx->needs_flush = false; ctx->cleared = ctx->restore = ctx->resolve = 0; - fd_resource(fb->cbufs[0]->texture)->dirty = false; - if (fb->zsbuf) - fd_resource(fb->zsbuf->texture)->dirty = false; + fd_resource(pfb->cbufs[0]->texture)->dirty = false; + if (pfb->zsbuf) + fd_resource(pfb->zsbuf->texture)->dirty = false; } static void diff --git a/src/gallium/drivers/freedreno/freedreno_context.h b/src/gallium/drivers/freedreno/freedreno_context.h index 6fff8f611b4..4ed31593d41 100644 --- a/src/gallium/drivers/freedreno/freedreno_context.h +++ b/src/gallium/drivers/freedreno/freedreno_context.h @@ -79,11 +79,13 @@ struct fd_vertexbuf_stateobj { uint32_t dirty_mask; }; -struct fd_framebuffer_stateobj { - struct pipe_framebuffer_state base; +struct fd_gmem_stateobj { + struct pipe_scissor_state scissor; + uint cpp; + uint16_t minx, miny; uint16_t bin_h, nbins_y; uint16_t bin_w, nbins_x; - uint32_t pa_su_sc_mode_cntl; + uint16_t width, height; }; struct fd_context { @@ -129,6 +131,17 @@ struct fd_context { */ struct pipe_scissor_state scissor; + /* Track the maximal bounds of the scissor of all the draws within a + * batch. Used at the tile rendering step (fd_gmem_render_tiles(), + * mem2gmem/gmem2mem) to avoid needlessly moving data in/out of gmem. + */ + struct pipe_scissor_state max_scissor; + + /* Current gmem/tiling configuration.. gets updated on render_tiles() + * if out of date with current maximal-scissor/cpp: + */ + struct fd_gmem_stateobj gmem; + /* which state objects need to be re-emit'd: */ enum { FD_DIRTY_BLEND = (1 << 0), @@ -163,7 +176,7 @@ struct fd_context { struct pipe_blend_color blend_color; struct pipe_stencil_ref stencil_ref; unsigned sample_mask; - struct fd_framebuffer_stateobj framebuffer; + struct pipe_framebuffer_state framebuffer; struct pipe_poly_stipple stipple; struct pipe_viewport_state viewport; struct fd_constbuf_stateobj constbuf[PIPE_SHADER_TYPES]; diff --git a/src/gallium/drivers/freedreno/freedreno_gmem.c b/src/gallium/drivers/freedreno/freedreno_gmem.c index 52b637629f2..896e434a927 100644 --- a/src/gallium/drivers/freedreno/freedreno_gmem.c +++ b/src/gallium/drivers/freedreno/freedreno_gmem.c @@ -110,8 +110,7 @@ static void emit_gmem2mem(struct fd_context *ctx, struct fd_ringbuffer *ring, uint32_t xoff, uint32_t yoff, uint32_t bin_w, uint32_t bin_h) { - struct fd_framebuffer_stateobj *fb = &ctx->framebuffer; - struct pipe_framebuffer_state *pfb = &fb->base; + struct pipe_framebuffer_state *pfb = &ctx->framebuffer; fd_emit_vertex_bufs(ring, 0x9c, (struct fd_vertex_buf[]) { { .prsc = ctx->solid_vertexbuf, .size = 48 }, @@ -224,8 +223,7 @@ static void emit_mem2gmem(struct fd_context *ctx, struct fd_ringbuffer *ring, uint32_t xoff, uint32_t yoff, uint32_t bin_w, uint32_t bin_h) { - struct fd_framebuffer_stateobj *fb = &ctx->framebuffer; - struct pipe_framebuffer_state *pfb = &fb->base; + struct pipe_framebuffer_state *pfb = &ctx->framebuffer; float x0, y0, x1, y1; fd_emit_vertex_bufs(ring, 0x9c, (struct fd_vertex_buf[]) { @@ -328,50 +326,146 @@ emit_mem2gmem(struct fd_context *ctx, struct fd_ringbuffer *ring, /* TODO blob driver seems to toss in a CACHE_FLUSH after each DRAW_INDX.. */ } +static void +calculate_tiles(struct fd_context *ctx) +{ + struct fd_gmem_stateobj *gmem = &ctx->gmem; + struct pipe_scissor_state *scissor = &ctx->max_scissor; + uint32_t cpp = util_format_get_blocksize(ctx->framebuffer.cbufs[0]->format); + uint32_t gmem_size = ctx->screen->gmemsize_bytes; + uint32_t minx, miny, width, height; + uint32_t nbins_x = 1, nbins_y = 1; + uint32_t bin_w, bin_h; + uint32_t max_width = 992; + + if ((gmem->cpp == cpp) && + !memcmp(&gmem->scissor, scissor, sizeof(gmem->scissor))) { + /* everything is up-to-date */ + return; + } + + minx = scissor->minx & ~31; /* round down to multiple of 32 */ + miny = scissor->miny & ~31; + width = scissor->maxx - minx; + height = scissor->maxy - miny; + +// TODO we probably could optimize this a bit if we know that +// Z or stencil is not enabled for any of the draw calls.. +// if (fd_stencil_enabled(ctx->zsa) || fd_depth_enabled(ctx->zsa)) { + gmem_size /= 2; + max_width = 256; +// } + + bin_w = ALIGN(width, 32); + bin_h = ALIGN(height, 32); + + /* first, find a bin width that satisfies the maximum width + * restrictions: + */ + while (bin_w > max_width) { + nbins_x++; + bin_w = ALIGN(width / nbins_x, 32); + } + + /* then find a bin height that satisfies the memory constraints: + */ + while ((bin_w * bin_h * cpp) > gmem_size) { + nbins_y++; + bin_h = ALIGN(height / nbins_y, 32); + } + + DBG("using %d bins of size %dx%d", nbins_x*nbins_y, bin_w, bin_h); + + gmem->scissor = *scissor; + gmem->cpp = cpp; + gmem->minx = minx; + gmem->miny = miny; + gmem->bin_h = bin_h; + gmem->bin_w = bin_w; + gmem->nbins_x = nbins_x; + gmem->nbins_y = nbins_y; + gmem->width = width; + gmem->height = height; +} + void fd_gmem_render_tiles(struct pipe_context *pctx) { struct fd_context *ctx = fd_context(pctx); - struct fd_framebuffer_stateobj *fb = &ctx->framebuffer; - struct pipe_framebuffer_state *pfb = &fb->base; - struct fd_ringbuffer *ring; - uint32_t i, yoff = 0; - uint32_t timestamp; - ring = ctx->ring; - - DBG("rendering %dx%d tiles (%s/%s)", fb->nbins_x, fb->nbins_y, + struct pipe_framebuffer_state *pfb = &ctx->framebuffer; + struct fd_gmem_stateobj *gmem = &ctx->gmem; + struct fd_ringbuffer *ring = ctx->ring; + enum rb_colorformatx colorformatx = fd_pipe2color(pfb->cbufs[0]->format); + uint32_t i, timestamp, yoff = 0; + uint32_t base, reg; + + calculate_tiles(ctx); + + /* this should be true because bin_w/bin_h should be multiples of 32: */ + assert(((gmem->bin_w * gmem->bin_h) % 1024) == 0); + + /* depth/stencil starts after color buffer in GMEM: */ + base = (gmem->bin_w * gmem->bin_h) / 1024; + + DBG("rendering %dx%d tiles (%s/%s)", gmem->nbins_x, gmem->nbins_y, util_format_name(pfb->cbufs[0]->format), pfb->zsbuf ? util_format_name(pfb->zsbuf->format) : "none"); /* mark the end of the clear/draw cmds before emitting per-tile cmds: */ fd_ringmarker_mark(ctx->draw_end); - for (i = 0; i < fb->nbins_y; i++) { - uint32_t j, xoff = 0; - uint32_t bin_h = fb->bin_h; + /* RB_SURFACE_INFO / RB_DEPTH_INFO can be emitted once per tile pass, + * but RB_COLOR_INFO gets overwritten by gmem2mem and mem2gmem and so + * needs to be emitted for each tile: + */ + OUT_PKT3(ring, CP_SET_CONSTANT, 4); + OUT_RING(ring, CP_REG(REG_RB_SURFACE_INFO)); + OUT_RING(ring, gmem->bin_w); /* RB_SURFACE_INFO */ + OUT_RING(ring, RB_COLOR_INFO_COLOR_SWAP(1) | /* RB_COLOR_INFO */ + RB_COLOR_INFO_COLOR_FORMAT(colorformatx)); + reg = RB_DEPTH_INFO_DEPTH_BASE(ALIGN(base, 4)); + if (pfb->zsbuf) + reg |= RB_DEPTH_INFO_DEPTH_FORMAT(fd_pipe2depth(pfb->zsbuf->format)); + OUT_RING(ring, reg); /* RB_DEPTH_INFO */ + + yoff= gmem->miny; + for (i = 0; i < gmem->nbins_y; i++) { + uint32_t j, xoff = gmem->minx; + uint32_t bh = gmem->bin_h; /* clip bin height: */ - bin_h = min(bin_h, pfb->height - yoff); + bh = min(bh, gmem->height - yoff); - for (j = 0; j < fb->nbins_x; j++) { - uint32_t bin_w = fb->bin_w; + for (j = 0; j < gmem->nbins_x; j++) { + uint32_t bw = gmem->bin_w; /* clip bin width: */ - bin_w = min(bin_w, pfb->width - xoff); + bw = min(bw, gmem->width - xoff); DBG("bin_h=%d, yoff=%d, bin_w=%d, xoff=%d", - bin_h, yoff, bin_w, xoff); + bh, yoff, bw, xoff); + + if ((i == 0) && (j == 0)) { + uint32_t reg; - fd_emit_framebuffer_state(ring, &ctx->framebuffer); + + } else { + + } /* setup screen scissor for current tile (same for mem2gmem): */ OUT_PKT3(ring, CP_SET_CONSTANT, 3); OUT_RING(ring, CP_REG(REG_PA_SC_SCREEN_SCISSOR_TL)); OUT_RING(ring, xy2d(0,0)); /* PA_SC_SCREEN_SCISSOR_TL */ - OUT_RING(ring, xy2d(bin_w, bin_h)); /* PA_SC_SCREEN_SCISSOR_BR */ + OUT_RING(ring, xy2d(bw, bh)); /* PA_SC_SCREEN_SCISSOR_BR */ if (ctx->restore) - emit_mem2gmem(ctx, ring, xoff, yoff, bin_w, bin_h); + emit_mem2gmem(ctx, ring, xoff, yoff, bw, bh); + + OUT_PKT3(ring, CP_SET_CONSTANT, 2); + OUT_RING(ring, CP_REG(REG_RB_COLOR_INFO)); + OUT_RING(ring, RB_COLOR_INFO_COLOR_SWAP(1) | /* RB_COLOR_INFO */ + RB_COLOR_INFO_COLOR_FORMAT(colorformatx)); /* setup window scissor and offset for current tile (different * from mem2gmem): @@ -389,12 +483,12 @@ fd_gmem_render_tiles(struct pipe_context *pctx) OUT_RING(ring, 0x00000000); /* PA_SC_WINDOW_OFFSET */ /* emit gmem2mem to transfer tile back to system memory: */ - emit_gmem2mem(ctx, ring, xoff, yoff, bin_w, bin_h); + emit_gmem2mem(ctx, ring, xoff, yoff, bw, bh); - xoff += bin_w; + xoff += bw; } - yoff += bin_h; + yoff += bh; } /* GPU executes starting from tile cmds, which IB back to draw cmds: */ @@ -409,6 +503,10 @@ fd_gmem_render_tiles(struct pipe_context *pctx) if (pfb->zsbuf) fd_resource(pfb->zsbuf->texture)->timestamp = timestamp; + /* reset maximal bounds: */ + ctx->max_scissor.minx = ctx->max_scissor.miny = ~0; + ctx->max_scissor.maxx = ctx->max_scissor.maxy = 0; + /* Note that because the per-tile setup and mem2gmem/gmem2mem are emitted * after the draw/clear calls, but executed before, we need to preemptively * flag some state as dirty before the first draw/clear call. @@ -431,61 +529,3 @@ fd_gmem_render_tiles(struct pipe_context *pctx) FD_DIRTY_FRAGTEX | FD_DIRTY_BLEND; } - -void -fd_gmem_calculate_tiles(struct pipe_context *pctx) -{ - struct fd_context *ctx = fd_context(pctx); - struct fd_framebuffer_stateobj *fb = &ctx->framebuffer; - struct pipe_framebuffer_state *pfb = &fb->base; - uint32_t nbins_x = 1, nbins_y = 1; - uint32_t bin_w, bin_h; - uint32_t cpp = util_format_get_blocksize(pfb->cbufs[0]->format); - uint32_t gmem_size = ctx->screen->gmemsize_bytes; - uint32_t max_width = 992; - -// TODO we probably could optimize this a bit if we know that -// Z or stencil is not enabled for any of the draw calls.. -// if (fd_stencil_enabled(ctx->zsa) || fd_depth_enabled(ctx->zsa)) { - gmem_size /= 2; - max_width = 256; -// } - - bin_w = ALIGN(pfb->width, 32); - bin_h = ALIGN(pfb->height, 32); - - /* first, find a bin width that satisfies the maximum width - * restrictions: - */ - while (bin_w > max_width) { - nbins_x++; - bin_w = ALIGN(pfb->width / nbins_x, 32); - } - - /* then find a bin height that satisfies the memory constraints: - */ - while ((bin_w * bin_h * cpp) > gmem_size) { - nbins_y++; - bin_h = ALIGN(pfb->height / nbins_y, 32); - } - - if ((nbins_x > 1) || (nbins_y > 1)) { - fb->pa_su_sc_mode_cntl |= PA_SU_SC_MODE_CNTL_VTX_WINDOW_OFFSET_ENABLE; - } else { - fb->pa_su_sc_mode_cntl &= ~PA_SU_SC_MODE_CNTL_VTX_WINDOW_OFFSET_ENABLE; - } - - DBG("using %d bins of size %dx%d", nbins_x*nbins_y, bin_w, bin_h); - -//if we use hw binning, tile sizes (in multiple of 32) need to -//fit in 5 bits.. for now don't care because we aren't using -//that: -// assert(!(bin_h/32 & ~0x1f)); -// assert(!(bin_w/32 & ~0x1f)); - - fb->nbins_x = nbins_x; - fb->nbins_y = nbins_y; - fb->bin_w = bin_w; - fb->bin_h = bin_h; - -} diff --git a/src/gallium/drivers/freedreno/freedreno_gmem.h b/src/gallium/drivers/freedreno/freedreno_gmem.h index 7b46f6b5e4e..0c978a4d0a0 100644 --- a/src/gallium/drivers/freedreno/freedreno_gmem.h +++ b/src/gallium/drivers/freedreno/freedreno_gmem.h @@ -32,6 +32,5 @@ #include "pipe/p_context.h" void fd_gmem_render_tiles(struct pipe_context *pctx); -void fd_gmem_calculate_tiles(struct pipe_context *pctx); #endif /* FREEDRENO_GMEM_H_ */ diff --git a/src/gallium/drivers/freedreno/freedreno_resource.c b/src/gallium/drivers/freedreno/freedreno_resource.c index 5159003db85..d89650a0636 100644 --- a/src/gallium/drivers/freedreno/freedreno_resource.c +++ b/src/gallium/drivers/freedreno/freedreno_resource.c @@ -260,7 +260,7 @@ fd_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info) util_blitter_save_depth_stencil_alpha(ctx->blitter, ctx->zsa); util_blitter_save_stencil_ref(ctx->blitter, &ctx->stencil_ref); util_blitter_save_sample_mask(ctx->blitter, ctx->sample_mask); - util_blitter_save_framebuffer(ctx->blitter, &ctx->framebuffer.base); + util_blitter_save_framebuffer(ctx->blitter, &ctx->framebuffer); util_blitter_save_fragment_sampler_states(ctx->blitter, ctx->fragtex.num_samplers, (void **)ctx->fragtex.samplers); diff --git a/src/gallium/drivers/freedreno/freedreno_state.c b/src/gallium/drivers/freedreno/freedreno_state.c index 529e246514c..fcb04daabca 100644 --- a/src/gallium/drivers/freedreno/freedreno_state.c +++ b/src/gallium/drivers/freedreno/freedreno_state.c @@ -115,7 +115,7 @@ fd_set_framebuffer_state(struct pipe_context *pctx, const struct pipe_framebuffer_state *framebuffer) { struct fd_context *ctx = fd_context(pctx); - struct pipe_framebuffer_state *cso = &ctx->framebuffer.base; + struct pipe_framebuffer_state *cso = &ctx->framebuffer; unsigned i; DBG("%d: cbufs[0]=%p, zsbuf=%p", ctx->needs_flush, @@ -125,7 +125,7 @@ fd_set_framebuffer_state(struct pipe_context *pctx, for (i = 0; i < framebuffer->nr_cbufs; i++) pipe_surface_reference(&cso->cbufs[i], framebuffer->cbufs[i]); - for (; i < ctx->framebuffer.base.nr_cbufs; i++) + for (; i < ctx->framebuffer.nr_cbufs; i++) pipe_surface_reference(&cso->cbufs[i], NULL); cso->nr_cbufs = framebuffer->nr_cbufs; @@ -134,9 +134,6 @@ fd_set_framebuffer_state(struct pipe_context *pctx, pipe_surface_reference(&cso->zsbuf, framebuffer->zsbuf); - if (cso->nr_cbufs > 0) - fd_gmem_calculate_tiles(pctx); - ctx->dirty |= FD_DIRTY_FRAMEBUFFER; } @@ -354,30 +351,6 @@ fd_emit_vertex_bufs(struct fd_ringbuffer *ring, uint32_t val, } } -void -fd_emit_framebuffer_state(struct fd_ringbuffer *ring, - struct fd_framebuffer_stateobj *fb) -{ - struct pipe_framebuffer_state *pfb = &fb->base; - uint32_t reg, base; - - /* this should be true because bin_w/bin_h should be multiples of 32: */ - assert(((fb->bin_w * fb->bin_h) % 1024) == 0); - - /* depth/stencil starts after color buffer in GMEM: */ - base = (fb->bin_w * fb->bin_h) / 1024; - - OUT_PKT3(ring, CP_SET_CONSTANT, 4); - OUT_RING(ring, CP_REG(REG_RB_SURFACE_INFO)); - OUT_RING(ring, fb->bin_w); /* RB_SURFACE_INFO */ - OUT_RING(ring, RB_COLOR_INFO_COLOR_SWAP(1) | /* RB_COLOR_INFO */ - RB_COLOR_INFO_COLOR_FORMAT(fd_pipe2color(pfb->cbufs[0]->format))); - reg = RB_DEPTH_INFO_DEPTH_BASE(ALIGN(base, 4)); - if (pfb->zsbuf) - reg |= RB_DEPTH_INFO_DEPTH_FORMAT(fd_pipe2depth(pfb->zsbuf->format)); - OUT_RING(ring, reg); /* RB_DEPTH_INFO */ -} - void fd_state_emit(struct pipe_context *pctx, uint32_t dirty) { @@ -418,7 +391,7 @@ fd_state_emit(struct pipe_context *pctx, uint32_t dirty) OUT_RING(ring, CP_REG(REG_PA_CL_CLIP_CNTL)); OUT_RING(ring, ctx->rasterizer->pa_cl_clip_cntl); OUT_RING(ring, ctx->rasterizer->pa_su_sc_mode_cntl | - ctx->framebuffer.pa_su_sc_mode_cntl); + PA_SU_SC_MODE_CNTL_VTX_WINDOW_OFFSET_ENABLE); OUT_PKT3(ring, CP_SET_CONSTANT, 5); OUT_RING(ring, CP_REG(REG_PA_SU_POINT_SIZE)); @@ -436,9 +409,6 @@ fd_state_emit(struct pipe_context *pctx, uint32_t dirty) OUT_RING(ring, f2d(1.0)); /* PA_CL_GB_HORZ_DISC_ADJ */ } - if (dirty & FD_DIRTY_FRAMEBUFFER) - fd_emit_framebuffer_state(ring, &ctx->framebuffer); - if (dirty & FD_DIRTY_SCISSOR) { OUT_PKT3(ring, CP_SET_CONSTANT, 3); OUT_RING(ring, CP_REG(REG_PA_SC_WINDOW_SCISSOR_TL)); @@ -446,6 +416,11 @@ fd_state_emit(struct pipe_context *pctx, uint32_t dirty) ctx->scissor.miny)); OUT_RING(ring, xy2d(ctx->scissor.maxx, /* PA_SC_WINDOW_SCISSOR_BR */ ctx->scissor.maxy)); + + ctx->max_scissor.minx = min(ctx->max_scissor.minx, ctx->scissor.minx); + ctx->max_scissor.miny = min(ctx->max_scissor.miny, ctx->scissor.miny); + ctx->max_scissor.maxx = max(ctx->max_scissor.maxx, ctx->scissor.maxx); + ctx->max_scissor.maxy = max(ctx->max_scissor.maxy, ctx->scissor.maxy); } if (dirty & FD_DIRTY_VIEWPORT) { diff --git a/src/gallium/drivers/freedreno/freedreno_state.h b/src/gallium/drivers/freedreno/freedreno_state.h index 4e68448f229..422f0ced484 100644 --- a/src/gallium/drivers/freedreno/freedreno_state.h +++ b/src/gallium/drivers/freedreno/freedreno_state.h @@ -45,8 +45,6 @@ struct fd_vertex_buf { void fd_emit_vertex_bufs(struct fd_ringbuffer *ring, uint32_t val, struct fd_vertex_buf *vbufs, uint32_t n); -void fd_emit_framebuffer_state(struct fd_ringbuffer *ring, - struct fd_framebuffer_stateobj *fb); void fd_state_emit(struct pipe_context *pctx, uint32_t dirty); void fd_state_emit_setup(struct pipe_context *pctx); diff --git a/src/gallium/drivers/freedreno/freedreno_vbo.c b/src/gallium/drivers/freedreno/freedreno_vbo.c index fc33539e213..e992b8cf452 100644 --- a/src/gallium/drivers/freedreno/freedreno_vbo.c +++ b/src/gallium/drivers/freedreno/freedreno_vbo.c @@ -141,7 +141,7 @@ static void fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) { struct fd_context *ctx = fd_context(pctx); - struct pipe_framebuffer_state *fb = &ctx->framebuffer.base; + struct pipe_framebuffer_state *fb = &ctx->framebuffer; struct fd_ringbuffer *ring = ctx->ring; struct fd_bo *idx_bo = NULL; enum pc_di_index_size idx_type = INDEX_SIZE_IGN; @@ -149,6 +149,12 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) uint32_t idx_size, idx_offset; unsigned buffers; + /* if we supported transform feedback, we'd have to disable this: */ + if (((ctx->scissor.maxx - ctx->scissor.minx) * + (ctx->scissor.maxy - ctx->scissor.miny)) == 0) { + return; + } + ctx->needs_flush = true; if (info->indexed) { -- 2.30.2