Skip to content

Commit a650525

Browse files
Emscripten core switching (#18174)
* Emscripten core switching * Update changelog * Add comments (#18174) * Better core switching for HTML dropdown
1 parent d049191 commit a650525

16 files changed

Lines changed: 684 additions & 356 deletions

File tree

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
- CLOUDSYNC: Enable WebDAV support for Android
1818
- CLOUDSYNC: Speed up cloudsync on Apple
1919
- DATABASE: Improve multidisk game scanning
20+
- EMSCRIPTEN: Support core switching
2021
- EMSCRIPTEN: Support suspend screensaver
2122
- EMSCRIPTEN/RWEBCAM: Fix camera driver
2223
- EMSCRIPTEN/RWEBINPUT: Add accelerometer/gyroscope support

Makefile.emscripten

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ ifeq ($(HAVE_SDL2), 1)
162162
endif
163163

164164
LDFLAGS := -L. --no-heap-copy -s STACK_SIZE=$(STACK_SIZE) -s INITIAL_MEMORY=$(INITIAL_HEAP) \
165-
-s EXPORTED_RUNTIME_METHODS=$(EXPORTS) \
165+
-s EXPORTED_RUNTIME_METHODS=$(EXPORTS) -s EXIT_RUNTIME=1 \
166166
-s ALLOW_MEMORY_GROWTH=1 -s EXPORTED_FUNCTIONS="$(EXPORTED_FUNCTIONS)" \
167167
-s MODULARIZE=1 -s EXPORT_ES6=1 -s EXPORT_NAME="libretro_$(subst -,_,$(LIBRETRO))" \
168168
-s DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR=0 \

audio/drivers/audioworklet.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,19 @@ bool audioworklet_external_block(void)
431431
}
432432
#endif
433433

434+
/* called on program exit */
435+
void audioworklet_close(void)
436+
{
437+
audioworklet_data_t *audioworklet = audioworklet_static_data;
438+
439+
if (!audioworklet)
440+
return;
441+
442+
MAIN_THREAD_EM_ASM({
443+
emscriptenGetAudioObject($0).close();
444+
}, audioworklet->context);
445+
}
446+
434447
static bool audioworklet_stop(void *data)
435448
{
436449
audioworklet_data_t *audioworklet = (audioworklet_data_t*)data;

command.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
#include "verbosity.h"
6868
#include "version.h"
6969
#include "version_git.h"
70+
#include "tasks/task_content.h"
7071

7172
#define CMD_BUF_SIZE 4096
7273

@@ -939,6 +940,14 @@ bool command_version(command_t *cmd, const char* arg)
939940
return true;
940941
}
941942

943+
bool command_load_core(command_t *cmd, const char* arg)
944+
{
945+
content_ctx_info_t content_info = {0};
946+
task_push_load_new_core(arg, NULL,
947+
&content_info, CORE_TYPE_PLAIN, NULL, NULL);
948+
return true;
949+
}
950+
942951
static const rarch_memory_descriptor_t* command_memory_get_descriptor(const rarch_memory_map_t* mmap, unsigned address, size_t* offset)
943952
{
944953
const rarch_memory_descriptor_t* desc = mmap->descriptors;

command.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,7 @@ bool command_write_ram(command_t *cmd, const char *arg);
433433
#endif
434434
bool command_read_memory(command_t *cmd, const char *arg);
435435
bool command_write_memory(command_t *cmd, const char *arg);
436+
bool command_load_core(command_t *cmd, const char* arg);
436437

437438
static const struct cmd_action_map action_map[] = {
438439
#if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
@@ -457,6 +458,8 @@ static const struct cmd_action_map action_map[] = {
457458

458459
{ "SAVE_FILES", command_save_savefiles, "No argument"},
459460
{ "LOAD_FILES", command_load_savefiles, "No argument"},
461+
462+
{ "LOAD_CORE", command_load_core, "<core path>"},
460463
};
461464

462465
static const struct cmd_map map[] = {

emscripten/library_platform_emscripten.js

Lines changed: 94 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,21 @@ var LibraryPlatformEmscripten = {
44
$RPE: {
55
canvasWidth: 0,
66
canvasHeight: 0,
7+
battery: null,
8+
observer: null,
9+
memoryUsageTimeout: null,
710
sentinelPromise: null,
811
command_queue: [],
912
command_reply_queue: []
1013
},
1114

12-
PlatformEmscriptenWatchCanvasSizeAndDpr__deps: ["platform_emscripten_update_canvas_dimensions_cb"],
15+
$PlatformEmscriptenOnWindowResize: function() {
16+
RPE.observer.unobserve(Module.canvas);
17+
RPE.observer.observe(Module.canvas);
18+
},
19+
20+
PlatformEmscriptenWatchCanvasSizeAndDpr__deps: ["platform_emscripten_update_canvas_dimensions_cb", "$PlatformEmscriptenOnWindowResize"],
21+
PlatformEmscriptenWatchCanvasSizeAndDpr__proxy: "sync",
1322
PlatformEmscriptenWatchCanvasSizeAndDpr: function(dpr) {
1423
if (RPE.observer) {
1524
RPE.observer.unobserve(Module.canvas);
@@ -34,39 +43,57 @@ var LibraryPlatformEmscripten = {
3443
_platform_emscripten_update_canvas_dimensions_cb(width, height, dpr);
3544
});
3645
RPE.observer.observe(Module.canvas);
37-
window.addEventListener("resize", function() {
38-
RPE.observer.unobserve(Module.canvas);
39-
RPE.observer.observe(Module.canvas);
40-
}, false);
46+
window.addEventListener("resize", PlatformEmscriptenOnWindowResize, false);
47+
},
48+
49+
$PlatformEmscriptenOnCanvasPointerDown: function() {
50+
Module.canvas.focus();
4151
},
4252

43-
PlatformEmscriptenWatchWindowVisibility__deps: ["platform_emscripten_update_window_hidden_cb"],
53+
$PlatformEmscriptenOnCanvasContextMenu: function(e) {
54+
e.preventDefault();
55+
},
56+
57+
PlatformEmscriptenCanvasListenersInit__deps: ["$PlatformEmscriptenOnCanvasPointerDown", "$PlatformEmscriptenOnCanvasContextMenu"],
58+
PlatformEmscriptenCanvasListenersInit__proxy: "sync",
59+
PlatformEmscriptenCanvasListenersInit: function() {
60+
Module.canvas.addEventListener("pointerdown", PlatformEmscriptenOnCanvasPointerDown, false);
61+
Module.canvas.addEventListener("contextmenu", PlatformEmscriptenOnCanvasContextMenu, false);
62+
},
63+
64+
$PlatformEmscriptenOnVisibilityChange__deps: ["platform_emscripten_update_window_hidden_cb"],
65+
$PlatformEmscriptenOnVisibilityChange: function() {
66+
_platform_emscripten_update_window_hidden_cb(document.visibilityState == "hidden");
67+
},
68+
69+
PlatformEmscriptenWatchWindowVisibility__deps: ["$PlatformEmscriptenOnVisibilityChange"],
70+
PlatformEmscriptenWatchWindowVisibility__proxy: "sync",
4471
PlatformEmscriptenWatchWindowVisibility: function() {
45-
document.addEventListener("visibilitychange", function() {
46-
_platform_emscripten_update_window_hidden_cb(document.visibilityState == "hidden");
47-
}, false);
72+
document.addEventListener("visibilitychange", PlatformEmscriptenOnVisibilityChange, false);
4873
},
4974

50-
$PlatformEmscriptenPowerStateChange__deps: ["platform_emscripten_update_power_state_cb"],
51-
$PlatformEmscriptenPowerStateChange: function(e) {
75+
$PlatformEmscriptenOnPowerStateChange__deps: ["platform_emscripten_update_power_state_cb"],
76+
$PlatformEmscriptenOnPowerStateChange: function(e) {
5277
_platform_emscripten_update_power_state_cb(true, Number.isFinite(e.target.dischargingTime) ? e.target.dischargingTime : 0x7FFFFFFF, e.target.level, e.target.charging);
5378
},
5479

55-
PlatformEmscriptenPowerStateInit__deps: ["$PlatformEmscriptenPowerStateChange"],
80+
PlatformEmscriptenPowerStateInit__deps: ["$PlatformEmscriptenOnPowerStateChange"],
81+
PlatformEmscriptenPowerStateInit__proxy: "sync",
5682
PlatformEmscriptenPowerStateInit: function() {
5783
if (!navigator.getBattery) return;
5884
navigator.getBattery().then(function(battery) {
59-
battery.addEventListener("chargingchange", PlatformEmscriptenPowerStateChange);
60-
battery.addEventListener("levelchange", PlatformEmscriptenPowerStateChange);
61-
PlatformEmscriptenPowerStateChange({target: battery});
85+
RPE.battery = battery;
86+
battery.addEventListener("chargingchange", PlatformEmscriptenOnPowerStateChange);
87+
battery.addEventListener("levelchange", PlatformEmscriptenOnPowerStateChange);
88+
PlatformEmscriptenOnPowerStateChange({target: battery});
6289
});
6390
},
6491

6592
$PlatformEmscriptenUpdateMemoryUsage__deps: ["platform_emscripten_update_memory_usage_cb"],
6693
$PlatformEmscriptenUpdateMemoryUsage: function() {
6794
// unfortunately this will be inaccurate in threaded (worker) builds
6895
_platform_emscripten_update_memory_usage_cb(BigInt(performance.memory.usedJSHeapSize || 0), BigInt(performance.memory.jsHeapSizeLimit || 0));
69-
setTimeout(PlatformEmscriptenUpdateMemoryUsage, 5000);
96+
RPE.memoryUsageTimeout = setTimeout(PlatformEmscriptenUpdateMemoryUsage, 5000);
7097
},
7198

7299
PlatformEmscriptenMemoryUsageInit__deps: ["$PlatformEmscriptenUpdateMemoryUsage"],
@@ -75,22 +102,33 @@ var LibraryPlatformEmscripten = {
75102
PlatformEmscriptenUpdateMemoryUsage();
76103
},
77104

78-
PlatformEmscriptenWatchFullscreen__deps: ["platform_emscripten_update_fullscreen_state_cb"],
105+
$PlatformEmscriptenOnFullscreenChange__deps: ["platform_emscripten_update_fullscreen_state_cb"],
106+
$PlatformEmscriptenOnFullscreenChange: function() {
107+
_platform_emscripten_update_fullscreen_state_cb(!!document.fullscreenElement);
108+
},
109+
110+
PlatformEmscriptenWatchFullscreen__deps: ["$PlatformEmscriptenOnFullscreenChange"],
111+
PlatformEmscriptenWatchFullscreen__proxy: "sync",
79112
PlatformEmscriptenWatchFullscreen: function() {
80-
document.addEventListener("fullscreenchange", function() {
81-
_platform_emscripten_update_fullscreen_state_cb(!!document.fullscreenElement);
82-
}, false);
113+
document.addEventListener("fullscreenchange", PlatformEmscriptenOnFullscreenChange, false);
83114
},
84115

85-
PlatformEmscriptenGLContextEventInit__deps: ["platform_emscripten_gl_context_lost_cb", "platform_emscripten_gl_context_restored_cb"],
116+
$PlatformEmscriptenOnGLContextLost__deps: ["platform_emscripten_gl_context_lost_cb"],
117+
$PlatformEmscriptenOnGLContextLost: function(e) {
118+
e.preventDefault();
119+
_platform_emscripten_gl_context_lost_cb();
120+
},
121+
122+
$PlatformEmscriptenOnGLContextRestored__deps: ["platform_emscripten_gl_context_restored_cb"],
123+
$PlatformEmscriptenOnGLContextRestored: function() {
124+
_platform_emscripten_gl_context_restored_cb();
125+
},
126+
127+
PlatformEmscriptenGLContextEventInit__deps: ["$PlatformEmscriptenOnGLContextLost", "$PlatformEmscriptenOnGLContextRestored"],
128+
PlatformEmscriptenGLContextEventInit__proxy: "sync",
86129
PlatformEmscriptenGLContextEventInit: function() {
87-
Module.canvas.addEventListener("webglcontextlost", function(e) {
88-
e.preventDefault();
89-
_platform_emscripten_gl_context_lost_cb();
90-
});
91-
Module.canvas.addEventListener("webglcontextrestored", function() {
92-
_platform_emscripten_gl_context_restored_cb();
93-
});
130+
Module.canvas.addEventListener("webglcontextlost", PlatformEmscriptenOnGLContextLost);
131+
Module.canvas.addEventListener("webglcontextrestored", PlatformEmscriptenOnGLContextRestored);
94132
},
95133

96134
$PlatformEmscriptenDoSetCanvasSize: async function(width, height) {
@@ -156,6 +194,34 @@ var LibraryPlatformEmscripten = {
156194

157195
$EmscriptenReceiveCommandReply: function() {
158196
return RPE.command_reply_queue.shift();
197+
},
198+
199+
$PlatformEmscriptenFreeBrowser__proxy: "sync",
200+
$PlatformEmscriptenFreeBrowser__deps: ["$PlatformEmscriptenDoSetWakeLock", "$PlatformEmscriptenOnCanvasPointerDown", "$PlatformEmscriptenOnCanvasContextMenu", "$PlatformEmscriptenOnWindowResize", "$PlatformEmscriptenOnVisibilityChange", "$PlatformEmscriptenOnFullscreenChange", "$PlatformEmscriptenOnPowerStateChange"],
201+
$PlatformEmscriptenFreeBrowser: function() {
202+
if (RPE.memoryUsageTimeout) clearTimeout(RPE.memoryUsageTimeout);
203+
PlatformEmscriptenDoSetWakeLock(false);
204+
if (RPE.observer) {
205+
RPE.observer.unobserve(Module.canvas);
206+
RPE.observer = null;
207+
}
208+
Module.canvas.removeEventListener("pointerdown", PlatformEmscriptenOnCanvasPointerDown);
209+
Module.canvas.removeEventListener("contextmenu", PlatformEmscriptenOnCanvasContextMenu);
210+
window.removeEventListener("resize", PlatformEmscriptenOnWindowResize);
211+
document.removeEventListener("visibilitychange", PlatformEmscriptenOnVisibilityChange);
212+
document.removeEventListener("fullscreenchange", PlatformEmscriptenOnFullscreenChange);
213+
if (RPE.battery) {
214+
RPE.battery.removeEventListener("chargingchange", PlatformEmscriptenOnPowerStateChange);
215+
RPE.battery.removeEventListener("levelchange", PlatformEmscriptenOnPowerStateChange);
216+
RPE.battery = null;
217+
}
218+
},
219+
220+
PlatformEmscriptenFree__deps: ["$PlatformEmscriptenFreeBrowser"],
221+
PlatformEmscriptenFree: function() {
222+
Module.canvas.removeEventListener("webglcontextlost", PlatformEmscriptenOnGLContextLost);
223+
Module.canvas.removeEventListener("webglcontextrestored", PlatformEmscriptenOnGLContextRestored);
224+
PlatformEmscriptenFreeBrowser();
159225
}
160226
};
161227

0 commit comments

Comments
 (0)