summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/RenderState.cpp
diff options
context:
space:
mode:
authordegasus <wickmarkus@web.de>2016-12-29 17:31:51 +0100
committerdegasus <wickmarkus@web.de>2017-01-06 14:01:36 +0100
commit3df828463d74645884414d5cc994e1fda4de6c67 (patch)
tree3d4e3bd004ef7ccf8bf8f99ff21d1ad449853f6a /Source/Core/VideoCommon/RenderState.cpp
parentc33c9532a78000224f63c4a293d031452606a8ed (diff)
VideoCommon: Assembly blending state in a shared state object.
Diffstat (limited to 'Source/Core/VideoCommon/RenderState.cpp')
-rw-r--r--Source/Core/VideoCommon/RenderState.cpp119
1 files changed, 119 insertions, 0 deletions
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.
+ }
+ }
+}