mirror of https://github.com/mgba-emu/mgba.git
Qt: Fix GL deadlocks
This commit is contained in:
parent
53d9e6b432
commit
eeee6fe44e
|
@ -153,10 +153,12 @@ static void _wait(struct mVideoLogger* logger) {
|
|||
_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) {
|
||||
|
|
|
@ -250,31 +250,21 @@ void GBVideoProxyRendererFinishScanline(struct GBVideoRenderer* renderer, int y)
|
|||
|
||||
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
|
|||
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) {
|
||||
|
|
|
@ -289,28 +289,20 @@ void GBAVideoProxyRendererDrawScanline(struct GBAVideoRenderer* renderer, int y)
|
|||
|
||||
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, si
|
|||
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) {
|
||||
|
|
|
@ -98,8 +98,7 @@ void GBAVideoReset(struct GBAVideo* video) {
|
|||
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) {
|
||||
|
|
|
@ -363,7 +363,6 @@ void CoreController::stop() {
|
|||
#endif
|
||||
setPaused(false);
|
||||
mCoreThreadEnd(&m_threadContext);
|
||||
emit stopping();
|
||||
}
|
||||
|
||||
void CoreController::reset() {
|
||||
|
|
|
@ -59,9 +59,6 @@ DisplayGL::DisplayGL(const QSurfaceFormat& format, QWidget* parent)
|
|||
|
||||
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 @@ void PainterGL::stop() {
|
|||
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();
|
||||
|
|
|
@ -24,6 +24,9 @@ VideoProxy::VideoProxy() {
|
|||
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 @@ void VideoProxy::init() {
|
|||
}
|
||||
|
||||
void VideoProxy::reset() {
|
||||
m_mutex.lock();
|
||||
RingFIFOClear(&m_dirtyQueue);
|
||||
m_toThreadCond.wakeAll();
|
||||
m_mutex.unlock();
|
||||
}
|
||||
|
||||
void VideoProxy::deinit() {
|
||||
|
@ -92,11 +98,13 @@ void VideoProxy::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) {
|
||||
|
|
|
@ -30,11 +30,11 @@ signals:
|
|||
|
||||
public slots:
|
||||
void processData();
|
||||
void reset();
|
||||
void handleEvent(int);
|
||||
|
||||
private:
|
||||
void init();
|
||||
void reset();
|
||||
void deinit();
|
||||
|
||||
bool writeData(const void* data, size_t length);
|
||||
|
|
|
@ -726,7 +726,6 @@ void Window::gameStarted() {
|
|||
menuBar()->hide();
|
||||
}
|
||||
#endif
|
||||
m_display->startDrawing(m_controller);
|
||||
|
||||
reloadAudioDriver();
|
||||
multiplayerChanged();
|
||||
|
@ -1733,6 +1732,7 @@ void Window::setController(CoreController* controller, const QString& fname) {
|
|||
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) {
|
||||
|
|
Loading…
Reference in New Issue