aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2013-03-20 13:44:50 -0700
committerAlon Zakai <alonzakai@gmail.com>2013-03-20 13:44:50 -0700
commit669c786e3554b280e31dcb7bd92931482547dae0 (patch)
tree110d48a9e6bf29ceed41ac6282dc37d2f0f3f433
parentb22f6fbbbebb5df55ceb8fdc9f7c4d111c902c5e (diff)
parent421e70ecf266d6619415b53c1bc03d4a127a585d (diff)
Merge branch 'incoming'
-rw-r--r--AUTHORS1
-rwxr-xr-xemscripten.py4
-rw-r--r--src/jsifier.js11
-rw-r--r--src/library.js402
-rw-r--r--src/library_browser.js54
-rw-r--r--src/library_gl.js109
-rw-r--r--src/library_openal.js154
-rw-r--r--src/library_sdl.js19
-rw-r--r--src/parseTools.js4
-rw-r--r--src/preamble.js48
-rw-r--r--src/settings.js16
-rw-r--r--src/shell.html8
-rw-r--r--system/include/libc/ctype.h44
-rw-r--r--tests/cases/alignedunaligned.ll6
-rw-r--r--tests/cases/phicubed.ll29
-rw-r--r--tests/cases/storestruct.ll5
-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.c241
-rw-r--r--tests/gl_ps_strides.pngbin0 -> 98713 bytes
-rwxr-xr-xtests/runner.py181
-rwxr-xr-xtools/bindings_generator.py5
-rw-r--r--tools/js-optimizer.js11
-rw-r--r--tools/shared.py2
24 files changed, 977 insertions, 377 deletions
diff --git a/AUTHORS b/AUTHORS
index 0eb8f7df..0fa41dd2 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -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') }}};