mirror of https://github.com/mgba-emu/mgba.git
DS GX: Fake re-rendering scenes
This commit is contained in:
parent
bda216be93
commit
abf57aa602
|
@ -200,7 +200,7 @@ void DSGXAssociateRenderer(struct DSGX* video, struct DSGXRenderer* renderer);
|
||||||
uint16_t DSGXWriteRegister(struct DSGX*, uint32_t address, uint16_t value);
|
uint16_t DSGXWriteRegister(struct DSGX*, uint32_t address, uint16_t value);
|
||||||
uint32_t DSGXWriteRegister32(struct DSGX*, uint32_t address, uint32_t value);
|
uint32_t DSGXWriteRegister32(struct DSGX*, uint32_t address, uint32_t value);
|
||||||
|
|
||||||
void DSGXSwapBuffers(struct DSGX*);
|
void DSGXFlush(struct DSGX*);
|
||||||
void DSGXUpdateGXSTAT(struct DSGX*);
|
void DSGXUpdateGXSTAT(struct DSGX*);
|
||||||
|
|
||||||
CXX_GUARD_END
|
CXX_GUARD_END
|
||||||
|
|
|
@ -77,6 +77,7 @@ struct DSGXSoftwareRenderer {
|
||||||
|
|
||||||
uint16_t depthBuffer[DS_VIDEO_HORIZONTAL_PIXELS];
|
uint16_t depthBuffer[DS_VIDEO_HORIZONTAL_PIXELS];
|
||||||
color_t* scanlineCache;
|
color_t* scanlineCache;
|
||||||
|
bool flushPending;
|
||||||
|
|
||||||
struct DSGXVertex* verts;
|
struct DSGXVertex* verts;
|
||||||
};
|
};
|
||||||
|
|
|
@ -901,6 +901,7 @@ static void DSGXUnpackCommand(struct DSGX* gx, uint32_t command) {
|
||||||
gx->outstandingParams[2] = _gxCommandParams[gx->outstandingCommand[2]];
|
gx->outstandingParams[2] = _gxCommandParams[gx->outstandingCommand[2]];
|
||||||
gx->outstandingParams[3] = _gxCommandParams[gx->outstandingCommand[3]];
|
gx->outstandingParams[3] = _gxCommandParams[gx->outstandingCommand[3]];
|
||||||
_flushOutstanding(gx);
|
_flushOutstanding(gx);
|
||||||
|
DSGXUpdateGXSTAT(gx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DSGXWriteFIFO(struct DSGX* gx, struct DSGXEntry entry) {
|
static void DSGXWriteFIFO(struct DSGX* gx, struct DSGXEntry entry) {
|
||||||
|
@ -1049,14 +1050,14 @@ uint32_t DSGXWriteRegister32(struct DSGX* gx, uint32_t address, uint32_t value)
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSGXSwapBuffers(struct DSGX* gx) {
|
void DSGXFlush(struct DSGX* gx) {
|
||||||
gx->swapBuffers = false;
|
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->swapBuffers = false;
|
||||||
gx->bufferIndex ^= 1;
|
gx->bufferIndex ^= 1;
|
||||||
gx->vertexIndex = 0;
|
gx->vertexIndex = 0;
|
||||||
gx->polygonIndex = 0;
|
gx->polygonIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (CircleBufferSize(&gx->fifo)) {
|
if (CircleBufferSize(&gx->fifo)) {
|
||||||
mTimingSchedule(&gx->p->ds9.timing, &gx->fifoEvent, 0);
|
mTimingSchedule(&gx->p->ds9.timing, &gx->fifoEvent, 0);
|
||||||
|
|
|
@ -225,12 +225,12 @@ static void DSGXSoftwareRendererInit(struct DSGXRenderer* renderer) {
|
||||||
DSGXSoftwareEdgeListInit(&softwareRenderer->activeEdges, DS_GX_POLYGON_BUFFER_SIZE);
|
DSGXSoftwareEdgeListInit(&softwareRenderer->activeEdges, DS_GX_POLYGON_BUFFER_SIZE);
|
||||||
DSGXSoftwareSpanListInit(&softwareRenderer->activeSpans, DS_GX_POLYGON_BUFFER_SIZE / 2);
|
DSGXSoftwareSpanListInit(&softwareRenderer->activeSpans, DS_GX_POLYGON_BUFFER_SIZE / 2);
|
||||||
softwareRenderer->bucket = anonymousMemoryMap(sizeof(*softwareRenderer->bucket) * DS_GX_POLYGON_BUFFER_SIZE);
|
softwareRenderer->bucket = anonymousMemoryMap(sizeof(*softwareRenderer->bucket) * DS_GX_POLYGON_BUFFER_SIZE);
|
||||||
softwareRenderer->scanlineCache = anonymousMemoryMap(sizeof(color_t) * DS_VIDEO_HORIZONTAL_PIXELS * 48);
|
softwareRenderer->scanlineCache = anonymousMemoryMap(sizeof(color_t) * DS_VIDEO_VERTICAL_PIXELS * DS_VIDEO_HORIZONTAL_PIXELS);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DSGXSoftwareRendererReset(struct DSGXRenderer* renderer) {
|
static void DSGXSoftwareRendererReset(struct DSGXRenderer* renderer) {
|
||||||
struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
|
struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
|
||||||
// TODO
|
softwareRenderer->flushPending = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DSGXSoftwareRendererDeinit(struct DSGXRenderer* renderer) {
|
static void DSGXSoftwareRendererDeinit(struct DSGXRenderer* renderer) {
|
||||||
|
@ -239,7 +239,7 @@ static void DSGXSoftwareRendererDeinit(struct DSGXRenderer* renderer) {
|
||||||
DSGXSoftwareEdgeListDeinit(&softwareRenderer->activeEdges);
|
DSGXSoftwareEdgeListDeinit(&softwareRenderer->activeEdges);
|
||||||
DSGXSoftwareSpanListDeinit(&softwareRenderer->activeSpans);
|
DSGXSoftwareSpanListDeinit(&softwareRenderer->activeSpans);
|
||||||
mappedMemoryFree(softwareRenderer->bucket, sizeof(*softwareRenderer->bucket) * DS_GX_POLYGON_BUFFER_SIZE);
|
mappedMemoryFree(softwareRenderer->bucket, sizeof(*softwareRenderer->bucket) * DS_GX_POLYGON_BUFFER_SIZE);
|
||||||
mappedMemoryFree(softwareRenderer->scanlineCache, sizeof(color_t) * DS_VIDEO_HORIZONTAL_PIXELS * 48);
|
mappedMemoryFree(softwareRenderer->scanlineCache, sizeof(color_t) * DS_VIDEO_VERTICAL_PIXELS * DS_VIDEO_HORIZONTAL_PIXELS);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DSGXSoftwareRendererInvalidateTex(struct DSGXRenderer* renderer, int slot) {
|
static void DSGXSoftwareRendererInvalidateTex(struct DSGXRenderer* renderer, int slot) {
|
||||||
|
@ -250,6 +250,7 @@ static void DSGXSoftwareRendererInvalidateTex(struct DSGXRenderer* renderer, int
|
||||||
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) {
|
||||||
struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
|
struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
|
||||||
|
|
||||||
|
softwareRenderer->flushPending = true;
|
||||||
softwareRenderer->verts = verts;
|
softwareRenderer->verts = verts;
|
||||||
DSGXSoftwarePolygonListClear(&softwareRenderer->activePolys);
|
DSGXSoftwarePolygonListClear(&softwareRenderer->activePolys);
|
||||||
DSGXSoftwareEdgeListClear(&softwareRenderer->activeEdges);
|
DSGXSoftwareEdgeListClear(&softwareRenderer->activeEdges);
|
||||||
|
@ -351,6 +352,9 @@ static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSG
|
||||||
|
|
||||||
static void DSGXSoftwareRendererDrawScanline(struct DSGXRenderer* renderer, int y) {
|
static void DSGXSoftwareRendererDrawScanline(struct DSGXRenderer* renderer, int y) {
|
||||||
struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
|
struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
|
||||||
|
if (!softwareRenderer->flushPending) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
DSGXSoftwareSpanListClear(&softwareRenderer->activeSpans);
|
DSGXSoftwareSpanListClear(&softwareRenderer->activeSpans);
|
||||||
memset(softwareRenderer->bucket, 0, sizeof(*softwareRenderer->bucket) * DS_GX_POLYGON_BUFFER_SIZE);
|
memset(softwareRenderer->bucket, 0, sizeof(*softwareRenderer->bucket) * DS_GX_POLYGON_BUFFER_SIZE);
|
||||||
int i;
|
int i;
|
||||||
|
@ -383,7 +387,6 @@ static void DSGXSoftwareRendererDrawScanline(struct DSGXRenderer* renderer, int
|
||||||
}
|
}
|
||||||
qsort(DSGXSoftwareSpanListGetPointer(&softwareRenderer->activeSpans, 0), DSGXSoftwareSpanListSize(&softwareRenderer->activeSpans), sizeof(struct DSGXSoftwareSpan), _spanSort);
|
qsort(DSGXSoftwareSpanListGetPointer(&softwareRenderer->activeSpans, 0), DSGXSoftwareSpanListSize(&softwareRenderer->activeSpans), sizeof(struct DSGXSoftwareSpan), _spanSort);
|
||||||
|
|
||||||
y %= 48;
|
|
||||||
color_t* scanline = &softwareRenderer->scanlineCache[DS_VIDEO_HORIZONTAL_PIXELS * y];
|
color_t* scanline = &softwareRenderer->scanlineCache[DS_VIDEO_HORIZONTAL_PIXELS * y];
|
||||||
|
|
||||||
int nextSpanX = DS_VIDEO_HORIZONTAL_PIXELS;
|
int nextSpanX = DS_VIDEO_HORIZONTAL_PIXELS;
|
||||||
|
@ -438,10 +441,12 @@ static void DSGXSoftwareRendererDrawScanline(struct DSGXRenderer* renderer, int
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (y == DS_VIDEO_VERTICAL_PIXELS - 1) {
|
||||||
|
softwareRenderer->flushPending = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DSGXSoftwareRendererGetScanline(struct DSGXRenderer* renderer, int y, color_t** output) {
|
static void DSGXSoftwareRendererGetScanline(struct DSGXRenderer* renderer, int y, color_t** output) {
|
||||||
struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
|
struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
|
||||||
y %= 48;
|
|
||||||
*output = &softwareRenderer->scanlineCache[DS_VIDEO_HORIZONTAL_PIXELS * y];
|
*output = &softwareRenderer->scanlineCache[DS_VIDEO_HORIZONTAL_PIXELS * y];
|
||||||
}
|
}
|
||||||
|
|
|
@ -290,9 +290,7 @@ void _startHdraw9(struct mTiming* timing, void* context, uint32_t cyclesLate) {
|
||||||
video->p->ds9.memory.io[DS_REG_DISPSTAT >> 1] = GBARegisterDISPSTATFillInVblank(dispstat);
|
video->p->ds9.memory.io[DS_REG_DISPSTAT >> 1] = GBARegisterDISPSTATFillInVblank(dispstat);
|
||||||
if (video->frameskipCounter <= 0) {
|
if (video->frameskipCounter <= 0) {
|
||||||
video->renderer->finishFrame(video->renderer);
|
video->renderer->finishFrame(video->renderer);
|
||||||
if (video->p->gx.swapBuffers) {
|
DSGXFlush(&video->p->gx);
|
||||||
DSGXSwapBuffers(&video->p->gx);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (GBARegisterDISPSTATIsVblankIRQ(dispstat)) {
|
if (GBARegisterDISPSTATIsVblankIRQ(dispstat)) {
|
||||||
DSRaiseIRQ(video->p->ds9.cpu, video->p->ds9.memory.io, DS_IRQ_VBLANK);
|
DSRaiseIRQ(video->p->ds9.cpu, video->p->ds9.memory.io, DS_IRQ_VBLANK);
|
||||||
|
|
Loading…
Reference in New Issue