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 * \brief Primitive rasterization/rendering (points, lines, triangles) 30 * 31 * \author Keith Whitwell <keithw@vmware.com> 32 * \author Brian Paul 33 */ 34 35#include "sp_context.h" 36#include "sp_screen.h" 37#include "sp_quad.h" 38#include "sp_quad_pipe.h" 39#include "sp_setup.h" 40#include "sp_state.h" 41#include "draw/draw_context.h" 42#include "pipe/p_shader_tokens.h" 43#include "util/u_math.h" 44#include "util/u_memory.h" 45 46 47#define DEBUG_VERTS 0 48#define DEBUG_FRAGS 0 49 50 51/** 52 * Triangle edge info 53 */ 54struct edge { 55 float dx; /**< X(v1) - X(v0), used only during setup */ 56 float dy; /**< Y(v1) - Y(v0), used only during setup */ 57 float dxdy; /**< dx/dy */ 58 float sx, sy; /**< first sample point coord */ 59 int lines; /**< number of lines on this edge */ 60}; 61 62 63/** 64 * Max number of quads (2x2 pixel blocks) to process per batch. 65 * This can't be arbitrarily increased since we depend on some 32-bit 66 * bitmasks (two bits per quad). 67 */ 68#define MAX_QUADS 16 69 70 71/** 72 * Triangle setup info. 73 * Also used for line drawing (taking some liberties). 74 */ 75struct setup_context { 76 struct softpipe_context *softpipe; 77 78 /* Vertices are just an array of floats making up each attribute in 79 * turn. Currently fixed at 4 floats, but should change in time. 80 * Codegen will help cope with this. 81 */ 82 const float (*vmax)[4]; 83 const float (*vmid)[4]; 84 const float (*vmin)[4]; 85 const float (*vprovoke)[4]; 86 87 struct edge ebot; 88 struct edge etop; 89 struct edge emaj; 90 91 float oneoverarea; 92 int facing; 93 94 float pixel_offset; 95 unsigned max_layer; 96 97 struct quad_header quad[MAX_QUADS]; 98 struct quad_header *quad_ptrs[MAX_QUADS]; 99 unsigned count; 100 101 struct tgsi_interp_coef coef[PIPE_MAX_SHADER_INPUTS]; 102 struct tgsi_interp_coef posCoef; /* For Z, W */ 103 104 struct { 105 int left[2]; /**< [0] = row0, [1] = row1 */ 106 int right[2]; 107 int y; 108 } span; 109 110#if DEBUG_FRAGS 111 uint numFragsEmitted; /**< per primitive */ 112 uint numFragsWritten; /**< per primitive */ 113#endif 114 115 unsigned cull_face; /* which faces cull */ 116 unsigned nr_vertex_attrs; 117}; 118 119 120 121 122 123 124 125/** 126 * Clip setup->quad against the scissor/surface bounds. 127 */ 128static inline void 129quad_clip(struct setup_context *setup, struct quad_header *quad) 130{ 131 unsigned viewport_index = quad[0].input.viewport_index; 132 const struct pipe_scissor_state *cliprect = &setup->softpipe->cliprect[viewport_index]; 133 const int minx = (int) cliprect->minx; 134 const int maxx = (int) cliprect->maxx; 135 const int miny = (int) cliprect->miny; 136 const int maxy = (int) cliprect->maxy; 137 138 if (quad->input.x0 >= maxx || 139 quad->input.y0 >= maxy || 140 quad->input.x0 + 1 < minx || 141 quad->input.y0 + 1 < miny) { 142 /* totally clipped */ 143 quad->inout.mask = 0x0; 144 return; 145 } 146 if (quad->input.x0 < minx) 147 quad->inout.mask &= (MASK_BOTTOM_RIGHT | MASK_TOP_RIGHT); 148 if (quad->input.y0 < miny) 149 quad->inout.mask &= (MASK_BOTTOM_LEFT | MASK_BOTTOM_RIGHT); 150 if (quad->input.x0 == maxx - 1) 151 quad->inout.mask &= (MASK_BOTTOM_LEFT | MASK_TOP_LEFT); 152 if (quad->input.y0 == maxy - 1) 153 quad->inout.mask &= (MASK_TOP_LEFT | MASK_TOP_RIGHT); 154} 155 156 157/** 158 * Emit a quad (pass to next stage) with clipping. 159 */ 160static inline void 161clip_emit_quad(struct setup_context *setup, struct quad_header *quad) 162{ 163 quad_clip(setup, quad); 164 165 if (quad->inout.mask) { 166 struct softpipe_context *sp = setup->softpipe; 167 168#if DEBUG_FRAGS 169 setup->numFragsEmitted += util_bitcount(quad->inout.mask); 170#endif 171 172 sp->quad.first->run( sp->quad.first, &quad, 1 ); 173 } 174} 175 176 177 178/** 179 * Given an X or Y coordinate, return the block/quad coordinate that it 180 * belongs to. 181 */ 182static inline int 183block(int x) 184{ 185 return x & ~(2-1); 186} 187 188 189static inline int 190block_x(int x) 191{ 192 return x & ~(16-1); 193} 194 195 196/** 197 * Render a horizontal span of quads 198 */ 199static void 200flush_spans(struct setup_context *setup) 201{ 202 const int step = MAX_QUADS; 203 const int xleft0 = setup->span.left[0]; 204 const int xleft1 = setup->span.left[1]; 205 const int xright0 = setup->span.right[0]; 206 const int xright1 = setup->span.right[1]; 207 struct quad_stage *pipe = setup->softpipe->quad.first; 208 209 const int minleft = block_x(MIN2(xleft0, xleft1)); 210 const int maxright = MAX2(xright0, xright1); 211 int x; 212 213 /* process quads in horizontal chunks of 16 */ 214 for (x = minleft; x < maxright; x += step) { 215 unsigned skip_left0 = CLAMP(xleft0 - x, 0, step); 216 unsigned skip_left1 = CLAMP(xleft1 - x, 0, step); 217 unsigned skip_right0 = CLAMP(x + step - xright0, 0, step); 218 unsigned skip_right1 = CLAMP(x + step - xright1, 0, step); 219 unsigned lx = x; 220 unsigned q = 0; 221 222 unsigned skipmask_left0 = (1U << skip_left0) - 1U; 223 unsigned skipmask_left1 = (1U << skip_left1) - 1U; 224 225 /* These calculations fail when step == 32 and skip_right == 0. 226 */ 227 unsigned skipmask_right0 = ~0U << (unsigned)(step - skip_right0); 228 unsigned skipmask_right1 = ~0U << (unsigned)(step - skip_right1); 229 230 unsigned mask0 = ~skipmask_left0 & ~skipmask_right0; 231 unsigned mask1 = ~skipmask_left1 & ~skipmask_right1; 232 233 if (mask0 | mask1) { 234 do { 235 unsigned quadmask = (mask0 & 3) | ((mask1 & 3) << 2); 236 if (quadmask) { 237 setup->quad[q].input.x0 = lx; 238 setup->quad[q].input.y0 = setup->span.y; 239 setup->quad[q].input.facing = setup->facing; 240 setup->quad[q].inout.mask = quadmask; 241 setup->quad_ptrs[q] = &setup->quad[q]; 242 q++; 243#if DEBUG_FRAGS 244 setup->numFragsEmitted += util_bitcount(quadmask); 245#endif 246 } 247 mask0 >>= 2; 248 mask1 >>= 2; 249 lx += 2; 250 } while (mask0 | mask1); 251 252 pipe->run( pipe, setup->quad_ptrs, q ); 253 } 254 } 255 256 257 setup->span.y = 0; 258 setup->span.right[0] = 0; 259 setup->span.right[1] = 0; 260 setup->span.left[0] = 1000000; /* greater than right[0] */ 261 setup->span.left[1] = 1000000; /* greater than right[1] */ 262} 263 264 265#if DEBUG_VERTS 266static void 267print_vertex(const struct setup_context *setup, 268 const float (*v)[4]) 269{ 270 int i; 271 debug_printf(" Vertex: (%p)\n", (void *) v); 272 for (i = 0; i < setup->nr_vertex_attrs; i++) { 273 debug_printf(" %d: %f %f %f %f\n", i, 274 v[i][0], v[i][1], v[i][2], v[i][3]); 275 if (util_is_inf_or_nan(v[i][0])) { 276 debug_printf(" NaN!\n"); 277 } 278 } 279} 280#endif 281 282 283/** 284 * Sort the vertices from top to bottom order, setting up the triangle 285 * edge fields (ebot, emaj, etop). 286 * \return FALSE if coords are inf/nan (cull the tri), TRUE otherwise 287 */ 288static boolean 289setup_sort_vertices(struct setup_context *setup, 290 float det, 291 const float (*v0)[4], 292 const float (*v1)[4], 293 const float (*v2)[4]) 294{ 295 if (setup->softpipe->rasterizer->flatshade_first) 296 setup->vprovoke = v0; 297 else 298 setup->vprovoke = v2; 299 300 /* determine bottom to top order of vertices */ 301 { 302 float y0 = v0[0][1]; 303 float y1 = v1[0][1]; 304 float y2 = v2[0][1]; 305 if (y0 <= y1) { 306 if (y1 <= y2) { 307 /* y0<=y1<=y2 */ 308 setup->vmin = v0; 309 setup->vmid = v1; 310 setup->vmax = v2; 311 } 312 else if (y2 <= y0) { 313 /* y2<=y0<=y1 */ 314 setup->vmin = v2; 315 setup->vmid = v0; 316 setup->vmax = v1; 317 } 318 else { 319 /* y0<=y2<=y1 */ 320 setup->vmin = v0; 321 setup->vmid = v2; 322 setup->vmax = v1; 323 } 324 } 325 else { 326 if (y0 <= y2) { 327 /* y1<=y0<=y2 */ 328 setup->vmin = v1; 329 setup->vmid = v0; 330 setup->vmax = v2; 331 } 332 else if (y2 <= y1) { 333 /* y2<=y1<=y0 */ 334 setup->vmin = v2; 335 setup->vmid = v1; 336 setup->vmax = v0; 337 } 338 else { 339 /* y1<=y2<=y0 */ 340 setup->vmin = v1; 341 setup->vmid = v2; 342 setup->vmax = v0; 343 } 344 } 345 } 346 347 setup->ebot.dx = setup->vmid[0][0] - setup->vmin[0][0]; 348 setup->ebot.dy = setup->vmid[0][1] - setup->vmin[0][1]; 349 setup->emaj.dx = setup->vmax[0][0] - setup->vmin[0][0]; 350 setup->emaj.dy = setup->vmax[0][1] - setup->vmin[0][1]; 351 setup->etop.dx = setup->vmax[0][0] - setup->vmid[0][0]; 352 setup->etop.dy = setup->vmax[0][1] - setup->vmid[0][1]; 353 354 /* 355 * Compute triangle's area. Use 1/area to compute partial 356 * derivatives of attributes later. 357 * 358 * The area will be the same as prim->det, but the sign may be 359 * different depending on how the vertices get sorted above. 360 * 361 * To determine whether the primitive is front or back facing we 362 * use the prim->det value because its sign is correct. 363 */ 364 { 365 const float area = (setup->emaj.dx * setup->ebot.dy - 366 setup->ebot.dx * setup->emaj.dy); 367 368 setup->oneoverarea = 1.0f / area; 369 370 /* 371 debug_printf("%s one-over-area %f area %f det %f\n", 372 __FUNCTION__, setup->oneoverarea, area, det ); 373 */ 374 if (util_is_inf_or_nan(setup->oneoverarea)) 375 return FALSE; 376 } 377 378 /* We need to know if this is a front or back-facing triangle for: 379 * - the GLSL gl_FrontFacing fragment attribute (bool) 380 * - two-sided stencil test 381 * 0 = front-facing, 1 = back-facing 382 */ 383 setup->facing = 384 ((det < 0.0) ^ 385 (setup->softpipe->rasterizer->front_ccw)); 386 387 { 388 unsigned face = setup->facing == 0 ? PIPE_FACE_FRONT : PIPE_FACE_BACK; 389 390 if (face & setup->cull_face) 391 return FALSE; 392 } 393 394 return TRUE; 395} 396 397 398/** 399 * Compute a0 for a constant-valued coefficient (GL_FLAT shading). 400 * The value value comes from vertex[slot][i]. 401 * The result will be put into setup->coef[slot].a0[i]. 402 * \param slot which attribute slot 403 * \param i which component of the slot (0..3) 404 */ 405static void 406const_coeff(struct setup_context *setup, 407 struct tgsi_interp_coef *coef, 408 uint vertSlot, uint i) 409{ 410 assert(i <= 3); 411 412 coef->dadx[i] = 0; 413 coef->dady[i] = 0; 414 415 /* need provoking vertex info! 416 */ 417 coef->a0[i] = setup->vprovoke[vertSlot][i]; 418} 419 420 421/** 422 * Compute a0, dadx and dady for a linearly interpolated coefficient, 423 * for a triangle. 424 * v[0], v[1] and v[2] are vmin, vmid and vmax, respectively. 425 */ 426static void 427tri_linear_coeff(struct setup_context *setup, 428 struct tgsi_interp_coef *coef, 429 uint i, 430 const float v[3]) 431{ 432 float botda = v[1] - v[0]; 433 float majda = v[2] - v[0]; 434 float a = setup->ebot.dy * majda - botda * setup->emaj.dy; 435 float b = setup->emaj.dx * botda - majda * setup->ebot.dx; 436 float dadx = a * setup->oneoverarea; 437 float dady = b * setup->oneoverarea; 438 439 assert(i <= 3); 440 441 coef->dadx[i] = dadx; 442 coef->dady[i] = dady; 443 444 /* calculate a0 as the value which would be sampled for the 445 * fragment at (0,0), taking into account that we want to sample at 446 * pixel centers, in other words (pixel_offset, pixel_offset). 447 * 448 * this is neat but unfortunately not a good way to do things for 449 * triangles with very large values of dadx or dady as it will 450 * result in the subtraction and re-addition from a0 of a very 451 * large number, which means we'll end up loosing a lot of the 452 * fractional bits and precision from a0. the way to fix this is 453 * to define a0 as the sample at a pixel center somewhere near vmin 454 * instead - i'll switch to this later. 455 */ 456 coef->a0[i] = (v[0] - 457 (dadx * (setup->vmin[0][0] - setup->pixel_offset) + 458 dady * (setup->vmin[0][1] - setup->pixel_offset))); 459} 460 461 462/** 463 * Compute a0, dadx and dady for a perspective-corrected interpolant, 464 * for a triangle. 465 * We basically multiply the vertex value by 1/w before computing 466 * the plane coefficients (a0, dadx, dady). 467 * Later, when we compute the value at a particular fragment position we'll 468 * divide the interpolated value by the interpolated W at that fragment. 469 * v[0], v[1] and v[2] are vmin, vmid and vmax, respectively. 470 */ 471static void 472tri_persp_coeff(struct setup_context *setup, 473 struct tgsi_interp_coef *coef, 474 uint i, 475 const float v[3]) 476{ 477 /* premultiply by 1/w (v[0][3] is always W): 478 */ 479 float mina = v[0] * setup->vmin[0][3]; 480 float mida = v[1] * setup->vmid[0][3]; 481 float maxa = v[2] * setup->vmax[0][3]; 482 float botda = mida - mina; 483 float majda = maxa - mina; 484 float a = setup->ebot.dy * majda - botda * setup->emaj.dy; 485 float b = setup->emaj.dx * botda - majda * setup->ebot.dx; 486 float dadx = a * setup->oneoverarea; 487 float dady = b * setup->oneoverarea; 488 489 assert(i <= 3); 490 491 coef->dadx[i] = dadx; 492 coef->dady[i] = dady; 493 coef->a0[i] = (mina - 494 (dadx * (setup->vmin[0][0] - setup->pixel_offset) + 495 dady * (setup->vmin[0][1] - setup->pixel_offset))); 496} 497 498 499/** 500 * Special coefficient setup for gl_FragCoord. 501 * X and Y are trivial, though Y may have to be inverted for OpenGL. 502 * Z and W are copied from posCoef which should have already been computed. 503 * We could do a bit less work if we'd examine gl_FragCoord's swizzle mask. 504 */ 505static void 506setup_fragcoord_coeff(struct setup_context *setup, uint slot) 507{ 508 const struct tgsi_shader_info *fsInfo = &setup->softpipe->fs_variant->info; 509 boolean origin_lower_left = 510 fsInfo->properties[TGSI_PROPERTY_FS_COORD_ORIGIN]; 511 boolean pixel_center_integer = 512 fsInfo->properties[TGSI_PROPERTY_FS_COORD_PIXEL_CENTER]; 513 514 /*X*/ 515 setup->coef[slot].a0[0] = pixel_center_integer ? 0.0f : 0.5f; 516 setup->coef[slot].dadx[0] = 1.0f; 517 setup->coef[slot].dady[0] = 0.0f; 518 /*Y*/ 519 setup->coef[slot].a0[1] = 520 (origin_lower_left ? setup->softpipe->framebuffer.height-1 : 0) 521 + (pixel_center_integer ? 0.0f : 0.5f); 522 setup->coef[slot].dadx[1] = 0.0f; 523 setup->coef[slot].dady[1] = origin_lower_left ? -1.0f : 1.0f; 524 /*Z*/ 525 setup->coef[slot].a0[2] = setup->posCoef.a0[2]; 526 setup->coef[slot].dadx[2] = setup->posCoef.dadx[2]; 527 setup->coef[slot].dady[2] = setup->posCoef.dady[2]; 528 /*W*/ 529 setup->coef[slot].a0[3] = setup->posCoef.a0[3]; 530 setup->coef[slot].dadx[3] = setup->posCoef.dadx[3]; 531 setup->coef[slot].dady[3] = setup->posCoef.dady[3]; 532} 533 534 535 536/** 537 * Compute the setup->coef[] array dadx, dady, a0 values. 538 * Must be called after setup->vmin,vmid,vmax,vprovoke are initialized. 539 */ 540static void 541setup_tri_coefficients(struct setup_context *setup) 542{ 543 struct softpipe_context *softpipe = setup->softpipe; 544 const struct tgsi_shader_info *fsInfo = &setup->softpipe->fs_variant->info; 545 const struct sp_setup_info *sinfo = &softpipe->setup_info; 546 uint fragSlot; 547 float v[3]; 548 549 assert(sinfo->valid); 550 551 /* z and w are done by linear interpolation: 552 */ 553 v[0] = setup->vmin[0][2]; 554 v[1] = setup->vmid[0][2]; 555 v[2] = setup->vmax[0][2]; 556 tri_linear_coeff(setup, &setup->posCoef, 2, v); 557 558 v[0] = setup->vmin[0][3]; 559 v[1] = setup->vmid[0][3]; 560 v[2] = setup->vmax[0][3]; 561 tri_linear_coeff(setup, &setup->posCoef, 3, v); 562 563 /* setup interpolation for all the remaining attributes: 564 */ 565 for (fragSlot = 0; fragSlot < fsInfo->num_inputs; fragSlot++) { 566 const uint vertSlot = sinfo->attrib[fragSlot].src_index; 567 uint j; 568 569 switch (sinfo->attrib[fragSlot].interp) { 570 case SP_INTERP_CONSTANT: 571 for (j = 0; j < TGSI_NUM_CHANNELS; j++) { 572 const_coeff(setup, &setup->coef[fragSlot], vertSlot, j); 573 } 574 break; 575 case SP_INTERP_LINEAR: 576 for (j = 0; j < TGSI_NUM_CHANNELS; j++) { 577 v[0] = setup->vmin[vertSlot][j]; 578 v[1] = setup->vmid[vertSlot][j]; 579 v[2] = setup->vmax[vertSlot][j]; 580 tri_linear_coeff(setup, &setup->coef[fragSlot], j, v); 581 } 582 break; 583 case SP_INTERP_PERSPECTIVE: 584 for (j = 0; j < TGSI_NUM_CHANNELS; j++) { 585 v[0] = setup->vmin[vertSlot][j]; 586 v[1] = setup->vmid[vertSlot][j]; 587 v[2] = setup->vmax[vertSlot][j]; 588 tri_persp_coeff(setup, &setup->coef[fragSlot], j, v); 589 } 590 break; 591 case SP_INTERP_POS: 592 setup_fragcoord_coeff(setup, fragSlot); 593 break; 594 default: 595 assert(0); 596 } 597 598 if (fsInfo->input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) { 599 /* convert 0 to 1.0 and 1 to -1.0 */ 600 setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f; 601 setup->coef[fragSlot].dadx[0] = 0.0; 602 setup->coef[fragSlot].dady[0] = 0.0; 603 } 604 605 if (0) { 606 for (j = 0; j < TGSI_NUM_CHANNELS; j++) { 607 debug_printf("attr[%d].%c: a0:%f dx:%f dy:%f\n", 608 fragSlot, "xyzw"[j], 609 setup->coef[fragSlot].a0[j], 610 setup->coef[fragSlot].dadx[j], 611 setup->coef[fragSlot].dady[j]); 612 } 613 } 614 } 615} 616 617 618static void 619setup_tri_edges(struct setup_context *setup) 620{ 621 float vmin_x = setup->vmin[0][0] + setup->pixel_offset; 622 float vmid_x = setup->vmid[0][0] + setup->pixel_offset; 623 624 float vmin_y = setup->vmin[0][1] - setup->pixel_offset; 625 float vmid_y = setup->vmid[0][1] - setup->pixel_offset; 626 float vmax_y = setup->vmax[0][1] - setup->pixel_offset; 627 628 setup->emaj.sy = ceilf(vmin_y); 629 setup->emaj.lines = (int) ceilf(vmax_y - setup->emaj.sy); 630 setup->emaj.dxdy = setup->emaj.dy ? setup->emaj.dx / setup->emaj.dy : .0f; 631 setup->emaj.sx = vmin_x + (setup->emaj.sy - vmin_y) * setup->emaj.dxdy; 632 633 setup->etop.sy = ceilf(vmid_y); 634 setup->etop.lines = (int) ceilf(vmax_y - setup->etop.sy); 635 setup->etop.dxdy = setup->etop.dy ? setup->etop.dx / setup->etop.dy : .0f; 636 setup->etop.sx = vmid_x + (setup->etop.sy - vmid_y) * setup->etop.dxdy; 637 638 setup->ebot.sy = ceilf(vmin_y); 639 setup->ebot.lines = (int) ceilf(vmid_y - setup->ebot.sy); 640 setup->ebot.dxdy = setup->ebot.dy ? setup->ebot.dx / setup->ebot.dy : .0f; 641 setup->ebot.sx = vmin_x + (setup->ebot.sy - vmin_y) * setup->ebot.dxdy; 642} 643 644 645/** 646 * Render the upper or lower half of a triangle. 647 * Scissoring/cliprect is applied here too. 648 */ 649static void 650subtriangle(struct setup_context *setup, 651 struct edge *eleft, 652 struct edge *eright, 653 int lines, 654 unsigned viewport_index) 655{ 656 const struct pipe_scissor_state *cliprect = &setup->softpipe->cliprect[viewport_index]; 657 const int minx = (int) cliprect->minx; 658 const int maxx = (int) cliprect->maxx; 659 const int miny = (int) cliprect->miny; 660 const int maxy = (int) cliprect->maxy; 661 int y, start_y, finish_y; 662 int sy = (int)eleft->sy; 663 664 assert((int)eleft->sy == (int) eright->sy); 665 assert(lines >= 0); 666 667 /* clip top/bottom */ 668 start_y = sy; 669 if (start_y < miny) 670 start_y = miny; 671 672 finish_y = sy + lines; 673 if (finish_y > maxy) 674 finish_y = maxy; 675 676 start_y -= sy; 677 finish_y -= sy; 678 679 /* 680 debug_printf("%s %d %d\n", __FUNCTION__, start_y, finish_y); 681 */ 682 683 for (y = start_y; y < finish_y; y++) { 684 685 /* avoid accumulating adds as floats don't have the precision to 686 * accurately iterate large triangle edges that way. luckily we 687 * can just multiply these days. 688 * 689 * this is all drowned out by the attribute interpolation anyway. 690 */ 691 int left = (int)(eleft->sx + y * eleft->dxdy); 692 int right = (int)(eright->sx + y * eright->dxdy); 693 694 /* clip left/right */ 695 if (left < minx) 696 left = minx; 697 if (right > maxx) 698 right = maxx; 699 700 if (left < right) { 701 int _y = sy + y; 702 if (block(_y) != setup->span.y) { 703 flush_spans(setup); 704 setup->span.y = block(_y); 705 } 706 707 setup->span.left[_y&1] = left; 708 setup->span.right[_y&1] = right; 709 } 710 } 711 712 713 /* save the values so that emaj can be restarted: 714 */ 715 eleft->sx += lines * eleft->dxdy; 716 eright->sx += lines * eright->dxdy; 717 eleft->sy += lines; 718 eright->sy += lines; 719} 720 721 722/** 723 * Recalculate prim's determinant. This is needed as we don't have 724 * get this information through the vbuf_render interface & we must 725 * calculate it here. 726 */ 727static float 728calc_det(const float (*v0)[4], 729 const float (*v1)[4], 730 const float (*v2)[4]) 731{ 732 /* edge vectors e = v0 - v2, f = v1 - v2 */ 733 const float ex = v0[0][0] - v2[0][0]; 734 const float ey = v0[0][1] - v2[0][1]; 735 const float fx = v1[0][0] - v2[0][0]; 736 const float fy = v1[0][1] - v2[0][1]; 737 738 /* det = cross(e,f).z */ 739 return ex * fy - ey * fx; 740} 741 742 743/** 744 * Do setup for triangle rasterization, then render the triangle. 745 */ 746void 747sp_setup_tri(struct setup_context *setup, 748 const float (*v0)[4], 749 const float (*v1)[4], 750 const float (*v2)[4]) 751{ 752 float det; 753 uint layer = 0; 754 unsigned viewport_index = 0; 755#if DEBUG_VERTS 756 debug_printf("Setup triangle:\n"); 757 print_vertex(setup, v0); 758 print_vertex(setup, v1); 759 print_vertex(setup, v2); 760#endif 761 762 if (unlikely(sp_debug & SP_DBG_NO_RAST) || 763 setup->softpipe->rasterizer->rasterizer_discard) 764 return; 765 766 det = calc_det(v0, v1, v2); 767 /* 768 debug_printf("%s\n", __FUNCTION__ ); 769 */ 770 771#if DEBUG_FRAGS 772 setup->numFragsEmitted = 0; 773 setup->numFragsWritten = 0; 774#endif 775 776 if (!setup_sort_vertices( setup, det, v0, v1, v2 )) 777 return; 778 779 setup_tri_coefficients( setup ); 780 setup_tri_edges( setup ); 781 782 assert(setup->softpipe->reduced_prim == PIPE_PRIM_TRIANGLES); 783 784 setup->span.y = 0; 785 setup->span.right[0] = 0; 786 setup->span.right[1] = 0; 787 /* setup->span.z_mode = tri_z_mode( setup->ctx ); */ 788 if (setup->softpipe->layer_slot > 0) { 789 layer = *(unsigned *)setup->vprovoke[setup->softpipe->layer_slot]; 790 layer = MIN2(layer, setup->max_layer); 791 } 792 setup->quad[0].input.layer = layer; 793 794 if (setup->softpipe->viewport_index_slot > 0) { 795 unsigned *udata = (unsigned*)v0[setup->softpipe->viewport_index_slot]; 796 viewport_index = sp_clamp_viewport_idx(*udata); 797 } 798 setup->quad[0].input.viewport_index = viewport_index; 799 800 /* init_constant_attribs( setup ); */ 801 802 if (setup->oneoverarea < 0.0) { 803 /* emaj on left: 804 */ 805 subtriangle(setup, &setup->emaj, &setup->ebot, setup->ebot.lines, viewport_index); 806 subtriangle(setup, &setup->emaj, &setup->etop, setup->etop.lines, viewport_index); 807 } 808 else { 809 /* emaj on right: 810 */ 811 subtriangle(setup, &setup->ebot, &setup->emaj, setup->ebot.lines, viewport_index); 812 subtriangle(setup, &setup->etop, &setup->emaj, setup->etop.lines, viewport_index); 813 } 814 815 flush_spans( setup ); 816 817 if (setup->softpipe->active_statistics_queries) { 818 setup->softpipe->pipeline_statistics.c_primitives++; 819 } 820 821#if DEBUG_FRAGS 822 printf("Tri: %u frags emitted, %u written\n", 823 setup->numFragsEmitted, 824 setup->numFragsWritten); 825#endif 826} 827 828 829/** 830 * Compute a0, dadx and dady for a linearly interpolated coefficient, 831 * for a line. 832 * v[0] and v[1] are vmin and vmax, respectively. 833 */ 834static void 835line_linear_coeff(const struct setup_context *setup, 836 struct tgsi_interp_coef *coef, 837 uint i, 838 const float v[2]) 839{ 840 const float da = v[1] - v[0]; 841 const float dadx = da * setup->emaj.dx * setup->oneoverarea; 842 const float dady = da * setup->emaj.dy * setup->oneoverarea; 843 coef->dadx[i] = dadx; 844 coef->dady[i] = dady; 845 coef->a0[i] = (v[0] - 846 (dadx * (setup->vmin[0][0] - setup->pixel_offset) + 847 dady * (setup->vmin[0][1] - setup->pixel_offset))); 848} 849 850 851/** 852 * Compute a0, dadx and dady for a perspective-corrected interpolant, 853 * for a line. 854 * v[0] and v[1] are vmin and vmax, respectively. 855 */ 856static void 857line_persp_coeff(const struct setup_context *setup, 858 struct tgsi_interp_coef *coef, 859 uint i, 860 const float v[2]) 861{ 862 const float a0 = v[0] * setup->vmin[0][3]; 863 const float a1 = v[1] * setup->vmax[0][3]; 864 const float da = a1 - a0; 865 const float dadx = da * setup->emaj.dx * setup->oneoverarea; 866 const float dady = da * setup->emaj.dy * setup->oneoverarea; 867 coef->dadx[i] = dadx; 868 coef->dady[i] = dady; 869 coef->a0[i] = (a0 - 870 (dadx * (setup->vmin[0][0] - setup->pixel_offset) + 871 dady * (setup->vmin[0][1] - setup->pixel_offset))); 872} 873 874 875/** 876 * Compute the setup->coef[] array dadx, dady, a0 values. 877 * Must be called after setup->vmin,vmax are initialized. 878 */ 879static boolean 880setup_line_coefficients(struct setup_context *setup, 881 const float (*v0)[4], 882 const float (*v1)[4]) 883{ 884 struct softpipe_context *softpipe = setup->softpipe; 885 const struct tgsi_shader_info *fsInfo = &setup->softpipe->fs_variant->info; 886 const struct sp_setup_info *sinfo = &softpipe->setup_info; 887 uint fragSlot; 888 float area; 889 float v[2]; 890 891 assert(sinfo->valid); 892 893 /* use setup->vmin, vmax to point to vertices */ 894 if (softpipe->rasterizer->flatshade_first) 895 setup->vprovoke = v0; 896 else 897 setup->vprovoke = v1; 898 setup->vmin = v0; 899 setup->vmax = v1; 900 901 setup->emaj.dx = setup->vmax[0][0] - setup->vmin[0][0]; 902 setup->emaj.dy = setup->vmax[0][1] - setup->vmin[0][1]; 903 904 /* NOTE: this is not really area but something proportional to it */ 905 area = setup->emaj.dx * setup->emaj.dx + setup->emaj.dy * setup->emaj.dy; 906 if (area == 0.0f || util_is_inf_or_nan(area)) 907 return FALSE; 908 setup->oneoverarea = 1.0f / area; 909 910 /* z and w are done by linear interpolation: 911 */ 912 v[0] = setup->vmin[0][2]; 913 v[1] = setup->vmax[0][2]; 914 line_linear_coeff(setup, &setup->posCoef, 2, v); 915 916 v[0] = setup->vmin[0][3]; 917 v[1] = setup->vmax[0][3]; 918 line_linear_coeff(setup, &setup->posCoef, 3, v); 919 920 /* setup interpolation for all the remaining attributes: 921 */ 922 for (fragSlot = 0; fragSlot < fsInfo->num_inputs; fragSlot++) { 923 const uint vertSlot = sinfo->attrib[fragSlot].src_index; 924 uint j; 925 926 switch (sinfo->attrib[fragSlot].interp) { 927 case SP_INTERP_CONSTANT: 928 for (j = 0; j < TGSI_NUM_CHANNELS; j++) 929 const_coeff(setup, &setup->coef[fragSlot], vertSlot, j); 930 break; 931 case SP_INTERP_LINEAR: 932 for (j = 0; j < TGSI_NUM_CHANNELS; j++) { 933 v[0] = setup->vmin[vertSlot][j]; 934 v[1] = setup->vmax[vertSlot][j]; 935 line_linear_coeff(setup, &setup->coef[fragSlot], j, v); 936 } 937 break; 938 case SP_INTERP_PERSPECTIVE: 939 for (j = 0; j < TGSI_NUM_CHANNELS; j++) { 940 v[0] = setup->vmin[vertSlot][j]; 941 v[1] = setup->vmax[vertSlot][j]; 942 line_persp_coeff(setup, &setup->coef[fragSlot], j, v); 943 } 944 break; 945 case SP_INTERP_POS: 946 setup_fragcoord_coeff(setup, fragSlot); 947 break; 948 default: 949 assert(0); 950 } 951 952 if (fsInfo->input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) { 953 /* convert 0 to 1.0 and 1 to -1.0 */ 954 setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f; 955 setup->coef[fragSlot].dadx[0] = 0.0; 956 setup->coef[fragSlot].dady[0] = 0.0; 957 } 958 } 959 return TRUE; 960} 961 962 963/** 964 * Plot a pixel in a line segment. 965 */ 966static inline void 967plot(struct setup_context *setup, int x, int y) 968{ 969 const int iy = y & 1; 970 const int ix = x & 1; 971 const int quadX = x - ix; 972 const int quadY = y - iy; 973 const int mask = (1 << ix) << (2 * iy); 974 975 if (quadX != setup->quad[0].input.x0 || 976 quadY != setup->quad[0].input.y0) 977 { 978 /* flush prev quad, start new quad */ 979 980 if (setup->quad[0].input.x0 != -1) 981 clip_emit_quad(setup, &setup->quad[0]); 982 983 setup->quad[0].input.x0 = quadX; 984 setup->quad[0].input.y0 = quadY; 985 setup->quad[0].inout.mask = 0x0; 986 } 987 988 setup->quad[0].inout.mask |= mask; 989} 990 991 992/** 993 * Do setup for line rasterization, then render the line. 994 * Single-pixel width, no stipple, etc. We rely on the 'draw' module 995 * to handle stippling and wide lines. 996 */ 997void 998sp_setup_line(struct setup_context *setup, 999 const float (*v0)[4], 1000 const float (*v1)[4]) 1001{ 1002 int x0 = (int) v0[0][0]; 1003 int x1 = (int) v1[0][0]; 1004 int y0 = (int) v0[0][1]; 1005 int y1 = (int) v1[0][1]; 1006 int dx = x1 - x0; 1007 int dy = y1 - y0; 1008 int xstep, ystep; 1009 uint layer = 0; 1010 unsigned viewport_index = 0; 1011 1012#if DEBUG_VERTS 1013 debug_printf("Setup line:\n"); 1014 print_vertex(setup, v0); 1015 print_vertex(setup, v1); 1016#endif 1017 1018 if (unlikely(sp_debug & SP_DBG_NO_RAST) || 1019 setup->softpipe->rasterizer->rasterizer_discard) 1020 return; 1021 1022 if (dx == 0 && dy == 0) 1023 return; 1024 1025 if (!setup_line_coefficients(setup, v0, v1)) 1026 return; 1027 1028 assert(v0[0][0] < 1.0e9); 1029 assert(v0[0][1] < 1.0e9); 1030 assert(v1[0][0] < 1.0e9); 1031 assert(v1[0][1] < 1.0e9); 1032 1033 if (dx < 0) { 1034 dx = -dx; /* make positive */ 1035 xstep = -1; 1036 } 1037 else { 1038 xstep = 1; 1039 } 1040 1041 if (dy < 0) { 1042 dy = -dy; /* make positive */ 1043 ystep = -1; 1044 } 1045 else { 1046 ystep = 1; 1047 } 1048 1049 assert(dx >= 0); 1050 assert(dy >= 0); 1051 assert(setup->softpipe->reduced_prim == PIPE_PRIM_LINES); 1052 1053 setup->quad[0].input.x0 = setup->quad[0].input.y0 = -1; 1054 setup->quad[0].inout.mask = 0x0; 1055 if (setup->softpipe->layer_slot > 0) { 1056 layer = *(unsigned *)setup->vprovoke[setup->softpipe->layer_slot]; 1057 layer = MIN2(layer, setup->max_layer); 1058 } 1059 setup->quad[0].input.layer = layer; 1060 1061 if (setup->softpipe->viewport_index_slot > 0) { 1062 unsigned *udata = (unsigned*)setup->vprovoke[setup->softpipe->viewport_index_slot]; 1063 viewport_index = sp_clamp_viewport_idx(*udata); 1064 } 1065 setup->quad[0].input.viewport_index = viewport_index; 1066 1067 /* XXX temporary: set coverage to 1.0 so the line appears 1068 * if AA mode happens to be enabled. 1069 */ 1070 setup->quad[0].input.coverage[0] = 1071 setup->quad[0].input.coverage[1] = 1072 setup->quad[0].input.coverage[2] = 1073 setup->quad[0].input.coverage[3] = 1.0; 1074 1075 if (dx > dy) { 1076 /*** X-major line ***/ 1077 int i; 1078 const int errorInc = dy + dy; 1079 int error = errorInc - dx; 1080 const int errorDec = error - dx; 1081 1082 for (i = 0; i < dx; i++) { 1083 plot(setup, x0, y0); 1084 1085 x0 += xstep; 1086 if (error < 0) { 1087 error += errorInc; 1088 } 1089 else { 1090 error += errorDec; 1091 y0 += ystep; 1092 } 1093 } 1094 } 1095 else { 1096 /*** Y-major line ***/ 1097 int i; 1098 const int errorInc = dx + dx; 1099 int error = errorInc - dy; 1100 const int errorDec = error - dy; 1101 1102 for (i = 0; i < dy; i++) { 1103 plot(setup, x0, y0); 1104 1105 y0 += ystep; 1106 if (error < 0) { 1107 error += errorInc; 1108 } 1109 else { 1110 error += errorDec; 1111 x0 += xstep; 1112 } 1113 } 1114 } 1115 1116 /* draw final quad */ 1117 if (setup->quad[0].inout.mask) { 1118 clip_emit_quad(setup, &setup->quad[0]); 1119 } 1120} 1121 1122 1123static void 1124point_persp_coeff(const struct setup_context *setup, 1125 const float (*vert)[4], 1126 struct tgsi_interp_coef *coef, 1127 uint vertSlot, uint i) 1128{ 1129 assert(i <= 3); 1130 coef->dadx[i] = 0.0F; 1131 coef->dady[i] = 0.0F; 1132 coef->a0[i] = vert[vertSlot][i] * vert[0][3]; 1133} 1134 1135 1136/** 1137 * Do setup for point rasterization, then render the point. 1138 * Round or square points... 1139 * XXX could optimize a lot for 1-pixel points. 1140 */ 1141void 1142sp_setup_point(struct setup_context *setup, 1143 const float (*v0)[4]) 1144{ 1145 struct softpipe_context *softpipe = setup->softpipe; 1146 const struct tgsi_shader_info *fsInfo = &setup->softpipe->fs_variant->info; 1147 const int sizeAttr = setup->softpipe->psize_slot; 1148 const float size 1149 = sizeAttr > 0 ? v0[sizeAttr][0] 1150 : setup->softpipe->rasterizer->point_size; 1151 const float halfSize = 0.5F * size; 1152 const boolean round = (boolean) setup->softpipe->rasterizer->point_smooth; 1153 const float x = v0[0][0]; /* Note: data[0] is always position */ 1154 const float y = v0[0][1]; 1155 const struct sp_setup_info *sinfo = &softpipe->setup_info; 1156 uint fragSlot; 1157 uint layer = 0; 1158 unsigned viewport_index = 0; 1159#if DEBUG_VERTS 1160 debug_printf("Setup point:\n"); 1161 print_vertex(setup, v0); 1162#endif 1163 1164 assert(sinfo->valid); 1165 1166 if (unlikely(sp_debug & SP_DBG_NO_RAST) || 1167 setup->softpipe->rasterizer->rasterizer_discard) 1168 return; 1169 1170 assert(setup->softpipe->reduced_prim == PIPE_PRIM_POINTS); 1171 1172 if (setup->softpipe->layer_slot > 0) { 1173 layer = *(unsigned *)v0[setup->softpipe->layer_slot]; 1174 layer = MIN2(layer, setup->max_layer); 1175 } 1176 setup->quad[0].input.layer = layer; 1177 1178 if (setup->softpipe->viewport_index_slot > 0) { 1179 unsigned *udata = (unsigned*)v0[setup->softpipe->viewport_index_slot]; 1180 viewport_index = sp_clamp_viewport_idx(*udata); 1181 } 1182 setup->quad[0].input.viewport_index = viewport_index; 1183 1184 /* For points, all interpolants are constant-valued. 1185 * However, for point sprites, we'll need to setup texcoords appropriately. 1186 * XXX: which coefficients are the texcoords??? 1187 * We may do point sprites as textured quads... 1188 * 1189 * KW: We don't know which coefficients are texcoords - ultimately 1190 * the choice of what interpolation mode to use for each attribute 1191 * should be determined by the fragment program, using 1192 * per-attribute declaration statements that include interpolation 1193 * mode as a parameter. So either the fragment program will have 1194 * to be adjusted for pointsprite vs normal point behaviour, or 1195 * otherwise a special interpolation mode will have to be defined 1196 * which matches the required behaviour for point sprites. But - 1197 * the latter is not a feature of normal hardware, and as such 1198 * probably should be ruled out on that basis. 1199 */ 1200 setup->vprovoke = v0; 1201 1202 /* setup Z, W */ 1203 const_coeff(setup, &setup->posCoef, 0, 2); 1204 const_coeff(setup, &setup->posCoef, 0, 3); 1205 1206 for (fragSlot = 0; fragSlot < fsInfo->num_inputs; fragSlot++) { 1207 const uint vertSlot = sinfo->attrib[fragSlot].src_index; 1208 uint j; 1209 1210 switch (sinfo->attrib[fragSlot].interp) { 1211 case SP_INTERP_CONSTANT: 1212 FALLTHROUGH; 1213 case SP_INTERP_LINEAR: 1214 for (j = 0; j < TGSI_NUM_CHANNELS; j++) 1215 const_coeff(setup, &setup->coef[fragSlot], vertSlot, j); 1216 break; 1217 case SP_INTERP_PERSPECTIVE: 1218 for (j = 0; j < TGSI_NUM_CHANNELS; j++) 1219 point_persp_coeff(setup, setup->vprovoke, 1220 &setup->coef[fragSlot], vertSlot, j); 1221 break; 1222 case SP_INTERP_POS: 1223 setup_fragcoord_coeff(setup, fragSlot); 1224 break; 1225 default: 1226 assert(0); 1227 } 1228 1229 if (fsInfo->input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) { 1230 /* convert 0 to 1.0 and 1 to -1.0 */ 1231 setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f; 1232 setup->coef[fragSlot].dadx[0] = 0.0; 1233 setup->coef[fragSlot].dady[0] = 0.0; 1234 } 1235 } 1236 1237 1238 if (halfSize <= 0.5 && !round) { 1239 /* special case for 1-pixel points */ 1240 const int ix = ((int) x) & 1; 1241 const int iy = ((int) y) & 1; 1242 setup->quad[0].input.x0 = (int) x - ix; 1243 setup->quad[0].input.y0 = (int) y - iy; 1244 setup->quad[0].inout.mask = (1 << ix) << (2 * iy); 1245 clip_emit_quad(setup, &setup->quad[0]); 1246 } 1247 else { 1248 if (round) { 1249 /* rounded points */ 1250 const int ixmin = block((int) (x - halfSize)); 1251 const int ixmax = block((int) (x + halfSize)); 1252 const int iymin = block((int) (y - halfSize)); 1253 const int iymax = block((int) (y + halfSize)); 1254 const float rmin = halfSize - 0.7071F; /* 0.7071 = sqrt(2)/2 */ 1255 const float rmax = halfSize + 0.7071F; 1256 const float rmin2 = MAX2(0.0F, rmin * rmin); 1257 const float rmax2 = rmax * rmax; 1258 const float cscale = 1.0F / (rmax2 - rmin2); 1259 int ix, iy; 1260 1261 for (iy = iymin; iy <= iymax; iy += 2) { 1262 for (ix = ixmin; ix <= ixmax; ix += 2) { 1263 float dx, dy, dist2, cover; 1264 1265 setup->quad[0].inout.mask = 0x0; 1266 1267 dx = (ix + 0.5f) - x; 1268 dy = (iy + 0.5f) - y; 1269 dist2 = dx * dx + dy * dy; 1270 if (dist2 <= rmax2) { 1271 cover = 1.0F - (dist2 - rmin2) * cscale; 1272 setup->quad[0].input.coverage[QUAD_TOP_LEFT] = MIN2(cover, 1.0f); 1273 setup->quad[0].inout.mask |= MASK_TOP_LEFT; 1274 } 1275 1276 dx = (ix + 1.5f) - x; 1277 dy = (iy + 0.5f) - y; 1278 dist2 = dx * dx + dy * dy; 1279 if (dist2 <= rmax2) { 1280 cover = 1.0F - (dist2 - rmin2) * cscale; 1281 setup->quad[0].input.coverage[QUAD_TOP_RIGHT] = MIN2(cover, 1.0f); 1282 setup->quad[0].inout.mask |= MASK_TOP_RIGHT; 1283 } 1284 1285 dx = (ix + 0.5f) - x; 1286 dy = (iy + 1.5f) - y; 1287 dist2 = dx * dx + dy * dy; 1288 if (dist2 <= rmax2) { 1289 cover = 1.0F - (dist2 - rmin2) * cscale; 1290 setup->quad[0].input.coverage[QUAD_BOTTOM_LEFT] = MIN2(cover, 1.0f); 1291 setup->quad[0].inout.mask |= MASK_BOTTOM_LEFT; 1292 } 1293 1294 dx = (ix + 1.5f) - x; 1295 dy = (iy + 1.5f) - y; 1296 dist2 = dx * dx + dy * dy; 1297 if (dist2 <= rmax2) { 1298 cover = 1.0F - (dist2 - rmin2) * cscale; 1299 setup->quad[0].input.coverage[QUAD_BOTTOM_RIGHT] = MIN2(cover, 1.0f); 1300 setup->quad[0].inout.mask |= MASK_BOTTOM_RIGHT; 1301 } 1302 1303 if (setup->quad[0].inout.mask) { 1304 setup->quad[0].input.x0 = ix; 1305 setup->quad[0].input.y0 = iy; 1306 clip_emit_quad(setup, &setup->quad[0]); 1307 } 1308 } 1309 } 1310 } 1311 else { 1312 /* square points */ 1313 const int xmin = (int) (x + 0.75 - halfSize); 1314 const int ymin = (int) (y + 0.25 - halfSize); 1315 const int xmax = xmin + (int) size; 1316 const int ymax = ymin + (int) size; 1317 /* XXX could apply scissor to xmin,ymin,xmax,ymax now */ 1318 const int ixmin = block(xmin); 1319 const int ixmax = block(xmax - 1); 1320 const int iymin = block(ymin); 1321 const int iymax = block(ymax - 1); 1322 int ix, iy; 1323 1324 /* 1325 debug_printf("(%f, %f) -> X:%d..%d Y:%d..%d\n", x, y, xmin, xmax,ymin,ymax); 1326 */ 1327 for (iy = iymin; iy <= iymax; iy += 2) { 1328 uint rowMask = 0xf; 1329 if (iy < ymin) { 1330 /* above the top edge */ 1331 rowMask &= (MASK_BOTTOM_LEFT | MASK_BOTTOM_RIGHT); 1332 } 1333 if (iy + 1 >= ymax) { 1334 /* below the bottom edge */ 1335 rowMask &= (MASK_TOP_LEFT | MASK_TOP_RIGHT); 1336 } 1337 1338 for (ix = ixmin; ix <= ixmax; ix += 2) { 1339 uint mask = rowMask; 1340 1341 if (ix < xmin) { 1342 /* fragment is past left edge of point, turn off left bits */ 1343 mask &= (MASK_BOTTOM_RIGHT | MASK_TOP_RIGHT); 1344 } 1345 if (ix + 1 >= xmax) { 1346 /* past the right edge */ 1347 mask &= (MASK_BOTTOM_LEFT | MASK_TOP_LEFT); 1348 } 1349 1350 setup->quad[0].inout.mask = mask; 1351 setup->quad[0].input.x0 = ix; 1352 setup->quad[0].input.y0 = iy; 1353 clip_emit_quad(setup, &setup->quad[0]); 1354 } 1355 } 1356 } 1357 } 1358} 1359 1360 1361/** 1362 * Called by vbuf code just before we start buffering primitives. 1363 */ 1364void 1365sp_setup_prepare(struct setup_context *setup) 1366{ 1367 struct softpipe_context *sp = setup->softpipe; 1368 int i; 1369 unsigned max_layer = ~0; 1370 if (sp->dirty) { 1371 softpipe_update_derived(sp, sp->reduced_api_prim); 1372 } 1373 1374 /* Note: nr_attrs is only used for debugging (vertex printing) */ 1375 setup->nr_vertex_attrs = draw_num_shader_outputs(sp->draw); 1376 1377 /* 1378 * Determine how many layers the fb has (used for clamping layer value). 1379 * OpenGL (but not d3d10) permits different amount of layers per rt, however 1380 * results are undefined if layer exceeds the amount of layers of ANY 1381 * attachment hence don't need separate per cbuf and zsbuf max. 1382 */ 1383 for (i = 0; i < setup->softpipe->framebuffer.nr_cbufs; i++) { 1384 struct pipe_surface *cbuf = setup->softpipe->framebuffer.cbufs[i]; 1385 if (cbuf) { 1386 max_layer = MIN2(max_layer, 1387 cbuf->u.tex.last_layer - cbuf->u.tex.first_layer); 1388 1389 } 1390 } 1391 1392 /* Prepare pixel offset for rasterisation: 1393 * - pixel center (0.5, 0.5) for GL, or 1394 * - assume (0.0, 0.0) for other APIs. 1395 */ 1396 if (setup->softpipe->rasterizer->half_pixel_center) { 1397 setup->pixel_offset = 0.5f; 1398 } else { 1399 setup->pixel_offset = 0.0f; 1400 } 1401 1402 setup->max_layer = max_layer; 1403 1404 sp->quad.first->begin( sp->quad.first ); 1405 1406 if (sp->reduced_api_prim == PIPE_PRIM_TRIANGLES && 1407 sp->rasterizer->fill_front == PIPE_POLYGON_MODE_FILL && 1408 sp->rasterizer->fill_back == PIPE_POLYGON_MODE_FILL) { 1409 /* we'll do culling */ 1410 setup->cull_face = sp->rasterizer->cull_face; 1411 } 1412 else { 1413 /* 'draw' will do culling */ 1414 setup->cull_face = PIPE_FACE_NONE; 1415 } 1416} 1417 1418 1419void 1420sp_setup_destroy_context(struct setup_context *setup) 1421{ 1422 FREE( setup ); 1423} 1424 1425 1426/** 1427 * Create a new primitive setup/render stage. 1428 */ 1429struct setup_context * 1430sp_setup_create_context(struct softpipe_context *softpipe) 1431{ 1432 struct setup_context *setup = CALLOC_STRUCT(setup_context); 1433 unsigned i; 1434 1435 setup->softpipe = softpipe; 1436 1437 for (i = 0; i < MAX_QUADS; i++) { 1438 setup->quad[i].coef = setup->coef; 1439 setup->quad[i].posCoef = &setup->posCoef; 1440 } 1441 1442 setup->span.left[0] = 1000000; /* greater than right[0] */ 1443 setup->span.left[1] = 1000000; /* greater than right[1] */ 1444 1445 return setup; 1446} 1447