From d0333811ee85131a9bcc8791d9542e38e762cc0e Mon Sep 17 00:00:00 2001 From: AlexPerrot Date: Tue, 7 Jan 2014 11:50:38 +0100 Subject: [PATCH 01/42] Implementing keycodes for numpad numbered keys. They return the same keycode as the numbers on the main keyboard. --- src/library_glut.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/library_glut.js b/src/library_glut.js index 76a52b7354763..ad85b0c82a8e0 100644 --- a/src/library_glut.js +++ b/src/library_glut.js @@ -122,6 +122,8 @@ var LibraryGLUT = { return keycode; // numeric TODO handle shift? if (65 <= keycode && keycode <= 90) return event['shiftKey'] ? keycode : keycode + 32; + if (96 <= keycode && keycode <= 105) + return keycode - 48; // numpad numbers if (106 <= keycode && keycode <= 111) return keycode - 106 + 42; // *,+-./ TODO handle shift? From b6395a1b86e06b3ed65ee0e0eee6dfc592c688fa Mon Sep 17 00:00:00 2001 From: AlexPerrot Date: Tue, 7 Jan 2014 13:39:33 +0100 Subject: [PATCH 02/42] Adding myself to AUTHORS file --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index 7e10ceab31da8..001af087ac6c5 100644 --- a/AUTHORS +++ b/AUTHORS @@ -115,3 +115,4 @@ a license to everyone to use it as detailed in LICENSE.) * Adam C. Clifton * Volo Zyko * Andre Weissflog +* Alexandre Perrot \ No newline at end of file From 3bb84257eac6bcf74e80dab5559fdc436773ccd6 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Tue, 7 Jan 2014 15:51:55 -0800 Subject: [PATCH 03/42] update other.test_simd test for llvm 3.3 and 3.4 --- src/settings.js | 1 + tests/test_other.py | 11 ++++++++++- tools/shared.py | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/settings.js b/src/settings.js index 04b2cc79ea99c..720fb53f49e5c 100644 --- a/src/settings.js +++ b/src/settings.js @@ -123,6 +123,7 @@ var PRECISE_F32 = 0; // 0: Use JS numbers for floating-point values. These are 6 // 2: Model C++ floats precisely using Math.fround if available in the JS engine, otherwise // use an empty polyfill. This will have less of a speed penalty than using the full // polyfill in cases where engine support is not present. +var SIMD = 0; // Whether to emit SIMD code ( https://github.com/johnmccutchan/ecmascript_simd ) var CLOSURE_ANNOTATIONS = 0; // If set, the generated code will be annotated for the closure // compiler. This potentially lets closure optimize the code better. diff --git a/tests/test_other.py b/tests/test_other.py index f9ee2d9d27112..3f9bd93c517ba 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -2152,8 +2152,17 @@ def test_fs_stream_proto(self): def test_simd(self): if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') + if get_clang_version() == '3.2': + simd_args = ['-O3', '-vectorize', '-vectorize-loops', '-bb-vectorize-vector-bits=128', '-force-vector-width=4'] + elif get_clang_version() == '3.3': + simd_args = ['-O3', '-vectorize-loops', '-vectorize-slp', '-vectorize-slp-aggressive'] + elif get_clang_version() == '3.4': + simd_args = ['-O3'] # vectorization on by default, SIMD=1 makes us not disable it + else: + raise Exception('unknown llvm version') + self.clear() - Popen([PYTHON, EMCC, path_from_root('tests', 'linpack.c'), '-O2', '-DSP', '--llvm-opts', '''['-O3', '-vectorize', '-vectorize-loops', '-bb-vectorize-vector-bits=128', '-force-vector-width=4']''']).communicate() + Popen([PYTHON, EMCC, path_from_root('tests', 'linpack.c'), '-O2', '-s', 'SIMD=1', '-DSP', '--llvm-opts', str(simd_args)]).communicate() self.assertContained('Unrolled Single Precision', run_js('a.out.js')) def test_dependency_file(self): diff --git a/tools/shared.py b/tools/shared.py index 4ab476d3a9cce..eac4b6588b75b 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -1171,7 +1171,7 @@ def llvm_opt(filename, opts, out=None): if type(opts) is int: opts = Building.pick_llvm_opts(opts) #opts += ['-debug-pass=Arguments'] - if get_clang_version() == '3.4': + if get_clang_version() == '3.4' and not Settings.SIMD: opts += ['-disable-loop-vectorization', '-disable-slp-vectorization'] # llvm 3.4 has these on by default logging.debug('emcc: LLVM opts: ' + str(opts)) target = out or (filename + '.opt.bc') From 9ca7d4129ee227ffdb3e53b0bda94e424e19ab18 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Tue, 7 Jan 2014 17:52:36 -0800 Subject: [PATCH 04/42] notice simd signal from fastcomp --- emscripten.py | 3 +++ src/jsifier.js | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/emscripten.py b/emscripten.py index 42db080352888..1a3bddd749fa2 100755 --- a/emscripten.py +++ b/emscripten.py @@ -804,6 +804,9 @@ def fix_dot_zero(m): map(lambda x: x[1:], metadata['implementedFunctions']) ) ) + map(lambda x: x[1:], metadata['externs']) + if metadata['simd']: + settings['SIMD'] = 1 + settings['ASM_JS'] = 2 # Save settings to a file to work around v8 issue 1579 settings_file = temp_files.get('.txt').name diff --git a/src/jsifier.js b/src/jsifier.js index 8de20c809dec9..a503e90d90707 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -1871,7 +1871,7 @@ function JSify(data, functionsOnly) { 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')); } From 1821ecec0b64b539d8bc52624687d97abb834c0d Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Tue, 7 Jan 2014 18:29:34 -0800 Subject: [PATCH 05/42] fix test_lua --- tests/test_core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_core.py b/tests/test_core.py index 1dc25dce1c278..ed01c5383db22 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -4652,7 +4652,7 @@ def test_lua(self): if Settings.QUANTUM_SIZE == 1: return self.skip('TODO: make this work') if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') - for aggro in ([0, 1] if '-O2' in self.emcc_args else [0]): + for aggro in ([0, 1] if Settings.ASM_JS and '-O2' in self.emcc_args else [0]): print aggro Settings.AGGRESSIVE_VARIABLE_ELIMINATION = aggro self.do_run('', From e9e70172fabe16015246cb52003d9b058b69d63f Mon Sep 17 00:00:00 2001 From: AlexPerrot Date: Wed, 8 Jan 2014 09:17:07 +0100 Subject: [PATCH 06/42] fixing indentation --- src/library_glut.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library_glut.js b/src/library_glut.js index ad85b0c82a8e0..65ac10c4388eb 100644 --- a/src/library_glut.js +++ b/src/library_glut.js @@ -123,7 +123,7 @@ var LibraryGLUT = { if (65 <= keycode && keycode <= 90) return event['shiftKey'] ? keycode : keycode + 32; if (96 <= keycode && keycode <= 105) - return keycode - 48; // numpad numbers + return keycode - 48; // numpad numbers if (106 <= keycode && keycode <= 111) return keycode - 106 + 42; // *,+-./ TODO handle shift? From c23a8a7d29effb37a00c3eb161c22d2027566187 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 8 Jan 2014 11:08:04 -0800 Subject: [PATCH 07/42] enable simd tests in fastcomp --- tests/test_core.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/test_core.py b/tests/test_core.py index ed01c5383db22..2157eeb0c8574 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -4604,7 +4604,6 @@ def test_cubescript(self): def test_simd(self): if Settings.USE_TYPED_ARRAYS != 2: return self.skip('needs ta2') if Settings.ASM_JS: Settings.ASM_JS = 2 # does not validate - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') test_path = path_from_root('tests', 'core', 'test_simd') src, output = (test_path + s for s in ('.in', '.out')) @@ -4613,7 +4612,6 @@ def test_simd(self): def test_simd2(self): if Settings.ASM_JS: Settings.ASM_JS = 2 # does not validate - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') test_path = path_from_root('tests', 'core', 'test_simd2') src, output = (test_path + s for s in ('.in', '.out')) @@ -4623,7 +4621,6 @@ def test_simd2(self): def test_simd3(self): if Settings.USE_TYPED_ARRAYS != 2: return self.skip('needs ta2') if Settings.ASM_JS: Settings.ASM_JS = 2 # does not validate - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') test_path = path_from_root('tests', 'core', 'test_simd3') src, output = (test_path + s for s in ('.in', '.out')) From 6a95326c3b8f577652457a3f5f410cb70fce587c Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 8 Jan 2014 11:43:21 -0800 Subject: [PATCH 08/42] fix and enable other.test_simd on fastcomp --- tests/test_other.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_other.py b/tests/test_other.py index 3f9bd93c517ba..c5f0c58334516 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -2150,17 +2150,17 @@ def test_fs_stream_proto(self): self.assertContained('File size: 722', out) def test_simd(self): - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') - if get_clang_version() == '3.2': - simd_args = ['-O3', '-vectorize', '-vectorize-loops', '-bb-vectorize-vector-bits=128', '-force-vector-width=4'] + simd_args = ['-O3', '-vectorize', '-vectorize-loops'] elif get_clang_version() == '3.3': - simd_args = ['-O3', '-vectorize-loops', '-vectorize-slp', '-vectorize-slp-aggressive'] + simd_args = ['-O3', '-vectorize-loops', '-vectorize-slp-aggressive', '-bb-vectorize-aligned-only'] # XXX this generates <2 x float> , '-vectorize-slp'] elif get_clang_version() == '3.4': simd_args = ['-O3'] # vectorization on by default, SIMD=1 makes us not disable it else: raise Exception('unknown llvm version') + simd_args += ['-bb-vectorize-vector-bits=128', '-force-vector-width=4'] + self.clear() Popen([PYTHON, EMCC, path_from_root('tests', 'linpack.c'), '-O2', '-s', 'SIMD=1', '-DSP', '--llvm-opts', str(simd_args)]).communicate() self.assertContained('Unrolled Single Precision', run_js('a.out.js')) From ed095a832d015fb8523d643d2b311124e000bfdf Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 8 Jan 2014 13:51:11 -0800 Subject: [PATCH 09/42] do minified name generation in js-optimizer.js, so that we have no more fixed limit on the # of minified names --- tools/js-optimizer.js | 44 ++++++++++++++++++++++++++++++++++++------- tools/js_optimizer.py | 32 +++---------------------------- 2 files changed, 40 insertions(+), 36 deletions(-) diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index b507a45ab1f5a..5324e15c96008 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -1743,6 +1743,36 @@ function getStackBumpSize(ast) { return node ? node[3][2][3][1] : 0; } +// Name minification + +var RESERVED = set('do', 'if', 'in', 'for', 'new', 'try', 'var', 'env', 'let'); +var VALID_MIN_INITS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$'; +var VALID_MIN_LATERS = VALID_MIN_INITS + '0123456789'; + +var minifiedNames = []; +var minifiedState = [0]; + +function ensureMinifiedNames(n) { // make sure the nth index in minifiedNames exists. done 100% deterministically + while (minifiedNames.length < n+1) { + // generate the current name + var name = VALID_MIN_INITS[minifiedState[0]]; + for (var i = 1; i < minifiedState.length; i++) { + name += VALID_MIN_LATERS[minifiedState[i]]; + } + if (!(name in RESERVED)) minifiedNames.push(name); + // increment the state + var i = 0; + while (1) { + minifiedState[i]++; + if (minifiedState[i] < (i === 0 ? VALID_MIN_INITS : VALID_MIN_LATERS).length) break; + // overflow + minifiedState[i] = 0; + i++; + if (i === minifiedState.length) minifiedState.push(-1); // will become 0 after increment in next loop head + } + } +} + // Very simple 'registerization', coalescing of variables into a smaller number, // as part of minification. Globals-level minification began in a previous pass, // we receive extraInfo which tells us how to rename globals. (Only in asm.js.) @@ -1853,14 +1883,14 @@ function registerize(ast) { return ret; } // find the next free minified name that is not used by a global that shows up in this function - while (nextRegName < extraInfo.names.length) { - var ret = extraInfo.names[nextRegName++]; + while (1) { + ensureMinifiedNames(nextRegName); + var ret = minifiedNames[nextRegName++]; if (!usedGlobals[ret]) { regTypes[ret] = type; return ret; } } - assert('ran out of names'); } // Find the # of uses of each variable. // While doing so, check if all a variable's uses are dominated in a simple @@ -2847,16 +2877,16 @@ function minifyGlobals(ast) { var vars = node[1]; for (var i = 0; i < vars.length; i++) { var name = vars[i][0]; - assert(next < extraInfo.names.length); - vars[i][0] = minified[name] = extraInfo.names[next++]; + ensureMinifiedNames(next); + vars[i][0] = minified[name] = minifiedNames[next++]; } } }); // add all globals in function chunks, i.e. not here but passed to us for (var i = 0; i < extraInfo.globals.length; i++) { name = extraInfo.globals[i]; - assert(next < extraInfo.names.length); - minified[name] = extraInfo.names[next++]; + ensureMinifiedNames(next); + minified[name] = minifiedNames[next++]; } // apply minification traverse(ast, function(node, type) { diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index dcc9cd5f825a0..d5b1df279e6f5 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -24,41 +24,16 @@ def path_from_root(*pathelems): class Minifier: ''' - asm.js minification support. We calculate possible names and minification of + asm.js minification support. We calculate minification of globals here, then pass that into the parallel js-optimizer.js runners which during registerize perform minification of locals. ''' - def __init__(self, js, js_engine, MAX_NAMES): + def __init__(self, js, js_engine): self.js = js self.js_engine = js_engine - MAX_NAMES = min(MAX_NAMES, 120000) - - # Create list of valid short names - - INVALID_2 = set(['do', 'if', 'in']) - INVALID_3 = set(['for', 'new', 'try', 'var', 'env', 'let']) - - self.names = [] - init_possibles = string.ascii_letters + '_$' - later_possibles = init_possibles + string.digits - for a in init_possibles: - if len(self.names) >= MAX_NAMES: break - self.names.append(a) - for a in init_possibles: - for b in later_possibles: - if len(self.names) >= MAX_NAMES: break - curr = a + b - if curr not in INVALID_2: self.names.append(curr) - for a in init_possibles: - for b in later_possibles: - for c in later_possibles: - if len(self.names) >= MAX_NAMES: break - curr = a + b + c - if curr not in INVALID_3: self.names.append(curr) def minify_shell(self, shell, minify_whitespace, source_map=False): - #print >> sys.stderr, "MINIFY SHELL 1111111111", shell, "\n222222222222222" # Run through js-optimizer.js to find and minify the global symbols # We send it the globals, which it parses at the proper time. JS decides how # to minify all global names, we receive a dictionary back, which is then @@ -91,7 +66,6 @@ def minify_shell(self, shell, minify_whitespace, source_map=False): def serialize(self): return { - 'names': self.names, 'globals': self.globs } @@ -187,7 +161,7 @@ def process(line): js = js[start_funcs + len(start_funcs_marker):end_funcs] # we assume there is a maximum of one new name per line - minifier = Minifier(js, js_engine, js.count('\n') + asm_shell.count('\n')) + minifier = Minifier(js, js_engine) asm_shell_pre, asm_shell_post = minifier.minify_shell(asm_shell, 'minifyWhitespace' in passes, source_map).split('EMSCRIPTEN_FUNCS();'); asm_shell_post = asm_shell_post.replace('});', '})'); pre += asm_shell_pre + '\n' + start_funcs_marker From be066182974f44a6efce0cb6339d0b15982182b0 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 8 Jan 2014 16:11:23 -0800 Subject: [PATCH 10/42] verify imul correctness, workaround for webkit bug 126345; closes #1991 --- src/preamble.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/preamble.js b/src/preamble.js index f9fccdf6a01c2..ac6ee7b32365d 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -1090,7 +1090,8 @@ Module['writeAsciiToMemory'] = writeAsciiToMemory; {{{ reSign }}} #if PRECISE_I32_MUL -if (!Math['imul']) Math['imul'] = function imul(a, b) { +// check for imul support, and also for correctness ( https://bugs.webkit.org/show_bug.cgi?id=126345 ) +if (!Math['imul'] || Math['imul'](0xffffffff, 5) !== -5) Math['imul'] = function imul(a, b) { var ah = a >>> 16; var al = a & 0xffff; var bh = b >>> 16; From d8048f8df3ca432543c34981756e1d59c8e3b9c5 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 8 Jan 2014 16:18:53 -0800 Subject: [PATCH 11/42] fix relooper compiler warnings --- src/relooper/Relooper.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/relooper/Relooper.h b/src/relooper/Relooper.h index 04f2ffc394b83..dfabcabbec7b9 100644 --- a/src/relooper/Relooper.h +++ b/src/relooper/Relooper.h @@ -89,11 +89,11 @@ struct Block { // setjmp returns, etc.) // -class SimpleShape; -class LabeledShape; -class MultipleShape; -class LoopShape; -class EmulatedShape; +struct SimpleShape; +struct LabeledShape; +struct MultipleShape; +struct LoopShape; +struct EmulatedShape; struct Shape { int Id; // A unique identifier. Used to identify loops, labels are Lx where x is the Id. Defined when added to relooper From 63aba3b4a4653ec5079f0f6fa4273053e1c750dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Thu, 9 Jan 2014 18:44:19 +0200 Subject: [PATCH 12/42] Fix GL emulation problems that caused particles and ground to disappear in Bananabread demo, caused by previous commit https://github.com/kripken/emscripten/commit/fc5dd62fc359397245aca85b1cc847393ba5858f that only partially tracked the changes to the FFP emulation state. --- src/library_gl.js | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/library_gl.js b/src/library_gl.js index 075d7cb5ade07..19e64c32b0e31 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -1777,7 +1777,10 @@ var LibraryGL = { // skipping renderer setup is aimed at the case of multiple glDraw* right after each other if (GL.immediate.lastRenderer) GL.immediate.lastRenderer.cleanup(); if (cap == 0x0B60 /* GL_FOG */) { - GLEmulation.fogEnabled = true; + if (GLEmulation.fogEnabled != true) { + GL.immediate.currentRenderer = null; // Fog parameter is part of the FFP shader state, we must re-lookup the renderer to use. + GLEmulation.fogEnabled = true; + } return; } else if (cap == 0x0de1 /* GL_TEXTURE_2D */) { // XXX not according to spec, and not in desktop GL, but works in some GLES1.x apparently, so support @@ -1797,7 +1800,10 @@ var LibraryGL = { _glDisable = function _glDisable(cap) { if (GL.immediate.lastRenderer) GL.immediate.lastRenderer.cleanup(); if (cap == 0x0B60 /* GL_FOG */) { - GLEmulation.fogEnabled = false; + if (GLEmulation.fogEnabled != false) { + GL.immediate.currentRenderer = null; // Fog parameter is part of the FFP shader state, we must re-lookup the renderer to use. + GLEmulation.fogEnabled = false; + } return; } else if (cap == 0x0de1 /* GL_TEXTURE_2D */) { // XXX not according to spec, and not in desktop GL, but works in some GLES1.x apparently, so support @@ -2104,7 +2110,7 @@ var LibraryGL = { } #endif if (GL.currProgram != program) { - GL.currentRenderer = null; // This changes the FFP emulation shader program, need to recompute that. + GL.immediate.currentRenderer = null; // This changes the FFP emulation shader program, need to recompute that. GL.currProgram = program; } glUseProgram(program); @@ -2113,7 +2119,10 @@ var LibraryGL = { var glDeleteProgram = _glDeleteProgram; _glDeleteProgram = function _glDeleteProgram(program) { glDeleteProgram(program); - if (program == GL.currProgram) GL.currProgram = 0; + if (program == GL.currProgram) { + GL.immediate.currentRenderer = null; // This changes the FFP emulation shader program, need to recompute that. + GL.currProgram = 0; + } }; // If attribute 0 was not bound, bind it to 0 for WebGL performance reasons. Track if 0 is free for that. @@ -4270,7 +4279,7 @@ var LibraryGL = { // Pop the old state: GL.immediate.enabledClientAttributes = GL.immediate.enabledClientAttributes_preBegin; GL.immediate.clientAttributes = GL.immediate.clientAttributes_preBegin; - + GL.immediate.currentRenderer = null; // The set of active client attributes changed, we must re-lookup the renderer to use. GL.immediate.modifiedClientAttributes = true; }, @@ -4409,9 +4418,17 @@ var LibraryGL = { switch (param) { case 0x0801: // GL_EXP2 case 0x2601: // GL_LINEAR - GLEmulation.fogMode = param; break; + if (GLEmulation.fogMode != param) { + GL.immediate.currentRenderer = null; // Fog mode is part of the FFP shader state, we must re-lookup the renderer to use. + GLEmulation.fogMode = param; + } + break; default: // default to GL_EXP - GLEmulation.fogMode = 0x0800 /* GL_EXP */; break; + if (GLEmulation.fogMode != 0x0800 /* GL_EXP */) { + GL.immediate.currentRenderer = null; // Fog mode is part of the FFP shader state, we must re-lookup the renderer to use. + GLEmulation.fogMode = 0x0800 /* GL_EXP */; + } + break; } break; } From 08af8ec7784fa0263f7bd319aac42be89d094587 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Thu, 2 Jan 2014 17:35:49 +0200 Subject: [PATCH 13/42] Minor optimization to FFP emulation: Use integers instead of strings as key to FFP matrix file. This allows using arrays instead of maps to store the file, and avoids unnecessary string operations. --- src/library_gl.js | 60 +++++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/library_gl.js b/src/library_gl.js index 19e64c32b0e31..20c7d85e3320a 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -2158,11 +2158,11 @@ var LibraryGL = { var glGetFloatv = _glGetFloatv; _glGetFloatv = function _glGetFloatv(pname, params) { if (pname == 0x0BA6) { // GL_MODELVIEW_MATRIX - HEAPF32.set(GL.immediate.matrix['m'], params >> 2); + HEAPF32.set(GL.immediate.matrix[0/*m*/], params >> 2); } else if (pname == 0x0BA7) { // GL_PROJECTION_MATRIX - HEAPF32.set(GL.immediate.matrix['p'], params >> 2); + HEAPF32.set(GL.immediate.matrix[1/*p*/], params >> 2); } else if (pname == 0x0BA8) { // GL_TEXTURE_MATRIX - HEAPF32.set(GL.immediate.matrix['t' + GL.immediate.clientActiveTexture], params >> 2); + HEAPF32.set(GL.immediate.matrix[2/*t*/ + GL.immediate.clientActiveTexture], params >> 2); } else if (pname == 0x0B66) { // GL_FOG_COLOR HEAPF32.set(GLEmulation.fogColor, params >> 2); } else if (pname == 0x0B63) { // GL_FOG_START @@ -3334,9 +3334,9 @@ var LibraryGL = { lastStride: -1, // "" // The following data structures are used for OpenGL Immediate Mode matrix routines. - matrix: {}, - matrixStack: {}, - currentMatrix: 'm', // default is modelview + matrix: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], + matrixStack: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], + currentMatrix: 0, // default is modelview tempMatrix: null, matricesModified: false, useTextureMatrix: false, @@ -3635,9 +3635,9 @@ var LibraryGL = { Module.ctx.linkProgram(this.program); } - // Stores a map that remembers which matrix uniforms are up-to-date in this FFP renderer, so they don't need to be resubmitted + // Stores an array that remembers which matrix uniforms are up-to-date in this FFP renderer, so they don't need to be resubmitted // each time we render with this program. - this.textureMatrixVersion = {}; + this.textureMatrixVersion = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]; this.positionLocation = Module.ctx.getAttribLocation(this.program, 'a_position'); @@ -3749,13 +3749,13 @@ var LibraryGL = { GL.immediate.fixedFunctionProgram = this.program; } - if (this.modelViewLocation && this.modelViewMatrixVersion != GL.immediate.matrixVersion['m']) { - this.modelViewMatrixVersion = GL.immediate.matrixVersion['m']; - Module.ctx.uniformMatrix4fv(this.modelViewLocation, false, GL.immediate.matrix['m']); + if (this.modelViewLocation && this.modelViewMatrixVersion != GL.immediate.matrixVersion[0/*m*/]) { + this.modelViewMatrixVersion = GL.immediate.matrixVersion[0/*m*/]; + Module.ctx.uniformMatrix4fv(this.modelViewLocation, false, GL.immediate.matrix[0/*m*/]); } - if (this.projectionLocation && this.projectionMatrixVersion != GL.immediate.matrixVersion['p']) { - this.projectionMatrixVersion = GL.immediate.matrixVersion['p']; - Module.ctx.uniformMatrix4fv(this.projectionLocation, false, GL.immediate.matrix['p']); + if (this.projectionLocation && this.projectionMatrixVersion != GL.immediate.matrixVersion[1/*p*/]) { + this.projectionMatrixVersion = GL.immediate.matrixVersion[1/*p*/]; + Module.ctx.uniformMatrix4fv(this.projectionLocation, false, GL.immediate.matrix[1/*p*/]); } var clientAttributes = GL.immediate.clientAttributes; @@ -3819,7 +3819,7 @@ var LibraryGL = { Module.ctx.disableVertexAttribArray(attribLoc); } #endif - var t = 't'+i; + var t = 2/*t*/+i; if (this.textureMatrixLocations[i] && this.textureMatrixVersion[t] != GL.immediate.matrixVersion[t]) { // XXX might we need this even without the condition we are currently in? this.textureMatrixVersion[t] = GL.immediate.matrixVersion[t]; Module.ctx.uniformMatrix4fv(this.textureMatrixLocations[i], false, GL.immediate.matrix[t]); @@ -4027,25 +4027,25 @@ var LibraryGL = { GLEmulation.enabledClientAttribIndices.push(false); } - this.matrixStack['m'] = []; - this.matrixStack['p'] = []; + this.matrixStack[0/*m*/] = []; + this.matrixStack[1/*p*/] = []; for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) { - this.matrixStack['t' + i] = []; + this.matrixStack[2/*t*/ + i] = []; } // Initialize matrix library // When user sets a matrix, increment a 'version number' on the new data, and when rendering, submit // the matrices to the shader program only if they have an old version of the data. - GL.immediate.matrixVersion = {}; - GL.immediate.matrix['m'] = GL.immediate.matrix.lib.mat4.create(); - GL.immediate.matrixVersion['m'] = 0; - GL.immediate.matrix.lib.mat4.identity(GL.immediate.matrix['m']); - GL.immediate.matrix['p'] = GL.immediate.matrix.lib.mat4.create(); - GL.immediate.matrixVersion['p'] = 0; - GL.immediate.matrix.lib.mat4.identity(GL.immediate.matrix['p']); + GL.immediate.matrixVersion = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]; + GL.immediate.matrix[0/*m*/] = GL.immediate.matrix.lib.mat4.create(); + GL.immediate.matrixVersion[0/*m*/] = 0; + GL.immediate.matrix.lib.mat4.identity(GL.immediate.matrix[0/*m*/]); + GL.immediate.matrix[1/*p*/] = GL.immediate.matrix.lib.mat4.create(); + GL.immediate.matrixVersion[1/*p*/] = 0; + GL.immediate.matrix.lib.mat4.identity(GL.immediate.matrix[1/*p*/]); for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) { - GL.immediate.matrix['t' + i] = GL.immediate.matrix.lib.mat4.create(); - GL.immediate.matrixVersion['t' + i] = 0; + GL.immediate.matrix[2/*t*/ + i] = GL.immediate.matrix.lib.mat4.create(); + GL.immediate.matrixVersion[2/*t*/ + i] = 0; } // Renderer cache @@ -4613,12 +4613,12 @@ var LibraryGL = { glMatrixMode__deps: ['$GL', '$GLImmediateSetup', '$GLEmulation'], // emulation is not strictly needed, this is a workaround glMatrixMode: function(mode) { if (mode == 0x1700 /* GL_MODELVIEW */) { - GL.immediate.currentMatrix = 'm'; + GL.immediate.currentMatrix = 0/*m*/; } else if (mode == 0x1701 /* GL_PROJECTION */) { - GL.immediate.currentMatrix = 'p'; + GL.immediate.currentMatrix = 1/*p*/; } else if (mode == 0x1702) { // GL_TEXTURE GL.immediate.useTextureMatrix = true; - GL.immediate.currentMatrix = 't' + GL.immediate.clientActiveTexture; + GL.immediate.currentMatrix = 2/*t*/ + GL.immediate.clientActiveTexture; } else { throw "Wrong mode " + mode + " passed to glMatrixMode"; } From c6582b7766e7754032f6fb7aae278f7f77090615 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Thu, 2 Jan 2014 18:00:32 +0200 Subject: [PATCH 14/42] Optimize GL FFP emulation layer by omitting redundant glUseProgram for identical shader programs. --- src/library_gl.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/library_gl.js b/src/library_gl.js index 20c7d85e3320a..3e022539d5567 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -2112,8 +2112,9 @@ var LibraryGL = { if (GL.currProgram != program) { GL.immediate.currentRenderer = null; // This changes the FFP emulation shader program, need to recompute that. GL.currProgram = program; + GL.immediate.fixedFunctionProgram = 0; + glUseProgram(program); } - glUseProgram(program); } var glDeleteProgram = _glDeleteProgram; @@ -3745,8 +3746,10 @@ var LibraryGL = { #endif if (!GL.currProgram) { - Module.ctx.useProgram(this.program); - GL.immediate.fixedFunctionProgram = this.program; + if (GL.immediate.fixedFunctionProgram != this.program) { + Module.ctx.useProgram(this.program); + GL.immediate.fixedFunctionProgram = this.program; + } } if (this.modelViewLocation && this.modelViewMatrixVersion != GL.immediate.matrixVersion[0/*m*/]) { From 8e69ae1e19523a15c1f9328f3c0e757c0661dc4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Thu, 2 Jan 2014 19:12:56 +0200 Subject: [PATCH 15/42] Optimize glEnableClientState by avoiding it to be called with different param count. --- src/library_gl.js | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/library_gl.js b/src/library_gl.js index 3e022539d5567..203721f8d4c15 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -4485,7 +4485,7 @@ var LibraryGL = { // ClientState/gl*Pointer - glEnableClientState: function(cap, disable) { + glEnableClientState: function(cap) { var attrib = GLEmulation.getAttributeFromCapability(cap); if (attrib === null) { #if ASSERTIONS @@ -4493,21 +4493,29 @@ var LibraryGL = { #endif return; } - if (disable && GL.immediate.enabledClientAttributes[attrib]) { - GL.immediate.enabledClientAttributes[attrib] = false; - GL.immediate.totalEnabledClientAttributes--; - this.currentRenderer = null; // Will need to change current renderer, since the set of active vertex pointers changed. - if (GLEmulation.currentVao) delete GLEmulation.currentVao.enabledClientStates[cap]; - } else if (!disable && !GL.immediate.enabledClientAttributes[attrib]) { + if (!GL.immediate.enabledClientAttributes[attrib]) { GL.immediate.enabledClientAttributes[attrib] = true; GL.immediate.totalEnabledClientAttributes++; this.currentRenderer = null; // Will need to change current renderer, since the set of active vertex pointers changed. if (GLEmulation.currentVao) GLEmulation.currentVao.enabledClientStates[cap] = 1; + GL.immediate.modifiedClientAttributes = true; } - GL.immediate.modifiedClientAttributes = true; }, glDisableClientState: function(cap) { - _glEnableClientState(cap, 1); + var attrib = GLEmulation.getAttributeFromCapability(cap); + if (attrib === null) { +#if ASSERTIONS + Module.printErr('WARNING: unhandled clientstate: ' + cap); +#endif + return; + } + if (GL.immediate.enabledClientAttributes[attrib]) { + GL.immediate.enabledClientAttributes[attrib] = false; + GL.immediate.totalEnabledClientAttributes--; + this.currentRenderer = null; // Will need to change current renderer, since the set of active vertex pointers changed. + if (GLEmulation.currentVao) delete GLEmulation.currentVao.enabledClientStates[cap]; + GL.immediate.modifiedClientAttributes = true; + } }, glVertexPointer__deps: ['$GLEmulation'], // if any pointers are used, glVertexPointer must be, and if it is, then we need emulation From d302f6121076f6a7c1191d4e5a27e35d3dd149b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Thu, 2 Jan 2014 19:36:04 +0200 Subject: [PATCH 16/42] Optimize glBindBuffer when GL emulation modes are not used. In that case, currently bound buffers do not need to be tracked. --- src/library_gl.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/library_gl.js b/src/library_gl.js index 203721f8d4c15..70ba105ef29d6 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -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: [ @@ -1335,11 +1339,20 @@ var LibraryGL = { #endif var bufferObj = buffer ? GL.buffers[buffer] : null; +#if FULL_ES2 if (target == Module.ctx.ARRAY_BUFFER) { GL.currArrayBuffer = buffer; } else if (target == Module.ctx.ELEMENT_ARRAY_BUFFER) { GL.currElementArrayBuffer = buffer; } +#endif +#if LEGACY_GL_EMULATION + if (target == Module.ctx.ARRAY_BUFFER) { + GL.currArrayBuffer = buffer; + } else if (target == Module.ctx.ELEMENT_ARRAY_BUFFER) { + GL.currElementArrayBuffer = buffer; + } +#endif Module.ctx.bindBuffer(target, bufferObj); }, From e158bd1e5d861f82efa84ce427034fb0098b6e2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Thu, 2 Jan 2014 19:46:41 +0200 Subject: [PATCH 17/42] Make caching of last bound GL_ARRAY_BUFFER in FFP emulation mode safe and always enable that optimization. --- src/library_gl.js | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/library_gl.js b/src/library_gl.js index 70ba105ef29d6..1c57dd9e7d269 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -1348,7 +1348,7 @@ var LibraryGL = { #endif #if LEGACY_GL_EMULATION if (target == Module.ctx.ARRAY_BUFFER) { - GL.currArrayBuffer = buffer; + GL.immediate.lastArrayBuffer = GL.currArrayBuffer = buffer; } else if (target == Module.ctx.ELEMENT_ARRAY_BUFFER) { GL.currElementArrayBuffer = buffer; } @@ -3739,20 +3739,17 @@ var LibraryGL = { #endif if (!GL.currArrayBuffer) { // Bind the array buffer and upload data after cleaning up the previous renderer -#if GL_UNSAFE_OPTS - // Potentially unsafe, since lastArrayBuffer might not reflect the true array buffer in code that mixes immediate/non-immediate + if (arrayBuffer != GL.immediate.lastArrayBuffer) { -#endif Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, arrayBuffer); -#if GL_UNSAFE_OPTS + GL.immediate.lastArrayBuffer = arrayBuffer; } -#endif + Module.ctx.bufferSubData(Module.ctx.ARRAY_BUFFER, start, GL.immediate.vertexData.subarray(start >> 2, end >> 2)); } #if GL_UNSAFE_OPTS if (canSkip) return; GL.immediate.lastRenderer = this; - GL.immediate.lastArrayBuffer = arrayBuffer; GL.immediate.lastProgram = GL.currProgram || this.program; GL.immediate.lastStride == GL.immediate.stride; GL.immediate.matricesModified = false; @@ -3894,11 +3891,11 @@ var LibraryGL = { } if (!GL.currArrayBuffer) { Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, null); + GL.immediate.lastArrayBuffer = null; } #if GL_UNSAFE_OPTS GL.immediate.lastRenderer = null; - GL.immediate.lastArrayBuffer = null; GL.immediate.lastProgram = null; #endif GL.immediate.matricesModified = true; From f4d8baa64b17a07aeece98a1b6db3bfb9ca0203c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Fri, 3 Jan 2014 23:49:17 +0200 Subject: [PATCH 18/42] Simplify verbose object dereference chains in GL library by consistently using the global name GLImmediate over the GL.immediate form. --- src/library_gl.js | 622 +++++++++++++++++++++++----------------------- 1 file changed, 311 insertions(+), 311 deletions(-) diff --git a/src/library_gl.js b/src/library_gl.js index 1c57dd9e7d269..57aba36c60fbf 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -1348,7 +1348,7 @@ var LibraryGL = { #endif #if LEGACY_GL_EMULATION if (target == Module.ctx.ARRAY_BUFFER) { - GL.immediate.lastArrayBuffer = GL.currArrayBuffer = buffer; + GLImmediate.lastArrayBuffer = GL.currArrayBuffer = buffer; } else if (target == Module.ctx.ELEMENT_ARRAY_BUFFER) { GL.currElementArrayBuffer = buffer; } @@ -1788,7 +1788,7 @@ var LibraryGL = { _glEnable = function _glEnable(cap) { // Clean up the renderer on any change to the rendering state. The optimization of // skipping renderer setup is aimed at the case of multiple glDraw* right after each other - if (GL.immediate.lastRenderer) GL.immediate.lastRenderer.cleanup(); + if (GLImmediate.lastRenderer) GLImmediate.lastRenderer.cleanup(); if (cap == 0x0B60 /* GL_FOG */) { if (GLEmulation.fogEnabled != true) { GL.immediate.currentRenderer = null; // Fog parameter is part of the FFP shader state, we must re-lookup the renderer to use. @@ -1811,7 +1811,7 @@ var LibraryGL = { var glDisable = _glDisable; _glDisable = function _glDisable(cap) { - if (GL.immediate.lastRenderer) GL.immediate.lastRenderer.cleanup(); + if (GLImmediate.lastRenderer) GLImmediate.lastRenderer.cleanup(); if (cap == 0x0B60 /* GL_FOG */) { if (GLEmulation.fogEnabled != false) { GL.immediate.currentRenderer = null; // Fog parameter is part of the FFP shader state, we must re-lookup the renderer to use. @@ -1844,7 +1844,7 @@ var LibraryGL = { _glGetBooleanv = function _glGetBooleanv(pname, p) { var attrib = GLEmulation.getAttributeFromCapability(pname); if (attrib !== null) { - var result = GL.immediate.enabledClientAttributes[attrib]; + var result = GLImmediate.enabledClientAttributes[attrib]; {{{ makeSetValue('p', '0', 'result === true ? 1 : 0', 'i8') }}}; return; } @@ -1998,7 +1998,7 @@ var LibraryGL = { if (need_mm && !has_mm) source = 'uniform mat4 u_modelView; \n' + source; if (need_pm && !has_pm) source = 'uniform mat4 u_projection; \n' + source; GL.shaderInfos[shader].ftransform = need_pm || need_mm || need_pv; // we will need to provide the fixed function stuff as attributes and uniforms - for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) { + for (var i = 0; i < GLImmediate.MAX_TEXTURES; i++) { // XXX To handle both regular texture mapping and cube mapping, we use vec4 for tex coordinates. var old = source; var need_vtc = source.search('v_texCoord' + i) == -1; @@ -2036,7 +2036,7 @@ var LibraryGL = { } source = ensurePrecision(source); } else { // Fragment shader - for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) { + for (var i = 0; i < GLImmediate.MAX_TEXTURES; i++) { var old = source; source = source.replace(new RegExp('gl_TexCoord\\[' + i + '\\]', 'g'), 'v_texCoord' + i); if (source != old) { @@ -2125,7 +2125,7 @@ var LibraryGL = { if (GL.currProgram != program) { GL.immediate.currentRenderer = null; // This changes the FFP emulation shader program, need to recompute that. GL.currProgram = program; - GL.immediate.fixedFunctionProgram = 0; + GLImmediate.fixedFunctionProgram = 0; glUseProgram(program); } } @@ -2172,11 +2172,11 @@ var LibraryGL = { var glGetFloatv = _glGetFloatv; _glGetFloatv = function _glGetFloatv(pname, params) { if (pname == 0x0BA6) { // GL_MODELVIEW_MATRIX - HEAPF32.set(GL.immediate.matrix[0/*m*/], params >> 2); + HEAPF32.set(GLImmediate.matrix[0/*m*/], params >> 2); } else if (pname == 0x0BA7) { // GL_PROJECTION_MATRIX - HEAPF32.set(GL.immediate.matrix[1/*p*/], params >> 2); + HEAPF32.set(GLImmediate.matrix[1/*p*/], params >> 2); } else if (pname == 0x0BA8) { // GL_TEXTURE_MATRIX - HEAPF32.set(GL.immediate.matrix[2/*t*/ + GL.immediate.clientActiveTexture], params >> 2); + HEAPF32.set(GLImmediate.matrix[2/*t*/ + GLImmediate.clientActiveTexture], params >> 2); } else if (pname == 0x0B66) { // GL_FOG_COLOR HEAPF32.set(GLEmulation.fogColor, params >> 2); } else if (pname == 0x0B63) { // GL_FOG_START @@ -2232,13 +2232,13 @@ var LibraryGL = { #endif // Fall through: case 0x8078: // GL_TEXTURE_COORD_ARRAY - attrib = GL.immediate.TEXTURE0 + GL.immediate.clientActiveTexture; break; + attrib = GLImmediate.TEXTURE0 + GLImmediate.clientActiveTexture; break; case 0x8074: // GL_VERTEX_ARRAY - attrib = GL.immediate.VERTEX; break; + attrib = GLImmediate.VERTEX; break; case 0x8075: // GL_NORMAL_ARRAY - attrib = GL.immediate.NORMAL; break; + attrib = GLImmediate.NORMAL; break; case 0x8076: // GL_COLOR_ARRAY - attrib = GL.immediate.COLOR; break; + attrib = GLImmediate.COLOR; break; } return attrib; }, @@ -2321,7 +2321,7 @@ var LibraryGL = { // See comment in GLEmulation.init() #if FULL_ES2 == 0 - $GLImmediate__postset: 'GL.immediate.setupFuncs(); Browser.moduleContextCreatedCallbacks.push(function() { GL.immediate.init() });', + $GLImmediate__postset: 'GLImmediate.setupFuncs(); Browser.moduleContextCreatedCallbacks.push(function() { GLImmediate.init() });', #endif $GLImmediate__deps: ['$Browser', '$GL', '$GLEmulation'], $GLImmediate: { @@ -2739,7 +2739,7 @@ var LibraryGL = { } this.invalidateKey = function() { this.key0 = -1; // The key of this texture unit must be recomputed when rendering the next time. - GL.immediate.currentRenderer = null; // The currently used renderer must be re-evaluated at next render. + GLImmediate.currentRenderer = null; // The currently used renderer must be re-evaluated at next render. } this.traverseState = function(keyView) { if (this.key0 == -1) { @@ -3110,25 +3110,25 @@ var LibraryGL = { switch (cap) { case GL_TEXTURE_1D: if (!cur.enabled_tex1D) { - GL.immediate.currentRenderer = null; // Renderer state changed, and must be recreated or looked up again. + GLImmediate.currentRenderer = null; // Renderer state changed, and must be recreated or looked up again. cur.enabled_tex1D = true; } break; case GL_TEXTURE_2D: if (!cur.enabled_tex2D) { - GL.immediate.currentRenderer = null; + GLImmediate.currentRenderer = null; cur.enabled_tex2D = true; } break; case GL_TEXTURE_3D: if (!cur.enabled_tex3D) { - GL.immediate.currentRenderer = null; + GLImmediate.currentRenderer = null; cur.enabled_tex3D = true; } break; case GL_TEXTURE_CUBE_MAP: if (!cur.enabled_texCube) { - GL.immediate.currentRenderer = null; + GLImmediate.currentRenderer = null; cur.enabled_texCube = true; } break; @@ -3140,25 +3140,25 @@ var LibraryGL = { switch (cap) { case GL_TEXTURE_1D: if (cur.enabled_tex1D) { - GL.immediate.currentRenderer = null; // Renderer state changed, and must be recreated or looked up again. + GLImmediate.currentRenderer = null; // Renderer state changed, and must be recreated or looked up again. cur.enabled_tex1D = false; } break; case GL_TEXTURE_2D: if (cur.enabled_tex2D) { - GL.immediate.currentRenderer = null; + GLImmediate.currentRenderer = null; cur.enabled_tex2D = false; } break; case GL_TEXTURE_3D: if (cur.enabled_tex3D) { - GL.immediate.currentRenderer = null; + GLImmediate.currentRenderer = null; cur.enabled_tex3D = false; } break; case GL_TEXTURE_CUBE_MAP: if (cur.enabled_texCube) { - GL.immediate.currentRenderer = null; + GLImmediate.currentRenderer = null; cur.enabled_texCube = false; } break; @@ -3431,8 +3431,8 @@ var LibraryGL = { } // return a renderer object given the liveClientAttributes // we maintain a cache of renderers, optimized to not generate garbage - var attributes = GL.immediate.liveClientAttributes; - var cacheMap = GL.immediate.rendererCache; + var attributes = GLImmediate.liveClientAttributes; + var cacheMap = GLImmediate.rendererCache; var temp; var keyView = cacheMap.getStaticKeyView().reset(); @@ -3463,7 +3463,7 @@ var LibraryGL = { // By cur program: keyView.next(GL.currProgram); if (!GL.currProgram) { - GL.immediate.TexEnvJIT.traverseState(keyView); + GLImmediate.TexEnvJIT.traverseState(keyView); } // If we don't already have it, create it. @@ -3484,14 +3484,14 @@ var LibraryGL = { createRenderer: function createRenderer(renderer) { var useCurrProgram = !!GL.currProgram; var hasTextures = false; - for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) { - var texAttribName = GL.immediate.TEXTURE0 + i; - if (!GL.immediate.enabledClientAttributes[texAttribName]) + for (var i = 0; i < GLImmediate.MAX_TEXTURES; i++) { + var texAttribName = GLImmediate.TEXTURE0 + i; + if (!GLImmediate.enabledClientAttributes[texAttribName]) continue; #if ASSERTIONS if (!useCurrProgram) { - if (GL.immediate.TexEnvJIT.getTexUnitType(i) == 0) { + if (GLImmediate.TexEnvJIT.getTexUnitType(i) == 0) { Runtime.warnOnce("GL_TEXTURE" + i + " coords are supplied, but that texture unit is disabled in the fixed-function pipeline."); } } @@ -3507,7 +3507,7 @@ var LibraryGL = { var aTexCoordPrefix = 'a_texCoord'; var vTexCoordPrefix = 'v_texCoord'; var vPrimColor = 'v_color'; - var uTexMatrixPrefix = GL.immediate.useTextureMatrix ? 'u_textureMatrix' : null; + var uTexMatrixPrefix = GLImmediate.useTextureMatrix ? 'u_textureMatrix' : null; if (useCurrProgram) { if (GL.shaderInfos[GL.programShaders[GL.currProgram][0]].type == Module.ctx.VERTEX_SHADER) { @@ -3541,14 +3541,14 @@ var LibraryGL = { } } - GL.immediate.TexEnvJIT.setGLSLVars(uTexUnitPrefix, vTexCoordPrefix, vPrimColor, uTexMatrixPrefix); - var fsTexEnvPass = GL.immediate.TexEnvJIT.genAllPassLines('gl_FragColor', 2); + GLImmediate.TexEnvJIT.setGLSLVars(uTexUnitPrefix, vTexCoordPrefix, vPrimColor, uTexMatrixPrefix); + var fsTexEnvPass = GLImmediate.TexEnvJIT.genAllPassLines('gl_FragColor', 2); var texUnitAttribList = ''; var texUnitVaryingList = ''; var texUnitUniformList = ''; var vsTexCoordInits = ''; - this.usedTexUnitList = GL.immediate.TexEnvJIT.getUsedTexUnitList(); + this.usedTexUnitList = GLImmediate.TexEnvJIT.getUsedTexUnitList(); for (var i = 0; i < this.usedTexUnitList.length; i++) { var texUnit = this.usedTexUnitList[i]; texUnitAttribList += 'attribute vec4 ' + aTexCoordPrefix + texUnit + ';\n'; @@ -3556,7 +3556,7 @@ var LibraryGL = { texUnitUniformList += 'uniform sampler2D ' + uTexUnitPrefix + texUnit + ';\n'; vsTexCoordInits += ' ' + vTexCoordPrefix + texUnit + ' = ' + aTexCoordPrefix + texUnit + ';\n'; - if (GL.immediate.useTextureMatrix) { + if (GLImmediate.useTextureMatrix) { texUnitUniformList += 'uniform mat4 ' + uTexMatrixPrefix + texUnit + ';\n'; } } @@ -3639,12 +3639,12 @@ var LibraryGL = { // code can submit attributes to any generated FFP shader without having to examine each shader in turn. // These prespecified locations are only assumed if GL_FFP_ONLY is specified, since user could also create their // own shaders that didn't have attributes in the same locations. - Module.ctx.bindAttribLocation(this.program, GL.immediate.VERTEX, 'a_position'); - Module.ctx.bindAttribLocation(this.program, GL.immediate.COLOR, 'a_color'); - Module.ctx.bindAttribLocation(this.program, GL.immediate.NORMAL, 'a_normal'); - for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) { - Module.ctx.bindAttribLocation(this.program, GL.immediate.TEXTURE0 + i, 'a_texCoord'+i); - Module.ctx.bindAttribLocation(this.program, GL.immediate.TEXTURE0 + i, aTexCoordPrefix+i); + Module.ctx.bindAttribLocation(this.program, GLImmediate.VERTEX, 'a_position'); + Module.ctx.bindAttribLocation(this.program, GLImmediate.COLOR, 'a_color'); + Module.ctx.bindAttribLocation(this.program, GLImmediate.NORMAL, 'a_normal'); + for (var i = 0; i < GLImmediate.MAX_TEXTURES; i++) { + Module.ctx.bindAttribLocation(this.program, GLImmediate.TEXTURE0 + i, 'a_texCoord'+i); + Module.ctx.bindAttribLocation(this.program, GLImmediate.TEXTURE0 + i, aTexCoordPrefix+i); } Module.ctx.linkProgram(this.program); } @@ -3657,8 +3657,8 @@ var LibraryGL = { this.texCoordLocations = []; - for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) { - if (!GL.immediate.enabledClientAttributes[GL.immediate.TEXTURE0 + i]) { + for (var i = 0; i < GLImmediate.MAX_TEXTURES; i++) { + if (!GLImmediate.enabledClientAttributes[GLImmediate.TEXTURE0 + i]) { this.texCoordLocations[i] = -1; continue; } @@ -3685,7 +3685,7 @@ var LibraryGL = { } this.textureMatrixLocations = []; - for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) { + for (var i = 0; i < GLImmediate.MAX_TEXTURES; i++) { this.textureMatrixLocations[i] = Module.ctx.getUniformLocation(this.program, 'u_textureMatrix' + i); } this.colorLocation = Module.ctx.getAttribLocation(this.program, 'a_color'); @@ -3695,8 +3695,8 @@ var LibraryGL = { this.projectionLocation = Module.ctx.getUniformLocation(this.program, 'u_projection'); this.hasTextures = hasTextures; - this.hasNormal = GL.immediate.enabledClientAttributes[GL.immediate.NORMAL] && - GL.immediate.clientAttributes[GL.immediate.NORMAL].size > 0 && + this.hasNormal = GLImmediate.enabledClientAttributes[GLImmediate.NORMAL] && + GLImmediate.clientAttributes[GLImmediate.NORMAL].size > 0 && this.normalLocation >= 0; this.hasColor = (this.colorLocation === 0) || this.colorLocation > 0; @@ -3714,8 +3714,8 @@ var LibraryGL = { // Calculate the array buffer var arrayBuffer; if (!GL.currArrayBuffer) { - var start = GL.immediate.firstVertex*GL.immediate.stride; - var end = GL.immediate.lastVertex*GL.immediate.stride; + var start = GLImmediate.firstVertex*GLImmediate.stride; + var end = GLImmediate.lastVertex*GLImmediate.stride; #if ASSERTIONS assert(end <= GL.MAX_TEMP_BUFFER_SIZE, 'too much vertex data'); #endif @@ -3729,85 +3729,85 @@ var LibraryGL = { // If the array buffer is unchanged and the renderer as well, then we can avoid all the work here // XXX We use some heuristics here, and this may not work in all cases. Try disabling GL_UNSAFE_OPTS if you // have odd glitches - var lastRenderer = GL.immediate.lastRenderer; + var lastRenderer = GLImmediate.lastRenderer; var canSkip = this == lastRenderer && - arrayBuffer == GL.immediate.lastArrayBuffer && - (GL.currProgram || this.program) == GL.immediate.lastProgram && - GL.immediate.stride == GL.immediate.lastStride && - !GL.immediate.matricesModified; + arrayBuffer == GLImmediate.lastArrayBuffer && + (GL.currProgram || this.program) == GLImmediate.lastProgram && + GLImmediate.stride == GLImmediate.lastStride && + !GLImmediate.matricesModified; if (!canSkip && lastRenderer) lastRenderer.cleanup(); #endif if (!GL.currArrayBuffer) { // Bind the array buffer and upload data after cleaning up the previous renderer - if (arrayBuffer != GL.immediate.lastArrayBuffer) { + if (arrayBuffer != GLImmediate.lastArrayBuffer) { Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, arrayBuffer); - GL.immediate.lastArrayBuffer = arrayBuffer; + GLImmediate.lastArrayBuffer = arrayBuffer; } - Module.ctx.bufferSubData(Module.ctx.ARRAY_BUFFER, start, GL.immediate.vertexData.subarray(start >> 2, end >> 2)); + Module.ctx.bufferSubData(Module.ctx.ARRAY_BUFFER, start, GLImmediate.vertexData.subarray(start >> 2, end >> 2)); } #if GL_UNSAFE_OPTS if (canSkip) return; - GL.immediate.lastRenderer = this; - GL.immediate.lastProgram = GL.currProgram || this.program; - GL.immediate.lastStride == GL.immediate.stride; - GL.immediate.matricesModified = false; + GLImmediate.lastRenderer = this; + GLImmediate.lastProgram = GL.currProgram || this.program; + GLImmediate.lastStride == GLImmediate.stride; + GLImmediate.matricesModified = false; #endif if (!GL.currProgram) { - if (GL.immediate.fixedFunctionProgram != this.program) { + if (GLImmediate.fixedFunctionProgram != this.program) { Module.ctx.useProgram(this.program); - GL.immediate.fixedFunctionProgram = this.program; + GLImmediate.fixedFunctionProgram = this.program; } } - if (this.modelViewLocation && this.modelViewMatrixVersion != GL.immediate.matrixVersion[0/*m*/]) { - this.modelViewMatrixVersion = GL.immediate.matrixVersion[0/*m*/]; - Module.ctx.uniformMatrix4fv(this.modelViewLocation, false, GL.immediate.matrix[0/*m*/]); + if (this.modelViewLocation && this.modelViewMatrixVersion != GLImmediate.matrixVersion[0/*m*/]) { + this.modelViewMatrixVersion = GLImmediate.matrixVersion[0/*m*/]; + Module.ctx.uniformMatrix4fv(this.modelViewLocation, false, GLImmediate.matrix[0/*m*/]); } - if (this.projectionLocation && this.projectionMatrixVersion != GL.immediate.matrixVersion[1/*p*/]) { - this.projectionMatrixVersion = GL.immediate.matrixVersion[1/*p*/]; - Module.ctx.uniformMatrix4fv(this.projectionLocation, false, GL.immediate.matrix[1/*p*/]); + if (this.projectionLocation && this.projectionMatrixVersion != GLImmediate.matrixVersion[1/*p*/]) { + this.projectionMatrixVersion = GLImmediate.matrixVersion[1/*p*/]; + Module.ctx.uniformMatrix4fv(this.projectionLocation, false, GLImmediate.matrix[1/*p*/]); } - var clientAttributes = GL.immediate.clientAttributes; - var posAttr = clientAttributes[GL.immediate.VERTEX]; + var clientAttributes = GLImmediate.clientAttributes; + var posAttr = clientAttributes[GLImmediate.VERTEX]; #if GL_ASSERTIONS - GL.validateVertexAttribPointer(posAttr.size, posAttr.type, GL.immediate.stride, clientAttributes[GL.immediate.VERTEX].offset); + GL.validateVertexAttribPointer(posAttr.size, posAttr.type, GLImmediate.stride, clientAttributes[GLImmediate.VERTEX].offset); #endif #if GL_FFP_ONLY if (!GL.currArrayBuffer) { - Module.ctx.vertexAttribPointer(GL.immediate.VERTEX, posAttr.size, posAttr.type, false, GL.immediate.stride, posAttr.offset); - GL.enableVertexAttribArray(GL.immediate.VERTEX); + Module.ctx.vertexAttribPointer(GLImmediate.VERTEX, posAttr.size, posAttr.type, false, GLImmediate.stride, posAttr.offset); + GL.enableVertexAttribArray(GLImmediate.VERTEX); if (this.hasNormal) { - var normalAttr = clientAttributes[GL.immediate.NORMAL]; - Module.ctx.vertexAttribPointer(GL.immediate.NORMAL, normalAttr.size, normalAttr.type, true, GL.immediate.stride, normalAttr.offset); - GL.enableVertexAttribArray(GL.immediate.NORMAL); + var normalAttr = clientAttributes[GLImmediate.NORMAL]; + Module.ctx.vertexAttribPointer(GLImmediate.NORMAL, normalAttr.size, normalAttr.type, true, GLImmediate.stride, normalAttr.offset); + GL.enableVertexAttribArray(GLImmediate.NORMAL); } } #else - Module.ctx.vertexAttribPointer(this.positionLocation, posAttr.size, posAttr.type, false, GL.immediate.stride, posAttr.offset); + Module.ctx.vertexAttribPointer(this.positionLocation, posAttr.size, posAttr.type, false, GLImmediate.stride, posAttr.offset); Module.ctx.enableVertexAttribArray(this.positionLocation); if (this.hasNormal) { - var normalAttr = clientAttributes[GL.immediate.NORMAL]; + var normalAttr = clientAttributes[GLImmediate.NORMAL]; #if GL_ASSERTIONS - GL.validateVertexAttribPointer(normalAttr.size, normalAttr.type, GL.immediate.stride, normalAttr.offset); + GL.validateVertexAttribPointer(normalAttr.size, normalAttr.type, GLImmediate.stride, normalAttr.offset); #endif - Module.ctx.vertexAttribPointer(this.normalLocation, normalAttr.size, normalAttr.type, true, GL.immediate.stride, normalAttr.offset); + Module.ctx.vertexAttribPointer(this.normalLocation, normalAttr.size, normalAttr.type, true, GLImmediate.stride, normalAttr.offset); Module.ctx.enableVertexAttribArray(this.normalLocation); } #endif if (this.hasTextures) { - for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) { + for (var i = 0; i < GLImmediate.MAX_TEXTURES; i++) { #if GL_FFP_ONLY if (!GL.currArrayBuffer) { - var attribLoc = GL.immediate.TEXTURE0+i; + var attribLoc = GLImmediate.TEXTURE0+i; var texAttr = clientAttributes[attribLoc]; if (texAttr.size) { - Module.ctx.vertexAttribPointer(attribLoc, texAttr.size, texAttr.type, false, GL.immediate.stride, texAttr.offset); + Module.ctx.vertexAttribPointer(attribLoc, texAttr.size, texAttr.type, false, GLImmediate.stride, texAttr.offset); GL.enableVertexAttribArray(attribLoc); } else { // These two might be dangerous, but let's try them. @@ -3818,13 +3818,13 @@ var LibraryGL = { #else var attribLoc = this.texCoordLocations[i]; if (attribLoc === undefined || attribLoc < 0) continue; - var texAttr = clientAttributes[GL.immediate.TEXTURE0+i]; + var texAttr = clientAttributes[GLImmediate.TEXTURE0+i]; if (texAttr.size) { #if GL_ASSERTIONS - GL.validateVertexAttribPointer(texAttr.size, texAttr.type, GL.immediate.stride, texAttr.offset); + GL.validateVertexAttribPointer(texAttr.size, texAttr.type, GLImmediate.stride, texAttr.offset); #endif - Module.ctx.vertexAttribPointer(attribLoc, texAttr.size, texAttr.type, false, GL.immediate.stride, texAttr.offset); + Module.ctx.vertexAttribPointer(attribLoc, texAttr.size, texAttr.type, false, GLImmediate.stride, texAttr.offset); Module.ctx.enableVertexAttribArray(attribLoc); } else { // These two might be dangerous, but let's try them. @@ -3833,33 +3833,33 @@ var LibraryGL = { } #endif var t = 2/*t*/+i; - if (this.textureMatrixLocations[i] && this.textureMatrixVersion[t] != GL.immediate.matrixVersion[t]) { // XXX might we need this even without the condition we are currently in? - this.textureMatrixVersion[t] = GL.immediate.matrixVersion[t]; - Module.ctx.uniformMatrix4fv(this.textureMatrixLocations[i], false, GL.immediate.matrix[t]); + if (this.textureMatrixLocations[i] && this.textureMatrixVersion[t] != GLImmediate.matrixVersion[t]) { // XXX might we need this even without the condition we are currently in? + this.textureMatrixVersion[t] = GLImmediate.matrixVersion[t]; + Module.ctx.uniformMatrix4fv(this.textureMatrixLocations[i], false, GLImmediate.matrix[t]); } } } - if (GL.immediate.enabledClientAttributes[GL.immediate.COLOR]) { - var colorAttr = clientAttributes[GL.immediate.COLOR]; + if (GLImmediate.enabledClientAttributes[GLImmediate.COLOR]) { + var colorAttr = clientAttributes[GLImmediate.COLOR]; #if GL_ASSERTIONS - GL.validateVertexAttribPointer(colorAttr.size, colorAttr.type, GL.immediate.stride, colorAttr.offset); + GL.validateVertexAttribPointer(colorAttr.size, colorAttr.type, GLImmediate.stride, colorAttr.offset); #endif #if GL_FFP_ONLY if (!GL.currArrayBuffer) { - Module.ctx.vertexAttribPointer(GL.immediate.COLOR, colorAttr.size, colorAttr.type, true, GL.immediate.stride, colorAttr.offset); - GL.enableVertexAttribArray(GL.immediate.COLOR); + Module.ctx.vertexAttribPointer(GLImmediate.COLOR, colorAttr.size, colorAttr.type, true, GLImmediate.stride, colorAttr.offset); + GL.enableVertexAttribArray(GLImmediate.COLOR); } #else - Module.ctx.vertexAttribPointer(this.colorLocation, colorAttr.size, colorAttr.type, true, GL.immediate.stride, colorAttr.offset); + Module.ctx.vertexAttribPointer(this.colorLocation, colorAttr.size, colorAttr.type, true, GLImmediate.stride, colorAttr.offset); Module.ctx.enableVertexAttribArray(this.colorLocation); #endif } else if (this.hasColor) { #if GL_FFP_ONLY - GL.disableVertexAttribArray(GL.immediate.COLOR); - Module.ctx.vertexAttrib4fv(GL.immediate.COLOR, GL.immediate.clientColor); + GL.disableVertexAttribArray(GLImmediate.COLOR); + Module.ctx.vertexAttrib4fv(GLImmediate.COLOR, GLImmediate.clientColor); #else Module.ctx.disableVertexAttribArray(this.colorLocation); - Module.ctx.vertexAttrib4fv(this.colorLocation, GL.immediate.clientColor); + Module.ctx.vertexAttrib4fv(this.colorLocation, GLImmediate.clientColor); #endif } if (this.hasFog) { @@ -3874,8 +3874,8 @@ var LibraryGL = { #if !GL_FFP_ONLY Module.ctx.disableVertexAttribArray(this.positionLocation); if (this.hasTextures) { - for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) { - if (GL.immediate.enabledClientAttributes[GL.immediate.TEXTURE0+i] && this.texCoordLocations[i] >= 0) { + for (var i = 0; i < GLImmediate.MAX_TEXTURES; i++) { + if (GLImmediate.enabledClientAttributes[GLImmediate.TEXTURE0+i] && this.texCoordLocations[i] >= 0) { Module.ctx.disableVertexAttribArray(this.texCoordLocations[i]); } } @@ -3891,14 +3891,14 @@ var LibraryGL = { } if (!GL.currArrayBuffer) { Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, null); - GL.immediate.lastArrayBuffer = null; + GLImmediate.lastArrayBuffer = null; } #if GL_UNSAFE_OPTS - GL.immediate.lastRenderer = null; - GL.immediate.lastProgram = null; + GLImmediate.lastRenderer = null; + GLImmediate.lastProgram = null; #endif - GL.immediate.matricesModified = true; + GLImmediate.matricesModified = true; #endif } }; @@ -3911,23 +3911,23 @@ var LibraryGL = { // attributes enabled, and we use webgl-friendly modes (no GL_QUADS), then no need // for emulation _glDrawArrays = function _glDrawArrays(mode, first, count) { - if (GL.immediate.totalEnabledClientAttributes == 0 && mode <= 6) { + if (GLImmediate.totalEnabledClientAttributes == 0 && mode <= 6) { Module.ctx.drawArrays(mode, first, count); return; } - GL.immediate.prepareClientAttributes(count, false); - GL.immediate.mode = mode; + GLImmediate.prepareClientAttributes(count, false); + GLImmediate.mode = mode; if (!GL.currArrayBuffer) { - GL.immediate.vertexData = {{{ makeHEAPView('F32', 'GL.immediate.vertexPointer', 'GL.immediate.vertexPointer + (first+count)*GL.immediate.stride') }}}; // XXX assuming float - GL.immediate.firstVertex = first; - GL.immediate.lastVertex = first + count; + GLImmediate.vertexData = {{{ makeHEAPView('F32', 'GLImmediate.vertexPointer', 'GLImmediate.vertexPointer + (first+count)*GLImmediate.stride') }}}; // XXX assuming float + GLImmediate.firstVertex = first; + GLImmediate.lastVertex = first + count; } - GL.immediate.flush(null, first); - GL.immediate.mode = -1; + GLImmediate.flush(null, first); + GLImmediate.mode = -1; }; _glDrawElements = function _glDrawElements(mode, count, type, indices, start, end) { // start, end are given if we come from glDrawRangeElements - if (GL.immediate.totalEnabledClientAttributes == 0 && mode <= 6 && GL.currElementArrayBuffer) { + if (GLImmediate.totalEnabledClientAttributes == 0 && mode <= 6 && GL.currElementArrayBuffer) { Module.ctx.drawElements(mode, count, type, indices); return; } @@ -3937,27 +3937,27 @@ var LibraryGL = { } console.log("DrawElements doesn't actually prepareClientAttributes properly."); #endif - GL.immediate.prepareClientAttributes(count, false); - GL.immediate.mode = mode; + GLImmediate.prepareClientAttributes(count, false); + GLImmediate.mode = mode; if (!GL.currArrayBuffer) { - GL.immediate.firstVertex = end ? start : TOTAL_MEMORY; // if we don't know the start, set an invalid value and we will calculate it later from the indices - GL.immediate.lastVertex = end ? end+1 : 0; - GL.immediate.vertexData = {{{ makeHEAPView('F32', 'GL.immediate.vertexPointer', '(end ? GL.immediate.vertexPointer + (end+1)*GL.immediate.stride : TOTAL_MEMORY)') }}}; // XXX assuming float + GLImmediate.firstVertex = end ? start : TOTAL_MEMORY; // if we don't know the start, set an invalid value and we will calculate it later from the indices + GLImmediate.lastVertex = end ? end+1 : 0; + GLImmediate.vertexData = {{{ makeHEAPView('F32', 'GLImmediate.vertexPointer', '(end ? GLImmediate.vertexPointer + (end+1)*GLImmediate.stride : TOTAL_MEMORY)') }}}; // XXX assuming float } - GL.immediate.flush(count, 0, indices); - GL.immediate.mode = -1; + GLImmediate.flush(count, 0, indices); + GLImmediate.mode = -1; }; // TexEnv stuff needs to be prepared early, so do it here. // init() is too late for -O2, since it freezes the GL functions // by that point. - GL.immediate.MapTreeLib = GL.immediate.spawnMapTreeLib(); - GL.immediate.spawnMapTreeLib = null; + GLImmediate.MapTreeLib = GLImmediate.spawnMapTreeLib(); + GLImmediate.spawnMapTreeLib = null; - GL.immediate.TexEnvJIT = GL.immediate.spawnTexEnvJIT(); - GL.immediate.spawnTexEnvJIT = null; + GLImmediate.TexEnvJIT = GLImmediate.spawnTexEnvJIT(); + GLImmediate.spawnTexEnvJIT = null; - GL.immediate.setupHooks(); + GLImmediate.setupHooks(); }, setupHooks: function() { @@ -3967,36 +3967,36 @@ var LibraryGL = { var glActiveTexture = _glActiveTexture; _glActiveTexture = function _glActiveTexture(texture) { - GL.immediate.TexEnvJIT.hook_activeTexture(texture); + GLImmediate.TexEnvJIT.hook_activeTexture(texture); glActiveTexture(texture); }; var glEnable = _glEnable; _glEnable = function _glEnable(cap) { - GL.immediate.TexEnvJIT.hook_enable(cap); + GLImmediate.TexEnvJIT.hook_enable(cap); glEnable(cap); }; var glDisable = _glDisable; _glDisable = function _glDisable(cap) { - GL.immediate.TexEnvJIT.hook_disable(cap); + GLImmediate.TexEnvJIT.hook_disable(cap); glDisable(cap); }; var glTexEnvf = (typeof(_glTexEnvf) != 'undefined') ? _glTexEnvf : function(){}; _glTexEnvf = function _glTexEnvf(target, pname, param) { - GL.immediate.TexEnvJIT.hook_texEnvf(target, pname, param); + GLImmediate.TexEnvJIT.hook_texEnvf(target, pname, param); // Don't call old func, since we are the implementor. //glTexEnvf(target, pname, param); }; var glTexEnvi = (typeof(_glTexEnvi) != 'undefined') ? _glTexEnvi : function(){}; _glTexEnvi = function _glTexEnvi(target, pname, param) { - GL.immediate.TexEnvJIT.hook_texEnvi(target, pname, param); + GLImmediate.TexEnvJIT.hook_texEnvi(target, pname, param); // Don't call old func, since we are the implementor. //glTexEnvi(target, pname, param); }; var glTexEnvfv = (typeof(_glTexEnvfv) != 'undefined') ? _glTexEnvfv : function(){}; _glTexEnvfv = function _glTexEnvfv(target, pname, param) { - GL.immediate.TexEnvJIT.hook_texEnvfv(target, pname, param); + GLImmediate.TexEnvJIT.hook_texEnvfv(target, pname, param); // Don't call old func, since we are the implementor. //glTexEnvfv(target, pname, param); }; @@ -4007,7 +4007,7 @@ var LibraryGL = { case 0x8B8D: { // GL_CURRENT_PROGRAM // Just query directly so we're working with WebGL objects. var cur = Module.ctx.getParameter(Module.ctx.CURRENT_PROGRAM); - if (cur == GL.immediate.fixedFunctionProgram) { + if (cur == GLImmediate.fixedFunctionProgram) { // Pretend we're not using a program. {{{ makeSetValue('params', '0', '0', 'i32') }}}; return; @@ -4023,7 +4023,7 @@ var LibraryGL = { initted: false, init: function() { Module.printErr('WARNING: using emscripten GL immediate mode emulation. This is very limited in what it supports'); - GL.immediate.initted = true; + GLImmediate.initted = true; if (!Module.useWebGL) return; // a 2D canvas may be currently used TODO: make sure we are actually called in that case @@ -4031,34 +4031,34 @@ var LibraryGL = { // User can override the maximum number of texture units that we emulate. Using fewer texture units increases runtime performance // slightly, so it is advantageous to choose as small value as needed. - GL.immediate.MAX_TEXTURES = Module['GL_MAX_TEXTURE_IMAGE_UNITS'] || Module.ctx.getParameter(Module.ctx.MAX_TEXTURE_IMAGE_UNITS); - GL.immediate.NUM_ATTRIBUTES = 3 /*pos+normal+color attributes*/ + GL.immediate.MAX_TEXTURES; - GL.immediate.clientAttributes = []; + GLImmediate.MAX_TEXTURES = Module['GL_MAX_TEXTURE_IMAGE_UNITS'] || Module.ctx.getParameter(Module.ctx.MAX_TEXTURE_IMAGE_UNITS); + GLImmediate.NUM_ATTRIBUTES = 3 /*pos+normal+color attributes*/ + GLImmediate.MAX_TEXTURES; + GLImmediate.clientAttributes = []; GLEmulation.enabledClientAttribIndices = []; - for (var i = 0; i < GL.immediate.NUM_ATTRIBUTES; i++) { - GL.immediate.clientAttributes.push({}); + for (var i = 0; i < GLImmediate.NUM_ATTRIBUTES; i++) { + GLImmediate.clientAttributes.push({}); GLEmulation.enabledClientAttribIndices.push(false); } this.matrixStack[0/*m*/] = []; this.matrixStack[1/*p*/] = []; - for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) { + for (var i = 0; i < GLImmediate.MAX_TEXTURES; i++) { this.matrixStack[2/*t*/ + i] = []; } // Initialize matrix library // When user sets a matrix, increment a 'version number' on the new data, and when rendering, submit // the matrices to the shader program only if they have an old version of the data. - GL.immediate.matrixVersion = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]; - GL.immediate.matrix[0/*m*/] = GL.immediate.matrix.lib.mat4.create(); - GL.immediate.matrixVersion[0/*m*/] = 0; - GL.immediate.matrix.lib.mat4.identity(GL.immediate.matrix[0/*m*/]); - GL.immediate.matrix[1/*p*/] = GL.immediate.matrix.lib.mat4.create(); - GL.immediate.matrixVersion[1/*p*/] = 0; - GL.immediate.matrix.lib.mat4.identity(GL.immediate.matrix[1/*p*/]); - for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) { - GL.immediate.matrix[2/*t*/ + i] = GL.immediate.matrix.lib.mat4.create(); - GL.immediate.matrixVersion[2/*t*/ + i] = 0; + GLImmediate.matrixVersion = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]; + GLImmediate.matrix[0/*m*/] = GLImmediate.matrix.lib.mat4.create(); + GLImmediate.matrixVersion[0/*m*/] = 0; + GLImmediate.matrix.lib.mat4.identity(GLImmediate.matrix[0/*m*/]); + GLImmediate.matrix[1/*p*/] = GLImmediate.matrix.lib.mat4.create(); + GLImmediate.matrixVersion[1/*p*/] = 0; + GLImmediate.matrix.lib.mat4.identity(GLImmediate.matrix[1/*p*/]); + for (var i = 0; i < GLImmediate.MAX_TEXTURES; i++) { + GLImmediate.matrix[2/*t*/ + i] = GLImmediate.matrix.lib.mat4.create(); + GLImmediate.matrixVersion[2/*t*/ + i] = 0; } // Renderer cache @@ -4084,16 +4084,16 @@ var LibraryGL = { // does not work for glBegin/End, where we generate renderer components dynamically and then // disable them ourselves, but it does help with glDrawElements/Arrays. if (!this.modifiedClientAttributes) { - GL.immediate.vertexCounter = (GL.immediate.stride * count) / 4; // XXX assuming float + GLImmediate.vertexCounter = (GLImmediate.stride * count) / 4; // XXX assuming float return; } this.modifiedClientAttributes = false; var stride = 0, start; - var attributes = GL.immediate.liveClientAttributes; + var attributes = GLImmediate.liveClientAttributes; attributes.length = 0; - for (var i = 0; i < GL.immediate.NUM_ATTRIBUTES; i++) { - if (GL.immediate.enabledClientAttributes[i]) attributes.push(GL.immediate.clientAttributes[i]); + for (var i = 0; i < GLImmediate.NUM_ATTRIBUTES; i++) { + if (GLImmediate.enabledClientAttributes[i]) attributes.push(GLImmediate.clientAttributes[i]); } attributes.sort(function(x, y) { return !x ? (!y ? 0 : 1) : (!y ? -1 : (x.pointer - y.pointer)) }); start = GL.currArrayBuffer ? 0 : attributes[0].pointer; @@ -4115,8 +4115,8 @@ var LibraryGL = { #if ASSERTIONS Runtime.warnOnce('Unpacking/restriding attributes, this is slow and dangerous'); #endif - if (!GL.immediate.restrideBuffer) GL.immediate.restrideBuffer = _malloc(GL.MAX_TEMP_BUFFER_SIZE); - start = GL.immediate.restrideBuffer; + if (!GLImmediate.restrideBuffer) GLImmediate.restrideBuffer = _malloc(GL.MAX_TEMP_BUFFER_SIZE); + start = GLImmediate.restrideBuffer; #if ASSERTIONS assert(start % 4 == 0); #endif @@ -4166,14 +4166,14 @@ var LibraryGL = { bytes = stride; } } - GL.immediate.stride = bytes; + GLImmediate.stride = bytes; if (!beginEnd) { bytes *= count; if (!GL.currArrayBuffer) { - GL.immediate.vertexPointer = start; + GLImmediate.vertexPointer = start; } - GL.immediate.vertexCounter = bytes / 4; // XXX assuming float + GLImmediate.vertexCounter = bytes / 4; // XXX assuming float } }, @@ -4187,7 +4187,7 @@ var LibraryGL = { var renderer = this.getRenderer(); // Generate index data in a format suitable for GLES 2.0/WebGL - var numVertexes = 4 * this.vertexCounter / GL.immediate.stride; + var numVertexes = 4 * this.vertexCounter / GLImmediate.stride; #if ASSERTIONS assert(numVertexes % 1 == 0, "`numVertexes` must be an integer."); #endif @@ -4195,7 +4195,7 @@ var LibraryGL = { var numIndexes = 0; if (numProvidedIndexes) { numIndexes = numProvidedIndexes; - if (!GL.currArrayBuffer && GL.immediate.firstVertex > GL.immediate.lastVertex) { + if (!GL.currArrayBuffer && GLImmediate.firstVertex > GLImmediate.lastVertex) { // Figure out the first and last vertex from the index data #if ASSERTIONS assert(!GL.currElementArrayBuffer); // If we are going to upload array buffer data, we need to find which range to @@ -4205,8 +4205,8 @@ var LibraryGL = { #endif for (var i = 0; i < numProvidedIndexes; i++) { var currIndex = {{{ makeGetValue('ptr', 'i*2', 'i16', null, 1) }}}; - GL.immediate.firstVertex = Math.min(GL.immediate.firstVertex, currIndex); - GL.immediate.lastVertex = Math.max(GL.immediate.lastVertex, currIndex+1); + GLImmediate.firstVertex = Math.min(GLImmediate.firstVertex, currIndex); + GLImmediate.lastVertex = Math.max(GLImmediate.lastVertex, currIndex+1); } } if (!GL.currElementArrayBuffer) { @@ -4220,15 +4220,15 @@ var LibraryGL = { ptr = 0; emulatedElementArrayBuffer = true; } - } else if (GL.immediate.mode > 6) { // above GL_TRIANGLE_FAN are the non-GL ES modes - if (GL.immediate.mode != 7) throw 'unsupported immediate mode ' + GL.immediate.mode; // GL_QUADS - // GL.immediate.firstVertex is the first vertex we want. Quad indexes are in the pattern + } else if (GLImmediate.mode > 6) { // above GL_TRIANGLE_FAN are the non-GL ES modes + if (GLImmediate.mode != 7) throw 'unsupported immediate mode ' + GLImmediate.mode; // GL_QUADS + // GLImmediate.firstVertex is the first vertex we want. Quad indexes are in the pattern // 0 1 2, 0 2 3, 4 5 6, 4 6 7, so we need to look at index firstVertex * 1.5 to see it. // Then since indexes are 2 bytes each, that means 3 #if ASSERTIONS - assert(GL.immediate.firstVertex % 4 == 0); + assert(GLImmediate.firstVertex % 4 == 0); #endif - ptr = GL.immediate.firstVertex*3; + ptr = GLImmediate.firstVertex*3; var numQuads = numVertexes / 4; numIndexes = numQuads * 6; // 0 1 2, 0 2 3 pattern #if ASSERTIONS @@ -4243,7 +4243,7 @@ var LibraryGL = { if (numIndexes) { Module.ctx.drawElements(Module.ctx.TRIANGLES, numIndexes, Module.ctx.UNSIGNED_SHORT, ptr); } else { - Module.ctx.drawArrays(GL.immediate.mode, startIndex, numVertexes); + Module.ctx.drawArrays(GLImmediate.mode, startIndex, numVertexes); } if (emulatedElementArrayBuffer) { @@ -4256,57 +4256,57 @@ var LibraryGL = { } }, - $GLImmediateSetup__deps: ['$GLImmediate', function() { return 'GL.immediate = GLImmediate; GL.immediate.matrix.lib = ' + read('gl-matrix.js') + ';\n' }], + $GLImmediateSetup__deps: ['$GLImmediate', function() { return 'GL.immediate = GLImmediate; GLImmediate.matrix.lib = ' + read('gl-matrix.js') + ';\n' }], $GLImmediateSetup: {}, glBegin__deps: ['$GLImmediateSetup'], glBegin: function(mode) { // Push the old state: - GL.immediate.enabledClientAttributes_preBegin = GL.immediate.enabledClientAttributes; - GL.immediate.enabledClientAttributes = []; + GLImmediate.enabledClientAttributes_preBegin = GLImmediate.enabledClientAttributes; + GLImmediate.enabledClientAttributes = []; - GL.immediate.clientAttributes_preBegin = GL.immediate.clientAttributes; - GL.immediate.clientAttributes = [] - for (var i = 0; i < GL.immediate.clientAttributes_preBegin.length; i++) { - GL.immediate.clientAttributes.push({}); + GLImmediate.clientAttributes_preBegin = GLImmediate.clientAttributes; + GLImmediate.clientAttributes = [] + for (var i = 0; i < GLImmediate.clientAttributes_preBegin.length; i++) { + GLImmediate.clientAttributes.push({}); } - GL.immediate.mode = mode; - GL.immediate.vertexCounter = 0; - var components = GL.immediate.rendererComponents = []; - for (var i = 0; i < GL.immediate.NUM_ATTRIBUTES; i++) { + GLImmediate.mode = mode; + GLImmediate.vertexCounter = 0; + var components = GLImmediate.rendererComponents = []; + for (var i = 0; i < GLImmediate.NUM_ATTRIBUTES; i++) { components[i] = 0; } - GL.immediate.rendererComponentPointer = 0; - GL.immediate.vertexData = GL.immediate.tempData; + GLImmediate.rendererComponentPointer = 0; + GLImmediate.vertexData = GLImmediate.tempData; }, glEnd: function() { - GL.immediate.prepareClientAttributes(GL.immediate.rendererComponents[GL.immediate.VERTEX], true); - GL.immediate.firstVertex = 0; - GL.immediate.lastVertex = GL.immediate.vertexCounter / (GL.immediate.stride >> 2); - GL.immediate.flush(); - GL.immediate.disableBeginEndClientAttributes(); - GL.immediate.mode = -1; + GLImmediate.prepareClientAttributes(GLImmediate.rendererComponents[GLImmediate.VERTEX], true); + GLImmediate.firstVertex = 0; + GLImmediate.lastVertex = GLImmediate.vertexCounter / (GLImmediate.stride >> 2); + GLImmediate.flush(); + GLImmediate.disableBeginEndClientAttributes(); + GLImmediate.mode = -1; // Pop the old state: - GL.immediate.enabledClientAttributes = GL.immediate.enabledClientAttributes_preBegin; - GL.immediate.clientAttributes = GL.immediate.clientAttributes_preBegin; + GLImmediate.enabledClientAttributes = GLImmediate.enabledClientAttributes_preBegin; + GLImmediate.clientAttributes = GLImmediate.clientAttributes_preBegin; GL.immediate.currentRenderer = null; // The set of active client attributes changed, we must re-lookup the renderer to use. - GL.immediate.modifiedClientAttributes = true; + GLImmediate.modifiedClientAttributes = true; }, glVertex3f: function(x, y, z) { #if ASSERTIONS - assert(GL.immediate.mode >= 0); // must be in begin/end + assert(GLImmediate.mode >= 0); // must be in begin/end #endif - GL.immediate.vertexData[GL.immediate.vertexCounter++] = x; - GL.immediate.vertexData[GL.immediate.vertexCounter++] = y; - GL.immediate.vertexData[GL.immediate.vertexCounter++] = z || 0; + GLImmediate.vertexData[GLImmediate.vertexCounter++] = x; + GLImmediate.vertexData[GLImmediate.vertexCounter++] = y; + GLImmediate.vertexData[GLImmediate.vertexCounter++] = z || 0; #if ASSERTIONS - assert(GL.immediate.vertexCounter << 2 < GL.MAX_TEMP_BUFFER_SIZE); + assert(GLImmediate.vertexCounter << 2 < GL.MAX_TEMP_BUFFER_SIZE); #endif - GL.immediate.addRendererComponent(GL.immediate.VERTEX, 3, Module.ctx.FLOAT); + GLImmediate.addRendererComponent(GLImmediate.VERTEX, 3, Module.ctx.FLOAT); }, glVertex2f: 'glVertex3f', @@ -4325,11 +4325,11 @@ var LibraryGL = { glTexCoord2i: function(u, v) { #if ASSERTIONS - assert(GL.immediate.mode >= 0); // must be in begin/end + assert(GLImmediate.mode >= 0); // must be in begin/end #endif - GL.immediate.vertexData[GL.immediate.vertexCounter++] = u; - GL.immediate.vertexData[GL.immediate.vertexCounter++] = v; - GL.immediate.addRendererComponent(GL.immediate.TEXTURE0, 2, Module.ctx.FLOAT); + GLImmediate.vertexData[GLImmediate.vertexCounter++] = u; + GLImmediate.vertexData[GLImmediate.vertexCounter++] = v; + GLImmediate.addRendererComponent(GLImmediate.TEXTURE0, 2, Module.ctx.FLOAT); }, glTexCoord2f: 'glTexCoord2i', @@ -4347,19 +4347,19 @@ var LibraryGL = { a = Math.max(Math.min(a, 1), 0); // TODO: make ub the default, not f, save a few mathops - if (GL.immediate.mode >= 0) { - var start = GL.immediate.vertexCounter << 2; - GL.immediate.vertexDataU8[start + 0] = r * 255; - GL.immediate.vertexDataU8[start + 1] = g * 255; - GL.immediate.vertexDataU8[start + 2] = b * 255; - GL.immediate.vertexDataU8[start + 3] = a * 255; - GL.immediate.vertexCounter++; - GL.immediate.addRendererComponent(GL.immediate.COLOR, 4, Module.ctx.UNSIGNED_BYTE); + if (GLImmediate.mode >= 0) { + var start = GLImmediate.vertexCounter << 2; + GLImmediate.vertexDataU8[start + 0] = r * 255; + GLImmediate.vertexDataU8[start + 1] = g * 255; + GLImmediate.vertexDataU8[start + 2] = b * 255; + GLImmediate.vertexDataU8[start + 3] = a * 255; + GLImmediate.vertexCounter++; + GLImmediate.addRendererComponent(GLImmediate.COLOR, 4, Module.ctx.UNSIGNED_BYTE); } else { - GL.immediate.clientColor[0] = r; - GL.immediate.clientColor[1] = g; - GL.immediate.clientColor[2] = b; - GL.immediate.clientColor[3] = a; + GLImmediate.clientColor[0] = r; + GLImmediate.clientColor[1] = g; + GLImmediate.clientColor[2] = b; + GLImmediate.clientColor[3] = a; } }, glColor4d: 'glColor4f', @@ -4503,12 +4503,12 @@ var LibraryGL = { #endif return; } - if (!GL.immediate.enabledClientAttributes[attrib]) { - GL.immediate.enabledClientAttributes[attrib] = true; - GL.immediate.totalEnabledClientAttributes++; + if (!GLImmediate.enabledClientAttributes[attrib]) { + GLImmediate.enabledClientAttributes[attrib] = true; + GLImmediate.totalEnabledClientAttributes++; this.currentRenderer = null; // Will need to change current renderer, since the set of active vertex pointers changed. if (GLEmulation.currentVao) GLEmulation.currentVao.enabledClientStates[cap] = 1; - GL.immediate.modifiedClientAttributes = true; + GLImmediate.modifiedClientAttributes = true; } }, glDisableClientState: function(cap) { @@ -4519,57 +4519,57 @@ var LibraryGL = { #endif return; } - if (GL.immediate.enabledClientAttributes[attrib]) { - GL.immediate.enabledClientAttributes[attrib] = false; - GL.immediate.totalEnabledClientAttributes--; + if (GLImmediate.enabledClientAttributes[attrib]) { + GLImmediate.enabledClientAttributes[attrib] = false; + GLImmediate.totalEnabledClientAttributes--; this.currentRenderer = null; // Will need to change current renderer, since the set of active vertex pointers changed. if (GLEmulation.currentVao) delete GLEmulation.currentVao.enabledClientStates[cap]; - GL.immediate.modifiedClientAttributes = true; + GLImmediate.modifiedClientAttributes = true; } }, glVertexPointer__deps: ['$GLEmulation'], // if any pointers are used, glVertexPointer must be, and if it is, then we need emulation glVertexPointer: function(size, type, stride, pointer) { - GL.immediate.setClientAttribute(GL.immediate.VERTEX, size, type, stride, pointer); + GLImmediate.setClientAttribute(GLImmediate.VERTEX, size, type, stride, pointer); #if GL_FFP_ONLY if (GL.currArrayBuffer) { - Module.ctx.vertexAttribPointer(GL.immediate.VERTEX, size, type, false, stride, pointer); - GL.enableVertexAttribArray(GL.immediate.VERTEX); + Module.ctx.vertexAttribPointer(GLImmediate.VERTEX, size, type, false, stride, pointer); + GL.enableVertexAttribArray(GLImmediate.VERTEX); } #endif }, glTexCoordPointer: function(size, type, stride, pointer) { - GL.immediate.setClientAttribute(GL.immediate.TEXTURE0 + GL.immediate.clientActiveTexture, size, type, stride, pointer); + GLImmediate.setClientAttribute(GLImmediate.TEXTURE0 + GLImmediate.clientActiveTexture, size, type, stride, pointer); #if GL_FFP_ONLY if (GL.currArrayBuffer) { - var loc = GL.immediate.TEXTURE0 + GL.immediate.clientActiveTexture; + var loc = GLImmediate.TEXTURE0 + GLImmediate.clientActiveTexture; Module.ctx.vertexAttribPointer(loc, size, type, false, stride, pointer); GL.enableVertexAttribArray(loc); } #endif }, glNormalPointer: function(type, stride, pointer) { - GL.immediate.setClientAttribute(GL.immediate.NORMAL, 3, type, stride, pointer); + GLImmediate.setClientAttribute(GLImmediate.NORMAL, 3, type, stride, pointer); #if GL_FFP_ONLY if (GL.currArrayBuffer) { - Module.ctx.vertexAttribPointer(GL.immediate.NORMAL, size, type, true, stride, pointer); - GL.enableVertexAttribArray(GL.immediate.NORMAL); + Module.ctx.vertexAttribPointer(GLImmediate.NORMAL, size, type, true, stride, pointer); + GL.enableVertexAttribArray(GLImmediate.NORMAL); } #endif }, glColorPointer: function(size, type, stride, pointer) { - GL.immediate.setClientAttribute(GL.immediate.COLOR, size, type, stride, pointer); + GLImmediate.setClientAttribute(GLImmediate.COLOR, size, type, stride, pointer); #if GL_FFP_ONLY if (GL.currArrayBuffer) { - Module.ctx.vertexAttribPointer(GL.immediate.COLOR, size, type, true, stride, pointer); - GL.enableVertexAttribArray(GL.immediate.COLOR); + Module.ctx.vertexAttribPointer(GLImmediate.COLOR, size, type, true, stride, pointer); + GL.enableVertexAttribArray(GLImmediate.COLOR); } #endif }, glClientActiveTexture__sig: 'vi', glClientActiveTexture: function(texture) { - GL.immediate.clientActiveTexture = texture - 0x84C0; // GL_TEXTURE0 + GLImmediate.clientActiveTexture = texture - 0x84C0; // GL_TEXTURE0 }, // Vertex array object (VAO) support. TODO: when the WebGL extension is popular, use that and remove this code and GL.vaos @@ -4601,16 +4601,16 @@ var LibraryGL = { 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 - if (GL.immediate.lastRenderer) GL.immediate.lastRenderer.cleanup(); + if (GLImmediate.lastRenderer) GLImmediate.lastRenderer.cleanup(); _glBindBuffer(Module.ctx.ARRAY_BUFFER, 0); // XXX if one was there before we were bound? _glBindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, 0); for (var vaa in GLEmulation.enabledVertexAttribArrays) { Module.ctx.disableVertexAttribArray(vaa); } GLEmulation.enabledVertexAttribArrays = {}; - GL.immediate.enabledClientAttributes = [0, 0]; - GL.immediate.totalEnabledClientAttributes = 0; - GL.immediate.modifiedClientAttributes = true; + GLImmediate.enabledClientAttributes = [0, 0]; + GLImmediate.totalEnabledClientAttributes = 0; + GLImmediate.modifiedClientAttributes = true; if (vao) { // replay vao var info = GLEmulation.vaos[vao]; @@ -4634,132 +4634,132 @@ var LibraryGL = { glMatrixMode__deps: ['$GL', '$GLImmediateSetup', '$GLEmulation'], // emulation is not strictly needed, this is a workaround glMatrixMode: function(mode) { if (mode == 0x1700 /* GL_MODELVIEW */) { - GL.immediate.currentMatrix = 0/*m*/; + GLImmediate.currentMatrix = 0/*m*/; } else if (mode == 0x1701 /* GL_PROJECTION */) { - GL.immediate.currentMatrix = 1/*p*/; + GLImmediate.currentMatrix = 1/*p*/; } else if (mode == 0x1702) { // GL_TEXTURE - GL.immediate.useTextureMatrix = true; - GL.immediate.currentMatrix = 2/*t*/ + GL.immediate.clientActiveTexture; + GLImmediate.useTextureMatrix = true; + GLImmediate.currentMatrix = 2/*t*/ + GLImmediate.clientActiveTexture; } else { throw "Wrong mode " + mode + " passed to glMatrixMode"; } }, glPushMatrix: function() { - GL.immediate.matricesModified = true; - GL.immediate.matrixVersion[GL.immediate.currentMatrix] = (GL.immediate.matrixVersion[GL.immediate.currentMatrix] + 1)|0; - GL.immediate.matrixStack[GL.immediate.currentMatrix].push( - Array.prototype.slice.call(GL.immediate.matrix[GL.immediate.currentMatrix])); + GLImmediate.matricesModified = true; + GLImmediate.matrixVersion[GLImmediate.currentMatrix] = (GLImmediate.matrixVersion[GLImmediate.currentMatrix] + 1)|0; + GLImmediate.matrixStack[GLImmediate.currentMatrix].push( + Array.prototype.slice.call(GLImmediate.matrix[GLImmediate.currentMatrix])); }, glPopMatrix: function() { - GL.immediate.matricesModified = true; - GL.immediate.matrixVersion[GL.immediate.currentMatrix] = (GL.immediate.matrixVersion[GL.immediate.currentMatrix] + 1)|0; - GL.immediate.matrix[GL.immediate.currentMatrix] = GL.immediate.matrixStack[GL.immediate.currentMatrix].pop(); + GLImmediate.matricesModified = true; + GLImmediate.matrixVersion[GLImmediate.currentMatrix] = (GLImmediate.matrixVersion[GLImmediate.currentMatrix] + 1)|0; + GLImmediate.matrix[GLImmediate.currentMatrix] = GLImmediate.matrixStack[GLImmediate.currentMatrix].pop(); }, glLoadIdentity__deps: ['$GL', '$GLImmediateSetup'], glLoadIdentity: function() { - GL.immediate.matricesModified = true; - GL.immediate.matrixVersion[GL.immediate.currentMatrix] = (GL.immediate.matrixVersion[GL.immediate.currentMatrix] + 1)|0; - GL.immediate.matrix.lib.mat4.identity(GL.immediate.matrix[GL.immediate.currentMatrix]); + GLImmediate.matricesModified = true; + GLImmediate.matrixVersion[GLImmediate.currentMatrix] = (GLImmediate.matrixVersion[GLImmediate.currentMatrix] + 1)|0; + GLImmediate.matrix.lib.mat4.identity(GLImmediate.matrix[GLImmediate.currentMatrix]); }, glLoadMatrixd: function(matrix) { - GL.immediate.matricesModified = true; - GL.immediate.matrixVersion[GL.immediate.currentMatrix] = (GL.immediate.matrixVersion[GL.immediate.currentMatrix] + 1)|0; - GL.immediate.matrix.lib.mat4.set({{{ makeHEAPView('F64', 'matrix', 'matrix+' + (16*8)) }}}, GL.immediate.matrix[GL.immediate.currentMatrix]); + GLImmediate.matricesModified = true; + GLImmediate.matrixVersion[GLImmediate.currentMatrix] = (GLImmediate.matrixVersion[GLImmediate.currentMatrix] + 1)|0; + GLImmediate.matrix.lib.mat4.set({{{ makeHEAPView('F64', 'matrix', 'matrix+' + (16*8)) }}}, GLImmediate.matrix[GLImmediate.currentMatrix]); }, glLoadMatrixf: function(matrix) { #if GL_DEBUG if (GL.debug) Module.printErr('glLoadMatrixf receiving: ' + Array.prototype.slice.call(HEAPF32.subarray(matrix >> 2, (matrix >> 2) + 16))); #endif - GL.immediate.matricesModified = true; - GL.immediate.matrixVersion[GL.immediate.currentMatrix] = (GL.immediate.matrixVersion[GL.immediate.currentMatrix] + 1)|0; - GL.immediate.matrix.lib.mat4.set({{{ makeHEAPView('F32', 'matrix', 'matrix+' + (16*4)) }}}, GL.immediate.matrix[GL.immediate.currentMatrix]); + GLImmediate.matricesModified = true; + GLImmediate.matrixVersion[GLImmediate.currentMatrix] = (GLImmediate.matrixVersion[GLImmediate.currentMatrix] + 1)|0; + GLImmediate.matrix.lib.mat4.set({{{ makeHEAPView('F32', 'matrix', 'matrix+' + (16*4)) }}}, GLImmediate.matrix[GLImmediate.currentMatrix]); }, glLoadTransposeMatrixd: function(matrix) { - GL.immediate.matricesModified = true; - GL.immediate.matrixVersion[GL.immediate.currentMatrix] = (GL.immediate.matrixVersion[GL.immediate.currentMatrix] + 1)|0; - GL.immediate.matrix.lib.mat4.set({{{ makeHEAPView('F64', 'matrix', 'matrix+' + (16*8)) }}}, GL.immediate.matrix[GL.immediate.currentMatrix]); - GL.immediate.matrix.lib.mat4.transpose(GL.immediate.matrix[GL.immediate.currentMatrix]); + GLImmediate.matricesModified = true; + GLImmediate.matrixVersion[GLImmediate.currentMatrix] = (GLImmediate.matrixVersion[GLImmediate.currentMatrix] + 1)|0; + GLImmediate.matrix.lib.mat4.set({{{ makeHEAPView('F64', 'matrix', 'matrix+' + (16*8)) }}}, GLImmediate.matrix[GLImmediate.currentMatrix]); + GLImmediate.matrix.lib.mat4.transpose(GLImmediate.matrix[GLImmediate.currentMatrix]); }, glLoadTransposeMatrixf: function(matrix) { - GL.immediate.matricesModified = true; - GL.immediate.matrixVersion[GL.immediate.currentMatrix] = (GL.immediate.matrixVersion[GL.immediate.currentMatrix] + 1)|0; - GL.immediate.matrix.lib.mat4.set({{{ makeHEAPView('F32', 'matrix', 'matrix+' + (16*4)) }}}, GL.immediate.matrix[GL.immediate.currentMatrix]); - GL.immediate.matrix.lib.mat4.transpose(GL.immediate.matrix[GL.immediate.currentMatrix]); + GLImmediate.matricesModified = true; + GLImmediate.matrixVersion[GLImmediate.currentMatrix] = (GLImmediate.matrixVersion[GLImmediate.currentMatrix] + 1)|0; + GLImmediate.matrix.lib.mat4.set({{{ makeHEAPView('F32', 'matrix', 'matrix+' + (16*4)) }}}, GLImmediate.matrix[GLImmediate.currentMatrix]); + GLImmediate.matrix.lib.mat4.transpose(GLImmediate.matrix[GLImmediate.currentMatrix]); }, glMultMatrixd: function(matrix) { - GL.immediate.matricesModified = true; - GL.immediate.matrixVersion[GL.immediate.currentMatrix] = (GL.immediate.matrixVersion[GL.immediate.currentMatrix] + 1)|0; - GL.immediate.matrix.lib.mat4.multiply(GL.immediate.matrix[GL.immediate.currentMatrix], + GLImmediate.matricesModified = true; + GLImmediate.matrixVersion[GLImmediate.currentMatrix] = (GLImmediate.matrixVersion[GLImmediate.currentMatrix] + 1)|0; + GLImmediate.matrix.lib.mat4.multiply(GLImmediate.matrix[GLImmediate.currentMatrix], {{{ makeHEAPView('F64', 'matrix', 'matrix+' + (16*8)) }}}); }, glMultMatrixf: function(matrix) { - GL.immediate.matricesModified = true; - GL.immediate.matrixVersion[GL.immediate.currentMatrix] = (GL.immediate.matrixVersion[GL.immediate.currentMatrix] + 1)|0; - GL.immediate.matrix.lib.mat4.multiply(GL.immediate.matrix[GL.immediate.currentMatrix], + GLImmediate.matricesModified = true; + GLImmediate.matrixVersion[GLImmediate.currentMatrix] = (GLImmediate.matrixVersion[GLImmediate.currentMatrix] + 1)|0; + GLImmediate.matrix.lib.mat4.multiply(GLImmediate.matrix[GLImmediate.currentMatrix], {{{ makeHEAPView('F32', 'matrix', 'matrix+' + (16*4)) }}}); }, glMultTransposeMatrixd: function(matrix) { - GL.immediate.matricesModified = true; - GL.immediate.matrixVersion[GL.immediate.currentMatrix] = (GL.immediate.matrixVersion[GL.immediate.currentMatrix] + 1)|0; - var colMajor = GL.immediate.matrix.lib.mat4.create(); - GL.immediate.matrix.lib.mat4.set({{{ makeHEAPView('F64', 'matrix', 'matrix+' + (16*8)) }}}, colMajor); - GL.immediate.matrix.lib.mat4.transpose(colMajor); - GL.immediate.matrix.lib.mat4.multiply(GL.immediate.matrix[GL.immediate.currentMatrix], colMajor); + GLImmediate.matricesModified = true; + GLImmediate.matrixVersion[GLImmediate.currentMatrix] = (GLImmediate.matrixVersion[GLImmediate.currentMatrix] + 1)|0; + var colMajor = GLImmediate.matrix.lib.mat4.create(); + GLImmediate.matrix.lib.mat4.set({{{ makeHEAPView('F64', 'matrix', 'matrix+' + (16*8)) }}}, colMajor); + GLImmediate.matrix.lib.mat4.transpose(colMajor); + GLImmediate.matrix.lib.mat4.multiply(GLImmediate.matrix[GLImmediate.currentMatrix], colMajor); }, glMultTransposeMatrixf: function(matrix) { - GL.immediate.matricesModified = true; - GL.immediate.matrixVersion[GL.immediate.currentMatrix] = (GL.immediate.matrixVersion[GL.immediate.currentMatrix] + 1)|0; - var colMajor = GL.immediate.matrix.lib.mat4.create(); - GL.immediate.matrix.lib.mat4.set({{{ makeHEAPView('F32', 'matrix', 'matrix+' + (16*4)) }}}, colMajor); - GL.immediate.matrix.lib.mat4.transpose(colMajor); - GL.immediate.matrix.lib.mat4.multiply(GL.immediate.matrix[GL.immediate.currentMatrix], colMajor); + GLImmediate.matricesModified = true; + GLImmediate.matrixVersion[GLImmediate.currentMatrix] = (GLImmediate.matrixVersion[GLImmediate.currentMatrix] + 1)|0; + var colMajor = GLImmediate.matrix.lib.mat4.create(); + GLImmediate.matrix.lib.mat4.set({{{ makeHEAPView('F32', 'matrix', 'matrix+' + (16*4)) }}}, colMajor); + GLImmediate.matrix.lib.mat4.transpose(colMajor); + GLImmediate.matrix.lib.mat4.multiply(GLImmediate.matrix[GLImmediate.currentMatrix], colMajor); }, glFrustum: function(left, right, bottom, top_, nearVal, farVal) { - GL.immediate.matricesModified = true; - GL.immediate.matrixVersion[GL.immediate.currentMatrix] = (GL.immediate.matrixVersion[GL.immediate.currentMatrix] + 1)|0; - GL.immediate.matrix.lib.mat4.multiply(GL.immediate.matrix[GL.immediate.currentMatrix], - GL.immediate.matrix.lib.mat4.frustum(left, right, bottom, top_, nearVal, farVal)); + GLImmediate.matricesModified = true; + GLImmediate.matrixVersion[GLImmediate.currentMatrix] = (GLImmediate.matrixVersion[GLImmediate.currentMatrix] + 1)|0; + GLImmediate.matrix.lib.mat4.multiply(GLImmediate.matrix[GLImmediate.currentMatrix], + GLImmediate.matrix.lib.mat4.frustum(left, right, bottom, top_, nearVal, farVal)); }, glFrustumf: 'glFrustum', glOrtho: function(left, right, bottom, top_, nearVal, farVal) { - GL.immediate.matricesModified = true; - GL.immediate.matrixVersion[GL.immediate.currentMatrix] = (GL.immediate.matrixVersion[GL.immediate.currentMatrix] + 1)|0; - GL.immediate.matrix.lib.mat4.multiply(GL.immediate.matrix[GL.immediate.currentMatrix], - GL.immediate.matrix.lib.mat4.ortho(left, right, bottom, top_, nearVal, farVal)); + GLImmediate.matricesModified = true; + GLImmediate.matrixVersion[GLImmediate.currentMatrix] = (GLImmediate.matrixVersion[GLImmediate.currentMatrix] + 1)|0; + GLImmediate.matrix.lib.mat4.multiply(GLImmediate.matrix[GLImmediate.currentMatrix], + GLImmediate.matrix.lib.mat4.ortho(left, right, bottom, top_, nearVal, farVal)); }, glOrthof: 'glOrtho', glScaled: function(x, y, z) { - GL.immediate.matricesModified = true; - GL.immediate.matrixVersion[GL.immediate.currentMatrix] = (GL.immediate.matrixVersion[GL.immediate.currentMatrix] + 1)|0; - GL.immediate.matrix.lib.mat4.scale(GL.immediate.matrix[GL.immediate.currentMatrix], [x, y, z]); + GLImmediate.matricesModified = true; + GLImmediate.matrixVersion[GLImmediate.currentMatrix] = (GLImmediate.matrixVersion[GLImmediate.currentMatrix] + 1)|0; + GLImmediate.matrix.lib.mat4.scale(GLImmediate.matrix[GLImmediate.currentMatrix], [x, y, z]); }, glScalef: 'glScaled', glTranslated: function(x, y, z) { - GL.immediate.matricesModified = true; - GL.immediate.matrixVersion[GL.immediate.currentMatrix] = (GL.immediate.matrixVersion[GL.immediate.currentMatrix] + 1)|0; - GL.immediate.matrix.lib.mat4.translate(GL.immediate.matrix[GL.immediate.currentMatrix], [x, y, z]); + GLImmediate.matricesModified = true; + GLImmediate.matrixVersion[GLImmediate.currentMatrix] = (GLImmediate.matrixVersion[GLImmediate.currentMatrix] + 1)|0; + GLImmediate.matrix.lib.mat4.translate(GLImmediate.matrix[GLImmediate.currentMatrix], [x, y, z]); }, glTranslatef: 'glTranslated', glRotated: function(angle, x, y, z) { - GL.immediate.matricesModified = true; - GL.immediate.matrixVersion[GL.immediate.currentMatrix] = (GL.immediate.matrixVersion[GL.immediate.currentMatrix] + 1)|0; - GL.immediate.matrix.lib.mat4.rotate(GL.immediate.matrix[GL.immediate.currentMatrix], angle*Math.PI/180, [x, y, z]); + GLImmediate.matricesModified = true; + GLImmediate.matrixVersion[GLImmediate.currentMatrix] = (GLImmediate.matrixVersion[GLImmediate.currentMatrix] + 1)|0; + GLImmediate.matrix.lib.mat4.rotate(GLImmediate.matrix[GLImmediate.currentMatrix], angle*Math.PI/180, [x, y, z]); }, glRotatef: 'glRotated', @@ -4840,17 +4840,17 @@ var LibraryGL = { // GLU gluPerspective: function(fov, aspect, near, far) { - GL.immediate.matricesModified = true; - GL.immediate.matrixVersion[GL.immediate.currentMatrix] = (GL.immediate.matrixVersion[GL.immediate.currentMatrix] + 1)|0; - GL.immediate.matrix[GL.immediate.currentMatrix] = - GL.immediate.matrix.lib.mat4.perspective(fov, aspect, near, far, - GL.immediate.matrix[GL.immediate.currentMatrix]); + GLImmediate.matricesModified = true; + GLImmediate.matrixVersion[GLImmediate.currentMatrix] = (GLImmediate.matrixVersion[GLImmediate.currentMatrix] + 1)|0; + GLImmediate.matrix[GLImmediate.currentMatrix] = + GLImmediate.matrix.lib.mat4.perspective(fov, aspect, near, far, + GLImmediate.matrix[GLImmediate.currentMatrix]); }, gluLookAt: function(ex, ey, ez, cx, cy, cz, ux, uy, uz) { - GL.immediate.matricesModified = true; - GL.immediate.matrixVersion[GL.immediate.currentMatrix] = (GL.immediate.matrixVersion[GL.immediate.currentMatrix] + 1)|0; - GL.immediate.matrix.lib.mat4.lookAt(GL.immediate.matrix[GL.immediate.currentMatrix], [ex, ey, ez], + GLImmediate.matricesModified = true; + GLImmediate.matrixVersion[GLImmediate.currentMatrix] = (GLImmediate.matrixVersion[GLImmediate.currentMatrix] + 1)|0; + GLImmediate.matrix.lib.mat4.lookAt(GLImmediate.matrix[GLImmediate.currentMatrix], [ex, ey, ez], [cx, cy, cz], [ux, uy, uz]); }, @@ -4859,9 +4859,9 @@ var LibraryGL = { var inVec = new Float32Array(4); var outVec = new Float32Array(4); - GL.immediate.matrix.lib.mat4.multiplyVec4({{{ makeHEAPView('F64', 'model', 'model+' + (16*8)) }}}, + GLImmediate.matrix.lib.mat4.multiplyVec4({{{ makeHEAPView('F64', 'model', 'model+' + (16*8)) }}}, [objX, objY, objZ, 1.0], outVec); - GL.immediate.matrix.lib.mat4.multiplyVec4({{{ makeHEAPView('F64', 'proj', 'proj+' + (16*8)) }}}, + GLImmediate.matrix.lib.mat4.multiplyVec4({{{ makeHEAPView('F64', 'proj', 'proj+' + (16*8)) }}}, outVec, inVec); if (inVec[3] == 0.0) { return 0 /* GL_FALSE */; @@ -4885,7 +4885,7 @@ var LibraryGL = { }, gluUnProject: function(winX, winY, winZ, model, proj, view, objX, objY, objZ) { - var result = GL.immediate.matrix.lib.mat4.unproject([winX, winY, winZ], + var result = GLImmediate.matrix.lib.mat4.unproject([winX, winY, winZ], {{{ makeHEAPView('F64', 'model', 'model+' + (16*8)) }}}, {{{ makeHEAPView('F64', 'proj', 'proj+' + (16*8)) }}}, {{{ makeHEAPView('32', 'view', 'view+' + (4*4)) }}}); From 53af5de771b71a3424e51e19aac4395521d99e4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Fri, 3 Jan 2014 23:53:30 +0200 Subject: [PATCH 19/42] Simplify verbose object dereference hierarchy in library_gl.js by storing global WebGL context in the variable GLctx in addition to Module.ctx. --- src/library_browser.js | 2 +- src/library_gl.js | 504 ++++++++++++++++++++--------------------- 2 files changed, 253 insertions(+), 253 deletions(-) diff --git a/src/library_browser.js b/src/library_browser.js index e0f53052d1639..d5e35339f9e22 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(); diff --git a/src/library_gl.js b/src/library_gl.js index 57aba36c60fbf..00d36bd3ba1c7 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -100,14 +100,14 @@ var LibraryGL = { } 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); + GL.tempVertexBuffers[curr] = GLctx.createBuffer(); + GLctx.bindBuffer(GLctx.ARRAY_BUFFER, GL.tempVertexBuffers[curr]); + GLctx.bufferData(GLctx.ARRAY_BUFFER, size, GLctx.DYNAMIC_DRAW); + GLctx.bindBuffer(GLctx.ARRAY_BUFFER, null); + GL.tempIndexBuffers[curr] = GLctx.createBuffer(); + GLctx.bindBuffer(GLctx.ELEMENT_ARRAY_BUFFER, GL.tempIndexBuffers[curr]); + GLctx.bufferData(GLctx.ELEMENT_ARRAY_BUFFER, size, GLctx.DYNAMIC_DRAW); + GLctx.bindBuffer(GLctx.ELEMENT_ARRAY_BUFFER, null); last = size; } GL.tempBufferIndexLookup[i] = curr; @@ -115,8 +115,8 @@ var LibraryGL = { 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; @@ -135,8 +135,8 @@ 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); } }, @@ -186,13 +186,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."); @@ -244,7 +244,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 @@ -256,7 +256,7 @@ var LibraryGL = { } if (ret === undefined) { - var result = Module.ctx.getParameter(name_); + var result = GLctx.getParameter(name_); switch (typeof(result)) { case "number": ret = result; @@ -395,7 +395,7 @@ var LibraryGL = { default: throw 'Invalid format (' + format + ')'; } - internalFormat = Module.ctx.RGBA; + internalFormat = GLctx.RGBA; break; default: throw 'Invalid type (' + type + ')'; @@ -421,13 +421,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 @@ -466,20 +466,20 @@ var LibraryGL = { 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, + 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 @@ -548,7 +548,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 }; @@ -558,18 +558,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. @@ -593,11 +593,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. } } }, @@ -624,9 +624,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); @@ -640,14 +640,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; @@ -663,7 +663,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', @@ -674,10 +674,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]); @@ -718,7 +718,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') }}}; @@ -730,7 +730,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; } @@ -746,7 +746,7 @@ var LibraryGL = { } else { data = null; } - Module.ctx['compressedTexImage2D'](target, level, internalFormat, width, height, border, data); + GLctx.compressedTexImage2D(target, level, internalFormat, width, height, border, data); }, glCompressedTexSubImage2D__sig: 'viiiiiiiii', @@ -759,7 +759,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', @@ -771,7 +771,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); }, glTexSubImage2D__sig: 'viiiiiiiii', @@ -782,7 +782,7 @@ var LibraryGL = { } else { pixels = null; } - Module.ctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels); + GLctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels); }, glReadPixels__sig: 'viiiiiii', @@ -806,7 +806,7 @@ var LibraryGL = { return; } var totalSize = width*height*sizePerPixel; - Module.ctx.readPixels(x, y, width, height, format, type, HEAPU8.subarray(pixels, pixels + totalSize)); + GLctx.readPixels(x, y, width, height, format, type, HEAPU8.subarray(pixels, pixels + totalSize)); }, glBindTexture__sig: 'vii', @@ -814,7 +814,7 @@ var LibraryGL = { #if GL_ASSERTIONS GL.validateGLObjectID(GL.textures, texture, 'glBindTexture', 'texture'); #endif - Module.ctx.bindTexture(target, texture ? GL.textures[texture] : null); + GLctx.bindTexture(target, texture ? GL.textures[texture] : null); }, glGetTexParameterfv__sig: 'viii', @@ -830,27 +830,27 @@ var LibraryGL = { glTexParameterfv__sig: 'viii', glTexParameterfv: function(target, pname, params) { var param = {{{ makeGetValue('params', '0', 'float') }}}; - Module.ctx.texParameterf(target, pname, param); + GLctx.texParameterf(target, pname, param); }, glTexParameteriv__sig: 'viii', glTexParameteriv: function(target, pname, params) { var param = {{{ makeGetValue('params', '0', 'i32') }}}; - Module.ctx.texParameteri(target, pname, param); + GLctx.texParameteri(target, pname, param); }, glIsTexture__sig: 'ii', glIsTexture: function(texture) { var texture = GL.textures[texture]; if (!texture) return 0; - return Module.ctx.isTexture(texture); + return GLctx.isTexture(texture); }, glGenBuffers__sig: 'vii', glGenBuffers: function(n, buffers) { for (var i = 0; i < n; i++) { var id = GL.getNewId(GL.buffers); - var buffer = Module.ctx.createBuffer(); + var buffer = GLctx.createBuffer(); buffer.name = id; GL.buffers[id] = buffer; {{{ makeSetValue('buffers', 'i*4', 'id', 'i32') }}}; @@ -867,7 +867,7 @@ var LibraryGL = { // correspond to existing buffer objects." if (!buffer) continue; - Module.ctx.deleteBuffer(buffer); + GLctx.deleteBuffer(buffer); buffer.name = 0; GL.buffers[id] = null; @@ -878,7 +878,7 @@ var LibraryGL = { glGetBufferParameteriv__sig: 'viii', glGetBufferParameteriv: function(target, value, data) { - {{{ makeSetValue('data', '0', 'Module.ctx.getBufferParameter(target, value)', 'i32') }}}; + {{{ makeSetValue('data', '0', 'GLctx.getBufferParameter(target, value)', 'i32') }}}; }, glBufferData__sig: 'viiii', @@ -897,26 +897,26 @@ var LibraryGL = { usage = 0x88E8; // GL_DYNAMIC_DRAW break; } - Module.ctx.bufferData(target, HEAPU8.subarray(data, data+size), usage); + GLctx.bufferData(target, HEAPU8.subarray(data, data+size), usage); }, glBufferSubData__sig: 'viiii', glBufferSubData: function(target, offset, size, data) { - Module.ctx.bufferSubData(target, offset, HEAPU8.subarray(data, data+size)); + GLctx.bufferSubData(target, offset, HEAPU8.subarray(data, data+size)); }, glIsBuffer__sig: 'ii', glIsBuffer: function(buffer) { var b = GL.buffers[buffer]; if (!b) return 0; - return Module.ctx.isBuffer(b); + return GLctx.isBuffer(b); }, glGenRenderbuffers__sig: 'vii', glGenRenderbuffers: function(n, renderbuffers) { for (var i = 0; i < n; i++) { var id = GL.getNewId(GL.renderbuffers); - var renderbuffer = Module.ctx.createRenderbuffer(); + var renderbuffer = GLctx.createRenderbuffer(); renderbuffer.name = id; GL.renderbuffers[id] = renderbuffer; {{{ makeSetValue('renderbuffers', 'i*4', 'id', 'i32') }}}; @@ -928,7 +928,7 @@ var LibraryGL = { for (var i = 0; i < n; i++) { var id = {{{ makeGetValue('renderbuffers', 'i*4', 'i32') }}}; var renderbuffer = GL.renderbuffers[id]; - Module.ctx.deleteRenderbuffer(renderbuffer); + GLctx.deleteRenderbuffer(renderbuffer); renderbuffer.name = 0; GL.renderbuffers[id] = null; } @@ -939,19 +939,19 @@ var LibraryGL = { #if GL_ASSERTIONS GL.validateGLObjectID(GL.renderbuffers, renderbuffer, 'glBindRenderbuffer', 'renderbuffer'); #endif - Module.ctx.bindRenderbuffer(target, renderbuffer ? GL.renderbuffers[renderbuffer] : null); + GLctx.bindRenderbuffer(target, renderbuffer ? GL.renderbuffers[renderbuffer] : null); }, glGetRenderbufferParameteriv__sig: 'viii', glGetRenderbufferParameteriv: function(target, pname, params) { - {{{ makeSetValue('params', '0', 'Module.ctx.getRenderbufferParameter(target, pname)', 'i32') }}}; + {{{ makeSetValue('params', '0', 'GLctx.getRenderbufferParameter(target, pname)', 'i32') }}}; }, glIsRenderbuffer__sig: 'ii', glIsRenderbuffer: function(renderbuffer) { var rb = GL.renderbuffers[renderbuffer]; if (!rb) return 0; - return Module.ctx.isRenderbuffer(rb); + return GLctx.isRenderbuffer(rb); }, glGetUniformfv__sig: 'viii', @@ -960,7 +960,7 @@ var LibraryGL = { GL.validateGLObjectID(GL.programs, program, 'glGetUniformfv', 'program'); GL.validateGLObjectID(GL.uniforms, location, 'glGetUniformfv', 'location'); #endif - var data = Module.ctx.getUniform(GL.programs[program], GL.uniforms[location]); + var data = GLctx.getUniform(GL.programs[program], GL.uniforms[location]); if (typeof data == 'number') { {{{ makeSetValue('params', '0', 'data', 'float') }}}; } else { @@ -976,7 +976,7 @@ var LibraryGL = { GL.validateGLObjectID(GL.programs, program, 'glGetUniformiv', 'program'); GL.validateGLObjectID(GL.uniforms, location, 'glGetUniformiv', 'location'); #endif - var data = Module.ctx.getUniform(GL.programs[program], GL.uniforms[location]); + var data = GLctx.getUniform(GL.programs[program], GL.uniforms[location]); if (typeof data == 'number' || typeof data == 'boolean') { {{{ makeSetValue('params', '0', 'data', 'i32') }}}; } else { @@ -1027,7 +1027,7 @@ var LibraryGL = { Module.printErr("glGetVertexAttribfv on client-side array: not supported, bad data returned"); } #endif - var data = Module.ctx.getVertexAttrib(index, pname); + var data = GLctx.getVertexAttrib(index, pname); if (typeof data == 'number') { {{{ makeSetValue('params', '0', 'data', 'float') }}}; } else { @@ -1044,7 +1044,7 @@ var LibraryGL = { Module.printErr("glGetVertexAttribiv on client-side array: not supported, bad data returned"); } #endif - var data = Module.ctx.getVertexAttrib(index, pname); + var data = GLctx.getVertexAttrib(index, pname); if (typeof data == 'number' || typeof data == 'boolean') { {{{ makeSetValue('params', '0', 'data', 'i32') }}}; } else { @@ -1061,7 +1061,7 @@ var LibraryGL = { Module.printErr("glGetVertexAttribPointer on client-side array: not supported, bad data returned"); } #endif - {{{ makeSetValue('pointer', '0', 'Module.ctx.getVertexAttribOffset(index, pname)', 'i32') }}}; + {{{ makeSetValue('pointer', '0', 'GLctx.getVertexAttribOffset(index, pname)', 'i32') }}}; }, glGetActiveUniform__sig: 'viiiiiii', @@ -1070,7 +1070,7 @@ var LibraryGL = { GL.validateGLObjectID(GL.programs, program, 'glGetActiveUniform', 'program'); #endif program = GL.programs[program]; - var info = Module.ctx.getActiveUniform(program, index); + var info = GLctx.getActiveUniform(program, index); var infoname = info.name.slice(0, Math.max(0, bufSize - 1)); writeStringToMemory(infoname, name); @@ -1092,7 +1092,7 @@ var LibraryGL = { GL.validateGLObjectID(GL.uniforms, location, 'glUniform1f', 'location'); #endif location = GL.uniforms[location]; - Module.ctx.uniform1f(location, v0); + GLctx.uniform1f(location, v0); }, glUniform2f__sig: 'viff', @@ -1101,7 +1101,7 @@ var LibraryGL = { GL.validateGLObjectID(GL.uniforms, location, 'glUniform2f', 'location'); #endif location = GL.uniforms[location]; - Module.ctx.uniform2f(location, v0, v1); + GLctx.uniform2f(location, v0, v1); }, glUniform3f__sig: 'vifff', @@ -1110,7 +1110,7 @@ var LibraryGL = { GL.validateGLObjectID(GL.uniforms, location, 'glUniform3f', 'location'); #endif location = GL.uniforms[location]; - Module.ctx.uniform3f(location, v0, v1, v2); + GLctx.uniform3f(location, v0, v1, v2); }, glUniform4f__sig: 'viffff', @@ -1119,7 +1119,7 @@ var LibraryGL = { GL.validateGLObjectID(GL.uniforms, location, 'glUniform4f', 'location'); #endif location = GL.uniforms[location]; - Module.ctx.uniform4f(location, v0, v1, v2, v3); + GLctx.uniform4f(location, v0, v1, v2, v3); }, glUniform1i__sig: 'vii', @@ -1128,7 +1128,7 @@ var LibraryGL = { GL.validateGLObjectID(GL.uniforms, location, 'glUniform1i', 'location'); #endif location = GL.uniforms[location]; - Module.ctx.uniform1i(location, v0); + GLctx.uniform1i(location, v0); }, glUniform2i__sig: 'viii', @@ -1137,7 +1137,7 @@ var LibraryGL = { GL.validateGLObjectID(GL.uniforms, location, 'glUniform2i', 'location'); #endif location = GL.uniforms[location]; - Module.ctx.uniform2i(location, v0, v1); + GLctx.uniform2i(location, v0, v1); }, glUniform3i__sig: 'viiii', @@ -1146,7 +1146,7 @@ var LibraryGL = { GL.validateGLObjectID(GL.uniforms, location, 'glUniform3i', 'location'); #endif location = GL.uniforms[location]; - Module.ctx.uniform3i(location, v0, v1, v2); + GLctx.uniform3i(location, v0, v1, v2); }, glUniform4i__sig: 'viiiii', @@ -1155,7 +1155,7 @@ var LibraryGL = { GL.validateGLObjectID(GL.uniforms, location, 'glUniform4i', 'location'); #endif location = GL.uniforms[location]; - Module.ctx.uniform4i(location, v0, v1, v2, v3); + GLctx.uniform4i(location, v0, v1, v2, v3); }, glUniform1iv__sig: 'viii', @@ -1165,7 +1165,7 @@ var LibraryGL = { #endif location = GL.uniforms[location]; value = {{{ makeHEAPView('32', 'value', 'value+count*4') }}}; - Module.ctx.uniform1iv(location, value); + GLctx.uniform1iv(location, value); }, glUniform2iv__sig: 'viii', @@ -1176,7 +1176,7 @@ var LibraryGL = { location = GL.uniforms[location]; count *= 2; value = {{{ makeHEAPView('32', 'value', 'value+count*4') }}}; - Module.ctx.uniform2iv(location, value); + GLctx.uniform2iv(location, value); }, glUniform3iv__sig: 'viii', @@ -1187,7 +1187,7 @@ var LibraryGL = { location = GL.uniforms[location]; count *= 3; value = {{{ makeHEAPView('32', 'value', 'value+count*4') }}}; - Module.ctx.uniform3iv(location, value); + GLctx.uniform3iv(location, value); }, glUniform4iv__sig: 'viii', @@ -1198,7 +1198,7 @@ var LibraryGL = { location = GL.uniforms[location]; count *= 4; value = {{{ makeHEAPView('32', 'value', 'value+count*4') }}}; - Module.ctx.uniform4iv(location, value); + GLctx.uniform4iv(location, value); }, glUniform1fv__sig: 'viii', @@ -1215,7 +1215,7 @@ var LibraryGL = { } else { view = {{{ makeHEAPView('F32', 'value', 'value+count*4') }}}; } - Module.ctx.uniform1fv(location, view); + GLctx.uniform1fv(location, view); }, glUniform2fv__sig: 'viii', @@ -1233,7 +1233,7 @@ var LibraryGL = { } else { view = {{{ makeHEAPView('F32', 'value', 'value+count*8') }}}; } - Module.ctx.uniform2fv(location, view); + GLctx.uniform2fv(location, view); }, glUniform3fv__sig: 'viii', @@ -1252,7 +1252,7 @@ var LibraryGL = { } else { view = {{{ makeHEAPView('F32', 'value', 'value+count*12') }}}; } - Module.ctx.uniform3fv(location, view); + GLctx.uniform3fv(location, view); }, glUniform4fv__sig: 'viii', @@ -1272,7 +1272,7 @@ var LibraryGL = { } else { view = {{{ makeHEAPView('F32', 'value', 'value+count*16') }}}; } - Module.ctx.uniform4fv(location, view); + GLctx.uniform4fv(location, view); }, glUniformMatrix2fv__sig: 'viiii', @@ -1291,7 +1291,7 @@ var LibraryGL = { } else { view = {{{ makeHEAPView('F32', 'value', 'value+count*16') }}}; } - Module.ctx.uniformMatrix2fv(location, transpose, view); + GLctx.uniformMatrix2fv(location, transpose, view); }, glUniformMatrix3fv__sig: 'viiii', @@ -1310,7 +1310,7 @@ var LibraryGL = { } else { view = {{{ makeHEAPView('F32', 'value', 'value+count*36') }}}; } - Module.ctx.uniformMatrix3fv(location, transpose, view); + GLctx.uniformMatrix3fv(location, transpose, view); }, glUniformMatrix4fv__sig: 'viiii', @@ -1329,7 +1329,7 @@ var LibraryGL = { } else { view = {{{ makeHEAPView('F32', 'value', 'value+count*64') }}}; } - Module.ctx.uniformMatrix4fv(location, transpose, view); + GLctx.uniformMatrix4fv(location, transpose, view); }, glBindBuffer__sig: 'vii', @@ -1340,52 +1340,52 @@ var LibraryGL = { var bufferObj = buffer ? GL.buffers[buffer] : null; #if FULL_ES2 - if (target == Module.ctx.ARRAY_BUFFER) { + if (target == GLctx.ARRAY_BUFFER) { GL.currArrayBuffer = buffer; - } else if (target == Module.ctx.ELEMENT_ARRAY_BUFFER) { + } else if (target == GLctx.ELEMENT_ARRAY_BUFFER) { GL.currElementArrayBuffer = buffer; } #endif #if LEGACY_GL_EMULATION - if (target == Module.ctx.ARRAY_BUFFER) { + if (target == GLctx.ARRAY_BUFFER) { GLImmediate.lastArrayBuffer = GL.currArrayBuffer = buffer; - } else if (target == Module.ctx.ELEMENT_ARRAY_BUFFER) { + } else if (target == GLctx.ELEMENT_ARRAY_BUFFER) { GL.currElementArrayBuffer = buffer; } #endif - Module.ctx.bindBuffer(target, bufferObj); + GLctx.bindBuffer(target, bufferObj); }, glVertexAttrib1fv__sig: 'vii', glVertexAttrib1fv: function(index, v) { v = {{{ makeHEAPView('F32', 'v', 'v+' + (1*4)) }}}; - Module.ctx.vertexAttrib1fv(index, v); + GLctx.vertexAttrib1fv(index, v); }, glVertexAttrib2fv__sig: 'vii', glVertexAttrib2fv: function(index, v) { v = {{{ makeHEAPView('F32', 'v', 'v+' + (2*4)) }}}; - Module.ctx.vertexAttrib2fv(index, v); + GLctx.vertexAttrib2fv(index, v); }, glVertexAttrib3fv__sig: 'vii', glVertexAttrib3fv: function(index, v) { v = {{{ makeHEAPView('F32', 'v', 'v+' + (3*4)) }}}; - Module.ctx.vertexAttrib3fv(index, v); + GLctx.vertexAttrib3fv(index, v); }, glVertexAttrib4fv__sig: 'vii', glVertexAttrib4fv: function(index, v) { v = {{{ makeHEAPView('F32', 'v', 'v+' + (4*4)) }}}; - Module.ctx.vertexAttrib4fv(index, v); + GLctx.vertexAttrib4fv(index, v); }, glGetAttribLocation__sig: 'vii', glGetAttribLocation: function(program, name) { program = GL.programs[program]; name = Pointer_stringify(name); - return Module.ctx.getAttribLocation(program, name); + return GLctx.getAttribLocation(program, name); }, glGetActiveAttrib__sig: 'viiiiiii', @@ -1394,7 +1394,7 @@ var LibraryGL = { GL.validateGLObjectID(GL.programs, program, 'glGetActiveAttrib', 'program'); #endif program = GL.programs[program]; - var info = Module.ctx.getActiveAttrib(program, index); + var info = GLctx.getActiveAttrib(program, index); var infoname = info.name.slice(0, Math.max(0, bufSize - 1)); writeStringToMemory(infoname, name); @@ -1413,13 +1413,13 @@ var LibraryGL = { glCreateShader__sig: 'ii', glCreateShader: function(shaderType) { var id = GL.getNewId(GL.shaders); - GL.shaders[id] = Module.ctx.createShader(shaderType); + GL.shaders[id] = GLctx.createShader(shaderType); return id; }, glDeleteShader__sig: 'vi', glDeleteShader: function(shader) { - Module.ctx.deleteShader(GL.shaders[shader]); + GLctx.deleteShader(GL.shaders[shader]); GL.shaders[shader] = null; }, @@ -1428,7 +1428,7 @@ var LibraryGL = { #if GL_ASSERTIONS GL.validateGLObjectID(GL.programs, program, 'glGetAttachedShaders', 'program'); #endif - var result = Module.ctx.getAttachedShaders(GL.programs[program]); + var result = GLctx.getAttachedShaders(GL.programs[program]); var len = result.length; if (len > maxCount) { len = maxCount; @@ -1449,7 +1449,7 @@ var LibraryGL = { GL.validateGLObjectID(GL.shaders, shader, 'glShaderSource', 'shader'); #endif var source = GL.getSource(shader, count, string, length); - Module.ctx.shaderSource(GL.shaders[shader], source); + GLctx.shaderSource(GL.shaders[shader], source); }, glGetShaderSource__sig: 'viiii', @@ -1457,7 +1457,7 @@ var LibraryGL = { #if GL_ASSERTIONS GL.validateGLObjectID(GL.shaders, shader, 'glGetShaderSource', 'shader'); #endif - var result = Module.ctx.getShaderSource(GL.shaders[shader]); + var result = GLctx.getShaderSource(GL.shaders[shader]); result = result.slice(0, Math.max(0, bufSize - 1)); writeStringToMemory(result, source); if (length) { @@ -1470,7 +1470,7 @@ var LibraryGL = { #if GL_ASSERTIONS GL.validateGLObjectID(GL.shaders, shader, 'glCompileShader', 'shader'); #endif - Module.ctx.compileShader(GL.shaders[shader]); + GLctx.compileShader(GL.shaders[shader]); }, glGetShaderInfoLog__sig: 'viiii', @@ -1478,7 +1478,7 @@ var LibraryGL = { #if GL_ASSERTIONS GL.validateGLObjectID(GL.shaders, shader, 'glGetShaderInfoLog', 'shader'); #endif - var log = Module.ctx.getShaderInfoLog(GL.shaders[shader]); + var log = GLctx.getShaderInfoLog(GL.shaders[shader]); // Work around a bug in Chromium which causes getShaderInfoLog to return null if (!log) { log = ""; @@ -1496,9 +1496,9 @@ var LibraryGL = { GL.validateGLObjectID(GL.shaders, shader, 'glGetShaderiv', 'shader'); #endif if (pname == 0x8B84) { // GL_INFO_LOG_LENGTH - {{{ makeSetValue('p', '0', 'Module.ctx.getShaderInfoLog(GL.shaders[shader]).length + 1', 'i32') }}}; + {{{ makeSetValue('p', '0', 'GLctx.getShaderInfoLog(GL.shaders[shader]).length + 1', 'i32') }}}; } else { - {{{ makeSetValue('p', '0', 'Module.ctx.getShaderParameter(GL.shaders[shader], pname)', 'i32') }}}; + {{{ makeSetValue('p', '0', 'GLctx.getShaderParameter(GL.shaders[shader], pname)', 'i32') }}}; } }, @@ -1508,7 +1508,7 @@ var LibraryGL = { GL.validateGLObjectID(GL.programs, program, 'glGetProgramiv', 'program'); #endif if (pname == 0x8B84) { // GL_INFO_LOG_LENGTH - {{{ makeSetValue('p', '0', 'Module.ctx.getProgramInfoLog(GL.programs[program]).length + 1', 'i32') }}}; + {{{ makeSetValue('p', '0', 'GLctx.getProgramInfoLog(GL.programs[program]).length + 1', 'i32') }}}; } else if (pname == 0x8B87 /* GL_ACTIVE_UNIFORM_MAX_LENGTH */) { var ptable = GL.programInfos[program]; if (ptable) { @@ -1530,10 +1530,10 @@ var LibraryGL = { if (ptable) { if (ptable.maxAttributeLength == -1) { var program = GL.programs[program]; - var numAttribs = Module.ctx.getProgramParameter(program, Module.ctx.ACTIVE_ATTRIBUTES); + var numAttribs = GLctx.getProgramParameter(program, GLctx.ACTIVE_ATTRIBUTES); ptable.maxAttributeLength = 0; // Spec says if there are no active attribs, 0 must be returned. for(var i = 0; i < numAttribs; ++i) { - var activeAttrib = Module.ctx.getActiveAttrib(program, i); + var activeAttrib = GLctx.getActiveAttrib(program, i); ptable.maxAttributeLength = Math.max(ptable.maxAttributeLength, activeAttrib.name.length+1); } } @@ -1551,7 +1551,7 @@ var LibraryGL = { GL.recordError(0x0501 /* GL_INVALID_VALUE */); } } else { - {{{ makeSetValue('p', '0', 'Module.ctx.getProgramParameter(GL.programs[program], pname)', 'i32') }}}; + {{{ makeSetValue('p', '0', 'GLctx.getProgramParameter(GL.programs[program], pname)', 'i32') }}}; } }, @@ -1559,13 +1559,13 @@ var LibraryGL = { glIsShader: function(shader) { var s = GL.shaders[shader]; if (!s) return 0; - return Module.ctx.isShader(s); + return GLctx.isShader(s); }, glCreateProgram__sig: 'i', glCreateProgram: function() { var id = GL.getNewId(GL.programs); - var program = Module.ctx.createProgram(); + var program = GLctx.createProgram(); program.name = id; GL.programs[id] = program; return id; @@ -1574,7 +1574,7 @@ var LibraryGL = { glDeleteProgram__sig: 'vi', glDeleteProgram: function(program) { var program = GL.programs[program]; - Module.ctx.deleteProgram(program); + GLctx.deleteProgram(program); program.name = 0; GL.programs[program] = null; GL.programInfos[program] = null; @@ -1586,7 +1586,7 @@ var LibraryGL = { GL.validateGLObjectID(GL.programs, program, 'glAttachShader', 'program'); GL.validateGLObjectID(GL.shaders, shader, 'glAttachShader', 'shader'); #endif - Module.ctx.attachShader(GL.programs[program], + GLctx.attachShader(GL.programs[program], GL.shaders[shader]); }, @@ -1596,12 +1596,12 @@ var LibraryGL = { GL.validateGLObjectID(GL.programs, program, 'glDetachShader', 'program'); GL.validateGLObjectID(GL.shaders, shader, 'glDetachShader', 'shader'); #endif - Module.ctx.detachShader(GL.programs[program], + GLctx.detachShader(GL.programs[program], GL.shaders[shader]); }, glGetShaderPrecisionFormat: function(shaderType, precisionType, range, precision) { - var result = Module.ctx.getShaderPrecisionFormat(shaderType, precisionType); + var result = GLctx.getShaderPrecisionFormat(shaderType, precisionType); {{{ makeSetValue('range', '0', 'result.rangeMin', 'i32') }}}; {{{ makeSetValue('range', '4', 'result.rangeMax', 'i32') }}}; {{{ makeSetValue('precision', '0', 'result.precision', 'i32') }}}; @@ -1612,7 +1612,7 @@ var LibraryGL = { #if GL_ASSERTIONS GL.validateGLObjectID(GL.programs, program, 'glLinkProgram', 'program'); #endif - Module.ctx.linkProgram(GL.programs[program]); + GLctx.linkProgram(GL.programs[program]); GL.programInfos[program] = null; // uniforms no longer keep the same names after linking GL.populateUniformTable(program); }, @@ -1622,7 +1622,7 @@ var LibraryGL = { #if GL_ASSERTIONS GL.validateGLObjectID(GL.programs, program, 'glGetProgramInfoLog', 'program'); #endif - var log = Module.ctx.getProgramInfoLog(GL.programs[program]); + var log = GLctx.getProgramInfoLog(GL.programs[program]); // Work around a bug in Chromium which causes getProgramInfoLog to return null if (!log) { log = ""; @@ -1639,7 +1639,7 @@ var LibraryGL = { #if GL_ASSERTIONS GL.validateGLObjectID(GL.programs, program, 'glUseProgram', 'program'); #endif - Module.ctx.useProgram(program ? GL.programs[program] : null); + GLctx.useProgram(program ? GL.programs[program] : null); }, glValidateProgram__sig: 'vi', @@ -1647,14 +1647,14 @@ var LibraryGL = { #if GL_ASSERTIONS GL.validateGLObjectID(GL.programs, program, 'glValidateProgram', 'program'); #endif - Module.ctx.validateProgram(GL.programs[program]); + GLctx.validateProgram(GL.programs[program]); }, glIsProgram__sig: 'ii', glIsProgram: function(program) { var program = GL.programs[program]; if (!program) return 0; - return Module.ctx.isProgram(program); + return GLctx.isProgram(program); }, glBindAttribLocation__sig: 'viii', @@ -1663,7 +1663,7 @@ var LibraryGL = { GL.validateGLObjectID(GL.programs, program, 'glBindAttribLocation', 'program'); #endif name = Pointer_stringify(name); - Module.ctx.bindAttribLocation(GL.programs[program], index, name); + GLctx.bindAttribLocation(GL.programs[program], index, name); }, glBindFramebuffer__sig: 'vii', @@ -1671,14 +1671,14 @@ var LibraryGL = { #if GL_ASSERTIONS GL.validateGLObjectID(GL.framebuffers, framebuffer, 'glBindFramebuffer', 'framebuffer'); #endif - Module.ctx.bindFramebuffer(target, framebuffer ? GL.framebuffers[framebuffer] : null); + GLctx.bindFramebuffer(target, framebuffer ? GL.framebuffers[framebuffer] : null); }, glGenFramebuffers__sig: 'vii', glGenFramebuffers: function(n, ids) { for (var i = 0; i < n; ++i) { var id = GL.getNewId(GL.framebuffers); - var framebuffer = Module.ctx.createFramebuffer(); + var framebuffer = GLctx.createFramebuffer(); framebuffer.name = id; GL.framebuffers[id] = framebuffer; {{{ makeSetValue('ids', 'i*4', 'id', 'i32') }}}; @@ -1690,7 +1690,7 @@ var LibraryGL = { for (var i = 0; i < n; ++i) { var id = {{{ makeGetValue('framebuffers', 'i*4', 'i32') }}}; var framebuffer = GL.framebuffers[id]; - Module.ctx.deleteFramebuffer(framebuffer); + GLctx.deleteFramebuffer(framebuffer); framebuffer.name = 0; GL.framebuffers[id] = null; } @@ -1701,7 +1701,7 @@ var LibraryGL = { #if GL_ASSERTIONS GL.validateGLObjectID(GL.renderbuffers, renderbuffer, 'glFramebufferRenderbuffer', 'renderbuffer'); #endif - Module.ctx.framebufferRenderbuffer(target, attachment, renderbuffertarget, + GLctx.framebufferRenderbuffer(target, attachment, renderbuffertarget, GL.renderbuffers[renderbuffer]); }, @@ -1710,13 +1710,13 @@ var LibraryGL = { #if GL_ASSERTIONS GL.validateGLObjectID(GL.textures, texture, 'glFramebufferTexture2D', 'texture'); #endif - Module.ctx.framebufferTexture2D(target, attachment, textarget, + GLctx.framebufferTexture2D(target, attachment, textarget, GL.textures[texture], level); }, glGetFramebufferAttachmentParameteriv__sig: 'viiii', glGetFramebufferAttachmentParameteriv: function(target, attachment, pname, params) { - var result = Module.ctx.getFramebufferAttachmentParameter(target, attachment, pname); + var result = GLctx.getFramebufferAttachmentParameter(target, attachment, pname); {{{ makeSetValue('params', '0', 'result', 'i32') }}}; }, @@ -1724,7 +1724,7 @@ var LibraryGL = { glIsFramebuffer: function(framebuffer) { var fb = GL.framebuffers[framebuffer]; if (!fb) return 0; - return Module.ctx.isFramebuffer(fb); + return GLctx.isFramebuffer(fb); }, #if LEGACY_GL_EMULATION @@ -1837,7 +1837,7 @@ var LibraryGL = { } else if (!(cap in validCapabilities)) { return 0; } - return Module.ctx.isEnabled(cap); + return GLctx.isEnabled(cap); }; var glGetBooleanv = _glGetBooleanv; @@ -1854,23 +1854,23 @@ var LibraryGL = { var glGetIntegerv = _glGetIntegerv; _glGetIntegerv = function _glGetIntegerv(pname, params) { switch (pname) { - case 0x84E2: pname = Module.ctx.MAX_TEXTURE_IMAGE_UNITS /* fake it */; break; // GL_MAX_TEXTURE_UNITS + case 0x84E2: pname = GLctx.MAX_TEXTURE_IMAGE_UNITS /* fake it */; break; // GL_MAX_TEXTURE_UNITS case 0x8B4A: { // GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB - var result = Module.ctx.getParameter(Module.ctx.MAX_VERTEX_UNIFORM_VECTORS); + var result = GLctx.getParameter(GLctx.MAX_VERTEX_UNIFORM_VECTORS); {{{ makeSetValue('params', '0', 'result*4', 'i32') }}}; // GLES gives num of 4-element vectors, GL wants individual components, so multiply return; } case 0x8B49: { // GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB - var result = Module.ctx.getParameter(Module.ctx.MAX_FRAGMENT_UNIFORM_VECTORS); + var result = GLctx.getParameter(GLctx.MAX_FRAGMENT_UNIFORM_VECTORS); {{{ makeSetValue('params', '0', 'result*4', 'i32') }}}; // GLES gives num of 4-element vectors, GL wants individual components, so multiply return; } case 0x8B4B: { // GL_MAX_VARYING_FLOATS_ARB - var result = Module.ctx.getParameter(Module.ctx.MAX_VARYING_VECTORS); + var result = GLctx.getParameter(GLctx.MAX_VARYING_VECTORS); {{{ makeSetValue('params', '0', 'result*4', 'i32') }}}; // GLES gives num of 4-element vectors, GL wants individual components, so multiply return; } - case 0x8871: pname = Module.ctx.MAX_COMBINED_TEXTURE_IMAGE_UNITS /* close enough */; break; // GL_MAX_TEXTURE_COORDS + case 0x8871: pname = GLctx.MAX_COMBINED_TEXTURE_IMAGE_UNITS /* close enough */; break; // GL_MAX_TEXTURE_COORDS case 0x807A: { // GL_VERTEX_ARRAY_SIZE var attribute = GLImmediate.clientAttributes[GLImmediate.VERTEX]; {{{ makeSetValue('params', '0', 'attribute ? attribute.size : 0', 'i32') }}}; @@ -1925,7 +1925,7 @@ var LibraryGL = { if (GL.stringCache[name_]) return GL.stringCache[name_]; switch(name_) { case 0x1F03 /* GL_EXTENSIONS */: // Add various extensions that we can support - var ret = allocate(intArrayFromString(Module.ctx.getSupportedExtensions().join(' ') + + var ret = allocate(intArrayFromString(GLctx.getSupportedExtensions().join(' ') + ' GL_EXT_texture_env_combine GL_ARB_texture_env_crossbar GL_ATI_texture_env_combine3 GL_NV_texture_env_combine4 GL_EXT_texture_env_dot3 GL_ARB_multitexture GL_ARB_vertex_buffer_object GL_EXT_framebuffer_object GL_ARB_vertex_program GL_ARB_fragment_program GL_ARB_shading_language_100 GL_ARB_shader_objects GL_ARB_vertex_shader GL_ARB_fragment_shader GL_ARB_texture_cube_map GL_EXT_draw_range_elements' + (GL.compressionExt ? ' GL_ARB_texture_compression GL_EXT_texture_compression_s3tc' : '') + (GL.anisotropicExt ? ' GL_EXT_texture_filter_anisotropic' : '') @@ -1970,7 +1970,7 @@ var LibraryGL = { #endif // XXX We add attributes and uniforms to shaders. The program can ask for the # of them, and see the // ones we generated, potentially confusing it? Perhaps we should hide them. - if (GL.shaderInfos[shader].type == Module.ctx.VERTEX_SHADER) { + if (GL.shaderInfos[shader].type == GLctx.VERTEX_SHADER) { // Replace ftransform() with explicit project/modelview transforms, and add position and matrix info. var has_pm = source.search(/u_projection/) >= 0; var has_mm = source.search(/u_modelView/) >= 0; @@ -2072,15 +2072,15 @@ var LibraryGL = { GL.shaderSources[shader] = source; console.log("glShaderSource: Output: \n" + source); #endif - Module.ctx.shaderSource(GL.shaders[shader], source); + GLctx.shaderSource(GL.shaders[shader], source); }; var glCompileShader = _glCompileShader; _glCompileShader = function _glCompileShader(shader) { - Module.ctx.compileShader(GL.shaders[shader]); + GLctx.compileShader(GL.shaders[shader]); #if GL_DEBUG - if (!Module.ctx.getShaderParameter(GL.shaders[shader], Module.ctx.COMPILE_STATUS)) { - Module.printErr('Failed to compile shader: ' + Module.ctx.getShaderInfoLog(GL.shaders[shader])); + if (!GLctx.getShaderParameter(GL.shaders[shader], GLctx.COMPILE_STATUS)) { + Module.printErr('Failed to compile shader: ' + GLctx.getShaderInfoLog(GL.shaders[shader])); Module.printErr('Info: ' + JSON.stringify(GL.shaderInfos[shader])); Module.printErr('Original source: ' + GL.shaderOriginalSources[shader]); Module.printErr('Source: ' + GL.shaderSources[shader]); @@ -2149,7 +2149,7 @@ var LibraryGL = { var glLinkProgram = _glLinkProgram; _glLinkProgram = function _glLinkProgram(program) { if (!(program in zeroUsedPrograms)) { - Module.ctx.bindAttribLocation(GL.programs[program], 0, 'a_position'); + GLctx.bindAttribLocation(GL.programs[program], 0, 'a_position'); } glLinkProgram(program); }; @@ -2157,14 +2157,14 @@ var LibraryGL = { var glBindBuffer = _glBindBuffer; _glBindBuffer = function _glBindBuffer(target, buffer) { glBindBuffer(target, buffer); - if (target == Module.ctx.ARRAY_BUFFER) { + if (target == GLctx.ARRAY_BUFFER) { if (GLEmulation.currentVao) { #if ASSERTIONS assert(GLEmulation.currentVao.arrayBuffer == buffer || GLEmulation.currentVao.arrayBuffer == 0 || buffer == 0, 'TODO: support for multiple array buffers in vao'); #endif GLEmulation.currentVao.arrayBuffer = buffer; } - } else if (target == Module.ctx.ELEMENT_ARRAY_BUFFER) { + } else if (target == GLctx.ELEMENT_ARRAY_BUFFER) { if (GLEmulation.currentVao) GLEmulation.currentVao.elementArrayBuffer = buffer; } }; @@ -2262,16 +2262,16 @@ var LibraryGL = { glGetObjectParameteriv: function(id, type, result) { if (GL.programs[id]) { if (type == 0x8B84) { // GL_OBJECT_INFO_LOG_LENGTH_ARB - {{{ makeSetValue('result', '0', 'Module.ctx.getProgramInfoLog(GL.programs[id]).length', 'i32') }}}; + {{{ makeSetValue('result', '0', 'GLctx.getProgramInfoLog(GL.programs[id]).length', 'i32') }}}; return; } _glGetProgramiv(id, type, result); } else if (GL.shaders[id]) { if (type == 0x8B84) { // GL_OBJECT_INFO_LOG_LENGTH_ARB - {{{ makeSetValue('result', '0', 'Module.ctx.getShaderInfoLog(GL.shaders[id]).length', 'i32') }}}; + {{{ makeSetValue('result', '0', 'GLctx.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') }}}; + {{{ makeSetValue('result', '0', 'GLctx.getShaderSource(GL.shaders[id]).length', 'i32') }}}; return; } _glGetShaderiv(id, type, result); @@ -3510,7 +3510,7 @@ var LibraryGL = { var uTexMatrixPrefix = GLImmediate.useTextureMatrix ? 'u_textureMatrix' : null; if (useCurrProgram) { - if (GL.shaderInfos[GL.programShaders[GL.currProgram][0]].type == Module.ctx.VERTEX_SHADER) { + if (GL.shaderInfos[GL.programShaders[GL.currProgram][0]].type == GLctx.VERTEX_SHADER) { this.vertexShader = GL.shaders[GL.programShaders[GL.currProgram][0]]; this.fragmentShader = GL.shaders[GL.programShaders[GL.currProgram][1]]; } else { @@ -3586,9 +3586,9 @@ var LibraryGL = { '' ].join('\n').replace(/\n\n+/g, '\n'); - this.vertexShader = Module.ctx.createShader(Module.ctx.VERTEX_SHADER); - Module.ctx.shaderSource(this.vertexShader, vsSource); - Module.ctx.compileShader(this.vertexShader); + this.vertexShader = GLctx.createShader(GLctx.VERTEX_SHADER); + GLctx.shaderSource(this.vertexShader, vsSource); + GLctx.compileShader(this.vertexShader); var fogHeaderIfNeeded = null; if (GLEmulation.fogEnabled) { @@ -3627,33 +3627,33 @@ var LibraryGL = { '' ].join("\n").replace(/\n\n+/g, '\n'); - this.fragmentShader = Module.ctx.createShader(Module.ctx.FRAGMENT_SHADER); - Module.ctx.shaderSource(this.fragmentShader, fsSource); - Module.ctx.compileShader(this.fragmentShader); + this.fragmentShader = GLctx.createShader(GLctx.FRAGMENT_SHADER); + GLctx.shaderSource(this.fragmentShader, fsSource); + GLctx.compileShader(this.fragmentShader); - this.program = Module.ctx.createProgram(); - Module.ctx.attachShader(this.program, this.vertexShader); - Module.ctx.attachShader(this.program, this.fragmentShader); + this.program = GLctx.createProgram(); + GLctx.attachShader(this.program, this.vertexShader); + GLctx.attachShader(this.program, this.fragmentShader); // As optimization, bind all attributes to prespecified locations, so that the FFP emulation // code can submit attributes to any generated FFP shader without having to examine each shader in turn. // These prespecified locations are only assumed if GL_FFP_ONLY is specified, since user could also create their // own shaders that didn't have attributes in the same locations. - Module.ctx.bindAttribLocation(this.program, GLImmediate.VERTEX, 'a_position'); - Module.ctx.bindAttribLocation(this.program, GLImmediate.COLOR, 'a_color'); - Module.ctx.bindAttribLocation(this.program, GLImmediate.NORMAL, 'a_normal'); + GLctx.bindAttribLocation(this.program, GLImmediate.VERTEX, 'a_position'); + GLctx.bindAttribLocation(this.program, GLImmediate.COLOR, 'a_color'); + GLctx.bindAttribLocation(this.program, GLImmediate.NORMAL, 'a_normal'); for (var i = 0; i < GLImmediate.MAX_TEXTURES; i++) { - Module.ctx.bindAttribLocation(this.program, GLImmediate.TEXTURE0 + i, 'a_texCoord'+i); - Module.ctx.bindAttribLocation(this.program, GLImmediate.TEXTURE0 + i, aTexCoordPrefix+i); + GLctx.bindAttribLocation(this.program, GLImmediate.TEXTURE0 + i, 'a_texCoord'+i); + GLctx.bindAttribLocation(this.program, GLImmediate.TEXTURE0 + i, aTexCoordPrefix+i); } - Module.ctx.linkProgram(this.program); + GLctx.linkProgram(this.program); } // Stores an array that remembers which matrix uniforms are up-to-date in this FFP renderer, so they don't need to be resubmitted // each time we render with this program. this.textureMatrixVersion = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]; - this.positionLocation = Module.ctx.getAttribLocation(this.program, 'a_position'); + this.positionLocation = GLctx.getAttribLocation(this.program, 'a_position'); this.texCoordLocations = []; @@ -3664,35 +3664,35 @@ var LibraryGL = { } if (useCurrProgram) { - this.texCoordLocations[i] = Module.ctx.getAttribLocation(this.program, 'a_texCoord' + i); + this.texCoordLocations[i] = GLctx.getAttribLocation(this.program, 'a_texCoord' + i); } else { - this.texCoordLocations[i] = Module.ctx.getAttribLocation(this.program, aTexCoordPrefix + i); + this.texCoordLocations[i] = GLctx.getAttribLocation(this.program, aTexCoordPrefix + i); } } if (!useCurrProgram) { // Temporarily switch to the program so we can set our sampler uniforms early. - var prevBoundProg = Module.ctx.getParameter(Module.ctx.CURRENT_PROGRAM); - Module.ctx.useProgram(this.program); + var prevBoundProg = GLctx.getParameter(GLctx.CURRENT_PROGRAM); + GLctx.useProgram(this.program); { for (var i = 0; i < this.usedTexUnitList.length; i++) { var texUnitID = this.usedTexUnitList[i]; - var texSamplerLoc = Module.ctx.getUniformLocation(this.program, uTexUnitPrefix + texUnitID); - Module.ctx.uniform1i(texSamplerLoc, texUnitID); + var texSamplerLoc = GLctx.getUniformLocation(this.program, uTexUnitPrefix + texUnitID); + GLctx.uniform1i(texSamplerLoc, texUnitID); } } - Module.ctx.useProgram(prevBoundProg); + GLctx.useProgram(prevBoundProg); } this.textureMatrixLocations = []; for (var i = 0; i < GLImmediate.MAX_TEXTURES; i++) { - this.textureMatrixLocations[i] = Module.ctx.getUniformLocation(this.program, 'u_textureMatrix' + i); + this.textureMatrixLocations[i] = GLctx.getUniformLocation(this.program, 'u_textureMatrix' + i); } - this.colorLocation = Module.ctx.getAttribLocation(this.program, 'a_color'); - this.normalLocation = Module.ctx.getAttribLocation(this.program, 'a_normal'); + this.colorLocation = GLctx.getAttribLocation(this.program, 'a_color'); + this.normalLocation = GLctx.getAttribLocation(this.program, 'a_normal'); - this.modelViewLocation = Module.ctx.getUniformLocation(this.program, 'u_modelView'); - this.projectionLocation = Module.ctx.getUniformLocation(this.program, 'u_projection'); + this.modelViewLocation = GLctx.getUniformLocation(this.program, 'u_modelView'); + this.projectionLocation = GLctx.getUniformLocation(this.program, 'u_projection'); this.hasTextures = hasTextures; this.hasNormal = GLImmediate.enabledClientAttributes[GLImmediate.NORMAL] && @@ -3700,12 +3700,12 @@ var LibraryGL = { this.normalLocation >= 0; this.hasColor = (this.colorLocation === 0) || this.colorLocation > 0; - this.floatType = Module.ctx.FLOAT; // minor optimization + this.floatType = GLctx.FLOAT; // minor optimization - this.fogColorLocation = Module.ctx.getUniformLocation(this.program, 'u_fogColor'); - this.fogEndLocation = Module.ctx.getUniformLocation(this.program, 'u_fogEnd'); - this.fogScaleLocation = Module.ctx.getUniformLocation(this.program, 'u_fogScale'); - this.fogDensityLocation = Module.ctx.getUniformLocation(this.program, 'u_fogDensity'); + this.fogColorLocation = GLctx.getUniformLocation(this.program, 'u_fogColor'); + this.fogEndLocation = GLctx.getUniformLocation(this.program, 'u_fogEnd'); + this.fogScaleLocation = GLctx.getUniformLocation(this.program, 'u_fogScale'); + this.fogDensityLocation = GLctx.getUniformLocation(this.program, 'u_fogDensity'); this.hasFog = !!(this.fogColorLocation || this.fogEndLocation || this.fogScaleLocation || this.fogDensityLocation); }, @@ -3741,11 +3741,11 @@ var LibraryGL = { // Bind the array buffer and upload data after cleaning up the previous renderer if (arrayBuffer != GLImmediate.lastArrayBuffer) { - Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, arrayBuffer); + GLctx.bindBuffer(GLctx.ARRAY_BUFFER, arrayBuffer); GLImmediate.lastArrayBuffer = arrayBuffer; } - Module.ctx.bufferSubData(Module.ctx.ARRAY_BUFFER, start, GLImmediate.vertexData.subarray(start >> 2, end >> 2)); + GLctx.bufferSubData(GLctx.ARRAY_BUFFER, start, GLImmediate.vertexData.subarray(start >> 2, end >> 2)); } #if GL_UNSAFE_OPTS if (canSkip) return; @@ -3757,18 +3757,18 @@ var LibraryGL = { if (!GL.currProgram) { if (GLImmediate.fixedFunctionProgram != this.program) { - Module.ctx.useProgram(this.program); + GLctx.useProgram(this.program); GLImmediate.fixedFunctionProgram = this.program; } } if (this.modelViewLocation && this.modelViewMatrixVersion != GLImmediate.matrixVersion[0/*m*/]) { this.modelViewMatrixVersion = GLImmediate.matrixVersion[0/*m*/]; - Module.ctx.uniformMatrix4fv(this.modelViewLocation, false, GLImmediate.matrix[0/*m*/]); + GLctx.uniformMatrix4fv(this.modelViewLocation, false, GLImmediate.matrix[0/*m*/]); } if (this.projectionLocation && this.projectionMatrixVersion != GLImmediate.matrixVersion[1/*p*/]) { this.projectionMatrixVersion = GLImmediate.matrixVersion[1/*p*/]; - Module.ctx.uniformMatrix4fv(this.projectionLocation, false, GLImmediate.matrix[1/*p*/]); + GLctx.uniformMatrix4fv(this.projectionLocation, false, GLImmediate.matrix[1/*p*/]); } var clientAttributes = GLImmediate.clientAttributes; @@ -3780,24 +3780,24 @@ var LibraryGL = { #if GL_FFP_ONLY if (!GL.currArrayBuffer) { - Module.ctx.vertexAttribPointer(GLImmediate.VERTEX, posAttr.size, posAttr.type, false, GLImmediate.stride, posAttr.offset); + GLctx.vertexAttribPointer(GLImmediate.VERTEX, posAttr.size, posAttr.type, false, GLImmediate.stride, posAttr.offset); GL.enableVertexAttribArray(GLImmediate.VERTEX); if (this.hasNormal) { var normalAttr = clientAttributes[GLImmediate.NORMAL]; - Module.ctx.vertexAttribPointer(GLImmediate.NORMAL, normalAttr.size, normalAttr.type, true, GLImmediate.stride, normalAttr.offset); + GLctx.vertexAttribPointer(GLImmediate.NORMAL, normalAttr.size, normalAttr.type, true, GLImmediate.stride, normalAttr.offset); GL.enableVertexAttribArray(GLImmediate.NORMAL); } } #else - Module.ctx.vertexAttribPointer(this.positionLocation, posAttr.size, posAttr.type, false, GLImmediate.stride, posAttr.offset); - Module.ctx.enableVertexAttribArray(this.positionLocation); + GLctx.vertexAttribPointer(this.positionLocation, posAttr.size, posAttr.type, false, GLImmediate.stride, posAttr.offset); + GLctx.enableVertexAttribArray(this.positionLocation); if (this.hasNormal) { var normalAttr = clientAttributes[GLImmediate.NORMAL]; #if GL_ASSERTIONS GL.validateVertexAttribPointer(normalAttr.size, normalAttr.type, GLImmediate.stride, normalAttr.offset); #endif - Module.ctx.vertexAttribPointer(this.normalLocation, normalAttr.size, normalAttr.type, true, GLImmediate.stride, normalAttr.offset); - Module.ctx.enableVertexAttribArray(this.normalLocation); + GLctx.vertexAttribPointer(this.normalLocation, normalAttr.size, normalAttr.type, true, GLImmediate.stride, normalAttr.offset); + GLctx.enableVertexAttribArray(this.normalLocation); } #endif if (this.hasTextures) { @@ -3807,11 +3807,11 @@ var LibraryGL = { var attribLoc = GLImmediate.TEXTURE0+i; var texAttr = clientAttributes[attribLoc]; if (texAttr.size) { - Module.ctx.vertexAttribPointer(attribLoc, texAttr.size, texAttr.type, false, GLImmediate.stride, texAttr.offset); + GLctx.vertexAttribPointer(attribLoc, texAttr.size, texAttr.type, false, GLImmediate.stride, texAttr.offset); GL.enableVertexAttribArray(attribLoc); } else { // These two might be dangerous, but let's try them. - Module.ctx.vertexAttrib4f(attribLoc, 0, 0, 0, 1); + GLctx.vertexAttrib4f(attribLoc, 0, 0, 0, 1); GL.disableVertexAttribArray(attribLoc); } } @@ -3824,18 +3824,18 @@ var LibraryGL = { #if GL_ASSERTIONS GL.validateVertexAttribPointer(texAttr.size, texAttr.type, GLImmediate.stride, texAttr.offset); #endif - Module.ctx.vertexAttribPointer(attribLoc, texAttr.size, texAttr.type, false, GLImmediate.stride, texAttr.offset); - Module.ctx.enableVertexAttribArray(attribLoc); + GLctx.vertexAttribPointer(attribLoc, texAttr.size, texAttr.type, false, GLImmediate.stride, texAttr.offset); + GLctx.enableVertexAttribArray(attribLoc); } else { // These two might be dangerous, but let's try them. - Module.ctx.vertexAttrib4f(attribLoc, 0, 0, 0, 1); - Module.ctx.disableVertexAttribArray(attribLoc); + GLctx.vertexAttrib4f(attribLoc, 0, 0, 0, 1); + GLctx.disableVertexAttribArray(attribLoc); } #endif var t = 2/*t*/+i; if (this.textureMatrixLocations[i] && this.textureMatrixVersion[t] != GLImmediate.matrixVersion[t]) { // XXX might we need this even without the condition we are currently in? this.textureMatrixVersion[t] = GLImmediate.matrixVersion[t]; - Module.ctx.uniformMatrix4fv(this.textureMatrixLocations[i], false, GLImmediate.matrix[t]); + GLctx.uniformMatrix4fv(this.textureMatrixLocations[i], false, GLImmediate.matrix[t]); } } } @@ -3846,51 +3846,51 @@ var LibraryGL = { #endif #if GL_FFP_ONLY if (!GL.currArrayBuffer) { - Module.ctx.vertexAttribPointer(GLImmediate.COLOR, colorAttr.size, colorAttr.type, true, GLImmediate.stride, colorAttr.offset); + GLctx.vertexAttribPointer(GLImmediate.COLOR, colorAttr.size, colorAttr.type, true, GLImmediate.stride, colorAttr.offset); GL.enableVertexAttribArray(GLImmediate.COLOR); } #else - Module.ctx.vertexAttribPointer(this.colorLocation, colorAttr.size, colorAttr.type, true, GLImmediate.stride, colorAttr.offset); - Module.ctx.enableVertexAttribArray(this.colorLocation); + GLctx.vertexAttribPointer(this.colorLocation, colorAttr.size, colorAttr.type, true, GLImmediate.stride, colorAttr.offset); + GLctx.enableVertexAttribArray(this.colorLocation); #endif } else if (this.hasColor) { #if GL_FFP_ONLY GL.disableVertexAttribArray(GLImmediate.COLOR); - Module.ctx.vertexAttrib4fv(GLImmediate.COLOR, GLImmediate.clientColor); + GLctx.vertexAttrib4fv(GLImmediate.COLOR, GLImmediate.clientColor); #else - Module.ctx.disableVertexAttribArray(this.colorLocation); - Module.ctx.vertexAttrib4fv(this.colorLocation, GLImmediate.clientColor); + GLctx.disableVertexAttribArray(this.colorLocation); + GLctx.vertexAttrib4fv(this.colorLocation, GLImmediate.clientColor); #endif } if (this.hasFog) { - if (this.fogColorLocation) Module.ctx.uniform4fv(this.fogColorLocation, GLEmulation.fogColor); - if (this.fogEndLocation) Module.ctx.uniform1f(this.fogEndLocation, GLEmulation.fogEnd); - if (this.fogScaleLocation) Module.ctx.uniform1f(this.fogScaleLocation, 1/(GLEmulation.fogEnd - GLEmulation.fogStart)); - if (this.fogDensityLocation) Module.ctx.uniform1f(this.fogDensityLocation, GLEmulation.fogDensity); + if (this.fogColorLocation) GLctx.uniform4fv(this.fogColorLocation, GLEmulation.fogColor); + if (this.fogEndLocation) GLctx.uniform1f(this.fogEndLocation, GLEmulation.fogEnd); + if (this.fogScaleLocation) GLctx.uniform1f(this.fogScaleLocation, 1/(GLEmulation.fogEnd - GLEmulation.fogStart)); + if (this.fogDensityLocation) GLctx.uniform1f(this.fogDensityLocation, GLEmulation.fogDensity); } }, cleanup: function cleanup() { #if !GL_FFP_ONLY - Module.ctx.disableVertexAttribArray(this.positionLocation); + GLctx.disableVertexAttribArray(this.positionLocation); if (this.hasTextures) { for (var i = 0; i < GLImmediate.MAX_TEXTURES; i++) { if (GLImmediate.enabledClientAttributes[GLImmediate.TEXTURE0+i] && this.texCoordLocations[i] >= 0) { - Module.ctx.disableVertexAttribArray(this.texCoordLocations[i]); + GLctx.disableVertexAttribArray(this.texCoordLocations[i]); } } } if (this.hasColor) { - Module.ctx.disableVertexAttribArray(this.colorLocation); + GLctx.disableVertexAttribArray(this.colorLocation); } if (this.hasNormal) { - Module.ctx.disableVertexAttribArray(this.normalLocation); + GLctx.disableVertexAttribArray(this.normalLocation); } if (!GL.currProgram) { - Module.ctx.useProgram(null); + GLctx.useProgram(null); } if (!GL.currArrayBuffer) { - Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, null); + GLctx.bindBuffer(GLctx.ARRAY_BUFFER, null); GLImmediate.lastArrayBuffer = null; } @@ -3912,7 +3912,7 @@ var LibraryGL = { // for emulation _glDrawArrays = function _glDrawArrays(mode, first, count) { if (GLImmediate.totalEnabledClientAttributes == 0 && mode <= 6) { - Module.ctx.drawArrays(mode, first, count); + GLctx.drawArrays(mode, first, count); return; } GLImmediate.prepareClientAttributes(count, false); @@ -3928,12 +3928,12 @@ var LibraryGL = { _glDrawElements = function _glDrawElements(mode, count, type, indices, start, end) { // start, end are given if we come from glDrawRangeElements if (GLImmediate.totalEnabledClientAttributes == 0 && mode <= 6 && GL.currElementArrayBuffer) { - Module.ctx.drawElements(mode, count, type, indices); + GLctx.drawElements(mode, count, type, indices); return; } #if ASSERTIONS if (!GL.currElementArrayBuffer) { - assert(type == Module.ctx.UNSIGNED_SHORT); // We can only emulate buffers of this kind, for now + assert(type == GLctx.UNSIGNED_SHORT); // We can only emulate buffers of this kind, for now } console.log("DrawElements doesn't actually prepareClientAttributes properly."); #endif @@ -4006,7 +4006,7 @@ var LibraryGL = { switch (pname) { case 0x8B8D: { // GL_CURRENT_PROGRAM // Just query directly so we're working with WebGL objects. - var cur = Module.ctx.getParameter(Module.ctx.CURRENT_PROGRAM); + var cur = GLctx.getParameter(GLctx.CURRENT_PROGRAM); if (cur == GLImmediate.fixedFunctionProgram) { // Pretend we're not using a program. {{{ makeSetValue('params', '0', '0', 'i32') }}}; @@ -4027,11 +4027,11 @@ var LibraryGL = { if (!Module.useWebGL) return; // a 2D canvas may be currently used TODO: make sure we are actually called in that case - this.TexEnvJIT.init(Module.ctx); + this.TexEnvJIT.init(GLctx); // User can override the maximum number of texture units that we emulate. Using fewer texture units increases runtime performance // slightly, so it is advantageous to choose as small value as needed. - GLImmediate.MAX_TEXTURES = Module['GL_MAX_TEXTURE_IMAGE_UNITS'] || Module.ctx.getParameter(Module.ctx.MAX_TEXTURE_IMAGE_UNITS); + GLImmediate.MAX_TEXTURES = Module['GL_MAX_TEXTURE_IMAGE_UNITS'] || GLctx.getParameter(GLctx.MAX_TEXTURE_IMAGE_UNITS); GLImmediate.NUM_ATTRIBUTES = 3 /*pos+normal+color attributes*/ + GLImmediate.MAX_TEXTURES; GLImmediate.clientAttributes = []; GLEmulation.enabledClientAttribIndices = []; @@ -4215,8 +4215,8 @@ var LibraryGL = { assert(numProvidedIndexes << 1 <= GL.MAX_TEMP_BUFFER_SIZE, 'too many immediate mode indexes (a)'); #endif 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)') }}}); + GLctx.bindBuffer(GLctx.ELEMENT_ARRAY_BUFFER, indexBuffer); + GLctx.bufferSubData(GLctx.ELEMENT_ARRAY_BUFFER, 0, {{{ makeHEAPView('U16', 'ptr', 'ptr + (numProvidedIndexes << 1)') }}}); ptr = 0; emulatedElementArrayBuffer = true; } @@ -4234,20 +4234,20 @@ var LibraryGL = { #if ASSERTIONS assert(ptr + (numIndexes << 1) <= GL.MAX_TEMP_BUFFER_SIZE, 'too many immediate mode indexes (b)'); #endif - Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, GL.tempQuadIndexBuffer); + GLctx.bindBuffer(GLctx.ELEMENT_ARRAY_BUFFER, GL.tempQuadIndexBuffer); emulatedElementArrayBuffer = true; } renderer.prepare(); if (numIndexes) { - Module.ctx.drawElements(Module.ctx.TRIANGLES, numIndexes, Module.ctx.UNSIGNED_SHORT, ptr); + GLctx.drawElements(GLctx.TRIANGLES, numIndexes, GLctx.UNSIGNED_SHORT, ptr); } else { - Module.ctx.drawArrays(GLImmediate.mode, startIndex, numVertexes); + GLctx.drawArrays(GLImmediate.mode, startIndex, numVertexes); } if (emulatedElementArrayBuffer) { - Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, GL.buffers[GL.currElementArrayBuffer] || null); + GLctx.bindBuffer(GLctx.ELEMENT_ARRAY_BUFFER, GL.buffers[GL.currElementArrayBuffer] || null); } #if GL_UNSAFE_OPTS == 0 && !GL_FFP_ONLY @@ -4306,7 +4306,7 @@ var LibraryGL = { #if ASSERTIONS assert(GLImmediate.vertexCounter << 2 < GL.MAX_TEMP_BUFFER_SIZE); #endif - GLImmediate.addRendererComponent(GLImmediate.VERTEX, 3, Module.ctx.FLOAT); + GLImmediate.addRendererComponent(GLImmediate.VERTEX, 3, GLctx.FLOAT); }, glVertex2f: 'glVertex3f', @@ -4329,7 +4329,7 @@ var LibraryGL = { #endif GLImmediate.vertexData[GLImmediate.vertexCounter++] = u; GLImmediate.vertexData[GLImmediate.vertexCounter++] = v; - GLImmediate.addRendererComponent(GLImmediate.TEXTURE0, 2, Module.ctx.FLOAT); + GLImmediate.addRendererComponent(GLImmediate.TEXTURE0, 2, GLctx.FLOAT); }, glTexCoord2f: 'glTexCoord2i', @@ -4354,7 +4354,7 @@ var LibraryGL = { GLImmediate.vertexDataU8[start + 2] = b * 255; GLImmediate.vertexDataU8[start + 3] = a * 255; GLImmediate.vertexCounter++; - GLImmediate.addRendererComponent(GLImmediate.COLOR, 4, Module.ctx.UNSIGNED_BYTE); + GLImmediate.addRendererComponent(GLImmediate.COLOR, 4, GLctx.UNSIGNED_BYTE); } else { GLImmediate.clientColor[0] = r; GLImmediate.clientColor[1] = g; @@ -4533,7 +4533,7 @@ var LibraryGL = { GLImmediate.setClientAttribute(GLImmediate.VERTEX, size, type, stride, pointer); #if GL_FFP_ONLY if (GL.currArrayBuffer) { - Module.ctx.vertexAttribPointer(GLImmediate.VERTEX, size, type, false, stride, pointer); + GLctx.vertexAttribPointer(GLImmediate.VERTEX, size, type, false, stride, pointer); GL.enableVertexAttribArray(GLImmediate.VERTEX); } #endif @@ -4543,7 +4543,7 @@ var LibraryGL = { #if GL_FFP_ONLY if (GL.currArrayBuffer) { var loc = GLImmediate.TEXTURE0 + GLImmediate.clientActiveTexture; - Module.ctx.vertexAttribPointer(loc, size, type, false, stride, pointer); + GLctx.vertexAttribPointer(loc, size, type, false, stride, pointer); GL.enableVertexAttribArray(loc); } #endif @@ -4552,7 +4552,7 @@ var LibraryGL = { GLImmediate.setClientAttribute(GLImmediate.NORMAL, 3, type, stride, pointer); #if GL_FFP_ONLY if (GL.currArrayBuffer) { - Module.ctx.vertexAttribPointer(GLImmediate.NORMAL, size, type, true, stride, pointer); + GLctx.vertexAttribPointer(GLImmediate.NORMAL, size, type, true, stride, pointer); GL.enableVertexAttribArray(GLImmediate.NORMAL); } #endif @@ -4561,7 +4561,7 @@ var LibraryGL = { GLImmediate.setClientAttribute(GLImmediate.COLOR, size, type, stride, pointer); #if GL_FFP_ONLY if (GL.currArrayBuffer) { - Module.ctx.vertexAttribPointer(GLImmediate.COLOR, size, type, true, stride, pointer); + GLctx.vertexAttribPointer(GLImmediate.COLOR, size, type, true, stride, pointer); GL.enableVertexAttribArray(GLImmediate.COLOR); } #endif @@ -4602,10 +4602,10 @@ var LibraryGL = { // 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 if (GLImmediate.lastRenderer) GLImmediate.lastRenderer.cleanup(); - _glBindBuffer(Module.ctx.ARRAY_BUFFER, 0); // XXX if one was there before we were bound? - _glBindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, 0); + _glBindBuffer(GLctx.ARRAY_BUFFER, 0); // XXX if one was there before we were bound? + _glBindBuffer(GLctx.ELEMENT_ARRAY_BUFFER, 0); for (var vaa in GLEmulation.enabledVertexAttribArrays) { - Module.ctx.disableVertexAttribArray(vaa); + GLctx.disableVertexAttribArray(vaa); } GLEmulation.enabledVertexAttribArrays = {}; GLImmediate.enabledClientAttributes = [0, 0]; @@ -4614,8 +4614,8 @@ var LibraryGL = { if (vao) { // replay vao var info = GLEmulation.vaos[vao]; - _glBindBuffer(Module.ctx.ARRAY_BUFFER, info.arrayBuffer); // XXX overwrite current binding? - _glBindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, info.elementArrayBuffer); + _glBindBuffer(GLctx.ARRAY_BUFFER, info.arrayBuffer); // XXX overwrite current binding? + _glBindBuffer(GLctx.ELEMENT_ARRAY_BUFFER, info.elementArrayBuffer); for (var vaa in info.enabledVertexAttribArrays) { _glEnableVertexAttribArray(vaa); } @@ -4929,7 +4929,7 @@ var LibraryGL = { #if GL_ASSERTIONS GL.validateVertexAttribPointer(size, type, stride, ptr); #endif - Module.ctx.vertexAttribPointer(index, size, type, normalized, stride, ptr); + GLctx.vertexAttribPointer(index, size, type, normalized, stride, ptr); }, glEnableVertexAttribArray__sig: 'vi', @@ -4941,7 +4941,7 @@ var LibraryGL = { #endif cb.enabled = true; #endif - Module.ctx.enableVertexAttribArray(index); + GLctx.enableVertexAttribArray(index); }, glDisableVertexAttribArray__sig: 'vi', @@ -4953,7 +4953,7 @@ var LibraryGL = { #endif cb.enabled = false; #endif - Module.ctx.disableVertexAttribArray(index); + GLctx.disableVertexAttribArray(index); }, glDrawArrays__sig: 'viii', @@ -4963,7 +4963,7 @@ var LibraryGL = { GL.preDrawHandleClientVertexAttribBindings(first + count); #endif - Module.ctx.drawArrays(mode, first, count); + GLctx.drawArrays(mode, first, count); #if FULL_ES2 GL.postDrawHandleClientVertexAttribBindings(); @@ -4977,8 +4977,8 @@ var LibraryGL = { if (!GL.currElementArrayBuffer) { var size = GL.calcBufLength(1, type, 0, count); buf = GL.tempIndexBuffers[GL.tempBufferIndexLookup[size]]; - Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, buf); - Module.ctx.bufferSubData(Module.ctx.ELEMENT_ARRAY_BUFFER, + GLctx.bindBuffer(GLctx.ELEMENT_ARRAY_BUFFER, buf); + GLctx.bufferSubData(GLctx.ELEMENT_ARRAY_BUFFER, 0, HEAPU8.subarray(indices, indices + size)); // the index is now 0 @@ -4989,13 +4989,13 @@ var LibraryGL = { GL.preDrawHandleClientVertexAttribBindings(count); #endif - Module.ctx.drawElements(mode, count, type, indices); + GLctx.drawElements(mode, count, type, indices); #if FULL_ES2 GL.postDrawHandleClientVertexAttribBindings(count); if (!GL.currElementArrayBuffer) { - Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, null); + GLctx.bindBuffer(GLctx.ELEMENT_ARRAY_BUFFER, null); } #endif }, @@ -5021,7 +5021,7 @@ var LibraryGL = { GL.lastError = 0/*GL_NO_ERROR*/; return error; } else { // If there were none, return the GL error from the browser GL context. - return Module.ctx.getError(); + return GLctx.getError(); } }, @@ -5112,8 +5112,8 @@ var LibraryGL = { var num = data[0]; var names = data[1]; var args = range(num).map(function(i) { return 'x' + i }).join(', '); - var plainStub = '(function(' + args + ') { Module.ctx.NAME(' + args + ') })'; - var returnStub = '(function(' + args + ') { return Module.ctx.NAME(' + args + ') })'; + var plainStub = '(function(' + args + ') { GLctx.NAME(' + args + ') })'; + var returnStub = '(function(' + args + ') { return GLctx.NAME(' + args + ') })'; var sigEnd = range(num).map(function() { return 'i' }).join(''); names.split(' ').forEach(function(name) { var stub = plainStub; From c244e89559d6d706345ddea45b39343e67fb3974 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Thu, 9 Jan 2014 20:29:50 +0200 Subject: [PATCH 20/42] Simplify GL emulation matrix stack initialization. Update code after rebase. --- src/library_gl.js | 46 +++++++++++++++++++--------------------------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/src/library_gl.js b/src/library_gl.js index 00d36bd3ba1c7..3f2d44e001b6f 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -1791,7 +1791,7 @@ var LibraryGL = { if (GLImmediate.lastRenderer) GLImmediate.lastRenderer.cleanup(); if (cap == 0x0B60 /* GL_FOG */) { if (GLEmulation.fogEnabled != true) { - GL.immediate.currentRenderer = null; // Fog parameter is part of the FFP shader state, we must re-lookup the renderer to use. + GLImmediate.currentRenderer = null; // Fog parameter is part of the FFP shader state, we must re-lookup the renderer to use. GLEmulation.fogEnabled = true; } return; @@ -1814,7 +1814,7 @@ var LibraryGL = { if (GLImmediate.lastRenderer) GLImmediate.lastRenderer.cleanup(); if (cap == 0x0B60 /* GL_FOG */) { if (GLEmulation.fogEnabled != false) { - GL.immediate.currentRenderer = null; // Fog parameter is part of the FFP shader state, we must re-lookup the renderer to use. + GLImmediate.currentRenderer = null; // Fog parameter is part of the FFP shader state, we must re-lookup the renderer to use. GLEmulation.fogEnabled = false; } return; @@ -2123,7 +2123,7 @@ var LibraryGL = { } #endif if (GL.currProgram != program) { - GL.immediate.currentRenderer = null; // This changes the FFP emulation shader program, need to recompute that. + GLImmediate.currentRenderer = null; // This changes the FFP emulation shader program, need to recompute that. GL.currProgram = program; GLImmediate.fixedFunctionProgram = 0; glUseProgram(program); @@ -2134,7 +2134,7 @@ var LibraryGL = { _glDeleteProgram = function _glDeleteProgram(program) { glDeleteProgram(program); if (program == GL.currProgram) { - GL.immediate.currentRenderer = null; // This changes the FFP emulation shader program, need to recompute that. + GLImmediate.currentRenderer = null; // This changes the FFP emulation shader program, need to recompute that. GL.currProgram = 0; } }; @@ -3348,9 +3348,9 @@ var LibraryGL = { lastStride: -1, // "" // The following data structures are used for OpenGL Immediate Mode matrix routines. - matrix: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], - matrixStack: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], - currentMatrix: 0, // default is modelview + matrix: [], + matrixStack: [], + currentMatrix: 0, // 0: modelview, 1: projection, 2+i, texture matrix i. tempMatrix: null, matricesModified: false, useTextureMatrix: false, @@ -4040,25 +4040,17 @@ var LibraryGL = { GLEmulation.enabledClientAttribIndices.push(false); } - this.matrixStack[0/*m*/] = []; - this.matrixStack[1/*p*/] = []; - for (var i = 0; i < GLImmediate.MAX_TEXTURES; i++) { - this.matrixStack[2/*t*/ + i] = []; - } - // Initialize matrix library // When user sets a matrix, increment a 'version number' on the new data, and when rendering, submit // the matrices to the shader program only if they have an old version of the data. - GLImmediate.matrixVersion = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]; - GLImmediate.matrix[0/*m*/] = GLImmediate.matrix.lib.mat4.create(); - GLImmediate.matrixVersion[0/*m*/] = 0; - GLImmediate.matrix.lib.mat4.identity(GLImmediate.matrix[0/*m*/]); - GLImmediate.matrix[1/*p*/] = GLImmediate.matrix.lib.mat4.create(); - GLImmediate.matrixVersion[1/*p*/] = 0; - GLImmediate.matrix.lib.mat4.identity(GLImmediate.matrix[1/*p*/]); - for (var i = 0; i < GLImmediate.MAX_TEXTURES; i++) { - GLImmediate.matrix[2/*t*/ + i] = GLImmediate.matrix.lib.mat4.create(); - GLImmediate.matrixVersion[2/*t*/ + i] = 0; + this.matrix = []; + this.matrixStack = []; + this.matrixVersion = []; + for (var i = 0; i < 2 + GLImmediate.MAX_TEXTURES; i++) { // Modelview, Projection, plus one matrix for each texture coordinate. + this.matrixStack.push([]); + this.matrixVersion.push(0); + GLImmediate.matrix.push(GLImmediate.matrix.lib.mat4.create()); + GLImmediate.matrix.lib.mat4.identity(GLImmediate.matrix[i]); } // Renderer cache @@ -4256,7 +4248,7 @@ var LibraryGL = { } }, - $GLImmediateSetup__deps: ['$GLImmediate', function() { return 'GL.immediate = GLImmediate; GLImmediate.matrix.lib = ' + read('gl-matrix.js') + ';\n' }], + $GLImmediateSetup__deps: ['$GLImmediate', function() { return 'GLImmediate.matrix.lib = ' + read('gl-matrix.js') + ';\n' }], $GLImmediateSetup: {}, glBegin__deps: ['$GLImmediateSetup'], @@ -4292,7 +4284,7 @@ var LibraryGL = { // Pop the old state: GLImmediate.enabledClientAttributes = GLImmediate.enabledClientAttributes_preBegin; GLImmediate.clientAttributes = GLImmediate.clientAttributes_preBegin; - GL.immediate.currentRenderer = null; // The set of active client attributes changed, we must re-lookup the renderer to use. + GLImmediate.currentRenderer = null; // The set of active client attributes changed, we must re-lookup the renderer to use. GLImmediate.modifiedClientAttributes = true; }, @@ -4432,13 +4424,13 @@ var LibraryGL = { case 0x0801: // GL_EXP2 case 0x2601: // GL_LINEAR if (GLEmulation.fogMode != param) { - GL.immediate.currentRenderer = null; // Fog mode is part of the FFP shader state, we must re-lookup the renderer to use. + GLImmediate.currentRenderer = null; // Fog mode is part of the FFP shader state, we must re-lookup the renderer to use. GLEmulation.fogMode = param; } break; default: // default to GL_EXP if (GLEmulation.fogMode != 0x0800 /* GL_EXP */) { - GL.immediate.currentRenderer = null; // Fog mode is part of the FFP shader state, we must re-lookup the renderer to use. + GLImmediate.currentRenderer = null; // Fog mode is part of the FFP shader state, we must re-lookup the renderer to use. GLEmulation.fogMode = 0x0800 /* GL_EXP */; } break; From 777fa6227ee3abe8315f1fe134cd1432e5624cc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Thu, 9 Jan 2014 20:52:56 +0200 Subject: [PATCH 21/42] Rename GLImmediate.matrix.lib to GLImmediate.matrixLib to not alias with GLImmediate.matrix array that contains emulated modelview,projection and texture matrices. Restore compressedTexImage2D symbols to be closure-friendly. --- src/library_gl.js | 70 ++++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/src/library_gl.js b/src/library_gl.js index 3f2d44e001b6f..54348a7673614 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -746,7 +746,8 @@ var LibraryGL = { } else { data = null; } - GLctx.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', @@ -759,7 +760,7 @@ var LibraryGL = { } else { data = null; } - CLctx.compressedTexSubImage2D(target, level, xoffset, yoffset, width, height, data); + CLctx['compressedTexSubImage2D'](target, level, xoffset, yoffset, width, height, data); }, glTexImage2D__sig: 'viiiiiiiii', @@ -4049,8 +4050,8 @@ var LibraryGL = { for (var i = 0; i < 2 + GLImmediate.MAX_TEXTURES; i++) { // Modelview, Projection, plus one matrix for each texture coordinate. this.matrixStack.push([]); this.matrixVersion.push(0); - GLImmediate.matrix.push(GLImmediate.matrix.lib.mat4.create()); - GLImmediate.matrix.lib.mat4.identity(GLImmediate.matrix[i]); + GLImmediate.matrix.push(GLImmediate.matrixLib.mat4.create()); + GLImmediate.matrixLib.mat4.identity(GLImmediate.matrix[i]); } // Renderer cache @@ -4248,7 +4249,8 @@ var LibraryGL = { } }, - $GLImmediateSetup__deps: ['$GLImmediate', function() { return 'GLImmediate.matrix.lib = ' + read('gl-matrix.js') + ';\n' }], + $GLImmediateSetup: {}, + $GLImmediateSetup__deps: ['$GLImmediate', function() { return 'GLImmediate.matrixLib = ' + read('gl-matrix.js') + ';\n' }], $GLImmediateSetup: {}, glBegin__deps: ['$GLImmediateSetup'], @@ -4654,13 +4656,13 @@ var LibraryGL = { glLoadIdentity: function() { GLImmediate.matricesModified = true; GLImmediate.matrixVersion[GLImmediate.currentMatrix] = (GLImmediate.matrixVersion[GLImmediate.currentMatrix] + 1)|0; - GLImmediate.matrix.lib.mat4.identity(GLImmediate.matrix[GLImmediate.currentMatrix]); + GLImmediate.matrixLib.mat4.identity(GLImmediate.matrix[GLImmediate.currentMatrix]); }, glLoadMatrixd: function(matrix) { GLImmediate.matricesModified = true; GLImmediate.matrixVersion[GLImmediate.currentMatrix] = (GLImmediate.matrixVersion[GLImmediate.currentMatrix] + 1)|0; - GLImmediate.matrix.lib.mat4.set({{{ makeHEAPView('F64', 'matrix', 'matrix+' + (16*8)) }}}, GLImmediate.matrix[GLImmediate.currentMatrix]); + GLImmediate.matrixLib.mat4.set({{{ makeHEAPView('F64', 'matrix', 'matrix+' + (16*8)) }}}, GLImmediate.matrix[GLImmediate.currentMatrix]); }, glLoadMatrixf: function(matrix) { @@ -4669,89 +4671,89 @@ var LibraryGL = { #endif GLImmediate.matricesModified = true; GLImmediate.matrixVersion[GLImmediate.currentMatrix] = (GLImmediate.matrixVersion[GLImmediate.currentMatrix] + 1)|0; - GLImmediate.matrix.lib.mat4.set({{{ makeHEAPView('F32', 'matrix', 'matrix+' + (16*4)) }}}, GLImmediate.matrix[GLImmediate.currentMatrix]); + GLImmediate.matrixLib.mat4.set({{{ makeHEAPView('F32', 'matrix', 'matrix+' + (16*4)) }}}, GLImmediate.matrix[GLImmediate.currentMatrix]); }, glLoadTransposeMatrixd: function(matrix) { GLImmediate.matricesModified = true; GLImmediate.matrixVersion[GLImmediate.currentMatrix] = (GLImmediate.matrixVersion[GLImmediate.currentMatrix] + 1)|0; - GLImmediate.matrix.lib.mat4.set({{{ makeHEAPView('F64', 'matrix', 'matrix+' + (16*8)) }}}, GLImmediate.matrix[GLImmediate.currentMatrix]); - GLImmediate.matrix.lib.mat4.transpose(GLImmediate.matrix[GLImmediate.currentMatrix]); + GLImmediate.matrixLib.mat4.set({{{ makeHEAPView('F64', 'matrix', 'matrix+' + (16*8)) }}}, GLImmediate.matrix[GLImmediate.currentMatrix]); + GLImmediate.matrixLib.mat4.transpose(GLImmediate.matrix[GLImmediate.currentMatrix]); }, glLoadTransposeMatrixf: function(matrix) { GLImmediate.matricesModified = true; GLImmediate.matrixVersion[GLImmediate.currentMatrix] = (GLImmediate.matrixVersion[GLImmediate.currentMatrix] + 1)|0; - GLImmediate.matrix.lib.mat4.set({{{ makeHEAPView('F32', 'matrix', 'matrix+' + (16*4)) }}}, GLImmediate.matrix[GLImmediate.currentMatrix]); - GLImmediate.matrix.lib.mat4.transpose(GLImmediate.matrix[GLImmediate.currentMatrix]); + GLImmediate.matrixLib.mat4.set({{{ makeHEAPView('F32', 'matrix', 'matrix+' + (16*4)) }}}, GLImmediate.matrix[GLImmediate.currentMatrix]); + GLImmediate.matrixLib.mat4.transpose(GLImmediate.matrix[GLImmediate.currentMatrix]); }, glMultMatrixd: function(matrix) { GLImmediate.matricesModified = true; GLImmediate.matrixVersion[GLImmediate.currentMatrix] = (GLImmediate.matrixVersion[GLImmediate.currentMatrix] + 1)|0; - GLImmediate.matrix.lib.mat4.multiply(GLImmediate.matrix[GLImmediate.currentMatrix], + GLImmediate.matrixLib.mat4.multiply(GLImmediate.matrix[GLImmediate.currentMatrix], {{{ makeHEAPView('F64', 'matrix', 'matrix+' + (16*8)) }}}); }, glMultMatrixf: function(matrix) { GLImmediate.matricesModified = true; GLImmediate.matrixVersion[GLImmediate.currentMatrix] = (GLImmediate.matrixVersion[GLImmediate.currentMatrix] + 1)|0; - GLImmediate.matrix.lib.mat4.multiply(GLImmediate.matrix[GLImmediate.currentMatrix], + GLImmediate.matrixLib.mat4.multiply(GLImmediate.matrix[GLImmediate.currentMatrix], {{{ makeHEAPView('F32', 'matrix', 'matrix+' + (16*4)) }}}); }, glMultTransposeMatrixd: function(matrix) { GLImmediate.matricesModified = true; GLImmediate.matrixVersion[GLImmediate.currentMatrix] = (GLImmediate.matrixVersion[GLImmediate.currentMatrix] + 1)|0; - var colMajor = GLImmediate.matrix.lib.mat4.create(); - GLImmediate.matrix.lib.mat4.set({{{ makeHEAPView('F64', 'matrix', 'matrix+' + (16*8)) }}}, colMajor); - GLImmediate.matrix.lib.mat4.transpose(colMajor); - GLImmediate.matrix.lib.mat4.multiply(GLImmediate.matrix[GLImmediate.currentMatrix], colMajor); + var colMajor = GLImmediate.matrixLib.mat4.create(); + GLImmediate.matrixLib.mat4.set({{{ makeHEAPView('F64', 'matrix', 'matrix+' + (16*8)) }}}, colMajor); + GLImmediate.matrixLib.mat4.transpose(colMajor); + GLImmediate.matrixLib.mat4.multiply(GLImmediate.matrix[GLImmediate.currentMatrix], colMajor); }, glMultTransposeMatrixf: function(matrix) { GLImmediate.matricesModified = true; GLImmediate.matrixVersion[GLImmediate.currentMatrix] = (GLImmediate.matrixVersion[GLImmediate.currentMatrix] + 1)|0; - var colMajor = GLImmediate.matrix.lib.mat4.create(); - GLImmediate.matrix.lib.mat4.set({{{ makeHEAPView('F32', 'matrix', 'matrix+' + (16*4)) }}}, colMajor); - GLImmediate.matrix.lib.mat4.transpose(colMajor); - GLImmediate.matrix.lib.mat4.multiply(GLImmediate.matrix[GLImmediate.currentMatrix], colMajor); + var colMajor = GLImmediate.matrixLib.mat4.create(); + GLImmediate.matrixLib.mat4.set({{{ makeHEAPView('F32', 'matrix', 'matrix+' + (16*4)) }}}, colMajor); + GLImmediate.matrixLib.mat4.transpose(colMajor); + GLImmediate.matrixLib.mat4.multiply(GLImmediate.matrix[GLImmediate.currentMatrix], colMajor); }, glFrustum: function(left, right, bottom, top_, nearVal, farVal) { GLImmediate.matricesModified = true; GLImmediate.matrixVersion[GLImmediate.currentMatrix] = (GLImmediate.matrixVersion[GLImmediate.currentMatrix] + 1)|0; - GLImmediate.matrix.lib.mat4.multiply(GLImmediate.matrix[GLImmediate.currentMatrix], - GLImmediate.matrix.lib.mat4.frustum(left, right, bottom, top_, nearVal, farVal)); + GLImmediate.matrixLib.mat4.multiply(GLImmediate.matrix[GLImmediate.currentMatrix], + GLImmediate.matrixLib.mat4.frustum(left, right, bottom, top_, nearVal, farVal)); }, glFrustumf: 'glFrustum', glOrtho: function(left, right, bottom, top_, nearVal, farVal) { GLImmediate.matricesModified = true; GLImmediate.matrixVersion[GLImmediate.currentMatrix] = (GLImmediate.matrixVersion[GLImmediate.currentMatrix] + 1)|0; - GLImmediate.matrix.lib.mat4.multiply(GLImmediate.matrix[GLImmediate.currentMatrix], - GLImmediate.matrix.lib.mat4.ortho(left, right, bottom, top_, nearVal, farVal)); + GLImmediate.matrixLib.mat4.multiply(GLImmediate.matrix[GLImmediate.currentMatrix], + GLImmediate.matrixLib.mat4.ortho(left, right, bottom, top_, nearVal, farVal)); }, glOrthof: 'glOrtho', glScaled: function(x, y, z) { GLImmediate.matricesModified = true; GLImmediate.matrixVersion[GLImmediate.currentMatrix] = (GLImmediate.matrixVersion[GLImmediate.currentMatrix] + 1)|0; - GLImmediate.matrix.lib.mat4.scale(GLImmediate.matrix[GLImmediate.currentMatrix], [x, y, z]); + GLImmediate.matrixLib.mat4.scale(GLImmediate.matrix[GLImmediate.currentMatrix], [x, y, z]); }, glScalef: 'glScaled', glTranslated: function(x, y, z) { GLImmediate.matricesModified = true; GLImmediate.matrixVersion[GLImmediate.currentMatrix] = (GLImmediate.matrixVersion[GLImmediate.currentMatrix] + 1)|0; - GLImmediate.matrix.lib.mat4.translate(GLImmediate.matrix[GLImmediate.currentMatrix], [x, y, z]); + GLImmediate.matrixLib.mat4.translate(GLImmediate.matrix[GLImmediate.currentMatrix], [x, y, z]); }, glTranslatef: 'glTranslated', glRotated: function(angle, x, y, z) { GLImmediate.matricesModified = true; GLImmediate.matrixVersion[GLImmediate.currentMatrix] = (GLImmediate.matrixVersion[GLImmediate.currentMatrix] + 1)|0; - GLImmediate.matrix.lib.mat4.rotate(GLImmediate.matrix[GLImmediate.currentMatrix], angle*Math.PI/180, [x, y, z]); + GLImmediate.matrixLib.mat4.rotate(GLImmediate.matrix[GLImmediate.currentMatrix], angle*Math.PI/180, [x, y, z]); }, glRotatef: 'glRotated', @@ -4835,14 +4837,14 @@ var LibraryGL = { GLImmediate.matricesModified = true; GLImmediate.matrixVersion[GLImmediate.currentMatrix] = (GLImmediate.matrixVersion[GLImmediate.currentMatrix] + 1)|0; GLImmediate.matrix[GLImmediate.currentMatrix] = - GLImmediate.matrix.lib.mat4.perspective(fov, aspect, near, far, + GLImmediate.matrixLib.mat4.perspective(fov, aspect, near, far, GLImmediate.matrix[GLImmediate.currentMatrix]); }, gluLookAt: function(ex, ey, ez, cx, cy, cz, ux, uy, uz) { GLImmediate.matricesModified = true; GLImmediate.matrixVersion[GLImmediate.currentMatrix] = (GLImmediate.matrixVersion[GLImmediate.currentMatrix] + 1)|0; - GLImmediate.matrix.lib.mat4.lookAt(GLImmediate.matrix[GLImmediate.currentMatrix], [ex, ey, ez], + GLImmediate.matrixLib.mat4.lookAt(GLImmediate.matrix[GLImmediate.currentMatrix], [ex, ey, ez], [cx, cy, cz], [ux, uy, uz]); }, @@ -4851,9 +4853,9 @@ var LibraryGL = { var inVec = new Float32Array(4); var outVec = new Float32Array(4); - GLImmediate.matrix.lib.mat4.multiplyVec4({{{ makeHEAPView('F64', 'model', 'model+' + (16*8)) }}}, + GLImmediate.matrixLib.mat4.multiplyVec4({{{ makeHEAPView('F64', 'model', 'model+' + (16*8)) }}}, [objX, objY, objZ, 1.0], outVec); - GLImmediate.matrix.lib.mat4.multiplyVec4({{{ makeHEAPView('F64', 'proj', 'proj+' + (16*8)) }}}, + GLImmediate.matrixLib.mat4.multiplyVec4({{{ makeHEAPView('F64', 'proj', 'proj+' + (16*8)) }}}, outVec, inVec); if (inVec[3] == 0.0) { return 0 /* GL_FALSE */; @@ -4877,7 +4879,7 @@ var LibraryGL = { }, gluUnProject: function(winX, winY, winZ, model, proj, view, objX, objY, objZ) { - var result = GLImmediate.matrix.lib.mat4.unproject([winX, winY, winZ], + var result = GLImmediate.matrixLib.mat4.unproject([winX, winY, winZ], {{{ makeHEAPView('F64', 'model', 'model+' + (16*8)) }}}, {{{ makeHEAPView('F64', 'proj', 'proj+' + (16*8)) }}}, {{{ makeHEAPView('32', 'view', 'view+' + (4*4)) }}}); From 86034e680b3b800e0767360b819a8f01000e4ff4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Thu, 9 Jan 2014 22:07:52 +0200 Subject: [PATCH 22/42] Add var GLctx; declaration to GL init to avoid polluting global namespace. Replace all 'this.xxx' with 'GLImmediate.xxx' when this==GLImmediate, to avoid throwing off Closure minification pass. --- src/library_gl.js | 72 +++++++++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/src/library_gl.js b/src/library_gl.js index 54348a7673614..b0f351dc3bff9 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, @@ -3376,11 +3376,11 @@ var LibraryGL = { fixedFunctionProgram: null, setClientAttribute: function setClientAttribute(name, size, type, stride, pointer) { - var attrib = this.clientAttributes[name]; + var attrib = GLImmediate.clientAttributes[name]; if (!attrib) { for (var i = 0; i <= name; i++) { // keep flat - if (!this.clientAttributes[i]) { - this.clientAttributes[i] = { + if (!GLImmediate.clientAttributes[i]) { + GLImmediate.clientAttributes[i] = { name: name, size: size, type: type, @@ -3398,37 +3398,37 @@ var LibraryGL = { attrib.pointer = pointer; attrib.offset = 0; } - this.modifiedClientAttributes = true; + GLImmediate.modifiedClientAttributes = true; }, // Renderers addRendererComponent: function addRendererComponent(name, size, type) { - if (!this.rendererComponents[name]) { - this.rendererComponents[name] = 1; + if (!GLImmediate.rendererComponents[name]) { + GLImmediate.rendererComponents[name] = 1; #if ASSERTIONS - if (this.enabledClientAttributes[name]) { + if (GLImmediate.enabledClientAttributes[name]) { console.log("Warning: glTexCoord used after EnableClientState for TEXTURE_COORD_ARRAY for TEXTURE0. Disabling TEXTURE_COORD_ARRAY..."); } #endif - this.enabledClientAttributes[name] = true; - this.setClientAttribute(name, size, type, 0, this.rendererComponentPointer); - this.rendererComponentPointer += size * GL.byteSizeByType[type - GL.byteSizeByTypeRoot]; + GLImmediate.enabledClientAttributes[name] = true; + GLImmediate.setClientAttribute(name, size, type, 0, GLImmediate.rendererComponentPointer); + GLImmediate.rendererComponentPointer += size * GL.byteSizeByType[type - GL.byteSizeByTypeRoot]; } else { - this.rendererComponents[name]++; + GLImmediate.rendererComponents[name]++; } }, disableBeginEndClientAttributes: function disableBeginEndClientAttributes() { - for (var i = 0; i < this.NUM_ATTRIBUTES; i++) { - if (this.rendererComponents[i]) this.enabledClientAttributes[i] = false; + for (var i = 0; i < GLImmediate.NUM_ATTRIBUTES; i++) { + if (GLImmediate.rendererComponents[i]) GLImmediate.enabledClientAttributes[i] = false; } }, getRenderer: function getRenderer() { // If no FFP state has changed that would have forced to re-evaluate which FFP emulation shader to use, // we have the currently used renderer in cache, and can immediately return that. - if (this.currentRenderer) { - return this.currentRenderer; + if (GLImmediate.currentRenderer) { + return GLImmediate.currentRenderer; } // return a renderer object given the liveClientAttributes // we maintain a cache of renderers, optimized to not generate garbage @@ -3473,12 +3473,12 @@ var LibraryGL = { #if GL_DEBUG Module.printErr('generating renderer for ' + JSON.stringify(attributes)); #endif - renderer = this.createRenderer(); - this.currentRenderer = renderer; + renderer = GLImmediate.createRenderer(); + GLImmediate.currentRenderer = renderer; keyView.set(renderer); return renderer; } - this.currentRenderer = renderer; // Cache the currently used renderer, so later lookups without state changes can get this fast. + GLImmediate.currentRenderer = renderer; // Cache the currently used renderer, so later lookups without state changes can get this fast. return renderer; }, @@ -4028,7 +4028,7 @@ var LibraryGL = { if (!Module.useWebGL) return; // a 2D canvas may be currently used TODO: make sure we are actually called in that case - this.TexEnvJIT.init(GLctx); + GLImmediate.TexEnvJIT.init(GLctx); // User can override the maximum number of texture units that we emulate. Using fewer texture units increases runtime performance // slightly, so it is advantageous to choose as small value as needed. @@ -4044,28 +4044,28 @@ var LibraryGL = { // Initialize matrix library // When user sets a matrix, increment a 'version number' on the new data, and when rendering, submit // the matrices to the shader program only if they have an old version of the data. - this.matrix = []; - this.matrixStack = []; - this.matrixVersion = []; + GLImmediate.matrix = []; + GLImmediate.matrixStack = []; + GLImmediate.matrixVersion = []; for (var i = 0; i < 2 + GLImmediate.MAX_TEXTURES; i++) { // Modelview, Projection, plus one matrix for each texture coordinate. - this.matrixStack.push([]); - this.matrixVersion.push(0); + GLImmediate.matrixStack.push([]); + GLImmediate.matrixVersion.push(0); GLImmediate.matrix.push(GLImmediate.matrixLib.mat4.create()); GLImmediate.matrixLib.mat4.identity(GLImmediate.matrix[i]); } // Renderer cache - this.rendererCache = this.MapTreeLib.create(); + GLImmediate.rendererCache = GLImmediate.MapTreeLib.create(); // Buffers for data - this.tempData = new Float32Array(GL.MAX_TEMP_BUFFER_SIZE >> 2); - this.indexData = new Uint16Array(GL.MAX_TEMP_BUFFER_SIZE >> 1); + GLImmediate.tempData = new Float32Array(GL.MAX_TEMP_BUFFER_SIZE >> 2); + GLImmediate.indexData = new Uint16Array(GL.MAX_TEMP_BUFFER_SIZE >> 1); - this.vertexDataU8 = new Uint8Array(this.tempData.buffer); + GLImmediate.vertexDataU8 = new Uint8Array(GLImmediate.tempData.buffer); GL.generateTempBuffers(true); - this.clientColor = new Float32Array([1, 1, 1, 1]); + GLImmediate.clientColor = new Float32Array([1, 1, 1, 1]); }, // Prepares and analyzes client attributes. @@ -4076,11 +4076,11 @@ var LibraryGL = { // If no client attributes were modified since we were last called, do nothing. Note that this // does not work for glBegin/End, where we generate renderer components dynamically and then // disable them ourselves, but it does help with glDrawElements/Arrays. - if (!this.modifiedClientAttributes) { + if (!GLImmediate.modifiedClientAttributes) { GLImmediate.vertexCounter = (GLImmediate.stride * count) / 4; // XXX assuming float return; } - this.modifiedClientAttributes = false; + GLImmediate.modifiedClientAttributes = false; var stride = 0, start; var attributes = GLImmediate.liveClientAttributes; @@ -4177,10 +4177,10 @@ var LibraryGL = { startIndex = startIndex || 0; ptr = ptr || 0; - var renderer = this.getRenderer(); + var renderer = GLImmediate.getRenderer(); // Generate index data in a format suitable for GLES 2.0/WebGL - var numVertexes = 4 * this.vertexCounter / GLImmediate.stride; + var numVertexes = 4 * GLImmediate.vertexCounter / GLImmediate.stride; #if ASSERTIONS assert(numVertexes % 1 == 0, "`numVertexes` must be an integer."); #endif @@ -4500,7 +4500,7 @@ var LibraryGL = { if (!GLImmediate.enabledClientAttributes[attrib]) { GLImmediate.enabledClientAttributes[attrib] = true; GLImmediate.totalEnabledClientAttributes++; - this.currentRenderer = null; // Will need to change current renderer, since the set of active vertex pointers changed. + GLImmediate.currentRenderer = null; // Will need to change current renderer, since the set of active vertex pointers changed. if (GLEmulation.currentVao) GLEmulation.currentVao.enabledClientStates[cap] = 1; GLImmediate.modifiedClientAttributes = true; } @@ -4516,7 +4516,7 @@ var LibraryGL = { if (GLImmediate.enabledClientAttributes[attrib]) { GLImmediate.enabledClientAttributes[attrib] = false; GLImmediate.totalEnabledClientAttributes--; - this.currentRenderer = null; // Will need to change current renderer, since the set of active vertex pointers changed. + GLImmediate.currentRenderer = null; // Will need to change current renderer, since the set of active vertex pointers changed. if (GLEmulation.currentVao) delete GLEmulation.currentVao.enabledClientStates[cap]; GLImmediate.modifiedClientAttributes = true; } From 84638738eeacf4abf5d2239ac2a749ea1dde59d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Thu, 9 Jan 2014 22:12:09 +0200 Subject: [PATCH 23/42] Fix preprocessor ifdef in GL emulation library. --- src/library_gl.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/library_gl.js b/src/library_gl.js index b0f351dc3bff9..0c601673e0e82 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -4243,8 +4243,10 @@ var LibraryGL = { GLctx.bindBuffer(GLctx.ELEMENT_ARRAY_BUFFER, GL.buffers[GL.currElementArrayBuffer] || null); } -#if GL_UNSAFE_OPTS == 0 && !GL_FFP_ONLY +#if GL_UNSAFE_OPTS == 0 +#if !GL_FFP_ONLY renderer.cleanup(); +#endif #endif } }, From 3cb6d3bca44377f9cf198a095da857413efdc9a8 Mon Sep 17 00:00:00 2001 From: Anthony Pesch Date: Wed, 8 Jan 2014 11:47:59 -0800 Subject: [PATCH 24/42] utilize stack member from base Error class --- src/library_fs.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/library_fs.js b/src/library_fs.js index 1e7856aa4d7ea..e6b060f6d9e73 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; From bcce3b5fb4528a9a10f85cdcd11cf169a84350cd Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 9 Jan 2014 15:58:16 -0800 Subject: [PATCH 25/42] support exceptions using fastcomp --- emcc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/emcc b/emcc index 00cf3f067ac0b..ba927da590bb3 100755 --- a/emcc +++ b/emcc @@ -1194,9 +1194,6 @@ try: if fastcomp: shared.Settings.ASM_JS = 1 - if shared.Settings.DISABLE_EXCEPTION_CATCHING == 0: - logging.warning('disabling exception catching since not supported in fastcomp yet') - shared.Settings.DISABLE_EXCEPTION_CATCHING = 1 assert shared.Settings.ALLOW_MEMORY_GROWTH == 0, 'memory growth not supported in fastcomp yet' assert shared.Settings.UNALIGNED_MEMORY == 0, 'forced unaligned memory not supported in fastcomp' assert shared.Settings.SAFE_HEAP == 0, 'safe heap not supported in fastcomp yet' @@ -1216,6 +1213,10 @@ try: logging.warning('jcache is not supported in fastcomp (you should not need it anyhow), disabling') jcache = False + fastcomp_opts = ['-pnacl-abi-simplify-preopt', '-pnacl-abi-simplify-postopt'] + if not shared.Settings.DISABLE_EXCEPTION_CATCHING: + fastcomp_opts += ['-enable-emscripten-cxx-exceptions'] + if shared.Settings.ASM_JS: assert opt_level >= 1 or fastcomp, 'asm.js requires -O1 or above' @@ -1744,7 +1745,6 @@ try: # At minimum remove dead functions etc., this potentially saves a lot in the size of the generated code (and the time to compile it) link_opts += shared.Building.get_safe_internalize() + ['-globaldce'] - if (not save_bc and not fastcomp) or AUTODEBUG: # let llvm opt directly emit ll, to skip writing and reading all the bitcode link_opts += ['-S'] @@ -1754,13 +1754,13 @@ try: else: if fastcomp and not save_bc: # Simplify LLVM bitcode for fastcomp - link_opts += ['-pnacl-abi-simplify-preopt', '-pnacl-abi-simplify-postopt'] + link_opts += fastcomp_opts shared.Building.llvm_opt(final, link_opts) if DEBUG: save_intermediate('linktime', 'bc') if save_bc: shutil.copyfile(final, save_bc) if fastcomp: - shared.Building.llvm_opt(final, ['-pnacl-abi-simplify-preopt', '-pnacl-abi-simplify-postopt'], final + '.adsimp.bc') + shared.Building.llvm_opt(final, fastcomp_opts, final + '.adsimp.bc') final += '.adsimp.bc' if DEBUG: save_intermediate('adsimp', 'bc') @@ -1780,7 +1780,7 @@ try: # Simplify bitcode after autodebug if fastcomp and (AUTODEBUG or LEAVE_INPUTS_RAW): - shared.Building.llvm_opt(final, ['-pnacl-abi-simplify-preopt', '-pnacl-abi-simplify-postopt'], final + '.adsimp.bc') + shared.Building.llvm_opt(final, fastcomp_opts, final + '.adsimp.bc') final += '.adsimp.bc' if DEBUG: save_intermediate('adsimp', 'bc') From dfd9cf8cc063158cbaeecc81bc0e4b27ef6bec20 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 9 Jan 2014 18:18:05 -0800 Subject: [PATCH 26/42] prevent calling run more than once; fixes #1992 --- src/postamble.js | 7 +++---- tests/test_other.py | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/postamble.js b/src/postamble.js index 634959149ee4f..d6c059b82ea2a 100644 --- a/src/postamble.js +++ b/src/postamble.js @@ -117,16 +117,15 @@ function run(args) { preRun(); - if (runDependencies > 0) { - // a preRun added a dependency, run will be called later - return; - } + if (runDependencies > 0) return; // a preRun added a dependency, run will be called later + if (Module['calledRun']) return; // run may have just been called through dependencies being fulfilled just in this very frame function doRun() { ensureInitRuntime(); preMain(); + assert(!Module['calledRun']); Module['calledRun'] = true; if (Module['_main'] && shouldRunNow) { Module['callMain'](args); diff --git a/tests/test_other.py b/tests/test_other.py index c5f0c58334516..f91b4683d1a82 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -2219,3 +2219,35 @@ def test_default_obj_ext(self): process.communicate() assert(os.path.isfile(outdir + 'hello_world.obj')) + + def test_doublestart_bug(self): + open('code.cpp', 'w').write(r''' +#include +#include + +void main_loop(void) { + static int cnt = 0; + if (++cnt >= 10) emscripten_cancel_main_loop(); +} + +int main(void) { + printf("This should only appear once.\n"); + emscripten_set_main_loop(main_loop, 10, 0); + return 0; +} +''') + + open('pre.js', 'w').write(r''' +if (typeof Module === 'undefined') Module = eval('(function() { try { return Module || {} } catch(e) { return {} } })()'); +if (!Module['preRun']) Module['preRun'] = []; +Module["preRun"].push(function () { + Module['addRunDependency']('test_run_dependency'); + Module['removeRunDependency']('test_run_dependency'); +}); +''') + + Popen([PYTHON, EMCC, 'code.cpp', '--pre-js', 'pre.js']).communicate() + output = run_js(os.path.join(self.get_dir(), 'a.out.js'), engine=NODE_JS) + + assert output.count('This should only appear once.') == 1, '\n'+output + From 4e3c1b3e862ffd8e324cd1f24ed84692bd50a83b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Fri, 10 Jan 2014 14:40:24 +0200 Subject: [PATCH 27/42] Optimize GL emulation prepareClientAttributes. Fix issues where the slow path was not able to handle unaligned source data. Annotate some unsupported cases. Remove liveClientAttributes, which does not seem to be a win in profiles. --- src/library_gl.js | 174 ++++++++++++++++++++++++++-------------------- 1 file changed, 98 insertions(+), 76 deletions(-) diff --git a/src/library_gl.js b/src/library_gl.js index 0c601673e0e82..14ea8795fb556 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -3367,7 +3367,6 @@ var LibraryGL = { totalEnabledClientAttributes: 0, enabledClientAttributes: [0, 0], clientAttributes: [], // raw data, including possible unneeded ones - liveClientAttributes: [], // the ones actually alive in the current computation, sorted currentRenderer: null, // Caches the currently active FFP emulation renderer, so that it does not have to be re-looked up unless relevant state changes. modifiedClientAttributes: false, clientActiveTexture: 0, @@ -3430,17 +3429,17 @@ var LibraryGL = { if (GLImmediate.currentRenderer) { return GLImmediate.currentRenderer; } - // return a renderer object given the liveClientAttributes // we maintain a cache of renderers, optimized to not generate garbage - var attributes = GLImmediate.liveClientAttributes; var cacheMap = GLImmediate.rendererCache; var temp; var keyView = cacheMap.getStaticKeyView().reset(); // By attrib state: var enabledAttributesKey = 0; - for (var i = 0; i < attributes.length; i++) { - enabledAttributesKey |= 1 << attributes[i].name; + for (var i = 0; i < GLImmediate.MAX_TEXTURES+3; i++) { + if (GLImmediate.enabledClientAttributes[i]) { + enabledAttributesKey |= 1 << i; + } } keyView.next(enabledAttributesKey); @@ -3471,7 +3470,13 @@ var LibraryGL = { var renderer = keyView.get(); if (!renderer) { #if GL_DEBUG - Module.printErr('generating renderer for ' + JSON.stringify(attributes)); + var liveClientAttributes = []; + for (var i = 0; i < GLImmediate.MAX_TEXTURES+3; i++) { + if (GLImmediate.enabledClientAttributes[i]) { + liveClientAttributes.push(clientAttributes[i]); + } + } + Module.printErr('generating renderer for ' + JSON.stringify(liveClientAttributes)); #endif renderer = GLImmediate.createRenderer(); GLImmediate.currentRenderer = renderer; @@ -4077,96 +4082,113 @@ var LibraryGL = { // does not work for glBegin/End, where we generate renderer components dynamically and then // disable them ourselves, but it does help with glDrawElements/Arrays. if (!GLImmediate.modifiedClientAttributes) { +#if GL_ASSERTIONS + if ((GLImmediate.stride & 3) != 0) { + Runtime.warnOnce('Warning: Rendering from client side vertex arrays where stride (' + GLImmediate.stride + ') is not a multiple of four! This is not currently supported!'); + } +#endif GLImmediate.vertexCounter = (GLImmediate.stride * count) / 4; // XXX assuming float return; } GLImmediate.modifiedClientAttributes = false; - var stride = 0, start; - var attributes = GLImmediate.liveClientAttributes; - attributes.length = 0; - for (var i = 0; i < GLImmediate.NUM_ATTRIBUTES; i++) { - if (GLImmediate.enabledClientAttributes[i]) attributes.push(GLImmediate.clientAttributes[i]); - } - attributes.sort(function(x, y) { return !x ? (!y ? 0 : 1) : (!y ? -1 : (x.pointer - y.pointer)) }); - start = GL.currArrayBuffer ? 0 : attributes[0].pointer; - var multiStrides = false; - for (var i = 0; i < attributes.length; i++) { - var attribute = attributes[i]; - if (!attribute) break; - if (stride != 0 && stride != attribute.stride) multiStrides = true; - if (attribute.stride) stride = attribute.stride; + // The role of prepareClientAttributes is to examine the set of client-side vertex attribute buffers + // that user code has submitted, and to prepare them to be uploaded to a VBO in GPU memory + // (since WebGL does not support client-side rendering, i.e. rendering from vertex data in CPU memory) + // User can submit vertex data generally in three different configurations: + // 1. Fully planar: all attributes are in their own separate tightly-packed arrays in CPU memory. + // 2. Fully interleaved: all attributes share a single array where data is interleaved something like (pos,uv,normal), (pos,uv,normal), ... + // 3. Complex hybrid: Multiple separate arrays that either are sparsely strided, and/or partially interleave vertex attributes. + + // For simplicity, we support the case (2) as the fast case. For (1) and (3), we do a memory copy of the + // vertex data here to prepare a relayouted buffer that is of the structure in case (2). The reason + // for this is that it allows the emulation code to get away with using just one VBO buffer for rendering, + // and not have to maintain multiple ones. Therefore cases (1) and (3) will be very slow, and case (2) is fast. + + // Detect which case we are in by using a quick heuristic by examining the strides of the buffers. If all the buffers have identical + // stride, we assume we have case (2), otherwise we have something more complex. + var clientStartPointer = 0x7FFFFFFF; + var bytes = 0; // Total number of bytes taken up by a single vertex. + var minStride = 0x7FFFFFFF; + var maxStride = 0; + for (var i = 0; i < 3+GLImmediate.MAX_TEXTURES; i++) { + if (GLImmediate.enabledClientAttributes[i]) { + var attr = GLImmediate.clientAttributes[i]; + clientStartPointer = Math.min(clientStartPointer, attr.pointer); + attr.sizeBytes = attr.size * GL.byteSizeByType[attr.type - GL.byteSizeByTypeRoot]; + bytes += attr.sizeBytes; + minStride = Math.min(minStride, attr.stride); + maxStride = Math.max(maxStride, attr.stride); + } } - if (multiStrides) stride = 0; // we will need to restride - var bytes = 0; // total size in bytes - if (!stride && !beginEnd) { - // beginEnd can not have stride in the attributes, that is fine. otherwise, - // no stride means that all attributes are in fact packed. to keep the rest of - // our emulation code simple, we perform unpacking/restriding here. this adds overhead, so - // it is a good idea to not hit this! -#if ASSERTIONS - Runtime.warnOnce('Unpacking/restriding attributes, this is slow and dangerous'); + if ((minStride != maxStride || maxStride < bytes) && !beginEnd) { + // We are in cases (1) or (3): slow path, shuffle the data around into a single interleaved vertex buffer. + // The immediate-mode glBegin()/glEnd() vertex submission gets automatically generated in appropriate layout, + // so never need to come down this path if that was used. +#if GL_ASSERTIONS + Runtime.warnOnce('Rendering from planar client-side vertex arrays. This is a very slow emulation path! Use interleaved vertex arrays for best performance.'); #endif if (!GLImmediate.restrideBuffer) GLImmediate.restrideBuffer = _malloc(GL.MAX_TEMP_BUFFER_SIZE); - start = GLImmediate.restrideBuffer; -#if ASSERTIONS - assert(start % 4 == 0); -#endif + var start = GLImmediate.restrideBuffer; + bytes = 0; // calculate restrided offsets and total size - for (var i = 0; i < attributes.length; i++) { - var attribute = attributes[i]; - if (!attribute) break; - var size = attribute.size * GL.byteSizeByType[attribute.type - GL.byteSizeByTypeRoot]; - if (size % 4 != 0) size += 4 - (size % 4); // align everything - attribute.offset = bytes; - bytes += size; + for (var i = 0; i < GLImmediate.clientAttributes.length; i++) { + if (GLImmediate.enabledClientAttributes[i]) { + var attribute = GLImmediate.clientAttributes[i]; + var size = attribute.sizeBytes; + if (size % 4 != 0) size += 4 - (size % 4); // align everything + attribute.offset = bytes; + bytes += size; + } } -#if ASSERTIONS - 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++) { - var attribute = attributes[i]; - if (!attribute) break; - var size4 = Math.floor((attribute.size * GL.byteSizeByType[attribute.type - GL.byteSizeByTypeRoot])/4); - for (var j = 0; j < count; j++) { - for (var k = 0; k < size4; k++) { // copy in chunks of 4 bytes, our alignment makes this possible - HEAP32[((start + attribute.offset + bytes*j)>>2) + k] = HEAP32[(attribute.pointer>>2) + j*size4 + k]; + // copy out the data (we need to know the stride for that, and define attribute.pointer) + for (var i = 0; i < GLImmediate.clientAttributes.length; i++) { + if (GLImmediate.enabledClientAttributes[i]) { + var attribute = GLImmediate.clientAttributes[i]; + var srcStride = Math.max(attribute.sizeBytes, attribute.stride); + if ((srcStride & 3) == 0 && (attribute.sizeBytes & 3) == 0) { + var size4 = attribute.sizeBytes>>2; + var srcStride4 = Math.max(attribute.sizeBytes, attribute.stride)>>2; + for (var j = 0; j < count; j++) { + for (var k = 0; k < size4; k++) { // copy in chunks of 4 bytes, our alignment makes this possible + HEAP32[((start + attribute.offset + bytes*j)>>2) + k] = HEAP32[(attribute.pointer>>2) + j*srcStride4 + k]; + } + } + } else { + for (var j = 0; j < count; j++) { + for (var k = 0; k < attribute.sizeBytes; k++) { // source data was not aligned to multiples of 4, must copy byte by byte. + HEAP8[start + attribute.offset + bytes*j + k] = HEAP8[attribute.pointer + j*srcStride + k]; + } + } } + attribute.pointer = start + attribute.offset; } - attribute.pointer = start + attribute.offset; } + GLImmediate.stride = bytes; + GLImmediate.vertexPointer = start; } else { - // normal situation, everything is strided and in the same buffer - for (var i = 0; i < attributes.length; i++) { - var attribute = attributes[i]; - if (!attribute) break; - attribute.offset = attribute.pointer - start; - if (attribute.offset > bytes) { // ensure we start where we should -#if ASSERTIONS - assert((attribute.offset - bytes)%4 == 0); // XXX assuming 4-alignment -#endif - bytes += attribute.offset - bytes; - } - bytes += attribute.size * GL.byteSizeByType[attribute.type - GL.byteSizeByTypeRoot]; - if (bytes % 4 != 0) bytes += 4 - (bytes % 4); // XXX assuming 4-alignment + // case (2): fast path, all data is interleaved to a single vertex array so we can get away with a single VBO upload. + if (GL.currArrayBuffer) { + GLImmediate.vertexPointer = 0; + } else { + GLImmediate.vertexPointer = clientStartPointer; } -#if ASSERTIONS - assert(beginEnd || bytes <= stride); // if not begin-end, explicit stride should make sense with total byte size -#endif - if (bytes < stride) { // ensure the size is that of the stride - bytes = stride; + for (var i = 0; i < 3+GLImmediate.MAX_TEXTURES; i++) { + if (GLImmediate.enabledClientAttributes[i]) { + var attr = GLImmediate.clientAttributes[i]; + attr.offset = attr.pointer - clientStartPointer; // Compute what will be the offset of this attribute in the VBO after we upload. + } } + GLImmediate.stride = Math.max(maxStride, bytes); } - GLImmediate.stride = bytes; - if (!beginEnd) { - bytes *= count; - if (!GL.currArrayBuffer) { - GLImmediate.vertexPointer = start; +#if GL_ASSERTIONS + if ((GLImmediate.stride & 3) != 0) { + Runtime.warnOnce('Warning: Rendering from client side vertex arrays where stride (' + GLImmediate.stride + ') is not a multiple of four! This is not currently supported!'); } - GLImmediate.vertexCounter = bytes / 4; // XXX assuming float +#endif + GLImmediate.vertexCounter = (GLImmediate.stride * count) / 4; // XXX assuming float } }, From b09c4e6ce1bb8cde51e501da4482588c1e867a41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emerson=20Jos=C3=A9=20Silveira=20da=20Costa?= Date: Fri, 10 Jan 2014 23:43:43 -0200 Subject: [PATCH 28/42] Update AUTHORS Adding my name to the AUTHORS list as instructed by kripken in response to: https://github.com/kripken/emscripten/pull/1996 --- AUTHORS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index 001af087ac6c5..cc5dfb56a4e3f 100644 --- a/AUTHORS +++ b/AUTHORS @@ -115,4 +115,5 @@ a license to everyone to use it as detailed in LICENSE.) * Adam C. Clifton * Volo Zyko * Andre Weissflog -* Alexandre Perrot \ No newline at end of file +* Alexandre Perrot +* Emerson José Silveira da Costa From e9ce1f707774c816e4a2697910fdaa478e7f9dfd Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 10 Jan 2014 18:15:18 -0800 Subject: [PATCH 29/42] enable first exceptions test for fastcomp --- tests/test_core.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_core.py b/tests/test_core.py index 2157eeb0c8574..df08b217df3e2 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -1300,7 +1300,6 @@ def test_white_list_exception(self): def test_uncaught_exception(self): if self.emcc_args is None: return self.skip('no libcxx inclusion without emcc') - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') Settings.DISABLE_EXCEPTION_CATCHING = 0 From 6ee92f8d2128edf5458a8993809d9e15d105e931 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 10 Jan 2014 18:21:30 -0800 Subject: [PATCH 30/42] enable more exceptions tests in fastcomp --- tests/test_core.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/test_core.py b/tests/test_core.py index df08b217df3e2..e617caad8ae5e 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -1186,7 +1186,6 @@ def test_setjmp_many(self): def test_exceptions(self): if Settings.QUANTUM_SIZE == 1: return self.skip("we don't support libcxx in q1") if self.emcc_args is None: return self.skip('need emcc to add in libcxx properly') - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') Settings.EXCEPTION_DEBUG = 1 @@ -1275,7 +1274,6 @@ class MyException def test_exception_2(self): if self.emcc_args is None: return self.skip('need emcc to add in libcxx properly') - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') Settings.DISABLE_EXCEPTION_CATCHING = 0 test_path = path_from_root('tests', 'core', 'test_exception_2') @@ -1358,7 +1356,6 @@ def test_multiexception(self): def test_std_exception(self): if self.emcc_args is None: return self.skip('requires emcc') - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') Settings.DISABLE_EXCEPTION_CATCHING = 0 self.emcc_args += ['-s', 'SAFE_HEAP=0'] From 9f74e557418e58ecdac3c9fc9c82c733bab1f308 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 11 Jan 2014 18:07:06 -0800 Subject: [PATCH 31/42] fix for nativize tool --- tools/nativize_llvm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/nativize_llvm.py b/tools/nativize_llvm.py index 413c8d14336f1..b327bdfcf4911 100755 --- a/tools/nativize_llvm.py +++ b/tools/nativize_llvm.py @@ -23,7 +23,7 @@ def path_from_root(*pathelems): print 'bc => clean bc' Popen([LLVM_OPT, filename, '-strip-debug', '-o', filename + '.clean.bc']).communicate()[0] print 'bc => s' -for params in [[], ['-march=x86-64']]: # try x86, then x86-64 FIXME +for params in [['-march=x86'], ['-march=x86-64']]: # try x86, then x86-64 FIXME print 'params', params Popen([LLVM_COMPILER] + params + [filename + '.clean.bc', '-o', filename + '.s']).communicate()[0] print 's => o' From 0bb7d8093a98b8bd41b9eeeaf8bde671f0b9894e Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 11 Jan 2014 18:07:31 -0800 Subject: [PATCH 32/42] more i64 switch tests --- tests/cases/switch64_ta2.ll | 44 +++++++++++++--------------- tests/cases/switch64_ta2.txt | 2 ++ tests/cases/switch64b_ta2.ll | 54 +++++++++++++++++++++++++++++++++++ tests/cases/switch64b_ta2.txt | 3 ++ 4 files changed, 79 insertions(+), 24 deletions(-) create mode 100644 tests/cases/switch64_ta2.txt create mode 100644 tests/cases/switch64b_ta2.ll create mode 100644 tests/cases/switch64b_ta2.txt diff --git a/tests/cases/switch64_ta2.ll b/tests/cases/switch64_ta2.ll index 4d5c6273ee393..1a6d52f3aaa97 100644 --- a/tests/cases/switch64_ta2.ll +++ b/tests/cases/switch64_ta2.ll @@ -1,12 +1,14 @@ target datalayout = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-p:32:32:32-v128:32:32" target triple = "le32-unknown-nacl" -@.str = private constant [15 x i8] c"hello, world!\0A\00", align 1 ; [#uses=1] +@.str = private constant [18 x i8] c"hello, world: %d\0A\00", align 1 + +declare i32 @printf(i8*, ...) define linkonce_odr i32 @main() align 2 { - %a333 = call i32 @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0)) ; [#uses=0] - %a444 = zext i32 %a333 to i64 - %a199 = trunc i8 1 to i1 ; [#uses=1] + %a333 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([18 x i8]* @.str, i32 0, i32 0), i32 5) + %a400 = zext i32 %a333 to i64 + %a444 = udiv i64 %a400, 3 switch i64 %a444, label %label999 [ i64 1000, label %label9950 i64 1001, label %label9951 @@ -18,41 +20,35 @@ define linkonce_odr i32 @main() align 2 { i64 1007, label %label9957 i64 1008, label %label9958 i64 1009, label %label9959 - ] ; switch should ignore all code after it in the block - ; No predecessors! - %a472 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) - cleanup - %a473 = extractvalue { i8*, i32 } %a472, 0 - %a474 = extractvalue { i8*, i32 } %a472, 1 - br label %label999 + ] label9950: - %a333b = call i32 @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0)) ; [#uses=0] + %waka = phi i32 [1000, %0], [0, %label9951], [1, %label9952], [2, %label9953], [3, %label9954], [4, %label9955], [5, %label9956], [6, %label9957], [7, %label9958], [8, %label9959] + %a333b = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([18 x i8]* @.str, i32 0, i32 0), i32 %waka) br label %label999 label9951: - br label %label999 + br label %label9950 label9952: - br label %label999 + br label %label9950 label9953: - br label %label999 + br label %label9950 label9954: - br label %label999 + br label %label9950 label9955: - br label %label999 + br label %label9950 label9956: - br label %label999 + br label %label9950 label9957: - br label %label999 + br label %label9950 label9958: - br label %label999 + br label %label9950 label9959: - br label %label999 + br label %label9950 label999: ; preds = %555 + %last = phi i32 [1, %0], [2, %label9950] + %a333c = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([18 x i8]* @.str, i32 0, i32 0), i32 %last) ret i32 0 } -declare i32 @printf(i8*) -declare i32 @__gxx_personality_v0(...) - diff --git a/tests/cases/switch64_ta2.txt b/tests/cases/switch64_ta2.txt new file mode 100644 index 0000000000000..72084b0ca5112 --- /dev/null +++ b/tests/cases/switch64_ta2.txt @@ -0,0 +1,2 @@ +hello, world: 5 +hello, world: 1 diff --git a/tests/cases/switch64b_ta2.ll b/tests/cases/switch64b_ta2.ll new file mode 100644 index 0000000000000..4364725fc7839 --- /dev/null +++ b/tests/cases/switch64b_ta2.ll @@ -0,0 +1,54 @@ +target datalayout = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-p:32:32:32-v128:32:32" +target triple = "le32-unknown-nacl" + +@.str = private constant [18 x i8] c"hello, world: %d\0A\00", align 1 + +declare i32 @printf(i8*, ...) + +define linkonce_odr i32 @main() align 2 { + %a333 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([18 x i8]* @.str, i32 0, i32 0), i32 5) + %a400 = zext i32 %a333 to i64 + %a444 = udiv i64 %a400, 3 + switch i64 %a444, label %label999 [ + i64 0, label %label9950 + i64 1, label %label9951 + i64 2, label %label9952 + i64 3, label %label9953 + i64 4, label %label9954 + i64 5, label %label9955 + i64 6, label %label9956 + i64 7, label %label9957 + i64 8, label %label9958 + i64 9, label %label9959 + ] + +label9950: + %waka = phi i32 [11000, %0], [10, %label9951], [11, %label9952], [12, %label9953], [13, %label9954], [14, %label9955], [15, %label9956], [16, %label9957], [17, %label9958], [18, %label9959] + %a333b = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([18 x i8]* @.str, i32 0, i32 0), i32 %waka) + br label %label999 + +label9951: + br label %label9950 +label9952: + br label %label9950 +label9953: + br label %label9950 +label9954: + br label %label9950 +label9955: + br label %label9950 +label9956: + br label %label9950 +label9957: + br label %label9950 +label9958: + br label %label9950 +label9959: + br label %label9950 + +label999: ; preds = %555 + %last = phi i32 [1, %0], [2, %label9950] + %a333c = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([18 x i8]* @.str, i32 0, i32 0), i32 %last) + ret i32 0 +} + diff --git a/tests/cases/switch64b_ta2.txt b/tests/cases/switch64b_ta2.txt new file mode 100644 index 0000000000000..917d42e566b2a --- /dev/null +++ b/tests/cases/switch64b_ta2.txt @@ -0,0 +1,3 @@ +hello, world: 5 +hello, world: 14 +hello, world: 2 From db386b079146ce333145e7470d82bb843591cf2a Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 12 Jan 2014 17:40:35 -0800 Subject: [PATCH 33/42] export named globals from fastcomp to js --- emscripten.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/emscripten.py b/emscripten.py index 1a3bddd749fa2..8ddb7375d7775 100755 --- a/emscripten.py +++ b/emscripten.py @@ -873,6 +873,10 @@ def save_settings(): if key in all_exported_functions or export_all or (export_bindings and key.startswith('_emscripten_bind')): exported_implemented_functions.add(key) + # Add named globals + named_globals = '\n'.join(['var %s = %s;' % (k, v) for k, v in metadata['namedGlobals'].iteritems()]) + pre = pre.replace('// === Body ===', '// === Body ===\n' + named_globals + '\n') + #if DEBUG: outfile.write('// pre\n') outfile.write(pre) pre = None From 238838982fc6a157ba95892c6bbd87252aba9d97 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 12 Jan 2014 19:58:34 -0800 Subject: [PATCH 34/42] enable test_typed_exceptions in fastcomp --- tests/test_core.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/test_core.py b/tests/test_core.py index e617caad8ae5e..3020c50c6f878 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -1336,8 +1336,6 @@ def test_uncaught_exception(self): self.do_run(src, 'success') def test_typed_exceptions(self): - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') - Settings.DISABLE_EXCEPTION_CATCHING = 0 Settings.SAFE_HEAP = 0 # Throwing null will cause an ignorable null pointer access. src = open(path_from_root('tests', 'exceptions', 'typed.cpp'), 'r').read() From e47ffbe2d2224dd0610e43979a35e4cb08c01cc6 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 12 Jan 2014 20:01:49 -0800 Subject: [PATCH 35/42] enable test_async_exit in fastcomp --- tests/test_core.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/test_core.py b/tests/test_core.py index 3020c50c6f878..399fb2f4e0be0 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -1363,8 +1363,6 @@ def test_std_exception(self): self.do_run_from_file(src, output) def test_async_exit(self): - if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') - open('main.c', 'w').write(r''' #include #include From 88d2ba5490b515245143e125b5ae52e27c2ee78c Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 12 Jan 2014 20:47:44 -0800 Subject: [PATCH 36/42] enable another test_cases case in fastcomp --- tests/test_core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_core.py b/tests/test_core.py index 399fb2f4e0be0..799e47f02dd5f 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -5027,7 +5027,7 @@ def test_cases(self): '2xi40', # pnacl limitations in ExpandGetElementPtr 'legalizer_ta2', '514_ta2', # pnacl limitation in not legalizing i104, i96, etc. 'longjmp_tiny', 'longjmp_tiny_invoke', 'longjmp_tiny_phi', 'longjmp_tiny_phi2', 'longjmp_tiny_invoke_phi', 'indirectbrphi', 'ptrtoint_blockaddr', 'quoted', # current fastcomp limitations FIXME - 'sillyfuncast', 'sillyfuncast2', 'sillybitcast', 'atomicrmw_unaligned' # TODO XXX + 'sillyfuncast2', 'sillybitcast', 'atomicrmw_unaligned' # TODO XXX ]: continue if '_ta2' in shortname and not Settings.USE_TYPED_ARRAYS == 2: print self.skip('case "%s" only relevant for ta2' % shortname) From d0446f2b9952ada6a5acd088cf54ef1313b8616d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Mon, 13 Jan 2014 16:11:30 +0200 Subject: [PATCH 37/42] Reintroduce liveClientAttributes to optimize the case where GL emulation code is called with a very large GLImmediate.MAX_TEXTURES size. --- src/library_gl.js | 76 +++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 42 deletions(-) diff --git a/src/library_gl.js b/src/library_gl.js index 14ea8795fb556..177495908037b 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -3367,6 +3367,7 @@ var LibraryGL = { totalEnabledClientAttributes: 0, enabledClientAttributes: [0, 0], clientAttributes: [], // raw data, including possible unneeded ones + liveClientAttributes: [], // the ones actually alive in the current computation, sorted currentRenderer: null, // Caches the currently active FFP emulation renderer, so that it does not have to be re-looked up unless relevant state changes. modifiedClientAttributes: false, clientActiveTexture: 0, @@ -3429,17 +3430,17 @@ var LibraryGL = { if (GLImmediate.currentRenderer) { return GLImmediate.currentRenderer; } + // return a renderer object given the liveClientAttributes // we maintain a cache of renderers, optimized to not generate garbage + var attributes = GLImmediate.liveClientAttributes; var cacheMap = GLImmediate.rendererCache; var temp; var keyView = cacheMap.getStaticKeyView().reset(); // By attrib state: var enabledAttributesKey = 0; - for (var i = 0; i < GLImmediate.MAX_TEXTURES+3; i++) { - if (GLImmediate.enabledClientAttributes[i]) { - enabledAttributesKey |= 1 << i; - } + for (var i = 0; i < attributes.length; i++) { + enabledAttributesKey |= 1 << attributes[i].name; } keyView.next(enabledAttributesKey); @@ -3470,13 +3471,7 @@ var LibraryGL = { var renderer = keyView.get(); if (!renderer) { #if GL_DEBUG - var liveClientAttributes = []; - for (var i = 0; i < GLImmediate.MAX_TEXTURES+3; i++) { - if (GLImmediate.enabledClientAttributes[i]) { - liveClientAttributes.push(clientAttributes[i]); - } - } - Module.printErr('generating renderer for ' + JSON.stringify(liveClientAttributes)); + Module.printErr('generating renderer for ' + JSON.stringify(attributes)); #endif renderer = GLImmediate.createRenderer(); GLImmediate.currentRenderer = renderer; @@ -4111,9 +4106,12 @@ var LibraryGL = { var bytes = 0; // Total number of bytes taken up by a single vertex. var minStride = 0x7FFFFFFF; var maxStride = 0; + var attributes = GLImmediate.liveClientAttributes; + attributes.length = 0; for (var i = 0; i < 3+GLImmediate.MAX_TEXTURES; i++) { if (GLImmediate.enabledClientAttributes[i]) { var attr = GLImmediate.clientAttributes[i]; + attributes.push(attr); clientStartPointer = Math.min(clientStartPointer, attr.pointer); attr.sizeBytes = attr.size * GL.byteSizeByType[attr.type - GL.byteSizeByTypeRoot]; bytes += attr.sizeBytes; @@ -4133,37 +4131,33 @@ var LibraryGL = { var start = GLImmediate.restrideBuffer; bytes = 0; // calculate restrided offsets and total size - for (var i = 0; i < GLImmediate.clientAttributes.length; i++) { - if (GLImmediate.enabledClientAttributes[i]) { - var attribute = GLImmediate.clientAttributes[i]; - var size = attribute.sizeBytes; - if (size % 4 != 0) size += 4 - (size % 4); // align everything - attribute.offset = bytes; - bytes += size; - } + for (var i = 0; i < attributes.length; i++) { + var attr = attributes[i]; + var size = attr.sizeBytes; + if (size % 4 != 0) size += 4 - (size % 4); // align everything + attr.offset = bytes; + bytes += size; } - // copy out the data (we need to know the stride for that, and define attribute.pointer) - for (var i = 0; i < GLImmediate.clientAttributes.length; i++) { - if (GLImmediate.enabledClientAttributes[i]) { - var attribute = GLImmediate.clientAttributes[i]; - var srcStride = Math.max(attribute.sizeBytes, attribute.stride); - if ((srcStride & 3) == 0 && (attribute.sizeBytes & 3) == 0) { - var size4 = attribute.sizeBytes>>2; - var srcStride4 = Math.max(attribute.sizeBytes, attribute.stride)>>2; - for (var j = 0; j < count; j++) { - for (var k = 0; k < size4; k++) { // copy in chunks of 4 bytes, our alignment makes this possible - HEAP32[((start + attribute.offset + bytes*j)>>2) + k] = HEAP32[(attribute.pointer>>2) + j*srcStride4 + k]; - } + // copy out the data (we need to know the stride for that, and define attr.pointer) + for (var i = 0; i < attributes.length; i++) { + var attr = attributes[i]; + var srcStride = Math.max(attr.sizeBytes, attr.stride); + if ((srcStride & 3) == 0 && (attr.sizeBytes & 3) == 0) { + var size4 = attr.sizeBytes>>2; + var srcStride4 = Math.max(attr.sizeBytes, attr.stride)>>2; + for (var j = 0; j < count; j++) { + for (var k = 0; k < size4; k++) { // copy in chunks of 4 bytes, our alignment makes this possible + HEAP32[((start + attr.offset + bytes*j)>>2) + k] = HEAP32[(attr.pointer>>2) + j*srcStride4 + k]; } - } else { - for (var j = 0; j < count; j++) { - for (var k = 0; k < attribute.sizeBytes; k++) { // source data was not aligned to multiples of 4, must copy byte by byte. - HEAP8[start + attribute.offset + bytes*j + k] = HEAP8[attribute.pointer + j*srcStride + k]; - } + } + } else { + for (var j = 0; j < count; j++) { + for (var k = 0; k < attr.sizeBytes; k++) { // source data was not aligned to multiples of 4, must copy byte by byte. + HEAP8[start + attr.offset + bytes*j + k] = HEAP8[attr.pointer + j*srcStride + k]; } } - attribute.pointer = start + attribute.offset; } + attr.pointer = start + attr.offset; } GLImmediate.stride = bytes; GLImmediate.vertexPointer = start; @@ -4174,11 +4168,9 @@ var LibraryGL = { } else { GLImmediate.vertexPointer = clientStartPointer; } - for (var i = 0; i < 3+GLImmediate.MAX_TEXTURES; i++) { - if (GLImmediate.enabledClientAttributes[i]) { - var attr = GLImmediate.clientAttributes[i]; - attr.offset = attr.pointer - clientStartPointer; // Compute what will be the offset of this attribute in the VBO after we upload. - } + for (var i = 0; i < attributes.length; i++) { + var attr = attributes[i]; + attr.offset = attr.pointer - clientStartPointer; // Compute what will be the offset of this attribute in the VBO after we upload. } GLImmediate.stride = Math.max(maxStride, bytes); } From e4876a3dd9e580ee5b290831baba2c3ae34b7d0e Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 13 Jan 2014 10:34:07 -0800 Subject: [PATCH 38/42] remove old test that cannot be done in fastcomp, relies on code miscompilation in original compiler --- tests/cases/breakinthemiddle3.ll | 29 ----------------------------- 1 file changed, 29 deletions(-) delete mode 100644 tests/cases/breakinthemiddle3.ll diff --git a/tests/cases/breakinthemiddle3.ll b/tests/cases/breakinthemiddle3.ll deleted file mode 100644 index 38da15efa5056..0000000000000 --- a/tests/cases/breakinthemiddle3.ll +++ /dev/null @@ -1,29 +0,0 @@ -target datalayout = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-p:32:32:32-v128:32:32" -target triple = "le32-unknown-nacl" - -@.str = private constant [15 x i8] c"hello, world!\0A\00", align 1 ; [#uses=1] - -define linkonce_odr i32 @main() align 2 { - %a333 = call i32 @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0)) ; [#uses=0] - %z199 = trunc i8 1 to i1 ; [#uses=1] - switch i32 %a333, label %label999 [ - i32 1000, label %label995 - ] ; switch should ignore all code after it in the block - ; No predecessors! - %a472 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) - cleanup - %a473 = extractvalue { i8*, i32 } %a472, 0 - %a474 = extractvalue { i8*, i32 } %a472, 1 - br label %label999 - -label995: - %b333b = call i32 @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0)) ; [#uses=0] - br label %label999 - -label999: ; preds = %555 - ret i32 0 -} - -declare i32 @printf(i8*) -declare i32 @__gxx_personality_v0(...) - From 502ba282c1ed5577bdfd2843d33808e4cbbeb401 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 13 Jan 2014 10:44:53 -0800 Subject: [PATCH 39/42] fix testcase to validate as llvm ir --- tests/cases/invokeundef.ll | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/cases/invokeundef.ll b/tests/cases/invokeundef.ll index be1dd67196fa8..2f13e7abea163 100644 --- a/tests/cases/invokeundef.ll +++ b/tests/cases/invokeundef.ll @@ -31,6 +31,8 @@ invcont33: ret i32 %retval1 lpad106: + %Z = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + cleanup ret i32 %retval1 return: ; preds = %entry @@ -40,3 +42,6 @@ return: ; preds = %entry ; [#uses=1] declare i32 @puts(i8*) + +declare i32 @__gxx_personality_v0(...) + From 4e64f48eeb95355ad214afc1add81b9cb7222e1e Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 13 Jan 2014 10:53:22 -0800 Subject: [PATCH 40/42] clean up some more tests/cases --- tests/cases/breakinthemiddle2.ll | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tests/cases/breakinthemiddle2.ll b/tests/cases/breakinthemiddle2.ll index ba96654f66f7b..2f8c1c91c35f0 100644 --- a/tests/cases/breakinthemiddle2.ll +++ b/tests/cases/breakinthemiddle2.ll @@ -11,10 +11,6 @@ define linkonce_odr i32 @main() align 2 { label555: ; preds = %0 br label %label569 ; branch should ignore all code after it in the block ; No predecessors! - %aa472 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) - cleanup - %aa473 = extractvalue { i8*, i32 } %aa472, 0 - %aa474 = extractvalue { i8*, i32 } %aa472, 1 br label %label569 label569: ; preds = %0 @@ -23,10 +19,6 @@ label569: ; preds = %0 label990: ret i32 0 ; ret should ignore all code after it in the block ; No predecessors! - %a472 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) - cleanup - %a473 = extractvalue { i8*, i32 } %a472, 0 - %a474 = extractvalue { i8*, i32 } %a472, 1 br label %label569 label999: ; preds = %555 From ec3eba770983ad300ca958db5764206924452b0b Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 13 Jan 2014 10:53:51 -0800 Subject: [PATCH 41/42] add dependencies so code with exceptions (invoke/landingpad) but without an actual throw will still pull in the necessary stuff --- src/library.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/library.js b/src/library.js index 354e55494eb19..3f0304895bed7 100644 --- a/src/library.js +++ b/src/library.js @@ -4455,6 +4455,7 @@ LibraryManager.library = { terminate: '__cxa_call_unexpected', + __gxx_personality_v0__deps: ['llvm_eh_exception', '_ZSt18uncaught_exceptionv', '__cxa_find_matching_catch'], __gxx_personality_v0: function() { }, From d1f37af9792b048f7ef98140d067ba129a97c565 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 13 Jan 2014 12:37:34 -0800 Subject: [PATCH 42/42] allow relooper to manager its own output buffer, to avoid fixed output limits --- src/relooper/Relooper.cpp | 59 +++++++++++++++++++++++++++++++-------- src/relooper/Relooper.h | 7 ++++- src/relooper/fuzzer.py | 14 ++++++++-- src/relooper/test.cpp | 28 +++++++++++++++++++ src/relooper/test.txt | 45 +++++++++++++++++++++++++++++ tools/shared.py | 2 +- 6 files changed, 139 insertions(+), 16 deletions(-) diff --git a/src/relooper/Relooper.cpp b/src/relooper/Relooper.cpp index 389d7447d963f..1bad872fc3f3b 100644 --- a/src/relooper/Relooper.cpp +++ b/src/relooper/Relooper.cpp @@ -40,27 +40,56 @@ static void PutIndented(const char *String); static char *OutputBufferRoot = NULL; static char *OutputBuffer = NULL; static int OutputBufferSize = 0; +static int OutputBufferOwned = false; + +static int LeftInOutputBuffer() { + return OutputBufferSize - (OutputBuffer - OutputBufferRoot); +} + +static bool EnsureOutputBuffer(int Needed) { // ensures the output buffer is sufficient. returns true is no problem happened + Needed++; // ensure the trailing \0 is not forgotten + int Left = LeftInOutputBuffer(); + if (!OutputBufferOwned) { + assert(Needed < Left); + } else { + // we own the buffer, and can resize if necessary + if (Needed >= Left) { + int Offset = OutputBuffer - OutputBufferRoot; + int TotalNeeded = OutputBufferSize + Needed - Left + 10240; + int NewSize = OutputBufferSize; + while (NewSize < TotalNeeded) NewSize = NewSize + (NewSize/2); + //printf("resize %d => %d\n", OutputBufferSize, NewSize); + OutputBufferRoot = (char*)realloc(OutputBufferRoot, NewSize); + OutputBuffer = OutputBufferRoot + Offset; + OutputBufferSize = NewSize; + return false; + } + } + return true; +} void PrintIndented(const char *Format, ...) { assert(OutputBuffer); - assert(OutputBuffer + Indenter::CurrIndent*INDENTATION - OutputBufferRoot < OutputBufferSize); + EnsureOutputBuffer(Indenter::CurrIndent*INDENTATION); for (int i = 0; i < Indenter::CurrIndent*INDENTATION; i++, OutputBuffer++) *OutputBuffer = ' '; - va_list Args; - va_start(Args, Format); - int left = OutputBufferSize - (OutputBuffer - OutputBufferRoot); - int written = vsnprintf(OutputBuffer, left, Format, Args); - assert(written < left); - OutputBuffer += written; - va_end(Args); + int Written; + while (1) { // write and potentially resize buffer until we have enough room + int Left = LeftInOutputBuffer(); + va_list Args; + va_start(Args, Format); + Written = vsnprintf(OutputBuffer, Left, Format, Args); + va_end(Args); + if (EnsureOutputBuffer(Written)) break; + } + OutputBuffer += Written; } void PutIndented(const char *String) { assert(OutputBuffer); - assert(OutputBuffer + Indenter::CurrIndent*INDENTATION - OutputBufferRoot < OutputBufferSize); + EnsureOutputBuffer(Indenter::CurrIndent*INDENTATION); for (int i = 0; i < Indenter::CurrIndent*INDENTATION; i++, OutputBuffer++) *OutputBuffer = ' '; - int left = OutputBufferSize - (OutputBuffer - OutputBufferRoot); - int needed = strlen(String)+1; - assert(needed < left); + int Needed = strlen(String)+1; + EnsureOutputBuffer(Needed); strcpy(OutputBuffer, String); OutputBuffer += strlen(String); *OutputBuffer++ = '\n'; @@ -1158,11 +1187,17 @@ void Relooper::Render() { void Relooper::SetOutputBuffer(char *Buffer, int Size) { OutputBufferRoot = OutputBuffer = Buffer; OutputBufferSize = Size; + OutputBufferOwned = false; } void Relooper::MakeOutputBuffer(int Size) { OutputBufferRoot = OutputBuffer = (char*)malloc(Size); OutputBufferSize = Size; + OutputBufferOwned = true; +} + +char *Relooper::GetOutputBuffer() { + return OutputBufferRoot; } void Relooper::SetAsmJSMode(int On) { diff --git a/src/relooper/Relooper.h b/src/relooper/Relooper.h index dfabcabbec7b9..6b9394dbaa1f2 100644 --- a/src/relooper/Relooper.h +++ b/src/relooper/Relooper.h @@ -200,11 +200,16 @@ struct Relooper { void Render(); // Sets the global buffer all printing goes to. Must call this or MakeOutputBuffer. + // XXX: this is deprecated, see MakeOutputBuffer static void SetOutputBuffer(char *Buffer, int Size); - // Creates an output buffer. Must call this or SetOutputBuffer. + // Creates an internal output buffer. Must call this or SetOutputBuffer. Size is + // a hint for the initial size of the buffer, it can be resized later one demand. + // For that reason this is more recommended than SetOutputBuffer. static void MakeOutputBuffer(int Size); + static char *GetOutputBuffer(); + // Sets asm.js mode on or off (default is off) static void SetAsmJSMode(int On); diff --git a/src/relooper/fuzzer.py b/src/relooper/fuzzer.py index fa47583e54438..18db997e7c7b1 100644 --- a/src/relooper/fuzzer.py +++ b/src/relooper/fuzzer.py @@ -47,8 +47,18 @@ int main() { char *buffer = (char*)malloc(10*1024*1024); +''' + + if random.randint(0, 1) == 0: + make = False + fast += ''' Relooper::SetOutputBuffer(buffer, 10*1024*1024); ''' + else: + make = True + fast += ''' + Relooper::MakeOutputBuffer(%d); +''' % random.randint(1, 1024*1024*10) for i in range(1, num): slow += ' case %d: print(%d); state = check(); modded = state %% %d\n' % (i, i, len(branches[i])+1) @@ -102,11 +112,11 @@ printf("\\n\\n"); r.Render(); - puts(buffer); + puts(%s); return 1; } -''' +''' % ('buffer' if not make else 'Relooper::GetOutputBuffer()') slow += '}' diff --git a/src/relooper/test.cpp b/src/relooper/test.cpp index 773f6ee496f3b..b4ce669c63454 100644 --- a/src/relooper/test.cpp +++ b/src/relooper/test.cpp @@ -286,5 +286,33 @@ int main() { puts(buffer); } + + if (1) { + Relooper::MakeOutputBuffer(10); + + printf("\n\n-- If pattern, emulated, using MakeOutputBuffer --\n\n"); + + Block *b_a = new Block("// block A\n", NULL); + Block *b_b = new Block("// block B\n", "b_check()"); + Block *b_c = new Block("// block C\n", NULL); + + b_a->AddBranchTo(b_b, "check == 10", "atob();"); + b_a->AddBranchTo(b_c, NULL, "atoc();"); + + b_b->AddBranchTo(b_c, "case 17:", "btoc();"); + b_b->AddBranchTo(b_a, NULL, NULL); + + Relooper r; + r.SetEmulate(true); + r.AddBlock(b_a); + r.AddBlock(b_b); + r.AddBlock(b_c); + + r.Calculate(b_a); + printf("\n\n", "the_var"); + r.Render(); + + puts(buffer); + } } diff --git a/src/relooper/test.txt b/src/relooper/test.txt index 9bdd40939c1ee..cb02b8678f8e0 100644 --- a/src/relooper/test.txt +++ b/src/relooper/test.txt @@ -276,6 +276,51 @@ + label = 1; + L0: while(1) { + switch(label|0) { + case 3: { + // block C + break; + } + case 1: { + // block A + if (check == 10) { + atob(); + label = 2; + continue L0; + } else { + atoc(); + label = 3; + continue L0; + } + break; + } + case 2: { + // block B + switch (b_check()) { + case 17: { + btoc(); + label = 3; + continue L0; + break; + } + default: { + label = 1; + continue L0; + } + } + break; + } + } + } + + + +-- If pattern, emulated, using MakeOutputBuffer -- + + + label = 1; L0: while(1) { switch(label|0) { diff --git a/tools/shared.py b/tools/shared.py index eac4b6588b75b..efca1a850b199 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -345,7 +345,7 @@ def find_temp_directory(): # we re-check sanity when the settings are changed) # We also re-check sanity and clear the cache when the version changes -EMSCRIPTEN_VERSION = '1.8.6' +EMSCRIPTEN_VERSION = '1.8.7' def generate_sanity(): return EMSCRIPTEN_VERSION + '|' + get_llvm_target() + '|' + LLVM_ROOT + '|' + get_clang_version()