mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-15 18:49:51 +01:00
Merge pull request #1618 from unknownbrackets/gpu-minor
Approximate better with two fixed blend colors
This commit is contained in:
commit
403f62844e
1 file changed
+51
-44
+51
-44
@@ -92,6 +92,27 @@ static const GLushort stencilOps[] = {
|
||||
GL_KEEP, // reserved
|
||||
};
|
||||
|
||||
static GLenum blendColor2Func(u32 fix) {
|
||||
if (fix == 0xFFFFFF)
|
||||
return GL_ONE;
|
||||
if (fix == 0)
|
||||
return GL_ZERO;
|
||||
|
||||
Vec3 fix3 = Vec3(fix);
|
||||
if (fix3.x >= 0.99 && fix3.y >= 0.99 && fix3.z >= 0.99)
|
||||
return GL_ONE;
|
||||
else if (fix3.x <= 0.01 && fix3.y <= 0.01 && fix3.z <= 0.01)
|
||||
return GL_ZERO;
|
||||
return GL_INVALID_ENUM;
|
||||
}
|
||||
|
||||
static bool blendColorSimilar(Vec3 a, Vec3 b, float margin = 0.1f) {
|
||||
Vec3 diff = a - b;
|
||||
if (fabsf(diff.x) <= margin && fabsf(diff.y) <= margin && fabsf(diff.z) <= margin)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void TransformDrawEngine::ApplyDrawState(int prim) {
|
||||
// TODO: All this setup is soon so expensive that we'll need dirty flags, or simply do it in the command writes where we detect dirty by xoring. Silly to do all this work on every drawcall.
|
||||
|
||||
@@ -127,49 +148,32 @@ void TransformDrawEngine::ApplyDrawState(int prim) {
|
||||
if (blendFuncA > GE_SRCBLEND_FIXA) blendFuncA = GE_SRCBLEND_FIXA;
|
||||
if (blendFuncB > GE_DSTBLEND_FIXB) blendFuncB = GE_DSTBLEND_FIXB;
|
||||
|
||||
glstate.blendEquation.set(eqLookup[blendFuncEq]);
|
||||
|
||||
if (blendFuncA != GE_SRCBLEND_FIXA && blendFuncB != GE_DSTBLEND_FIXB) {
|
||||
// All is valid, no blendcolor needed
|
||||
glstate.blendFunc.set(aLookup[blendFuncA], bLookup[blendFuncB]);
|
||||
} else {
|
||||
GLuint glBlendFuncA = blendFuncA == GE_SRCBLEND_FIXA ? GL_INVALID_ENUM : aLookup[blendFuncA];
|
||||
GLuint glBlendFuncB = blendFuncB == GE_DSTBLEND_FIXB ? GL_INVALID_ENUM : bLookup[blendFuncB];
|
||||
u32 fixA = gstate.getFixA();
|
||||
u32 fixB = gstate.getFixB();
|
||||
// Shortcut by using GL_ONE where possible, no need to set blendcolor
|
||||
if (glBlendFuncA == GL_INVALID_ENUM && blendFuncA == GE_SRCBLEND_FIXA) {
|
||||
if (fixA == 0xFFFFFF)
|
||||
glBlendFuncA = GL_ONE;
|
||||
else if (fixA == 0)
|
||||
glBlendFuncA = GL_ZERO;
|
||||
}
|
||||
if (glBlendFuncB == GL_INVALID_ENUM && blendFuncB == GE_DSTBLEND_FIXB) {
|
||||
if (fixB == 0xFFFFFF)
|
||||
glBlendFuncB = GL_ONE;
|
||||
else if (fixB == 0)
|
||||
glBlendFuncB = GL_ZERO;
|
||||
}
|
||||
// Shortcut by using GL_ONE where possible, no need to set blendcolor
|
||||
GLuint glBlendFuncA = blendFuncA == GE_SRCBLEND_FIXA ? blendColor2Func(gstate.getFixA()) : aLookup[blendFuncA];
|
||||
GLuint glBlendFuncB = blendFuncB == GE_DSTBLEND_FIXB ? blendColor2Func(gstate.getFixB()) : bLookup[blendFuncB];
|
||||
if (blendFuncA == GE_SRCBLEND_FIXA || blendFuncB == GE_DSTBLEND_FIXB) {
|
||||
Vec3 fixA = Vec3(gstate.getFixA());
|
||||
Vec3 fixB = Vec3(gstate.getFixB());
|
||||
if (glBlendFuncA == GL_INVALID_ENUM && glBlendFuncB != GL_INVALID_ENUM) {
|
||||
// Can use blendcolor trivially.
|
||||
const float blendColor[4] = {(fixA & 0xFF)/255.0f, ((fixA >> 8) & 0xFF)/255.0f, ((fixA >> 16) & 0xFF)/255.0f, 1.0f};
|
||||
const float blendColor[4] = {fixA.x, fixA.y, fixA.z, 1.0f};
|
||||
glstate.blendColor.set(blendColor);
|
||||
glBlendFuncA = GL_CONSTANT_COLOR;
|
||||
} else if (glBlendFuncA != GL_INVALID_ENUM && glBlendFuncB == GL_INVALID_ENUM) {
|
||||
// Can use blendcolor trivially.
|
||||
const float blendColor[4] = {(fixB & 0xFF)/255.0f, ((fixB >> 8) & 0xFF)/255.0f, ((fixB >> 16) & 0xFF)/255.0f, 1.0f};
|
||||
const float blendColor[4] = {fixB.x, fixB.y, fixB.z, 1.0f};
|
||||
glstate.blendColor.set(blendColor);
|
||||
glBlendFuncB = GL_CONSTANT_COLOR;
|
||||
} else if (glBlendFuncA == GL_INVALID_ENUM && glBlendFuncB == GL_INVALID_ENUM) { // Should also check for approximate equality
|
||||
if (fixA == (fixB ^ 0xFFFFFF)) {
|
||||
} else if (glBlendFuncA == GL_INVALID_ENUM && glBlendFuncB == GL_INVALID_ENUM) {
|
||||
if (blendColorSimilar(fixA, Vec3(1.0f) - fixB)) {
|
||||
glBlendFuncA = GL_CONSTANT_COLOR;
|
||||
glBlendFuncB = GL_ONE_MINUS_CONSTANT_COLOR;
|
||||
const float blendColor[4] = {(fixA & 0xFF)/255.0f, ((fixA >> 8) & 0xFF)/255.0f, ((fixA >> 16) & 0xFF)/255.0f, 1.0f};
|
||||
const float blendColor[4] = {fixA.x, fixA.y, fixA.z, 1.0f};
|
||||
glstate.blendColor.set(blendColor);
|
||||
} else if (fixA == fixB) {
|
||||
} else if (blendColorSimilar(fixA, fixB)) {
|
||||
glBlendFuncA = GL_CONSTANT_COLOR;
|
||||
glBlendFuncB = GL_CONSTANT_COLOR;
|
||||
const float blendColor[4] = {(fixA & 0xFF)/255.0f, ((fixA >> 8) & 0xFF)/255.0f, ((fixA >> 16) & 0xFF)/255.0f, 1.0f};
|
||||
const float blendColor[4] = {fixA.x, fixA.y, fixA.z, 1.0f};
|
||||
glstate.blendColor.set(blendColor);
|
||||
} else {
|
||||
static bool didReportBlend = false;
|
||||
@@ -178,25 +182,28 @@ void TransformDrawEngine::ApplyDrawState(int prim) {
|
||||
didReportBlend = true;
|
||||
|
||||
DEBUG_LOG(HLE, "ERROR INVALID blendcolorstate: FixA=%06x FixB=%06x FuncA=%i FuncB=%i", gstate.getFixA(), gstate.getFixB(), gstate.getBlendFuncA(), gstate.getBlendFuncB());
|
||||
// Let's approximate, at least.
|
||||
int blendSumA = (fixA & 0xFF) + ((fixA >> 8) & 0xFF) + ((fixA >> 16) & 0xFF);
|
||||
int blendSumB = (fixB & 0xFF) + ((fixB >> 8) & 0xFF) + ((fixB >> 16) & 0xFF);
|
||||
if (blendSumA < 64 * 3 && blendSumB > 192 * 3) {
|
||||
glBlendFuncA = GL_ZERO;
|
||||
glBlendFuncB = GL_ONE;
|
||||
} else if (blendSumA > 192 * 3 && blendSumB < 64 * 3) {
|
||||
glBlendFuncA = GL_ONE;
|
||||
glBlendFuncB = GL_ZERO;
|
||||
// Let's approximate, at least. Close is better than totally off.
|
||||
const bool nearZeroA = blendColorSimilar(fixA, 0.0f, 0.25f);
|
||||
const bool nearZeroB = blendColorSimilar(fixB, 0.0f, 0.25f);
|
||||
if (nearZeroA || blendColorSimilar(fixA, 1.0f, 0.25f)) {
|
||||
glBlendFuncA = nearZeroA ? GL_ZERO : GL_ONE;
|
||||
glBlendFuncB = GL_CONSTANT_COLOR;
|
||||
const float blendColor[4] = {fixB.x, fixB.y, fixB.z, 1.0f};
|
||||
glstate.blendColor.set(blendColor);
|
||||
// We need to pick something. Let's go with A as the fixed color.
|
||||
} else {
|
||||
glBlendFuncA = GL_ONE;
|
||||
glBlendFuncB = GL_ONE;
|
||||
glBlendFuncA = GL_CONSTANT_COLOR;
|
||||
glBlendFuncB = nearZeroB ? GL_ZERO : GL_ONE;
|
||||
const float blendColor[4] = {fixA.x, fixA.y, fixA.z, 1.0f};
|
||||
glstate.blendColor.set(blendColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
// At this point, through all paths above, glBlendFuncA and glBlendFuncB will be set somehow.
|
||||
|
||||
glstate.blendFunc.set(glBlendFuncA, glBlendFuncB);
|
||||
}
|
||||
|
||||
// At this point, through all paths above, glBlendFuncA and glBlendFuncB will be set right somehow.
|
||||
glstate.blendFunc.set(glBlendFuncA, glBlendFuncB);
|
||||
glstate.blendEquation.set(eqLookup[blendFuncEq]);
|
||||
}
|
||||
|
||||
// Set Dither
|
||||
|
||||
Reference in new issue
Block a user