spu_tri.c File Reference

Include dependency graph for spu_tri.c:

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


Define Documentation

#define CEILF (  )     ((float) (int) ((X) + 0.99999))

Definition at line 64 of file spu_tri.c.

#define DEBUG_VERTS   0

Definition at line 78 of file spu_tri.c.

#define MASK_ALL   0xf

Definition at line 75 of file spu_tri.c.

#define MASK_BOTTOM_LEFT   (1 << QUAD_BOTTOM_LEFT)

Definition at line 73 of file spu_tri.c.

#define MASK_BOTTOM_RIGHT   (1 << QUAD_BOTTOM_RIGHT)

Definition at line 74 of file spu_tri.c.

#define MASK_TOP_LEFT   (1 << QUAD_TOP_LEFT)

Definition at line 71 of file spu_tri.c.

#define MASK_TOP_RIGHT   (1 << QUAD_TOP_RIGHT)

Definition at line 72 of file spu_tri.c.

#define QUAD_BOTTOM_LEFT   2

Definition at line 69 of file spu_tri.c.

#define QUAD_BOTTOM_RIGHT   3

Definition at line 70 of file spu_tri.c.

#define QUAD_TOP_LEFT   0

Definition at line 67 of file spu_tri.c.

#define QUAD_TOP_RIGHT   1

Definition at line 68 of file spu_tri.c.


Typedef Documentation

typedef vector unsigned int mask_t

Triangle rendering within a tile.

Masks are uint[4] vectors with each element being 0 or 0xffffffff

Definition at line 44 of file spu_tri.c.


Function Documentation

static int block ( int  x  )  [static]

Given an X or Y coordinate, return the block/quad coordinate that it belongs to.

Definition at line 383 of file spu_tri.c.

00387 {

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]

Compute a0 for a constant-valued coefficient (GL_FLAT shading).

The value value comes from vertex->data[slot]. The result will be put into setup.coef[slot].a0.

Parameters:
slot which attribute slot

Definition at line 622 of file spu_tri.c.

00626 {
00627    setup.coef[slot].dadx.v = (vector float) {0.0, 0.0, 0.0, 0.0};

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 

static void subtriangle ( struct edge eleft,
struct edge eright,
unsigned  lines 
) [static]

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     */

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.

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    }

static void tri_linear_coeff ( uint  slot,
uint  firstComp,
uint  lastComp 
) [static]

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);


Variable Documentation

struct setup_stage setup [static]

Definition at line 146 of file spu_tri.c.


Generated on Tue Sep 29 06:25:33 2009 for Gallium3D by  doxygen 1.5.4