diff --git a/src/client/refresh/soft/sw_polyset.c b/src/client/refresh/soft/sw_polyset.c index 0f77c7da..30fc46c4 100644 --- a/src/client/refresh/soft/sw_polyset.c +++ b/src/client/refresh/soft/sw_polyset.c @@ -24,7 +24,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include typedef struct { - int isflattop; int numleftedges; compactvert_t *pleftedgevert0; compactvert_t *pleftedgevert1; @@ -44,18 +43,18 @@ static int d_xdenom; static edgetable *pedgetable; static edgetable edgetables[12] = { - {0, 1, &r_p0, &r_p2, NULL, 2, &r_p0, &r_p1, &r_p2}, - {0, 2, &r_p1, &r_p0, &r_p2, 1, &r_p1, &r_p2, NULL}, - {1, 1, &r_p0, &r_p2, NULL, 1, &r_p1, &r_p2, NULL}, - {0, 1, &r_p1, &r_p0, NULL, 2, &r_p1, &r_p2, &r_p0}, - {0, 2, &r_p0, &r_p2, &r_p1, 1, &r_p0, &r_p1, NULL}, - {0, 1, &r_p2, &r_p1, NULL, 1, &r_p2, &r_p0, NULL}, - {0, 1, &r_p2, &r_p1, NULL, 2, &r_p2, &r_p0, &r_p1}, - {0, 2, &r_p2, &r_p1, &r_p0, 1, &r_p2, &r_p0, NULL}, - {0, 1, &r_p1, &r_p0, NULL, 1, &r_p1, &r_p2, NULL}, - {1, 1, &r_p2, &r_p1, NULL, 1, &r_p0, &r_p1, NULL}, - {1, 1, &r_p1, &r_p0, NULL, 1, &r_p2, &r_p0, NULL}, - {0, 1, &r_p0, &r_p2, NULL, 1, &r_p0, &r_p1, NULL}, + {1, &r_p0, &r_p2, &r_p2, 2, &r_p0, &r_p1, &r_p2}, + {2, &r_p1, &r_p0, &r_p2, 1, &r_p1, &r_p2, &r_p2}, + {1, &r_p0, &r_p2, &r_p2, 1, &r_p1, &r_p2, &r_p2}, // flat top + {1, &r_p1, &r_p0, &r_p0, 2, &r_p1, &r_p2, &r_p0}, + {2, &r_p0, &r_p2, &r_p1, 1, &r_p0, &r_p1, &r_p1}, + {1, &r_p2, &r_p1, &r_p1, 1, &r_p2, &r_p0, &r_p0}, + {1, &r_p2, &r_p1, &r_p1, 2, &r_p2, &r_p0, &r_p1}, + {2, &r_p2, &r_p1, &r_p0, 1, &r_p2, &r_p0, &r_p0}, + {1, &r_p1, &r_p0, &r_p0, 1, &r_p1, &r_p2, &r_p2}, + {1, &r_p2, &r_p1, &r_p1, 1, &r_p0, &r_p1, &r_p1}, // flat top + {1, &r_p1, &r_p0, &r_p0, 1, &r_p2, &r_p0, &r_p0}, // flat top + {1, &r_p0, &r_p2, &r_p2, 1, &r_p0, &r_p1, &r_p1}, }; // FIXME: some of these can become statics @@ -200,13 +199,6 @@ static void 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) { - if (d_pedgespanpackage >= triangles_max) - { - // no space any more - r_outoftriangles = true; - return; - } - d_pedgespanpackage->u = u; d_pedgespanpackage->v = v; d_pedgespanpackage->count = count; @@ -299,6 +291,41 @@ quotient must fit in 32 bits. 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 FloorDivMod (float numer, float denom, int *quotient, int *rem) @@ -331,7 +358,7 @@ FloorDivMod (float numer, float denom, int *quotient, *quotient = q; *rem = r; } - +#endif /* =================== @@ -342,20 +369,17 @@ static void R_PolysetSetUpForLineScan(fixed8_t startvertu, fixed8_t startvertv, fixed8_t endvertu, fixed8_t endvertv) { - float tm, tn; - - errorterm = -1; + int tm, tn; tm = endvertu - startvertu; tn = endvertv - startvertv; - FloorDivMod (tm, tn, &ubasestep, &erroradjustup); - + errorterm = -1; erroradjustdown = tn; + + FloorDivMod (tm, tn, &ubasestep, &erroradjustup); } - - /* ================ R_PolysetCalcGradients @@ -492,7 +516,7 @@ R_PolysetDrawSpans8_33(const entity_t *currententity, spanpackage_t *pspanpackag } pspanpackage++; - } while ((pspanpackage < triangles_max) && (pspanpackage->count != INT_MIN)); + } while (pspanpackage->count != INT_MIN); } void @@ -539,7 +563,7 @@ R_PolysetDrawSpansConstant8_33(const entity_t *currententity, spanpackage_t *psp } pspanpackage++; - } while ((pspanpackage < triangles_max) && (pspanpackage->count != INT_MIN)); + } while (pspanpackage->count != INT_MIN); } void @@ -621,7 +645,7 @@ R_PolysetDrawSpans8_66(const entity_t *currententity, spanpackage_t *pspanpackag } pspanpackage++; - } while ((pspanpackage < triangles_max) && (pspanpackage->count != INT_MIN)); + } while (pspanpackage->count != INT_MIN); } void @@ -679,7 +703,7 @@ R_PolysetDrawSpansConstant8_66(const entity_t *currententity, spanpackage_t *psp } pspanpackage++; - } while ((pspanpackage < triangles_max) && (pspanpackage->count != INT_MIN)); + } while (pspanpackage->count != INT_MIN); } void @@ -762,7 +786,79 @@ R_PolysetDrawSpans8_Opaque (const entity_t *currententity, spanpackage_t *pspanp } 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 R_RasterizeAliasPolySmooth(const entity_t *currententity) { - int initialleftheight, initialrightheight; - compactvert_t *plefttop, *prighttop, *pleftbottom, *prightbottom; - light3_t working_lstepx; + compactvert_t *plefttop, *prighttop, *pleftbottom, *prightbottom; + spanpackage_t *pstart; int originalcount; - int u, v; - pixel_t *d_ptex; + int leftheight, rightheight; + + // 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; prighttop = pedgetable->prightedgevert0; @@ -786,204 +884,76 @@ R_RasterizeAliasPolySmooth(const entity_t *currententity) pleftbottom = pedgetable->pleftedgevert1; prightbottom = pedgetable->prightedgevert1; - initialleftheight = pleftbottom->v - plefttop->v; - initialrightheight = prightbottom->v - prighttop->v; - - // - // 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); - // - // 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; + // make sure we have enough spans for the full height + // plus 1 more for the list terminator. + // vert2 in the edgetable is always the lowest. + // (this is silly anyway, just allocate vid.height+1) + leftheight = pedgetable->pleftedgevert2->v - plefttop->v; + rightheight = pedgetable->prightedgevert2->v - prighttop->v; + if (leftheight < rightheight) + leftheight = rightheight; + if (&triangle_spans[leftheight] >= triangles_max) { - 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; return; } - originalcount = triangle_spans[initialrightheight].count; - triangle_spans[initialrightheight].count = INT_MIN; // mark end of the spanpackages + // init span allocation ptr + 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); - // 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) { - int height; - spanpackage_t *pstart; - - pstart = triangle_spans + initialrightheight; + // 4.1 restore the starting span count pstart->count = originalcount; d_aspancount = prightbottom->u - prighttop->u; + // 4.2 shift verts like in step 2 prighttop = prightbottom; 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, - 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 + prightbottom->u, prightbottom->v); (*d_pdrawspans) (currententity, pstart); } } - /* ================ R_PolysetSetEdgeTable