1/************************************************************************** 2 * 3 * Copyright 2010-2021 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 THE AUTHORS 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 * Setup/binning code for screen-aligned quads. 30 */ 31 32#include "util/u_math.h" 33#include "util/u_memory.h" 34#include "lp_perf.h" 35#include "lp_setup_context.h" 36#include "lp_rast.h" 37#include "lp_state_fs.h" 38#include "lp_state_setup.h" 39 40 41#define NUM_CHANNELS 4 42 43#define UNDETERMINED_BLIT -1 44 45 46static inline int 47subpixel_snap(float a) 48{ 49 return util_iround(FIXED_ONE * a); 50} 51 52 53static inline float 54fixed_to_float(int a) 55{ 56 return a * (1.0f / FIXED_ONE); 57} 58 59 60/** 61 * Alloc space for a new rectangle plus the input.a0/dadx/dady arrays 62 * immediately after it. 63 * The memory is allocated from the per-scene pool, not per-tile. 64 * \param size returns number of bytes allocated 65 * \param nr_inputs number of fragment shader inputs 66 * \return pointer to rectangle space 67 */ 68struct lp_rast_rectangle * 69lp_setup_alloc_rectangle(struct lp_scene *scene, unsigned nr_inputs) 70{ 71 unsigned input_array_sz = NUM_CHANNELS * (nr_inputs + 1) * sizeof(float); 72 struct lp_rast_rectangle *rect; 73 unsigned bytes; 74 75 bytes = sizeof(*rect) + (3 * input_array_sz); 76 77 rect = lp_scene_alloc_aligned( scene, bytes, 16 ); 78 if (rect == NULL) 79 return NULL; 80 81 rect->inputs.stride = input_array_sz; 82 83 return rect; 84} 85 86 87/** 88 * The rectangle covers the whole tile- shade whole tile. 89 * XXX no rectangle/triangle dependencies in this file - share it with 90 * the same code in lp_setup_tri.c 91 * \param tx, ty the tile position in tiles, not pixels 92 */ 93boolean 94lp_setup_whole_tile(struct lp_setup_context *setup, 95 const struct lp_rast_shader_inputs *inputs, 96 int tx, int ty) 97{ 98 struct lp_scene *scene = setup->scene; 99 100 LP_COUNT(nr_fully_covered_64); 101 102 /* if variant is opaque and scissor doesn't effect the tile */ 103 if (inputs->opaque) { 104 /* Several things prevent this optimization from working: 105 * - For layered rendering we can't determine if this covers the same layer 106 * as previous rendering (or in case of clears those actually always cover 107 * all layers so optimization is impossible). Need to use fb_max_layer and 108 * not setup->layer_slot to determine this since even if there's currently 109 * no slot assigned previous rendering could have used one. 110 * - If there were any Begin/End query commands in the scene then those 111 * would get removed which would be very wrong. Furthermore, if queries 112 * were just active we also can't do the optimization since to get 113 * accurate query results we unfortunately need to execute the rendering 114 * commands. 115 */ 116 if (!scene->fb.zsbuf && scene->fb_max_layer == 0 && !scene->had_queries) { 117 /* 118 * All previous rendering will be overwritten so reset the bin. 119 */ 120 lp_scene_bin_reset( scene, tx, ty ); 121 } 122 123 if (inputs->is_blit) { 124 LP_COUNT(nr_blit_64); 125 return lp_scene_bin_cmd_with_state( scene, tx, ty, 126 setup->fs.stored, 127 LP_RAST_OP_BLIT, 128 lp_rast_arg_inputs(inputs) ); 129 } 130 else { 131 LP_COUNT(nr_shade_opaque_64); 132 return lp_scene_bin_cmd_with_state( scene, tx, ty, 133 setup->fs.stored, 134 LP_RAST_OP_SHADE_TILE_OPAQUE, 135 lp_rast_arg_inputs(inputs) ); 136 } 137 } 138 else { 139 LP_COUNT(nr_shade_64); 140 return lp_scene_bin_cmd_with_state( scene, tx, ty, 141 setup->fs.stored, 142 LP_RAST_OP_SHADE_TILE, 143 lp_rast_arg_inputs(inputs) ); 144 } 145} 146 147 148boolean 149lp_setup_is_blit(const struct lp_setup_context *setup, 150 const struct lp_rast_shader_inputs *inputs) 151{ 152 const struct lp_fragment_shader_variant *variant = 153 setup->fs.current.variant; 154 155 if (variant->blit) { 156 /* 157 * Detect blits. 158 */ 159 const struct lp_jit_texture *texture = 160 &setup->fs.current.jit_context.textures[0]; 161 float dsdx, dsdy, dtdx, dtdy; 162 163 /* XXX: dadx vs dady confusion below? 164 */ 165 dsdx = GET_DADX(inputs)[1][0]*texture->width; 166 dsdy = GET_DADX(inputs)[1][1]*texture->width; 167 dtdx = GET_DADY(inputs)[1][0]*texture->height; 168 dtdy = GET_DADY(inputs)[1][1]*texture->height; 169 170 /* 171 * We don't need to check s0/t0 tolerances 172 * as we establish as pre-condition that there is no 173 * texture filtering. 174 */ 175 176 ASSERTED struct lp_sampler_static_state *samp0 = lp_fs_variant_key_sampler_idx(&variant->key, 0); 177 assert(samp0); 178 assert(samp0->sampler_state.min_img_filter == PIPE_TEX_FILTER_NEAREST); 179 assert(samp0->sampler_state.mag_img_filter == PIPE_TEX_FILTER_NEAREST); 180 181 /* 182 * Check for 1:1 match of texels to dest pixels 183 */ 184 185 if (util_is_approx(dsdx, 1.0f, 1.0f/LP_MAX_WIDTH) && 186 util_is_approx(dsdy, 0.0f, 1.0f/LP_MAX_HEIGHT) && 187 util_is_approx(dtdx, 0.0f, 1.0f/LP_MAX_WIDTH) && 188 util_is_approx(dtdy, 1.0f, 1.0f/LP_MAX_HEIGHT)) { 189 return true; 190 } 191 else { 192#if 0 193 debug_printf("dsdx = %f\n", dsdx); 194 debug_printf("dsdy = %f\n", dsdy); 195 debug_printf("dtdx = %f\n", dtdx); 196 debug_printf("dtdy = %f\n", dtdy); 197 debug_printf("\n"); 198#endif 199 return FALSE; 200 } 201 } 202 203 return FALSE; 204} 205 206 207static inline void 208partial(struct lp_setup_context *setup, 209 const struct lp_rast_rectangle *rect, 210 unsigned ix, unsigned iy, 211 unsigned mask) 212{ 213 if (mask == 0) { 214 assert(rect->box.x0 <= ix * TILE_SIZE); 215 assert(rect->box.y0 <= iy * TILE_SIZE); 216 assert(rect->box.x1 >= (ix+1) * TILE_SIZE - 1); 217 assert(rect->box.y1 >= (iy+1) * TILE_SIZE - 1); 218 219 lp_setup_whole_tile(setup, &rect->inputs, ix, iy); 220 } 221 else { 222 LP_COUNT(nr_partially_covered_64); 223 lp_scene_bin_cmd_with_state( setup->scene, 224 ix, iy, 225 setup->fs.stored, 226 LP_RAST_OP_RECTANGLE, 227 lp_rast_arg_rectangle(rect) ); 228 } 229} 230 231 232/** 233 * Setup/bin a screen-aligned rect. 234 * We need three corner vertices in order to correctly setup 235 * interpolated parameters. We *could* get away with just the 236 * diagonal vertices but it'd cause ugliness elsewhere. 237 * 238 * + -------v0 239 * | | 240 * v2 ------ v1 241 * 242 * By an unfortunate mixup between GL and D3D coordinate spaces, half 243 * of this file talks about clockwise rectangles (which were CCW in GL 244 * coordinate space), while the other half prefers to work with D3D 245 * CCW rectangles. 246 */ 247static boolean 248try_rect_cw(struct lp_setup_context *setup, 249 const float (*v0)[4], 250 const float (*v1)[4], 251 const float (*v2)[4], 252 boolean frontfacing) 253{ 254 const struct lp_fragment_shader_variant *variant = 255 setup->fs.current.variant; 256 const struct lp_setup_variant_key *key = &setup->setup.variant->key; 257 struct lp_scene *scene = setup->scene; 258 struct lp_rast_rectangle *rect; 259 boolean cw; 260 struct u_rect bbox; 261 unsigned viewport_index = 0; 262 unsigned layer = 0; 263 const float (*pv)[4]; 264 265 /* x/y positions in fixed point */ 266 int x0 = subpixel_snap(v0[0][0] - setup->pixel_offset); 267 int x1 = subpixel_snap(v1[0][0] - setup->pixel_offset); 268 int x2 = subpixel_snap(v2[0][0] - setup->pixel_offset); 269 int y0 = subpixel_snap(v0[0][1] - setup->pixel_offset); 270 int y1 = subpixel_snap(v1[0][1] - setup->pixel_offset); 271 int y2 = subpixel_snap(v2[0][1] - setup->pixel_offset); 272 273 LP_COUNT(nr_rects); 274 275 /* Cull clockwise rects without overflowing. 276 */ 277 cw = (x2 < x1) ^ (y0 < y2); 278 if (cw) { 279 LP_COUNT(nr_culled_rects); 280 return TRUE; 281 } 282 283 if (setup->flatshade_first) { 284 pv = v0; 285 } 286 else { 287 pv = v2; 288 } 289 if (setup->viewport_index_slot > 0) { 290 unsigned *udata = (unsigned*)pv[setup->viewport_index_slot]; 291 viewport_index = lp_clamp_viewport_idx(*udata); 292 } 293 if (setup->layer_slot > 0) { 294 layer = *(unsigned*)pv[setup->layer_slot]; 295 layer = MIN2(layer, scene->fb_max_layer); 296 } 297 298 /* Bounding rectangle (in pixels) */ 299 { 300 /* Yes this is necessary to accurately calculate bounding boxes 301 * with the two fill-conventions we support. GL (normally) ends 302 * up needing a bottom-left fill convention, which requires 303 * slightly different rounding. 304 */ 305 int adj = (setup->bottom_edge_rule != 0) ? 1 : 0; 306 307 bbox.x0 = (MIN3(x0, x1, x2) + (FIXED_ONE-1)) >> FIXED_ORDER; 308 bbox.x1 = (MAX3(x0, x1, x2) + (FIXED_ONE-1)) >> FIXED_ORDER; 309 bbox.y0 = (MIN3(y0, y1, y2) + (FIXED_ONE-1) + adj) >> FIXED_ORDER; 310 bbox.y1 = (MAX3(y0, y1, y2) + (FIXED_ONE-1) + adj) >> FIXED_ORDER; 311 312 /* Inclusive coordinates: 313 */ 314 bbox.x1--; 315 bbox.y1--; 316 } 317 318 if (!u_rect_test_intersection(&setup->draw_regions[viewport_index], &bbox)) { 319 if (0) debug_printf("no intersection\n"); 320 LP_COUNT(nr_culled_rects); 321 return TRUE; 322 } 323 324 u_rect_find_intersection(&setup->draw_regions[viewport_index], &bbox); 325 326 rect = lp_setup_alloc_rectangle(scene, key->num_inputs); 327 if (!rect) 328 return FALSE; 329 330#ifdef DEBUG 331 rect->v[0][0] = v0[0][0]; 332 rect->v[0][1] = v0[0][1]; 333 rect->v[1][0] = v1[0][0]; 334 rect->v[1][1] = v1[0][1]; 335#endif 336 337 rect->box.x0 = bbox.x0; 338 rect->box.x1 = bbox.x1; 339 rect->box.y0 = bbox.y0; 340 rect->box.y1 = bbox.y1; 341 342 /* Setup parameter interpolants: 343 */ 344 setup->setup.variant->jit_function( v0, 345 v1, 346 v2, 347 frontfacing, 348 GET_A0(&rect->inputs), 349 GET_DADX(&rect->inputs), 350 GET_DADY(&rect->inputs), 351 &setup->setup.variant->key ); 352 353 rect->inputs.frontfacing = frontfacing; 354 rect->inputs.disable = FALSE; 355 rect->inputs.is_blit = lp_setup_is_blit(setup, &rect->inputs); 356 rect->inputs.opaque = variant->opaque; 357 rect->inputs.layer = layer; 358 rect->inputs.viewport_index = viewport_index; 359 rect->inputs.view_index = setup->view_index; 360 361 return lp_setup_bin_rectangle(setup, rect); 362} 363 364 365boolean 366lp_setup_bin_rectangle(struct lp_setup_context *setup, 367 struct lp_rast_rectangle *rect) 368{ 369 struct lp_scene *scene = setup->scene; 370 unsigned ix0, iy0, ix1, iy1; 371 unsigned i, j; 372 unsigned left_mask = 0; 373 unsigned right_mask = 0; 374 unsigned top_mask = 0; 375 unsigned bottom_mask = 0; 376 377 /* 378 * All fields of 'rect' are now set. The remaining code here is 379 * concerned with binning. 380 */ 381 382 /* Convert to inclusive tile coordinates: 383 */ 384 ix0 = rect->box.x0 / TILE_SIZE; 385 iy0 = rect->box.y0 / TILE_SIZE; 386 ix1 = rect->box.x1 / TILE_SIZE; 387 iy1 = rect->box.y1 / TILE_SIZE; 388 389 /* 390 * Clamp to framebuffer size 391 */ 392 assert(ix0 == MAX2(ix0, 0)); 393 assert(iy0 == MAX2(iy0, 0)); 394 assert(ix1 == MIN2(ix1, scene->tiles_x - 1)); 395 assert(iy1 == MIN2(iy1, scene->tiles_y - 1)); 396 397 if (ix0 * TILE_SIZE != rect->box.x0) 398 left_mask = RECT_PLANE_LEFT; 399 400 if (ix1 * TILE_SIZE + TILE_SIZE - 1 != rect->box.x1) 401 right_mask = RECT_PLANE_RIGHT; 402 403 if (iy0 * TILE_SIZE != rect->box.y0) 404 top_mask = RECT_PLANE_TOP; 405 406 if (iy1 * TILE_SIZE + TILE_SIZE - 1 != rect->box.y1) 407 bottom_mask = RECT_PLANE_BOTTOM; 408 409 /* Determine which tile(s) intersect the rectangle's bounding box 410 */ 411 if (iy0 == iy1 && ix0 == ix1) { 412 partial(setup, rect, ix0, iy0, 413 (left_mask | right_mask | top_mask | bottom_mask)); 414 } 415 else if (ix0 == ix1) { 416 unsigned mask = left_mask | right_mask; 417 partial(setup, rect, ix0, iy0, mask | top_mask); 418 for (i = iy0 + 1; i < iy1; i++) 419 partial(setup, rect, ix0, i, mask); 420 partial(setup, rect, ix0, iy1, mask | bottom_mask); 421 } 422 else if (iy0 == iy1) { 423 unsigned mask = top_mask | bottom_mask; 424 partial(setup, rect, ix0, iy0, mask | left_mask); 425 for (i = ix0 + 1; i < ix1; i++) 426 partial(setup, rect, i, iy0, mask); 427 partial(setup, rect, ix1, iy0, mask | right_mask); 428 } 429 else { 430 partial(setup, rect, ix0, iy0, left_mask | top_mask); 431 partial(setup, rect, ix0, iy1, left_mask | bottom_mask); 432 partial(setup, rect, ix1, iy0, right_mask | top_mask); 433 partial(setup, rect, ix1, iy1, right_mask | bottom_mask); 434 435 /* Top/Bottom fringes 436 */ 437 for (i = ix0 + 1; i < ix1; i++) { 438 partial(setup, rect, i, iy0, top_mask); 439 partial(setup, rect, i, iy1, bottom_mask); 440 } 441 442 /* Left/Right fringes 443 */ 444 for (i = iy0 + 1; i < iy1; i++) { 445 partial(setup, rect, ix0, i, left_mask); 446 partial(setup, rect, ix1, i, right_mask); 447 } 448 449 /* Full interior tiles 450 */ 451 for (j = iy0 + 1; j < iy1; j++) { 452 for (i = ix0 + 1; i < ix1; i++) { 453 lp_setup_whole_tile(setup, &rect->inputs, i, j); 454 } 455 } 456 } 457 458 /* Catch any out-of-memory which occurred during binning. Do this 459 * once here rather than checking all the return values throughout. 460 */ 461 if (lp_scene_is_oom(scene)) { 462 /* Disable rasterization of this partially-binned rectangle. 463 * We'll flush this scene and re-bin the entire rectangle: 464 */ 465 rect->inputs.disable = TRUE; 466 return FALSE; 467 } 468 469 return TRUE; 470} 471 472 473void 474lp_rect_cw(struct lp_setup_context *setup, 475 const float (*v0)[4], 476 const float (*v1)[4], 477 const float (*v2)[4], 478 boolean frontfacing) 479{ 480 if (!try_rect_cw(setup, v0, v1, v2, frontfacing)) { 481 if (!lp_setup_flush_and_restart(setup)) 482 return; 483 484 if (!try_rect_cw(setup, v0, v1, v2, frontfacing)) 485 return; 486 } 487} 488 489 490/** 491 * Take the six vertices for two triangles and try to determine if they 492 * form a screen-aligned quad/rectangle. If so, draw the rect directly, 493 * else, draw as two regular triangles. 494 */ 495static boolean 496do_rect_ccw(struct lp_setup_context *setup, 497 const float (*v0)[4], 498 const float (*v1)[4], 499 const float (*v2)[4], 500 const float (*v3)[4], 501 const float (*v4)[4], 502 const float (*v5)[4], 503 boolean front) 504{ 505 const float (*rv0)[4], (*rv1)[4], (*rv2)[4], (*rv3)[4]; /* rect verts */ 506 507#define SAME_POS(A, B) (A[0][0] == B[0][0] && \ 508 A[0][1] == B[0][1] && \ 509 A[0][2] == B[0][2] && \ 510 A[0][3] == B[0][3]) 511 512 /* Only need to consider CCW orientations. There are nine ways 513 * that two counter-clockwise triangles can join up: 514 */ 515 if (SAME_POS(v0, v3)) { 516 if (SAME_POS(v2, v4)) { 517 /* 518 * v5 v4/v2 519 * +-----+ 520 * | / | 521 * | / | 522 * | / | 523 * +-----+ 524 * v3/v0 v1 525 */ 526 rv0 = v5; 527 rv1 = v0; 528 rv2 = v1; 529 rv3 = v2; 530 } 531 else if (SAME_POS(v1, v5)) { 532 /* 533 * v4 v3/v0 534 * +-----+ 535 * | / | 536 * | / | 537 * | / | 538 * +-----+ 539 * v5/v1 v2 540 */ 541 rv0 = v4; 542 rv1 = v1; 543 rv2 = v2; 544 rv3 = v0; 545 } 546 else { 547 goto emit_triangles; 548 } 549 } 550 else if (SAME_POS(v0, v5)) { 551 if (SAME_POS(v2, v3)) { 552 /* 553 * v4 v3/v2 554 * +-----+ 555 * | / | 556 * | / | 557 * | / | 558 * +-----+ 559 * v5/v0 v1 560 */ 561 rv0 = v4; 562 rv1 = v0; 563 rv2 = v1; 564 rv3 = v2; 565 } 566 else if (SAME_POS(v1, v4)) { 567 /* 568 * v3 v5/v0 569 * +-----+ 570 * | / | 571 * | / | 572 * | / | 573 * +-----+ 574 * v4/v1 v2 575 */ 576 rv0 = v3; 577 rv1 = v1; 578 rv2 = v2; 579 rv3 = v0; 580 } 581 else { 582 goto emit_triangles; 583 } 584 } 585 else if (SAME_POS(v0, v4)) { 586 if (SAME_POS(v2, v5)) { 587 /* 588 * v3 v5/v2 589 * +-----+ 590 * | / | 591 * | / | 592 * | / | 593 * +-----+ 594 * v4/v0 v1 595 */ 596 rv0 = v3; 597 rv1 = v0; 598 rv2 = v1; 599 rv3 = v2; 600 } 601 else if (SAME_POS(v1, v3)) { 602 /* 603 * v5 v4/v0 604 * +-----+ 605 * | / | 606 * | / | 607 * | / | 608 * +-----+ 609 * v3/v1 v2 610 */ 611 rv0 = v5; 612 rv1 = v1; 613 rv2 = v2; 614 rv3 = v0; 615 } 616 else { 617 goto emit_triangles; 618 } 619 } 620 else if (SAME_POS(v2, v3)) { 621 if (SAME_POS(v1, v4)) { 622 /* 623 * v5 v4/v1 624 * +-----+ 625 * | / | 626 * | / | 627 * | / | 628 * +-----+ 629 * v3/v2 v0 630 */ 631 rv0 = v5; 632 rv1 = v2; 633 rv2 = v0; 634 rv3 = v1; 635 } 636 else { 637 goto emit_triangles; 638 } 639 } 640 else if (SAME_POS(v2, v5)) { 641 if (SAME_POS(v1, v3)) { 642 /* 643 * v4 v3/v1 644 * +-----+ 645 * | / | 646 * | / | 647 * | / | 648 * +-----+ 649 * v5/v2 v0 650 */ 651 rv0 = v4; 652 rv1 = v2; 653 rv2 = v0; 654 rv3 = v1; 655 } 656 else { 657 goto emit_triangles; 658 } 659 } 660 else if (SAME_POS(v2, v4)) { 661 if (SAME_POS(v1, v5)) { 662 /* 663 * v3 v5/v1 664 * +-----+ 665 * | / | 666 * | / | 667 * | / | 668 * +-----+ 669 * v4/v2 v0 670 */ 671 rv0 = v3; 672 rv1 = v2; 673 rv2 = v0; 674 rv3 = v1; 675 } 676 else { 677 goto emit_triangles; 678 } 679 } 680 else { 681 goto emit_triangles; 682 } 683 684 685#define SAME_X(A, B) (A[0][0] == B[0][0]) 686#define SAME_Y(A, B) (A[0][1] == B[0][1]) 687 688 /* The vertices are now counter clockwise, as such: 689 * 690 * rv0 -------rv3 691 * | | 692 * rv1 ------ rv2 693 * 694 * To render as a rectangle, 695 * * The X values should be the same at v0, v1 and v2, v3. 696 * * The Y values should be the same at v0, v3 and v1, v2. 697 */ 698 if (SAME_Y(rv0, rv1)) { 699 const float (*tmp)[4]; 700 tmp = rv0; 701 rv0 = rv1; 702 rv1 = rv2; 703 rv2 = rv3; 704 rv3 = tmp; 705 } 706 707 if (SAME_X(rv0, rv1) && SAME_X(rv2, rv3) && 708 SAME_Y(rv0, rv3) && SAME_Y(rv1, rv2)) { 709 710 const struct lp_setup_variant_key *key = &setup->setup.variant->key; 711 const unsigned n = key->num_inputs; 712 unsigned i, j; 713 714 /* We have a rectangle. Check that the other attributes are 715 * coplanar. 716 */ 717 for (i = 0; i < n; i++) { 718 for (j = 0; j < 4; j++) { 719 if (key->inputs[i].usage_mask & (1<<j)) { 720 unsigned k = key->inputs[i].src_index; 721 float dxdx1, dxdx2, dxdy1, dxdy2; 722 dxdx1 = rv0[k][j] - rv3[k][j]; 723 dxdx2 = rv1[k][j] - rv2[k][j]; 724 dxdy1 = rv0[k][j] - rv1[k][j]; 725 dxdy2 = rv3[k][j] - rv2[k][j]; 726 if (dxdx1 != dxdx2 || 727 dxdy1 != dxdy2) { 728 goto emit_triangles; 729 } 730 } 731 } 732 } 733 734 /* Note we're changing to clockwise here. Fix this by reworking 735 * lp_rect_cw to expect/operate on ccw rects. Note that 736 * function was previously misnamed. 737 */ 738 lp_rect_cw(setup, rv0, rv2, rv1, front); 739 return TRUE; 740 } 741 else { 742 /* setup->quad(setup, rv0, rv1, rv2, rv3); */ 743 } 744 745emit_triangles: 746 return FALSE; 747} 748 749 750enum winding { 751 WINDING_NONE = 0, 752 WINDING_CCW, 753 WINDING_CW 754}; 755 756 757static inline enum winding 758winding(const float (*v0)[4], 759 const float (*v1)[4], 760 const float (*v2)[4]) 761{ 762 /* edge vectors e = v0 - v2, f = v1 - v2 */ 763 const float ex = v0[0][0] - v2[0][0]; 764 const float ey = v0[0][1] - v2[0][1]; 765 const float fx = v1[0][0] - v2[0][0]; 766 const float fy = v1[0][1] - v2[0][1]; 767 768 /* det = cross(e,f).z */ 769 const float det = ex * fy - ey * fx; 770 771 if (det < 0.0f) 772 return WINDING_CCW; 773 else if (det > 0.0f) 774 return WINDING_CW; 775 else 776 return WINDING_NONE; 777} 778 779 780static boolean 781setup_rect_cw(struct lp_setup_context *setup, 782 const float (*v0)[4], 783 const float (*v1)[4], 784 const float (*v2)[4], 785 const float (*v3)[4], 786 const float (*v4)[4], 787 const float (*v5)[4]) 788{ 789 enum winding winding0 = winding(v0, v1, v2); 790 enum winding winding1 = winding(v3, v4, v5); 791 792 if (winding0 == WINDING_CW && 793 winding1 == WINDING_CW) { 794 return do_rect_ccw(setup, v0, v2, v1, v3, v5, v4, !setup->ccw_is_frontface); 795 } else if (winding0 == WINDING_CW) { 796 setup->triangle(setup, v0, v1, v2); 797 return TRUE; 798 } else if (winding1 == WINDING_CW) { 799 setup->triangle(setup, v3, v4, v5); 800 return TRUE; 801 } else { 802 return TRUE; 803 } 804} 805 806 807static boolean 808setup_rect_ccw(struct lp_setup_context *setup, 809 const float (*v0)[4], 810 const float (*v1)[4], 811 const float (*v2)[4], 812 const float (*v3)[4], 813 const float (*v4)[4], 814 const float (*v5)[4]) 815{ 816 enum winding winding0 = winding(v0, v1, v2); 817 enum winding winding1 = winding(v3, v4, v5); 818 819 if (winding0 == WINDING_CCW && 820 winding1 == WINDING_CCW) { 821 return do_rect_ccw(setup, v0, v1, v2, v3, v4, v5, setup->ccw_is_frontface); 822 } else if (winding0 == WINDING_CCW) { 823 setup->triangle(setup, v0, v1, v2); 824 return TRUE; 825 } else if (winding1 == WINDING_CCW) { 826 return FALSE; 827 setup->triangle(setup, v3, v4, v5); 828 return TRUE; 829 } else { 830 return TRUE; 831 } 832} 833 834 835static boolean 836setup_rect_noop(struct lp_setup_context *setup, 837 const float (*v0)[4], 838 const float (*v1)[4], 839 const float (*v2)[4], 840 const float (*v3)[4], 841 const float (*v4)[4], 842 const float (*v5)[4]) 843{ 844 return TRUE; 845} 846 847 848static boolean 849setup_rect_both(struct lp_setup_context *setup, 850 const float (*v0)[4], 851 const float (*v1)[4], 852 const float (*v2)[4], 853 const float (*v3)[4], 854 const float (*v4)[4], 855 const float (*v5)[4]) 856{ 857 enum winding winding0 = winding(v0, v1, v2); 858 enum winding winding1 = winding(v3, v4, v5); 859 860 if (winding0 != winding1) { 861 /* If we knew that the "front" parameter wasn't going to be 862 * referenced, could rearrange one of the two triangles such 863 * that they were both CCW. Aero actually does send mixed 864 * CW/CCW rectangles under some circumstances, but we catch them 865 * explicitly. 866 */ 867 return FALSE; 868 } 869 else if (winding0 == WINDING_CCW) { 870 return do_rect_ccw(setup, v0, v1, v2, v3, v4, v5, setup->ccw_is_frontface); 871 } 872 else if (winding0 == WINDING_CW) { 873 return do_rect_ccw(setup, v0, v2, v1, v3, v5, v4, !setup->ccw_is_frontface); 874 } else { 875 return TRUE; 876 } 877} 878 879 880void 881lp_setup_choose_rect( struct lp_setup_context *setup ) 882{ 883 if (setup->rasterizer_discard) { 884 setup->rect = setup_rect_noop; 885 return; 886 } 887 888 switch (setup->cullmode) { 889 case PIPE_FACE_NONE: 890 setup->rect = setup_rect_both; 891 break; 892 case PIPE_FACE_BACK: 893 setup->rect = setup->ccw_is_frontface ? setup_rect_ccw : setup_rect_cw; 894 break; 895 case PIPE_FACE_FRONT: 896 setup->rect = setup->ccw_is_frontface ? setup_rect_cw : setup_rect_ccw; 897 break; 898 default: 899 setup->rect = setup_rect_noop; 900 break; 901 } 902} 903