129 lines
3.4 KiB
C++
129 lines
3.4 KiB
C++
// 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)
|
|
{
|
|
if (bp.blendmode.logicmode == BlendMode::NOOP)
|
|
{
|
|
// Fast path for Kirby's Return to Dreamland, they use it with dstAlpha.
|
|
colorupdate = false;
|
|
alphaupdate = alphaupdate && dstalpha;
|
|
}
|
|
else
|
|
{
|
|
logicopenable = true;
|
|
logicmode = bp.blendmode.logicmode;
|
|
|
|
if (dstalpha)
|
|
{
|
|
// TODO: Not supported by backends.
|
|
}
|
|
}
|
|
}
|
|
}
|