all repos — mgba @ 30cac2e24b271277d66b42041b0c8a5a95a89f6b

mGBA Game Boy Advance Emulator

DS GX: Add z-depth sorting
Vicki Pfau vi@endrift.com
Fri, 03 Mar 2017 04:00:47 -0800
commit

30cac2e24b271277d66b42041b0c8a5a95a89f6b

parent

c5157bda7f0f7bea246b88053629f36bcb4fbd74

M include/mgba/internal/ds/gx.hinclude/mgba/internal/ds/gx.h

@@ -131,7 +131,7 @@ void (*reset)(struct DSGXRenderer* renderer);

void (*deinit)(struct DSGXRenderer* renderer); void (*invalidateTex)(struct DSGXRenderer* renderer, int slot); - void (*setRAM)(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount); + void (*setRAM)(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount, bool wSort); void (*drawScanline)(struct DSGXRenderer* renderer, int y); void (*getScanline)(struct DSGXRenderer* renderer, int y, color_t** output);

@@ -156,6 +156,7 @@ int activeParams;

struct DSGXEntry activeEntries[32]; bool swapBuffers; + bool wSort; int bufferIndex; int vertexIndex; int polygonIndex;
M include/mgba/internal/ds/gx/software.hinclude/mgba/internal/ds/gx/software.h

@@ -22,15 +22,13 @@ uint16_t* palBase;

int texFormat; int texW; int texH; - int32_t topY; - int32_t bottomY; - int32_t topZ; }; struct DSGXSoftwareEdge { unsigned polyId; int32_t y0; // 20.12 int32_t x0; // 20.12 + int32_t z0; // 20.12 int32_t w0; // 20.12 uint8_t cr0; uint8_t cg0;

@@ -40,6 +38,7 @@ int16_t t0;

int32_t y1; // 20.12 int32_t x1; // 20.12 + int32_t z1; // 20.12 int32_t w1; // 20.12 uint8_t cr1; uint8_t cg1;

@@ -50,6 +49,7 @@ };

struct DSGXSoftwareEndpoint { int32_t x; // 20.12 + int64_t z; int64_t w; uint8_t cr; uint8_t cg;

@@ -78,6 +78,7 @@

uint16_t depthBuffer[DS_VIDEO_HORIZONTAL_PIXELS]; color_t* scanlineCache; bool flushPending; + bool wSort; struct DSGXVertex* verts; };
M src/ds/gx.csrc/ds/gx.c

@@ -17,7 +17,7 @@ static void DSGXDummyRendererInit(struct DSGXRenderer* renderer);

static void DSGXDummyRendererReset(struct DSGXRenderer* renderer); static void DSGXDummyRendererDeinit(struct DSGXRenderer* renderer); static void DSGXDummyRendererInvalidateTex(struct DSGXRenderer* renderer, int slot); -static void DSGXDummyRendererSetRAM(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount); +static void DSGXDummyRendererSetRAM(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount, bool wSort); static void DSGXDummyRendererDrawScanline(struct DSGXRenderer* renderer, int y); static void DSGXDummyRendererGetScanline(struct DSGXRenderer* renderer, int y, color_t** output);

@@ -877,6 +877,7 @@ gx->vertexMode = -1;

break; case DS_GX_CMD_SWAP_BUFFERS: gx->swapBuffers = true; + gx->wSort = entry.params[0] & 2; break; case DS_GX_CMD_VIEWPORT: gx->viewportX1 = (uint8_t) entry.params[0];

@@ -1186,7 +1187,7 @@ }

void DSGXFlush(struct DSGX* gx) { if (gx->swapBuffers) { - gx->renderer->setRAM(gx->renderer, gx->vertexBuffer[gx->bufferIndex], gx->polygonBuffer[gx->bufferIndex], gx->polygonIndex); + gx->renderer->setRAM(gx->renderer, gx->vertexBuffer[gx->bufferIndex], gx->polygonBuffer[gx->bufferIndex], gx->polygonIndex, gx->wSort); gx->swapBuffers = false; gx->bufferIndex ^= 1; gx->vertexIndex = 0;

@@ -1220,7 +1221,7 @@ UNUSED(slot);

// Nothing to do } -static void DSGXDummyRendererSetRAM(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount) { +static void DSGXDummyRendererSetRAM(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount, bool wSort) { UNUSED(renderer); UNUSED(verts); UNUSED(polys);
M src/ds/gx/software.csrc/ds/gx/software.c

@@ -18,7 +18,7 @@ static void DSGXSoftwareRendererInit(struct DSGXRenderer* renderer);

static void DSGXSoftwareRendererReset(struct DSGXRenderer* renderer); static void DSGXSoftwareRendererDeinit(struct DSGXRenderer* renderer); static void DSGXSoftwareRendererInvalidateTex(struct DSGXRenderer* renderer, int slot); -static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount); +static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount, bool wSort); static void DSGXSoftwareRendererDrawScanline(struct DSGXRenderer* renderer, int y); static void DSGXSoftwareRendererGetScanline(struct DSGXRenderer* renderer, int y, color_t** output);

@@ -165,6 +165,7 @@ wRecip = 0x100000000;

