summaryrefslogtreecommitdiffstats
path: root/src/gallium
diff options
context:
space:
mode:
authorRob Clark <[email protected]>2013-10-25 15:33:09 -0400
committerRob Clark <[email protected]>2013-10-29 16:49:43 -0400
commit2bc1fc2fb61897ab188f4a7150233827747827ff (patch)
treec7a66a18ae8c6042b47f4ef81f17b2b3e9a7dc6b /src/gallium
parentb88191708816872a0bc93decec0507d797cd4018 (diff)
freedreno: emulated unsupported primitive types
Use u_primconvert to convert unsupported primitives into supported primitive plus index buffer. Signed-off-by: Rob Clark <[email protected]>
Diffstat (limited to 'src/gallium')
-rw-r--r--src/gallium/drivers/freedreno/a2xx/fd2_context.c24
-rw-r--r--src/gallium/drivers/freedreno/a3xx/fd3_context.c12
-rw-r--r--src/gallium/drivers/freedreno/freedreno_context.c16
-rw-r--r--src/gallium/drivers/freedreno/freedreno_context.h18
-rw-r--r--src/gallium/drivers/freedreno/freedreno_draw.c29
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;
/*