Support INCR/DECR with stencil value replacement.

This commit is contained in:
Unknown W. Brackets
2014-08-24 09:20:17 -07:00
parent 7b308247f8
commit 0018638458
3 changed files with 72 additions and 8 deletions
+19 -3
View File
@@ -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;
+4
View File
@@ -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 {
+49 -5
View File
@@ -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);
}
}