diff options
-rw-r--r-- | src/library_browser.js | 21 | ||||
-rw-r--r-- | src/preamble.js | 15 | ||||
-rw-r--r-- | system/include/EGL/eglplatform.h | 6 | ||||
-rw-r--r-- | system/include/emscripten/emscripten.h | 26 | ||||
-rw-r--r-- | tests/emscripten_api_browser.cpp | 24 | ||||
-rw-r--r-- | tools/reproduceriter.js | 3 | ||||
-rwxr-xr-x | tools/reproduceriter.py | 23 | ||||
-rw-r--r-- | tools/reproduceriter_shell.js | 27 |
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) { |