freedreno: emulated unsupported primitive types
authorRob Clark <robclark@freedesktop.org>
Fri, 25 Oct 2013 19:33:09 +0000 (15:33 -0400)
committerRob Clark <robclark@freedesktop.org>
Tue, 29 Oct 2013 20:49:43 +0000 (16:49 -0400)
Use u_primconvert to convert unsupported primitives into supported
primitive plus index buffer.

Signed-off-by: Rob Clark <robclark@freedesktop.org>
src/gallium/drivers/freedreno/a2xx/fd2_context.c
src/gallium/drivers/freedreno/a3xx/fd3_context.c
src/gallium/drivers/freedreno/freedreno_context.c
src/gallium/drivers/freedreno/freedreno_context.h
src/gallium/drivers/freedreno/freedreno_draw.c

index a3192751164e146e16e99ce9db1448f83dfa9bf9..ec9eaf664177d86806873812e178903ff3fee2da 100644 (file)
@@ -67,9 +67,29 @@ create_solid_vertexbuf(struct pipe_context *pctx)
        return prsc;
 }
 
+static const uint8_t a22x_primtypes[PIPE_PRIM_MAX] = {
+               [PIPE_PRIM_POINTS]         = DI_PT_POINTLIST_A2XX,
+               [PIPE_PRIM_LINES]          = DI_PT_LINELIST,
+               [PIPE_PRIM_LINE_STRIP]     = DI_PT_LINESTRIP,
+               [PIPE_PRIM_LINE_LOOP]      = DI_PT_LINELOOP,
+               [PIPE_PRIM_TRIANGLES]      = DI_PT_TRILIST,
+               [PIPE_PRIM_TRIANGLE_STRIP] = DI_PT_TRISTRIP,
+               [PIPE_PRIM_TRIANGLE_FAN]   = DI_PT_TRIFAN,
+};
+
+static const uint8_t a20x_primtypes[PIPE_PRIM_MAX] = {
+               [PIPE_PRIM_POINTS]         = DI_PT_POINTLIST_A2XX,
+               [PIPE_PRIM_LINES]          = DI_PT_LINELIST,
+               [PIPE_PRIM_LINE_STRIP]     = DI_PT_LINESTRIP,
+               [PIPE_PRIM_TRIANGLES]      = DI_PT_TRILIST,
+               [PIPE_PRIM_TRIANGLE_STRIP] = DI_PT_TRISTRIP,
+               [PIPE_PRIM_TRIANGLE_FAN]   = DI_PT_TRIFAN,
+};
+
 struct pipe_context *
 fd2_context_create(struct pipe_screen *pscreen, void *priv)
 {
+       struct fd_screen *screen = fd_screen(pscreen);
        struct fd2_context *fd2_ctx = CALLOC_STRUCT(fd2_context);
        struct pipe_context *pctx;
 
@@ -88,7 +108,9 @@ fd2_context_create(struct pipe_screen *pscreen, void *priv)
        fd2_texture_init(pctx);
        fd2_prog_init(pctx);
 
-       pctx = fd_context_init(&fd2_ctx->base, pscreen, priv);
+       pctx = fd_context_init(&fd2_ctx->base, pscreen,
+                       (screen->gpu_id >= 220) ? a22x_primtypes : a20x_primtypes,
+                       priv);
        if (!pctx)
                return NULL;
 
index 589aeed45788cfff410df533e33a519292dfdd76..13f91e9de0c55f179fbda320db05f5e6e238323d 100644 (file)
@@ -82,6 +82,16 @@ create_blit_texcoord_vertexbuf(struct pipe_context *pctx)
        return prsc;
 }
 
+static const uint8_t primtypes[PIPE_PRIM_MAX] = {
+               [PIPE_PRIM_POINTS]         = DI_PT_POINTLIST_A3XX,
+               [PIPE_PRIM_LINES]          = DI_PT_LINELIST,
+               [PIPE_PRIM_LINE_STRIP]     = DI_PT_LINESTRIP,
+               [PIPE_PRIM_LINE_LOOP]      = DI_PT_LINELOOP,
+               [PIPE_PRIM_TRIANGLES]      = DI_PT_TRILIST,
+               [PIPE_PRIM_TRIANGLE_STRIP] = DI_PT_TRISTRIP,
+               [PIPE_PRIM_TRIANGLE_FAN]   = DI_PT_TRIFAN,
+};
+
 struct pipe_context *
 fd3_context_create(struct pipe_screen *pscreen, void *priv)
 {
@@ -106,7 +116,7 @@ fd3_context_create(struct pipe_screen *pscreen, void *priv)
        fd3_texture_init(pctx);
        fd3_prog_init(pctx);
 
-       pctx = fd_context_init(&fd3_ctx->base, pscreen, priv);
+       pctx = fd_context_init(&fd3_ctx->base, pscreen, primtypes, priv);
        if (!pctx)
                return NULL;
 
index 96e1ef6e5792d6fa7efcc78b927b033e3bb7b9a3..ddb8a0b78fbe10eff46c9853a52b35ed564e7e5e 100644 (file)
@@ -123,6 +123,9 @@ fd_context_destroy(struct pipe_context *pctx)
        if (ctx->blitter)
                util_blitter_destroy(ctx->blitter);
 
+       if (ctx->primconvert)
+               util_primconvert_destroy(ctx->primconvert);
+
        fd_ringmarker_del(ctx->draw_start);
        fd_ringmarker_del(ctx->draw_end);
        fd_ringbuffer_del(ctx->ring);
@@ -131,8 +134,8 @@ fd_context_destroy(struct pipe_context *pctx)
 }
 
 struct pipe_context *
