r300_render.c revision ef513776b5bdd11968d2ca03862e9d1ac48e099f
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 "pipe/p_inlines.h" 30 31#include "util/u_memory.h" 32#include "util/u_prim.h" 33 34#include "r300_cs.h" 35#include "r300_context.h" 36#include "r300_emit.h" 37#include "r300_reg.h" 38#include "r300_render.h" 39#include "r300_state_derived.h" 40#include "r300_vbo.h" 41 42/* r300_render: Vertex and index buffer primitive emission. */ 43#define R300_MAX_VBO_SIZE (1024 * 1024) 44 45uint32_t r300_translate_primitive(unsigned prim) 46{ 47 switch (prim) { 48 case PIPE_PRIM_POINTS: 49 return R300_VAP_VF_CNTL__PRIM_POINTS; 50 case PIPE_PRIM_LINES: 51 return R300_VAP_VF_CNTL__PRIM_LINES; 52 case PIPE_PRIM_LINE_LOOP: 53 return R300_VAP_VF_CNTL__PRIM_LINE_LOOP; 54 case PIPE_PRIM_LINE_STRIP: 55 return R300_VAP_VF_CNTL__PRIM_LINE_STRIP; 56 case PIPE_PRIM_TRIANGLES: 57 return R300_VAP_VF_CNTL__PRIM_TRIANGLES; 58 case PIPE_PRIM_TRIANGLE_STRIP: 59 return R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP; 60 case PIPE_PRIM_TRIANGLE_FAN: 61 return R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN; 62 case PIPE_PRIM_QUADS: 63 return R300_VAP_VF_CNTL__PRIM_QUADS; 64 case PIPE_PRIM_QUAD_STRIP: 65 return R300_VAP_VF_CNTL__PRIM_QUAD_STRIP; 66 case PIPE_PRIM_POLYGON: 67 return R300_VAP_VF_CNTL__PRIM_POLYGON; 68 default: 69 return 0; 70 } 71} 72 73static void r300_emit_draw_arrays(struct r300_context *r300, 74 unsigned mode, 75 unsigned count) 76{ 77 CS_LOCALS(r300); 78 79 BEGIN_CS(4); 80 OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, count); 81 OUT_CS_PKT3(R300_PACKET3_3D_DRAW_VBUF_2, 0); 82 OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (count << 16) | 83 r300_translate_primitive(mode)); 84 END_CS; 85} 86 87static void r300_emit_draw_elements(struct r300_context *r300, 88 struct pipe_buffer* indexBuffer, 89 unsigned indexSize, 90 unsigned minIndex, 91 unsigned maxIndex, 92 unsigned mode, 93 unsigned start, 94 unsigned count) 95{ 96 uint32_t count_dwords; 97 uint32_t offset_dwords = indexSize * start / sizeof(uint32_t); 98 CS_LOCALS(r300); 99 100 /* XXX most of these are stupid */ 101 assert(indexSize == 4 || indexSize == 2); 102 assert((start * indexSize) % 4 == 0); 103 assert(offset_dwords == 0); 104 105 BEGIN_CS(10); 106 OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, maxIndex); 107 OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, 0); 108 if (indexSize == 4) { 109 count_dwords = count + start; 110 OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | 111 R300_VAP_VF_CNTL__INDEX_SIZE_32bit | 112 r300_translate_primitive(mode)); 113 } else { 114 count_dwords = (count + start + 1) / 2; 115 OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | 116 r300_translate_primitive(mode)); 117 } 118 119 /* INDX_BUFFER is a truly special packet3. 120 * Unlike most other packet3, where the offset is after the count, 121 * the order is reversed, so the relocation ends up carrying the 122 * size of the indexbuf instead of the offset. 123 * 124 * XXX Fix offset 125 */ 126 OUT_CS_PKT3(R300_PACKET3_INDX_BUFFER, 2); 127 OUT_CS(R300_INDX_BUFFER_ONE_REG_WR | (R300_VAP_PORT_IDX0 >> 2) | 128 (0 << R300_INDX_BUFFER_SKIP_SHIFT)); 129 OUT_CS(offset_dwords); 130 OUT_CS_RELOC(indexBuffer, count_dwords, 131 RADEON_GEM_DOMAIN_GTT, 0, 0); 132 133 END_CS; 134} 135 136 137static boolean r300_setup_vertex_buffers(struct r300_context *r300) 138{ 139 unsigned vbuf_count = r300->aos_count; 140 struct pipe_vertex_buffer *vbuf = r300->vertex_buffer; 141 struct pipe_vertex_element *velem = r300->vertex_element; 142 143validate: 144 for (int i = 0; i < vbuf_count; i++) { 145 if (!r300->winsys->add_buffer(r300->winsys, 146 vbuf[velem[i].vertex_buffer_index].buffer, 147 RADEON_GEM_DOMAIN_GTT, 0)) { 148 r300->context.flush(&r300->context, 0, NULL); 149 goto validate; 150 } 151 } 152 153 if (!r300->winsys->validate(r300->winsys)) { 154 r300->context.flush(&r300->context, 0, NULL); 155 return r300->winsys->validate(r300->winsys); 156 } 157 158 return TRUE; 159} 160 161/* This is the fast-path drawing & emission for HW TCL. */ 162boolean r300_draw_range_elements(struct pipe_context* pipe, 163 struct pipe_buffer* indexBuffer, 164 unsigned indexSize, 165 unsigned minIndex, 166 unsigned maxIndex, 167 unsigned mode, 168 unsigned start, 169 unsigned count) 170{ 171 struct r300_context* r300 = r300_context(pipe); 172 173 if (!u_trim_pipe_prim(mode, &count)) { 174 return FALSE; 175 } 176 177 if (count > 65535) { 178 return FALSE; 179 } 180 181 r300_update_derived_state(r300); 182 183 if (!r300_setup_vertex_buffers(r300)) { 184 return FALSE; 185 } 186 187 setup_vertex_attributes(r300); 188 189 setup_index_buffer(r300, indexBuffer, indexSize); 190 191 r300_emit_dirty_state(r300); 192 193 r300_emit_aos(r300, 0); 194 195 r300_emit_draw_elements(r300, indexBuffer, indexSize, minIndex, maxIndex, 196 mode, start, count); 197 198 return TRUE; 199} 200 201/* Simple helpers for context setup. Should probably be moved to util. */ 202boolean r300_draw_elements(struct pipe_context* pipe, 203 struct pipe_buffer* indexBuffer, 204 unsigned indexSize, unsigned mode, 205 unsigned start, unsigned count) 206{ 207 return pipe->draw_range_elements(pipe, indexBuffer, indexSize, 0, ~0, 208 mode, start, count); 209} 210 211boolean r300_draw_arrays(struct pipe_context* pipe, unsigned mode, 212 unsigned start, unsigned count) 213{ 214 struct r300_context* r300 = r300_context(pipe); 215 216 if (!u_trim_pipe_prim(mode, &count)) { 217 return FALSE; 218 } 219 220 if (count > 65535) { 221 return FALSE; 222 } 223 224 r300_update_derived_state(r300); 225 226 if (!r300_setup_vertex_buffers(r300)) { 227 return FALSE; 228 } 229 230 setup_vertex_attributes(r300); 231 232 r300_emit_dirty_state(r300); 233 234 r300_emit_aos(r300, start); 235 236 r300_emit_draw_arrays(r300, mode, count); 237 238 return TRUE; 239} 240 241/**************************************************************************** 242 * The rest of this file is for SW TCL rendering only. Please be polite and * 243 * keep these functions separated so that they are easier to locate. ~C. * 244 ***************************************************************************/ 245 246/* Draw-based drawing for SW TCL chipsets. */ 247boolean r300_swtcl_draw_range_elements(struct pipe_context* pipe, 248 struct pipe_buffer* indexBuffer, 249 unsigned indexSize, 250 unsigned minIndex, 251 unsigned maxIndex, 252 unsigned mode, 253 unsigned start, 254 unsigned count) 255{ 256 assert(0); 257#if 0 258 struct r300_context* r300 = r300_context(pipe); 259 int i; 260 261 if (!u_trim_pipe_prim(mode, &count)) { 262 return FALSE; 263 } 264 265 for (i = 0; i < r300->vertex_buffer_count; i++) { 266 void* buf = pipe_buffer_map(pipe->screen, 267 r300->vertex_buffers[i].buffer, 268 PIPE_BUFFER_USAGE_CPU_READ); 269 draw_set_mapped_vertex_buffer(r300->draw, i, buf); 270 } 271 272 if (indexBuffer) { 273 void* indices = pipe_buffer_map(pipe->screen, indexBuffer, 274 PIPE_BUFFER_USAGE_CPU_READ); 275 draw_set_mapped_element_buffer_range(r300->draw, indexSize, 276 minIndex, maxIndex, indices); 277 } else { 278 draw_set_mapped_element_buffer(r300->draw, 0, NULL); 279 } 280 281 draw_set_mapped_constant_buffer(r300->draw, 282 r300->shader_constants[PIPE_SHADER_VERTEX].constants, 283 r300->shader_constants[PIPE_SHADER_VERTEX].count * 284 (sizeof(float) * 4)); 285 286 draw_arrays(r300->draw, mode, start, count); 287 288 for (i = 0; i < r300->vertex_buffer_count; i++) { 289 pipe_buffer_unmap(pipe->screen, r300->vertex_buffers[i].buffer); 290 draw_set_mapped_vertex_buffer(r300->draw, i, NULL); 291 } 292 293 if (indexBuffer) { 294 pipe_buffer_unmap(pipe->screen, indexBuffer); 295 draw_set_mapped_element_buffer_range(r300->draw, 0, start, 296 start + count - 1, NULL); 297 } 298#endif 299 return TRUE; 300} 301 302/* Object for rendering using Draw. */ 303struct r300_render { 304 /* Parent class */ 305 struct vbuf_render base; 306 307 /* Pipe context */ 308 struct r300_context* r300; 309 310 /* Vertex information */ 311 size_t vertex_size; 312 unsigned prim; 313 unsigned hwprim; 314 315 /* VBO */ 316 struct pipe_buffer* vbo; 317 size_t vbo_size; 318 size_t vbo_offset; 319 size_t vbo_max_used; 320 void * vbo_ptr; 321}; 322 323static INLINE struct r300_render* 324r300_render(struct vbuf_render* render) 325{ 326 return (struct r300_render*)render; 327} 328 329static const struct vertex_info* 330r300_render_get_vertex_info(struct vbuf_render* render) 331{ 332 struct r300_render* r300render = r300_render(render); 333 struct r300_context* r300 = r300render->r300; 334 335 r300_update_derived_state(r300); 336 337 return &r300->vertex_info->vinfo; 338} 339 340static boolean r300_render_allocate_vertices(struct vbuf_render* render, 341 ushort vertex_size, 342 ushort count) 343{ 344 struct r300_render* r300render = r300_render(render); 345 struct r300_context* r300 = r300render->r300; 346 struct pipe_screen* screen = r300->context.screen; 347 size_t size = (size_t)vertex_size * (size_t)count; 348 349 if (size + r300render->vbo_offset > r300render->vbo_size) 350 { 351 pipe_buffer_reference(&r300->vbo, NULL); 352 r300render->vbo = pipe_buffer_create(screen, 353 64, 354 PIPE_BUFFER_USAGE_VERTEX, 355 R300_MAX_VBO_SIZE); 356 r300render->vbo_offset = 0; 357 r300render->vbo_size = R300_MAX_VBO_SIZE; 358 } 359 360 r300render->vertex_size = vertex_size; 361 r300->vbo = r300render->vbo; 362 r300->vbo_offset = r300render->vbo_offset; 363 364 return (r300render->vbo) ? TRUE : FALSE; 365} 366 367static void* r300_render_map_vertices(struct vbuf_render* render) 368{ 369 struct r300_render* r300render = r300_render(render); 370 struct pipe_screen* screen = r300render->r300->context.screen; 371 372 r300render->vbo_ptr = pipe_buffer_map(screen, r300render->vbo, 373 PIPE_BUFFER_USAGE_CPU_WRITE); 374 375 return (r300render->vbo_ptr + r300render->vbo_offset); 376} 377 378static void r300_render_unmap_vertices(struct vbuf_render* render, 379 ushort min, 380 ushort max) 381{ 382 struct r300_render* r300render = r300_render(render); 383 struct pipe_screen* screen = r300render->r300->context.screen; 384 CS_LOCALS(r300render->r300); 385 BEGIN_CS(2); 386 OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, max); 387 END_CS; 388 389 r300render->vbo_max_used = MAX2(r300render->vbo_max_used, 390 r300render->vertex_size * (max + 1)); 391 pipe_buffer_unmap(screen, r300render->vbo); 392} 393 394static void r300_render_release_vertices(struct vbuf_render* render) 395{ 396 struct r300_render* r300render = r300_render(render); 397 398 r300render->vbo_offset += r300render->vbo_max_used; 399 r300render->vbo_max_used = 0; 400} 401 402static boolean r300_render_set_primitive(struct vbuf_render* render, 403 unsigned prim) 404{ 405 struct r300_render* r300render = r300_render(render); 406 407 r300render->prim = prim; 408 r300render->hwprim = r300_translate_primitive(prim); 409 410 return TRUE; 411} 412 413static void r300_render_draw_arrays(struct vbuf_render* render, 414 unsigned start, 415 unsigned count) 416{ 417 struct r300_render* r300render = r300_render(render); 418 struct r300_context* r300 = r300render->r300; 419 420 CS_LOCALS(r300); 421 422 r300_emit_dirty_state(r300); 423 424 DBG(r300, DBG_DRAW, "r300: Doing vbuf render, count %d\n", count); 425 426 BEGIN_CS(2); 427 OUT_CS_PKT3(R300_PACKET3_3D_DRAW_VBUF_2, 0); 428 OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (count << 16) | 429 r300render->hwprim); 430 END_CS; 431} 432 433static void r300_render_draw(struct vbuf_render* render, 434 const ushort* indices, 435 uint count) 436{ 437 struct r300_render* r300render = r300_render(render); 438 struct r300_context* r300 = r300render->r300; 439 int i; 440 441 CS_LOCALS(r300); 442 443 r300_emit_dirty_state(r300); 444 445 BEGIN_CS(2 + (count+1)/2); 446 OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, (count+1)/2); 447 OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | 448 r300render->hwprim); 449 for (i = 0; i < count-1; i += 2) { 450 OUT_CS(indices[i+1] << 16 | indices[i]); 451 } 452 if (count % 2) { 453 OUT_CS(indices[count-1]); 454 } 455 END_CS; 456} 457 458static void r300_render_destroy(struct vbuf_render* render) 459{ 460 FREE(render); 461} 462 463static struct vbuf_render* r300_render_create(struct r300_context* r300) 464{ 465 struct r300_render* r300render = CALLOC_STRUCT(r300_render); 466 467 r300render->r300 = r300; 468 469 /* XXX find real numbers plz */ 470 r300render->base.max_vertex_buffer_bytes = 128 * 1024; 471 r300render->base.max_indices = 16 * 1024; 472 473 r300render->base.get_vertex_info = r300_render_get_vertex_info; 474 r300render->base.allocate_vertices = r300_render_allocate_vertices; 475 r300render->base.map_vertices = r300_render_map_vertices; 476 r300render->base.unmap_vertices = r300_render_unmap_vertices; 477 r300render->base.set_primitive = r300_render_set_primitive; 478 r300render->base.draw = r300_render_draw; 479 r300render->base.draw_arrays = r300_render_draw_arrays; 480 r300render->base.release_vertices = r300_render_release_vertices; 481 r300render->base.destroy = r300_render_destroy; 482 483 r300render->vbo = NULL; 484 r300render->vbo_size = 0; 485 r300render->vbo_offset = 0; 486 487 return &r300render->base; 488} 489 490struct draw_stage* r300_draw_stage(struct r300_context* r300) 491{ 492 struct vbuf_render* render; 493 struct draw_stage* stage; 494 495 render = r300_render_create(r300); 496 497 if (!render) { 498 return NULL; 499 } 500 501 stage = draw_vbuf_stage(r300->draw, render); 502 503 if (!stage) { 504 render->destroy(render); 505 return NULL; 506 } 507 508 draw_set_render(r300->draw, render); 509 510 return stage; 511} 512