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]) |
| |
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_context * | setup_create_context (struct softpipe_context *softpipe) |
Create a new primitive setup/render stage. |
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).
Definition at line 51 of file sp_setup.c.
#define EMIT_QUAD | ( | setup, | |||
x, | |||||
y, | |||||
mask | ) |
#define WAIT_FOR_COMPLETION | ( | setup | ) | ((void) 0) |
Definition at line 251 of file sp_setup.c.
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.
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].
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.
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 | ) |
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] |
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)));