From 4bcf194c5017d4f2af2025a6b22f14e8d1c8cacc Mon Sep 17 00:00:00 2001 From: Jeffy Chen Date: Mon, 29 Oct 2018 09:54:50 +0800 Subject: [PATCH] pgm: Support threaded draw, and bind it to cpu 0 Signed-off-by: Jeffy Chen --- makefile.libretro_common | 6 ++ src/burn/drv/pgm/pgm.h | 22 +++++++ src/burn/drv/pgm/pgm_draw.cpp | 13 ++++ src/burn/drv/pgm/pgm_run.cpp | 133 +++++++++++++++++++++++++++++++++++++++ src/burner/libretro/libretro.cpp | 4 +- 5 files changed, 177 insertions(+), 1 deletion(-) diff --git a/makefile.libretro_common b/makefile.libretro_common index b7b2850..28b0beb 100644 --- a/makefile.libretro_common +++ b/makefile.libretro_common @@ -315,3 +315,9 @@ GIT_VERSION := " $(shell git rev-parse --short HEAD || echo unknown)" ifneq ($(GIT_VERSION)," unknown") CXXFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\" endif + +ENABLE_PGM_THREADED_DRAW = 1 +ifeq ($(ENABLE_PGM_THREADED_DRAW),1) + FBA_DEFINES += -DPGM_THREADED_DRAW + LDFLAGS += -lpthread +endif diff --git a/src/burn/drv/pgm/pgm.h b/src/burn/drv/pgm/pgm.h index 5927233..7d83d85 100644 --- a/src/burn/drv/pgm/pgm.h +++ b/src/burn/drv/pgm/pgm.h @@ -6,6 +6,28 @@ #define HARDWARE_IGS_JAMMAPCB 0x0002 +// threaded pgm draw +#ifdef PGM_THREADED_DRAW + +/* Mirror memory for pgmDraw() */ +struct PGM_DRAW_CONTEXT { + /* Sizes come from pgm_run.cpp:pgmMemIndex() */ + UINT32 PGMBgRAM[0x0001000 / 4]; + UINT32 PGMTxtRAM[0x0002000 / 4]; + UINT16 PGMRowRAM[0x0001000 / 2]; + UINT16 PGMPalRAM[0x0001400 / 2]; + UINT16 PGMVidReg[0x0010000 / 2]; + UINT16 PGMSprBuf[0x0000a00 / 2]; + UINT32 RamCurPal[0x0001204 / 2]; + + UINT8 *pBurnDraw; + volatile int nDirty; +}; + +extern struct PGM_DRAW_CONTEXT PgmDrawCtx; + +#endif // PGM_THREADED_DRAW + // pgm_run extern INT32 nPGM68KROMLen; extern INT32 nPGMSPRColMaskLen; diff --git a/src/burn/drv/pgm/pgm_draw.cpp b/src/burn/drv/pgm/pgm_draw.cpp index bbf070c..604f01a 100644 --- a/src/burn/drv/pgm/pgm_draw.cpp +++ b/src/burn/drv/pgm/pgm_draw.cpp @@ -1,6 +1,19 @@ #include "pgm.h" #include "pgm_sprite.h" +#ifdef PGM_THREADED_DRAW + +/* Redirect to mirror draw ctx */ +#define PGMBgRAM PgmDrawCtx.PGMBgRAM +#define PGMTxtRAM PgmDrawCtx.PGMTxtRAM +#define PGMRowRAM PgmDrawCtx.PGMRowRAM +#define PGMPalRAM PgmDrawCtx.PGMPalRAM +#define PGMVidReg PgmDrawCtx.PGMVidReg +#define PGMSprBuf PgmDrawCtx.PGMSprBuf +#define RamCurPal PgmDrawCtx.RamCurPal + +#endif + //#define DUMP_SPRITE_BITMAPS //#define DRAW_SPRITE_NUMBER diff --git a/src/burn/drv/pgm/pgm_run.cpp b/src/burn/drv/pgm/pgm_run.cpp index cf8ab4d..30db0ea 100644 --- a/src/burn/drv/pgm/pgm_run.cpp +++ b/src/burn/drv/pgm/pgm_run.cpp @@ -4,6 +4,139 @@ #include "ics2115.h" #include "timer.h" +#ifdef PGM_THREADED_DRAW + +#include +#include +#include +#include + +#define gettid() syscall(SYS_gettid) + +#define PGM_DRAW_SIZE (nScreenWidth * nScreenHeight * sizeof(UINT32)) + +struct PGM_DRAW_CONTEXT PgmDrawCtx; +static struct PGM_DRAW_CONTEXT PgmTempDrawCtx; + +static pthread_t PgmDrawThread; +static volatile int PgmDrawThreadExit = 0; + +static pthread_mutex_t PgmDrawMutex; +static pthread_mutex_t PgmBurnDrawMutex; + +static inline void pgmInitDrawReal() { pgmInitDraw(); } +static inline void pgmExitDrawReal() { pgmExitDraw(); } +static inline void pgmDrawReal() { pgmDraw(); } +#define pgmInitDraw() pgmInitThreadDraw() +#define pgmExitDraw() pgmExitThreadDraw() +#define pgmDraw() pgmThreadedDraw() + +extern void *pBurnDrawCustom; + +static void pgmThreadedDraw() +{ + pthread_mutex_lock(&PgmDrawMutex); + + // Update mirror memory. +#define PGM_COPY_CTX(ctx, area) memcpy(ctx.area, area, sizeof(ctx.area)) + PGM_COPY_CTX(PgmTempDrawCtx, PGMBgRAM); + PGM_COPY_CTX(PgmTempDrawCtx, PGMTxtRAM); + PGM_COPY_CTX(PgmTempDrawCtx, PGMRowRAM); + PGM_COPY_CTX(PgmTempDrawCtx, PGMPalRAM); + PGM_COPY_CTX(PgmTempDrawCtx, PGMVidReg); + PGM_COPY_CTX(PgmTempDrawCtx, PGMSprBuf); + PGM_COPY_CTX(PgmTempDrawCtx, RamCurPal); + + PgmTempDrawCtx.nDirty = 1; + pthread_mutex_unlock(&PgmDrawMutex); + + // Update pBurnDrawCustom. + pthread_mutex_lock(&PgmBurnDrawMutex); + memcpy(pBurnDrawCustom, PgmTempDrawCtx.pBurnDraw, PGM_DRAW_SIZE); + pthread_mutex_unlock(&PgmBurnDrawMutex); +} + +/* Try to bind draw thread to the cpu 0. */ +static void pgm_draw_thread_bind_cpu() +{ + int i; + cpu_set_t mask; + + CPU_ZERO(&mask); + CPU_SET(0, &mask); + + if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) < 0) + perror("pthread_setaffinity_np"); + + if (pthread_getaffinity_np(pthread_self(), sizeof(mask), &mask) < 0) + perror("pthread_getaffinity_np"); + + printf("Thread(%ld) bound to cpu:", gettid()); + for (i = 0; i < CPU_SETSIZE; i++) { + if (CPU_ISSET(i, &mask)) + printf(" %d", i); + } + printf("\n"); +} + +void *pgmDrawFunc(void *arg) +{ + pgm_draw_thread_bind_cpu(); + + while (!PgmDrawThreadExit) { + if (!PgmTempDrawCtx.nDirty) { + pthread_yield(); + continue; + } + + // The PgmTempDrawCtx is dirty. + pthread_mutex_lock(&PgmDrawMutex); + memcpy(&PgmDrawCtx, &PgmTempDrawCtx, sizeof(PgmDrawCtx)); + PgmTempDrawCtx.nDirty = 0; + pthread_mutex_unlock(&PgmDrawMutex); + + pgmDrawReal(); + + // Update PgmTempDrawCtx.pBurnDraw. + pthread_mutex_lock(&PgmBurnDrawMutex); + memcpy(PgmTempDrawCtx.pBurnDraw, pBurnDraw, PGM_DRAW_SIZE); + pthread_mutex_unlock(&PgmBurnDrawMutex); + } + return NULL; +} + +static void pgmInitThreadDraw() +{ + pgmInitDrawReal(); + + memset(&PgmDrawCtx, 0, sizeof(PgmDrawCtx)); + memset(&PgmTempDrawCtx, 0, sizeof(PgmTempDrawCtx)); + + PgmTempDrawCtx.pBurnDraw = (UINT8*)BurnMalloc(PGM_DRAW_SIZE); + pBurnDrawCustom = BurnMalloc(PGM_DRAW_SIZE); + + pthread_mutex_init(&PgmDrawMutex, NULL); + pthread_mutex_init(&PgmBurnDrawMutex, NULL); + + PgmDrawThreadExit = 0; + pthread_create(&PgmDrawThread, NULL, pgmDrawFunc, NULL); +} + +static void pgmExitThreadDraw() +{ + PgmDrawThreadExit = 1; + pthread_join(PgmDrawThread, NULL); + + pthread_mutex_destroy(&PgmDrawMutex); + pthread_mutex_destroy(&PgmBurnDrawMutex); + + BurnFree (pBurnDrawCustom); + BurnFree (PgmTempDrawCtx.pBurnDraw); + + pgmExitDrawReal(); +} +#endif + UINT8 PgmJoy1[8] = {0,0,0,0,0,0,0,0}; UINT8 PgmJoy2[8] = {0,0,0,0,0,0,0,0}; UINT8 PgmJoy3[8] = {0,0,0,0,0,0,0,0}; diff --git a/src/burner/libretro/libretro.cpp b/src/burner/libretro/libretro.cpp index 241dfec..3fc2d02 100644 --- a/src/burner/libretro/libretro.cpp +++ b/src/burner/libretro/libretro.cpp @@ -149,6 +149,7 @@ static unsigned fba_devices[5] = { RETROPAD_CLASSIC, RETROPAD_CLASSIC, RETROPAD_ INT32 g_audio_samplerate = 48000; INT32 nAudSegLen = 0; +void *pBurnDrawCustom = NULL; static uint32_t *g_fba_frame; static int16_t *g_audio_buf; @@ -1499,7 +1500,8 @@ void retro_run() nBurnPitch = width * pitch_size; } - video_cb(g_fba_frame, width, height, nBurnPitch); + // Allow overriding frame data. + video_cb(pBurnDrawCustom ? pBurnDrawCustom : g_fba_frame, width, height, nBurnPitch); audio_batch_cb(g_audio_buf, nBurnSoundLen); bool updated = false; -- 2.11.0