ppsspp/GPU/Software/FuncId.cpp
Unknown W. Brackets aa3786ed21 softgpu: Force off alpha blend if uselessly on.
This is a simple optimization to prevent some work games sometimes waste.
2021-11-20 15:27:04 -08:00

85 lines
3.9 KiB
C++

// Copyright (c) 2021- PPSSPP Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0 or later versions.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "GPU/Software/FuncId.h"
#include "GPU/GPUState.h"
void ComputePixelFuncID(PixelFuncID *id) {
id->fullKey = 0;
// TODO: Could this be minz > 0x0000 || maxz < 0xFFFF? Maybe unsafe, depending on verts...
id->applyDepthRange = !gstate.isModeThrough();
// Dither happens even in clear mode.
id->dithering = gstate.isDitherEnabled();
id->fbFormat = gstate.FrameBufFormat();
id->useStandardStride = gstate.FrameBufStride() == 512 && gstate.DepthBufStride() == 512;
id->applyColorWriteMask = gstate.getColorMask() != 0;
id->clearMode = gstate.isModeClear();
if (id->clearMode) {
id->colorClear = gstate.isClearModeColorMask();
id->stencilClear = gstate.isClearModeAlphaMask();
id->depthClear = gstate.isClearModeDepthMask();
} else {
id->colorTest = gstate.isColorTestEnabled() && gstate.getColorTestFunction() != GE_COMP_ALWAYS;
if (gstate.isStencilTestEnabled() && gstate.getStencilTestFunction() == GE_COMP_ALWAYS) {
// If stencil always passes, force off when we won't write any stencil bits.
bool stencilWrite = (gstate.pmska & 0xFF) != 0xFF && gstate.FrameBufFormat() != GE_FORMAT_565;
if (gstate.isDepthTestEnabled() && gstate.getDepthTestFunction() != GE_COMP_ALWAYS)
id->stencilTest = stencilWrite && (gstate.getStencilOpZPass() != GE_STENCILOP_KEEP || gstate.getStencilOpZFail() != GE_STENCILOP_KEEP);
else
id->stencilTest = stencilWrite && gstate.getStencilOpZPass() != GE_STENCILOP_KEEP;
} else {
id->stencilTest = gstate.isStencilTestEnabled();
}
id->depthWrite = gstate.isDepthTestEnabled() && gstate.isDepthWriteEnabled();
if (id->stencilTest) {
id->stencilTestFunc = gstate.getStencilTestFunction();
id->stencilTestRef = gstate.getStencilTestRef() & gstate.getStencilTestMask();
id->hasStencilTestMask = gstate.getStencilTestMask() != 0xFF;
id->sFail = gstate.getStencilOpSFail();
id->zFail = gstate.isDepthTestEnabled() ? gstate.getStencilOpZFail() : GE_STENCILOP_KEEP;
id->zPass = gstate.getStencilOpZPass();
}
id->depthTestFunc = gstate.isDepthTestEnabled() ? gstate.getDepthTestFunction() : GE_COMP_ALWAYS;
id->alphaTestFunc = gstate.isAlphaTestEnabled() ? gstate.getAlphaTestFunction() : GE_COMP_ALWAYS;
if (id->alphaTestFunc != GE_COMP_ALWAYS) {
id->alphaTestRef = gstate.getAlphaTestRef() & gstate.getAlphaTestMask();
id->hasAlphaTestMask = gstate.getAlphaTestMask() != 0xFF;
}
id->alphaBlend = gstate.isAlphaBlendEnabled();
// Force it off if the factors are constant and don't blend. Some games use this...
if (id->alphaBlend && gstate.getBlendEq() == GE_BLENDMODE_MUL_AND_ADD) {
bool srcFixedOne = gstate.getBlendFuncA() == GE_SRCBLEND_FIXA && gstate.getFixA() == 0x00FFFFFF;
bool dstFixedZero = gstate.getBlendFuncB() == GE_DSTBLEND_FIXB && gstate.getFixB() == 0x00000000;
if (srcFixedOne && dstFixedZero)
id->alphaBlend = false;
}
if (id->alphaBlend) {
id->alphaBlendEq = gstate.getBlendEq();
id->alphaBlendSrc = gstate.getBlendFuncA();
id->alphaBlendDst = gstate.getBlendFuncB();
}
id->applyLogicOp = gstate.isLogicOpEnabled() && gstate.getLogicOp() != GE_LOGIC_COPY;
id->applyFog = gstate.isFogEnabled() && !gstate.isModeThrough();
}
}