r300_render.c revision 162bc831c93bf8632b25c11f116a1405b93a1704
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/* r300_render: Vertex and index buffer primitive emission. */ 45#define R300_MAX_VBO_SIZE (1024 * 1024) 46 47/* XXX The DRM rejects VAP_ALT_NUM_VERTICES.. */ 48//#define ENABLE_ALT_NUM_VERTS 49 50uint32_t r300_translate_primitive(unsigned prim) 51{ 52 switch (prim) { 53 case PIPE_PRIM_POINTS: 54 return R300_VAP_VF_CNTL__PRIM_POINTS; 55 case PIPE_PRIM_LINES: 56 return R300_VAP_VF_CNTL__PRIM_LINES; 57 case PIPE_PRIM_LINE_LOOP: 58 return R300_VAP_VF_CNTL__PRIM_LINE_LOOP; 59 case PIPE_PRIM_LINE_STRIP: 60 return R300_VAP_VF_CNTL__PRIM_LINE_STRIP; 61 case PIPE_PRIM_TRIANGLES: 62 return R300_VAP_VF_CNTL__PRIM_TRIANGLES; 63 case PIPE_PRIM_TRIANGLE_STRIP: 64 return R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP; 65 case PIPE_PRIM_TRIANGLE_FAN: 66 return R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN; 67 case PIPE_PRIM_QUADS: 68 return R300_VAP_VF_CNTL__PRIM_QUADS; 69 case PIPE_PRIM_QUAD_STRIP: 70 return R300_VAP_VF_CNTL__PRIM_QUAD_STRIP; 71 case PIPE_PRIM_POLYGON: 72 return R300_VAP_VF_CNTL__PRIM_POLYGON; 73 default: 74 return 0; 75 } 76} 77 78static uint32_t r300_provoking_vertex_fixes(struct r300_context *r300, 79 unsigned mode) 80{ 81 struct r300_rs_state* rs = (struct r300_rs_state*)r300->rs_state.state; 82 uint32_t color_control = rs->color_control; 83 84 /* By default (see r300_state.c:r300_create_rs_state) color_control is 85 * initialized to provoking the first vertex. 86 * 87 * Triangle fans must be reduced to the second vertex, not the first, in 88 * Gallium flatshade-first mode, as per the GL spec. 89 * (http://www.opengl.org/registry/specs/ARB/provoking_vertex.txt) 90 * 91 * Quads never provoke correctly in flatshade-first mode. The first 92 * vertex is never considered as provoking, so only the second, third, 93 * and fourth vertices can be selected, and both "third" and "last" modes 94 * select the fourth vertex. This is probably due to D3D lacking quads. 95 * 96 * Similarly, polygons reduce to the first, not the last, vertex, when in 97 * "last" mode, and all other modes start from the second vertex. 98 * 99 * ~ C. 100 */ 101 102 if (rs->rs.flatshade_first) { 103 switch (mode) { 104 case PIPE_PRIM_TRIANGLE_FAN: 105 color_control |= R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_SECOND; 106 break; 107 case PIPE_PRIM_QUADS: 108 case PIPE_PRIM_QUAD_STRIP: 109 case PIPE_PRIM_POLYGON: 110 color_control |= R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_LAST; 111 break; 112 default: 113 color_control |= R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_FIRST; 114 break; 115 } 116 } else { 117 color_control |= R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_LAST; 118 } 119 120 return color_control; 121} 122 123/* Check if the requested number of dwords is available in the CS and 124 * if not, flush. Return TRUE if the flush occured. */ 125static boolean r300_reserve_cs_space(struct r300_context *r300, 126 unsigned dwords) 127{ 128 if (!r300->rws->check_cs(r300->rws, dwords)) { 129 r300->context.flush(&r300->context, 0, NULL); 130 return TRUE; 131 } 132 return FALSE; 133} 134 135static boolean immd_is_good_idea(struct r300_context *r300, 136 unsigned count) 137{ 138 struct pipe_vertex_element* velem; 139 struct pipe_vertex_buffer* vbuf; 140 boolean checked[PIPE_MAX_ATTRIBS] = {0}; 141 unsigned vertex_element_count = r300->velems->count; 142 unsigned i, vbi; 143 144 if (count > 10) { 145 return FALSE; 146 } 147 148 /* We shouldn't map buffers referenced by CS, busy buffers, 149 * and ones placed in VRAM. */ 150 /* XXX Check for VRAM buffers. */ 151 for (i = 0; i < vertex_element_count; i++) { 152 velem = &r300->velems->velem[i]; 153 vbi = velem->vertex_buffer_index; 154 155 if (!checked[vbi]) { 156 vbuf = &r300->vertex_buffer[vbi]; 157 158 if (r300_buffer_is_referenced(r300, vbuf->buffer)) { 159 /* It's a very bad idea to map it... */ 160 return FALSE; 161 } 162 checked[vbi] = TRUE; 163 } 164 } 165 return TRUE; 166} 167 168static void r300_emit_draw_arrays_immediate(struct r300_context *r300, 169 unsigned mode, 170 unsigned start, 171 unsigned count) 172{ 173 struct pipe_vertex_element* velem; 174 struct pipe_vertex_buffer* vbuf; 175 unsigned vertex_element_count = r300->velems->count; 176 unsigned i, v, vbi, dw, elem_offset, dwords; 177 178 /* Size of the vertex, in dwords. */ 179 unsigned vertex_size = 0; 180 181 /* Offsets of the attribute, in dwords, from the start of the vertex. */ 182 unsigned offset[PIPE_MAX_ATTRIBS]; 183 184 /* Size of the vertex element, in dwords. */ 185 unsigned size[PIPE_MAX_ATTRIBS]; 186 187 /* Stride to the same attrib in the next vertex in the vertex buffer, 188 * in dwords. */ 189 unsigned stride[PIPE_MAX_ATTRIBS] = {0}; 190 191 /* Mapped vertex buffers. */ 192 uint32_t* map[PIPE_MAX_ATTRIBS] = {0}; 193 194 CS_LOCALS(r300); 195 196 /* Calculate the vertex size, offsets, strides etc. and map the buffers. */ 197 for (i = 0; i < vertex_element_count; i++) { 198 velem = &r300->velems->velem[i]; 199 offset[i] = velem->src_offset / 4; 200 size[i] = util_format_get_blocksize(velem->src_format) / 4; 201 vertex_size += size[i]; 202 vbi = velem->vertex_buffer_index; 203 204 /* Map the buffer. */ 205 if (!map[vbi]) { 206 vbuf = &r300->vertex_buffer[vbi]; 207 map[vbi] = (uint32_t*)pipe_buffer_map(r300->context.screen, 208 vbuf->buffer, 209 PIPE_BUFFER_USAGE_CPU_READ); 210 map[vbi] += vbuf->buffer_offset / 4; 211 stride[vbi] = vbuf->stride / 4; 212 } 213 } 214 215 dwords = 9 + count * vertex_size; 216 217 r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + dwords); 218 r300_emit_buffer_validate(r300, FALSE, NULL); 219 r300_emit_dirty_state(r300); 220 221 BEGIN_CS(dwords); 222 OUT_CS_REG(R300_GA_COLOR_CONTROL, 223 r300_provoking_vertex_fixes(r300, mode)); 224 OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size); 225 OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); 226 OUT_CS(count - 1); 227 OUT_CS(0); 228 OUT_CS_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, count * vertex_size); 229 OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (count << 16) | 230 r300_translate_primitive(mode)); 231 232 /* Emit vertices. */ 233 for (v = 0; v < count; v++) { 234 for (i = 0; i < vertex_element_count; i++) { 235 velem = &r300->velems->velem[i]; 236 vbi = velem->vertex_buffer_index; 237 elem_offset = offset[i] + stride[vbi] * (v + start); 238 239 for (dw = 0; dw < size[i]; dw++) { 240 OUT_CS(map[vbi][elem_offset + dw]); 241 } 242 } 243 } 244 END_CS; 245 246 /* Unmap buffers. */ 247 for (i = 0; i < vertex_element_count; i++) { 248 vbi = r300->velems->velem[i].vertex_buffer_index; 249 250 if (map[vbi]) { 251 vbuf = &r300->vertex_buffer[vbi]; 252 pipe_buffer_unmap(r300->context.screen, vbuf->buffer); 253 map[vbi] = NULL; 254 } 255 } 256} 257 258static void r300_emit_draw_arrays(struct r300_context *r300, 259 unsigned mode, 260 unsigned count) 261{ 262#if defined(ENABLE_ALT_NUM_VERTS) 263 boolean alt_num_verts = count > 65535; 264#else 265 boolean alt_num_verts = FALSE; 266#endif 267 CS_LOCALS(r300); 268 269 if (alt_num_verts) { 270 assert(count < (1 << 24)); 271 BEGIN_CS(9); 272 OUT_CS_REG(R500_VAP_ALT_NUM_VERTICES, count); 273 } else { 274 BEGIN_CS(7); 275 } 276 OUT_CS_REG(R300_GA_COLOR_CONTROL, 277 r300_provoking_vertex_fixes(r300, mode)); 278 OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); 279 OUT_CS(count - 1); 280 OUT_CS(0); 281 OUT_CS_PKT3(R300_PACKET3_3D_DRAW_VBUF_2, 0); 282 OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (count << 16) | 283 r300_translate_primitive(mode) | 284 (alt_num_verts ? R500_VAP_VF_CNTL__USE_ALT_NUM_VERTS : 0)); 285 END_CS; 286} 287 288static void r300_emit_draw_elements(struct r300_context *r300, 289 struct pipe_buffer* indexBuffer, 290 unsigned indexSize, 291 unsigned minIndex, 292 unsigned maxIndex, 293 unsigned mode, 294 unsigned start, 295 unsigned count) 296{ 297 uint32_t count_dwords; 298 uint32_t offset_dwords = indexSize * start / sizeof(uint32_t); 299#if defined(ENABLE_ALT_NUM_VERTS) 300 boolean alt_num_verts = count > 65535; 301#else 302 boolean alt_num_verts = FALSE; 303#endif 304 CS_LOCALS(r300); 305 306 assert(count < (1 << 24)); 307 308 maxIndex = MIN2(maxIndex, r300->vertex_buffer_max_index); 309 310 DBG(r300, DBG_DRAW, "r300: Indexbuf of %u indices, min %u max %u\n", 311 count, minIndex, maxIndex); 312 313 if (alt_num_verts) { 314 BEGIN_CS(15); 315 OUT_CS_REG(R500_VAP_ALT_NUM_VERTICES, count); 316 } else { 317 BEGIN_CS(13); 318 } 319 OUT_CS_REG(R300_GA_COLOR_CONTROL, 320 r300_provoking_vertex_fixes(r300, mode)); 321 OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); 322 OUT_CS(maxIndex); 323 OUT_CS(minIndex); 324 OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, 0); 325 if (indexSize == 4) { 326 count_dwords = count; 327 OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | 328 R300_VAP_VF_CNTL__INDEX_SIZE_32bit | 329 r300_translate_primitive(mode) | 330 (alt_num_verts ? R500_VAP_VF_CNTL__USE_ALT_NUM_VERTS : 0)); 331 } else { 332 count_dwords = (count + 1) / 2; 333 OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | 334 r300_translate_primitive(mode) | 335 (alt_num_verts ? R500_VAP_VF_CNTL__USE_ALT_NUM_VERTS : 0)); 336 } 337 338 /* INDX_BUFFER is a truly special packet3. 339 * Unlike most other packet3, where the offset is after the count, 340 * the order is reversed, so the relocation ends up carrying the 341 * size of the indexbuf instead of the offset. 342 */ 343 OUT_CS_PKT3(R300_PACKET3_INDX_BUFFER, 2); 344 OUT_CS(R300_INDX_BUFFER_ONE_REG_WR | (R300_VAP_PORT_IDX0 >> 2) | 345 (0 << R300_INDX_BUFFER_SKIP_SHIFT)); 346 OUT_CS(offset_dwords << 2); 347 OUT_CS_BUF_RELOC(indexBuffer, count_dwords, 348 RADEON_GEM_DOMAIN_GTT, 0, 0); 349 350 END_CS; 351} 352 353static void r300_shorten_ubyte_elts(struct r300_context* r300, 354 struct pipe_buffer** elts, 355 unsigned start, 356 unsigned count) 357{ 358 struct pipe_screen* screen = r300->context.screen; 359 struct pipe_buffer* new_elts; 360 unsigned char *in_map; 361 unsigned short *out_map; 362 unsigned i; 363 364 new_elts = screen->buffer_create(screen, 32, 365 PIPE_BUFFER_USAGE_INDEX | 366 PIPE_BUFFER_USAGE_CPU_WRITE | 367 PIPE_BUFFER_USAGE_GPU_READ, 368 2 * count); 369 370 in_map = pipe_buffer_map(screen, *elts, PIPE_BUFFER_USAGE_CPU_READ); 371 out_map = pipe_buffer_map(screen, new_elts, PIPE_BUFFER_USAGE_CPU_WRITE); 372 373 in_map += start; 374 375 for (i = 0; i < count; i++) { 376 *out_map = (unsigned short)*in_map; 377 in_map++; 378 out_map++; 379 } 380 381 pipe_buffer_unmap(screen, *elts); 382 pipe_buffer_unmap(screen, new_elts); 383 384 *elts = new_elts; 385} 386 387static void r300_align_ushort_elts(struct r300_context *r300, 388 struct pipe_buffer **elts, 389 unsigned start, unsigned count) 390{ 391 struct pipe_screen* screen = r300->context.screen; 392 struct pipe_buffer* new_elts; 393 unsigned short *in_map; 394 unsigned short *out_map; 395 396 new_elts = screen->buffer_create(screen, 32, 397 PIPE_BUFFER_USAGE_INDEX | 398 PIPE_BUFFER_USAGE_CPU_WRITE | 399 PIPE_BUFFER_USAGE_GPU_READ, 400 2 * count); 401 402 in_map = pipe_buffer_map(screen, *elts, PIPE_BUFFER_USAGE_CPU_READ); 403 out_map = pipe_buffer_map(screen, new_elts, PIPE_BUFFER_USAGE_CPU_WRITE); 404 405 memcpy(out_map, in_map+start, 2 * count); 406 407 pipe_buffer_unmap(screen, *elts); 408 pipe_buffer_unmap(screen, new_elts); 409 410 *elts = new_elts; 411} 412 413/* This is the fast-path drawing & emission for HW TCL. */ 414void r300_draw_range_elements(struct pipe_context* pipe, 415 struct pipe_buffer* indexBuffer, 416 unsigned indexSize, 417 unsigned minIndex, 418 unsigned maxIndex, 419 unsigned mode, 420 unsigned start, 421 unsigned count) 422{ 423 struct r300_context* r300 = r300_context(pipe); 424 struct pipe_buffer* orgIndexBuffer = indexBuffer; 425#if defined(ENABLE_ALT_NUM_VERTS) 426 boolean alt_num_verts = r300_screen(pipe->screen)->caps->is_r500 && 427 count > 65536; 428#else 429 boolean alt_num_verts = FALSE; 430#endif 431 unsigned short_count; 432 433 if (!u_trim_pipe_prim(mode, &count)) { 434 return; 435 } 436 437 if (indexSize == 1) { 438 r300_shorten_ubyte_elts(r300, &indexBuffer, start, count); 439 indexSize = 2; 440 start = 0; 441 } else if (indexSize == 2 && start % 2 != 0) { 442 r300_align_ushort_elts(r300, &indexBuffer, start, count); 443 start = 0; 444 } 445 446 r300_update_derived_state(r300); 447 448 r300_upload_index_buffer(r300, &indexBuffer, indexSize, start, count); 449 450 /* 128 dwords for emit_aos and emit_draw_elements */ 451 r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + 128); 452 r300_emit_buffer_validate(r300, TRUE, indexBuffer); 453 r300_emit_dirty_state(r300); 454 r300_emit_aos(r300, 0); 455 456 u_upload_flush(r300->upload_vb); 457 u_upload_flush(r300->upload_ib); 458 if (alt_num_verts || count <= 65535) { 459 r300_emit_draw_elements(r300, indexBuffer, indexSize, minIndex, 460 maxIndex, mode, start, count); 461 } else { 462 do { 463 short_count = MIN2(count, 65534); 464 r300_emit_draw_elements(r300, indexBuffer, indexSize, minIndex, 465 maxIndex, mode, start, short_count); 466 467 start += short_count; 468 count -= short_count; 469 470 /* 16 spare dwords are enough for emit_draw_elements. */ 471 if (count && r300_reserve_cs_space(r300, 16)) { 472 r300_emit_buffer_validate(r300, TRUE, indexBuffer); 473 r300_emit_dirty_state(r300); 474 r300_emit_aos(r300, 0); 475 } 476 } while (count); 477 } 478 479 if (indexBuffer != orgIndexBuffer) { 480 pipe_buffer_reference( &indexBuffer, NULL ); 481 } 482} 483 484/* Simple helpers for context setup. Should probably be moved to util. */ 485void r300_draw_elements(struct pipe_context* pipe, 486 struct pipe_buffer* indexBuffer, 487 unsigned indexSize, unsigned mode, 488 unsigned start, unsigned count) 489{ 490 struct r300_context *r300 = r300_context(pipe); 491 492 pipe->draw_range_elements(pipe, indexBuffer, indexSize, 0, 493 r300->vertex_buffer_max_index, 494 mode, start, count); 495} 496 497void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, 498 unsigned start, unsigned count) 499{ 500 struct r300_context* r300 = r300_context(pipe); 501#if defined(ENABLE_ALT_NUM_VERTS) 502 boolean alt_num_verts = r300_screen(pipe->screen)->caps->is_r500 && 503 count > 65536; 504#else 505 boolean alt_num_verts = FALSE; 506#endif 507 unsigned short_count; 508 509 if (!u_trim_pipe_prim(mode, &count)) { 510 return; 511 } 512 513 r300_update_derived_state(r300); 514 515 if (immd_is_good_idea(r300, count)) { 516 r300_emit_draw_arrays_immediate(r300, mode, start, count); 517 } else { 518 /* Make sure there are at least 128 spare dwords in the command buffer. 519 * (most of it being consumed by emit_aos) */ 520 r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + 128); 521 r300_emit_buffer_validate(r300, TRUE, NULL); 522 r300_emit_dirty_state(r300); 523 524 if (alt_num_verts || count <= 65535) { 525 r300_emit_aos(r300, start); 526 r300_emit_draw_arrays(r300, mode, count); 527 } else { 528 do { 529 short_count = MIN2(count, 65535); 530 r300_emit_aos(r300, start); 531 r300_emit_draw_arrays(r300, mode, short_count); 532 533 start += short_count; 534 count -= short_count; 535 536 /* Again, we emit both AOS and draw_arrays so there should be 537 * at least 128 spare dwords. */ 538 if (count && r300_reserve_cs_space(r300, 128)) { 539 r300_emit_buffer_validate(r300, TRUE, NULL); 540 r300_emit_dirty_state(r300); 541 } 542 } while (count); 543 } 544 u_upload_flush(r300->upload_vb); 545 } 546} 547 548/**************************************************************************** 549 * The rest of this file is for SW TCL rendering only. Please be polite and * 550 * keep these functions separated so that they are easier to locate. ~C. * 551 ***************************************************************************/ 552 553/* SW TCL arrays, using Draw. */ 554void r300_swtcl_draw_arrays(struct pipe_context* pipe, 555 unsigned mode, 556 unsigned start, 557 unsigned count) 558{ 559 struct r300_context* r300 = r300_context(pipe); 560 int i; 561 562 if (!u_trim_pipe_prim(mode, &count)) { 563 return; 564 } 565 566 for (i = 0; i < r300->vertex_buffer_count; i++) { 567 void* buf = pipe_buffer_map(pipe->screen, 568 r300->vertex_buffer[i].buffer, 569 PIPE_BUFFER_USAGE_CPU_READ); 570 draw_set_mapped_vertex_buffer(r300->draw, i, buf); 571 } 572 573 draw_set_mapped_element_buffer(r300->draw, 0, NULL); 574 575 draw_set_mapped_constant_buffer(r300->draw, 576 PIPE_SHADER_VERTEX, 577 0, 578 r300->shader_constants[PIPE_SHADER_VERTEX].constants, 579 r300->shader_constants[PIPE_SHADER_VERTEX].count * 580 (sizeof(float) * 4)); 581 582 draw_arrays(r300->draw, mode, start, count); 583 584 for (i = 0; i < r300->vertex_buffer_count; i++) { 585 pipe_buffer_unmap(pipe->screen, r300->vertex_buffer[i].buffer); 586 draw_set_mapped_vertex_buffer(r300->draw, i, NULL); 587 } 588} 589 590/* SW TCL elements, using Draw. */ 591void r300_swtcl_draw_range_elements(struct pipe_context* pipe, 592 struct pipe_buffer* indexBuffer, 593 unsigned indexSize, 594 unsigned minIndex, 595 unsigned maxIndex, 596 unsigned mode, 597 unsigned start, 598 unsigned count) 599{ 600 struct r300_context* r300 = r300_context(pipe); 601 int i; 602 void* indices; 603 604 if (!u_trim_pipe_prim(mode, &count)) { 605 return; 606 } 607 608 for (i = 0; i < r300->vertex_buffer_count; i++) { 609 void* buf = pipe_buffer_map(pipe->screen, 610 r300->vertex_buffer[i].buffer, 611 PIPE_BUFFER_USAGE_CPU_READ); 612 draw_set_mapped_vertex_buffer(r300->draw, i, buf); 613 } 614 615 indices = pipe_buffer_map(pipe->screen, indexBuffer, 616 PIPE_BUFFER_USAGE_CPU_READ); 617 draw_set_mapped_element_buffer_range(r300->draw, indexSize, 618 minIndex, maxIndex, indices); 619 620 draw_set_mapped_constant_buffer(r300->draw, 621 PIPE_SHADER_VERTEX, 622 0, 623 r300->shader_constants[PIPE_SHADER_VERTEX].constants, 624 r300->shader_constants[PIPE_SHADER_VERTEX].count * 625 (sizeof(float) * 4)); 626 627 draw_arrays(r300->draw, mode, start, count); 628 629 for (i = 0; i < r300->vertex_buffer_count; i++) { 630 pipe_buffer_unmap(pipe->screen, r300->vertex_buffer[i].buffer); 631 draw_set_mapped_vertex_buffer(r300->draw, i, NULL); 632 } 633 634 pipe_buffer_unmap(pipe->screen, indexBuffer); 635 draw_set_mapped_element_buffer_range(r300->draw, 0, start, 636 start + count - 1, NULL); 637} 638 639/* Object for rendering using Draw. */ 640struct r300_render { 641 /* Parent class */ 642 struct vbuf_render base; 643 644 /* Pipe context */ 645 struct r300_context* r300; 646 647 /* Vertex information */ 648 size_t vertex_size; 649 unsigned prim; 650 unsigned hwprim; 651 652 /* VBO */ 653 struct pipe_buffer* vbo; 654 size_t vbo_size; 655 size_t vbo_offset; 656 size_t vbo_max_used; 657 void * vbo_ptr; 658}; 659 660static INLINE struct r300_render* 661r300_render(struct vbuf_render* render) 662{ 663 return (struct r300_render*)render; 664} 665 666static const struct vertex_info* 667r300_render_get_vertex_info(struct vbuf_render* render) 668{ 669 struct r300_render* r300render = r300_render(render); 670 struct r300_context* r300 = r300render->r300; 671 672 r300_update_derived_state(r300); 673 674 return &r300->vertex_info; 675} 676 677static boolean r300_render_allocate_vertices(struct vbuf_render* render, 678 ushort vertex_size, 679 ushort count) 680{ 681 struct r300_render* r300render = r300_render(render); 682 struct r300_context* r300 = r300render->r300; 683 struct pipe_screen* screen = r300->context.screen; 684 size_t size = (size_t)vertex_size * (size_t)count; 685 686 if (size + r300render->vbo_offset > r300render->vbo_size) 687 { 688 pipe_buffer_reference(&r300->vbo, NULL); 689 r300render->vbo = pipe_buffer_create(screen, 690 64, 691 PIPE_BUFFER_USAGE_VERTEX, 692 R300_MAX_VBO_SIZE); 693 r300render->vbo_offset = 0; 694 r300render->vbo_size = R300_MAX_VBO_SIZE; 695 } 696 697 r300render->vertex_size = vertex_size; 698 r300->vbo = r300render->vbo; 699 r300->vbo_offset = r300render->vbo_offset; 700 701 return (r300render->vbo) ? TRUE : FALSE; 702} 703 704static void* r300_render_map_vertices(struct vbuf_render* render) 705{ 706 struct r300_render* r300render = r300_render(render); 707 struct pipe_screen* screen = r300render->r300->context.screen; 708 709 r300render->vbo_ptr = pipe_buffer_map(screen, r300render->vbo, 710 PIPE_BUFFER_USAGE_CPU_WRITE); 711 712 return ((uint8_t*)r300render->vbo_ptr + r300render->vbo_offset); 713} 714 715static void r300_render_unmap_vertices(struct vbuf_render* render, 716 ushort min, 717 ushort max) 718{ 719 struct r300_render* r300render = r300_render(render); 720 struct pipe_screen* screen = r300render->r300->context.screen; 721 CS_LOCALS(r300render->r300); 722 BEGIN_CS(2); 723 OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, max); 724 END_CS; 725 726 r300render->vbo_max_used = MAX2(r300render->vbo_max_used, 727 r300render->vertex_size * (max + 1)); 728 pipe_buffer_unmap(screen, r300render->vbo); 729} 730 731static void r300_render_release_vertices(struct vbuf_render* render) 732{ 733 struct r300_render* r300render = r300_render(render); 734 735 r300render->vbo_offset += r300render->vbo_max_used; 736 r300render->vbo_max_used = 0; 737} 738 739static boolean r300_render_set_primitive(struct vbuf_render* render, 740 unsigned prim) 741{ 742 struct r300_render* r300render = r300_render(render); 743 744 r300render->prim = prim; 745 r300render->hwprim = r300_translate_primitive(prim); 746 747 return TRUE; 748} 749 750static void r300_render_draw_arrays(struct vbuf_render* render, 751 unsigned start, 752 unsigned count) 753{ 754 struct r300_render* r300render = r300_render(render); 755 struct r300_context* r300 = r300render->r300; 756 757 CS_LOCALS(r300); 758 759 r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + 2); 760 r300_emit_buffer_validate(r300, FALSE, NULL); 761 r300_emit_dirty_state(r300); 762 763 DBG(r300, DBG_DRAW, "r300: Doing vbuf render, count %d\n", count); 764 765 BEGIN_CS(2); 766 OUT_CS_PKT3(R300_PACKET3_3D_DRAW_VBUF_2, 0); 767 OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (count << 16) | 768 r300render->hwprim); 769 END_CS; 770} 771 772static void r300_render_draw(struct vbuf_render* render, 773 const ushort* indices, 774 uint count) 775{ 776 struct r300_render* r300render = r300_render(render); 777 struct r300_context* r300 = r300render->r300; 778 int i; 779 unsigned dwords = 2 + (count+1)/2; 780 781 CS_LOCALS(r300); 782 783 r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + dwords); 784 r300_emit_buffer_validate(r300, FALSE, NULL); 785 r300_emit_dirty_state(r300); 786 787 BEGIN_CS(dwords); 788 OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, (count+1)/2); 789 OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | 790 r300render->hwprim); 791 for (i = 0; i < count-1; i += 2) { 792 OUT_CS(indices[i+1] << 16 | indices[i]); 793 } 794 if (count % 2) { 795 OUT_CS(indices[count-1]); 796 } 797 END_CS; 798} 799 800static void r300_render_destroy(struct vbuf_render* render) 801{ 802 FREE(render); 803} 804 805static struct vbuf_render* r300_render_create(struct r300_context* r300) 806{ 807 struct r300_render* r300render = CALLOC_STRUCT(r300_render); 808 809 r300render->r300 = r300; 810 811 /* XXX find real numbers plz */ 812 r300render->base.max_vertex_buffer_bytes = 128 * 1024; 813 r300render->base.max_indices = 16 * 1024; 814 815 r300render->base.get_vertex_info = r300_render_get_vertex_info; 816 r300render->base.allocate_vertices = r300_render_allocate_vertices; 817 r300render->base.map_vertices = r300_render_map_vertices; 818 r300render->base.unmap_vertices = r300_render_unmap_vertices; 819 r300render->base.set_primitive = r300_render_set_primitive; 820 r300render->base.draw = r300_render_draw; 821 r300render->base.draw_arrays = r300_render_draw_arrays; 822 r300render->base.release_vertices = r300_render_release_vertices; 823 r300render->base.destroy = r300_render_destroy; 824 825 r300render->vbo = NULL; 826 r300render->vbo_size = 0; 827 r300render->vbo_offset = 0; 828 829 return &r300render->base; 830} 831 832struct draw_stage* r300_draw_stage(struct r300_context* r300) 833{ 834 struct vbuf_render* render; 835 struct draw_stage* stage; 836 837 render = r300_render_create(r300); 838 839 if (!render) { 840 return NULL; 841 } 842 843 stage = draw_vbuf_stage(r300->draw, render); 844 845 if (!stage) { 846 render->destroy(render); 847 return NULL; 848 } 849 850 draw_set_render(r300->draw, render); 851 852 return stage; 853} 854