diff options
author | Jeff Gilbert <jgilbert@mozilla.com> | 2013-04-25 17:42:53 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2013-05-20 10:48:40 -0700 |
commit | 6210052164cc0f255b45050e08df56e57819a093 (patch) | |
tree | 3c314dbb9e9949cb595e8bd3df180c75b1ba2b6c | |
parent | 6346adec3b5f59415d9eb9650eeefd4120f32763 (diff) |
Adding texEnv emulation to Immediate mode.
-rw-r--r-- | src/library_gl.js | 1434 | ||||
-rw-r--r-- | tests/aniso.c | 16 | ||||
-rw-r--r-- | tests/gl_ps.c | 40 | ||||
-rw-r--r-- | tests/gl_ps_workaround.c | 42 | ||||
-rw-r--r-- | tests/gl_ps_workaround2.c | 40 | ||||
-rw-r--r-- | tests/glbegin_points.c | 44 | ||||
-rw-r--r-- | tests/s3tc.c | 16 | ||||
-rw-r--r-- | tests/s3tc_crunch.c | 16 | ||||
-rw-r--r-- | tests/sdl_fog_density.c | 48 | ||||
-rw-r--r-- | tests/sdl_fog_exp2.c | 48 | ||||
-rw-r--r-- | tests/sdl_fog_linear.c | 48 | ||||
-rw-r--r-- | tests/sdl_fog_negative.c | 48 | ||||
-rw-r--r-- | tests/sdl_fog_simple.c | 51 | ||||
-rw-r--r-- | tests/sdl_ogl.c | 48 | ||||
-rw-r--r-- | tests/sdl_ogl_defaultMatrixMode.c | 46 | ||||
-rw-r--r-- | tests/sdl_ogl_p.c | 44 | ||||
-rw-r--r-- | third_party/lzma.js/lzip/Makefile | 18 |
17 files changed, 1572 insertions, 475 deletions
diff --git a/src/library_gl.js b/src/library_gl.js index ba99eaa8..1f9afd28 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -373,7 +373,7 @@ var LibraryGL = { glGetIntegerv__sig: 'vii', glGetIntegerv: function(name_, p) { - switch(name_) { // Handle a few trivial GLES values + switch(name_) { // Handle a few trivial GLES values case 0x8DFA: // GL_SHADER_COMPILER {{{ makeSetValue('p', '0', '1', 'i32') }}}; return; @@ -507,7 +507,7 @@ var LibraryGL = { glGenTextures__sig: 'vii', glGenTextures: function(n, textures) { for (var i = 0; i < n; i++) { - var id = GL.getNewId(GL.textures); + var id = GL.getNewId(GL.textures); GL.textures[id] = Module.ctx.createTexture(); {{{ makeSetValue('textures', 'i*4', 'id', 'i32') }}}; } @@ -726,7 +726,7 @@ var LibraryGL = { var ptable = GL.uniformTable[program]; if (!ptable) ptable = GL.uniformTable[program] = {}; var id = ptable[name]; - if (id) return id; + if (id) return id; var loc = Module.ctx.getUniformLocation(GL.programs[program], name); if (!loc) return -1; id = GL.getNewId(GL.uniforms); @@ -989,13 +989,16 @@ var LibraryGL = { glBindBuffer__sig: 'vii', glBindBuffer: function(target, buffer) { + var bufferObj = buffer ? GL.buffers[buffer] : null; + if (target == Module.ctx.ARRAY_BUFFER) { GL.currArrayBuffer = buffer; + GL.currArrayBufferObj = bufferObj; } else if (target == Module.ctx.ELEMENT_ARRAY_BUFFER) { GL.currElementArrayBuffer = buffer; } - Module.ctx.bindBuffer(target, buffer ? GL.buffers[buffer] : null); + Module.ctx.bindBuffer(target, bufferObj); }, glVertexAttrib1fv__sig: 'vii', @@ -1275,7 +1278,13 @@ var LibraryGL = { currentVao: null, enabledVertexAttribArrays: {}, // helps with vao cleanups + hasRunInit: false, + init: function() { + if (GLEmulation.hasRunInit) + return; + GLEmulation.hasRunInit = true; + GLEmulation.fogColor = new Float32Array(4); // Add some emulation workarounds @@ -1297,6 +1306,7 @@ var LibraryGL = { 0x80A0: 1 // GL_SAMPLE_COVERAGE }; + var glEnable = _glEnable; _glEnable = function(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 @@ -1307,13 +1317,18 @@ var LibraryGL = { } 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 // it by forwarding to glEnableClientState + /* Actually, let's not, for now. (This sounds exceedingly broken) + * This is in gl_ps_workaround2.c. _glEnableClientState(cap); + */ return; } else if (!(cap in validCapabilities)) { return; } - Module.ctx.enable(cap); + glEnable(cap); }; + + var glDisable = _glDisable; _glDisable = function(cap) { if (GL.immediate.lastRenderer) GL.immediate.lastRenderer.cleanup(); if (cap == 0x0B60 /* GL_FOG */) { @@ -1322,12 +1337,15 @@ var LibraryGL = { } 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 // it by forwarding to glDisableClientState + /* Actually, let's not, for now. (This sounds exceedingly broken) + * This is in gl_ps_workaround2.c. _glDisableClientState(cap); + */ return; } else if (!(cap in validCapabilities)) { return; } - Module.ctx.disable(cap); + glDisable(cap); }; _glIsEnabled = function(cap) { if (cap == 0x0B60 /* GL_FOG */) { @@ -1452,6 +1470,7 @@ var LibraryGL = { var glShaderSource = _glShaderSource; _glShaderSource = function(shader, count, string, length) { var source = GL.getSource(shader, count, string, length); + console.log("glShaderSource: Input: \n" + source); #if GL_DEBUG GL.shaderOriginalSources[shader] = source; #endif @@ -1510,9 +1529,7 @@ var LibraryGL = { } if (source.indexOf('gl_Color') >= 0) { source = 'attribute vec4 a_color; \n' + - 'uniform vec4 u_color; \n' + - 'uniform int u_hasColorAttrib; \n' + - source.replace(/gl_Color/g, '(u_hasColorAttrib > 0 ? a_color : u_color)'); + source.replace(/gl_Color/g, 'a_color'); } if (source.indexOf('gl_Normal') >= 0) { source = 'attribute vec3 a_normal; \n' + @@ -1559,6 +1576,7 @@ var LibraryGL = { #if GL_DEBUG GL.shaderSources[shader] = source; #endif + console.log("glShaderSource: Output: \n" + source); Module.ctx.shaderSource(GL.shaders[shader], source); }; @@ -1706,8 +1724,14 @@ var LibraryGL = { getAttributeFromCapability: function(cap) { var attrib = null; switch (cap) { - case 0x8078: // GL_TEXTURE_COORD_ARRAY case 0x0de1: // GL_TEXTURE_2D - XXX not according to spec, and not in desktop GL, but works in some GLES1.x apparently, so support it +#if ASSERTIONS + var text = "GL_TEXTURE_2D is not a spec-defined capability for gl{Enable,Disable}ClientState." + console.log("Warning: " + text); + assert(false, text); +#endif + // Fall through: + case 0x8078: // GL_TEXTURE_COORD_ARRAY attrib = GL.immediate.TEXTURE0 + GL.immediate.clientActiveTexture; break; case 0x8074: // GL_VERTEX_ARRAY attrib = GL.immediate.VERTEX; break; @@ -1963,7 +1987,888 @@ var LibraryGL = { $GLImmediate__postset: 'GL.immediate.setupFuncs(); Browser.moduleContextCreatedCallbacks.push(function() { GL.immediate.init() });', $GLImmediate__deps: ['$Browser', '$GL', '$GLEmulation'], $GLImmediate: { - MAX_TEXTURES: 7, + MapTreeLib: null, + SpawnMapTreeLib: function() { + /* A naive implementation of a map backed by an array, and accessed by + * naive iteration along the array. (hashmap with only one bucket) + */ + var NaiveListMap = function() { + "use strict"; + var list = []; + + this.Insert = function(key, val) { + if (this.Contains(key|0)) + return false; + + list.push([key, val]); + return true; + }; + + var __Contains_i; + this.Contains = function(key) { + for (__Contains_i = 0; __Contains_i < list.length; ++__Contains_i) + if (list[__Contains_i][0] === key) + return true; + + return false; + }; + + var __Get_i; + this.Get = function(key) { + for (__Get_i = 0; __Get_i < list.length; ++__Get_i) + if (list[__Get_i][0] === key) + return list[__Get_i][1]; + + return undefined; + }; + }; + + /* A tree of map nodes. + Uses `KeyView`s to allow descending the tree without garbage. + Example: { + // Create our map object. + var map = new ObjTreeMap(); + + // Grab the static keyView for the map. + var keyView = map.GetStaticKeyView(); + + // Let's make a map for: + // root: <undefined> + // 1: <undefined> + // 2: <undefined> + // 5: "Three, sir!" + // 3: "Three!" + + // Note how we can chain together `Reset` and `Next` to + // easily descend based on multiple key fragments. + keyView.Reset().Next(1).Next(2).Next(5).Set("Three, sir!"); + keyView.Reset().Next(1).Next(2).Next(3).Set("Three!"); + } + */ + var MapTree = function() { + "use strict"; + + var NLNode = function() { + var map = new NaiveListMap(); + + this.Child = function(keyFrag) { + if (!map.Contains(keyFrag|0)) + map.Insert(keyFrag|0, new NLNode()); + + return map.Get(keyFrag|0); + }; + + this.value = undefined; + this.Get = function() { + return this.value; + }; + + this.Set = function(val) { + this.value = val; + }; + } + + var KeyView = function(root) { + var cur; + + this.Reset = function() { + cur = root; + return this; + }; + this.Reset(); + + this.Next = function(keyFrag) { + cur = cur.Child(keyFrag); + return this; + }; + + this.Get = function() { + return cur.Get(); + }; + + this.Set = function(val) { + cur.Set(val); + }; + }; + + var root; + var staticKeyView; + + this.CreateKeyView = function() { + return new KeyView(root); + } + + this.Clear = function() { + root = new NLNode(); + staticKeyView = this.CreateKeyView(); + }; + this.Clear(); + + this.GetStaticKeyView = function() { + staticKeyView.Reset(); + return staticKeyView; + }; + }; + + // Exports: + return { + Create: function() { + return new MapTree(); + }, + }; + }, + + TexEnvJIT: null, + SpawnTexEnvJIT: function() { + // GL defs: + var GL_TEXTURE0 = 0x84C0; + var GL_TEXTURE_1D = 0x0DE0; + var GL_TEXTURE_2D = 0x0DE1; + var GL_TEXTURE_3D = 0x806f; + var GL_TEXTURE_CUBE_MAP = 0x8513; + var GL_TEXTURE_ENV = 0x2300; + var GL_TEXTURE_ENV_MODE = 0x2200; + var GL_TEXTURE_ENV_COLOR = 0x2201; + var GL_TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515; + var GL_TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516; + var GL_TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517; + var GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518; + var GL_TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519; + var GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A; + + var GL_SRC0_RGB = 0x8580; + var GL_SRC1_RGB = 0x8581; + var GL_SRC2_RGB = 0x8582; + + var GL_SRC0_ALPHA = 0x8588; + var GL_SRC1_ALPHA = 0x8589; + var GL_SRC2_ALPHA = 0x858A; + + var GL_OPERAND0_RGB = 0x8590; + var GL_OPERAND1_RGB = 0x8591; + var GL_OPERAND2_RGB = 0x8592; + + var GL_OPERAND0_ALPHA = 0x8598; + var GL_OPERAND1_ALPHA = 0x8599; + var GL_OPERAND2_ALPHA = 0x859A; + + var GL_COMBINE_RGB = 0x8571; + var GL_COMBINE_ALPHA = 0x8572; + + var GL_RGB_SCALE = 0x8573; + var GL_ALPHA_SCALE = 0x0D1C; + + // env.mode + var GL_ADD = 0x0104; + var GL_BLEND = 0x0BE2; + var GL_REPLACE = 0x1E01; + var GL_MODULATE = 0x2100; + var GL_DECAL = 0x2101; + var GL_COMBINE = 0x8570; + + // env.color/alphaCombiner + //var GL_ADD = 0x0104; + //var GL_REPLACE = 0x1E01; + //var GL_MODULATE = 0x2100; + var GL_SUBTRACT = 0x84E7; + var GL_INTERPOLATE = 0x8575; + + // env.color/alphaSrc + var GL_TEXTURE = 0x1702; + var GL_CONSTANT = 0x8576; + var GL_PRIMARY_COLOR = 0x8577; + var GL_PREVIOUS = 0x8578; + + // env.color/alphaOp + var GL_SRC_COLOR = 0x0300; + var GL_ONE_MINUS_SRC_COLOR = 0x0301; + var GL_SRC_ALPHA = 0x0302; + var GL_ONE_MINUS_SRC_ALPHA = 0x0303; + + var GL_RGB = 0x1907; + var GL_RGBA = 0x1908; + + // Our defs: + var TEXENVJIT_NAMESPACE_PREFIX = "tej_"; + // Not actually constant, as they can be changed between JIT passes: + var TEX_UNIT_UNIFORM_PREFIX = "uTexUnit"; + var TEX_COORD_VARYING_PREFIX = "vTexCoord"; + var PRIM_COLOR_VARYING = "vPrimColor"; + var TEX_MATRIX_UNIFORM_PREFIX = "uTexMatrix"; + + // Static vars: + var s_texUnits = null; //[]; + var s_activeTexture = 0; + + var s_requiredTexUnitsForPass = []; + + // Static funcs: + function Abort(info) { + assert(false, "[TexEnvJIT] ABORT: " + info); + } + + function Abort_NoSupport(info) { + console.log("[TexEnvJIT] ABORT: No support: " + info); + Abort(); + } + + function Abort_Sanity(info) { + Abort("Sanity failure: " + info); + } + + function GenTexUnitSampleExpr(texUnitID) { + var texUnit = s_texUnits[texUnitID]; + var texType = texUnit.GetTexType(); + + var func = null; + switch (texType) { + case GL_TEXTURE_1D: + func = "texture2D"; + break; + case GL_TEXTURE_2D: + func = "texture2D"; + break; + case GL_TEXTURE_3D: + return Abort_NoSupport("No support for 3D textures."); + case GL_TEXTURE_CUBE_MAP: + func = "textureCube"; + break; + default: + return Abort_Sanity("Unknown texType: 0x" + texType.toString(16)); + } + + var texCoordExpr = TEX_COORD_VARYING_PREFIX + texUnitID; + if (TEX_MATRIX_UNIFORM_PREFIX != null) + texCoordExpr = "(" + TEX_MATRIX_UNIFORM_PREFIX + texUnitID + " * " + texCoordExpr + ")"; + + return func + "(" + TEX_UNIT_UNIFORM_PREFIX + texUnitID + ", " + texCoordExpr + ".xy)"; + } + + function GetTypeFromCombineOp(op) { + switch (op) { + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + return "vec3"; + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + return "float"; + } + + return Abort_NoSupport("Unsupported combiner op: 0x" + op.toString(16)); + } + + function GetCurTexUnit() { + return s_texUnits[s_activeTexture]; + } + + function GenCombinerSourceExpr(texUnitID, constantExpr, previousVar, + src, op) + { + var srcExpr = null; + switch (src) { + case GL_TEXTURE: + srcExpr = GenTexUnitSampleExpr(texUnitID); + break; + case GL_CONSTANT: + srcExpr = constantExpr; + break; + case GL_PRIMARY_COLOR: + srcExpr = PRIM_COLOR_VARYING; + break; + case GL_PREVIOUS: + srcExpr = previousVar; + break; + default: + return Abort_NoSupport("Unsupported combiner src: 0x" + src.toString(16)); + } + + var expr = null; + switch (op) { + case GL_SRC_COLOR: + expr = srcExpr + ".rgb"; + break; + case GL_ONE_MINUS_SRC_COLOR: + expr = "(vec3(1.0) - " + srcExpr + ".rgb)"; + break; + case GL_SRC_ALPHA: + expr = srcExpr + ".a"; + break; + case GL_ONE_MINUS_SRC_ALPHA: + expr = "(1.0 - " + srcExpr + ".a)"; + break; + default: + return Abort_NoSupport("Unsupported combiner op: 0x" + op.toString(16)); + } + + return expr; + } + + function ValToFloatLiteral(val) { + if (val == Math.round(val)) + return val + ".0"; + + return val; + } + + + // Classes: + function CTexEnv() { + this.mode = GL_MODULATE; + this.colorCombiner = GL_MODULATE; + this.alphaCombiner = GL_MODULATE; + this.colorScale = 1; + this.alphaScale = 1; + this.envColor = [0, 0, 0, 0]; + + this.colorSrc = [ + GL_TEXTURE, + GL_PREVIOUS, + GL_CONSTANT + ]; + this.alphaSrc = [ + GL_TEXTURE, + GL_PREVIOUS, + GL_CONSTANT + ]; + this.colorOp = [ + GL_SRC_COLOR, + GL_SRC_COLOR, + GL_SRC_ALPHA + ]; + this.alphaOp = [ + GL_SRC_ALPHA, + GL_SRC_ALPHA, + GL_SRC_ALPHA + ]; + + this.TraverseState = function(keyView) { + keyView.Next(this.mode); + keyView.Next(this.colorCombiner); + keyView.Next(this.alphaCombiner); + keyView.Next(this.colorCombiner); + keyView.Next(this.alphaScale); + keyView.Next(this.envColor[0]); + keyView.Next(this.envColor[1]); + keyView.Next(this.envColor[2]); + keyView.Next(this.envColor[3]); + + keyView.Next(this.colorSrc[0]); + keyView.Next(this.colorSrc[1]); + keyView.Next(this.colorSrc[2]); + + keyView.Next(this.alphaSrc[0]); + keyView.Next(this.alphaSrc[1]); + keyView.Next(this.alphaSrc[2]); + + keyView.Next(this.colorOp[0]); + keyView.Next(this.colorOp[1]); + keyView.Next(this.colorOp[2]); + + keyView.Next(this.alphaOp[0]); + keyView.Next(this.alphaOp[1]); + keyView.Next(this.alphaOp[2]); + }; + } + + function CTexUnit() { + this.env = new CTexEnv(); + this.enabled_tex1D = false; + this.enabled_tex2D = false; + this.enabled_tex3D = false; + this.enabled_texCube = false; + + this.TraverseState = function(keyView) { + var texUnitType = this.GetTexType(); + keyView.Next(texUnitType); + if (!texUnitType) + return; + + this.env.TraverseState(keyView); + }; + }; + + // Class impls: + CTexUnit.prototype.Enabled = function() { + return this.GetTexType() != 0; + } + + CTexUnit.prototype.GenPassLines = function(passOutputVar, passInputVar, texUnitID) { + if (!this.Enabled()) { + return ["vec4 " + passOutputVar + " = " + passInputVar + ";"]; + } + + return this.env.GenPassLines(passOutputVar, passInputVar, texUnitID); + } + + CTexUnit.prototype.GetTexType = function() { + if (this.enabled_texCube) + return GL_TEXTURE_CUBE_MAP; + else if (this.enabled_tex3D) + return GL_TEXTURE_3D; + else if (this.enabled_tex2D) + return GL_TEXTURE_2D; + else if (this.enabled_tex1D) + return GL_TEXTURE_1D; + + return 0; + } + + CTexEnv.prototype.GenPassLines = function(passOutputVar, passInputVar, texUnitID) { + switch (this.mode) { + case GL_REPLACE: { + /* RGB: + * Cv = Cs + * Av = Ap // Note how this is different, and that we'll + * need to track the bound texture internalFormat + * to get this right. + * + * RGBA: + * Cv = Cs + * Av = As + */ + return [ + "vec4 " + passOutputVar + " = " + GenTexUnitSampleExpr(texUnitID) + ";", + ]; + } + case GL_ADD: { + /* RGBA: + * Cv = Cp + Cs + * Av = ApAs + */ + var prefix = TEXENVJIT_NAMESPACE_PREFIX + 'env' + texUnitID + "_"; + var texVar = prefix + "tex"; + var colorVar = prefix + "color"; + var alphaVar = prefix + "alpha"; + + return [ + "vec4 " + texVar + " = " + GenTexUnitSampleExpr(texUnitID) + ";", + "vec3 " + colorVar + " = " + passInputVar + ".rgb + " + texVar + ".rgb;", + "float " + alphaVar + " = " + passInputVar + ".a * " + texVar + ".a;", + "vec4 " + passOutputVar + " = vec4(" + colorVar + ", " + alphaVar + ");", + ]; + } + case GL_MODULATE: { + /* RGBA: + * Cv = CpCs + * Av = ApAs + */ + var line = [ + "vec4 " + passOutputVar, + " = ", + passInputVar, + " * ", + GenTexUnitSampleExpr(texUnitID), + ";", + ]; + return [line.join("")]; + } + case GL_DECAL: { + /* RGBA: + * Cv = Cp(1 - As) + CsAs + * Av = Ap + */ + var prefix = TEXENVJIT_NAMESPACE_PREFIX + 'env' + texUnitID + "_"; + var texVar = prefix + "tex"; + var colorVar = prefix + "color"; + var alphaVar = prefix + "alpha"; + + return [ + "vec4 " + texVar + " = " + GenTexUnitSampleExpr(texUnitID) + ";", + [ + "vec3 " + colorVar + " = ", + passInputVar + ".rgb * (1.0 - " + texVar + ".a)", + " + ", + texVar + ".rgb * " + texVar + ".a", + ";" + ].join(""), + "float " + alphaVar + " = " + passInputVar + ".a;", + "vec4 " + passOutputVar + " = vec4(" + colorVar + ", " + alphaVar + ");", + ]; + } + case GL_BLEND: { + /* RGBA: + * Cv = Cp(1 - Cs) + CcCs + * Av = As + */ + var prefix = TEXENVJIT_NAMESPACE_PREFIX + 'env' + texUnitID + "_"; + var texVar = prefix + "tex"; + var colorVar = prefix + "color"; + var alphaVar = prefix + "alpha"; + + return [ + "vec4 " + texVar + " = " + GenTexUnitSampleExpr(texUnitID) + ";", + [ + "vec3 " + colorVar + " = ", + passInputVar + ".rgb * (1.0 - " + texVar + ".rgb)", + " + ", + PRIM_COLOR_VARYING + ".rgb * " + texVar + ".rgb", + ";" + ].join(""), + "float " + alphaVar + " = " + texVar + ".a;", + "vec4 " + passOutputVar + " = vec4(" + colorVar + ", " + alphaVar + ");", + ]; + } + case GL_COMBINE: { + var prefix = TEXENVJIT_NAMESPACE_PREFIX + 'env' + texUnitID + "_"; + var colorVar = prefix + "color"; + var alphaVar = prefix + "alpha"; + var colorLines = this.GenCombinerLines(true, colorVar, + passInputVar, texUnitID, + this.colorCombiner, this.colorSrc, this.colorOp); + var alphaLines = this.GenCombinerLines(false, alphaVar, + passInputVar, texUnitID, + this.alphaCombiner, this.alphaSrc, this.alphaOp); + var line = [ + "vec4 " + passOutputVar, + " = ", + "vec4(", + colorVar + " * " + ValToFloatLiteral(this.colorScale), + ", ", + alphaVar + " * " + ValToFloatLiteral(this.alphaScale), + ")", + ";", + ].join(""); + return [].concat(colorLines, alphaLines, [line]); + } + } + + return Abort_NoSupport("Unsupported TexEnv mode: 0x" + this.mode.toString(16)); + } + + CTexEnv.prototype.GenCombinerLines = function(isColor, outputVar, + passInputVar, texUnitID, + combiner, srcArr, opArr) + { + var argsNeeded = null; + switch (combiner) { + case GL_REPLACE: + argsNeeded = 1; + break; + + case GL_MODULATE: + case GL_ADD: + case GL_SUBTRACT: + argsNeeded = 2; + break; + + case GL_INTERPOLATE: + argsNeeded = 3; + break; + + default: + return Abort_NoSupport("Unsupported combiner: 0x" + combiner.toString(16)); + } + + var constantExpr = [ + "vec4(", + ValToFloatLiteral(this.envColor[0]), + ", ", + ValToFloatLiteral(this.envColor[1]), + ", ", + ValToFloatLiteral(this.envColor[2]), + ", ", + ValToFloatLiteral(this.envColor[3]), + ")", + ].join(""); + var src0Expr = (argsNeeded >= 1) ? GenCombinerSourceExpr(texUnitID, constantExpr, passInputVar, srcArr[0], opArr[0]) + : null; + var src1Expr = (argsNeeded >= 2) ? GenCombinerSourceExpr(texUnitID, constantExpr, passInputVar, srcArr[1], opArr[1]) + : null; + var src2Expr = (argsNeeded >= 3) ? GenCombinerSourceExpr(texUnitID, constantExpr, passInputVar, srcArr[2], opArr[2]) + : null; + + var outputType = isColor ? "vec3" : "float"; + var lines = null; + switch (combiner) { + case GL_REPLACE: { + var line = [ + outputType + " " + outputVar, + " = ", + src0Expr, + ";", + ]; + lines = [line.join("")]; + break; + } + case GL_MODULATE: { + var line = [ + outputType + " " + outputVar + " = ", + src0Expr + " * " + src1Expr, + ";", + ]; + lines = [line.join("")]; + break; + } + case GL_ADD: { + var line = [ + outputType + " " + outputVar + " = ", + src0Expr + " + " + src1Expr, + ";", + ]; + lines = [line.join("")]; + break; + } + case GL_SUBTRACT: { + var line = [ + outputType + " " + outputVar + " = ", + src0Expr + " - " + src1Expr, + ";", + ]; + lines = [line.join("")]; + break; + } + case GL_INTERPOLATE: { + var prefix = TEXENVJIT_NAMESPACE_PREFIX + 'env' + texUnitID + "_"; + var arg2Var = prefix + "colorSrc2"; + var arg2Line = GetTypeFromCombineOp(this.colorOp[2]) + " " + arg2Var + " = " + src2Expr + ";"; + + var line = [ + outputType + " " + outputVar, + " = ", + src0Expr + " * " + arg2Var, + " + ", + src1Expr + " * (1.0 - " + arg2Var + ")", + ";", + ]; + lines = [ + arg2Line, + line.join(""), + ]; + break; + } + + default: + return Abort_Sanity("Unmatched TexEnv.colorCombiner?"); + } + + return lines; + } + + return { + // Exports: + Init: function(gl, specifiedMaxTextureImageUnits) { + var maxTexUnits = 0; + if (specifiedMaxTextureImageUnits) { + maxTexUnits = specifiedMaxTextureImageUnits; + } else if (gl) { + maxTexUnits = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS); + } + + assert(maxTexUnits > 0); + + s_texUnits = []; + for (var i = 0; i < maxTexUnits; i++) { + s_texUnits.push(new CTexUnit()); + } + }, + + SetGLSLVars: function(uTexUnitPrefix, vTexCoordPrefix, vPrimColor, uTexMatrixPrefix) { + TEX_UNIT_UNIFORM_PREFIX = uTexUnitPrefix; + TEX_COORD_VARYING_PREFIX = vTexCoordPrefix; + PRIM_COLOR_VARYING = vPrimColor; + TEX_MATRIX_UNIFORM_PREFIX = uTexMatrixPrefix; + }, + + GenAllPassLines: function(resultDest, indentSize) { + indentSize = indentSize || 0; + + s_requiredTexUnitsForPass.length = 0; // Clear the list. + var lines = []; + var lastPassVar = PRIM_COLOR_VARYING; + for (var i = 0; i < s_texUnits.length; i++) { + if (!s_texUnits[i].Enabled()) + continue; + + s_requiredTexUnitsForPass.push(i); + + var prefix = TEXENVJIT_NAMESPACE_PREFIX + 'env' + i + "_"; + var passOutputVar = prefix + "result"; + + var newLines = s_texUnits[i].GenPassLines(passOutputVar, lastPassVar, i); + lines = lines.concat(newLines, [""]); + + lastPassVar = passOutputVar; + } + lines.push(resultDest + " = " + lastPassVar + ";"); + + var indent = ""; + for (var i = 0; i < indentSize; i++) + indent += " "; + + var output = indent + lines.join("\n" + indent); + + return output; + }, + + GetUsedTexUnitList: function() { + return s_requiredTexUnitsForPass; + }, + + TraverseState: function(keyView) { + for (var i = 0; i < s_texUnits.length; i++) { + var texUnit = s_texUnits[i]; + var enabled = texUnit.Enabled(); + keyView.Next(enabled); + if (enabled) { + texUnit.TraverseState(keyView); + } + } + }, + + GetTexUnitType: function(texUnitID) { + assert(texUnitID >= 0 && + texUnitID < s_texUnits.length); + + return s_texUnits[texUnitID].GetTexType(); + }, + + // Hooks: + Hook_ActiveTexture: function(texture) { + s_activeTexture = texture - GL_TEXTURE0; + }, + + Hook_Enable: function(cap) { + var cur = GetCurTexUnit(); + switch (cap) { + case GL_TEXTURE_1D: + cur.enabled_tex1D = true; + break; + case GL_TEXTURE_2D: + cur.enabled_tex2D = true; + break; + case GL_TEXTURE_3D: + cur.enabled_tex3D = true; + break; + case GL_TEXTURE_CUBE_MAP: + cur.enabled_texCube = true; + break; + } + }, + + Hook_Disable: function(cap) { + var cur = GetCurTexUnit(); + switch (cap) { + case GL_TEXTURE_1D: + cur.enabled_tex1D = false; + break; + case GL_TEXTURE_2D: + cur.enabled_tex2D = false; + break; + case GL_TEXTURE_3D: + cur.enabled_tex3D = false; + break; + case GL_TEXTURE_CUBE_MAP: + cur.enabled_texCube = false; + break; + } + }, + + Hook_TexEnvf: function(target, pname, param) { + if (target != GL_TEXTURE_ENV) + return; + + var env = GetCurTexUnit().env; + switch (pname) { + case GL_RGB_SCALE: + env.colorScale = param; + break; + case GL_ALPHA_SCALE: + env.alphaScale = param; + break; + + default: + Module.printErr('WARNING: Unhandled `pname` in call to `glTexEnvf`.'); + } + }, + + Hook_TexEnvi: function(target, pname, param) { + if (target != GL_TEXTURE_ENV) + return; + + var env = GetCurTexUnit().env; + switch (pname) { + case GL_TEXTURE_ENV_MODE: + env.mode = param; + break; + + case GL_COMBINE_RGB: + env.colorCombiner = param; + break; + case GL_COMBINE_ALPHA: + env.alphaCombiner = param; + break; + + case GL_SRC0_RGB: + env.colorSrc[0] = param; |