w0 = 0x10000; w1 = 0x10000; span->ep[index].w = w; + span->ep[index].z = (((edge->z1 - edge->z0) * yw) >> 32) + edge->z0; span->ep[index].cr = (((((edge->cr1 * (int64_t) w1 - edge->cr0 * (int64_t) w0) * yw) >> 32) + edge->cr0 * (int64_t) w0) * wRecip) >> 48; span->ep[index].cg = (((((edge->cg1 * (int64_t) w1 - edge->cg0 * (int64_t) w0) * yw) >> 32) + edge->cg0 * (int64_t) w0) * wRecip) >> 48; span->ep[index].cb = (((((edge->cb1 * (int64_t) w1 - edge->cb0 * (int64_t) w0) * yw) >> 32) + edge->cb0 * (int64_t) w0) * wRecip) >> 48;

@@ -216,6 +217,8 @@ // XXX: Disable perspective correction until I figure out how to fix it

wRecip = 0x100000000; w0 = 0x10000; w1 = 0x10000; + + ep->z = (((span->ep[1].z - span->ep[0].z) * xw) >> 32) + span->ep[0].z; uint64_t r = (((span->ep[1].cr * (int64_t) w1 - span->ep[0].cr * (int64_t) w0) * xw) >> 32) + span->ep[0].cr * (int64_t) w0; uint64_t g = (((span->ep[1].cg * (int64_t) w1 - span->ep[0].cg * (int64_t) w0) * xw) >> 32) + span->ep[0].cg * (int64_t) w0;

@@ -268,10 +271,11 @@ struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;

// TODO } -static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount) { +static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount, bool wSort) { struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer; softwareRenderer->flushPending = true; + softwareRenderer->wSort = wSort; softwareRenderer->verts = verts; DSGXSoftwarePolygonListClear(&softwareRenderer->activePolys); DSGXSoftwareEdgeListClear(&softwareRenderer->activeEdges);

@@ -309,6 +313,7 @@ v1 = &verts[poly->poly->vertIds[v]];

if (v0->vy >= v1->vy) { edge->y0 = SCREEN_SIZE - v0->vy; edge->x0 = v0->vx; + edge->z0 = v0->vz; edge->w0 = v0->vw; _expandColor(v0->color, &edge->cr0, &edge->cg0, &edge->cb0); edge->s0 = v0->vs;

@@ -316,6 +321,7 @@ edge->t0 = v0->vt;

edge->y1 = SCREEN_SIZE - v1->vy; edge->x1 = v1->vx; + edge->z1 = v1->vz; edge->w1 = v1->vw; _expandColor(v1->color, &edge->cr1, &edge->cg1, &edge->cb1); edge->s1 = v1->vs;

@@ -323,6 +329,7 @@ edge->t1 = v1->vt;

} else { edge->y0 = SCREEN_SIZE - v1->vy; edge->x0 = v1->vx; + edge->z0 = v1->vz; edge->w0 = v1->vw; _expandColor(v1->color, &edge->cr0, &edge->cg0, &edge->cb0); edge->s0 = v1->vs;

@@ -330,6 +337,7 @@ edge->t0 = v1->vt;

edge->y1 = SCREEN_SIZE - v0->vy; edge->x1 = v0->vx; + edge->z1 = v0->vz; edge->w1 = v0->vw; _expandColor(v0->color, &edge->cr1, &edge->cg1, &edge->cb1); edge->s1 = v0->vs;

@@ -345,6 +353,7 @@ v1 = &verts[poly->poly->vertIds[0]];

if (v0->vy >= v1->vy) { edge->y0 = SCREEN_SIZE - v0->vy; edge->x0 = v0->vx; + edge->z0 = v0->vz; edge->w0 = v0->vw; _expandColor(v0->color, &edge->cr0, &edge->cg0, &edge->cb0); edge->s0 = v0->vs;

@@ -352,6 +361,7 @@ edge->t0 = v0->vt;

edge->y1 = SCREEN_SIZE - v1->vy; edge->x1 = v1->vx; + edge->z1 = v1->vz; edge->w1 = v1->vw; _expandColor(v1->color, &edge->cr1, &edge->cg1, &edge->cb1); edge->s1 = v1->vs;

@@ -360,12 +370,14 @@ } else {

edge->y0 = SCREEN_SIZE - v1->vy; edge->x0 = v1->vx; edge->w0 = v1->vw; + edge->z0 = v1->vz; _expandColor(v1->color, &edge->cr0, &edge->cg0, &edge->cb0); edge->s0 = v1->vs; edge->t0 = v1->vt; edge->y1 = SCREEN_SIZE - v0->vy; edge->x1 = v0->vx; + edge->z1 = v0->vz; edge->w1 = v0->vw; _expandColor(v0->color, &edge->cr1, &edge->cg1, &edge->cb1); edge->s1 = v0->vs;

@@ -438,16 +450,22 @@ }

span = DSGXSoftwareSpanListGetPointer(&softwareRenderer->activeSpans, nextSpanId - 1); nextSpanX = span->ep[0].x >> 12; } - while (i > (span->ep[0].x >> 12)) { + while (span && i > (span->ep[0].x >> 12)) { if (i <= (span->ep[1].x >> 12)) { _lerpEndpoint(span, &ep, i); color_t color = _lookupColor(&ep, span->poly); - if (scanline[i] == FLAG_UNWRITTEN) { - scanline[i] = color; - } - if (ep.w < depth && color != FLAG_UNWRITTEN) { - depth = ep.w; - scanline[i] = color; + if (color != FLAG_UNWRITTEN) { + if (softwareRenderer->wSort) { + if (ep.w < depth) { + depth = ep.w; + scanline[i] = color; + } + } else { + if (ep.z < depth) { + depth = ep.z; + scanline[i] = color; + } + } } } --nextSpanId;