GBA Video: GL screenshots

This commit is contained in:
Vicki Pfau 2019-05-16 17:09:50 -07:00
parent ac7ae74822
commit 8a26a7977c
6 changed files with 41 additions and 12 deletions

View File

@ -32,6 +32,7 @@ enum mVideoLoggerEvent {
LOGGER_EVENT_INIT,
LOGGER_EVENT_DEINIT,
LOGGER_EVENT_RESET,
LOGGER_EVENT_GET_PIXELS,
};
struct mVideoLoggerDirtyInfo {
@ -73,6 +74,9 @@ struct mVideoLogger {
uint16_t* vram;
uint16_t* oam;
uint16_t* palette;
const void* pixelBuffer;
size_t pixelStride;
};
void mVideoLoggerRendererCreate(struct mVideoLogger* logger, bool readonly);

View File

@ -121,6 +121,8 @@ struct GBAVideoGLShader {
struct GBAVideoGLRenderer {
struct GBAVideoRenderer d;
uint32_t* temporaryBuffer;
struct GBAVideoGLBackground bg[4];
int oamMax;

View File

@ -283,11 +283,13 @@ static void GBVideoProxyRendererGetPixels(struct GBVideoRenderer* renderer, size
proxyRenderer->logger->lock(proxyRenderer->logger);
// Insert an extra item into the queue to make sure it gets flushed
mVideoLoggerRendererFlush(proxyRenderer->logger);
proxyRenderer->logger->wait(proxyRenderer->logger);
}
proxyRenderer->backend->getPixels(proxyRenderer->backend, stride, pixels);
if (proxyRenderer->logger->block && proxyRenderer->logger->wait) {
proxyRenderer->logger->postEvent(proxyRenderer->logger, LOGGER_EVENT_GET_PIXELS);
mVideoLoggerRendererFlush(proxyRenderer->logger);
proxyRenderer->logger->unlock(proxyRenderer->logger);
*pixels = proxyRenderer->logger->pixelBuffer;
*stride = proxyRenderer->logger->pixelStride;
} else {
proxyRenderer->backend->getPixels(proxyRenderer->backend, stride, pixels);
}
}

View File

@ -310,13 +310,13 @@ static void _GBACoreSetVideoGLTex(struct mCore* core, unsigned texid) {
}
static void _GBACoreGetPixels(struct mCore* core, const void** buffer, size_t* stride) {
struct GBACore* gbacore = (struct GBACore*) core;
gbacore->renderer.d.getPixels(&gbacore->renderer.d, stride, buffer);
struct GBA* gba = core->board;
gba->video.renderer->getPixels(gba->video.renderer, 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);
struct GBA* gba = core->board;
gba->video.renderer->putPixels(gba->video.renderer, stride, buffer);
}
static struct blip_t* _GBACoreGetAudioChannel(struct mCore* core, int ch) {

View File

@ -152,6 +152,9 @@ static void _handleEvent(struct mVideoLogger* logger, enum mVideoLoggerEvent eve
case LOGGER_EVENT_RESET:
proxyRenderer->backend->reset(proxyRenderer->backend);
break;
case LOGGER_EVENT_GET_PIXELS:
proxyRenderer->backend->getPixels(proxyRenderer->backend, &logger->pixelStride, &logger->pixelBuffer);
break;
}
}
@ -305,10 +308,13 @@ static void GBAVideoProxyRendererGetPixels(struct GBAVideoRenderer* renderer, si
proxyRenderer->logger->lock(proxyRenderer->logger);
// Insert an extra item into the queue to make sure it gets flushed
mVideoLoggerRendererFlush(proxyRenderer->logger);
}
proxyRenderer->backend->getPixels(proxyRenderer->backend, stride, pixels);
if (proxyRenderer->logger->block && proxyRenderer->logger->wait) {
proxyRenderer->logger->postEvent(proxyRenderer->logger, LOGGER_EVENT_GET_PIXELS);
mVideoLoggerRendererFlush(proxyRenderer->logger);
proxyRenderer->logger->unlock(proxyRenderer->logger);
*pixels = proxyRenderer->logger->pixelBuffer;
*stride = proxyRenderer->logger->pixelStride;
} else {
proxyRenderer->backend->getPixels(proxyRenderer->backend, stride, pixels);
}
}

View File

@ -11,6 +11,7 @@
#include <mgba/internal/arm/macros.h>
#include <mgba/internal/gba/io.h>
#include <mgba/internal/gba/renderers/cache-set.h>
#include <mgba-util/memory.h>
static void GBAVideoGLRendererInit(struct GBAVideoRenderer* renderer);
static void GBAVideoGLRendererDeinit(struct GBAVideoRenderer* renderer);
@ -435,6 +436,8 @@ static void _initFramebufferTexture(GLuint tex, GLenum format, GLenum attachment
void GBAVideoGLRendererInit(struct GBAVideoRenderer* renderer) {
struct GBAVideoGLRenderer* glRenderer = (struct GBAVideoGLRenderer*) renderer;
glRenderer->temporaryBuffer = NULL;
glGenFramebuffers(GBA_GL_FBO_MAX, glRenderer->fbo);
glGenTextures(GBA_GL_TEX_MAX, glRenderer->layers);
@ -552,6 +555,9 @@ void GBAVideoGLRendererInit(struct GBAVideoRenderer* renderer) {
void GBAVideoGLRendererDeinit(struct GBAVideoRenderer* renderer) {
struct GBAVideoGLRenderer* glRenderer = (struct GBAVideoGLRenderer*) renderer;
if (glRenderer->temporaryBuffer) {
mappedMemoryFree(glRenderer->temporaryBuffer, GBA_VIDEO_HORIZONTAL_PIXELS * GBA_VIDEO_VERTICAL_PIXELS * glRenderer->scale * glRenderer->scale);
}
glDeleteFramebuffers(GBA_GL_FBO_MAX, glRenderer->fbo);
glDeleteTextures(GBA_GL_TEX_MAX, glRenderer->layers);
glDeleteTextures(1, &glRenderer->paletteTex);
@ -928,7 +934,16 @@ void GBAVideoGLRendererFinishFrame(struct GBAVideoRenderer* renderer) {
}
void GBAVideoGLRendererGetPixels(struct GBAVideoRenderer* renderer, size_t* stride, const void** pixels) {
struct GBAVideoGLRenderer* glRenderer = (struct GBAVideoGLRenderer*) renderer;
*stride = GBA_VIDEO_HORIZONTAL_PIXELS * glRenderer->scale;
if (!glRenderer->temporaryBuffer) {
glRenderer->temporaryBuffer = anonymousMemoryMap(GBA_VIDEO_HORIZONTAL_PIXELS * GBA_VIDEO_VERTICAL_PIXELS * glRenderer->scale * glRenderer->scale * BYTES_PER_PIXEL);
}
glBindFramebuffer(GL_FRAMEBUFFER, glRenderer->fbo[GBA_GL_FBO_OUTPUT]);
glPixelStorei(GL_PACK_ROW_LENGTH, GBA_VIDEO_HORIZONTAL_PIXELS * glRenderer->scale);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0, 0, GBA_VIDEO_HORIZONTAL_PIXELS * glRenderer->scale, GBA_VIDEO_VERTICAL_PIXELS * glRenderer->scale, GL_RGBA, GL_UNSIGNED_BYTE, (void*) glRenderer->temporaryBuffer);
*pixels = glRenderer->temporaryBuffer;
}
void GBAVideoGLRendererPutPixels(struct GBAVideoRenderer* renderer, size_t stride, const void* pixels) {