From c35b18751db55c9fe1fd7e6003674dc83bc9ee02 Mon Sep 17 00:00:00 2001 From: mjbudd77 Date: Mon, 13 Dec 2021 21:16:53 -0500 Subject: [PATCH] Added a triple buffer for video frame data to ensure clean transfer of that data between emulation and Qt GUI threads. --- src/drivers/Qt/ConsoleViewerGL.cpp | 12 +++++++++--- src/drivers/Qt/ConsoleViewerSDL.cpp | 12 +++++++++--- src/drivers/Qt/ConsoleWindow.cpp | 4 ++-- src/drivers/Qt/nes_shm.h | 4 +++- src/drivers/Qt/sdl-video.cpp | 12 +++++++++--- 5 files changed, 32 insertions(+), 12 deletions(-) diff --git a/src/drivers/Qt/ConsoleViewerGL.cpp b/src/drivers/Qt/ConsoleViewerGL.cpp index 079e5521..c473895a 100644 --- a/src/drivers/Qt/ConsoleViewerGL.cpp +++ b/src/drivers/Qt/ConsoleViewerGL.cpp @@ -464,16 +464,22 @@ double ConsoleViewGL_t::getAspectRatio(void) void ConsoleViewGL_t::transfer2LocalBuffer(void) { - int i=0, hq = 0; + int i=0, hq = 0, bufIdx; int numPixels = nes_shm->video.ncol * nes_shm->video.nrow; unsigned int cpSize = numPixels * 4; uint8_t *src, *dest; + bufIdx = nes_shm->pixBufIdx-1; + + if ( bufIdx < 0 ) + { + bufIdx = NES_VIDEO_BUFLEN-1; + } if ( cpSize > localBufSize ) { cpSize = localBufSize; } - src = (uint8_t*)nes_shm->pixbuf; + src = (uint8_t*)nes_shm->pixbuf[bufIdx]; dest = (uint8_t*)localBuf; hq = (nes_shm->video.preScaler == 1) || (nes_shm->video.preScaler == 4); // hq2x and hq3x @@ -492,7 +498,7 @@ void ConsoleViewGL_t::transfer2LocalBuffer(void) } else { - memcpy( localBuf, nes_shm->pixbuf, cpSize ); + memcpy( localBuf, src, cpSize ); } } diff --git a/src/drivers/Qt/ConsoleViewerSDL.cpp b/src/drivers/Qt/ConsoleViewerSDL.cpp index 08d3c6c9..04216592 100644 --- a/src/drivers/Qt/ConsoleViewerSDL.cpp +++ b/src/drivers/Qt/ConsoleViewerSDL.cpp @@ -206,16 +206,22 @@ double ConsoleViewSDL_t::getAspectRatio(void) void ConsoleViewSDL_t::transfer2LocalBuffer(void) { - int i=0, hq = 0; + int i=0, hq = 0, bufIdx; int numPixels = nes_shm->video.ncol * nes_shm->video.nrow; unsigned int cpSize = numPixels * 4; uint8_t *src, *dest; + bufIdx = nes_shm->pixBufIdx-1; + + if ( bufIdx < 0 ) + { + bufIdx = NES_VIDEO_BUFLEN-1; + } if ( cpSize > localBufSize ) { cpSize = localBufSize; } - src = (uint8_t*)nes_shm->pixbuf; + src = (uint8_t*)nes_shm->pixbuf[bufIdx]; dest = (uint8_t*)localBuf; hq = (nes_shm->video.preScaler == 1) || (nes_shm->video.preScaler == 4); // hq2x and hq3x @@ -234,7 +240,7 @@ void ConsoleViewSDL_t::transfer2LocalBuffer(void) } else { - memcpy( localBuf, nes_shm->pixbuf, cpSize ); + memcpy( localBuf, src, cpSize ); } } diff --git a/src/drivers/Qt/ConsoleWindow.cpp b/src/drivers/Qt/ConsoleWindow.cpp index 274a93c0..50671376 100644 --- a/src/drivers/Qt/ConsoleWindow.cpp +++ b/src/drivers/Qt/ConsoleWindow.cpp @@ -4253,16 +4253,16 @@ void consoleWin_t::transferVideoBuffer(void) { if ( nes_shm->blitUpdated ) { + nes_shm->blitUpdated = 0; + if ( viewport_SDL ) { viewport_SDL->transfer2LocalBuffer(); - nes_shm->blitUpdated = 0; viewport_SDL->render(); } else if ( viewport_GL ) { viewport_GL->transfer2LocalBuffer(); - nes_shm->blitUpdated = 0; viewport_GL->update(); } } diff --git a/src/drivers/Qt/nes_shm.h b/src/drivers/Qt/nes_shm.h index ce83a131..5497430e 100644 --- a/src/drivers/Qt/nes_shm.h +++ b/src/drivers/Qt/nes_shm.h @@ -11,6 +11,7 @@ #define GL_NES_WIDTH 256 #define GL_NES_HEIGHT 240 +#define NES_VIDEO_BUFLEN 3 #define NES_AUDIO_BUFLEN 480000 struct nes_shm_t @@ -35,7 +36,8 @@ struct nes_shm_t char runEmulator; char blitUpdated; - uint32_t pixbuf[1048576]; // 1024 x 1024 + int pixBufIdx; + uint32_t pixbuf[NES_VIDEO_BUFLEN][1048576]; // 1024 x 1024 uint32_t avibuf[1048576]; // 1024 x 1024 void clear_pixbuf(void) diff --git a/src/drivers/Qt/sdl-video.cpp b/src/drivers/Qt/sdl-video.cpp index bc08c1de..da4a3254 100644 --- a/src/drivers/Qt/sdl-video.cpp +++ b/src/drivers/Qt/sdl-video.cpp @@ -398,6 +398,9 @@ static void vsync_test(void) int i, j, k, l; int cycleLen, halfCycleLen; static int ofs = 0; + uint32_t *pixbuf; + + pixbuf = nes_shm->pixbuf[nes_shm->pixBufIdx]; cycleLen = nes_shm->video.ncol / 4; @@ -412,11 +415,11 @@ static void vsync_test(void) if ( l < halfCycleLen ) { - nes_shm->pixbuf[k] = 0xffffffff; k++; + pixbuf[k] = 0xFFFFFFFF; k++; } else { - nes_shm->pixbuf[k] = 0x00000000; k++; + pixbuf[k] = 0x00000000; k++; } } } @@ -492,8 +495,11 @@ doBlitScreen(uint8_t *XBuf, uint8_t *dest) void BlitScreen(uint8 *XBuf) { - doBlitScreen(XBuf, (uint8_t*)nes_shm->pixbuf); + int i = nes_shm->pixBufIdx; + doBlitScreen(XBuf, (uint8_t*)nes_shm->pixbuf[i]); + + nes_shm->pixBufIdx = (i+1) % NES_VIDEO_BUFLEN; nes_shm->blit_count++; nes_shm->blitUpdated = 1; }