-fd_context_init(struct fd_context *ctx,
-               struct pipe_screen *pscreen, void *priv)
+fd_context_init(struct fd_context *ctx, struct pipe_screen *pscreen,
+               const uint8_t *primtypes, void *priv)
 {
        struct fd_screen *screen = fd_screen(pscreen);
        struct pipe_context *pctx;
@@ -140,6 +143,12 @@ fd_context_init(struct fd_context *ctx,
 
        ctx->screen = screen;
 
+       ctx->primtypes = primtypes;
+       ctx->primtype_mask = 0;
+       for (i = 0; i < PIPE_PRIM_MAX; i++)
+               if (primtypes[i])
+                       ctx->primtype_mask |= (1 << i);
+
        /* need some sane default in case state tracker doesn't
         * set some state:
         */
@@ -170,6 +179,9 @@ fd_context_init(struct fd_context *ctx,
        if (!ctx->blitter)
                goto fail;
 
+       ctx->primconvert = util_primconvert_create(pctx, ctx->primtype_mask);
+       if (!ctx->primconvert)
+               goto fail;
 
        return pctx;
 
index 808e3a72f02017a0b1f5908fb1890879962fbb85..d3a01fcb84b1dc447d979cc9600b6684eccb0f2c 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "draw/draw_context.h"
 #include "pipe/p_context.h"
+#include "indices/u_primconvert.h"
 #include "util/u_blitter.h"
 #include "util/u_slab.h"
 #include "util/u_string.h"
@@ -93,9 +94,17 @@ struct fd_context {
 
        struct fd_screen *screen;
        struct blitter_context *blitter;
+       struct primconvert_context *primconvert;
 
        struct util_slab_mempool transfer_pool;
 
+       /* table with PIPE_PRIM_MAX entries mapping PIPE_PRIM_x to
+        * DI_PT_x value to use for draw initiator.  There are some
+        * slight differences between generation:
+        */
+       const uint8_t *primtypes;
+       uint32_t primtype_mask;
+
        /* shaders used by clear, and gmem->mem blits: */
        struct fd_program_stateobj solid_prog; // TODO move to screen?
 
@@ -244,8 +253,15 @@ fd_context_get_scissor(struct fd_context *ctx)
        return &ctx->disabled_scissor;
 }
 
+static INLINE bool
+fd_supported_prim(struct fd_context *ctx, unsigned prim)
+{
+       return (1 << prim) & ctx->primtype_mask;
+}
+
 struct pipe_context * fd_context_init(struct fd_context *ctx,
-               struct pipe_screen *pscreen, void *priv);
+               struct pipe_screen *pscreen, const uint8_t *primtypes,
+               void *priv);
 
 void fd_context_render(struct pipe_context *pctx);
 
index c00595f7d82280031edceae1f7e4b72cb622f2bf..0069438c87da5c8bd5433661cd5aa18958136e5d 100644 (file)
 #include "freedreno_util.h"
 
 
-static enum pc_di_primtype
-mode2primtype(unsigned mode)
-{
-       switch (mode) {
-       case PIPE_PRIM_POINTS:         return DI_PT_POINTLIST_A2XX;
-       case PIPE_PRIM_LINES:          return DI_PT_LINELIST;
-       case PIPE_PRIM_LINE_STRIP:     return DI_PT_LINESTRIP;
-       case PIPE_PRIM_TRIANGLES:      return DI_PT_TRILIST;
-       case PIPE_PRIM_TRIANGLE_STRIP: return DI_PT_TRISTRIP;
-       case PIPE_PRIM_TRIANGLE_FAN:   return DI_PT_TRIFAN;
-       case PIPE_PRIM_QUADS:          return DI_PT_QUADLIST;
-       case PIPE_PRIM_QUAD_STRIP:     return DI_PT_QUADSTRIP;
-       case PIPE_PRIM_POLYGON:        return DI_PT_POLYGON;
-       }
-       DBG("unsupported mode: (%s) %d", u_prim_name(mode), mode);
-       assert(0);
-       return DI_PT_NONE;
-}
-
 static enum pc_di_index_size
 size2indextype(unsigned index_size)
 {
@@ -97,7 +78,7 @@ fd_draw_emit(struct fd_context *ctx, const struct pipe_draw_info *info)
                src_sel = DI_SRC_SEL_AUTO_INDEX;
        }
 
-       fd_draw(ctx, mode2primtype(info->mode), src_sel, info->count,
+       fd_draw(ctx, ctx->primtypes[info->mode], src_sel, info->count,
                        idx_type, idx_size, idx_offset, idx_bo);
 }
 
@@ -115,6 +96,14 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
                return;
        }
 
+       /* emulate unsupported primitives: */
+       if (!fd_supported_prim(ctx, info->mode)) {
+               util_primconvert_save_index_buffer(ctx->primconvert, &ctx->indexbuf);
+               util_primconvert_save_rasterizer_state(ctx->primconvert, ctx->rasterizer);
+               util_primconvert_draw_vbo(ctx->primconvert, info);
+               return;
+       }
+
        ctx->needs_flush = true;
 
        /*