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_INIT,
LOGGER_EVENT_DEINIT, LOGGER_EVENT_DEINIT,
LOGGER_EVENT_RESET, LOGGER_EVENT_RESET,
LOGGER_EVENT_GET_PIXELS,
}; };
struct mVideoLoggerDirtyInfo { struct mVideoLoggerDirtyInfo {
@ -73,6 +74,9 @@ struct mVideoLogger {
uint16_t* vram; uint16_t* vram;
uint16_t* oam; uint16_t* oam;
uint16_t* palette; uint16_t* palette;
const void* pixelBuffer;
size_t pixelStride;
}; };
void mVideoLoggerRendererCreate(struct mVideoLogger* logger, bool readonly); void mVideoLoggerRendererCreate(struct mVideoLogger* logger, bool readonly);

View File

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

View File

@ -283,11 +283,13 @@ static void GBVideoProxyRendererGetPixels(struct GBVideoRenderer* renderer, size
proxyRenderer->logger->lock(proxyRenderer->logger); proxyRenderer->logger->lock(proxyRenderer->logger);
// Insert an extra item into the queue to make sure it gets flushed // Insert an extra item into the queue to make sure it gets flushed
mVideoLoggerRendererFlush(proxyRenderer->logger); mVideoLoggerRendererFlush(proxyRenderer->logger);
proxyRenderer->logger->wait(proxyRenderer->logger); proxyRenderer->logger->postEvent(proxyRenderer->logger, LOGGER_EVENT_GET_PIXELS);
} mVideoLoggerRendererFlush(proxyRenderer->logger);
proxyRenderer->backend->getPixels(proxyRenderer->backend, stride, pixels);
if (proxyRenderer->logger->block && proxyRenderer->logger->wait) {
proxyRenderer->logger->unlock(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) { static void _GBACoreGetPixels(struct mCore* core, const void** buffer, size_t* stride) {
struct GBACore* gbacore = (struct GBACore*) core; struct GBA* gba = core->board;
gbacore->renderer.d.getPixels(&gbacore->renderer.d, stride, buffer); gba->video.renderer->getPixels(gba->video.renderer, stride, buffer);
} }
static void _GBACorePutPixels(struct mCore* core, const void* buffer, size_t stride) { static void _GBACorePutPixels(struct mCore* core, const void* buffer, size_t stride) {
struct GBACore* gbacore = (struct GBACore*) core; struct GBA* gba = core->board;
gbacore->renderer.d.putPixels(&gbacore->renderer.d, stride, buffer); gba->video.renderer->putPixels(gba->video.renderer, stride, buffer);
} }
static struct blip_t* _GBACoreGetAudioChannel(struct mCore* core, int ch) { 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: case LOGGER_EVENT_RESET:
proxyRenderer->backend->reset(proxyRenderer->backend); proxyRenderer->backend->reset(proxyRenderer->backend);
break; 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); proxyRenderer->logger->lock(proxyRenderer->logger);
// Insert an extra item into the queue to make sure it gets flushed // Insert an extra item into the queue to make sure it gets flushed
mVideoLoggerRendererFlush(proxyRenderer->logger); mVideoLoggerRendererFlush(proxyRenderer->logger);
} proxyRenderer->logger->postEvent(proxyRenderer->logger, LOGGER_EVENT_GET_PIXELS);
proxyRenderer->backend->getPixels(proxyRenderer->backend, stride, pixels); mVideoLoggerRendererFlush(proxyRenderer->logger);
if (proxyRenderer->logger->block && proxyRenderer->logger->wait) {
proxyRenderer->logger->unlock(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/arm/macros.h>
#include <mgba/internal/gba/io.h> #include <mgba/internal/gba/io.h>
#include <mgba/internal/gba/renderers/cache-set.h> #include <mgba/internal/gba/renderers/cache-set.h>
#include <mgba-util/memory.h>
static void GBAVideoGLRendererInit(struct GBAVideoRenderer* renderer); static void GBAVideoGLRendererInit(struct GBAVideoRenderer* renderer);
static void GBAVideoGLRendererDeinit(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) { void GBAVideoGLRendererInit(struct GBAVideoRenderer* renderer) {
struct GBAVideoGLRenderer* glRenderer = (struct GBAVideoGLRenderer*) renderer; struct GBAVideoGLRenderer* glRenderer = (struct GBAVideoGLRenderer*) renderer;
glRenderer->temporaryBuffer = NULL;
glGenFramebuffers(GBA_GL_FBO_MAX, glRenderer->fbo); glGenFramebuffers(GBA_GL_FBO_MAX, glRenderer->fbo);
glGenTextures(GBA_GL_TEX_MAX, glRenderer->layers); glGenTextures(GBA_GL_TEX_MAX, glRenderer->layers);
@ -552,6 +555,9 @@ void GBAVideoGLRendererInit(struct GBAVideoRenderer* renderer) {
void GBAVideoGLRendererDeinit(struct GBAVideoRenderer* renderer) { void GBAVideoGLRendererDeinit(struct GBAVideoRenderer* renderer) {
struct GBAVideoGLRenderer* glRenderer = (struct GBAVideoGLRenderer*) 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); glDeleteFramebuffers(GBA_GL_FBO_MAX, glRenderer->fbo);
glDeleteTextures(GBA_GL_TEX_MAX, glRenderer->layers); glDeleteTextures(GBA_GL_TEX_MAX, glRenderer->layers);
glDeleteTextures(1, &glRenderer->paletteTex); glDeleteTextures(1, &glRenderer->paletteTex);
@ -928,7 +934,16 @@ void GBAVideoGLRendererFinishFrame(struct GBAVideoRenderer* renderer) {
} }
void GBAVideoGLRendererGetPixels(struct GBAVideoRenderer* renderer, size_t* stride, const void** pixels) { 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) { void GBAVideoGLRendererPutPixels(struct GBAVideoRenderer* renderer, size_t stride, const void* pixels) {