summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/cell/spu/spu_tri.c
diff options
context:
space:
mode:
authorRobert Ellison <papillo@tungstengraphics.com>2008-10-03 18:00:43 -0600
committerRobert Ellison <papillo@tungstengraphics.com>2008-10-03 18:05:14 -0600
commitafaa53040bd01ca86762e7d7b1a5a65810767921 (patch)
treed17e24553e5863e688de582f9a3043b1128acac5 /src/gallium/drivers/cell/spu/spu_tri.c
parent22eb067c8863cbd9078f136706effd5df3375dbb (diff)
CELL: changes to generate SPU code for stenciling
This set of code changes are for stencil code generation support. Both one-sided and two-sided stenciling are supported. In addition to the raw code generation changes, these changes had to be made elsewhere in the system: - Added new "register set" feature to the SPE assembly generation. A "register set" is a way to allocate multiple registers and free them all at the same time, delegating register allocation management to the spe_function unit. It's quite useful in complex register allocation schemes (like stenciling). - Added and improved SPE macro calculations. These are operations between registers and unsigned integer immediates. In many cases, the calculation can be performed with a single instruction; the macros will generate the single instruction if possible, or generate a register load and register-to-register operation if not. These macro functions are: spe_load_uint() (which has new ways to load a value in a single instruction), spe_and_uint(), spe_xor_uint(), spe_compare_equal_uint(), and spe_compare_greater_uint(). - Added facing to fragment generation. While rendering, the rasterizer needs to be able to determine front- and back-facing fragments, in order to correctly apply two-sided stencil. That requires these changes: - Added front_winding field to the cell_command_render block, so that the state tracker could communicate to the rasterizer what it considered to be the front-facing direction. - Added fragment facing as an input to the fragment function. - Calculated facing is passed during emit_quad().
Diffstat (limited to 'src/gallium/drivers/cell/spu/spu_tri.c')
-rw-r--r--src/gallium/drivers/cell/spu/spu_tri.c35
1 files changed, 30 insertions, 5 deletions
diff --git a/src/gallium/drivers/cell/spu/spu_tri.c b/src/gallium/drivers/cell/spu/spu_tri.c
index 0a8fb56a62..6039cd80b2 100644
--- a/src/gallium/drivers/cell/spu/spu_tri.c
+++ b/src/gallium/drivers/cell/spu/spu_tri.c
@@ -118,6 +118,8 @@ struct setup_stage {
float oneoverarea;
+ uint facing;
+
uint tx, ty;
int cliprect_minx, cliprect_maxx, cliprect_miny, cliprect_maxy;
@@ -274,7 +276,7 @@ eval_z(float x, float y)
* overall.
*/
static INLINE void
-emit_quad( int x, int y, mask_t mask )
+emit_quad( int x, int y, mask_t mask)
{
/* If any bits in mask are set... */
if (spu_extract(spu_orx(mask), 0)) {
@@ -344,7 +346,8 @@ emit_quad( int x, int y, mask_t mask )
fragZ,
soa_frag[0], soa_frag[1],
soa_frag[2], soa_frag[3],
- mask);
+ mask,
+ setup.facing);
}
}
@@ -379,7 +382,8 @@ emit_quad( int x, int y, mask_t mask )
outputs[0*4+1],
outputs[0*4+2],
outputs[0*4+3],
- mask);
+ mask,
+ setup.facing);
}
}
}
@@ -483,7 +487,7 @@ static void flush_spans( void )
*/
for (x = block(minleft); x <= block(maxright); x += 2) {
#if 1
- emit_quad( x, setup.span.y, calculate_mask( x ) );
+ emit_quad( x, setup.span.y, calculate_mask( x ));
#endif
}
@@ -902,13 +906,28 @@ static void subtriangle( struct edge *eleft,
eright->sy += lines;
}
+static float
+determinant( const float *v0,
+ const float *v1,
+ const float *v2 )
+{
+ /* edge vectors e = v0 - v2, f = v1 - v2 */
+ const float ex = v0[0] - v2[0];
+ const float ey = v0[1] - v2[1];
+ const float fx = v1[0] - v2[0];
+ const float fy = v1[1] - v2[1];
+
+ /* det = cross(e,f).z */
+ return ex * fy - ey * fx;
+}
+
/**
* Draw triangle into tile at (tx, ty) (tile coords)
* The tile data should have already been fetched.
*/
boolean
-tri_draw(const float *v0, const float *v1, const float *v2, uint tx, uint ty)
+tri_draw(const float *v0, const float *v1, const float *v2, uint tx, uint ty, uint front_winding)
{
setup.tx = tx;
setup.ty = ty;
@@ -919,6 +938,12 @@ tri_draw(const float *v0, const float *v1, const float *v2, uint tx, uint ty)
setup.cliprect_maxx = (tx + 1) * TILE_SIZE;
setup.cliprect_maxy = (ty + 1) * TILE_SIZE;
+ /* Before we sort vertices, determine the facing of the triangle,
+ * which will be needed for front/back-face stencil application
+ */
+ float det = determinant(v0, v1, v2);
+ setup.facing = (det > 0.0) ^ (front_winding == PIPE_WINDING_CW);
+
if (!setup_sort_vertices((struct vertex_header *) v0,
(struct vertex_header *) v1,
(struct vertex_header *) v2)) {