diff --git a/GPU/Software/DrawPixel.cpp b/GPU/Software/DrawPixel.cpp index e3c7534523..cff4c9e1a8 100644 --- a/GPU/Software/DrawPixel.cpp +++ b/GPU/Software/DrawPixel.cpp @@ -591,47 +591,73 @@ void ComputePixelBlendState(PixelBlendState &state, const PixelFuncID &id) { if (state.usesFactors) { switch (id.AlphaBlendSrc()) { - case GE_SRCBLEND_DSTALPHA: - case GE_SRCBLEND_INVDSTALPHA: - case GE_SRCBLEND_DOUBLEDSTALPHA: - case GE_SRCBLEND_DOUBLEINVDSTALPHA: + case PixelBlendFactor::DSTALPHA: + case PixelBlendFactor::INVDSTALPHA: + case PixelBlendFactor::DOUBLEDSTALPHA: + case PixelBlendFactor::DOUBLEINVDSTALPHA: state.usesDstAlpha = true; break; + case PixelBlendFactor::OTHERCOLOR: + case PixelBlendFactor::INVOTHERCOLOR: + state.dstColorAsFactor = true; + break; + + case PixelBlendFactor::SRCALPHA: + case PixelBlendFactor::INVSRCALPHA: + case PixelBlendFactor::DOUBLESRCALPHA: + case PixelBlendFactor::DOUBLEINVSRCALPHA: + state.srcColorAsFactor = true; + break; + default: break; } switch (id.AlphaBlendDst()) { - case GE_DSTBLEND_INVSRCALPHA: - state.dstFactorIsInverse = id.AlphaBlendSrc() == GE_SRCBLEND_SRCALPHA; + case PixelBlendFactor::INVSRCALPHA: + state.dstFactorIsInverse = id.AlphaBlendSrc() == PixelBlendFactor::SRCALPHA; + state.srcColorAsFactor = true; break; - case GE_DSTBLEND_DOUBLEINVSRCALPHA: - state.dstFactorIsInverse = id.AlphaBlendSrc() == GE_SRCBLEND_DOUBLESRCALPHA; + case PixelBlendFactor::DOUBLEINVSRCALPHA: + state.dstFactorIsInverse = id.AlphaBlendSrc() == PixelBlendFactor::DOUBLESRCALPHA; + state.srcColorAsFactor = true; break; - case GE_DSTBLEND_DSTALPHA: + case PixelBlendFactor::DSTALPHA: state.usesDstAlpha = true; break; - case GE_DSTBLEND_INVDSTALPHA: - state.dstFactorIsInverse = id.AlphaBlendSrc() == GE_SRCBLEND_DSTALPHA; + case PixelBlendFactor::INVDSTALPHA: + state.dstFactorIsInverse = id.AlphaBlendSrc() == PixelBlendFactor::DSTALPHA; state.usesDstAlpha = true; break; - case GE_DSTBLEND_DOUBLEDSTALPHA: + case PixelBlendFactor::DOUBLEDSTALPHA: state.usesDstAlpha = true; break; - case GE_DSTBLEND_DOUBLEINVDSTALPHA: - state.dstFactorIsInverse = id.AlphaBlendSrc() == GE_SRCBLEND_DOUBLEDSTALPHA; + case PixelBlendFactor::DOUBLEINVDSTALPHA: + state.dstFactorIsInverse = id.AlphaBlendSrc() == PixelBlendFactor::DOUBLEDSTALPHA; state.usesDstAlpha = true; break; + case PixelBlendFactor::OTHERCOLOR: + case PixelBlendFactor::INVOTHERCOLOR: + state.dstColorAsFactor = true; + break; + + case PixelBlendFactor::SRCALPHA: + case PixelBlendFactor::DOUBLESRCALPHA: + state.srcColorAsFactor = true; + break; + default: break; } + + state.dstColorAsFactor = state.dstColorAsFactor || state.usesDstAlpha; } } diff --git a/GPU/Software/DrawPixel.h b/GPU/Software/DrawPixel.h index aea79cc3a9..8322aa0e1d 100644 --- a/GPU/Software/DrawPixel.h +++ b/GPU/Software/DrawPixel.h @@ -47,6 +47,8 @@ struct PixelBlendState { bool usesFactors = false; bool usesDstAlpha = false; bool dstFactorIsInverse = false; + bool srcColorAsFactor = false; + bool dstColorAsFactor = false; }; void ComputePixelBlendState(PixelBlendState &state, const PixelFuncID &id); @@ -88,7 +90,7 @@ private: bool Jit_DepthTest(const PixelFuncID &id); bool Jit_WriteDepth(const PixelFuncID &id); bool Jit_AlphaBlend(const PixelFuncID &id); - bool Jit_BlendFactor(const PixelFuncID &id, RegCache::Reg factorReg, RegCache::Reg dstReg, GEBlendSrcFactor factor); + bool Jit_BlendFactor(const PixelFuncID &id, RegCache::Reg factorReg, RegCache::Reg dstReg, PixelBlendFactor factor); bool Jit_DstBlendFactor(const PixelFuncID &id, RegCache::Reg srcFactorReg, RegCache::Reg dstFactorReg, RegCache::Reg dstReg); bool Jit_Dither(const PixelFuncID &id); bool Jit_WriteColor(const PixelFuncID &id); diff --git a/GPU/Software/DrawPixelX86.cpp b/GPU/Software/DrawPixelX86.cpp index 60b63a90fe..fff96467c9 100644 --- a/GPU/Software/DrawPixelX86.cpp +++ b/GPU/Software/DrawPixelX86.cpp @@ -1081,34 +1081,59 @@ bool PixelJitCache::Jit_AlphaBlend(const PixelFuncID &id) { } colorIs16Bit_ = true; + // Skip multiplying by factors if we can. + bool multiplySrc = id.AlphaBlendSrc() != PixelBlendFactor::ZERO && id.AlphaBlendSrc() != PixelBlendFactor::ONE; + bool multiplyDst = id.AlphaBlendDst() != PixelBlendFactor::ZERO && id.AlphaBlendDst() != PixelBlendFactor::ONE; // We also shift left by 4, so mulhi gives us a free shift // We also need to add a half bit later, so this gives us space. - PSLLW(argColorReg, 4); - PSLLW(dstReg, 4); + if (multiplySrc || blendState.srcColorAsFactor) + PSLLW(argColorReg, 4); + if (multiplyDst || blendState.dstColorAsFactor) + PSLLW(dstReg, 4); - // Okay, now grab our factors. - success = success && Jit_BlendFactor(id, srcFactorReg, dstReg, id.AlphaBlendSrc()); - success = success && Jit_DstBlendFactor(id, srcFactorReg, dstFactorReg, dstReg); + // Okay, now grab our factors. Don't bother if they're known values. + if (id.AlphaBlendSrc() < PixelBlendFactor::ZERO) + success = success && Jit_BlendFactor(id, srcFactorReg, dstReg, id.AlphaBlendSrc()); + if (id.AlphaBlendDst() < PixelBlendFactor::ZERO) + success = success && Jit_DstBlendFactor(id, srcFactorReg, dstFactorReg, dstReg); - X64Reg constReg = GetConstBase(); - X64Reg halfReg = regCache_.Alloc(RegCache::VEC_TEMP3); - // We'll use this several times, so load into a reg. - MOVDQA(halfReg, MConstDisp(constReg, &blendHalf_11_4s[0])); - regCache_.Unlock(constReg, RegCache::GEN_CONST_BASE); + X64Reg halfReg = INVALID_REG; + if (multiplySrc || multiplyDst) { + X64Reg constReg = GetConstBase(); + halfReg = regCache_.Alloc(RegCache::VEC_TEMP3); + // We'll use this several times, so load into a reg. + MOVDQA(halfReg, MConstDisp(constReg, &blendHalf_11_4s[0])); + regCache_.Unlock(constReg, RegCache::GEN_CONST_BASE); + } // Add in the half bit to the factors and color values, then multiply. // We take the high 16 bits to get a free right shift by 16. - POR(srcFactorReg, R(halfReg)); - POR(argColorReg, R(halfReg)); - PMULHUW(argColorReg, R(srcFactorReg)); + if (multiplySrc) { + POR(srcFactorReg, R(halfReg)); + POR(argColorReg, R(halfReg)); + PMULHUW(argColorReg, R(srcFactorReg)); + } else if (id.AlphaBlendSrc() == PixelBlendFactor::ZERO) { + PXOR(argColorReg, R(argColorReg)); + } else if (id.AlphaBlendSrc() == PixelBlendFactor::ONE) { + if (blendState.srcColorAsFactor) + PSRLW(argColorReg, 4); + } - POR(dstFactorReg, R(halfReg)); - POR(dstReg, R(halfReg)); - PMULHUW(dstReg, R(dstFactorReg)); + if (multiplyDst) { + POR(dstFactorReg, R(halfReg)); + POR(dstReg, R(halfReg)); + PMULHUW(dstReg, R(dstFactorReg)); + } else if (id.AlphaBlendDst() == PixelBlendFactor::ZERO) { + PXOR(dstReg, R(dstReg)); + } else if (id.AlphaBlendDst() == PixelBlendFactor::ONE) { + if (blendState.dstColorAsFactor) + PSRLW(dstReg, 4); + } regCache_.Release(srcFactorReg, RegCache::VEC_TEMP1); regCache_.Release(dstFactorReg, RegCache::VEC_TEMP2); - regCache_.Release(halfReg, RegCache::VEC_TEMP3); + if (halfReg != INVALID_REG) + regCache_.Release(halfReg, RegCache::VEC_TEMP3); } else if (colorIs16Bit_) { // If it's expanded, shrink and clamp for our min/max/absdiff handling. PACKUSWB(argColorReg, R(argColorReg)); @@ -1165,7 +1190,7 @@ bool PixelJitCache::Jit_AlphaBlend(const PixelFuncID &id) { } -bool PixelJitCache::Jit_BlendFactor(const PixelFuncID &id, RegCache::Reg factorReg, RegCache::Reg dstReg, GEBlendSrcFactor factor) { +bool PixelJitCache::Jit_BlendFactor(const PixelFuncID &id, RegCache::Reg factorReg, RegCache::Reg dstReg, PixelBlendFactor factor) { X64Reg constReg = INVALID_REG; X64Reg gstateReg = INVALID_REG; X64Reg tempReg = INVALID_REG; @@ -1178,21 +1203,21 @@ bool PixelJitCache::Jit_BlendFactor(const PixelFuncID &id, RegCache::Reg factorR // In those cases, it uses SRCCOLOR, INVSRCCOLOR, and FIXB respectively. switch (factor) { - case GE_SRCBLEND_DSTCOLOR: + case PixelBlendFactor::OTHERCOLOR: MOVDQA(factorReg, R(dstReg)); break; - case GE_SRCBLEND_INVDSTCOLOR: + case PixelBlendFactor::INVOTHERCOLOR: constReg = GetConstBase(); MOVDQA(factorReg, MConstDisp(constReg, &blendInvert_11_4s[0])); PSUBUSW(factorReg, R(dstReg)); break; - case GE_SRCBLEND_SRCALPHA: + case PixelBlendFactor::SRCALPHA: PSHUFLW(factorReg, R(argColorReg), _MM_SHUFFLE(3, 3, 3, 3)); break; - case GE_SRCBLEND_INVSRCALPHA: + case PixelBlendFactor::INVSRCALPHA: constReg = GetConstBase(); tempReg = regCache_.Alloc(RegCache::VEC_TEMP3); @@ -1201,11 +1226,11 @@ bool PixelJitCache::Jit_BlendFactor(const PixelFuncID &id, RegCache::Reg factorR PSUBUSW(factorReg, R(tempReg)); break; - case GE_SRCBLEND_DSTALPHA: + case PixelBlendFactor::DSTALPHA: PSHUFLW(factorReg, R(dstReg), _MM_SHUFFLE(3, 3, 3, 3)); break; - case GE_SRCBLEND_INVDSTALPHA: + case PixelBlendFactor::INVDSTALPHA: constReg = GetConstBase(); tempReg = regCache_.Alloc(RegCache::VEC_TEMP3); @@ -1214,12 +1239,12 @@ bool PixelJitCache::Jit_BlendFactor(const PixelFuncID &id, RegCache::Reg factorR PSUBUSW(factorReg, R(tempReg)); break; - case GE_SRCBLEND_DOUBLESRCALPHA: + case PixelBlendFactor::DOUBLESRCALPHA: PSHUFLW(factorReg, R(argColorReg), _MM_SHUFFLE(3, 3, 3, 3)); PSLLW(factorReg, 1); break; - case GE_SRCBLEND_DOUBLEINVSRCALPHA: + case PixelBlendFactor::DOUBLEINVSRCALPHA: constReg = GetConstBase(); tempReg = regCache_.Alloc(RegCache::VEC_TEMP3); @@ -1229,12 +1254,12 @@ bool PixelJitCache::Jit_BlendFactor(const PixelFuncID &id, RegCache::Reg factorR PSUBUSW(factorReg, R(tempReg)); break; - case GE_SRCBLEND_DOUBLEDSTALPHA: + case PixelBlendFactor::DOUBLEDSTALPHA: PSHUFLW(factorReg, R(dstReg), _MM_SHUFFLE(3, 3, 3, 3)); PSLLW(factorReg, 1); break; - case GE_SRCBLEND_DOUBLEINVDSTALPHA: + case PixelBlendFactor::DOUBLEINVDSTALPHA: constReg = GetConstBase(); tempReg = regCache_.Alloc(RegCache::VEC_TEMP3); @@ -1244,7 +1269,19 @@ bool PixelJitCache::Jit_BlendFactor(const PixelFuncID &id, RegCache::Reg factorR PSUBUSW(factorReg, R(tempReg)); break; - case GE_SRCBLEND_FIXA: + case PixelBlendFactor::ZERO: + // Special value meaning zero. + PXOR(factorReg, R(factorReg)); + break; + + case PixelBlendFactor::ONE: + // Special value meaning all 255s. + PCMPEQD(factorReg, R(factorReg)); + PSLLW(factorReg, 8); + PSRLW(factorReg, 4); + break; + + case PixelBlendFactor::FIX: default: gstateReg = GetGState(); if (cpu_info.bSSE4_1) { @@ -1285,37 +1322,39 @@ bool PixelJitCache::Jit_DstBlendFactor(const PixelFuncID &id, RegCache::Reg srcF // We might be able to reuse srcFactorReg for dst, in some cases. switch (id.AlphaBlendDst()) { - case GE_DSTBLEND_SRCCOLOR: + case PixelBlendFactor::OTHERCOLOR: MOVDQA(dstFactorReg, R(argColorReg)); break; - case GE_DSTBLEND_INVSRCCOLOR: + case PixelBlendFactor::INVOTHERCOLOR: constReg = GetConstBase(); MOVDQA(dstFactorReg, MConstDisp(constReg, &blendInvert_11_4s[0])); PSUBUSW(dstFactorReg, R(argColorReg)); break; - case GE_DSTBLEND_SRCALPHA: - case GE_DSTBLEND_INVSRCALPHA: - case GE_DSTBLEND_DSTALPHA: - case GE_DSTBLEND_INVDSTALPHA: - case GE_DSTBLEND_DOUBLESRCALPHA: - case GE_DSTBLEND_DOUBLEINVSRCALPHA: - case GE_DSTBLEND_DOUBLEDSTALPHA: - case GE_DSTBLEND_DOUBLEINVDSTALPHA: + case PixelBlendFactor::SRCALPHA: + case PixelBlendFactor::INVSRCALPHA: + case PixelBlendFactor::DSTALPHA: + case PixelBlendFactor::INVDSTALPHA: + case PixelBlendFactor::DOUBLESRCALPHA: + case PixelBlendFactor::DOUBLEINVSRCALPHA: + case PixelBlendFactor::DOUBLEDSTALPHA: + case PixelBlendFactor::DOUBLEINVDSTALPHA: + case PixelBlendFactor::ZERO: + case PixelBlendFactor::ONE: // These are all equivalent for src factor, so reuse that logic. - if (id.AlphaBlendSrc() == GEBlendSrcFactor(id.AlphaBlendDst())) { + if (id.AlphaBlendSrc() == id.AlphaBlendDst()) { MOVDQA(dstFactorReg, R(srcFactorReg)); } else if (blendState.dstFactorIsInverse) { constReg = GetConstBase(); MOVDQA(dstFactorReg, MConstDisp(constReg, &blendInvert_11_4s[0])); PSUBUSW(dstFactorReg, R(srcFactorReg)); } else { - success = success && Jit_BlendFactor(id, dstFactorReg, dstReg, GEBlendSrcFactor(id.AlphaBlendDst())); + success = success && Jit_BlendFactor(id, dstFactorReg, dstReg, id.AlphaBlendDst()); } break; - case GE_DSTBLEND_FIXB: + case PixelBlendFactor::FIX: default: gstateReg = GetGState(); if (cpu_info.bSSE4_1) { diff --git a/GPU/Software/FuncId.cpp b/GPU/Software/FuncId.cpp index 4a23072669..cf0472f1b9 100644 --- a/GPU/Software/FuncId.cpp +++ b/GPU/Software/FuncId.cpp @@ -42,6 +42,14 @@ static inline GEComparison OptimizeRefByteCompare(GEComparison func, u8 ref) { return func; } +static inline PixelBlendFactor OptimizeAlphaFactor(uint32_t color) { + if (color == 0x00000000) + return PixelBlendFactor::ZERO; + if (color == 0x00FFFFFF) + return PixelBlendFactor::ONE; + return PixelBlendFactor::FIX; +} + void ComputePixelFuncID(PixelFuncID *id) { id->fullKey = 0; @@ -143,10 +151,16 @@ void ComputePixelFuncID(PixelFuncID *id) { if (srcFixedOne && dstFixedZero) id->alphaBlend = false; } - if (id->alphaBlend) { + if (id->alphaBlend) id->alphaBlendEq = gstate.getBlendEq(); + if (id->alphaBlend && id->alphaBlendEq <= GE_BLENDMODE_MUL_AND_SUBTRACT_REVERSE) { id->alphaBlendSrc = gstate.getBlendFuncA(); id->alphaBlendDst = gstate.getBlendFuncB(); + // Special values. + if (id->alphaBlendSrc == GE_SRCBLEND_FIXA) + id->alphaBlendSrc = (uint8_t)OptimizeAlphaFactor(gstate.getFixA()); + if (id->alphaBlendDst == GE_DSTBLEND_FIXB) + id->alphaBlendDst = (uint8_t)OptimizeAlphaFactor(gstate.getFixB()); } id->applyLogicOp = gstate.isLogicOpEnabled() && gstate.getLogicOp() != GE_LOGIC_COPY; @@ -301,30 +315,34 @@ std::string DescribePixelFuncID(const PixelFuncID &id) { case GE_BLENDMODE_ABSDIFF: desc += "BlendDiff<"; break; } switch (id.AlphaBlendSrc()) { - case GE_SRCBLEND_DSTCOLOR: desc += "DstRGB,"; break; - case GE_SRCBLEND_INVDSTCOLOR: desc += "1-DstRGB,"; break; - case GE_SRCBLEND_SRCALPHA: desc += "SrcA,"; break; - case GE_SRCBLEND_INVSRCALPHA: desc += "1-SrcA,"; break; - case GE_SRCBLEND_DSTALPHA: desc += "DstA,"; break; - case GE_SRCBLEND_INVDSTALPHA: desc += "1-DstA,"; break; - case GE_SRCBLEND_DOUBLESRCALPHA: desc += "2*SrcA,"; break; - case GE_SRCBLEND_DOUBLEINVSRCALPHA: desc += "1-2*SrcA,"; break; - case GE_SRCBLEND_DOUBLEDSTALPHA: desc += "2*DstA,"; break; - case GE_SRCBLEND_DOUBLEINVDSTALPHA: desc += "1-2*DstA,"; break; - case GE_SRCBLEND_FIXA: desc += "Fix,"; break; + case PixelBlendFactor::OTHERCOLOR: desc += "DstRGB,"; break; + case PixelBlendFactor::INVOTHERCOLOR: desc += "1-DstRGB,"; break; + case PixelBlendFactor::SRCALPHA: desc += "SrcA,"; break; + case PixelBlendFactor::INVSRCALPHA: desc += "1-SrcA,"; break; + case PixelBlendFactor::DSTALPHA: desc += "DstA,"; break; + case PixelBlendFactor::INVDSTALPHA: desc += "1-DstA,"; break; + case PixelBlendFactor::DOUBLESRCALPHA: desc += "2*SrcA,"; break; + case PixelBlendFactor::DOUBLEINVSRCALPHA: desc += "1-2*SrcA,"; break; + case PixelBlendFactor::DOUBLEDSTALPHA: desc += "2*DstA,"; break; + case PixelBlendFactor::DOUBLEINVDSTALPHA: desc += "1-2*DstA,"; break; + case PixelBlendFactor::FIX: desc += "Fix,"; break; + case PixelBlendFactor::ZERO: desc += "0,"; break; + case PixelBlendFactor::ONE: desc += "1,"; break; } switch (id.AlphaBlendDst()) { - case GE_DSTBLEND_SRCCOLOR: desc += "SrcRGB>:"; break; - case GE_DSTBLEND_INVSRCCOLOR: desc += "1-SrcRGB>:"; break; - case GE_DSTBLEND_SRCALPHA: desc += "SrcA>:"; break; - case GE_DSTBLEND_INVSRCALPHA: desc += "1-SrcA>:"; break; - case GE_DSTBLEND_DSTALPHA: desc += "DstA>:"; break; - case GE_DSTBLEND_INVDSTALPHA: desc += "1-DstA>:"; break; - case GE_DSTBLEND_DOUBLESRCALPHA: desc += "2*SrcA>:"; break; - case GE_DSTBLEND_DOUBLEINVSRCALPHA: desc += "1-2*SrcA>:"; break; - case GE_DSTBLEND_DOUBLEDSTALPHA: desc += "2*DstA>:"; break; - case GE_DSTBLEND_DOUBLEINVDSTALPHA: desc += "1-2*DstA>:"; break; - case GE_DSTBLEND_FIXB: desc += "Fix>:"; break; + case PixelBlendFactor::OTHERCOLOR: desc += "SrcRGB>:"; break; + case PixelBlendFactor::INVOTHERCOLOR: desc += "1-SrcRGB>:"; break; + case PixelBlendFactor::SRCALPHA: desc += "SrcA>:"; break; + case PixelBlendFactor::INVSRCALPHA: desc += "1-SrcA>:"; break; + case PixelBlendFactor::DSTALPHA: desc += "DstA>:"; break; + case PixelBlendFactor::INVDSTALPHA: desc += "1-DstA>:"; break; + case PixelBlendFactor::DOUBLESRCALPHA: desc += "2*SrcA>:"; break; + case PixelBlendFactor::DOUBLEINVSRCALPHA: desc += "1-2*SrcA>:"; break; + case PixelBlendFactor::DOUBLEDSTALPHA: desc += "2*DstA>:"; break; + case PixelBlendFactor::DOUBLEINVDSTALPHA: desc += "1-2*DstA>:"; break; + case PixelBlendFactor::FIX: desc += "Fix>:"; break; + case PixelBlendFactor::ZERO: desc += "0>:"; break; + case PixelBlendFactor::ONE: desc += "1>:"; break; } } diff --git a/GPU/Software/FuncId.h b/GPU/Software/FuncId.h index 738b3bb51b..9eafdf6090 100644 --- a/GPU/Software/FuncId.h +++ b/GPU/Software/FuncId.h @@ -25,6 +25,24 @@ #define SOFTPIXEL_USE_CACHE 1 +// 0-10 match GEBlendSrcFactor/GEBlendDstFactor. +enum class PixelBlendFactor { + OTHERCOLOR, + INVOTHERCOLOR, + SRCALPHA, + INVSRCALPHA, + DSTALPHA, + INVDSTALPHA, + DOUBLESRCALPHA, + DOUBLEINVSRCALPHA, + DOUBLEDSTALPHA, + DOUBLEINVDSTALPHA, + FIX, + // These are invented, but common FIX values. + ZERO, + ONE, +}; + #pragma pack(push, 1) struct PixelFuncID { @@ -110,11 +128,11 @@ struct PixelFuncID { GEBlendMode AlphaBlendEq() const { return GEBlendMode(alphaBlendEq); } - GEBlendSrcFactor AlphaBlendSrc() const { - return GEBlendSrcFactor(alphaBlendSrc); + PixelBlendFactor AlphaBlendSrc() const { + return PixelBlendFactor(alphaBlendSrc); } - GEBlendDstFactor AlphaBlendDst() const { - return GEBlendDstFactor(alphaBlendDst); + PixelBlendFactor AlphaBlendDst() const { + return PixelBlendFactor(alphaBlendDst); } GEStencilOp SFail() const { diff --git a/GPU/Software/Rasterizer.cpp b/GPU/Software/Rasterizer.cpp index e74be3716c..b4ee296adf 100644 --- a/GPU/Software/Rasterizer.cpp +++ b/GPU/Software/Rasterizer.cpp @@ -379,8 +379,8 @@ static inline Vec3 GetDestFactor(GEBlendDstFactor factor, const Vec4 & Vec3 AlphaBlendingResult(const PixelFuncID &pixelID, const Vec4 &source, const Vec4 &dst) { // Note: These factors cannot go below 0, but they can go above 255 when doubling. - Vec3 srcfactor = GetSourceFactor(pixelID.AlphaBlendSrc(), source, dst); - Vec3 dstfactor = GetDestFactor(pixelID.AlphaBlendDst(), source, dst); + Vec3 srcfactor = GetSourceFactor(GEBlendSrcFactor(pixelID.AlphaBlendSrc()), source, dst); + Vec3 dstfactor = GetDestFactor(GEBlendDstFactor(pixelID.AlphaBlendDst()), source, dst); switch (pixelID.AlphaBlendEq()) { case GE_BLENDMODE_MUL_AND_ADD: