freedreno/a3xx: add basic clip plane support
authorIlia Mirkin <imirkin@alum.mit.edu>
Tue, 25 Aug 2015 03:31:00 +0000 (23:31 -0400)
committerIlia Mirkin <imirkin@alum.mit.edu>
Sat, 29 Aug 2015 20:18:04 +0000 (16:18 -0400)
The hardware is capable of dealing with GL1-style user clip planes.
No clip vertex, no clip distances. Fixes a number of ucp tests, as well
as neverball.

Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
Cc: "11.0" <mesa-stable@lists.freedesktop.org>
src/gallium/drivers/freedreno/a3xx/fd3_emit.c
src/gallium/drivers/freedreno/freedreno_context.h
src/gallium/drivers/freedreno/freedreno_state.c

index 752e7f88cb974599d4b40db0d0f36c5c3b7fb7e1..6f514ed05df1de00cfea7d7489b2f11097e1bd8f 100644 (file)
@@ -563,10 +563,29 @@ fd3_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring,
                val |= COND(fp->writes_pos, A3XX_GRAS_CL_CLIP_CNTL_ZCLIP_DISABLE);
                val |= COND(fp->frag_coord, A3XX_GRAS_CL_CLIP_CNTL_ZCOORD |
                                A3XX_GRAS_CL_CLIP_CNTL_WCOORD);
+               /* TODO only use if prog doesn't use clipvertex/clipdist */
+               val |= MIN2(util_bitcount(ctx->rasterizer->clip_plane_enable), 6) << 26;
                OUT_PKT0(ring, REG_A3XX_GRAS_CL_CLIP_CNTL, 1);
                OUT_RING(ring, val);
        }
 
+       if (dirty & (FD_DIRTY_RASTERIZER | FD_DIRTY_UCP)) {
+               uint32_t planes = ctx->rasterizer->clip_plane_enable;
+               int count = 0;
+
+               while (planes && count < 6) {
+                       int i = ffs(planes) - 1;
+
+                       planes &= ~(1U << i);
+                       fd_wfi(ctx, ring);
+                       OUT_PKT0(ring, REG_A3XX_GRAS_CL_USER_PLANE(count++), 4);
+                       OUT_RING(ring, fui(ctx->ucp.ucp[i][0]));
+                       OUT_RING(ring, fui(ctx->ucp.ucp[i][1]));
+                       OUT_RING(ring, fui(ctx->ucp.ucp[i][2]));
+                       OUT_RING(ring, fui(ctx->ucp.ucp[i][3]));
+               }
+       }
+
        /* NOTE: since primitive_restart is not actually part of any
         * state object, we need to make sure that we always emit
         * PRIM_VTX_CNTL.. either that or be more clever and detect
index 509a90fdf2395cba7d5362613f5466c5302aa6e6..3486c2fd1b7bdb4c508010bdfa00a2a4781e4e2f 100644 (file)
@@ -334,6 +334,7 @@ struct fd_context {
                FD_DIRTY_INDEXBUF    = (1 << 16),
                FD_DIRTY_SCISSOR     = (1 << 17),
                FD_DIRTY_STREAMOUT   = (1 << 18),
+               FD_DIRTY_UCP         = (1 << 19),
        } dirty;
 
        struct pipe_blend_state *blend;
@@ -355,6 +356,7 @@ struct fd_context {
        struct fd_constbuf_stateobj constbuf[PIPE_SHADER_TYPES];
        struct pipe_index_buffer indexbuf;
        struct fd_streamout_stateobj streamout;
+       struct pipe_clip_state ucp;
 
        /* GMEM/tile handling fxns: */
        void (*emit_tile_init)(struct fd_context *ctx);
index 7bf8bdb45070691ed4cc22c2bbeaf8ded156f0dd..e75865a9387f0d7694b70df469fa94a8e0f133ff 100644 (file)
@@ -65,7 +65,9 @@ static void
 fd_set_clip_state(struct pipe_context *pctx,
                const struct pipe_clip_state *clip)
 {
-       DBG("TODO: ");
+       struct fd_context *ctx = fd_context(pctx);
+       ctx->ucp = *clip;
+       ctx->dirty |= FD_DIRTY_UCP;
 }
 
 static void