aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/library_browser.js21
-rw-r--r--src/preamble.js15
-rw-r--r--system/include/EGL/eglplatform.h6
-rw-r--r--system/include/emscripten/emscripten.h26
-rw-r--r--tests/emscripten_api_browser.cpp24
-rw-r--r--tools/reproduceriter.js3
-rwxr-xr-xtools/reproduceriter.py23
-rw-r--r--tools/reproduceriter_shell.js27
8 files changed, 97 insertions, 48 deletions
diff --git a/src/library_browser.js b/src/library_browser.js
index 43732e5b..5291dcee 100644
--- a/src/library_browser.js
+++ b/src/library_browser.js
@@ -384,7 +384,7 @@ mergeInto(LibraryManager.library, {
if (Browser.mainLoop.queue.length > 0) {
var start = Date.now();
var blocker = Browser.mainLoop.queue.shift();
- blocker.func();
+ blocker.func(blocker.arg);
if (Browser.mainLoop.remainingBlockers) {
var remaining = Browser.mainLoop.remainingBlockers;
var next = remaining%1 == 0 ? remaining-1 : Math.floor(remaining);
@@ -451,13 +451,13 @@ mergeInto(LibraryManager.library, {
Browser.mainLoop.resume();
},
- _emscripten_push_main_loop_blocker: function(func, name) {
- Browser.mainLoop.queue.push({ func: FUNCTION_TABLE[func], name: Pointer_stringify(name), counted: true });
+ _emscripten_push_main_loop_blocker: function(func, arg, name) {
+ Browser.mainLoop.queue.push({ func: FUNCTION_TABLE[func], arg: arg, name: Pointer_stringify(name), counted: true });
Browser.mainLoop.updateStatus();
},
- _emscripten_push_uncounted_main_loop_blocker: function(func, name) {
- Browser.mainLoop.queue.push({ func: FUNCTION_TABLE[func], name: Pointer_stringify(name), counted: false });
+ _emscripten_push_uncounted_main_loop_blocker: function(func, arg, name) {
+ Browser.mainLoop.queue.push({ func: FUNCTION_TABLE[func], arg: arg, name: Pointer_stringify(name), counted: false });
Browser.mainLoop.updateStatus();
},
@@ -467,14 +467,17 @@ mergeInto(LibraryManager.library, {
Browser.mainLoop.updateStatus();
},
- emscripten_async_call: function(func, millis) {
+ emscripten_async_call: function(func, arg, millis) {
Module['noExitRuntime'] = true;
- var asyncCall = Runtime.getFuncWrapper(func);
+ function wrapper() {
+ Runtime.getFuncWrapper(func)(arg);
+ }
+
if (millis >= 0) {
- setTimeout(asyncCall, millis);
+ setTimeout(wrapper, millis);
} else {
- Browser.requestAnimationFrame(asyncCall);
+ Browser.requestAnimationFrame(wrapper);
}
},
diff --git a/src/preamble.js b/src/preamble.js
index b3cfca85..f1b95958 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -457,8 +457,6 @@ function getValue(ptr, type, noSafe) {
}
Module['getValue'] = getValue;
-// Allocates memory for some data and initializes it properly.
-
var ALLOC_NORMAL = 0; // Tries to use _malloc()
var ALLOC_STACK = 1; // Lives for the duration of the current function call
var ALLOC_STATIC = 2; // Cannot be freed
@@ -466,6 +464,19 @@ Module['ALLOC_NORMAL'] = ALLOC_NORMAL;
Module['ALLOC_STACK'] = ALLOC_STACK;
Module['ALLOC_STATIC'] = ALLOC_STATIC;
+// allocate(): This is for internal use. You can use it yourself as well, but the interface
+// is a little tricky (see docs right below). The reason is that it is optimized
+// for multiple syntaxes to save space in generated code. So you should
+// normally not use allocate(), and instead allocate memory using _malloc(),
+// initialize it with setValue(), and so forth.
+// @slab: An array of data, or a number. If a number, then the size of the block to allocate,
+// in *bytes* (note that this is sometimes confusing: the next parameter does not
+// affect this!)
+// @types: Either an array of types, one for each byte (or 0 if no type at that position),
+// or a single type which is used for the entire block. This only matters if there
+// is initial data - if @slab is a number, then this does not matter at all and is
+// ignored.
+// @allocator: How to allocate memory, see ALLOC_*
function allocate(slab, types, allocator) {
var zeroinit, size;
if (typeof slab === 'number') {
diff --git a/system/include/EGL/eglplatform.h b/system/include/EGL/eglplatform.h
index 4512fd84..2db2cc47 100644
--- a/system/include/EGL/eglplatform.h
+++ b/system/include/EGL/eglplatform.h
@@ -75,6 +75,12 @@ typedef HDC EGLNativeDisplayType;
typedef HBITMAP EGLNativePixmapType;
typedef HWND EGLNativeWindowType;
+#elif defined(EMSCRIPTEN)
+
+typedef int EGLNativeDisplayType;
+typedef int EGLNativeWindowType;
+typedef int EGLNativePixmapType;
+
#elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */
typedef int EGLNativeDisplayType;
diff --git a/system/include/emscripten/emscripten.h b/system/include/emscripten/emscripten.h
index 4d489142..8c42a18a 100644
--- a/system/include/emscripten/emscripten.h
+++ b/system/include/emscripten/emscripten.h
@@ -62,20 +62,20 @@ extern void emscripten_cancel_main_loop();
* at specific time in the future.
*/
#if EMSCRIPTEN
-extern void _emscripten_push_main_loop_blocker(void (*func)(), const char *name);
-extern void _emscripten_push_uncounted_main_loop_blocker(void (*func)(), const char *name);
+extern void _emscripten_push_main_loop_blocker(void (*func)(void *), void *arg, const char *name);
+extern void _emscripten_push_uncounted_main_loop_blocker(void (*func)(void *), void *arg, const char *name);
#else
-inline void _emscripten_push_main_loop_blocker(void (*func)(), const char *name) {
- func();
+inline void _emscripten_push_main_loop_blocker(void (*func)(void *), void *arg, const char *name) {
+ func(arg);
}
-inline void _emscripten_push_uncounted_main_loop_blocker(void (*func)(), const char *name) {
- func();
+inline void _emscripten_push_uncounted_main_loop_blocker(void (*func)(void *), void *arg, const char *name) {
+ func(arg);
}
#endif
-#define emscripten_push_main_loop_blocker(func) \
- _emscripten_push_main_loop_blocker(func, #func)
-#define emscripten_push_uncounted_main_loop_blocker(func) \
- _emscripten_push_uncounted_main_loop_blocker(func, #func)
+#define emscripten_push_main_loop_blocker(func, arg) \
+ _emscripten_push_main_loop_blocker(func, arg, #func)
+#define emscripten_push_uncounted_main_loop_blocker(func, arg) \
+ _emscripten_push_uncounted_main_loop_blocker(func, arg, #func)
/*
* Sets the number of blockers remaining until some user-relevant
@@ -99,11 +99,11 @@ inline void emscripten_set_main_loop_expected_blockers(int num) {}
* mechanism is used.
*/
#if EMSCRIPTEN
-extern void emscripten_async_call(void (*func)(), int millis);
+extern void emscripten_async_call(void (*func)(void *), void *arg, int millis);
#else
-inline void emscripten_async_call(void (*func)(), int millis) {
+inline void emscripten_async_call(void (*func)(void *), void *arg, int millis) {
if (millis) SDL_Delay(millis);
- func();
+ func(arg);
}
#endif
diff --git a/tests/emscripten_api_browser.cpp b/tests/emscripten_api_browser.cpp
index 305265e5..c209550b 100644
--- a/tests/emscripten_api_browser.cpp
+++ b/tests/emscripten_api_browser.cpp
@@ -11,19 +11,22 @@ extern "C" {
bool pre1ed = false;
bool pre2ed = false;
-void pre1() {
+void pre1(void *arg) {
assert(!pre1ed);
assert(!pre2ed);
+ assert((int)arg == 123);
pre1ed = true;
}
-void pre2() {
+void pre2(void *arg) {
assert(pre1ed);
assert(!pre2ed);
+ assert((int)arg == 98);
pre2ed = true;
}
bool fived = false;
-void five() {
+void five(void *arg) {
+ assert((int)arg == 55);
fived = true;
emscripten_resume_main_loop();
}
@@ -33,11 +36,11 @@ void mainey() {
printf("mainey: %d\n", counter++);
if (counter == 20) {
emscripten_pause_main_loop();
- emscripten_async_call(five, 1000);
+ emscripten_async_call(five, (void*)55, 1000);
} else if (counter == 22) { // very soon after 20, so without pausing we fail
assert(fived);
- emscripten_push_main_loop_blocker(pre1);
- emscripten_push_main_loop_blocker(pre2);
+ emscripten_push_main_loop_blocker(pre1, (void*)123);
+ emscripten_push_main_loop_blocker(pre2, (void*)98);
} else if (counter == 23) {
assert(pre1ed);
assert(pre2ed);
@@ -47,7 +50,8 @@ void mainey() {
}
}
-void four() {
+void four(void *arg) {
+ assert((int)arg == 43);
printf("four!\n");
emscripten_set_main_loop(mainey, 0);
}
@@ -56,10 +60,10 @@ void __attribute__((used)) third() {
int now = SDL_GetTicks();
printf("thard! %d\n", now);
assert(fabs(now - last - 1000) < 500);
- emscripten_async_call(four, -1); // triggers requestAnimationFrame
+ emscripten_async_call(four, (void*)43, -1); // triggers requestAnimationFrame
}
-void second() {
+void second(void *arg) {
int now = SDL_GetTicks();
printf("sacond! %d\n", now);
assert(fabs(now - last - 500) < 250);
@@ -81,7 +85,7 @@ int main() {
atexit(never); // should never be called - it is wrong to exit the runtime orderly if we have async calls!
- emscripten_async_call(second, 500);
+ emscripten_async_call(second, (void*)0, 500);
return 1;
}
diff --git a/tools/reproduceriter.js b/tools/reproduceriter.js
index 715052fb..9dce8199 100644
--- a/tools/reproduceriter.js
+++ b/tools/reproduceriter.js
@@ -40,7 +40,8 @@ var Recorder = (function() {
return ret;
};
recorder.pnows = [];
- recorder.pnow = performance.now;
+ var pnow = performance.now || performance.webkitNow || performance.mozNow || performance.oNow || performance.msNow;
+ recorder.pnow = function() { return pnow.call(performance) };
performance.now = function() {
var ret = recorder.pnow();
recorder.pnows.push(ret);
diff --git a/tools/reproduceriter.py b/tools/reproduceriter.py
index 89fcc41c..a1912396 100755
--- a/tools/reproduceriter.py
+++ b/tools/reproduceriter.py
@@ -1,9 +1,6 @@
#!/usr/bin/env python
'''
-
-* This is a work in progress *
-
Reproducer Rewriter
===================
@@ -30,7 +27,8 @@ Usage:
specified, we will make a build that runs in the shell and not in
a browser. WINDOW_LOCATION is the fake window.location we set in the
fake DOM, and ON_IDLE is code that runs when the fake main browser
- event loop runs out of actions.
+ event loop runs out of actions. (Note that only a browser build can
+ do recording, shell builds just replay.)
You will need to call
@@ -86,7 +84,24 @@ Examples
emscripten/tools/reproduceriter.py bb bench js/game-setup.js game.html?low,low,reproduce=repro.data "function(){ print('triggering click'); document.querySelector('.fullscreen-button.low-res').callEventListeners('click'); window.onIdle = null; }"
+ for a shell build, or
+
+ emscripten/tools/reproduceriter.py bb bench js/game-setup.js
+
+ for a browser build. Since only a browser build can do recording, you would normally
+ make a browser build, record a trace, then make a shell build and copy the trace
+ there so you can run it.
+
The last parameter specifies what to do when the event loop is idle: We fire an event and then set onIdle (which was this function) to null, so this is a one-time occurence.
+
+Notes
+
+ * Replay can depend on browser state. One case is if you are replaying a fullscreen
+ game with pointer lock, then you will need to manually allow pointer lock if it
+ isn't already on for the machine. If you do it too early or too late, the replay
+ can be different, since mousemove events mean different things depending on
+ whether the pointer is locked or not.
+
'''
import os, sys, shutil, re
diff --git a/tools/reproduceriter_shell.js b/tools/reproduceriter_shell.js
index 05138797..f425df82 100644
--- a/tools/reproduceriter_shell.js
+++ b/tools/reproduceriter_shell.js
@@ -86,7 +86,8 @@ var document = {
getElementById: function(id) {
switch(id) {
case 'canvas': {
- return {
+ if (this.canvas) return this.canvas;
+ return this.canvas = {
getContext: function(which) {
switch(which) {
case 'experimental-webgl': {
@@ -650,6 +651,9 @@ var document = {
bindRenderbuffer: function(){},
renderbufferStorage: function(){},
framebufferRenderbuffer: function(){},
+ scissor: function(){},
+ colorMask: function(){},
+ lineWidth: function(){},
};
}
case '2d': {
@@ -668,18 +672,23 @@ var document = {
}
},
requestPointerLock: function() {
- document.callEventListeners('pointerlockchange');
+ document.pointerLockElement = document.getElementById('canvas');
+ window.setTimeout(function() {
+ document.callEventListeners('pointerlockchange');
+ });
},
style: {},
eventListeners: {},
addEventListener: document.addEventListener,
callEventListeners: document.callEventListeners,
requestFullScreen: function() {
- var that = this;
+ document.fullscreenElement = document.getElementById('canvas');
window.setTimeout(function() {
- that.callEventListeners('fullscreenchange');
+ document.callEventListeners('fullscreenchange');
});
},
+ offsetTop: 0,
+ offsetLeft: 0,
};
}
case 'status-text': case 'progress': {
@@ -835,11 +844,11 @@ var Worker = function(workerPath) {
};
Worker.id = 0;
Worker.messageId = 0;
-var screen = {
- width: 800,
- height: 600,
- availWidth: 800,
- availHeight: 600,
+var screen = { // XXX these values may need to be adjusted
+ width: 2100,
+ height: 1313,
+ availWidth: 2100,
+ availHeight: 1283,
};
var console = {
log: function(x) {