From e9edbf0a688c68ef0896e5d4278f411f6b6f8398 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Sat, 1 Jun 2013 14:16:30 -0400 Subject: [PATCH] freedreno: better scissor fix Actually respect rasterizer state. Signed-off-by: Rob Clark --- src/gallium/drivers/freedreno/a2xx/fd2_emit.c | 20 ++++++++++--------- src/gallium/drivers/freedreno/a3xx/fd3_emit.c | 20 ++++++++++--------- .../drivers/freedreno/freedreno_context.h | 14 +++++++++++++ .../drivers/freedreno/freedreno_draw.c | 5 +++-- .../drivers/freedreno/freedreno_state.c | 12 ++++------- 5 files changed, 43 insertions(+), 28 deletions(-) diff --git a/src/gallium/drivers/freedreno/a2xx/fd2_emit.c b/src/gallium/drivers/freedreno/a2xx/fd2_emit.c index 8a40f9ab7ab..b03390ec436 100644 --- a/src/gallium/drivers/freedreno/a2xx/fd2_emit.c +++ b/src/gallium/drivers/freedreno/a2xx/fd2_emit.c @@ -238,17 +238,19 @@ fd2_emit_state(struct fd_context *ctx, uint32_t dirty) } if (dirty & FD_DIRTY_SCISSOR) { + struct pipe_scissor_state *scissor = fd_context_get_scissor(ctx); + OUT_PKT3(ring, CP_SET_CONSTANT, 3); OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_WINDOW_SCISSOR_TL)); - OUT_RING(ring, xy2d(ctx->scissor.minx, /* PA_SC_WINDOW_SCISSOR_TL */ - ctx->scissor.miny)); - OUT_RING(ring, xy2d(ctx->scissor.maxx, /* PA_SC_WINDOW_SCISSOR_BR */ - ctx->scissor.maxy)); - - ctx->max_scissor.minx = MIN2(ctx->max_scissor.minx, ctx->scissor.minx); - ctx->max_scissor.miny = MIN2(ctx->max_scissor.miny, ctx->scissor.miny); - ctx->max_scissor.maxx = MAX2(ctx->max_scissor.maxx, ctx->scissor.maxx); - ctx->max_scissor.maxy = MAX2(ctx->max_scissor.maxy, ctx->scissor.maxy); + OUT_RING(ring, xy2d(scissor->minx, /* PA_SC_WINDOW_SCISSOR_TL */ + scissor->miny)); + OUT_RING(ring, xy2d(scissor->maxx, /* PA_SC_WINDOW_SCISSOR_BR */ + scissor->maxy)); + + ctx->max_scissor.minx = MIN2(ctx->max_scissor.minx, scissor->minx); + ctx->max_scissor.miny = MIN2(ctx->max_scissor.miny, scissor->miny); + ctx->max_scissor.maxx = MAX2(ctx->max_scissor.maxx, scissor->maxx); + ctx->max_scissor.maxy = MAX2(ctx->max_scissor.maxy, scissor->maxy); } if (dirty & FD_DIRTY_VIEWPORT) { diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_emit.c b/src/gallium/drivers/freedreno/a3xx/fd3_emit.c index 1d048b08c83..a7a4bf78d62 100644 --- a/src/gallium/drivers/freedreno/a3xx/fd3_emit.c +++ b/src/gallium/drivers/freedreno/a3xx/fd3_emit.c @@ -401,16 +401,18 @@ fd3_emit_state(struct fd_context *ctx, uint32_t dirty) } if (dirty & FD_DIRTY_SCISSOR) { + struct pipe_scissor_state *scissor = fd_context_get_scissor(ctx); + OUT_PKT0(ring, REG_A3XX_GRAS_SC_WINDOW_SCISSOR_TL, 2); - OUT_RING(ring, A3XX_GRAS_SC_WINDOW_SCISSOR_TL_X(ctx->scissor.minx) | - A3XX_GRAS_SC_WINDOW_SCISSOR_TL_Y(ctx->scissor.miny)); - OUT_RING(ring, A3XX_GRAS_SC_WINDOW_SCISSOR_BR_X(ctx->scissor.maxx - 1) | - A3XX_GRAS_SC_WINDOW_SCISSOR_BR_Y(ctx->scissor.maxy - 1)); - - ctx->max_scissor.minx = MIN2(ctx->max_scissor.minx, ctx->scissor.minx); - ctx->max_scissor.miny = MIN2(ctx->max_scissor.miny, ctx->scissor.miny); - ctx->max_scissor.maxx = MAX2(ctx->max_scissor.maxx, ctx->scissor.maxx); - ctx->max_scissor.maxy = MAX2(ctx->max_scissor.maxy, ctx->scissor.maxy); + OUT_RING(ring, A3XX_GRAS_SC_WINDOW_SCISSOR_TL_X(scissor->minx) | + A3XX_GRAS_SC_WINDOW_SCISSOR_TL_Y(scissor->miny)); + OUT_RING(ring, A3XX_GRAS_SC_WINDOW_SCISSOR_BR_X(scissor->maxx - 1) | + A3XX_GRAS_SC_WINDOW_SCISSOR_BR_Y(scissor->maxy - 1)); + + ctx->max_scissor.minx = MIN2(ctx->max_scissor.minx, scissor->minx); + ctx->max_scissor.miny = MIN2(ctx->max_scissor.miny, scissor->miny); + ctx->max_scissor.maxx = MAX2(ctx->max_scissor.maxx, scissor->maxx); + ctx->max_scissor.maxy = MAX2(ctx->max_scissor.maxy, scissor->maxy); } if (dirty & FD_DIRTY_VIEWPORT) { diff --git a/src/gallium/drivers/freedreno/freedreno_context.h b/src/gallium/drivers/freedreno/freedreno_context.h index 54759314e26..3d18260445f 100644 --- a/src/gallium/drivers/freedreno/freedreno_context.h +++ b/src/gallium/drivers/freedreno/freedreno_context.h @@ -139,6 +139,12 @@ struct fd_context { struct pipe_scissor_state scissor; + /* we don't have a disable/enable bit for scissor, so instead we keep + * a disabled-scissor state which matches the entire bound framebuffer + * and use that when scissor is not enabled. + */ + struct pipe_scissor_state disabled_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. @@ -218,6 +224,14 @@ fd_context(struct pipe_context *pctx) return (struct fd_context *)pctx; } +static INLINE struct pipe_scissor_state * +fd_context_get_scissor(struct fd_context *ctx) +{ + if (ctx->rasterizer && ctx->rasterizer->scissor) + return &ctx->scissor; + return &ctx->disabled_scissor; +} + struct pipe_context * fd_context_init(struct fd_context *ctx, struct pipe_screen *pscreen, void *priv); diff --git a/src/gallium/drivers/freedreno/freedreno_draw.c b/src/gallium/drivers/freedreno/freedreno_draw.c index dbdf5732658..b02b8b9f9f9 100644 --- a/src/gallium/drivers/freedreno/freedreno_draw.c +++ b/src/gallium/drivers/freedreno/freedreno_draw.c @@ -114,11 +114,12 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) { struct fd_context *ctx = fd_context(pctx); struct pipe_framebuffer_state *pfb = &ctx->framebuffer; + struct pipe_scissor_state *scissor = fd_context_get_scissor(ctx); unsigned i, buffers = 0; /* 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) { + if (((scissor->maxx - scissor->minx) * + (scissor->maxy - scissor->miny)) == 0) { return; } diff --git a/src/gallium/drivers/freedreno/freedreno_state.c b/src/gallium/drivers/freedreno/freedreno_state.c index 10031977e61..2f5d52c017c 100644 --- a/src/gallium/drivers/freedreno/freedreno_state.c +++ b/src/gallium/drivers/freedreno/freedreno_state.c @@ -137,14 +137,10 @@ fd_set_framebuffer_state(struct pipe_context *pctx, ctx->dirty |= FD_DIRTY_FRAMEBUFFER; - /* also need to reset the scissor.. mesa/gl state tracker - * does this for us, but u_blitter doesn't and other - * state trackers might not.. - */ - ctx->scissor.minx = 0; - ctx->scissor.miny = 0; - ctx->scissor.maxx = cso->width; - ctx->scissor.maxy = cso->height; + ctx->disabled_scissor.minx = 0; + ctx->disabled_scissor.miny = 0; + ctx->disabled_scissor.maxx = cso->width; + ctx->disabled_scissor.maxy = cso->height; ctx->dirty |= FD_DIRTY_SCISSOR; } -- 2.30.2