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 +