diff options
| -rw-r--r-- | src/video_core/pica.h | 6 | ||||
| -rw-r--r-- | src/video_core/rasterizer.cpp | 45 |
2 files changed, 49 insertions, 2 deletions
diff --git a/src/video_core/pica.h b/src/video_core/pica.h index 1566b890d..9c1a12dc8 100644 --- a/src/video_core/pica.h +++ b/src/video_core/pica.h | |||
| @@ -338,7 +338,11 @@ struct Regs { | |||
| 338 | 338 | ||
| 339 | union { | 339 | union { |
| 340 | enum BlendEquation : u32 { | 340 | enum BlendEquation : u32 { |
| 341 | Add = 0, | 341 | Add = 0, |
| 342 | Subtract = 1, | ||
| 343 | ReverseSubtract = 2, | ||
| 344 | Min = 3, | ||
| 345 | Max = 4 | ||
| 342 | }; | 346 | }; |
| 343 | 347 | ||
| 344 | enum BlendFactor : u32 { | 348 | enum BlendFactor : u32 { |
diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp index 5920477eb..06fd8d140 100644 --- a/src/video_core/rasterizer.cpp +++ b/src/video_core/rasterizer.cpp | |||
| @@ -616,17 +616,60 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0, | |||
| 616 | LookupFactorA(params.factor_source_a)); | 616 | LookupFactorA(params.factor_source_a)); |
| 617 | auto dstfactor = Math::MakeVec(LookupFactorRGB(params.factor_dest_rgb), | 617 | auto dstfactor = Math::MakeVec(LookupFactorRGB(params.factor_dest_rgb), |
| 618 | LookupFactorA(params.factor_dest_a)); | 618 | LookupFactorA(params.factor_dest_a)); |
| 619 | |||
| 620 | auto src_result = (combiner_output * srcfactor).Cast<int>(); | ||
| 621 | auto dst_result = (dest * dstfactor).Cast<int>(); | ||
| 619 | 622 | ||
| 620 | switch (params.blend_equation_rgb) { | 623 | switch (params.blend_equation_rgb) { |
| 621 | case params.Add: | 624 | case params.Add: |
| 622 | { | 625 | { |
| 623 | auto result = (combiner_output * srcfactor + dest * dstfactor) / 255; | 626 | auto result = (src_result + dst_result) / 255; |
| 624 | result.r() = std::min(255, result.r()); | 627 | result.r() = std::min(255, result.r()); |
| 625 | result.g() = std::min(255, result.g()); | 628 | result.g() = std::min(255, result.g()); |
| 626 | result.b() = std::min(255, result.b()); | 629 | result.b() = std::min(255, result.b()); |
| 627 | combiner_output = result.Cast<u8>(); | 630 | combiner_output = result.Cast<u8>(); |
| 628 | break; | 631 | break; |
| 629 | } | 632 | } |
| 633 | |||
| 634 | case params.Subtract: | ||
| 635 | { | ||
| 636 | auto result = (src_result - dst_result) / 255; | ||
| 637 | result.r() = std::max(0, result.r()); | ||
| 638 | result.g() = std::max(0, result.g()); | ||
| 639 | result.b() = std::max(0, result.b()); | ||
| 640 | combiner_output = result.Cast<u8>(); | ||
| 641 | break; | ||
| 642 | } | ||
| 643 | |||
| 644 | case params.ReverseSubtract: | ||
| 645 | { | ||
| 646 | auto result = (dst_result - src_result) / 255; | ||
| 647 | result.r() = std::max(0, result.r()); | ||
| 648 | result.g() = std::max(0, result.g()); | ||
| 649 | result.b() = std::max(0, result.b()); | ||
| 650 | combiner_output = result.Cast<u8>(); | ||
| 651 | break; | ||
| 652 | } | ||
| 653 | |||
| 654 | case params.Min: | ||
| 655 | { | ||
| 656 | Math::Vec4<int> result; | ||
| 657 | result.r() = std::min(src_result.r(),dst_result.r()); | ||
| 658 | result.g() = std::min(src_result.g(),dst_result.g()); | ||
| 659 | result.b() = std::min(src_result.b(),dst_result.b()); | ||
| 660 | combiner_output = result.Cast<u8>(); | ||
| 661 | break; | ||
| 662 | } | ||
| 663 | |||
| 664 | case params.Max: | ||
| 665 | { | ||
| 666 | Math::Vec4<int> result; | ||
| 667 | result.r() = std::max(src_result.r(),dst_result.r()); | ||
| 668 | result.g() = std::max(src_result.g(),dst_result.g()); | ||
| 669 | result.b() = std::max(src_result.b(),dst_result.b()); | ||
| 670 | combiner_output = result.Cast<u8>(); | ||
| 671 | break; | ||
| 672 | } | ||
| 630 | 673 | ||
| 631 | default: | 674 | default: |
| 632 | LOG_CRITICAL(HW_GPU, "Unknown RGB blend equation %x", params.blend_equation_rgb.Value()); | 675 | LOG_CRITICAL(HW_GPU, "Unknown RGB blend equation %x", params.blend_equation_rgb.Value()); |