nvc0_push.c revision 5655f8d42d919270791588162399ac7a2c718733
1 2#include "pipe/p_context.h" 3#include "pipe/p_state.h" 4#include "util/u_inlines.h" 5#include "util/u_format.h" 6#include "translate/translate.h" 7 8#include "nvc0_context.h" 9#include "nvc0_resource.h" 10 11#include "nvc0_3d.xml.h" 12 13struct push_context { 14 struct nouveau_channel *chan; 15 16 void *idxbuf; 17 18 float edgeflag; 19 int edgeflag_attr; 20 21 uint32_t vertex_words; 22 uint32_t packet_vertex_limit; 23 24 struct translate *translate; 25 26 boolean primitive_restart; 27 uint32_t prim; 28 uint32_t restart_index; 29}; 30 31static INLINE unsigned 32prim_restart_search_i08(uint8_t *elts, unsigned push, uint8_t index) 33{ 34 unsigned i; 35 for (i = 0; i < push; ++i) 36 if (elts[i] == index) 37 break; 38 return i; 39} 40 41static INLINE unsigned 42prim_restart_search_i16(uint16_t *elts, unsigned push, uint16_t index) 43{ 44 unsigned i; 45 for (i = 0; i < push; ++i) 46 if (elts[i] == index) 47 break; 48 return i; 49} 50 51static INLINE unsigned 52prim_restart_search_i32(uint32_t *elts, unsigned push, uint32_t index) 53{ 54 unsigned i; 55 for (i = 0; i < push; ++i) 56 if (elts[i] == index) 57 break; 58 return i; 59} 60 61static void 62emit_vertices_i08(struct push_context *ctx, unsigned start, unsigned count) 63{ 64 uint8_t *elts = (uint8_t *)ctx->idxbuf + start; 65 66 while (count) { 67 unsigned push = MIN2(count, ctx->packet_vertex_limit); 68 unsigned size, nr; 69 70 nr = push; 71 if (ctx->primitive_restart) 72 nr = prim_restart_search_i08(elts, push, ctx->restart_index); 73 74 size = ctx->vertex_words * nr; 75 76 BEGIN_RING_NI(ctx->chan, RING_3D(VERTEX_DATA), size); 77 78 ctx->translate->run_elts8(ctx->translate, elts, push, 0, ctx->chan->cur); 79 80 ctx->chan->cur += size; 81 count -= push; 82 elts += push; 83 84 if (nr != push) { 85 BEGIN_RING(ctx->chan, RING_3D(VERTEX_END_GL), 2); 86 OUT_RING (ctx->chan, 0); 87 OUT_RING (ctx->chan, ctx->prim); 88 } 89 } 90} 91 92static void 93emit_vertices_i16(struct push_context *ctx, unsigned start, unsigned count) 94{ 95 uint16_t *elts = (uint16_t *)ctx->idxbuf + start; 96 97 while (count) { 98 unsigned push = MIN2(count, ctx->packet_vertex_limit); 99 unsigned size, nr; 100 101 nr = push; 102 if (ctx->primitive_restart) 103 nr = prim_restart_search_i16(elts, push, ctx->restart_index); 104 105 size = ctx->vertex_words * nr; 106 107 BEGIN_RING_NI(ctx->chan, RING_3D(VERTEX_DATA), size); 108 109 ctx->translate->run_elts16(ctx->translate, elts, push, 0, ctx->chan->cur); 110 111 ctx->chan->cur += size; 112 count -= push; 113 elts += push; 114 115 if (nr != push) { 116 BEGIN_RING(ctx->chan, RING_3D(VERTEX_END_GL), 2); 117 OUT_RING (ctx->chan, 0); 118 OUT_RING (ctx->chan, ctx->prim); 119 } 120 } 121} 122 123static void 124emit_vertices_i32(struct push_context *ctx, unsigned start, unsigned count) 125{ 126 uint32_t *elts = (uint32_t *)ctx->idxbuf + start; 127 128 while (count) { 129 unsigned push = MIN2(count, ctx->packet_vertex_limit); 130 unsigned size, nr; 131 132 nr = push; 133 if (ctx->primitive_restart) 134 nr = prim_restart_search_i32(elts, push, ctx->restart_index); 135 136 size = ctx->vertex_words * nr; 137 138 BEGIN_RING_NI(ctx->chan, RING_3D(VERTEX_DATA), size); 139 140 ctx->translate->run_elts(ctx->translate, elts, push, 0, ctx->chan->cur); 141 142 ctx->chan->cur += size; 143 count -= push; 144 elts += push; 145 146 if (nr != push) { 147 BEGIN_RING(ctx->chan, RING_3D(VERTEX_END_GL), 2); 148 OUT_RING (ctx->chan, 0); 149 OUT_RING (ctx->chan, ctx->prim); 150 } 151 } 152} 153 154static void 155emit_vertices_seq(struct push_context *ctx, unsigned start, unsigned count) 156{ 157 while (count) { 158 unsigned push = MIN2(count, ctx->packet_vertex_limit); 159 unsigned size = ctx->vertex_words * push; 160 161 BEGIN_RING_NI(ctx->chan, RING_3D(VERTEX_DATA), size); 162 163 ctx->translate->run(ctx->translate, start, push, 0, ctx->chan->cur); 164 ctx->chan->cur += size; 165 count -= push; 166 start += push; 167 } 168} 169 170 171#define NVC0_PRIM_GL_CASE(n) \ 172 case PIPE_PRIM_##n: return NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_##n 173 174static INLINE unsigned 175nvc0_prim_gl(unsigned prim) 176{ 177 switch (prim) { 178 NVC0_PRIM_GL_CASE(POINTS); 179 NVC0_PRIM_GL_CASE(LINES); 180 NVC0_PRIM_GL_CASE(LINE_LOOP); 181 NVC0_PRIM_GL_CASE(LINE_STRIP); 182 NVC0_PRIM_GL_CASE(TRIANGLES); 183 NVC0_PRIM_GL_CASE(TRIANGLE_STRIP); 184 NVC0_PRIM_GL_CASE(TRIANGLE_FAN); 185 NVC0_PRIM_GL_CASE(QUADS); 186 NVC0_PRIM_GL_CASE(QUAD_STRIP); 187 NVC0_PRIM_GL_CASE(POLYGON); 188 NVC0_PRIM_GL_CASE(LINES_ADJACENCY); 189 NVC0_PRIM_GL_CASE(LINE_STRIP_ADJACENCY); 190 NVC0_PRIM_GL_CASE(TRIANGLES_ADJACENCY); 191 NVC0_PRIM_GL_CASE(TRIANGLE_STRIP_ADJACENCY); 192 /* 193 NVC0_PRIM_GL_CASE(PATCHES); */ 194 default: 195 return NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_POINTS; 196 break; 197 } 198} 199 200void 201nvc0_push_vbo(struct nvc0_context *nvc0, const struct pipe_draw_info *info) 202{ 203 struct push_context ctx; 204 struct pipe_transfer *transfer = NULL; 205 unsigned i, index_size; 206 unsigned inst = info->instance_count; 207 208 ctx.chan = nvc0->screen->base.channel; 209 ctx.translate = nvc0->vertex->translate; 210 ctx.packet_vertex_limit = nvc0->vertex->vtx_per_packet_max; 211 ctx.vertex_words = nvc0->vertex->vtx_size; 212 213 for (i = 0; i < nvc0->num_vtxbufs; ++i) { 214 uint8_t *data; 215 struct pipe_vertex_buffer *vb = &nvc0->vtxbuf[i]; 216 struct nvc0_resource *res = nvc0_resource(vb->buffer); 217 218 if (nouveau_bo_map(res->bo, NOUVEAU_BO_RD)) 219 return; 220 data = (uint8_t *)res->bo->map + vb->buffer_offset; 221 if (info->indexed) 222 data += info->index_bias * vb->stride; 223 224 ctx.translate->set_buffer(ctx.translate, i, data, vb->stride, ~0); 225 } 226 227 if (info->indexed) { 228 ctx.idxbuf = pipe_buffer_map(&nvc0->pipe, nvc0->idxbuf.buffer, 229 PIPE_TRANSFER_READ, &transfer); 230 if (!ctx.idxbuf) 231 return; 232 index_size = nvc0->idxbuf.index_size; 233 ctx.primitive_restart = info->primitive_restart; 234 ctx.restart_index = info->restart_index; 235 } else { 236 ctx.idxbuf = NULL; 237 index_size = 0; 238 ctx.primitive_restart = FALSE; 239 ctx.restart_index = 0; 240 } 241 242 ctx.prim = nvc0_prim_gl(info->mode); 243 244 while (inst--) { 245 BEGIN_RING(ctx.chan, RING_3D(VERTEX_BEGIN_GL), 1); 246 OUT_RING (ctx.chan, ctx.prim); 247 switch (index_size) { 248 case 0: 249 emit_vertices_seq(&ctx, info->start, info->count); 250 break; 251 case 1: 252 emit_vertices_i08(&ctx, info->start, info->count); 253 break; 254 case 2: 255 emit_vertices_i16(&ctx, info->start, info->count); 256 break; 257 case 4: 258 emit_vertices_i32(&ctx, info->start, info->count); 259 break; 260 default: 261 assert(0); 262 break; 263 } 264 INLIN_RING(ctx.chan, RING_3D(VERTEX_END_GL), 0); 265 266 ctx.prim |= NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT; 267 } 268 269 if (info->indexed) 270 pipe_buffer_unmap(&nvc0->pipe, nvc0->idxbuf.buffer, transfer); 271 272 for (i = 0; i < nvc0->num_vtxbufs; ++i) { 273 struct nvc0_resource *res = nvc0_resource(nvc0->vtxbuf[i].buffer); 274 275 if (res->bo) 276 nouveau_bo_unmap(res->bo); 277 } 278} 279