For Qt GUI, add video buffer mutex to ensure clean transfer between emulation and GUI threads. Use common FCEU::mutex wrapper for cleaner code.
This commit is contained in:
parent
cb0edc5a21
commit
d363d04dbb
|
@ -170,11 +170,6 @@ consoleWin_t::consoleWin_t(QWidget *parent)
|
||||||
setAcceptDrops(true);
|
setAcceptDrops(true);
|
||||||
|
|
||||||
gameTimer = new QTimer( this );
|
gameTimer = new QTimer( this );
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
|
|
||||||
mutex = new QRecursiveMutex();
|
|
||||||
#else
|
|
||||||
mutex = new QMutex( QMutex::Recursive );
|
|
||||||
#endif
|
|
||||||
emulatorThread = new emulatorThread_t(this);
|
emulatorThread = new emulatorThread_t(this);
|
||||||
|
|
||||||
connect(emulatorThread, &QThread::finished, emulatorThread, &QObject::deleteLater);
|
connect(emulatorThread, &QThread::finished, emulatorThread, &QObject::deleteLater);
|
||||||
|
@ -336,8 +331,6 @@ consoleWin_t::~consoleWin_t(void)
|
||||||
|
|
||||||
unloadVideoDriver();
|
unloadVideoDriver();
|
||||||
|
|
||||||
delete mutex;
|
|
||||||
|
|
||||||
// LoadGame() checks for an IP and if it finds one begins a network session
|
// LoadGame() checks for an IP and if it finds one begins a network session
|
||||||
// clear the NetworkIP field so this doesn't happen unintentionally
|
// clear the NetworkIP field so this doesn't happen unintentionally
|
||||||
//g_config->setOption ("SDL.NetworkIP", "");
|
//g_config->setOption ("SDL.NetworkIP", "");
|
||||||
|
@ -4564,17 +4557,28 @@ int consoleWin_t::getPeriodicInterval(void)
|
||||||
|
|
||||||
void consoleWin_t::transferVideoBuffer(void)
|
void consoleWin_t::transferVideoBuffer(void)
|
||||||
{
|
{
|
||||||
|
bool redraw = false;
|
||||||
FCEU_PROFILE_FUNC(prof, "VideoXfer");
|
FCEU_PROFILE_FUNC(prof, "VideoXfer");
|
||||||
if ( nes_shm->blitUpdated )
|
|
||||||
{
|
|
||||||
nes_shm->blitUpdated = 0;
|
|
||||||
|
|
||||||
if (viewport_Interface)
|
{
|
||||||
|
FCEU::autoScopedLock lock(videoBufferMutex);
|
||||||
|
if ( nes_shm->blitUpdated )
|
||||||
{
|
{
|
||||||
viewport_Interface->transfer2LocalBuffer();
|
nes_shm->blitUpdated = 0;
|
||||||
viewport_Interface->queueRedraw();
|
|
||||||
|
if (viewport_Interface != nullptr)
|
||||||
|
{
|
||||||
|
viewport_Interface->transfer2LocalBuffer();
|
||||||
|
redraw = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Don't queue redraw in mutex lock scope
|
||||||
|
if (redraw && (viewport_Interface != nullptr))
|
||||||
|
{
|
||||||
|
viewport_Interface->queueRedraw();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void consoleWin_t::emuFrameFinish(void)
|
void consoleWin_t::emuFrameFinish(void)
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <QRecursiveMutex>
|
#include <QRecursiveMutex>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "utils/mutex.h"
|
||||||
#include "Qt/ColorMenu.h"
|
#include "Qt/ColorMenu.h"
|
||||||
#include "Qt/ConsoleViewerGL.h"
|
#include "Qt/ConsoleViewerGL.h"
|
||||||
#include "Qt/ConsoleViewerSDL.h"
|
#include "Qt/ConsoleViewerSDL.h"
|
||||||
|
@ -134,11 +135,8 @@ class consoleWin_t : public QMainWindow
|
||||||
|
|
||||||
void setCyclePeriodms( int ms );
|
void setCyclePeriodms( int ms );
|
||||||
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
|
FCEU::mutex emulatorMutex;
|
||||||
QRecursiveMutex *mutex;
|
FCEU::mutex videoBufferMutex;
|
||||||
#else
|
|
||||||
QMutex *mutex;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int videoInit(void);
|
int videoInit(void);
|
||||||
void videoReset(void);
|
void videoReset(void);
|
||||||
|
|
|
@ -1382,7 +1382,7 @@ void fceuWrapperLock(void)
|
||||||
mutexPending++;
|
mutexPending++;
|
||||||
if ( consoleWindow != NULL )
|
if ( consoleWindow != NULL )
|
||||||
{
|
{
|
||||||
consoleWindow->mutex->lock();
|
consoleWindow->emulatorMutex.lock();
|
||||||
}
|
}
|
||||||
mutexPending--;
|
mutexPending--;
|
||||||
mutexLocks++;
|
mutexLocks++;
|
||||||
|
@ -1412,7 +1412,7 @@ bool fceuWrapperTryLock(int timeout)
|
||||||
mutexPending++;
|
mutexPending++;
|
||||||
if ( consoleWindow != NULL )
|
if ( consoleWindow != NULL )
|
||||||
{
|
{
|
||||||
lockAcq = consoleWindow->mutex->tryLock( timeout );
|
lockAcq = consoleWindow->emulatorMutex.tryLock( timeout );
|
||||||
}
|
}
|
||||||
mutexPending--;
|
mutexPending--;
|
||||||
|
|
||||||
|
@ -1430,7 +1430,7 @@ void fceuWrapperUnLock(void)
|
||||||
mutexLocks--;
|
mutexLocks--;
|
||||||
if ( consoleWindow != NULL )
|
if ( consoleWindow != NULL )
|
||||||
{
|
{
|
||||||
consoleWindow->mutex->unlock();
|
consoleWindow->emulatorMutex.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -496,8 +496,6 @@ doBlitScreen(uint8_t *XBuf, uint8_t *dest)
|
||||||
void
|
void
|
||||||
BlitScreen(uint8 *XBuf)
|
BlitScreen(uint8 *XBuf)
|
||||||
{
|
{
|
||||||
int i = nes_shm->pixBufIdx;
|
|
||||||
|
|
||||||
if (usePaletteForVideoBg)
|
if (usePaletteForVideoBg)
|
||||||
{
|
{
|
||||||
unsigned char r, g, b;
|
unsigned char r, g, b;
|
||||||
|
@ -511,11 +509,18 @@ BlitScreen(uint8 *XBuf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
doBlitScreen(XBuf, (uint8_t*)nes_shm->pixbuf[i]);
|
if (consoleWindow != nullptr)
|
||||||
|
{
|
||||||
|
FCEU::autoScopedLock lock(consoleWindow->videoBufferMutex);
|
||||||
|
|
||||||
nes_shm->pixBufIdx = (i+1) % NES_VIDEO_BUFLEN;
|
int i = nes_shm->pixBufIdx;
|
||||||
nes_shm->blit_count++;
|
|
||||||
nes_shm->blitUpdated = 1;
|
doBlitScreen(XBuf, (uint8_t*)nes_shm->pixbuf[i]);
|
||||||
|
|
||||||
|
nes_shm->pixBufIdx = (i+1) % NES_VIDEO_BUFLEN;
|
||||||
|
nes_shm->blit_count++;
|
||||||
|
nes_shm->blitUpdated = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCEUI_AviVideoUpdate(const unsigned char* buffer)
|
void FCEUI_AviVideoUpdate(const unsigned char* buffer)
|
||||||
|
|
|
@ -48,6 +48,24 @@ void mutex::unlock(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool mutex::tryLock()
|
||||||
|
{
|
||||||
|
bool success = false;
|
||||||
|
#ifdef __QT_DRIVER__
|
||||||
|
success = mtx->tryLock();
|
||||||
|
#endif
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mutex::tryLock(int timeout)
|
||||||
|
{
|
||||||
|
bool success = false;
|
||||||
|
#ifdef __QT_DRIVER__
|
||||||
|
success = mtx->tryLock(timeout);
|
||||||
|
#endif
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------
|
//-----------------------------------------------------
|
||||||
// Scoped AutoLock
|
// Scoped AutoLock
|
||||||
//-----------------------------------------------------
|
//-----------------------------------------------------
|
||||||
|
|
|
@ -18,6 +18,8 @@ namespace FCEU
|
||||||
|
|
||||||
void lock(void);
|
void lock(void);
|
||||||
void unlock(void);
|
void unlock(void);
|
||||||
|
bool tryLock(void);
|
||||||
|
bool tryLock(int timeout);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#ifdef __QT_DRIVER__
|
#ifdef __QT_DRIVER__
|
||||||
|
|
Loading…
Reference in New Issue