[Mesa-dev] [PATCH 3/3] freedreno: emulated unsupported primitive types

Rob Clark robdclark at gmail.com
Fri Oct 25 21:53:06 CEST 2013


From: Rob Clark <robclark at freedesktop.org>

Use u_primconvert to convert unsupported primitives into supported
primitive plus index buffer.

Signed-off-by: Rob Clark <robclark at freedesktop.org>
---
 src/gallium/drivers/freedreno/a2xx/fd2_context.c  | 24 ++++++++++++++++++-
 src/gallium/drivers/freedreno/a3xx/fd3_context.c  | 12 +++++++++-
 src/gallium/drivers/freedreno/freedreno_context.c | 16 +++++++++++--
 src/gallium/drivers/freedreno/freedreno_context.h | 18 +++++++++++++-
 src/gallium/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 a319275..ec9eaf6 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 589aeed..13f91e9 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 96e1ef6..ddb8a0b 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 808e3a7..d3a01fc 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 c00595f..0069438 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;
 
 	/*
-- 
1.8.3.1



More information about the mesa-dev mailing list