Feature: More video logging plumbing
@@ -29,6 +29,7 @@ Condition fromThreadCond;
Condition toThreadCond; Mutex mutex; enum mVideoThreadProxyState threadState; + enum mVideoLoggerEvent event; struct RingFIFO dirtyQueue; };
@@ -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;
@@ -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;
@@ -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) {
@@ -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() {
@@ -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() {
@@ -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();