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