aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Gilbert <jgilbert@mozilla.com>2013-04-25 17:42:53 -0700
committerAlon Zakai <alonzakai@gmail.com>2013-05-20 10:48:40 -0700
commit6210052164cc0f255b45050e08df56e57819a093 (patch)
tree3c314dbb9e9949cb595e8bd3df180c75b1ba2b6c
parent6346adec3b5f59415d9eb9650eeefd4120f32763 (diff)
Adding texEnv emulation to Immediate mode.
-rw-r--r--src/library_gl.js1434
-rw-r--r--tests/aniso.c16
-rw-r--r--tests/gl_ps.c40
-rw-r--r--tests/gl_ps_workaround.c42
-rw-r--r--tests/gl_ps_workaround2.c40
-rw-r--r--tests/glbegin_points.c44
-rw-r--r--tests/s3tc.c16
-rw-r--r--tests/s3tc_crunch.c16
-rw-r--r--tests/sdl_fog_density.c48
-rw-r--r--tests/sdl_fog_exp2.c48
-rw-r--r--tests/sdl_fog_linear.c48
-rw-r--r--tests/sdl_fog_negative.c48
-rw-r--r--tests/sdl_fog_simple.c51
-rw-r--r--tests/sdl_ogl.c48
-rw-r--r--tests/sdl_ogl_defaultMatrixMode.c46
-rw-r--r--tests/sdl_ogl_p.c44
-rw-r--r--third_party/lzma.js/lzip/Makefile18
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;