mirror of
https://github.com/izzy2lost/ppsspp.git
synced 2026-03-10 12:43:04 -07:00
Support INCR/DECR with stencil value replacement.
This commit is contained in:
@@ -201,7 +201,11 @@ StencilValueType ReplaceAlphaWithStencilType() {
|
||||
}
|
||||
|
||||
case GE_STENCILOP_DECR:
|
||||
return gstate.FrameBufFormat() == GE_FORMAT_4444 ? STENCIL_VALUE_DECR_4 : STENCIL_VALUE_DECR_8;
|
||||
|
||||
case GE_STENCILOP_INCR:
|
||||
return gstate.FrameBufFormat() == GE_FORMAT_4444 ? STENCIL_VALUE_INCR_4 : STENCIL_VALUE_INCR_8;
|
||||
|
||||
case GE_STENCILOP_INVERT:
|
||||
return STENCIL_VALUE_UNKNOWN;
|
||||
|
||||
@@ -411,17 +415,17 @@ void ComputeFragmentShaderID(FragmentShaderID *id) {
|
||||
id0 |= (stencilToAlpha) << 22;
|
||||
|
||||
if (stencilToAlpha != REPLACE_ALPHA_NO) {
|
||||
// 3 bits
|
||||
// 4 bits
|
||||
id0 |= ReplaceAlphaWithStencilType() << 24;
|
||||
}
|
||||
|
||||
id0 |= (alphaTestAgainstZero & 1) << 27;
|
||||
id0 |= (alphaTestAgainstZero & 1) << 28;
|
||||
if (enableAlphaTest)
|
||||
gpuStats.numAlphaTestedDraws++;
|
||||
else
|
||||
gpuStats.numNonAlphaTestedDraws++;
|
||||
|
||||
// 28 - 31 are free.
|
||||
// 29 - 31 are free.
|
||||
|
||||
// 3 bits.
|
||||
id1 |= replaceBlend << 0;
|
||||
@@ -929,6 +933,18 @@ void GenerateFragmentShader(char *buffer) {
|
||||
WRITE(p, " %s.a = 0.0;\n", fragColor0);
|
||||
break;
|
||||
|
||||
case STENCIL_VALUE_INCR_4:
|
||||
case STENCIL_VALUE_DECR_4:
|
||||
// We're adding/subtracting, just by the smallest value in 4-bit.
|
||||
WRITE(p, " %s.a = %f;\n", fragColor0, 1.0 / 15.0);
|
||||
break;
|
||||
|
||||
case STENCIL_VALUE_INCR_8:
|
||||
case STENCIL_VALUE_DECR_8:
|
||||
// We're adding/subtracting, just by the smallest value in 8-bit.
|
||||
WRITE(p, " %s.a = %f;\n", fragColor0, 1.0 / 255.0);
|
||||
break;
|
||||
|
||||
case STENCIL_VALUE_KEEP:
|
||||
// Do nothing. We'll mask out the alpha using color mask.
|
||||
break;
|
||||
|
||||
@@ -50,6 +50,10 @@ enum StencilValueType {
|
||||
STENCIL_VALUE_ZERO,
|
||||
STENCIL_VALUE_ONE,
|
||||
STENCIL_VALUE_KEEP,
|
||||
STENCIL_VALUE_INCR_4,
|
||||
STENCIL_VALUE_INCR_8,
|
||||
STENCIL_VALUE_DECR_4,
|
||||
STENCIL_VALUE_DECR_8,
|
||||
};
|
||||
|
||||
enum ReplaceAlphaType {
|
||||
|
||||
@@ -264,8 +264,23 @@ void TransformDrawEngine::ApplyBlendState() {
|
||||
float constantAlpha = 1.0f;
|
||||
ReplaceAlphaType replaceAlphaWithStencil = ReplaceAlphaWithStencil(replaceBlend);
|
||||
if (gstate.isStencilTestEnabled() && replaceAlphaWithStencil == REPLACE_ALPHA_NO) {
|
||||
if (ReplaceAlphaWithStencilType() == STENCIL_VALUE_UNIFORM) {
|
||||
switch (ReplaceAlphaWithStencilType()) {
|
||||
case STENCIL_VALUE_UNIFORM:
|
||||
constantAlpha = (float) gstate.getStencilTestRef() * (1.0f / 255.0f);
|
||||
break;
|
||||
|
||||
case STENCIL_VALUE_INCR_4:
|
||||
case STENCIL_VALUE_DECR_4:
|
||||
constantAlpha = 1.0f / 15.0f;
|
||||
break;
|
||||
|
||||
case STENCIL_VALUE_INCR_8:
|
||||
case STENCIL_VALUE_DECR_8:
|
||||
constantAlpha = 1.0f / 255.0f;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -368,9 +383,27 @@ void TransformDrawEngine::ApplyBlendState() {
|
||||
// do any blending in the alpha channel as that doesn't seem to happen on PSP. So lacking a better option,
|
||||
// the only value we can set alpha to here without multipass and dual source alpha is zero (by setting
|
||||
// the factors to zero). So let's do that.
|
||||
GLenum alphaFunc = GL_FUNC_ADD;
|
||||
if (replaceAlphaWithStencil != REPLACE_ALPHA_NO) {
|
||||
// Let the fragment shader take care of it.
|
||||
glstate.blendFuncSeparate.set(glBlendFuncA, glBlendFuncB, GL_ONE, GL_ZERO);
|
||||
switch (ReplaceAlphaWithStencilType()) {
|
||||
case STENCIL_VALUE_INCR_4:
|
||||
case STENCIL_VALUE_INCR_8:
|
||||
// We'll add the increment value.
|
||||
glstate.blendFuncSeparate.set(glBlendFuncA, glBlendFuncB, GL_ONE, GL_ONE);
|
||||
break;
|
||||
|
||||
case STENCIL_VALUE_DECR_4:
|
||||
case STENCIL_VALUE_DECR_8:
|
||||
// Like add with a small value, but subtracting.
|
||||
alphaFunc = GL_FUNC_SUBTRACT;
|
||||
glstate.blendFuncSeparate.set(glBlendFuncA, glBlendFuncB, GL_ONE, GL_ONE);
|
||||
break;
|
||||
|
||||
default:
|
||||
glstate.blendFuncSeparate.set(glBlendFuncA, glBlendFuncB, GL_ONE, GL_ZERO);
|
||||
break;
|
||||
}
|
||||
} else if (gstate.isStencilTestEnabled()) {
|
||||
switch (ReplaceAlphaWithStencilType()) {
|
||||
case STENCIL_VALUE_KEEP:
|
||||
@@ -391,8 +424,19 @@ void TransformDrawEngine::ApplyBlendState() {
|
||||
glstate.blendFuncSeparate.set(glBlendFuncA, glBlendFuncB, GL_ONE, GL_ZERO);
|
||||
}
|
||||
break;
|
||||
case STENCIL_VALUE_INCR_4:
|
||||
case STENCIL_VALUE_INCR_8:
|
||||
// This won't give a correct value always, but it will try to increase at least.
|
||||
glstate.blendFuncSeparate.set(glBlendFuncA, glBlendFuncB, GL_CONSTANT_ALPHA, GL_ONE);
|
||||
break;
|
||||
case STENCIL_VALUE_DECR_4:
|
||||
case STENCIL_VALUE_DECR_8:
|
||||
// This won't give a correct value always, but it will try to decrease at least.
|
||||
glstate.blendFuncSeparate.set(glBlendFuncA, glBlendFuncB, GL_CONSTANT_ALPHA, GL_ONE);
|
||||
alphaFunc = GL_FUNC_SUBTRACT;
|
||||
break;
|
||||
case STENCIL_VALUE_UNKNOWN:
|
||||
// For now, let's err at zero. This is INVERT or INCR/DECR.
|
||||
// For now, let's err at zero. This is INVERT.
|
||||
glstate.blendFuncSeparate.set(glBlendFuncA, glBlendFuncB, GL_ZERO, GL_ZERO);
|
||||
break;
|
||||
}
|
||||
@@ -402,9 +446,9 @@ void TransformDrawEngine::ApplyBlendState() {
|
||||
}
|
||||
|
||||
if (gl_extensions.EXT_blend_minmax || gl_extensions.GLES3) {
|
||||
glstate.blendEquationSeparate.set(eqLookup[blendFuncEq], GL_FUNC_ADD);
|
||||
glstate.blendEquationSeparate.set(eqLookup[blendFuncEq], alphaFunc);
|
||||
} else {
|
||||
glstate.blendEquationSeparate.set(eqLookupNoMinMax[blendFuncEq], GL_FUNC_ADD);
|
||||
glstate.blendEquationSeparate.set(eqLookupNoMinMax[blendFuncEq], alphaFunc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user