diff --git a/Source/Core/VideoCommon/CMakeLists.txt b/Source/Core/VideoCommon/CMakeLists.txt
index 38829432f9..cb9bc61720 100644
--- a/Source/Core/VideoCommon/CMakeLists.txt
+++ b/Source/Core/VideoCommon/CMakeLists.txt
@@ -25,6 +25,7 @@ set(SRCS AsyncRequests.cpp
PixelShaderManager.cpp
PostProcessing.cpp
RenderBase.cpp
+ RenderState.cpp
Statistics.cpp
TextureCacheBase.cpp
TextureConversionShader.cpp
diff --git a/Source/Core/VideoCommon/RenderState.cpp b/Source/Core/VideoCommon/RenderState.cpp
new file mode 100644
index 0000000000..2750d43695
--- /dev/null
+++ b/Source/Core/VideoCommon/RenderState.cpp
@@ -0,0 +1,119 @@
+// Copyright 2016 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#include "VideoCommon/RenderState.h"
+
+// If the framebuffer format has no alpha channel, it is assumed to
+// ONE on blending. As the backends may emulate this framebuffer
+// configuration with an alpha channel, we just drop all references
+// to the destination alpha channel.
+static BlendMode::BlendFactor RemoveDstAlphaUsage(BlendMode::BlendFactor factor)
+{
+ switch (factor)
+ {
+ case BlendMode::DSTALPHA:
+ return BlendMode::ONE;
+ case BlendMode::INVDSTALPHA:
+ return BlendMode::ZERO;
+ default:
+ return factor;
+ }
+}
+
+// We separate the blending parameter for rgb and alpha. For blending
+// the alpha component, CLR and ALPHA are indentical. So just always
+// use ALPHA as this makes it easier for the backends to use the second
+// alpha value of dual source blending.
+static BlendMode::BlendFactor RemoveSrcColorUsage(BlendMode::BlendFactor factor)
+{
+ switch (factor)
+ {
+ case BlendMode::SRCCLR:
+ return BlendMode::SRCALPHA;
+ case BlendMode::INVSRCCLR:
+ return BlendMode::INVSRCALPHA;
+ default:
+ return factor;
+ }
+}
+
+// Same as RemoveSrcColorUsage, but because of the overlapping enum,
+// this must be written as another function.
+static BlendMode::BlendFactor RemoveDstColorUsage(BlendMode::BlendFactor factor)
+{
+ switch (factor)
+ {
+ case BlendMode::DSTCLR:
+ return BlendMode::DSTALPHA;
+ case BlendMode::INVDSTCLR:
+ return BlendMode::INVDSTALPHA;
+ default:
+ return factor;
+ }
+}
+
+void BlendingState::Generate(const BPMemory& bp)
+{
+ // Start with everything disabled.
+ hex = 0;
+
+ bool target_has_alpha = bp.zcontrol.pixel_format == PEControl::RGBA6_Z24;
+ bool alpha_test_may_success = bp.alpha_test.TestResult() != AlphaTest::FAIL;
+
+ dither = bp.blendmode.dither;
+ colorupdate = bp.blendmode.colorupdate && alpha_test_may_success;
+ alphaupdate = bp.blendmode.alphaupdate && target_has_alpha && alpha_test_may_success;
+ dstalpha = bp.dstalpha.enable && alphaupdate;
+
+ // The subtract bit has the highest priority
+ if (bp.blendmode.subtract)
+ {
+ blendenable = true;
+ subtractAlpha = subtract = true;
+ srcfactoralpha = srcfactor = BlendMode::ONE;
+ dstfactoralpha = dstfactor = BlendMode::ONE;
+
+ if (dstalpha)
+ {
+ subtractAlpha = false;
+ srcfactoralpha = BlendMode::ONE;
+ dstfactoralpha = BlendMode::ZERO;
+ }
+ }
+
+ // The blendenable bit has the middle priority
+ else if (bp.blendmode.blendenable)
+ {
+ blendenable = true;
+ srcfactor = bp.blendmode.srcfactor;
+ dstfactor = bp.blendmode.dstfactor;
+ if (!target_has_alpha)
+ {
+ // uses ONE instead of DSTALPHA
+ srcfactor = RemoveDstAlphaUsage(srcfactor);
+ dstfactor = RemoveDstAlphaUsage(dstfactor);
+ }
+ // replaces SRCCLR with SRCALPHA
+ srcfactoralpha = RemoveSrcColorUsage(srcfactor);
+ dstfactoralpha = RemoveDstColorUsage(dstfactor);
+
+ if (dstalpha)
+ {
+ srcfactoralpha = BlendMode::ONE;
+ dstfactoralpha = BlendMode::ZERO;
+ }
+ }
+
+ // The logicop bit has the lowest priority
+ else if (bp.blendmode.logicopenable)
+ {
+ logicopenable = true;
+ logicmode = bp.blendmode.logicmode;
+
+ if (dstalpha)
+ {
+ // TODO: Not supported by backends.
+ }
+ }
+}
diff --git a/Source/Core/VideoCommon/RenderState.h b/Source/Core/VideoCommon/RenderState.h
new file mode 100644
index 0000000000..cadd83e1a3
--- /dev/null
+++ b/Source/Core/VideoCommon/RenderState.h
@@ -0,0 +1,31 @@
+// Copyright 2016 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "Common/BitField.h"
+
+#include "VideoCommon/BPMemory.h"
+#include "VideoCommon/BPStructs.h"
+
+union BlendingState
+{
+ void Generate(const BPMemory& bp);
+
+ BitField<0, 1, u32> blendenable;
+ BitField<1, 1, u32> logicopenable;
+ BitField<2, 1, u32> dstalpha;
+ BitField<3, 1, u32> dither;
+ BitField<4, 1, u32> colorupdate;
+ BitField<5, 1, u32> alphaupdate;
+ BitField<6, 1, u32> subtract;
+ BitField<7, 1, u32> subtractAlpha;
+ BitField<8, 3, BlendMode::BlendFactor> dstfactor;
+ BitField<11, 3, BlendMode::BlendFactor> srcfactor;
+ BitField<14, 3, BlendMode::BlendFactor> dstfactoralpha;
+ BitField<17, 3, BlendMode::BlendFactor> srcfactoralpha;
+ BitField<20, 4, BlendMode::LogicOp> logicmode;
+
+ u32 hex;
+};
diff --git a/Source/Core/VideoCommon/VideoCommon.vcxproj b/Source/Core/VideoCommon/VideoCommon.vcxproj
index 205f225101..e742711edf 100644
--- a/Source/Core/VideoCommon/VideoCommon.vcxproj
+++ b/Source/Core/VideoCommon/VideoCommon.vcxproj
@@ -80,6 +80,7 @@
+
@@ -134,6 +135,7 @@
+
@@ -183,4 +185,4 @@
-
\ No newline at end of file
+
diff --git a/Source/Core/VideoCommon/VideoCommon.vcxproj.filters b/Source/Core/VideoCommon/VideoCommon.vcxproj.filters
index 32e0a870cf..5340250808 100644
--- a/Source/Core/VideoCommon/VideoCommon.vcxproj.filters
+++ b/Source/Core/VideoCommon/VideoCommon.vcxproj.filters
@@ -44,6 +44,9 @@
Base
+
+ Base
+
Base
@@ -182,6 +185,9 @@
Base
+
+ Base
+
Base
@@ -312,4 +318,4 @@
-
\ No newline at end of file
+