all repos — mgba @ 82ef919ee27e93f684d260dd147f71f601806b64

mGBA Game Boy Advance Emulator

Feature: More video logging plumbing
Vicki Pfau vi@endrift.com
Fri, 10 May 2019 11:13:21 -0700
commit

82ef919ee27e93f684d260dd147f71f601806b64

parent

42813bb197dee028b64ba70b0a9b63aea2cf264c

M include/mgba/feature/thread-proxy.hinclude/mgba/feature/thread-proxy.h

@@ -29,6 +29,7 @@ Condition fromThreadCond;

Condition toThreadCond; Mutex mutex; enum mVideoThreadProxyState threadState; + enum mVideoLoggerEvent event; struct RingFIFO dirtyQueue; };
M include/mgba/feature/video-logger.hinclude/mgba/feature/video-logger.h

@@ -27,6 +27,13 @@ DIRTY_RANGE,

DIRTY_BUFFER, }; +enum mVideoLoggerEvent { + LOGGER_EVENT_NONE = 0, + LOGGER_EVENT_INIT, + LOGGER_EVENT_DEINIT, + LOGGER_EVENT_RESET, +}; + struct mVideoLoggerDirtyInfo { enum mVideoLoggerDirtyType type; uint32_t address;

@@ -38,6 +45,7 @@ struct VFile;

struct mVideoLogger { bool (*writeData)(struct mVideoLogger* logger, const void* data, size_t length); bool (*readData)(struct mVideoLogger* logger, void* data, size_t length, bool block); + void (*postEvent)(struct mVideoLogger* logger, enum mVideoLoggerEvent event); void* dataContext; bool block;

@@ -52,6 +60,7 @@ void (*wake)(struct mVideoLogger*, int y);

void* context; bool (*parsePacket)(struct mVideoLogger* logger, const struct mVideoLoggerDirtyInfo* packet); + void (*handleEvent)(struct mVideoLogger* logger, enum mVideoLoggerEvent event); uint16_t* (*vramBlock)(struct mVideoLogger* logger, uint32_t address); size_t vramSize;
M src/feature/thread-proxy.csrc/feature/thread-proxy.c

@@ -18,6 +18,7 @@ static THREAD_ENTRY _proxyThread(void* renderer);

static bool _writeData(struct mVideoLogger* logger, const void* data, size_t length); static bool _readData(struct mVideoLogger* logger, void* data, size_t length, bool block); +static void _postEvent(struct mVideoLogger* logger, enum mVideoLoggerEvent); static void _lock(struct mVideoLogger* logger); static void _unlock(struct mVideoLogger* logger);

@@ -38,6 +39,7 @@ renderer->d.wake = _wake;

renderer->d.writeData = _writeData; renderer->d.readData = _readData; + renderer->d.postEvent = _postEvent; } void mVideoThreadProxyInit(struct mVideoLogger* logger) {

@@ -131,6 +133,14 @@ }

return read; } +static void _postEvent(struct mVideoLogger* logger, enum mVideoLoggerEvent event) { + struct mVideoThreadProxy* proxyRenderer = (struct mVideoThreadProxy*) logger; + MutexLock(&proxyRenderer->mutex); + proxyRenderer->event = event; + ConditionWake(&proxyRenderer->toThreadCond); + MutexUnlock(&proxyRenderer->mutex); +} + static void _lock(struct mVideoLogger* logger) { struct mVideoThreadProxy* proxyRenderer = (struct mVideoThreadProxy*) logger; MutexLock(&proxyRenderer->mutex);

@@ -172,13 +182,18 @@ if (proxyRenderer->threadState == PROXY_THREAD_STOPPED) {

break; } proxyRenderer->threadState = PROXY_THREAD_BUSY; - MutexUnlock(&proxyRenderer->mutex); - if (!mVideoLoggerRendererRun(&proxyRenderer->d, false)) { - // FIFO was corrupted - proxyRenderer->threadState = PROXY_THREAD_STOPPED; - mLOG(GBA_VIDEO, ERROR, "Proxy thread queue got corrupted!"); + if (proxyRenderer->event) { + proxyRenderer->d.handleEvent(&proxyRenderer->d, proxyRenderer->event); + proxyRenderer->event = 0; + } else { + MutexUnlock(&proxyRenderer->mutex); + if (!mVideoLoggerRendererRun(&proxyRenderer->d, false)) { + // FIFO was corrupted + proxyRenderer->threadState = PROXY_THREAD_STOPPED; + mLOG(GBA_VIDEO, ERROR, "Proxy thread queue got corrupted!"); + } + MutexLock(&proxyRenderer->mutex); } - MutexLock(&proxyRenderer->mutex); ConditionWake(&proxyRenderer->fromThreadCond); if (proxyRenderer->threadState != PROXY_THREAD_STOPPED) { proxyRenderer->threadState = PROXY_THREAD_IDLE;
M src/gba/extra/proxy.csrc/gba/extra/proxy.c

@@ -21,6 +21,7 @@ static void GBAVideoProxyRendererFinishFrame(struct GBAVideoRenderer* renderer);

static void GBAVideoProxyRendererGetPixels(struct GBAVideoRenderer* renderer, size_t* stride, const void** pixels); static void GBAVideoProxyRendererPutPixels(struct GBAVideoRenderer* renderer, size_t stride, const void* pixels); +static void _handleEvent(struct mVideoLogger* logger, enum mVideoLoggerEvent event); static bool _parsePacket(struct mVideoLogger* logger, const struct mVideoLoggerDirtyInfo* packet); static uint16_t* _vramBlock(struct mVideoLogger* logger, uint32_t address);

@@ -45,6 +46,7 @@ renderer->d.disableOBJ = false;

renderer->logger->context = renderer; renderer->logger->parsePacket = _parsePacket; + renderer->logger->handleEvent = _handleEvent; renderer->logger->vramBlock = _vramBlock; renderer->logger->paletteSize = SIZE_PALETTE_RAM; renderer->logger->vramSize = SIZE_VRAM;

@@ -105,7 +107,11 @@

_init(proxyRenderer); _reset(proxyRenderer); - proxyRenderer->backend->init(proxyRenderer->backend); + if (!proxyRenderer->logger->block) { + proxyRenderer->backend->init(proxyRenderer->backend); + } else { + proxyRenderer->logger->postEvent(proxyRenderer->logger, LOGGER_EVENT_INIT); + } } void GBAVideoProxyRendererReset(struct GBAVideoRenderer* renderer) {

@@ -113,15 +119,40 @@ struct GBAVideoProxyRenderer* proxyRenderer = (struct GBAVideoProxyRenderer*) renderer;

_reset(proxyRenderer); - proxyRenderer->backend->reset(proxyRenderer->backend); + if (!proxyRenderer->logger->block) { + proxyRenderer->backend->reset(proxyRenderer->backend); + } else { + proxyRenderer->logger->postEvent(proxyRenderer->logger, LOGGER_EVENT_RESET); + } } void GBAVideoProxyRendererDeinit(struct GBAVideoRenderer* renderer) { struct GBAVideoProxyRenderer* proxyRenderer = (struct GBAVideoProxyRenderer*) renderer; - proxyRenderer->backend->deinit(proxyRenderer->backend); + if (!proxyRenderer->logger->block) { + proxyRenderer->backend->deinit(proxyRenderer->backend); + } else { + proxyRenderer->logger->postEvent(proxyRenderer->logger, LOGGER_EVENT_DEINIT); + } mVideoLoggerRendererDeinit(proxyRenderer->logger); +} + +static void _handleEvent(struct mVideoLogger* logger, enum mVideoLoggerEvent event) { + struct GBAVideoProxyRenderer* proxyRenderer = logger->context; + switch (event) { + default: + break; + case LOGGER_EVENT_INIT: + proxyRenderer->backend->init(proxyRenderer->backend); + break; + case LOGGER_EVENT_DEINIT: + proxyRenderer->backend->deinit(proxyRenderer->backend); + break; + case LOGGER_EVENT_RESET: + proxyRenderer->backend->reset(proxyRenderer->backend); + break; + } } static bool _parsePacket(struct mVideoLogger* logger, const struct mVideoLoggerDirtyInfo* item) {
M src/platform/qt/DisplayGL.cppsrc/platform/qt/DisplayGL.cpp

@@ -40,6 +40,7 @@ m_gl->setAttribute(Qt::WA_TransparentForMouseEvents); // This doesn't seem to work?

setUpdatesEnabled(false); // Prevent paint events, which can cause race conditions connect(&m_videoProxy, &VideoProxy::dataAvailable, &m_videoProxy, &VideoProxy::processData); + connect(&m_videoProxy, &VideoProxy::eventPosted, &m_videoProxy, &VideoProxy::handleEvent); } DisplayGL::~DisplayGL() {
M src/platform/qt/VideoProxy.cppsrc/platform/qt/VideoProxy.cpp

@@ -23,6 +23,7 @@ m_logger.d.wake = &callback<void, int>::func<&VideoProxy::wake>;

m_logger.d.writeData = &callback<bool, const void*, size_t>::func<&VideoProxy::writeData>; m_logger.d.readData = &callback<bool, void*, size_t, bool>::func<&VideoProxy::readData>; + m_logger.d.postEvent = &callback<void, enum mVideoLoggerEvent>::func<&VideoProxy::postEvent>; } void VideoProxy::attach(CoreController* controller) {

@@ -72,6 +73,14 @@ m_toThreadCond.wait(&m_mutex);

m_mutex.unlock(); } return read; +} + +void VideoProxy::postEvent(enum mVideoLoggerEvent event) { + emit eventPosted(event); +} + +void VideoProxy::handleEvent(int event) { + m_logger.d.handleEvent(&m_logger.d, static_cast<enum mVideoLoggerEvent>(event)); } void VideoProxy::lock() {
M src/platform/qt/VideoProxy.hsrc/platform/qt/VideoProxy.h

@@ -26,9 +26,11 @@ void attach(CoreController*);

signals: void dataAvailable(); + void eventPosted(int); public slots: void processData(); + void handleEvent(int); private: void init();

@@ -37,6 +39,7 @@ void deinit();

bool writeData(const void* data, size_t length); bool readData(void* data, size_t length, bool block); + void postEvent(enum mVideoLoggerEvent event); void lock(); void unlock();