Arithmetic mode now has the option of not validating the output color, which will allow multiple arithmetic operations to be done sequentially, without intermediate clamping. This is required for mimicking blink's current behavior.

BUG=skia:
R=senorblanco@google.com, senorblanco@chromium.org, reed@google.com, bsalomon@google.com

Author: sugoi@chromium.org

Review URL: https://codereview.chromium.org/204543006

git-svn-id: http://skia.googlecode.com/svn/trunk@14031 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
commit-bot@chromium.org 2014-04-02 19:32:15 +00:00
parent dc5cd8552e
commit 51a11b7f2f
2 changed files with 53 additions and 21 deletions

View File

@ -26,7 +26,8 @@ public:
* k1=k2=k4=0, k3=1.0 results in returning the dst
*/
static SkXfermode* Create(SkScalar k1, SkScalar k2,
SkScalar k3, SkScalar k4);
SkScalar k3, SkScalar k4,
bool enforcePMColor = true);
SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP();

View File

@ -22,8 +22,9 @@ static const bool gUseUnpremul = false;
class SkArithmeticMode_scalar : public SkXfermode {
public:
static SkArithmeticMode_scalar* Create(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4) {
return SkNEW_ARGS(SkArithmeticMode_scalar, (k1, k2, k3, k4));
static SkArithmeticMode_scalar* Create(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4,
bool enforcePMColor) {
return SkNEW_ARGS(SkArithmeticMode_scalar, (k1, k2, k3, k4, enforcePMColor));
}
virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
@ -37,11 +38,12 @@ public:
#endif
private:
SkArithmeticMode_scalar(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4) {
SkArithmeticMode_scalar(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4, bool enforcePMColor) {
fK[0] = k1;
fK[1] = k2;
fK[2] = k3;
fK[3] = k4;
fEnforcePMColor = enforcePMColor;
}
SkArithmeticMode_scalar(SkReadBuffer& buffer) : INHERITED(buffer) {
@ -49,6 +51,7 @@ private:
fK[1] = buffer.readScalar();
fK[2] = buffer.readScalar();
fK[3] = buffer.readScalar();
fEnforcePMColor = buffer.readBool();
}
virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE {
@ -57,8 +60,10 @@ private:
buffer.writeScalar(fK[1]);
buffer.writeScalar(fK[2]);
buffer.writeScalar(fK[3]);
buffer.writeBool(fEnforcePMColor);
}
SkScalar fK[4];
bool fEnforcePMColor;
typedef SkXfermode INHERITED;
};
@ -145,12 +150,14 @@ void SkArithmeticMode_scalar::xfer32(SkPMColor dst[], const SkPMColor src[],
} else {
a = arith(k1, k2, k3, k4, SkGetPackedA32(sc), SkGetPackedA32(dc));
r = arith(k1, k2, k3, k4, SkGetPackedR32(sc), SkGetPackedR32(dc));
r = SkMin32(r, a);
g = arith(k1, k2, k3, k4, SkGetPackedG32(sc), SkGetPackedG32(dc));
g = SkMin32(g, a);
b = arith(k1, k2, k3, k4, SkGetPackedB32(sc), SkGetPackedB32(dc));
if (fEnforcePMColor) {
r = SkMin32(r, a);
g = SkMin32(g, a);
b = SkMin32(b, a);
}
}
// apply antialias coverage if necessary
if (aaCoverage && 0xFF != aaCoverage[i]) {
@ -168,7 +175,7 @@ void SkArithmeticMode_scalar::xfer32(SkPMColor dst[], const SkPMColor src[],
g = SkAlphaMul(g, scale);
b = SkAlphaMul(b, scale);
}
dst[i] = SkPackARGB32(a, r, g, b);
dst[i] = fEnforcePMColor ? SkPackARGB32(a, r, g, b) : SkPackARGB32NoCheck(a, r, g, b);
}
}
}
@ -178,10 +185,9 @@ void SkArithmeticMode_scalar::toString(SkString* str) const {
str->append("SkArithmeticMode_scalar: ");
for (int i = 0; i < 4; ++i) {
str->appendScalar(fK[i]);
if (i < 3) {
str->append(" ");
}
}
str->appendS32(fEnforcePMColor ? 1 : 0);
}
#endif
@ -198,7 +204,8 @@ static int32_t toDot8(SkScalar x) {
#endif
SkXfermode* SkArithmeticMode::Create(SkScalar k1, SkScalar k2,
SkScalar k3, SkScalar k4) {
SkScalar k3, SkScalar k4,
bool enforcePMColor) {
if (fitsInBits(k1, 8) && fitsInBits(k2, 16) &&
fitsInBits(k2, 16) && fitsInBits(k2, 24)) {
@ -219,7 +226,7 @@ SkXfermode* SkArithmeticMode::Create(SkScalar k1, SkScalar k2,
return SkNEW_ARGS(SkArithmeticMode_linear, (i2, i3, i4));
#endif
}
return SkArithmeticMode_scalar::Create(k1, k2, k3, k4);
return SkArithmeticMode_scalar::Create(k1, k2, k3, k4, enforcePMColor);
}
@ -242,8 +249,11 @@ public:
virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
static EffectKey GenKey(const GrDrawEffect&, const GrGLCaps& caps);
private:
GrGLUniformManager::UniformHandle fKUni;
bool fEnforcePMColor;
typedef GrGLEffect INHERITED;
};
@ -252,8 +262,10 @@ private:
class GrArithmeticEffect : public GrEffect {
public:
static GrEffectRef* Create(float k1, float k2, float k3, float k4, GrTexture* background) {
AutoEffectUnref effect(SkNEW_ARGS(GrArithmeticEffect, (k1, k2, k3, k4, background)));
static GrEffectRef* Create(float k1, float k2, float k3, float k4, bool enforcePMColor,
GrTexture* background) {
AutoEffectUnref effect(SkNEW_ARGS(GrArithmeticEffect, (k1, k2, k3, k4, enforcePMColor,
background)));
return CreateEffectRef(effect);
}
@ -271,12 +283,15 @@ public:
float k2() const { return fK2; }
float k3() const { return fK3; }
float k4() const { return fK4; }
bool enforcePMColor() const { return fEnforcePMColor; }
private:
virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
GrArithmeticEffect(float k1, float k2, float k3, float k4, GrTexture* background);
GrArithmeticEffect(float k1, float k2, float k3, float k4, bool enforcePMColor,
GrTexture* background);
float fK1, fK2, fK3, fK4;
bool fEnforcePMColor;
GrCoordTransform fBackgroundTransform;
GrTextureAccess fBackgroundAccess;
@ -288,8 +303,8 @@ private:
///////////////////////////////////////////////////////////////////////////////
GrArithmeticEffect::GrArithmeticEffect(float k1, float k2, float k3, float k4,
GrTexture* background)
: fK1(k1), fK2(k2), fK3(k3), fK4(k4) {
bool enforcePMColor, GrTexture* background)
: fK1(k1), fK2(k2), fK3(k3), fK4(k4), fEnforcePMColor(enforcePMColor) {
if (background) {
fBackgroundTransform.reset(kLocal_GrCoordSet, background);
this->addCoordTransform(&fBackgroundTransform);
@ -309,6 +324,7 @@ bool GrArithmeticEffect::onIsEqual(const GrEffect& sBase) const {
fK2 == s.fK2 &&
fK3 == s.fK3 &&
fK4 == s.fK4 &&
fEnforcePMColor == s.fEnforcePMColor &&
backgroundTexture() == s.backgroundTexture();
}
@ -325,7 +341,8 @@ void GrArithmeticEffect::getConstantColorComponents(GrColor* color, uint32_t* va
GrGLArithmeticEffect::GrGLArithmeticEffect(const GrBackendEffectFactory& factory,
const GrDrawEffect& drawEffect)
: INHERITED(factory) {
: INHERITED(factory),
fEnforcePMColor(true) {
}
GrGLArithmeticEffect::~GrGLArithmeticEffect() {
@ -374,7 +391,7 @@ void GrGLArithmeticEffect::emitCode(GrGLShaderBuilder* builder,
builder->fsCodeAppendf("\t\t%s = clamp(%s, 0.0, 1.0);\n", outputColor, outputColor);
if (gUseUnpremul) {
builder->fsCodeAppendf("\t\t%s.rgb *= %s.a;\n", outputColor, outputColor);
} else {
} else if (fEnforcePMColor) {
builder->fsCodeAppendf("\t\t%s.rgb = min(%s.rgb, %s.a);\n", outputColor, outputColor, outputColor);
}
}
@ -382,6 +399,17 @@ void GrGLArithmeticEffect::emitCode(GrGLShaderBuilder* builder,
void GrGLArithmeticEffect::setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) {
const GrArithmeticEffect& arith = drawEffect.castEffect<GrArithmeticEffect>();
uman.set4f(fKUni, arith.k1(), arith.k2(), arith.k3(), arith.k4());
fEnforcePMColor = arith.enforcePMColor();
}
GrGLEffect::EffectKey GrGLArithmeticEffect::GenKey(const GrDrawEffect& drawEffect,
const GrGLCaps&) {
const GrArithmeticEffect& arith = drawEffect.castEffect<GrArithmeticEffect>();
EffectKey key = arith.enforcePMColor() ? 1 : 0;
if (arith.backgroundTexture()) {
key |= 2;
}
return key;
}
GrEffectRef* GrArithmeticEffect::TestCreate(SkRandom* rand,
@ -392,8 +420,10 @@ GrEffectRef* GrArithmeticEffect::TestCreate(SkRandom* rand,
float k2 = rand->nextF();
float k3 = rand->nextF();
float k4 = rand->nextF();
bool enforcePMColor = rand->nextBool();
AutoEffectUnref gEffect(SkNEW_ARGS(GrArithmeticEffect, (k1, k2, k3, k4, NULL)));
AutoEffectUnref gEffect(SkNEW_ARGS(GrArithmeticEffect,
(k1, k2, k3, k4, enforcePMColor, NULL)));
return CreateEffectRef(gEffect);
}
@ -405,6 +435,7 @@ bool SkArithmeticMode_scalar::asNewEffect(GrEffectRef** effect, GrTexture* backg
SkScalarToFloat(fK[1]),
SkScalarToFloat(fK[2]),
SkScalarToFloat(fK[3]),
fEnforcePMColor,
background);
}
return true;