sp_setup.c File Reference

Include dependency graph for sp_setup.c:

Go to the source code of this file.

Data Structures

struct  edge
 Triangle edge info. More...
struct  setup_context
 Triangle setup info (derived from draw_stage). More...

Defines

#define DEBUG_VERTS   0
 Primitive rasterization/rendering (points, lines, triangles).
#define DEBUG_FRAGS   0
#define WAIT_FOR_COMPLETION(setup)   ((void) 0)
#define CLIP_EMIT_QUAD(setup)   clip_emit_quad( setup, &setup->quad, 0 )
#define EMIT_QUAD(setup, x, y, mask)

Functions

static boolean is_inf_or_nan (float x)
 Test if x is NaN or +/- infinity.
static boolean cull_tri (struct setup_context *setup, float det)
static void quad_clip (struct setup_context *setup, struct quad_header *quad)
 Clip setup->quad against the scissor/surface bounds.
static void clip_emit_quad (struct setup_context *setup, struct quad_header *quad, uint thread)
 Emit a quad (pass to next stage) with clipping.
static void emit_quad (struct setup_context *setup, struct quad_header *quad, uint thread)
 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 void flush_spans (struct setup_context *setup)
 Render a horizontal span of quads.
static boolean setup_sort_vertices (struct setup_context *setup, float det, const float(*v0)[4], const float(*v1)[4], const float(*v2)[4])
 
Returns:
FALSE if coords are inf/nan (cull the tri), TRUE otherwise

static void const_coeff (struct setup_context *setup, struct tgsi_interp_coef *coef, uint vertSlot, uint i)
 Compute a0 for a constant-valued coefficient (GL_FLAT shading).
static void tri_linear_coeff (struct setup_context *setup, struct tgsi_interp_coef *coef, uint vertSlot, uint i)
 Compute a0, dadx and dady for a linearly interpolated coefficient, for a triangle.
static void tri_persp_coeff (struct setup_context *setup, struct tgsi_interp_coef *coef, uint vertSlot, uint i)
 Compute a0, dadx and dady for a perspective-corrected interpolant, for a triangle.
static void setup_fragcoord_coeff (struct setup_context *setup, uint slot)
 Special coefficient setup for gl_FragCoord.
static void setup_tri_coefficients (struct setup_context *setup)
 Compute the setup->coef[] array dadx, dady, a0 values.
static void setup_tri_edges (struct setup_context *setup)
static void subtriangle (struct setup_context *setup, struct edge *eleft, struct edge *eright, unsigned lines)
 Render the upper or lower half of a triangle.
static float calc_det (const float(*v0)[4], const float(*v1)[4], const float(*v2)[4])
 Recalculate prim's determinant.
void setup_tri (struct setup_context *setup, const float(*v0)[4], const float(*v1)[4], const float(*v2)[4])
 Do setup for triangle rasterization, then render the triangle.
static void line_linear_coeff (struct setup_context *setup, struct tgsi_interp_coef *coef, uint vertSlot, uint i)
 Compute a0, dadx and dady for a linearly interpolated coefficient, for a line.
static void line_persp_coeff (struct setup_context *setup, struct tgsi_interp_coef *coef, uint vertSlot, uint i)
 Compute a0, dadx and dady for a perspective-corrected interpolant, for a line.
static boolean setup_line_coefficients (struct setup_context *setup, const float(*v0)[4], const float(*v1)[4])
 Compute the setup->coef[] array dadx, dady, a0 values.
static void plot (struct setup_context *setup, int x, int y)
 Plot a pixel in a line segment.
void setup_line (struct setup_context *setup, const float(*v0)[4], const float(*v1)[4])
 Do setup for line rasterization, then render the line.
static void point_persp_coeff (struct setup_context *setup, const float(*vert)[4], struct tgsi_interp_coef *coef, uint vertSlot, uint i)
void setup_point (struct setup_context *setup, const float(*v0)[4])
 Do setup for point rasterization, then render the point.
void setup_prepare (struct setup_context *setup)
void setup_destroy_context (struct setup_context *setup)
struct setup_contextsetup_create_context (struct softpipe_context *softpipe)
 Create a new primitive setup/render stage.


Define Documentation

#define CLIP_EMIT_QUAD ( setup   )     clip_emit_quad( setup, &setup->quad, 0 )

Definition at line 352 of file sp_setup.c.

#define DEBUG_FRAGS   0

Definition at line 52 of file sp_setup.c.

#define DEBUG_VERTS   0

Primitive rasterization/rendering (points, lines, triangles).

Author:
Keith Whitwell <keith@tungstengraphics.com>

Brian Paul

Definition at line 51 of file sp_setup.c.

#define EMIT_QUAD ( setup,
x,
y,
mask   ) 

Value:

do {\
      setup->quad.input.x0 = x;\
      setup->quad.input.y0 = y;\
      setup->quad.inout.mask = mask;\
      emit_quad( setup, &setup->quad, 0 );\
   } while (0)

Definition at line 407 of file sp_setup.c.

#define WAIT_FOR_COMPLETION ( setup   )     ((void) 0)

Definition at line 251 of file sp_setup.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 420 of file sp_setup.c.

