summaryrefslogtreecommitdiff
path: root/src/video_core/rasterizer.cpp
diff options
context:
space:
mode:
authorGravatar Tony Wasserka2015-02-11 21:39:43 +0100
committerGravatar Tony Wasserka2015-02-18 14:50:28 +0100
commit156120434251d0ae726442206f8b5b41338d700d (patch)
treeb61426e3aa93a56c80283037172fbf61dc45f7a0 /src/video_core/rasterizer.cpp
parentPica/TextureEnvironment: Add a note. (diff)
downloadyuzu-156120434251d0ae726442206f8b5b41338d700d.tar.gz
yuzu-156120434251d0ae726442206f8b5b41338d700d.tar.xz
yuzu-156120434251d0ae726442206f8b5b41338d700d.zip
Pica/BlendUnit: Implement separate color/alpha blend equations.
Diffstat (limited to 'src/video_core/rasterizer.cpp')
-rw-r--r--src/video_core/rasterizer.cpp122
1 files changed, 58 insertions, 64 deletions
diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp
index b7a7e62ab..f96015de4 100644
--- a/src/video_core/rasterizer.cpp
+++ b/src/video_core/rasterizer.cpp
@@ -5,6 +5,7 @@
5#include <algorithm> 5#include <algorithm>
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8#include "common/math_util.h"
8 9
9#include "math.h" 10#include "math.h"
10#include "pica.h" 11#include "pica.h"
@@ -596,6 +597,7 @@ static void ProcessTriangleInternal(const VertexShader::OutputVertex& v0,
596 } 597 }
597 598
598 auto dest = GetPixel(x >> 4, y >> 4); 599 auto dest = GetPixel(x >> 4, y >> 4);
600 Math::Vec4<u8> blend_output = combiner_output;
599 601
600 if (registers.output_merger.alphablend_enable) { 602 if (registers.output_merger.alphablend_enable) {
601 auto params = registers.output_merger.alpha_blending; 603 auto params = registers.output_merger.alpha_blending;
@@ -684,81 +686,73 @@ static void ProcessTriangleInternal(const VertexShader::OutputVertex& v0,
684 } 686 }
685 }; 687 };
686 688
689 using BlendEquation = decltype(params)::BlendEquation;
690 static auto EvaluateBlendEquation = [](const Math::Vec4<u8>& src, const Math::Vec4<u8>& srcfactor,
691 const Math::Vec4<u8>& dest, const Math::Vec4<u8>& destfactor,
692 BlendEquation equation) {
693 Math::Vec4<int> result;
694
695 auto src_result = (src * srcfactor).Cast<int>();
696 auto dst_result = (dest * destfactor).Cast<int>();
697
698 switch (equation) {
699 case BlendEquation::Add:
700 result = (src_result + dst_result) / 255;
701 break;
702
703 case BlendEquation::Subtract:
704 result = (src_result - dst_result) / 255;
705 break;
706
707 case BlendEquation::ReverseSubtract:
708 result = (dst_result - src_result) / 255;
709 break;
710
711 // TODO: How do these two actually work?
712 // OpenGL doesn't include the blend factors in the min/max computations,
713 // but is this what the 3DS actually does?
714 case BlendEquation::Min:
715 result.r() = std::min(src.r(), dest.r());
716 result.g() = std::min(src.g(), dest.g());
717 result.b() = std::min(src.b(), dest.b());
718 result.a() = std::min(src.a(), dest.a());
719 break;
720
721 case BlendEquation::Max:
722 result.r() = std::max(src.r(), dest.r());
723 result.g() = std::max(src.g(), dest.g());
724 result.b() = std::max(src.b(), dest.b());
725 result.a() = std::max(src.a(), dest.a());
726 break;
727
728 default:
729 LOG_CRITICAL(HW_GPU, "Unknown RGB blend equation %x", equation);
730 exit(0);
731 }
732
733 return Math::Vec4<u8>(MathUtil::Clamp(result.r(), 0, 255),
734 MathUtil::Clamp(result.g(), 0, 255),
735 MathUtil::Clamp(result.b(), 0, 255),
736 MathUtil::Clamp(result.a(), 0, 255));
737 };
738
687 auto srcfactor = Math::MakeVec(LookupFactorRGB(params.factor_source_rgb), 739 auto srcfactor = Math::MakeVec(LookupFactorRGB(params.factor_source_rgb),
688 LookupFactorA(params.factor_source_a)); 740 LookupFactorA(params.factor_source_a));
689 auto dstfactor = Math::MakeVec(LookupFactorRGB(params.factor_dest_rgb), 741 auto dstfactor = Math::MakeVec(LookupFactorRGB(params.factor_dest_rgb),
690 LookupFactorA(params.factor_dest_a)); 742 LookupFactorA(params.factor_dest_a));
691
692 auto src_result = (combiner_output * srcfactor).Cast<int>();
693 auto dst_result = (dest * dstfactor).Cast<int>();
694
695 switch (params.blend_equation_rgb) {
696 case params.Add:
697 {
698 auto result = (src_result + dst_result) / 255;
699 result.r() = std::min(255, result.r());
700 result.g() = std::min(255, result.g());
701 result.b() = std::min(255, result.b());
702 combiner_output = result.Cast<u8>();
703 break;
704 }
705
706 case params.Subtract:
707 {
708 auto result = (src_result - dst_result) / 255;
709 result.r() = std::max(0, result.r());
710 result.g() = std::max(0, result.g());
711 result.b() = std::max(0, result.b());
712 combiner_output = result.Cast<u8>();
713 break;
714 }
715
716 case params.ReverseSubtract:
717 {
718 auto result = (dst_result - src_result) / 255;
719 result.r() = std::max(0, result.r());
720 result.g() = std::max(0, result.g());
721 result.b() = std::max(0, result.b());
722 combiner_output = result.Cast<u8>();
723 break;
724 }
725
726 case params.Min:
727 {
728 // TODO: GL spec says to do it without the factors, but is this what the 3DS does?
729 Math::Vec4<int> result;
730 result.r() = std::min(combiner_output.r(),dest.r());
731 result.g() = std::min(combiner_output.g(),dest.g());
732 result.b() = std::min(combiner_output.b(),dest.b());
733 combiner_output = result.Cast<u8>();
734 break;
735 }
736
737 case params.Max:
738 {
739 // TODO: GL spec says to do it without the factors, but is this what the 3DS does?
740 Math::Vec4<int> result;
741 result.r() = std::max(combiner_output.r(),dest.r());
742 result.g() = std::max(combiner_output.g(),dest.g());
743 result.b() = std::max(combiner_output.b(),dest.b());
744 combiner_output = result.Cast<u8>();
745 break;
746 }
747 743
748 default: 744 blend_output = EvaluateBlendEquation(combiner_output, srcfactor, dest, dstfactor, params.blend_equation_rgb);
749 LOG_CRITICAL(HW_GPU, "Unknown RGB blend equation %x", params.blend_equation_rgb.Value()); 745 blend_output.a() = EvaluateBlendEquation(combiner_output, srcfactor, dest, dstfactor, params.blend_equation_a).a();
750 exit(0);
751 }
752 } else { 746 } else {
753 LOG_CRITICAL(HW_GPU, "logic op: %x", registers.output_merger.logic_op); 747 LOG_CRITICAL(HW_GPU, "logic op: %x", registers.output_merger.logic_op);
754 exit(0); 748 exit(0);
755 } 749 }
756 750
757 const Math::Vec4<u8> result = { 751 const Math::Vec4<u8> result = {
758 registers.output_merger.red_enable ? combiner_output.r() : dest.r(), 752 registers.output_merger.red_enable ? blend_output.r() : dest.r(),
759 registers.output_merger.green_enable ? combiner_output.g() : dest.g(), 753 registers.output_merger.green_enable ? blend_output.g() : dest.g(),
760 registers.output_merger.blue_enable ? combiner_output.b() : dest.b(), 754 registers.output_merger.blue_enable ? blend_output.b() : dest.b(),
761 registers.output_merger.alpha_enable ? combiner_output.a() : dest.a() 755 registers.output_merger.alpha_enable ? blend_output.a() : dest.a()
762 }; 756 };
763 757
764 DrawPixel(x >> 4, y >> 4, result); 758 DrawPixel(x >> 4, y >> 4, result);