Feature: More video logging plumbing

This commit is contained in:
Vicki Pfau 2019-05-10 11:13:21 -07:00
parent 42813bb197
commit 82ef919ee2
7 changed files with 78 additions and 9 deletions

View File

@ -29,6 +29,7 @@ struct mVideoThreadProxy {
Condition toThreadCond; Condition toThreadCond;
Mutex mutex; Mutex mutex;
enum mVideoThreadProxyState threadState; enum mVideoThreadProxyState threadState;
enum mVideoLoggerEvent event;
struct RingFIFO dirtyQueue; struct RingFIFO dirtyQueue;
}; };

View File

@ -27,6 +27,13 @@ enum mVideoLoggerDirtyType {
DIRTY_BUFFER, DIRTY_BUFFER,
}; };
enum mVideoLoggerEvent {
LOGGER_EVENT_NONE = 0,
LOGGER_EVENT_INIT,
LOGGER_EVENT_DEINIT,
LOGGER_EVENT_RESET,
};
struct mVideoLoggerDirtyInfo { struct mVideoLoggerDirtyInfo {
enum mVideoLoggerDirtyType type; enum mVideoLoggerDirtyType type;
uint32_t address; uint32_t address;
@ -38,6 +45,7 @@ struct VFile;
struct mVideoLogger { struct mVideoLogger {
bool (*writeData)(struct mVideoLogger* logger, const void* data, size_t length); bool (*writeData)(struct mVideoLogger* logger, const void* data, size_t length);
bool (*readData)(struct mVideoLogger* logger, void* data, size_t length, bool block); bool (*readData)(struct mVideoLogger* logger, void* data, size_t length, bool block);
void (*postEvent)(struct mVideoLogger* logger, enum mVideoLoggerEvent event);
void* dataContext; void* dataContext;
bool block; bool block;
@ -52,6 +60,7 @@ struct mVideoLogger {
void* context; void* context;
bool (*parsePacket)(struct mVideoLogger* logger, const struct mVideoLoggerDirtyInfo* packet); 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); uint16_t* (*vramBlock)(struct mVideoLogger* logger, uint32_t address);
size_t vramSize; size_t vramSize;

View File

@ -18,6 +18,7 @@ static THREAD_ENTRY _proxyThread(void* renderer);
static bool _writeData(struct mVideoLogger* logger, const void* data, size_t length); 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 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 _lock(struct mVideoLogger* logger);
static void _unlock(struct mVideoLogger* logger); static void _unlock(struct mVideoLogger* logger);
@ -38,6 +39,7 @@ void mVideoThreadProxyCreate(struct mVideoThreadProxy* renderer) {
renderer->d.writeData = _writeData; renderer->d.writeData = _writeData;
renderer->d.readData = _readData; renderer->d.readData = _readData;
renderer->d.postEvent = _postEvent;
} }
void mVideoThreadProxyInit(struct mVideoLogger* logger) { void mVideoThreadProxyInit(struct mVideoLogger* logger) {
@ -131,6 +133,14 @@ static bool _readData(struct mVideoLogger* logger, void* data, size_t length, bo
return read; 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) { static void _lock(struct mVideoLogger* logger) {
struct mVideoThreadProxy* proxyRenderer = (struct mVideoThreadProxy*) logger; struct mVideoThreadProxy* proxyRenderer = (struct mVideoThreadProxy*) logger;
MutexLock(&proxyRenderer->mutex); MutexLock(&proxyRenderer->mutex);
@ -172,13 +182,18 @@ static THREAD_ENTRY _proxyThread(void* logger) {
break; break;
} }
proxyRenderer->threadState = PROXY_THREAD_BUSY; proxyRenderer->threadState = PROXY_THREAD_BUSY;
MutexUnlock(&proxyRenderer->mutex); if (proxyRenderer->event) {
if (!mVideoLoggerRendererRun(&proxyRenderer->d, false)) { proxyRenderer->d.handleEvent(&proxyRenderer->d, proxyRenderer->event);
// FIFO was corrupted proxyRenderer->event = 0;
proxyRenderer->threadState = PROXY_THREAD_STOPPED; } else {
mLOG(GBA_VIDEO, ERROR, "Proxy thread queue got corrupted!"); 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); ConditionWake(&proxyRenderer->fromThreadCond);
if (proxyRenderer->threadState != PROXY_THREAD_STOPPED) { if (proxyRenderer->threadState != PROXY_THREAD_STOPPED) {
proxyRenderer->threadState = PROXY_THREAD_IDLE; proxyRenderer->threadState = PROXY_THREAD_IDLE;

View File

@ -21,6 +21,7 @@ static void GBAVideoProxyRendererFinishFrame(struct GBAVideoRenderer* renderer);
static void GBAVideoProxyRendererGetPixels(struct GBAVideoRenderer* renderer, size_t* stride, const void** pixels); 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 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 bool _parsePacket(struct mVideoLogger* logger, const struct mVideoLoggerDirtyInfo* packet);
static uint16_t* _vramBlock(struct mVideoLogger* logger, uint32_t address); static uint16_t* _vramBlock(struct mVideoLogger* logger, uint32_t address);
@ -45,6 +46,7 @@ void GBAVideoProxyRendererCreate(struct GBAVideoProxyRenderer* renderer, struct
renderer->logger->context = renderer; renderer->logger->context = renderer;
renderer->logger->parsePacket = _parsePacket; renderer->logger->parsePacket = _parsePacket;
renderer->logger->handleEvent = _handleEvent;
renderer->logger->vramBlock = _vramBlock; renderer->logger->vramBlock = _vramBlock;
renderer->logger->paletteSize = SIZE_PALETTE_RAM; renderer->logger->paletteSize = SIZE_PALETTE_RAM;
renderer->logger->vramSize = SIZE_VRAM; renderer->logger->vramSize = SIZE_VRAM;
@ -105,7 +107,11 @@ void GBAVideoProxyRendererInit(struct GBAVideoRenderer* renderer) {
_init(proxyRenderer); _init(proxyRenderer);
_reset(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) { void GBAVideoProxyRendererReset(struct GBAVideoRenderer* renderer) {
@ -113,17 +119,42 @@ void GBAVideoProxyRendererReset(struct GBAVideoRenderer* renderer) {
_reset(proxyRenderer); _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) { void GBAVideoProxyRendererDeinit(struct GBAVideoRenderer* renderer) {
struct GBAVideoProxyRenderer* proxyRenderer = (struct GBAVideoProxyRenderer*) 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); 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) { static bool _parsePacket(struct mVideoLogger* logger, const struct mVideoLoggerDirtyInfo* item) {
struct GBAVideoProxyRenderer* proxyRenderer = logger->context; struct GBAVideoProxyRenderer* proxyRenderer = logger->context;
switch (item->type) { switch (item->type) {

View File

@ -40,6 +40,7 @@ DisplayGL::DisplayGL(const QGLFormat& format, QWidget* parent)
setUpdatesEnabled(false); // Prevent paint events, which can cause race conditions setUpdatesEnabled(false); // Prevent paint events, which can cause race conditions
connect(&m_videoProxy, &VideoProxy::dataAvailable, &m_videoProxy, &VideoProxy::processData); connect(&m_videoProxy, &VideoProxy::dataAvailable, &m_videoProxy, &VideoProxy::processData);
connect(&m_videoProxy, &VideoProxy::eventPosted, &m_videoProxy, &VideoProxy::handleEvent);
} }
DisplayGL::~DisplayGL() { DisplayGL::~DisplayGL() {

View File

@ -23,6 +23,7 @@ VideoProxy::VideoProxy() {
m_logger.d.writeData = &callback<bool, const void*, size_t>::func<&VideoProxy::writeData>; 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.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) { void VideoProxy::attach(CoreController* controller) {
@ -74,6 +75,14 @@ bool VideoProxy::readData(void* data, size_t length, bool block) {
return read; 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() { void VideoProxy::lock() {
m_mutex.lock(); m_mutex.lock();
} }

View File

@ -26,9 +26,11 @@ public:
signals: signals:
void dataAvailable(); void dataAvailable();
void eventPosted(int);
public slots: public slots:
void processData(); void processData();
void handleEvent(int);
private: private:
void init(); void init();
@ -37,6 +39,7 @@ private:
bool writeData(const void* data, size_t length); bool writeData(const void* data, size_t length);
bool readData(void* data, size_t length, bool block); bool readData(void* data, size_t length, bool block);
void postEvent(enum mVideoLoggerEvent event);
void lock(); void lock();
void unlock(); void unlock();