all repos — mgba @ eeee6fe44eb11e77774c7bb3f08c2016682d33cd

mGBA Game Boy Advance Emulator

Qt: Fix GL deadlocks
Vicki Pfau vi@endrift.com
Mon, 20 May 2019 14:42:55 -0700
commit

eeee6fe44eb11e77774c7bb3f08c2016682d33cd

parent

53d9e6b43213d9eed2c7bc5b38d16f4fdad37bc3

M src/feature/thread-proxy.csrc/feature/thread-proxy.c

@@ -153,10 +153,12 @@ mLOG(GBA_VIDEO, ERROR, "Proxy thread stopped prematurely!");

_proxyThreadRecover(proxyRenderer); return; } + MutexLock(&proxyRenderer->mutex); while (RingFIFOSize(&proxyRenderer->dirtyQueue)) { ConditionWake(&proxyRenderer->toThreadCond); ConditionWait(&proxyRenderer->fromThreadCond, &proxyRenderer->mutex); } + MutexUnlock(&proxyRenderer->mutex); } static void _unlock(struct mVideoLogger* logger) {
M src/gb/extra/proxy.csrc/gb/extra/proxy.c

@@ -250,31 +250,21 @@ }

void GBVideoProxyRendererFinishFrame(struct GBVideoRenderer* renderer) { struct GBVideoProxyRenderer* proxyRenderer = (struct GBVideoProxyRenderer*) renderer; - if (proxyRenderer->logger->block && proxyRenderer->logger->wait) { - proxyRenderer->logger->lock(proxyRenderer->logger); - } if (!proxyRenderer->logger->block) { proxyRenderer->backend->finishFrame(proxyRenderer->backend); } mVideoLoggerRendererFinishFrame(proxyRenderer->logger); mVideoLoggerRendererFlush(proxyRenderer->logger); - if (proxyRenderer->logger->block && proxyRenderer->logger->wait) { - proxyRenderer->logger->unlock(proxyRenderer->logger); - } } static void GBVideoProxyRendererEnableSGBBorder(struct GBVideoRenderer* renderer, bool enable) { struct GBVideoProxyRenderer* proxyRenderer = (struct GBVideoProxyRenderer*) renderer; 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->enableSGBBorder(proxyRenderer->backend, enable); - if (proxyRenderer->logger->block && proxyRenderer->logger->wait) { - proxyRenderer->logger->unlock(proxyRenderer->logger); - } } static void GBVideoProxyRendererGetPixels(struct GBVideoRenderer* renderer, size_t* stride, const void** pixels) {

@@ -297,9 +287,6 @@ static void GBVideoProxyRendererPutPixels(struct GBVideoRenderer* renderer, size_t stride, const void* pixels) {

struct GBVideoProxyRenderer* proxyRenderer = (struct GBVideoProxyRenderer*) renderer; 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->putPixels(proxyRenderer->backend, stride, pixels); if (proxyRenderer->logger->block && proxyRenderer->logger->wait) {
M src/gba/extra/proxy.csrc/gba/extra/proxy.c

@@ -289,28 +289,20 @@ }

void GBAVideoProxyRendererFinishFrame(struct GBAVideoRenderer* renderer) { struct GBAVideoProxyRenderer* proxyRenderer = (struct GBAVideoProxyRenderer*) renderer; - if (proxyRenderer->logger->block && proxyRenderer->logger->wait) { - proxyRenderer->logger->lock(proxyRenderer->logger); - } if (!proxyRenderer->logger->block) { proxyRenderer->backend->finishFrame(proxyRenderer->backend); } mVideoLoggerRendererFinishFrame(proxyRenderer->logger); mVideoLoggerRendererFlush(proxyRenderer->logger); - if (proxyRenderer->logger->block && proxyRenderer->logger->wait) { - proxyRenderer->logger->unlock(proxyRenderer->logger); - } } static void GBAVideoProxyRendererGetPixels(struct GBAVideoRenderer* renderer, size_t* stride, const void** pixels) { struct GBAVideoProxyRenderer* proxyRenderer = (struct GBAVideoProxyRenderer*) renderer; 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->postEvent(proxyRenderer->logger, LOGGER_EVENT_GET_PIXELS); mVideoLoggerRendererFlush(proxyRenderer->logger); - proxyRenderer->logger->unlock(proxyRenderer->logger); *pixels = proxyRenderer->logger->pixelBuffer; *stride = proxyRenderer->logger->pixelStride; } else {

@@ -322,8 +314,6 @@ static void GBAVideoProxyRendererPutPixels(struct GBAVideoRenderer* renderer, size_t stride, const void* pixels) {

struct GBAVideoProxyRenderer* proxyRenderer = (struct GBAVideoProxyRenderer*) renderer; 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->putPixels(proxyRenderer->backend, stride, pixels); if (proxyRenderer->logger->block && proxyRenderer->logger->wait) {
M src/gba/video.csrc/gba/video.c

@@ -98,8 +98,7 @@

memset(video->palette, 0, sizeof(video->palette)); memset(video->oam.raw, 0, sizeof(video->oam.raw)); - video->renderer->deinit(video->renderer); - video->renderer->init(video->renderer); + video->renderer->reset(video->renderer); } void GBAVideoDeinit(struct GBAVideo* video) {
M src/platform/qt/CoreController.cppsrc/platform/qt/CoreController.cpp

@@ -363,7 +363,6 @@ setDebugger(nullptr);

#endif setPaused(false); mCoreThreadEnd(&m_threadContext); - emit stopping(); } void CoreController::reset() {
M src/platform/qt/DisplayGL.cppsrc/platform/qt/DisplayGL.cpp

@@ -59,9 +59,6 @@ }

m_painter = new PainterGL(&m_videoProxy, windowHandle(), m_gl); 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() {

@@ -417,6 +414,9 @@ m_started = false;

dequeueAll(); m_backend->clear(m_backend); m_backend->swap(m_backend); + if (m_videoProxy) { + m_videoProxy->reset(); + } m_gl->doneCurrent(); m_gl->moveToThread(m_surface->thread()); m_context.reset();
M src/platform/qt/VideoProxy.cppsrc/platform/qt/VideoProxy.cpp

@@ -24,6 +24,9 @@

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>; + + connect(this, &VideoProxy::dataAvailable, this, &VideoProxy::processData); + connect(this, &VideoProxy::eventPosted, this, &VideoProxy::handleEvent); } void VideoProxy::attach(CoreController* controller) {

@@ -41,7 +44,10 @@ RingFIFOInit(&m_dirtyQueue, 0x80000);

} void VideoProxy::reset() { + m_mutex.lock(); RingFIFOClear(&m_dirtyQueue); + m_toThreadCond.wakeAll(); + m_mutex.unlock(); } void VideoProxy::deinit() {

@@ -92,11 +98,13 @@ m_mutex.unlock();

} void VideoProxy::wait() { + m_mutex.lock(); while (RingFIFOSize(&m_dirtyQueue)) { emit dataAvailable(); m_toThreadCond.wakeAll(); m_fromThreadCond.wait(&m_mutex, 1); } + m_mutex.unlock(); } void VideoProxy::wake(int y) {
M src/platform/qt/VideoProxy.hsrc/platform/qt/VideoProxy.h

@@ -30,11 +30,11 @@ void eventPosted(int);

public slots: void processData(); + void reset(); void handleEvent(int); private: void init(); - void reset(); void deinit(); bool writeData(const void* data, size_t length);
M src/platform/qt/Window.cppsrc/platform/qt/Window.cpp

@@ -726,7 +726,6 @@ if (isFullScreen()) {

menuBar()->hide(); } #endif - m_display->startDrawing(m_controller); reloadAudioDriver(); multiplayerChanged();

@@ -1733,6 +1732,7 @@ m_controller = std::shared_ptr<CoreController>(controller);

m_inputController.recalibrateAxes(); m_controller->setInputController(&m_inputController); m_controller->setLogger(&m_log); + m_display->startDrawing(m_controller); connect(this, &Window::shutdown, [this]() { if (!m_controller) {