hc
2023-05-26 a23f51ed7a39e452c1037343a84d7db1ca2c5bd7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
From 4bcf194c5017d4f2af2025a6b22f14e8d1c8cacc Mon Sep 17 00:00:00 2001
From: Jeffy Chen <jeffy.chen@rock-chips.com>
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 <jeffy.chen@rock-chips.com>
---
 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 <pthread.h>
+#include <sched.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+#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