struct nouveau_channel *chan;
void *idxbuf;
- int32_t idxbias;
float edgeflag;
- int edgeflat_attr;
+ int edgeflag_attr;
- uint32_t vertex_size;
+ uint32_t vertex_words;
uint32_t packet_vertex_limit;
struct translate *translate;
+
+ boolean primitive_restart;
+ uint32_t prim;
+ uint32_t restart_index;
};
+static INLINE unsigned
+prim_restart_search_i08(uint8_t *elts, unsigned push, uint8_t index)
+{
+ unsigned i;
+ for (i = 0; i < push; ++i)
+ if (elts[i] == index)
+ break;
+ return i;
+}
+
+static INLINE unsigned
+prim_restart_search_i16(uint16_t *elts, unsigned push, uint16_t index)
+{
+ unsigned i;
+ for (i = 0; i < push; ++i)
+ if (elts[i] == index)
+ break;
+ return i;
+}
+
+static INLINE unsigned
+prim_restart_search_i32(uint32_t *elts, unsigned push, uint32_t index)
+{
+ unsigned i;
+ for (i = 0; i < push; ++i)
+ if (elts[i] == index)
+ break;
+ return i;
+}
+
static void
emit_vertices_i08(struct push_context *ctx, unsigned start, unsigned count)
{
while (count) {
unsigned push = MIN2(count, ctx->packet_vertex_limit);
- unsigned size = ctx->vertex_size * push;
+ unsigned size, nr;
+
+ nr = push;
+ if (ctx->primitive_restart)
+ nr = prim_restart_search_i08(elts, push, ctx->restart_index);
+
+ size = ctx->vertex_words * nr;
BEGIN_RING_NI(ctx->chan, RING_3D(VERTEX_DATA), size);
ctx->translate->run_elts8(ctx->translate, elts, push, 0, ctx->chan->cur);
+
ctx->chan->cur += size;
count -= push;
elts += push;
+
+ if (nr != push) {
+ BEGIN_RING(ctx->chan, RING_3D(VERTEX_END_GL), 2);
+ OUT_RING (ctx->chan, 0);
+ OUT_RING (ctx->chan, ctx->prim);
+ }
}
}
while (count) {
unsigned push = MIN2(count, ctx->packet_vertex_limit);
- unsigned size = ctx->vertex_size * push;
+ unsigned size, nr;
+
+ nr = push;
+ if (ctx->primitive_restart)
+ nr = prim_restart_search_i16(elts, push, ctx->restart_index);
+
+ size = ctx->vertex_words * nr;
BEGIN_RING_NI(ctx->chan, RING_3D(VERTEX_DATA), size);
ctx->translate->run_elts16(ctx->translate, elts, push, 0, ctx->chan->cur);
+
ctx->chan->cur += size;
count -= push;
elts += push;
+
+ if (nr != push) {
+ BEGIN_RING(ctx->chan, RING_3D(VERTEX_END_GL), 2);
+ OUT_RING (ctx->chan, 0);
+ OUT_RING (ctx->chan, ctx->prim);
+ }
}
}
while (count) {
unsigned push = MIN2(count, ctx->packet_vertex_limit);
- unsigned size = ctx->vertex_size * push;
+ unsigned size, nr;
+
+ nr = push;
+ if (ctx->primitive_restart)
+ nr = prim_restart_search_i32(elts, push, ctx->restart_index);
+
+ size = ctx->vertex_words * nr;
BEGIN_RING_NI(ctx->chan, RING_3D(VERTEX_DATA), size);
ctx->translate->run_elts(ctx->translate, elts, push, 0, ctx->chan->cur);
+
ctx->chan->cur += size;
count -= push;
elts += push;
+
+ if (nr != push) {
+ BEGIN_RING(ctx->chan, RING_3D(VERTEX_END_GL), 2);
+ OUT_RING (ctx->chan, 0);
+ OUT_RING (ctx->chan, ctx->prim);
+ }
}
}
{
while (count) {
unsigned push = MIN2(count, ctx->packet_vertex_limit);
- unsigned size = ctx->vertex_size * push;
+ unsigned size = ctx->vertex_words * push;
BEGIN_RING_NI(ctx->chan, RING_3D(VERTEX_DATA), size);
struct push_context ctx;
struct pipe_transfer *transfer = NULL;
unsigned i, index_size;
- unsigned prim = nvc0_prim_gl(info->mode);
unsigned inst = info->instance_count;
ctx.chan = nvc0->screen->base.channel;
ctx.translate = nvc0->vertex->translate;
ctx.packet_vertex_limit = nvc0->vertex->vtx_per_packet_max;
- ctx.vertex_size = nvc0->vertex->vtx_size;
+ ctx.vertex_words = nvc0->vertex->vtx_size;
for (i = 0; i < nvc0->num_vtxbufs; ++i) {
uint8_t *data;
if (!ctx.idxbuf)
return;
index_size = nvc0->idxbuf.index_size;
+ ctx.primitive_restart = info->primitive_restart;
+ ctx.restart_index = info->restart_index;
} else {
ctx.idxbuf = NULL;
index_size = 0;
+ ctx.primitive_restart = FALSE;
+ ctx.restart_index = 0;
}
+ ctx.prim = nvc0_prim_gl(info->mode);
+
while (inst--) {
BEGIN_RING(ctx.chan, RING_3D(VERTEX_BEGIN_GL), 1);
- OUT_RING (ctx.chan, prim);
+ OUT_RING (ctx.chan, ctx.prim);
switch (index_size) {
case 0:
emit_vertices_seq(&ctx, info->start, info->count);
}
INLIN_RING(ctx.chan, RING_3D(VERTEX_END_GL), 0);
- prim |= NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT;
+ ctx.prim |= NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT;
}
if (info->indexed)
static void
nvc0_draw_arrays(struct nvc0_context *nvc0,
unsigned mode, unsigned start, unsigned count,
- unsigned start_instance, unsigned instance_count)
+ unsigned instance_count)
{
struct nouveau_channel *chan = nvc0->screen->base.channel;
unsigned prim;
prim = nvc0_prim_gl(mode);
- if (nvc0->state.instance_base != start_instance) {
- nvc0->state.instance_base = start_instance;
- BEGIN_RING(chan, RING_3D(VB_INSTANCE_BASE), 1);
- OUT_RING (chan, start_instance);
- }
-
while (instance_count--) {
BEGIN_RING(chan, RING_3D(VERTEX_BEGIN_GL), 1);
OUT_RING (chan, prim);
static void
nvc0_draw_elements(struct nvc0_context *nvc0,
unsigned mode, unsigned start, unsigned count,
- unsigned start_instance, unsigned instance_count,
+ unsigned instance_count,
unsigned index_size, int index_bias)
{
struct nouveau_channel *chan = nvc0->screen->base.channel;
}
BEGIN_RING(chan, RING_3D(VERTEX_END_GL), 1);
OUT_RING (chan, 0);
+
+ prim |= NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT;
}
chan->flush_notify = NULL;
nvc0_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
{
struct nvc0_context *nvc0 = nvc0_context(pipe);
+ struct nouveau_channel *chan = nvc0->screen->base.channel;
nvc0_state_validate(nvc0);
+ if (nvc0->state.instance_base != info->start_instance) {
+ nvc0->state.instance_base = info->start_instance;
+ BEGIN_RING(chan, RING_3D(VB_INSTANCE_BASE), 1);
+ OUT_RING (chan, info->start_instance);
+ }
+
if (nvc0->vbo_fifo) {
nvc0_push_vbo(nvc0, info);
return;
}
if (nvc0->vbo_dirty) {
- BEGIN_RING(nvc0->screen->base.channel, RING_3D_(0x142c), 1);
- OUT_RING (nvc0->screen->base.channel, 0);
+ BEGIN_RING(chan, RING_3D_(0x142c), 1);
+ OUT_RING (chan, 0);
nvc0->vbo_dirty = FALSE;
}
if (!info->indexed) {
nvc0_draw_arrays(nvc0,
info->mode, info->start, info->count,
- info->start_instance, info->instance_count);
- } else
- if (nvc0->idxbuf.buffer) {
+ info->instance_count);
+ } else {
+ assert(nvc0->idxbuf.buffer);
+
+ if (info->primitive_restart != nvc0->state.prim_restart) {
+ if (info->primitive_restart) {
+ BEGIN_RING(chan, RING_3D(PRIM_RESTART_ENABLE), 2);
+ OUT_RING (chan, 1);
+ OUT_RING (chan, info->restart_index);
+ } else {
+ INLIN_RING(chan, RING_3D(PRIM_RESTART_ENABLE), 0);
+ }
+ nvc0->state.prim_restart = info->primitive_restart;
+ } else
+ if (info->primitive_restart) {
+ BEGIN_RING(chan, RING_3D(PRIM_RESTART_INDEX), 1);
+ OUT_RING (chan, info->restart_index);
+ }
+
nvc0_draw_elements(nvc0,
info->mode, info->start, info->count,
- info->start_instance, info->instance_count,
+ info->instance_count,
nvc0->idxbuf.index_size, info->index_bias);
- } else {
- NOUVEAU_ERR("draw_indexed: no index buffer\n");
}
}