From 6210052164cc0f255b45050e08df56e57819a093 Mon Sep 17 00:00:00 2001 From: Jeff Gilbert Date: Thu, 25 Apr 2013 17:42:53 -0700 Subject: [PATCH] Adding texEnv emulation to Immediate mode. --- src/library_gl.js | 1436 ++++++++++++++++++++++++++--- tests/aniso.c | 16 +- tests/gl_ps.c | 40 +- tests/gl_ps_workaround.c | 42 +- tests/gl_ps_workaround2.c | 40 +- tests/glbegin_points.c | 44 +- tests/s3tc.c | 16 +- tests/s3tc_crunch.c | 16 +- tests/sdl_fog_density.c | 48 +- tests/sdl_fog_exp2.c | 48 +- tests/sdl_fog_linear.c | 48 +- tests/sdl_fog_negative.c | 48 +- tests/sdl_fog_simple.c | 51 +- tests/sdl_ogl.c | 48 +- tests/sdl_ogl_defaultMatrixMode.c | 46 +- tests/sdl_ogl_p.c | 44 +- third_party/lzma.js/lzip/Makefile | 18 +- 17 files changed, 1573 insertions(+), 476 deletions(-) diff --git a/src/library_gl.js b/src/library_gl.js index ba99eaa80..1f9afd28a 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: + // 1: + // 2: + // 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; + break; + case GL_SRC1_RGB: + env.colorSrc[1] = param; + break; + case GL_SRC2_RGB: + env.colorSrc[2] = param; + break; + + case GL_SRC0_ALPHA: + env.alphaSrc[0] = param; + break; + case GL_SRC1_ALPHA: + env.alphaSrc[1] = param; + break; + case GL_SRC2_ALPHA: + env.alphaSrc[2] = param; + break; + + case GL_OPERAND0_RGB: + env.colorOp[0] = param; + break; + case GL_OPERAND1_RGB: + env.colorOp[1] = param; + break; + case GL_OPERAND2_RGB: + env.colorOp[2] = param; + break; + + case GL_OPERAND0_ALPHA: + env.alphaOp[0] = param; + break; + case GL_OPERAND1_ALPHA: + env.alphaOp[1] = param; + break; + case GL_OPERAND2_ALPHA: + env.alphaOp[2] = param; + break; + + 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 `glTexEnvi`.'); + } + }, + + Hook_TexEnvfv: function(target, pname, params) { + if (target != GL_TEXTURE_ENV) + return; + + var env = GetCurTexUnit().env; + switch (pname) { + case GL_TEXTURE_ENV_COLOR: { + for (var i = 0; i < 4; i++) { + var param = {{{ makeGetValue('params', 'i*4', 'float') }}}; + env.envColor[i] = param; + } + break + } + default: + Module.printErr('WARNING: Unhandled `pname` in call to `glTexEnvfv`.'); + } + }, + }; + }, // Vertex and index data vertexData: null, // current vertex data. either tempData (glBegin etc.) or a view into the heap (gl*Pointer). Default view is F32 @@ -1974,7 +2879,6 @@ var LibraryGL = { mode: -1, rendererCache: null, - rendererCacheItemTemplate: [null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null], // 16 nulls rendererComponents: [], // small cache for calls inside glBegin/end. counts how many times the element was seen rendererComponentPointer: 0, // next place to start a glBegin/end component lastRenderer: null, // used to avoid cleaning up and re-preparing the same renderer @@ -1988,6 +2892,7 @@ var LibraryGL = { currentMatrix: 'm', // default is modelview tempMatrix: null, matricesModified: false, + useTextureMatrix: false, // Clientside attributes VERTEX: 0, @@ -2000,8 +2905,8 @@ var LibraryGL = { TEXTURE4: 7, TEXTURE5: 8, TEXTURE6: 9, - NUM_ATTRIBUTES: 10, - NUM_TEXTURES: 7, + NUM_ATTRIBUTES: 10, // Overwritten in init(). + MAX_TEXTURES: 7, // Overwritten in init(). totalEnabledClientAttributes: 0, enabledClientAttributes: [0, 0], @@ -2010,6 +2915,8 @@ var LibraryGL = { modifiedClientAttributes: false, clientActiveTexture: 0, clientColor: null, + usedTexUnitList: [], + fixedFunctionProgram: null, setClientAttribute: function(name, size, type, stride, pointer) { var attrib = this.clientAttributes[name]; @@ -2042,7 +2949,9 @@ var LibraryGL = { if (!this.rendererComponents[name]) { this.rendererComponents[name] = 1; #if ASSERTIONS - assert(!this.enabledClientAttributes[name]); // cannot get mixed up with this, for example we will disable this later + if (this.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); @@ -2062,19 +2971,18 @@ 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 cacheItem = GL.immediate.rendererCache; + var cacheMap = GL.immediate.rendererCache; var temp; + var keyView = cacheMap.GetStaticKeyView().Reset(); + + // By attrib state: for (var i = 0; i < attributes.length; i++) { var attribute = attributes[i]; - temp = cacheItem[attribute.name]; - cacheItem = temp ? temp : (cacheItem[attribute.name] = GL.immediate.rendererCacheItemTemplate.slice()); - temp = cacheItem[attribute.size]; - cacheItem = temp ? temp : (cacheItem[attribute.size] = GL.immediate.rendererCacheItemTemplate.slice()); - var typeIndex = attribute.type - GL.byteSizeByTypeRoot; // ensure it starts at 0 to keep the cache items dense - temp = cacheItem[typeIndex]; - cacheItem = temp ? temp : (cacheItem[typeIndex] = GL.immediate.rendererCacheItemTemplate.slice()); + keyView.Next(attribute.name).Next(attribute.size).Next(attribute.type); } - var fogParam; + + // By fog state: + var fogParam = 0; if (GLEmulation.fogEnabled) { switch (GLEmulation.fogMode) { case 0x0801: // GL_EXP2 @@ -2087,33 +2995,40 @@ var LibraryGL = { fogParam = 3; break; } - } else { - fogParam = 0; } - temp = cacheItem[fogParam]; - cacheItem = temp ? temp : (cacheItem[fogParam] = GL.immediate.rendererCacheItemTemplate.slice()); - if (GL.currProgram) { // Note the order here; this one is last, and optional. Note that we cannot ensure it is dense, sadly - temp = cacheItem[GL.currProgram]; - cacheItem = temp ? temp : (cacheItem[GL.currProgram] = GL.immediate.rendererCacheItemTemplate.slice()); + keyView.Next(fogParam); + + // By cur program: + keyView.Next(GL.currProgram); + if (!GL.currProgram) { + GL.immediate.TexEnvJIT.TraverseState(keyView); } - if (!cacheItem.renderer) { + + // If we don't already have it, create it. + if (!keyView.Get()) { #if GL_DEBUG Module.printErr('generating renderer for ' + JSON.stringify(attributes)); #endif - cacheItem.renderer = this.createRenderer(); + keyView.Set(this.createRenderer()); } - return cacheItem.renderer; + return keyView.Get(); }, createRenderer: function(renderer) { var useCurrProgram = !!GL.currProgram; var hasTextures = false, textureSizes = [], textureTypes = []; - for (var i = 0; i < GL.immediate.NUM_TEXTURES; i++) { - if (GL.immediate.enabledClientAttributes[GL.immediate.TEXTURE0 + i]) { - textureSizes[i] = GL.immediate.clientAttributes[GL.immediate.TEXTURE0 + i].size; - textureTypes[i] = GL.immediate.clientAttributes[GL.immediate.TEXTURE0 + i].type; - hasTextures = true; + for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) { + var texAttribName = GL.immediate.TEXTURE0 + i; + if (!GL.immediate.enabledClientAttributes[texAttribName]) + continue; + + if (!useCurrProgram) { + assert(GL.immediate.TexEnvJIT.GetTexUnitType(i) != 0, "GL_TEXTURE" + i + " coords are supplied, but that texture unit is disabled in the fixed-function pipeline."); } + + textureSizes[i] = GL.immediate.clientAttributes[texAttribName].size; + textureTypes[i] = GL.immediate.clientAttributes[texAttribName].type; + hasTextures = true; } var positionSize = GL.immediate.clientAttributes[GL.immediate.VERTEX].size; var positionType = GL.immediate.clientAttributes[GL.immediate.VERTEX].type; @@ -2129,6 +3044,13 @@ var LibraryGL = { } var ret = { init: function() { + // For fixed-function shader generation. + var uTexUnitPrefix = 'u_texUnit'; + var aTexCoordPrefix = 'a_texCoord'; + var vTexCoordPrefix = 'v_texCoord'; + var vPrimColor = 'v_color'; + var uTexMatrixPrefix = GL.immediate.useTextureMatrix ? 'u_textureMatrix' : null; + if (useCurrProgram) { if (GL.shaderInfos[GL.programShaders[GL.currProgram][0]].type == Module.ctx.VERTEX_SHADER) { this.vertexShader = GL.shaders[GL.programShaders[GL.currProgram][0]]; @@ -2138,13 +3060,12 @@ var LibraryGL = { this.fragmentShader = GL.shaders[GL.programShaders[GL.currProgram][0]]; } this.program = GL.programs[GL.currProgram]; + this.usedTexUnitList = []; } else { // IMPORTANT NOTE: If you parameterize the shader source based on any runtime values // in order to create the least expensive shader possible based on the features being // used, you should also update the code in the beginning of getRenderer to make sure // that you cache the renderer based on the said parameters. - this.vertexShader = Module.ctx.createShader(Module.ctx.VERTEX_SHADER); - var zero = positionSize == 2 ? '0, ' : ''; if (GLEmulation.fogEnabled) { switch (GLEmulation.fogMode) { case 0x0801: // GL_EXP2 @@ -2161,47 +3082,94 @@ var LibraryGL = { break; } } - Module.ctx.shaderSource(this.vertexShader, 'attribute vec' + positionSize + ' a_position; \n' + - 'attribute vec2 a_texCoord0; \n' + - (hasTextures ? 'varying vec2 v_texCoord; \n' : '') + - 'varying vec4 v_color; \n' + - (colorSize ? 'attribute vec4 a_color; \n': 'uniform vec4 u_color; \n') + - (GLEmulation.fogEnabled ? 'varying float v_fogFragCoord; \n' : '') + - 'uniform mat4 u_modelView; \n' + - 'uniform mat4 u_projection; \n' + - 'void main() \n' + - '{ \n' + - ' vec4 ecPosition = (u_modelView * vec4(a_position, ' + zero + '1.0)); \n' + // eye-coordinate position - ' gl_Position = u_projection * ecPosition; \n' + - (hasTextures ? 'v_texCoord = a_texCoord0; \n' : '') + - (colorSize ? 'v_color = a_color; \n' : 'v_color = u_color; \n') + - (GLEmulation.fogEnabled ? 'v_fogFragCoord = abs(ecPosition.z);\n' : '') + - '} \n'); + + GL.immediate.TexEnvJIT.SetGLSLVars(uTexUnitPrefix, vTexCoordPrefix, vPrimColor, uTexMatrixPrefix); + var fsTexEnvPass = GL.immediate.TexEnvJIT.GenAllPassLines('gl_FragColor', 2); + + var texUnitAttribList = ''; + var texUnitVaryingList = ''; + var texUnitUniformList = ''; + var vsTexCoordInits = ''; + this.usedTexUnitList = GL.immediate.TexEnvJIT.GetUsedTexUnitList(); + for (var i = 0; i < this.usedTexUnitList.length; i++) { + var texUnit = this.usedTexUnitList[i]; + texUnitAttribList += 'attribute vec4 ' + aTexCoordPrefix + texUnit + ';\n'; + texUnitVaryingList += 'varying vec4 ' + vTexCoordPrefix + texUnit + ';\n'; + texUnitUniformList += 'uniform sampler2D ' + uTexUnitPrefix + texUnit + ';\n'; + vsTexCoordInits += ' ' + vTexCoordPrefix + texUnit + ' = ' + aTexCoordPrefix + texUnit + ';\n'; + + if (GL.immediate.useTextureMatrix) + texUnitUniformList += 'uniform mat4 ' + uTexMatrixPrefix + texUnit + ';\n'; + } + + var vsFogVaryingInit = null; + if (GLEmulation.fogEnabled) + vsFogVaryingInit = ' v_fogFragCoord = abs(ecPosition.z);\n'; + + + var vsSource = [ + 'attribute vec4 a_position;', + 'attribute vec4 a_color;', + 'varying vec4 v_color;', + texUnitAttribList, + texUnitVaryingList, + (GLEmulation.fogEnabled ? 'varying float v_fogFragCoord;' : null), + 'uniform mat4 u_modelView;', + 'uniform mat4 u_projection;', + 'void main()', + '{', + ' vec4 ecPosition = u_modelView * a_position;', // eye-coordinate position + ' gl_Position = u_projection * ecPosition;', + ' v_color = a_color;', + vsTexCoordInits, + vsFogVaryingInit, + '}', + '' + ].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); + var fogHeaderIfNeeded = null; + if (GLEmulation.fogEnabled) { + fogHeaderIfNeeded = [ + '', + 'varying float v_fogFragCoord; ', + 'uniform vec4 u_fogColor; ', + 'uniform float u_fogEnd; ', + 'uniform float u_fogScale; ', + 'uniform float u_fogDensity; ', + 'float ffog(in float ecDistance) { ', + fogFormula, + ' fog = clamp(fog, 0.0, 1.0); ', + ' return fog; ', + '}', + '', + ].join("\n"); + } + + var fogPass = null; + if (GLEmulation.fogEnabled) { + fogPass = 'gl_FragColor = vec4(mix(u_fogColor.rgb, gl_FragColor.rgb, ffog(v_fogFragCoord)), gl_FragColor.a);\n'; + } + + var fsSource = [ + 'precision mediump float;', + texUnitVaryingList, + texUnitUniformList, + 'varying vec4 v_color;', + fogHeaderIfNeeded, + 'void main()', + '{', + fsTexEnvPass, + fogPass, + '}', + '' + ].join("\n").replace(/\n\n+/g, '\n'); + this.fragmentShader = Module.ctx.createShader(Module.ctx.FRAGMENT_SHADER); - Module.ctx.shaderSource(this.fragmentShader, 'precision mediump float; \n' + - 'varying vec2 v_texCoord; \n' + - 'uniform sampler2D u_texture; \n' + - 'varying vec4 v_color; \n' + - (GLEmulation.fogEnabled ? ( - 'varying float v_fogFragCoord; \n' + - 'uniform vec4 u_fogColor; \n' + - 'uniform float u_fogEnd; \n' + - 'uniform float u_fogScale; \n' + - 'uniform float u_fogDensity; \n' + - 'float ffog(in float ecDistance) { \n' + - fogFormula + - ' fog = clamp(fog, 0.0, 1.0); \n' + - ' return fog; \n' + - '} \n' - ) : '') + - 'void main() \n' + - '{ \n' + - (hasTextures ? 'gl_FragColor = v_color * texture2D( u_texture, v_texCoord );\n' : - 'gl_FragColor = v_color;\n') + - (GLEmulation.fogEnabled ? 'gl_FragColor = vec4(mix(u_fogColor.rgb, gl_FragColor.rgb, ffog(v_fogFragCoord)), gl_FragColor.a); \n' : '') + - '} \n'); + Module.ctx.shaderSource(this.fragmentShader, fsSource); Module.ctx.compileShader(this.fragmentShader); this.program = Module.ctx.createProgram(); @@ -2212,12 +3180,36 @@ var LibraryGL = { } this.positionLocation = Module.ctx.getAttribLocation(this.program, 'a_position'); + this.texCoordLocations = []; - for (var i = 0; i < textureSizes.length; i++) { - if (textureSizes[i]) { + + for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) { + if (!GL.immediate.enabledClientAttributes[GL.immediate.TEXTURE0 + i]) { + this.texCoordLocations[i] = -1; + continue; + } + + if (useCurrProgram) { this.texCoordLocations[i] = Module.ctx.getAttribLocation(this.program, 'a_texCoord' + i); + } else { + this.texCoordLocations[i] = Module.ctx.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); + { + 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); + } + } + Module.ctx.useProgram(prevBoundProg); + } + this.textureMatrixLocations = []; for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) { this.textureMatrixLocations[i] = Module.ctx.getUniformLocation(this.program, 'u_textureMatrix' + i); @@ -2225,16 +3217,12 @@ var LibraryGL = { this.colorLocation = Module.ctx.getAttribLocation(this.program, 'a_color'); this.normalLocation = Module.ctx.getAttribLocation(this.program, 'a_normal'); - this.textureLocation = Module.ctx.getUniformLocation(this.program, 'u_texture'); // only for immediate mode with no shaders, so only one is enough this.modelViewLocation = Module.ctx.getUniformLocation(this.program, 'u_modelView'); this.projectionLocation = Module.ctx.getUniformLocation(this.program, 'u_projection'); - this.hasColorAttribLocation = Module.ctx.getUniformLocation(this.program, 'u_hasColorAttrib'); - this.colorUniformLocation = Module.ctx.getUniformLocation(this.program, 'u_color'); this.hasTextures = hasTextures; - this.hasColorAttrib = colorSize > 0 && this.colorLocation >= 0; - this.hasColorUniform = !!this.colorUniformLocation; this.hasNormal = normalSize > 0 && this.normalLocation >= 0; + this.hasColor = (this.colorLocation === 0) || this.colorLocation > 0; this.floatType = Module.ctx.FLOAT; // minor optimization @@ -2294,6 +3282,7 @@ var LibraryGL = { if (!GL.currProgram) { Module.ctx.useProgram(this.program); + GL.immediate.fixedFunctionProgram = this.program; } if (this.modelViewLocation) Module.ctx.uniformMatrix4fv(this.modelViewLocation, false, GL.immediate.matrix['m']); @@ -2305,11 +3294,24 @@ var LibraryGL = { GL.immediate.stride, clientAttributes[GL.immediate.VERTEX].offset); Module.ctx.enableVertexAttribArray(this.positionLocation); if (this.hasTextures) { - for (var i = 0; i < textureSizes.length; i++) { - if (textureSizes[i] && this.texCoordLocations[i] >= 0) { - Module.ctx.vertexAttribPointer(this.texCoordLocations[i], textureSizes[i], textureTypes[i], false, - GL.immediate.stride, clientAttributes[GL.immediate.TEXTURE0 + i].offset); - Module.ctx.enableVertexAttribArray(this.texCoordLocations[i]); + //for (var i = 0; i < this.usedTexUnitList.length; i++) { + // var texUnitID = this.usedTexUnitList[i]; + for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) { + var texUnitID = i; + var attribLoc = this.texCoordLocations[texUnitID]; + if (attribLoc === undefined) + continue; + if (attribLoc < 0) + continue; + + if (texUnitID < textureSizes.length && textureSizes[texUnitID]) { + Module.ctx.vertexAttribPointer(attribLoc, textureSizes[texUnitID], textureTypes[texUnitID], false, + GL.immediate.stride, GL.immediate.clientAttributes[GL.immediate.TEXTURE0 + texUnitID].offset); + Module.ctx.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); } } for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) { @@ -2318,26 +3320,19 @@ var LibraryGL = { } } } - if (this.hasColorAttrib) { + if (colorSize) { Module.ctx.vertexAttribPointer(this.colorLocation, colorSize, colorType, true, GL.immediate.stride, clientAttributes[GL.immediate.COLOR].offset); Module.ctx.enableVertexAttribArray(this.colorLocation); - Module.ctx.uniform1i(this.hasColorAttribLocation, 1); - } else if (this.hasColorUniform) { - Module.ctx.uniform1i(this.hasColorAttribLocation, 0); - Module.ctx.uniform4fv(this.colorUniformLocation, GL.immediate.clientColor); + } else if (this.hasColor) { + Module.ctx.disableVertexAttribArray(this.colorLocation); + Module.ctx.vertexAttrib4fv(this.colorLocation, GL.immediate.clientColor); } if (this.hasNormal) { Module.ctx.vertexAttribPointer(this.normalLocation, normalSize, normalType, true, GL.immediate.stride, clientAttributes[GL.immediate.NORMAL].offset); Module.ctx.enableVertexAttribArray(this.normalLocation); } - if (!useCurrProgram) { // otherwise, the user program will set the sampler2D binding and uniform itself - var texture = Module.ctx.getParameter(Module.ctx.TEXTURE_BINDING_2D); - Module.ctx.activeTexture(Module.ctx.TEXTURE0); - Module.ctx.bindTexture(Module.ctx.TEXTURE_2D, texture); - Module.ctx.uniform1i(this.textureLocation, 0); - } if (this.hasFog) { if (this.fogColorLocation) Module.ctx.uniform4fv(this.fogColorLocation, GLEmulation.fogColor); if (this.fogEndLocation) Module.ctx.uniform1f(this.fogEndLocation, GLEmulation.fogEnd); @@ -2355,7 +3350,7 @@ var LibraryGL = { } } } - if (this.hasColorAttrib) { + if (this.hasColor) { Module.ctx.disableVertexAttribArray(this.colorLocation); } if (this.hasNormal) { @@ -2389,7 +3384,7 @@ var LibraryGL = { Module.ctx.drawArrays(mode, first, count); return; } - GL.immediate.prepareClientAttributes(count, false); + GL.immediate.prepareClientAttributes(first, count, false); GL.immediate.mode = mode; if (!GL.currArrayBuffer) { GL.immediate.vertexData = {{{ makeHEAPView('F32', 'GL.immediate.vertexPointer', 'GL.immediate.vertexPointer + (first+count)*GL.immediate.stride') }}}; // XXX assuming float @@ -2408,7 +3403,10 @@ var LibraryGL = { if (!GL.currElementArrayBuffer) { assert(type == Module.ctx.UNSIGNED_SHORT); // We can only emulate buffers of this kind, for now } - GL.immediate.prepareClientAttributes(count, false); +#if ASSERTIONS + console.log("DrawElements doesn't actually prepareClientAttributes properly."); +#endif + GL.immediate.prepareClientAttributes(0, count, false); GL.immediate.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 @@ -2418,6 +3416,75 @@ var LibraryGL = { GL.immediate.flush(count, 0, indices); GL.immediate.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; + + GL.immediate.TexEnvJIT = GL.immediate.SpawnTexEnvJIT(); + GL.immediate.SpawnTexEnvJIT = null; + + GL.immediate.setupHooks(); + }, + + setupHooks: function() { + if (!GLEmulation.hasRunInit) + GLEmulation.init(); + + var glActiveTexture = _glActiveTexture; + _glActiveTexture = function(texture) { + GL.immediate.TexEnvJIT.Hook_ActiveTexture(texture); + glActiveTexture(texture); + }; + + var glEnable = _glEnable; + _glEnable = function(cap) { + GL.immediate.TexEnvJIT.Hook_Enable(cap); + glEnable(cap); + }; + var glDisable = _glDisable; + _glDisable = function(cap) { + GL.immediate.TexEnvJIT.Hook_Disable(cap); + glDisable(cap); + }; + + var glTexEnvf = (typeof(_glTexEnvf) != 'undefined') ? _glTexEnvf : function(){}; + _glTexEnvf = function(target, pname, param) { + GL.immediate.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(target, pname, param) { + GL.immediate.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(target, pname, param) { + GL.immediate.TexEnvJIT.Hook_TexEnvfv(target, pname, param); + // Don't call old func, since we are the implementor. + //glTexEnvfv(target, pname, param); + }; + + var glGetIntegerv = _glGetIntegerv; + _glGetIntegerv = function(pname, params) { + 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); + if (cur == GL.immediate.fixedFunctionProgram) { + // Pretend we're not using a program. + {{{ makeSetValue('params', '0', '0', 'i32') }}}; + return; + } + break; + } + } + glGetIntegerv(pname, params); + }; }, // Main functions @@ -2428,6 +3495,15 @@ 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); + + GL.immediate.MAX_TEXTURES = Module.ctx.getParameter(Module.ctx.MAX_TEXTURE_IMAGE_UNITS); + GL.immediate.NUM_ATTRIBUTES = GL.immediate.TEXTURE0 + GL.immediate.MAX_TEXTURES; + GL.immediate.clientAttributes = []; + for (var i = 0; i < GL.immediate.NUM_ATTRIBUTES; i++) { + GL.immediate.clientAttributes.push({}); + } + this.matrixStack['m'] = []; this.matrixStack['p'] = []; for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) { @@ -2445,7 +3521,7 @@ var LibraryGL = { } // Renderer cache - this.rendererCache = this.rendererCacheItemTemplate.slice(); + this.rendererCache = this.MapTreeLib.Create(); // Buffers for data this.tempData = new Float32Array(GL.MAX_TEMP_BUFFER_SIZE >> 2); @@ -2462,7 +3538,7 @@ var LibraryGL = { // Modifies liveClientAttributes, stride, vertexPointer, vertexCounter // count: number of elements we will draw // beginEnd: whether we are drawing the results of a begin/end block - prepareClientAttributes: function(count, beginEnd) { + prepareClientAttributes: function(drawStart, drawCount, beginEnd) { // 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. @@ -2478,17 +3554,34 @@ var LibraryGL = { if (GL.immediate.enabledClientAttributes[i]) attributes.push(GL.immediate.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; + + var needsRepack = false; + if (beginEnd) { + needsRepack = true; + } else { + stride = null; + for (var i = 0; i < attributes.length; i++) { + var attribute = attributes[i]; + if (!attribute) + break; + if (stride === null) + stride = attribute.stride; + + if (attribute.stride != stride) { +#if ASSERTIONS + console.log("Perf warning: Stride mismatch in `prepareClientAttributes()`."); +#endif + needsRepack = true; + break; + } + } + + if (!stride) + needsRepack = true; } - if (multiStrides) stride = 0; // we will need to restride - var bytes = 0; // total size in bytes - if (!stride && !beginEnd) { + + var vertCount = drawStart + drawCount; + if (needsRepack) { // 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 @@ -2501,57 +3594,76 @@ var LibraryGL = { #if ASSERTIONS assert(start % 4 == 0); #endif + var pos = 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; + + attribute.offset = pos; + pos += size; } + + // Alright, we know what our new stride will be. + var newStride = pos; + #if ASSERTIONS - assert(count*bytes <= GL.MAX_TEMP_BUFFER_SIZE); + assert(vertCount*newStride <= 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]; + if (!attribute) + break; + + var size = attribute.size * GL.byteSizeByType[attribute.type - GL.byteSizeByTypeRoot]; + if (size % 4 != 0) size += 4 - (size % 4); // align everything + // Note that we don't have to assert here, since at worst, we + // fill out dword-padded space with some garbage. + + assert(attribute.pointer % 4 == 0, "Error: We assume attrib.pointer is dword-aligned"); + var dwordStart = attribute.pointer / 4; + var dwordCount = size / 4; + for (var j = 0; j < vertCount; j++) { + for (var k = 0; k < dwordCount; k++) { // copy in chunks of 4 bytes, our alignment makes this possible + HEAP32[((start + attribute.offset + newStride*j)>>2) + k] = HEAP32[dwordStart + j*dwordCount + k]; } } attribute.pointer = start + attribute.offset; } + + stride = newStride; } else { // normal situation, everything is strided and in the same buffer +#if ASSERTIONS + assert(!beginEnd, "Immediate mode should not get here."); +#endif + // This will always give us the proper start, as we sorted + // `attributes` by `.pointer` earlier. + start = GL.currArrayBuffer ? 0 : attributes[0].pointer; + 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 - assert((attribute.offset - bytes)%4 == 0); // XXX assuming 4-alignment - 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 - } - assert(beginEnd || bytes <= stride); // if not begin-end, explicit stride should make sense with total byte size - if (bytes < stride) { // ensure the size is that of the stride - bytes = stride; - } - } - GL.immediate.stride = bytes; + if (!attribute) + break; - if (!beginEnd) { - bytes *= count; - if (!GL.currArrayBuffer) { - GL.immediate.vertexPointer = start; + attribute.offset = attribute.pointer - start; +#if ASSERTIONS + var size = attribute.size * GL.byteSizeByType[attribute.type - GL.byteSizeByTypeRoot]; + assert(attribute.offset + size <= stride); +#endif } - GL.immediate.vertexCounter = bytes / 4; // XXX assuming float } + GL.immediate.stride = stride; + + if (!beginEnd && !GL.currArrayBuffer) { + // This is only used in this case. + GL.immediate.vertexPointer = start; + } + GL.immediate.vertexCounter = drawCount; }, flush: function(numProvidedIndexes, startIndex, ptr) { @@ -2564,8 +3676,8 @@ 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; // XXX assuming float - assert(numVertexes % 1 == 0); + var numVertexes = this.vertexCounter; + assert(numVertexes % 1 == 0, "`numVertexes` must be an integer."); var emulatedElementArrayBuffer = false; var numIndexes = 0; @@ -2629,6 +3741,16 @@ var LibraryGL = { glBegin__deps: ['$GLImmediateSetup'], glBegin: function(mode) { + // Push the old state: + GL.immediate.enabledClientAttributes_preBegin = GL.immediate.enabledClientAttributes; + GL.immediate.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({}); + } + GL.immediate.mode = mode; GL.immediate.vertexCounter = 0; var components = GL.immediate.rendererComponents = []; @@ -2640,12 +3762,18 @@ var LibraryGL = { }, glEnd: function() { - GL.immediate.prepareClientAttributes(GL.immediate.rendererComponents[GL.immediate.VERTEX], true); + GL.immediate.prepareClientAttributes(0, 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.disableBeginEndClientAttributes(); GL.immediate.mode = -1; + + // Pop the old state: + GL.immediate.enabledClientAttributes = GL.immediate.enabledClientAttributes_preBegin; + GL.immediate.clientAttributes = GL.immediate.clientAttributes_preBegin; + + GL.immediate.modifiedClientAttributes = true; }, glVertex3f: function(x, y, z) { @@ -2670,7 +3798,7 @@ var LibraryGL = { glVertex2fv: function(p) { _glVertex3f({{{ makeGetValue('p', '0', 'float') }}}, {{{ makeGetValue('p', '4', 'float') }}}, 0); }, - + glVertex3i: 'glVertex3f', glVertex2i: 'glVertex3f', @@ -2883,7 +4011,7 @@ var LibraryGL = { glGenVertexArrays__sig: 'vii', glGenVertexArrays: function(n, vaos) { for (var i = 0; i < n; i++) { - var id = GL.getNewId(GLEmulation.vaos); + var id = GL.getNewId(GLEmulation.vaos); GLEmulation.vaos[id] = { id: id, arrayBuffer: 0, @@ -2944,6 +4072,7 @@ var LibraryGL = { } else if (mode == 0x1701 /* GL_PROJECTION */) { GL.immediate.currentMatrix = 'p'; } else if (mode == 0x1702) { // GL_TEXTURE + GL.immediate.useTextureMatrix = true; GL.immediate.currentMatrix = 't' + GL.immediate.clientActiveTexture; } else { throw "Wrong mode " + mode + " passed to glMatrixMode"; @@ -3113,7 +4242,7 @@ var LibraryGL = { return 1 /* GL_TRUE */; }, - + gluOrtho2D: function(left, right, bottom, top) { _glOrtho(left, right, bottom, top, -1, 1); }, @@ -3280,9 +4409,10 @@ var LibraryGL = { glGenVertexArraysOES: 'glGenVertexArrays', glDeleteVertexArraysOES: 'glDeleteVertexArrays', glBindVertexArrayOES: 'glBindVertexArray', - glFramebufferTexture2DOES: 'glFramebufferTexture2D' + glFramebufferTexture2DOES: 'glFramebufferTexture2D', }; + // Simple pass-through functions. Starred ones have return values. [X] ones have X in the C name but not in the JS name [[0, 'getError* finish flush'], [1, 'clearDepth clearDepth[f] depthFunc enable disable frontFace cullFace clear lineWidth clearStencil depthMask stencilMask checkFramebufferStatus* generateMipmap activeTexture blendEquation sampleCoverage isEnabled*'], diff --git a/tests/aniso.c b/tests/aniso.c index e02c20ace..1126265e5 100644 --- a/tests/aniso.c +++ b/tests/aniso.c @@ -64,7 +64,7 @@ int main(int argc, char *argv[]) const char *exts = (const char *)glGetString(GL_EXTENSIONS); assert(hasext(exts, "GL_EXT_texture_filter_anisotropic")); - + GLint aniso; glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &aniso); printf("Max anisotropy: %d (using that)\n", aniso); @@ -73,10 +73,8 @@ int main(int argc, char *argv[]) // Set the OpenGL state after creating the context with SDL_SetVideoMode glClearColor( 0, 0, 0, 0 ); - -#if !EMSCRIPTEN - glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL -#endif + + glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline. glViewport( 0, 0, 600, 600 ); @@ -155,7 +153,7 @@ int main(int argc, char *argv[]) // Clear the screen before drawing glClear( GL_COLOR_BUFFER_BIT ); - + // Bind the texture to which subsequent calls refer to int w = 10; int n = 15; @@ -200,7 +198,7 @@ int main(int argc, char *argv[]) } */ SDL_GL_SwapBuffers(); - + #if !EMSCRIPTEN // Wait for 3 seconds to give us a chance to see the image SDL_Delay(2000); @@ -208,8 +206,8 @@ int main(int argc, char *argv[]) // Now we can delete the OpenGL texture and close down SDL glDeleteTextures( 1, &texture ); - + SDL_Quit(); - + return 0; } diff --git a/tests/gl_ps.c b/tests/gl_ps.c index 6ea0e3dbc..4fa799224 100644 --- a/tests/gl_ps.c +++ b/tests/gl_ps.c @@ -115,11 +115,11 @@ int main(int argc, char *argv[]) printf("Unable to set video mode: %s\n", SDL_GetError()); return 1; } - + // Set the OpenGL state after creating the context with SDL_SetVideoMode glClearColor( 0, 0, 0, 0 ); - + #if !EMSCRIPTEN glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL #endif @@ -135,30 +135,30 @@ int main(int argc, char *argv[]) glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); - + // Load the OpenGL texture GLuint texture; // Texture object handle SDL_Surface *surface; // Gives us the information to make the texture - - if ( (surface = IMG_Load("screenshot.png")) ) { - + + if ( (surface = IMG_Load("screenshot.png")) ) { + // Check that the image's width is a power of 2 if ( (surface->w & (surface->w - 1)) != 0 ) { printf("warning: image.bmp's width is not a power of 2\n"); } - + // Also check if the height is a power of 2 if ( (surface->h & (surface->h - 1)) != 0 ) { printf("warning: image.bmp's height is not a power of 2\n"); } - + // Have OpenGL generate a texture object handle for us glGenTextures( 1, &texture ); - + // Bind the texture object glBindTexture( GL_TEXTURE_2D, texture ); - + // Set the texture's stretching properties glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); @@ -169,25 +169,25 @@ int main(int argc, char *argv[]) memset(surface->pixels, 0x66, surface->w*surface->h); // Edit the texture object's image data using the information SDL_Surface gives us - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels ); //SDL_UnlockSurface(surface); - } + } else { printf("SDL could not load image.bmp: %s\n", SDL_GetError()); SDL_Quit(); return 1; - } - + } + // Free the SDL_Surface only if it was successfully created - if ( surface ) { + if ( surface ) { SDL_FreeSurface( surface ); } - + // Clear the screen before drawing glClear( GL_COLOR_BUFFER_BIT ); - + shaders(); // Bind the texture to which subsequent calls refer to @@ -218,7 +218,7 @@ int main(int argc, char *argv[]) glDisableClientState(GL_VERTEX_ARRAY); SDL_GL_SwapBuffers(); - + #if !EMSCRIPTEN // Wait for 3 seconds to give us a chance to see the image SDL_Delay(3000); @@ -226,8 +226,8 @@ int main(int argc, char *argv[]) // Now we can delete the OpenGL texture and close down SDL glDeleteTextures( 1, &texture ); - + SDL_Quit(); - + return 0; } diff --git a/tests/gl_ps_workaround.c b/tests/gl_ps_workaround.c index 1e2a5c41c..268eaf22c 100644 --- a/tests/gl_ps_workaround.c +++ b/tests/gl_ps_workaround.c @@ -99,11 +99,11 @@ int main(int argc, char *argv[]) printf("Unable to set video mode: %s\n", SDL_GetError()); return 1; } - + // Set the OpenGL state after creating the context with SDL_SetVideoMode glClearColor( 0, 0, 0, 0 ); - + #if !EMSCRIPTEN glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL #endif @@ -119,30 +119,30 @@ int main(int argc, char *argv[]) glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); - + // Load the OpenGL texture GLuint texture; // Texture object handle SDL_Surface *surface; // Gives us the information to make the texture - - if ( (surface = IMG_Load("screenshot.png")) ) { - + + if ( (surface = IMG_Load("screenshot.png")) ) { + // Check that the image's width is a power of 2 if ( (surface->w & (surface->w - 1)) != 0 ) { printf("warning: image.bmp's width is not a power of 2\n"); } - + // Also check if the height is a power of 2 if ( (surface->h & (surface->h - 1)) != 0 ) { printf("warning: image.bmp's height is not a power of 2\n"); } - + // Have OpenGL generate a texture object handle for us glGenTextures( 1, &texture ); - + // Bind the texture object glBindTexture( GL_TEXTURE_2D, texture ); - + // Set the texture's stretching properties glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); @@ -153,25 +153,25 @@ int main(int argc, char *argv[]) memset(surface->pixels, 0x66, surface->w*surface->h); // Edit the texture object's image data using the information SDL_Surface gives us - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels ); //SDL_UnlockSurface(surface); - } + } else { printf("SDL could not load image.bmp: %s\n", SDL_GetError()); SDL_Quit(); return 1; - } - + } + // Free the SDL_Surface only if it was successfully created - if ( surface ) { + if ( surface ) { SDL_FreeSurface( surface ); } - + // Clear the screen before drawing glClear( GL_COLOR_BUFFER_BIT ); - + shaders(); // Bind the texture to which subsequent calls refer to @@ -204,7 +204,7 @@ int main(int argc, char *argv[]) 1, 1, 0, 1, }; - glEnableClientState(GL_TEXTURE_2D); // XXX should be GL_TEXTURE_COORD_ARRAY); // XXX + glEnableClientState(GL_TEXTURE_2D); // XXX should be GL_TEXTURE_COORD_ARRAY); // XXX glTexCoordPointer(2, GL_FLOAT, 0, textureData); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_FLOAT, 0, vertexData); @@ -215,7 +215,7 @@ int main(int argc, char *argv[]) glDisableClientState(GL_VERTEX_ARRAY); SDL_GL_SwapBuffers(); - + #if !EMSCRIPTEN // Wait for 3 seconds to give us a chance to see the image SDL_Delay(3000); @@ -223,8 +223,8 @@ int main(int argc, char *argv[]) // Now we can delete the OpenGL texture and close down SDL glDeleteTextures( 1, &texture ); - + SDL_Quit(); - + return 0; } diff --git a/tests/gl_ps_workaround2.c b/tests/gl_ps_workaround2.c index e5bd2fd1a..55145fa6a 100644 --- a/tests/gl_ps_workaround2.c +++ b/tests/gl_ps_workaround2.c @@ -99,11 +99,11 @@ int main(int argc, char *argv[]) printf("Unable to set video mode: %s\n", SDL_GetError()); return 1; } - + // Set the OpenGL state after creating the context with SDL_SetVideoMode glClearColor( 0, 0, 0, 0 ); - + #if !EMSCRIPTEN glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL #endif @@ -119,30 +119,30 @@ int main(int argc, char *argv[]) glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); - + // Load the OpenGL texture GLuint texture; // Texture object handle SDL_Surface *surface; // Gives us the information to make the texture - - if ( (surface = IMG_Load("screenshot.png")) ) { - + + if ( (surface = IMG_Load("screenshot.png")) ) { + // Check that the image's width is a power of 2 if ( (surface->w & (surface->w - 1)) != 0 ) { printf("warning: image.bmp's width is not a power of 2\n"); } - + // Also check if the height is a power of 2 if ( (surface->h & (surface->h - 1)) != 0 ) { printf("warning: image.bmp's height is not a power of 2\n"); } - + // Have OpenGL generate a texture object handle for us glGenTextures( 1, &texture ); - + // Bind the texture object glBindTexture( GL_TEXTURE_2D, texture ); - + // Set the texture's stretching properties glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); @@ -153,25 +153,25 @@ int main(int argc, char *argv[]) memset(surface->pixels, 0x66, surface->w*surface->h); // Edit the texture object's image data using the information SDL_Surface gives us - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels ); //SDL_UnlockSurface(surface); - } + } else { printf("SDL could not load image.bmp: %s\n", SDL_GetError()); SDL_Quit(); return 1; - } - + } + // Free the SDL_Surface only if it was successfully created - if ( surface ) { + if ( surface ) { SDL_FreeSurface( surface ); } - + // Clear the screen before drawing glClear( GL_COLOR_BUFFER_BIT ); - + shaders(); // Bind the texture to which subsequent calls refer to @@ -215,7 +215,7 @@ int main(int argc, char *argv[]) glDisableClientState(GL_VERTEX_ARRAY); SDL_GL_SwapBuffers(); - + #if !EMSCRIPTEN // Wait for 3 seconds to give us a chance to see the image SDL_Delay(3000); @@ -223,8 +223,8 @@ int main(int argc, char *argv[]) // Now we can delete the OpenGL texture and close down SDL glDeleteTextures( 1, &texture ); - + SDL_Quit(); - + return 0; } diff --git a/tests/glbegin_points.c b/tests/glbegin_points.c index b28cca4ed..9128a4f56 100644 --- a/tests/glbegin_points.c +++ b/tests/glbegin_points.c @@ -46,14 +46,12 @@ int main(int argc, char *argv[]) printf("Unable to set video mode: %s\n", SDL_GetError()); return 1; } - + // Set the OpenGL state after creating the context with SDL_SetVideoMode glClearColor( 0, 0, 0, 0 ); - -#if !EMSCRIPTEN - glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL -#endif + + glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline. glViewport( 0, 0, 640, 480 ); @@ -66,30 +64,30 @@ int main(int argc, char *argv[]) glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); - + // Load the OpenGL texture GLuint texture; // Texture object handle SDL_Surface *surface; // Gives us the information to make the texture - - if ( (surface = IMG_Load("screenshot.png")) ) { - + + if ( (surface = IMG_Load("screenshot.png")) ) { + // Check that the image's width is a power of 2 if ( (surface->w & (surface->w - 1)) != 0 ) { printf("warning: image.bmp's width is not a power of 2\n"); } - + // Also check if the height is a power of 2 if ( (surface->h & (surface->h - 1)) != 0 ) { printf("warning: image.bmp's height is not a power of 2\n"); } - + // Have OpenGL generate a texture object handle for us glGenTextures( 1, &texture ); - + // Bind the texture object glBindTexture( GL_TEXTURE_2D, texture ); - + // Set the texture's stretching properties glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); @@ -100,25 +98,25 @@ int main(int argc, char *argv[]) memset(surface->pixels, 0x66, surface->w*surface->h); // Edit the texture object's image data using the information SDL_Surface gives us - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels ); //SDL_UnlockSurface(surface); - } + } else { printf("SDL could not load image.bmp: %s\n", SDL_GetError()); SDL_Quit(); return 1; - } - + } + // Free the SDL_Surface only if it was successfully created - if ( surface ) { + if ( surface ) { SDL_FreeSurface( surface ); } - + // Clear the screen before drawing glClear( GL_COLOR_BUFFER_BIT ); - + // Bind the texture to which subsequent calls refer to glBindTexture( GL_TEXTURE_2D, texture ); @@ -151,7 +149,7 @@ int main(int argc, char *argv[]) glEnd(); SDL_GL_SwapBuffers(); - + #if !EMSCRIPTEN // Wait for 3 seconds to give us a chance to see the image SDL_Delay(3000); @@ -159,8 +157,8 @@ int main(int argc, char *argv[]) // Now we can delete the OpenGL texture and close down SDL glDeleteTextures( 1, &texture ); - + SDL_Quit(); - + return 0; } diff --git a/tests/s3tc.c b/tests/s3tc.c index c2736febd..16ee783fa 100644 --- a/tests/s3tc.c +++ b/tests/s3tc.c @@ -63,14 +63,12 @@ int main(int argc, char *argv[]) const char *exts = (const char *)glGetString(GL_EXTENSIONS); assert(hasext(exts, "GL_ARB_texture_compression")); assert(hasext(exts, "GL_EXT_texture_compression_s3tc")); - + // Set the OpenGL state after creating the context with SDL_SetVideoMode glClearColor( 0, 0, 0, 0 ); - -#if !EMSCRIPTEN - glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL -#endif + + glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline. glViewport( 0, 0, 640, 480 ); @@ -110,7 +108,7 @@ int main(int argc, char *argv[]) // Clear the screen before drawing glClear( GL_COLOR_BUFFER_BIT ); - + // Bind the texture to which subsequent calls refer to glBindTexture( GL_TEXTURE_2D, texture ); @@ -143,7 +141,7 @@ int main(int argc, char *argv[]) glEnd(); SDL_GL_SwapBuffers(); - + #if !EMSCRIPTEN // Wait for 3 seconds to give us a chance to see the image SDL_Delay(1500); @@ -151,8 +149,8 @@ int main(int argc, char *argv[]) // Now we can delete the OpenGL texture and close down SDL glDeleteTextures( 1, &texture ); - + SDL_Quit(); - + return 0; } diff --git a/tests/s3tc_crunch.c b/tests/s3tc_crunch.c index 579741090..90ed02d99 100644 --- a/tests/s3tc_crunch.c +++ b/tests/s3tc_crunch.c @@ -63,14 +63,12 @@ int main(int argc, char *argv[]) const char *exts = (const char *)glGetString(GL_EXTENSIONS); assert(hasext(exts, "GL_ARB_texture_compression")); assert(hasext(exts, "GL_EXT_texture_compression_s3tc")); - + // Set the OpenGL state after creating the context with SDL_SetVideoMode glClearColor( 0, 0, 0, 0 ); - -#if !EMSCRIPTEN - glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL -#endif + + glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline. glViewport( 0, 0, 640, 480 ); @@ -158,7 +156,7 @@ int main(int argc, char *argv[]) // Clear the screen before drawing glClear( GL_COLOR_BUFFER_BIT ); - + // Bind the texture to which subsequent calls refer to glBindTexture( GL_TEXTURE_2D, texture ); @@ -195,7 +193,7 @@ int main(int argc, char *argv[]) glEnd(); SDL_GL_SwapBuffers(); - + #if !EMSCRIPTEN // Wait for 3 seconds to give us a chance to see the image SDL_Delay(1500); @@ -203,8 +201,8 @@ int main(int argc, char *argv[]) // Now we can delete the OpenGL texture and close down SDL glDeleteTextures( 1, &texture ); - + SDL_Quit(); - + return 0; } diff --git a/tests/sdl_fog_density.c b/tests/sdl_fog_density.c index 957734198..cab6a4d27 100644 --- a/tests/sdl_fog_density.c +++ b/tests/sdl_fog_density.c @@ -47,14 +47,12 @@ int main(int argc, char *argv[]) printf("Unable to set video mode: %s\n", SDL_GetError()); return 1; } - + // Set the OpenGL state after creating the context with SDL_SetVideoMode glClearColor( 0, 0, 0, 0 ); - -#if !EMSCRIPTEN - glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL -#endif + + glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline. glViewport( 0, 0, 640, 480 ); @@ -63,33 +61,33 @@ int main(int argc, char *argv[]) glLoadIdentity(); glOrtho( 0, 640, 480, 0, -1000, 1000 ); - + glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); - + // Load the OpenGL texture GLuint texture; // Texture object handle SDL_Surface *surface; // Gives us the information to make the texture - - if ( (surface = IMG_Load("screenshot.png")) ) { - + + if ( (surface = IMG_Load("screenshot.png")) ) { + // Check that the image's width is a power of 2 if ( (surface->w & (surface->w - 1)) != 0 ) { printf("warning: image.bmp's width is not a power of 2\n"); } - + // Also check if the height is a power of 2 if ( (surface->h & (surface->h - 1)) != 0 ) { printf("warning: image.bmp's height is not a power of 2\n"); } - + // Have OpenGL generate a texture object handle for us glGenTextures( 1, &texture ); - + // Bind the texture object glBindTexture( GL_TEXTURE_2D, texture ); - + // Set the texture's stretching properties glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); @@ -100,25 +98,25 @@ int main(int argc, char *argv[]) memset(surface->pixels, 0x66, surface->w*surface->h); // Edit the texture object's image data using the information SDL_Surface gives us - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels ); //SDL_UnlockSurface(surface); - } + } else { printf("SDL could not load image.bmp: %s\n", SDL_GetError()); SDL_Quit(); return 1; - } - + } + // Free the SDL_Surface only if it was successfully created - if ( surface ) { + if ( surface ) { SDL_FreeSurface( surface ); } - + // Clear the screen before drawing glClear( GL_COLOR_BUFFER_BIT ); - + // Bind the texture to which subsequent calls refer to glBindTexture( GL_TEXTURE_2D, texture ); @@ -148,9 +146,7 @@ int main(int argc, char *argv[]) glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, 1 ); glEnd(); -#if !EMSCRIPTEN glDisable(GL_TEXTURE_2D); -#endif glColor3ub(90, 255, 255); glBegin( GL_QUADS ); @@ -168,7 +164,7 @@ int main(int argc, char *argv[]) glEnd(); SDL_GL_SwapBuffers(); - + #if !EMSCRIPTEN // Wait for 3 seconds to give us a chance to see the image SDL_Delay(30000); @@ -176,8 +172,8 @@ int main(int argc, char *argv[]) // Now we can delete the OpenGL texture and close down SDL glDeleteTextures( 1, &texture ); - + SDL_Quit(); - + return 0; } diff --git a/tests/sdl_fog_exp2.c b/tests/sdl_fog_exp2.c index a09a5e3d1..dba0c708b 100644 --- a/tests/sdl_fog_exp2.c +++ b/tests/sdl_fog_exp2.c @@ -47,14 +47,12 @@ int main(int argc, char *argv[]) printf("Unable to set video mode: %s\n", SDL_GetError()); return 1; } - + // Set the OpenGL state after creating the context with SDL_SetVideoMode glClearColor( 0, 0, 0, 0 ); - -#if !EMSCRIPTEN - glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL -#endif + + glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline. glViewport( 0, 0, 640, 480 ); @@ -63,33 +61,33 @@ int main(int argc, char *argv[]) glLoadIdentity(); glOrtho( 0, 640, 480, 0, -1000, 1000 ); - + glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); - + // Load the OpenGL texture GLuint texture; // Texture object handle SDL_Surface *surface; // Gives us the information to make the texture - - if ( (surface = IMG_Load("screenshot.png")) ) { - + + if ( (surface = IMG_Load("screenshot.png")) ) { + // Check that the image's width is a power of 2 if ( (surface->w & (surface->w - 1)) != 0 ) { printf("warning: image.bmp's width is not a power of 2\n"); } - + // Also check if the height is a power of 2 if ( (surface->h & (surface->h - 1)) != 0 ) { printf("warning: image.bmp's height is not a power of 2\n"); } - + // Have OpenGL generate a texture object handle for us glGenTextures( 1, &texture ); - + // Bind the texture object glBindTexture( GL_TEXTURE_2D, texture ); - + // Set the texture's stretching properties glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); @@ -100,25 +98,25 @@ int main(int argc, char *argv[]) memset(surface->pixels, 0x66, surface->w*surface->h); // Edit the texture object's image data using the information SDL_Surface gives us - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels ); //SDL_UnlockSurface(surface); - } + } else { printf("SDL could not load image.bmp: %s\n", SDL_GetError()); SDL_Quit(); return 1; - } - + } + // Free the SDL_Surface only if it was successfully created - if ( surface ) { + if ( surface ) { SDL_FreeSurface( surface ); } - + // Clear the screen before drawing glClear( GL_COLOR_BUFFER_BIT ); - + // Bind the texture to which subsequent calls refer to glBindTexture( GL_TEXTURE_2D, texture ); @@ -149,9 +147,7 @@ int main(int argc, char *argv[]) glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, 1 ); glEnd(); -#if !EMSCRIPTEN glDisable(GL_TEXTURE_2D); -#endif glColor3ub(90, 255, 255); glBegin( GL_QUADS ); @@ -169,7 +165,7 @@ int main(int argc, char *argv[]) glEnd(); SDL_GL_SwapBuffers(); - + #if !EMSCRIPTEN // Wait for 3 seconds to give us a chance to see the image SDL_Delay(30000); @@ -177,8 +173,8 @@ int main(int argc, char *argv[]) // Now we can delete the OpenGL texture and close down SDL glDeleteTextures( 1, &texture ); - + SDL_Quit(); - + return 0; } diff --git a/tests/sdl_fog_linear.c b/tests/sdl_fog_linear.c index 8fc18b7ca..f0805650a 100644 --- a/tests/sdl_fog_linear.c +++ b/tests/sdl_fog_linear.c @@ -47,14 +47,12 @@ int main(int argc, char *argv[]) printf("Unable to set video mode: %s\n", SDL_GetError()); return 1; } - + // Set the OpenGL state after creating the context with SDL_SetVideoMode glClearColor( 0, 0, 0, 0 ); - -#if !EMSCRIPTEN - glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL -#endif + + glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline. glViewport( 0, 0, 640, 480 ); @@ -63,33 +61,33 @@ int main(int argc, char *argv[]) glLoadIdentity(); glOrtho( 0, 640, 480, 0, -1000, 1000 ); - + glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); - + // Load the OpenGL texture GLuint texture; // Texture object handle SDL_Surface *surface; // Gives us the information to make the texture - - if ( (surface = IMG_Load("screenshot.png")) ) { - + + if ( (surface = IMG_Load("screenshot.png")) ) { + // Check that the image's width is a power of 2 if ( (surface->w & (surface->w - 1)) != 0 ) { printf("warning: image.bmp's width is not a power of 2\n"); } - + // Also check if the height is a power of 2 if ( (surface->h & (surface->h - 1)) != 0 ) { printf("warning: image.bmp's height is not a power of 2\n"); } - + // Have OpenGL generate a texture object handle for us glGenTextures( 1, &texture ); - + // Bind the texture object glBindTexture( GL_TEXTURE_2D, texture ); - + // Set the texture's stretching properties glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); @@ -100,25 +98,25 @@ int main(int argc, char *argv[]) memset(surface->pixels, 0x66, surface->w*surface->h); // Edit the texture object's image data using the information SDL_Surface gives us - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels ); //SDL_UnlockSurface(surface); - } + } else { printf("SDL could not load image.bmp: %s\n", SDL_GetError()); SDL_Quit(); return 1; - } - + } + // Free the SDL_Surface only if it was successfully created - if ( surface ) { + if ( surface ) { SDL_FreeSurface( surface ); } - + // Clear the screen before drawing glClear( GL_COLOR_BUFFER_BIT ); - + // Bind the texture to which subsequent calls refer to glBindTexture( GL_TEXTURE_2D, texture ); @@ -150,9 +148,7 @@ int main(int argc, char *argv[]) glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, 1 ); glEnd(); -#if !EMSCRIPTEN glDisable(GL_TEXTURE_2D); -#endif glColor3ub(90, 255, 255); glBegin( GL_QUADS ); @@ -170,7 +166,7 @@ int main(int argc, char *argv[]) glEnd(); SDL_GL_SwapBuffers(); - + #if !EMSCRIPTEN // Wait for 3 seconds to give us a chance to see the image SDL_Delay(30000); @@ -178,8 +174,8 @@ int main(int argc, char *argv[]) // Now we can delete the OpenGL texture and close down SDL glDeleteTextures( 1, &texture ); - + SDL_Quit(); - + return 0; } diff --git a/tests/sdl_fog_negative.c b/tests/sdl_fog_negative.c index 2d589a470..1ede63a7c 100644 --- a/tests/sdl_fog_negative.c +++ b/tests/sdl_fog_negative.c @@ -47,14 +47,12 @@ int main(int argc, char *argv[]) printf("Unable to set video mode: %s\n", SDL_GetError()); return 1; } - + // Set the OpenGL state after creating the context with SDL_SetVideoMode glClearColor( 0, 0, 0, 0 ); - -#if !EMSCRIPTEN - glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL -#endif + + glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline. glViewport( 0, 0, 640, 480 ); @@ -63,33 +61,33 @@ int main(int argc, char *argv[]) glLoadIdentity(); glOrtho( 0, 640, 480, 0, -1000, 1000 ); - + glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); - + // Load the OpenGL texture GLuint texture; // Texture object handle SDL_Surface *surface; // Gives us the information to make the texture - - if ( (surface = IMG_Load("screenshot.png")) ) { - + + if ( (surface = IMG_Load("screenshot.png")) ) { + // Check that the image's width is a power of 2 if ( (surface->w & (surface->w - 1)) != 0 ) { printf("warning: image.bmp's width is not a power of 2\n"); } - + // Also check if the height is a power of 2 if ( (surface->h & (surface->h - 1)) != 0 ) { printf("warning: image.bmp's height is not a power of 2\n"); } - + // Have OpenGL generate a texture object handle for us glGenTextures( 1, &texture ); - + // Bind the texture object glBindTexture( GL_TEXTURE_2D, texture ); - + // Set the texture's stretching properties glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); @@ -100,25 +98,25 @@ int main(int argc, char *argv[]) memset(surface->pixels, 0x66, surface->w*surface->h); // Edit the texture object's image data using the information SDL_Surface gives us - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels ); //SDL_UnlockSurface(surface); - } + } else { printf("SDL could not load image.bmp: %s\n", SDL_GetError()); SDL_Quit(); return 1; - } - + } + // Free the SDL_Surface only if it was successfully created - if ( surface ) { + if ( surface ) { SDL_FreeSurface( surface ); } - + // Clear the screen before drawing glClear( GL_COLOR_BUFFER_BIT ); - + // Bind the texture to which subsequent calls refer to glBindTexture( GL_TEXTURE_2D, texture ); @@ -147,9 +145,7 @@ int main(int argc, char *argv[]) glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, -1 ); glEnd(); -#if !EMSCRIPTEN glDisable(GL_TEXTURE_2D); -#endif glColor3ub(90, 255, 255); glBegin( GL_QUADS ); @@ -167,7 +163,7 @@ int main(int argc, char *argv[]) glEnd(); SDL_GL_SwapBuffers(); - + #if !EMSCRIPTEN // Wait for 3 seconds to give us a chance to see the image SDL_Delay(30000); @@ -175,8 +171,8 @@ int main(int argc, char *argv[]) // Now we can delete the OpenGL texture and close down SDL glDeleteTextures( 1, &texture ); - + SDL_Quit(); - + return 0; } diff --git a/tests/sdl_fog_simple.c b/tests/sdl_fog_simple.c index be0235933..6c052bf57 100644 --- a/tests/sdl_fog_simple.c +++ b/tests/sdl_fog_simple.c @@ -47,14 +47,10 @@ int main(int argc, char *argv[]) printf("Unable to set video mode: %s\n", SDL_GetError()); return 1; } - + // Set the OpenGL state after creating the context with SDL_SetVideoMode glClearColor( 0, 0, 0, 0 ); - -#if !EMSCRIPTEN - glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL -#endif glViewport( 0, 0, 640, 480 ); @@ -63,33 +59,38 @@ int main(int argc, char *argv[]) glLoadIdentity(); glOrtho( 0, 640, 480, 0, -1000, 1000 ); - + glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); - + + // Delay Enable to after MatrixMode to assure we've activated + // immediate mode. Otherwise, we don't properly record that + // TEXTURE_2D is enabled for imm mode emulation. + glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline. + // Load the OpenGL texture GLuint texture; // Texture object handle SDL_Surface *surface; // Gives us the information to make the texture - - if ( (surface = IMG_Load("screenshot.png")) ) { - + + if ( (surface = IMG_Load("screenshot.png")) ) { + // Check that the image's width is a power of 2 if ( (surface->w & (surface->w - 1)) != 0 ) { printf("warning: image.bmp's width is not a power of 2\n"); } - + // Also check if the height is a power of 2 if ( (surface->h & (surface->h - 1)) != 0 ) { printf("warning: image.bmp's height is not a power of 2\n"); } - + // Have OpenGL generate a texture object handle for us glGenTextures( 1, &texture ); - + // Bind the texture object glBindTexture( GL_TEXTURE_2D, texture ); - + // Set the texture's stretching properties glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); @@ -100,25 +101,25 @@ int main(int argc, char *argv[]) memset(surface->pixels, 0x66, surface->w*surface->h); // Edit the texture object's image data using the information SDL_Surface gives us - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels ); //SDL_UnlockSurface(surface); - } + } else { printf("SDL could not load image.bmp: %s\n", SDL_GetError()); SDL_Quit(); return 1; - } - + } + // Free the SDL_Surface only if it was successfully created - if ( surface ) { + if ( surface ) { SDL_FreeSurface( surface ); } - + // Clear the screen before drawing glClear( GL_COLOR_BUFFER_BIT ); - + // Bind the texture to which subsequent calls refer to glBindTexture( GL_TEXTURE_2D, texture ); @@ -147,9 +148,7 @@ int main(int argc, char *argv[]) glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, 1 ); glEnd(); -#if !EMSCRIPTEN glDisable(GL_TEXTURE_2D); -#endif glColor3ub(90, 255, 255); glBegin( GL_QUADS ); @@ -167,7 +166,7 @@ int main(int argc, char *argv[]) glEnd(); SDL_GL_SwapBuffers(); - + #if !EMSCRIPTEN // Wait for 3 seconds to give us a chance to see the image SDL_Delay(30000); @@ -175,8 +174,8 @@ int main(int argc, char *argv[]) // Now we can delete the OpenGL texture and close down SDL glDeleteTextures( 1, &texture ); - + SDL_Quit(); - + return 0; } diff --git a/tests/sdl_ogl.c b/tests/sdl_ogl.c index 6b6a5b4a6..e7071dcd1 100644 --- a/tests/sdl_ogl.c +++ b/tests/sdl_ogl.c @@ -46,14 +46,12 @@ int main(int argc, char *argv[]) printf("Unable to set video mode: %s\n", SDL_GetError()); return 1; } - + // Set the OpenGL state after creating the context with SDL_SetVideoMode glClearColor( 0, 0, 0, 0 ); - -#if !EMSCRIPTEN - glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL -#endif + + glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline. glViewport( 0, 0, 640, 480 ); @@ -62,33 +60,33 @@ int main(int argc, char *argv[]) glLoadIdentity(); glOrtho( 0, 640, 480, 0, -1, 1 ); - + glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); - + // Load the OpenGL texture GLuint texture; // Texture object handle SDL_Surface *surface; // Gives us the information to make the texture - - if ( (surface = IMG_Load("screenshot.png")) ) { - + + if ( (surface = IMG_Load("screenshot.png")) ) { + // Check that the image's width is a power of 2 if ( (surface->w & (surface->w - 1)) != 0 ) { printf("warning: image.bmp's width is not a power of 2\n"); } - + // Also check if the height is a power of 2 if ( (surface->h & (surface->h - 1)) != 0 ) { printf("warning: image.bmp's height is not a power of 2\n"); } - + // Have OpenGL generate a texture object handle for us glGenTextures( 1, &texture ); - + // Bind the texture object glBindTexture( GL_TEXTURE_2D, texture ); - + // Set the texture's stretching properties glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); @@ -99,25 +97,25 @@ int main(int argc, char *argv[]) memset(surface->pixels, 0x66, surface->w*surface->h); // Edit the texture object's image data using the information SDL_Surface gives us - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels ); //SDL_UnlockSurface(surface); - } + } else { printf("SDL could not load image.bmp: %s\n", SDL_GetError()); SDL_Quit(); return 1; - } - + } + // Free the SDL_Surface only if it was successfully created - if ( surface ) { + if ( surface ) { SDL_FreeSurface( surface ); } - + // Clear the screen before drawing glClear( GL_COLOR_BUFFER_BIT ); - + // Bind the texture to which subsequent calls refer to glBindTexture( GL_TEXTURE_2D, texture ); @@ -140,9 +138,7 @@ int main(int argc, char *argv[]) glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, 0 ); glEnd(); -#if !EMSCRIPTEN glDisable(GL_TEXTURE_2D); -#endif glColor3ub(90, 255, 255); glBegin( GL_QUADS ); @@ -160,7 +156,7 @@ int main(int argc, char *argv[]) glEnd(); SDL_GL_SwapBuffers(); - + #if !EMSCRIPTEN // Wait for 3 seconds to give us a chance to see the image SDL_Delay(3000); @@ -168,8 +164,8 @@ int main(int argc, char *argv[]) // Now we can delete the OpenGL texture and close down SDL glDeleteTextures( 1, &texture ); - + SDL_Quit(); - + return 0; } diff --git a/tests/sdl_ogl_defaultMatrixMode.c b/tests/sdl_ogl_defaultMatrixMode.c index 0da0a3262..eec2a8315 100644 --- a/tests/sdl_ogl_defaultMatrixMode.c +++ b/tests/sdl_ogl_defaultMatrixMode.c @@ -46,14 +46,12 @@ int main(int argc, char *argv[]) printf("Unable to set video mode: %s\n", SDL_GetError()); return 1; } - + // Set the OpenGL state after creating the context with SDL_SetVideoMode glClearColor( 0, 0, 0, 0 ); - -#if !EMSCRIPTEN - glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL -#endif + + glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline. glViewport( 0, 0, 640, 480 ); @@ -66,30 +64,30 @@ int main(int argc, char *argv[]) glLoadIdentity(); glOrtho( 0, 640, 480, 0, -1, 1 ); - + // Load the OpenGL texture GLuint texture; // Texture object handle SDL_Surface *surface; // Gives us the information to make the texture - - if ( (surface = IMG_Load("screenshot.png")) ) { - + + if ( (surface = IMG_Load("screenshot.png")) ) { + // Check that the image's width is a power of 2 if ( (surface->w & (surface->w - 1)) != 0 ) { printf("warning: image.bmp's width is not a power of 2\n"); } - + // Also check if the height is a power of 2 if ( (surface->h & (surface->h - 1)) != 0 ) { printf("warning: image.bmp's height is not a power of 2\n"); } - + // Have OpenGL generate a texture object handle for us glGenTextures( 1, &texture ); - + // Bind the texture object glBindTexture( GL_TEXTURE_2D, texture ); - + // Set the texture's stretching properties glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); @@ -100,25 +98,25 @@ int main(int argc, char *argv[]) memset(surface->pixels, 0x66, surface->w*surface->h); // Edit the texture object's image data using the information SDL_Surface gives us - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels ); //SDL_UnlockSurface(surface); - } + } else { printf("SDL could not load image.bmp: %s\n", SDL_GetError()); SDL_Quit(); return 1; - } - + } + // Free the SDL_Surface only if it was successfully created - if ( surface ) { + if ( surface ) { SDL_FreeSurface( surface ); } - + // Clear the screen before drawing glClear( GL_COLOR_BUFFER_BIT ); - + // Bind the texture to which subsequent calls refer to glBindTexture( GL_TEXTURE_2D, texture ); @@ -141,9 +139,7 @@ int main(int argc, char *argv[]) glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, 0 ); glEnd(); -#if !EMSCRIPTEN glDisable(GL_TEXTURE_2D); -#endif glColor3ub(90, 255, 255); glBegin( GL_QUADS ); @@ -161,7 +157,7 @@ int main(int argc, char *argv[]) glEnd(); SDL_GL_SwapBuffers(); - + #if !EMSCRIPTEN // Wait for 3 seconds to give us a chance to see the image SDL_Delay(3000); @@ -169,8 +165,8 @@ int main(int argc, char *argv[]) // Now we can delete the OpenGL texture and close down SDL glDeleteTextures( 1, &texture ); - + SDL_Quit(); - + return 0; } diff --git a/tests/sdl_ogl_p.c b/tests/sdl_ogl_p.c index fcc53a409..1889d9264 100644 --- a/tests/sdl_ogl_p.c +++ b/tests/sdl_ogl_p.c @@ -46,14 +46,12 @@ int main(int argc, char *argv[]) printf("Unable to set video mode: %s\n", SDL_GetError()); return 1; } - + // Set the OpenGL state after creating the context with SDL_SetVideoMode glClearColor( 0, 0, 0, 0 ); - -#if !EMSCRIPTEN - glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL -#endif + + glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline. glViewport( 0, 0, 640, 480 ); @@ -66,30 +64,30 @@ int main(int argc, char *argv[]) glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); - + // Load the OpenGL texture GLuint texture; // Texture object handle SDL_Surface *surface; // Gives us the information to make the texture - - if ( (surface = IMG_Load("screenshot.png")) ) { - + + if ( (surface = IMG_Load("screenshot.png")) ) { + // Check that the image's width is a power of 2 if ( (surface->w & (surface->w - 1)) != 0 ) { printf("warning: image.bmp's width is not a power of 2\n"); } - + // Also check if the height is a power of 2 if ( (surface->h & (surface->h - 1)) != 0 ) { printf("warning: image.bmp's height is not a power of 2\n"); } - + // Have OpenGL generate a texture object handle for us glGenTextures( 1, &texture ); - + // Bind the texture object glBindTexture( GL_TEXTURE_2D, texture ); - + // Set the texture's stretching properties glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); @@ -100,25 +98,25 @@ int main(int argc, char *argv[]) memset(surface->pixels, 0x66, surface->w*surface->h); // Edit the texture object's image data using the information SDL_Surface gives us - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels ); //SDL_UnlockSurface(surface); - } + } else { printf("SDL could not load image.bmp: %s\n", SDL_GetError()); SDL_Quit(); return 1; - } - + } + // Free the SDL_Surface only if it was successfully created - if ( surface ) { + if ( surface ) { SDL_FreeSurface( surface ); } - + // Clear the screen before drawing glClear( GL_COLOR_BUFFER_BIT ); - + // Bind the texture to which subsequent calls refer to glBindTexture( GL_TEXTURE_2D, texture ); @@ -151,7 +149,7 @@ int main(int argc, char *argv[]) glEnd(); SDL_GL_SwapBuffers(); - + #if !EMSCRIPTEN // Wait for 3 seconds to give us a chance to see the image SDL_Delay(3000); @@ -159,8 +157,8 @@ int main(int argc, char *argv[]) // Now we can delete the OpenGL texture and close down SDL glDeleteTextures( 1, &texture ); - + SDL_Quit(); - + return 0; } diff --git a/third_party/lzma.js/lzip/Makefile b/third_party/lzma.js/lzip/Makefile index ca6a6ef70..8a5baee3a 100644 --- a/third_party/lzma.js/lzip/Makefile +++ b/third_party/lzma.js/lzip/Makefile @@ -16,7 +16,8 @@ datadir = $(prefix)/share infodir = $(datadir)/info mandir = $(datadir)/man sysconfdir = $(prefix)/etc -CPPFLAGS = -DDECODER_ONLY=$(DECODER_ONLY) +CXX = g++ +CPPFLAGS = CXXFLAGS = -Wall -W -O2 LDFLAGS = @@ -27,16 +28,16 @@ INSTALL_DATA = $(INSTALL) -p -m 644 INSTALL_DIR = $(INSTALL) -d -m 755 SHELL = /bin/sh -objs = decoder.o encoder.o fast_encoder.o main.o -recobjs = decoder.o lziprecover.o -unzobjs = unzcrash.o +objs = arg_parser.o decoder.o encoder.o fast_encoder.o main.o +recobjs = arg_parser.o decoder.o lziprecover.o +unzobjs = arg_parser.o unzcrash.o .PHONY : all install install-info install-man install-strip \ uninstall uninstall-info uninstall-man \ doc info man check dist clean distclean -all : $(progname) +all : $(progname) lziprecover $(progname) : $(objs) $(CXX) $(LDFLAGS) -o $@ $(objs) @@ -63,12 +64,13 @@ unzcrash.o : testsuite/unzcrash.cc $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< $(objs) : Makefile +arg_parser.o : arg_parser.h decoder.o : lzip.h decoder.h encoder.o : lzip.h encoder.h fast_encoder.o : lzip.h encoder.h fast_encoder.h -main.o : lzip.h decoder.h encoder.h fast_encoder.h -lziprecover.o : lzip.h decoder.h Makefile -unzcrash.o : Makefile +main.o : arg_parser.h lzip.h decoder.h encoder.h fast_encoder.h +lziprecover.o : arg_parser.h lzip.h decoder.h Makefile +unzcrash.o : arg_parser.h Makefile doc : info man