diff options
Diffstat (limited to 'src/video_core/rasterizer.cpp')
-rw-r--r-- | src/video_core/rasterizer.cpp | 192 |
1 files changed, 139 insertions, 53 deletions
diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp index 7f66c6d4..06fd8d14 100644 --- a/src/video_core/rasterizer.cpp +++ b/src/video_core/rasterizer.cpp @@ -260,7 +260,7 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0, using AlphaModifier = Regs::TevStageConfig::AlphaModifier; using Operation = Regs::TevStageConfig::Operation; - auto GetColorSource = [&](Source source) -> Math::Vec4<u8> { + auto GetSource = [&](Source source) -> Math::Vec4<u8> { switch (source) { case Source::PrimaryColor: return primary_color; @@ -287,36 +287,8 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0, } }; - auto GetAlphaSource = [&](Source source) -> u8 { - switch (source) { - case Source::PrimaryColor: - return primary_color.a(); - - case Source::Texture0: - return texture_color[0].a(); - - case Source::Texture1: - return texture_color[1].a(); - - case Source::Texture2: - return texture_color[2].a(); - - case Source::Constant: - return tev_stage.const_a; - - case Source::Previous: - return combiner_output.a(); - - default: - LOG_ERROR(HW_GPU, "Unknown alpha combiner source %d\n", (int)source); - _dbg_assert_(HW_GPU, 0); - return 0; - } - }; - static auto GetColorModifier = [](ColorModifier factor, const Math::Vec4<u8>& values) -> Math::Vec3<u8> { - switch (factor) - { + switch (factor) { case ColorModifier::SourceColor: return values.rgb(); @@ -324,27 +296,56 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0, return (Math::Vec3<u8>(255, 255, 255) - values.rgb()).Cast<u8>(); case ColorModifier::SourceAlpha: - return { values.a(), values.a(), values.a() }; + return values.aaa(); - default: - LOG_ERROR(HW_GPU, "Unknown color factor %d\n", (int)factor); - _dbg_assert_(HW_GPU, 0); - return {}; + case ColorModifier::OneMinusSourceAlpha: + return (Math::Vec3<u8>(255, 255, 255) - values.aaa()).Cast<u8>(); + + case ColorModifier::SourceRed: + return values.rrr(); + + case ColorModifier::OneMinusSourceRed: + return (Math::Vec3<u8>(255, 255, 255) - values.rrr()).Cast<u8>(); + + case ColorModifier::SourceGreen: + return values.ggg(); + + case ColorModifier::OneMinusSourceGreen: + return (Math::Vec3<u8>(255, 255, 255) - values.ggg()).Cast<u8>(); + + case ColorModifier::SourceBlue: + return values.bbb(); + + case ColorModifier::OneMinusSourceBlue: + return (Math::Vec3<u8>(255, 255, 255) - values.bbb()).Cast<u8>(); } }; - static auto GetAlphaModifier = [](AlphaModifier factor, u8 value) -> u8 { + static auto GetAlphaModifier = [](AlphaModifier factor, const Math::Vec4<u8>& values) -> u8 { switch (factor) { case AlphaModifier::SourceAlpha: - return value; + return values.a(); case AlphaModifier::OneMinusSourceAlpha: - return 255 - value; + return 255 - values.a(); - default: - LOG_ERROR(HW_GPU, "Unknown alpha factor %d\n", (int)factor); - _dbg_assert_(HW_GPU, 0); - return 0; + case AlphaModifier::SourceRed: + return values.r(); + + case AlphaModifier::OneMinusSourceRed: + return 255 - values.r(); + + case AlphaModifier::SourceGreen: + return values.g(); + + case AlphaModifier::OneMinusSourceGreen: + return 255 - values.g(); + + case AlphaModifier::SourceBlue: + return values.b(); + + case AlphaModifier::OneMinusSourceBlue: + return 255 - values.b(); } }; @@ -414,17 +415,17 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0, // combiner_output.rgb(), but instead store it in a temporary variable until // alpha combining has been done. Math::Vec3<u8> color_result[3] = { - GetColorModifier(tev_stage.color_modifier1, GetColorSource(tev_stage.color_source1)), - GetColorModifier(tev_stage.color_modifier2, GetColorSource(tev_stage.color_source2)), - GetColorModifier(tev_stage.color_modifier3, GetColorSource(tev_stage.color_source3)) + GetColorModifier(tev_stage.color_modifier1, GetSource(tev_stage.color_source1)), + GetColorModifier(tev_stage.color_modifier2, GetSource(tev_stage.color_source2)), + GetColorModifier(tev_stage.color_modifier3, GetSource(tev_stage.color_source3)) }; auto color_output = ColorCombine(tev_stage.color_op, color_result); // alpha combiner std::array<u8,3> alpha_result = { - GetAlphaModifier(tev_stage.alpha_modifier1, GetAlphaSource(tev_stage.alpha_source1)), - GetAlphaModifier(tev_stage.alpha_modifier2, GetAlphaSource(tev_stage.alpha_source2)), - GetAlphaModifier(tev_stage.alpha_modifier3, GetAlphaSource(tev_stage.alpha_source3)) + GetAlphaModifier(tev_stage.alpha_modifier1, GetSource(tev_stage.alpha_source1)), + GetAlphaModifier(tev_stage.alpha_modifier2, GetSource(tev_stage.alpha_source2)), + GetAlphaModifier(tev_stage.alpha_modifier3, GetSource(tev_stage.alpha_source3)) }; auto alpha_output = AlphaCombine(tev_stage.alpha_op, alpha_result); @@ -528,18 +529,48 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0, auto params = registers.output_merger.alpha_blending; auto LookupFactorRGB = [&](decltype(params)::BlendFactor factor) -> Math::Vec3<u8> { - switch(factor) { + switch (factor) { case params.Zero: return Math::Vec3<u8>(0, 0, 0); case params.One: return Math::Vec3<u8>(255, 255, 255); + case params.SourceColor: + return combiner_output.rgb(); + + case params.OneMinusSourceColor: + return Math::Vec3<u8>(255 - combiner_output.r(), 255 - combiner_output.g(), 255 - combiner_output.b()); + + case params.DestColor: + return dest.rgb(); + + case params.OneMinusDestColor: + return Math::Vec3<u8>(255 - dest.r(), 255 - dest.g(), 255 - dest.b()); + case params.SourceAlpha: - return Math::MakeVec(combiner_output.a(), combiner_output.a(), combiner_output.a()); + return Math::Vec3<u8>(combiner_output.a(), combiner_output.a(), combiner_output.a()); case params.OneMinusSourceAlpha: - return Math::Vec3<u8>(255-combiner_output.a(), 255-combiner_output.a(), 255-combiner_output.a()); + return Math::Vec3<u8>(255 - combiner_output.a(), 255 - combiner_output.a(), 255 - combiner_output.a()); + + case params.DestAlpha: + return Math::Vec3<u8>(dest.a(), dest.a(), dest.a()); + + case params.OneMinusDestAlpha: + return Math::Vec3<u8>(255 - dest.a(), 255 - dest.a(), 255 - dest.a()); + + case params.ConstantColor: + return Math::Vec3<u8>(registers.output_merger.blend_const.r, registers.output_merger.blend_const.g, registers.output_merger.blend_const.b); + + case params.OneMinusConstantColor: + return Math::Vec3<u8>(255 - registers.output_merger.blend_const.r, 255 - registers.output_merger.blend_const.g, 255 - registers.output_merger.blend_const.b); + + case params.ConstantAlpha: + return Math::Vec3<u8>(registers.output_merger.blend_const.a, registers.output_merger.blend_const.a, registers.output_merger.blend_const.a); + + case params.OneMinusConstantAlpha: + return Math::Vec3<u8>(255 - registers.output_merger.blend_const.a, 255 - registers.output_merger.blend_const.a, 255 - registers.output_merger.blend_const.a); default: LOG_CRITICAL(HW_GPU, "Unknown color blend factor %x", factor); @@ -549,7 +580,7 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0, }; auto LookupFactorA = [&](decltype(params)::BlendFactor factor) -> u8 { - switch(factor) { + switch (factor) { case params.Zero: return 0; @@ -562,6 +593,18 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0, case params.OneMinusSourceAlpha: return 255 - combiner_output.a(); + case params.DestAlpha: + return dest.a(); + + case params.OneMinusDestAlpha: + return 255 - dest.a(); + + case params.ConstantAlpha: + return registers.output_merger.blend_const.a; + + case params.OneMinusConstantAlpha: + return 255 - registers.output_merger.blend_const.a; + default: LOG_CRITICAL(HW_GPU, "Unknown alpha blend factor %x", factor); exit(0); @@ -573,17 +616,60 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0, LookupFactorA(params.factor_source_a)); auto dstfactor = Math::MakeVec(LookupFactorRGB(params.factor_dest_rgb), LookupFactorA(params.factor_dest_a)); + + auto src_result = (combiner_output * srcfactor).Cast<int>(); + auto dst_result = (dest * dstfactor).Cast<int>(); switch (params.blend_equation_rgb) { case params.Add: { - auto result = (combiner_output * srcfactor + dest * dstfactor) / 255; + auto result = (src_result + dst_result) / 255; result.r() = std::min(255, result.r()); result.g() = std::min(255, result.g()); result.b() = std::min(255, result.b()); combiner_output = result.Cast<u8>(); break; } + + case params.Subtract: + { + auto result = (src_result - dst_result) / 255; + result.r() = std::max(0, result.r()); + result.g() = std::max(0, result.g()); + result.b() = std::max(0, result.b()); + combiner_output = result.Cast<u8>(); + break; + } + + case params.ReverseSubtract: + { + auto result = (dst_result - src_result) / 255; + result.r() = std::max(0, result.r()); + result.g() = std::max(0, result.g()); + result.b() = std::max(0, result.b()); + combiner_output = result.Cast<u8>(); + break; + } + + case params.Min: + { + Math::Vec4<int> result; + result.r() = std::min(src_result.r(),dst_result.r()); + result.g() = std::min(src_result.g(),dst_result.g()); + result.b() = std::min(src_result.b(),dst_result.b()); + combiner_output = result.Cast<u8>(); + break; + } + + case params.Max: + { + Math::Vec4<int> result; + result.r() = std::max(src_result.r(),dst_result.r()); + result.g() = std::max(src_result.g(),dst_result.g()); + result.b() = std::max(src_result.b(),dst_result.b()); + combiner_output = result.Cast<u8>(); + break; + } default: LOG_CRITICAL(HW_GPU, "Unknown RGB blend equation %x", params.blend_equation_rgb.Value()); |