Index: src/effects/SkArithmeticMode.cpp |
diff --git a/src/effects/SkArithmeticMode.cpp b/src/effects/SkArithmeticMode.cpp |
index e9dc7824bca5a1fd96c9578042bf5bc6c1393fc5..3d03a2d58f9c2be16d810604ae63832e56ba643f 100644 |
--- a/src/effects/SkArithmeticMode.cpp |
+++ b/src/effects/SkArithmeticMode.cpp |
@@ -20,11 +20,12 @@ |
class SkArithmeticMode_scalar : public SkXfermode { |
public: |
- SkArithmeticMode_scalar(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4) { |
+ SkArithmeticMode_scalar(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4, bool unpremultiply) { |
fK[0] = k1; |
fK[1] = k2; |
fK[2] = k3; |
fK[3] = k4; |
+ fUnpremultiply = unpremultiply; |
} |
virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count, |
@@ -43,6 +44,7 @@ private: |
fK[1] = buffer.readScalar(); |
fK[2] = buffer.readScalar(); |
fK[3] = buffer.readScalar(); |
+ fUnpremultiply = buffer.readBool(); |
} |
virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE { |
@@ -51,8 +53,10 @@ private: |
buffer.writeScalar(fK[1]); |
buffer.writeScalar(fK[2]); |
buffer.writeScalar(fK[3]); |
+ buffer.writeBool(fUnpremultiply); |
} |
SkScalar fK[4]; |
+ bool fUnpremultiply; |
typedef SkXfermode INHERITED; |
}; |
@@ -98,8 +102,8 @@ void SkArithmeticMode_scalar::xfer32(SkPMColor dst[], const SkPMColor src[], |
int sa = SkGetPackedA32(sc); |
int da = SkGetPackedA32(dc); |
- int srcNeedsUnpremul = needsUnpremul(sa); |
- int dstNeedsUnpremul = needsUnpremul(da); |
+ int srcNeedsUnpremul = fUnpremultiply && needsUnpremul(sa); |
+ int dstNeedsUnpremul = fUnpremultiply && needsUnpremul(da); |
int a, r, g, b; |
@@ -145,7 +149,7 @@ void SkArithmeticMode_scalar::xfer32(SkPMColor dst[], const SkPMColor src[], |
} |
// turn the result back into premul |
- if (0xFF != a) { |
+ if (fUnpremultiply && 0xFF != a) { |
int scale = a + (a >> 7); |
r = SkAlphaMul(r, scale); |
g = SkAlphaMul(g, scale); |
@@ -194,7 +198,7 @@ static int32_t toDot8(SkScalar x) { |
#endif |
SkXfermode* SkArithmeticMode::Create(SkScalar k1, SkScalar k2, |
- SkScalar k3, SkScalar k4) { |
+ SkScalar k3, SkScalar k4, bool unpremultiply) { |
if (fitsInBits(k1, 8) && fitsInBits(k2, 16) && |
fitsInBits(k2, 16) && fitsInBits(k2, 24)) { |
@@ -215,7 +219,7 @@ SkXfermode* SkArithmeticMode::Create(SkScalar k1, SkScalar k2, |
return SkNEW_ARGS(SkArithmeticMode_linear, (i2, i3, i4)); |
#endif |
} |
- return SkNEW_ARGS(SkArithmeticMode_scalar, (k1, k2, k3, k4)); |
+ return SkNEW_ARGS(SkArithmeticMode_scalar, (k1, k2, k3, k4, unpremultiply)); |
} |
@@ -251,8 +255,8 @@ 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 unpremultiply, GrTexture* background) { |
+ AutoEffectUnref effect(SkNEW_ARGS(GrArithmeticEffect, (k1, k2, k3, k4, unpremultiply, background))); |
return CreateEffectRef(effect); |
} |
@@ -270,12 +274,14 @@ public: |
float k2() const { return fK2; } |
float k3() const { return fK3; } |
float k4() const { return fK4; } |
+ bool unpremultiply() const { return fUnpremultiply; } |
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 unpremultiply, GrTexture* background); |
float fK1, fK2, fK3, fK4; |
+ bool fUnpremultiply; |
GrTextureAccess fBackgroundAccess; |
GR_DECLARE_EFFECT_TEST; |
@@ -286,8 +292,8 @@ private: |
/////////////////////////////////////////////////////////////////////////////// |
GrArithmeticEffect::GrArithmeticEffect(float k1, float k2, float k3, float k4, |
- GrTexture* background) |
- : fK1(k1), fK2(k2), fK3(k3), fK4(k4) { |
+ bool unpremultiply, GrTexture* background) |
+ : fK1(k1), fK2(k2), fK3(k3), fK4(k4), fUnpremultiply(unpremultiply) { |
if (background) { |
fBackgroundAccess.reset(background); |
this->addTextureAccess(&fBackgroundAccess); |
@@ -305,6 +311,7 @@ bool GrArithmeticEffect::onIsEqual(const GrEffect& sBase) const { |
fK2 == s.fK2 && |
fK3 == s.fK3 && |
fK4 == s.fK4 && |
+ fUnpremultiply == s.fUnpremultiply && |
backgroundTexture() == s.backgroundTexture(); |
} |
@@ -335,7 +342,9 @@ void GrGLArithmeticEffect::emitCode(GrGLShaderBuilder* builder, |
const char* inputColor, |
const TextureSamplerArray& samplers) { |
- GrTexture* backgroundTex = drawEffect.castEffect<GrArithmeticEffect>().backgroundTexture(); |
+ const GrArithmeticEffect& arith = drawEffect.castEffect<GrArithmeticEffect>(); |
+ GrTexture* backgroundTex = arith.backgroundTexture(); |
+ bool unpremultiply = arith.unpremultiply(); |
const char* dstColor; |
if (backgroundTex) { |
const char* bgCoords; |
@@ -361,15 +370,23 @@ void GrGLArithmeticEffect::emitCode(GrGLShaderBuilder* builder, |
builder->fsCodeAppendf("\t\tconst vec4 src = %s;\n", GrGLSLOnesVecf(4)); |
} else { |
builder->fsCodeAppendf("\t\tvec4 src = %s;\n", inputColor); |
- builder->fsCodeAppendf("\t\tsrc.rgb = clamp(src.rgb / src.a, 0.0, 1.0);\n"); |
+ if (unpremultiply) { |
+ builder->fsCodeAppendf("\t\tsrc.rgb = clamp(src.rgb / src.a, 0.0, 1.0);\n"); |
+ } |
} |
builder->fsCodeAppendf("\t\tvec4 dst = %s;\n", dstColor); |
- builder->fsCodeAppendf("\t\tdst.rgb = clamp(dst.rgb / dst.a, 0.0, 1.0);\n"); |
+ if (unpremultiply) { |
+ builder->fsCodeAppendf("\t\tdst.rgb = clamp(dst.rgb / dst.a, 0.0, 1.0);\n"); |
+ } |
builder->fsCodeAppendf("\t\t%s = %s.x * src * dst + %s.y * src + %s.z * dst + %s.w;\n", outputColor, kUni, kUni, kUni, kUni); |
builder->fsCodeAppendf("\t\t%s = clamp(%s, 0.0, 1.0);\n", outputColor, outputColor); |
- builder->fsCodeAppendf("\t\t%s.rgb *= %s.a;\n", outputColor, outputColor); |
+ if (unpremultiply) { |
+ builder->fsCodeAppendf("\t\t%s.rgb *= %s.a;\n", outputColor, outputColor); |
+ } else { |
+ builder->fsCodeAppendf("\t\t%s.rgb = min(%s.rgb, %s.a);\n", outputColor, outputColor, outputColor); |
+ } |
} |
void GrGLArithmeticEffect::setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) { |
@@ -394,7 +411,8 @@ GrGLEffect::EffectKey GrGLArithmeticEffect::GenKey(const GrDrawEffect& drawEffec |
GrGLArithmeticEffect::kCoordsType, |
bgTex); |
} |
- return bgKey; |
+ EffectKey unpremulKey = (effect.unpremultiply() ? 0x1 : 0x0) << GrGLEffectMatrix::kKeyBits; |
+ return unpremulKey | bgKey; |
} |
GrEffectRef* GrArithmeticEffect::TestCreate(SkMWCRandom* rand, |
@@ -405,8 +423,9 @@ GrEffectRef* GrArithmeticEffect::TestCreate(SkMWCRandom* rand, |
float k2 = rand->nextF(); |
float k3 = rand->nextF(); |
float k4 = rand->nextF(); |
+ bool unpremultiply = rand->nextBool(); |
- static AutoEffectUnref gEffect(SkNEW_ARGS(GrArithmeticEffect, (k1, k2, k3, k4, NULL))); |
+ static AutoEffectUnref gEffect(SkNEW_ARGS(GrArithmeticEffect, (k1, k2, k3, k4, unpremultiply, NULL))); |
return CreateEffectRef(gEffect); |
} |
@@ -422,6 +441,7 @@ bool SkArithmeticMode_scalar::asNewEffectOrCoeff(GrContext*, |
SkScalarToFloat(fK[1]), |
SkScalarToFloat(fK[2]), |
SkScalarToFloat(fK[3]), |
+ fUnpremultiply, |
background); |
} |
return true; |