Merge pull request #4581 from degasus/blendstate
OGL: Move blending logic in VideoCommon.
This commit is contained in:
commit
c380dceb78
|
@ -39,6 +39,7 @@
|
||||||
#include "VideoCommon/OnScreenDisplay.h"
|
#include "VideoCommon/OnScreenDisplay.h"
|
||||||
#include "VideoCommon/PixelEngine.h"
|
#include "VideoCommon/PixelEngine.h"
|
||||||
#include "VideoCommon/PixelShaderManager.h"
|
#include "VideoCommon/PixelShaderManager.h"
|
||||||
|
#include "VideoCommon/RenderState.h"
|
||||||
#include "VideoCommon/VertexShaderManager.h"
|
#include "VideoCommon/VertexShaderManager.h"
|
||||||
#include "VideoCommon/VideoConfig.h"
|
#include "VideoCommon/VideoConfig.h"
|
||||||
|
|
||||||
|
@ -63,8 +64,6 @@ static int s_last_multisamples = 1;
|
||||||
static bool s_last_stereo_mode = false;
|
static bool s_last_stereo_mode = false;
|
||||||
static bool s_last_xfb_mode = false;
|
static bool s_last_xfb_mode = false;
|
||||||
|
|
||||||
static u32 s_blendMode;
|
|
||||||
|
|
||||||
static bool s_vsync;
|
static bool s_vsync;
|
||||||
|
|
||||||
// EFB cache related
|
// EFB cache related
|
||||||
|
@ -328,8 +327,6 @@ static void InitDriverInfo()
|
||||||
// Init functions
|
// Init functions
|
||||||
Renderer::Renderer()
|
Renderer::Renderer()
|
||||||
{
|
{
|
||||||
s_blendMode = 0;
|
|
||||||
|
|
||||||
bool bSuccess = true;
|
bool bSuccess = true;
|
||||||
|
|
||||||
// Init extension support.
|
// Init extension support.
|
||||||
|
@ -832,20 +829,6 @@ void Renderer::SetScissorRect(const EFBRectangle& rc)
|
||||||
glScissor(trc.left, trc.bottom, trc.GetWidth(), trc.GetHeight());
|
glScissor(trc.left, trc.bottom, trc.GetWidth(), trc.GetHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::SetColorMask()
|
|
||||||
{
|
|
||||||
// Only enable alpha channel if it's supported by the current EFB format
|
|
||||||
GLenum ColorMask = GL_FALSE, AlphaMask = GL_FALSE;
|
|
||||||
if (bpmem.alpha_test.TestResult() != AlphaTest::FAIL)
|
|
||||||
{
|
|
||||||
if (bpmem.blendmode.colorupdate)
|
|
||||||
ColorMask = GL_TRUE;
|
|
||||||
if (bpmem.blendmode.alphaupdate && (bpmem.zcontrol.pixel_format == PEControl::RGBA6_Z24))
|
|
||||||
AlphaMask = GL_TRUE;
|
|
||||||
}
|
|
||||||
glColorMask(ColorMask, ColorMask, ColorMask, AlphaMask);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClearEFBCache()
|
void ClearEFBCache()
|
||||||
{
|
{
|
||||||
if (!s_efbCacheIsCleared)
|
if (!s_efbCacheIsCleared)
|
||||||
|
@ -1224,111 +1207,72 @@ void Renderer::ReinterpretPixelData(unsigned int convtype)
|
||||||
|
|
||||||
void Renderer::SetBlendMode(bool forceUpdate)
|
void Renderer::SetBlendMode(bool forceUpdate)
|
||||||
{
|
{
|
||||||
// Our render target always uses an alpha channel, so we need to override the blend functions to
|
BlendingState state;
|
||||||
// assume a destination alpha of 1 if the render target isn't supposed to have an alpha channel
|
state.Generate(bpmem);
|
||||||
// Example: D3DBLEND_DESTALPHA needs to be D3DBLEND_ONE since the result without an alpha channel
|
|
||||||
// is assumed to always be 1.
|
|
||||||
bool target_has_alpha = bpmem.zcontrol.pixel_format == PEControl::RGBA6_Z24;
|
|
||||||
|
|
||||||
bool useDstAlpha = bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate && target_has_alpha;
|
bool useDualSource =
|
||||||
bool useDualSource = g_ActiveConfig.backend_info.bSupportsDualSourceBlend;
|
g_ActiveConfig.backend_info.bSupportsDualSourceBlend &&
|
||||||
|
(!DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DUAL_SOURCE_BLENDING) || state.dstalpha);
|
||||||
|
|
||||||
// Only use dual-source blending when required on drivers that don't support it very well.
|
const GLenum src_factors[8] = {
|
||||||
if (DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DUAL_SOURCE_BLENDING) && !useDstAlpha)
|
|
||||||
useDualSource = false;
|
|
||||||
|
|
||||||
const GLenum glSrcFactors[8] = {
|
|
||||||
GL_ZERO,
|
GL_ZERO,
|
||||||
GL_ONE,
|
GL_ONE,
|
||||||
GL_DST_COLOR,
|
GL_DST_COLOR,
|
||||||
GL_ONE_MINUS_DST_COLOR,
|
GL_ONE_MINUS_DST_COLOR,
|
||||||
(useDualSource) ? GL_SRC1_ALPHA : (GLenum)GL_SRC_ALPHA,
|
useDualSource ? GL_SRC1_ALPHA : (GLenum)GL_SRC_ALPHA,
|
||||||
(useDualSource) ? GL_ONE_MINUS_SRC1_ALPHA : (GLenum)GL_ONE_MINUS_SRC_ALPHA,
|
useDualSource ? GL_ONE_MINUS_SRC1_ALPHA : (GLenum)GL_ONE_MINUS_SRC_ALPHA,
|
||||||
(target_has_alpha) ? GL_DST_ALPHA : (GLenum)GL_ONE,
|
GL_DST_ALPHA,
|
||||||
(target_has_alpha) ? GL_ONE_MINUS_DST_ALPHA : (GLenum)GL_ZERO};
|
GL_ONE_MINUS_DST_ALPHA};
|
||||||
const GLenum glDestFactors[8] = {
|
const GLenum dst_factors[8] = {
|
||||||
GL_ZERO,
|
GL_ZERO,
|
||||||
GL_ONE,
|
GL_ONE,
|
||||||
GL_SRC_COLOR,
|
GL_SRC_COLOR,
|
||||||
GL_ONE_MINUS_SRC_COLOR,
|
GL_ONE_MINUS_SRC_COLOR,
|
||||||
(useDualSource) ? GL_SRC1_ALPHA : (GLenum)GL_SRC_ALPHA,
|
useDualSource ? GL_SRC1_ALPHA : (GLenum)GL_SRC_ALPHA,
|
||||||
(useDualSource) ? GL_ONE_MINUS_SRC1_ALPHA : (GLenum)GL_ONE_MINUS_SRC_ALPHA,
|
useDualSource ? GL_ONE_MINUS_SRC1_ALPHA : (GLenum)GL_ONE_MINUS_SRC_ALPHA,
|
||||||
(target_has_alpha) ? GL_DST_ALPHA : (GLenum)GL_ONE,
|
GL_DST_ALPHA,
|
||||||
(target_has_alpha) ? GL_ONE_MINUS_DST_ALPHA : (GLenum)GL_ZERO};
|
GL_ONE_MINUS_DST_ALPHA};
|
||||||
|
|
||||||
// blend mode bit mask
|
if (state.blendenable)
|
||||||
// 0 - blend enable
|
|
||||||
// 1 - dst alpha enabled
|
|
||||||
// 2 - reverse subtract enable (else add)
|
|
||||||
// 3-5 - srcRGB function
|
|
||||||
// 6-8 - dstRGB function
|
|
||||||
|
|
||||||
u32 newval = useDstAlpha << 1;
|
|
||||||
newval |= bpmem.blendmode.subtract << 2;
|
|
||||||
|
|
||||||
if (bpmem.blendmode.subtract)
|
|
||||||
{
|
{
|
||||||
newval |= 0x0049; // enable blending src 1 dst 1
|
GLenum equation = state.subtract ? GL_FUNC_REVERSE_SUBTRACT : GL_FUNC_ADD;
|
||||||
}
|
GLenum equationAlpha = state.subtractAlpha ? GL_FUNC_REVERSE_SUBTRACT : GL_FUNC_ADD;
|
||||||
else if (bpmem.blendmode.blendenable)
|
|
||||||
{
|
|
||||||
newval |= 1; // enable blending
|
|
||||||
newval |= bpmem.blendmode.srcfactor << 3;
|
|
||||||
newval |= bpmem.blendmode.dstfactor << 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 changes = forceUpdate ? 0xFFFFFFFF : newval ^ s_blendMode;
|
|
||||||
|
|
||||||
if (changes & 1)
|
|
||||||
{
|
|
||||||
// blend enable change
|
|
||||||
(newval & 1) ? glEnable(GL_BLEND) : glDisable(GL_BLEND);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changes & 4)
|
|
||||||
{
|
|
||||||
// subtract enable change
|
|
||||||
GLenum equation = newval & 4 ? GL_FUNC_REVERSE_SUBTRACT : GL_FUNC_ADD;
|
|
||||||
GLenum equationAlpha = useDstAlpha ? GL_FUNC_ADD : equation;
|
|
||||||
|
|
||||||
|
glEnable(GL_BLEND);
|
||||||
glBlendEquationSeparate(equation, equationAlpha);
|
glBlendEquationSeparate(equation, equationAlpha);
|
||||||
|
glBlendFuncSeparate(src_factors[state.srcfactor], dst_factors[state.dstfactor],
|
||||||
|
src_factors[state.srcfactoralpha], dst_factors[state.dstfactoralpha]);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (changes & 0x1FA)
|
|
||||||
{
|
{
|
||||||
u32 srcidx = (newval >> 3) & 7;
|
glDisable(GL_BLEND);
|
||||||
u32 dstidx = (newval >> 6) & 7;
|
|
||||||
GLenum srcFactor = glSrcFactors[srcidx];
|
|
||||||
GLenum dstFactor = glDestFactors[dstidx];
|
|
||||||
|
|
||||||
// adjust alpha factors
|
|
||||||
if (useDstAlpha)
|
|
||||||
{
|
|
||||||
srcidx = BlendMode::ONE;
|
|
||||||
dstidx = BlendMode::ZERO;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// we can't use GL_DST_COLOR or GL_ONE_MINUS_DST_COLOR for source in alpha channel so use
|
|
||||||
// their alpha equivalent instead
|
|
||||||
if (srcidx == BlendMode::DSTCLR)
|
|
||||||
srcidx = BlendMode::DSTALPHA;
|
|
||||||
else if (srcidx == BlendMode::INVDSTCLR)
|
|
||||||
srcidx = BlendMode::INVDSTALPHA;
|
|
||||||
|
|
||||||
// we can't use GL_SRC_COLOR or GL_ONE_MINUS_SRC_COLOR for destination in alpha channel so use
|
|
||||||
// their alpha equivalent instead
|
|
||||||
if (dstidx == BlendMode::SRCCLR)
|
|
||||||
dstidx = BlendMode::SRCALPHA;
|
|
||||||
else if (dstidx == BlendMode::INVSRCCLR)
|
|
||||||
dstidx = BlendMode::INVSRCALPHA;
|
|
||||||
}
|
|
||||||
GLenum srcFactorAlpha = glSrcFactors[srcidx];
|
|
||||||
GLenum dstFactorAlpha = glDestFactors[dstidx];
|
|
||||||
// blend RGB change
|
|
||||||
glBlendFuncSeparate(srcFactor, dstFactor, srcFactorAlpha, dstFactorAlpha);
|
|
||||||
}
|
}
|
||||||
s_blendMode = newval;
|
|
||||||
|
const GLenum logic_op_codes[16] = {
|
||||||
|
GL_CLEAR, GL_AND, GL_AND_REVERSE, GL_COPY, GL_AND_INVERTED, GL_NOOP,
|
||||||
|
GL_XOR, GL_OR, GL_NOR, GL_EQUIV, GL_INVERT, GL_OR_REVERSE,
|
||||||
|
GL_COPY_INVERTED, GL_OR_INVERTED, GL_NAND, GL_SET};
|
||||||
|
|
||||||
|
if (GLInterface->GetMode() != GLInterfaceMode::MODE_OPENGL)
|
||||||
|
{
|
||||||
|
// Logic ops aren't available in GLES3
|
||||||
|
}
|
||||||
|
else if (state.logicopenable)
|
||||||
|
{
|
||||||
|
glEnable(GL_COLOR_LOGIC_OP);
|
||||||
|
glLogicOp(logic_op_codes[state.logicmode]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glDisable(GL_COLOR_LOGIC_OP);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.dither)
|
||||||
|
glEnable(GL_DITHER);
|
||||||
|
else
|
||||||
|
glDisable(GL_DITHER);
|
||||||
|
|
||||||
|
glColorMask(state.colorupdate, state.colorupdate, state.colorupdate, state.alphaupdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function has the final picture. We adjust the aspect ratio here.
|
// This function has the final picture. We adjust the aspect ratio here.
|
||||||
|
@ -1783,10 +1727,8 @@ void Renderer::RestoreAPIState()
|
||||||
}
|
}
|
||||||
SetGenerationMode();
|
SetGenerationMode();
|
||||||
BPFunctions::SetScissor();
|
BPFunctions::SetScissor();
|
||||||
SetColorMask();
|
|
||||||
SetDepthMode();
|
SetDepthMode();
|
||||||
SetBlendMode(true);
|
SetBlendMode(true);
|
||||||
SetLogicOpMode();
|
|
||||||
SetViewport();
|
SetViewport();
|
||||||
|
|
||||||
const VertexManager* const vm = static_cast<VertexManager*>(g_vertex_manager.get());
|
const VertexManager* const vm = static_cast<VertexManager*>(g_vertex_manager.get());
|
||||||
|
@ -1833,35 +1775,6 @@ void Renderer::SetDepthMode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::SetLogicOpMode()
|
|
||||||
{
|
|
||||||
if (GLInterface->GetMode() != GLInterfaceMode::MODE_OPENGL)
|
|
||||||
return;
|
|
||||||
// Logic ops aren't available in GLES3/GLES2
|
|
||||||
const GLenum glLogicOpCodes[16] = {
|
|
||||||
GL_CLEAR, GL_AND, GL_AND_REVERSE, GL_COPY, GL_AND_INVERTED, GL_NOOP,
|
|
||||||
GL_XOR, GL_OR, GL_NOR, GL_EQUIV, GL_INVERT, GL_OR_REVERSE,
|
|
||||||
GL_COPY_INVERTED, GL_OR_INVERTED, GL_NAND, GL_SET};
|
|
||||||
|
|
||||||
if (bpmem.blendmode.logicopenable && !bpmem.blendmode.blendenable)
|
|
||||||
{
|
|
||||||
glEnable(GL_COLOR_LOGIC_OP);
|
|
||||||
glLogicOp(glLogicOpCodes[bpmem.blendmode.logicmode]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
glDisable(GL_COLOR_LOGIC_OP);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::SetDitherMode()
|
|
||||||
{
|
|
||||||
if (bpmem.blendmode.dither)
|
|
||||||
glEnable(GL_DITHER);
|
|
||||||
else
|
|
||||||
glDisable(GL_DITHER);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::SetSamplerState(int stage, int texindex, bool custom_tex)
|
void Renderer::SetSamplerState(int stage, int texindex, bool custom_tex)
|
||||||
{
|
{
|
||||||
auto const& tex = bpmem.tex[texindex];
|
auto const& tex = bpmem.tex[texindex];
|
||||||
|
|
|
@ -72,13 +72,10 @@ public:
|
||||||
static void Init();
|
static void Init();
|
||||||
static void Shutdown();
|
static void Shutdown();
|
||||||
|
|
||||||
void SetColorMask() override;
|
|
||||||
void SetBlendMode(bool forceUpdate) override;
|
void SetBlendMode(bool forceUpdate) override;
|
||||||
void SetScissorRect(const EFBRectangle& rc) override;
|
void SetScissorRect(const EFBRectangle& rc) override;
|
||||||
void SetGenerationMode() override;
|
void SetGenerationMode() override;
|
||||||
void SetDepthMode() override;
|
void SetDepthMode() override;
|
||||||
void SetLogicOpMode() override;
|
|
||||||
void SetDitherMode() override;
|
|
||||||
void SetSamplerState(int stage, int texindex, bool custom_tex) override;
|
void SetSamplerState(int stage, int texindex, bool custom_tex) override;
|
||||||
void SetInterlacingMode() override;
|
void SetInterlacingMode() override;
|
||||||
void SetViewport() override;
|
void SetViewport() override;
|
||||||
|
|
|
@ -142,6 +142,10 @@ static void BPWritten(const BPCmd& bp)
|
||||||
(int)bpmem.blendmode.dstfactor, (int)bpmem.blendmode.srcfactor,
|
(int)bpmem.blendmode.dstfactor, (int)bpmem.blendmode.srcfactor,
|
||||||
(int)bpmem.blendmode.subtract, (int)bpmem.blendmode.logicmode);
|
(int)bpmem.blendmode.subtract, (int)bpmem.blendmode.logicmode);
|
||||||
|
|
||||||
|
// Set Blending Mode
|
||||||
|
if (bp.changes)
|
||||||
|
SetBlendMode();
|
||||||
|
|
||||||
// Set LogicOp Blending Mode
|
// Set LogicOp Blending Mode
|
||||||
if (bp.changes & 0xF002) // logicopenable | logicmode
|
if (bp.changes & 0xF002) // logicopenable | logicmode
|
||||||
SetLogicOpMode();
|
SetLogicOpMode();
|
||||||
|
@ -150,10 +154,6 @@ static void BPWritten(const BPCmd& bp)
|
||||||
if (bp.changes & 4) // dither
|
if (bp.changes & 4) // dither
|
||||||
SetDitherMode();
|
SetDitherMode();
|
||||||
|
|
||||||
// Set Blending Mode
|
|
||||||
if (bp.changes & 0xFF1) // blendenable | alphaupdate | dstfactor | srcfactor | subtract
|
|
||||||
SetBlendMode();
|
|
||||||
|
|
||||||
// Set Color Mask
|
// Set Color Mask
|
||||||
if (bp.changes & 0x18) // colorupdate | alphaupdate
|
if (bp.changes & 0x18) // colorupdate | alphaupdate
|
||||||
SetColorMask();
|
SetColorMask();
|
||||||
|
@ -316,7 +316,10 @@ static void BPWritten(const BPCmd& bp)
|
||||||
if (bp.changes & 0xFFFF)
|
if (bp.changes & 0xFFFF)
|
||||||
PixelShaderManager::SetAlpha();
|
PixelShaderManager::SetAlpha();
|
||||||
if (bp.changes)
|
if (bp.changes)
|
||||||
|
{
|
||||||
g_renderer->SetColorMask();
|
g_renderer->SetColorMask();
|
||||||
|
SetBlendMode();
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
case BPMEM_BIAS: // BIAS
|
case BPMEM_BIAS: // BIAS
|
||||||
PRIM_LOG("ztex bias=0x%x", bpmem.ztex1.bias);
|
PRIM_LOG("ztex bias=0x%x", bpmem.ztex1.bias);
|
||||||
|
|
|
@ -25,6 +25,7 @@ set(SRCS AsyncRequests.cpp
|
||||||
PixelShaderManager.cpp
|
PixelShaderManager.cpp
|
||||||
PostProcessing.cpp
|
PostProcessing.cpp
|
||||||
RenderBase.cpp
|
RenderBase.cpp
|
||||||
|
RenderState.cpp
|
||||||
Statistics.cpp
|
Statistics.cpp
|
||||||
TextureCacheBase.cpp
|
TextureCacheBase.cpp
|
||||||
TextureConversionShader.cpp
|
TextureConversionShader.cpp
|
||||||
|
|
|
@ -0,0 +1,128 @@
|
||||||
|
// 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.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
};
|
|
@ -80,6 +80,7 @@
|
||||||
<ClCompile Include="PixelShaderManager.cpp" />
|
<ClCompile Include="PixelShaderManager.cpp" />
|
||||||
<ClCompile Include="PostProcessing.cpp" />
|
<ClCompile Include="PostProcessing.cpp" />
|
||||||
<ClCompile Include="RenderBase.cpp" />
|
<ClCompile Include="RenderBase.cpp" />
|
||||||
|
<ClCompile Include="RenderState.cpp" />
|
||||||
<ClCompile Include="LightingShaderGen.cpp" />
|
<ClCompile Include="LightingShaderGen.cpp" />
|
||||||
<ClCompile Include="Statistics.cpp" />
|
<ClCompile Include="Statistics.cpp" />
|
||||||
<ClCompile Include="GeometryShaderGen.cpp" />
|
<ClCompile Include="GeometryShaderGen.cpp" />
|
||||||
|
@ -134,6 +135,7 @@
|
||||||
<ClInclude Include="PixelShaderManager.h" />
|
<ClInclude Include="PixelShaderManager.h" />
|
||||||
<ClInclude Include="PostProcessing.h" />
|
<ClInclude Include="PostProcessing.h" />
|
||||||
<ClInclude Include="RenderBase.h" />
|
<ClInclude Include="RenderBase.h" />
|
||||||
|
<ClInclude Include="RenderState.h" />
|
||||||
<ClInclude Include="SamplerCommon.h" />
|
<ClInclude Include="SamplerCommon.h" />
|
||||||
<ClInclude Include="ShaderGenCommon.h" />
|
<ClInclude Include="ShaderGenCommon.h" />
|
||||||
<ClInclude Include="Statistics.h" />
|
<ClInclude Include="Statistics.h" />
|
||||||
|
|
|
@ -44,6 +44,9 @@
|
||||||
<ClCompile Include="RenderBase.cpp">
|
<ClCompile Include="RenderBase.cpp">
|
||||||
<Filter>Base</Filter>
|
<Filter>Base</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="RenderState.cpp">
|
||||||
|
<Filter>Base</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="TextureCacheBase.cpp">
|
<ClCompile Include="TextureCacheBase.cpp">
|
||||||
<Filter>Base</Filter>
|
<Filter>Base</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -182,6 +185,9 @@
|
||||||
<ClInclude Include="RenderBase.h">
|
<ClInclude Include="RenderBase.h">
|
||||||
<Filter>Base</Filter>
|
<Filter>Base</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="RenderState.h">
|
||||||
|
<Filter>Base</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="TextureCacheBase.h">
|
<ClInclude Include="TextureCacheBase.h">
|
||||||
<Filter>Base</Filter>
|
<Filter>Base</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
Loading…
Reference in New Issue