From 4ad333103f8ebd8eb12150a1ebf6b777d1e39684 Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Fri, 25 Jul 2025 10:58:29 +0200 Subject: [PATCH] etnaviv: Emulate rasterizer_discard When rasterizer discard is enabled, we need to prevent all rasterization without affecting vertex processing or transform feedback. Emulate this by setting a zero-sized scissor rectangle (0,0,0,0) which effectively clips all fragments while allowing the vertex shader to continue running normally. This matches the behavior implemented by the binary blob. Passes all dEQP-GLES3.functional.rasterizer_discard.* on GC7000. Signed-off-by: Christian Gmeiner Reviewed-by: Lucas Stach Part-of: --- src/gallium/drivers/etnaviv/etnaviv_state.c | 39 ++++++++++++--------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/src/gallium/drivers/etnaviv/etnaviv_state.c b/src/gallium/drivers/etnaviv/etnaviv_state.c index d04195c3afc..a46c286fd03 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_state.c +++ b/src/gallium/drivers/etnaviv/etnaviv_state.c @@ -810,25 +810,32 @@ etna_update_clipping(struct etna_context *ctx) const struct etna_rasterizer_state *rasterizer = etna_rasterizer_state(ctx->rasterizer); const struct pipe_framebuffer_state *fb = &ctx->framebuffer_s; - /* clip framebuffer against viewport */ - uint32_t scissor_left = ctx->viewport.SE_SCISSOR_LEFT; - uint32_t scissor_top = ctx->viewport.SE_SCISSOR_TOP; - uint32_t scissor_right = MIN2(fb->width, ctx->viewport.SE_SCISSOR_RIGHT); - uint32_t scissor_bottom = MIN2(fb->height, ctx->viewport.SE_SCISSOR_BOTTOM); + if (ctx->rasterizer->rasterizer_discard) { + ctx->clipping.minx = 0; + ctx->clipping.miny = 0; + ctx->clipping.maxx = 0; + ctx->clipping.maxy = 0; + } else { + /* clip framebuffer against viewport */ + uint32_t scissor_left = ctx->viewport.SE_SCISSOR_LEFT; + uint32_t scissor_top = ctx->viewport.SE_SCISSOR_TOP; + uint32_t scissor_right = MIN2(fb->width, ctx->viewport.SE_SCISSOR_RIGHT); + uint32_t scissor_bottom = MIN2(fb->height, ctx->viewport.SE_SCISSOR_BOTTOM); - /* clip against scissor */ - if (rasterizer->scissor) { - scissor_left = MAX2(ctx->scissor.minx, scissor_left); - scissor_top = MAX2(ctx->scissor.miny, scissor_top); - scissor_right = MIN2(ctx->scissor.maxx, scissor_right); - scissor_bottom = MIN2(ctx->scissor.maxy, scissor_bottom); + /* clip against scissor */ + if (rasterizer->scissor) { + scissor_left = MAX2(ctx->scissor.minx, scissor_left); + scissor_top = MAX2(ctx->scissor.miny, scissor_top); + scissor_right = MIN2(ctx->scissor.maxx, scissor_right); + scissor_bottom = MIN2(ctx->scissor.maxy, scissor_bottom); + } + + ctx->clipping.minx = scissor_left; + ctx->clipping.miny = scissor_top; + ctx->clipping.maxx = scissor_right; + ctx->clipping.maxy = scissor_bottom; } - ctx->clipping.minx = scissor_left; - ctx->clipping.miny = scissor_top; - ctx->clipping.maxx = scissor_right; - ctx->clipping.maxy = scissor_bottom; - ctx->dirty |= ETNA_DIRTY_SCISSOR_CLIP; return true;