aboutsummaryrefslogtreecommitdiff
path: root/src/library_browser.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/library_browser.js')
-rw-r--r--src/library_browser.js180
1 files changed, 126 insertions, 54 deletions
diff --git a/src/library_browser.js b/src/library_browser.js
index 1740eaed..a3e68209 100644
--- a/src/library_browser.js
+++ b/src/library_browser.js
@@ -41,6 +41,26 @@ mergeInto(LibraryManager.library, {
Module['setStatus']('');
}
}
+ },
+ runIter: function(func) {
+ if (ABORT) return;
+ if (Module['preMainLoop']) {
+ var preRet = Module['preMainLoop']();
+ if (preRet === false) {
+ return; // |return false| skips a frame
+ }
+ }
+ try {
+ func();
+ } catch (e) {
+ if (e instanceof ExitStatus) {
+ return;
+ } else {
+ if (e && typeof e === 'object' && e.stack) Module.printErr('exception thrown: ' + [e, e.stack]);
+ throw e;
+ }
+ }
+ if (Module['postMainLoop']) Module['postMainLoop']();
}
},
isFullScreen: false,
@@ -51,7 +71,7 @@ mergeInto(LibraryManager.library, {
init: function() {
if (!Module["preloadPlugins"]) Module["preloadPlugins"] = []; // needs to exist even in workers
- if (Browser.initted || ENVIRONMENT_IS_WORKER) return;
+ if (Browser.initted || ENVIRONMENT_IS_WORKER) return; // workers do not support Image and Audio elements
Browser.initted = true;
try {
@@ -242,6 +262,8 @@ mergeInto(LibraryManager.library, {
return null;
}
#endif
+ if (useWebGL && Module.ctx) return Module.ctx; // no need to recreate singleton GL context
+
var ctx;
var errorInfo = '?';
function onContextCreationError(event) {
@@ -282,49 +304,98 @@ mergeInto(LibraryManager.library, {
}
if (useWebGL) {
#if GL_DEBUG
- // Useful to debug native webgl apps: var Module = { printErr: function(x) { console.log(x) } };
- var tempCtx = ctx;
- var wrapper = {};
- for (var prop in tempCtx) {
- (function(prop) {
- switch (typeof tempCtx[prop]) {
- case 'function': {
- wrapper[prop] = function gl_wrapper() {
- if (GL.debug) {
- var printArgs = Array.prototype.slice.call(arguments).map(Runtime.prettyPrint);
- Module.printErr('[gl_f:' + prop + ':' + printArgs + ']');
- }
- var ret = tempCtx[prop].apply(tempCtx, arguments);
- if (GL.debug && typeof ret != 'undefined') {
- Module.printErr('[ gl:' + prop + ':return:' + Runtime.prettyPrint(ret) + ']');
- }
- return ret;
- }
- break;
+ function wrapDebugGL(ctx) {
+
+ var printObjectList = [];
+
+ function prettyPrint(arg) {
+ if (typeof arg == 'undefined') return '!UNDEFINED!';
+ if (typeof arg == 'boolean') arg = arg + 0;
+ if (!arg) return arg;
+ var index = printObjectList.indexOf(arg);
+ if (index >= 0) return '<' + arg + '|'; // + index + '>';
+ if (arg.toString() == '[object HTMLImageElement]') {
+ return arg + '\n\n';
+ }
+ if (arg.byteLength) {
+ return '{' + Array.prototype.slice.call(arg, 0, Math.min(arg.length, 400)) + '}'; // Useful for correct arrays, less so for compiled arrays, see the code below for that
+ var buf = new ArrayBuffer(32);
+ var i8buf = new Int8Array(buf);
+ var i16buf = new Int16Array(buf);
+ var f32buf = new Float32Array(buf);
+ switch(arg.toString()) {
+ case '[object Uint8Array]':
+ i8buf.set(arg.subarray(0, 32));
+ break;
+ case '[object Float32Array]':
+ f32buf.set(arg.subarray(0, 5));
+ break;
+ case '[object Uint16Array]':
+ i16buf.set(arg.subarray(0, 16));
+ break;
+ default:
+ alert('unknown array for debugging: ' + arg);
+ throw 'see alert';
}
- case 'number': case 'string': {
- wrapper.__defineGetter__(prop, function() {
- //Module.printErr('[gl_g:' + prop + ':' + tempCtx[prop] + ']');
- return tempCtx[prop];
- });
- wrapper.__defineSetter__(prop, function(value) {
- if (GL.debug) {
- Module.printErr('[gl_s:' + prop + ':' + value + ']');
+ var ret = '{' + arg.byteLength + ':\n';
+ var arr = Array.prototype.slice.call(i8buf);
+ ret += 'i8:' + arr.toString().replace(/,/g, ',') + '\n';
+ arr = Array.prototype.slice.call(f32buf, 0, 8);
+ ret += 'f32:' + arr.toString().replace(/,/g, ',') + '}';
+ return ret;
+ }
+ if (typeof arg == 'object') {
+ printObjectList.push(arg);
+ return '<' + arg + '|'; // + (printObjectList.length-1) + '>';
+ }
+ if (typeof arg == 'number') {
+ if (arg > 0) return '0x' + arg.toString(16) + ' (' + arg + ')';
+ }
+ return arg;
+ }
+
+ var wrapper = {};
+ for (var prop in ctx) {
+ (function(prop) {
+ switch (typeof ctx[prop]) {
+ case 'function': {
+ wrapper[prop] = function gl_wrapper() {
+ var printArgs = Array.prototype.slice.call(arguments).map(prettyPrint);
+ dump('[gl_f:' + prop + ':' + printArgs + ']\n');
+ var ret = ctx[prop].apply(ctx, arguments);
+ if (typeof ret != 'undefined') {
+ dump('[ gl:' + prop + ':return:' + prettyPrint(ret) + ']\n');
+ }
+ return ret;
}
- tempCtx[prop] = value;
- });
- break;
+ break;
+ }
+ case 'number': case 'string': {
+ wrapper.__defineGetter__(prop, function() {
+ //dump('[gl_g:' + prop + ':' + ctx[prop] + ']\n');
+ return ctx[prop];
+ });
+ wrapper.__defineSetter__(prop, function(value) {
+ dump('[gl_s:' + prop + ':' + value + ']\n');
+ ctx[prop] = value;
+ });
+ break;
+ }
}
- }
- })(prop);
+ })(prop);
+ }
+ return wrapper;
}
- ctx = wrapper;
#endif
+ // possible GL_DEBUG entry point: ctx = wrapDebugGL(ctx);
+
// Set the background of the WebGL canvas to black
canvas.style.backgroundColor = "black";
}
if (setInModule) {
- GLctx = Module.ctx = ctx;
+ if (!useWebGL) assert(typeof GLctx === 'undefined', 'cannot set in module if GLctx is used, but we are a non-GL context that would replace it');
+ Module.ctx = ctx;
+ if (useWebGL) GLctx = ctx;
Module.useWebGL = useWebGL;
Browser.moduleContextCreatedCallbacks.forEach(function(callback) { callback() });
Browser.init();
@@ -395,9 +466,25 @@ mergeInto(LibraryManager.library, {
canvasContainer.requestFullScreen();
},
+ nextRAF: 0,
+
+ fakeRequestAnimationFrame: function(func) {
+ // try to keep 60fps between calls to here
+ var now = Date.now();
+ if (Browser.nextRAF === 0) {
+ Browser.nextRAF = now + 1000/60;
+ } else {
+ while (now + 2 >= Browser.nextRAF) { // fudge a little, to avoid timer jitter causing us to do lots of delay:0
+ Browser.nextRAF += 1000/60;
+ }
+ }
+ var delay = Math.max(Browser.nextRAF - now, 0);
+ setTimeout(func, delay);
+ },
+
requestAnimationFrame: function requestAnimationFrame(func) {
if (typeof window === 'undefined') { // Provide fallback to setTimeout if window is undefined (e.g. in Node.js)
- setTimeout(func, 1000/60);
+ Browser.fakeRequestAnimationFrame(func);
} else {
if (!window.requestAnimationFrame) {
window.requestAnimationFrame = window['requestAnimationFrame'] ||
@@ -405,7 +492,7 @@ mergeInto(LibraryManager.library, {
window['webkitRequestAnimationFrame'] ||
window['msRequestAnimationFrame'] ||
window['oRequestAnimationFrame'] ||
- window['setTimeout'];
+ Browser.fakeRequestAnimationFrame;
}
window.requestAnimationFrame(func);
}
@@ -954,28 +1041,13 @@ mergeInto(LibraryManager.library, {
Browser.mainLoop.method = ''; // just warn once per call to set main loop
}
- if (Module['preMainLoop']) {
- Module['preMainLoop']();
- }
-
- try {
+ Browser.mainLoop.runIter(function() {
if (typeof arg !== 'undefined') {
Runtime.dynCall('vi', func, [arg]);
} else {
Runtime.dynCall('v', func);
}
- } catch (e) {
- if (e instanceof ExitStatus) {
- return;
- } else {
- if (e && typeof e === 'object' && e.stack) Module.printErr('exception thrown: ' + [e, e.stack]);
- throw e;
- }
- }
-
- if (Module['postMainLoop']) {
- Module['postMainLoop']();
- }
+ });
if (Browser.mainLoop.shouldPause) {
// catch pauses from the main loop itself