Added a triple buffer for video frame data to ensure clean transfer of that data between emulation and Qt GUI threads.

This commit is contained in:
mjbudd77 2021-12-13 21:16:53 -05:00
parent 74a48e92d6
commit c35b18751d
5 changed files with 32 additions and 12 deletions

View File

@ -464,16 +464,22 @@ double ConsoleViewGL_t::getAspectRatio(void)
void ConsoleViewGL_t::transfer2LocalBuffer(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; int numPixels = nes_shm->video.ncol * nes_shm->video.nrow;
unsigned int cpSize = numPixels * 4; unsigned int cpSize = numPixels * 4;
uint8_t *src, *dest; uint8_t *src, *dest;
bufIdx = nes_shm->pixBufIdx-1;
if ( bufIdx < 0 )
{
bufIdx = NES_VIDEO_BUFLEN-1;
}
if ( cpSize > localBufSize ) if ( cpSize > localBufSize )
{ {
cpSize = localBufSize; cpSize = localBufSize;
} }
src = (uint8_t*)nes_shm->pixbuf; src = (uint8_t*)nes_shm->pixbuf[bufIdx];
dest = (uint8_t*)localBuf; dest = (uint8_t*)localBuf;
hq = (nes_shm->video.preScaler == 1) || (nes_shm->video.preScaler == 4); // hq2x and hq3x hq = (nes_shm->video.preScaler == 1) || (nes_shm->video.preScaler == 4); // hq2x and hq3x
@ -492,7 +498,7 @@ void ConsoleViewGL_t::transfer2LocalBuffer(void)
} }
else else
{ {
memcpy( localBuf, nes_shm->pixbuf, cpSize ); memcpy( localBuf, src, cpSize );
} }
} }

View File

@ -206,16 +206,22 @@ double ConsoleViewSDL_t::getAspectRatio(void)
void ConsoleViewSDL_t::transfer2LocalBuffer(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; int numPixels = nes_shm->video.ncol * nes_shm->video.nrow;
unsigned int cpSize = numPixels * 4; unsigned int cpSize = numPixels * 4;
uint8_t *src, *dest; uint8_t *src, *dest;
bufIdx = nes_shm->pixBufIdx-1;
if ( bufIdx < 0 )
{
bufIdx = NES_VIDEO_BUFLEN-1;
}
if ( cpSize > localBufSize ) if ( cpSize > localBufSize )
{ {
cpSize = localBufSize; cpSize = localBufSize;
} }
src = (uint8_t*)nes_shm->pixbuf; src = (uint8_t*)nes_shm->pixbuf[bufIdx];
dest = (uint8_t*)localBuf; dest = (uint8_t*)localBuf;
hq = (nes_shm->video.preScaler == 1) || (nes_shm->video.preScaler == 4); // hq2x and hq3x hq = (nes_shm->video.preScaler == 1) || (nes_shm->video.preScaler == 4); // hq2x and hq3x
@ -234,7 +240,7 @@ void ConsoleViewSDL_t::transfer2LocalBuffer(void)
} }
else else
{ {
memcpy( localBuf, nes_shm->pixbuf, cpSize ); memcpy( localBuf, src, cpSize );
} }
} }

View File

@ -4253,16 +4253,16 @@ void consoleWin_t::transferVideoBuffer(void)
{ {
if ( nes_shm->blitUpdated ) if ( nes_shm->blitUpdated )
{ {
nes_shm->blitUpdated = 0;
if ( viewport_SDL ) if ( viewport_SDL )
{ {
viewport_SDL->transfer2LocalBuffer(); viewport_SDL->transfer2LocalBuffer();
nes_shm->blitUpdated = 0;
viewport_SDL->render(); viewport_SDL->render();
} }
else if ( viewport_GL ) else if ( viewport_GL )
{ {
viewport_GL->transfer2LocalBuffer(); viewport_GL->transfer2LocalBuffer();
nes_shm->blitUpdated = 0;
viewport_GL->update(); viewport_GL->update();
} }
} }

View File

@ -11,6 +11,7 @@
#define GL_NES_WIDTH 256 #define GL_NES_WIDTH 256
#define GL_NES_HEIGHT 240 #define GL_NES_HEIGHT 240
#define NES_VIDEO_BUFLEN 3
#define NES_AUDIO_BUFLEN 480000 #define NES_AUDIO_BUFLEN 480000
struct nes_shm_t struct nes_shm_t
@ -35,7 +36,8 @@ struct nes_shm_t
char runEmulator; char runEmulator;
char blitUpdated; 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 uint32_t avibuf[1048576]; // 1024 x 1024
void clear_pixbuf(void) void clear_pixbuf(void)

View File

@ -398,6 +398,9 @@ static void vsync_test(void)
int i, j, k, l; int i, j, k, l;
int cycleLen, halfCycleLen; int cycleLen, halfCycleLen;
static int ofs = 0; static int ofs = 0;
uint32_t *pixbuf;
pixbuf = nes_shm->pixbuf[nes_shm->pixBufIdx];
cycleLen = nes_shm->video.ncol / 4; cycleLen = nes_shm->video.ncol / 4;
@ -412,11 +415,11 @@ static void vsync_test(void)
if ( l < halfCycleLen ) if ( l < halfCycleLen )
{ {
nes_shm->pixbuf[k] = 0xffffffff; k++; pixbuf[k] = 0xFFFFFFFF; k++;
} }
else else
{ {
nes_shm->pixbuf[k] = 0x00000000; k++; pixbuf[k] = 0x00000000; k++;
} }
} }
} }
@ -492,8 +495,11 @@ doBlitScreen(uint8_t *XBuf, uint8_t *dest)
void void
BlitScreen(uint8 *XBuf) 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->blit_count++;
nes_shm->blitUpdated = 1; nes_shm->blitUpdated = 1;
} }