diff options
author | Alon Zakai <alonzakai@gmail.com> | 2014-01-15 17:01:19 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2014-01-15 17:01:19 -0800 |
commit | c42b937808924f6b922b29d2e0fd1fe1d1b0411c (patch) | |
tree | 4027d435b6638a7e72b9519990298fb9314ecc96 /src | |
parent | 8478d6aee54d6c52de16d8c58309534afbf5bf9e (diff) | |
parent | e5ccf17e84e7a5102bf9e05ffef01e6672b4c15a (diff) |
Merge branch 'incoming'
Diffstat (limited to 'src')
-rw-r--r-- | src/closure-externs.js | 110 | ||||
-rw-r--r-- | src/intertyper.js | 2 | ||||
-rw-r--r-- | src/jsifier.js | 15 | ||||
-rw-r--r-- | src/library.js | 26 | ||||
-rw-r--r-- | src/library_browser.js | 30 | ||||
-rw-r--r-- | src/library_fs.js | 4 | ||||
-rw-r--r-- | src/library_gl.js | 1549 | ||||
-rw-r--r-- | src/library_glew.js | 135 | ||||
-rw-r--r-- | src/library_glut.js | 4 | ||||
-rw-r--r-- | src/library_sdl.js | 34 | ||||
-rw-r--r-- | src/library_uuid.js | 140 | ||||
-rw-r--r-- | src/modules.js | 2 | ||||
-rw-r--r-- | src/parseTools.js | 26 | ||||
-rw-r--r-- | src/postamble.js | 10 | ||||
-rw-r--r-- | src/preamble.js | 3 | ||||
-rw-r--r-- | src/relooper/Relooper.cpp | 74 | ||||
-rw-r--r-- | src/relooper/Relooper.h | 17 | ||||
-rw-r--r-- | src/relooper/fuzzer.py | 14 | ||||
-rw-r--r-- | src/relooper/test.cpp | 28 | ||||
-rw-r--r-- | src/relooper/test.txt | 49 | ||||
-rw-r--r-- | src/settings.js | 3 | ||||
-rw-r--r-- | src/struct_info.json | 12 |
22 files changed, 1506 insertions, 781 deletions
diff --git a/src/closure-externs.js b/src/closure-externs.js new file mode 100644 index 00000000..a82aa669 --- /dev/null +++ b/src/closure-externs.js @@ -0,0 +1,110 @@ +/** + * This file contains definitions for things that we'd really rather the closure compiler *didn't* minify. + * See http://code.google.com/p/closure-compiler/wiki/FAQ#How_do_I_write_an_externs_file + * See also the discussion here: https://github.com/kripken/emscripten/issues/1979 + * + * The closure_compiler() method in tools/shared.py refers to this file when calling closure. + */ + +// Closure externs used by library_uuid.js + +/** + * @param {Array} typedArray + */ +crypto.getRandomValues = function(typedArray) {}; + +/** + BEGIN_NODE_INCLUDE + var crypto = require('crypto'); + END_NODE_INCLUDE + */ + +/** + * @type {Object.<string,*>} + */ +var crypto = {}; + +/** + * @param {number} size + * @param {function(Error, buffer.Buffer)} callback + */ +crypto.randomBytes = function(size, callback) {}; + + +// Closure externs used by library_sockfs.js + +/** + BEGIN_NODE_INCLUDE + var ws = require('ws'); + END_NODE_INCLUDE + */ + +/** + * @type {Object.<string,*>} + */ +var ws = {}; + +/** + * @param {string} event + * @param {function()} callback + */ +ws.on = function(event, callback) {}; + +/** + * @param {Object} data + * @param {Object} flags + * @param {function()=} callback + */ +ws.send = function(data, flags, callback) {}; + +/** +* @type {boolean} +*/ +ws.binaryType; + +/** + * @type {Object.<string,*>} + */ +var wss = ws.Server; + +/** + * @param {string} event + * @param {function()} callback + */ +wss.on = function(event, callback) {}; + +/** + * @param {function()} callback + */ +wss.broadcast = function(callback) {}; + +/** +* @type {Object.<string,*>} +*/ +wss._socket; + +/** +* @type {string} +*/ +wss.url; + +/** +* @type {string} +*/ +wss._socket.remoteAddress; + +/** +* @type {number} +*/ +wss._socket.remotePort; + +/** +* @type {Object.<string,*>} +*/ +var flags = {}; +/** +* @type {boolean} +*/ +flags.binary; + + diff --git a/src/intertyper.js b/src/intertyper.js index b34d0c08..10822e48 100644 --- a/src/intertyper.js +++ b/src/intertyper.js @@ -241,7 +241,7 @@ function intertyper(lines, sidePass, baseLineNums) { if (mainPass && /^}.*/.test(line)) { inFunction = false; if (mainPass) { - var func = funcHeaderHandler({ tokens: tokenize(currFunctionLines[0], currFunctionLineNum) }); + var func = funcHeaderHandler({ tokens: tokenize(currFunctionLines[0]) }); if (SKIP_STACK_IN_SMALL && /emscripten_autodebug/.exec(func.ident)) { warnOnce('Disabling SKIP_STACK_IN_SMALL because we are apparently processing autodebugger data'); diff --git a/src/jsifier.js b/src/jsifier.js index 58dc4653..726a5eda 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -18,7 +18,7 @@ var INDENTATION = ' '; var functionStubSigs = {}; // JSifier -function JSify(data, functionsOnly, givenFunctions) { +function JSify(data, functionsOnly) { //B.start('jsifier'); var mainPass = !functionsOnly; @@ -109,7 +109,7 @@ function JSify(data, functionsOnly, givenFunctions) { dprint('unparsedFunctions','====================\n// Processing function batch of ' + currBaseLineNums.length + ' functions, ' + currFuncLines.length + ' lines, functions left: ' + data.unparsedFunctions.length); if (DEBUG_MEMORY) MemoryDebugger.tick('pre-func'); - JSify(analyzer(intertyper(currFuncLines, true, currBaseLineNums), true), true, Functions); + JSify(analyzer(intertyper(currFuncLines, true, currBaseLineNums), true), true); if (DEBUG_MEMORY) MemoryDebugger.tick('post-func'); } currFuncLines = currBaseLineNums = null; // Do not hold on to anything from inside that loop (JS function scoping..) @@ -215,6 +215,9 @@ function JSify(data, functionsOnly, givenFunctions) { function parseConst(value, type, ident) { var constant = makeConst(value, type); + // Sadly, we've thrown away type information in makeConst, so we're not + // passing correct type info to parseNumerical which works around this + // lack. constant = flatten(constant).map(function(x) { return parseNumerical(x) }) return constant; } @@ -625,8 +628,8 @@ function JSify(data, functionsOnly, givenFunctions) { } } - if (CLOSURE_ANNOTATIONS) func.JS += '/** @type {number} */'; if (!ASM_JS) { + if (CLOSURE_ANNOTATIONS) func.JS += '/** @type {number} */'; func.JS += INDENTATION + 'var label=0;\n'; } @@ -878,8 +881,8 @@ function JSify(data, functionsOnly, givenFunctions) { function makeAssign(item) { var valueJS = item.JS; item.JS = ''; - if (CLOSURE_ANNOTATIONS) item.JS += '/** @type {number} */ '; if (!ASM_JS || item.intertype != 'alloca' || item.funcData.variables[item.assignTo].impl == VAR_EMULATED) { // asm only needs non-allocas + if (CLOSURE_ANNOTATIONS) item.JS += '/** @type {number} */ '; item.JS += ((ASM_JS || item.overrideSSA) ? '' : 'var ') + toNiceIdent(item.assignTo); } var value = parseNumerical(valueJS); @@ -1796,7 +1799,7 @@ function JSify(data, functionsOnly, givenFunctions) { } }); } - JSify(globalsData, true, Functions); + JSify(globalsData, true); globalsData = null; data.unparsedGlobalss = null; @@ -1871,7 +1874,7 @@ function JSify(data, functionsOnly, givenFunctions) { print('// Warning: printing of i64 values may be slightly rounded! No deep i64 math used, so precise i64 code not included'); print('var i64Math = null;'); } - if (Types.usesSIMD) { + if (Types.usesSIMD || SIMD) { print(read('simd.js')); } diff --git a/src/library.js b/src/library.js index 354e5549..69569601 100644 --- a/src/library.js +++ b/src/library.js @@ -1950,9 +1950,9 @@ LibraryManager.library = { } // Handle precision. - var precisionSet = false; + var precisionSet = false, precision = -1; if (next == {{{ charCode('.') }}}) { - var precision = 0; + precision = 0; precisionSet = true; textIndex++; next = {{{ makeGetValue(0, 'textIndex+1', 'i8') }}}; @@ -1969,8 +1969,10 @@ LibraryManager.library = { } } next = {{{ makeGetValue(0, 'textIndex+1', 'i8') }}}; - } else { - var precision = 6; // Standard default. + } + if (precision === -1) { + precision = 6; // Standard default. + precisionSet = false; } // Handle integer sizes. WARNING: These assume a 32-bit architecture! @@ -4455,6 +4457,7 @@ LibraryManager.library = { terminate: '__cxa_call_unexpected', + __gxx_personality_v0__deps: ['llvm_eh_exception', '_ZSt18uncaught_exceptionv', '__cxa_find_matching_catch'], __gxx_personality_v0: function() { }, @@ -4827,15 +4830,6 @@ LibraryManager.library = { llvm_log_f64: 'Math_log', llvm_exp_f32: 'Math_exp', llvm_exp_f64: 'Math_exp', - ldexp: function(x, exp_) { - return x * Math.pow(2, exp_); - }, - ldexpf: 'ldexp', - scalb: 'ldexp', - scalbn: 'ldexp', - scalbnf: 'ldexp', - scalbln: 'ldexp', - scalblnf: 'ldexp', cbrt: function(x) { return Math.pow(x, 1/3); }, @@ -9178,6 +9172,10 @@ LibraryManager.library = { tempRet0 = 0; return (high >>> (bits - 32))|0; }, + + // misc shims for musl + __lockfile: function() { return 1 }, + __unlockfile: function(){}, }; function autoAddDeps(object, name) { @@ -9190,7 +9188,7 @@ function autoAddDeps(object, name) { } // Add aborting stubs for various libc stuff needed by libc++ -['pthread_cond_signal', 'pthread_equal', 'wcstol', 'wcstoll', 'wcstoul', 'wcstoull', 'wcstof', 'wcstod', 'wcstold', 'pthread_join', 'pthread_detach', 'catgets', 'catopen', 'catclose', 'fputwc', '__lockfile', '__unlockfile'].forEach(function(aborter) { +['pthread_cond_signal', 'pthread_equal', 'pthread_join', 'pthread_detach', 'catgets', 'catopen', 'catclose'].forEach(function(aborter) { LibraryManager.library[aborter] = function aborting_stub() { throw 'TODO: ' + aborter }; }); diff --git a/src/library_browser.js b/src/library_browser.js index b368c6ac..458a8dd2 100644 --- a/src/library_browser.js +++ b/src/library_browser.js @@ -319,7 +319,7 @@ mergeInto(LibraryManager.library, { }, false); } if (setInModule) { - Module.ctx = ctx; + GLctx = Module.ctx = ctx; Module.useWebGL = useWebGL; Browser.moduleContextCreatedCallbacks.forEach(function(callback) { callback() }); Browser.init(); @@ -478,19 +478,30 @@ mergeInto(LibraryManager.library, { // in the coordinates. var rect = Module["canvas"].getBoundingClientRect(); var x, y; + + // Neither .scrollX or .pageXOffset are defined in a spec, but + // we prefer .scrollX because it is currently in a spec draft. + // (see: http://www.w3.org/TR/2013/WD-cssom-view-20131217/) + var scrollX = ((typeof window.scrollX !== 'undefined') ? window.scrollX : window.pageXOffset); + var scrollY = ((typeof window.scrollY !== 'undefined') ? window.scrollY : window.pageYOffset); +#if ASSERTIONS + // If this assert lands, it's likely because the browser doesn't support scrollX or pageXOffset + // and we have no viable fallback. + assert((typeof scrollX !== 'undefined') && (typeof scrollY !== 'undefined'), 'Unable to retrieve scroll position, mouse positions likely broken.'); +#endif if (event.type == 'touchstart' || event.type == 'touchend' || event.type == 'touchmove') { var t = event.touches.item(0); if (t) { - x = t.pageX - (window.scrollX + rect.left); - y = t.pageY - (window.scrollY + rect.top); + x = t.pageX - (scrollX + rect.left); + y = t.pageY - (scrollY + rect.top); } else { return; } } else { - x = event.pageX - (window.scrollX + rect.left); - y = event.pageY - (window.scrollY + rect.top); + x = event.pageX - (scrollX + rect.left); + y = event.pageY - (scrollY + rect.top); } // the canvas might be CSS-scaled compared to its backbuffer; @@ -764,6 +775,15 @@ mergeInto(LibraryManager.library, { return; } + // Signal GL rendering layer that processing of a new frame is about to start. This helps it optimize + // VBO double-buffering and reduce GPU stalls. +#if FULL_ES2 + GL.newRenderingFrameStarted(); +#endif +#if LEGACY_GL_EMULATION + GL.newRenderingFrameStarted(); +#endif + if (Module['preMainLoop']) { Module['preMainLoop'](); } diff --git a/src/library_fs.js b/src/library_fs.js index 1e7856aa..e6b060f6 100644 --- a/src/library_fs.js +++ b/src/library_fs.js @@ -1102,7 +1102,9 @@ mergeInto(LibraryManager.library, { } } this.message = ERRNO_MESSAGES[errno]; - this.stack = stackTrace(); +#if ASSERTIONS + if (this.stack) this.stack = demangleAll(this.stack); +#endif }; FS.ErrnoError.prototype = new Error(); FS.ErrnoError.prototype.constructor = FS.ErrnoError; diff --git a/src/library_gl.js b/src/library_gl.js index 075d7cb5..61ca8957 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -4,7 +4,7 @@ */ var LibraryGL = { - $GL__postset: 'GL.init()', + $GL__postset: 'var GLctx; GL.init()', $GL: { #if GL_DEBUG debug: true, @@ -22,9 +22,13 @@ var LibraryGL = { #if FULL_ES2 clientBuffers: [], + currArrayBuffer: 0, + currElementArrayBuffer: 0, #endif +#if LEGACY_GL_EMULATION currArrayBuffer: 0, currElementArrayBuffer: 0, +#endif byteSizeByTypeRoot: 0x1400, // GL_BYTE byteSizeByType: [ @@ -53,6 +57,7 @@ var LibraryGL = { unpackAlignment: 4, // default alignment is 4 bytes init: function() { + GL.createLog2ceilLookup(GL.MAX_TEMP_BUFFER_SIZE); Browser.moduleContextCreatedCallbacks.push(GL.initExtensions); }, @@ -77,42 +82,64 @@ var LibraryGL = { miniTempBuffer: null, miniTempBufferViews: [0], // index i has the view of size i+1 - // Large temporary buffers + // When user GL code wants to render from client-side memory, we need to upload the vertex data to a temp VBO + // for rendering. Maintain a set of temp VBOs that are created-on-demand to appropriate sizes, and never destroyed. + // Also, for best performance the VBOs are double-buffered, i.e. every second frame we switch the set of VBOs we + // upload to, so that rendering from the previous frame is not disturbed by uploading from new data to it, which + // could cause a GPU-CPU pipeline stall. + // Note that index buffers are not double-buffered (at the moment) in this manner. MAX_TEMP_BUFFER_SIZE: {{{ GL_MAX_TEMP_BUFFER_SIZE }}}, - tempBufferIndexLookup: null, - tempVertexBuffers: null, - tempIndexBuffers: null, + tempVertexBuffers1: [], + tempVertexBufferCounters1: [], + tempVertexBuffers2: [], + tempVertexBufferCounters2: [], + // Maximum number of temp VBOs of one size to maintain, after that we start reusing old ones, which is safe but can give + // a performance impact. If CPU-GPU stalls are a problem, increasing this might help. + numTempVertexBuffersPerSize: 64, // (const) + tempIndexBuffers: [], tempQuadIndexBuffer: null, - generateTempBuffers: function(quads) { - GL.tempBufferIndexLookup = new Uint8Array(GL.MAX_TEMP_BUFFER_SIZE+1); - GL.tempVertexBuffers = []; - GL.tempIndexBuffers = []; - var last = -1, curr = -1; - var size = 1; - for (var i = 0; i <= GL.MAX_TEMP_BUFFER_SIZE; i++) { - if (i > size) { - size <<= 1; + // Precompute a lookup table for the function ceil(log2(x)), i.e. how many bits are needed to represent x, or, + // if x was rounded up to next pow2, which index is the single '1' bit at? + // Then log2ceilLookup[x] returns ceil(log2(x)). + log2ceilLookup: null, + createLog2ceilLookup: function(maxValue) { + GL.log2ceilLookup = new Uint8Array(maxValue+1); + var log2 = 0; + var pow2 = 1; + GL.log2ceilLookup[0] = 0; + for(var i = 1; i <= maxValue; ++i) { + if (i > pow2) { + pow2 <<= 1; + ++log2; } - if (size != last) { - curr++; - GL.tempVertexBuffers[curr] = Module.ctx.createBuffer(); - Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, GL.tempVertexBuffers[curr]); - Module.ctx.bufferData(Module.ctx.ARRAY_BUFFER, size, Module.ctx.DYNAMIC_DRAW); - Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, null); - GL.tempIndexBuffers[curr] = Module.ctx.createBuffer(); - Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, GL.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; + GL.log2ceilLookup[i] = log2; + } + }, + + generateTempBuffers: function(quads) { + var largestIndex = GL.log2ceilLookup[GL.MAX_TEMP_BUFFER_SIZE]; + GL.tempVertexBufferCounters1.length = GL.tempVertexBufferCounters2.length = largestIndex+1; + GL.tempVertexBuffers1.length = GL.tempVertexBuffers2.length = largestIndex+1; + GL.tempIndexBuffers.length = largestIndex+1; + for(var i = 0; i <= largestIndex; ++i) { + GL.tempIndexBuffers[i] = null; // Created on-demand + GL.tempVertexBufferCounters1[i] = GL.tempVertexBufferCounters2[i] = 0; + var ringbufferLength = GL.numTempVertexBuffersPerSize; + GL.tempVertexBuffers1[i] = []; + GL.tempVertexBuffers2[i] = []; + var ringbuffer1 = GL.tempVertexBuffers1[i]; + var ringbuffer2 = GL.tempVertexBuffers2[i]; + ringbuffer1.length = ringbuffer2.length = ringbufferLength; + for(var j = 0; j < ringbufferLength; ++j) { + ringbuffer1[j] = ringbuffer2[j] = null; // Created on-demand } - GL.tempBufferIndexLookup[i] = curr; } if (quads) { // GL_QUAD indexes can be precalculated - GL.tempQuadIndexBuffer = Module.ctx.createBuffer(); - Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, GL.tempQuadIndexBuffer); + GL.tempQuadIndexBuffer = GLctx.createBuffer(); + GLctx.bindBuffer(GLctx.ELEMENT_ARRAY_BUFFER, GL.tempQuadIndexBuffer); var numIndexes = GL.MAX_TEMP_BUFFER_SIZE >> 1; var quadIndexes = new Uint16Array(numIndexes); var i = 0, v = 0; @@ -131,8 +158,55 @@ var LibraryGL = { 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); + GLctx.bufferData(GLctx.ELEMENT_ARRAY_BUFFER, quadIndexes, GLctx.STATIC_DRAW); + GLctx.bindBuffer(GLctx.ELEMENT_ARRAY_BUFFER, null); + } + }, + + getTempVertexBuffer: function getTempVertexBuffer(sizeBytes) { + var idx = GL.log2ceilLookup[sizeBytes]; + var ringbuffer = GL.tempVertexBuffers1[idx]; + var nextFreeBufferIndex = GL.tempVertexBufferCounters1[idx]; + GL.tempVertexBufferCounters1[idx] = (GL.tempVertexBufferCounters1[idx]+1) & (GL.numTempVertexBuffersPerSize-1); + var vbo = ringbuffer[nextFreeBufferIndex]; + if (vbo) { + return vbo; + } + var prevVBO = GLctx.getParameter(GLctx.ARRAY_BUFFER_BINDING); + ringbuffer[nextFreeBufferIndex] = GLctx.createBuffer(); + GLctx.bindBuffer(GLctx.ARRAY_BUFFER, ringbuffer[nextFreeBufferIndex]); + GLctx.bufferData(GLctx.ARRAY_BUFFER, 1 << idx, GLctx.DYNAMIC_DRAW); + GLctx.bindBuffer(GLctx.ARRAY_BUFFER, prevVBO); + return ringbuffer[nextFreeBufferIndex]; + }, + + getTempIndexBuffer: function getTempIndexBuffer(sizeBytes) { + var idx = GL.log2ceilLookup[sizeBytes]; + var ibo = GL.tempIndexBuffers[idx]; + if (ibo) { + return ibo; + } + var prevIBO = GLctx.getParameter(GLctx.ELEMENT_ARRAY_BUFFER_BINDING); + GL.tempIndexBuffers[idx] = GLctx.createBuffer(); + GLctx.bindBuffer(GLctx.ELEMENT_ARRAY_BUFFER, GL.tempIndexBuffers[idx]); + GLctx.bufferData(GLctx.ELEMENT_ARRAY_BUFFER, 1 << idx, GLctx.DYNAMIC_DRAW); + GLctx.bindBuffer(GLctx.ELEMENT_ARRAY_BUFFER, prevIBO); + return GL.tempIndexBuffers[idx]; + }, + + // Called at start of each new WebGL rendering frame. This swaps the doublebuffered temp VB memory pointers, + // so that every second frame utilizes different set of temp buffers. The aim is to keep the set of buffers + // being rendered, and the set of buffers being updated disjoint. + newRenderingFrameStarted: function newRenderingFrameStarted() { + var vb = GL.tempVertexBuffers1; + GL.tempVertexBuffers1 = GL.tempVertexBuffers2; + GL.tempVertexBuffers2 = vb; + vb = GL.tempVertexBufferCounters1; + GL.tempVertexBufferCounters1 = GL.tempVertexBufferCounters2; + GL.tempVertexBufferCounters2 = vb; + var largestIndex = GL.log2ceilLookup[GL.MAX_TEMP_BUFFER_SIZE]; + for(var i = 0; i <= largestIndex; ++i) { + GL.tempVertexBufferCounters1[i] = 0; } }, @@ -182,13 +256,13 @@ var LibraryGL = { source += frag; } // Let's see if we need to enable the standard derivatives extension - type = Module.ctx.getShaderParameter(GL.shaders[shader], 0x8B4F /* GL_SHADER_TYPE */); + type = GLctx.getShaderParameter(GL.shaders[shader], 0x8B4F /* GL_SHADER_TYPE */); if (type == 0x8B30 /* GL_FRAGMENT_SHADER */) { if (GL.findToken(source, "dFdx") || GL.findToken(source, "dFdy") || GL.findToken(source, "fwidth")) { source = "#extension GL_OES_standard_derivatives : enable\n" + source; - var extension = Module.ctx.getExtension("OES_standard_derivatives"); + var extension = GLctx.getExtension("OES_standard_derivatives"); #if GL_DEBUG if (!extension) { Module.printErr("Shader attempts to use the standard derivatives extension which is not available."); @@ -240,7 +314,7 @@ var LibraryGL = { case 0x86A2: // GL_NUM_COMPRESSED_TEXTURE_FORMATS // WebGL doesn't have GL_NUM_COMPRESSED_TEXTURE_FORMATS (it's obsolete since GL_COMPRESSED_TEXTURE_FORMATS returns a JS array that can be queried for length), // so implement it ourselves to allow C++ GLES2 code get the length. - var formats = Module.ctx.getParameter(0x86A3 /*GL_COMPRESSED_TEXTURE_FORMATS*/); + var formats = GLctx.getParameter(0x86A3 /*GL_COMPRESSED_TEXTURE_FORMATS*/); ret = formats.length; break; case 0x8B9A: // GL_IMPLEMENTATION_COLOR_READ_TYPE @@ -252,7 +326,7 @@ var LibraryGL = { } if (ret === undefined) { - var result = Module.ctx.getParameter(name_); + var result = GLctx.getParameter(name_); switch (typeof(result)) { case "number": ret = result; @@ -391,7 +465,7 @@ var LibraryGL = { default: throw 'Invalid format (' + format + ')'; } - internalFormat = Module.ctx.RGBA; + internalFormat = GLctx.RGBA; break; default: throw 'Invalid type (' + type + ')'; @@ -417,13 +491,13 @@ var LibraryGL = { enableVertexAttribArray: function enableVertexAttribArray(index) { if (!GL.enabledClientAttribIndices[index]) { GL.enabledClientAttribIndices[index] = true; - Module.ctx.enableVertexAttribArray(index); + GLctx.enableVertexAttribArray(index); } }, disableVertexAttribArray: function disableVertexAttribArray(index) { if (GL.enabledClientAttribIndices[index]) { GL.enabledClientAttribIndices[index] = false; - Module.ctx.disableVertexAttribArray(index); + GLctx.disableVertexAttribArray(index); } }, #endif @@ -442,9 +516,6 @@ var LibraryGL = { preDrawHandleClientVertexAttribBindings: function preDrawHandleClientVertexAttribBindings(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) { var cb = GL.clientBuffers[i]; @@ -453,29 +524,21 @@ var LibraryGL = { 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.bufferSubData(Module.ctx.ARRAY_BUFFER, + var buf = GL.getTempVertexBuffer(size); + GLctx.bindBuffer(GLctx.ARRAY_BUFFER, buf); + GLctx.bufferSubData(GLctx.ARRAY_BUFFER, 0, HEAPU8.subarray(cb.ptr, cb.ptr + size)); #if GL_ASSERTIONS GL.validateVertexAttribPointer(cb.size, cb.type, cb.stride, 0); #endif - Module.ctx.vertexAttribPointer(i, cb.size, cb.type, cb.normalized, cb.stride, 0); + GLctx.vertexAttribPointer(i, cb.size, cb.type, cb.normalized, cb.stride, 0); } }, postDrawHandleClientVertexAttribBindings: function postDrawHandleClientVertexAttribBindings() { if (GL.resetBufferBinding) { - Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, GL.buffers[GL.currArrayBuffer]); + GLctx.bindBuffer(GLctx.ARRAY_BUFFER, GL.buffers[GL.currArrayBuffer]); } }, #endif @@ -544,7 +607,7 @@ var LibraryGL = { GL.miniTempBufferViews[i] = GL.miniTempBuffer.subarray(0, i+1); } - GL.maxVertexAttribs = Module.ctx.getParameter(Module.ctx.MAX_VERTEX_ATTRIBS); + GL.maxVertexAttribs = GLctx.getParameter(GLctx.MAX_VERTEX_ATTRIBS); #if FULL_ES2 for (var i = 0; i < GL.maxVertexAttribs; i++) { GL.clientBuffers[i] = { enabled: false, clientside: false, size: 0, type: 0, normalized: 0, stride: 0, ptr: 0 }; @@ -554,18 +617,18 @@ var LibraryGL = { #endif // Detect the presence of a few extensions manually, this GL interop layer itself will need to know if they exist. - GL.compressionExt = Module.ctx.getExtension('WEBGL_compressed_texture_s3tc') || - Module.ctx.getExtension('MOZ_WEBGL_compressed_texture_s3tc') || - Module.ctx.getExtension('WEBKIT_WEBGL_compressed_texture_s3tc'); + GL.compressionExt = GLctx.getExtension('WEBGL_compressed_texture_s3tc') || + GLctx.getExtension('MOZ_WEBGL_compressed_texture_s3tc') || + GLctx.getExtension('WEBKIT_WEBGL_compressed_texture_s3tc'); - GL.anisotropicExt = Module.ctx.getExtension('EXT_texture_filter_anisotropic') || - Module.ctx.getExtension('MOZ_EXT_texture_filter_anisotropic') || - Module.ctx.getExtension('WEBKIT_EXT_texture_filter_anisotropic'); + GL.anisotropicExt = GLctx.getExtension('EXT_texture_filter_anisotropic') || + GLctx.getExtension('MOZ_EXT_texture_filter_anisotropic') || + GLctx.getExtension('WEBKIT_EXT_texture_filter_anisotropic'); - GL.floatExt = Module.ctx.getExtension('OES_texture_float'); + GL.floatExt = GLctx.getExtension('OES_texture_float'); // Extension available from Firefox 26 and Google Chrome 30 - GL.instancedArraysExt = Module.ctx.getExtension('ANGLE_instanced_arrays'); + GL.instancedArraysExt = GLctx.getExtension('ANGLE_instanced_arrays'); // These are the 'safe' feature-enabling extensions that don't add any performance impact related to e.g. debugging, and // should be enabled by default so that client GLES2/GL code will not need to go through extra hoops to get its stuff working. @@ -589,11 +652,11 @@ var LibraryGL = { return false; } - var extensions = Module.ctx.getSupportedExtensions(); + var extensions = GLctx.getSupportedExtensions(); for(var e in extensions) { var ext = extensions[e].replace('MOZ_', '').replace('WEBKIT_', ''); if (automaticallyEnabledExtensions.indexOf(ext) != -1) { - Module.ctx.getExtension(ext); // Calling .getExtension enables that extension permanently, no need to store the return value to be enabled. + GLctx.getExtension(ext); // Calling .getExtension enables that extension permanently, no need to store the return value to be enabled. } } }, @@ -620,9 +683,9 @@ var LibraryGL = { var utable = ptable.uniforms; // A program's uniform table maps the string name of an uniform to an integer location of that uniform. // The global GL.uniforms map maps integer locations to WebGLUniformLocations. - var numUniforms = Module.ctx.getProgramParameter(p, Module.ctx.ACTIVE_UNIFORMS); + var numUniforms = GLctx.getProgramParameter(p, GLctx.ACTIVE_UNIFORMS); for (var i = 0; i < numUniforms; ++i) { - var u = Module.ctx.getActiveUniform(p, i); + var u = GLctx.getActiveUniform(p, i); var name = u.name; ptable.maxUniformLength = Math.max(ptable.maxUniformLength, name.length+1); @@ -636,14 +699,14 @@ var LibraryGL = { // Optimize memory usage slightly: If we have an array of uniforms, e.g. 'vec3 colors[3];', then // only store the string 'colors' in utable, and 'colors[0]', 'colors[1]' and 'colors[2]' will be parsed as 'colors'+i. // Note that for the GL.uniforms table, we still need to fetch the all WebGLUniformLocations for all the indices. - var loc = Module.ctx.getUniformLocation(p, name); + var loc = GLctx.getUniformLocation(p, name); var id = GL.getNewId(GL.uniforms); utable[name] = [u.size, id]; GL.uniforms[id] = loc; for (var j = 1; j < u.size; ++j) { var n = name + '['+j+']'; - loc = Module.ctx.getUniformLocation(p, n); + loc = GLctx.getUniformLocation(p, n); id = GL.getNewId(GL.uniforms); GL.uniforms[id] = loc; @@ -659,7 +722,7 @@ var LibraryGL = { } else if (pname == 0x0cf5 /* GL_UNPACK_ALIGNMENT */) { GL.unpackAlignment = param; } - Module.ctx.pixelStorei(pname, param); + GLctx.pixelStorei(pname, param); }, glGetString__sig: 'ii', @@ -670,10 +733,10 @@ var LibraryGL = { case 0x1F00 /* GL_VENDOR */: case 0x1F01 /* GL_RENDERER */: case 0x1F02 /* GL_VERSION */: - ret = allocate(intArrayFromString(Module.ctx.getParameter(name_)), 'i8', ALLOC_NORMAL); + ret = allocate(intArrayFromString(GLctx.getParameter(name_)), 'i8', ALLOC_NORMAL); break; case 0x1F03 /* GL_EXTENSIONS */: - var exts = Module.ctx.getSupportedExtensions(); + var exts = GLctx.getSupportedExtensions(); var gl_exts = []; for (i in exts) { gl_exts.push(exts[i]); @@ -714,7 +777,7 @@ var LibraryGL = { glGenTextures: function(n, textures) { for (var i = 0; i < n; i++) { var id = GL.getNewId(GL.textures); - var texture = Module.ctx.createTexture(); + var texture = GLctx.createTexture(); texture.name = id; GL.textures[id] = texture; {{{ makeSetValue('textures', 'i*4', 'id', 'i32') }}}; @@ -726,7 +789,7 @@ var LibraryGL = { for (var i = 0; i < n; i++) { var id = {{{ makeGetValue('textures', 'i*4', 'i32') }}}; var texture = GL.textures[id]; - Module.ctx.deleteTexture(texture); + GLctx.deleteTexture(texture); texture.name = 0; GL.textures[id] = null; } @@ -742,7 +805,8 @@ var LibraryGL = { } else { data = null; } - Module.ctx['compressedTexImage2D'](target, level, internalFormat, width, height, border, data); + // N.b. using array notation explicitly to not confuse Closure minification. + GLctx['compressedTexImage2D'](target, level, internalFormat, width, height, border, data); }, glCompressedTexSubImage2D__sig: 'viiiiiiiii', @@ -755,7 +819,7 @@ var LibraryGL = { } else { data = null; } - Module.ctx['compressedTexSubImage2D'](target, level, xoffset, yoffset, width, height, data); + CLctx['compressedTexSubImage2D'](target, level, xoffset, yoffset, width, height, data); }, glTexImage2D__sig: 'viiiiiiiii', @@ -767,7 +831,7 @@ var LibraryGL = { } else { pixels = null; } - Module.ctx.texImage2D(target, level, internalFormat, width, height, border, format, type, pixels); + GLctx.texImage2D(target, level, internalFormat, width, height, border, format, type, pixels); }, |