llvmpipe: fixed-point rasterization
This commit is contained in:
parent
301c1494b2
commit
0580079864
|
@ -39,7 +39,10 @@
|
||||||
struct lp_rasterizer;
|
struct lp_rasterizer;
|
||||||
struct pipe_screen;
|
struct pipe_screen;
|
||||||
|
|
||||||
#define TILESIZE 64
|
#define FIXED_ORDER 4
|
||||||
|
#define FIXED_ONE (1<<FIXED_ORDER)
|
||||||
|
#define TILE_ORDER 6
|
||||||
|
#define TILESIZE (1<<TILE_ORDER)
|
||||||
|
|
||||||
|
|
||||||
struct lp_rast_state {
|
struct lp_rast_state {
|
||||||
|
@ -84,29 +87,29 @@ struct lp_rast_triangle {
|
||||||
int maxy;
|
int maxy;
|
||||||
|
|
||||||
/* one-pixel sized trivial accept offsets for each plane */
|
/* one-pixel sized trivial accept offsets for each plane */
|
||||||
float ei1;
|
int ei1;
|
||||||
float ei2;
|
int ei2;
|
||||||
float ei3;
|
int ei3;
|
||||||
|
|
||||||
/* one-pixel sized trivial reject offsets for each plane */
|
/* one-pixel sized trivial reject offsets for each plane */
|
||||||
float eo1;
|
int eo1;
|
||||||
float eo2;
|
int eo2;
|
||||||
float eo3;
|
int eo3;
|
||||||
|
|
||||||
/* y deltas for vertex pairs */
|
/* y deltas for vertex pairs */
|
||||||
float dy12;
|
int dy12;
|
||||||
float dy23;
|
int dy23;
|
||||||
float dy31;
|
int dy31;
|
||||||
|
|
||||||
/* x deltas for vertex pairs */
|
/* x deltas for vertex pairs */
|
||||||
float dx12;
|
int dx12;
|
||||||
float dx23;
|
int dx23;
|
||||||
float dx31;
|
int dx31;
|
||||||
|
|
||||||
/* edge function values at minx,miny ?? */
|
/* edge function values at minx,miny ?? */
|
||||||
float c1;
|
int c1;
|
||||||
float c2;
|
int c2;
|
||||||
float c3;
|
int c3;
|
||||||
|
|
||||||
/* XXX: this is only used inside lp_setup_tri.c, don't really
|
/* XXX: this is only used inside lp_setup_tri.c, don't really
|
||||||
* need it here:
|
* need it here:
|
||||||
|
|
|
@ -66,15 +66,15 @@ static void block_full( struct lp_rasterizer *rast,
|
||||||
static INLINE unsigned
|
static INLINE unsigned
|
||||||
do_quad( const struct lp_rast_triangle *tri,
|
do_quad( const struct lp_rast_triangle *tri,
|
||||||
int x, int y,
|
int x, int y,
|
||||||
float c1, float c2, float c3 )
|
int c1, int c2, int c3 )
|
||||||
{
|
{
|
||||||
float xstep1 = -tri->dy12;
|
const int xstep1 = -tri->dy12 * FIXED_ONE;
|
||||||
float xstep2 = -tri->dy23;
|
const int xstep2 = -tri->dy23 * FIXED_ONE;
|
||||||
float xstep3 = -tri->dy31;
|
const int xstep3 = -tri->dy31 * FIXED_ONE;
|
||||||
|
|
||||||
float ystep1 = tri->dx12;
|
const int ystep1 = tri->dx12 * FIXED_ONE;
|
||||||
float ystep2 = tri->dx23;
|
const int ystep2 = tri->dx23 * FIXED_ONE;
|
||||||
float ystep3 = tri->dx31;
|
const int ystep3 = tri->dx31 * FIXED_ONE;
|
||||||
|
|
||||||
unsigned mask = 0;
|
unsigned mask = 0;
|
||||||
|
|
||||||
|
@ -108,26 +108,26 @@ static void
|
||||||
do_block( struct lp_rasterizer *rast,
|
do_block( struct lp_rasterizer *rast,
|
||||||
const struct lp_rast_triangle *tri,
|
const struct lp_rast_triangle *tri,
|
||||||
int x, int y,
|
int x, int y,
|
||||||
float c1,
|
int c1,
|
||||||
float c2,
|
int c2,
|
||||||
float c3 )
|
int c3 )
|
||||||
{
|
{
|
||||||
const int step = 2;
|
const int step = 2 * FIXED_ONE;
|
||||||
|
|
||||||
float xstep1 = -step * tri->dy12;
|
const int xstep1 = -step * tri->dy12;
|
||||||
float xstep2 = -step * tri->dy23;
|
const int xstep2 = -step * tri->dy23;
|
||||||
float xstep3 = -step * tri->dy31;
|
const int xstep3 = -step * tri->dy31;
|
||||||
|
|
||||||
float ystep1 = step * tri->dx12;
|
const int ystep1 = step * tri->dx12;
|
||||||
float ystep2 = step * tri->dx23;
|
const int ystep2 = step * tri->dx23;
|
||||||
float ystep3 = step * tri->dx31;
|
const int ystep3 = step * tri->dx31;
|
||||||
|
|
||||||
int ix, iy;
|
int ix, iy;
|
||||||
|
|
||||||
for (iy = 0; iy < BLOCKSIZE; iy += 2) {
|
for (iy = 0; iy < BLOCKSIZE; iy += 2) {
|
||||||
float cx1 = c1;
|
int cx1 = c1;
|
||||||
float cx2 = c2;
|
int cx2 = c2;
|
||||||
float cx3 = c3;
|
int cx3 = c3;
|
||||||
|
|
||||||
unsigned masks[4] = {0, 0, 0, 0};
|
unsigned masks[4] = {0, 0, 0, 0};
|
||||||
|
|
||||||
|
@ -160,23 +160,23 @@ void lp_rast_triangle( struct lp_rasterizer *rast,
|
||||||
{
|
{
|
||||||
const struct lp_rast_triangle *tri = arg.triangle;
|
const struct lp_rast_triangle *tri = arg.triangle;
|
||||||
|
|
||||||
const int step = BLOCKSIZE;
|
const int step = BLOCKSIZE * FIXED_ONE;
|
||||||
|
|
||||||
float ei1 = tri->ei1 * step;
|
int ei1 = tri->ei1 * step;
|
||||||
float ei2 = tri->ei2 * step;
|
int ei2 = tri->ei2 * step;
|
||||||
float ei3 = tri->ei3 * step;
|
int ei3 = tri->ei3 * step;
|
||||||
|
|
||||||
float eo1 = tri->eo1 * step;
|
int eo1 = tri->eo1 * step;
|
||||||
float eo2 = tri->eo2 * step;
|
int eo2 = tri->eo2 * step;
|
||||||
float eo3 = tri->eo3 * step;
|
int eo3 = tri->eo3 * step;
|
||||||
|
|
||||||
float xstep1 = -step * tri->dy12;
|
int xstep1 = -step * tri->dy12;
|
||||||
float xstep2 = -step * tri->dy23;
|
int xstep2 = -step * tri->dy23;
|
||||||
float xstep3 = -step * tri->dy31;
|
int xstep3 = -step * tri->dy31;
|
||||||
|
|
||||||
float ystep1 = step * tri->dx12;
|
int ystep1 = step * tri->dx12;
|
||||||
float ystep2 = step * tri->dx23;
|
int ystep2 = step * tri->dx23;
|
||||||
float ystep3 = step * tri->dx31;
|
int ystep3 = step * tri->dx31;
|
||||||
|
|
||||||
/* Clamp to tile dimensions:
|
/* Clamp to tile dimensions:
|
||||||
*/
|
*/
|
||||||
|
@ -186,8 +186,8 @@ void lp_rast_triangle( struct lp_rasterizer *rast,
|
||||||
int maxy = MIN2(tri->maxy, rast->y + TILE_SIZE);
|
int maxy = MIN2(tri->maxy, rast->y + TILE_SIZE);
|
||||||
|
|
||||||
int x, y;
|
int x, y;
|
||||||
float x0, y0;
|
int x0, y0;
|
||||||
float c1, c2, c3;
|
int c1, c2, c3;
|
||||||
|
|
||||||
debug_printf("%s\n", __FUNCTION__);
|
debug_printf("%s\n", __FUNCTION__);
|
||||||
|
|
||||||
|
@ -196,23 +196,23 @@ void lp_rast_triangle( struct lp_rasterizer *rast,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
minx &= ~(step-1);
|
minx &= ~(BLOCKSIZE-1);
|
||||||
miny &= ~(step-1);
|
miny &= ~(BLOCKSIZE-1);
|
||||||
|
|
||||||
x0 = (float)minx;
|
x0 = minx << FIXED_ORDER;
|
||||||
y0 = (float)miny;
|
y0 = miny << FIXED_ORDER;
|
||||||
|
|
||||||
c1 = tri->c1 + tri->dx12 * y0 - tri->dy12 * x0;
|
c1 = tri->c1 + tri->dx12 * y0 - tri->dy12 * x0;
|
||||||
c2 = tri->c2 + tri->dx23 * y0 - tri->dy23 * x0;
|
c2 = tri->c2 + tri->dx23 * y0 - tri->dy23 * x0;
|
||||||
c3 = tri->c3 + tri->dx31 * y0 - tri->dy31 * x0;
|
c3 = tri->c3 + tri->dx31 * y0 - tri->dy31 * x0;
|
||||||
|
|
||||||
for (y = miny; y < maxy; y += step)
|
for (y = miny; y < maxy; y += BLOCKSIZE)
|
||||||
{
|
{
|
||||||
float cx1 = c1;
|
int cx1 = c1;
|
||||||
float cx2 = c2;
|
int cx2 = c2;
|
||||||
float cx3 = c3;
|
int cx3 = c3;
|
||||||
|
|
||||||
for (x = minx; x < maxx; x += step)
|
for (x = minx; x < maxx; x += BLOCKSIZE)
|
||||||
{
|
{
|
||||||
if (cx1 + eo1 < 0 ||
|
if (cx1 + eo1 < 0 ||
|
||||||
cx2 + eo2 < 0 ||
|
cx2 + eo2 < 0 ||
|
||||||
|
|
|
@ -169,6 +169,15 @@ static INLINE void *get_data( struct data_block_list *list,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Put back data if we decide not to use it, eg. culled triangles.
|
||||||
|
*/
|
||||||
|
static INLINE void putback_data( struct data_block_list *list,
|
||||||
|
unsigned size)
|
||||||
|
{
|
||||||
|
list->tail->used -= size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static INLINE void *get_data_aligned( struct data_block_list *list,
|
static INLINE void *get_data_aligned( struct data_block_list *list,
|
||||||
unsigned size,
|
unsigned size,
|
||||||
unsigned alignment )
|
unsigned alignment )
|
||||||
|
|
|
@ -223,10 +223,9 @@ static void setup_tri_coefficients( struct setup_context *setup,
|
||||||
|
|
||||||
/* XXX: do this by add/subtracting a large floating point number:
|
/* XXX: do this by add/subtracting a large floating point number:
|
||||||
*/
|
*/
|
||||||
static inline float subpixel_snap( float a )
|
static inline int subpixel_snap( float a )
|
||||||
{
|
{
|
||||||
int i = a * 16;
|
return util_iround(FIXED_ONE * a);
|
||||||
return (float)i * (1.0/16);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -256,23 +255,18 @@ do_triangle_ccw(struct setup_context *setup,
|
||||||
const float (*v3)[4],
|
const float (*v3)[4],
|
||||||
boolean frontfacing )
|
boolean frontfacing )
|
||||||
{
|
{
|
||||||
const int rt_width = setup->fb.width;
|
|
||||||
const int rt_height = setup->fb.height;
|
|
||||||
|
|
||||||
const float y1 = subpixel_snap(v1[0][1]);
|
const int y1 = subpixel_snap(v1[0][1]);
|
||||||
const float y2 = subpixel_snap(v2[0][1]);
|
const int y2 = subpixel_snap(v2[0][1]);
|
||||||
const float y3 = subpixel_snap(v3[0][1]);
|
const int y3 = subpixel_snap(v3[0][1]);
|
||||||
|
|
||||||
const float x1 = subpixel_snap(v1[0][0]);
|
const int x1 = subpixel_snap(v1[0][0]);
|
||||||
const float x2 = subpixel_snap(v2[0][0]);
|
const int x2 = subpixel_snap(v2[0][0]);
|
||||||
const float x3 = subpixel_snap(v3[0][0]);
|
const int x3 = subpixel_snap(v3[0][0]);
|
||||||
|
|
||||||
struct lp_rast_triangle *tri = get_data( &setup->data, sizeof *tri );
|
struct lp_rast_triangle *tri = get_data( &setup->data, sizeof *tri );
|
||||||
float area;
|
float area;
|
||||||
int minx, maxx, miny, maxy;
|
int minx, maxx, miny, maxy;
|
||||||
float c1, c2, c3;
|
|
||||||
|
|
||||||
tri->inputs.state = setup->fs.stored;
|
|
||||||
|
|
||||||
tri->dx12 = x1 - x2;
|
tri->dx12 = x1 - x2;
|
||||||
tri->dx23 = x2 - x3;
|
tri->dx23 = x2 - x3;
|
||||||
|
@ -285,35 +279,32 @@ do_triangle_ccw(struct setup_context *setup,
|
||||||
area = (tri->dx12 * tri->dy31 -
|
area = (tri->dx12 * tri->dy31 -
|
||||||
tri->dx31 * tri->dy12);
|
tri->dx31 * tri->dy12);
|
||||||
|
|
||||||
/* Cull non-ccw and zero-sized triangles.
|
/* Cull non-ccw and zero-sized triangles.
|
||||||
|
*
|
||||||
|
* XXX: subject to overflow??
|
||||||
*/
|
*/
|
||||||
if (area <= 0 || util_is_inf_or_nan(area))
|
if (area <= 0) {
|
||||||
|
putback_data( &setup->data, sizeof *tri );
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Bounding rectangle
|
// Bounding rectangle
|
||||||
minx = util_iround(MIN3(x1, x2, x3) - .5);
|
tri->minx = (MIN3(x1, x2, x3) + 0xf) >> FIXED_ORDER;
|
||||||
maxx = util_iround(MAX3(x1, x2, x3) + .5);
|
tri->maxx = (MAX3(x1, x2, x3) + 0xf) >> FIXED_ORDER;
|
||||||
miny = util_iround(MIN3(y1, y2, y3) - .5);
|
tri->miny = (MIN3(y1, y2, y3) + 0xf) >> FIXED_ORDER;
|
||||||
maxy = util_iround(MAX3(y1, y2, y3) + .5);
|
tri->maxy = (MAX3(y1, y2, y3) + 0xf) >> FIXED_ORDER;
|
||||||
|
|
||||||
/* Clamp to framebuffer (or tile) dimensions:
|
if (tri->miny == tri->maxy ||
|
||||||
*/
|
tri->minx == tri->maxx) {
|
||||||
miny = MAX2(0, miny);
|
putback_data( &setup->data, sizeof *tri );
|
||||||
minx = MAX2(0, minx);
|
|
||||||
maxy = MIN2(rt_height, maxy);
|
|
||||||
maxx = MIN2(rt_width, maxx);
|
|
||||||
|
|
||||||
if (miny == maxy || minx == maxx)
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
tri->miny = miny;
|
tri->inputs.state = setup->fs.stored;
|
||||||
tri->minx = minx;
|
|
||||||
tri->maxy = maxy;
|
|
||||||
tri->maxx = maxx;
|
|
||||||
|
|
||||||
/* The only divide in this code. Is it really needed?
|
/*
|
||||||
*/
|
*/
|
||||||
tri->oneoverarea = 1.0f / area;
|
tri->oneoverarea = ((float)FIXED_ONE) / (float)area;
|
||||||
|
|
||||||
/* Setup parameter interpolants:
|
/* Setup parameter interpolants:
|
||||||
*/
|
*/
|
||||||
|
@ -328,9 +319,9 @@ do_triangle_ccw(struct setup_context *setup,
|
||||||
|
|
||||||
/* correct for top-left fill convention:
|
/* correct for top-left fill convention:
|
||||||
*/
|
*/
|
||||||
if (tri->dy12 < 0 || (tri->dy12 == 0 && tri->dx12 > 0)) tri->c1 += 1.0/16.0f;
|
if (tri->dy12 < 0 || (tri->dy12 == 0 && tri->dx12 > 0)) tri->c1++;
|
||||||
if (tri->dy23 < 0 || (tri->dy23 == 0 && tri->dx23 > 0)) tri->c2 += 1.0/16.0f;
|
if (tri->dy23 < 0 || (tri->dy23 == 0 && tri->dx23 > 0)) tri->c2++;
|
||||||
if (tri->dy31 < 0 || (tri->dy31 == 0 && tri->dx31 > 0)) tri->c3 += 1.0/16.0f;
|
if (tri->dy31 < 0 || (tri->dy31 == 0 && tri->dx31 > 0)) tri->c3++;
|
||||||
|
|
||||||
/* find trivial reject offsets for each edge for a single-pixel
|
/* find trivial reject offsets for each edge for a single-pixel
|
||||||
* sized block. These will be scaled up at each recursive level to
|
* sized block. These will be scaled up at each recursive level to
|
||||||
|
@ -355,17 +346,10 @@ do_triangle_ccw(struct setup_context *setup,
|
||||||
tri->ei2 = tri->dx23 - tri->dy23 - tri->eo2;
|
tri->ei2 = tri->dx23 - tri->dy23 - tri->eo2;
|
||||||
tri->ei3 = tri->dx31 - tri->dy31 - tri->eo3;
|
tri->ei3 = tri->dx31 - tri->dy31 - tri->eo3;
|
||||||
|
|
||||||
minx &= ~(TILESIZE-1); /* aligned blocks */
|
minx = tri->minx / TILESIZE;
|
||||||
miny &= ~(TILESIZE-1); /* aligned blocks */
|
miny = tri->miny / TILESIZE;
|
||||||
|
maxx = tri->maxx / TILESIZE;
|
||||||
c1 = tri->c1 + tri->dx12 * miny - tri->dy12 * minx;
|
maxy = tri->maxy / TILESIZE;
|
||||||
c2 = tri->c2 + tri->dx23 * miny - tri->dy23 * minx;
|
|
||||||
c3 = tri->c3 + tri->dx31 * miny - tri->dy31 * minx;
|
|
||||||
|
|
||||||
minx /= TILESIZE;
|
|
||||||
miny /= TILESIZE;
|
|
||||||
maxx /= TILESIZE;
|
|
||||||
maxy /= TILESIZE;
|
|
||||||
|
|
||||||
/* Convert to tile coordinates:
|
/* Convert to tile coordinates:
|
||||||
*/
|
*/
|
||||||
|
@ -378,23 +362,31 @@ do_triangle_ccw(struct setup_context *setup,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const int step = TILESIZE;
|
int c1 = (tri->c1 +
|
||||||
|
tri->dx12 * miny * TILESIZE * FIXED_ONE -
|
||||||
|
tri->dy12 * minx * TILESIZE * FIXED_ONE);
|
||||||
|
int c2 = (tri->c2 +
|
||||||
|
tri->dx23 * miny * TILESIZE * FIXED_ONE -
|
||||||
|
tri->dy23 * minx * TILESIZE * FIXED_ONE);
|
||||||
|
int c3 = (tri->c3 +
|
||||||
|
tri->dx31 * miny * TILESIZE * FIXED_ONE -
|
||||||
|
tri->dy31 * minx * TILESIZE * FIXED_ONE);
|
||||||
|
|
||||||
float ei1 = tri->ei1 * step;
|
int ei1 = tri->ei1 << (FIXED_ORDER + TILE_ORDER);
|
||||||
float ei2 = tri->ei2 * step;
|
int ei2 = tri->ei2 << (FIXED_ORDER + TILE_ORDER);
|
||||||
float ei3 = tri->ei3 * step;
|
int ei3 = tri->ei3 << (FIXED_ORDER + TILE_ORDER);
|
||||||
|
|
||||||
float eo1 = tri->eo1 * step;
|
int eo1 = tri->eo1 << (FIXED_ORDER + TILE_ORDER);
|
||||||
float eo2 = tri->eo2 * step;
|
int eo2 = tri->eo2 << (FIXED_ORDER + TILE_ORDER);
|
||||||
float eo3 = tri->eo3 * step;
|
int eo3 = tri->eo3 << (FIXED_ORDER + TILE_ORDER);
|
||||||
|
|
||||||
float xstep1 = -step * tri->dy12;
|
int xstep1 = -(tri->dy12 << (FIXED_ORDER + TILE_ORDER));
|
||||||
float xstep2 = -step * tri->dy23;
|
int xstep2 = -(tri->dy23 << (FIXED_ORDER + TILE_ORDER));
|
||||||
float xstep3 = -step * tri->dy31;
|
int xstep3 = -(tri->dy31 << (FIXED_ORDER + TILE_ORDER));
|
||||||
|
|
||||||
float ystep1 = step * tri->dx12;
|
int ystep1 = tri->dx12 << (FIXED_ORDER + TILE_ORDER);
|
||||||
float ystep2 = step * tri->dx23;
|
int ystep2 = tri->dx23 << (FIXED_ORDER + TILE_ORDER);
|
||||||
float ystep3 = step * tri->dx31;
|
int ystep3 = tri->dx31 << (FIXED_ORDER + TILE_ORDER);
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
||||||
|
|
||||||
|
@ -406,12 +398,25 @@ do_triangle_ccw(struct setup_context *setup,
|
||||||
*/
|
*/
|
||||||
for (y = miny; y <= maxy; y++)
|
for (y = miny; y <= maxy; y++)
|
||||||
{
|
{
|
||||||
float cx1 = c1;
|
int cx1 = c1;
|
||||||
float cx2 = c2;
|
int cx2 = c2;
|
||||||
float cx3 = c3;
|
int cx3 = c3;
|
||||||
|
|
||||||
for (x = minx; x <= maxx; x++)
|
for (x = minx; x <= maxx; x++)
|
||||||
{
|
{
|
||||||
|
assert(cx1 ==
|
||||||
|
tri->c1 +
|
||||||
|
tri->dx12 * y * TILESIZE * FIXED_ONE -
|
||||||
|
tri->dy12 * x * TILESIZE * FIXED_ONE);
|
||||||
|
assert(cx2 ==
|
||||||
|
tri->c2 +
|
||||||
|
tri->dx23 * y * TILESIZE * FIXED_ONE -
|
||||||
|
tri->dy23 * x * TILESIZE * FIXED_ONE);
|
||||||
|
assert(cx3 ==
|
||||||
|
tri->c3 +
|
||||||
|
tri->dx31 * y * TILESIZE * FIXED_ONE -
|
||||||
|
tri->dy31 * x * TILESIZE * FIXED_ONE);
|
||||||
|
|
||||||
if (cx1 + eo1 < 0 ||
|
if (cx1 + eo1 < 0 ||
|
||||||
cx2 + eo2 < 0 ||
|
cx2 + eo2 < 0 ||
|
||||||
cx3 + eo3 < 0)
|
cx3 + eo3 < 0)
|
||||||
|
@ -427,9 +432,9 @@ do_triangle_ccw(struct setup_context *setup,
|
||||||
lp_rast_arg_inputs(&tri->inputs) );
|
lp_rast_arg_inputs(&tri->inputs) );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* shade partial tile */
|
/* shade partial tile */
|
||||||
bin_command( &setup->tile[x][y],
|
bin_command( &setup->tile[x][y],
|
||||||
lp_rast_triangle,
|
lp_rast_triangle,
|
||||||
lp_rast_arg_triangle(tri) );
|
lp_rast_arg_triangle(tri) );
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue