aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xemcc24
-rwxr-xr-xemscripten.py2
-rw-r--r--src/analyzer.js6
-rw-r--r--src/experimental/allow_loopvars_from_memsetcpy_inasm.diff97
-rw-r--r--src/library.js13
-rw-r--r--src/library_browser.js80
-rw-r--r--src/library_gl.js219
-rw-r--r--src/library_sdl.js34
-rw-r--r--src/long.js11
-rw-r--r--src/parseTools.js24
-rw-r--r--src/shell.html9
-rw-r--r--system/include/err.h95
-rw-r--r--system/lib/libc.symbols19
-rw-r--r--system/lib/libc/gen/err.c49
-rw-r--r--system/lib/libc/gen/errx.c49
-rw-r--r--system/lib/libc/gen/verr.c58
-rw-r--r--system/lib/libc/gen/verrx.c51
-rw-r--r--system/lib/libc/gen/vwarn.c55
-rw-r--r--system/lib/libc/gen/vwarnx.c48
-rw-r--r--system/lib/libc/gen/warn.c49
-rw-r--r--system/lib/libc/gen/warnx.c49
-rw-r--r--system/lib/libc/stdlib/getopt_long.c511
-rw-r--r--tests/cases/emptystruct.ll2
-rw-r--r--tests/cases/gepoverflow.ll2
-rw-r--r--tests/cases/storestruct.ll8
-rwxr-xr-xtests/fuzz/csmith_driver.py6
-rw-r--r--tests/hello_world_gles_full.c742
-rwxr-xr-xtests/runner.py175
-rw-r--r--tools/cache.py5
-rw-r--r--tools/shared.py2
30 files changed, 2332 insertions, 162 deletions
diff --git a/emcc b/emcc
index d773dd85..d54b30f7 100755
--- a/emcc
+++ b/emcc
@@ -75,7 +75,7 @@ emcc can be influenced by a few environment variables:
EMMAKEN_COMPILER - The compiler to be used, if you don't want the default clang.
'''
-import os, sys, shutil, tempfile, subprocess, shlex, time
+import os, sys, shutil, tempfile, subprocess, shlex, time, re
from subprocess import PIPE, STDOUT
from tools import shared
from tools.shared import Compression, execute, suffix, unsuffixed, unsuffixed_basename
@@ -1069,7 +1069,21 @@ try:
def create_libc():
if DEBUG: print >> sys.stderr, 'emcc: building libc for cache'
o_s = []
- for src in ['dlmalloc.c', os.path.join('libcxx', 'new.cpp')]:
+ libc_files = [
+ 'dlmalloc.c',
+ os.path.join('libcxx', 'new.cpp'),
+ os.path.join('libc', 'stdlib', 'getopt_long.c'),
+ os.path.join('libc', 'gen', 'err.c'),
+ os.path.join('libc', 'gen', 'errx.c'),
+ os.path.join('libc', 'gen', 'warn.c'),
+ os.path.join('libc', 'gen', 'warnx.c'),
+ os.path.join('libc', 'gen', 'verr.c'),
+ os.path.join('libc', 'gen', 'verrx.c'),
+ os.path.join('libc', 'gen', 'vwarn.c'),
+ os.path.join('libc', 'gen', 'vwarnx.c'),
+ ];
+
+ for src in libc_files:
o = in_temp(os.path.basename(src) + '.o')
execute([shared.PYTHON, shared.EMCC, shared.path_from_root('system', 'lib', src), '-o', o], stdout=stdout, stderr=stderr)
o_s.append(o)
@@ -1347,6 +1361,12 @@ try:
flush_js_optimizer_queue()
+ if not minify_whitespace:
+ # Remove some trivial whitespace
+ src = open(final).read()
+ src = re.sub(r'\n+[ \n]*\n+', '\n', src)
+ open(final, 'w').write(src)
+
# If we were asked to also generate HTML, do that
if final_suffix == 'html':
if DEBUG: print >> sys.stderr, 'emcc: generating HTML'
diff --git a/emscripten.py b/emscripten.py
index 08ae85c5..b698654b 100755
--- a/emscripten.py
+++ b/emscripten.py
@@ -238,7 +238,7 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
outputs = [output.split('//FORWARDED_DATA:') for output in outputs]
for output in outputs:
- assert len(output) == 2, 'Did not receive forwarded data in an output - process failed? We only got: ' + output[0][-300:]
+ assert len(output) == 2, 'Did not receive forwarded data in an output - process failed? We only got: ' + output[0][-3000:]
if DEBUG: print >> sys.stderr, ' emscript: phase 2 took %s seconds' % (time.time() - t)
if DEBUG: t = time.time()
diff --git a/src/analyzer.js b/src/analyzer.js
index dbbb267d..209e3140 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -290,7 +290,7 @@ function analyzer(data, sidePass) {
var elements = getLegalParams([item.value], bits)[0];
var j = 0;
elements.forEach(function(element) {
- var tempVar = '$st$' + i + '$' + j;
+ var tempVar = '$st$' + (tempId++) + '$' + j;
toAdd.push({
intertype: 'getelementptr',
assignTo: tempVar,
@@ -401,7 +401,7 @@ function analyzer(data, sidePass) {
var j = 0;
var toAdd = [];
elements.forEach(function(element) {
- var tempVar = '$st$' + i + '$' + j;
+ var tempVar = '$ld$' + (tempId++) + '$' + j;
toAdd.push({
intertype: 'getelementptr',
assignTo: tempVar,
@@ -952,6 +952,7 @@ function analyzer(data, sidePass) {
// Function parameters
func.params.forEach(function(param) {
if (param.intertype !== 'varargs') {
+ if (func.variables[param.ident]) warn('cannot have duplicate variable names: ' + param.ident); // toNiceIdent collisions?
func.variables[param.ident] = {
ident: param.ident,
type: param.type,
@@ -965,6 +966,7 @@ function analyzer(data, sidePass) {
// Normal variables
func.lines.forEach(function(item, i) {
if (item.assignTo) {
+ if (func.variables[item.assignTo]) warn('cannot have duplicate variable names: ' + item.assignTo); // toNiceIdent collisions?
var variable = func.variables[item.assignTo] = {
ident: item.assignTo,
type: item.type,
diff --git a/src/experimental/allow_loopvars_from_memsetcpy_inasm.diff b/src/experimental/allow_loopvars_from_memsetcpy_inasm.diff
new file mode 100644
index 00000000..a2dde7da
--- /dev/null
+++ b/src/experimental/allow_loopvars_from_memsetcpy_inasm.diff
@@ -0,0 +1,97 @@
+commit a61ef3dbbaf7333ad67fca29c0aad5bcc99b653a
+Author: Alon Zakai <alonzakai@gmail.com>
+Date: Wed Mar 6 18:18:03 2013 -0800
+
+ handle new vars in asm code, such as the loop vars from memset/memcpy loops
+
+diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js
+index f2dc516..65059e8 100644
+--- a/tools/js-optimizer.js
++++ b/tools/js-optimizer.js
+@@ -1321,7 +1321,7 @@ function normalizeAsm(func) {
+ var name = v[0];
+ var value = v[1];
+ if (!(name in data.vars)) {
+- assert(value[0] == 'num' || (value[0] == 'unary-prefix' && value[2][0] == 'num')); // must be valid coercion no-op
++ if (!(value[0] == 'num' || (value[0] == 'unary-prefix' && value[2][0] == 'num'))) break outer; // must be valid coercion no-op
+ data.vars[name] = detectAsmCoercion(value);
+ v.length = 1; // make an un-assigning var
+ } else {
+@@ -1331,6 +1331,7 @@ function normalizeAsm(func) {
+ i++;
+ }
+ // finally, look for other var definitions and collect them
++ var extra = [];
+ while (i < stats.length) {
+ traverse(stats[i], function(node, type) {
+ if (type == 'var') {
+@@ -1340,6 +1341,7 @@ function normalizeAsm(func) {
+ var value = v[1];
+ if (!(name in data.vars)) {
+ data.vars[name] = detectAsmCoercion(value);
++ extra.push(['var', [[name]]]); // add a 'var' for normal JS
+ }
+ }
+ unVarify(node[1], node);
+@@ -1353,6 +1355,7 @@ function normalizeAsm(func) {
+ });
+ i++;
+ }
++ if (extra.length > 0) stats.splice.apply(stats, [0, 0].concat(extra));
+ //printErr('normalized \n\n' + astToSrc(func) + '\n\nwith: ' + JSON.stringify(data));
+ return data;
+ }
+diff --git a/tools/test-js-optimizer-asm-regs-output.js b/tools/test-js-optimizer-asm-regs-output.js
+index 99bccd2..f84b8d5 100644
+--- a/tools/test-js-optimizer-asm-regs-output.js
++++ b/tools/test-js-optimizer-asm-regs-output.js
+@@ -9,6 +9,18 @@ function asm(d1, i2) {
+ d4 = d1 * 5;
+ return d4;
+ }
++function asm2(d1, i2) {
++ d1 = +d1;
++ i2 = i2 | 0;
++ var i3 = 0, d4 = +0;
++ i3 = i2;
++ i2 = d1 + i3 | 0;
++ d1 = d(Math_max(10, Math_min(5, f())));
++ i3 = i2 + 2 | 0;
++ print(i3);
++ d4 = d1 * 5;
++ return d4;
++}
+ function _doit(i1, i2, i3) {
+ i1 = i1 | 0;
+ i2 = i2 | 0;
+diff --git a/tools/test-js-optimizer-asm-regs.js b/tools/test-js-optimizer-asm-regs.js
+index 0afced2..fbaa7c4 100644
+--- a/tools/test-js-optimizer-asm-regs.js
++++ b/tools/test-js-optimizer-asm-regs.js
+@@ -10,6 +10,19 @@ function asm(x, y) {
+ double2 = double1*5;
+ return double2;
+ }
++function asm2(x, y) {
++ x = +x;
++ y = y | 0;
++ var int1 = 0, int2 = 0; // do not mix the types!
++ var double1 = +0, double2 = +0;
++ var tempy = y;
++ int1 = (x+tempy)|0;
++ double1 = d(Math.max(10, Math_min(5, f())));
++ int2 = (int1+2)|0;
++ print(int2);
++ double2 = double1*5;
++ return double2;
++}
+ function _doit($x, $y$0, $y$1) {
+ $x = $x | 0;
+ $y$0 = $y$0 | 0;
+@@ -41,5 +54,5 @@ function retf() {
+ }
+ // missing final return, need it as a float
+ }
+-// EMSCRIPTEN_GENERATED_FUNCTIONS: ["asm", "_doit", "rett", "ret2t", "retf"]
++// EMSCRIPTEN_GENERATED_FUNCTIONS: ["asm", "asm2", "_doit", "rett", "ret2t", "retf"]
+
diff --git a/src/library.js b/src/library.js
index 8220f780..7c9cc22c 100644
--- a/src/library.js
+++ b/src/library.js
@@ -3670,6 +3670,17 @@ LibraryManager.library = {
abs: 'Math.abs',
labs: 'Math.abs',
+#if USE_TYPED_ARRAYS == 2
+ llabs__deps: [function() { Types.preciseI64MathUsed = 1 }],
+ llabs: function(lo, hi) {
+ i64Math.abs(lo, hi);
+ {{{ makeStructuralReturn([makeGetTempDouble(0, 'i32'), makeGetTempDouble(1, 'i32')]) }}};
+ },
+#else
+ llabs: function(lo, hi) {
+ throw 'unsupported llabs';
+ },
+#endif
exit__deps: ['_exit'],
exit: function(status) {
@@ -4315,7 +4326,7 @@ LibraryManager.library = {
ptr = ptr|0; value = value|0; num = num|0;
var stop = 0, value4 = 0, stop4 = 0, unaligned = 0;
stop = (ptr + num)|0;
- if ((num|0) >= {{{ SEEK_OPTIMAL_ALIGN_MIN }}}) {
+ if ((num|0) >= {{{ Math.round(2.5*UNROLL_LOOP_MAX) }}}) {
// This is unaligned, but quite large, so work hard to get to aligned settings
value = value & 0xff;
unaligned = ptr & 3;
diff --git a/src/library_browser.js b/src/library_browser.js
index 5b19a360..bdd94bac 100644
--- a/src/library_browser.js
+++ b/src/library_browser.js
@@ -3,7 +3,7 @@
// Utilities for browser environments
mergeInto(LibraryManager.library, {
- $Browser__postset: 'Module["requestFullScreen"] = function() { Browser.requestFullScreen() };\n' + // exports
+ $Browser__postset: 'Module["requestFullScreen"] = function(lockPointer, resizeCanvas) { Browser.requestFullScreen(lockPointer, resizeCanvas) };\n' + // exports
'Module["requestAnimationFrame"] = function(func) { Browser.requestAnimationFrame(func) };\n' +
'Module["pauseMainLoop"] = function() { Browser.mainLoop.pause() };\n' +
'Module["resumeMainLoop"] = function() { Browser.mainLoop.resume() };\n',
@@ -40,6 +40,7 @@ mergeInto(LibraryManager.library, {
}
}
},
+ isFullScreen: false,
pointerLock: false,
moduleContextCreatedCallbacks: [],
workers: [],
@@ -205,10 +206,10 @@ mergeInto(LibraryManager.library, {
try {
if (useWebGL) {
ctx = canvas.getContext('experimental-webgl', {
- alpha: false,
#if GL_TESTING
- preserveDrawingBuffer: true
+ preserveDrawingBuffer: true,
#endif
+ alpha: false
});
} else {
ctx = canvas.getContext('2d');
@@ -273,36 +274,60 @@ mergeInto(LibraryManager.library, {
}
return ctx;
},
+
destroyContext: function(canvas, useWebGL, setInModule) {},
- requestFullScreen: function() {
+
+ fullScreenHandlersInstalled: false,
+ lockPointer: undefined,
+ resizeCanvas: undefined,
+ requestFullScreen: function(lockPointer, resizeCanvas) {
+ this.lockPointer = lockPointer;
+ this.resizeCanvas = resizeCanvas;
+ if (typeof this.lockPointer === 'undefined') this.lockPointer = true;
+ if (typeof this.resizeCanvas === 'undefined') this.resizeCanvas = false;
+
var canvas = Module['canvas'];
function fullScreenChange() {
- var isFullScreen = false;
+ Browser.isFullScreen = false;
if ((document['webkitFullScreenElement'] || document['webkitFullscreenElement'] ||
document['mozFullScreenElement'] || document['mozFullscreenElement'] ||
document['fullScreenElement'] || document['fullscreenElement']) === canvas) {
canvas.requestPointerLock = canvas['requestPointerLock'] ||
canvas['mozRequestPointerLock'] ||
canvas['webkitRequestPointerLock'];
- canvas.requestPointerLock();
- isFullScreen = true;
+ canvas.exitPointerLock = document['exitPointerLock'] ||
+ document['mozExitPointerLock'] ||
+ document['webkitExitPointerLock'];
+ canvas.exitPointerLock = canvas.exitPointerLock.bind(document);
+ canvas.cancelFullScreen = document['cancelFullScreen'] ||
+ document['mozCancelFullScreen'] ||
+ document['webkitCancelFullScreen'];
+ canvas.cancelFullScreen = canvas.cancelFullScreen.bind(document);
+ if (Browser.lockPointer) canvas.requestPointerLock();
+ Browser.isFullScreen = true;
+ if (Browser.resizeCanvas) Browser.setFullScreenCanvasSize();
+ } else if (Browser.resizeCanvas){
+ Browser.setWindowedCanvasSize();
}
- if (Module['onFullScreen']) Module['onFullScreen'](isFullScreen);
+ if (Module['onFullScreen']) Module['onFullScreen'](Browser.isFullScreen);
}
- document.addEventListener('fullscreenchange', fullScreenChange, false);
- document.addEventListener('mozfullscreenchange', fullScreenChange, false);
- document.addEventListener('webkitfullscreenchange', fullScreenChange, false);
-
function pointerLockChange() {
Browser.pointerLock = document['pointerLockElement'] === canvas ||
document['mozPointerLockElement'] === canvas ||
document['webkitPointerLockElement'] === canvas;
}
- document.addEventListener('pointerlockchange', pointerLockChange, false);
- document.addEventListener('mozpointerlockchange', pointerLockChange, false);
- document.addEventListener('webkitpointerlockchange', pointerLockChange, false);
+ if (!this.fullScreenHandlersInstalled) {
+ this.fullScreenHandlersInstalled = true;
+ document.addEventListener('fullscreenchange', fullScreenChange, false);
+ document.addEventListener('mozfullscreenchange', fullScreenChange, false);
+ document.addEventListener('webkitfullscreenchange', fullScreenChange, false);
+
+ document.addEventListener('pointerlockchange', pointerLockChange, false);
+ document.addEventListener('mozpointerlockchange', pointerLockChange, false);
+ document.addEventListener('webkitpointerlockchange', pointerLockChange, false);
+ }
canvas.requestFullScreen = canvas['requestFullScreen'] ||
canvas['mozRequestFullScreen'] ||
@@ -380,7 +405,32 @@ mergeInto(LibraryManager.library, {
canvas.width = width;
canvas.height = height;
if (!noUpdates) Browser.updateResizeListeners();
+ },
+
+ windowedWidth: 0,
+ windowedHeight: 0,
+ setFullScreenCanvasSize: function() {
+ var canvas = Module['canvas'];
+ this.windowedWidth = canvas.width;
+ this.windowedHeight = canvas.height;
+ canvas.width = screen.width;
+ canvas.height = screen.height;
+ var flags = {{{ makeGetValue('SDL.screen+Runtime.QUANTUM_SIZE*0', '0', 'i32', 0, 1) }}};
+ flags = flags | 0x00800000; // set SDL_FULLSCREEN flag
+ {{{ makeSetValue('SDL.screen+Runtime.QUANTUM_SIZE*0', '0', 'flags', 'i32') }}}
+ Browser.updateResizeListeners();
+ },
+
+ setWindowedCanvasSize: function() {
+ var canvas = Module['canvas'];
+ canvas.width = this.windowedWidth;
+ canvas.height = this.windowedHeight;
+ var flags = {{{ makeGetValue('SDL.screen+Runtime.QUANTUM_SIZE*0', '0', 'i32', 0, 1) }}};
+ flags = flags & ~0x00800000; // clear SDL_FULLSCREEN flag
+ {{{ makeSetValue('SDL.screen+Runtime.QUANTUM_SIZE*0', '0', 'flags', 'i32') }}}
+ Browser.updateResizeListeners();
}
+
},
emscripten_async_wget: function(url, file, onload, onerror) {
diff --git a/src/library_gl.js b/src/library_gl.js
index 4977d2e9..c6007809 100644
--- a/src/library_gl.js
+++ b/src/library_gl.js
@@ -21,7 +21,6 @@ var LibraryGL = {
#if FULL_ES2
clientBuffers: [],
- enabledClientBuffers: [],
#endif
currArrayBuffer: 0,
currElementArrayBuffer: 0,
@@ -59,6 +58,65 @@ var LibraryGL = {
return ret;
},
+ // Temporary buffers
+ MAX_TEMP_BUFFER_SIZE: {{{ GL_MAX_TEMP_BUFFER_SIZE }}},
+ tempBufferIndexLookup: null,
+ tempVertexBuffers: null,
+ tempIndexBuffers: null,
+ tempQuadIndexBuffer: null,
+
+ generateTempBuffers: function(quads) {
+ this.tempBufferIndexLookup = new Uint8Array(this.MAX_TEMP_BUFFER_SIZE+1);
+ this.tempVertexBuffers = [];
+ this.tempIndexBuffers = [];
+ var last = -1, curr = -1;
+ var size = 1;
+ for (var i = 0; i <= this.MAX_TEMP_BUFFER_SIZE; i++) {
+ if (i > size) {
+ size <<= 1;
+ }
+ if (size != last) {
+ curr++;
+ this.tempVertexBuffers[curr] = Module.ctx.createBuffer();
+ Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, this.tempVertexBuffers[curr]);
+ Module.ctx.bufferData(Module.ctx.ARRAY_BUFFER, size, Module.ctx.DYNAMIC_DRAW);
+ Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, null);
+ this.tempIndexBuffers[curr] = Module.ctx.createBuffer();
+ Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, this.tempIndexBuffers[curr]);
+ Module.ctx.bufferData(Module.ctx.ELEMENT_ARRAY_BUFFER, size, Module.ctx.DYNAMIC_DRAW);
+ Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, null);
+ last = size;
+ }
+ this.tempBufferIndexLookup[i] = curr;
+ }
+
+ if (quads) {
+ // GL_QUAD indexes can be precalculated
+ this.tempQuadIndexBuffer = Module.ctx.createBuffer();
+ Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, this.tempQuadIndexBuffer);
+ var numIndexes = this.MAX_TEMP_BUFFER_SIZE >> 1;
+ var quadIndexes = new Uint16Array(numIndexes);
+ var i = 0, v = 0;
+ while (1) {
+ quadIndexes[i++] = v;
+ if (i >= numIndexes) break;
+ quadIndexes[i++] = v+1;
+ if (i >= numIndexes) break;
+ quadIndexes[i++] = v+2;
+ if (i >= numIndexes) break;
+ quadIndexes[i++] = v;
+ if (i >= numIndexes) break;
+ quadIndexes[i++] = v+2;
+ if (i >= numIndexes) break;
+ quadIndexes[i++] = v+3;
+ if (i >= numIndexes) break;
+ v += 4;
+ }
+ Module.ctx.bufferData(Module.ctx.ELEMENT_ARRAY_BUFFER, quadIndexes, Module.ctx.STATIC_DRAW);
+ Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, null);
+ }
+ },
+
// Linear lookup in one of the tables (buffers, programs, etc.). TODO: consider using a weakmap to make this faster, if it matters
scan: function(table, object) {
for (var item in table) {
@@ -207,19 +265,34 @@ var LibraryGL = {
return size * typeSize * count;
},
+ usedTempBuffers: [],
+
preDrawHandleClientVertexAttribBindings: function(count) {
GL.resetBufferBinding = false;
+
+ var used = GL.usedTempBuffers;
+ used.length = 0;
+
+ // TODO: initial pass to detect ranges we need to upload, might not need an upload per attrib
for (var i = 0; i < GL.maxVertexAttribs; ++i) {
- if (!GL.enabledClientBuffers[i] || !GL.clientBuffers[i]) continue;
-
- GL.resetBufferBinding = true;
-
var cb = GL.clientBuffers[i];
-
- var buf = Module.ctx.createBuffer();
+ if (!cb.enabled) continue;
+
+ GL.resetBufferBinding = true;
+
+ var size = GL.calcBufLength(cb.size, cb.type, cb.stride, count);
+ var index = GL.tempBufferIndexLookup[size];
+ var buf;
+ do {
+#if ASSERTIONS
+ assert(index < GL.tempVertexBuffers.length);
+#endif
+ buf = GL.tempVertexBuffers[index++];
+ } while (used.indexOf(buf) >= 0);
+ used.push(buf);
Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, buf);
Module.ctx.bufferData(Module.ctx.ARRAY_BUFFER,
- HEAPU8.subarray(cb.ptr, cb.ptr + GL.calcBufLength(cb.size, cb.type, cb.stride, count)),
+ HEAPU8.subarray(cb.ptr, cb.ptr + size),
Module.ctx.DYNAMIC_DRAW);
Module.ctx.vertexAttribPointer(i, cb.size, cb.type, cb.normalized, cb.stride, 0);
}
@@ -239,6 +312,13 @@ var LibraryGL = {
if (!Module.useWebGL) return; // an app might link both gl and 2d backends
GL.maxVertexAttribs = Module.ctx.getParameter(Module.ctx.MAX_VERTEX_ATTRIBS);
+#if FULL_ES2
+ for (var i = 0; i < GL.maxVertexAttribs; i++) {
+ GL.clientBuffers[i] = { enabled: false, size: 0, type: 0, normalized: 0, stride: 0, ptr: 0 };
+ }
+
+ GL.generateTempBuffers();
+#endif
GL.compressionExt = Module.ctx.getExtension('WEBGL_compressed_texture_s3tc') ||
Module.ctx.getExtension('MOZ_WEBGL_compressed_texture_s3tc') ||
@@ -612,7 +692,7 @@ var LibraryGL = {
glGetVertexAttribfv: function(index, pname, params) {
#if FULL_ES2
- if (GL.clientBuffers[index]) {
+ if (GL.clientBuffers[index].enabled) {
Module.printErr("glGetVertexAttribfv on client-side array: not supported, bad data returned");
}
#endif
@@ -628,7 +708,7 @@ var LibraryGL = {
glGetVertexAttribiv: function(index, pname, params) {
#if FULL_ES2
- if (GL.clientBuffers[index]) {
+ if (GL.clientBuffers[index].enabled) {
Module.printErr("glGetVertexAttribiv on client-side array: not supported, bad data returned");
}
#endif
@@ -644,7 +724,7 @@ var LibraryGL = {
glGetVertexAttribPointerv: function(index, pname, pointer) {
#if FULL_ES2
- if (GL.clientBuffers[index]) {
+ if (GL.clientBuffers[index].enabled) {
Module.printErr("glGetVertexAttribPointer on client-side array: not supported, bad data returned");
}
#endif
@@ -1693,62 +1773,6 @@ var LibraryGL = {
this.modifiedClientAttributes = true;
},
- // Temporary buffers
- MAX_TEMP_BUFFER_SIZE: {{{ GL_MAX_TEMP_BUFFER_SIZE }}},
- tempBufferIndexLookup: null,
- tempVertexBuffers: null,
- tempIndexBuffers: null,
- tempQuadIndexBuffer: null,
-
- generateTempBuffers: function() {
- this.tempBufferIndexLookup = new Uint8Array(this.MAX_TEMP_BUFFER_SIZE+1);
- this.tempVertexBuffers = [];
- this.tempIndexBuffers = [];
- var last = -1, curr = -1;
- var size = 1;
- for (var i = 0; i <= this.MAX_TEMP_BUFFER_SIZE; i++) {
- if (i > size) {
- size <<= 1;
- }
- if (size != last) {
- curr++;
- this.tempVertexBuffers[curr] = Module.ctx.createBuffer();
- Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, this.tempVertexBuffers[curr]);
- Module.ctx.bufferData(Module.ctx.ARRAY_BUFFER, size, Module.ctx.DYNAMIC_DRAW);
- Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, null);
- this.tempIndexBuffers[curr] = Module.ctx.createBuffer();
- Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, this.tempIndexBuffers[curr]);
- Module.ctx.bufferData(Module.ctx.ELEMENT_ARRAY_BUFFER, size, Module.ctx.DYNAMIC_DRAW);
- Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, null);
- last = size;
- }
- this.tempBufferIndexLookup[i] = curr;
- }
- // GL_QUAD indexes can be precalculated
- this.tempQuadIndexBuffer = Module.ctx.createBuffer();
- Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, this.tempQuadIndexBuffer);
- var numIndexes = this.MAX_TEMP_BUFFER_SIZE >> 1;
- var quadIndexes = new Uint16Array(numIndexes);
- var i = 0, v = 0;
- while (1) {
- quadIndexes[i++] = v;
- if (i >= numIndexes) break;
- quadIndexes[i++] = v+1;
- if (i >= numIndexes) break;
- quadIndexes[i++] = v+2;
- if (i >= numIndexes) break;
- quadIndexes[i++] = v;
- if (i >= numIndexes) break;
- quadIndexes[i++] = v+2;
- if (i >= numIndexes) break;
- quadIndexes[i++] = v+3;
- if (i >= numIndexes) break;
- v += 4;
- }
- Module.ctx.bufferData(Module.ctx.ELEMENT_ARRAY_BUFFER, quadIndexes, Module.ctx.STATIC_DRAW);
- Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, null);
- },
-
// Renderers
addRendererComponent: function(name, size, type) {
if (!this.rendererComponents[name]) {
@@ -1969,8 +1993,8 @@ var LibraryGL = {
if (!GL.currArrayBuffer) {
var start = GL.immediate.firstVertex*GL.immediate.stride;
var end = GL.immediate.lastVertex*GL.immediate.stride;
- assert(end <= GL.immediate.MAX_TEMP_BUFFER_SIZE, 'too much vertex data');
- arrayBuffer = GL.immediate.tempVertexBuffers[GL.immediate.tempBufferIndexLookup[end]];
+ assert(end <= GL.MAX_TEMP_BUFFER_SIZE, 'too much vertex data');
+ arrayBuffer = GL.tempVertexBuffers[GL.tempBufferIndexLookup[end]];
// TODO: consider using the last buffer we bound, if it was larger. downside is larger buffer, but we might avoid rebinding and preparing
} else {
arrayBuffer = GL.currArrayBuffer;
@@ -2161,12 +2185,12 @@ var LibraryGL = {
this.rendererCache = this.rendererCacheItemTemplate.slice();
// Buffers for data
- this.tempData = new Float32Array(this.MAX_TEMP_BUFFER_SIZE >> 2);
- this.indexData = new Uint16Array(this.MAX_TEMP_BUFFER_SIZE >> 1);
+ this.tempData = new Float32Array(GL.MAX_TEMP_BUFFER_SIZE >> 2);
+ this.indexData = new Uint16Array(GL.MAX_TEMP_BUFFER_SIZE >> 1);
this.vertexDataU8 = new Uint8Array(this.tempData.buffer);
- this.generateTempBuffers();
+ GL.generateTempBuffers(true);
this.clientColor = new Float32Array([1, 1, 1, 1]);
},
@@ -2209,7 +2233,7 @@ var LibraryGL = {
#if ASSERTIONS
Runtime.warnOnce('Unpacking/restriding attributes, this is not fast');
#endif
- if (!GL.immediate.restrideBuffer) GL.immediate.restrideBuffer = _malloc(GL.immediate.MAX_TEMP_BUFFER_SIZE);
+ if (!GL.immediate.restrideBuffer) GL.immediate.restrideBuffer = _malloc(GL.MAX_TEMP_BUFFER_SIZE);
start = GL.immediate.restrideBuffer;
#if ASSERTIONS
assert(start % 4 == 0);
@@ -2224,7 +2248,7 @@ var LibraryGL = {
bytes += size;
}
#if ASSERTIONS
- assert(count*bytes <= GL.immediate.MAX_TEMP_BUFFER_SIZE);
+ assert(count*bytes <= GL.MAX_TEMP_BUFFER_SIZE);
#endif
// copy out the data (we need to know the stride for that, and define attribute.pointer
for (var i = 0; i < attributes.length; i++) {
@@ -2298,8 +2322,8 @@ var LibraryGL = {
}
if (!GL.currElementArrayBuffer) {
// If no element array buffer is bound, then indices is a literal pointer to clientside data
- assert(numProvidedIndexes << 1 <= GL.immediate.MAX_TEMP_BUFFER_SIZE, 'too many immediate mode indexes (a)');
- var indexBuffer = GL.immediate.tempIndexBuffers[GL.immediate.tempBufferIndexLookup[numProvidedIndexes << 1]];
+ assert(numProvidedIndexes << 1 <= GL.MAX_TEMP_BUFFER_SIZE, 'too many immediate mode indexes (a)');
+ var indexBuffer = GL.tempIndexBuffers[GL.tempBufferIndexLookup[numProvidedIndexes << 1]];
Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, indexBuffer);
Module.ctx.bufferSubData(Module.ctx.ELEMENT_ARRAY_BUFFER, 0, {{{ makeHEAPView('U16', 'ptr', 'ptr + (numProvidedIndexes << 1)') }}});
ptr = 0;
@@ -2314,8 +2338,8 @@ var LibraryGL = {
ptr = GL.immediate.firstVertex*3;
var numQuads = numVertexes / 4;
numIndexes = numQuads * 6; // 0 1 2, 0 2 3 pattern
- assert(ptr + (numIndexes << 1) <= GL.immediate.MAX_TEMP_BUFFER_SIZE, 'too many immediate mode indexes (b)');
- Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, this.tempQuadIndexBuffer);
+ assert(ptr + (numIndexes << 1) <= GL.MAX_TEMP_BUFFER_SIZE, 'too many immediate mode indexes (b)');
+ Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, GL.tempQuadIndexBuffer);
emulatedElementArrayBuffer = true;
}
@@ -2369,7 +2393,7 @@ var LibraryGL = {
GL.immediate.vertexData[GL.immediate.vertexCounter++] = y;
GL.immediate.vertexData[GL.immediate.vertexCounter++] = z || 0;
#if ASSERTIONS
- assert(GL.immediate.vertexCounter << 2 < GL.immediate.MAX_TEMP_BUFFER_SIZE);
+ assert(GL.immediate.vertexCounter << 2 < GL.MAX_TEMP_BUFFER_SIZE);
#endif
GL.immediate.addRendererComponent(GL.immediate.VERTEX, 3, Module.ctx.FLOAT);
},
@@ -2849,15 +2873,24 @@ var LibraryGL = {
glShadeModel: function() { Runtime.warnOnce('TODO: glShadeModel') },
+ // GLES2 emulation
+
glVertexAttribPointer__sig: 'viiiiii',
glVertexAttribPointer: function(index, size, type, normalized, stride, ptr) {
#if FULL_ES2
+ var cb = GL.clientBuffers[index];
+#if ASSERTIONS
+ assert(cb, index);
+#endif
if (!GL.currArrayBuffer) {
- GL.clientBuffers[index] = { size: size, type: type, normalized: normalized, stride: stride, ptr: ptr };
+ cb.size = size;
+ cb.type = type;
+ cb.normalized = normalized;
+ cb.stride = stride;
+ cb.ptr = ptr;
return;
}
-
- GL.clientBuffers[index] = null;
+ cb.enabled = false;
#endif
Module.ctx.vertexAttribPointer(index, size, type, normalized, stride, ptr);
},
@@ -2865,7 +2898,11 @@ var LibraryGL = {
glEnableVertexAttribArray__sig: 'vi',
glEnableVertexAttribArray: function(index) {
#if FULL_ES2
- GL.enabledClientBuffers[index] = true;