1/************************************************************************** 2 * 3 * Copyright 2007 VMware, Inc. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28/** 29 * Interface between 'draw' module's output and the llvmpipe rasterizer/setup 30 * code. When the 'draw' module has finished filling a vertex buffer, the 31 * draw_arrays() functions below will be called. Loop over the vertices and 32 * call the point/line/tri setup functions. 33 * 34 * Authors 35 * Brian Paul 36 */ 37 38 39#include "lp_setup_context.h" 40#include "lp_context.h" 41#include "draw/draw_vbuf.h" 42#include "draw/draw_vertex.h" 43#include "util/u_memory.h" 44#include "util/u_math.h" 45#include "lp_state_fs.h" 46#include "lp_perf.h" 47 48 49/* It should be a multiple of both 6 and 4 (in other words, a multiple of 12) 50 * to ensure draw splits between a whole number of rectangles. 51 */ 52#define LP_MAX_VBUF_INDEXES 1020 53 54#define LP_MAX_VBUF_SIZE 4096 55 56 57 58/** cast wrapper */ 59static struct lp_setup_context * 60lp_setup_context(struct vbuf_render *vbr) 61{ 62 return (struct lp_setup_context *) vbr; 63} 64 65 66 67static const struct vertex_info * 68lp_setup_get_vertex_info(struct vbuf_render *vbr) 69{ 70 struct lp_setup_context *setup = lp_setup_context(vbr); 71 72 /* Vertex size/info depends on the latest state. 73 * The draw module may have issued additional state-change commands. 74 */ 75 lp_setup_update_state(setup, FALSE); 76 77 return setup->vertex_info; 78} 79 80 81static boolean 82lp_setup_allocate_vertices(struct vbuf_render *vbr, 83 ushort vertex_size, ushort nr_vertices) 84{ 85 struct lp_setup_context *setup = lp_setup_context(vbr); 86 unsigned size = vertex_size * nr_vertices; 87 88 if (setup->vertex_buffer_size < size) { 89 align_free(setup->vertex_buffer); 90 setup->vertex_buffer = align_malloc(size, 16); 91 setup->vertex_buffer_size = size; 92 } 93 94 setup->vertex_size = vertex_size; 95 setup->nr_vertices = nr_vertices; 96 97 return setup->vertex_buffer != NULL; 98} 99 100static void 101lp_setup_release_vertices(struct vbuf_render *vbr) 102{ 103 /* keep the old allocation for next time */ 104} 105 106static void * 107lp_setup_map_vertices(struct vbuf_render *vbr) 108{ 109 struct lp_setup_context *setup = lp_setup_context(vbr); 110 return setup->vertex_buffer; 111} 112 113static void 114lp_setup_unmap_vertices(struct vbuf_render *vbr, 115 ushort min_index, 116 ushort max_index ) 117{ 118 ASSERTED struct lp_setup_context *setup = lp_setup_context(vbr); 119 assert( setup->vertex_buffer_size >= (max_index+1) * setup->vertex_size ); 120 /* do nothing */ 121} 122 123 124static void 125lp_setup_set_primitive(struct vbuf_render *vbr, enum pipe_prim_type prim) 126{ 127 lp_setup_context(vbr)->prim = prim; 128} 129 130static void 131lp_setup_set_view_index(struct vbuf_render *vbr, unsigned view_index) 132{ 133 lp_setup_context(vbr)->view_index = view_index; 134} 135 136typedef const float (*const_float4_ptr)[4]; 137 138static inline const_float4_ptr get_vert( const void *vertex_buffer, 139 int index, 140 int stride ) 141{ 142 return (const_float4_ptr)((char *)vertex_buffer + index * stride); 143} 144 145static inline void 146rect(struct lp_setup_context *setup, 147 const float (*v0)[4], 148 const float (*v1)[4], 149 const float (*v2)[4], 150 const float (*v3)[4], 151 const float (*v4)[4], 152 const float (*v5)[4]) 153{ 154 if (!setup->permit_linear_rasterizer || 155 !setup->rect( setup, v0, v1, v2, v3, v4, v5)) { 156 setup->triangle(setup, v0, v1, v2); 157 setup->triangle(setup, v3, v4, v5); 158 } 159} 160 161/** 162 * draw elements / indexed primitives 163 */ 164static void 165lp_setup_draw_elements(struct vbuf_render *vbr, const ushort *indices, uint nr) 166{ 167 struct lp_setup_context *setup = lp_setup_context(vbr); 168 const unsigned stride = setup->vertex_info->size * sizeof(float); 169 const void *vertex_buffer = setup->vertex_buffer; 170 const boolean flatshade_first = setup->flatshade_first; 171 boolean uses_constant_interp; 172 unsigned i; 173 174 assert(setup->setup.variant); 175 176 if (!lp_setup_update_state(setup, TRUE)) 177 return; 178 179 uses_constant_interp = setup->setup.variant->key.uses_constant_interp; 180 181 switch (setup->prim) { 182 case PIPE_PRIM_POINTS: 183 for (i = 0; i < nr; i++) { 184 setup->point( setup, 185 get_vert(vertex_buffer, indices[i-0], stride) ); 186 } 187 break; 188 189 case PIPE_PRIM_LINES: 190 for (i = 1; i < nr; i += 2) { 191 setup->line( setup, 192 get_vert(vertex_buffer, indices[i-1], stride), 193 get_vert(vertex_buffer, indices[i-0], stride) ); 194 } 195 break; 196 197 case PIPE_PRIM_LINE_STRIP: 198 for (i = 1; i < nr; i ++) { 199 setup->line( setup, 200 get_vert(vertex_buffer, indices[i-1], stride), 201 get_vert(vertex_buffer, indices[i-0], stride) ); 202 } 203 break; 204 205 case PIPE_PRIM_LINE_LOOP: 206 for (i = 1; i < nr; i ++) { 207 setup->line( setup, 208 get_vert(vertex_buffer, indices[i-1], stride), 209 get_vert(vertex_buffer, indices[i-0], stride) ); 210 } 211 if (nr) { 212 setup->line( setup, 213 get_vert(vertex_buffer, indices[nr-1], stride), 214 get_vert(vertex_buffer, indices[0], stride) ); 215 } 216 break; 217 218 case PIPE_PRIM_TRIANGLES: 219 if (nr % 6 == 0 && !uses_constant_interp) { 220 for (i = 5; i < nr; i += 6) { 221 rect( setup, 222 get_vert(vertex_buffer, indices[i-5], stride), 223 get_vert(vertex_buffer, indices[i-4], stride), 224 get_vert(vertex_buffer, indices[i-3], stride), 225 get_vert(vertex_buffer, indices[i-2], stride), 226 get_vert(vertex_buffer, indices[i-1], stride), 227 get_vert(vertex_buffer, indices[i-0], stride) ); 228 } 229 } 230 else { 231 for (i = 2; i < nr; i += 3) { 232 setup->triangle( setup, 233 get_vert(vertex_buffer, indices[i-2], stride), 234 get_vert(vertex_buffer, indices[i-1], stride), 235 get_vert(vertex_buffer, indices[i-0], stride) ); 236 } 237 } 238 break; 239 240 case PIPE_PRIM_TRIANGLE_STRIP: 241 if (flatshade_first) { 242 for (i = 2; i < nr; i += 1) { 243 /* emit first triangle vertex as first triangle vertex */ 244 setup->triangle( setup, 245 get_vert(vertex_buffer, indices[i-2], stride), 246 get_vert(vertex_buffer, indices[i+(i&1)-1], stride), 247 get_vert(vertex_buffer, indices[i-(i&1)], stride) ); 248 249 } 250 } 251 else { 252 for (i = 2; i < nr; i += 1) { 253 /* emit last triangle vertex as last triangle vertex */ 254 setup->triangle( setup, 255 get_vert(vertex_buffer, indices[i+(i&1)-2], stride), 256 get_vert(vertex_buffer, indices[i-(i&1)-1], stride), 257 get_vert(vertex_buffer, indices[i-0], stride) ); 258 } 259 } 260 break; 261 262 case PIPE_PRIM_TRIANGLE_FAN: 263 if (flatshade_first) { 264 for (i = 2; i < nr; i += 1) { 265 /* emit first non-spoke vertex as first vertex */ 266 setup->triangle( setup, 267 get_vert(vertex_buffer, indices[i-1], stride), 268 get_vert(vertex_buffer, indices[i-0], stride), 269 get_vert(vertex_buffer, indices[0], stride) ); 270 } 271 } 272 else { 273 for (i = 2; i < nr; i += 1) { 274 /* emit last non-spoke vertex as last vertex */ 275 setup->triangle( setup, 276 get_vert(vertex_buffer, indices[0], stride), 277 get_vert(vertex_buffer, indices[i-1], stride), 278 get_vert(vertex_buffer, indices[i-0], stride) ); 279 } 280 } 281 break; 282 283 case PIPE_PRIM_QUADS: 284 /* GL quads don't follow provoking vertex convention */ 285 if (flatshade_first) { 286 /* emit last quad vertex as first triangle vertex */ 287 for (i = 3; i < nr; i += 4) { 288 setup->triangle( setup, 289 get_vert(vertex_buffer, indices[i-0], stride), 290 get_vert(vertex_buffer, indices[i-3], stride), 291 get_vert(vertex_buffer, indices[i-2], stride) ); 292 293 setup->triangle( setup, 294 get_vert(vertex_buffer, indices[i-0], stride), 295 get_vert(vertex_buffer, indices[i-2], stride), 296 get_vert(vertex_buffer, indices[i-1], stride) ); 297 } 298 } 299 else { 300 /* emit last quad vertex as last triangle vertex */ 301 for (i = 3; i < nr; i += 4) { 302 setup->triangle( setup, 303 get_vert(vertex_buffer, indices[i-3], stride), 304 get_vert(vertex_buffer, indices[i-2], stride), 305 get_vert(vertex_buffer, indices[i-0], stride) ); 306 307 setup->triangle( setup, 308 get_vert(vertex_buffer, indices[i-2], stride), 309 get_vert(vertex_buffer, indices[i-1], stride), 310 get_vert(vertex_buffer, indices[i-0], stride) ); 311 } 312 } 313 break; 314 315 case PIPE_PRIM_QUAD_STRIP: 316 /* GL quad strips don't follow provoking vertex convention */ 317 if (flatshade_first) { 318 /* emit last quad vertex as first triangle vertex */ 319 for (i = 3; i < nr; i += 2) { 320 setup->triangle( setup, 321 get_vert(vertex_buffer, indices[i-0], stride), 322 get_vert(vertex_buffer, indices[i-3], stride), 323 get_vert(vertex_buffer, indices[i-2], stride) ); 324 setup->triangle( setup, 325 get_vert(vertex_buffer, indices[i-0], stride), 326 get_vert(vertex_buffer, indices[i-1], stride), 327 get_vert(vertex_buffer, indices[i-3], stride) ); 328 } 329 } 330 else { 331 /* emit last quad vertex as last triangle vertex */ 332 for (i = 3; i < nr; i += 2) { 333 setup->triangle( setup, 334 get_vert(vertex_buffer, indices[i-3], stride), 335 get_vert(vertex_buffer, indices[i-2], stride), 336 get_vert(vertex_buffer, indices[i-0], stride) ); 337 setup->triangle( setup, 338 get_vert(vertex_buffer, indices[i-1], stride), 339 get_vert(vertex_buffer, indices[i-3], stride), 340 get_vert(vertex_buffer, indices[i-0], stride) ); 341 } 342 } 343 break; 344 345 case PIPE_PRIM_POLYGON: 346 /* Almost same as tri fan but the _first_ vertex specifies the flat 347 * shading color. 348 */ 349 if (flatshade_first) { 350 /* emit first polygon vertex as first triangle vertex */ 351 for (i = 2; i < nr; i += 1) { 352 setup->triangle( setup, 353 get_vert(vertex_buffer, indices[0], stride), 354 get_vert(vertex_buffer, indices[i-1], stride), 355 get_vert(vertex_buffer, indices[i-0], stride) ); 356 } 357 } 358 else { 359 /* emit first polygon vertex as last triangle vertex */ 360 for (i = 2; i < nr; i += 1) { 361 setup->triangle( setup, 362 get_vert(vertex_buffer, indices[i-1], stride), 363 get_vert(vertex_buffer, indices[i-0], stride), 364 get_vert(vertex_buffer, indices[0], stride) ); 365 } 366 } 367 break; 368 369 default: 370 assert(0); 371 } 372} 373 374 375/** 376 * This function is hit when the draw module is working in pass-through mode. 377 * It's up to us to convert the vertex array into point/line/tri prims. 378 */ 379static void 380lp_setup_draw_arrays(struct vbuf_render *vbr, uint start, uint nr) 381{ 382 struct lp_setup_context *setup = lp_setup_context(vbr); 383 const unsigned stride = setup->vertex_info->size * sizeof(float); 384 const void *vertex_buffer = 385 (void *) get_vert(setup->vertex_buffer, start, stride); 386 const boolean flatshade_first = setup->flatshade_first; 387 boolean uses_constant_interp; 388 unsigned i; 389 390 if (!lp_setup_update_state(setup, TRUE)) 391 return; 392 393 uses_constant_interp = setup->setup.variant->key.uses_constant_interp; 394 395 switch (setup->prim) { 396 case PIPE_PRIM_POINTS: 397 for (i = 0; i < nr; i++) { 398 setup->point( setup, 399 get_vert(vertex_buffer, i-0, stride) ); 400 } 401 break; 402 403 case PIPE_PRIM_LINES: 404 for (i = 1; i < nr; i += 2) { 405 setup->line( setup, 406 get_vert(vertex_buffer, i-1, stride), 407 get_vert(vertex_buffer, i-0, stride) ); 408 } 409 break; 410 411 case PIPE_PRIM_LINE_STRIP: 412 for (i = 1; i < nr; i ++) { 413 setup->line( setup, 414 get_vert(vertex_buffer, i-1, stride), 415 get_vert(vertex_buffer, i-0, stride) ); 416 } 417 break; 418 419 case PIPE_PRIM_LINE_LOOP: 420 for (i = 1; i < nr; i ++) { 421 setup->line( setup, 422 get_vert(vertex_buffer, i-1, stride), 423 get_vert(vertex_buffer, i-0, stride) ); 424 } 425 if (nr) { 426 setup->line( setup, 427 get_vert(vertex_buffer, nr-1, stride), 428 get_vert(vertex_buffer, 0, stride) ); 429 } 430 break; 431 432 case PIPE_PRIM_TRIANGLES: 433 if (nr % 6 == 0 && !uses_constant_interp) { 434 for (i = 5; i < nr; i += 6) { 435 rect( setup, 436 get_vert(vertex_buffer, i-5, stride), 437 get_vert(vertex_buffer, i-4, stride), 438 get_vert(vertex_buffer, i-3, stride), 439 get_vert(vertex_buffer, i-2, stride), 440 get_vert(vertex_buffer, i-1, stride), 441 get_vert(vertex_buffer, i-0, stride) ); 442 } 443 } 444 else if (!uses_constant_interp && 445 lp_setup_analyse_triangles(setup, vertex_buffer, stride, nr)) { 446 /* If lp_setup_analyse_triangles() returned true, it also 447 * emitted (setup) the rect or triangles. 448 */ 449 } 450 else { 451 for (i = 2; i < nr; i += 3) { 452 setup->triangle( setup, 453 get_vert(vertex_buffer, i-2, stride), 454 get_vert(vertex_buffer, i-1, stride), 455 get_vert(vertex_buffer, i-0, stride) ); 456 } 457 } 458 break; 459 460 case PIPE_PRIM_TRIANGLE_STRIP: 461 if (flatshade_first) { 462 if (!uses_constant_interp) { 463 int j; 464 i = 2; 465 j = 3; 466 while (j < nr) { 467 /* emit first triangle vertex as first triangle vertex */ 468 const float (*v0)[4] = get_vert(vertex_buffer, i-2, stride); 469 const float (*v1)[4] = get_vert(vertex_buffer, i+(i&1)-1, stride); 470 const float (*v2)[4] = get_vert(vertex_buffer, i-(i&1), stride); 471 const float (*v3)[4] = get_vert(vertex_buffer, j-2, stride); 472 const float (*v4)[4] = get_vert(vertex_buffer, j+(j&1)-1, stride); 473 const float (*v5)[4] = get_vert(vertex_buffer, j-(j&1), stride); 474 if (setup->permit_linear_rasterizer && 475 setup->rect(setup, v0, v1, v2, v3, v4, v5)) { 476 i += 2; 477 j += 2; 478 } else { 479 /* emit one triangle, and retry rectangle in the next one */ 480 setup->triangle(setup, v0, v1, v2); 481 i += 1; 482 j += 1; 483 } 484 } 485 if (i < nr) { 486 /* emit last triangle */ 487 setup->triangle( setup, 488 get_vert(vertex_buffer, i-2, stride), 489 get_vert(vertex_buffer, i+(i&1)-1, stride), 490 get_vert(vertex_buffer, i-(i&1), stride) ); 491 } 492 } 493 else { 494 for (i = 2; i < nr; i++) { 495 /* emit first triangle vertex as first triangle vertex */ 496 setup->triangle( setup, 497 get_vert(vertex_buffer, i-2, stride), 498 get_vert(vertex_buffer, i+(i&1)-1, stride), 499 get_vert(vertex_buffer, i-(i&1), stride) ); 500 } 501 } 502 } 503 else { 504 for (i = 2; i < nr; i++) { 505 /* emit last triangle vertex as last triangle vertex */ 506 setup->triangle( setup, 507 get_vert(vertex_buffer, i+(i&1)-2, stride), 508 get_vert(vertex_buffer, i-(i&1)-1, stride), 509 get_vert(vertex_buffer, i-0, stride) ); 510 } 511 } 512 break; 513 514 case PIPE_PRIM_TRIANGLE_FAN: 515 if (nr == 4 && !uses_constant_interp) { 516 rect( setup, 517 get_vert(vertex_buffer, 0, stride), 518 get_vert(vertex_buffer, 1, stride), 519 get_vert(vertex_buffer, 2, stride), 520 get_vert(vertex_buffer, 0, stride), 521 get_vert(vertex_buffer, 2, stride), 522 get_vert(vertex_buffer, 3, stride) ); 523 } 524 else if (flatshade_first) { 525 for (i = 2; i < nr; i += 1) { 526 /* emit first non-spoke vertex as first vertex */ 527 setup->triangle( setup, 528 get_vert(vertex_buffer, i-1, stride), 529 get_vert(vertex_buffer, i-0, stride), 530 get_vert(vertex_buffer, 0, stride) ); 531 } 532 } 533 else { 534 for (i = 2; i < nr; i += 1) { 535 /* emit last non-spoke vertex as last vertex */ 536 setup->triangle( setup, 537 get_vert(vertex_buffer, 0, stride), 538 get_vert(vertex_buffer, i-1, stride), 539 get_vert(vertex_buffer, i-0, stride) ); 540 } 541 } 542 break; 543 544 case PIPE_PRIM_QUADS: 545 /* GL quads don't follow provoking vertex convention */ 546 if (flatshade_first) { 547 /* emit last quad vertex as first triangle vertex */ 548 for (i = 3; i < nr; i += 4) { 549 setup->triangle( setup, 550 get_vert(vertex_buffer, i-0, stride), 551 get_vert(vertex_buffer, i-3, stride), 552 get_vert(vertex_buffer, i-2, stride) ); 553 setup->triangle( setup, 554 get_vert(vertex_buffer, i-0, stride), 555 get_vert(vertex_buffer, i-2, stride), 556 get_vert(vertex_buffer, i-1, stride) ); 557 } 558 } 559 else { 560 /* emit last quad vertex as last triangle vertex */ 561 if (!uses_constant_interp) { 562 for (i = 3; i < nr; i += 4) { 563 rect( setup, 564 get_vert(vertex_buffer, i-3, stride), 565 get_vert(vertex_buffer, i-2, stride), 566 get_vert(vertex_buffer, i-1, stride), 567 get_vert(vertex_buffer, i-3, stride), 568 get_vert(vertex_buffer, i-1, stride), 569 get_vert(vertex_buffer, i-0, stride) ); 570 } 571 } 572 else { 573 for (i = 3; i < nr; i += 4) { 574 setup->triangle( setup, 575 get_vert(vertex_buffer, i-3, stride), 576 get_vert(vertex_buffer, i-2, stride), 577 get_vert(vertex_buffer, i-0, stride) ); 578 setup->triangle( setup, 579 get_vert(vertex_buffer, i-2, stride), 580 get_vert(vertex_buffer, i-1, stride), 581 get_vert(vertex_buffer, i-0, stride) ); 582 } 583 } 584 } 585 break; 586 587 case PIPE_PRIM_QUAD_STRIP: 588 /* GL quad strips don't follow provoking vertex convention */ 589 if (flatshade_first) { 590 /* emit last quad vertex as first triangle vertex */ 591 for (i = 3; i < nr; i += 2) { 592 setup->triangle( setup, 593 get_vert(vertex_buffer, i-0, stride), 594 get_vert(vertex_buffer, i-3, stride), 595 get_vert(vertex_buffer, i-2, stride) ); 596 setup->triangle( setup, 597 get_vert(vertex_buffer, i-0, stride), 598 get_vert(vertex_buffer, i-1, stride), 599 get_vert(vertex_buffer, i-3, stride) ); 600 } 601 } 602 else { 603 /* emit last quad vertex as last triangle vertex */ 604 for (i = 3; i < nr; i += 2) { 605 setup->triangle( setup, 606 get_vert(vertex_buffer, i-3, stride), 607 get_vert(vertex_buffer, i-2, stride), 608 get_vert(vertex_buffer, i-0, stride) ); 609 setup->triangle( setup, 610 get_vert(vertex_buffer, i-1, stride), 611 get_vert(vertex_buffer, i-3, stride), 612 get_vert(vertex_buffer, i-0, stride) ); 613 } 614 } 615 break; 616 617 case PIPE_PRIM_POLYGON: 618 /* Almost same as tri fan but the _first_ vertex specifies the flat 619 * shading color. 620 */ 621 if (flatshade_first) { 622 /* emit first polygon vertex as first triangle vertex */ 623 for (i = 2; i < nr; i += 1) { 624 setup->triangle( setup, 625 get_vert(vertex_buffer, 0, stride), 626 get_vert(vertex_buffer, i-1, stride), 627 get_vert(vertex_buffer, i-0, stride) ); 628 } 629 } 630 else { 631 /* emit first polygon vertex as last triangle vertex */ 632 for (i = 2; i < nr; i += 1) { 633 setup->triangle( setup, 634 get_vert(vertex_buffer, i-1, stride), 635 get_vert(vertex_buffer, i-0, stride), 636 get_vert(vertex_buffer, 0, stride) ); 637 } 638 } 639 break; 640 641 default: 642 assert(0); 643 } 644} 645 646 647 648static void 649lp_setup_vbuf_destroy(struct vbuf_render *vbr) 650{ 651 struct lp_setup_context *setup = lp_setup_context(vbr); 652 if (setup->vertex_buffer) { 653 align_free(setup->vertex_buffer); 654 setup->vertex_buffer = NULL; 655 } 656 lp_setup_destroy(setup); 657} 658 659/* 660 * FIXME: it is unclear if primitives_storage_needed (which is generally 661 * the same as pipe query num_primitives_generated) should increase 662 * if SO is disabled for d3d10, but for GL we definitely need to 663 * increase num_primitives_generated and this is only called for active 664 * SO. If it must not increase for d3d10 need to disambiguate the counters 665 * in the driver and do some work for getting correct values, if it should 666 * increase too should call this from outside streamout code. 667 */ 668static void 669lp_setup_so_info(struct vbuf_render *vbr, uint stream, uint primitives, uint prim_generated) 670{ 671 struct lp_setup_context *setup = lp_setup_context(vbr); 672 struct llvmpipe_context *lp = llvmpipe_context(setup->pipe); 673 674 lp->so_stats[stream].num_primitives_written += primitives; 675 lp->so_stats[stream].primitives_storage_needed += prim_generated; 676} 677 678static void 679lp_setup_pipeline_statistics( 680 struct vbuf_render *vbr, 681 const struct pipe_query_data_pipeline_statistics *stats) 682{ 683 struct lp_setup_context *setup = lp_setup_context(vbr); 684 struct llvmpipe_context *llvmpipe = llvmpipe_context(setup->pipe); 685 686 llvmpipe->pipeline_statistics.ia_vertices += 687 stats->ia_vertices; 688 llvmpipe->pipeline_statistics.ia_primitives += 689 stats->ia_primitives; 690 llvmpipe->pipeline_statistics.vs_invocations += 691 stats->vs_invocations; 692 llvmpipe->pipeline_statistics.gs_invocations += 693 stats->gs_invocations; 694 llvmpipe->pipeline_statistics.gs_primitives += 695 stats->gs_primitives; 696 llvmpipe->pipeline_statistics.hs_invocations += 697 stats->hs_invocations; 698 llvmpipe->pipeline_statistics.ds_invocations += 699 stats->ds_invocations; 700 if (!setup->rasterizer_discard) { 701 llvmpipe->pipeline_statistics.c_invocations += 702 stats->c_invocations; 703 } else { 704 llvmpipe->pipeline_statistics.c_invocations = 0; 705 } 706} 707 708/** 709 * Create the post-transform vertex handler for the given context. 710 */ 711void 712lp_setup_init_vbuf(struct lp_setup_context *setup) 713{ 714 setup->base.max_indices = LP_MAX_VBUF_INDEXES; 715 setup->base.max_vertex_buffer_bytes = LP_MAX_VBUF_SIZE; 716 717 setup->base.get_vertex_info = lp_setup_get_vertex_info; 718 setup->base.allocate_vertices = lp_setup_allocate_vertices; 719 setup->base.map_vertices = lp_setup_map_vertices; 720 setup->base.unmap_vertices = lp_setup_unmap_vertices; 721 setup->base.set_primitive = lp_setup_set_primitive; 722 setup->base.set_view_index = lp_setup_set_view_index; 723 setup->base.draw_elements = lp_setup_draw_elements; 724 setup->base.draw_arrays = lp_setup_draw_arrays; 725 setup->base.release_vertices = lp_setup_release_vertices; 726 setup->base.destroy = lp_setup_vbuf_destroy; 727 setup->base.set_stream_output_info = lp_setup_so_info; 728 setup->base.pipeline_statistics = lp_setup_pipeline_statistics; 729} 730