cleanup alias scan conversion

This commit is contained in:
Denis 2024-03-31 22:45:30 +03:00
parent 85b7ae87ef
commit 6d1ac97a77

View file

@ -24,7 +24,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <limits.h> #include <limits.h>
typedef struct { typedef struct {
int isflattop;
int numleftedges; int numleftedges;
compactvert_t *pleftedgevert0; compactvert_t *pleftedgevert0;
compactvert_t *pleftedgevert1; compactvert_t *pleftedgevert1;
@ -44,18 +43,18 @@ static int d_xdenom;
static edgetable *pedgetable; static edgetable *pedgetable;
static edgetable edgetables[12] = { static edgetable edgetables[12] = {
{0, 1, &r_p0, &r_p2, NULL, 2, &r_p0, &r_p1, &r_p2}, {1, &r_p0, &r_p2, &r_p2, 2, &r_p0, &r_p1, &r_p2},
{0, 2, &r_p1, &r_p0, &r_p2, 1, &r_p1, &r_p2, NULL}, {2, &r_p1, &r_p0, &r_p2, 1, &r_p1, &r_p2, &r_p2},
{1, 1, &r_p0, &r_p2, NULL, 1, &r_p1, &r_p2, NULL}, {1, &r_p0, &r_p2, &r_p2, 1, &r_p1, &r_p2, &r_p2}, // flat top
{0, 1, &r_p1, &r_p0, NULL, 2, &r_p1, &r_p2, &r_p0}, {1, &r_p1, &r_p0, &r_p0, 2, &r_p1, &r_p2, &r_p0},
{0, 2, &r_p0, &r_p2, &r_p1, 1, &r_p0, &r_p1, NULL}, {2, &r_p0, &r_p2, &r_p1, 1, &r_p0, &r_p1, &r_p1},
{0, 1, &r_p2, &r_p1, NULL, 1, &r_p2, &r_p0, NULL}, {1, &r_p2, &r_p1, &r_p1, 1, &r_p2, &r_p0, &r_p0},
{0, 1, &r_p2, &r_p1, NULL, 2, &r_p2, &r_p0, &r_p1}, {1, &r_p2, &r_p1, &r_p1, 2, &r_p2, &r_p0, &r_p1},
{0, 2, &r_p2, &r_p1, &r_p0, 1, &r_p2, &r_p0, NULL}, {2, &r_p2, &r_p1, &r_p0, 1, &r_p2, &r_p0, &r_p0},
{0, 1, &r_p1, &r_p0, NULL, 1, &r_p1, &r_p2, NULL}, {1, &r_p1, &r_p0, &r_p0, 1, &r_p1, &r_p2, &r_p2},
{1, 1, &r_p2, &r_p1, NULL, 1, &r_p0, &r_p1, NULL}, {1, &r_p2, &r_p1, &r_p1, 1, &r_p0, &r_p1, &r_p1}, // flat top
{1, 1, &r_p1, &r_p0, NULL, 1, &r_p2, &r_p0, NULL}, {1, &r_p1, &r_p0, &r_p0, 1, &r_p2, &r_p0, &r_p0}, // flat top
{0, 1, &r_p0, &r_p2, NULL, 1, &r_p0, &r_p1, NULL}, {1, &r_p0, &r_p2, &r_p2, 1, &r_p0, &r_p1, &r_p1},
}; };
// FIXME: some of these can become statics // FIXME: some of these can become statics
@ -200,13 +199,6 @@ static void
R_PushEdgesSpan(int u, int v, int count, R_PushEdgesSpan(int u, int v, int count,
pixel_t* d_ptex, int d_sfrac, int d_tfrac, light3_t d_light, zvalue_t d_zi) pixel_t* d_ptex, int d_sfrac, int d_tfrac, light3_t d_light, zvalue_t d_zi)
{ {
if (d_pedgespanpackage >= triangles_max)
{
// no space any more
r_outoftriangles = true;
return;
}
d_pedgespanpackage->u = u; d_pedgespanpackage->u = u;
d_pedgespanpackage->v = v; d_pedgespanpackage->v = v;
d_pedgespanpackage->count = count; d_pedgespanpackage->count = count;
@ -299,6 +291,41 @@ quotient must fit in 32 bits.
FIXME: GET RID OF THIS! (FloorDivMod) FIXME: GET RID OF THIS! (FloorDivMod)
==================== ====================
*/ */
#if defined(__i386__) || defined(__amd64__)
// just exclude ARM32 with FPU, e.g. Pi 1
static void
FloorDivMod(int numer, int denom, int *quo, int *rem)
{
int q, r;
q = numer / denom;
r = numer - q * denom;
if (-1/2 || 1/-2 || -1/-2) {
// long live C89
if (r < 0 && r < denom) {
q += 1;
r -= denom;
}
} else {
// C99 always truncates to 0
if ((numer ^ denom) < 0 && r != 0) {
q -= 1;
r += denom;
}
}
assert(r == numer - q * denom);
if ((numer < 0) ^ (denom < 0))
assert(q <= 0);
else
assert(q >= 0);
if (denom < 0)
assert(r > denom && r <= 0);
else
assert(r >= 0 && r < denom);
*quo = q;
*rem = r;
}
#else
static void static void
FloorDivMod (float numer, float denom, int *quotient, FloorDivMod (float numer, float denom, int *quotient,
int *rem) int *rem)
@ -331,7 +358,7 @@ FloorDivMod (float numer, float denom, int *quotient,
*quotient = q; *quotient = q;
*rem = r; *rem = r;
} }
#endif
/* /*
=================== ===================
@ -342,20 +369,17 @@ static void
R_PolysetSetUpForLineScan(fixed8_t startvertu, fixed8_t startvertv, R_PolysetSetUpForLineScan(fixed8_t startvertu, fixed8_t startvertv,
fixed8_t endvertu, fixed8_t endvertv) fixed8_t endvertu, fixed8_t endvertv)
{ {
float tm, tn; int tm, tn;
errorterm = -1;
tm = endvertu - startvertu; tm = endvertu - startvertu;
tn = endvertv - startvertv; tn = endvertv - startvertv;
FloorDivMod (tm, tn, &ubasestep, &erroradjustup); errorterm = -1;
erroradjustdown = tn; erroradjustdown = tn;
FloorDivMod (tm, tn, &ubasestep, &erroradjustup);
} }
/* /*
================ ================
R_PolysetCalcGradients R_PolysetCalcGradients
@ -492,7 +516,7 @@ R_PolysetDrawSpans8_33(const entity_t *currententity, spanpackage_t *pspanpackag
} }
pspanpackage++; pspanpackage++;
} while ((pspanpackage < triangles_max) && (pspanpackage->count != INT_MIN)); } while (pspanpackage->count != INT_MIN);
} }
void void
@ -539,7 +563,7 @@ R_PolysetDrawSpansConstant8_33(const entity_t *currententity, spanpackage_t *psp
} }
pspanpackage++; pspanpackage++;
} while ((pspanpackage < triangles_max) && (pspanpackage->count != INT_MIN)); } while (pspanpackage->count != INT_MIN);
} }
void void
@ -621,7 +645,7 @@ R_PolysetDrawSpans8_66(const entity_t *currententity, spanpackage_t *pspanpackag
} }
pspanpackage++; pspanpackage++;
} while ((pspanpackage < triangles_max) && (pspanpackage->count != INT_MIN)); } while (pspanpackage->count != INT_MIN);
} }
void void
@ -679,7 +703,7 @@ R_PolysetDrawSpansConstant8_66(const entity_t *currententity, spanpackage_t *psp
} }
pspanpackage++; pspanpackage++;
} while ((pspanpackage < triangles_max) && (pspanpackage->count != INT_MIN)); } while (pspanpackage->count != INT_MIN);
} }
void void
@ -762,7 +786,79 @@ R_PolysetDrawSpans8_Opaque (const entity_t *currententity, spanpackage_t *pspanp
} }
pspanpackage++; pspanpackage++;
} while ((pspanpackage < triangles_max) && (pspanpackage->count != INT_MIN)); } while (pspanpackage->count != INT_MIN);
}
static void
R_ProcessLeftEdge(compactvert_t *plefttop, compactvert_t *prighttop,
compactvert_t *pleftbottom)
{
light3_t working_lstepx;
pixel_t *d_ptex;
int u, v;
int s, t;
int height;
int i;
u = plefttop->u;
v = plefttop->v;
d_aspancount = plefttop->u - prighttop->u;
s = plefttop->s;
t = plefttop->t;
i = (s >> SHIFT16XYZ) + (t >> SHIFT16XYZ) * r_affinetridesc.skinwidth;
d_ptex = &r_affinetridesc.pskin[i];
d_sfrac = s & 0xFFFF;
d_tfrac = t & 0xFFFF;
memcpy(d_light, plefttop->l, sizeof(light3_t));
d_zi = plefttop->zi;
height = pleftbottom->v - plefttop->v;
if (height == 1)
{
// skip calculations needed for 2+ spans
R_PushEdgesSpan(u, v, d_aspancount,
d_ptex, d_sfrac, d_tfrac, d_light, d_zi);
return;
}
R_PolysetSetUpForLineScan(plefttop->u, plefttop->v,
pleftbottom->u, pleftbottom->v);
// for negative steps in x along left edge, bias toward overflow rather than
// underflow (sort of turning the floor () we did in the gradient calcs into
// ceil (), but plus a little bit)
t = ubasestep < 0;
for (i = 0; i < 3; i++)
working_lstepx[i] = r_lstepx[i] - t;
// base steps for drawers
s = r_sstepy + r_sstepx * ubasestep;
t = r_tstepy + r_tstepx * ubasestep;
d_ptexbasestep = (s >> SHIFT16XYZ) +
(t >> SHIFT16XYZ) * r_affinetridesc.skinwidth;
d_sfracbasestep = s & 0xFFFF;
d_tfracbasestep = t & 0xFFFF;
for (i = 0; i < 3; i++)
d_lightbasestep[i] = r_lstepy[i] + working_lstepx[i] * ubasestep;
d_zibasestep = r_zistepy + r_zistepx * ubasestep;
// extra steps for drawers
s += r_sstepx;
t += r_tstepx;
d_ptexextrastep = (s >> SHIFT16XYZ) +
(t >> SHIFT16XYZ) * r_affinetridesc.skinwidth;
d_sfracextrastep = s & 0xFFFF;
d_tfracextrastep = t & 0xFFFF;
for (i = 0; i < 3; i++)
d_lightextrastep[i] = d_lightbasestep[i] + working_lstepx[i];
d_ziextrastep = d_zibasestep + r_zistepx;
R_PolysetScanLeftEdge_C(height, d_ptex, u, v);
} }
/* /*
@ -773,12 +869,14 @@ R_RasterizeAliasPolySmooth
static void static void
R_RasterizeAliasPolySmooth(const entity_t *currententity) R_RasterizeAliasPolySmooth(const entity_t *currententity)
{ {
int initialleftheight, initialrightheight;
compactvert_t *plefttop, *prighttop, *pleftbottom, *prightbottom; compactvert_t *plefttop, *prighttop, *pleftbottom, *prightbottom;
light3_t working_lstepx; spanpackage_t *pstart;
int originalcount; int originalcount;
int u, v; int leftheight, rightheight;
pixel_t *d_ptex;
// set the s, t, and light gradients, which are consistent across
// the triangle because being a triangle, things are affine
R_PolysetCalcGradients (r_affinetridesc.skinwidth);
plefttop = pedgetable->pleftedgevert0; plefttop = pedgetable->pleftedgevert0;
prighttop = pedgetable->prightedgevert0; prighttop = pedgetable->prightedgevert0;
@ -786,204 +884,76 @@ R_RasterizeAliasPolySmooth(const entity_t *currententity)
pleftbottom = pedgetable->pleftedgevert1; pleftbottom = pedgetable->pleftedgevert1;
prightbottom = pedgetable->prightedgevert1; prightbottom = pedgetable->prightedgevert1;
initialleftheight = pleftbottom->v - plefttop->v; // make sure we have enough spans for the full height
initialrightheight = prightbottom->v - prighttop->v; // plus 1 more for the list terminator.
// vert2 in the edgetable is always the lowest.
// // (this is silly anyway, just allocate vid.height+1)
// set the s, t, and light gradients, which are consistent across the triangle leftheight = pedgetable->pleftedgevert2->v - plefttop->v;
// because being a triangle, things are affine rightheight = pedgetable->prightedgevert2->v - prighttop->v;
// if (leftheight < rightheight)
R_PolysetCalcGradients (r_affinetridesc.skinwidth); leftheight = rightheight;
// if (&triangle_spans[leftheight] >= triangles_max)
// rasterize the polygon
//
//
// scan out the top (and possibly only) part of the left edge
//
d_pedgespanpackage = triangle_spans;
u = plefttop->u;
v = plefttop->v;
d_aspancount = plefttop->u - prighttop->u;
d_ptex = r_affinetridesc.pskin + (plefttop->s >> SHIFT16XYZ) +
(plefttop->t >> SHIFT16XYZ) * r_affinetridesc.skinwidth;
{ {
d_sfrac = plefttop->s & 0xFFFF;
d_tfrac = plefttop->t & 0xFFFF;
}
memcpy(d_light, plefttop->l, sizeof(light3_t));
d_zi = plefttop->zi;
if (initialleftheight == 1)
{
R_PushEdgesSpan(u, v, d_aspancount,
d_ptex, d_sfrac, d_tfrac, d_light, d_zi);
}
else
{
int i;
R_PolysetSetUpForLineScan(plefttop->u, plefttop->v,
pleftbottom->u, pleftbottom->v);
// TODO: can reuse partial expressions here
// for negative steps in x along left edge, bias toward overflow rather than
// underflow (sort of turning the floor () we did in the gradient calcs into
// ceil (), but plus a little bit)
if (ubasestep < 0)
{
for(i=0; i<3; i++)
working_lstepx[i] = r_lstepx[i] - 1;
}
else
memcpy(working_lstepx, r_lstepx, sizeof(light3_t));
d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> SHIFT16XYZ) +
((r_tstepy + r_tstepx * ubasestep) >> SHIFT16XYZ) *
r_affinetridesc.skinwidth;
d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF;
d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF;
for(i=0; i<3; i++)
d_lightbasestep[i] = r_lstepy[i] + working_lstepx[i] * ubasestep;
d_zibasestep = r_zistepy + r_zistepx * ubasestep;
d_ptexextrastep = ((r_sstepy + r_sstepx * (ubasestep + 1)) >> SHIFT16XYZ) +
((r_tstepy + r_tstepx * (ubasestep + 1)) >> SHIFT16XYZ) *
r_affinetridesc.skinwidth;
d_sfracextrastep = (r_sstepy + r_sstepx*(ubasestep + 1)) & 0xFFFF;
d_tfracextrastep = (r_tstepy + r_tstepx*(ubasestep + 1)) & 0xFFFF;
for(i=0; i<3; i++)
d_lightextrastep[i] = d_lightbasestep[i] + working_lstepx[i];
d_ziextrastep = d_zibasestep + r_zistepx;
R_PolysetScanLeftEdge_C(initialleftheight, d_ptex, u, v);
}
//
// scan out the bottom part of the left edge, if it exists
//
if (pedgetable->numleftedges == 2)
{
int height;
plefttop = pleftbottom;
pleftbottom = pedgetable->pleftedgevert2;
height = pleftbottom->v - plefttop->v;
// TODO: make this a function; modularize this function in general
u = plefttop->u;
v = plefttop->v;
d_aspancount = plefttop->u - prighttop->u;
d_ptex = r_affinetridesc.pskin + (plefttop->s >> SHIFT16XYZ) +
(plefttop->t >> SHIFT16XYZ) * r_affinetridesc.skinwidth;
d_sfrac = 0;
d_tfrac = 0;
memcpy(d_light, plefttop->l, sizeof(light3_t));
d_zi = plefttop->zi;
if (height == 1)
{
R_PushEdgesSpan(u, v, d_aspancount,
d_ptex, d_sfrac, d_tfrac, d_light, d_zi);
}
else
{
int i;
R_PolysetSetUpForLineScan(plefttop->u, plefttop->v,
pleftbottom->u, pleftbottom->v);
if (ubasestep < 0)
{
for(i=0; i<3; i++)
working_lstepx[i] = r_lstepx[i] - 1;
}
else
memcpy(working_lstepx, r_lstepx, sizeof(light3_t));
d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> SHIFT16XYZ) +
((r_tstepy + r_tstepx * ubasestep) >> SHIFT16XYZ) *
r_affinetridesc.skinwidth;
d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF;
d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF;
for(i=0; i<3; i++)
d_lightbasestep[i] = r_lstepy[i] + working_lstepx[i] * ubasestep;
d_zibasestep = r_zistepy + r_zistepx * ubasestep;
d_ptexextrastep = ((r_sstepy + r_sstepx * (ubasestep + 1)) >> SHIFT16XYZ) +
((r_tstepy + r_tstepx * (ubasestep + 1)) >> SHIFT16XYZ) *
r_affinetridesc.skinwidth;
d_sfracextrastep = (r_sstepy+r_sstepx*(ubasestep + 1)) & 0xFFFF;
d_tfracextrastep = (r_tstepy+r_tstepx*(ubasestep + 1)) & 0xFFFF;
for(i=0; i<3; i++)
d_lightextrastep[i] = d_lightbasestep[i] + working_lstepx[i];
d_ziextrastep = d_zibasestep + r_zistepx;
R_PolysetScanLeftEdge_C(height, d_ptex, u, v);
}
}
// scan out the top (and possibly only) part of the right edge, updating the
// count field
R_PolysetSetUpForLineScan(prighttop->u, prighttop->v,
prightbottom->u, prightbottom->v);
d_aspancount = 0;
if ((triangle_spans + initialrightheight) >= triangles_max)
{
// we dont have enough triangles for save full height
r_outoftriangles = true; r_outoftriangles = true;
return; return;
} }
originalcount = triangle_spans[initialrightheight].count; // init span allocation ptr
triangle_spans[initialrightheight].count = INT_MIN; // mark end of the spanpackages d_pedgespanpackage = triangle_spans;
// 1. scan out the top (and possibly only) part of the left edge
R_ProcessLeftEdge(plefttop, prighttop, pleftbottom);
// 2. scan out the bottom part of the left edge, if it exists
if (pedgetable->numleftedges == 2)
{
plefttop = pleftbottom;
pleftbottom = pedgetable->pleftedgevert2;
R_ProcessLeftEdge(plefttop, prighttop, pleftbottom);
}
assert(d_pedgespanpackage <= triangles_max);
// 3. scan out the top (and possibly only) part of the right edge,
// drawing spans that terminate on it
rightheight = prightbottom->v - prighttop->v;
// reset u delta before drawing the top
d_aspancount = 0;
// save for step 4
pstart = &triangle_spans[rightheight];
originalcount = pstart->count;
// mark end of the spanpackages
pstart->count = INT_MIN;
R_PolysetSetUpForLineScan(prighttop->u, prighttop->v,
prightbottom->u, prightbottom->v);
(*d_pdrawspans) (currententity, triangle_spans); (*d_pdrawspans) (currententity, triangle_spans);
// scan out the bottom part of the right edge, if it exists // 4. scan out the bottom part of the right edge, if it exists
if (pedgetable->numrightedges == 2) if (pedgetable->numrightedges == 2)
{ {
int height; // 4.1 restore the starting span count
spanpackage_t *pstart;
pstart = triangle_spans + initialrightheight;
pstart->count = originalcount; pstart->count = originalcount;
d_aspancount = prightbottom->u - prighttop->u; d_aspancount = prightbottom->u - prighttop->u;
// 4.2 shift verts like in step 2
prighttop = prightbottom; prighttop = prightbottom;
prightbottom = pedgetable->prightedgevert2; prightbottom = pedgetable->prightedgevert2;
height = prightbottom->v - prighttop->v; // 4.3 increase right height
rightheight += prightbottom->v - prighttop->v;
// mark end of the spanpackages
triangle_spans[rightheight].count = INT_MIN;
R_PolysetSetUpForLineScan(prighttop->u, prighttop->v, R_PolysetSetUpForLineScan(prighttop->u, prighttop->v,
prightbottom->u, prightbottom->v); prightbottom->u, prightbottom->v);
if ((triangle_spans + initialrightheight + height) >= triangles_max)
{
// we dont have enough triangles for save full height
r_outoftriangles = true;
return;
}
triangle_spans[initialrightheight + height].count = INT_MIN; // mark end of the spanpackages
(*d_pdrawspans) (currententity, pstart); (*d_pdrawspans) (currententity, pstart);
} }
} }
/* /*
================ ================
R_PolysetSetEdgeTable R_PolysetSetEdgeTable