r300_render.c revision 0b4df63609e9fb25319debd56142a90b11d75671
1/* 2 * Copyright 2009 Corbin Simpson <MostAwesomeDude@gmail.com> 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 * on the rights to use, copy, modify, merge, publish, distribute, sub 8 * license, and/or sell copies of the Software, and to permit persons to whom 9 * the Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21 * USE OR OTHER DEALINGS IN THE SOFTWARE. */ 22 23/* r300_render: Vertex and index buffer primitive emission. Contains both 24 * HW TCL fastpath rendering, and SW TCL Draw-assisted rendering. */ 25 26#include "draw/draw_context.h" 27#include "draw/draw_vbuf.h" 28 29#include "util/u_inlines.h" 30 31#include "util/u_format.h" 32#include "util/u_memory.h" 33#include "util/u_upload_mgr.h" 34#include "util/u_prim.h" 35 36#include "r300_cs.h" 37#include "r300_context.h" 38#include "r300_screen_buffer.h" 39#include "r300_emit.h" 40#include "r300_reg.h" 41#include "r300_render.h" 42#include "r300_state_derived.h" 43 44/* XXX The DRM rejects VAP_ALT_NUM_VERTICES.. */ 45//#define ENABLE_ALT_NUM_VERTS 46 47static uint32_t r300_translate_primitive(unsigned prim) 48{ 49 switch (prim) { 50 case PIPE_PRIM_POINTS: 51 return R300_VAP_VF_CNTL__PRIM_POINTS; 52 case PIPE_PRIM_LINES: 53 return R300_VAP_VF_CNTL__PRIM_LINES; 54 case PIPE_PRIM_LINE_LOOP: 55 return R300_VAP_VF_CNTL__PRIM_LINE_LOOP; 56 case PIPE_PRIM_LINE_STRIP: 57 return R300_VAP_VF_CNTL__PRIM_LINE_STRIP; 58 case PIPE_PRIM_TRIANGLES: 59 return R300_VAP_VF_CNTL__PRIM_TRIANGLES; 60 case PIPE_PRIM_TRIANGLE_STRIP: 61 return R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP; 62 case PIPE_PRIM_TRIANGLE_FAN: 63 return R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN; 64 case PIPE_PRIM_QUADS: 65 return R300_VAP_VF_CNTL__PRIM_QUADS; 66 case PIPE_PRIM_QUAD_STRIP: 67 return R300_VAP_VF_CNTL__PRIM_QUAD_STRIP; 68 case PIPE_PRIM_POLYGON: 69 return R300_VAP_VF_CNTL__PRIM_POLYGON; 70 default: 71 return 0; 72 } 73} 74 75static uint32_t r300_provoking_vertex_fixes(struct r300_context *r300, 76 unsigned mode) 77{ 78 struct r300_rs_state* rs = (struct r300_rs_state*)r300->rs_state.state; 79 uint32_t color_control = rs->color_control; 80 81 /* By default (see r300_state.c:r300_create_rs_state) color_control is 82 * initialized to provoking the first vertex. 83 * 84 * Triangle fans must be reduced to the second vertex, not the first, in 85 * Gallium flatshade-first mode, as per the GL spec. 86 * (http://www.opengl.org/registry/specs/ARB/provoking_vertex.txt) 87 * 88 * Quads never provoke correctly in flatshade-first mode. The first 89 * vertex is never considered as provoking, so only the second, third, 90 * and fourth vertices can be selected, and both "third" and "last" modes 91 * select the fourth vertex. This is probably due to D3D lacking quads. 92 * 93 * Similarly, polygons reduce to the first, not the last, vertex, when in 94 * "last" mode, and all other modes start from the second vertex. 95 * 96 * ~ C. 97 */ 98 99 if (rs->rs.flatshade_first) { 100 switch (mode) { 101 case PIPE_PRIM_TRIANGLE_FAN: 102 color_control |= R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_SECOND; 103 break; 104 case PIPE_PRIM_QUADS: 105 case PIPE_PRIM_QUAD_STRIP: 106 case PIPE_PRIM_POLYGON: 107 color_control |= R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_LAST; 108 break; 109 default: 110 color_control |= R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_FIRST; 111 break; 112 } 113 } else { 114 color_control |= R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_LAST; 115 } 116 117 return color_control; 118} 119 120/* Check if the requested number of dwords is available in the CS and 121 * if not, flush. Return TRUE if the flush occured. */ 122static boolean r300_reserve_cs_space(struct r300_context *r300, 123 unsigned dwords) 124{ 125 if (!r300->rws->check_cs(r300->rws, dwords)) { 126 r300->context.flush(&r300->context, 0, NULL); 127 return TRUE; 128 } 129 return FALSE; 130} 131 132static boolean immd_is_good_idea(struct r300_context *r300, 133 unsigned count) 134{ 135 struct pipe_vertex_element* velem; 136 struct pipe_vertex_buffer* vbuf; 137 boolean checked[PIPE_MAX_ATTRIBS] = {0}; 138 unsigned vertex_element_count = r300->velems->count; 139 unsigned i, vbi; 140 141 if (count > 10 || DBG_ON(r300, DBG_NO_IMMD)) { 142 return FALSE; 143 } 144 145 /* We shouldn't map buffers referenced by CS, busy buffers, 146 * and ones placed in VRAM. */ 147 /* XXX Check for VRAM buffers. */ 148 for (i = 0; i < vertex_element_count; i++) { 149 velem = &r300->velems->velem[i]; 150 vbi = velem->vertex_buffer_index; 151 152 if (!checked[vbi]) { 153 vbuf = &r300->vertex_buffer[vbi]; 154 155 if (r300->context.is_resource_referenced(&r300->context, 156 vbuf->buffer, 157 0, 0)) { 158 /* It's a very bad idea to map it... */ 159 return FALSE; 160 } 161 checked[vbi] = TRUE; 162 } 163 } 164 return TRUE; 165} 166 167/***************************************************************************** 168 * The emission of draw packets for r500. Older GPUs may use these functions * 169 * after resolving fallback issues (e.g. stencil ref two-sided). * 170 ****************************************************************************/ 171 172void r500_emit_draw_arrays_immediate(struct r300_context *r300, 173 unsigned mode, 174 unsigned start, 175 unsigned count) 176{ 177 struct pipe_vertex_element* velem; 178 struct pipe_vertex_buffer* vbuf; 179 unsigned vertex_element_count = r300->velems->count; 180 unsigned i, v, vbi, dw, elem_offset, dwords; 181 182 /* Size of the vertex, in dwords. */ 183 unsigned vertex_size = 0; 184 185 /* Offsets of the attribute, in dwords, from the start of the vertex. */ 186 unsigned offset[PIPE_MAX_ATTRIBS]; 187 188 /* Size of the vertex element, in dwords. */ 189 unsigned size[PIPE_MAX_ATTRIBS]; 190 191 /* Stride to the same attrib in the next vertex in the vertex buffer, 192 * in dwords. */ 193 unsigned stride[PIPE_MAX_ATTRIBS] = {0}; 194 195 /* Mapped vertex buffers. */ 196 uint32_t* map[PIPE_MAX_ATTRIBS] = {0}; 197 struct pipe_transfer* transfer[PIPE_MAX_ATTRIBS] = {NULL}; 198 199 CS_LOCALS(r300); 200 201 /* Calculate the vertex size, offsets, strides etc. and map the buffers. */ 202 for (i = 0; i < vertex_element_count; i++) { 203 velem = &r300->velems->velem[i]; 204 offset[i] = velem->src_offset / 4; 205 size[i] = util_format_get_blocksize(velem->src_format) / 4; 206 vertex_size += size[i]; 207 vbi = velem->vertex_buffer_index; 208 209 /* Map the buffer. */ 210 if (!map[vbi]) { 211 vbuf = &r300->vertex_buffer[vbi]; 212 map[vbi] = (uint32_t*)pipe_buffer_map(&r300->context, 213 vbuf->buffer, 214 PIPE_TRANSFER_READ, 215 &transfer[vbi]); 216 map[vbi] += vbuf->buffer_offset / 4; 217 stride[vbi] = vbuf->stride / 4; 218 } 219 } 220 221 dwords = 9 + count * vertex_size; 222 223 r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + dwords); 224 r300_emit_buffer_validate(r300, FALSE, NULL); 225 r300_emit_dirty_state(r300); 226 227 BEGIN_CS(dwords); 228 OUT_CS_REG(R300_GA_COLOR_CONTROL, 229 r300_provoking_vertex_fixes(r300, mode)); 230 OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size); 231 OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); 232 OUT_CS(count - 1); 233 OUT_CS(0); 234 OUT_CS_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, count * vertex_size); 235 OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (count << 16) | 236 r300_translate_primitive(mode)); 237 238 /* Emit vertices. */ 239 for (v = 0; v < count; v++) { 240 for (i = 0; i < vertex_element_count; i++) { 241 velem = &r300->velems->velem[i]; 242 vbi = velem->vertex_buffer_index; 243 elem_offset = offset[i] + stride[vbi] * (v + start); 244 245 for (dw = 0; dw < size[i]; dw++) { 246 OUT_CS(map[vbi][elem_offset + dw]); 247 } 248 } 249 } 250 END_CS; 251 252 /* Unmap buffers. */ 253 for (i = 0; i < vertex_element_count; i++) { 254 vbi = r300->velems->velem[i].vertex_buffer_index; 255 256 if (map[vbi]) { 257 vbuf = &r300->vertex_buffer[vbi]; 258 pipe_buffer_unmap(&r300->context, vbuf->buffer, transfer[vbi]); 259 map[vbi] = NULL; 260 } 261 } 262} 263 264void r500_emit_draw_arrays(struct r300_context *r300, 265 unsigned mode, 266 unsigned count) 267{ 268#if defined(ENABLE_ALT_NUM_VERTS) 269 boolean alt_num_verts = count > 65535; 270#else 271 boolean alt_num_verts = FALSE; 272#endif 273 CS_LOCALS(r300); 274 275 if (alt_num_verts) { 276 if (count >= (1 << 24)) { 277 fprintf(stderr, "r300: Got a huge number of vertices: %i, " 278 "refusing to render.\n", count); 279 return; 280 } 281 BEGIN_CS(9); 282 OUT_CS_REG(R500_VAP_ALT_NUM_VERTICES, count); 283 } else { 284 BEGIN_CS(7); 285 } 286 OUT_CS_REG(R300_GA_COLOR_CONTROL, 287 r300_provoking_vertex_fixes(r300, mode)); 288 OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); 289 OUT_CS(count - 1); 290 OUT_CS(0); 291 OUT_CS_PKT3(R300_PACKET3_3D_DRAW_VBUF_2, 0); 292 OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (count << 16) | 293 r300_translate_primitive(mode) | 294 (alt_num_verts ? R500_VAP_VF_CNTL__USE_ALT_NUM_VERTS : 0)); 295 END_CS; 296} 297 298void r500_emit_draw_elements(struct r300_context *r300, 299 struct pipe_resource* indexBuffer, 300 unsigned indexSize, 301 unsigned minIndex, 302 unsigned maxIndex, 303 unsigned mode, 304 unsigned start, 305 unsigned count) 306{ 307 uint32_t count_dwords; 308 uint32_t offset_dwords = indexSize * start / sizeof(uint32_t); 309#if defined(ENABLE_ALT_NUM_VERTS) 310 boolean alt_num_verts = count > 65535; 311#else 312 boolean alt_num_verts = FALSE; 313#endif 314 CS_LOCALS(r300); 315 316 if (count >= (1 << 24)) { 317 fprintf(stderr, "r300: Got a huge number of vertices: %i, " 318 "refusing to render.\n", count); 319 return; 320 } 321 322 maxIndex = MIN2(maxIndex, r300->vertex_buffer_max_index); 323 324 DBG(r300, DBG_DRAW, "r300: Indexbuf of %u indices, min %u max %u\n", 325 count, minIndex, maxIndex); 326 327 if (alt_num_verts) { 328 BEGIN_CS(15); 329 OUT_CS_REG(R500_VAP_ALT_NUM_VERTICES, count); 330 } else { 331 BEGIN_CS(13); 332 } 333 OUT_CS_REG(R300_GA_COLOR_CONTROL, 334 r300_provoking_vertex_fixes(r300, mode)); 335 OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); 336 OUT_CS(maxIndex); 337 OUT_CS(minIndex); 338 OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, 0); 339 if (indexSize == 4) { 340 count_dwords = count; 341 OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | 342 R300_VAP_VF_CNTL__INDEX_SIZE_32bit | 343 r300_translate_primitive(mode) | 344 (alt_num_verts ? R500_VAP_VF_CNTL__USE_ALT_NUM_VERTS : 0)); 345 } else { 346 count_dwords = (count + 1) / 2; 347 OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | 348 r300_translate_primitive(mode) | 349 (alt_num_verts ? R500_VAP_VF_CNTL__USE_ALT_NUM_VERTS : 0)); 350 } 351 352 /* INDX_BUFFER is a truly special packet3. 353 * Unlike most other packet3, where the offset is after the count, 354 * the order is reversed, so the relocation ends up carrying the 355 * size of the indexbuf instead of the offset. 356 */ 357 OUT_CS_PKT3(R300_PACKET3_INDX_BUFFER, 2); 358 OUT_CS(R300_INDX_BUFFER_ONE_REG_WR | (R300_VAP_PORT_IDX0 >> 2) | 359 (0 << R300_INDX_BUFFER_SKIP_SHIFT)); 360 OUT_CS(offset_dwords << 2); 361 OUT_CS_BUF_RELOC(indexBuffer, count_dwords, 362 RADEON_GEM_DOMAIN_GTT, 0, 0); 363 364 END_CS; 365} 366 367/***************************************************************************** 368 * The emission of draw packets for r300 which take care of the two-sided * 369 * stencil ref fallback and call r500's functions. * 370 ****************************************************************************/ 371 372/* Set drawing for front faces. */ 373static void r300_begin_stencil_ref_fallback(struct r300_context *r300) 374{ 375 struct r300_rs_state *rs = (struct r300_rs_state*)r300->rs_state.state; 376 CS_LOCALS(r300); 377 378 BEGIN_CS(2); 379 OUT_CS_REG(R300_SU_CULL_MODE, rs->cull_mode | R300_CULL_BACK); 380 END_CS; 381} 382 383/* Set drawing for back faces. */ 384static void r300_switch_stencil_ref_side(struct r300_context *r300) 385{ 386 struct r300_rs_state *rs = (struct r300_rs_state*)r300->rs_state.state; 387 struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state; 388 CS_LOCALS(r300); 389 390 BEGIN_CS(4); 391 OUT_CS_REG(R300_SU_CULL_MODE, rs->cull_mode | R300_CULL_FRONT); 392 OUT_CS_REG(R300_ZB_STENCILREFMASK, 393 dsa->stencil_ref_bf | r300->stencil_ref.ref_value[1]); 394 END_CS; 395} 396 397/* Restore the original state. */ 398static void r300_end_stencil_ref_fallback(struct r300_context *r300) 399{ 400 struct r300_rs_state *rs = (struct r300_rs_state*)r300->rs_state.state; 401 struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state; 402 CS_LOCALS(r300); 403 404 BEGIN_CS(4); 405 OUT_CS_REG(R300_SU_CULL_MODE, rs->cull_mode); 406 OUT_CS_REG(R300_ZB_STENCILREFMASK, 407 dsa->stencil_ref_mask | r300->stencil_ref.ref_value[0]); 408 END_CS; 409} 410 411void r300_emit_draw_arrays_immediate(struct r300_context *r300, 412 unsigned mode, 413 unsigned start, 414 unsigned count) 415{ 416 if (!r300->stencil_ref_bf_fallback) { 417 r500_emit_draw_arrays_immediate(r300, mode, start, count); 418 } else { 419 r300_begin_stencil_ref_fallback(r300); 420 r500_emit_draw_arrays_immediate(r300, mode, start, count); 421 r300_switch_stencil_ref_side(r300); 422 r500_emit_draw_arrays_immediate(r300, mode, start, count); 423 r300_end_stencil_ref_fallback(r300); 424 } 425} 426 427void r300_emit_draw_arrays(struct r300_context *r300, 428 unsigned mode, 429 unsigned count) 430{ 431 if (!r300->stencil_ref_bf_fallback) { 432 r500_emit_draw_arrays(r300, mode, count); 433 } else { 434 r300_begin_stencil_ref_fallback(r300); 435 r500_emit_draw_arrays(r300, mode, count); 436 r300_switch_stencil_ref_side(r300); 437 r500_emit_draw_arrays(r300, mode, count); 438 r300_end_stencil_ref_fallback(r300); 439 } 440} 441 442void r300_emit_draw_elements(struct r300_context *r300, 443 struct pipe_resource* indexBuffer, 444 unsigned indexSize, 445 unsigned minIndex, 446 unsigned maxIndex, 447 unsigned mode, 448 unsigned start, 449 unsigned count) 450{ 451 if (!r300->stencil_ref_bf_fallback) { 452 r500_emit_draw_elements(r300, indexBuffer, indexSize, minIndex, 453 maxIndex, mode, start, count); 454 } else { 455 r300_begin_stencil_ref_fallback(r300); 456 r500_emit_draw_elements(r300, indexBuffer, indexSize, minIndex, 457 maxIndex, mode, start, count); 458 r300_switch_stencil_ref_side(r300); 459 r500_emit_draw_elements(r300, indexBuffer, indexSize, minIndex, 460 maxIndex, mode, start, count); 461 r300_end_stencil_ref_fallback(r300); 462 } 463} 464 465static void r300_shorten_ubyte_elts(struct r300_context* r300, 466 struct pipe_resource** elts, 467 unsigned start, 468 unsigned count) 469{ 470 struct pipe_context* context = &r300->context; 471 struct pipe_screen* screen = r300->context.screen; 472 struct pipe_resource* new_elts; 473 unsigned char *in_map; 474 unsigned short *out_map; 475 struct pipe_transfer *src_transfer, *dst_transfer; 476 unsigned i; 477 478 new_elts = pipe_buffer_create(screen, 479 PIPE_BIND_INDEX_BUFFER, 480 2 * count); 481 482 in_map = pipe_buffer_map(context, *elts, PIPE_TRANSFER_READ, &src_transfer); 483 out_map = pipe_buffer_map(context, new_elts, PIPE_TRANSFER_WRITE, &dst_transfer); 484 485 in_map += start; 486 487 for (i = 0; i < count; i++) { 488 *out_map = (unsigned short)*in_map; 489 in_map++; 490 out_map++; 491 } 492 493 pipe_buffer_unmap(context, *elts, src_transfer); 494 pipe_buffer_unmap(context, new_elts, dst_transfer); 495 496 *elts = new_elts; 497} 498 499static void r300_align_ushort_elts(struct r300_context *r300, 500 struct pipe_resource **elts, 501 unsigned start, unsigned count) 502{ 503 struct pipe_context* context = &r300->context; 504 struct pipe_transfer *in_transfer = NULL; 505 struct pipe_transfer *out_transfer = NULL; 506 struct pipe_resource* new_elts; 507 unsigned short *in_map; 508 unsigned short *out_map; 509 510 new_elts = pipe_buffer_create(context->screen, 511 PIPE_BIND_INDEX_BUFFER, 512 2 * count); 513 514 in_map = pipe_buffer_map(context, *elts, 515 PIPE_TRANSFER_READ, &in_transfer); 516 out_map = pipe_buffer_map(context, new_elts, 517 PIPE_TRANSFER_WRITE, &out_transfer); 518 519 memcpy(out_map, in_map+start, 2 * count); 520 521 pipe_buffer_unmap(context, *elts, in_transfer); 522 pipe_buffer_unmap(context, new_elts, out_transfer); 523 524 *elts = new_elts; 525} 526 527/* This is the fast-path drawing & emission for HW TCL. */ 528void r300_draw_range_elements(struct pipe_context* pipe, 529 struct pipe_resource* indexBuffer, 530 unsigned indexSize, 531 unsigned minIndex, 532 unsigned maxIndex, 533 unsigned mode, 534 unsigned start, 535 unsigned count) 536{ 537 struct r300_context* r300 = r300_context(pipe); 538 struct pipe_resource* orgIndexBuffer = indexBuffer; 539#if defined(ENABLE_ALT_NUM_VERTS) 540 boolean alt_num_verts = r300->screen->caps.is_r500 && 541 count > 65536; 542#else 543 boolean alt_num_verts = FALSE; 544#endif 545 unsigned short_count; 546 547 if (r300->skip_rendering) { 548 return; 549 } 550 551 if (!u_trim_pipe_prim(mode, &count)) { 552 return; 553 } 554 555 if (indexSize == 1) { 556 r300_shorten_ubyte_elts(r300, &indexBuffer, start, count); 557 indexSize = 2; 558 start = 0; 559 } else if (indexSize == 2 && start % 2 != 0) { 560 r300_align_ushort_elts(r300, &indexBuffer, start, count); 561 start = 0; 562 } 563 564 r300_update_derived_state(r300); 565 566 r300_upload_index_buffer(r300, &indexBuffer, indexSize, start, count); 567 568 /* 128 dwords for emit_aos and emit_draw_elements */ 569 r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + 128); 570 r300_emit_buffer_validate(r300, TRUE, indexBuffer); 571 r300_emit_dirty_state(r300); 572 r300_emit_aos(r300, 0); 573 574 u_upload_flush(r300->upload_vb); 575 u_upload_flush(r300->upload_ib); 576 if (alt_num_verts || count <= 65535) { 577 r300->emit_draw_elements(r300, indexBuffer, indexSize, minIndex, 578 maxIndex, mode, start, count); 579 } else { 580 do { 581 short_count = MIN2(count, 65534); 582 r300->emit_draw_elements(r300, indexBuffer, indexSize, minIndex, 583 maxIndex, mode, start, short_count); 584 585 start += short_count; 586 count -= short_count; 587 588 /* 16 spare dwords are enough for emit_draw_elements. */ 589 if (count && r300_reserve_cs_space(r300, 16)) { 590 r300_emit_buffer_validate(r300, TRUE, indexBuffer); 591 r300_emit_dirty_state(r300); 592 r300_emit_aos(r300, 0); 593 } 594 } while (count); 595 } 596 597 if (indexBuffer != orgIndexBuffer) { 598 pipe_resource_reference( &indexBuffer, NULL ); 599 } 600} 601 602/* Simple helpers for context setup. Should probably be moved to util. */ 603void r300_draw_elements(struct pipe_context* pipe, 604 struct pipe_resource* indexBuffer, 605 unsigned indexSize, unsigned mode, 606 unsigned start, unsigned count) 607{ 608 struct r300_context *r300 = r300_context(pipe); 609 610 pipe->draw_range_elements(pipe, indexBuffer, indexSize, 0, 611 r300->vertex_buffer_max_index, 612 mode, start, count); 613} 614 615void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, 616 unsigned start, unsigned count) 617{ 618 struct r300_context* r300 = r300_context(pipe); 619#if defined(ENABLE_ALT_NUM_VERTS) 620 boolean alt_num_verts = r300->screen->caps.is_r500 && 621 count > 65536; 622#else 623 boolean alt_num_verts = FALSE; 624#endif 625 unsigned short_count; 626 627 if (r300->skip_rendering) { 628 return; 629 } 630 631 if (!u_trim_pipe_prim(mode, &count)) { 632 return; 633 } 634 635 r300_update_derived_state(r300); 636 637 if (immd_is_good_idea(r300, count)) { 638 r300->emit_draw_arrays_immediate(r300, mode, start, count); 639 } else { 640 /* Make sure there are at least 128 spare dwords in the command buffer. 641 * (most of it being consumed by emit_aos) */ 642 r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + 128); 643 r300_emit_buffer_validate(r300, TRUE, NULL); 644 r300_emit_dirty_state(r300); 645 646 if (alt_num_verts || count <= 65535) { 647 r300_emit_aos(r300, start); 648 r300->emit_draw_arrays(r300, mode, count); 649 } else { 650 do { 651 short_count = MIN2(count, 65535); 652 r300_emit_aos(r300, start); 653 r300->emit_draw_arrays(r300, mode, short_count); 654 655 start += short_count; 656 count -= short_count; 657 658 /* Again, we emit both AOS and draw_arrays so there should be 659 * at least 128 spare dwords. */ 660 if (count && r300_reserve_cs_space(r300, 128)) { 661 r300_emit_buffer_validate(r300, TRUE, NULL); 662 r300_emit_dirty_state(r300); 663 } 664 } while (count); 665 } 666 u_upload_flush(r300->upload_vb); 667 } 668} 669 670/**************************************************************************** 671 * The rest of this file is for SW TCL rendering only. Please be polite and * 672 * keep these functions separated so that they are easier to locate. ~C. * 673 ***************************************************************************/ 674 675/* SW TCL arrays, using Draw. */ 676void r300_swtcl_draw_arrays(struct pipe_context* pipe, 677 unsigned mode, 678 unsigned start, 679 unsigned count) 680{ 681 struct r300_context* r300 = r300_context(pipe); 682 struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS]; 683 int i; 684 685 if (r300->skip_rendering) { 686 return; 687 } 688 689 if (!u_trim_pipe_prim(mode, &count)) { 690 return; 691 } 692 693 for (i = 0; i < r300->vertex_buffer_count; i++) { 694 void* buf = pipe_buffer_map(pipe, 695 r300->vertex_buffer[i].buffer, 696 PIPE_TRANSFER_READ, 697 &vb_transfer[i]); 698 draw_set_mapped_vertex_buffer(r300->draw, i, buf); 699 } 700 701 draw_set_mapped_element_buffer(r300->draw, 0, NULL); 702 703 draw_arrays(r300->draw, mode, start, count); 704 705 for (i = 0; i < r300->vertex_buffer_count; i++) { 706 pipe_buffer_unmap(pipe, r300->vertex_buffer[i].buffer, 707 vb_transfer[i]); 708 draw_set_mapped_vertex_buffer(r300->draw, i, NULL); 709 } 710} 711 712/* SW TCL elements, using Draw. */ 713void r300_swtcl_draw_range_elements(struct pipe_context* pipe, 714 struct pipe_resource* indexBuffer, 715 unsigned indexSize, 716 unsigned minIndex, 717 unsigned maxIndex, 718 unsigned mode, 719 unsigned start, 720 unsigned count) 721{ 722 struct r300_context* r300 = r300_context(pipe); 723 struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS]; 724 struct pipe_transfer *ib_transfer; 725 int i; 726 void* indices; 727 728 if (r300->skip_rendering) { 729 return; 730 } 731 732 if (!u_trim_pipe_prim(mode, &count)) { 733 return; 734 } 735 736 for (i = 0; i < r300->vertex_buffer_count; i++) { 737 void* buf = pipe_buffer_map(pipe, 738 r300->vertex_buffer[i].buffer, 739 PIPE_TRANSFER_READ, 740 &vb_transfer[i]); 741 draw_set_mapped_vertex_buffer(r300->draw, i, buf); 742 } 743 744 indices = pipe_buffer_map(pipe, indexBuffer, 745 PIPE_TRANSFER_READ, &ib_transfer); 746 draw_set_mapped_element_buffer_range(r300->draw, indexSize, 747 minIndex, maxIndex, indices); 748 749 draw_arrays(r300->draw, mode, start, count); 750 751 for (i = 0; i < r300->vertex_buffer_count; i++) { 752 pipe_buffer_unmap(pipe, r300->vertex_buffer[i].buffer, 753 vb_transfer[i]); 754 draw_set_mapped_vertex_buffer(r300->draw, i, NULL); 755 } 756 757 pipe_buffer_unmap(pipe, indexBuffer, 758 ib_transfer); 759 draw_set_mapped_element_buffer_range(r300->draw, 0, start, 760 start + count - 1, NULL); 761} 762 763/* Object for rendering using Draw. */ 764struct r300_render { 765 /* Parent class */ 766 struct vbuf_render base; 767 768 /* Pipe context */ 769 struct r300_context* r300; 770 771 /* Vertex information */ 772 size_t vertex_size; 773 unsigned prim; 774 unsigned hwprim; 775 776 /* VBO */ 777 struct pipe_resource* vbo; 778 size_t vbo_size; 779 size_t vbo_offset; 780 size_t vbo_max_used; 781 void * vbo_ptr; 782 783 struct pipe_transfer *vbo_transfer; 784}; 785 786static INLINE struct r300_render* 787r300_render(struct vbuf_render* render) 788{ 789 return (struct r300_render*)render; 790} 791 792static const struct vertex_info* 793r300_render_get_vertex_info(struct vbuf_render* render) 794{ 795 struct r300_render* r300render = r300_render(render); 796 struct r300_context* r300 = r300render->r300; 797 798 r300_update_derived_state(r300); 799 800 return &r300->vertex_info; 801} 802 803static boolean r300_render_allocate_vertices(struct vbuf_render* render, 804 ushort vertex_size, 805 ushort count) 806{ 807 struct r300_render* r300render = r300_render(render); 808 struct r300_context* r300 = r300render->r300; 809 struct pipe_screen* screen = r300->context.screen; 810 size_t size = (size_t)vertex_size * (size_t)count; 811 812 if (size + r300render->vbo_offset > r300render->vbo_size) 813 { 814 pipe_resource_reference(&r300->vbo, NULL); 815 r300render->vbo = pipe_buffer_create(screen, 816 PIPE_BIND_VERTEX_BUFFER, 817 R300_MAX_DRAW_VBO_SIZE); 818 r300render->vbo_offset = 0; 819 r300render->vbo_size = R300_MAX_DRAW_VBO_SIZE; 820 } 821 822 r300render->vertex_size = vertex_size; 823 r300->vbo = r300render->vbo; 824 r300->vbo_offset = r300render->vbo_offset; 825 826 return (r300render->vbo) ? TRUE : FALSE; 827} 828 829static void* r300_render_map_vertices(struct vbuf_render* render) 830{ 831 struct r300_render* r300render = r300_render(render); 832 833 r300render->vbo_ptr = pipe_buffer_map(&r300render->r300->context, 834 r300render->vbo, 835 PIPE_TRANSFER_WRITE, 836 &r300render->vbo_transfer); 837 838 return ((uint8_t*)r300render->vbo_ptr + r300render->vbo_offset); 839} 840 841static void r300_render_unmap_vertices(struct vbuf_render* render, 842 ushort min, 843 ushort max) 844{ 845 struct r300_render* r300render = r300_render(render); 846 struct pipe_context* context = &r300render->r300->context; 847 CS_LOCALS(r300render->r300); 848 BEGIN_CS(2); 849 OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, max); 850 END_CS; 851 852 r300render->vbo_max_used = MAX2(r300render->vbo_max_used, 853 r300render->vertex_size * (max + 1)); 854 pipe_buffer_unmap(context, r300render->vbo, r300render->vbo_transfer); 855} 856 857static void r300_render_release_vertices(struct vbuf_render* render) 858{ 859 struct r300_render* r300render = r300_render(render); 860 861 r300render->vbo_offset += r300render->vbo_max_used; 862 r300render->vbo_max_used = 0; 863} 864 865static boolean r300_render_set_primitive(struct vbuf_render* render, 866 unsigned prim) 867{ 868 struct r300_render* r300render = r300_render(render); 869 870 r300render->prim = prim; 871 r300render->hwprim = r300_translate_primitive(prim); 872 873 return TRUE; 874} 875 876static void r500_render_draw_arrays(struct vbuf_render* render, 877 unsigned start, 878 unsigned count) 879{ 880 struct r300_render* r300render = r300_render(render); 881 struct r300_context* r300 = r300render->r300; 882 883 CS_LOCALS(r300); 884 885 r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + 2); 886 r300_emit_buffer_validate(r300, FALSE, NULL); 887 r300_emit_dirty_state(r300); 888 889 DBG(r300, DBG_DRAW, "r300: Doing vbuf render, count %d\n", count); 890 891 BEGIN_CS(2); 892 OUT_CS_PKT3(R300_PACKET3_3D_DRAW_VBUF_2, 0); 893 OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (count << 16) | 894 r300render->hwprim); 895 END_CS; 896} 897 898static void r500_render_draw(struct vbuf_render* render, 899 const ushort* indices, 900 uint count) 901{ 902 struct r300_render* r300render = r300_render(render); 903 struct r300_context* r300 = r300render->r300; 904 int i; 905 unsigned dwords = 2 + (count+1)/2; 906 907 CS_LOCALS(r300); 908 909 r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + dwords); 910 r300_emit_buffer_validate(r300, FALSE, NULL); 911 r300_emit_dirty_state(r300); 912 913 BEGIN_CS(dwords); 914 OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, (count+1)/2); 915 OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | 916 r300render->hwprim); 917 for (i = 0; i < count-1; i += 2) { 918 OUT_CS(indices[i+1] << 16 | indices[i]); 919 } 920 if (count % 2) { 921 OUT_CS(indices[count-1]); 922 } 923 END_CS; 924} 925 926static void r300_render_draw_arrays(struct vbuf_render* render, 927 unsigned start, 928 unsigned count) 929{ 930 struct r300_context* r300 = r300_render(render)->r300; 931 932 if (!r300->stencil_ref_bf_fallback) { 933 r500_render_draw_arrays(render, start, count); 934 } else { 935 r300_begin_stencil_ref_fallback(r300); 936 r500_render_draw_arrays(render, start, count); 937 r300_switch_stencil_ref_side(r300); 938 r500_render_draw_arrays(render, start, count); 939 r300_end_stencil_ref_fallback(r300); 940 } 941} 942 943static void r300_render_draw(struct vbuf_render* render, 944 const ushort* indices, 945 uint count) 946{ 947 struct r300_context* r300 = r300_render(render)->r300; 948 949 if (!r300->stencil_ref_bf_fallback) { 950 r500_render_draw(render, indices, count); 951 } else { 952 r300_begin_stencil_ref_fallback(r300); 953 r500_render_draw(render, indices, count); 954 r300_switch_stencil_ref_side(r300); 955 r500_render_draw(render, indices, count); 956 r300_end_stencil_ref_fallback(r300); 957 } 958} 959 960static void r300_render_destroy(struct vbuf_render* render) 961{ 962 FREE(render); 963} 964 965static struct vbuf_render* r300_render_create(struct r300_context* r300) 966{ 967 struct r300_render* r300render = CALLOC_STRUCT(r300_render); 968 969 r300render->r300 = r300; 970 971 /* XXX find real numbers plz */ 972 r300render->base.max_vertex_buffer_bytes = 128 * 1024; 973 r300render->base.max_indices = 16 * 1024; 974 975 r300render->base.get_vertex_info = r300_render_get_vertex_info; 976 r300render->base.allocate_vertices = r300_render_allocate_vertices; 977 r300render->base.map_vertices = r300_render_map_vertices; 978 r300render->base.unmap_vertices = r300_render_unmap_vertices; 979 r300render->base.set_primitive = r300_render_set_primitive; 980 if (r300->screen->caps.is_r500) { 981 r300render->base.draw = r500_render_draw; 982 r300render->base.draw_arrays = r500_render_draw_arrays; 983 } else { 984 r300render->base.draw = r300_render_draw; 985 r300render->base.draw_arrays = r300_render_draw_arrays; 986 } 987 r300render->base.release_vertices = r300_render_release_vertices; 988 r300render->base.destroy = r300_render_destroy; 989 990 r300render->vbo = NULL; 991 r300render->vbo_size = 0; 992 r300render->vbo_offset = 0; 993 994 return &r300render->base; 995} 996 997struct draw_stage* r300_draw_stage(struct r300_context* r300) 998{ 999 struct vbuf_render* render; 1000 struct draw_stage* stage; 1001 1002 render = r300_render_create(r300); 1003 1004 if (!render) { 1005 return NULL; 1006 } 1007 1008 stage = draw_vbuf_stage(r300->draw, render); 1009 1010 if (!stage) { 1011 render->destroy(render); 1012 return NULL; 1013 } 1014 1015 draw_set_render(r300->draw, render); 1016 1017 return stage; 1018} 1019