Go to the source code of this file.
Data Structures | |
union | float4 |
struct | vertex_header |
Basic vertex info. More... | |
struct | edge |
Triangle edge info. More... | |
struct | interp_coef |
struct | setup_stage |
Triangle setup info (derived from draw_stage). More... | |
Defines | |
#define | CEILF(X) ((float) (int) ((X) + 0.99999)) |
#define | QUAD_TOP_LEFT 0 |
#define | QUAD_TOP_RIGHT 1 |
#define | QUAD_BOTTOM_LEFT 2 |
#define | QUAD_BOTTOM_RIGHT 3 |
#define | MASK_TOP_LEFT (1 << QUAD_TOP_LEFT) |
#define | MASK_TOP_RIGHT (1 << QUAD_TOP_RIGHT) |
#define | MASK_BOTTOM_LEFT (1 << QUAD_BOTTOM_LEFT) |
#define | MASK_BOTTOM_RIGHT (1 << QUAD_BOTTOM_RIGHT) |
#define | MASK_ALL 0xf |
#define | DEBUG_VERTS 0 |
Typedefs | |
typedef vector unsigned int | mask_t |
Triangle rendering within a tile. | |
Functions | |
static void | eval_coeff (uint slot, float x, float y, vector float result[4]) |
Evaluate attribute coefficients (plane equations) to compute attribute values for the four fragments in a quad. | |
static vector float | eval_z (float x, float y) |
static void | emit_quad (int x, int y, mask_t mask) |
Emit a quad (pass to next stage). | |
static int | block (int x) |
Given an X or Y coordinate, return the block/quad coordinate that it belongs to. | |
static mask_t | calculate_mask (int x) |
Compute mask which indicates which pixels in the 2x2 quad are actually inside the triangle's bounds. | |
static void | flush_spans (void) |
Render a horizontal span of quads. | |
static boolean | setup_sort_vertices (const struct vertex_header *v0, const struct vertex_header *v1, const struct vertex_header *v2) |
static void | const_coeff (uint slot) |
Compute a0 for a constant-valued coefficient (GL_FLAT shading). | |
static void | tri_linear_coeff (uint slot, uint firstComp, uint lastComp) |
Compute a0, dadx and dady for a linearly interpolated coefficient, for a triangle. | |
static void | tri_linear_coeff4 (uint slot) |
As above, but interp setup all four vector components. | |
static void | setup_tri_coefficients (void) |
Compute the setup.coef[] array dadx, dady, a0 values. | |
static void | setup_tri_edges (void) |
static void | subtriangle (struct edge *eleft, struct edge *eright, unsigned lines) |
Render the upper or lower half of a triangle. | |
boolean | tri_draw (const float *v0, const float *v1, const float *v2, uint tx, uint ty) |
Draw triangle into tile at (tx, ty) (tile coords) The tile data should have already been fetched. | |
Variables | |
static struct setup_stage | setup |
typedef vector unsigned int mask_t |
static int block | ( | int | x | ) | [static] |
static mask_t calculate_mask | ( | int | x | ) | [static] |
Compute mask which indicates which pixels in the 2x2 quad are actually inside the triangle's bounds.
The mask is a uint4 vector and each element will be 0 or 0xffffffff.
Definition at line 394 of file spu_tri.c.
00398 { 00399 /* This is a little tricky. 00400 * Use & instead of && to avoid branches. 00401 * Use negation to convert true/false to ~0/0 values. 00402 */ 00403 mask_t mask; 00404 mask = spu_insert(-((x >= setup.span.left[0]) & (x < setup.span.right[0])), mask, 0); 00405 mask = spu_insert(-((x+1 >= setup.span.left[0]) & (x+1 < setup.span.right[0])), mask, 1); 00406 mask = spu_insert(-((x >= setup.span.left[1]) & (x < setup.span.right[1])), mask, 2);
static void const_coeff | ( | uint | slot | ) | [static] |
static void emit_quad | ( | int | x, | |
int | y, | |||
mask_t | mask | |||
) | [static] |
Emit a quad (pass to next stage).
No clipping is done. Note: about 1/5 to 1/7 of the time, mask is zero and this function should be skipped. But adding the test for that slows things down overall.
< modified locally, but not put back yet
< modified locally, but not put back yet
Definition at line 261 of file spu_tri.c.
00265 { 00266 /* If any bits in mask are set... */ 00267 if (spu_extract(spu_orx(mask), 0)) { 00268 const int ix = x - setup.cliprect_minx; 00269 const int iy = y - setup.cliprect_miny; 00270 vector float colors[4]; 00271 00272 spu.cur_ctile_status = TILE_STATUS_DIRTY; 00273 spu.cur_ztile_status = TILE_STATUS_DIRTY; 00274 00275 if (spu.texture[0].start) { 00276 /* texture mapping */ 00277 const uint unit = 0; 00278 vector float texcoords[4]; 00279 eval_coeff(2, (float) x, (float) y, texcoords); 00280 00281 if (spu_extract(mask, 0)) 00282 colors[0] = spu.sample_texture[unit](unit, texcoords[0]); 00283 if (spu_extract(mask, 1)) 00284 colors[1] = spu.sample_texture[unit](unit, texcoords[1]); 00285 if (spu_extract(mask, 2)) 00286 colors[2] = spu.sample_texture[unit](unit, texcoords[2]); 00287 if (spu_extract(mask, 3)) 00288 colors[3] = spu.sample_texture[unit](unit, texcoords[3]); 00289 00290 00291 if (spu.texture[1].start) { 00292 /* multi-texture mapping */ 00293 const uint unit = 1; 00294 vector float colors1[4]; 00295 00296 eval_coeff(2, (float) x, (float) y, texcoords); 00297 00298 if (spu_extract(mask, 0)) 00299 colors1[0] = spu.sample_texture[unit](unit, texcoords[0]); 00300 if (spu_extract(mask, 1)) 00301 colors1[1] = spu.sample_texture[unit](unit, texcoords[1]); 00302 if (spu_extract(mask, 2)) 00303 colors1[2] = spu.sample_texture[unit](unit, texcoords[2]); 00304 if (spu_extract(mask, 3)) 00305 colors1[3] = spu.sample_texture[unit](unit, texcoords[3]); 00306 00307 /* hack: modulate first texture by second */ 00308 colors[0] = spu_mul(colors[0], colors1[0]); 00309 colors[1] = spu_mul(colors[1], colors1[1]); 00310 colors[2] = spu_mul(colors[2], colors1[2]); 00311 colors[3] = spu_mul(colors[3], colors1[3]); 00312 } 00313 00314 } 00315 else { 00316 /* simple shading */ 00317 #if 0 00318 eval_coeff(1, (float) x, (float) y, colors); 00319 00320 #else 00321 /* XXX new fragment program code */ 00322 00323 if (spu.fragment_program) { 00324 vector float inputs[4*4], outputs[2*4]; 00325 00326 /* setup inputs */ 00327 eval_coeff(1, (float) x, (float) y, inputs); 00328 00329 /* Execute the current fragment program */ 00330 spu.fragment_program(inputs, outputs, spu.constants); 00331 00332 /* Copy outputs */ 00333 colors[0] = outputs[0*4+0]; 00334 colors[1] = outputs[0*4+1]; 00335 colors[2] = outputs[0*4+2]; 00336 colors[3] = outputs[0*4+3]; 00337 00338 if (0 && spu.init.id==0 && y == 48) { 00339 printf("colors[0] = %f %f %f %f\n", 00340 spu_extract(colors[0], 0), 00341 spu_extract(colors[0], 1), 00342 spu_extract(colors[0], 2), 00343 spu_extract(colors[0], 3)); 00344 printf("colors[1] = %f %f %f %f\n", 00345 spu_extract(colors[1], 0), 00346 spu_extract(colors[1], 1), 00347 spu_extract(colors[1], 2), 00348 spu_extract(colors[1], 3)); 00349 } 00350 00351 } 00352 #endif 00353 } 00354 00355 00356 { 00357 /* Convert fragment data from AoS to SoA format. 00358 * I.e. (RGBA,RGBA,RGBA,RGBA) -> (RRRR,GGGG,BBBB,AAAA) 00359 * This is temporary! 00360 */ 00361 vector float soa_frag[4]; 00362 _transpose_matrix4x4(soa_frag, colors); 00363 00364 float4 fragZ; 00365 00366 fragZ.v = eval_z((float) x, (float) y); 00367 00368 /* Do all per-fragment/quad operations here, including: 00369 * alpha test, z test, stencil test, blend and framebuffer writing. 00370 */ 00371 spu.fragment_ops(ix, iy, &spu.ctile, &spu.ztile, 00372 fragZ.v, 00373 soa_frag[0], soa_frag[1], 00374 soa_frag[2], soa_frag[3], 00375 mask); 00376 }
static void eval_coeff | ( | uint | slot, | |
float | x, | |||
float | y, | |||
vector float | result[4] | |||
) | [static] |
Evaluate attribute coefficients (plane equations) to compute attribute values for the four fragments in a quad.
Eg: four colors will be computed (in AoS format).
Definition at line 211 of file spu_tri.c.
00211 : four colors will be computed (in AoS format). 00212 */ 00213 static INLINE void 00214 eval_coeff(uint slot, float x, float y, vector float result[4]) 00215 { 00216 switch (spu.vertex_info.interp_mode[slot]) { 00217 case INTERP_CONSTANT: 00218 result[QUAD_TOP_LEFT] = 00219 result[QUAD_TOP_RIGHT] = 00220 result[QUAD_BOTTOM_LEFT] = 00221 result[QUAD_BOTTOM_RIGHT] = setup.coef[slot].a0.v; 00222 break; 00223 00224 case INTERP_LINEAR: 00225 /* fall-through, for now */ 00226 default: 00227 { 00228 register vector float dadx = setup.coef[slot].dadx.v; 00229 register vector float dady = setup.coef[slot].dady.v; 00230 register vector float topLeft 00231 = spu_add(setup.coef[slot].a0.v, 00232 spu_add(spu_mul(spu_splats(x), dadx), 00233 spu_mul(spu_splats(y), dady))); 00234 00235 result[QUAD_TOP_LEFT] = topLeft; 00236 result[QUAD_TOP_RIGHT] = spu_add(topLeft, dadx); 00237 result[QUAD_BOTTOM_LEFT] = spu_add(topLeft, dady); 00238 result[QUAD_BOTTOM_RIGHT] = spu_add(spu_add(topLeft, dadx), dady);
static vector float eval_z | ( | float | x, | |
float | y | |||
) | [static] |
Definition at line 242 of file spu_tri.c.
References interp_coef::a0, setup_stage::coef, interp_coef::dadx, interp_coef::dady, and float4::f.
00246 { 00247 const uint slot = 0; 00248 const float dzdx = setup.coef[slot].dadx.f[2]; 00249 const float dzdy = setup.coef[slot].dady.f[2]; 00250 const float topLeft = setup.coef[slot].a0.f[2] + x * dzdx + y * dzdy; 00251 const vector float topLeftv = spu_splats(topLeft);
static void flush_spans | ( | void | ) | [static] |
Render a horizontal span of quads.
< mfc_get() called but not yet arrived
< in local store, but not changed
< modified locally, but not put back yet
< defined in FB, but not in local store
< mfc_get() called but not yet arrived
< in local store, but not changed
< modified locally, but not put back yet
< defined in FB, but not in local store
Definition at line 412 of file spu_tri.c.
00416 { 00417 int minleft, maxright; 00418 int x; 00419 00420 switch (setup.span.y_flags) { 00421 case 0x3: 00422 /* both odd and even lines written (both quad rows) */ 00423 minleft = MIN2(setup.span.left[0], setup.span.left[1]); 00424 maxright = MAX2(setup.span.right[0], setup.span.right[1]); 00425 break; 00426 00427 case 0x1: 00428 /* only even line written (quad top row) */ 00429 minleft = setup.span.left[0]; 00430 maxright = setup.span.right[0]; 00431 break; 00432 00433 case 0x2: 00434 /* only odd line written (quad bottom row) */ 00435 minleft = setup.span.left[1]; 00436 maxright = setup.span.right[1]; 00437 break; 00438 00439 default: 00440 return; 00441 } 00442 00443 00444 /* OK, we're very likely to need the tile data now. 00445 * clear or finish waiting if needed. 00446 */ 00447 if (spu.cur_ctile_status == TILE_STATUS_GETTING) { 00448 /* wait for mfc_get() to complete */ 00449 //printf("SPU: %u: waiting for ctile\n", spu.init.id); 00450 wait_on_mask(1 << TAG_READ_TILE_COLOR); 00451 spu.cur_ctile_status = TILE_STATUS_CLEAN; 00452 } 00453 else if (spu.cur_ctile_status == TILE_STATUS_CLEAR) { 00454 //printf("SPU %u: clearing C tile %u, %u\n", spu.init.id, setup.tx, setup.ty); 00455 clear_c_tile(&spu.ctile); 00456 spu.cur_ctile_status = TILE_STATUS_DIRTY; 00457 } 00458 ASSERT(spu.cur_ctile_status != TILE_STATUS_DEFINED); 00459 00460 if (spu.read_depth) { 00461 if (spu.cur_ztile_status == TILE_STATUS_GETTING) { 00462 /* wait for mfc_get() to complete */ 00463 //printf("SPU: %u: waiting for ztile\n", spu.init.id); 00464 wait_on_mask(1 << TAG_READ_TILE_Z); 00465 spu.cur_ztile_status = TILE_STATUS_CLEAN; 00466 } 00467 else if (spu.cur_ztile_status == TILE_STATUS_CLEAR) { 00468 //printf("SPU %u: clearing Z tile %u, %u\n", spu.init.id, setup.tx, setup.ty); 00469 clear_z_tile(&spu.ztile); 00470 spu.cur_ztile_status = TILE_STATUS_DIRTY; 00471 } 00472 ASSERT(spu.cur_ztile_status != TILE_STATUS_DEFINED); 00473 } 00474 00475 /* XXX this loop could be moved into the above switch cases and 00476 * calculate_mask() could be simplified a bit... 00477 */ 00478 for (x = block(minleft); x <= block(maxright); x += 2) { 00479 #if 1 00480 emit_quad( x, setup.span.y, calculate_mask( x ) ); 00481 #endif 00482 } 00483 00484 setup.span.y = 0; 00485 setup.span.y_flags = 0;
static boolean setup_sort_vertices | ( | const struct vertex_header * | v0, | |
const struct vertex_header * | v1, | |||
const struct vertex_header * | v2 | |||
) | [static] |
Definition at line 500 of file spu_tri.c.
References setup_stage::cliprect_maxx, setup_stage::cliprect_maxy, setup_stage::cliprect_minx, setup_stage::cliprect_miny, vertex_header::data, edge::dx, edge::dy, setup_stage::ebot, setup_stage::emaj, setup_stage::etop, FALSE, setup_stage::oneoverarea, PIPE_WINDING_CW, TRUE, setup_stage::vmax, setup_stage::vmid, setup_stage::vmin, and setup_stage::vprovoke.
00506 { 00507 00508 #if DEBUG_VERTS 00509 fprintf(stderr, "Triangle:\n"); 00510 print_vertex(v0); 00511 print_vertex(v1); 00512 print_vertex(v2); 00513 #endif 00514 00515 setup.vprovoke = v2; 00516 00517 /* determine bottom to top order of vertices */ 00518 { 00519 float y0 = spu_extract(v0->data[0], 1); 00520 float y1 = spu_extract(v1->data[0], 1); 00521 float y2 = spu_extract(v2->data[0], 1); 00522 if (y0 <= y1) { 00523 if (y1 <= y2) { 00524 /* y0<=y1<=y2 */ 00525 setup.vmin = v0; 00526 setup.vmid = v1; 00527 setup.vmax = v2; 00528 } 00529 else if (y2 <= y0) { 00530 /* y2<=y0<=y1 */ 00531 setup.vmin = v2; 00532 setup.vmid = v0; 00533 setup.vmax = v1; 00534 } 00535 else { 00536 /* y0<=y2<=y1 */ 00537 setup.vmin = v0; 00538 setup.vmid = v2; 00539 setup.vmax = v1; 00540 } 00541 } 00542 else { 00543 if (y0 <= y2) { 00544 /* y1<=y0<=y2 */ 00545 setup.vmin = v1; 00546 setup.vmid = v0; 00547 setup.vmax = v2; 00548 } 00549 else if (y2 <= y1) { 00550 /* y2<=y1<=y0 */ 00551 setup.vmin = v2; 00552 setup.vmid = v1; 00553 setup.vmax = v0; 00554 } 00555 else { 00556 /* y1<=y2<=y0 */ 00557 setup.vmin = v1; 00558 setup.vmid = v2; 00559 setup.vmax = v0; 00560 } 00561 } 00562 } 00563 00564 /* Check if triangle is completely outside the tile bounds */ 00565 if (spu_extract(setup.vmin->data[0], 1) > setup.cliprect_maxy) 00566 return FALSE; 00567 if (spu_extract(setup.vmax->data[0], 1) < setup.cliprect_miny) 00568 return FALSE; 00569 if (spu_extract(setup.vmin->data[0], 0) < setup.cliprect_minx && 00570 spu_extract(setup.vmid->data[0], 0) < setup.cliprect_minx && 00571 spu_extract(setup.vmax->data[0], 0) < setup.cliprect_minx) 00572 return FALSE; 00573 if (spu_extract(setup.vmin->data[0], 0) > setup.cliprect_maxx && 00574 spu_extract(setup.vmid->data[0], 0) > setup.cliprect_maxx && 00575 spu_extract(setup.vmax->data[0], 0) > setup.cliprect_maxx) 00576 return FALSE; 00577 00578 setup.ebot.dx = spu_extract(setup.vmid->data[0], 0) - spu_extract(setup.vmin->data[0], 0); 00579 setup.ebot.dy = spu_extract(setup.vmid->data[0], 1) - spu_extract(setup.vmin->data[0], 1); 00580 setup.emaj.dx = spu_extract(setup.vmax->data[0], 0) - spu_extract(setup.vmin->data[0], 0); 00581 setup.emaj.dy = spu_extract(setup.vmax->data[0], 1) - spu_extract(setup.vmin->data[0], 1); 00582 setup.etop.dx = spu_extract(setup.vmax->data[0], 0) - spu_extract(setup.vmid->data[0], 0); 00583 setup.etop.dy = spu_extract(setup.vmax->data[0], 1) - spu_extract(setup.vmid->data[0], 1); 00584 00585 /* 00586 * Compute triangle's area. Use 1/area to compute partial 00587 * derivatives of attributes later. 00588 * 00589 * The area will be the same as prim->det, but the sign may be 00590 * different depending on how the vertices get sorted above. 00591 * 00592 * To determine whether the primitive is front or back facing we 00593 * use the prim->det value because its sign is correct. 00594 */ 00595 { 00596 const float area = (setup.emaj.dx * setup.ebot.dy - 00597 setup.ebot.dx * setup.emaj.dy); 00598 00599 setup.oneoverarea = 1.0f / area; 00600 /* 00601 _mesa_printf("%s one-over-area %f area %f det %f\n", 00602 __FUNCTION__, setup.oneoverarea, area, prim->det ); 00603 */ 00604 } 00605 00606 #if 0 00607 /* We need to know if this is a front or back-facing triangle for: 00608 * - the GLSL gl_FrontFacing fragment attribute (bool) 00609 * - two-sided stencil test 00610 */ 00611 setup.quad.facing = (prim->det > 0.0) ^ (setup.softpipe->rasterizer->front_winding == PIPE_WINDING_CW); 00612 #endif
static void setup_tri_coefficients | ( | void | ) | [static] |
Compute the setup.coef[] array dadx, dady, a0 values.
Must be called after setup.vmin,vmid,vmax,vprovoke are initialized.
Definition at line 759 of file spu_tri.c.
00764 { 00765 #if 1 00766 uint i; 00767 00768 for (i = 0; i < spu.vertex_info.num_attribs; i++) { 00769 switch (spu.vertex_info.interp_mode[i]) { 00770 case INTERP_NONE: 00771 break; 00772 case INTERP_POS: 00773 /*tri_linear_coeff(i, 2, 3);*/ 00774 /* XXX interp W if PERSPECTIVE... */ 00775 tri_linear_coeff4(i); 00776 break; 00777 case INTERP_CONSTANT: 00778 const_coeff(i); 00779 break; 00780 case INTERP_LINEAR: 00781 tri_linear_coeff4(i); 00782 break; 00783 case INTERP_PERSPECTIVE: 00784 tri_linear_coeff4(i); /* temporary */ 00785 break; 00786 default: 00787 ASSERT(0); 00788 } 00789 } 00790 #else 00791 ASSERT(spu.vertex_info.interp_mode[0] == INTERP_POS); 00792 ASSERT(spu.vertex_info.interp_mode[1] == INTERP_LINEAR ||
static void setup_tri_edges | ( | void | ) | [static] |
Definition at line 795 of file spu_tri.c.
00801 { 00802 float vmin_x = spu_extract(setup.vmin->data[0], 0) + 0.5f; 00803 float vmid_x = spu_extract(setup.vmid->data[0], 0) + 0.5f; 00804 00805 float vmin_y = spu_extract(setup.vmin->data[0], 1) - 0.5f; 00806 float vmid_y = spu_extract(setup.vmid->data[0], 1) - 0.5f; 00807 float vmax_y = spu_extract(setup.vmax->data[0], 1) - 0.5f; 00808 00809 setup.emaj.sy = CEILF(vmin_y); 00810 setup.emaj.lines = (int) CEILF(vmax_y - setup.emaj.sy); 00811 setup.emaj.dxdy = setup.emaj.dx / setup.emaj.dy; 00812 setup.emaj.sx = vmin_x + (setup.emaj.sy - vmin_y) * setup.emaj.dxdy; 00813 00814 setup.etop.sy = CEILF(vmid_y); 00815 setup.etop.lines = (int) CEILF(vmax_y - setup.etop.sy); 00816 setup.etop.dxdy = setup.etop.dx / setup.etop.dy; 00817 setup.etop.sx = vmid_x + (setup.etop.sy - vmid_y) * setup.etop.dxdy; 00818
Render the upper or lower half of a triangle.
Scissoring/cliprect is applied here too.
Definition at line 825 of file spu_tri.c.
References ASSERT, block(), setup_stage::cliprect_maxx, setup_stage::cliprect_maxy, setup_stage::cliprect_minx, setup_stage::cliprect_miny, edge::dxdy, flush_spans(), setup_stage::left, setup_stage::right, setup_stage::span, edge::sx, edge::sy, setup_stage::y, and setup_stage::y_flags.
00833 { 00834 const int minx = setup.cliprect_minx; 00835 const int maxx = setup.cliprect_maxx; 00836 const int miny = setup.cliprect_miny; 00837 const int maxy = setup.cliprect_maxy; 00838 int y, start_y, finish_y; 00839 int sy = (int)eleft->sy; 00840 00841 ASSERT((int)eleft->sy == (int) eright->sy); 00842 00843 /* clip top/bottom */ 00844 start_y = sy; 00845 finish_y = sy + lines; 00846 00847 if (start_y < miny) 00848 start_y = miny; 00849 00850 if (finish_y > maxy) 00851 finish_y = maxy; 00852 00853 start_y -= sy; 00854 finish_y -= sy; 00855 00856 /* 00857 _mesa_printf("%s %d %d\n", __FUNCTION__, start_y, finish_y); 00858 */ 00859 00860 for (y = start_y; y < finish_y; y++) { 00861 00862 /* avoid accumulating adds as floats don't have the precision to 00863 * accurately iterate large triangle edges that way. luckily we 00864 * can just multiply these days. 00865 * 00866 * this is all drowned out by the attribute interpolation anyway. 00867 */ 00868 int left = (int)(eleft->sx + y * eleft->dxdy); 00869 int right = (int)(eright->sx + y * eright->dxdy); 00870 00871 /* clip left/right */ 00872 if (left < minx) 00873 left = minx; 00874 if (right > maxx) 00875 right = maxx; 00876 00877 if (left < right) { 00878 int _y = sy + y; 00879 if (block(_y) != setup.span.y) { 00880 flush_spans(); 00881 setup.span.y = block(_y); 00882 } 00883 00884 setup.span.left[_y&1] = left; 00885 setup.span.right[_y&1] = right; 00886 setup.span.y_flags |= 1<<(_y&1); 00887 } 00888 } 00889 00890 00891 /* save the values so that emaj can be restarted: 00892 */
Draw triangle into tile at (tx, ty) (tile coords) The tile data should have already been fetched.
Definition at line 900 of file spu_tri.c.
00906 { 00907 setup.tx = tx; 00908 setup.ty = ty; 00909 00910 /* set clipping bounds to tile bounds */ 00911 setup.cliprect_minx = tx * TILE_SIZE; 00912 setup.cliprect_miny = ty * TILE_SIZE; 00913 setup.cliprect_maxx = (tx + 1) * TILE_SIZE; 00914 setup.cliprect_maxy = (ty + 1) * TILE_SIZE; 00915 00916 if (!setup_sort_vertices((struct vertex_header *) v0, 00917 (struct vertex_header *) v1, 00918 (struct vertex_header *) v2)) { 00919 return FALSE; /* totally clipped */ 00920 } 00921 00922 setup_tri_coefficients(); 00923 setup_tri_edges(); 00924 00925 setup.span.y = 0; 00926 setup.span.y_flags = 0; 00927 setup.span.right[0] = 0; 00928 setup.span.right[1] = 0; 00929 /* setup.span.z_mode = tri_z_mode( setup.ctx ); */ 00930 00931 /* init_constant_attribs( setup ); */ 00932 00933 if (setup.oneoverarea < 0.0) { 00934 /* emaj on left: 00935 */ 00936 subtriangle( &setup.emaj, &setup.ebot, setup.ebot.lines ); 00937 subtriangle( &setup.emaj, &setup.etop, setup.etop.lines ); 00938 } 00939 else { 00940 /* emaj on right: 00941 */ 00942 subtriangle( &setup.ebot, &setup.emaj, setup.ebot.lines ); 00943 subtriangle( &setup.etop, &setup.emaj, setup.etop.lines ); 00944 }
Compute a0, dadx and dady for a linearly interpolated coefficient, for a triangle.
Definition at line 635 of file spu_tri.c.
00639 { 00640 uint i; 00641 const float *vmin_d = (float *) &setup.vmin->data[slot]; 00642 const float *vmid_d = (float *) &setup.vmid->data[slot]; 00643 const float *vmax_d = (float *) &setup.vmax->data[slot]; 00644 const float x = spu_extract(setup.vmin->data[0], 0) - 0.5f; 00645 const float y = spu_extract(setup.vmin->data[0], 1) - 0.5f; 00646 00647 for (i = firstComp; i < lastComp; i++) { 00648 float botda = vmid_d[i] - vmin_d[i]; 00649 float majda = vmax_d[i] - vmin_d[i]; 00650 float a = setup.ebot.dy * majda - botda * setup.emaj.dy; 00651 float b = setup.emaj.dx * botda - majda * setup.ebot.dx; 00652 00653 ASSERT(slot < PIPE_MAX_SHADER_INPUTS); 00654 00655 setup.coef[slot].dadx.f[i] = a * setup.oneoverarea; 00656 setup.coef[slot].dady.f[i] = b * setup.oneoverarea; 00657 00658 /* calculate a0 as the value which would be sampled for the 00659 * fragment at (0,0), taking into account that we want to sample at 00660 * pixel centers, in other words (0.5, 0.5). 00661 * 00662 * this is neat but unfortunately not a good way to do things for 00663 * triangles with very large values of dadx or dady as it will 00664 * result in the subtraction and re-addition from a0 of a very 00665 * large number, which means we'll end up loosing a lot of the 00666 * fractional bits and precision from a0. the way to fix this is 00667 * to define a0 as the sample at a pixel center somewhere near vmin 00668 * instead - i'll switch to this later. 00669 */ 00670 setup.coef[slot].a0.f[i] = (vmin_d[i] - 00671 (setup.coef[slot].dadx.f[i] * x + 00672 setup.coef[slot].dady.f[i] * y)); 00673 } 00674 00675 /* 00676 _mesa_printf("attr[%d].%c: %f dx:%f dy:%f\n", 00677 slot, "xyzw"[i], 00678 setup.coef[slot].a0[i], 00679 setup.coef[slot].dadx.f[i],
static void tri_linear_coeff4 | ( | uint | slot | ) | [static] |
As above, but interp setup all four vector components.
Definition at line 686 of file spu_tri.c.
00690 { 00691 const vector float vmin_d = setup.vmin->data[slot]; 00692 const vector float vmid_d = setup.vmid->data[slot]; 00693 const vector float vmax_d = setup.vmax->data[slot]; 00694 const vector float xxxx = spu_splats(spu_extract(setup.vmin->data[0], 0) - 0.5f); 00695 const vector float yyyy = spu_splats(spu_extract(setup.vmin->data[0], 1) - 0.5f); 00696 00697 vector float botda = vmid_d - vmin_d; 00698 vector float majda = vmax_d - vmin_d; 00699 00700 vector float a = spu_sub(spu_mul(spu_splats(setup.ebot.dy), majda), 00701 spu_mul(botda, spu_splats(setup.emaj.dy))); 00702 vector float b = spu_sub(spu_mul(spu_splats(setup.emaj.dx), botda), 00703 spu_mul(majda, spu_splats(setup.ebot.dx))); 00704 00705 setup.coef[slot].dadx.v = spu_mul(a, spu_splats(setup.oneoverarea)); 00706 setup.coef[slot].dady.v = spu_mul(b, spu_splats(setup.oneoverarea)); 00707 00708 vector float tempx = spu_mul(setup.coef[slot].dadx.v, xxxx); 00709 vector float tempy = spu_mul(setup.coef[slot].dady.v, yyyy);
struct setup_stage setup [static] |