DS GX: Pay down tech debt around coordinates

This commit is contained in:
Vicki Pfau 2017-03-21 16:25:32 -07:00
parent 2a29a4dd58
commit 2b6ed2661e
4 changed files with 135 additions and 421 deletions

View File

@ -109,9 +109,7 @@ struct DSGXEntry {
struct DSGXVertex {
// World coords
int16_t x; // 4.12
int16_t y; // 4.12
int16_t z; // 4.12
int16_t coord[3]; // 4.12
// Color/Texcoords
uint16_t color; // 5.5.5
@ -119,10 +117,7 @@ struct DSGXVertex {
int16_t t; // 12.4
// Viewport coords
int32_t vx;
int32_t vy;
int32_t vz;
int32_t vw;
int32_t viewCoord[4];
int16_t vs; // 12.4
int16_t vt; // 12.4
};

View File

@ -49,9 +49,7 @@ struct DSGXSoftwareEdge {
};
struct DSGXSoftwareEndpoint {
int32_t x; // 20.12
int32_t z;
int32_t w;
int32_t coord[4]; // 20.12
int64_t wRecip;
uint8_t cr;
uint8_t cg;
@ -91,7 +89,7 @@ struct DSGXSoftwareRenderer {
uint8_t stencilBuffer[DS_VIDEO_HORIZONTAL_PIXELS];
color_t* scanlineCache;
bool flushPending;
bool wSort;
int sort;
struct DSGXVertex* verts;
};

View File

@ -25,15 +25,6 @@ static void DSGXWriteFIFO(struct DSGX* gx, struct DSGXEntry entry);
static bool _boxTestVertex(struct DSGX* gx, struct DSGXVertex* vertex);
enum CSCode {
CS_LEFT = 1,
CS_RIGHT = 2,
CS_BOTTOM = 4,
CS_TOP = 8,
CS_NEAR = 16,
CS_FAR = 32
};
static const int32_t _gxCommandCycleBase[DS_GX_CMD_MAX] = {
[DS_GX_CMD_NOP] = 0,
[DS_GX_CMD_MTX_MODE] = 2,
@ -195,22 +186,22 @@ static inline int32_t _lerp(int32_t x0, int32_t x1, int32_t q, int64_t r) {
return x;
}
static int _cohenSutherlandCode(const struct DSGX* gx, const struct DSGXVertex* v) {
static int _cohenSutherlandCode(const struct DSGXVertex* v) {
int code = 0;
if (v->vx < -v->vw) {
code |= CS_LEFT;
} else if (v->vx > v->vw) {
code |= CS_RIGHT;
if (v->viewCoord[0] < -v->viewCoord[3]) {
code |= 1 << 0;
} else if (v->viewCoord[0] > v->viewCoord[3]) {
code |= 2 << 0;
}
if (v->vy < -v->vw) {
code |= CS_BOTTOM;
} else if (v->vy > v->vw) {
code |= CS_TOP;
if (v->viewCoord[1] < -v->viewCoord[3]) {
code |= 1 << 2;
} else if (v->viewCoord[1] > v->viewCoord[3]) {
code |= 2 << 2;
}
if (v->vz < -v->vw) {
code |= CS_NEAR;
} else if (v->vz > v->vw) {
code |= CS_FAR;
if (v->viewCoord[2] < -v->viewCoord[3]) {
code |= 1 << 4;
} else if (v->viewCoord[2] > v->viewCoord[3]) {
code |= 2 << 4;
}
return code;
}
@ -230,31 +221,19 @@ static bool _lerpVertex(const struct DSGXVertex* v0, const struct DSGXVertex* v1
cb0 = _lerp(cb0, cb1, q, r) & 0x1F;
out->color = cr0 | (cg0 << 5) | (cb0 << 10);
out->vx = _lerp(v0->vx, v1->vx, q, r);
out->vy = _lerp(v0->vy, v1->vy, q, r);
out->vz = _lerp(v0->vz, v1->vz, q, r);
out->vw = _lerp(v0->vw, v1->vw, q, r);
out->viewCoord[0] = _lerp(v0->viewCoord[0], v1->viewCoord[0], q, r);
out->viewCoord[1] = _lerp(v0->viewCoord[1], v1->viewCoord[1], q, r);
out->viewCoord[2] = _lerp(v0->viewCoord[2], v1->viewCoord[2], q, r);
out->viewCoord[3] = _lerp(v0->viewCoord[3], v1->viewCoord[3], q, r);
out->vs = _lerp(v0->vs, v1->vs, q, r);
out->vt = _lerp(v0->vt, v1->vt, q, r);
return true;
}
static bool _lerpVertexX(const struct DSGXVertex* v0, const struct DSGXVertex* v1, struct DSGXVertex* out, int sign) {
int32_t q = v0->vw - sign * v0->vx;
int64_t r = q - (v1->vw - sign * v1->vx);
return _lerpVertex(v0, v1, out, q, r);
}
static bool _lerpVertexY(const struct DSGXVertex* v0, const struct DSGXVertex* v1, struct DSGXVertex* out, int sign) {
int32_t q = v0->vw - sign * v0->vy;
int64_t r = q - (v1->vw - sign * v1->vy);
return _lerpVertex(v0, v1, out, q, r);
}
static bool _lerpVertexZ(const struct DSGXVertex* v0, const struct DSGXVertex* v1, struct DSGXVertex* out, int sign) {
int32_t q = v0->vw - sign * v0->vz;
int64_t r = q - (v1->vw - sign * v1->vz);
static bool _lerpVertexP(const struct DSGXVertex* v0, const struct DSGXVertex* v1, struct DSGXVertex* out, int plane, int sign) {
int32_t q = v0->viewCoord[3] - sign * v0->viewCoord[plane];
int64_t r = q - (v1->viewCoord[3] - sign * v1->viewCoord[plane]);
return _lerpVertex(v0, v1, out, q, r);
}
@ -284,10 +263,10 @@ static bool _clipPolygon(struct DSGX* gx, struct DSGXPolygon* poly) {
v1 = &gx->pendingVertices[poly->vertIds[v + 1 - poly->verts]];
v2 = &gx->pendingVertices[poly->vertIds[v + 2 - poly->verts]];
}
nx = ((int64_t) v0->vy * v2->vw - (int64_t) v0->vw * v2->vy) >> 24;
ny = ((int64_t) v0->vw * v2->vx - (int64_t) v0->vx * v2->vw) >> 24;
nz = ((int64_t) v0->vx * v2->vy - (int64_t) v0->vy * v2->vx) >> 24;
dot += nx * v1->vx + ny * v1->vy + nz * v1->vw;
nx = ((int64_t) v0->viewCoord[1] * v2->viewCoord[3] - (int64_t) v0->viewCoord[3] * v2->viewCoord[1]) >> 24;
ny = ((int64_t) v0->viewCoord[3] * v2->viewCoord[0] - (int64_t) v0->viewCoord[0] * v2->viewCoord[3]) >> 24;
nz = ((int64_t) v0->viewCoord[0] * v2->viewCoord[1] - (int64_t) v0->viewCoord[1] * v2->viewCoord[0]) >> 24;
dot += nx * v1->viewCoord[0] + ny * v1->viewCoord[1] + nz * v1->viewCoord[3];
}
if (!DSGXPolygonAttrsIsBackFace(poly->polyParams) && dot < 0) {
return false;
@ -299,7 +278,7 @@ static bool _clipPolygon(struct DSGX* gx, struct DSGXPolygon* poly) {
// Collect offscreen vertices
for (v = 0; v < poly->verts; ++v) {
offscreenVerts[v] = _cohenSutherlandCode(gx, &gx->pendingVertices[poly->vertIds[v]]);
offscreenVerts[v] = _cohenSutherlandCode(&gx->pendingVertices[poly->vertIds[v]]);
oldVerts[v] = poly->vertIds[v];
if (offscreenVerts[v]) {
++nOffscreen;
@ -335,61 +314,11 @@ static bool _clipPolygon(struct DSGX* gx, struct DSGXPolygon* poly) {
int newV;
// Clip near
newV = 0;
for (v = 0; v < poly->verts; ++v) {
if (!(offscreenVerts[v] & CS_NEAR)) {
outList[newV] = inList[v];
outOffscreenVerts[newV] = offscreenVerts[v];
++newV;
} else {
struct DSGXVertex* in = &inList[v];
struct DSGXVertex* in2;
struct DSGXVertex* out;
int iv;
if (v > 0) {
iv = v - 1;
} else {
iv = poly->verts - 1;
}
if (!(offscreenVerts[iv] & CS_NEAR)) {
in2 = &inList[iv];
out = &outList[newV];
if (_lerpVertexZ(in, in2, out, -1)) {
outOffscreenVerts[newV] = _cohenSutherlandCode(gx, out);
++newV;
}
}
if (v < poly->verts - 1) {
iv = v + 1;
} else {
iv = 0;
}
if (!(offscreenVerts[iv] & CS_NEAR)) {
in2 = &inList[iv];
out = &outList[newV];
if (_lerpVertexZ(in, in2, out, -1)) {
outOffscreenVerts[newV] = _cohenSutherlandCode(gx, out);
++newV;
}
}
}
}
poly->verts = newV;
memcpy(inList, outList, newV * sizeof(*inList));
memcpy(offscreenVerts, outOffscreenVerts, newV * sizeof(*offscreenVerts));
// Clip far
newV = 0;
for (v = 0; v < poly->verts; ++v) {
if (!(offscreenVerts[v] & CS_FAR)) {
outList[newV] = inList[v];
outOffscreenVerts[newV] = offscreenVerts[v];
++newV;
} else {
if (!(offscreenVerts[v] & CS_NEAR)) {
int plane;
for (plane = 5; plane >= 0; --plane) {
newV = 0;
for (v = 0; v < poly->verts; ++v) {
if (!(offscreenVerts[v] & (1 << plane))) {
outList[newV] = inList[v];
outOffscreenVerts[newV] = offscreenVerts[v];
++newV;
@ -404,11 +333,11 @@ static bool _clipPolygon(struct DSGX* gx, struct DSGXPolygon* poly) {
} else {
iv = poly->verts - 1;
}
if (!(offscreenVerts[iv] & CS_FAR)) {
if (!(offscreenVerts[iv] & (1 << plane))) {
in2 = &inList[iv];
out = &outList[newV];
if (_lerpVertexZ(in, in2, out, 1)) {
outOffscreenVerts[newV] = _cohenSutherlandCode(gx, out);
if (_lerpVertexP(in, in2, out, plane >> 1, -1 + (plane & 1) * 2)) {
outOffscreenVerts[newV] = _cohenSutherlandCode(out);
++newV;
}
}
@ -418,204 +347,20 @@ static bool _clipPolygon(struct DSGX* gx, struct DSGXPolygon* poly) {
} else {
iv = 0;
}
if (!(offscreenVerts[iv] & CS_FAR)) {
if (!(offscreenVerts[iv] & (1 << plane))) {
in2 = &inList[iv];
out = &outList[newV];
if (_lerpVertexZ(in, in2, out, 1)) {
outOffscreenVerts[newV] = _cohenSutherlandCode(gx, out);
if (_lerpVertexP(in, in2, out, plane >> 1, -1 + (plane & 1) * 2)) {
outOffscreenVerts[newV] = _cohenSutherlandCode(out);
++newV;
}
}
}
}
poly->verts = newV;
memcpy(inList, outList, newV * sizeof(*inList));
memcpy(offscreenVerts, outOffscreenVerts, newV * sizeof(*offscreenVerts));
}
poly->verts = newV;
memcpy(inList, outList, newV * sizeof(*inList));
memcpy(offscreenVerts, outOffscreenVerts, newV * sizeof(*offscreenVerts));
// Clip left
newV = 0;
for (v = 0; v < poly->verts; ++v) {
if (!(offscreenVerts[v] & CS_LEFT)) {
outList[newV] = inList[v];
outOffscreenVerts[newV] = offscreenVerts[v];
++newV;
} else {
struct DSGXVertex* in = &inList[v];
struct DSGXVertex* in2;
struct DSGXVertex* out;
int iv;
if (v > 0) {
iv = v - 1;
} else {
iv = poly->verts - 1;
}
if (!(offscreenVerts[iv] & CS_LEFT)) {
in2 = &inList[iv];
out = &outList[newV];
if (_lerpVertexX(in, in2, out, -1)) {
outOffscreenVerts[newV] = _cohenSutherlandCode(gx, out);
++newV;
}
}
if (v < poly->verts - 1) {
iv = v + 1;
} else {
iv = 0;
}
if (!(offscreenVerts[iv] & CS_LEFT)) {
in2 = &inList[iv];
out = &outList[newV];
if (_lerpVertexX(in, in2, out, -1)) {
outOffscreenVerts[newV] = _cohenSutherlandCode(gx, out);
++newV;
}
}
}
}
poly->verts = newV;
memcpy(inList, outList, newV * sizeof(*inList));
memcpy(offscreenVerts, outOffscreenVerts, newV * sizeof(*offscreenVerts));
// Clip right
newV = 0;
for (v = 0; v < poly->verts; ++v) {
if (!(offscreenVerts[v] & CS_RIGHT)) {
outList[newV] = inList[v];
outOffscreenVerts[newV] = offscreenVerts[v];
++newV;
} else {
struct DSGXVertex* in = &inList[v];
struct DSGXVertex* in2;
struct DSGXVertex* out;
int iv;
if (v > 0) {
iv = v - 1;
} else {
iv = poly->verts - 1;
}
if (!(offscreenVerts[iv] & CS_RIGHT)) {
in2 = &inList[iv];
out = &outList[newV];
if (_lerpVertexX(in, in2, out, 1)) {
outOffscreenVerts[newV] = _cohenSutherlandCode(gx, out);
++newV;
}
}
if (v < poly->verts - 1) {
iv = v + 1;
} else {
iv = 0;
}
if (!(offscreenVerts[iv] & CS_RIGHT)) {
in2 = &inList[iv];
out = &outList[newV];
if (_lerpVertexX(in, in2, out, 1)) {
outOffscreenVerts[newV] = _cohenSutherlandCode(gx, out);
++newV;
}
}
}
}
poly->verts = newV;
memcpy(inList, outList, newV * sizeof(*inList));
memcpy(offscreenVerts, outOffscreenVerts, newV * sizeof(*offscreenVerts));
// Clip bottom
newV = 0;
for (v = 0; v < poly->verts; ++v) {
if (!(offscreenVerts[v] & CS_BOTTOM)) {
outList[newV] = inList[v];
outOffscreenVerts[newV] = offscreenVerts[v];
++newV;
} else {
struct DSGXVertex* in = &inList[v];
struct DSGXVertex* in2;
struct DSGXVertex* out;
int iv;
if (v > 0) {
iv = v - 1;
} else {
iv = poly->verts - 1;
}
if (!(offscreenVerts[iv] & CS_BOTTOM)) {
in2 = &inList[iv];
out = &outList[newV];
if (_lerpVertexY(in, in2, out, -1)) {
outOffscreenVerts[newV] = _cohenSutherlandCode(gx, out);
++newV;
}
}
if (v < poly->verts - 1) {
iv = v + 1;
} else {
iv = 0;
}
if (!(offscreenVerts[iv] & CS_BOTTOM)) {
in2 = &inList[iv];
out = &outList[newV];
if (_lerpVertexY(in, in2, out, -1)) {
outOffscreenVerts[newV] = _cohenSutherlandCode(gx, out);
++newV;
}
}
}
}
poly->verts = newV;
memcpy(inList, outList, newV * sizeof(*inList));
memcpy(offscreenVerts, outOffscreenVerts, newV * sizeof(*offscreenVerts));
// Clip top
newV = 0;
for (v = 0; v < poly->verts; ++v) {
if (!(offscreenVerts[v] & CS_TOP)) {
outList[newV] = inList[v];
outOffscreenVerts[newV] = offscreenVerts[v];
++newV;
} else {
struct DSGXVertex* in = &inList[v];
struct DSGXVertex* in2;
struct DSGXVertex* out;
int iv;
if (v > 0) {
iv = v - 1;
} else {
iv = poly->verts - 1;
}
if (!(offscreenVerts[iv] & CS_TOP)) {
in2 = &inList[iv];
out = &outList[newV];
if (_lerpVertexY(in, in2, out, 1)) {
outOffscreenVerts[newV] = _cohenSutherlandCode(gx, out);
++newV;
}
}
if (v < poly->verts - 1) {
iv = v + 1;
} else {
iv = 0;
}
if (!(offscreenVerts[iv] & CS_TOP)) {
in2 = &inList[iv];
out = &outList[newV];
if (_lerpVertexY(in, in2, out, 1)) {
outOffscreenVerts[newV] = _cohenSutherlandCode(gx, out);
++newV;
}
}
}
}
poly->verts = newV;
memcpy(inList, outList, newV * sizeof(*inList));
memcpy(offscreenVerts, outOffscreenVerts, newV * sizeof(*offscreenVerts));
for (v = 0; v < poly->verts; ++v) {
if (gx->vertexIndex == DS_GX_VERTEX_BUFFER_SIZE) {
@ -635,13 +380,13 @@ static int32_t _dotViewport(struct DSGXVertex* vertex, int32_t* col) {
int64_t b;
int64_t sum;
a = col[0];
b = vertex->x;
b = vertex->coord[0];
sum = a * b;
a = col[4];
b = vertex->y;
b = vertex->coord[1];
sum += a * b;
a = col[8];
b = vertex->z;
b = vertex->coord[2];
sum += a * b;
a = col[12];
b = MTX_ONE;
@ -672,13 +417,13 @@ static int16_t _dotTexture(struct DSGXVertex* vertex, int mode, int32_t* col) {
return 0;
case 3:
a = col[0];
b = vertex->vx << 8;
b = vertex->viewCoord[0] << 8;
sum = a * b;
a = col[4];
b = vertex->vy << 8;
b = vertex->viewCoord[1] << 8;
sum += a * b;
a = col[8];
b = vertex->vz << 8;
b = vertex->viewCoord[2] << 8;
sum += a * b;
a = col[12];
b = MTX_ONE;
@ -720,13 +465,13 @@ static void _emitVertex(struct DSGX* gx, uint16_t x, uint16_t y, uint16_t z) {
if (gx->vertexMode < 0 || gx->vertexIndex == DS_GX_VERTEX_BUFFER_SIZE || gx->polygonIndex == DS_GX_POLYGON_BUFFER_SIZE) {
return;
}
gx->currentVertex.x = x;
gx->currentVertex.y = y;
gx->currentVertex.z = z;
gx->currentVertex.vx = _dotViewport(&gx->currentVertex, &gx->clipMatrix.m[0]);
gx->currentVertex.vy = _dotViewport(&gx->currentVertex, &gx->clipMatrix.m[1]);
gx->currentVertex.vz = _dotViewport(&gx->currentVertex, &gx->clipMatrix.m[2]);
gx->currentVertex.vw = _dotViewport(&gx->currentVertex, &gx->clipMatrix.m[3]);
gx->currentVertex.coord[0] = x;
gx->currentVertex.coord[1] = y;
gx->currentVertex.coord[2] = z;
gx->currentVertex.viewCoord[0] = _dotViewport(&gx->currentVertex, &gx->clipMatrix.m[0]);
gx->currentVertex.viewCoord[1] = _dotViewport(&gx->currentVertex, &gx->clipMatrix.m[1]);
gx->currentVertex.viewCoord[2] = _dotViewport(&gx->currentVertex, &gx->clipMatrix.m[2]);
gx->currentVertex.viewCoord[3] = _dotViewport(&gx->currentVertex, &gx->clipMatrix.m[3]);
if (DSGXTexParamsGetCoordTfMode(gx->currentPoly.texParams) == 0) {
gx->currentVertex.vs = gx->currentVertex.s;
@ -861,49 +606,47 @@ static bool _boxTest(struct DSGX* gx) {
d |= gx->activeEntries[2].params[3] << 8;
struct DSGXVertex vertex = {
.x = x,
.y = y,
.z = z
.coord = { x, y, z }
};
if (_boxTestVertex(gx, &vertex)) {
return true;
}
vertex.x += w;
vertex.coord[0] += w;
if (_boxTestVertex(gx, &vertex)) {
return true;
}
vertex.x = x;
vertex.y += h;
vertex.coord[0] = x;
vertex.coord[1] += h;
if (_boxTestVertex(gx, &vertex)) {
return true;
}
vertex.x += w;
vertex.coord[0] += w;
if (_boxTestVertex(gx, &vertex)) {
return true;
}
vertex.x = x;
vertex.y = y;
vertex.z += d;
vertex.coord[0] = x;
vertex.coord[1] = y;
vertex.coord[2] += d;
if (_boxTestVertex(gx, &vertex)) {
return true;
}
vertex.x += w;
vertex.coord[0] += w;
if (_boxTestVertex(gx, &vertex)) {
return true;
}
vertex.x = x;
vertex.y += h;
vertex.coord[0] = x;
vertex.coord[1] += h;
if (_boxTestVertex(gx, &vertex)) {
return true;
}
vertex.x += w;
vertex.coord[0] += w;
if (_boxTestVertex(gx, &vertex)) {
return true;
}
@ -1391,7 +1134,7 @@ static void _fifoRun(struct mTiming* timing, void* context, uint32_t cyclesLate)
x |= entry.params[1] << 8;
int16_t y = entry.params[2];
y |= entry.params[3] << 8;
_emitVertex(gx, x, y, gx->currentVertex.z);
_emitVertex(gx, x, y, gx->currentVertex.coord[2]);
break;
}
case DS_GX_CMD_VTX_XZ: {
@ -1399,7 +1142,7 @@ static void _fifoRun(struct mTiming* timing, void* context, uint32_t cyclesLate)
x |= entry.params[1] << 8;
int16_t z = entry.params[2];
z |= entry.params[3] << 8;
_emitVertex(gx, x, gx->currentVertex.y, z);
_emitVertex(gx, x, gx->currentVertex.coord[1], z);
break;
}
case DS_GX_CMD_VTX_YZ: {
@ -1407,7 +1150,7 @@ static void _fifoRun(struct mTiming* timing, void* context, uint32_t cyclesLate)
y |= entry.params[1] << 8;
int16_t z = entry.params[2];
z |= entry.params[3] << 8;
_emitVertex(gx, gx->currentVertex.x, y, z);
_emitVertex(gx, gx->currentVertex.coord[0], y, z);
break;
}
case DS_GX_CMD_VTX_DIFF: {
@ -1418,7 +1161,9 @@ static void _fifoRun(struct mTiming* timing, void* context, uint32_t cyclesLate)
int16_t x = (xyz << 6) & 0xFFC0;
int16_t y = (xyz >> 4) & 0xFFC0;
int16_t z = (xyz >> 14) & 0xFFC0;
_emitVertex(gx, gx->currentVertex.x + (x >> 6), gx->currentVertex.y + (y >> 6), gx->currentVertex.z + (z >> 6));
_emitVertex(gx, gx->currentVertex.coord[0] + (x >> 6),
gx->currentVertex.coord[1] + (y >> 6),
gx->currentVertex.coord[2] + (z >> 6));
break;
}
case DS_GX_CMD_DIF_AMB:

View File

@ -300,16 +300,16 @@ static bool _edgeToSpan(struct DSGXSoftwareSpan* span, const struct DSGXSoftware
return false;
}
span->ep[index].x = (((int64_t) (edge->x1 - edge->x0) * yw) / height) + edge->x0;
span->ep[index].coord[0] = (((int64_t) (edge->x1 - edge->x0) * yw) / height) + edge->x0;
if (index) {
if (span->ep[0].x == span->ep[index].x) {
if (span->ep[0].coord[0] == span->ep[index].coord[0]) {
return false;
}
if (span->ep[0].x > span->ep[index].x) {
int32_t temp = span->ep[index].x;
if (span->ep[0].coord[0] > span->ep[index].coord[0]) {
int32_t temp = span->ep[index].coord[0];
span->ep[index] = span->ep[0];
span->ep[0].x = temp;
span->ep[0].coord[0] = temp;
index = 0;
}
}
@ -329,11 +329,11 @@ static bool _edgeToSpan(struct DSGXSoftwareSpan* span, const struct DSGXSoftware
w += div;
w += w0;
span->ep[index].w = 0x7FFFFFFFFFFFFFFF / w;
span->ep[index].coord[3] = 0x7FFFFFFFFFFFFFFF / w;
span->ep[index].wRecip = w;
int32_t qr = (yw << 12) / height;
span->ep[index].z = _interpolate(edge->z0, edge->z1, w0, w1, w, qr);
span->ep[index].coord[2] = _interpolate(edge->z0, edge->z1, w0, w1, w, qr);
span->ep[index].cr = _interpolate(edge->cr0, edge->cr1, w0, w1, w, qr);
span->ep[index].cg = _interpolate(edge->cg0, edge->cg1, w0, w1, w, qr);
span->ep[index].cb = _interpolate(edge->cb0, edge->cb1, w0, w1, w, qr);
@ -344,10 +344,10 @@ static bool _edgeToSpan(struct DSGXSoftwareSpan* span, const struct DSGXSoftware
}
static void _createStep(struct DSGXSoftwareSpan* span) {
int32_t width = (span->ep[1].x - span->ep[0].x) >> 7;
int32_t width = (span->ep[1].coord[0] - span->ep[0].coord[0]) >> 7;
span->ep[0].stepW = span->ep[0].wRecip;
span->ep[0].stepZ = span->ep[0].z * span->ep[0].wRecip;
span->ep[0].stepZ = span->ep[0].coord[2] * span->ep[0].wRecip;
span->ep[0].stepR = span->ep[0].cr * span->ep[0].wRecip;
span->ep[0].stepG = span->ep[0].cg * span->ep[0].wRecip;
span->ep[0].stepB = span->ep[0].cb * span->ep[0].wRecip;
@ -355,7 +355,7 @@ static void _createStep(struct DSGXSoftwareSpan* span) {
span->ep[0].stepT = span->ep[0].t * span->ep[0].wRecip;
span->ep[1].stepW = span->ep[1].wRecip;
span->ep[1].stepZ = span->ep[1].z * span->ep[1].wRecip;
span->ep[1].stepZ = span->ep[1].coord[2] * span->ep[1].wRecip;
span->ep[1].stepR = span->ep[1].cr * span->ep[1].wRecip;
span->ep[1].stepG = span->ep[1].cg * span->ep[1].wRecip;
span->ep[1].stepB = span->ep[1].cb * span->ep[1].wRecip;
@ -365,7 +365,7 @@ static void _createStep(struct DSGXSoftwareSpan* span) {
if (!width) {
return;
}
span->step.x = span->ep[1].x - span->ep[0].x;
span->step.coord[0] = span->ep[1].coord[0] - span->ep[0].coord[0];
span->step.stepW = (span->ep[1].stepW - span->ep[0].stepW) / width;
span->step.stepZ = (span->ep[1].stepZ - span->ep[0].stepZ) / width;
span->step.stepR = (span->ep[1].stepR - span->ep[0].stepR) / width;
@ -377,32 +377,32 @@ static void _createStep(struct DSGXSoftwareSpan* span) {
static void _stepEndpoint(struct DSGXSoftwareSpan* span) {
int i = 28;
int32_t nextX = (span->ep[0].x & ~0xFFF) + 0x1000;
span->ep[0].x += 0x80 * i;
while (span->ep[0].x < nextX) {
span->ep[0].x += 0x80;
int32_t nextX = (span->ep[0].coord[0] & ~0xFFF) + 0x1000;
span->ep[0].coord[0] += 0x80 * i;
while (span->ep[0].coord[0] < nextX) {
span->ep[0].coord[0] += 0x80;
++i;
}
span->ep[0].wRecip += span->step.stepW * i;
span->ep[0].w = (0x7FFFFFFFFFFFFFFF / span->ep[0].wRecip) + 1;
span->ep[0].coord[3] = (0x7FFFFFFFFFFFFFFF / span->ep[0].wRecip) + 1;
span->ep[0].stepZ += span->step.stepZ * i;
span->ep[0].z = _divideBy(span->ep[0].stepZ, span->ep[0].w);
span->ep[0].coord[2] = _divideBy(span->ep[0].stepZ, span->ep[0].coord[3]);
span->ep[0].stepR += span->step.stepR * i;
span->ep[0].cr = _divideBy(span->ep[0].stepR, span->ep[0].w);
span->ep[0].cr = _divideBy(span->ep[0].stepR, span->ep[0].coord[3]);
span->ep[0].stepG += span->step.stepG * i;
span->ep[0].cg = _divideBy(span->ep[0].stepG, span->ep[0].w);
span->ep[0].cg = _divideBy(span->ep[0].stepG, span->ep[0].coord[3]);
span->ep[0].stepB += span->step.stepB * i;
span->ep[0].cb = _divideBy(span->ep[0].stepB, span->ep[0].w);
span->ep[0].cb = _divideBy(span->ep[0].stepB, span->ep[0].coord[3]);
span->ep[0].stepS += span->step.stepS * i;
span->ep[0].s = _divideBy(span->ep[0].stepS, span->ep[0].w);
span->ep[0].s = _divideBy(span->ep[0].stepS, span->ep[0].coord[3]);
span->ep[0].stepT += span->step.stepT * i;
span->ep[0].t = _divideBy(span->ep[0].stepT, span->ep[0].w);
span->ep[0].t = _divideBy(span->ep[0].stepT, span->ep[0].coord[3]);
}
void DSGXSoftwareRendererCreate(struct DSGXSoftwareRenderer* renderer) {
@ -475,44 +475,44 @@ static void _preparePoly(struct DSGXRenderer* renderer, struct DSGXVertex* verts
struct DSGXVertex* v0 = &verts[poly->poly->vertIds[0]];
struct DSGXVertex* v1;
int32_t v0x = (v0->vx + v0->vw) * (int64_t) (renderer->viewportWidth << 12) / (v0->vw * 2) + (renderer->viewportX << 12);
int32_t v0y = (-v0->vy + v0->vw) * (int64_t) (renderer->viewportHeight << 12) / (v0->vw * 2) + (renderer->viewportY << 12);
int32_t v0x = (v0->viewCoord[0] + v0->viewCoord[3]) * (int64_t) (renderer->viewportWidth << 12) / (v0->viewCoord[3] * 2) + (renderer->viewportX << 12);
int32_t v0y = (-v0->viewCoord[1] + v0->viewCoord[3]) * (int64_t) (renderer->viewportHeight << 12) / (v0->viewCoord[3] * 2) + (renderer->viewportY << 12);
int v;
for (v = 1; v < poly->poly->verts; ++v) {
v1 = &verts[poly->poly->vertIds[v]];
int32_t v1x = (v1->vx + v1->vw) * (int64_t) (renderer->viewportWidth << 12) / (v1->vw * 2) + (renderer->viewportX << 12);
int32_t v1y = (-v1->vy + v1->vw) * (int64_t) (renderer->viewportHeight << 12) / (v1->vw * 2) + (renderer->viewportY << 12);
int32_t v1x = (v1->viewCoord[0] + v1->viewCoord[3]) * (int64_t) (renderer->viewportWidth << 12) / (v1->viewCoord[3] * 2) + (renderer->viewportX << 12);
int32_t v1y = (-v1->viewCoord[1] + v1->viewCoord[3]) * (int64_t) (renderer->viewportHeight << 12) / (v1->viewCoord[3] * 2) + (renderer->viewportY << 12);
if (v0y <= v1y) {
edge->y0 = v0y;
edge->x0 = v0x;
edge->z0 = v0->vz;
edge->w0 = v0->vw;
edge->z0 = v0->viewCoord[2];
edge->w0 = v0->viewCoord[3];
_expandColor(v0->color, &edge->cr0, &edge->cg0, &edge->cb0);
edge->s0 = v0->vs;
edge->t0 = v0->vt;
edge->y1 = v1y;
edge->x1 = v1x;
edge->z1 = v1->vz;
edge->w1 = v1->vw;
edge->z1 = v1->viewCoord[2];
edge->w1 = v1->viewCoord[3];
_expandColor(v1->color, &edge->cr1, &edge->cg1, &edge->cb1);
edge->s1 = v1->vs;
edge->t1 = v1->vt;
} else {
edge->y0 = v1y;
edge->x0 = v1x;
edge->z0 = v1->vz;
edge->w0 = v1->vw;
edge->z0 = v1->viewCoord[2];
edge->w0 = v1->viewCoord[3];
_expandColor(v1->color, &edge->cr0, &edge->cg0, &edge->cb0);
edge->s0 = v1->vs;
edge->t0 = v1->vt;
edge->y1 = v0y;
edge->x1 = v0x;
edge->z1 = v0->vz;
edge->w1 = v0->vw;
edge->z1 = v0->viewCoord[2];
edge->w1 = v0->viewCoord[3];
_expandColor(v0->color, &edge->cr1, &edge->cg1, &edge->cb1);
edge->s1 = v0->vs;
edge->t1 = v0->vt;
@ -526,38 +526,38 @@ static void _preparePoly(struct DSGXRenderer* renderer, struct DSGXVertex* verts
}
v1 = &verts[poly->poly->vertIds[0]];
int32_t v1x = (v1->vx + v1->vw) * (int64_t) (renderer->viewportWidth << 12) / (v1->vw * 2) + (renderer->viewportX << 12);
int32_t v1y = (-v1->vy + v1->vw) * (int64_t) (renderer->viewportHeight << 12) / (v1->vw * 2) + (renderer->viewportY << 12);
int32_t v1x = (v1->viewCoord[0] + v1->viewCoord[3]) * (int64_t) (renderer->viewportWidth << 12) / (v1->viewCoord[3] * 2) + (renderer->viewportX << 12);
int32_t v1y = (-v1->viewCoord[1] + v1->viewCoord[3]) * (int64_t) (renderer->viewportHeight << 12) / (v1->viewCoord[3] * 2) + (renderer->viewportY << 12);
if (v0y <= v1y) {
edge->y0 = v0y;
edge->x0 = v0x;
edge->z0 = v0->vz;
edge->w0 = v0->vw;
edge->z0 = v0->viewCoord[2];
edge->w0 = v0->viewCoord[3];
_expandColor(v0->color, &edge->cr0, &edge->cg0, &edge->cb0);
edge->s0 = v0->vs;
edge->t0 = v0->vt;
edge->y1 = v1y;
edge->x1 = v1x;
edge->z1 = v1->vz;
edge->w1 = v1->vw;
edge->z1 = v1->viewCoord[2];
edge->w1 = v1->viewCoord[3];
_expandColor(v1->color, &edge->cr1, &edge->cg1, &edge->cb1);
edge->s1 = v1->vs;
edge->t1 = v1->vt;
} else {
edge->y0 = v1y;
edge->x0 = v1x;
edge->z0 = v1->vz;
edge->w0 = v1->vw;
edge->z0 = v1->viewCoord[2];
edge->w0 = v1->viewCoord[3];
_expandColor(v1->color, &edge->cr0, &edge->cg0, &edge->cb0);
edge->s0 = v1->vs;
edge->t0 = v1->vt;
edge->y1 = v0y;
edge->x1 = v0x;
edge->z1 = v0->vz;
edge->w1 = v0->vw;
edge->z1 = v0->viewCoord[2];
edge->w1 = v0->viewCoord[3];
_expandColor(v0->color, &edge->cr1, &edge->cg1, &edge->cb1);
edge->s1 = v0->vs;
edge->t1 = v0->vt;
@ -568,7 +568,7 @@ static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSG
struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
softwareRenderer->flushPending = true;
softwareRenderer->wSort = wSort;
softwareRenderer->sort = wSort ? 3 : 2;
softwareRenderer->verts = verts;
DSGXSoftwarePolygonListClear(&softwareRenderer->activePolys);
DSGXSoftwareEdgeListClear(&softwareRenderer->activeEdges);
@ -631,7 +631,7 @@ static void DSGXSoftwareRendererDrawScanline(struct DSGXRenderer* renderer, int
unsigned poly = edge->polyId;
struct DSGXSoftwareSpan* span = softwareRenderer->bucket[poly];
if (span && !span->ep[1].w) {
if (span && !span->ep[1].coord[3]) {
if (_edgeToSpan(span, edge, 1, y << 12)) {
_createStep(span);
softwareRenderer->bucket[poly] = NULL;
@ -663,11 +663,11 @@ static void DSGXSoftwareRendererDrawScanline(struct DSGXRenderer* renderer, int
for (i = 0; i < DSGXSoftwareSpanListSize(&softwareRenderer->activeSpans); ++i) {
struct DSGXSoftwareSpan* span = DSGXSoftwareSpanListGetPointer(&softwareRenderer->activeSpans, i);
int32_t x = span->ep[0].x >> 12;
int32_t x = span->ep[0].coord[0] >> 12;
if (x < 0) {
x = 0;
}
for (; x < (span->ep[1].x >> 12) && x < DS_VIDEO_HORIZONTAL_PIXELS; ++x) {
for (; x < (span->ep[1].coord[0] >> 12) && x < DS_VIDEO_HORIZONTAL_PIXELS; ++x) {
color_t color = _lookupColor(softwareRenderer, &span->ep[0], span->poly);
_stepEndpoint(span);
unsigned a = color >> 27;
@ -682,24 +682,13 @@ static void DSGXSoftwareRendererDrawScanline(struct DSGXRenderer* renderer, int
s |= 0x40;
}
if (a == 0x1F) {
if (softwareRenderer->wSort) {
if (span->ep[0].w < softwareRenderer->depthBuffer[x]) {
if (!(s & 0x40) || !(softwareRenderer->stencilBuffer[x] & s & 0x40)) {
softwareRenderer->depthBuffer[x] = span->ep[0].w;
scanline[x] = color;
s &= ~0x40;
}
softwareRenderer->stencilBuffer[x] = s;
}
} else {
if (span->ep[0].z < softwareRenderer->depthBuffer[x]) {
if (!(s & 0x40) || !(softwareRenderer->stencilBuffer[x] & s & 0x40)) {
softwareRenderer->depthBuffer[x] = span->ep[0].z;
scanline[x] = color;
s &= ~0x40;
}
softwareRenderer->stencilBuffer[x] = s;
if (span->ep[0].coord[softwareRenderer->sort] < softwareRenderer->depthBuffer[x]) {
if (s != 0x40 && !(softwareRenderer->stencilBuffer[x] & 0x40)) {
softwareRenderer->depthBuffer[x] = span->ep[0].coord[softwareRenderer->sort];
scanline[x] = color;
s &= ~0x40;
}
softwareRenderer->stencilBuffer[x] = s;
}
} else if (a) {
// TODO: Disable alpha?
@ -708,28 +697,15 @@ static void DSGXSoftwareRendererDrawScanline(struct DSGXRenderer* renderer, int
color |= ab << 27;
}
if (softwareRenderer->stencilBuffer[x] != s) {
if (softwareRenderer->wSort) {
if (span->ep[0].w < softwareRenderer->depthBuffer[x]) {
if (s != 0x40 && !(softwareRenderer->stencilBuffer[x] & 0x40)) {
if (DSGXPolygonAttrsIsUpdateDepth(span->poly->poly->polyParams)) {
softwareRenderer->depthBuffer[x] = span->ep[0].w;
}
scanline[x] = color;
s &= ~0x40;
if (span->ep[0].coord[softwareRenderer->sort] < softwareRenderer->depthBuffer[x]) {
if (s != 0x40 && !(softwareRenderer->stencilBuffer[x] & 0x40)) {
if (DSGXPolygonAttrsIsUpdateDepth(span->poly->poly->polyParams)) {
softwareRenderer->depthBuffer[x] = span->ep[0].coord[softwareRenderer->sort];
}
softwareRenderer->stencilBuffer[x] = s;
}
} else {
if (span->ep[0].z < softwareRenderer->depthBuffer[x]) {
if (s != 0x40 && !(softwareRenderer->stencilBuffer[x] & 0x40)) {
if (DSGXPolygonAttrsIsUpdateDepth(span->poly->poly->polyParams)) {
softwareRenderer->depthBuffer[x] = span->ep[0].z;
}
scanline[x] = color;
s &= ~0x40;
}
softwareRenderer->stencilBuffer[x] = s;
scanline[x] = color;
s &= ~0x40;
}
softwareRenderer->stencilBuffer[x] = s;
}
}
}