Merge pull request #6113 from ToadKing/more-emscripten-fixes

Emscripten fixes Part 2
This commit is contained in:
Twinaphex 2018-01-15 12:27:57 +01:00 committed by GitHub
commit 09c49aad11
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 121 additions and 119 deletions

7
.gitignore vendored
View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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;
}
}
};

View File

@ -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;
}

View File

@ -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,

View File

@ -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;

View File

@ -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>

View File

@ -112,3 +112,8 @@ textarea {
#icnShowMenu {
color: #565656 !important;
}
/* fix weird white bar in chrome when fullscreen */
:-webkit-full-screen {
height: 100%;
}

View File

@ -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();