Merge pull request #6113 from ToadKing/more-emscripten-fixes
Emscripten fixes Part 2
This commit is contained in:
commit
09c49aad11
|
@ -132,3 +132,10 @@ obj-unix/
|
|||
/pkg/msvc/msvc-2010/Release Cg/*.pdb
|
||||
retroarch.cfg
|
||||
Makefile.local
|
||||
|
||||
# Emscripten artifacts
|
||||
|
||||
retroarch.js
|
||||
retroarch.js.mem
|
||||
*.bc
|
||||
*.wasm
|
||||
|
|
|
@ -21,13 +21,15 @@ HAVE_SDL = 0
|
|||
HAVE_SDL2 = 0
|
||||
HAVE_ZLIB = 1
|
||||
WANT_ZLIB = 1
|
||||
HAVE_SHADERPIPELINE = 1
|
||||
HAVE_STATIC_VIDEO_FILTERS = 1
|
||||
HAVE_STATIC_AUDIO_FILTERS = 1
|
||||
MEMORY = 536870912
|
||||
|
||||
# XXX: setting this to 1/2 currently crashes Firefox nightly
|
||||
PRECISE_F32 = 2
|
||||
|
||||
OBJDIR := obj-emscripten
|
||||
|
||||
ifneq ($(NATIVE_ZLIB),)
|
||||
WANT_ZLIB = 0
|
||||
endif
|
||||
|
@ -65,7 +67,7 @@ ifeq ($(DEBUG), 1)
|
|||
LDFLAGS += -O0 -g
|
||||
CFLAGS += -O0 -g
|
||||
else
|
||||
LDFLAGS += -O2
|
||||
LDFLAGS += -O2 -s WASM=1
|
||||
# WARNING: some optimizations can break some cores (ex: LTO breaks tyrquake)
|
||||
LDFLAGS += -s PRECISE_F32=$(PRECISE_F32)
|
||||
ifeq ($(LTO), 1)
|
||||
|
@ -74,48 +76,29 @@ else
|
|||
CFLAGS += -O2
|
||||
endif
|
||||
|
||||
CFLAGS += -DHAVE_RPNG -Wall -Wno-unused-result -Wno-unused-variable -I. -Ilibretro-common/include -std=gnu99 -s USE_ZLIB=1 \
|
||||
CFLAGS += -DHAVE_RPNG -Wall -I. -Ilibretro-common/include -std=gnu99 -s USE_ZLIB=1 \
|
||||
-s EXPORTED_FUNCTIONS="['_main', '_malloc', '_cmd_savefiles', '_cmd_save_state', '_cmd_take_screenshot']"
|
||||
|
||||
RARCH_OBJ := $(addprefix $(OBJDIR)/,$(OBJ))
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
$(TARGET): $(OBJ)
|
||||
$(TARGET): $(RARCH_OBJ)
|
||||
@$(if $(Q), $(shell echo echo LD $@),)
|
||||
$(Q)$(LD) -o $@ $(OBJ) $(libretro) $(LIBS) $(LDFLAGS)
|
||||
$(Q)$(LD) -o $@ $(RARCH_OBJ) $(libretro) $(LIBS) $(LDFLAGS)
|
||||
|
||||
%.o: %.c
|
||||
$(OBJDIR)/%.o: %.c
|
||||
@mkdir -p $(dir $@)
|
||||
@$(if $(Q), $(shell echo echo CC $<),)
|
||||
$(Q)$(CC) $(CFLAGS) $(DEFINES) $(EOPTS) -c -o $@ $<
|
||||
|
||||
%.o: %.cpp
|
||||
$(OBJDIR)/%.o: %.cpp
|
||||
@mkdir -p $(dir $@)
|
||||
@$(if $(Q), $(shell echo echo CXX $<),)
|
||||
$(Q)$(CXX) $(CXXFLAGS) $(DEFINES) $(EOPTS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -f *.o
|
||||
rm -f deps/libz/*.o
|
||||
rm -f frontend/*.o
|
||||
rm -f menu/*.o
|
||||
rm -f menu/disp/*.o
|
||||
rm -f audio/*.o
|
||||
rm -f compat/*.o
|
||||
rm -f compat/rxml/*.o
|
||||
rm -f conf/*.o
|
||||
rm -f gfx/scaler/*.o
|
||||
rm -f gfx/*.o
|
||||
rm -f gfx/d3d/*.o
|
||||
rm -f gfx/drivers_context/*.o
|
||||
rm -f gfx/math/*.o
|
||||
rm -f gfx/drivers_font/*.o
|
||||
rm -f gfx/drivers_font_renderer/*.o
|
||||
rm -f gfx/py_state/*.o
|
||||
rm -f gfx/rpng/*.o
|
||||
rm -f gfx/glsym/*.o
|
||||
rm -f record/*.o
|
||||
rm -f input/*.o
|
||||
rm -f tools/*.o
|
||||
rm -f libretro-common/*/*.o
|
||||
rm -rf $(OBJDIR)
|
||||
rm -f $(TARGET)
|
||||
rm -f *.d
|
||||
|
||||
.PHONY: all clean
|
||||
|
|
|
@ -224,6 +224,7 @@ enum joypad_driver_enum
|
|||
JOYPAD_DOS,
|
||||
JOYPAD_HID,
|
||||
JOYPAD_QNX,
|
||||
JOYPAD_RWEBPAD,
|
||||
JOYPAD_NULL
|
||||
};
|
||||
|
||||
|
@ -454,6 +455,8 @@ static enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_DOS;
|
|||
static enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_HID;
|
||||
#elif defined(__QNX__)
|
||||
static enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_QNX;
|
||||
#elif defined(EMSCRIPTEN)
|
||||
static enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_RWEBPAD;
|
||||
#else
|
||||
static enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_NULL;
|
||||
#endif
|
||||
|
@ -783,9 +786,9 @@ const char *config_get_default_input(void)
|
|||
case INPUT_COCOA:
|
||||
return "cocoa";
|
||||
case INPUT_QNX:
|
||||
return "qnx_input";
|
||||
return "qnx_input";
|
||||
case INPUT_RWEBINPUT:
|
||||
return "rwebinput";
|
||||
return "rwebinput";
|
||||
case INPUT_DOS:
|
||||
return "dos";
|
||||
case INPUT_NULL:
|
||||
|
@ -846,6 +849,8 @@ const char *config_get_default_joypad(void)
|
|||
return "hid";
|
||||
case JOYPAD_QNX:
|
||||
return "qnx";
|
||||
case JOYPAD_RWEBPAD:
|
||||
return "rwebpad";
|
||||
case JOYPAD_DOS:
|
||||
return "dos";
|
||||
case JOYPAD_NULL:
|
||||
|
|
|
@ -23,13 +23,14 @@ var LibraryRWebAudio = {
|
|||
|
||||
getCurrentPerfTime: function() {
|
||||
if (RA.startTime) return (window['performance']['now']() - RA.startTime) / 1000;
|
||||
else throw 'getCurrentPerfTime() called before start time set';
|
||||
else return 0;
|
||||
},
|
||||
|
||||
process: function(queueBuffers) {
|
||||
var currentTime = RA.getCurrentPerfTime();
|
||||
for (var i = 0; i < RA.bufIndex; i++) {
|
||||
if (RA.buffers[i].endTime < currentTime) {
|
||||
if (RA.buffers[i].endTime !== 0 && RA.buffers[i].endTime < currentTime) {
|
||||
RA.buffers[i].endTime = 0;
|
||||
var buf = RA.buffers.splice(i, 1);
|
||||
RA.buffers[RA.numBuffers - 1] = buf[0];
|
||||
i--;
|
||||
|
@ -40,8 +41,8 @@ var LibraryRWebAudio = {
|
|||
|
||||
fillBuffer: function(buf, samples) {
|
||||
var count = 0;
|
||||
var leftBuffer = RA.buffers[RA.bufIndex].getChannelData(0);
|
||||
var rightBuffer = RA.buffers[RA.bufIndex].getChannelData(1);
|
||||
const leftBuffer = RA.buffers[RA.bufIndex].getChannelData(0);
|
||||
const rightBuffer = RA.buffers[RA.bufIndex].getChannelData(1);
|
||||
while (samples && RA.bufOffset !== RA.BUFFER_SIZE) {
|
||||
leftBuffer[RA.bufOffset] = {{{ makeGetValue('buf', 'count * 8', 'float') }}};
|
||||
rightBuffer[RA.bufOffset] = {{{ makeGetValue('buf', 'count * 8 + 4', 'float') }}};
|
||||
|
@ -73,7 +74,7 @@ var LibraryRWebAudio = {
|
|||
block: function() {
|
||||
do {
|
||||
RA.process();
|
||||
} while (RA.bufIndex === RA.numBuffers - 1);
|
||||
} while (RA.bufIndex === RA.numBuffers);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -87,7 +88,10 @@ var LibraryRWebAudio = {
|
|||
RA.numBuffers = ((latency * RA.context.sampleRate) / (1000 * RA.BUFFER_SIZE))|0;
|
||||
if (RA.numBuffers < 2) RA.numBuffers = 2;
|
||||
|
||||
for (var i = 0; i < RA.numBuffers; i++) RA.buffers[i] = RA.context.createBuffer(2, RA.BUFFER_SIZE, RA.context.sampleRate);
|
||||
for (var i = 0; i < RA.numBuffers; i++) {
|
||||
RA.buffers[i] = RA.context.createBuffer(2, RA.BUFFER_SIZE, RA.context.sampleRate);
|
||||
RA.buffers[i].endTime = 0
|
||||
}
|
||||
|
||||
RA.nonblock = false;
|
||||
RA.startTime = 0;
|
||||
|
@ -97,7 +101,7 @@ var LibraryRWebAudio = {
|
|||
Module["pauseMainLoop"]();
|
||||
return 1;
|
||||
},
|
||||
|
||||
|
||||
RWebAudioSampleRate: function() {
|
||||
return RA.context.sampleRate;
|
||||
},
|
||||
|
@ -108,16 +112,17 @@ var LibraryRWebAudio = {
|
|||
var count = 0;
|
||||
|
||||
while (samples) {
|
||||
if (RA.bufIndex === RA.numBuffers) {
|
||||
if (RA.nonblock) break;
|
||||
else RA.block();
|
||||
}
|
||||
|
||||
var fill = RA.fillBuffer(buf, samples);
|
||||
samples -= fill;
|
||||
count += fill;
|
||||
buf += fill * 8;
|
||||
|
||||
if (RA.bufOffset === RA.BUFFER_SIZE) {
|
||||
if (RA.bufIndex === RA.numBuffers - 1) {
|
||||
if (RA.nonblock) break;
|
||||
else RA.block();
|
||||
}
|
||||
RA.queueAudio();
|
||||
}
|
||||
}
|
||||
|
@ -142,16 +147,21 @@ var LibraryRWebAudio = {
|
|||
RWebAudioFree: function() {
|
||||
RA.bufIndex = 0;
|
||||
RA.bufOffset = 0;
|
||||
return;
|
||||
},
|
||||
|
||||
RWebAudioBufferSize: function() {
|
||||
return RA.numBuffers * RA.BUFFER_SIZE + RA.BUFFER_SIZE;
|
||||
return RA.numBuffers * RA.BUFFER_SIZE * 8;
|
||||
},
|
||||
|
||||
RWebAudioWriteAvail: function() {
|
||||
RA.process();
|
||||
return ((RA.numBuffers - RA.bufIndex) * RA.BUFFER_SIZE - RA.bufOffset) * 8;
|
||||
},
|
||||
|
||||
RWebAudioRecalibrateTime: function() {
|
||||
if (RA.startTime) {
|
||||
RA.startTime = window['performance']['now']() - RA.context.currentTime * 1000;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -39,14 +39,42 @@
|
|||
#include "../../defaults.h"
|
||||
#include "../../content.h"
|
||||
#include "../../retroarch.h"
|
||||
#include "../../verbosity.h"
|
||||
#include "../../command.h"
|
||||
#include "../../tasks/tasks_internal.h"
|
||||
#include "../../file_path_special.h"
|
||||
|
||||
void RWebAudioRecalibrateTime(void);
|
||||
|
||||
static unsigned emscripten_fullscreen_reinit;
|
||||
|
||||
static EM_BOOL emscripten_fullscreenchange_cb(int event_type,
|
||||
const EmscriptenFullscreenChangeEvent *fullscreen_change_event,
|
||||
void *user_data)
|
||||
{
|
||||
(void)event_type;
|
||||
(void)fullscreen_change_event;
|
||||
(void)user_data;
|
||||
|
||||
emscripten_fullscreen_reinit = 5;
|
||||
|
||||
return EM_TRUE;
|
||||
}
|
||||
|
||||
static void emscripten_mainloop(void)
|
||||
{
|
||||
unsigned sleep_ms = 0;
|
||||
int ret = runloop_iterate(&sleep_ms);
|
||||
int ret;
|
||||
|
||||
RWebAudioRecalibrateTime();
|
||||
|
||||
if (emscripten_fullscreen_reinit != 0)
|
||||
{
|
||||
if (--emscripten_fullscreen_reinit == 0)
|
||||
command_event(CMD_EVENT_REINIT, NULL);
|
||||
}
|
||||
|
||||
ret = runloop_iterate(&sleep_ms);
|
||||
|
||||
if (ret == 1 && sleep_ms > 0)
|
||||
retro_sleep(sleep_ms);
|
||||
|
@ -162,19 +190,24 @@ static void frontend_emscripten_get_env(int *argc, char *argv[],
|
|||
if (!string_is_empty(dir_path))
|
||||
path_mkdir(dir_path);
|
||||
}
|
||||
|
||||
snprintf(g_defaults.settings.menu, sizeof(g_defaults.settings.menu), "rgui");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
EMSCRIPTEN_RESULT r;
|
||||
|
||||
emscripten_set_canvas_element_size("#canvas", 800, 600);
|
||||
emscripten_set_element_css_size("#canvas", 800.0, 600.0);
|
||||
emscripten_set_main_loop(emscripten_mainloop, 0, 0);
|
||||
rarch_main(argc, argv, NULL);
|
||||
emscripten_set_main_loop(emscripten_mainloop,
|
||||
settings->bools.video_vsync ? 0 : INT_MAX, 1);
|
||||
|
||||
r = emscripten_set_fullscreenchange_callback("#document", NULL, false,
|
||||
emscripten_fullscreenchange_cb);
|
||||
if (r != EMSCRIPTEN_RESULT_SUCCESS)
|
||||
{
|
||||
RARCH_ERR(
|
||||
"[EMSCRIPTEN/CTX] failed to create fullscreen callback: %d\n", r);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -51,8 +51,11 @@ static int emscripten_initial_height;
|
|||
static void gfx_ctx_emscripten_swap_interval(void *data, unsigned interval)
|
||||
{
|
||||
(void)data;
|
||||
/* no way to control VSync in WebGL. */
|
||||
(void)interval;
|
||||
|
||||
if (interval == 0)
|
||||
emscripten_set_main_loop_timing(EM_TIMING_SETIMMEDIATE, 0);
|
||||
else
|
||||
emscripten_set_main_loop_timing(EM_TIMING_RAF, (int)interval);
|
||||
}
|
||||
|
||||
static void gfx_ctx_emscripten_get_canvas_size(int *width, int *height)
|
||||
|
@ -138,8 +141,13 @@ static void gfx_ctx_emscripten_check_window(void *data, bool *quit,
|
|||
|
||||
static void gfx_ctx_emscripten_swap_buffers(void *data, void *data2)
|
||||
{
|
||||
(void)data;
|
||||
/* no-op in emscripten, no way to force swap/wait for VSync in browsers */
|
||||
emscripten_ctx_data_t *emscripten = (emscripten_ctx_data_t*)data;
|
||||
|
||||
/* doesn't really do anything in WebGL, but it might if we use WebGL workers
|
||||
* in the future */
|
||||
#ifdef HAVE_EGL
|
||||
egl_swap_buffers(&emscripten->egl);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void gfx_ctx_emscripten_get_video_size(void *data,
|
||||
|
|
|
@ -567,7 +567,6 @@ static void rwebinput_input_free(void *data)
|
|||
static void rwebinput_process_keyboard_events(rwebinput_input_t *rwebinput,
|
||||
rwebinput_keyboard_event_t *event)
|
||||
{
|
||||
uint32_t crc;
|
||||
uint32_t keycode;
|
||||
unsigned translated_keycode;
|
||||
uint32_t character = 0;
|
||||
|
|
|
@ -86,7 +86,7 @@
|
|||
<span class="fa fa-trash-o" id="icnClean"></span> <span class="sr-only">Cleanup</span>
|
||||
</button>
|
||||
<input class="btn btn-primary disabled" style="display: none" type="file" id="btnRom" name="upload" onclick="document.getElementById('btnAdd').click();" onchange="selectFiles(event.target.files)" multiple />
|
||||
<button class="btn btn-primary disabled tooltip-enable" id="btnMenu" onclick="keyPress(112);" title="Menu toggle" disabled>
|
||||
<button class="btn btn-primary disabled tooltip-enable" id="btnMenu" onclick="keyPress('F1');" title="Menu toggle" disabled>
|
||||
<span class="fa fa-bars" id="btnMenu"></span> <span class="sr-only">Menu</span>
|
||||
</button>
|
||||
<button class="btn btn-primary disabled tooltip-enable" id="btnFullscreen" onclick="Module.requestFullScreen()" title="Fullscreen" disabled>
|
||||
|
@ -105,27 +105,14 @@
|
|||
</div>
|
||||
</nav>
|
||||
<div class="bg-inverse webplayer-container">
|
||||
<div class="container">
|
||||
<div class="webplayer_border text-xs-center" id="canvas_div">
|
||||
<div class="showMenu">
|
||||
<button type="button" class="btn btn-link">
|
||||
<span class="fa fa-chevron-down" id="icnShowMenu"></span> <span class="sr-only">Show Top Navigation</span>
|
||||
</button>
|
||||
</div>
|
||||
<canvas class="webplayer" id="canvas" tabindex="1" oncontextmenu="event.preventDefault()" style="display: none"></canvas>
|
||||
<img class="webplayer-preview img-fluid" src="media/canvas.png" width="960px" height="720px" alt="RetroArch Logo">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 form-group btn-group text-xs-center p-t-2">
|
||||
<div class="card">
|
||||
<div class="view overlay hm-white-slight" align="center">
|
||||
<textarea id="output" rows="15"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="webplayer_border text-xs-center" id="canvas_div">
|
||||
<div class="showMenu">
|
||||
<button type="button" class="btn btn-link">
|
||||
<span class="fa fa-chevron-down" id="icnShowMenu"></span> <span class="sr-only">Show Top Navigation</span>
|
||||
</button>
|
||||
</div>
|
||||
<canvas class="webplayer" id="canvas" tabindex="1" oncontextmenu="event.preventDefault()" style="display: none"></canvas>
|
||||
<img class="webplayer-preview img-fluid" src="media/canvas.png" width="960px" height="720px" alt="RetroArch Logo">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -112,3 +112,8 @@ textarea {
|
|||
#icnShowMenu {
|
||||
color: #565656 !important;
|
||||
}
|
||||
|
||||
/* fix weird white bar in chrome when fullscreen */
|
||||
:-webkit-full-screen {
|
||||
height: 100%;
|
||||
}
|
||||
|
|
|
@ -184,24 +184,13 @@ var Module =
|
|||
arguments: ["-v", "--menu"],
|
||||
preRun: [],
|
||||
postRun: [],
|
||||
print: (function()
|
||||
print: function(text)
|
||||
{
|
||||
var element = document.getElementById('output');
|
||||
element.value = ''; // clear browser cache
|
||||
return function(text)
|
||||
{
|
||||
text = Array.prototype.slice.call(arguments).join(' ');
|
||||
element.value += text + "\n";
|
||||
element.scrollTop = 99999; // focus on bottom
|
||||
};
|
||||
})(),
|
||||
|
||||
console.log(text);
|
||||
},
|
||||
printErr: function(text)
|
||||
{
|
||||
var text = Array.prototype.slice.call(arguments).join(' ');
|
||||
var element = document.getElementById('output');
|
||||
element.value += text + "\n";
|
||||
element.scrollTop = 99999; // focus on bottom
|
||||
console.log(text);
|
||||
},
|
||||
canvas: document.getElementById('canvas'),
|
||||
totalDependencies: 0,
|
||||
|
@ -306,31 +295,7 @@ function keyPress(k)
|
|||
}
|
||||
|
||||
kp = function(k, event) {
|
||||
var oEvent = document.createEvent('KeyboardEvent');
|
||||
|
||||
// Chromium Hack
|
||||
Object.defineProperty(oEvent, 'keyCode', {
|
||||
get : function() {
|
||||
return this.keyCodeVal;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(oEvent, 'which', {
|
||||
get : function() {
|
||||
return this.keyCodeVal;
|
||||
}
|
||||
});
|
||||
|
||||
if (oEvent.initKeyboardEvent) {
|
||||
oEvent.initKeyboardEvent(event, true, true, document.defaultView, false, false, false, false, k, k);
|
||||
} else {
|
||||
oEvent.initKeyEvent(event, true, true, document.defaultView, false, false, false, false, k, 0);
|
||||
}
|
||||
|
||||
oEvent.keyCodeVal = k;
|
||||
|
||||
if (oEvent.keyCode !== k) {
|
||||
alert("keyCode mismatch " + oEvent.keyCode + "(" + oEvent.which + ")");
|
||||
}
|
||||
var oEvent = new KeyboardEvent(event, { code: k });
|
||||
|
||||
document.dispatchEvent(oEvent);
|
||||
document.getElementById('canvas').focus();
|
||||
|
|
Loading…
Reference in New Issue