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 13 struct push_context { 14 struct nouveau_pushbuf *push; 15 16 void *idxbuf; 17 18 uint32_t vertex_words; 19 uint32_t packet_vertex_limit; 20 21 struct translate *translate; 22 23 boolean primitive_restart; 24 boolean need_vertex_id; 25 uint32_t prim; 26 uint32_t restart_index; 27 uint32_t instance_id; 28 29 struct { 30 int buffer; 31 float value; 32 uint8_t *data; 33 unsigned offset; 34 unsigned stride; 35 } edgeflag; 36 }; 37 38 static void 39 init_push_context(struct nvc0_context *nvc0, struct push_context *ctx) 40 { 41 struct pipe_vertex_element *ve; 42 43 ctx->push = nvc0->base.pushbuf; 44 ctx->translate = nvc0->vertex->translate; 45 46 if (likely(nvc0->vertex->num_elements < 32)) 47 ctx->need_vertex_id = nvc0->vertprog->vp.need_vertex_id; 48 else 49 ctx->need_vertex_id = FALSE; 50 51 ctx->edgeflag.buffer = -1; 52 ctx->edgeflag.value = 0.5f; 53 54 if (unlikely(nvc0->vertprog->vp.edgeflag < PIPE_MAX_ATTRIBS)) { 55 ve = &nvc0->vertex->element[nvc0->vertprog->vp.edgeflag].pipe; 56 ctx->edgeflag.buffer = ve->vertex_buffer_index; 57 ctx->edgeflag.offset = ve->src_offset; 58 ctx->packet_vertex_limit = 1; 59 } else { 60 ctx->packet_vertex_limit = nvc0->vertex->vtx_per_packet_max; 61 if (unlikely(ctx->need_vertex_id)) 62 ctx->packet_vertex_limit = 1; 63 } 64 65 ctx->vertex_words = nvc0->vertex->vtx_size; 66 } 67 68 static INLINE void 69 set_edgeflag(struct push_context *ctx, unsigned vtx_id) 70 { 71 float f = *(float *)(ctx->edgeflag.data + vtx_id * ctx->edgeflag.stride); 72 73 if (ctx->edgeflag.value != f) { 74 ctx->edgeflag.value = f; 75 IMMED_NVC0(ctx->push, NVC0_3D(EDGEFLAG), f ? 1 : 0); 76 } 77 } 78 79 static INLINE void 80 set_vertexid(struct push_context *ctx, uint32_t vtx_id) 81 { 82 #if 0 83 BEGIN_NVC0(ctx->push, NVC0_3D(VERTEX_ID), 1); /* broken on nvc0 */ 84 #else 85 BEGIN_NVC0(ctx->push, NVC0_3D(VERTEX_DATA), 1); /* as last attribute */ 86 #endif 87 PUSH_DATA (ctx->push, vtx_id); 88 } 89 90 static INLINE unsigned 91 prim_restart_search_i08(uint8_t *elts, unsigned push, uint8_t index) 92 { 93 unsigned i; 94 for (i = 0; i < push; ++i) 95 if (elts[i] == index) 96 break; 97 return i; 98 } 99 100 static INLINE unsigned 101 prim_restart_search_i16(uint16_t *elts, unsigned push, uint16_t index) 102 { 103 unsigned i; 104 for (i = 0; i < push; ++i) 105 if (elts[i] == index) 106 break; 107 return i; 108 } 109 110 static INLINE unsigned 111 prim_restart_search_i32(uint32_t *elts, unsigned push, uint32_t index) 112 { 113 unsigned i; 114 for (i = 0; i < push; ++i) 115 if (elts[i] == index) 116 break; 117 return i; 118 } 119 120 static void 121 emit_vertices_i08(struct push_context *ctx, unsigned start, unsigned count) 122 { 123 uint8_t *restrict elts = (uint8_t *)ctx->idxbuf + start; 124 125 while (count) { 126 unsigned push = MIN2(count, ctx->packet_vertex_limit); 127 unsigned size, nr; 128 129 nr = push; 130 if (ctx->primitive_restart) 131 nr = prim_restart_search_i08(elts, push, ctx->restart_index); 132 133 if (unlikely(ctx->edgeflag.buffer >= 0) && likely(nr)) 134 set_edgeflag(ctx, elts[0]); 135 136 size = ctx->vertex_words * nr; 137 138 BEGIN_NIC0(ctx->push, NVC0_3D(VERTEX_DATA), size); 139 140 ctx->translate->run_elts8(ctx->translate, elts, nr, ctx->instance_id, 141 ctx->push->cur); 142 ctx->push->cur += size; 143 144 if (unlikely(ctx->need_vertex_id) && likely(size)) 145 set_vertexid(ctx, elts[0]); 146 147 count -= nr; 148 elts += nr; 149 150 if (nr != push) { 151 count--; 152 elts++; 153 BEGIN_NVC0(ctx->push, NVC0_3D(VERTEX_END_GL), 2); 154 PUSH_DATA (ctx->push, 0); 155 PUSH_DATA (ctx->push, NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_CONT | 156 (ctx->prim & ~NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT)); 157 } 158 } 159 } 160 161 static void 162 emit_vertices_i16(struct push_context *ctx, unsigned start, unsigned count) 163 { 164 uint16_t *restrict elts = (uint16_t *)ctx->idxbuf + start; 165 166 while (count) { 167 unsigned push = MIN2(count, ctx->packet_vertex_limit); 168 unsigned size, nr; 169 170 nr = push; 171 if (ctx->primitive_restart) 172 nr = prim_restart_search_i16(elts, push, ctx->restart_index); 173 174 if (unlikely(ctx->edgeflag.buffer >= 0) && likely(nr)) 175 set_edgeflag(ctx, elts[0]); 176 177 size = ctx->vertex_words * nr; 178 179 BEGIN_NIC0(ctx->push, NVC0_3D(VERTEX_DATA), size); 180 181 ctx->translate->run_elts16(ctx->translate, elts, nr, ctx->instance_id, 182 ctx->push->cur); 183 ctx->push->cur += size; 184 185 if (unlikely(ctx->need_vertex_id)) 186 set_vertexid(ctx, elts[0]); 187 188 count -= nr; 189 elts += nr; 190 191 if (nr != push) { 192 count--; 193 elts++; 194 BEGIN_NVC0(ctx->push, NVC0_3D(VERTEX_END_GL), 2); 195 PUSH_DATA (ctx->push, 0); 196 PUSH_DATA (ctx->push, NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_CONT | 197 (ctx->prim & ~NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT)); 198 } 199 } 200 } 201 202 static void 203 emit_vertices_i32(struct push_context *ctx, unsigned start, unsigned count) 204 { 205 uint32_t *restrict elts = (uint32_t *)ctx->idxbuf + start; 206 207 while (count) { 208 unsigned push = MIN2(count, ctx->packet_vertex_limit); 209 unsigned size, nr; 210 211 nr = push; 212 if (ctx->primitive_restart) 213 nr = prim_restart_search_i32(elts, push, ctx->restart_index); 214 215 if (unlikely(ctx->edgeflag.buffer >= 0) && likely(nr)) 216 set_edgeflag(ctx, elts[0]); 217 218 size = ctx->vertex_words * nr; 219 220 BEGIN_NIC0(ctx->push, NVC0_3D(VERTEX_DATA), size); 221 222 ctx->translate->run_elts(ctx->translate, elts, nr, ctx->instance_id, 223 ctx->push->cur); 224 ctx->push->cur += size; 225 226 if (unlikely(ctx->need_vertex_id)) 227 set_vertexid(ctx, elts[0]); 228 229 count -= nr; 230 elts += nr; 231 232 if (nr != push) { 233 count--; 234 elts++; 235 BEGIN_NVC0(ctx->push, NVC0_3D(VERTEX_END_GL), 2); 236 PUSH_DATA (ctx->push, 0); 237 PUSH_DATA (ctx->push, NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_CONT | 238 (ctx->prim & ~NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT)); 239 } 240 } 241 } 242 243 static void 244 emit_vertices_seq(struct push_context *ctx, unsigned start, unsigned count) 245 { 246 while (count) { 247 unsigned push = MIN2(count, ctx->packet_vertex_limit); 248 unsigned size = ctx->vertex_words * push; 249 250 if (unlikely(ctx->edgeflag.buffer >= 0)) 251 set_edgeflag(ctx, start); 252 253 BEGIN_NIC0(ctx->push, NVC0_3D(VERTEX_DATA), size); 254 255 ctx->translate->run(ctx->translate, start, push, ctx->instance_id, 256 ctx->push->cur); 257 ctx->push->cur += size; 258 259 if (unlikely(ctx->need_vertex_id)) 260 set_vertexid(ctx, start); 261 262 count -= push; 263 start += push; 264 } 265 } 266 267 268 #define NVC0_PRIM_GL_CASE(n) \ 269 case PIPE_PRIM_##n: return NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_##n 270 271 static INLINE unsigned 272 nvc0_prim_gl(unsigned prim) 273 { 274 switch (prim) { 275 NVC0_PRIM_GL_CASE(POINTS); 276 NVC0_PRIM_GL_CASE(LINES); 277 NVC0_PRIM_GL_CASE(LINE_LOOP); 278 NVC0_PRIM_GL_CASE(LINE_STRIP); 279 NVC0_PRIM_GL_CASE(TRIANGLES); 280 NVC0_PRIM_GL_CASE(TRIANGLE_STRIP); 281 NVC0_PRIM_GL_CASE(TRIANGLE_FAN); 282 NVC0_PRIM_GL_CASE(QUADS); 283 NVC0_PRIM_GL_CASE(QUAD_STRIP); 284 NVC0_PRIM_GL_CASE(POLYGON); 285 NVC0_PRIM_GL_CASE(LINES_ADJACENCY); 286 NVC0_PRIM_GL_CASE(LINE_STRIP_ADJACENCY); 287 NVC0_PRIM_GL_CASE(TRIANGLES_ADJACENCY); 288 NVC0_PRIM_GL_CASE(TRIANGLE_STRIP_ADJACENCY); 289 /* 290 NVC0_PRIM_GL_CASE(PATCHES); */ 291 default: 292 return NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_POINTS; 293 break; 294 } 295 } 296 297 void 298 nvc0_push_vbo(struct nvc0_context *nvc0, const struct pipe_draw_info *info) 299 { 300 struct push_context ctx; 301 unsigned i, index_size; 302 unsigned inst_count = info->instance_count; 303 unsigned vert_count = info->count; 304 boolean apply_bias = info->indexed && info->index_bias; 305 306 init_push_context(nvc0, &ctx); 307 308 for (i = 0; i < nvc0->num_vtxbufs; ++i) { 309 uint8_t *data; 310 struct pipe_vertex_buffer *vb = &nvc0->vtxbuf[i]; 311 struct nv04_resource *res = nv04_resource(vb->buffer); 312 313 data = nouveau_resource_map_offset(&nvc0->base, res, 314 vb->buffer_offset, NOUVEAU_BO_RD); 315 316 if (apply_bias && likely(!(nvc0->vertex->instance_bufs & (1 << i)))) 317 data += info->index_bias * vb->stride; 318 319 ctx.translate->set_buffer(ctx.translate, i, data, vb->stride, ~0); 320 321 if (unlikely(i == ctx.edgeflag.buffer)) { 322 ctx.edgeflag.data = data + ctx.edgeflag.offset; 323 ctx.edgeflag.stride = vb->stride; 324 } 325 } 326 327 if (info->indexed) { 328 ctx.idxbuf = 329 nouveau_resource_map_offset(&nvc0->base, 330 nv04_resource(nvc0->idxbuf.buffer), 331 nvc0->idxbuf.offset, NOUVEAU_BO_RD); 332 if (!ctx.idxbuf) 333 return; 334 index_size = nvc0->idxbuf.index_size; 335 ctx.primitive_restart = info->primitive_restart; 336 ctx.restart_index = info->restart_index; 337 } else { 338 ctx.idxbuf = NULL; 339 index_size = 0; 340 ctx.primitive_restart = FALSE; 341 ctx.restart_index = 0; 342 343 if (info->count_from_stream_output) { 344 struct pipe_context *pipe = &nvc0->base.pipe; 345 struct nvc0_so_target *targ; 346 targ = nvc0_so_target(info->count_from_stream_output); 347 pipe->get_query_result(pipe, targ->pq, TRUE, (void*)&vert_count); 348 vert_count /= targ->stride; 349 } 350 } 351 352 ctx.instance_id = info->start_instance; 353 ctx.prim = nvc0_prim_gl(info->mode); 354 355 if (unlikely(ctx.need_vertex_id)) { 356 const unsigned a = nvc0->vertex->num_elements; 357 BEGIN_NVC0(ctx.push, NVC0_3D(VERTEX_ATTRIB_FORMAT(a)), 1); 358 PUSH_DATA (ctx.push, (a << NVC0_3D_VERTEX_ATTRIB_FORMAT_BUFFER__SHIFT) | 359 NVC0_3D_VERTEX_ATTRIB_FORMAT_TYPE_FLOAT | 360 NVC0_3D_VERTEX_ATTRIB_FORMAT_SIZE_32); 361 BEGIN_NVC0(ctx.push, NVC0_3D(VERTEX_ID_REPLACE), 1); 362 PUSH_DATA (ctx.push, (((0x80 + a * 0x10) / 4) << 4) | 1); 363 } 364 365 while (inst_count--) { 366 BEGIN_NVC0(ctx.push, NVC0_3D(VERTEX_BEGIN_GL), 1); 367 PUSH_DATA (ctx.push, ctx.prim); 368 switch (index_size) { 369 case 0: 370 emit_vertices_seq(&ctx, info->start, vert_count); 371 break; 372 case 1: 373 emit_vertices_i08(&ctx, info->start, vert_count); 374 break; 375 case 2: 376 emit_vertices_i16(&ctx, info->start, vert_count); 377 break; 378 case 4: 379 emit_vertices_i32(&ctx, info->start, vert_count); 380 break; 381 default: 382 assert(0); 383 break; 384 } 385 IMMED_NVC0(ctx.push, NVC0_3D(VERTEX_END_GL), 0); 386 387 ctx.instance_id++; 388 ctx.prim |= NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT; 389 } 390 391 if (unlikely(ctx.edgeflag.value == 0.0f)) 392 IMMED_NVC0(ctx.push, NVC0_3D(EDGEFLAG), 1); 393 394 if (unlikely(ctx.need_vertex_id)) { 395 const unsigned a = nvc0->vertex->num_elements; 396 IMMED_NVC0(ctx.push, NVC0_3D(VERTEX_ID_REPLACE), 0); 397 BEGIN_NVC0(ctx.push, NVC0_3D(VERTEX_ATTRIB_FORMAT(a)), 1); 398 PUSH_DATA (ctx.push, 399 NVC0_3D_VERTEX_ATTRIB_FORMAT_CONST | 400 NVC0_3D_VERTEX_ATTRIB_FORMAT_TYPE_FLOAT | 401 NVC0_3D_VERTEX_ATTRIB_FORMAT_SIZE_32); 402 } 403 404 if (info->indexed) 405 nouveau_resource_unmap(nv04_resource(nvc0->idxbuf.buffer)); 406 407 for (i = 0; i < nvc0->num_vtxbufs; ++i) 408 nouveau_resource_unmap(nv04_resource(nvc0->vtxbuf[i].buffer)); 409 } 410