[PATCH] etnaviv: Fix viewport/clipping computation

Wladimir J. van der Laan laanwj at gmail.com
Sat Nov 26 08:40:54 UTC 2016


Don't merge this patch yet - there's still some issue.
Will re-send when I'm sure.

On Fri, Nov 25, 2016 at 08:36:48AM +0100, Wladimir J. van der Laan wrote:
> This fixes rendering of full-screen quads (and other screen-filling
> geometry, e.g. ioquake3 walls up-close) on gc3000.
> 
> - It looks like SE_CLIP registers were not set at all.
>   I'm amazed that rendering worked without them. Emit them to
>   avoid issues on gc3000.
> 
> - From command stream dumps from Vivante driver SE_*_RIGHT and
>   SE_*_BOTTOM appear to be really SE_*_WIDTH and SE_*_HEIGHT.
>   Fix their computation (should probably rename the registers as
>   well?)
> 
> - Define constants
>   ETNA_SE_SCISSOR_MARGIN_RIGHT (0x1119)
>   ETNA_SE_SCISSOR_MARGIN_BOTTOM (0x1111)
>   ETNA_SE_CLIP_MARGIN_RIGHT (0xffff)
>   ETNA_SE_CLIP_MARGIN_BOTTOM (0xffff)
> 
>   These demarcate the margin (fixp16) between the computed sizes and the
>   value sent to the chip. I have set these to the numbers used for
>   gc2000. I am not sure whether any old hardware was relying on the old
>   numbers, or whether those were just a guess. But if so, these need to
>   be moved to the _specs structure.
> 
> Signed-off-by: Wladimir J. van der Laan <laanwj at gmail.com>
> ---
>  src/gallium/drivers/etnaviv/etnaviv_emit.c     | 17 ++++++++++
>  src/gallium/drivers/etnaviv/etnaviv_internal.h | 17 ++++++++++
>  src/gallium/drivers/etnaviv/etnaviv_state.c    | 45 ++++++++++++++------------
>  3 files changed, 59 insertions(+), 20 deletions(-)
> 
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_emit.c b/src/gallium/drivers/etnaviv/etnaviv_emit.c
> index 7eeeda5..8394474 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 fa75c3e..f340116 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? */
> @@ -126,6 +137,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 */
> @@ -140,6 +153,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;
>  };
> @@ -162,6 +177,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 2256261..fcc3bad 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,19 @@ 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;
> +   int width_fixp = ((ss->maxx - ss->minx) << 16);
> +   int height_fixp = ((ss->maxy - ss->miny) << 16);
> +   cs->SE_SCISSOR_RIGHT = width_fixp + ETNA_SE_SCISSOR_MARGIN_RIGHT;
> +   cs->SE_SCISSOR_BOTTOM = height_fixp + ETNA_SE_SCISSOR_MARGIN_BOTTOM;
> +   cs->SE_CLIP_RIGHT = width_fixp + ETNA_SE_CLIP_MARGIN_RIGHT;
> +   cs->SE_CLIP_BOTTOM = height_fixp + ETNA_SE_CLIP_MARGIN_BOTTOM;
>  
>     ctx->dirty |= ETNA_DIRTY_SCISSOR;
>  }
> @@ -387,22 +395,19 @@ 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;
> -   }
> +   int left_fixp = etna_f32_to_fixp16(MAX2(vs->translate[0] - fabsf(vs->scale[0]), 0.0f));
> +   int top_fixp = etna_f32_to_fixp16(MAX2(vs->translate[1] - fabsf(vs->scale[1]), 0.0f));
> +   int right_fixp = etna_f32_to_fixp16(MAX2(vs->translate[0] + fabsf(vs->scale[0]), 0.0f));
> +   int bottom_fixp = etna_f32_to_fixp16(MAX2(vs->translate[1] + fabsf(vs->scale[1]), 0.0f));
> +   int width_fixp = right_fixp - left_fixp;
> +   int height_fixp = bottom_fixp - top_fixp;
> +
> +   cs->SE_SCISSOR_LEFT = left_fixp;
> +   cs->SE_SCISSOR_TOP = top_fixp;
> +   cs->SE_SCISSOR_RIGHT = width_fixp + ETNA_SE_SCISSOR_MARGIN_RIGHT;
> +   cs->SE_SCISSOR_BOTTOM = height_fixp + ETNA_SE_SCISSOR_MARGIN_BOTTOM;
> +   cs->SE_CLIP_RIGHT = width_fixp + ETNA_SE_CLIP_MARGIN_RIGHT;
> +   cs->SE_CLIP_BOTTOM = height_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);
> -- 
> 2.7.4
> 


More information about the etnaviv mailing list