00422 {
00423    return x & ~1;

static float calc_det ( const float *  v0[4],
const float *  v1[4],
const float *  v2[4] 
) [static]

Recalculate prim's determinant.

This is needed as we don't have get this information through the vbuf_render interface & we must calculate it here.

Definition at line 917 of file sp_setup.c.

00921 {
00922    /* edge vectors e = v0 - v2, f = v1 - v2 */
00923    const float ex = v0[0][0] - v2[0][0];
00924    const float ey = v0[0][1] - v2[0][1];
00925    const float fx = v1[0][0] - v2[0][0];
00926    const float fy = v1[0][1] - v2[0][1];
00927 
00928    /* det = cross(e,f).z */
00929    return ex * fy - ey * fx;

static void clip_emit_quad ( struct setup_context setup,
struct quad_header quad,
uint  thread 
) [static]

Emit a quad (pass to next stage) with clipping.

Definition at line 323 of file sp_setup.c.

References softpipe_context::first, quad_header::inout, quad_header_inout::mask, softpipe_context::quad, quad_clip(), quad_stage::run, and setup_context::softpipe.

00325 {
00326    quad_clip( setup, quad );
00327    if (quad->inout.mask) {
00328       struct softpipe_context *sp = setup->softpipe;
00329 
00330       sp->quad[thread].first->run( sp->quad[thread].first, quad );
00331    }

static void const_coeff ( struct setup_context setup,
struct tgsi_interp_coef coef,
uint  vertSlot,
uint  i 
) [static]

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

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

Parameters:
slot which attribute slot
i which component of the slot (0..3)

Definition at line 616 of file sp_setup.c.

00620 {
00621    assert(i <= 3);
00622 
00623    coef->dadx[i] = 0;
00624    coef->dady[i] = 0;
00625 
00626    /* need provoking vertex info!
00627     */
00628    coef->a0[i] = setup->vprovoke[vertSlot][i];

static boolean cull_tri ( struct setup_context setup,
float  det 
) [static]

Definition at line 267 of file sp_setup.c.

References FALSE, PIPE_WINDING_CCW, PIPE_WINDING_CW, TRUE, and setup_context::winding.

00270 {
00271    if (det != 0) 
00272    {   
00273       /* if (det < 0 then Z points toward camera and triangle is 
00274        * counter-clockwise winding.
00275        */
00276       unsigned winding = (det < 0) ? PIPE_WINDING_CCW : PIPE_WINDING_CW;
00277       
00278       if ((winding & setup->winding) == 0) 
00279          return FALSE;
00280    }
00281 
00282    /* Culled:
00283     */
00284    return TRUE;

static void emit_quad ( struct setup_context setup,
struct quad_header quad,
uint  thread 
) [static]

Emit a quad (pass to next stage).

No clipping is done.

Definition at line 360 of file sp_setup.c.

References softpipe_context::first, quad_header::inout, quad_header_inout::mask, softpipe_context::quad, quad_stage::run, and setup_context::softpipe.

00362 {
00363    struct softpipe_context *sp = setup->softpipe;
00364 #if DEBUG_FRAGS
00365    uint mask = quad->inout.mask;
00366 #endif
00367 
00368 #if DEBUG_FRAGS
00369    if (mask & 1) setup->numFragsEmitted++;
00370    if (mask & 2) setup->numFragsEmitted++;
00371    if (mask & 4) setup->numFragsEmitted++;
00372    if (mask & 8) setup->numFragsEmitted++;
00373 #endif
00374    sp->quad[thread].first->run( sp->quad[thread].first, quad );
00375 #if DEBUG_FRAGS
00376    mask = quad->inout.mask;
00377    if (mask & 1) setup->numFragsWritten++;
00378    if (mask & 2) setup->numFragsWritten++;
00379    if (mask & 4) setup->numFragsWritten++;
00380    if (mask & 8) setup->numFragsWritten++;
00381 #endif

static void flush_spans ( struct setup_context setup  )  [static]

Render a horizontal span of quads.

Definition at line 429 of file sp_setup.c.

00431 {
00432    const int xleft0 = setup->span.left[0];
00433    const int xleft1 = setup->span.left[1];
00434    const int xright0 = setup->span.right[0];
00435    const int xright1 = setup->span.right[1];
00436    int minleft, maxright;
00437    int x;
00438 
00439    switch (setup->span.y_flags) {
00440    case 0x3:
00441       /* both odd and even lines written (both quad rows) */
00442       minleft = block(MIN2(xleft0, xleft1));
00443       maxright = block(MAX2(xright0, xright1));
00444       for (x = minleft; x <= maxright; x += 2) {
00445          /* determine which of the four pixels is inside the span bounds */
00446          uint mask = 0x0;
00447          if (x >= xleft0 && x < xright0)
00448             mask |= MASK_TOP_LEFT;
00449          if (x >= xleft1 && x < xright1)
00450             mask |= MASK_BOTTOM_LEFT;
00451          if (x+1 >= xleft0 && x+1 < xright0)
00452             mask |= MASK_TOP_RIGHT;
00453          if (x+1 >= xleft1 && x+1 < xright1)
00454             mask |= MASK_BOTTOM_RIGHT;
00455          EMIT_QUAD( setup, x, setup->span.y, mask );
00456       }
00457       break;
00458 
00459    case 0x1:
00460       /* only even line written (quad top row) */
00461       minleft = block(xleft0);
00462       maxright = block(xright0);
00463       for (x = minleft; x <= maxright; x += 2) {
00464          uint mask = 0x0;
00465          if (x >= xleft0 && x < xright0)
00466             mask |= MASK_TOP_LEFT;
00467          if (x+1 >= xleft0 && x+1 < xright0)
00468             mask |= MASK_TOP_RIGHT;
00469          EMIT_QUAD( setup, x, setup->span.y, mask );
00470       }
00471       break;
00472 
00473    case 0x2:
00474       /* only odd line written (quad bottom row) */
00475       minleft = block(xleft1);
00476       maxright = block(xright1);
00477       for (x = minleft; x <= maxright; x += 2) {
00478          uint mask = 0x0;
00479          if (x >= xleft1 && x < xright1)
00480             mask |= MASK_BOTTOM_LEFT;
00481          if (x+1 >= xleft1 && x+1 < xright1)
00482             mask |= MASK_BOTTOM_RIGHT;
00483          EMIT_QUAD( setup, x, setup->span.y, mask );
00484       }
00485       break;
00486 
00487    default:
00488       return;
00489    }
00490 
00491    setup->span.y = 0;
00492    setup->span.y_flags = 0;
00493    setup->span.right[0] = 0;
00494    setup->span.right[1] = 0;

static boolean is_inf_or_nan ( float  x  )  [static]

Test if x is NaN or +/- infinity.

Definition at line 259 of file sp_setup.c.

References fi::f, and fi::i.

00261 {
00262    union fi tmp;
00263    tmp.f = x;
00264    return !(int)((unsigned int)((tmp.i & 0x7fffffff)-0x7f800000) >> 31);

static void line_linear_coeff ( struct setup_context setup,
struct tgsi_interp_coef coef,
uint  vertSlot,
uint  i 
) [static]

Compute a0, dadx and dady for a linearly interpolated coefficient, for a line.

Definition at line 1011 of file sp_setup.c.

References tgsi_interp_coef::a0, tgsi_interp_coef::dadx, tgsi_interp_coef::dady, edge::dx, edge::dy, setup_context::emaj, setup_context::oneoverarea, setup_context::vmax, and setup_context::vmin.

01015 {
01016    const float da = setup->vmax[vertSlot][i] - setup->vmin[vertSlot][i];
01017    const float dadx = da * setup->emaj.dx * setup->oneoverarea;
01018    const float dady = da * setup->emaj.dy * setup->oneoverarea;
01019    coef->dadx[i] = dadx;
01020    coef->dady[i] = dady;
01021    coef->a0[i] = (setup->vmin[vertSlot][i] -
01022                   (dadx * (setup->vmin[0][0] - 0.5f) +
01023                    dady * (setup->vmin[0][1] - 0.5f)));

static void line_persp_coeff ( struct setup_context setup,
struct tgsi_interp_coef coef,
uint  vertSlot,
uint  i 
) [static]

Compute a0, dadx and dady for a perspective-corrected interpolant, for a line.

Definition at line 1031 of file sp_setup.c.

References tgsi_interp_coef::a0, tgsi_interp_coef::dadx, tgsi_interp_coef::dady, edge::dx, edge::dy, setup_context::emaj, setup_context::oneoverarea, setup_context::vmax, and setup_context::vmin.

01035 {
01036    /* XXX double-check/verify this arithmetic */
01037    const float a0 = setup->vmin[vertSlot][i] * setup->vmin[0][3];
01038    const float a1 = setup->vmax[vertSlot][i] * setup->vmax[0][3];
01039    const float da = a1 - a0;
01040    const float dadx = da * setup->emaj.dx * setup->oneoverarea;
01041    const float dady = da * setup->emaj.dy * setup->oneoverarea;
01042    coef->dadx[i] = dadx;
01043    coef->dady[i] = dady;
01044    coef->a0[i] = (setup->vmin[vertSlot][i] -
01045                   (dadx * (setup->vmin[0][0] - 0.5f) +
01046                    dady * (setup->vmin[0][1] - 0.5f)));

static void plot ( struct setup_context setup,
int  x,
int  y 
) [static]

Plot a pixel in a line segment.

Definition at line 1124 of file sp_setup.c.

References CLIP_EMIT_QUAD, quad_header::inout, quad_header::input, quad_header_inout::mask, setup_context::quad, quad_header_input::x0, and quad_header_input::y0.

01126 {
01127    const int iy = y & 1;
01128    const int ix = x & 1;
01129    const int quadX = x - ix;
01130    const int quadY = y - iy;
01131    const int mask = (1 << ix) << (2 * iy);
01132 
01133    if (quadX != setup->quad.input.x0 ||
01134        quadY != setup->quad.input.y0)
01135    {
01136       /* flush prev quad, start new quad */
01137 
01138       if (setup->quad.input.x0 != -1)
01139          CLIP_EMIT_QUAD(setup);
01140 
01141       setup->quad.input.x0 = quadX;
01142       setup->quad.input.y0 = quadY;
01143       setup->quad.inout.mask = 0x0;
01144    }
01145 
01146    setup->quad.inout.mask |= mask;

static void point_persp_coeff ( struct setup_context setup,
const float *  vert[4],
struct tgsi_interp_coef coef,
uint  vertSlot,
uint  i 
) [static]

Definition at line 1268 of file sp_setup.c.

References tgsi_interp_coef::a0, assert, tgsi_interp_coef::dadx, and tgsi_interp_coef::dady.

01273 {
01274    assert(i <= 3);
01275    coef->dadx[i] = 0.0F;
01276    coef->dady[i] = 0.0F;
01277    coef->a0[i] = vert[vertSlot][i] * vert[0][3];

static void quad_clip ( struct setup_context setup,
struct quad_header quad 
) [static]

Clip setup->quad against the scissor/surface bounds.

Definition at line 292 of file sp_setup.c.

References softpipe_context::cliprect, quad_header::inout, quad_header::input, quad_header_inout::mask, MASK_BOTTOM_LEFT, MASK_BOTTOM_RIGHT, MASK_TOP_LEFT, MASK_TOP_RIGHT, pipe_scissor_state::maxx, pipe_scissor_state::maxy, pipe_scissor_state::minx, pipe_scissor_state::miny, setup_context::softpipe, quad_header_input::x0, and quad_header_input::y0.

00294 {
00295    const struct pipe_scissor_state *cliprect = &setup->softpipe->cliprect;
00296    const int minx = (int) cliprect->minx;
00297    const int maxx = (int) cliprect->maxx;
00298    const int miny = (int) cliprect->miny;
00299    const int maxy = (int) cliprect->maxy;
00300 
00301    if (quad->input.x0 >= maxx ||
00302        quad->input.y0 >= maxy ||
00303        quad->input.x0 + 1 < minx ||
00304        quad->input.y0 + 1 < miny) {
00305       /* totally clipped */
00306       quad->inout.mask = 0x0;
00307       return;
00308    }
00309    if (quad->input.x0 < minx)
00310       quad->inout.mask &= (MASK_BOTTOM_RIGHT | MASK_TOP_RIGHT);
00311    if (quad->input.y0 < miny)
00312       quad->inout.mask &= (MASK_BOTTOM_LEFT | MASK_BOTTOM_RIGHT);
00313    if (quad->input.x0 == maxx - 1)
00314       quad->inout.mask &= (MASK_BOTTOM_LEFT | MASK_TOP_LEFT);
00315    if (quad->input.y0 == maxy - 1)
00316       quad->inout.mask &= (MASK_TOP_LEFT | MASK_TOP_RIGHT);

struct setup_context* setup_create_context ( struct softpipe_context softpipe  )  [read]

Create a new primitive setup/render stage.

Definition at line 1538 of file sp_setup.c.

01540 {
01541    struct setup_context *setup = CALLOC_STRUCT(setup_context);
01542 #if SP_NUM_QUAD_THREADS > 1
01543    uint i;
01544 #endif
01545 
01546    setup->softpipe = softpipe;
01547 
01548    setup->quad.coef = setup->coef;
01549    setup->quad.posCoef = &setup->posCoef;
01550 
01551 #if SP_NUM_QUAD_THREADS > 1
01552    setup->que.first = 0;
01553    setup->que.last = 0;
01554    pipe_mutex_init( setup->que.que_mutex );
01555    pipe_condvar_init( setup->que.que_notfull_condvar );
01556    pipe_condvar_init( setup->que.que_notempty_condvar );
01557    setup->que.jobs_added = 0;
01558    setup->que.jobs_done = 0;
01559    pipe_condvar_init( setup->que.que_done_condvar );
01560    for (i = 0; i < SP_NUM_QUAD_THREADS; i++) {
01561       setup->threads[i].setup = setup;
01562       setup->threads[i].id = i;
01563       setup->threads[i].handle = pipe_thread_create( quad_thread, &setup->threads[i] );
01564    }
01565 #endif
01566 
01567    return setup;

void setup_destroy_context ( struct setup_context setup  ) 

Definition at line 1529 of file sp_setup.c.

References FREE.

01531 {
01532    FREE( setup );

static void setup_fragcoord_coeff ( struct setup_context setup,
uint  slot 
) [static]

Special coefficient setup for gl_FragCoord.

X and Y are trivial, though Y has to be inverted for OpenGL. Z and W are copied from posCoef which should have already been computed. We could do a bit less work if we'd examine gl_FragCoord's swizzle mask.

Definition at line 725 of file sp_setup.c.

References tgsi_interp_coef::a0, setup_context::coef, tgsi_interp_coef::dadx, tgsi_interp_coef::dady, softpipe_context::framebuffer, pipe_framebuffer_state::height, pipe_rasterizer_state::origin_lower_left, setup_context::posCoef, softpipe_context::rasterizer, and setup_context::softpipe.

00727 {
00728    /*X*/
00729    setup->coef[slot].a0[0] = 0;
00730    setup->coef[slot].dadx[0] = 1.0;
00731    setup->coef[slot].dady[0] = 0.0;
00732    /*Y*/
00733    if (setup->softpipe->rasterizer->origin_lower_left) {
00734       /* y=0=bottom */
00735       const int winHeight = setup->softpipe->framebuffer.height;
00736       setup->coef[slot].a0[1] = (float) (winHeight - 1);
00737       setup->coef[slot].dady[1] = -1.0;
00738    }
00739    else {
00740       /* y=0=top */
00741       setup->coef[slot].a0[1] = 0.0;
00742       setup->coef[slot].dady[1] = 1.0;
00743    }
00744    setup->coef[slot].dadx[1] = 0.0;
00745    /*Z*/
00746    setup->coef[slot].a0[2] = setup->posCoef.a0[2];
00747    setup->coef[slot].dadx[2] = setup->posCoef.dadx[2];
00748    setup->coef[slot].dady[2] = setup->posCoef.dady[2];
00749    /*W*/
00750    setup->coef[slot].a0[3] = setup->posCoef.a0[3];
00751    setup->coef[slot].dadx[3] = setup->posCoef.dadx[3];
00752    setup->coef[slot].dady[3] = setup->posCoef.dady[3];

void setup_line ( struct setup_context setup,
const float *  v0[4],
const float *  v1[4] 
)

Do setup for line rasterization, then render the line.

Single-pixel width, no stipple, etc. We rely on the 'draw' module to handle stippling and wide lines.

Definition at line 1155 of file sp_setup.c.

References assert, CLIP_EMIT_QUAD, quad_header_input::coverage, debug_printf(), quad_header::inout, quad_header::input, quad_header_inout::mask, softpipe_context::no_rast, plot(), quad_header_input::prim, PRIM_LINE, setup_context::quad, setup_line_coefficients(), setup_context::softpipe, WAIT_FOR_COMPLETION, quad_header_input::x0, and quad_header_input::y0.

01159 {
01160    int x0 = (int) v0[0][0];
01161    int x1 = (int) v1[0][0];
01162    int y0 = (int) v0[0][1];
01163    int y1 = (int) v1[0][1];
01164    int dx = x1 - x0;
01165    int dy = y1 - y0;
01166    int xstep, ystep;
01167 
01168 #if DEBUG_VERTS
01169    debug_printf("Setup line:\n");
01170    print_vertex(setup, v0);
01171    print_vertex(setup, v1);
01172 #endif
01173 
01174    if (setup->softpipe->no_rast)
01175       return;
01176 
01177    if (dx == 0 && dy == 0)
01178       return;
01179 
01180    if (!setup_line_coefficients(setup, v0, v1))
01181       return;
01182 
01183    assert(v0[0][0] < 1.0e9);
01184    assert(v0[0][1] < 1.0e9);
01185    assert(v1[0][0] < 1.0e9);
01186    assert(v1[0][1] < 1.0e9);
01187 
01188    if (dx < 0) {
01189       dx = -dx;   /* make positive */
01190       xstep = -1;
01191    }
01192    else {
01193       xstep = 1;
01194    }
01195 
01196    if (dy < 0) {
01197       dy = -dy;   /* make positive */
01198       ystep = -1;
01199    }
01200    else {
01201       ystep = 1;
01202    }
01203 
01204    assert(dx >= 0);
01205    assert(dy >= 0);
01206 
01207    setup->quad.input.x0 = setup->quad.input.y0 = -1;
01208    setup->quad.inout.mask = 0x0;
01209    setup->quad.input.prim = PRIM_LINE;
01210    /* XXX temporary: set coverage to 1.0 so the line appears
01211     * if AA mode happens to be enabled.
01212     */
01213    setup->quad.input.coverage[0] =
01214    setup->quad.input.coverage[1] =
01215    setup->quad.input.coverage[2] =
01216    setup->quad.input.coverage[3] = 1.0;
01217 
01218    if (dx > dy) {
01219       /*** X-major line ***/
01220       int i;
01221       const int errorInc = dy + dy;
01222       int error = errorInc - dx;
01223       const int errorDec = error - dx;
01224 
01225       for (i = 0; i < dx; i++) {
01226          plot(setup, x0, y0);
01227 
01228          x0 += xstep;
01229          if (error < 0) {
01230             error += errorInc;
01231          }
01232          else {
01233             error += errorDec;
01234             y0 += ystep;
01235          }
01236       }
01237    }
01238    else {
01239       /*** Y-major line ***/
01240       int i;
01241       const int errorInc = dx + dx;
01242       int error = errorInc - dy;
01243       const int errorDec = error - dy;
01244 
01245       for (i = 0; i < dy; i++) {
01246          plot(setup, x0, y0);
01247 
01248          y0 += ystep;
01249          if (error < 0) {
01250             error += errorInc;
01251          }
01252          else {
01253             error += errorDec;
01254             x0 += xstep;
01255          }
01256       }
01257    }
01258 
01259    /* draw final quad */
01260    if (setup->quad.inout.mask) {
01261       CLIP_EMIT_QUAD(setup);
01262    }
01263 
01264    WAIT_FOR_COMPLETION(setup);

static boolean setup_line_coefficients ( struct setup_context setup,
const float *  v0[4],
const float *  v1[4] 
) [static]

Compute the setup->coef[] array dadx, dady, a0 values.

Must be called after setup->vmin,vmax are initialized.

Definition at line 1054 of file sp_setup.c.

References tgsi_interp_coef::a0, assert, vertex_info::attrib, setup_context::coef, const_coeff(), tgsi_interp_coef::dadx, tgsi_interp_coef::dady, edge::dx, edge::dy, setup_context::emaj, quad_header_input::facing, FALSE, softpipe_context::fs, sp_fragment_shader::info, quad_header::input, tgsi_shader_info::input_semantic_name, INTERP_CONSTANT, INTERP_LINEAR, vertex_info::interp_mode, INTERP_PERSPECTIVE, INTERP_POS, is_inf_or_nan(), line_linear_coeff(), line_persp_coeff(), tgsi_shader_info::num_inputs, setup_context::oneoverarea, setup_context::posCoef, setup_context::quad, setup_fragcoord_coeff(), setup_context::softpipe, softpipe_get_vertex_info(), vertex_info::src_index, TGSI_SEMANTIC_FOG, TRUE, setup_context::vmax, setup_context::vmin, and setup_context::vprovoke.

01058 {
01059    struct softpipe_context *softpipe = setup->softpipe;
01060    const struct sp_fragment_shader *spfs = softpipe->fs;
01061    const struct vertex_info *vinfo = softpipe_get_vertex_info(softpipe);
01062    uint fragSlot;
01063    float area;
01064 
01065    /* use setup->vmin, vmax to point to vertices */
01066    setup->vprovoke = v1;
01067    setup->vmin = v0;
01068    setup->vmax = v1;
01069 
01070    setup->emaj.dx = setup->vmax[0][0] - setup->vmin[0][0];
01071    setup->emaj.dy = setup->vmax[0][1] - setup->vmin[0][1];
01072 
01073    /* NOTE: this is not really area but something proportional to it */
01074    area = setup->emaj.dx * setup->emaj.dx + setup->emaj.dy * setup->emaj.dy;
01075    if (area == 0.0f || is_inf_or_nan(area))
01076       return FALSE;
01077    setup->oneoverarea = 1.0f / area;
01078 
01079    /* z and w are done by linear interpolation:
01080     */
01081    line_linear_coeff(setup, &setup->posCoef, 0, 2);
01082    line_linear_coeff(setup, &setup->posCoef, 0, 3);
01083 
01084    /* setup interpolation for all the remaining attributes:
01085     */
01086    for (fragSlot = 0; fragSlot < spfs->info.num_inputs; fragSlot++) {
01087       const uint vertSlot = vinfo->attrib[fragSlot].src_index;
01088       uint j;
01089 
01090       switch (vinfo->attrib[fragSlot].interp_mode) {
01091       case INTERP_CONSTANT:
01092          for (j = 0; j < NUM_CHANNELS; j++)
01093             const_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
01094          break;
01095       case INTERP_LINEAR:
01096          for (j = 0; j < NUM_CHANNELS; j++)
01097             line_linear_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
01098          break;
01099       case INTERP_PERSPECTIVE:
01100          for (j = 0; j < NUM_CHANNELS; j++)
01101             line_persp_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
01102          break;
01103       case INTERP_POS:
01104          setup_fragcoord_coeff(setup, fragSlot);
01105          break;
01106       default:
01107          assert(0);
01108       }
01109 
01110       if (spfs->info.input_semantic_name[fragSlot] == TGSI_SEMANTIC_FOG) {
01111          /* FOG.y = front/back facing  XXX fix this */
01112          setup->coef[fragSlot].a0[1] = 1.0f - setup->quad.input.facing;
01113          setup->coef[fragSlot].dadx[1] = 0.0;
01114          setup->coef[fragSlot].dady[1] = 0.0;
01115       }
01116    }
01117    return TRUE;

void setup_point ( struct setup_context setup,
const float *  v0[4] 
)

Do setup for point rasterization, then render the point.

Round or square points... XXX could optimize a lot for 1-pixel points.

Definition at line 1286 of file sp_setup.c.

References tgsi_interp_coef::a0, assert, vertex_info::attrib, block(), CLIP_EMIT_QUAD, setup_context::coef, const_coeff(), quad_header_input::coverage, tgsi_interp_coef::dadx, tgsi_interp_coef::dady, debug_printf(), quad_header_input::facing, softpipe_context::fs, sp_fragment_shader::info, quad_header::inout, quad_header::input, tgsi_shader_info::input_semantic_name, INTERP_CONSTANT, INTERP_LINEAR, vertex_info::interp_mode, INTERP_PERSPECTIVE, INTERP_POS, quad_header_inout::mask, MASK_BOTTOM_LEFT, MASK_BOTTOM_RIGHT, MASK_TOP_LEFT, MASK_TOP_RIGHT, MAX2, MIN2, softpipe_context::no_rast, tgsi_shader_info::num_inputs, point_persp_coeff(), pipe_rasterizer_state::point_size, pipe_rasterizer_state::point_smooth, setup_context::posCoef, quad_header_input::prim, PRIM_POINT, softpipe_context::psize_slot, setup_context::quad, QUAD_BOTTOM_LEFT, QUAD_BOTTOM_RIGHT, QUAD_TOP_LEFT, QUAD_TOP_RIGHT, softpipe_context::rasterizer, setup_fragcoord_coeff(), setup_context::softpipe, softpipe_get_vertex_info(), vertex_info::src_index, TGSI_SEMANTIC_FOG, setup_context::vprovoke, WAIT_FOR_COMPLETION, quad_header_input::x0, and quad_header_input::y0.

01289 {
01290    struct softpipe_context *softpipe = setup->softpipe;
01291    const struct sp_fragment_shader *spfs = softpipe->fs;
01292    const int sizeAttr = setup->softpipe->psize_slot;
01293    const float size
01294       = sizeAttr > 0 ? v0[sizeAttr][0]
01295       : setup->softpipe->rasterizer->point_size;
01296    const float halfSize = 0.5F * size;
01297    const boolean round = (boolean) setup->softpipe->rasterizer->point_smooth;
01298    const float x = v0[0][0];  /* Note: data[0] is always position */
01299    const float y = v0[0][1];
01300    const struct vertex_info *vinfo = softpipe_get_vertex_info(softpipe);
01301    uint fragSlot;
01302 
01303 #if DEBUG_VERTS
01304    debug_printf("Setup point:\n");
01305    print_vertex(setup, v0);
01306 #endif
01307 
01308    if (softpipe->no_rast)
01309       return;
01310 
01311    /* For points, all interpolants are constant-valued.
01312     * However, for point sprites, we'll need to setup texcoords appropriately.
01313     * XXX: which coefficients are the texcoords???
01314     * We may do point sprites as textured quads...
01315     *
01316     * KW: We don't know which coefficients are texcoords - ultimately
01317     * the choice of what interpolation mode to use for each attribute
01318     * should be determined by the fragment program, using
01319     * per-attribute declaration statements that include interpolation
01320     * mode as a parameter.  So either the fragment program will have
01321     * to be adjusted for pointsprite vs normal point behaviour, or
01322     * otherwise a special interpolation mode will have to be defined
01323     * which matches the required behaviour for point sprites.  But -
01324     * the latter is not a feature of normal hardware, and as such
01325     * probably should be ruled out on that basis.
01326     */
01327    setup->vprovoke = v0;
01328 
01329    /* setup Z, W */
01330    const_coeff(setup, &setup->posCoef, 0, 2);
01331    const_coeff(setup, &setup->posCoef, 0, 3);
01332 
01333    for (fragSlot = 0; fragSlot < spfs->info.num_inputs; fragSlot++) {
01334       const uint vertSlot = vinfo->attrib[fragSlot].src_index;
01335       uint j;
01336 
01337       switch (vinfo->attrib[fragSlot].interp_mode) {
01338       case INTERP_CONSTANT:
01339          /* fall-through */
01340       case INTERP_LINEAR:
01341          for (j = 0; j < NUM_CHANNELS; j++)
01342             const_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
01343          break;
01344       case INTERP_PERSPECTIVE:
01345          for (j = 0; j < NUM_CHANNELS; j++)
01346             point_persp_coeff(setup, setup->vprovoke,
01347                               &setup->coef[fragSlot], vertSlot, j);
01348          break;
01349       case INTERP_POS:
01350          setup_fragcoord_coeff(setup, fragSlot);
01351          break;
01352       default:
01353          assert(0);
01354       }
01355 
01356       if (spfs->info.input_semantic_name[fragSlot] == TGSI_SEMANTIC_FOG) {
01357          /* FOG.y = front/back facing  XXX fix this */
01358          setup->coef[fragSlot].a0[1] = 1.0f - setup->quad.input.facing;
01359          setup->coef[fragSlot].dadx[1] = 0.0;
01360          setup->coef[fragSlot].dady[1] = 0.0;
01361       }
01362    }
01363 
01364    setup->quad.input.prim = PRIM_POINT;
01365 
01366    if (halfSize <= 0.5 && !round) {
01367       /* special case for 1-pixel points */
01368       const int ix = ((int) x) & 1;
01369       const int iy = ((int) y) & 1;
01370       setup->quad.input.x0 = (int) x - ix;
01371       setup->quad.input.y0 = (int) y - iy;
01372       setup->quad.inout.mask = (1 << ix) << (2 * iy);
01373       CLIP_EMIT_QUAD(setup);
01374    }
01375    else {
01376       if (round) {
01377          /* rounded points */
01378          const int ixmin = block((int) (x - halfSize));
01379          const int ixmax = block((int) (x + halfSize));
01380          const int iymin = block((int) (y - halfSize));
01381          const int iymax = block((int) (y + halfSize));
01382          const float rmin = halfSize - 0.7071F;  /* 0.7071 = sqrt(2)/2 */
01383          const float rmax = halfSize + 0.7071F;
01384          const float rmin2 = MAX2(0.0F, rmin * rmin);
01385          const float rmax2 = rmax * rmax;
01386          const float cscale = 1.0F / (rmax2 - rmin2);
01387          int ix, iy;
01388 
01389          for (iy = iymin; iy <= iymax; iy += 2) {
01390             for (ix = ixmin; ix <= ixmax; ix += 2) {
01391                float dx, dy, dist2, cover;
01392 
01393                setup->quad.inout.mask = 0x0;
01394 
01395                dx = (ix + 0.5f) - x;
01396                dy = (iy + 0.5f) - y;
01397                dist2 = dx * dx + dy * dy;
01398                if (dist2 <= rmax2) {
01399                   cover = 1.0F - (dist2 - rmin2) * cscale;
01400                   setup->quad.input.coverage[QUAD_TOP_LEFT] = MIN2(cover, 1.0f);
01401                   setup->quad.inout.mask |= MASK_TOP_LEFT;
01402                }
01403 
01404                dx = (ix + 1.5f) - x;
01405                dy = (iy + 0.5f) - y;
01406                dist2 = dx * dx + dy * dy;
01407                if (dist2 <= rmax2) {
01408                   cover = 1.0F - (dist2 - rmin2) * cscale;
01409                   setup->quad.input.coverage[QUAD_TOP_RIGHT] = MIN2(cover, 1.0f);
01410                   setup->quad.inout.mask |= MASK_TOP_RIGHT;
01411                }
01412 
01413                dx = (ix + 0.5f) - x;
01414                dy = (iy + 1.5f) - y;
01415                dist2 = dx * dx + dy * dy;
01416                if (dist2 <= rmax2) {
01417                   cover = 1.0F - (dist2 - rmin2) * cscale;
01418                   setup->quad.input.coverage[QUAD_BOTTOM_LEFT] = MIN2(cover, 1.0f);
01419                   setup->quad.inout.mask |= MASK_BOTTOM_LEFT;
01420                }
01421 
01422                dx = (ix + 1.5f) - x;
01423                dy = (iy + 1.5f) - y;
01424                dist2 = dx * dx + dy * dy;
01425                if (dist2 <= rmax2) {
01426                   cover = 1.0F - (dist2 - rmin2) * cscale;
01427                   setup->quad.input.coverage[QUAD_BOTTOM_RIGHT] = MIN2(cover, 1.0f);
01428                   setup->quad.inout.mask |= MASK_BOTTOM_RIGHT;
01429                }
01430 
01431                if (setup->quad.inout.mask) {
01432                   setup->quad.input.x0 = ix;
01433                   setup->quad.input.y0 = iy;
01434                   CLIP_EMIT_QUAD(setup);
01435                }
01436             }
01437          }
01438       }
01439       else {
01440          /* square points */
01441          const int xmin = (int) (x + 0.75 - halfSize);
01442          const int ymin = (int) (y + 0.25 - halfSize);
01443          const int xmax = xmin + (int) size;
01444          const int ymax = ymin + (int) size;
01445          /* XXX could apply scissor to xmin,ymin,xmax,ymax now */
01446          const int ixmin = block(xmin);
01447          const int ixmax = block(xmax - 1);
01448          const int iymin = block(ymin);
01449          const int iymax = block(ymax - 1);
01450          int ix, iy;
01451 
01452          /*
01453          debug_printf("(%f, %f) -> X:%d..%d Y:%d..%d\n", x, y, xmin, xmax,ymin,ymax);
01454          */
01455          for (iy = iymin; iy <= iymax; iy += 2) {
01456             uint rowMask = 0xf;
01457             if (iy < ymin) {
01458                /* above the top edge */
01459                rowMask &= (MASK_BOTTOM_LEFT | MASK_BOTTOM_RIGHT);
01460             }
01461             if (iy + 1 >= ymax) {
01462                /* below the bottom edge */
01463                rowMask &= (MASK_TOP_LEFT | MASK_TOP_RIGHT);
01464             }
01465 
01466             for (ix = ixmin; ix <= ixmax; ix += 2) {
01467                uint mask = rowMask;
01468 
01469                if (ix < xmin) {
01470                   /* fragment is past left edge of point, turn off left bits */
01471                   mask &= (MASK_BOTTOM_RIGHT | MASK_TOP_RIGHT);
01472                }
01473                if (ix + 1 >= xmax) {
01474                   /* past the right edge */
01475                   mask &= (MASK_BOTTOM_LEFT | MASK_TOP_LEFT);
01476                }
01477 
01478                setup->quad.inout.mask = mask;
01479                setup->quad.input.x0 = ix;
01480                setup->quad.input.y0 = iy;
01481                CLIP_EMIT_QUAD(setup);
01482             }
01483          }
01484       }
01485    }
01486 
01487    WAIT_FOR_COMPLETION(setup);

void setup_prepare ( struct setup_context setup  ) 

Definition at line 1489 of file sp_setup.c.

References quad_stage::begin, pipe_framebuffer_state::cbufs, pipe_rasterizer_state::cull_mode, softpipe_context::dirty, softpipe_context::draw, draw_num_vs_outputs(), pipe_rasterizer_state::fill_ccw, pipe_rasterizer_state::fill_cw, softpipe_context::first, softpipe_context::framebuffer, quad_header::nr_attrs, pipe_framebuffer_state::num_cbufs, PIPE_POLYGON_MODE_FILL, PIPE_PRIM_TRIANGLES, PIPE_SURFACE_STATUS_DEFINED, PIPE_WINDING_NONE, softpipe_context::quad, setup_context::quad, softpipe_context::rasterizer, softpipe_context::reduced_api_prim, setup_context::softpipe, softpipe_update_derived(), SP_NUM_QUAD_THREADS, pipe_surface::status, setup_context::winding, and pipe_framebuffer_state::zsbuf.

01491 {
01492    struct softpipe_context *sp = setup->softpipe;
01493    unsigned i;
01494 
01495    if (sp->dirty) {
01496       softpipe_update_derived(sp);
01497    }
01498 
01499    /* Mark surfaces as defined now */
01500    for (i = 0; i < sp->framebuffer.num_cbufs; i++){
01501       if (sp->framebuffer.cbufs[i]) {
01502          sp->framebuffer.cbufs[i]->status = PIPE_SURFACE_STATUS_DEFINED;
01503       }
01504    }
01505    if (sp->framebuffer.zsbuf) {
01506       sp->framebuffer.zsbuf->status = PIPE_SURFACE_STATUS_DEFINED;
01507    }
01508 
01509    /* Note: nr_attrs is only used for debugging (vertex printing) */
01510    setup->quad.nr_attrs = draw_num_vs_outputs(sp->draw);
01511 
01512    for (i = 0; i < SP_NUM_QUAD_THREADS; i++) {
01513       sp->quad[i].first->begin( sp->quad[i].first );
01514    }
01515 
01516    if (sp->reduced_api_prim == PIPE_PRIM_TRIANGLES &&
01517        sp->rasterizer->fill_cw == PIPE_POLYGON_MODE_FILL &&
01518        sp->rasterizer->fill_ccw == PIPE_POLYGON_MODE_FILL) {
01519       /* we'll do culling */
01520       setup->winding = sp->rasterizer->cull_mode;
01521    }
01522    else {
01523       /* 'draw' will do culling */
01524       setup->winding = PIPE_WINDING_NONE;
01525    }

static boolean setup_sort_vertices ( struct setup_context setup,
float  det,
const float *  v0[4],
const float *  v1[4],
const float *  v2[4] 
) [static]

Returns:
FALSE if coords are inf/nan (cull the tri), TRUE otherwise

Definition at line 513 of file sp_setup.c.

00519 {
00520    setup->vprovoke = v2;
00521 
00522    /* determine bottom to top order of vertices */
00523    {
00524       float y0 = v0[0][1];
00525       float y1 = v1[0][1];
00526       float y2 = v2[0][1];
00527       if (y0 <= y1) {
00528          if (y1 <= y2) {
00529             /* y0<=y1<=y2 */
00530             setup->vmin = v0;
00531             setup->vmid = v1;
00532             setup->vmax = v2;
00533          }
00534          else if (y2 <= y0) {
00535             /* y2<=y0<=y1 */
00536             setup->vmin = v2;
00537             setup->vmid = v0;
00538             setup->vmax = v1;
00539          }
00540          else {
00541             /* y0<=y2<=y1 */
00542             setup->vmin = v0;
00543             setup->vmid = v2;
00544             setup->vmax = v1;
00545          }
00546       }
00547       else {
00548          if (y0 <= y2) {
00549             /* y1<=y0<=y2 */
00550             setup->vmin = v1;
00551             setup->vmid = v0;
00552             setup->vmax = v2;
00553          }
00554          else if (y2 <= y1) {
00555             /* y2<=y1<=y0 */
00556             setup->vmin = v2;
00557             setup->vmid = v1;
00558             setup->vmax = v0;
00559          }
00560          else {
00561             /* y1<=y2<=y0 */
00562             setup->vmin = v1;
00563             setup->vmid = v2;
00564             setup->vmax = v0;
00565          }
00566       }
00567    }
00568 
00569    setup->ebot.dx = setup->vmid[0][0] - setup->vmin[0][0];
00570    setup->ebot.dy = setup->vmid[0][1] - setup->vmin[0][1];
00571    setup->emaj.dx = setup->vmax[0][0] - setup->vmin[0][0];
00572    setup->emaj.dy = setup->vmax[0][1] - setup->vmin[0][1];
00573    setup->etop.dx = setup->vmax[0][0] - setup->vmid[0][0];
00574    setup->etop.dy = setup->vmax[0][1] - setup->vmid[0][1];
00575 
00576    /*
00577     * Compute triangle's area.  Use 1/area to compute partial
00578     * derivatives of attributes later.
00579     *
00580     * The area will be the same as prim->det, but the sign may be
00581     * different depending on how the vertices get sorted above.
00582     *
00583     * To determine whether the primitive is front or back facing we
00584     * use the prim->det value because its sign is correct.
00585     */
00586    {
00587       const float area = (setup->emaj.dx * setup->ebot.dy -
00588                             setup->ebot.dx * setup->emaj.dy);
00589 
00590       setup->oneoverarea = 1.0f / area;
00591 
00592       /*
00593       debug_printf("%s one-over-area %f  area %f  det %f\n",
00594                    __FUNCTION__, setup->oneoverarea, area, det );
00595       */
00596       if (is_inf_or_nan(setup->oneoverarea))
00597          return FALSE;
00598    }
00599 
00600    /* We need to know if this is a front or back-facing triangle for:
00601     *  - the GLSL gl_FrontFacing fragment attribute (bool)
00602     *  - two-sided stencil test
00603     */
00604    setup->quad.input.facing = (det > 0.0) ^ (setup->softpipe->rasterizer->front_winding == PIPE_WINDING_CW);
00605 
00606    return TRUE;

void setup_tri ( struct setup_context setup,
const float *  v0[4],
const float *  v1[4],
const float *  v2[4] 
)

Do setup for triangle rasterization, then render the triangle.

Definition at line 935 of file sp_setup.c.

00940 {
00941    float det;
00942 
00943 #if DEBUG_VERTS
00944    debug_printf("Setup triangle:\n");
00945    print_vertex(setup, v0);
00946    print_vertex(setup, v1);
00947    print_vertex(setup, v2);
00948 #endif
00949 
00950    if (setup->softpipe->no_rast)
00951       return;
00952    
00953    det = calc_det(v0, v1, v2);
00954    /*
00955    debug_printf("%s\n", __FUNCTION__ );
00956    */
00957 
00958 #if DEBUG_FRAGS
00959    setup->numFragsEmitted = 0;
00960    setup->numFragsWritten = 0;
00961 #endif
00962 
00963    if (cull_tri( setup, det ))
00964       return;
00965 
00966    if (!setup_sort_vertices( setup, det, v0, v1, v2 ))
00967       return;
00968    setup_tri_coefficients( setup );
00969    setup_tri_edges( setup );
00970 
00971    setup->quad.input.prim = PRIM_TRI;
00972 
00973    setup->span.y = 0;
00974    setup->span.y_flags = 0;
00975    setup->span.right[0] = 0;
00976    setup->span.right[1] = 0;
00977    /*   setup->span.z_mode = tri_z_mode( setup->ctx ); */
00978 
00979    /*   init_constant_attribs( setup ); */
00980 
00981    if (setup->oneoverarea < 0.0) {
00982       /* emaj on left:
00983        */
00984       subtriangle( setup, &setup->emaj, &setup->ebot, setup->ebot.lines );
00985       subtriangle( setup, &setup->emaj, &setup->etop, setup->etop.lines );
00986    }
00987    else {
00988       /* emaj on right:
00989        */
00990       subtriangle( setup, &setup->ebot, &setup->emaj, setup->ebot.lines );
00991       subtriangle( setup, &setup->etop, &setup->emaj, setup->etop.lines );
00992    }
00993 
00994    flush_spans( setup );
00995 
00996    WAIT_FOR_COMPLETION(setup);
00997 
00998 #if DEBUG_FRAGS
00999    printf("Tri: %u frags emitted, %u written\n",
01000           setup->numFragsEmitted,
01001           setup->numFragsWritten);
01002 #endif

static void setup_tri_coefficients ( struct setup_context setup  )  [static]

Compute the setup->coef[] array dadx, dady, a0 values.

Must be called after setup->vmin,vmid,vmax,vprovoke are initialized.

Definition at line 760 of file sp_setup.c.

00762 {
00763    struct softpipe_context *softpipe = setup->softpipe;
00764    const struct sp_fragment_shader *spfs = softpipe->fs;
00765    const struct vertex_info *vinfo = softpipe_get_vertex_info(softpipe);
00766    uint fragSlot;
00767 
00768    /* z and w are done by linear interpolation:
00769     */
00770    tri_linear_coeff(setup, &setup->posCoef, 0, 2);
00771    tri_linear_coeff(setup, &setup->posCoef, 0, 3);
00772 
00773    /* setup interpolation for all the remaining attributes:
00774     */
00775    for (fragSlot = 0; fragSlot < spfs->info.num_inputs; fragSlot++) {
00776       const uint vertSlot = vinfo->attrib[fragSlot].src_index;
00777       uint j;
00778 
00779       switch (vinfo->attrib[fragSlot].interp_mode) {
00780       case INTERP_CONSTANT:
00781          for (j = 0; j < NUM_CHANNELS; j++)
00782             const_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
00783          break;
00784       case INTERP_LINEAR:
00785          for (j = 0; j < NUM_CHANNELS; j++)
00786             tri_linear_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
00787          break;
00788       case INTERP_PERSPECTIVE:
00789          for (j = 0; j < NUM_CHANNELS; j++)
00790             tri_persp_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
00791          break;
00792       case INTERP_POS:
00793          setup_fragcoord_coeff(setup, fragSlot);
00794          break;
00795       default:
00796          assert(0);
00797       }
00798 
00799       if (spfs->info.input_semantic_name[fragSlot] == TGSI_SEMANTIC_FOG) {
00800          /* FOG.y = front/back facing  XXX fix this */
00801          setup->coef[fragSlot].a0[1] = 1.0f - setup->quad.input.facing;
00802          setup->coef[fragSlot].dadx[1] = 0.0;
00803          setup->coef[fragSlot].dady[1] = 0.0;
00804       }
00805    }

static void setup_tri_edges ( struct setup_context setup  )  [static]

Definition at line 809 of file sp_setup.c.

References edge::dx, edge::dxdy, edge::dy, setup_context::ebot, setup_context::emaj, setup_context::etop, edge::lines, edge::sx, edge::sy, setup_context::vmax, setup_context::vmid, and setup_context::vmin.

00811 {
00812    float vmin_x = setup->vmin[0][0] + 0.5f;
00813    float vmid_x = setup->vmid[0][0] + 0.5f;
00814 
00815    float vmin_y = setup->vmin[0][1] - 0.5f;
00816    float vmid_y = setup->vmid[0][1] - 0.5f;
00817    float vmax_y = setup->vmax[0][1] - 0.5f;
00818 
00819    setup->emaj.sy = ceilf(vmin_y);
00820    setup->emaj.lines = (int) ceilf(vmax_y - setup->emaj.sy);
00821    setup->emaj.dxdy = setup->emaj.dx / setup->emaj.dy;
00822    setup->emaj.sx = vmin_x + (setup->emaj.sy - vmin_y) * setup->emaj.dxdy;
00823 
00824    setup->etop.sy = ceilf(vmid_y);
00825    setup->etop.lines = (int) ceilf(vmax_y - setup->etop.sy);
00826    setup->etop.dxdy = setup->etop.dx / setup->etop.dy;
00827    setup->etop.sx = vmid_x + (setup->etop.sy - vmid_y) * setup->etop.dxdy;
00828 
00829    setup->ebot.sy = ceilf(vmin_y);
00830    setup->ebot.lines = (int) ceilf(vmid_y - setup->ebot.sy);
00831    setup->ebot.dxdy = setup->ebot.dx / setup->ebot.dy;
00832    setup->ebot.sx = vmin_x + (setup->ebot.sy - vmin_y) * setup->ebot.dxdy;

static void subtriangle ( struct setup_context setup,
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 839 of file sp_setup.c.

00844 {
00845    const struct pipe_scissor_state *cliprect = &setup->softpipe->cliprect;
00846    const int minx = (int) cliprect->minx;
00847    const int maxx = (int) cliprect->maxx;
00848    const int miny = (int) cliprect->miny;
00849    const int maxy = (int) cliprect->maxy;
00850    int y, start_y, finish_y;
00851    int sy = (int)eleft->sy;
00852 
00853    assert((int)eleft->sy == (int) eright->sy);
00854 
00855    /* clip top/bottom */
00856    start_y = sy;
00857    finish_y = sy + lines;
00858 
00859    if (start_y < miny)
00860       start_y = miny;
00861 
00862    if (finish_y > maxy)
00863       finish_y = maxy;
00864 
00865    start_y -= sy;
00866    finish_y -= sy;
00867 
00868    /*
00869    debug_printf("%s %d %d\n", __FUNCTION__, start_y, finish_y);
00870    */
00871 
00872    for (y = start_y; y < finish_y; y++) {
00873 
00874       /* avoid accumulating adds as floats don't have the precision to
00875        * accurately iterate large triangle edges that way.  luckily we
00876        * can just multiply these days.
00877        *
00878        * this is all drowned out by the attribute interpolation anyway.
00879        */
00880       int left = (int)(eleft->sx + y * eleft->dxdy);
00881       int right = (int)(eright->sx + y * eright->dxdy);
00882 
00883       /* clip left/right */
00884       if (left < minx)
00885          left = minx;
00886       if (right > maxx)
00887          right = maxx;
00888 
00889       if (left < right) {
00890          int _y = sy + y;
00891          if (block(_y) != setup->span.y) {
00892             flush_spans(setup);
00893             setup->span.y = block(_y);
00894          }
00895 
00896          setup->span.left[_y&1] = left;
00897          setup->span.right[_y&1] = right;
00898          setup->span.y_flags |= 1<<(_y&1);
00899       }
00900    }
00901 
00902 
00903    /* save the values so that emaj can be restarted:
00904     */
00905    eleft->sx += lines * eleft->dxdy;
00906    eright->sx += lines * eright->dxdy;
00907    eleft->sy += lines;
00908    eright->sy += lines;

static void tri_linear_coeff ( struct setup_context setup,
struct tgsi_interp_coef coef,
uint  vertSlot,
uint  i 
) [static]

Compute a0, dadx and dady for a linearly interpolated coefficient, for a triangle.

Definition at line 635 of file sp_setup.c.

00639 {
00640    float botda = setup->vmid[vertSlot][i] - setup->vmin[vertSlot][i];
00641    float majda = setup->vmax[vertSlot][i] - setup->vmin[vertSlot][i];
00642    float a = setup->ebot.dy * majda - botda * setup->emaj.dy;
00643    float b = setup->emaj.dx * botda - majda * setup->ebot.dx;
00644    float dadx = a * setup->oneoverarea;
00645    float dady = b * setup->oneoverarea;
00646 
00647    assert(i <= 3);
00648 
00649    coef->dadx[i] = dadx;
00650    coef->dady[i] = dady;
00651 
00652    /* calculate a0 as the value which would be sampled for the
00653     * fragment at (0,0), taking into account that we want to sample at
00654     * pixel centers, in other words (0.5, 0.5).
00655     *
00656     * this is neat but unfortunately not a good way to do things for
00657     * triangles with very large values of dadx or dady as it will
00658     * result in the subtraction and re-addition from a0 of a very
00659     * large number, which means we'll end up loosing a lot of the
00660     * fractional bits and precision from a0.  the way to fix this is
00661     * to define a0 as the sample at a pixel center somewhere near vmin
00662     * instead - i'll switch to this later.
00663     */
00664    coef->a0[i] = (setup->vmin[vertSlot][i] -
00665                   (dadx * (setup->vmin[0][0] - 0.5f) +
00666                    dady * (setup->vmin[0][1] - 0.5f)));
00667 
00668    /*
00669    debug_printf("attr[%d].%c: %f dx:%f dy:%f\n",
00670                 slot, "xyzw"[i],
00671                 setup->coef[slot].a0[i],
00672                 setup->coef[slot].dadx[i],
00673                 setup->coef[slot].dady[i]);
00674    */

static void tri_persp_coeff ( struct setup_context setup,
struct tgsi_interp_coef coef,
uint  vertSlot,
uint  i 
) [static]

Compute a0, dadx and dady for a perspective-corrected interpolant, for a triangle.

We basically multiply the vertex value by 1/w before computing the plane coefficients (a0, dadx, dady). Later, when we compute the value at a particular fragment position we'll divide the interpolated value by the interpolated W at that fragment.

Definition at line 685 of file sp_setup.c.

00689 {
00690    /* premultiply by 1/w  (v[0][3] is always W):
00691     */
00692    float mina = setup->vmin[vertSlot][i] * setup->vmin[0][3];
00693    float mida = setup->vmid[vertSlot][i] * setup->vmid[0][3];
00694    float maxa = setup->vmax[vertSlot][i] * setup->vmax[0][3];
00695    float botda = mida - mina;
00696    float majda = maxa - mina;
00697    float a = setup->ebot.dy * majda - botda * setup->emaj.dy;
00698    float b = setup->emaj.dx * botda - majda * setup->ebot.dx;
00699    float dadx = a * setup->oneoverarea;
00700    float dady = b * setup->oneoverarea;
00701 
00702    /*
00703    debug_printf("tri persp %d,%d: %f %f %f\n", vertSlot, i,
00704                 setup->vmin[vertSlot][i],
00705                 setup->vmid[vertSlot][i],
00706                 setup->vmax[vertSlot][i]
00707           );
00708    */
00709    assert(i <= 3);
00710 
00711    coef->dadx[i] = dadx;
00712    coef->dady[i] = dady;
00713    coef->a0[i] = (mina -
00714                   (dadx * (setup->vmin[0][0] - 0.5f) +
00715                    dady * (setup->vmin[0][1] - 0.5f)));


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