Add GrEffect::updateKnownColorComponents(). It is used to determine whether the output of an effect has a constant output value for r,g,b, or a.
Review URL: https://codereview.appspot.com/7064057
git-svn-id: http://skia.googlecode.com/svn/trunk@7144 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/effects/SkColorMatrixFilter.cpp b/src/effects/SkColorMatrixFilter.cpp
index ed34f64..2ff4fd6 100644
--- a/src/effects/SkColorMatrixFilter.cpp
+++ b/src/effects/SkColorMatrixFilter.cpp
@@ -338,6 +338,51 @@
return cme.fMatrix == fMatrix;
}
+ virtual void getConstantColorComponents(GrColor* color,
+ uint32_t* validFlags) const SK_OVERRIDE {
+ // We only bother to check whether the alpha channel will be constant. If SkColorMatrix had
+ // type flags it might be worth checking the other components.
+
+ // The matrix is defined such the 4th row determines the output alpha. The first four
+ // columns of that row multiply the input r, g, b, and a, respectively, and the last column
+ // is the "translation".
+ static const ValidComponentFlags kRGBAFlags[] = {
+ kR_ValidComponentFlag,
+ kG_ValidComponentFlag,
+ kB_ValidComponentFlag,
+ kA_ValidComponentFlag
+ };
+ static const int kShifts[] = {
+ GrColor_SHIFT_R, GrColor_SHIFT_G, GrColor_SHIFT_B, GrColor_SHIFT_A,
+ };
+ enum {
+ kAlphaRowStartIdx = 15,
+ kAlphaRowTranslateIdx = 19,
+ };
+
+ SkScalar outputA = 0;
+ for (int i = 0; i < 4; ++i) {
+ // If any relevant component of the color to be passed through the matrix is non-const
+ // then we can't know the final result.
+ if (0 != fMatrix.fMat[kAlphaRowStartIdx + i]) {
+ if (!(*validFlags & kRGBAFlags[i])) {
+ *validFlags = 0;
+ return;
+ } else {
+ uint32_t component = (*color >> kShifts[i]) & 0xFF;
+ outputA += fMatrix.fMat[kAlphaRowStartIdx + i] * component;
+ }
+ }
+ }
+ outputA += fMatrix.fMat[kAlphaRowTranslateIdx];
+ *validFlags = kA_ValidComponentFlag;
+ // We pin the color to [0,1]. This would happen to the *final* color output from the frag
+ // shader but currently the effect does not pin its own output. So in the case of over/
+ // underflow this may deviate from the actual result. Maybe the effect should pin its
+ // result if the matrix could over/underflow for any component?
+ *color = static_cast<uint8_t>(SkScalarPin(outputA, 0, 255)) << GrColor_SHIFT_A;
+ }
+
GR_DECLARE_EFFECT_TEST;
class GLEffect : public GrGLEffect {