Core: Add functions for pakcing and unpacking pixels

This commit is contained in:
Jeffrey Pfau 2016-09-17 03:37:04 -07:00
parent 36ea350c6a
commit 5425cff3e2
14 changed files with 82 additions and 92 deletions

View File

@ -171,7 +171,7 @@ void mCoreDeleteState(struct mCore* core, int slot) {
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 @@ void mCoreTakeScreenshot(struct mCore* core) {
#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);

View File

@ -56,7 +56,9 @@ struct mCore {
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);

View File

@ -7,7 +7,6 @@
#include "core/core.h"
#include "core/cheats.h"
#include "core/sync.h"
#include "util/memory.h"
#include "util/vfs.h"
@ -148,18 +147,12 @@ bool mStateExtdataDeserialize(struct mStateExtdata* extdata, struct VFile* vf) {
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 @@ bool mCoreLoadStateNamed(struct mCore* core, struct VFile* vf, int flags) {
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");
}

View File

@ -121,10 +121,14 @@ static void _GBCoreSetVideoBuffer(struct mCore* core, color_t* buffer, size_t st
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 @@ struct mCore* GBCoreCreate(void) {
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;

View File

@ -15,8 +15,8 @@ static void GBVideoSoftwareRendererWritePalette(struct GBVideoRenderer* renderer
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 @@ void GBVideoSoftwareRendererCreate(struct GBVideoSoftwareRenderer* renderer) {
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 GBVideoSoftwareRendererDrawObj(struct GBVideoSoftwareRenderer* rende
}
}
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 @@ static void GBVideoSoftwareRendererGetPixels(struct GBVideoRenderer* renderer, u
*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);
}
}

View File

@ -20,7 +20,8 @@ static void GBVideoDummyRendererWritePalette(struct GBVideoRenderer* renderer, i
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 @@ static struct GBVideoRenderer dummyRenderer = {
.drawRange = GBVideoDummyRendererDrawRange,
.finishScanline = GBVideoDummyRendererFinishScanline,
.finishFrame = GBVideoDummyRendererFinishFrame,
.getPixels = GBVideoDummyRendererGetPixels
.getPixels = GBVideoDummyRendererGetPixels,
.putPixels = GBVideoDummyRendererPutPixels,
};
void GBVideoInit(struct GBVideo* video) {
@ -127,7 +129,7 @@ int32_t GBVideoProcessEvents(struct GBVideo* video, int32_t cycles) {
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 @@ static void GBVideoDummyRendererFinishFrame(struct GBVideoRenderer* 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);

View File

@ -63,8 +63,8 @@ struct GBVideoRenderer {
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;

View File

@ -152,10 +152,14 @@ static void _GBACoreSetVideoBuffer(struct mCore* core, color_t* buffer, size_t s
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 @@ struct mCore* GBACoreCreate(void) {
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;

View File

@ -856,7 +856,7 @@ void GBAFrameEnded(struct GBA* gba) {
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);
}

View File

@ -38,8 +38,8 @@ static void GBAVideoThreadProxyRendererWritePalette(struct GBAVideoRenderer* ren
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 @@ void GBAVideoThreadProxyRendererFinishFrame(struct GBAVideoRenderer* renderer) {
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 @@ static void GBAVideoThreadProxyRendererGetPixels(struct GBAVideoRenderer* render
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

View File

@ -21,8 +21,8 @@ static void GBAVideoSoftwareRendererWritePalette(struct GBAVideoRenderer* render
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 @@ static void GBAVideoSoftwareRendererFinishFrame(struct GBAVideoRenderer* rendere
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
}
}

View File

@ -25,7 +25,8 @@ static void GBAVideoDummyRendererWritePalette(struct GBAVideoRenderer* renderer,
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 @@ static struct GBAVideoRenderer dummyRenderer = {
.drawScanline = GBAVideoDummyRendererDrawScanline,
.finishFrame = GBAVideoDummyRendererFinishFrame,
.getPixels = GBAVideoDummyRendererGetPixels,
.putPixels = GBAVideoDummyRendererPutPixels,
.cache = NULL
};
@ -294,7 +296,14 @@ static void GBAVideoDummyRendererFinishFrame(struct GBAVideoRenderer* 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);

View File

@ -164,8 +164,8 @@ struct GBAVideoRenderer {
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;

View File

@ -205,7 +205,7 @@ bool PNGReadPixels(png_structp png, png_infop info, void* pixels, unsigned width
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 @@ bool PNGReadPixels(png_structp png, png_infop info, void* pixels, unsigned width
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
}
}