diff options
author | Alon Zakai <alonzakai@gmail.com> | 2013-03-20 13:44:50 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2013-03-20 13:44:50 -0700 |
commit | 669c786e3554b280e31dcb7bd92931482547dae0 (patch) | |
tree | 110d48a9e6bf29ceed41ac6282dc37d2f0f3f433 | |
parent | b22f6fbbbebb5df55ceb8fdc9f7c4d111c902c5e (diff) | |
parent | 421e70ecf266d6619415b53c1bc03d4a127a585d (diff) |
Merge branch 'incoming'
-rw-r--r-- | AUTHORS | 1 | ||||
-rwxr-xr-x | emscripten.py | 4 | ||||
-rw-r--r-- | src/jsifier.js | 11 | ||||
-rw-r--r-- | src/library.js | 402 | ||||
-rw-r--r-- | src/library_browser.js | 54 | ||||
-rw-r--r-- | src/library_gl.js | 109 | ||||
-rw-r--r-- | src/library_openal.js | 154 | ||||
-rw-r--r-- | src/library_sdl.js | 19 | ||||
-rw-r--r-- | src/parseTools.js | 4 | ||||
-rw-r--r-- | src/preamble.js | 48 | ||||
-rw-r--r-- | src/settings.js | 16 | ||||
-rw-r--r-- | src/shell.html | 8 | ||||
-rw-r--r-- | system/include/libc/ctype.h | 44 | ||||
-rw-r--r-- | tests/cases/alignedunaligned.ll | 6 | ||||
-rw-r--r-- | tests/cases/phicubed.ll | 29 | ||||
-rw-r--r-- | tests/cases/storestruct.ll | 5 | ||||
-rw-r--r-- | tests/cases/unannotated__noasm.ll (renamed from tests/cases/unannotated.ll) | 0 | ||||
-rw-r--r-- | tests/cases/unannotated__noasm.txt (renamed from tests/cases/unannotated.txt) | 0 | ||||
-rw-r--r-- | tests/gl_ps_strides.c | 241 | ||||
-rw-r--r-- | tests/gl_ps_strides.png | bin | 0 -> 98713 bytes | |||
-rwxr-xr-x | tests/runner.py | 181 | ||||
-rwxr-xr-x | tools/bindings_generator.py | 5 | ||||
-rw-r--r-- | tools/js-optimizer.js | 11 | ||||
-rw-r--r-- | tools/shared.py | 2 |
24 files changed, 977 insertions, 377 deletions
@@ -54,4 +54,5 @@ a license to everyone to use it as detailed in LICENSE.) * Lorant Pinter <lorant.pinter@prezi.com> * Tobias Doerffel <tobias.doerffel@gmail.com> * Martin von Gagern <martin@von-gagern.net> +* Ting-Yuan Huang <thuang@mozilla.com> diff --git a/emscripten.py b/emscripten.py index 0698c783..c9d8505d 100755 --- a/emscripten.py +++ b/emscripten.py @@ -269,8 +269,10 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None, for key in curr_forwarded_json['Functions']['indexedFunctions'].iterkeys(): indexed_functions.add(key) if settings.get('ASM_JS'): + export_bindings = settings['EXPORT_BINDINGS'] for key in curr_forwarded_json['Functions']['implementedFunctions'].iterkeys(): - if key in all_exported_functions: exported_implemented_functions.add(key) + if key in all_exported_functions or (export_bindings and key.startswith('_emscripten_bind')): + exported_implemented_functions.add(key) for key, value in curr_forwarded_json['Functions']['unimplementedFunctions'].iteritems(): forwarded_json['Functions']['unimplementedFunctions'][key] = value diff --git a/src/jsifier.js b/src/jsifier.js index 4263618a..7db2ee70 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -512,9 +512,13 @@ function JSify(data, functionsOnly, givenFunctions) { } else if (LibraryManager.library.hasOwnProperty(shortident)) { item.JS = addFromLibrary(shortident); } else if (!LibraryManager.library.hasOwnProperty(shortident + '__inline')) { - item.JS = 'var ' + item.ident + '; // stub for ' + item.ident; - if (WARN_ON_UNDEFINED_SYMBOLS || ASM_JS) { // always warn on undefs in asm, since it breaks validation - warn('Unresolved symbol: ' + item.ident); + if (!(item.ident in DEAD_FUNCTIONS) && !UNRESOLVED_AS_DEAD) { + item.JS = 'var ' + item.ident + '; // stub for ' + item.ident; + if (ASM_JS) { + throw 'Unresolved symbol: ' + item.ident + ', this must be corrected for asm.js validation to succeed. Consider adding it to DEAD_FUNCTIONS.'; + } else if (WARN_ON_UNDEFINED_SYMBOLS) { + warn('Unresolved symbol: ' + item.ident); + } } } return ret; @@ -722,6 +726,7 @@ function JSify(data, functionsOnly, givenFunctions) { ret += indent + 'label = ' + getLabelId(block.entries[0]) + '; ' + (SHOW_LABELS ? '/* ' + getOriginalLabelId(block.entries[0]) + ' */' : '') + '\n'; } // otherwise, should have been set before! if (func.setjmpTable) { + assert(!ASM_JS, 'asm.js mode does not support setjmp yet'); var setjmpTable = {}; ret += indent + 'var mySetjmpIds = {};\n'; ret += indent + 'var setjmpTable = {'; diff --git a/src/library.js b/src/library.js index 45187d8d..aebad63b 100644 --- a/src/library.js +++ b/src/library.js @@ -382,7 +382,7 @@ LibraryManager.library = { // do preloading for the Image/Audio part, as if the typed array were the // result of an XHR that you did manually. createPreloadedFile: function(parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile) { - Browser.ensureObjects(); + Browser.init(); var fullname = FS.joinPath([parent, name], true); function processData(byteArray) { function finish(byteArray) { @@ -2638,11 +2638,11 @@ LibraryManager.library = { } return fields; }, - // Performs prtinf-style formatting. + // Performs printf-style formatting. // format: A pointer to the format string. // varargs: A pointer to the start of the arguments list. // Returns the resulting string string as a character array. - _formatString__deps: ['strlen'], + _formatString__deps: ['strlen', '_reallyNegative'], _formatString: function(format, varargs) { var textIndex = format; var argIndex = 0; @@ -2782,226 +2782,251 @@ LibraryManager.library = { next = {{{ makeGetValue(0, 'textIndex+1', 'i8') }}}; // Handle type specifier. - if (['d', 'i', 'u', 'o', 'x', 'X', 'p'].indexOf(String.fromCharCode(next)) != -1) { - // Integer. - var signed = next == {{{ charCode('d') }}} || next == {{{ charCode('i') }}}; - argSize = argSize || 4; - var currArg = getNextArg('i' + (argSize * 8)); + switch (String.fromCharCode(next)) { + case 'd': case 'i': case 'u': case 'o': case 'x': case 'X': case 'p': { + // Integer. + var signed = next == {{{ charCode('d') }}} || next == {{{ charCode('i') }}}; + argSize = argSize || 4; + var currArg = getNextArg('i' + (argSize * 8)); #if PRECISE_I64_MATH - var origArg = currArg; + var origArg = currArg; #endif - var argText; + var argText; #if USE_TYPED_ARRAYS == 2 - // Flatten i64-1 [low, high] into a (slightly rounded) double - if (argSize == 8) { - currArg = Runtime.makeBigInt(currArg[0], currArg[1], next == {{{ charCode('u') }}}); - } + // Flatten i64-1 [low, high] into a (slightly rounded) double + if (argSize == 8) { + currArg = Runtime.makeBigInt(currArg[0], currArg[1], next == {{{ charCode('u') }}}); + } #endif - // Truncate to requested size. - if (argSize <= 4) { - var limit = Math.pow(256, argSize) - 1; - currArg = (signed ? reSign : unSign)(currArg & limit, argSize * 8); - } - // Format the number. - var currAbsArg = Math.abs(currArg); - var prefix = ''; - if (next == {{{ charCode('d') }}} || next == {{{ charCode('i') }}}) { + // Truncate to requested size. + if (argSize <= 4) { + var limit = Math.pow(256, argSize) - 1; + currArg = (signed ? reSign : unSign)(currArg & limit, argSize * 8); + } + // Format the number. + var currAbsArg = Math.abs(currArg); + var prefix = ''; + if (next == {{{ charCode('d') }}} || next == {{{ charCode('i') }}}) { #if PRECISE_I64_MATH - if (argSize == 8 && i64Math) argText = i64Math.stringify(origArg[0], origArg[1], null); else + if (argSize == 8 && i64Math) argText = i64Math.stringify(origArg[0], origArg[1], null); else #endif - argText = reSign(currArg, 8 * argSize, 1).toString(10); - } else if (next == {{{ charCode('u') }}}) { + argText = reSign(currArg, 8 * argSize, 1).toString(10); + } else if (next == {{{ charCode('u') }}}) { #if PRECISE_I64_MATH - if (argSize == 8 && i64Math) argText = i64Math.stringify(origArg[0], origArg[1], true); else + if (argSize == 8 && i64Math) argText = i64Math.stringify(origArg[0], origArg[1], true); else #endif - argText = unSign(currArg, 8 * argSize, 1).toString(10); - currArg = Math.abs(currArg); - } else if (next == {{{ charCode('o') }}}) { - argText = (flagAlternative ? '0' : '') + currAbsArg.toString(8); - } else if (next == {{{ charCode('x') }}} || next == {{{ charCode('X') }}}) { - prefix = flagAlternative ? '0x' : ''; + argText = unSign(currArg, 8 * argSize, 1).toString(10); + currArg = Math.abs(currArg); + } else if (next == {{{ charCode('o') }}}) { + argText = (flagAlternative ? '0' : '') + currAbsArg.toString(8); + } else if (next == {{{ charCode('x') }}} || next == {{{ charCode('X') }}}) { + prefix = flagAlternative ? '0x' : ''; #if PRECISE_I64_MATH - if (argSize == 8 && i64Math) argText = (origArg[1]>>>0).toString(16) + (origArg[0]>>>0).toString(16); else + if (argSize == 8 && i64Math) { + if (origArg[1]) { + argText = (origArg[1]>>>0).toString(16); + var lower = (origArg[0]>>>0).toString(16); + while (lower.length < 8) lower = '0' + lower; + argText += lower; + } else { + argText = (origArg[0]>>>0).toString(16); + } + } else #endif - if (currArg < 0) { - // Represent negative numbers in hex as 2's complement. - currArg = -currArg; - argText = (currAbsArg - 1).toString(16); - var buffer = []; - for (var i = 0; i < argText.length; i++) { - buffer.push((0xF - parseInt(argText[i], 16)).toString(16)); + if (currArg < 0) { + // Represent negative numbers in hex as 2's complement. + currArg = -currArg; + argText = (currAbsArg - 1).toString(16); + var buffer = []; + for (var i = 0; i < argText.length; i++) { + buffer.push((0xF - parseInt(argText[i], 16)).toString(16)); + } + argText = buffer.join(''); + while (argText.length < argSize * 2) argText = 'f' + argText; + } else { + argText = currAbsArg.toString(16); + } + if (next == {{{ charCode('X') }}}) { + prefix = prefix.toUpperCase(); + argText = argText.toUpperCase(); + } + } else if (next == {{{ charCode('p') }}}) { + if (currAbsArg === 0) { + argText = '(nil)'; + } else { + prefix = '0x'; + argText = currAbsArg.toString(16); } - argText = buffer.join(''); - while (argText.length < argSize * 2) argText = 'f' + argText; - } else { - argText = currAbsArg.toString(16); - } - if (next == {{{ charCode('X') }}}) { - prefix = prefix.toUpperCase(); - argText = argText.toUpperCase(); - } - } else if (next == {{{ charCode('p') }}}) { - if (currAbsArg === 0) { - argText = '(nil)'; - } else { - prefix = '0x'; - argText = currAbsArg.toString(16); } - } - if (precisionSet) { - while (argText.length < precision) { - argText = '0' + argText; + if (precisionSet) { + while (argText.length < precision) { + argText = '0' + argText; + } } - } - // Add sign if needed - if (flagAlwaysSigned) { - if (currArg < 0) { - prefix = '-' + prefix; - } else { - prefix = '+' + prefix; + // Add sign if needed + if (flagAlwaysSigned) { + if (currArg < 0) { + prefix = '-' + prefix; + } else { + prefix = '+' + prefix; + } } - } - // Add padding. - while (prefix.length + argText.length < width) { - if (flagLeftAlign) { - argText += ' '; - } else { - if (flagZeroPad) { - argText = '0' + argText; + // Add padding. + while (prefix.length + argText.length < width) { + if (flagLeftAlign) { + argText += ' '; } else { - prefix = ' ' + prefix; + if (flagZeroPad) { + argText = '0' + argText; + } else { + prefix = ' ' + prefix; + } } } + + // Insert the result into the buffer. + argText = prefix + argText; + argText.split('').forEach(function(chr) { + ret.push(chr.charCodeAt(0)); + }); + break; } + case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': { + // Float. + var currArg = getNextArg('double'); + var argText; + if (isNaN(currArg)) { + argText = 'nan'; + flagZeroPad = false; + } else if (!isFinite(currArg)) { + argText = (currArg < 0 ? '-' : '') + 'inf'; + flagZeroPad = false; + } else { + var isGeneral = false; + var effectivePrecision = Math.min(precision, 20); + + // Convert g/G to f/F or e/E, as per: + // http://pubs.opengroup.org/onlinepubs/9699919799/functions/printf.html + if (next == {{{ charCode('g') }}} || next == {{{ charCode('G') }}}) { + isGeneral = true; + precision = precision || 1; + var exponent = parseInt(currArg.toExponential(effectivePrecision).split('e')[1], 10); + if (precision > exponent && exponent >= -4) { + next = ((next == {{{ charCode('g') }}}) ? 'f' : 'F').charCodeAt(0); + precision -= exponent + 1; + } else { + next = ((next == {{{ charCode('g') }}}) ? 'e' : 'E').charCodeAt(0); + precision--; + } + effectivePrecision = Math.min(precision, 20); + } - // Insert the result into the buffer. - argText = prefix + argText; - argText.split('').forEach(function(chr) { - ret.push(chr.charCodeAt(0)); - }); - } else if (['f', 'F', 'e', 'E', 'g', 'G'].indexOf(String.fromCharCode(next)) != -1) { - // Float. - var currArg = getNextArg('double'); - var argText; - - if (isNaN(currArg)) { - argText = 'nan'; - flagZeroPad = false; - } else if (!isFinite(currArg)) { - argText = (currArg < 0 ? '-' : '') + 'inf'; - flagZeroPad = false; - } else { - var isGeneral = false; - var effectivePrecision = Math.min(precision, 20); - - // Convert g/G to f/F or e/E, as per: - // http://pubs.opengroup.org/onlinepubs/9699919799/functions/printf.html - if (next == {{{ charCode('g') }}} || next == {{{ charCode('G') }}}) { - isGeneral = true; - precision = precision || 1; - var exponent = parseInt(currArg.toExponential(effectivePrecision).split('e')[1], 10); - if (precision > exponent && exponent >= -4) { - next = ((next == {{{ charCode('g') }}}) ? 'f' : 'F').charCodeAt(0); - precision -= exponent + 1; + if (next == {{{ charCode('e') }}} || next == {{{ charCode('E') }}}) { + argText = currArg.toExponential(effectivePrecision); + // Make sure the exponent has at least 2 digits. + if (/[eE][-+]\d$/.test(argText)) { + argText = argText.slice(0, -1) + '0' + argText.slice(-1); + } + } else if (next == {{{ charCode('f') }}} || next == {{{ charCode('F') }}}) { + argText = currArg.toFixed(effectivePrecision); + if (currArg === 0 && __reallyNegative(currArg)) { + argText = '-' + argText; + } + } + + var parts = argText.split('e'); + if (isGeneral && !flagAlternative) { + // Discard trailing zeros and periods. + while (parts[0].length > 1 && parts[0].indexOf('.') != -1 && + (parts[0].slice(-1) == '0' || parts[0].slice(-1) == '.')) { + parts[0] = parts[0].slice(0, -1); + } } else { - next = ((next == {{{ charCode('g') }}}) ? 'e' : 'E').charCodeAt(0); - precision--; + // Make sure we have a period in alternative mode. + if (flagAlternative && argText.indexOf('.') == -1) parts[0] += '.'; + // Zero pad until required precision. + while (precision > effectivePrecision++) parts[0] += '0'; } - effectivePrecision = Math.min(precision, 20); - } + argText = parts[0] + (parts.length > 1 ? 'e' + parts[1] : ''); - if (next == {{{ charCode('e') }}} || next == {{{ charCode('E') }}}) { - argText = currArg.toExponential(effectivePrecision); - // Make sure the exponent has at least 2 digits. - if (/[eE][-+]\d$/.test(argText)) { - argText = argText.slice(0, -1) + '0' + argText.slice(-1); + // Capitalize 'E' if needed. + if (next == {{{ charCode('E') }}}) argText = argText.toUpperCase(); + + // Add sign. + if (flagAlwaysSigned && currArg >= 0) { + argText = '+' + argText; } - } else if (next == {{{ charCode('f') }}} || next == {{{ charCode('F') }}}) { - argText = currArg.toFixed(effectivePrecision); } - var parts = argText.split('e'); - if (isGeneral && !flagAlternative) { - // Discard trailing zeros and periods. - while (parts[0].length > 1 && parts[0].indexOf('.') != -1 && - (parts[0].slice(-1) == '0' || parts[0].slice(-1) == '.')) { - parts[0] = parts[0].slice(0, -1); + // Add padding. + while (argText.length < width) { + if (flagLeftAlign) { + argText += ' '; + } else { + if (flagZeroPad && (argText[0] == '-' || argText[0] == '+')) { + argText = argText[0] + '0' + argText.slice(1); + } else { + argText = (flagZeroPad ? '0' : ' ') + argText; + } } - } else { - // Make sure we have a period in alternative mode. - if (flagAlternative && argText.indexOf('.') == -1) parts[0] += '.'; - // Zero pad until required precision. - while (precision > effectivePrecision++) parts[0] += '0'; } - argText = parts[0] + (parts.length > 1 ? 'e' + parts[1] : ''); - // Capitalize 'E' if needed. - if (next == {{{ charCode('E') }}}) argText = argText.toUpperCase(); + // Adjust case. + if (next < {{{ charCode('a') }}}) argText = argText.toUpperCase(); - // Add sign. - if (flagAlwaysSigned && currArg >= 0) { - argText = '+' + argText; - } + // Insert the result into the buffer. + argText.split('').forEach(function(chr) { + ret.push(chr.charCodeAt(0)); + }); + break; } - - // Add padding. - while (argText.length < width) { + case 's': { + // String. + var arg = getNextArg('i8*') || nullString; + var argLength = _strlen(arg); + if (precisionSet) argLength = Math.min(argLength, precision); + if (!flagLeftAlign) { + while (argLength < width--) { + ret.push({{{ charCode(' ') }}}); + } + } + for (var i = 0; i < argLength; i++) { + ret.push({{{ makeGetValue('arg++', 0, 'i8', null, true) }}}); + } if (flagLeftAlign) { - argText += ' '; - } else { - if (flagZeroPad && (argText[0] == '-' || argText[0] == '+')) { - argText = argText[0] + '0' + argText.slice(1); - } else { - argText = (flagZeroPad ? '0' : ' ') + argText; + while (argLength < width--) { + ret.push({{{ charCode(' ') }}}); } } + break; } - - // Adjust case. - if (next < {{{ charCode('a') }}}) argText = argText.toUpperCase(); - - // Insert the result into the buffer. - argText.split('').forEach(function(chr) { - ret.push(chr.charCodeAt(0)); - }); - } else if (next == {{{ charCode('s') }}}) { - // String. - var arg = getNextArg('i8*') || nullString; - var argLength = _strlen(arg); - if (precisionSet) argLength = Math.min(argLength, precision); - if (!flagLeftAlign) { - while (argLength < width--) { + case 'c': { + // Character. + if (flagLeftAlign) ret.push(getNextArg('i8')); + while (--width > 0) { ret.push({{{ charCode(' ') }}}); } + if (!flagLeftAlign) ret.push(getNextArg('i8')); + break; } - for (var i = 0; i < argLength; i++) { - ret.push({{{ makeGetValue('arg++', 0, 'i8', null, true) }}}); - } - if (flagLeftAlign) { - while (argLength < width--) { - ret.push({{{ charCode(' ') }}}); - } + case 'n': { + // Write the length written so far to the next parameter. + var ptr = getNextArg('i32*'); + {{{ makeSetValue('ptr', '0', 'ret.length', 'i32') }}} + break; } - } else if (next == {{{ charCode('c') }}}) { - // Character. - if (flagLeftAlign) ret.push(getNextArg('i8')); - while (--width > 0) { - ret.push({{{ charCode(' ') }}}); + case '%': { + // Literal percent sign. + ret.push(curr); + break; } - if (!flagLeftAlign) ret.push(getNextArg('i8')); - } else if (next == {{{ charCode('n') }}}) { - // Write the length written so far to the next parameter. - var ptr = getNextArg('i32*'); - {{{ makeSetValue('ptr', '0', 'ret.length', 'i32') }}} - } else if (next == {{{ charCode('%') }}}) { - // Literal percent sign. - ret.push(curr); - } else { - // Unknown specifiers remain untouched. - for (var i = startTextIndex; i < textIndex + 2; i++) { - ret.push({{{ makeGetValue(0, 'i', 'i8') }}}); + default: { + // Unknown specifiers remain untouched. + for (var i = startTextIndex; i < textIndex + 2; i++) { + ret.push({{{ makeGetValue(0, 'i', 'i8') }}}); + } } } textIndex += 2; @@ -3147,7 +3172,7 @@ LibraryManager.library = { for (var i = 0; i < n - 1 && byte_ != {{{ charCode('\n') }}}; i++) { byte_ = _fgetc(stream); if (byte_ == -1) { - if (streamObj.error) return 0; + if (streamObj.error || (streamObj.eof && i == 0)) return 0; else if (streamObj.eof) break; } {{{ makeSetValue('s', 'i', 'byte_', 'i8') }}} @@ -4927,7 +4952,7 @@ LibraryManager.library = { var ret = 0; while (x) { if (x&1) ret++; - x >>= 1; + x >>>= 1; } return ret; }, @@ -5455,9 +5480,14 @@ LibraryManager.library = { return isNaN(x); }, __isnan: 'isnan', + + _reallyNegative: function(x) { + return x < 0 || (x === 0 && (1/x) === -Infinity); + }, + + copysign__deps: ['_reallyNegative'], copysign: function(a, b) { - if (a < 0 === b < 0) return a; - return -a; + return __reallyNegative(a) === __reallyNegative(b) ? a : -a; }, copysignf: 'copysign', __signbit__deps: ['copysign'], diff --git a/src/library_browser.js b/src/library_browser.js index bdd94bac..e61f84b5 100644 --- a/src/library_browser.js +++ b/src/library_browser.js @@ -45,9 +45,9 @@ mergeInto(LibraryManager.library, { moduleContextCreatedCallbacks: [], workers: [], - ensureObjects: function() { - if (Browser.ensured) return; - Browser.ensured = true; + init: function() { + if (Browser.initted) return; + Browser.initted = true; try { new Blob(); Browser.hasBlobConstructor = true; @@ -193,6 +193,36 @@ mergeInto(LibraryManager.library, { } }; Module['preloadPlugins'].push(audioPlugin); + + // Canvas event setup + + var canvas = Module['canvas']; + canvas.requestPointerLock = canvas['requestPointerLock'] || + canvas['mozRequestPointerLock'] || + canvas['webkitRequestPointerLock']; + canvas.exitPointerLock = document['exitPointerLock'] || + document['mozExitPointerLock'] || + document['webkitExitPointerLock']; + canvas.exitPointerLock = canvas.exitPointerLock.bind(document); + + function pointerLockChange() { + Browser.pointerLock = document['pointerLockElement'] === canvas || + document['mozPointerLockElement'] === canvas || + document['webkitPointerLockElement'] === canvas; + } + + document.addEventListener('pointerlockchange', pointerLockChange, false); + document.addEventListener('mozpointerlockchange', pointerLockChange, false); + document.addEventListener('webkitpointerlockchange', pointerLockChange, false); + + if (Module['elementPointerLock']) { + canvas.addEventListener("click", function(ev) { + if (!Browser.pointerLock && canvas.requestPointerLock) { + canvas.requestPointerLock(); + ev.preventDefault(); + } + }, false); + } }, createContext: function(canvas, useWebGL, setInModule) { @@ -271,6 +301,7 @@ mergeInto(LibraryManager.library, { Module.ctx = ctx; Module.useWebGL = useWebGL; Browser.moduleContextCreatedCallbacks.forEach(function(callback) { callback() }); + Browser.init(); } return ctx; }, @@ -292,13 +323,6 @@ mergeInto(LibraryManager.library, { if ((document['webkitFullScreenElement'] || document['webkitFullscreenElement'] || document['mozFullScreenElement'] || document['mozFullscreenElement'] || document['fullScreenElement'] || document['fullscreenElement']) === canvas) { - canvas.requestPointerLock = canvas['requestPointerLock'] || - canvas['mozRequestPointerLock'] || - canvas['webkitRequestPointerLock']; - canvas.exitPointerLock = document['exitPointerLock'] || - document['mozExitPointerLock'] || - document['webkitExitPointerLock']; - canvas.exitPointerLock = canvas.exitPointerLock.bind(document); canvas.cancelFullScreen = document['cancelFullScreen'] || document['mozCancelFullScreen'] || document['webkitCancelFullScreen']; @@ -312,21 +336,11 @@ mergeInto(LibraryManager.library, { if (Module['onFullScreen']) Module['onFullScreen'](Browser.isFullScreen); } - function pointerLockChange() { - Browser.pointerLock = document['pointerLockElement'] === canvas || - document['mozPointerLockElement'] === canvas || - document['webkitPointerLockElement'] === canvas; - } - if (!this.fullScreenHandlersInstalled) { this.fullScreenHandlersInstalled = true; document.addEventListener('fullscreenchange', fullScreenChange, false); document.addEventListener('mozfullscreenchange', fullScreenChange, false); document.addEventListener('webkitfullscreenchange', fullScreenChange, false); - - document.addEventListener('pointerlockchange', pointerLockChange, false); - document.addEventListener('mozpointerlockchange', pointerLockChange, false); - document.addEventListener('webkitpointerlockchange', pointerLockChange, false); } canvas.requestFullScreen = canvas['requestFullScreen'] || diff --git a/src/library_gl.js b/src/library_gl.js index 9e12e4ee..297a36cf 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -58,7 +58,12 @@ var LibraryGL = { return ret; }, - // Temporary buffers + // Mini temp buffer + MINI_TEMP_BUFFER_SIZE: 16, + miniTempBuffer: null, + miniTempBufferViews: [0], // index i has the view of size i+1 + + // Large temporary buffers MAX_TEMP_BUFFER_SIZE: {{{ GL_MAX_TEMP_BUFFER_SIZE }}}, tempBufferIndexLookup: null, tempVertexBuffers: null, @@ -311,6 +316,11 @@ var LibraryGL = { if (!Module.useWebGL) return; // an app might link both gl and 2d backends + GL.miniTempBuffer = new Float32Array(GL.MINI_TEMP_BUFFER_SIZE); + for (var i = 0; i < GL.MINI_TEMP_BUFFER_SIZE; i++) { + GL.miniTempBufferViews[i] = GL.miniTempBuffer.subarray(0, i+1); + } + GL.maxVertexAttribs = Module.ctx.getParameter(Module.ctx.MAX_VERTEX_ATTRIBS); #if FULL_ES2 for (var i = 0; i < GL.maxVertexAttribs; i++) { @@ -832,53 +842,108 @@ var LibraryGL = { glUniform1fv__sig: 'viii', glUniform1fv: function(location, count, value) { location = GL.uniforms[location]; - value = {{{ makeHEAPView('F32', 'value', 'value+count*4') }}}; - Module.ctx.uniform1fv(location, value); + var view; + if (count == 1) { + // avoid allocation for the common case of uploading one uniform + view = GL.miniTempBufferViews[0]; + view[0] = {{{ makeGetValue('value', '0', 'float') }}}; + } else { + view = {{{ makeHEAPView('F32', 'value', 'value+count*4') }}}; + } + Module.ctx.uniform1fv(location, view); }, glUniform2fv__sig: 'viii', glUniform2fv: function(location, count, value) { location = GL.uniforms[location]; - count *= 2; - value = {{{ makeHEAPView('F32', 'value', 'value+count*4') }}}; - Module.ctx.uniform2fv(location, value); + var view; + if (count == 1) { + // avoid allocation for the common case of uploading one uniform + view = GL.miniTempBufferViews[1]; + view[0] = {{{ makeGetValue('value', '0', 'float') }}}; + view[1] = {{{ makeGetValue('value', '4', 'float') }}}; + } else { + view = {{{ makeHEAPView('F32', 'value', 'value+count*8') }}}; + } + Module.ctx.uniform2fv(location, view); }, glUniform3fv__sig: 'viii', glUniform3fv: function(location, count, value) { location = GL.uniforms[location]; - count *= 3; - value = {{{ makeHEAPView('F32', 'value', 'value+count*4') }}}; - Module.ctx.uniform3fv(location, value); + var view; + if (count == 1) { + // avoid allocation for the common case of uploading one uniform + view = GL.miniTempBufferViews[2]; + view[0] = {{{ makeGetValue('value', '0', 'float') }}}; + view[1] = {{{ makeGetValue('value', '4', 'float') }}}; + view[2] = {{{ makeGetValue('value', '8', 'float') }}}; + } else { + view = {{{ makeHEAPView('F32', 'value', 'value+count*12') }}}; + } + Module.ctx.uniform3fv(location, view); }, glUniform4fv__sig: 'viii', glUniform4fv: function(location, count, value) { location = GL.uniforms[location]; - count *= 4; - value = {{{ makeHEAPView('F32', 'value', 'value+count*4') }}}; - Module.ctx.uniform4fv(location, value); + var view; + if (count == 1) { + // avoid allocation for the common case of uploading one uniform + view = GL.miniTempBufferViews[3]; + view[0] = {{{ makeGetValue('value', '0', 'float') }}}; |