aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/analyzer.js78
-rw-r--r--src/compiler.js2
-rw-r--r--src/jsifier.js1
-rw-r--r--src/library.js136
-rw-r--r--src/library_browser.js41
-rw-r--r--src/library_gl.js63
-rw-r--r--src/library_glfw.js29
-rw-r--r--src/library_glut.js41
-rw-r--r--src/library_sdl.js122
-rw-r--r--src/modules.js43
-rw-r--r--src/parseTools.js8
-rw-r--r--src/settings.js10
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)) {