- struct nv30_context *nv30 = nv30_context(pipe);
- struct nv30_screen *screen = nv30->screen;
- struct nouveau_channel *chan = screen->base.channel;
- struct nouveau_grobj *rankine = screen->rankine;
- unsigned restart = 0;
-
- while (count) {
- unsigned nr, vc;
-
- nv30_state_emit(nv30);
-
- vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 256,
- mode, start, count, &restart);
- if (!vc) {
- FIRE_RING(chan);
- continue;
- }
-
- BEGIN_RING(chan, rankine, NV34TCL_VERTEX_BEGIN_END, 1);
- OUT_RING (chan, nvgl_primitive(mode));
-
- nr = (vc & 0xff);
- if (nr) {
- BEGIN_RING(chan, rankine, NV34TCL_VB_INDEX_BATCH, 1);
- OUT_RING (chan, ((nr - 1) << 24) | start);
- start += nr;
- }
-
- nr = vc >> 8;
- while (nr) {
- unsigned push = nr > 2047 ? 2047 : nr;
-
- nr -= push;
-
- BEGIN_RING_NI(chan, rankine, NV34TCL_VB_INDEX_BATCH, push);
- while (push--) {
- OUT_RING(chan, ((0x100 - 1) << 24) | start);
- start += 0x100;
- }
- }
-
- BEGIN_RING(chan, rankine, NV34TCL_VERTEX_BEGIN_END, 1);
- OUT_RING (chan, 0);
-
- count -= vc;
- start = restart;
- }
+ const unsigned index_size = nv30->idxbuf.index_size;
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ struct nouveau_object *eng3d = nv30->screen->eng3d;
+ unsigned prim = nv30_prim_gl(mode);
+
+#if 0 /*XXX*/
+ if (index_bias != nv30->state.index_bias) {
+ BEGIN_NV04(push, NV30_3D(VB_ELEMENT_BASE), 1);
+ PUSH_DATA (push, index_bias);
+ nv30->state.index_bias = index_bias;
+ }
+#endif
+
+ if (eng3d->oclass == NV40_3D_CLASS && index_size > 1 &&
+ nv30->idxbuf.buffer) {
+ struct nv04_resource *res = nv04_resource(nv30->idxbuf.buffer);
+ unsigned offset = nv30->idxbuf.offset;
+
+ assert(nouveau_resource_mapped_by_gpu(&res->base));
+
+ BEGIN_NV04(push, NV30_3D(IDXBUF_OFFSET), 2);
+ PUSH_RESRC(push, NV30_3D(IDXBUF_OFFSET), BUFCTX_IDXBUF, res, offset,
+ NOUVEAU_BO_LOW | NOUVEAU_BO_RD, 0, 0);
+ PUSH_MTHD (push, NV30_3D(IDXBUF_FORMAT), BUFCTX_IDXBUF, res->bo,
+ (index_size == 2) ? 0x00000010 : 0x00000000,
+ res->domain | NOUVEAU_BO_RD,
+ 0, NV30_3D_IDXBUF_FORMAT_DMA1);
+ BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
+ PUSH_DATA (push, prim);
+ while (count) {
+ const unsigned mpush = 2047 * 256;
+ unsigned npush = (count > mpush) ? mpush : count;
+ unsigned wpush = ((npush + 255) & ~255) >> 8;
+
+ count -= npush;
+
+ BEGIN_NI04(push, NV30_3D(VB_INDEX_BATCH), wpush);
+ while (npush >= 256) {
+ PUSH_DATA (push, 0xff000000 | start);
+ start += 256;
+ npush -= 256;
+ }
+
+ if (npush)
+ PUSH_DATA (push, ((npush - 1) << 24) | start);
+ }
+ BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
+ PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP);
+ PUSH_RESET(push, BUFCTX_IDXBUF);
+ } else {
+ const void *data;
+ if (nv30->idxbuf.buffer)
+ data = nouveau_resource_map_offset(&nv30->base,
+ nv04_resource(nv30->idxbuf.buffer),
+ nv30->idxbuf.offset, NOUVEAU_BO_RD);
+ else
+ data = nv30->idxbuf.user_buffer;
+ if (!data)
+ return;
+
+ BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
+ PUSH_DATA (push, prim);
+ switch (index_size) {
+ case 1:
+ nv30_draw_elements_inline_u08(push, data, start, count);
+ break;
+ case 2:
+ nv30_draw_elements_inline_u16(push, data, start, count);
+ break;
+ case 4:
+ if (shorten)
+ nv30_draw_elements_inline_u32_short(push, data, start, count);
+ else
+ nv30_draw_elements_inline_u32(push, data, start, count);
+ break;
+ default:
+ assert(0);
+ return;
+ }
+ BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
+ PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP);
+ }