From 2bc1fc2fb61897ab188f4a7150233827747827ff Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Fri, 25 Oct 2013 15:33:09 -0400 Subject: [PATCH] freedreno: emulated unsupported primitive types Use u_primconvert to convert unsupported primitives into supported primitive plus index buffer. Signed-off-by: Rob Clark --- .../drivers/freedreno/a2xx/fd2_context.c | 24 ++++++++++++++- .../drivers/freedreno/a3xx/fd3_context.c | 12 +++++++- .../drivers/freedreno/freedreno_context.c | 16 ++++++++-- .../drivers/freedreno/freedreno_context.h | 18 +++++++++++- .../drivers/freedreno/freedreno_draw.c | 29 ++++++------------- 5 files changed, 74 insertions(+), 25 deletions(-) diff --git a/src/gallium/drivers/freedreno/a2xx/fd2_context.c b/src/gallium/drivers/freedreno/a2xx/fd2_context.c index a3192751164..ec9eaf66417 100644 --- a/src/gallium/drivers/freedreno/a2xx/fd2_context.c +++ b/src/gallium/drivers/freedreno/a2xx/fd2_context.c @@ -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; diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_context.c b/src/gallium/drivers/freedreno/a3xx/fd3_context.c index 589aeed4578..13f91e9de0c 100644 --- a/src/gallium/drivers/freedreno/a3xx/fd3_context.c +++ b/src/gallium/drivers/freedreno/a3xx/fd3_context.c @@ -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; diff --git a/src/gallium/drivers/freedreno/freedreno_context.c b/src/gallium/drivers/freedreno/freedreno_context.c index 96e1ef6e579..ddb8a0b78fb 100644 --- a/src/gallium/drivers/freedreno/freedreno_context.c +++ b/src/gallium/drivers/freedreno/freedreno_context.c @@ -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; diff --git a/src/gallium/drivers/freedreno/freedreno_context.h b/src/gallium/drivers/freedreno/freedreno_context.h index 808e3a72f02..d3a01fcb84b 100644 --- a/src/gallium/drivers/freedreno/freedreno_context.h +++ b/src/gallium/drivers/freedreno/freedreno_context.h @@ -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); diff --git a/src/gallium/drivers/freedreno/freedreno_draw.c b/src/gallium/drivers/freedreno/freedreno_draw.c index c00595f7d82..0069438c87d 100644 --- a/src/gallium/drivers/freedreno/freedreno_draw.c +++ b/src/gallium/drivers/freedreno/freedreno_draw.c @@ -39,25 +39,6 @@ #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; /* -- 2.30.2