aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/video_core/rasterizer.cpp
diff options
context:
space:
mode:
authorGravatar Tony Wasserka <NeoBrainX@gmail.com>2014-12-21 03:00:25 +0100
committerGravatar Tony Wasserka <NeoBrainX@gmail.com>2014-12-31 16:32:55 +0100
commita7ae0330b1e4d5aa7fab3bb07bb2cf58f8572dc5 (patch)
treec95a7eb9b78dde4ae716ce8b168cc4fd80eebea9 /src/video_core/rasterizer.cpp
parente229ff8c836fa213f1bdd31cabe924457f5e7e0c (diff)
Pica/Rasterizer: Implement alpha blending.
Diffstat (limited to 'src/video_core/rasterizer.cpp')
-rw-r--r--src/video_core/rasterizer.cpp84
1 files changed, 84 insertions, 0 deletions
diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp
index 8dff2db2..5f7971fe 100644
--- a/src/video_core/rasterizer.cpp
+++ b/src/video_core/rasterizer.cpp
@@ -25,6 +25,18 @@ static void DrawPixel(int x, int y, const Math::Vec4<u8>& color) {
*(color_buffer + x + y * registers.framebuffer.GetWidth()) = value;
}
+static const Math::Vec4<u8> GetPixel(int x, int y) {
+ u32* color_buffer_u32 = reinterpret_cast<u32*>(Memory::GetPointer(PAddrToVAddr(registers.framebuffer.GetColorBufferPhysicalAddress())));
+
+ u32 value = *(color_buffer_u32 + x + y * registers.framebuffer.GetWidth());
+ Math::Vec4<u8> ret;
+ ret.a() = value >> 24;
+ ret.r() = (value >> 16) & 0xFF;
+ ret.g() = (value >> 8) & 0xFF;
+ ret.b() = value & 0xFF;
+ return ret;
+ }
+
static u32 GetDepth(int x, int y) {
u16* depth_buffer = reinterpret_cast<u16*>(Memory::GetPointer(PAddrToVAddr(registers.framebuffer.GetDepthBufferPhysicalAddress())));
@@ -430,6 +442,78 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
SetDepth(x >> 4, y >> 4, z);
}
+ auto dest = GetPixel(x >> 4, y >> 4);
+
+ if (registers.output_merger.alphablend_enable) {
+ auto params = registers.output_merger.alpha_blending;
+
+ auto LookupFactorRGB = [&](decltype(params)::BlendFactor factor) -> Math::Vec3<u8> {
+ switch(factor) {
+ case params.Zero:
+ return Math::Vec3<u8>(0, 0, 0);
+
+ case params.One:
+ return Math::Vec3<u8>(255, 255, 255);
+
+ case params.SourceAlpha:
+ return Math::MakeVec(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());
+
+ default:
+ LOG_CRITICAL(HW_GPU, "Unknown color blend factor %x", factor);
+ exit(0);
+ break;
+ }
+ };
+
+ auto LookupFactorA = [&](decltype(params)::BlendFactor factor) -> u8 {
+ switch(factor) {
+ case params.Zero:
+ return 0;
+
+ case params.One:
+ return 255;
+
+ case params.SourceAlpha:
+ return combiner_output.a();
+
+ case params.OneMinusSourceAlpha:
+ return 255 - combiner_output.a();
+
+ default:
+ LOG_CRITICAL(HW_GPU, "Unknown alpha blend factor %x", factor);
+ exit(0);
+ break;
+ }
+ };
+
+ auto srcfactor = Math::MakeVec(LookupFactorRGB(params.factor_source_rgb),
+ LookupFactorA(params.factor_source_a));
+ auto dstfactor = Math::MakeVec(LookupFactorRGB(params.factor_dest_rgb),
+ LookupFactorA(params.factor_dest_a));
+
+ switch (params.blend_equation_rgb) {
+ case params.Add:
+ {
+ auto result = (combiner_output * srcfactor + dest * dstfactor) / 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;
+ }
+
+ default:
+ LOG_CRITICAL(HW_GPU, "Unknown RGB blend equation %x", params.blend_equation_rgb.Value());
+ exit(0);
+ }
+ } else {
+ LOG_CRITICAL(HW_GPU, "logic op: %x", registers.output_merger.logic_op);
+ exit(0);
+ }
+
DrawPixel(x >> 4, y >> 4, combiner_output);
}
}