diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/jsifier.js | 5 | ||||
-rw-r--r-- | src/library.js | 6 | ||||
-rw-r--r-- | src/library_gl.js | 107 | ||||
-rw-r--r-- | src/library_sdl.js | 27 | ||||
-rw-r--r-- | src/preamble.js | 19 | ||||
-rw-r--r-- | src/settings.js | 21 |
6 files changed, 139 insertions, 46 deletions
diff --git a/src/jsifier.js b/src/jsifier.js index 4263618a..bc89b0c4 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -513,7 +513,9 @@ function JSify(data, functionsOnly, givenFunctions) { 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 + 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); } } @@ -722,6 +724,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..51921541 100644 --- a/src/library.js +++ b/src/library.js @@ -2638,7 +2638,7 @@ 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. @@ -2821,7 +2821,9 @@ LibraryManager.library = { } 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) { + argText = (origArg[1] ? (origArg[1]>>>0).toString(16) : '') + (origArg[0]>>>0).toString(16); + } else #endif if (currArg < 0) { // Represent negative numbers in hex as 2's complement. diff --git a/src/library_gl.js b/src/library_gl.js index 9e12e4ee..031f4560 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') }}}; + view[1] = {{{ makeGetValue('value', '4', 'float') }}}; + view[2] = {{{ makeGetValue('value', '8', 'float') }}}; + view[3] = {{{ makeGetValue('value', '12', 'float') }}}; + } else { + view = {{{ makeHEAPView('F32', 'value', 'value+count*16') }}}; + } + Module.ctx.uniform4fv(location, view); }, glUniformMatrix2fv: function(location, count, transpose, value) { location = GL.uniforms[location]; - count *= 4; - value = {{{ makeHEAPView('F32', 'value', 'value+count*4') }}}; - Module.ctx.uniformMatrix2fv(location, transpose, value); + var view; + if (count == 1) { + // avoid allocation for the common case of uploading one uniform matrix + view = GL.miniTempBufferViews[3]; + for (var i = 0; i < 4; i++) { + view[i] = {{{ makeGetValue('value', 'i*4', 'float') }}}; + } + } else { + view = {{{ makeHEAPView('F32', 'value', 'value+count*16') }}}; + } + Module.ctx.uniformMatrix2fv(location, transpose, view); }, glUniformMatrix3fv: function(location, count, transpose, value) { location = GL.uniforms[location]; - count *= 9; - value = {{{ makeHEAPView('F32', 'value', 'value+count*4') }}}; - Module.ctx.uniformMatrix3fv(location, transpose, value); + var view; + if (count == 1) { + // avoid allocation for the common case of uploading one uniform matrix + view = GL.miniTempBufferViews[8]; + for (var i = 0; i < 9; i++) { + view[i] = {{{ makeGetValue('value', 'i*4', 'float') }}}; + } + } else { + view = {{{ makeHEAPView('F32', 'value', 'value+count*36') }}}; + } + Module.ctx.uniformMatrix3fv(location, transpose, view); }, glUniformMatrix4fv: function(location, count, transpose, value) { location = GL.uniforms[location]; - count *= 16; - value = {{{ makeHEAPView('F32', 'value', 'value+count*4') }}}; - Module.ctx.uniformMatrix4fv(location, transpose, value); + var view; + if (count == 1) { + // avoid allocation for the common case of uploading one uniform matrix + view = GL.miniTempBufferViews[15]; + for (var i = 0; i < 16; i++) { + view[i] = {{{ makeGetValue('value', 'i*4', 'float') }}}; + } + } else { + view = {{{ makeHEAPView('F32', 'value', 'value+count*64') }}}; + } + Module.ctx.uniformMatrix4fv(location, transpose, view); }, glBindBuffer__sig: 'vii', diff --git a/src/library_sdl.js b/src/library_sdl.js index 9fc979d2..77305609 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -443,6 +443,23 @@ var LibrarySDL = { return false; }, + offsetsTemp: { left: 0, top: 0 }, // temporary object to avoid generating garbage in offsets(). assumes the object is not captured + + offsets: function(element) { + var left = 0; + var top = 0; + + do { + left += element.offsetLeft; + top += element.offsetTop; + } while (element = element.offsetParent) + + var ret = SDL.offsetsTemp; + ret.left = left; + ret.top = top; + return ret; + }, + makeCEvent: function(event, ptr) { if (typeof event === 'number') { // This is a pointer to a native C event that was SDL_PushEvent'ed @@ -524,8 +541,9 @@ var LibrarySDL = { } else { // Otherwise, calculate the movement based on the changes // in the coordinates. - var x = event.pageX - Module["canvas"].offsetLeft; - var y = event.pageY - Module["canvas"].offsetTop; + var offsets = SDL.offsets(Module["canvas"]); + var x = event.pageX - offsets.left; + var y = event.pageY - offsets.top; var movementX = x - SDL.mouseX; var movementY = y - SDL.mouseY; } @@ -912,10 +930,11 @@ var LibrarySDL = { SDL_WarpMouse: function(x, y) { return; // TODO: implement this in a non-buggy way. Need to keep relative mouse movements correct after calling this + var offsets = SDL.offsets(Module["canvas"]); SDL.events.push({ type: 'mousemove', - pageX: x + Module['canvas'].offsetLeft, - pageY: y + Module['canvas'].offsetTop + pageX: x + offsets.left, + pageY: y + offsets.top }); }, diff --git a/src/preamble.js b/src/preamble.js index 7538b19c..a1755798 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -503,6 +503,7 @@ function allocate(slab, types, allocator, ptr) { Module['allocate'] = allocate; function Pointer_stringify(ptr, /* optional */ length) { +#if UTF_STRING_SUPPORT var utf8 = new Runtime.UTF8Processor(); var nullTerminated = typeof(length) == "undefined"; var ret = ""; @@ -519,18 +520,16 @@ function Pointer_stringify(ptr, /* optional */ length) { if (!nullTerminated && i == length) break; } return ret; +#else +#if USE_TYPED_ARRAYS == 2 + return String.fromCharCode.apply(String, HEAPU8.subarray(ptr, ptr + (length || _strlen(ptr)))); +#else + throw 'unsupported combination'; +#endif +#endif } Module['Pointer_stringify'] = Pointer_stringify; -function Array_stringify(array) { - var ret = ""; - for (var i = 0; i < array.length; i++) { - ret += String.fromCharCode(array[i]); - } - return ret; -} -Module['Array_stringify'] = Array_stringify; - // Memory management var PAGE_SIZE = 4096; @@ -557,7 +556,7 @@ function enlargeMemory() { #if ASM_JS == 0 abort('Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value, (2) compile with ALLOW_MEMORY_GROWTH which adjusts the size at runtime but prevents some optimizations, or (3) set Module.TOTAL_MEMORY before the program runs.'); #else - abort('Cannot enlarge memory arrays in asm.js. Compile with -s TOTAL_MEMORY=X with X higher than the current value.'); + abort('Cannot enlarge memory arrays in asm.js. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value, or (2) set Module.TOTAL_MEMORY before the program runs.'); #endif #else // TOTAL_MEMORY is the current size of the actual array, and STATICTOP is the new top. diff --git a/src/settings.js b/src/settings.js index 101c403c..37c594ac 100644 --- a/src/settings.js +++ b/src/settings.js @@ -171,6 +171,8 @@ var GL_UNSAFE_OPTS = 1; // Enables some potentially-unsafe optimizations in GL e var FULL_ES2 = 0; // Forces support for all GLES2 features, not just the WebGL-friendly subset. var FORCE_GL_EMULATION = 0; // Forces inclusion of full GL emulation code. +var UTF_STRING_SUPPORT = 1; // Perform utf-8 conversion between C and JS strings (adds overhead in such conversions) + var DISABLE_EXCEPTION_CATCHING = 0; // Disables generating code to actually catch exceptions. If the code you // are compiling does not actually rely on catching exceptions (but the // compiler generates code for it, maybe because of stdlibc++ stuff), @@ -224,19 +226,22 @@ var NAMED_GLOBALS = 0; // If 1, we use global variables for globals. Otherwise // they are referred to by a base plus an offset (called an indexed global), // saving global variables but adding runtime overhead. -var EXPORT_ALL = 0; // If true, we export all the symbols var EXPORTED_FUNCTIONS = ['_main']; // Functions that are explicitly exported. These functions are kept alive // through LLVM dead code elimination, and also made accessible outside of // the generated code even after running closure compiler (on "Module"). // Note the necessary prefix of "_". +var EXPORT_ALL = 0; // If true, we export all the symbols +var EXPORT_BINDINGS = 0; // Export all bindings generator functions (prefixed with emscripten_bind_). This + // is necessary to use the bindings generator with asm.js -var DEFAULT_LIBRARY_FUNCS_TO_INCLUDE = ['memcpy', 'memset', 'malloc', 'free', '$Browser']; // JS library functions (C functions implemented in JS) - // that we include by default. If you want to make sure - // something is included by the JS compiler, add it here. - // For example, if you do not use some emscripten_* - // C API call from C, but you want to call it from JS, - // add it here (and in EXPORTED FUNCTIONS with prefix - // "_", for closure). +// JS library functions (C functions implemented in JS) +// that we include by default. If you want to make sure +// something is included by the JS compiler, add it here. +// For example, if you do not use some emscripten_* +// C API call from C, but you want to call it from JS, +// add it here (and in EXPORTED FUNCTIONS with prefix +// "_", for closure). +var DEFAULT_LIBRARY_FUNCS_TO_INCLUDE = ['memcpy', 'memset', 'malloc', 'free', 'strlen', '$Browser']; var LIBRARY_DEPS_TO_AUTOEXPORT = ['memcpy']; // This list is also used to determine // auto-exporting of library dependencies (i.e., functions that |