all repos — mgba @ 812d063b73cf9231123e9600160d4f4d0eb7a8cf

mGBA Game Boy Advance Emulator

GBA Video: More threaded renderer improvements, still stomping on itself sometimes though
Jeffrey Pfau jeffrey@endrift.com
Sun, 14 Aug 2016 04:20:37 -0700
commit

812d063b73cf9231123e9600160d4f4d0eb7a8cf

parent

6797cbe6b1f78763c9c81773a57e69f89b44e0fc

1 files changed, 16 insertions(+), 3 deletions(-)

jump to
M src/gba/renderers/thread-proxy.csrc/gba/renderers/thread-proxy.c

@@ -69,7 +69,7 @@ struct GBAVideoThreadProxyRenderer* proxyRenderer = (struct GBAVideoThreadProxyRenderer*) renderer;

ConditionInit(&proxyRenderer->fromThreadCond); ConditionInit(&proxyRenderer->toThreadCond); MutexInit(&proxyRenderer->mutex); - RingFIFOInit(&proxyRenderer->dirtyQueue, 0x40000, 0x1000); + RingFIFOInit(&proxyRenderer->dirtyQueue, 0x48000, 0x1000); proxyRenderer->vramProxy = anonymousMemoryMap(SIZE_VRAM); proxyRenderer->backend->palette = proxyRenderer->paletteProxy;

@@ -208,7 +208,13 @@ 0xABCD,

0xDEADBEEF, }; RingFIFOWrite(&proxyRenderer->dirtyQueue, &dirty, sizeof(dirty)); - RingFIFOWrite(&proxyRenderer->dirtyQueue, &proxyRenderer->d.vram[j * 0x800], 0x1000); + while (!RingFIFOWrite(&proxyRenderer->dirtyQueue, &proxyRenderer->d.vram[j * 0x800], 0x1000)) { + ConditionWake(&proxyRenderer->toThreadCond); + if (proxyRenderer->threadState == PROXY_THREAD_STOPPED) { + mLOG(GBA_VIDEO, FATAL, "Proxy thread stopped prematurely!"); + return; + } + } } } struct GBAVideoDirtyInfo dirty = {

@@ -225,6 +231,10 @@ }

void GBAVideoThreadProxyRendererFinishFrame(struct GBAVideoRenderer* renderer) { struct GBAVideoThreadProxyRenderer* proxyRenderer = (struct GBAVideoThreadProxyRenderer*) renderer; + if (proxyRenderer->threadState == PROXY_THREAD_STOPPED) { + mLOG(GBA_VIDEO, FATAL, "Proxy thread stopped prematurely!"); + return; + } MutexLock(&proxyRenderer->mutex); // Insert an extra item into the queue to make sure it gets flushed struct GBAVideoDirtyInfo dirty = {

@@ -308,7 +318,9 @@ proxyRenderer->oamProxy.raw[item.address] = item.value;

proxyRenderer->backend->writeOAM(proxyRenderer->backend, item.address); break; case DIRTY_VRAM: - while (!RingFIFORead(&proxyRenderer->dirtyQueue, &proxyRenderer->vramProxy[item.address >> 1], 0x1000)); + while (!RingFIFORead(&proxyRenderer->dirtyQueue, &proxyRenderer->vramProxy[item.address >> 1], 0x1000)) { + ConditionWake(&proxyRenderer->fromThreadCond); + } proxyRenderer->backend->writeVRAM(proxyRenderer->backend, item.address); break; case DIRTY_SCANLINE:

@@ -321,6 +333,7 @@ default:

// FIFO was corrupted MutexLock(&proxyRenderer->mutex); proxyRenderer->threadState = PROXY_THREAD_STOPPED; + mLOG(GBA_VIDEO, FATAL, "Proxy thread queue got corrupted!"); goto out; } } while (proxyRenderer->threadState == PROXY_THREAD_BUSY && RingFIFORead(&proxyRenderer->dirtyQueue, &item, sizeof(item)));