diff options
| author | degasus <wickmarkus@web.de> | 2016-12-29 17:31:51 +0100 |
|---|---|---|
| committer | degasus <wickmarkus@web.de> | 2017-01-06 14:01:36 +0100 |
| commit | 3df828463d74645884414d5cc994e1fda4de6c67 (patch) | |
| tree | 3d4e3bd004ef7ccf8bf8f99ff21d1ad449853f6a /Source/Core/VideoCommon/RenderState.cpp | |
| parent | c33c9532a78000224f63c4a293d031452606a8ed (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.cpp | 119 |
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. + } + } +} |
