GBA Video: GL screenshots
Vicki Pfau vi@endrift.com
Thu, 16 May 2019 17:09:50 -0700
6 files changed,
41 insertions(+),
12 deletions(-)
M
include/mgba/feature/video-logger.h
→
include/mgba/feature/video-logger.h
@@ -32,6 +32,7 @@ LOGGER_EVENT_NONE = 0,
LOGGER_EVENT_INIT, LOGGER_EVENT_DEINIT, LOGGER_EVENT_RESET, + LOGGER_EVENT_GET_PIXELS, }; struct mVideoLoggerDirtyInfo {@@ -73,6 +74,9 @@
uint16_t* vram; uint16_t* oam; uint16_t* palette; + + const void* pixelBuffer; + size_t pixelStride; }; void mVideoLoggerRendererCreate(struct mVideoLogger* logger, bool readonly);
M
include/mgba/internal/gba/renderers/gl.h
→
include/mgba/internal/gba/renderers/gl.h
@@ -121,6 +121,8 @@
struct GBAVideoGLRenderer { struct GBAVideoRenderer d; + uint32_t* temporaryBuffer; + struct GBAVideoGLBackground bg[4]; int oamMax;
M
src/gb/extra/proxy.c
→
src/gb/extra/proxy.c
@@ -283,11 +283,13 @@ if (proxyRenderer->logger->block && proxyRenderer->logger->wait) {
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); } }
M
src/gba/core.c
→
src/gba/core.c
@@ -310,13 +310,13 @@ #endif
} 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) {
M
src/gba/extra/proxy.c
→
src/gba/extra/proxy.c
@@ -152,6 +152,9 @@ break;
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 @@ if (proxyRenderer->logger->block && proxyRenderer->logger->wait) {
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); } }
M
src/gba/renderers/gl.c
→
src/gba/renderers/gl.c
@@ -11,6 +11,7 @@ #include <mgba/core/cache-set.h>
#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 @@ }
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 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 @@ glFlush();
} 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) {