diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/analyzer.js | 78 | ||||
-rw-r--r-- | src/compiler.js | 2 | ||||
-rw-r--r-- | src/jsifier.js | 1 | ||||
-rw-r--r-- | src/library.js | 136 | ||||
-rw-r--r-- | src/library_browser.js | 41 | ||||
-rw-r--r-- | src/library_gl.js | 63 | ||||
-rw-r--r-- | src/library_glfw.js | 29 | ||||
-rw-r--r-- | src/library_glut.js | 41 | ||||
-rw-r--r-- | src/library_sdl.js | 122 | ||||
-rw-r--r-- | src/modules.js | 43 | ||||
-rw-r--r-- | src/parseTools.js | 8 | ||||
-rw-r--r-- | src/settings.js | 10 |
12 files changed, 371 insertions, 203 deletions
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/jsifier.js b/src/jsifier.js index 8270b443..3f52337f 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -1463,6 +1463,7 @@ function JSify(data, functionsOnly, givenFunctions) { if (!byPointerForced && !funcData.setjmpTable) { // normal asm function pointer call callIdent = '(' + callIdent + ')&{{{ FTM_' + sig + ' }}}'; // the function table mask is set in emscripten.py + Functions.neededTables[sig] = 1; } else { // This is a call through an invoke_*, either a forced one, or a setjmp-required one // note: no need to update argsTypes at this point diff --git a/src/library.js b/src/library.js index cfe83c6e..d19fd531 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]) { @@ -3453,7 +3482,8 @@ LibraryManager.library = { } else if (oldObj.isRoot || oldObj.path == FS.currentPath) { ___setErrNo(ERRNO_CODES.EBUSY); return -1; - } else if (newObj.path && newObj.path.indexOf(oldObj.path) == 0) { + } else if (newObj.parentPath && + newObj.parentPath.indexOf(oldObj.path) == 0) { ___setErrNo(ERRNO_CODES.EINVAL); return -1; } else if (newObj.exists && newObj.object.isFolder) { 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..2e59f0d0 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 { @@ -2859,7 +2880,7 @@ var LibraryGL = { // Vertex array object (VAO) support. TODO: when the WebGL extension is popular, use that and remove this code and GL.vaos glGenVertexArrays__deps: ['$GLEMulation'], - glGenVertexArrays__sig: ['vii'], + glGenVertexArrays__sig: 'vii', glGenVertexArrays: function(n, vaos) { for (var i = 0; i < n; i++) { var id = GL.getNewId(GLEmulation.vaos); @@ -2874,7 +2895,7 @@ var LibraryGL = { {{{ makeSetValue('vaos', 'i*4', 'id', 'i32') }}}; } }, - glDeleteVertexArrays__sig: ['vii'], + glDeleteVertexArrays__sig: 'vii', glDeleteVertexArrays: function(n, vaos) { for (var i = 0; i < n; i++) { var id = {{{ makeGetValue('vaos', 'i*4', 'i32') }}}; @@ -2882,7 +2903,7 @@ var LibraryGL = { if (GLEmulation.currentVao && GLEmulation.currentVao.id == id) GLEmulation.currentVao = null; } }, - glBindVertexArray__sig: ['vi'], + glBindVertexArray__sig: 'vi', glBindVertexArray: function(vao) { // undo vao-related things, wipe the slate clean, both for vao of 0 or an actual vao GLEmulation.currentVao = null; // make sure the commands we run here are not recorded @@ -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' }, @@ -3309,7 +3331,10 @@ for (var item in LibraryGL) { } LibraryGL.$GLEmulation__deps = LibraryGL.$GLEmulation__deps.concat(glFuncs); LibraryGL.$GLEmulation__deps.push(function() { - for (var func in Functions.getIndex.tentative) Functions.getIndex(func); + for (var func in Functions.getIndex.tentative) { + Functions.getIndex(func); + Functions.unimplementedFunctions[func] = LibraryGL[func.substr(1) + '__sig']; + } }); if (FORCE_GL_EMULATION) { 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); - Runtime.dynCall('vii', GLUT.motionFunc, [GLUT.lastX, GLUT.lastY]); + Runtime.dynCall('vii', GLUT.motionFunc, [lastX, lastY]); } }, @@ -159,7 +152,7 @@ var LibraryGLUT = { if( GLUT.specialFunc ) { event.preventDefault(); GLUT.saveModifiers(event); - Runtime.dynCall('viii', GLUT.specialFunc, [key, GLUT.lastX, GLUT.lastY]); + Runtime.dynCall('viii', GLUT.specialFunc, [key, Browser.mouseX, Browser.mouseY]); } } else @@ -168,7 +161,7 @@ var LibraryGLUT = { if( key !== null && GLUT.keyboardFunc ) { event.preventDefault(); GLUT.saveModifiers(event); - Runtime.dynCall('viii', GLUT.keyboardFunc, [key, GLUT.lastX, GLUT.lastY]); + Runtime.dynCall('viii', GLUT.keyboardFunc, [key, Browser.mouseX, Browser.mouseY]); } } } @@ -181,7 +174,7 @@ var LibraryGLUT = { if(GLUT.specialUpFunc) { event.preventDefault (); GLUT.saveModifiers(event); - Runtime.dynCall('viii', GLUT.specialUpFunc, [key, GLUT.lastX, GLUT.lastY]); + Runtime.dynCall('viii', GLUT.specialUpFunc, [key, Browser.mouseX, Browser.mouseY]); } } else @@ -190,14 +183,15 @@ var LibraryGLUT = { if( key !== null && GLUT.keyboardUpFunc ) { event.preventDefault (); GLUT.saveModifiers(event); - Runtime.dynCall('viii', GLUT.keyboardUpFunc, [key, GLUT.lastX, GLUT.lastY]); + Runtime.dynCall('viii', GLUT.keyboardUpFunc, [key, Browser.mouseX, Browser.mouseY]); } } } }, onMouseButtonDown: function(event){ - GLUT.savePosition(event); + Browser.calculateMouseEvent(event); + GLUT.buttons |= (1 << event['button']); if(event.target == Module["canvas"] && GLUT.mouseFunc){ @@ -206,18 +200,19 @@ var LibraryGLUT = { } catch (e) {} event.preventDefault(); GLUT.saveModifiers(event); - Runtime.dynCall('viiii', GLUT.mouseFunc, [event['button'], 0/*GLUT_DOWN*/, GLUT.lastX, GLUT.lastY]); + Runtime.dynCall('viiii', GLUT.mouseFunc, [event['button'], 0/*GLUT_DOWN*/, Browser.mouseX, Browser.mouseY]); } }, onMouseButtonUp: function(event){ - GLUT.savePosition(event); + Browser.calculateMouseEvent(event); + GLUT.buttons &= ~(1 << event['button']); if(GLUT.mouseFunc) { event.preventDefault(); GLUT.saveModifiers(event); - Runtime.dynCall('viiii', GLUT.mouseFunc, [event['button'], 1/*GLUT_UP*/, GLUT.lastX, GLUT.lastY]); + Runtime.dynCall('viiii', GLUT.mouseFunc, [event['button'], 1/*GLUT_UP*/, Browser.mouseX, Browser.mouseY]); } }, diff --git a/src/library_sdl.js b/src/library_sdl.js index a1fb871f..75544765 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -46,8 +46,6 @@ var LibrarySDL = { textInput: false, startTime: null, - mouseX: 0, - mouseY: 0, buttonState: 0, DOMButtons: [0, 0, 0], @@ -515,54 +513,22 @@ var LibrarySDL = { } // fall through case 'mousemove': { - 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)) { |