mirror of https://github.com/mgba-emu/mgba.git
GBA Video: GL screenshots
This commit is contained in:
parent
ac7ae74822
commit
8a26a7977c
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue