1d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
26270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens//
3d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// Licensed under the Apache License, Version 2.0 (the "License");
4d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// you may not use this file except in compliance with the License.
5d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// You may obtain a copy of the License at
66270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens//
7d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens//    http://www.apache.org/licenses/LICENSE-2.0
86270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens//
9d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// Unless required by applicable law or agreed to in writing, software
10d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// distributed under the License is distributed on an "AS IS" BASIS,
11d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// See the License for the specific language governing permissions and
13d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// limitations under the License.
146270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens
156270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens#include "PixelPipeline.hpp"
166270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens#include "Renderer.hpp"
176270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens#include "SamplerCore.hpp"
186270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens
196270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capensnamespace sw
206270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens{
216270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens	extern bool postBlendSRGB;
226270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens
23a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens	void PixelPipeline::setBuiltins(Int &x, Int &y, Float4(&z)[4], Float4 &w)
246270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens	{
25a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		if(state.color[0].component & 0x1) diffuse.x = convertFixed12(v[0].x); else diffuse.x = Short4(0x1000);
26a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		if(state.color[0].component & 0x2) diffuse.y = convertFixed12(v[0].y); else diffuse.y = Short4(0x1000);
27a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		if(state.color[0].component & 0x4) diffuse.z = convertFixed12(v[0].z); else diffuse.z = Short4(0x1000);
28a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		if(state.color[0].component & 0x8) diffuse.w = convertFixed12(v[0].w); else diffuse.w = Short4(0x1000);
29a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens
30cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu		if(state.color[1].component & 0x1) specular.x = convertFixed12(v[1].x); else specular.x = Short4(0x0000);
31cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu		if(state.color[1].component & 0x2) specular.y = convertFixed12(v[1].y); else specular.y = Short4(0x0000);
32cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu		if(state.color[1].component & 0x4) specular.z = convertFixed12(v[1].z); else specular.z = Short4(0x0000);
33cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu		if(state.color[1].component & 0x8) specular.w = convertFixed12(v[1].w); else specular.w = Short4(0x0000);
346270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens	}
356270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens
36a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens	void PixelPipeline::fixedFunction()
376270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens	{
38a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		current = diffuse;
39f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Vector4s temp(0x0000, 0x0000, 0x0000, 0x0000);
40f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
41f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		for(int stage = 0; stage < 8; stage++)
42f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
43f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			if(state.textureStage[stage].stageOperation == TextureStage::STAGE_DISABLE)
44f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			{
45f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
46f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			}
47f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
48f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			Vector4s texture;
49f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
50f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			if(state.textureStage[stage].usesTexture)
51f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			{
52a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				sampleTexture(texture, stage, stage);
53f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			}
54f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
55a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			blendTexture(temp, texture, stage);
56f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
57f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
58a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		specularPixel(current, specular);
596270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens	}
606270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens
61a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens	void PixelPipeline::applyShader(Int cMask[4])
62f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
63f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		if(!shader)
64f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
65a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			fixedFunction();
66f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			return;
67f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
68f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
69f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		int pad = 0;        // Count number of texm3x3pad instructions
70f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Vector4s dPairing;   // Destination for first pairing instruction
71f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
72f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		for(size_t i = 0; i < shader->getLength(); i++)
73f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
74f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			const Shader::Instruction *instruction = shader->getInstruction(i);
75f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			Shader::Opcode opcode = instruction->opcode;
76f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
77f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			//	#ifndef NDEBUG   // FIXME: Centralize debug output control
78f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			//		shader->printInstruction(i, "debug.txt");
79f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			//	#endif
80f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
81f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			if(opcode == Shader::OPCODE_DCL || opcode == Shader::OPCODE_DEF || opcode == Shader::OPCODE_DEFI || opcode == Shader::OPCODE_DEFB)
82f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			{
83f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				continue;
84f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			}
85f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
86f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			const Dst &dst = instruction->dst;
87f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			const Src &src0 = instruction->src[0];
88f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			const Src &src1 = instruction->src[1];
89f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			const Src &src2 = instruction->src[2];
90f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
91f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			unsigned short version = shader->getVersion();
92f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			bool pairing = i + 1 < shader->getLength() && shader->getInstruction(i + 1)->coissue;   // First instruction of pair
93f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			bool coissue = instruction->coissue;                                                              // Second instruction of pair
94f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
95f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			Vector4s d;
96f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			Vector4s s0;
97f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			Vector4s s1;
98f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			Vector4s s2;
99f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1009d86a36eb381ffce11fc116490abf74b21f49ca5Nicolas Capens			if(src0.type != Shader::PARAMETER_VOID) s0 = fetchRegister(src0);
1019d86a36eb381ffce11fc116490abf74b21f49ca5Nicolas Capens			if(src1.type != Shader::PARAMETER_VOID) s1 = fetchRegister(src1);
1029d86a36eb381ffce11fc116490abf74b21f49ca5Nicolas Capens			if(src2.type != Shader::PARAMETER_VOID) s2 = fetchRegister(src2);
103f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
104a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			Float4 x = version < 0x0104 ? v[2 + dst.index].x : v[2 + src0.index].x;
105a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			Float4 y = version < 0x0104 ? v[2 + dst.index].y : v[2 + src0.index].y;
106a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			Float4 z = version < 0x0104 ? v[2 + dst.index].z : v[2 + src0.index].z;
107a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			Float4 w = version < 0x0104 ? v[2 + dst.index].w : v[2 + src0.index].w;
108f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
109f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			switch(opcode)
110f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			{
111f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case Shader::OPCODE_PS_1_0: break;
112f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case Shader::OPCODE_PS_1_1: break;
113f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case Shader::OPCODE_PS_1_2: break;
114f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case Shader::OPCODE_PS_1_3: break;
115f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case Shader::OPCODE_PS_1_4: break;
116f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
117f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case Shader::OPCODE_DEF:    break;
118f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
119f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case Shader::OPCODE_NOP:    break;
120f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case Shader::OPCODE_MOV: MOV(d, s0);         break;
121f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case Shader::OPCODE_ADD: ADD(d, s0, s1);     break;
122f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case Shader::OPCODE_SUB: SUB(d, s0, s1);     break;
123f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case Shader::OPCODE_MAD: MAD(d, s0, s1, s2); break;
124f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case Shader::OPCODE_MUL: MUL(d, s0, s1);     break;
125f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case Shader::OPCODE_DP3: DP3(d, s0, s1);     break;
126f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case Shader::OPCODE_DP4: DP4(d, s0, s1);     break;
127f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case Shader::OPCODE_LRP: LRP(d, s0, s1, s2); break;
128f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case Shader::OPCODE_TEXCOORD:
129f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				if(version < 0x0104)
130f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				{
131a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens					TEXCOORD(d, x, y, z, dst.index);
132a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			}
133f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				else
134f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				{
135f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu					if((src0.swizzle & 0x30) == 0x20)   // .xyz
136f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu					{
137a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens						TEXCRD(d, x, y, z, src0.index, src0.modifier == Shader::MODIFIER_DZ || src0.modifier == Shader::MODIFIER_DW);
138f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu					}
139a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens					else   // .xwy
140f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu					{
141a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens						TEXCRD(d, x, y, w, src0.index, src0.modifier == Shader::MODIFIER_DZ || src0.modifier == Shader::MODIFIER_DW);
142f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu					}
143f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				}
144f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
145f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case Shader::OPCODE_TEXKILL:
146f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				if(version < 0x0104)
147f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				{
148a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens					TEXKILL(cMask, x, y, z);
149f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				}
150f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				else if(version == 0x0104)
151f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				{
152f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu					if(dst.type == Shader::PARAMETER_TEXTURE)
153f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu					{
154a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens						TEXKILL(cMask, x, y, z);
155f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu					}
156f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu					else
157f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu					{
158a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens						TEXKILL(cMask, rs[dst.index]);
159f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu					}
160f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				}
161f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				else ASSERT(false);
162f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
163f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case Shader::OPCODE_TEX:
164f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				if(version < 0x0104)
165f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				{
166a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens					TEX(d, x, y, z, dst.index, false);
167f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				}
168f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				else if(version == 0x0104)
169f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				{
170f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu					if(src0.type == Shader::PARAMETER_TEXTURE)
171f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu					{
172f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu						if((src0.swizzle & 0x30) == 0x20)   // .xyz
173f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu						{
174a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens							TEX(d, x, y, z, dst.index, src0.modifier == Shader::MODIFIER_DZ || src0.modifier == Shader::MODIFIER_DW);
175f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu						}
176f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu						else   // .xyw
177f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu						{
178a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens							TEX(d, x, y, w, dst.index, src0.modifier == Shader::MODIFIER_DZ || src0.modifier == Shader::MODIFIER_DW);
179f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu						}
180f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu					}
181f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu					else
182f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu					{
183a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens						TEXLD(d, s0, dst.index, src0.modifier == Shader::MODIFIER_DZ || src0.modifier == Shader::MODIFIER_DW);
184f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu					}
185f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				}
186f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				else ASSERT(false);
187f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
188a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			case Shader::OPCODE_TEXBEM:       TEXBEM(d, s0, x, y, z, dst.index);                                             break;
189a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			case Shader::OPCODE_TEXBEML:      TEXBEML(d, s0, x, y, z, dst.index);                                            break;
190a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			case Shader::OPCODE_TEXREG2AR:    TEXREG2AR(d, s0, dst.index);                                                   break;
191a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			case Shader::OPCODE_TEXREG2GB:    TEXREG2GB(d, s0, dst.index);                                                   break;
192a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			case Shader::OPCODE_TEXM3X2PAD:   TEXM3X2PAD(x, y, z, s0, 0, src0.modifier == Shader::MODIFIER_SIGN);            break;
193a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			case Shader::OPCODE_TEXM3X2TEX:   TEXM3X2TEX(d, x, y, z, dst.index, s0, src0.modifier == Shader::MODIFIER_SIGN); break;
194a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			case Shader::OPCODE_TEXM3X3PAD:   TEXM3X3PAD(x, y, z, s0, pad++ % 2, src0.modifier == Shader::MODIFIER_SIGN);    break;
195a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			case Shader::OPCODE_TEXM3X3TEX:   TEXM3X3TEX(d, x, y, z, dst.index, s0, src0.modifier == Shader::MODIFIER_SIGN); break;
196a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			case Shader::OPCODE_TEXM3X3SPEC:  TEXM3X3SPEC(d, x, y, z, dst.index, s0, s1);                                    break;
197a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			case Shader::OPCODE_TEXM3X3VSPEC: TEXM3X3VSPEC(d, x, y, z, dst.index, s0);                                       break;
198a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			case Shader::OPCODE_CND:          CND(d, s0, s1, s2);                                                            break;
199a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			case Shader::OPCODE_TEXREG2RGB:   TEXREG2RGB(d, s0, dst.index);                                                  break;
200a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			case Shader::OPCODE_TEXDP3TEX:    TEXDP3TEX(d, x, y, z, dst.index, s0);                                          break;
201a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			case Shader::OPCODE_TEXM3X2DEPTH: TEXM3X2DEPTH(d, x, y, z, s0, src0.modifier == Shader::MODIFIER_SIGN);          break;
202a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			case Shader::OPCODE_TEXDP3:       TEXDP3(d, x, y, z, s0);                                                        break;
203a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			case Shader::OPCODE_TEXM3X3:      TEXM3X3(d, x, y, z, s0, src0.modifier == Shader::MODIFIER_SIGN);               break;
204a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			case Shader::OPCODE_TEXDEPTH:     TEXDEPTH();                                                                    break;
205a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			case Shader::OPCODE_CMP0:         CMP(d, s0, s1, s2);                                                            break;
206a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			case Shader::OPCODE_BEM:          BEM(d, s0, s1, dst.index);                                                     break;
207a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			case Shader::OPCODE_PHASE:                                                                                       break;
208a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			case Shader::OPCODE_END:                                                                                         break;
209f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			default:
210f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				ASSERT(false);
211f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			}
212f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
213f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			if(dst.type != Shader::PARAMETER_VOID && opcode != Shader::OPCODE_TEXKILL)
214f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			{
215f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				if(dst.shift > 0)
216f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				{
217f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu					if(dst.mask & 0x1) { d.x = AddSat(d.x, d.x); if(dst.shift > 1) d.x = AddSat(d.x, d.x); if(dst.shift > 2) d.x = AddSat(d.x, d.x); }
218f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu					if(dst.mask & 0x2) { d.y = AddSat(d.y, d.y); if(dst.shift > 1) d.y = AddSat(d.y, d.y); if(dst.shift > 2) d.y = AddSat(d.y, d.y); }
219f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu					if(dst.mask & 0x4) { d.z = AddSat(d.z, d.z); if(dst.shift > 1) d.z = AddSat(d.z, d.z); if(dst.shift > 2) d.z = AddSat(d.z, d.z); }
220f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu					if(dst.mask & 0x8) { d.w = AddSat(d.w, d.w); if(dst.shift > 1) d.w = AddSat(d.w, d.w); if(dst.shift > 2) d.w = AddSat(d.w, d.w); }
221f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				}
222f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				else if(dst.shift < 0)
223f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				{
224f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu					if(dst.mask & 0x1) d.x = d.x >> -dst.shift;
225f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu					if(dst.mask & 0x2) d.y = d.y >> -dst.shift;
226f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu					if(dst.mask & 0x4) d.z = d.z >> -dst.shift;
227f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu					if(dst.mask & 0x8) d.w = d.w >> -dst.shift;
228f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				}
229f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
230f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				if(dst.saturate)
231f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				{
232cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu					if(dst.mask & 0x1) { d.x = Min(d.x, Short4(0x1000)); d.x = Max(d.x, Short4(0x0000)); }
233cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu					if(dst.mask & 0x2) { d.y = Min(d.y, Short4(0x1000)); d.y = Max(d.y, Short4(0x0000)); }
234cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu					if(dst.mask & 0x4) { d.z = Min(d.z, Short4(0x1000)); d.z = Max(d.z, Short4(0x0000)); }
235cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu					if(dst.mask & 0x8) { d.w = Min(d.w, Short4(0x1000)); d.w = Max(d.w, Short4(0x0000)); }
236f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				}
237f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
238f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				if(pairing)
239f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				{
240f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu					if(dst.mask & 0x1) dPairing.x = d.x;
241f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu					if(dst.mask & 0x2) dPairing.y = d.y;
242f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu					if(dst.mask & 0x4) dPairing.z = d.z;
243f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu					if(dst.mask & 0x8) dPairing.w = d.w;
244f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				}
245f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
246f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				if(coissue)
247f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				{
248f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu					const Dst &dst = shader->getInstruction(i - 1)->dst;
249f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
250a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens					writeDestination(dPairing, dst);
251f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				}
252f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
253f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				if(!pairing)
254f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				{
255a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens					writeDestination(d, dst);
256f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				}
257f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			}
258f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
2596270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens	}
2606270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens
261a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens	Bool PixelPipeline::alphaTest(Int cMask[4])
2626270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens	{
263cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu		current.x = Min(current.x, Short4(0x0FFF)); current.x = Max(current.x, Short4(0x0000));
264cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu		current.y = Min(current.y, Short4(0x0FFF)); current.y = Max(current.y, Short4(0x0000));
265cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu		current.z = Min(current.z, Short4(0x0FFF)); current.z = Max(current.z, Short4(0x0000));
266cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu		current.w = Min(current.w, Short4(0x0FFF)); current.w = Max(current.w, Short4(0x0000));
267f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
268f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		if(!state.alphaTestActive())
269f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
270f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			return true;
271f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
272f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
273f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Int aMask;
274f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
275f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		if(state.transparencyAntialiasing == TRANSPARENCY_NONE)
276f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
277a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			PixelRoutine::alphaTest(aMask, current.w);
278f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
279f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			for(unsigned int q = 0; q < state.multiSample; q++)
280f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			{
281f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				cMask[q] &= aMask;
282f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			}
283f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
284f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		else if(state.transparencyAntialiasing == TRANSPARENCY_ALPHA_TO_COVERAGE)
285f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
286a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			Float4 alpha = Float4(current.w) * Float4(1.0f / 0x1000);
287f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
288a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			alphaToCoverage(cMask, alpha);
289f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
290f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		else ASSERT(false);
291f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
292f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Int pass = cMask[0];
293f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
294f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		for(unsigned int q = 1; q < state.multiSample; q++)
295f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
296f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			pass = pass | cMask[q];
297f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
298f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
2996270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens		return pass != 0x0;
3006270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens	}
3016270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens
302a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens	void PixelPipeline::rasterOperation(Float4 &fog, Pointer<Byte> cBuffer[4], Int &x, Int sMask[4], Int zMask[4], Int cMask[4])
3036270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens	{
304f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		if(!state.colorWriteActive(0))
305f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
306f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			return;
307f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
308f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
309f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Vector4f oC;
310f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
311f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		switch(state.targetFormat[0])
312f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
313f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case FORMAT_R5G6B5:
314f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case FORMAT_X8R8G8B8:
315f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case FORMAT_X8B8G8R8:
316f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case FORMAT_A8R8G8B8:
317f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case FORMAT_A8B8G8R8:
318f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case FORMAT_A8:
319f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case FORMAT_G16R16:
320f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case FORMAT_A16B16G16R16:
321f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			if(!postBlendSRGB && state.writeSRGB)
322f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			{
323a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				linearToSRGB12_16(current);
324f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			}
325f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			else
326f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			{
327a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				current.x <<= 4;
328a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				current.y <<= 4;
329a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				current.z <<= 4;
330a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				current.w <<= 4;
331f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			}
332f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
333f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			if(state.targetFormat[0] == FORMAT_R5G6B5)
334f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			{
335a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				current.x &= Short4(0xF800u);
336a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				current.y &= Short4(0xFC00u);
337a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				current.z &= Short4(0xF800u);
338f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			}
339f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
340a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			fogBlend(current, fog);
341f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
342f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			for(unsigned int q = 0; q < state.multiSample; q++)
343f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			{
344a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				Pointer<Byte> buffer = cBuffer[0] + q * *Pointer<Int>(data + OFFSET(DrawData, colorSliceB[0]));
345a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				Vector4s color = current;
346f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
347f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				if(state.multiSampleMask & (1 << q))
348f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				{
349a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens					alphaBlend(0, buffer, color, x);
350a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens					logicOperation(0, buffer, color, x);
351a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens					writeColor(0, buffer, x, color, sMask[q], zMask[q], cMask[q]);
352f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				}
353f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			}
354f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
355f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case FORMAT_R32F:
356f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case FORMAT_G32R32F:
357f946d78bc45fed74fbad8343f415e2a5d0fb2187Alexis Hetu		case FORMAT_X32B32G32R32F:
358f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case FORMAT_A32B32G32R32F:
359a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			convertSigned12(oC, current);
360a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			PixelRoutine::fogBlend(oC, fog);
361f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
362f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			for(unsigned int q = 0; q < state.multiSample; q++)
363f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			{
364a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				Pointer<Byte> buffer = cBuffer[0] + q * *Pointer<Int>(data + OFFSET(DrawData, colorSliceB[0]));
365f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				Vector4f color = oC;
366f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
367f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				if(state.multiSampleMask & (1 << q))
368f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				{
369a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens					alphaBlend(0, buffer, color, x);
370a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens					writeColor(0, buffer, x, color, sMask[q], zMask[q], cMask[q]);
371f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				}
372f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			}
373f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
374f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		default:
375f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			ASSERT(false);
3766270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens		}
3776270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens	}
3786270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens
379a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens	void PixelPipeline::blendTexture(Vector4s &temp, Vector4s &texture, int stage)
380f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
3815c1bdd21ac35e805af79dd426499603fc7b7f8ceAlexis Hetu		Vector4s *arg1 = nullptr;
3825c1bdd21ac35e805af79dd426499603fc7b7f8ceAlexis Hetu		Vector4s *arg2 = nullptr;
3835c1bdd21ac35e805af79dd426499603fc7b7f8ceAlexis Hetu		Vector4s *arg3 = nullptr;
384f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Vector4s res;
385f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
386f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Vector4s constant;
387f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Vector4s tfactor;
388f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
389f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		const TextureStage::State &textureStage = state.textureStage[stage];
390f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
391f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		if(textureStage.firstArgument == TextureStage::SOURCE_CONSTANT ||
392f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		   textureStage.firstArgumentAlpha == TextureStage::SOURCE_CONSTANT ||
393f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		   textureStage.secondArgument == TextureStage::SOURCE_CONSTANT ||
394f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		   textureStage.secondArgumentAlpha == TextureStage::SOURCE_CONSTANT ||
395f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		   textureStage.thirdArgument == TextureStage::SOURCE_CONSTANT ||
396f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		   textureStage.thirdArgumentAlpha == TextureStage::SOURCE_CONSTANT)
397f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
398a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			constant.x = *Pointer<Short4>(data + OFFSET(DrawData, textureStage[stage].constantColor4[0]));
399a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			constant.y = *Pointer<Short4>(data + OFFSET(DrawData, textureStage[stage].constantColor4[1]));
400a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			constant.z = *Pointer<Short4>(data + OFFSET(DrawData, textureStage[stage].constantColor4[2]));
401a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			constant.w = *Pointer<Short4>(data + OFFSET(DrawData, textureStage[stage].constantColor4[3]));
402f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
403f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
404f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		if(textureStage.firstArgument == TextureStage::SOURCE_TFACTOR ||
405f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		   textureStage.firstArgumentAlpha == TextureStage::SOURCE_TFACTOR ||
406f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		   textureStage.secondArgument == TextureStage::SOURCE_TFACTOR ||
407f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		   textureStage.secondArgumentAlpha == TextureStage::SOURCE_TFACTOR ||
408f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		   textureStage.thirdArgument == TextureStage::SOURCE_TFACTOR ||
409f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		   textureStage.thirdArgumentAlpha == TextureStage::SOURCE_TFACTOR)
410f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
411a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			tfactor.x = *Pointer<Short4>(data + OFFSET(DrawData, factor.textureFactor4[0]));
412a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			tfactor.y = *Pointer<Short4>(data + OFFSET(DrawData, factor.textureFactor4[1]));
413a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			tfactor.z = *Pointer<Short4>(data + OFFSET(DrawData, factor.textureFactor4[2]));
414a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			tfactor.w = *Pointer<Short4>(data + OFFSET(DrawData, factor.textureFactor4[3]));
415f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
416f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
417f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		// Premodulate
418f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		if(stage > 0 && textureStage.usesTexture)
419f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
420f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			if(state.textureStage[stage - 1].stageOperation == TextureStage::STAGE_PREMODULATE)
421f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			{
422a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				current.x = MulHigh(current.x, texture.x) << 4;
423a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				current.y = MulHigh(current.y, texture.y) << 4;
424a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				current.z = MulHigh(current.z, texture.z) << 4;
425f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			}
426f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
427f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			if(state.textureStage[stage - 1].stageOperationAlpha == TextureStage::STAGE_PREMODULATE)
428f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			{
429a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				current.w = MulHigh(current.w, texture.w) << 4;
430f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			}
431f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
432f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
433f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		if(luminance)
434f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
435a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			texture.x = MulHigh(texture.x, L) << 4;
436a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			texture.y = MulHigh(texture.y, L) << 4;
437a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			texture.z = MulHigh(texture.z, L) << 4;
438f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
439f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			luminance = false;
440f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
441f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
442f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		switch(textureStage.firstArgument)
443f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
444f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::SOURCE_TEXTURE:	arg1 = &texture;    break;
445f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::SOURCE_CONSTANT:	arg1 = &constant;   break;
446a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		case TextureStage::SOURCE_CURRENT:	arg1 = &current;  break;
447a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		case TextureStage::SOURCE_DIFFUSE:	arg1 = &diffuse;  break;
448a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		case TextureStage::SOURCE_SPECULAR:	arg1 = &specular; break;
449f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::SOURCE_TEMP:		arg1 = &temp;       break;
450f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::SOURCE_TFACTOR:	arg1 = &tfactor;    break;
451f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		default:
452f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			ASSERT(false);
453f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
454f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
455f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		switch(textureStage.secondArgument)
456f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
457f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::SOURCE_TEXTURE:	arg2 = &texture;    break;
458f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::SOURCE_CONSTANT:	arg2 = &constant;   break;
459a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		case TextureStage::SOURCE_CURRENT:	arg2 = &current;  break;
460a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		case TextureStage::SOURCE_DIFFUSE:	arg2 = &diffuse;  break;
461a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		case TextureStage::SOURCE_SPECULAR:	arg2 = &specular; break;
462f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::SOURCE_TEMP:		arg2 = &temp;       break;
463f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::SOURCE_TFACTOR:	arg2 = &tfactor;    break;
464f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		default:
465f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			ASSERT(false);
466f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
467f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
468f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		switch(textureStage.thirdArgument)
469f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
470f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::SOURCE_TEXTURE:	arg3 = &texture;    break;
471f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::SOURCE_CONSTANT:	arg3 = &constant;   break;
472a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		case TextureStage::SOURCE_CURRENT:	arg3 = &current;  break;
473a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		case TextureStage::SOURCE_DIFFUSE:	arg3 = &diffuse;  break;
474a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		case TextureStage::SOURCE_SPECULAR:	arg3 = &specular; break;
475f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::SOURCE_TEMP:		arg3 = &temp;       break;
476f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::SOURCE_TFACTOR:	arg3 = &tfactor;    break;
477f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		default:
478f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			ASSERT(false);
479f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
480f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
481f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Vector4s mod1;
482f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Vector4s mod2;
483f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Vector4s mod3;
484f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
485f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		switch(textureStage.firstModifier)
486f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
487f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::MODIFIER_COLOR:
488f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
489f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::MODIFIER_INVCOLOR:
490f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod1.x = SubSat(Short4(0x1000), arg1->x);
491f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod1.y = SubSat(Short4(0x1000), arg1->y);
492f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod1.z = SubSat(Short4(0x1000), arg1->z);
493f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod1.w = SubSat(Short4(0x1000), arg1->w);
494f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
495f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			arg1 = &mod1;
496f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
497f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::MODIFIER_ALPHA:
498f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod1.x = arg1->w;
499f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod1.y = arg1->w;
500f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod1.z = arg1->w;
501f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod1.w = arg1->w;
502f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
503f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			arg1 = &mod1;
504f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
505f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::MODIFIER_INVALPHA:
506f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod1.x = SubSat(Short4(0x1000), arg1->w);
507f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod1.y = SubSat(Short4(0x1000), arg1->w);
508f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod1.z = SubSat(Short4(0x1000), arg1->w);
509f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod1.w = SubSat(Short4(0x1000), arg1->w);
510f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
511f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			arg1 = &mod1;
512f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
513f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		default:
514f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			ASSERT(false);
515f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
516f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
517f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		switch(textureStage.secondModifier)
518f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
519f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::MODIFIER_COLOR:
520f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
521f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::MODIFIER_INVCOLOR:
522f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod2.x = SubSat(Short4(0x1000), arg2->x);
523f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod2.y = SubSat(Short4(0x1000), arg2->y);
524f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod2.z = SubSat(Short4(0x1000), arg2->z);
525f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod2.w = SubSat(Short4(0x1000), arg2->w);
526f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
527f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			arg2 = &mod2;
528f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
529f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::MODIFIER_ALPHA:
530f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod2.x = arg2->w;
531f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod2.y = arg2->w;
532f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod2.z = arg2->w;
533f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod2.w = arg2->w;
534f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
535f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			arg2 = &mod2;
536f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
537f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::MODIFIER_INVALPHA:
538f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod2.x = SubSat(Short4(0x1000), arg2->w);
539f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod2.y = SubSat(Short4(0x1000), arg2->w);
540f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod2.z = SubSat(Short4(0x1000), arg2->w);
541f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod2.w = SubSat(Short4(0x1000), arg2->w);
542f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
543f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			arg2 = &mod2;
544f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
545f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		default:
546f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			ASSERT(false);
547f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
548f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
549f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		switch(textureStage.thirdModifier)
550f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
551f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::MODIFIER_COLOR:
552f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
553f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::MODIFIER_INVCOLOR:
554f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod3.x = SubSat(Short4(0x1000), arg3->x);
555f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod3.y = SubSat(Short4(0x1000), arg3->y);
556f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod3.z = SubSat(Short4(0x1000), arg3->z);
557f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod3.w = SubSat(Short4(0x1000), arg3->w);
558f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
559f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			arg3 = &mod3;
560f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
561f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::MODIFIER_ALPHA:
562f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod3.x = arg3->w;
563f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod3.y = arg3->w;
564f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod3.z = arg3->w;
565f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod3.w = arg3->w;
566f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
567f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			arg3 = &mod3;
568f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
569f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::MODIFIER_INVALPHA:
570f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod3.x = SubSat(Short4(0x1000), arg3->w);
571f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod3.y = SubSat(Short4(0x1000), arg3->w);
572f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod3.z = SubSat(Short4(0x1000), arg3->w);
573f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod3.w = SubSat(Short4(0x1000), arg3->w);
574f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
575f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			arg3 = &mod3;
576f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
577f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		default:
578f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			ASSERT(false);
579f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
580f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
581f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		switch(textureStage.stageOperation)
582f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
583f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_DISABLE:
584f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
585f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_SELECTARG1: // Arg1
586f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.x = arg1->x;
587f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.y = arg1->y;
588f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.z = arg1->z;
589f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
590f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_SELECTARG2: // Arg2
591f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.x = arg2->x;
592f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.y = arg2->y;
593f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.z = arg2->z;
594f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
595f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_SELECTARG3: // Arg3
596f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.x = arg3->x;
597f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.y = arg3->y;
598f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.z = arg3->z;
599f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
600f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATE: // Arg1 * Arg2
601f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.x = MulHigh(arg1->x, arg2->x) << 4;
602f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.y = MulHigh(arg1->y, arg2->y) << 4;
603f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.z = MulHigh(arg1->z, arg2->z) << 4;
604f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
605f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATE2X: // Arg1 * Arg2 * 2
606f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.x = MulHigh(arg1->x, arg2->x) << 5;
607f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.y = MulHigh(arg1->y, arg2->y) << 5;
608f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.z = MulHigh(arg1->z, arg2->z) << 5;
609f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
610f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATE4X: // Arg1 * Arg2 * 4
611f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.x = MulHigh(arg1->x, arg2->x) << 6;
612f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.y = MulHigh(arg1->y, arg2->y) << 6;
613f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.z = MulHigh(arg1->z, arg2->z) << 6;
614f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
615f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_ADD: // Arg1 + Arg2
616f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.x = AddSat(arg1->x, arg2->x);
617f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.y = AddSat(arg1->y, arg2->y);
618f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.z = AddSat(arg1->z, arg2->z);
619f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
620f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_ADDSIGNED: // Arg1 + Arg2 - 0.5
621f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.x = AddSat(arg1->x, arg2->x);
622f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.y = AddSat(arg1->y, arg2->y);
623f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.z = AddSat(arg1->z, arg2->z);
624f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
625cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			res.x = SubSat(res.x, Short4(0x0800));
626cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			res.y = SubSat(res.y, Short4(0x0800));
627cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			res.z = SubSat(res.z, Short4(0x0800));
628f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
629f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_ADDSIGNED2X: // (Arg1 + Arg2 - 0.5) << 1
630f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.x = AddSat(arg1->x, arg2->x);
631f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.y = AddSat(arg1->y, arg2->y);
632f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.z = AddSat(arg1->z, arg2->z);
633f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
634cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			res.x = SubSat(res.x, Short4(0x0800));
635cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			res.y = SubSat(res.y, Short4(0x0800));
636cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			res.z = SubSat(res.z, Short4(0x0800));
637f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
638f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.x = AddSat(res.x, res.x);
639f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.y = AddSat(res.y, res.y);
640f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.z = AddSat(res.z, res.z);
641f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
642f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_SUBTRACT: // Arg1 - Arg2
643f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.x = SubSat(arg1->x, arg2->x);
644f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.y = SubSat(arg1->y, arg2->y);
645f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.z = SubSat(arg1->z, arg2->z);
646f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
647f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_ADDSMOOTH: // Arg1 + Arg2 - Arg1 * Arg2
648f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			{
649f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				Short4 tmp;
650f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
651f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				tmp = MulHigh(arg1->x, arg2->x) << 4; res.x = AddSat(arg1->x, arg2->x); res.x = SubSat(res.x, tmp);
652f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				tmp = MulHigh(arg1->y, arg2->y) << 4; res.y = AddSat(arg1->y, arg2->y); res.y = SubSat(res.y, tmp);
653f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				tmp = MulHigh(arg1->z, arg2->z) << 4; res.z = AddSat(arg1->z, arg2->z); res.z = SubSat(res.z, tmp);
654f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			}
655f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
656f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MULTIPLYADD: // Arg3 + Arg1 * Arg2
657f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.x = MulHigh(arg1->x, arg2->x) << 4; res.x = AddSat(res.x, arg3->x);
658f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.y = MulHigh(arg1->y, arg2->y) << 4; res.y = AddSat(res.y, arg3->y);
659f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.z = MulHigh(arg1->z, arg2->z) << 4; res.z = AddSat(res.z, arg3->z);
660f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
661f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_LERP: // Arg3 * (Arg1 - Arg2) + Arg2
662f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.x = SubSat(arg1->x, arg2->x); res.x = MulHigh(res.x, arg3->x) << 4; res.x = AddSat(res.x, arg2->x);
663f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.y = SubSat(arg1->y, arg2->y); res.y = MulHigh(res.y, arg3->y) << 4; res.y = AddSat(res.y, arg2->y);
664f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.z = SubSat(arg1->z, arg2->z); res.z = MulHigh(res.z, arg3->z) << 4; res.z = AddSat(res.z, arg2->z);
665f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
666f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_DOT3: // 2 * (Arg1.x - 0.5) * 2 * (Arg2.x - 0.5) + 2 * (Arg1.y - 0.5) * 2 * (Arg2.y - 0.5) + 2 * (Arg1.z - 0.5) * 2 * (Arg2.z - 0.5)
667f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			{
668f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				Short4 tmp;
669f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
670cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu				res.x = SubSat(arg1->x, Short4(0x0800)); tmp = SubSat(arg2->x, Short4(0x0800)); res.x = MulHigh(res.x, tmp);
671cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu				res.y = SubSat(arg1->y, Short4(0x0800)); tmp = SubSat(arg2->y, Short4(0x0800)); res.y = MulHigh(res.y, tmp);
672cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu				res.z = SubSat(arg1->z, Short4(0x0800)); tmp = SubSat(arg2->z, Short4(0x0800)); res.z = MulHigh(res.z, tmp);
673f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
674f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				res.x = res.x << 6;
675f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				res.y = res.y << 6;
676f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				res.z = res.z << 6;
677f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
678f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				res.x = AddSat(res.x, res.y);
679f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				res.x = AddSat(res.x, res.z);
680f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
681f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				// Clamp to [0, 1]
682cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu				res.x = Max(res.x, Short4(0x0000));
683f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				res.x = Min(res.x, Short4(0x1000));
684f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
685f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				res.y = res.x;
686f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				res.z = res.x;
687f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				res.w = res.x;
688f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			}
689f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
690f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BLENDCURRENTALPHA: // Alpha * (Arg1 - Arg2) + Arg2
691a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			res.x = SubSat(arg1->x, arg2->x); res.x = MulHigh(res.x, current.w) << 4; res.x = AddSat(res.x, arg2->x);
692a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			res.y = SubSat(arg1->y, arg2->y); res.y = MulHigh(res.y, current.w) << 4; res.y = AddSat(res.y, arg2->y);
693a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			res.z = SubSat(arg1->z, arg2->z); res.z = MulHigh(res.z, current.w) << 4; res.z = AddSat(res.z, arg2->z);
694f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
695f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BLENDDIFFUSEALPHA: // Alpha * (Arg1 - Arg2) + Arg2
696a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			res.x = SubSat(arg1->x, arg2->x); res.x = MulHigh(res.x, diffuse.w) << 4; res.x = AddSat(res.x, arg2->x);
697a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			res.y = SubSat(arg1->y, arg2->y); res.y = MulHigh(res.y, diffuse.w) << 4; res.y = AddSat(res.y, arg2->y);
698a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			res.z = SubSat(arg1->z, arg2->z); res.z = MulHigh(res.z, diffuse.w) << 4; res.z = AddSat(res.z, arg2->z);
699f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
700f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BLENDFACTORALPHA: // Alpha * (Arg1 - Arg2) + Arg2
701a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			res.x = SubSat(arg1->x, arg2->x); res.x = MulHigh(res.x, *Pointer<Short4>(data + OFFSET(DrawData, factor.textureFactor4[3]))) << 4; res.x = AddSat(res.x, arg2->x);
702a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			res.y = SubSat(arg1->y, arg2->y); res.y = MulHigh(res.y, *Pointer<Short4>(data + OFFSET(DrawData, factor.textureFactor4[3]))) << 4; res.y = AddSat(res.y, arg2->y);
703a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			res.z = SubSat(arg1->z, arg2->z); res.z = MulHigh(res.z, *Pointer<Short4>(data + OFFSET(DrawData, factor.textureFactor4[3]))) << 4; res.z = AddSat(res.z, arg2->z);
704f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
705f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BLENDTEXTUREALPHA: // Alpha * (Arg1 - Arg2) + Arg2
706f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.x = SubSat(arg1->x, arg2->x); res.x = MulHigh(res.x, texture.w) << 4; res.x = AddSat(res.x, arg2->x);
707f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.y = SubSat(arg1->y, arg2->y); res.y = MulHigh(res.y, texture.w) << 4; res.y = AddSat(res.y, arg2->y);
708f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.z = SubSat(arg1->z, arg2->z); res.z = MulHigh(res.z, texture.w) << 4; res.z = AddSat(res.z, arg2->z);
709f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
710f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BLENDTEXTUREALPHAPM: // Arg1 + Arg2 * (1 - Alpha)
711f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.x = SubSat(Short4(0x1000), texture.w); res.x = MulHigh(res.x, arg2->x) << 4; res.x = AddSat(res.x, arg1->x);
712f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.y = SubSat(Short4(0x1000), texture.w); res.y = MulHigh(res.y, arg2->y) << 4; res.y = AddSat(res.y, arg1->y);
713f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.z = SubSat(Short4(0x1000), texture.w); res.z = MulHigh(res.z, arg2->z) << 4; res.z = AddSat(res.z, arg1->z);
714f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
715f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_PREMODULATE:
716f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.x = arg1->x;
717f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.y = arg1->y;
718f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.z = arg1->z;
719f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
720f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATEALPHA_ADDCOLOR: // Arg1 + Arg1.w * Arg2
721f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.x = MulHigh(arg1->w, arg2->x) << 4; res.x = AddSat(res.x, arg1->x);
722f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.y = MulHigh(arg1->w, arg2->y) << 4; res.y = AddSat(res.y, arg1->y);
723f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.z = MulHigh(arg1->w, arg2->z) << 4; res.z = AddSat(res.z, arg1->z);
724f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
725f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATECOLOR_ADDALPHA: // Arg1 * Arg2 + Arg1.w
726f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.x = MulHigh(arg1->x, arg2->x) << 4; res.x = AddSat(res.x, arg1->w);
727f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.y = MulHigh(arg1->y, arg2->y) << 4; res.y = AddSat(res.y, arg1->w);
728f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.z = MulHigh(arg1->z, arg2->z) << 4; res.z = AddSat(res.z, arg1->w);
729f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
730f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATEINVALPHA_ADDCOLOR: // (1 - Arg1.w) * Arg2 + Arg1
731f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			{
732f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				Short4 tmp;
733f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
734f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				res.x = AddSat(arg1->x, arg2->x); tmp = MulHigh(arg1->w, arg2->x) << 4; res.x = SubSat(res.x, tmp);
735f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				res.y = AddSat(arg1->y, arg2->y); tmp = MulHigh(arg1->w, arg2->y) << 4; res.y = SubSat(res.y, tmp);
736f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				res.z = AddSat(arg1->z, arg2->z); tmp = MulHigh(arg1->w, arg2->z) << 4; res.z = SubSat(res.z, tmp);
737f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			}
738f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
739f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATEINVCOLOR_ADDALPHA: // (1 - Arg1) * Arg2 + Arg1.w
740f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			{
741f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				Short4 tmp;
742f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
743f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				res.x = AddSat(arg1->w, arg2->x); tmp = MulHigh(arg1->x, arg2->x) << 4; res.x = SubSat(res.x, tmp);
744f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				res.y = AddSat(arg1->w, arg2->y); tmp = MulHigh(arg1->y, arg2->y) << 4; res.y = SubSat(res.y, tmp);
745f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				res.z = AddSat(arg1->w, arg2->z); tmp = MulHigh(arg1->z, arg2->z) << 4; res.z = SubSat(res.z, tmp);
746f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			}
747f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
748f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BUMPENVMAP:
749f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			{
750a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				du = Float4(texture.x) * Float4(1.0f / 0x0FE0);
751a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				dv = Float4(texture.y) * Float4(1.0f / 0x0FE0);
752f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
753f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				Float4 du2;
754f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				Float4 dv2;
755f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
756a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				du2 = du;
757a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				dv2 = dv;
758a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				du *= *Pointer<Float4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4F[0][0]));
759a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				dv2 *= *Pointer<Float4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4F[1][0]));
760a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				du += dv2;
761a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				dv *= *Pointer<Float4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4F[1][1]));
762a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				du2 *= *Pointer<Float4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4F[0][1]));
763a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				dv += du2;
764f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
765f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				perturbate = true;
766f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
767a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				res.x = current.x;
768a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				res.y = current.y;
769a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				res.z = current.z;
770a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				res.w = current.w;
771f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			}
772f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
773f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BUMPENVMAPLUMINANCE:
774f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			{
775a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				du = Float4(texture.x) * Float4(1.0f / 0x0FE0);
776a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				dv = Float4(texture.y) * Float4(1.0f / 0x0FE0);
777f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
778f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				Float4 du2;
779f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				Float4 dv2;
780f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
781a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				du2 = du;
782a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				dv2 = dv;
783f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
784a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				du *= *Pointer<Float4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4F[0][0]));
785a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				dv2 *= *Pointer<Float4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4F[1][0]));
786a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				du += dv2;
787a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				dv *= *Pointer<Float4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4F[1][1]));
788a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				du2 *= *Pointer<Float4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4F[0][1]));
789a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				dv += du2;
790f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
791f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				perturbate = true;
792f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
793a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				L = texture.z;
794a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				L = MulHigh(L, *Pointer<Short4>(data + OFFSET(DrawData, textureStage[stage].luminanceScale4)));
795a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				L = L << 4;
796a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				L = AddSat(L, *Pointer<Short4>(data + OFFSET(DrawData, textureStage[stage].luminanceOffset4)));
797cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu				L = Max(L, Short4(0x0000));
798a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				L = Min(L, Short4(0x1000));
799f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
800f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				luminance = true;
801f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
802a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				res.x = current.x;
803a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				res.y = current.y;
804a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				res.z = current.z;
805a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				res.w = current.w;
806f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			}
807f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
808f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		default:
809f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			ASSERT(false);
810f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
811f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
812f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		if(textureStage.stageOperation != TextureStage::STAGE_DOT3)
813f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
814f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			switch(textureStage.firstArgumentAlpha)
815f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			{
816f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::SOURCE_TEXTURE:	arg1 = &texture;		break;
817f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::SOURCE_CONSTANT:	arg1 = &constant;		break;
818a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			case TextureStage::SOURCE_CURRENT:	arg1 = &current;		break;
819a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			case TextureStage::SOURCE_DIFFUSE:	arg1 = &diffuse;		break;
820a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			case TextureStage::SOURCE_SPECULAR:	arg1 = &specular;		break;
821f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::SOURCE_TEMP:		arg1 = &temp;			break;
822f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::SOURCE_TFACTOR:	arg1 = &tfactor;		break;
823f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			default:
824f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				ASSERT(false);
825f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			}
826f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
827f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			switch(textureStage.secondArgumentAlpha)
828f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			{
829f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::SOURCE_TEXTURE:	arg2 = &texture;		break;
830f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::SOURCE_CONSTANT:	arg2 = &constant;		break;
831a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			case TextureStage::SOURCE_CURRENT:	arg2 = &current;		break;
832a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			case TextureStage::SOURCE_DIFFUSE:	arg2 = &diffuse;		break;
833a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			case TextureStage::SOURCE_SPECULAR:	arg2 = &specular;		break;
834f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::SOURCE_TEMP:		arg2 = &temp;			break;
835f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::SOURCE_TFACTOR:	arg2 = &tfactor;		break;
836f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			default:
837f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				ASSERT(false);
838f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			}
839f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
840f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			switch(textureStage.thirdArgumentAlpha)
841f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			{
842f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::SOURCE_TEXTURE:	arg3 = &texture;		break;
843f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::SOURCE_CONSTANT:	arg3 = &constant;		break;
844a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			case TextureStage::SOURCE_CURRENT:	arg3 = &current;		break;
845a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			case TextureStage::SOURCE_DIFFUSE:	arg3 = &diffuse;		break;
846a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			case TextureStage::SOURCE_SPECULAR:	arg3 = &specular;		break;
847f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::SOURCE_TEMP:		arg3 = &temp;			break;
848f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::SOURCE_TFACTOR:	arg3 = &tfactor;		break;
849f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			default:
850f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				ASSERT(false);
851f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			}
852f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
853f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			switch(textureStage.firstModifierAlpha)   // FIXME: Check if actually used
854f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			{
855f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::MODIFIER_COLOR:
856f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
857f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::MODIFIER_INVCOLOR:
858f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				mod1.w = SubSat(Short4(0x1000), arg1->w);
859f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
860f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				arg1 = &mod1;
861f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
862f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::MODIFIER_ALPHA:
863f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				// Redudant
864f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
865f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::MODIFIER_INVALPHA:
866f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				mod1.w = SubSat(Short4(0x1000), arg1->w);
867f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
868f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				arg1 = &mod1;
869f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
870f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			default:
871f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				ASSERT(false);
872f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			}
873f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
874f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			switch(textureStage.secondModifierAlpha)   // FIXME: Check if actually used
875f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			{
876f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::MODIFIER_COLOR:
877f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
878f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::MODIFIER_INVCOLOR:
879f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				mod2.w = SubSat(Short4(0x1000), arg2->w);
880f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
881f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				arg2 = &mod2;
882f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
883f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::MODIFIER_ALPHA:
884f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				// Redudant
885f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
886f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::MODIFIER_INVALPHA:
887f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				mod2.w = SubSat(Short4(0x1000), arg2->w);
888f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
889f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				arg2 = &mod2;
890f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
891f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			default:
892f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				ASSERT(false);
893f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			}
894f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
895f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			switch(textureStage.thirdModifierAlpha)   // FIXME: Check if actually used
896f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			{
897f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::MODIFIER_COLOR:
898f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
899f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::MODIFIER_INVCOLOR:
900f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				mod3.w = SubSat(Short4(0x1000), arg3->w);
901f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
902f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				arg3 = &mod3;
903f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
904f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::MODIFIER_ALPHA:
905f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				// Redudant
906f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
907f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::MODIFIER_INVALPHA:
908f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				mod3.w = SubSat(Short4(0x1000), arg3->w);
909f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
910f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				arg3 = &mod3;
911f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
912f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			default:
913f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				ASSERT(false);
914f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			}
915f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
916f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			switch(textureStage.stageOperationAlpha)
917f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			{
918f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::STAGE_DISABLE:
919f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
920f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::STAGE_SELECTARG1: // Arg1
921f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				res.w = arg1->w;
922f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
923f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::STAGE_SELECTARG2: // Arg2
924f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				res.w = arg2->w;
925f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
926f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::STAGE_SELECTARG3: // Arg3
927f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				res.w = arg3->w;
928f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
929f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::STAGE_MODULATE: // Arg1 * Arg2
930f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				res.w = MulHigh(arg1->w, arg2->w) << 4;
931f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
932f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::STAGE_MODULATE2X: // Arg1 * Arg2 * 2
933f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				res.w = MulHigh(arg1->w, arg2->w) << 5;
934f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
935f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::STAGE_MODULATE4X: // Arg1 * Arg2 * 4
936f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				res.w = MulHigh(arg1->w, arg2->w) << 6;
937f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
938f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::STAGE_ADD: // Arg1 + Arg2
939f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				res.w = AddSat(arg1->w, arg2->w);
940f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
941f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::STAGE_ADDSIGNED: // Arg1 + Arg2 - 0.5
942f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				res.w = AddSat(arg1->w, arg2->w);
943cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu				res.w = SubSat(res.w, Short4(0x0800));
944f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
945f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::STAGE_ADDSIGNED2X: // (Arg1 + Arg2 - 0.5) << 1
946f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				res.w = AddSat(arg1->w, arg2->w);
947cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu				res.w = SubSat(res.w, Short4(0x0800));
948f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				res.w = AddSat(res.w, res.w);
949f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
950f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::STAGE_SUBTRACT: // Arg1 - Arg2
951f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				res.w = SubSat(arg1->w, arg2->w);
952f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
953f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::STAGE_ADDSMOOTH: // Arg1 + Arg2 - Arg1 * Arg2
954f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				{
955f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu					Short4 tmp;
956f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
957f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu					tmp = MulHigh(arg1->w, arg2->w) << 4; res.w = AddSat(arg1->w, arg2->w); res.w = SubSat(res.w, tmp);
958f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				}
959f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
960f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::STAGE_MULTIPLYADD: // Arg3 + Arg1 * Arg2
961f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				res.w = MulHigh(arg1->w, arg2->w) << 4; res.w = AddSat(res.w, arg3->w);
962f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
963f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::STAGE_LERP: // Arg3 * (Arg1 - Arg2) + Arg2
964f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				res.w = SubSat(arg1->w, arg2->w); res.w = MulHigh(res.w, arg3->w) << 4; res.w = AddSat(res.w, arg2->w);
965f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
966f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::STAGE_DOT3:
967f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;   // Already computed in color channel
968f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::STAGE_BLENDCURRENTALPHA: // Alpha * (Arg1 - Arg2) + Arg2
969a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				res.w = SubSat(arg1->w, arg2->w); res.w = MulHigh(res.w, current.w) << 4; res.w = AddSat(res.w, arg2->w);
970f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
971f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::STAGE_BLENDDIFFUSEALPHA: // Arg1 * (Alpha) + Arg2 * (1 - Alpha)
972a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				res.w = SubSat(arg1->w, arg2->w); res.w = MulHigh(res.w, diffuse.w) << 4; res.w = AddSat(res.w, arg2->w);
973f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
974f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::STAGE_BLENDFACTORALPHA:
975a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens				res.w = SubSat(arg1->w, arg2->w); res.w = MulHigh(res.w, *Pointer<Short4>(data + OFFSET(DrawData, factor.textureFactor4[3]))) << 4; res.w = AddSat(res.w, arg2->w);
976f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
977f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::STAGE_BLENDTEXTUREALPHA: // Arg1 * (Alpha) + Arg2 * (1 - Alpha)
978f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				res.w = SubSat(arg1->w, arg2->w); res.w = MulHigh(res.w, texture.w) << 4; res.w = AddSat(res.w, arg2->w);
979f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
980f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::STAGE_BLENDTEXTUREALPHAPM: // Arg1 + Arg2 * (1 - Alpha)
981f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				res.w = SubSat(Short4(0x1000), texture.w); res.w = MulHigh(res.w, arg2->w) << 4; res.w = AddSat(res.w, arg1->w);
982f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
983f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::STAGE_PREMODULATE:
984f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				res.w = arg1->w;
985f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;
986f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::STAGE_MODULATEALPHA_ADDCOLOR:
987f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::STAGE_MODULATECOLOR_ADDALPHA:
988f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::STAGE_MODULATEINVALPHA_ADDCOLOR:
989f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::STAGE_MODULATEINVCOLOR_ADDALPHA:
990f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::STAGE_BUMPENVMAP:
991f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			case TextureStage::STAGE_BUMPENVMAPLUMINANCE:
992f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;   // Invalid alpha operations
993f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			default:
994f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				ASSERT(false);
995f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			}
996f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
997f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
998f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		// Clamp result to [0, 1]
999f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1000f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		switch(textureStage.stageOperation)
1001f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1002f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_DISABLE:
1003f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_SELECTARG1:
1004f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_SELECTARG2:
1005f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_SELECTARG3:
1006f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATE:
1007f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATE2X:
1008f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATE4X:
1009f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_ADD:
1010f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MULTIPLYADD:
1011f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_LERP:
1012f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BLENDCURRENTALPHA:
1013f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BLENDDIFFUSEALPHA:
1014f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BLENDFACTORALPHA:
1015f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BLENDTEXTUREALPHA:
1016f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BLENDTEXTUREALPHAPM:
1017f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_DOT3:   // Already clamped
1018f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_PREMODULATE:
1019f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATEALPHA_ADDCOLOR:
1020f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATECOLOR_ADDALPHA:
1021f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATEINVALPHA_ADDCOLOR:
1022f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATEINVCOLOR_ADDALPHA:
1023f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BUMPENVMAP:
1024f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BUMPENVMAPLUMINANCE:
1025f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			if(state.textureStage[stage].cantUnderflow)
1026f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			{
1027f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;   // Can't go below zero
1028f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			}
1029f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_ADDSIGNED:
1030f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_ADDSIGNED2X:
1031f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_SUBTRACT:
1032f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_ADDSMOOTH:
1033cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			res.x = Max(res.x, Short4(0x0000));
1034cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			res.y = Max(res.y, Short4(0x0000));
1035cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			res.z = Max(res.z, Short4(0x0000));
1036f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
1037f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		default:
1038f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			ASSERT(false);
1039f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
1040f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1041f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		switch(textureStage.stageOperationAlpha)
1042f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1043f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_DISABLE:
1044f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_SELECTARG1:
1045f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_SELECTARG2:
1046f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_SELECTARG3:
1047f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATE:
1048f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATE2X:
1049f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATE4X:
1050f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_ADD:
1051f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MULTIPLYADD:
1052f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_LERP:
1053f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BLENDCURRENTALPHA:
1054f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BLENDDIFFUSEALPHA:
1055f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BLENDFACTORALPHA:
1056f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BLENDTEXTUREALPHA:
1057f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BLENDTEXTUREALPHAPM:
1058f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_DOT3:   // Already clamped
1059f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_PREMODULATE:
1060f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATEALPHA_ADDCOLOR:
1061f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATECOLOR_ADDALPHA:
1062f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATEINVALPHA_ADDCOLOR:
1063f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATEINVCOLOR_ADDALPHA:
1064f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BUMPENVMAP:
1065f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BUMPENVMAPLUMINANCE:
1066f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			if(state.textureStage[stage].cantUnderflow)
1067f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			{
1068f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu				break;   // Can't go below zero
1069f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			}
1070f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_ADDSIGNED:
1071f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_ADDSIGNED2X:
1072f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_SUBTRACT:
1073f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_ADDSMOOTH:
1074cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			res.w = Max(res.w, Short4(0x0000));
1075f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
1076f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		default:
1077f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			ASSERT(false);
1078f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
1079f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1080f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		switch(textureStage.stageOperation)
1081f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1082f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_DISABLE:
1083f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_SELECTARG1:
1084f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_SELECTARG2:
1085f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_SELECTARG3:
1086f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATE:
1087f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_SUBTRACT:
1088f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_ADDSMOOTH:
1089f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_LERP:
1090f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BLENDCURRENTALPHA:
1091f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BLENDDIFFUSEALPHA:
1092f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BLENDFACTORALPHA:
1093f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BLENDTEXTUREALPHA:
1094f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_DOT3:   // Already clamped
1095f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_PREMODULATE:
1096f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATEINVALPHA_ADDCOLOR:
1097f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATEINVCOLOR_ADDALPHA:
1098f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BUMPENVMAP:
1099f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BUMPENVMAPLUMINANCE:
1100f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;   // Can't go above one
1101f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATE2X:
1102f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATE4X:
1103f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_ADD:
1104f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_ADDSIGNED:
1105f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_ADDSIGNED2X:
1106f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MULTIPLYADD:
1107f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BLENDTEXTUREALPHAPM:
1108f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATEALPHA_ADDCOLOR:
1109f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATECOLOR_ADDALPHA:
1110f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.x = Min(res.x, Short4(0x1000));
1111f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.y = Min(res.y, Short4(0x1000));
1112f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.z = Min(res.z, Short4(0x1000));
1113f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
1114f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		default:
1115f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			ASSERT(false);
1116f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
1117f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1118f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		switch(textureStage.stageOperationAlpha)
1119f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1120f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_DISABLE:
1121f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_SELECTARG1:
1122f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_SELECTARG2:
1123f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_SELECTARG3:
1124f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATE:
1125f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_SUBTRACT:
1126f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_ADDSMOOTH:
1127f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_LERP:
1128f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BLENDCURRENTALPHA:
1129f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BLENDDIFFUSEALPHA:
1130f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BLENDFACTORALPHA:
1131f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BLENDTEXTUREALPHA:
1132f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_DOT3:   // Already clamped
1133f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_PREMODULATE:
1134f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATEINVALPHA_ADDCOLOR:
1135f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATEINVCOLOR_ADDALPHA:
1136f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BUMPENVMAP:
1137f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BUMPENVMAPLUMINANCE:
1138f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;   // Can't go above one
1139f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATE2X:
1140f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATE4X:
1141f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_ADD:
1142f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_ADDSIGNED:
1143f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_ADDSIGNED2X:
1144f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MULTIPLYADD:
1145f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_BLENDTEXTUREALPHAPM:
1146f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATEALPHA_ADDCOLOR:
1147f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::STAGE_MODULATECOLOR_ADDALPHA:
1148f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			res.w = Min(res.w, Short4(0x1000));
1149f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
1150f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		default:
1151f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			ASSERT(false);
1152f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
1153f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1154f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		switch(textureStage.destinationArgument)
1155f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1156f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::DESTINATION_CURRENT:
1157a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			current.x = res.x;
1158a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			current.y = res.y;
1159a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			current.z = res.z;
1160a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			current.w = res.w;
1161f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
1162f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case TextureStage::DESTINATION_TEMP:
1163f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			temp.x = res.x;
1164f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			temp.y = res.y;
1165f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			temp.z = res.z;
1166f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			temp.w = res.w;
1167f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
1168f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		default:
1169f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			ASSERT(false);
1170f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
11716270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens	}
11726270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens
1173a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens	void PixelPipeline::fogBlend(Vector4s &current, Float4 &f)
1174f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1175f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		if(!state.fogActive)
1176f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1177f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			return;
1178f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
1179f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1180f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		if(state.pixelFogMode != FOG_NONE)
1181f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1182a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			pixelFog(f);
1183f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
1184f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1185f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		UShort4 fog = convertFixed16(f, true);
1186f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1187f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		current.x = As<Short4>(MulHigh(As<UShort4>(current.x), fog));
1188f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		current.y = As<Short4>(MulHigh(As<UShort4>(current.y), fog));
1189f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		current.z = As<Short4>(MulHigh(As<UShort4>(current.z), fog));
1190f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1191f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		UShort4 invFog = UShort4(0xFFFFu) - fog;
1192f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1193a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		current.x += As<Short4>(MulHigh(invFog, *Pointer<UShort4>(data + OFFSET(DrawData, fog.color4[0]))));
1194a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		current.y += As<Short4>(MulHigh(invFog, *Pointer<UShort4>(data + OFFSET(DrawData, fog.color4[1]))));
1195a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		current.z += As<Short4>(MulHigh(invFog, *Pointer<UShort4>(data + OFFSET(DrawData, fog.color4[2]))));
11966270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens	}
11976270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens
1198f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	void PixelPipeline::specularPixel(Vector4s &current, Vector4s &specular)
1199f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1200f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		if(!state.specularAdd)
1201f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1202f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			return;
1203f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
1204f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1205f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		current.x = AddSat(current.x, specular.x);
1206f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		current.y = AddSat(current.y, specular.y);
1207f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		current.z = AddSat(current.z, specular.z);
12086270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens	}
12096270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens
1210a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens	void PixelPipeline::sampleTexture(Vector4s &c, int coordinates, int stage, bool project)
1211f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1212a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		Float4 x = v[2 + coordinates].x;
1213a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		Float4 y = v[2 + coordinates].y;
1214a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		Float4 z = v[2 + coordinates].z;
1215a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		Float4 w = v[2 + coordinates].w;
1216f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1217f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		if(perturbate)
1218f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1219a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			x += du;
1220a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			y += dv;
1221f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1222f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			perturbate = false;
1223f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
1224f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1225a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		sampleTexture(c, stage, x, y, z, w, project);
1226f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1227f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
12289d86a36eb381ffce11fc116490abf74b21f49ca5Nicolas Capens	void PixelPipeline::sampleTexture(Vector4s &c, int stage, Float4 &u, Float4 &v, Float4 &w, Float4 &q, bool project)
1229f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
12309d86a36eb381ffce11fc116490abf74b21f49ca5Nicolas Capens		#if PERF_PROFILE
12319d86a36eb381ffce11fc116490abf74b21f49ca5Nicolas Capens			Long texTime = Ticks();
12329d86a36eb381ffce11fc116490abf74b21f49ca5Nicolas Capens		#endif
12339d86a36eb381ffce11fc116490abf74b21f49ca5Nicolas Capens
1234f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Vector4f dsx;
1235f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Vector4f dsy;
1236f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1237a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		Pointer<Byte> texture = data + OFFSET(DrawData, mipmap) + stage * sizeof(Texture);
1238f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1239f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		if(!project)
1240f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
12419d86a36eb381ffce11fc116490abf74b21f49ca5Nicolas Capens			sampler[stage]->sampleTexture(texture, c, u, v, w, q, dsx, dsy);
1242f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
1243f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		else
1244f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1245f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			Float4 rq = reciprocal(q);
1246f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1247f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			Float4 u_q = u * rq;
1248f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			Float4 v_q = v * rq;
1249f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			Float4 w_q = w * rq;
1250f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
12519d86a36eb381ffce11fc116490abf74b21f49ca5Nicolas Capens			sampler[stage]->sampleTexture(texture, c, u_q, v_q, w_q, q, dsx, dsy);
1252f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
1253f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
12549d86a36eb381ffce11fc116490abf74b21f49ca5Nicolas Capens		#if PERF_PROFILE
12559d86a36eb381ffce11fc116490abf74b21f49ca5Nicolas Capens			cycles[PERF_TEX] += Ticks() - texTime;
12569d86a36eb381ffce11fc116490abf74b21f49ca5Nicolas Capens		#endif
1257f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
12586270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens
1259f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	Short4 PixelPipeline::convertFixed12(RValue<Float4> cf)
1260f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1261f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		return RoundShort4(cf * Float4(0x1000));
1262f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1263f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1264f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	void PixelPipeline::convertFixed12(Vector4s &cs, Vector4f &cf)
1265f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1266f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		cs.x = convertFixed12(cf.x);
1267f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		cs.y = convertFixed12(cf.y);
1268f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		cs.z = convertFixed12(cf.z);
1269f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		cs.w = convertFixed12(cf.w);
1270f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1271f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1272f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	Float4 PixelPipeline::convertSigned12(Short4 &cs)
1273f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1274f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		return Float4(cs) * Float4(1.0f / 0x0FFE);
1275f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1276f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1277f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	void PixelPipeline::convertSigned12(Vector4f &cf, Vector4s &cs)
1278f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1279f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		cf.x = convertSigned12(cs.x);
1280f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		cf.y = convertSigned12(cs.y);
1281f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		cf.z = convertSigned12(cs.z);
1282f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		cf.w = convertSigned12(cs.w);
1283f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
12846270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens
1285a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens	void PixelPipeline::writeDestination(Vector4s &d, const Dst &dst)
1286f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1287f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		switch(dst.type)
1288f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1289f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case Shader::PARAMETER_TEMP:
1290a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			if(dst.mask & 0x1) rs[dst.index].x = d.x;
1291a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			if(dst.mask & 0x2) rs[dst.index].y = d.y;
1292a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			if(dst.mask & 0x4) rs[dst.index].z = d.z;
1293a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			if(dst.mask & 0x8) rs[dst.index].w = d.w;
1294f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
1295f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case Shader::PARAMETER_INPUT:
1296a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			if(dst.mask & 0x1) vs[dst.index].x = d.x;
1297a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			if(dst.mask & 0x2) vs[dst.index].y = d.y;
1298a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			if(dst.mask & 0x4) vs[dst.index].z = d.z;
1299a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			if(dst.mask & 0x8) vs[dst.index].w = d.w;
1300f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
1301f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case Shader::PARAMETER_CONST: ASSERT(false); break;
1302f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case Shader::PARAMETER_TEXTURE:
1303a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			if(dst.mask & 0x1) ts[dst.index].x = d.x;
1304a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			if(dst.mask & 0x2) ts[dst.index].y = d.y;
1305a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			if(dst.mask & 0x4) ts[dst.index].z = d.z;
1306a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			if(dst.mask & 0x8) ts[dst.index].w = d.w;
1307f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
1308f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case Shader::PARAMETER_COLOROUT:
1309a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			if(dst.mask & 0x1) vs[dst.index].x = d.x;
1310a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			if(dst.mask & 0x2) vs[dst.index].y = d.y;
1311a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			if(dst.mask & 0x4) vs[dst.index].z = d.z;
1312a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			if(dst.mask & 0x8) vs[dst.index].w = d.w;
1313f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
1314f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		default:
1315f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			ASSERT(false);
1316f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
1317f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
13186270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens
13199d86a36eb381ffce11fc116490abf74b21f49ca5Nicolas Capens	Vector4s PixelPipeline::fetchRegister(const Src &src)
1320f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1321f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Vector4s *reg;
1322f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		int i = src.index;
1323f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1324f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Vector4s c;
1325f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1326f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		if(src.type == Shader::PARAMETER_CONST)
1327f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1328a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			c.x = *Pointer<Short4>(data + OFFSET(DrawData, ps.cW[i][0]));
1329a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			c.y = *Pointer<Short4>(data + OFFSET(DrawData, ps.cW[i][1]));
1330a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			c.z = *Pointer<Short4>(data + OFFSET(DrawData, ps.cW[i][2]));
1331a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			c.w = *Pointer<Short4>(data + OFFSET(DrawData, ps.cW[i][3]));
1332f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
1333f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1334f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		switch(src.type)
1335f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1336a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		case Shader::PARAMETER_TEMP:          reg = &rs[i]; break;
1337a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		case Shader::PARAMETER_INPUT:         reg = &vs[i]; break;
1338f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case Shader::PARAMETER_CONST:         reg = &c;       break;
1339a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		case Shader::PARAMETER_TEXTURE:       reg = &ts[i]; break;
1340a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		case Shader::PARAMETER_VOID:          return rs[0]; // Dummy
1341a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		case Shader::PARAMETER_FLOAT4LITERAL: return rs[0]; // Dummy
1342a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		default: ASSERT(false); return rs[0];
1343f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
1344f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1345f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		const Short4 &x = (*reg)[(src.swizzle >> 0) & 0x3];
1346f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		const Short4 &y = (*reg)[(src.swizzle >> 2) & 0x3];
1347f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		const Short4 &z = (*reg)[(src.swizzle >> 4) & 0x3];
1348f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		const Short4 &w = (*reg)[(src.swizzle >> 6) & 0x3];
1349f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1350f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Vector4s mod;
1351f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1352f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		switch(src.modifier)
1353f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1354f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case Shader::MODIFIER_NONE:
1355f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.x = x;
1356f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.y = y;
1357f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.z = z;
1358f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.w = w;
1359f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
1360f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case Shader::MODIFIER_BIAS:
1361cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			mod.x = SubSat(x, Short4(0x0800));
1362cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			mod.y = SubSat(y, Short4(0x0800));
1363cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			mod.z = SubSat(z, Short4(0x0800));
1364cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			mod.w = SubSat(w, Short4(0x0800));
1365f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
1366f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case Shader::MODIFIER_BIAS_NEGATE:
1367cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			mod.x = SubSat(Short4(0x0800), x);
1368cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			mod.y = SubSat(Short4(0x0800), y);
1369cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			mod.z = SubSat(Short4(0x0800), z);
1370cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			mod.w = SubSat(Short4(0x0800), w);
1371f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
1372f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case Shader::MODIFIER_COMPLEMENT:
1373f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.x = SubSat(Short4(0x1000), x);
1374f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.y = SubSat(Short4(0x1000), y);
1375f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.z = SubSat(Short4(0x1000), z);
1376f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.w = SubSat(Short4(0x1000), w);
1377f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
1378f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case Shader::MODIFIER_NEGATE:
1379f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.x = -x;
1380f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.y = -y;
1381f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.z = -z;
1382f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.w = -w;
1383f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
1384f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case Shader::MODIFIER_X2:
1385f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.x = AddSat(x, x);
1386f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.y = AddSat(y, y);
1387f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.z = AddSat(z, z);
1388f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.w = AddSat(w, w);
1389f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
1390f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case Shader::MODIFIER_X2_NEGATE:
1391f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.x = -AddSat(x, x);
1392f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.y = -AddSat(y, y);
1393f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.z = -AddSat(z, z);
1394f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.w = -AddSat(w, w);
1395f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
1396f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case Shader::MODIFIER_SIGN:
1397cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			mod.x = SubSat(x, Short4(0x0800));
1398cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			mod.y = SubSat(y, Short4(0x0800));
1399cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			mod.z = SubSat(z, Short4(0x0800));
1400cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			mod.w = SubSat(w, Short4(0x0800));
1401f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.x = AddSat(mod.x, mod.x);
1402f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.y = AddSat(mod.y, mod.y);
1403f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.z = AddSat(mod.z, mod.z);
1404f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.w = AddSat(mod.w, mod.w);
1405f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
1406f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case Shader::MODIFIER_SIGN_NEGATE:
1407cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			mod.x = SubSat(Short4(0x0800), x);
1408cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			mod.y = SubSat(Short4(0x0800), y);
1409cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			mod.z = SubSat(Short4(0x0800), z);
1410cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			mod.w = SubSat(Short4(0x0800), w);
1411f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.x = AddSat(mod.x, mod.x);
1412f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.y = AddSat(mod.y, mod.y);
1413f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.z = AddSat(mod.z, mod.z);
1414f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.w = AddSat(mod.w, mod.w);
1415f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
1416f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case Shader::MODIFIER_DZ:
1417f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.x = x;
1418f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.y = y;
1419f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.z = z;
1420f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.w = w;
1421f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			// Projection performed by texture sampler
1422f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
1423f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		case Shader::MODIFIER_DW:
1424f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.x = x;
1425f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.y = y;
1426f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.z = z;
1427f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			mod.w = w;
1428f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			// Projection performed by texture sampler
1429f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			break;
1430f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		default:
1431f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			ASSERT(false);
1432f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
1433f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1434f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		if(src.type == Shader::PARAMETER_CONST && (src.modifier == Shader::MODIFIER_X2 || src.modifier == Shader::MODIFIER_X2_NEGATE))
1435f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1436cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			mod.x = Min(mod.x, Short4(0x1000)); mod.x = Max(mod.x, Short4(-0x1000));
1437cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			mod.y = Min(mod.y, Short4(0x1000)); mod.y = Max(mod.y, Short4(-0x1000));
1438cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			mod.z = Min(mod.z, Short4(0x1000)); mod.z = Max(mod.z, Short4(-0x1000));
1439cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			mod.w = Min(mod.w, Short4(0x1000)); mod.w = Max(mod.w, Short4(-0x1000));
1440f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
1441f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1442f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		return mod;
1443f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
14446270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens
1445f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	void PixelPipeline::MOV(Vector4s &dst, Vector4s &src0)
1446f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1447f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dst.x = src0.x;
1448f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dst.y = src0.y;
1449f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dst.z = src0.z;
1450f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dst.w = src0.w;
1451f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1452f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1453f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	void PixelPipeline::ADD(Vector4s &dst, Vector4s &src0, Vector4s &src1)
1454f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1455f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dst.x = AddSat(src0.x, src1.x);
1456f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dst.y = AddSat(src0.y, src1.y);
1457f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dst.z = AddSat(src0.z, src1.z);
1458f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dst.w = AddSat(src0.w, src1.w);
1459f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1460f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1461f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	void PixelPipeline::SUB(Vector4s &dst, Vector4s &src0, Vector4s &src1)
1462f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1463f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dst.x = SubSat(src0.x, src1.x);
1464f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dst.y = SubSat(src0.y, src1.y);
1465f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dst.z = SubSat(src0.z, src1.z);
1466f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dst.w = SubSat(src0.w, src1.w);
1467f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1468f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1469f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	void PixelPipeline::MAD(Vector4s &dst, Vector4s &src0, Vector4s &src1, Vector4s &src2)
1470f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1471f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		// FIXME: Long fixed-point multiply fixup
1472f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{ dst.x = MulHigh(src0.x, src1.x); dst.x = AddSat(dst.x, dst.x); dst.x = AddSat(dst.x, dst.x); dst.x = AddSat(dst.x, dst.x); dst.x = AddSat(dst.x, dst.x); dst.x = AddSat(dst.x, src2.x); }
1473f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1474f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dst.y = MulHigh(src0.y, src1.y); dst.y = AddSat(dst.y, dst.y); dst.y = AddSat(dst.y, dst.y); dst.y = AddSat(dst.y, dst.y); dst.y = AddSat(dst.y, dst.y); dst.y = AddSat(dst.y, src2.y);
1475f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1476f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{dst.z = MulHigh(src0.z, src1.z); dst.z = AddSat(dst.z, dst.z); dst.z = AddSat(dst.z, dst.z); dst.z = AddSat(dst.z, dst.z); dst.z = AddSat(dst.z, dst.z); dst.z = AddSat(dst.z, src2.z); }
1477f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{dst.w = MulHigh(src0.w, src1.w); dst.w = AddSat(dst.w, dst.w); dst.w = AddSat(dst.w, dst.w); dst.w = AddSat(dst.w, dst.w); dst.w = AddSat(dst.w, dst.w); dst.w = AddSat(dst.w, src2.w); }
1478f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1479f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1480f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	void PixelPipeline::MUL(Vector4s &dst, Vector4s &src0, Vector4s &src1)
1481f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1482f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		// FIXME: Long fixed-point multiply fixup
1483f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{ dst.x = MulHigh(src0.x, src1.x); dst.x = AddSat(dst.x, dst.x); dst.x = AddSat(dst.x, dst.x); dst.x = AddSat(dst.x, dst.x); dst.x = AddSat(dst.x, dst.x); }
1484f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1485f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dst.y = MulHigh(src0.y, src1.y); dst.y = AddSat(dst.y, dst.y); dst.y = AddSat(dst.y, dst.y); dst.y = AddSat(dst.y, dst.y); dst.y = AddSat(dst.y, dst.y);
1486f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1487f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{dst.z = MulHigh(src0.z, src1.z); dst.z = AddSat(dst.z, dst.z); dst.z = AddSat(dst.z, dst.z); dst.z = AddSat(dst.z, dst.z); dst.z = AddSat(dst.z, dst.z); }
1488f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{dst.w = MulHigh(src0.w, src1.w); dst.w = AddSat(dst.w, dst.w); dst.w = AddSat(dst.w, dst.w); dst.w = AddSat(dst.w, dst.w); dst.w = AddSat(dst.w, dst.w); }
1489f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1490f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1491f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	void PixelPipeline::DP3(Vector4s &dst, Vector4s &src0, Vector4s &src1)
1492f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1493f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Short4 t0;
1494f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Short4 t1;
1495f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1496f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		// FIXME: Long fixed-point multiply fixup
1497f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		t0 = MulHigh(src0.x, src1.x); t0 = AddSat(t0, t0); t0 = AddSat(t0, t0); t0 = AddSat(t0, t0); t0 = AddSat(t0, t0);
1498f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		t1 = MulHigh(src0.y, src1.y); t1 = AddSat(t1, t1); t1 = AddSat(t1, t1); t1 = AddSat(t1, t1); t1 = AddSat(t1, t1);
1499f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		t0 = AddSat(t0, t1);
1500f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		t1 = MulHigh(src0.z, src1.z); t1 = AddSat(t1, t1); t1 = AddSat(t1, t1); t1 = AddSat(t1, t1); t1 = AddSat(t1, t1);
1501f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		t0 = AddSat(t0, t1);
1502f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1503f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dst.x = t0;
1504f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dst.y = t0;
1505f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dst.z = t0;
1506f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dst.w = t0;
1507f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1508f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1509f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	void PixelPipeline::DP4(Vector4s &dst, Vector4s &src0, Vector4s &src1)
1510f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1511f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Short4 t0;
1512f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Short4 t1;
1513f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1514f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		// FIXME: Long fixed-point multiply fixup
1515f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		t0 = MulHigh(src0.x, src1.x); t0 = AddSat(t0, t0); t0 = AddSat(t0, t0); t0 = AddSat(t0, t0); t0 = AddSat(t0, t0);
1516f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		t1 = MulHigh(src0.y, src1.y); t1 = AddSat(t1, t1); t1 = AddSat(t1, t1); t1 = AddSat(t1, t1); t1 = AddSat(t1, t1);
1517f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		t0 = AddSat(t0, t1);
1518f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		t1 = MulHigh(src0.z, src1.z); t1 = AddSat(t1, t1); t1 = AddSat(t1, t1); t1 = AddSat(t1, t1); t1 = AddSat(t1, t1);
1519f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		t0 = AddSat(t0, t1);
1520f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		t1 = MulHigh(src0.w, src1.w); t1 = AddSat(t1, t1); t1 = AddSat(t1, t1); t1 = AddSat(t1, t1); t1 = AddSat(t1, t1);
1521f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		t0 = AddSat(t0, t1);
1522f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1523f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dst.x = t0;
1524f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dst.y = t0;
1525f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dst.z = t0;
1526f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dst.w = t0;
1527f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1528f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1529f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	void PixelPipeline::LRP(Vector4s &dst, Vector4s &src0, Vector4s &src1, Vector4s &src2)
1530f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1531f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		// FIXME: Long fixed-point multiply fixup
1532f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{ dst.x = SubSat(src1.x, src2.x); dst.x = MulHigh(dst.x, src0.x); dst.x = AddSat(dst.x, dst.x); dst.x = AddSat(dst.x, dst.x); dst.x = AddSat(dst.x, dst.x); dst.x = AddSat(dst.x, dst.x); dst.x = AddSat(dst.x, src2.x); }
1533f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1534f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dst.y = SubSat(src1.y, src2.y); dst.y = MulHigh(dst.y, src0.y); dst.y = AddSat(dst.y, dst.y); dst.y = AddSat(dst.y, dst.y); dst.y = AddSat(dst.y, dst.y); dst.y = AddSat(dst.y, dst.y); dst.y = AddSat(dst.y, src2.y);
1535f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1536f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{dst.z = SubSat(src1.z, src2.z); dst.z = MulHigh(dst.z, src0.z); dst.z = AddSat(dst.z, dst.z); dst.z = AddSat(dst.z, dst.z); dst.z = AddSat(dst.z, dst.z); dst.z = AddSat(dst.z, dst.z); dst.z = AddSat(dst.z, src2.z); }
1537f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{dst.w = SubSat(src1.w, src2.w); dst.w = MulHigh(dst.w, src0.w); dst.w = AddSat(dst.w, dst.w); dst.w = AddSat(dst.w, dst.w); dst.w = AddSat(dst.w, dst.w); dst.w = AddSat(dst.w, dst.w); dst.w = AddSat(dst.w, src2.w); }
1538f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1539f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1540f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	void PixelPipeline::TEXCOORD(Vector4s &dst, Float4 &u, Float4 &v, Float4 &s, int coordinate)
1541f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1542f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 uw;
1543f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 vw;
1544f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 sw;
1545f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1546f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		if(state.interpolant[2 + coordinate].component & 0x01)
1547f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1548f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			uw = Max(u, Float4(0.0f));
1549f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			uw = Min(uw, Float4(1.0f));
1550f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			dst.x = convertFixed12(uw);
1551f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
1552f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		else
1553f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1554cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			dst.x = Short4(0x0000);
1555f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
1556f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1557f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		if(state.interpolant[2 + coordinate].component & 0x02)
1558f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1559f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			vw = Max(v, Float4(0.0f));
1560f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			vw = Min(vw, Float4(1.0f));
1561f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			dst.y = convertFixed12(vw);
1562f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
1563f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		else
1564f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1565cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			dst.y = Short4(0x0000);
1566f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
1567f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1568f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		if(state.interpolant[2 + coordinate].component & 0x04)
1569f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1570f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			sw = Max(s, Float4(0.0f));
1571f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			sw = Min(sw, Float4(1.0f));
1572f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			dst.z = convertFixed12(sw);
1573f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
1574f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		else
1575f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1576cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			dst.z = Short4(0x0000);
1577f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
1578f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1579f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dst.w = Short4(0x1000);
1580f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1581f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1582f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	void PixelPipeline::TEXCRD(Vector4s &dst, Float4 &u, Float4 &v, Float4 &s, int coordinate, bool project)
1583f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1584f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 uw = u;
1585f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 vw = v;
1586f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 sw = s;
1587f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1588f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		if(project)
1589f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1590f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			uw *= Rcp_pp(s);
1591f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			vw *= Rcp_pp(s);
1592f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
1593f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1594f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		if(state.interpolant[2 + coordinate].component & 0x01)
1595f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1596f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			uw *= Float4(0x1000);
1597f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			uw = Max(uw, Float4(-0x8000));
1598f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			uw = Min(uw, Float4(0x7FFF));
1599f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			dst.x = RoundShort4(uw);
1600f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
1601f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		else
1602f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1603f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			dst.x = Short4(0x0000);
1604f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
1605f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1606f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		if(state.interpolant[2 + coordinate].component & 0x02)
1607f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1608f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			vw *= Float4(0x1000);
1609f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			vw = Max(vw, Float4(-0x8000));
1610f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			vw = Min(vw, Float4(0x7FFF));
1611f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			dst.y = RoundShort4(vw);
1612f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
1613f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		else
1614f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1615cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			dst.y = Short4(0x0000);
1616f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
1617f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1618f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		if(state.interpolant[2 + coordinate].component & 0x04)
1619f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1620f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			sw *= Float4(0x1000);
1621f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			sw = Max(sw, Float4(-0x8000));
1622f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			sw = Min(sw, Float4(0x7FFF));
1623f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			dst.z = RoundShort4(sw);
1624f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
1625f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		else
1626f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1627cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu			dst.z = Short4(0x0000);
1628f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
1629f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1630f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1631a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens	void PixelPipeline::TEXDP3(Vector4s &dst, Float4 &u, Float4 &v, Float4 &s, Vector4s &src)
1632f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1633a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		TEXM3X3PAD(u, v, s, src, 0, false);
1634f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1635a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		Short4 t0 = RoundShort4(u_ * Float4(0x1000));
1636f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1637f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dst.x = t0;
1638f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dst.y = t0;
1639f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dst.z = t0;
1640f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dst.w = t0;
1641f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1642f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1643a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens	void PixelPipeline::TEXDP3TEX(Vector4s &dst, Float4 &u, Float4 &v, Float4 &s, int stage, Vector4s &src0)
1644f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1645a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		TEXM3X3PAD(u, v, s, src0, 0, false);
1646f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1647a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		v_ = Float4(0.0f);
1648a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		w_ = Float4(0.0f);
1649f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1650a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		sampleTexture(dst, stage, u_, v_, w_, w_);
1651f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1652f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1653f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	void PixelPipeline::TEXKILL(Int cMask[4], Float4 &u, Float4 &v, Float4 &s)
1654f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1655f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Int kill = SignMask(CmpNLT(u, Float4(0.0f))) &
1656f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			SignMask(CmpNLT(v, Float4(0.0f))) &
1657f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			SignMask(CmpNLT(s, Float4(0.0f)));
1658f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1659f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		for(unsigned int q = 0; q < state.multiSample; q++)
1660f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1661f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			cMask[q] &= kill;
1662f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
1663f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1664f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1665f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	void PixelPipeline::TEXKILL(Int cMask[4], Vector4s &src)
1666f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1667f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Short4 test = src.x | src.y | src.z;
1668f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Int kill = SignMask(Pack(test, test)) ^ 0x0000000F;
1669f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1670f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		for(unsigned int q = 0; q < state.multiSample; q++)
1671f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1672f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			cMask[q] &= kill;
1673f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
1674f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1675f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1676a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens	void PixelPipeline::TEX(Vector4s &dst, Float4 &u, Float4 &v, Float4 &s, int sampler, bool project)
1677f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1678a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		sampleTexture(dst, sampler, u, v, s, s, project);
1679f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1680f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1681a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens	void PixelPipeline::TEXLD(Vector4s &dst, Vector4s &src, int sampler, bool project)
1682f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1683f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 u = Float4(src.x) * Float4(1.0f / 0x0FFE);
1684f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 v = Float4(src.y) * Float4(1.0f / 0x0FFE);
1685f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 s = Float4(src.z) * Float4(1.0f / 0x0FFE);
1686f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1687a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		sampleTexture(dst, sampler, u, v, s, s, project);
1688f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1689f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1690a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens	void PixelPipeline::TEXBEM(Vector4s &dst, Vector4s &src, Float4 &u, Float4 &v, Float4 &s, int stage)
1691f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1692f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 du = Float4(src.x) * Float4(1.0f / 0x0FFE);
1693f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 dv = Float4(src.y) * Float4(1.0f / 0x0FFE);
1694f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1695f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 du2 = du;
1696f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 dv2 = dv;
1697f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1698a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		du *= *Pointer<Float4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4F[0][0]));
1699a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		dv2 *= *Pointer<Float4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4F[1][0]));
1700f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		du += dv2;
1701a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		dv *= *Pointer<Float4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4F[1][1]));
1702a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		du2 *= *Pointer<Float4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4F[0][1]));
1703f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dv += du2;
1704f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1705f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 u_ = u + du;
1706f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 v_ = v + dv;
1707f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1708a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		sampleTexture(dst, stage, u_, v_, s, s);
1709f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1710f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1711a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens	void PixelPipeline::TEXBEML(Vector4s &dst, Vector4s &src, Float4 &u, Float4 &v, Float4 &s, int stage)
1712f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1713f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 du = Float4(src.x) * Float4(1.0f / 0x0FFE);
1714f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 dv = Float4(src.y) * Float4(1.0f / 0x0FFE);
1715f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1716f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 du2 = du;
1717f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 dv2 = dv;
1718f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1719a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		du *= *Pointer<Float4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4F[0][0]));
1720a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		dv2 *= *Pointer<Float4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4F[1][0]));
1721f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		du += dv2;
1722a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		dv *= *Pointer<Float4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4F[1][1]));
1723a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		du2 *= *Pointer<Float4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4F[0][1]));
1724f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dv += du2;
1725f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1726f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 u_ = u + du;
1727f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 v_ = v + dv;
1728f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1729a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		sampleTexture(dst, stage, u_, v_, s, s);
1730f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1731f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Short4 L;
1732f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1733f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		L = src.z;
1734a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		L = MulHigh(L, *Pointer<Short4>(data + OFFSET(DrawData, textureStage[stage].luminanceScale4)));
1735f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		L = L << 4;
1736a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		L = AddSat(L, *Pointer<Short4>(data + OFFSET(DrawData, textureStage[stage].luminanceOffset4)));
1737cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu		L = Max(L, Short4(0x0000));
1738f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		L = Min(L, Short4(0x1000));
1739f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1740f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dst.x = MulHigh(dst.x, L); dst.x = dst.x << 4;
1741f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dst.y = MulHigh(dst.y, L); dst.y = dst.y << 4;
1742f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dst.z = MulHigh(dst.z, L); dst.z = dst.z << 4;
1743f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1744f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1745a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens	void PixelPipeline::TEXREG2AR(Vector4s &dst, Vector4s &src0, int stage)
1746f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1747f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 u = Float4(src0.w) * Float4(1.0f / 0x0FFE);
1748f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 v = Float4(src0.x) * Float4(1.0f / 0x0FFE);
1749f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 s = Float4(src0.z) * Float4(1.0f / 0x0FFE);
1750f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1751a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		sampleTexture(dst, stage, u, v, s, s);
1752f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1753f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1754a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens	void PixelPipeline::TEXREG2GB(Vector4s &dst, Vector4s &src0, int stage)
1755f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1756f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 u = Float4(src0.y) * Float4(1.0f / 0x0FFE);
1757f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 v = Float4(src0.z) * Float4(1.0f / 0x0FFE);
1758f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 s = v;
1759f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1760a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		sampleTexture(dst, stage, u, v, s, s);
1761f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1762f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1763a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens	void PixelPipeline::TEXREG2RGB(Vector4s &dst, Vector4s &src0, int stage)
1764f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1765f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 u = Float4(src0.x) * Float4(1.0f / 0x0FFE);
1766f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 v = Float4(src0.y) * Float4(1.0f / 0x0FFE);
1767f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 s = Float4(src0.z) * Float4(1.0f / 0x0FFE);
1768f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1769a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		sampleTexture(dst, stage, u, v, s, s);
1770f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1771f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1772a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens	void PixelPipeline::TEXM3X2DEPTH(Vector4s &dst, Float4 &u, Float4 &v, Float4 &s, Vector4s &src, bool signedScaling)
1773f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1774a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		TEXM3X2PAD(u, v, s, src, 1, signedScaling);
1775f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1776f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		// z / w
1777a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		u_ *= Rcp_pp(v_);   // FIXME: Set result to 1.0 when division by zero
1778f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1779a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		oDepth = u_;
1780f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1781f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1782a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens	void PixelPipeline::TEXM3X2PAD(Float4 &u, Float4 &v, Float4 &s, Vector4s &src0, int component, bool signedScaling)
1783f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1784a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		TEXM3X3PAD(u, v, s, src0, component, signedScaling);
1785f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1786f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1787a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens	void PixelPipeline::TEXM3X2TEX(Vector4s &dst, Float4 &u, Float4 &v, Float4 &s, int stage, Vector4s &src0, bool signedScaling)
1788f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1789a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		TEXM3X2PAD(u, v, s, src0, 1, signedScaling);
1790f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1791a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		w_ = Float4(0.0f);
1792f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1793a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		sampleTexture(dst, stage, u_, v_, w_, w_);
1794f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1795f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1796a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens	void PixelPipeline::TEXM3X3(Vector4s &dst, Float4 &u, Float4 &v, Float4 &s, Vector4s &src0, bool signedScaling)
1797f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1798a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		TEXM3X3PAD(u, v, s, src0, 2, signedScaling);
1799f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1800a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		dst.x = RoundShort4(u_ * Float4(0x1000));
1801a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		dst.y = RoundShort4(v_ * Float4(0x1000));
1802a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		dst.z = RoundShort4(w_ * Float4(0x1000));
1803f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dst.w = Short4(0x1000);
1804f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1805f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1806a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens	void PixelPipeline::TEXM3X3PAD(Float4 &u, Float4 &v, Float4 &s, Vector4s &src0, int component, bool signedScaling)
1807f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1808f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		if(component == 0 || previousScaling != signedScaling)   // FIXME: Other source modifiers?
1809f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1810a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			U = Float4(src0.x);
1811a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			V = Float4(src0.y);
1812a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens			W = Float4(src0.z);
1813f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1814f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu			previousScaling = signedScaling;
1815f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
1816f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1817a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		Float4 x = U * u + V * v + W * s;
1818f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1819f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		x *= Float4(1.0f / 0x1000);
1820f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1821f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		switch(component)
1822f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		{
1823a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		case 0:	u_ = x; break;
1824a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		case 1:	v_ = x; break;
1825a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		case 2: w_ = x; break;
1826f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		default: ASSERT(false);
1827f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		}
1828f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1829f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1830a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens	void PixelPipeline::TEXM3X3SPEC(Vector4s &dst, Float4 &u, Float4 &v, Float4 &s, int stage, Vector4s &src0, Vector4s &src1)
1831f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1832a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		TEXM3X3PAD(u, v, s, src0, 2, false);
1833f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1834f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 E[3];   // Eye vector
1835f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1836f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		E[0] = Float4(src1.x) * Float4(1.0f / 0x0FFE);
1837f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		E[1] = Float4(src1.y) * Float4(1.0f / 0x0FFE);
1838f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		E[2] = Float4(src1.z) * Float4(1.0f / 0x0FFE);
1839f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1840f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		// Reflection
1841f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 u__;
1842f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 v__;
1843f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 w__;
1844f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1845f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		// (u'', v'', w'') = 2 * (N . E) * N - E * (N . N)
1846a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		u__ = u_ * E[0];
1847a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		v__ = v_ * E[1];
1848a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		w__ = w_ * E[2];
1849f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		u__ += v__ + w__;
1850f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		u__ += u__;
1851f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		v__ = u__;
1852f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		w__ = u__;
1853a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		u__ *= u_;
1854a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		v__ *= v_;
1855a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		w__ *= w_;
1856a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		u_ *= u_;
1857a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		v_ *= v_;
1858a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		w_ *= w_;
1859a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		u_ += v_ + w_;
1860a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		u__ -= E[0] * u_;
1861a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		v__ -= E[1] * u_;
1862a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		w__ -= E[2] * u_;
1863a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens
1864a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		sampleTexture(dst, stage, u__, v__, w__, w__);
1865f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1866f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1867a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens	void PixelPipeline::TEXM3X3TEX(Vector4s &dst, Float4 &u, Float4 &v, Float4 &s, int stage, Vector4s &src0, bool signedScaling)
1868f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1869a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		TEXM3X3PAD(u, v, s, src0, 2, signedScaling);
1870f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1871a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		sampleTexture(dst, stage, u_, v_, w_, w_);
1872f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1873f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1874a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens	void PixelPipeline::TEXM3X3VSPEC(Vector4s &dst, Float4 &x, Float4 &y, Float4 &z, int stage, Vector4s &src0)
1875f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1876a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		TEXM3X3PAD(x, y, z, src0, 2, false);
1877f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1878f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 E[3];   // Eye vector
1879f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1880a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		E[0] = v[2 + stage - 2].w;
1881a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		E[1] = v[2 + stage - 1].w;
1882a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		E[2] = v[2 + stage - 0].w;
1883f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1884f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		// Reflection
1885f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 u__;
1886f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 v__;
1887f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Float4 w__;
1888f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1889f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		// (u'', v'', w'') = 2 * (N . E) * N - E * (N . N)
1890a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		u__ = u_ * E[0];
1891a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		v__ = v_ * E[1];
1892a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		w__ = w_ * E[2];
1893f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		u__ += v__ + w__;
1894f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		u__ += u__;
1895f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		v__ = u__;
1896f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		w__ = u__;
1897a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		u__ *= u_;
1898a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		v__ *= v_;
1899a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		w__ *= w_;
1900a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		u_ *= u_;
1901a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		v_ *= v_;
1902a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		w_ *= w_;
1903a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		u_ += v_ + w_;
1904a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		u__ -= E[0] * u_;
1905a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		v__ -= E[1] * u_;
1906a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		w__ -= E[2] * u_;
1907a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens
1908a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		sampleTexture(dst, stage, u__, v__, w__, w__);
1909f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1910f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1911a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens	void PixelPipeline::TEXDEPTH()
1912f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1913a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		u_ = Float4(rs[5].x);
1914a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		v_ = Float4(rs[5].y);
1915f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1916f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		// z / w
1917a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		u_ *= Rcp_pp(v_);   // FIXME: Set result to 1.0 when division by zero
1918f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1919a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		oDepth = u_;
1920f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1921f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1922f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	void PixelPipeline::CND(Vector4s &dst, Vector4s &src0, Vector4s &src1, Vector4s &src2)
1923f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1924cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu		{Short4 t0; t0 = src0.x; t0 = CmpGT(t0, Short4(0x0800)); Short4 t1; t1 = src1.x; t1 = t1 & t0; t0 = ~t0 & src2.x; t0 = t0 | t1; dst.x = t0; };
1925cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu		{Short4 t0; t0 = src0.y; t0 = CmpGT(t0, Short4(0x0800)); Short4 t1; t1 = src1.y; t1 = t1 & t0; t0 = ~t0 & src2.y; t0 = t0 | t1; dst.y = t0; };
1926cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu		{Short4 t0; t0 = src0.z; t0 = CmpGT(t0, Short4(0x0800)); Short4 t1; t1 = src1.z; t1 = t1 & t0; t0 = ~t0 & src2.z; t0 = t0 | t1; dst.z = t0; };
1927cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu		{Short4 t0; t0 = src0.w; t0 = CmpGT(t0, Short4(0x0800)); Short4 t1; t1 = src1.w; t1 = t1 & t0; t0 = ~t0 & src2.w; t0 = t0 | t1; dst.w = t0; };
1928f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1929f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1930f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	void PixelPipeline::CMP(Vector4s &dst, Vector4s &src0, Vector4s &src1, Vector4s &src2)
1931f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1932cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu		{Short4 t0 = CmpGT(Short4(0x0000), src0.x); Short4 t1; t1 = src2.x; t1 &= t0; t0 = ~t0 & src1.x; t0 |= t1; dst.x = t0; };
1933cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu		{Short4 t0 = CmpGT(Short4(0x0000), src0.y); Short4 t1; t1 = src2.y; t1 &= t0; t0 = ~t0 & src1.y; t0 |= t1; dst.y = t0; };
1934cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu		{Short4 t0 = CmpGT(Short4(0x0000), src0.z); Short4 t1; t1 = src2.z; t1 &= t0; t0 = ~t0 & src1.z; t0 |= t1; dst.z = t0; };
1935cb96dc100fa702162e2aee6a0c46c7615b49a7dcAlexis Hetu		{Short4 t0 = CmpGT(Short4(0x0000), src0.w); Short4 t1; t1 = src2.w; t1 &= t0; t0 = ~t0 & src1.w; t0 |= t1; dst.w = t0; };
1936f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
1937f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1938a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens	void PixelPipeline::BEM(Vector4s &dst, Vector4s &src0, Vector4s &src1, int stage)
1939f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	{
1940f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Short4 t0;
1941f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		Short4 t1;
1942f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1943f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		// dst.x = src0.x + BUMPENVMAT00(stage) * src1.x + BUMPENVMAT10(stage) * src1.y
1944a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		t0 = MulHigh(src1.x, *Pointer<Short4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4W[0][0]))); t0 = t0 << 4;   // FIXME: Matrix components range? Overflow hazard.
1945a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		t1 = MulHigh(src1.y, *Pointer<Short4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4W[1][0]))); t1 = t1 << 4;   // FIXME: Matrix components range? Overflow hazard.
1946f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		t0 = AddSat(t0, t1);
1947f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		t0 = AddSat(t0, src0.x);
1948f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dst.x = t0;
1949f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu
1950f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		// dst.y = src0.y + BUMPENVMAT01(stage) * src1.x + BUMPENVMAT11(stage) * src1.y
1951a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		t0 = MulHigh(src1.x, *Pointer<Short4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4W[0][1]))); t0 = t0 << 4;   // FIXME: Matrix components range? Overflow hazard.
1952a106b35e674fc2d3cbc4328554c5fc976713963dNicolas Capens		t1 = MulHigh(src1.y, *Pointer<Short4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4W[1][1]))); t1 = t1 << 4;   // FIXME: Matrix components range? Overflow hazard.
1953f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		t0 = AddSat(t0, t1);
1954f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		t0 = AddSat(t0, src0.y);
1955f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu		dst.y = t0;
1956f2a8c37e70fc0d7b5a09a1ab8db2fe9ec4017b27Alexis Hetu	}
19576270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens}
19586270e94c49983d9650f05ada32cb1e8f544a05e0Nicolas Capens
1959