1 /* 2 * Copyright 2010 Christoph Bumiller 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 * SOFTWARE. 21 */ 22 23 #define NVC0_PUSH_EXPLICIT_SPACE_CHECKING 24 25 #include "pipe/p_context.h" 26 #include "pipe/p_state.h" 27 #include "util/u_inlines.h" 28 #include "util/u_format.h" 29 #include "translate/translate.h" 30 31 #include "nvc0_context.h" 32 #include "nvc0_resource.h" 33 34 #include "nvc0_3d.xml.h" 35 36 void 37 nvc0_vertex_state_delete(struct pipe_context *pipe, 38 void *hwcso) 39 { 40 struct nvc0_vertex_stateobj *so = hwcso; 41 42 if (so->translate) 43 so->translate->release(so->translate); 44 FREE(hwcso); 45 } 46 47 void * 48 nvc0_vertex_state_create(struct pipe_context *pipe, 49 unsigned num_elements, 50 const struct pipe_vertex_element *elements) 51 { 52 struct nvc0_vertex_stateobj *so; 53 struct translate_key transkey; 54 unsigned i; 55 unsigned src_offset_max = 0; 56 57 so = MALLOC(sizeof(*so) + 58 num_elements * sizeof(struct nvc0_vertex_element)); 59 if (!so) 60 return NULL; 61 so->num_elements = num_elements; 62 so->instance_elts = 0; 63 so->instance_bufs = 0; 64 so->shared_slots = FALSE; 65 so->need_conversion = FALSE; 66 67 memset(so->vb_access_size, 0, sizeof(so->vb_access_size)); 68 69 for (i = 0; i < PIPE_MAX_ATTRIBS; ++i) 70 so->min_instance_div[i] = 0xffffffff; 71 72 transkey.nr_elements = 0; 73 transkey.output_stride = 0; 74 75 for (i = 0; i < num_elements; ++i) { 76 const struct pipe_vertex_element *ve = &elements[i]; 77 const unsigned vbi = ve->vertex_buffer_index; 78 unsigned size; 79 enum pipe_format fmt = ve->src_format; 80 81 so->element[i].pipe = elements[i]; 82 so->element[i].state = nvc0_format_table[fmt].vtx; 83 84 if (!so->element[i].state) { 85 switch (util_format_get_nr_components(fmt)) { 86 case 1: fmt = PIPE_FORMAT_R32_FLOAT; break; 87 case 2: fmt = PIPE_FORMAT_R32G32_FLOAT; break; 88 case 3: fmt = PIPE_FORMAT_R32G32B32_FLOAT; break; 89 case 4: fmt = PIPE_FORMAT_R32G32B32A32_FLOAT; break; 90 default: 91 assert(0); 92 return NULL; 93 } 94 so->element[i].state = nvc0_format_table[fmt].vtx; 95 so->need_conversion = TRUE; 96 } 97 size = util_format_get_blocksize(fmt); 98 99 src_offset_max = MAX2(src_offset_max, ve->src_offset); 100 101 if (so->vb_access_size[vbi] < (ve->src_offset + size)) 102 so->vb_access_size[vbi] = ve->src_offset + size; 103 104 if (unlikely(ve->instance_divisor)) { 105 so->instance_elts |= 1 << i; 106 so->instance_bufs |= 1 << vbi; 107 if (ve->instance_divisor < so->min_instance_div[vbi]) 108 so->min_instance_div[vbi] = ve->instance_divisor; 109 } 110 111 if (1) { 112 unsigned ca; 113 unsigned j = transkey.nr_elements++; 114 115 ca = util_format_description(fmt)->channel[0].size / 8; 116 if (ca != 1 && ca != 2) 117 ca = 4; 118 119 transkey.element[j].type = TRANSLATE_ELEMENT_NORMAL; 120 transkey.element[j].input_format = ve->src_format; 121 transkey.element[j].input_buffer = vbi; 122 transkey.element[j].input_offset = ve->src_offset; 123 transkey.element[j].instance_divisor = ve->instance_divisor; 124 125 transkey.output_stride = align(transkey.output_stride, ca); 126 transkey.element[j].output_format = fmt; 127 transkey.element[j].output_offset = transkey.output_stride; 128 transkey.output_stride += size; 129 130 so->element[i].state_alt = so->element[i].state; 131 so->element[i].state_alt |= transkey.element[j].output_offset << 7; 132 } 133 134 so->element[i].state |= i << NVC0_3D_VERTEX_ATTRIB_FORMAT_BUFFER__SHIFT; 135 } 136 transkey.output_stride = align(transkey.output_stride, 4); 137 138 so->size = transkey.output_stride; 139 so->translate = translate_create(&transkey); 140 141 if (so->instance_elts || src_offset_max >= (1 << 14)) 142 return so; 143 so->shared_slots = TRUE; 144 145 for (i = 0; i < num_elements; ++i) { 146 const unsigned b = elements[i].vertex_buffer_index; 147 const unsigned s = elements[i].src_offset; 148 so->element[i].state &= ~NVC0_3D_VERTEX_ATTRIB_FORMAT_BUFFER__MASK; 149 so->element[i].state |= b << NVC0_3D_VERTEX_ATTRIB_FORMAT_BUFFER__SHIFT; 150 so->element[i].state |= s << NVC0_3D_VERTEX_ATTRIB_FORMAT_OFFSET__SHIFT; 151 } 152 return so; 153 } 154 155 #define NVC0_3D_VERTEX_ATTRIB_INACTIVE \ 156 NVC0_3D_VERTEX_ATTRIB_FORMAT_TYPE_FLOAT | \ 157 NVC0_3D_VERTEX_ATTRIB_FORMAT_SIZE_32 | NVC0_3D_VERTEX_ATTRIB_FORMAT_CONST 158 159 #define VTX_ATTR(a, c, t, s) \ 160 ((NVC0_3D_VTX_ATTR_DEFINE_TYPE_##t) | \ 161 (NVC0_3D_VTX_ATTR_DEFINE_SIZE_##s) | \ 162 ((a) << NVC0_3D_VTX_ATTR_DEFINE_ATTR__SHIFT) | \ 163 ((c) << NVC0_3D_VTX_ATTR_DEFINE_COMP__SHIFT)) 164 165 static void 166 nvc0_set_constant_vertex_attrib(struct nvc0_context *nvc0, const unsigned a) 167 { 168 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 169 struct pipe_vertex_element *ve = &nvc0->vertex->element[a].pipe; 170 struct pipe_vertex_buffer *vb = &nvc0->vtxbuf[ve->vertex_buffer_index]; 171 uint32_t mode; 172 const struct util_format_description *desc; 173 void *dst; 174 const void *src = (const uint8_t *)vb->user_buffer + ve->src_offset; 175 assert(!vb->buffer); 176 177 desc = util_format_description(ve->src_format); 178 179 PUSH_SPACE(push, 6); 180 BEGIN_NVC0(push, NVC0_3D(VTX_ATTR_DEFINE), 5); 181 dst = &push->cur[1]; 182 if (desc->channel[0].pure_integer) { 183 if (desc->channel[0].type == UTIL_FORMAT_TYPE_SIGNED) { 184 mode = VTX_ATTR(a, 4, SINT, 32); 185 desc->unpack_rgba_sint(dst, 0, src, 0, 1, 1); 186 } else { 187 mode = VTX_ATTR(a, 4, UINT, 32); 188 desc->unpack_rgba_uint(dst, 0, src, 0, 1, 1); 189 } 190 } else { 191 mode = VTX_ATTR(a, 4, FLOAT, 32); 192 desc->unpack_rgba_float(dst, 0, src, 0, 1, 1); 193 } 194 push->cur[0] = mode; 195 push->cur += 5; 196 } 197 198 static INLINE void 199 nvc0_user_vbuf_range(struct nvc0_context *nvc0, int vbi, 200 uint32_t *base, uint32_t *size) 201 { 202 if (unlikely(nvc0->vertex->instance_bufs & (1 << vbi))) { 203 const uint32_t div = nvc0->vertex->min_instance_div[vbi]; 204 *base = nvc0->instance_off * nvc0->vtxbuf[vbi].stride; 205 *size = (nvc0->instance_max / div) * nvc0->vtxbuf[vbi].stride + 206 nvc0->vertex->vb_access_size[vbi]; 207 } else { 208 /* NOTE: if there are user buffers, we *must* have index bounds */ 209 assert(nvc0->vb_elt_limit != ~0); 210 *base = nvc0->vb_elt_first * nvc0->vtxbuf[vbi].stride; 211 *size = nvc0->vb_elt_limit * nvc0->vtxbuf[vbi].stride + 212 nvc0->vertex->vb_access_size[vbi]; 213 } 214 } 215 216 static INLINE void 217 nvc0_release_user_vbufs(struct nvc0_context *nvc0) 218 { 219 if (nvc0->vbo_user) { 220 nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_VTX_TMP); 221 nouveau_scratch_done(&nvc0->base); 222 } 223 } 224 225 static void 226 nvc0_update_user_vbufs(struct nvc0_context *nvc0) 227 { 228 uint64_t address[PIPE_MAX_ATTRIBS]; 229 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 230 int i; 231 uint32_t written = 0; 232 233 PUSH_SPACE(push, nvc0->vertex->num_elements * 8); 234 for (i = 0; i < nvc0->vertex->num_elements; ++i) { 235 struct pipe_vertex_element *ve = &nvc0->vertex->element[i].pipe; 236 const unsigned b = ve->vertex_buffer_index; 237 struct pipe_vertex_buffer *vb = &nvc0->vtxbuf[b]; 238 uint32_t base, size; 239 240 if (!(nvc0->vbo_user & (1 << b))) 241 continue; 242 if (!vb->stride) { 243 nvc0_set_constant_vertex_attrib(nvc0, i); 244 continue; 245 } 246 nvc0_user_vbuf_range(nvc0, b, &base, &size); 247 248 if (!(written & (1 << b))) { 249 struct nouveau_bo *bo; 250 const uint32_t bo_flags = NOUVEAU_BO_RD | NOUVEAU_BO_GART; 251 written |= 1 << b; 252 address[b] = nouveau_scratch_data(&nvc0->base, vb->user_buffer, 253 base, size, &bo); 254 if (bo) 255 BCTX_REFN_bo(nvc0->bufctx_3d, VTX_TMP, bo_flags, bo); 256 } 257 258 BEGIN_1IC0(push, NVC0_3D(MACRO_VERTEX_ARRAY_SELECT), 5); 259 PUSH_DATA (push, i); 260 PUSH_DATAh(push, address[b] + base + size - 1); 261 PUSH_DATA (push, address[b] + base + size - 1); 262 PUSH_DATAh(push, address[b] + ve->src_offset); 263 PUSH_DATA (push, address[b] + ve->src_offset); 264 } 265 nvc0->base.vbo_dirty = TRUE; 266 } 267 268 static void 269 nvc0_update_user_vbufs_shared(struct nvc0_context *nvc0) 270 { 271 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 272 uint32_t mask = nvc0->vbo_user & ~nvc0->constant_vbos; 273 274 PUSH_SPACE(push, nvc0->num_vtxbufs * 8); 275 while (mask) { 276 struct nouveau_bo *bo; 277 const uint32_t bo_flags = NOUVEAU_BO_RD | NOUVEAU_BO_GART; 278 uint64_t address; 279 uint32_t base, size; 280 const int b = ffs(mask) - 1; 281 mask &= ~(1 << b); 282 283 nvc0_user_vbuf_range(nvc0, b, &base, &size); 284 285 address = nouveau_scratch_data(&nvc0->base, nvc0->vtxbuf[b].user_buffer, 286 base, size, &bo); 287 if (bo) 288 BCTX_REFN_bo(nvc0->bufctx_3d, VTX_TMP, bo_flags, bo); 289 290 BEGIN_1IC0(push, NVC0_3D(MACRO_VERTEX_ARRAY_SELECT), 5); 291 PUSH_DATA (push, b); 292 PUSH_DATAh(push, address + base + size - 1); 293 PUSH_DATA (push, address + base + size - 1); 294 PUSH_DATAh(push, address); 295 PUSH_DATA (push, address); 296 } 297 298 mask = nvc0->state.constant_elts; 299 while (mask) { 300 int i = ffs(mask) - 1; 301 mask &= ~(1 << i); 302 nvc0_set_constant_vertex_attrib(nvc0, i); 303 } 304 } 305 306 static void 307 nvc0_validate_vertex_buffers(struct nvc0_context *nvc0) 308 { 309 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 310 const struct nvc0_vertex_stateobj *vertex = nvc0->vertex; 311 uint32_t refd = 0; 312 unsigned i; 313 314 PUSH_SPACE(push, vertex->num_elements * 8); 315 for (i = 0; i < vertex->num_elements; ++i) { 316 const struct nvc0_vertex_element *ve; 317 const struct pipe_vertex_buffer *vb; 318 struct nv04_resource *res; 319 unsigned b; 320 unsigned limit, offset; 321 322 if (nvc0->state.constant_elts & (1 << i)) 323 continue; 324 ve = &vertex->element[i]; 325 b = ve->pipe.vertex_buffer_index; 326 vb = &nvc0->vtxbuf[b]; 327 328 if (!vb->buffer) { 329 if (vb->stride) { 330 if (ve->pipe.instance_divisor) { 331 BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_DIVISOR(i)), 1); 332 PUSH_DATA (push, ve->pipe.instance_divisor); 333 } 334 BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(i)), 1); 335 PUSH_DATA (push, (1 << 12) | vb->stride); 336 } 337 /* address/value set in nvc0_update_user_vbufs */ 338 continue; 339 } 340 res = nv04_resource(vb->buffer); 341 offset = ve->pipe.src_offset + vb->buffer_offset; 342 limit = vb->buffer->width0 - 1; 343 344 if (unlikely(ve->pipe.instance_divisor)) { 345 BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(i)), 4); 346 PUSH_DATA (push, (1 << 12) | vb->stride); 347 PUSH_DATAh(push, res->address + offset); 348 PUSH_DATA (push, res->address + offset); 349 PUSH_DATA (push, ve->pipe.instance_divisor); 350 } else { 351 BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(i)), 3); 352 PUSH_DATA (push, (1 << 12) | vb->stride); 353 PUSH_DATAh(push, res->address + offset); 354 PUSH_DATA (push, res->address + offset); 355 } 356 BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_LIMIT_HIGH(i)), 2); 357 PUSH_DATAh(push, res->address + limit); 358 PUSH_DATA (push, res->address + limit); 359 360 if (!(refd & (1 << b))) { 361 refd |= 1 << b; 362 BCTX_REFN(nvc0->bufctx_3d, VTX, res, RD); 363 } 364 } 365 if (nvc0->vbo_user) 366 nvc0_update_user_vbufs(nvc0); 367 } 368 369 static void 370 nvc0_validate_vertex_buffers_shared(struct nvc0_context *nvc0) 371 { 372 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 373 unsigned b; 374 const uint32_t mask = nvc0->vbo_user; 375 376 PUSH_SPACE(push, nvc0->num_vtxbufs * 8); 377 for (b = 0; b < nvc0->num_vtxbufs; ++b) { 378 struct pipe_vertex_buffer *vb = &nvc0->vtxbuf[b]; 379 struct nv04_resource *buf; 380 uint32_t offset, limit; 381 382 if (mask & (1 << b)) { 383 if (vb->stride) { 384 BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(b)), 1); 385 PUSH_DATA (push, NVC0_3D_VERTEX_ARRAY_FETCH_ENABLE | vb->stride); 386 } 387 /* address/value set in nvc0_update_user_vbufs_shared */ 388 continue; 389 } 390 buf = nv04_resource(vb->buffer); 391 offset = vb->buffer_offset; 392 limit = buf->base.width0 - 1; 393 394 BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(b)), 3); 395 PUSH_DATA (push, NVC0_3D_VERTEX_ARRAY_FETCH_ENABLE | vb->stride); 396 PUSH_DATAh(push, buf->address + offset); 397 PUSH_DATA (push, buf->address + offset); 398 BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_LIMIT_HIGH(b)), 2); 399 PUSH_DATAh(push, buf->address + limit); 400 PUSH_DATA (push, buf->address + limit); 401 402 BCTX_REFN(nvc0->bufctx_3d, VTX, buf, RD); 403 } 404 if (nvc0->vbo_user) 405 nvc0_update_user_vbufs_shared(nvc0); 406 } 407 408 void 409 nvc0_vertex_arrays_validate(struct nvc0_context *nvc0) 410 { 411 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 412 struct nvc0_vertex_stateobj *vertex = nvc0->vertex; 413 struct nvc0_vertex_element *ve; 414 uint32_t const_vbos; 415 unsigned i; 416 uint8_t vbo_mode; 417 boolean update_vertex; 418 419 nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_VTX); 420 421 if (unlikely(vertex->need_conversion) || 422 unlikely(nvc0->vertprog->vp.edgeflag < PIPE_MAX_ATTRIBS)) { 423 vbo_mode = 3; 424 } else { 425 vbo_mode = (nvc0->vbo_user && nvc0->vbo_push_hint) ? 1 : 0; 426 } 427 const_vbos = vbo_mode ? 0 : nvc0->constant_vbos; 428 429 update_vertex = (nvc0->dirty & NVC0_NEW_VERTEX) || 430 (const_vbos != nvc0->state.constant_vbos) || 431 (vbo_mode != nvc0->state.vbo_mode); 432 433 if (update_vertex) { 434 const unsigned n = MAX2(vertex->num_elements, nvc0->state.num_vtxelts); 435 436 nvc0->state.constant_vbos = const_vbos; 437 nvc0->state.constant_elts = 0; 438 nvc0->state.num_vtxelts = vertex->num_elements; 439 nvc0->state.vbo_mode = vbo_mode; 440 441 if (unlikely(vbo_mode)) { 442 if (unlikely(nvc0->state.instance_elts & 3)) { 443 /* translate mode uses only 2 vertex buffers */ 444 nvc0->state.instance_elts &= ~3; 445 PUSH_SPACE(push, 3); 446 BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_PER_INSTANCE(0)), 2); 447 PUSH_DATA (push, 0); 448 PUSH_DATA (push, 0); 449 } 450 451 PUSH_SPACE(push, n * 2 + 4); 452 453 BEGIN_NVC0(push, NVC0_3D(VERTEX_ATTRIB_FORMAT(0)), n); 454 for (i = 0; i < vertex->num_elements; ++i) 455 PUSH_DATA(push, vertex->element[i].state_alt); 456 for (; i < n; ++i) 457 PUSH_DATA(push, NVC0_3D_VERTEX_ATTRIB_INACTIVE); 458 459 BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(0)), 1); 460 PUSH_DATA (push, (1 << 12) | vertex->size); 461 for (i = 1; i < n; ++i) 462 IMMED_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(i)), 0); 463 } else { 464 uint32_t *restrict data; 465 466 if (unlikely(vertex->instance_elts != nvc0->state.instance_elts)) { 467 nvc0->state.instance_elts = vertex->instance_elts; 468 assert(n); /* if (n == 0), both masks should be 0 */ 469 PUSH_SPACE(push, 3); 470 BEGIN_NVC0(push, NVC0_3D(MACRO_VERTEX_ARRAY_PER_INSTANCE), 2); 471 PUSH_DATA (push, n); 472 PUSH_DATA (push, vertex->instance_elts); 473 } 474 475 PUSH_SPACE(push, n * 2 + 1); 476 BEGIN_NVC0(push, NVC0_3D(VERTEX_ATTRIB_FORMAT(0)), n); 477 data = push->cur; 478 push->cur += n; 479 for (i = 0; i < vertex->num_elements; ++i) { 480 ve = &vertex->element[i]; 481 data[i] = ve->state; 482 if (unlikely(const_vbos & (1 << ve->pipe.vertex_buffer_index))) { 483 nvc0->state.constant_elts |= 1 << i; 484 data[i] |= NVC0_3D_VERTEX_ATTRIB_FORMAT_CONST; 485 IMMED_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(i)), 0); 486 } 487 } 488 for (; i < n; ++i) { 489 data[i] = NVC0_3D_VERTEX_ATTRIB_INACTIVE; 490 IMMED_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(i)), 0); 491 } 492 } 493 } 494 if (nvc0->state.vbo_mode) /* using translate, don't set up arrays here */ 495 return; 496 497 if (vertex->shared_slots) 498 nvc0_validate_vertex_buffers_shared(nvc0); 499 else 500 nvc0_validate_vertex_buffers(nvc0); 501 } 502 503 void 504 nvc0_idxbuf_validate(struct nvc0_context *nvc0) 505 { 506 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 507 struct nv04_resource *buf = nv04_resource(nvc0->idxbuf.buffer); 508 509 assert(buf); 510 assert(nouveau_resource_mapped_by_gpu(&buf->base)); 511 512 PUSH_SPACE(push, 6); 513 BEGIN_NVC0(push, NVC0_3D(INDEX_ARRAY_START_HIGH), 5); 514 PUSH_DATAh(push, buf->address + nvc0->idxbuf.offset); 515 PUSH_DATA (push, buf->address + nvc0->idxbuf.offset); 516 PUSH_DATAh(push, buf->address + buf->base.width0 - 1); 517 PUSH_DATA (push, buf->address + buf->base.width0 - 1); 518 PUSH_DATA (push, nvc0->idxbuf.index_size >> 1); 519 520 BCTX_REFN(nvc0->bufctx_3d, IDX, buf, RD); 521 } 522 523 #define NVC0_PRIM_GL_CASE(n) \ 524 case PIPE_PRIM_##n: return NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_##n 525 526 static INLINE unsigned 527 nvc0_prim_gl(unsigned prim) 528 { 529 switch (prim) { 530 NVC0_PRIM_GL_CASE(POINTS); 531 NVC0_PRIM_GL_CASE(LINES); 532 NVC0_PRIM_GL_CASE(LINE_LOOP); 533 NVC0_PRIM_GL_CASE(LINE_STRIP); 534 NVC0_PRIM_GL_CASE(TRIANGLES); 535 NVC0_PRIM_GL_CASE(TRIANGLE_STRIP); 536 NVC0_PRIM_GL_CASE(TRIANGLE_FAN); 537 NVC0_PRIM_GL_CASE(QUADS); 538 NVC0_PRIM_GL_CASE(QUAD_STRIP); 539 NVC0_PRIM_GL_CASE(POLYGON); 540 NVC0_PRIM_GL_CASE(LINES_ADJACENCY); 541 NVC0_PRIM_GL_CASE(LINE_STRIP_ADJACENCY); 542 NVC0_PRIM_GL_CASE(TRIANGLES_ADJACENCY); 543 NVC0_PRIM_GL_CASE(TRIANGLE_STRIP_ADJACENCY); 544 /* 545 NVC0_PRIM_GL_CASE(PATCHES); */ 546 default: 547 return NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_POINTS; 548 } 549 } 550 551 static void 552 nvc0_draw_vbo_kick_notify(struct nouveau_pushbuf *push) 553 { 554 struct nvc0_screen *screen = push->user_priv; 555 556 nouveau_fence_update(&screen->base, TRUE); 557 } 558 559 static void 560 nvc0_draw_arrays(struct nvc0_context *nvc0, 561 unsigned mode, unsigned start, unsigned count, 562 unsigned instance_count) 563 { 564 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 565 unsigned prim; 566 567 if (nvc0->state.index_bias) { 568 PUSH_SPACE(push, 1); 569 IMMED_NVC0(push, NVC0_3D(VB_ELEMENT_BASE), 0); 570 nvc0->state.index_bias = 0; 571 } 572 573 prim = nvc0_prim_gl(mode); 574 575 while (instance_count--) { 576 PUSH_SPACE(push, 6); 577 BEGIN_NVC0(push, NVC0_3D(VERTEX_BEGIN_GL), 1); 578 PUSH_DATA (push, prim); 579 BEGIN_NVC0(push, NVC0_3D(VERTEX_BUFFER_FIRST), 2); 580 PUSH_DATA (push, start); 581 PUSH_DATA (push, count); 582 IMMED_NVC0(push, NVC0_3D(VERTEX_END_GL), 0); 583 584 prim |= NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT; 585 } 586 } 587 588 static void 589 nvc0_draw_elements_inline_u08(struct nouveau_pushbuf *push, const uint8_t *map, 590 unsigned start, unsigned count) 591 { 592 map += start; 593 594 if (count & 3) { 595 unsigned i; 596 PUSH_SPACE(push, 4); 597 BEGIN_NIC0(push, NVC0_3D(VB_ELEMENT_U32), count & 3); 598 for (i = 0; i < (count & 3); ++i) 599 PUSH_DATA(push, *map++); 600 count &= ~3; 601 } 602 while (count) { 603 unsigned i, nr = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN * 4) / 4; 604 605 PUSH_SPACE(push, nr + 1); 606 BEGIN_NIC0(push, NVC0_3D(VB_ELEMENT_U8), nr); 607 for (i = 0; i < nr; ++i) { 608 PUSH_DATA(push, 609 (map[3] << 24) | (map[2] << 16) | (map[1] << 8) | map[0]); 610 map += 4; 611 } 612 count -= nr * 4; 613 } 614 } 615 616 static void 617 nvc0_draw_elements_inline_u16(struct nouveau_pushbuf *push, const uint16_t *map, 618 unsigned start, unsigned count) 619 { 620 map += start; 621 622 if (count & 1) { 623 count &= ~1; 624 PUSH_SPACE(push, 2); 625 BEGIN_NVC0(push, NVC0_3D(VB_ELEMENT_U32), 1); 626 PUSH_DATA (push, *map++); 627 } 628 while (count) { 629 unsigned i, nr = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN * 2) / 2; 630 631 PUSH_SPACE(push, nr + 1); 632 BEGIN_NIC0(push, NVC0_3D(VB_ELEMENT_U16), nr); 633 for (i = 0; i < nr; ++i) { 634 PUSH_DATA(push, (map[1] << 16) | map[0]); 635 map += 2; 636 } 637 count -= nr * 2; 638 } 639 } 640 641 static void 642 nvc0_draw_elements_inline_u32(struct nouveau_pushbuf *push, const uint32_t *map, 643 unsigned start, unsigned count) 644 { 645 map += start; 646 647 while (count) { 648 const unsigned nr = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN); 649 650 PUSH_SPACE(push, nr + 1); 651 BEGIN_NIC0(push, NVC0_3D(VB_ELEMENT_U32), nr); 652 PUSH_DATAp(push, map, nr); 653 654 map += nr; 655 count -= nr; 656 } 657 } 658 659 static void 660 nvc0_draw_elements_inline_u32_short(struct nouveau_pushbuf *push, 661 const uint32_t *map, 662 unsigned start, unsigned count) 663 { 664 map += start; 665 666 if (count & 1) { 667 count--; 668 PUSH_SPACE(push, 1); 669 BEGIN_NVC0(push, NVC0_3D(VB_ELEMENT_U32), 1); 670 PUSH_DATA (push, *map++); 671 } 672 while (count) { 673 unsigned i, nr = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN * 2) / 2; 674 675 PUSH_SPACE(push, nr + 1); 676 BEGIN_NIC0(push, NVC0_3D(VB_ELEMENT_U16), nr); 677 for (i = 0; i < nr; ++i) { 678 PUSH_DATA(push, (map[1] << 16) | map[0]); 679 map += 2; 680 } 681 count -= nr * 2; 682 } 683 } 684 685 static void 686 nvc0_draw_elements(struct nvc0_context *nvc0, boolean shorten, 687 unsigned mode, unsigned start, unsigned count, 688 unsigned instance_count, int32_t index_bias) 689 { 690 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 691 unsigned prim; 692 const unsigned index_size = nvc0->idxbuf.index_size; 693 694 prim = nvc0_prim_gl(mode); 695 696 if (index_bias != nvc0->state.index_bias) { 697 PUSH_SPACE(push, 2); 698 BEGIN_NVC0(push, NVC0_3D(VB_ELEMENT_BASE), 1); 699 PUSH_DATA (push, index_bias); 700 nvc0->state.index_bias = index_bias; 701 } 702 703 if (nvc0->idxbuf.buffer) { 704 PUSH_SPACE(push, 1); 705 IMMED_NVC0(push, NVC0_3D(VERTEX_BEGIN_GL), prim); 706 do { 707 PUSH_SPACE(push, 7); 708 BEGIN_NVC0(push, NVC0_3D(INDEX_BATCH_FIRST), 2); 709 PUSH_DATA (push, start); 710 PUSH_DATA (push, count); 711 if (--instance_count) { 712 BEGIN_NVC0(push, NVC0_3D(VERTEX_END_GL), 2); 713 PUSH_DATA (push, 0); 714 PUSH_DATA (push, prim | NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT); 715 } 716 } while (instance_count); 717 IMMED_NVC0(push, NVC0_3D(VERTEX_END_GL), 0); 718 } else { 719 const void *data = nvc0->idxbuf.user_buffer; 720 721 while (instance_count--) { 722 PUSH_SPACE(push, 2); 723 BEGIN_NVC0(push, NVC0_3D(VERTEX_BEGIN_GL), 1); 724 PUSH_DATA (push, prim); 725 switch (index_size) { 726 case 1: 727 nvc0_draw_elements_inline_u08(push, data, start, count); 728 break; 729 case 2: 730 nvc0_draw_elements_inline_u16(push, data, start, count); 731 break; 732 case 4: 733 if (shorten) 734 nvc0_draw_elements_inline_u32_short(push, data, start, count); 735 else 736 nvc0_draw_elements_inline_u32(push, data, start, count); 737 break; 738 default: 739 assert(0); 740 return; 741 } 742 PUSH_SPACE(push, 1); 743 IMMED_NVC0(push, NVC0_3D(VERTEX_END_GL), 0); 744 745 prim |= NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT; 746 } 747 } 748 } 749 750 static void 751 nvc0_draw_stream_output(struct nvc0_context *nvc0, 752 const struct pipe_draw_info *info) 753 { 754 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 755 struct nvc0_so_target *so = nvc0_so_target(info->count_from_stream_output); 756 struct nv04_resource *res = nv04_resource(so->pipe.buffer); 757 unsigned mode = nvc0_prim_gl(info->mode); 758 unsigned num_instances = info->instance_count; 759 760 if (res->status & NOUVEAU_BUFFER_STATUS_GPU_WRITING) { 761 res->status &= ~NOUVEAU_BUFFER_STATUS_GPU_WRITING; 762 PUSH_SPACE(push, 2); 763 IMMED_NVC0(push, NVC0_3D(SERIALIZE), 0); 764 nvc0_query_fifo_wait(push, so->pq); 765 IMMED_NVC0(push, NVC0_3D(VERTEX_ARRAY_FLUSH), 0); 766 } 767 768 while (num_instances--) { 769 PUSH_SPACE(push, 8); 770 BEGIN_NVC0(push, NVC0_3D(VERTEX_BEGIN_GL), 1); 771 PUSH_DATA (push, mode); 772 BEGIN_NVC0(push, NVC0_3D(DRAW_TFB_BASE), 1); 773 PUSH_DATA (push, 0); 774 BEGIN_NVC0(push, NVC0_3D(DRAW_TFB_STRIDE), 1); 775 PUSH_DATA (push, so->stride); 776 BEGIN_NVC0(push, NVC0_3D(DRAW_TFB_BYTES), 1); 777 nvc0_query_pushbuf_submit(push, so->pq, 0x4); 778 IMMED_NVC0(push, NVC0_3D(VERTEX_END_GL), 0); 779 780 mode |= NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT; 781 } 782 } 783 784 void 785 nvc0_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info) 786 { 787 struct nvc0_context *nvc0 = nvc0_context(pipe); 788 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 789 790 /* NOTE: caller must ensure that (min_index + index_bias) is >= 0 */ 791 nvc0->vb_elt_first = info->min_index + info->index_bias; 792 nvc0->vb_elt_limit = info->max_index - info->min_index; 793 nvc0->instance_off = info->start_instance; 794 nvc0->instance_max = info->instance_count - 1; 795 796 /* For picking only a few vertices from a large user buffer, push is better, 797 * if index count is larger and we expect repeated vertices, suggest upload. 798 */ 799 nvc0->vbo_push_hint = 800 info->indexed && (nvc0->vb_elt_limit >= (info->count * 2)); 801 802 /* Check whether we want to switch vertex-submission mode. */ 803 if (nvc0->vbo_user && !(nvc0->dirty & (NVC0_NEW_ARRAYS | NVC0_NEW_VERTEX))) { 804 if (nvc0->vbo_push_hint != !!nvc0->state.vbo_mode) 805 if (nvc0->state.vbo_mode != 3) 806 nvc0->dirty |= NVC0_NEW_ARRAYS; 807 808 if (!(nvc0->dirty & NVC0_NEW_ARRAYS) && nvc0->state.vbo_mode == 0) { 809 if (nvc0->vertex->shared_slots) 810 nvc0_update_user_vbufs_shared(nvc0); 811 else 812 nvc0_update_user_vbufs(nvc0); 813 } 814 } 815 816 /* 8 as minimum to avoid immediate double validation of new buffers */ 817 nvc0_state_validate(nvc0, ~0, 8); 818 819 push->kick_notify = nvc0_draw_vbo_kick_notify; 820 821 if (nvc0->state.vbo_mode) { 822 nvc0_push_vbo(nvc0, info); 823 push->kick_notify = nvc0_default_kick_notify; 824 return; 825 } 826 827 /* space for base instance, flush, and prim restart */ 828 PUSH_SPACE(push, 8); 829 830 if (nvc0->state.instance_base != info->start_instance) { 831 nvc0->state.instance_base = info->start_instance; 832 /* NOTE: this does not affect the shader input, should it ? */ 833 BEGIN_NVC0(push, NVC0_3D(VB_INSTANCE_BASE), 1); 834 PUSH_DATA (push, info->start_instance); 835 } 836 837 if (nvc0->base.vbo_dirty) { 838 IMMED_NVC0(push, NVC0_3D(VERTEX_ARRAY_FLUSH), 0); 839 nvc0->base.vbo_dirty = FALSE; 840 } 841 842 if (info->indexed) { 843 boolean shorten = info->max_index <= 65535; 844 845 if (info->primitive_restart != nvc0->state.prim_restart) { 846 if (info->primitive_restart) { 847 BEGIN_NVC0(push, NVC0_3D(PRIM_RESTART_ENABLE), 2); 848 PUSH_DATA (push, 1); 849 PUSH_DATA (push, info->restart_index); 850 851 if (info->restart_index > 65535) 852 shorten = FALSE; 853 } else { 854 IMMED_NVC0(push, NVC0_3D(PRIM_RESTART_ENABLE), 0); 855 } 856 nvc0->state.prim_restart = info->primitive_restart; 857 } else 858 if (info->primitive_restart) { 859 BEGIN_NVC0(push, NVC0_3D(PRIM_RESTART_INDEX), 1); 860 PUSH_DATA (push, info->restart_index); 861 862 if (info->restart_index > 65535) 863 shorten = FALSE; 864 } 865 866 nvc0_draw_elements(nvc0, shorten, 867 info->mode, info->start, info->count, 868 info->instance_count, info->index_bias); 869 } else 870 if (unlikely(info->count_from_stream_output)) { 871 nvc0_draw_stream_output(nvc0, info); 872 } else { 873 nvc0_draw_arrays(nvc0, 874 info->mode, info->start, info->count, 875 info->instance_count); 876 } 877 push->kick_notify = nvc0_default_kick_notify; 878 879 nvc0_release_user_vbufs(nvc0); 880 } 881