From c011b6f67e909cffe6496bc07d3359b5b74b1d63 Mon Sep 17 00:00:00 2001
From: Subv <subv2112@gmail.com>
Date: Fri, 8 Jun 2018 17:05:52 -0500
Subject: [PATCH] GPU: Synchronize the blend state on every draw call.

Only independent blending on render target 0 is implemented for now.

This fixes the elongated squids in Splatoon 2's boot screen.
---
 .../renderer_opengl/gl_rasterizer.cpp         | 26 +++++++++++++------
 .../renderer_opengl/gl_rasterizer.h           | 10 ++-----
 2 files changed, 20 insertions(+), 16 deletions(-)

diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 6bc0dbd38..6f05f24a0 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -349,6 +349,9 @@ void RasterizerOpenGL::DrawArrays() {
     // Sync the viewport
     SyncViewport(surfaces_rect, res_scale);
 
+    // Sync the blend state registers
+    SyncBlendState();
+
     // TODO(bunnei): Sync framebuffer_scale uniform here
     // TODO(bunnei): Sync scissorbox uniform(s) here
 
@@ -735,14 +738,21 @@ void RasterizerOpenGL::SyncDepthOffset() {
     UNREACHABLE();
 }
 
-void RasterizerOpenGL::SyncBlendEnabled() {
-    UNREACHABLE();
-}
+void RasterizerOpenGL::SyncBlendState() {
+    const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
+    ASSERT_MSG(regs.independent_blend_enable == 1, "Only independent blending is implemented");
 
-void RasterizerOpenGL::SyncBlendFuncs() {
-    UNREACHABLE();
-}
+    // TODO(Subv): Support more than just render target 0.
+    state.blend.enabled = regs.blend.enable[0] != 0;
 
-void RasterizerOpenGL::SyncBlendColor() {
-    UNREACHABLE();
+    if (!state.blend.enabled)
+        return;
+
+    ASSERT_MSG(!regs.independent_blend[0].separate_alpha, "Unimplemented");
+    state.blend.rgb_equation = MaxwellToGL::BlendEquation(regs.independent_blend[0].equation_rgb);
+    state.blend.src_rgb_func = MaxwellToGL::BlendFunc(regs.independent_blend[0].factor_source_rgb);
+    state.blend.dst_rgb_func = MaxwellToGL::BlendFunc(regs.independent_blend[0].factor_dest_rgb);
+    state.blend.a_equation = MaxwellToGL::BlendEquation(regs.independent_blend[0].equation_a);
+    state.blend.src_a_func = MaxwellToGL::BlendFunc(regs.independent_blend[0].factor_source_a);
+    state.blend.dst_a_func = MaxwellToGL::BlendFunc(regs.independent_blend[0].factor_dest_a);
 }
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index d3f0558ed..b7c8cf843 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -121,14 +121,8 @@ private:
     /// Syncs the depth offset to match the guest state
     void SyncDepthOffset();
 
-    /// Syncs the blend enabled status to match the guest state
-    void SyncBlendEnabled();
-
-    /// Syncs the blend functions to match the guest state
-    void SyncBlendFuncs();
-
-    /// Syncs the blend color to match the guest state
-    void SyncBlendColor();
+    /// Syncs the blend state to match the guest state
+    void SyncBlendState();
 
     bool has_ARB_buffer_storage;
     bool has_ARB_direct_state_access;