diff --git a/src/gallium/drivers/etnaviv/etnaviv_emit.c b/src/gallium/drivers/etnaviv/etnaviv_emit.c index 7eeeda57b66..8394474b4b5 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_emit.c +++ b/src/gallium/drivers/etnaviv/etnaviv_emit.c @@ -491,6 +491,23 @@ etna_emit_state(struct etna_context *ctx) /*00C14*/ EMIT_STATE(SE_DEPTH_BIAS, rasterizer->SE_DEPTH_BIAS); /*00C18*/ EMIT_STATE(SE_CONFIG, rasterizer->SE_CONFIG); } + if (unlikely(dirty & (ETNA_DIRTY_SCISSOR | ETNA_DIRTY_FRAMEBUFFER | + ETNA_DIRTY_RASTERIZER | ETNA_DIRTY_VIEWPORT))) { + struct etna_rasterizer_state *rasterizer = etna_rasterizer_state(ctx->rasterizer); + + uint32_t clip_right = + MIN2(ctx->framebuffer.SE_CLIP_RIGHT, ctx->viewport.SE_CLIP_RIGHT); + uint32_t clip_bottom = + MIN2(ctx->framebuffer.SE_CLIP_BOTTOM, ctx->viewport.SE_CLIP_BOTTOM); + + if (rasterizer->scissor) { + clip_right = MIN2(ctx->scissor.SE_CLIP_RIGHT, clip_right); + clip_bottom = MIN2(ctx->scissor.SE_CLIP_BOTTOM, clip_bottom); + } + + /*00C20*/ EMIT_STATE_FIXP(SE_CLIP_RIGHT, clip_right); + /*00C24*/ EMIT_STATE_FIXP(SE_CLIP_BOTTOM, clip_bottom); + } if (unlikely(dirty & (ETNA_DIRTY_SHADER))) { /*00E00*/ EMIT_STATE(RA_CONTROL, ctx->shader_state.RA_CONTROL); } diff --git a/src/gallium/drivers/etnaviv/etnaviv_internal.h b/src/gallium/drivers/etnaviv/etnaviv_internal.h index 983321a9d93..2f09d555bc2 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_internal.h +++ b/src/gallium/drivers/etnaviv/etnaviv_internal.h @@ -47,6 +47,17 @@ /* PE render targets must be aligned to 64 bytes */ #define ETNA_PE_ALIGNMENT (64) +/* These demarcate the margin (fixp16) between the computed sizes and the + value sent to the chip. These have been set to the numbers used by the + Vivante driver on gc2000. They used to be -1 for scissor right and bottom. I + am not sure whether older hardware was relying on these or they were just a + guess. But if so, these need to be moved to the _specs structure. +*/ +#define ETNA_SE_SCISSOR_MARGIN_RIGHT (0x1119) +#define ETNA_SE_SCISSOR_MARGIN_BOTTOM (0x1111) +#define ETNA_SE_CLIP_MARGIN_RIGHT (0xffff) +#define ETNA_SE_CLIP_MARGIN_BOTTOM (0xffff) + /* GPU chip 3D specs */ struct etna_specs { /* supports SUPERTILE (64x64) tiling? */ @@ -128,6 +139,8 @@ struct compiled_scissor_state { uint32_t SE_SCISSOR_TOP; uint32_t SE_SCISSOR_RIGHT; uint32_t SE_SCISSOR_BOTTOM; + uint32_t SE_CLIP_RIGHT; + uint32_t SE_CLIP_BOTTOM; }; /* Compiled pipe_viewport_state */ @@ -142,6 +155,8 @@ struct compiled_viewport_state { uint32_t SE_SCISSOR_TOP; uint32_t SE_SCISSOR_RIGHT; uint32_t SE_SCISSOR_BOTTOM; + uint32_t SE_CLIP_RIGHT; + uint32_t SE_CLIP_BOTTOM; uint32_t PE_DEPTH_NEAR; uint32_t PE_DEPTH_FAR; }; @@ -164,6 +179,8 @@ struct compiled_framebuffer_state { uint32_t SE_SCISSOR_TOP; uint32_t SE_SCISSOR_RIGHT; uint32_t SE_SCISSOR_BOTTOM; + uint32_t SE_CLIP_RIGHT; + uint32_t SE_CLIP_BOTTOM; uint32_t RA_MULTISAMPLE_UNK00E04; uint32_t RA_MULTISAMPLE_UNK00E10[VIVS_RA_MULTISAMPLE_UNK00E10__LEN]; uint32_t RA_CENTROID_TABLE[VIVS_RA_CENTROID_TABLE__LEN]; diff --git a/src/gallium/drivers/etnaviv/etnaviv_state.c b/src/gallium/drivers/etnaviv/etnaviv_state.c index 2256261c429..141a34a4c67 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_state.c +++ b/src/gallium/drivers/etnaviv/etnaviv_state.c @@ -323,8 +323,10 @@ etna_set_framebuffer_state(struct pipe_context *pctx, /* Scissor setup */ cs->SE_SCISSOR_LEFT = 0; /* affected by rasterizer and scissor state as well */ cs->SE_SCISSOR_TOP = 0; - cs->SE_SCISSOR_RIGHT = (sv->width << 16) - 1; - cs->SE_SCISSOR_BOTTOM = (sv->height << 16) - 1; + cs->SE_SCISSOR_RIGHT = (sv->width << 16) + ETNA_SE_SCISSOR_MARGIN_RIGHT; + cs->SE_SCISSOR_BOTTOM = (sv->height << 16) + ETNA_SE_SCISSOR_MARGIN_BOTTOM; + cs->SE_CLIP_RIGHT = (sv->width << 16) + ETNA_SE_CLIP_MARGIN_RIGHT; + cs->SE_CLIP_BOTTOM = (sv->height << 16) + ETNA_SE_CLIP_MARGIN_BOTTOM; cs->TS_MEM_CONFIG = ts_mem_config; @@ -345,13 +347,17 @@ etna_set_scissor_states(struct pipe_context *pctx, unsigned start_slot, { struct etna_context *ctx = etna_context(pctx); struct compiled_scissor_state *cs = &ctx->scissor; + assert(ss->minx <= ss->maxx); + assert(ss->miny <= ss->maxy); /* note that this state is only used when rasterizer_state->scissor is on */ ctx->scissor_s = *ss; cs->SE_SCISSOR_LEFT = (ss->minx << 16); cs->SE_SCISSOR_TOP = (ss->miny << 16); - cs->SE_SCISSOR_RIGHT = (ss->maxx << 16) - 1; - cs->SE_SCISSOR_BOTTOM = (ss->maxy << 16) - 1; + cs->SE_SCISSOR_RIGHT = (ss->maxx << 16) + ETNA_SE_SCISSOR_MARGIN_RIGHT; + cs->SE_SCISSOR_BOTTOM = (ss->maxy << 16) + ETNA_SE_SCISSOR_MARGIN_BOTTOM; + cs->SE_CLIP_RIGHT = (ss->maxx << 16) + ETNA_SE_CLIP_MARGIN_RIGHT; + cs->SE_CLIP_BOTTOM = (ss->maxy << 16) + ETNA_SE_CLIP_MARGIN_BOTTOM; ctx->dirty |= ETNA_DIRTY_SCISSOR; } @@ -387,22 +393,14 @@ etna_set_viewport_states(struct pipe_context *pctx, unsigned start_slot, /* Compute scissor rectangle (fixp) from viewport. * Make sure left is always < right and top always < bottom. */ - cs->SE_SCISSOR_LEFT = etna_f32_to_fixp16(MAX2(vs->translate[0] - vs->scale[0], 0.0f)); - cs->SE_SCISSOR_TOP = etna_f32_to_fixp16(MAX2(vs->translate[1] - vs->scale[1], 0.0f)); - cs->SE_SCISSOR_RIGHT = etna_f32_to_fixp16(MAX2(vs->translate[0] + vs->scale[0], 0.0f)); - cs->SE_SCISSOR_BOTTOM = etna_f32_to_fixp16(MAX2(vs->translate[1] + vs->scale[1], 0.0f)); - - if (cs->SE_SCISSOR_LEFT > cs->SE_SCISSOR_RIGHT) { - uint32_t tmp = cs->SE_SCISSOR_RIGHT; - cs->SE_SCISSOR_RIGHT = cs->SE_SCISSOR_LEFT; - cs->SE_SCISSOR_LEFT = tmp; - } - - if (cs->SE_SCISSOR_TOP > cs->SE_SCISSOR_BOTTOM) { - uint32_t tmp = cs->SE_SCISSOR_BOTTOM; - cs->SE_SCISSOR_BOTTOM = cs->SE_SCISSOR_TOP; - cs->SE_SCISSOR_TOP = tmp; - } + cs->SE_SCISSOR_LEFT = etna_f32_to_fixp16(MAX2(vs->translate[0] - fabsf(vs->scale[0]), 0.0f)); + cs->SE_SCISSOR_TOP = etna_f32_to_fixp16(MAX2(vs->translate[1] - fabsf(vs->scale[1]), 0.0f)); + uint32_t right_fixp = etna_f32_to_fixp16(MAX2(vs->translate[0] + fabsf(vs->scale[0]), 0.0f)); + uint32_t bottom_fixp = etna_f32_to_fixp16(MAX2(vs->translate[1] + fabsf(vs->scale[1]), 0.0f)); + cs->SE_SCISSOR_RIGHT = right_fixp + ETNA_SE_SCISSOR_MARGIN_RIGHT; + cs->SE_SCISSOR_BOTTOM = bottom_fixp + ETNA_SE_SCISSOR_MARGIN_BOTTOM; + cs->SE_CLIP_RIGHT = right_fixp + ETNA_SE_CLIP_MARGIN_RIGHT; + cs->SE_CLIP_BOTTOM = bottom_fixp + ETNA_SE_CLIP_MARGIN_BOTTOM; cs->PE_DEPTH_NEAR = fui(0.0); /* not affected if depth mode is Z (as in GL) */ cs->PE_DEPTH_FAR = fui(1.0);