diff options
-rw-r--r-- | AUTHORS | 3 | ||||
-rw-r--r-- | docs/paper.pdf | bin | 220318 -> 220476 bytes | |||
-rw-r--r-- | docs/paper.tex | 10 | ||||
-rwxr-xr-x | emcc | 4 | ||||
-rw-r--r-- | src/analyzer.js | 78 | ||||
-rw-r--r-- | src/compiler.js | 2 | ||||
-rw-r--r-- | src/library.js | 133 | ||||
-rw-r--r-- | src/library_browser.js | 41 | ||||
-rw-r--r-- | src/library_gl.js | 52 | ||||
-rw-r--r-- | src/library_glfw.js | 29 | ||||
-rw-r--r-- | src/library_glut.js | 41 | ||||
-rw-r--r-- | src/library_sdl.js | 106 | ||||
-rw-r--r-- | src/modules.js | 2 | ||||
-rw-r--r-- | src/parseTools.js | 8 | ||||
-rw-r--r-- | src/settings.js | 6 | ||||
-rw-r--r-- | tests/box2d/Benchmark.cpp | 2 | ||||
-rw-r--r-- | tests/cases/trace.ll | 2 | ||||
-rw-r--r-- | tests/nbody-java/nbody_nbody.c | 16 | ||||
-rwxr-xr-x | tests/runner.py | 135 | ||||
-rw-r--r-- | tools/eliminator/asm-eliminator-test-output.js | 243 | ||||
-rw-r--r-- | tools/eliminator/asm-eliminator-test.js | 429 | ||||
-rw-r--r-- | tools/js-optimizer.js | 43 | ||||
-rw-r--r-- | tools/shared.py | 4 |
23 files changed, 1156 insertions, 233 deletions
@@ -72,5 +72,8 @@ a license to everyone to use it as detailed in LICENSE.) * Robert Bragg <robert.bragg@intel.com> (copyright owned by Intel Corporation) * Sylvestre Ledru <sylvestre@debian.org> * Tom Fairfield <fairfield@cs.xu.edu> +* Anthony J. Thibault <ajt@hyperlogic.org> +* John Allwine <jallwine86@gmail.com> +* Martin Gerhardy <martin.gerhardy@gmail.com> diff --git a/docs/paper.pdf b/docs/paper.pdf Binary files differindex 401162ac..fc8ecf7c 100644 --- a/docs/paper.pdf +++ b/docs/paper.pdf diff --git a/docs/paper.tex b/docs/paper.tex index 3b8da618..9e460bac 100644 --- a/docs/paper.tex +++ b/docs/paper.tex @@ -214,7 +214,7 @@ following simple example of a C program: int main() { int sum = 0; - for (int i = 1; i < 100; i++) + for (int i = 1; i <= 100; i++) sum += i; printf("1+...+100=%d\n", sum); return 0; @@ -239,7 +239,7 @@ define i32 @main() { ; <label>:2 %3 = load i32* %i, align 4 - %4 = icmp slt i32 %3, 100 + %4 = icmp sle i32 %3, 100 br i1 %4, label %5, label %12 ; <label>:5 @@ -314,7 +314,7 @@ function _main() { __label__ = 0; break; case 0: var $3 = HEAP[$i]; - var $4 = $3 < 100; + var $4 = $3 <= 100; if ($4) { __label__ = 1; break; } else { __label__ = 2; break; } case 1: @@ -594,7 +594,7 @@ function _main() { $i = 0; $2$2: while(1) { var $3 = $i; - var $4 = $3 < 100; + var $4 = $3 <= 100; if (!($4)) { __label__ = 2; break $2$2; } var $6 = $i; var $7 = $sum; @@ -616,7 +616,7 @@ function K() { var a, b; b = a = 0; a:for(;;) { - if(!(b < 100)) { + if(!(b <= 100)) { break a } a += b; @@ -167,6 +167,7 @@ Options that are modified or new in %s include: -O3 As -O2, plus dangerous optimizations that may break the generated code! This adds + -s FORCE_ALIGNED_MEMORY=1 -s DOUBLE_MODE=0 -s PRECISE_I64_MATH=0 --closure 1 @@ -174,7 +175,8 @@ Options that are modified or new in %s include: This is not recommended at all. A better idea is to try each of these separately on top of - -O2 to see what works. See the wiki for more + -O2 to see what works. See the wiki and + src/settings.js (for the -s options) for more information. -s OPTION=VALUE JavaScript code generation option passed diff --git a/src/analyzer.js b/src/analyzer.js index 3f9025da..a131406c 100644 --- a/src/analyzer.js +++ b/src/analyzer.js @@ -20,6 +20,7 @@ var BRANCH_INVOKE = set('branch', 'invoke'); var LABEL_ENDERS = set('branch', 'return', 'switch'); var SIDE_EFFECT_CAUSERS = set('call', 'invoke', 'atomic'); var UNUNFOLDABLE = set('value', 'structvalue', 'type', 'phiparam'); +var I64_DOUBLE_FLIP = { i64: 'double', double: 'i64' }; // Analyzer @@ -103,61 +104,81 @@ function analyzer(data, sidePass) { } }); - // CastAway - try to remove bitcasts of double to i64, which LLVM sometimes generates unnecessarily + // CastAway - try to remove bitcasts of double<-->i64, which LLVM sometimes generates unnecessarily // (load a double, convert to i64, use as i64). - // We optimize this by checking if the value is later converted to an i64. If so we create a shadow - // variable that is a load of an i64, and use that in those places. (As SSA, this is valid, and + // We optimize this by checking if there are such bitcasts. If so we create a shadow + // variable that is of the other type, and use that in the relevant places. (As SSA, this is valid, and // variable elimination later will remove the double load if it is no longer needed.) // + // Note that aside from being an optimization, this is needed for correctness in some cases: If code + // assumes it can bitcast a double to an i64 and back and forth without loss, that may be violated + // due to NaN canonicalization. substrate.addActor('CastAway', { processItem: function(item) { this.forwardItem(item, 'Legalizer'); if (USE_TYPED_ARRAYS != 2) return; item.functions.forEach(function(func) { - var changed = false; + var has = false; + func.labels.forEach(function(label) { + var lines = label.lines; + for (var i = 0; i < lines.length; i++) { + var line = lines[i]; + if (line.intertype == 'bitcast' && line.type in I64_DOUBLE_FLIP) { + has = true; + } + } + }); + if (!has) return; + // there are i64<-->double bitcasts, create shadows for everything + var shadowed = {}; func.labels.forEach(function(label) { - var doubleVars = {}; var lines = label.lines; var i = 0; while (i < lines.length) { + var lines = label.lines; var line = lines[i]; - if (line.intertype == 'load' && line.type == 'double') { - doubleVars[line.assignTo] = i; - } else if (line.intertype == 'bitcast' && line.type == 'i64' && line.ident in doubleVars) { - // this is a bitcast of a loaded double into an i64. create shadow var - var shadow = line.ident + '$$i64doubleSHADOW'; - var loadI = doubleVars[line.ident]; - var load = lines[loadI]; - if (load.pointer.intertype != 'value') { i++; continue } // TODO - // create shadow - lines.splice(loadI + 1, 0, { // this element will be legalized in the next phase + if (line.intertype == 'load' && line.type in I64_DOUBLE_FLIP) { + if (line.pointer.intertype != 'value') { i++; continue } // TODO + shadowed[line.assignTo] = 1; + var shadow = line.assignTo + '$$SHADOW'; + var flip = I64_DOUBLE_FLIP[line.type]; + lines.splice(i + 1, 0, { // if necessary this element will be legalized in the next phase tokens: null, indent: 2, - lineNum: load.lineNum + 0.5, + lineNum: line.lineNum + 0.5, assignTo: shadow, intertype: 'load', - pointerType: 'i64*', - type: 'i64', - valueType: 'i64', + pointerType: flip + '*', + type: flip, + valueType: flip, pointer: { intertype: 'value', - ident: load.pointer.ident, - type: 'i64*' + ident: line.pointer.ident, + type: flip + '*' }, - align: load.align, - ident: load.ident + align: line.align, + ident: line.ident }); - // use shadow - line.params[0].ident = shadow; - line.params[0].type = 'i64'; - line.type2 = 'i64'; // note: no need to update func.lines, it is generated in a later pass i++; } i++; } }); + // use shadows where possible + func.labels.forEach(function(label) { + var lines = label.lines; + for (var i = 0; i < lines.length; i++) { + var line = lines[i]; + if (line.intertype == 'bitcast' && line.type in I64_DOUBLE_FLIP && line.ident in shadowed) { + var shadow = line.ident + '$$SHADOW'; + line.params[0].ident = shadow; + line.params[0].type = line.type; + line.type2 = line.type; + } + } + }); }); } }); @@ -233,12 +254,15 @@ function analyzer(data, sidePass) { var factor = (next - prev)/(4*toAdd.length+3); for (var k = 0; k < toAdd.length; k++) { toAdd[k].lineNum = prev + ((k+1)*factor); + assert(k == 0 || toAdd[k].lineNum > toAdd[k-1].lineNum); } } function removeAndAdd(lines, i, toAdd) { var item = lines[i]; interpLines(lines, i, toAdd); Array.prototype.splice.apply(lines, [i, 1].concat(toAdd)); + if (i > 0) assert(lines[i].lineNum > lines[i-1].lineNum); + if (i + toAdd.length < lines.length) assert(lines[i + toAdd.length - 1].lineNum < lines[i + toAdd.length].lineNum); return toAdd.length; } function legalizeFunctionParameters(params) { diff --git a/src/compiler.js b/src/compiler.js index 8b9606f1..94e77e26 100644 --- a/src/compiler.js +++ b/src/compiler.js @@ -183,8 +183,8 @@ if (ASM_JS) { assert(!ALLOW_MEMORY_GROWTH, 'Cannot grow asm.js heap'); assert((TOTAL_MEMORY&(TOTAL_MEMORY-1)) == 0, 'asm.js heap must be power of 2'); } -assert(!(!NAMED_GLOBALS && BUILD_AS_SHARED_LIB)); // shared libraries must have named globals assert(!BUILD_AS_SHARED_LIB, 'shared libs are deprecated'); +//assert(!(!NAMED_GLOBALS && BUILD_AS_SHARED_LIB), 'shared libraries must have named globals'); // Output some info and warnings based on settings diff --git a/src/library.js b/src/library.js index cfe83c6e..84071b68 100644 --- a/src/library.js +++ b/src/library.js @@ -296,74 +296,97 @@ LibraryManager.library = { if (typeof XMLHttpRequest !== 'undefined') { if (!ENVIRONMENT_IS_WORKER) throw 'Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc'; // Lazy chunked Uint8Array (implements get and length from Uint8Array). Actual getting is abstracted away for eventual reuse. - var LazyUint8Array = function(chunkSize, length) { - this.length = length; - this.chunkSize = chunkSize; + var LazyUint8Array = function() { + this.lengthKnown = false; this.chunks = []; // Loaded chunks. Index is the chunk number } LazyUint8Array.prototype.get = function(idx) { if (idx > this.length-1 || idx < 0) { return undefined; } - var chunkOffset = idx % chunkSize; - var chunkNum = Math.floor(idx / chunkSize); + var chunkOffset = idx % this.chunkSize; + var chunkNum = Math.floor(idx / this.chunkSize); return this.getter(chunkNum)[chunkOffset]; } LazyUint8Array.prototype.setDataGetter = function(getter) { this.getter = getter; } - - // Find length - var xhr = new XMLHttpRequest(); - xhr.open('HEAD', url, false); - xhr.send(null); - if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status); - var datalength = Number(xhr.getResponseHeader("Content-length")); - var header; - var hasByteServing = (header = xhr.getResponseHeader("Accept-Ranges")) && header === "bytes"; + + LazyUint8Array.prototype.cacheLength = function() { + // Find length + var xhr = new XMLHttpRequest(); + xhr.open('HEAD', url, false); + xhr.send(null); + if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status); + var datalength = Number(xhr.getResponseHeader("Content-length")); + var header; + var hasByteServing = (header = xhr.getResponseHeader("Accept-Ranges")) && header === "bytes"; #if SMALL_XHR_CHUNKS - var chunkSize = 1024; // Chunk size in bytes + var chunkSize = 1024; // Chunk size in bytes #else - var chunkSize = 1024*1024; // Chunk size in bytes + var chunkSize = 1024*1024; // Chunk size in bytes #endif - if (!hasByteServing) chunkSize = datalength; - - // Function to get a range from the remote URL. - var doXHR = (function(from, to) { - if (from > to) throw new Error("invalid range (" + from + ", " + to + ") or no bytes requested!"); - if (to > datalength-1) throw new Error("only " + datalength + " bytes available! programmer error!"); - - // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available. - var xhr = new XMLHttpRequest(); - xhr.open('GET', url, false); - if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to); - - // Some hints to the browser that we want binary data. - if (typeof Uint8Array != 'undefined') xhr.responseType = 'arraybuffer'; - if (xhr.overrideMimeType) { - xhr.overrideMimeType('text/plain; charset=x-user-defined'); - } + if (!hasByteServing) chunkSize = datalength; + + // Function to get a range from the remote URL. + var doXHR = (function(from, to) { + if (from > to) throw new Error("invalid range (" + from + ", " + to + ") or no bytes requested!"); + if (to > datalength-1) throw new Error("only " + datalength + " bytes available! programmer error!"); + + // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available. + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to); + + // Some hints to the browser that we want binary data. + if (typeof Uint8Array != 'undefined') xhr.responseType = 'arraybuffer'; + if (xhr.overrideMimeType) { + xhr.overrideMimeType('text/plain; charset=x-user-defined'); + } + + xhr.send(null); + if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status); + if (xhr.response !== undefined) { + return new Uint8Array(xhr.response || []); + } else { + return intArrayFromString(xhr.responseText || '', true); + } + }); + var lazyArray = this; + lazyArray.setDataGetter(function(chunkNum) { + var start = chunkNum * chunkSize; + var end = (chunkNum+1) * chunkSize - 1; // including this byte + end = Math.min(end, datalength-1); // if datalength-1 is selected, this is the last block + if (typeof(lazyArray.chunks[chunkNum]) === "undefined") { + lazyArray.chunks[chunkNum] = doXHR(start, end); + } + if (typeof(lazyArray.chunks[chunkNum]) === "undefined") throw new Error("doXHR failed!"); + return lazyArray.chunks[chunkNum]; + }); + + this._length = datalength; + this._chunkSize = chunkSize; + this.lengthKnown = true; + } - xhr.send(null); - if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status); - if (xhr.response !== undefined) { - return new Uint8Array(xhr.response || []); - } else { - return intArrayFromString(xhr.responseText || '', true); - } + var lazyArray = new LazyUint8Array(); + Object.defineProperty(lazyArray, "length", { + get: function() { + if(!this.lengthKnown) { + this.cacheLength(); + } + return this._length; + } }); - - var lazyArray = new LazyUint8Array(chunkSize, datalength); - lazyArray.setDataGetter(function(chunkNum) { - var start = chunkNum * lazyArray.chunkSize; - var end = (chunkNum+1) * lazyArray.chunkSize - 1; // including this byte - end = Math.min(end, datalength-1); // if datalength-1 is selected, this is the last block - if (typeof(lazyArray.chunks[chunkNum]) === "undefined") { - lazyArray.chunks[chunkNum] = doXHR(start, end); - } - if (typeof(lazyArray.chunks[chunkNum]) === "undefined") throw new Error("doXHR failed!"); - return lazyArray.chunks[chunkNum]; + Object.defineProperty(lazyArray, "chunkSize", { + get: function() { + if(!this.lengthKnown) { + this.cacheLength(); + } + return this._chunkSize; + } }); + var properties = { isDevice: false, contents: lazyArray }; } else { var properties = { isDevice: false, url: url }; @@ -2465,9 +2488,15 @@ LibraryManager.library = { __scanString.whiteSpace[{{{ charCode(' ') }}}] = 1; __scanString.whiteSpace[{{{ charCode('\t') }}}] = 1; __scanString.whiteSpace[{{{ charCode('\n') }}}] = 1; + __scanString.whiteSpace[{{{ charCode('\v') }}}] = 1; + __scanString.whiteSpace[{{{ charCode('\f') }}}] = 1; + __scanString.whiteSpace[{{{ charCode('\r') }}}] = 1; __scanString.whiteSpace[' '] = 1; __scanString.whiteSpace['\t'] = 1; __scanString.whiteSpace['\n'] = 1; + __scanString.whiteSpace['\v'] = 1; + __scanString.whiteSpace['\f'] = 1; + __scanString.whiteSpace['\r'] = 1; } // Supports %x, %4x, %d.%d, %lld, %s, %f, %lf. // TODO: Support all format specifiers. @@ -2840,7 +2869,7 @@ LibraryManager.library = { } else if (next == {{{ charCode('o') }}}) { argText = (flagAlternative ? '0' : '') + currAbsArg.toString(8); } else if (next == {{{ charCode('x') }}} || next == {{{ charCode('X') }}}) { - prefix = flagAlternative ? '0x' : ''; + prefix = (flagAlternative && currArg != 0) ? '0x' : ''; #if PRECISE_I64_MATH if (argSize == 8 && i64Math) { if (origArg[1]) { diff --git a/src/library_browser.js b/src/library_browser.js index 85eb93f7..97233c36 100644 --- a/src/library_browser.js +++ b/src/library_browser.js @@ -374,6 +374,47 @@ mergeInto(LibraryManager.library, { 0; }, + mouseX: 0, + mouseY: 0, + mouseMovementX: 0, + mouseMovementY: 0, + + calculateMouseEvent: function(event) { // event should be mousemove, mousedown or mouseup + if (Browser.pointerLock) { + // When the pointer is locked, calculate the coordinates + // based on the movement of the mouse. + // Workaround for Firefox bug 764498 + if (event.type != 'mousemove' && + ('mozMovementX' in event)) { + Browser.mouseMovementX = Browser.mouseMovementY = 0; + } else { + Browser.mouseMovementX = Browser.getMovementX(event); + Browser.mouseMovementY = Browser.getMovementY(event); + } + Browser.mouseX = SDL.mouseX + Browser.mouseMovementX; + Browser.mouseY = SDL.mouseY + Browser.mouseMovementY; + } else { + // Otherwise, calculate the movement based on the changes + // in the coordinates. + var rect = Module["canvas"].getBoundingClientRect(); + var x = event.pageX - (window.scrollX + rect.left); + var y = event.pageY - (window.scrollY + rect.top); + + // the canvas might be CSS-scaled compared to its backbuffer; + // SDL-using content will want mouse coordinates in terms + // of backbuffer units. + var cw = Module["canvas"].width; + var ch = Module["canvas"].height; + x = x * (cw / rect.width); + y = y * (ch / rect.height); + + Browser.mouseMovementX = x - Browser.mouseX; + Browser.mouseMovementY = y - Browser.mouseY; + Browser.mouseX = x; + Browser.mouseY = y; + } + }, + xhrLoad: function(url, onload, onerror) { var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); diff --git a/src/library_gl.js b/src/library_gl.js index 813da761..0f6fb670 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -339,6 +339,9 @@ var LibraryGL = { Module.ctx.getExtension('WEBKIT_EXT_texture_filter_anisotropic'); GL.floatExt = Module.ctx.getExtension('OES_texture_float'); + + GL.elementIndexUintExt = Module.ctx.getExtension('OES_element_index_uint'); + GL.standardDerivativesExt = Module.ctx.getExtension('OES_standard_derivatives'); } }, @@ -781,7 +784,7 @@ var LibraryGL = { program = GL.programs[program]; var info = Module.ctx.getActiveUniform(program, index); - var infoname = info.name.slice(0, bufSize - 1); + var infoname = info.name.slice(0, Math.max(0, bufSize - 1)); writeStringToMemory(infoname, name); if (length) { @@ -795,25 +798,25 @@ var LibraryGL = { } }, - glUniform1f__sig: 'vid', + glUniform1f__sig: 'vif', glUniform1f: function(location, v0) { location = GL.uniforms[location]; Module.ctx.uniform1f(location, v0); }, - glUniform2f__sig: 'vidd', + glUniform2f__sig: 'viff', glUniform2f: function(location, v0, v1) { location = GL.uniforms[location]; Module.ctx.uniform2f(location, v0, v1); }, - glUniform3f__sig: 'viddd', + glUniform3f__sig: 'vifff', glUniform3f: function(location, v0, v1, v2) { location = GL.uniforms[location]; Module.ctx.uniform3f(location, v0, v1, v2); }, - glUniform4f__sig: 'vidddd', + glUniform4f__sig: 'viffff', glUniform4f: function(location, v0, v1, v2, v3) { location = GL.uniforms[location]; Module.ctx.uniform4f(location, v0, v1, v2, v3); @@ -1031,7 +1034,7 @@ var LibraryGL = { program = GL.programs[program]; var info = Module.ctx.getActiveAttrib(program, index); - var infoname = info.name.slice(0, bufSize - 1); + var infoname = info.name.slice(0, Math.max(0, bufSize - 1)); writeStringToMemory(infoname, name); if (length) { @@ -1058,12 +1061,6 @@ var LibraryGL = { GL.shaders[shader] = null; }, - glDetachShader__sig: 'vii', - glDetachShader: function(program, shader) { - Module.ctx.detachShader(GL.programs[program], - GL.shaders[shader]); - }, - glGetAttachedShaders__sig: 'viiii', glGetAttachedShaders: function(program, maxCount, count, shaders) { var result = Module.ctx.getAttachedShaders(GL.programs[program]); @@ -1086,7 +1083,7 @@ var LibraryGL = { glGetShaderSource__sig: 'viiii', glGetShaderSource: function(shader, bufSize, length, source) { var result = Module.ctx.getShaderSource(GL.shaders[shader]); - result = result.slice(0, bufSize - 1); + result = result.slice(0, Math.max(0, bufSize - 1)); writeStringToMemory(result, source); if (length) { {{{ makeSetValue('length', '0', 'result.length', 'i32') }}}; @@ -1157,6 +1154,12 @@ var LibraryGL = { GL.shaders[shader]); }, + glDetachShader__sig: 'vii', + glDetachShader: function(program, shader) { + Module.ctx.detachShader(GL.programs[program], + GL.shaders[shader]); + }, + glGetShaderPrecisionFormat: function(shaderType, precisionType, range, precision) { var result = Module.ctx.getShaderPrecisionFormat(shaderType, precisionType); {{{ makeSetValue('range', '0', 'result.rangeMin', 'i32') }}}; @@ -1194,7 +1197,7 @@ var LibraryGL = { Module.ctx.validateProgram(GL.programs[program]); }, - glIsProgram__sig: 'vi', + glIsProgram__sig: 'ii', glIsProgram: function(program) { var program = GL.programs[program]; if (!program) return 0; @@ -1583,6 +1586,18 @@ var LibraryGL = { glAttachShader(program, shader); }; + var glDetachShader = _glDetachShader; + _glDetachShader = function(program, shader) { + var programShader = GL.programShaders[program]; + if (!programShader) { + Module.printErr('WARNING: _glDetachShader received invalid program: ' + program); + return; + } + var index = programShader.indexOf(shader); + programShader.splice(index, 1); + glDetachShader(program, shader); + }; + var glUseProgram = _glUseProgram; _glUseProgram = function(program) { #if GL_DEBUG @@ -1713,6 +1728,7 @@ var LibraryGL = { case 'glCreateProgramObject': case 'glCreateProgram': ret = {{{ Functions.getIndex('_glCreateProgram', true) }}}; break; case 'glAttachObject': case 'glAttachShader': ret = {{{ Functions.getIndex('_glAttachShader', true) }}}; break; case 'glUseProgramObject': case 'glUseProgram': ret = {{{ Functions.getIndex('_glUseProgram', true) }}}; break; + case 'glDetachObject': case 'glDetachShader': ret = {{{ Functions.getIndex('_glDetachShader', true) }}}; break; case 'glDeleteObject': ret = {{{ Functions.getIndex('_glDeleteObject', true) }}}; break; case 'glGetObjectParameteriv': ret = {{{ Functions.getIndex('_glGetObjectParameteriv', true) }}}; break; case 'glGetInfoLog': ret = {{{ Functions.getIndex('_glGetInfoLog', true) }}}; break; @@ -1786,7 +1802,9 @@ var LibraryGL = { case 'glGetBufferParameteriv': ret = {{{ Functions.getIndex('_glGetBufferParameteriv', true) }}}; break; case 'glIsBuffer': ret = {{{ Functions.getIndex('_glIsBuffer', true) }}}; break; case 'glDeleteShader': ret = {{{ Functions.getIndex('_glDeleteShader', true) }}}; break; - case 'glUniformMatrix2fv': ret = {{{ Functions.getIndex('_glUniformMatrix2fv', true) }}}; break; + case 'glUniformMatrix2fv': ret = {{{ Functions.getIndex('_glUniformMatrix2fv', true) }}}; break; + case 'glUniformMatrix3fv': ret = {{{ Functions.getIndex('_glUniformMatrix3fv', true) }}}; break; + case 'glUniformMatrix4fv': ret = {{{ Functions.getIndex('_glUniformMatrix4fv', true) }}}; break; case 'glIsRenderbuffer': ret = {{{ Functions.getIndex('_glIsRenderbuffer', true) }}}; break; case 'glBlendEquation': ret = {{{ Functions.getIndex('_glBlendEquation', true) }}}; break; case 'glBlendFunc': ret = {{{ Functions.getIndex('_glBlendFunc', true) }}}; break; @@ -1900,6 +1918,9 @@ var LibraryGL = { if (type == 0x8B84) { // GL_OBJECT_INFO_LOG_LENGTH_ARB {{{ makeSetValue('result', '0', 'Module.ctx.getShaderInfoLog(GL.shaders[id]).length', 'i32') }}}; return; + } else if (type == 0x8B88) { // GL_OBJECT_SHADER_SOURCE_LENGTH_ARB + {{{ makeSetValue('result', '0', 'Module.ctx.getShaderSource(GL.shaders[id]).length', 'i32') }}}; + return; } _glGetShaderiv(id, type, result); } else { @@ -3107,6 +3128,7 @@ var LibraryGL = { glTexGeni: function() { throw 'glTexGeni: TODO' }, glTexGenfv: function() { throw 'glTexGenfv: TODO' }, glTexEnvi: function() { Runtime.warnOnce('glTexEnvi: TODO') }, + glTexEnvf: function() { Runtime.warnOnce('glTexEnvf: TODO') }, glTexEnvfv: function() { Runtime.warnOnce('glTexEnvfv: TODO') }, glTexImage1D: function() { throw 'glTexImage1D: TODO' }, diff --git a/src/library_glfw.js b/src/library_glfw.js index 8bf3616f..5e76071f 100644 --- a/src/library_glfw.js +++ b/src/library_glfw.js @@ -35,8 +35,6 @@ var LibraryGLFW = { params: null, initTime: null, wheelPos: 0, - lastX: 0, - lastY: 0, buttons: 0, keys: 0, initWindowWidth: 640, @@ -145,28 +143,20 @@ var LibraryGLFW = { GLFW.onKeyChanged(event, 0);//GLFW_RELEASE }, - savePosition: function(event) { - /* TODO maybe loop here ala http://www.quirksmode.org/js/findpos.html */ - GLFW.lastX = event['clientX'] - Module['canvas'].offsetLeft; - GLFW.lastY = event['clientY'] - Module['canvas'].offsetTop; - }, - onMousemove: function(event) { /* Send motion event only if the motion changed, prevents * spamming our app with uncessary callback call. It does happen in * Chrome on Windows. */ - var newX = event['clientX'] - Module['canvas'].offsetLeft; - var newY = event['clientY'] - Module['canvas'].offsetTop; - if (newX == GLFW.lastX && newY == GLFW.lastY) { - return; - } - - GLFW.savePosition(event); + var lastX = Browser.mouseX; + var lastY = Browser.mouseY; + Browser.calculateMouseEvent(event); + var newX = Browser.mouseX; + var newY = Browser.mouseY; if (event.target == Module["canvas"] && GLFW.mousePosFunc) { event.preventDefault(); - Runtime.dynCall('vii', GLFW.mousePosFunc, [GLFW.lastX, GLFW.lastY]); + Runtime.dynCall('vii', GLFW.mousePosFunc, [lastX, lastY]); } }, @@ -175,7 +165,8 @@ var LibraryGLFW = { return; } - GLFW.savePosition(event); + Browser.calculateMouseEvent(event); + if (event.target != Module["canvas"]) { return; } @@ -441,8 +432,8 @@ var LibraryGLFW = { }, glfwGetMousePos: function(xpos, ypos) { - setValue(xpos, GLFW.lastX, 'i32'); - setValue(ypos, GLFW.lastY, 'i32'); + setValue(xpos, Browser.mouseX, 'i32'); + setValue(ypos, Browser.mouseY, 'i32'); }, //I believe it is not possible to move the mouse with javascript diff --git a/src/library_glut.js b/src/library_glut.js index 49380367..35348028 100644 --- a/src/library_glut.js +++ b/src/library_glut.js @@ -12,8 +12,6 @@ var LibraryGLUT = { motionFunc: null, passiveMotionFunc: null, mouseFunc: null, - lastX: 0, - lastY: 0, buttons: 0, modifiers: 0, initWindowWidth: 256, @@ -24,12 +22,6 @@ var LibraryGLUT = { windowWidth: 0, windowHeight: 0, - savePosition: function(event) { - /* TODO maybe loop here ala http://www.quirksmode.org/js/findpos.html */ - GLUT.lastX = event['clientX'] - Module['canvas'].offsetLeft; - GLUT.lastY = event['clientY'] - Module['canvas'].offsetTop; - }, - saveModifiers: function(event) { GLUT.modifiers = 0; if (event['shiftKey']) @@ -45,20 +37,21 @@ var LibraryGLUT = { * spamming our app with uncessary callback call. It does happen in * Chrome on Windows. */ - var newX = event['clientX'] - Module['canvas'].offsetLeft; - var newY = event['clientY'] - Module['canvas'].offsetTop; - if (newX == GLUT.lastX && newY == GLUT.lastY) - return; + var lastX = Browser.mouseX; + var lastY = Browser.mouseY; + Browser.calculateMouseEvent(event); + var newX = Browser.mouseX; + var newY = Browser.mouseY; + if (newX == lastX && newY == lastY) return; - GLUT.savePosition(event); if (GLUT.buttons == 0 && event.target == Module["canvas"] && GLUT.passiveMotionFunc) { event.preventDefault(); GLUT.saveModifiers(event); - Runtime.dynCall('vii', GLUT.passiveMotionFunc, [GLUT.lastX, GLUT.lastY]); + Runtime.dynCall('vii', GLUT.passiveMotionFunc, [lastX, lastY]); } else if (GLUT.buttons != 0 && GLUT.motionFunc) { event.preventDefault(); GLUT.saveModifiers(event); - |