Core: Add functions for pakcing and unpacking pixels
@@ -171,7 +171,7 @@
void mCoreTakeScreenshot(struct mCore* core) { #ifdef USE_PNG size_t stride; - color_t* pixels = 0; + const void* pixels = 0; unsigned width, height; core->desiredVideoDimensions(core, &width, &height); struct VFile* vf;@@ -182,7 +182,7 @@ vf = VFileMemChunk(0, 0);
#endif bool success = false; if (vf) { - core->getVideoBuffer(core, &pixels, &stride); + core->getPixels(core, &pixels, &stride); png_structp png = PNGWriteOpen(vf); png_infop info = PNGWriteHeader(png, width, height); success = PNGWritePixels(png, width, height, stride, pixels);
@@ -56,7 +56,9 @@ void (*loadConfig)(struct mCore*, const struct mCoreConfig*);
void (*desiredVideoDimensions)(struct mCore*, unsigned* width, unsigned* height); void (*setVideoBuffer)(struct mCore*, color_t* buffer, size_t stride); - void (*getVideoBuffer)(struct mCore*, color_t** buffer, size_t* stride); + + void (*getPixels)(struct mCore*, const void** buffer, size_t* stride); + void (*putPixels)(struct mCore*, const void* buffer, size_t stride); struct blip_t* (*getAudioChannel)(struct mCore*, int ch); void (*setAudioBufferSize)(struct mCore*, size_t samples);
@@ -7,7 +7,6 @@ #include "serialize.h"
#include "core/core.h" #include "core/cheats.h" -#include "core/sync.h" #include "util/memory.h" #include "util/vfs.h"@@ -148,18 +147,12 @@ };
return true; } - - - - - - #ifdef USE_PNG static bool _savePNGState(struct mCore* core, struct VFile* vf, struct mStateExtdata* extdata) { size_t stride; - color_t* pixels = 0; + const void* pixels = 0; - core->getVideoBuffer(core, &pixels, &stride); + core->getPixels(core, &pixels, &stride); if (!pixels) { return false; }@@ -409,9 +402,7 @@ struct mStateExtdataItem item;
if (flags & SAVESTATE_SCREENSHOT && mStateExtdataGet(&extdata, EXTDATA_SCREENSHOT, &item)) { mLOG(SAVESTATE, INFO, "Loading screenshot"); if (item.size >= (int) (width * height) * 4) { - // TODO: Put back - /*gba->video.renderer->putPixels(gba->video.renderer, width, item.data); - mCoreSyncForceFrame(core->sync);*/ + core->putPixels(core, item.data, width); } else { mLOG(SAVESTATE, WARN, "Savestate includes invalid screenshot"); }
@@ -121,10 +121,14 @@ gbcore->renderer.outputBuffer = buffer;
gbcore->renderer.outputBufferStride = stride; } -static void _GBCoreGetVideoBuffer(struct mCore* core, color_t** buffer, size_t* stride) { +static void _GBCoreGetPixels(struct mCore* core, const void** buffer, size_t* stride) { struct GBCore* gbcore = (struct GBCore*) core; - *buffer = gbcore->renderer.outputBuffer; - *stride = gbcore->renderer.outputBufferStride; + gbcore->renderer.d.getPixels(&gbcore->renderer.d, stride, buffer); +} + +static void _GBCorePutPixels(struct mCore* core, const void* buffer, size_t stride) { + struct GBCore* gbcore = (struct GBCore*) core; + gbcore->renderer.d.putPixels(&gbcore->renderer.d, stride, buffer); } static struct blip_t* _GBCoreGetAudioChannel(struct mCore* core, int ch) {@@ -501,7 +505,8 @@ core->setSync = _GBCoreSetSync;
core->loadConfig = _GBCoreLoadConfig; core->desiredVideoDimensions = _GBCoreDesiredVideoDimensions; core->setVideoBuffer = _GBCoreSetVideoBuffer; - core->getVideoBuffer = _GBCoreGetVideoBuffer; + core->getPixels = _GBCoreGetPixels; + core->putPixels = _GBCorePutPixels; core->getAudioChannel = _GBCoreGetAudioChannel; core->setAudioBufferSize = _GBCoreSetAudioBufferSize; core->getAudioBufferSize = _GBCoreGetAudioBufferSize;
@@ -15,8 +15,8 @@ static void GBVideoSoftwareRendererWritePalette(struct GBVideoRenderer* renderer, int index, uint16_t value);
static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, int startX, int endX, int y, struct GBObj* obj, size_t oamMax); static void GBVideoSoftwareRendererFinishScanline(struct GBVideoRenderer* renderer, int y); static void GBVideoSoftwareRendererFinishFrame(struct GBVideoRenderer* renderer); -static void GBVideoSoftwareRendererGetPixels(struct GBVideoRenderer* renderer, unsigned* stride, const void** pixels); -static void GBVideoSoftwareRendererPutPixels(struct GBVideoRenderer* renderer, unsigned stride, void* pixels); +static void GBVideoSoftwareRendererGetPixels(struct GBVideoRenderer* renderer, size_t* stride, const void** pixels); +static void GBVideoSoftwareRendererPutPixels(struct GBVideoRenderer* renderer, size_t stride, const void* pixels); static void GBVideoSoftwareRendererDrawBackground(struct GBVideoSoftwareRenderer* renderer, uint8_t* maps, int startX, int endX, int sx, int sy); static void GBVideoSoftwareRendererDrawObj(struct GBVideoSoftwareRenderer* renderer, struct GBObj* obj, int startX, int endX, int y);@@ -30,7 +30,7 @@ renderer->d.drawRange = GBVideoSoftwareRendererDrawRange;
renderer->d.finishScanline = GBVideoSoftwareRendererFinishScanline; renderer->d.finishFrame = GBVideoSoftwareRendererFinishFrame; renderer->d.getPixels = GBVideoSoftwareRendererGetPixels; - renderer->d.putPixels = 0; + renderer->d.putPixels = GBVideoSoftwareRendererPutPixels; renderer->temporaryBuffer = 0; }@@ -407,7 +407,7 @@ }
} } -static void GBVideoSoftwareRendererGetPixels(struct GBVideoRenderer* renderer, unsigned* stride, const void** pixels) { +static void GBVideoSoftwareRendererGetPixels(struct GBVideoRenderer* renderer, size_t* stride, const void** pixels) { struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer; // TODO: Share with GBAVideoSoftwareRendererGetPixels #ifdef COLOR_16_BIT@@ -438,3 +438,15 @@ *stride = softwareRenderer->outputBufferStride;
*pixels = softwareRenderer->outputBuffer; #endif } + + +static void GBVideoSoftwareRendererPutPixels(struct GBVideoRenderer* renderer, size_t stride, const void* pixels) { + struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer; + // TODO: Share with GBAVideoSoftwareRendererGetPixels + + const color_t* colorPixels = pixels; + unsigned i; + for (i = 0; i < GB_VIDEO_VERTICAL_PIXELS; ++i) { + memmove(&softwareRenderer->outputBuffer[softwareRenderer->outputBufferStride * i], &colorPixels[stride * i], GB_VIDEO_HORIZONTAL_PIXELS * BYTES_PER_PIXEL); + } +}
@@ -20,7 +20,8 @@ static void GBVideoDummyRendererWritePalette(struct GBVideoRenderer* renderer, int index, uint16_t value);
static void GBVideoDummyRendererDrawRange(struct GBVideoRenderer* renderer, int startX, int endX, int y, struct GBObj* obj, size_t oamMax); static void GBVideoDummyRendererFinishScanline(struct GBVideoRenderer* renderer, int y); static void GBVideoDummyRendererFinishFrame(struct GBVideoRenderer* renderer); -static void GBVideoDummyRendererGetPixels(struct GBVideoRenderer* renderer, unsigned* stride, const void** pixels); +static void GBVideoDummyRendererGetPixels(struct GBVideoRenderer* renderer, size_t* stride, const void** pixels); +static void GBVideoDummyRendererPutPixels(struct GBVideoRenderer* renderer, size_t stride, const void* pixels); static void _cleanOAM(struct GBVideo* video, int y);@@ -32,7 +33,8 @@ .writePalette = GBVideoDummyRendererWritePalette,
.drawRange = GBVideoDummyRendererDrawRange, .finishScanline = GBVideoDummyRendererFinishScanline, .finishFrame = GBVideoDummyRendererFinishFrame, - .getPixels = GBVideoDummyRendererGetPixels + .getPixels = GBVideoDummyRendererGetPixels, + .putPixels = GBVideoDummyRendererPutPixels, }; void GBVideoInit(struct GBVideo* video) {@@ -127,7 +129,7 @@ }
if (video->p->stream && video->p->stream->postVideoFrame) { const color_t* pixels; - unsigned stride; + size_t stride; video->renderer->getPixels(video->renderer, &stride, (const void**) &pixels); video->p->stream->postVideoFrame(video->p->stream, pixels, stride); }@@ -435,7 +437,14 @@ UNUSED(renderer);
// Nothing to do } -static void GBVideoDummyRendererGetPixels(struct GBVideoRenderer* renderer, unsigned* stride, const void** pixels) { +static void GBVideoDummyRendererGetPixels(struct GBVideoRenderer* renderer, size_t* stride, const void** pixels) { + UNUSED(renderer); + UNUSED(stride); + UNUSED(pixels); + // Nothing to do +} + +static void GBVideoDummyRendererPutPixels(struct GBVideoRenderer* renderer, size_t stride, const void* pixels) { UNUSED(renderer); UNUSED(stride); UNUSED(pixels);
@@ -63,8 +63,8 @@ void (*drawRange)(struct GBVideoRenderer* renderer, int startX, int endX, int y, struct GBObj* objOnLine, size_t nObj);
void (*finishScanline)(struct GBVideoRenderer* renderer, int y); void (*finishFrame)(struct GBVideoRenderer* renderer); - void (*getPixels)(struct GBVideoRenderer* renderer, unsigned* stride, const void** pixels); - void (*putPixels)(struct GBVideoRenderer* renderer, unsigned stride, void* pixels); + void (*getPixels)(struct GBVideoRenderer* renderer, size_t* stride, const void** pixels); + void (*putPixels)(struct GBVideoRenderer* renderer, size_t stride, const void* pixels); uint8_t* vram; union GBOAM* oam;
@@ -152,10 +152,14 @@ gbacore->renderer.outputBuffer = buffer;
gbacore->renderer.outputBufferStride = stride; } -static void _GBACoreGetVideoBuffer(struct mCore* core, color_t** buffer, size_t* stride) { +static void _GBACoreGetPixels(struct mCore* core, const void** buffer, size_t* stride) { struct GBACore* gbacore = (struct GBACore*) core; - *buffer = gbacore->renderer.outputBuffer; - *stride = gbacore->renderer.outputBufferStride; + gbacore->renderer.d.getPixels(&gbacore->renderer.d, stride, buffer); +} + +static void _GBACorePutPixels(struct mCore* core, const void* buffer, size_t stride) { + struct GBACore* gbacore = (struct GBACore*) core; + gbacore->renderer.d.putPixels(&gbacore->renderer.d, stride, buffer); } static struct blip_t* _GBACoreGetAudioChannel(struct mCore* core, int ch) {@@ -528,7 +532,8 @@ core->setSync = _GBACoreSetSync;
core->loadConfig = _GBACoreLoadConfig; core->desiredVideoDimensions = _GBACoreDesiredVideoDimensions; core->setVideoBuffer = _GBACoreSetVideoBuffer; - core->getVideoBuffer = _GBACoreGetVideoBuffer; + core->getPixels = _GBACoreGetPixels; + core->putPixels = _GBACorePutPixels; core->getAudioChannel = _GBACoreGetAudioChannel; core->setAudioBufferSize = _GBACoreSetAudioBufferSize; core->getAudioBufferSize = _GBACoreGetAudioBufferSize;
@@ -856,7 +856,7 @@ }
if (gba->stream && gba->stream->postVideoFrame) { const color_t* pixels; - unsigned stride; + size_t stride; gba->video.renderer->getPixels(gba->video.renderer, &stride, (const void**) &pixels); gba->stream->postVideoFrame(gba->stream, pixels, stride); }
@@ -38,8 +38,8 @@ static void GBAVideoThreadProxyRendererWritePalette(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value);
static void GBAVideoThreadProxyRendererWriteOAM(struct GBAVideoRenderer* renderer, uint32_t oam); static void GBAVideoThreadProxyRendererDrawScanline(struct GBAVideoRenderer* renderer, int y); static void GBAVideoThreadProxyRendererFinishFrame(struct GBAVideoRenderer* renderer); -static void GBAVideoThreadProxyRendererGetPixels(struct GBAVideoRenderer* renderer, unsigned* stride, const void** pixels); -static void GBAVideoThreadProxyRendererPutPixels(struct GBAVideoRenderer* renderer, unsigned stride, void* pixels); +static void GBAVideoThreadProxyRendererGetPixels(struct GBAVideoRenderer* renderer, size_t* stride, const void** pixels); +static void GBAVideoThreadProxyRendererPutPixels(struct GBAVideoRenderer* renderer, size_t stride, const void* pixels); static THREAD_ENTRY _proxyThread(void* renderer);@@ -279,7 +279,7 @@ proxyRenderer->vramDirtyBitmap = 0;
MutexUnlock(&proxyRenderer->mutex); } -static void GBAVideoThreadProxyRendererGetPixels(struct GBAVideoRenderer* renderer, unsigned* stride, const void** pixels) { +static void GBAVideoThreadProxyRendererGetPixels(struct GBAVideoRenderer* renderer, size_t* stride, const void** pixels) { struct GBAVideoThreadProxyRenderer* proxyRenderer = (struct GBAVideoThreadProxyRenderer*) renderer; MutexLock(&proxyRenderer->mutex); // Insert an extra item into the queue to make sure it gets flushed@@ -298,7 +298,7 @@ proxyRenderer->backend->getPixels(proxyRenderer->backend, stride, pixels);
MutexUnlock(&proxyRenderer->mutex); } -static void GBAVideoThreadProxyRendererPutPixels(struct GBAVideoRenderer* renderer, unsigned stride, void* pixels) { +static void GBAVideoThreadProxyRendererPutPixels(struct GBAVideoRenderer* renderer, size_t stride, const void* pixels) { struct GBAVideoThreadProxyRenderer* proxyRenderer = (struct GBAVideoThreadProxyRenderer*) renderer; MutexLock(&proxyRenderer->mutex); // Insert an extra item into the queue to make sure it gets flushed
@@ -21,8 +21,8 @@ static void GBAVideoSoftwareRendererWritePalette(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value);
static uint16_t GBAVideoSoftwareRendererWriteVideoRegister(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value); static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* renderer, int y); static void GBAVideoSoftwareRendererFinishFrame(struct GBAVideoRenderer* renderer); -static void GBAVideoSoftwareRendererGetPixels(struct GBAVideoRenderer* renderer, unsigned* stride, const void** pixels); -static void GBAVideoSoftwareRendererPutPixels(struct GBAVideoRenderer* renderer, unsigned stride, void* pixels); +static void GBAVideoSoftwareRendererGetPixels(struct GBAVideoRenderer* renderer, size_t* stride, const void** pixels); +static void GBAVideoSoftwareRendererPutPixels(struct GBAVideoRenderer* renderer, size_t stride, const void* pixels); static void GBAVideoSoftwareRendererUpdateDISPCNT(struct GBAVideoSoftwareRenderer* renderer); static void GBAVideoSoftwareRendererWriteBGCNT(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* bg, uint16_t value);@@ -615,63 +615,19 @@ softwareRenderer->bg[3].sx = softwareRenderer->bg[3].refx;
softwareRenderer->bg[3].sy = softwareRenderer->bg[3].refy; } -static void GBAVideoSoftwareRendererGetPixels(struct GBAVideoRenderer* renderer, unsigned* stride, const void** pixels) { +static void GBAVideoSoftwareRendererGetPixels(struct GBAVideoRenderer* renderer, size_t* stride, const void** pixels) { struct GBAVideoSoftwareRenderer* softwareRenderer = (struct GBAVideoSoftwareRenderer*) renderer; - -#ifdef COLOR_16_BIT - *stride = VIDEO_HORIZONTAL_PIXELS; - if (!softwareRenderer->temporaryBuffer) { - softwareRenderer->temporaryBuffer = anonymousMemoryMap(VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * 4); - } - *pixels = softwareRenderer->temporaryBuffer; - unsigned y, x; - for (y = 0; y < VIDEO_VERTICAL_PIXELS; ++y) { - for (x = 0; x < VIDEO_HORIZONTAL_PIXELS; ++x) { - color_t inColor = softwareRenderer->outputBuffer[softwareRenderer->outputBufferStride * y + x]; - uint32_t outColor; -#ifdef COLOR_5_6_5 - outColor = (inColor & 0x1F) << 19; - outColor |= (inColor & 0x7C0) << 5; - outColor |= (inColor & 0xF800) >> 8; -#else - outColor = (inColor & 0x1F) << 3; - outColor |= (inColor & 0x3E0) << 6; - outColor |= (inColor & 0x7C00) << 9; -#endif - softwareRenderer->temporaryBuffer[VIDEO_HORIZONTAL_PIXELS * y + x] = outColor; - } - } -#else *stride = softwareRenderer->outputBufferStride; *pixels = softwareRenderer->outputBuffer; -#endif } -static void GBAVideoSoftwareRendererPutPixels(struct GBAVideoRenderer* renderer, unsigned stride, void* pixels) { +static void GBAVideoSoftwareRendererPutPixels(struct GBAVideoRenderer* renderer, size_t stride, const void* pixels) { struct GBAVideoSoftwareRenderer* softwareRenderer = (struct GBAVideoSoftwareRenderer*) renderer; - uint32_t* colorPixels = pixels; + const color_t* colorPixels = pixels; unsigned i; for (i = 0; i < VIDEO_VERTICAL_PIXELS; ++i) { -#ifdef COLOR_16_BIT - unsigned x; - for (x = 0; x < VIDEO_HORIZONTAL_PIXELS; ++x) { - uint32_t inColor = colorPixels[stride * i + x]; - color_t outColor; -#ifdef COLOR_5_6_5 - outColor = (inColor >> 19) & 0x1F; - outColor |= (inColor >> 5) & 0x7C0; - outColor |= (inColor << 8) & 0xF800; -#else - outColor = (inColor >> 3) & 0x1F; - outColor |= (inColor >> 6) & 0x3E0; - outColor |= (inColor >> 9) & 0x7C00; -#endif - softwareRenderer->outputBuffer[softwareRenderer->outputBufferStride * i + x] = outColor; - } -#else memmove(&softwareRenderer->outputBuffer[softwareRenderer->outputBufferStride * i], &colorPixels[stride * i], VIDEO_HORIZONTAL_PIXELS * BYTES_PER_PIXEL); -#endif } }
@@ -25,7 +25,8 @@ static void GBAVideoDummyRendererWritePalette(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value);
static void GBAVideoDummyRendererWriteOAM(struct GBAVideoRenderer* renderer, uint32_t oam); static void GBAVideoDummyRendererDrawScanline(struct GBAVideoRenderer* renderer, int y); static void GBAVideoDummyRendererFinishFrame(struct GBAVideoRenderer* renderer); -static void GBAVideoDummyRendererGetPixels(struct GBAVideoRenderer* renderer, unsigned* stride, const void** pixels); +static void GBAVideoDummyRendererGetPixels(struct GBAVideoRenderer* renderer, size_t* stride, const void** pixels); +static void GBAVideoDummyRendererPutPixels(struct GBAVideoRenderer* renderer, size_t stride, const void* pixels); const int GBAVideoObjSizes[16][2] = { { 8, 8 },@@ -57,6 +58,7 @@ .writeOAM = GBAVideoDummyRendererWriteOAM,
.drawScanline = GBAVideoDummyRendererDrawScanline, .finishFrame = GBAVideoDummyRendererFinishFrame, .getPixels = GBAVideoDummyRendererGetPixels, + .putPixels = GBAVideoDummyRendererPutPixels, .cache = NULL };@@ -294,7 +296,14 @@ UNUSED(renderer);
// Nothing to do } -static void GBAVideoDummyRendererGetPixels(struct GBAVideoRenderer* renderer, unsigned* stride, const void** pixels) { +static void GBAVideoDummyRendererGetPixels(struct GBAVideoRenderer* renderer, size_t* stride, const void** pixels) { + UNUSED(renderer); + UNUSED(stride); + UNUSED(pixels); + // Nothing to do +} + +static void GBAVideoDummyRendererPutPixels(struct GBAVideoRenderer* renderer, size_t stride, const void* pixels) { UNUSED(renderer); UNUSED(stride); UNUSED(pixels);
@@ -164,8 +164,8 @@ void (*writeOAM)(struct GBAVideoRenderer* renderer, uint32_t oam);
void (*drawScanline)(struct GBAVideoRenderer* renderer, int y); void (*finishFrame)(struct GBAVideoRenderer* renderer); - void (*getPixels)(struct GBAVideoRenderer* renderer, unsigned* stride, const void** pixels); - void (*putPixels)(struct GBAVideoRenderer* renderer, unsigned stride, void* pixels); + void (*getPixels)(struct GBAVideoRenderer* renderer, size_t* stride, const void** pixels); + void (*putPixels)(struct GBAVideoRenderer* renderer, size_t stride, const void* pixels); uint16_t* palette; uint16_t* vram;
@@ -205,7 +205,7 @@ c |= (row[x * 3 + 1] << 2) & 0x3E0;
c |= (row[x * 3] << 7) & 0x7C00; #endif ((uint16_t*) pixelData)[stride * i + x] = c; -#endif +#else #if __BIG_ENDIAN__ pixelData[stride * i * 4 + x * 4 + 3] = row[x * 3]; pixelData[stride * i * 4 + x * 4 + 2] = row[x * 3 + 1];@@ -216,6 +216,7 @@ pixelData[stride * i * 4 + x * 4] = row[x * 3];
pixelData[stride * i * 4 + x * 4 + 1] = row[x * 3 + 1]; pixelData[stride * i * 4 + x * 4 + 2] = row[x * 3 + 2]; pixelData[stride * i * 4 + x * 4 + 3] = 0xFF; +#endif #endif } }