Home | History | Annotate | Download | only in effects
      1 /*
      2  * Copyright 2006 The Android Open Source Project
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkBlitRow.h"
      9 #include "SkColorFilter.h"
     10 #include "SkColorPriv.h"
     11 #include "SkModeColorFilter.h"
     12 #include "SkReadBuffer.h"
     13 #include "SkWriteBuffer.h"
     14 #include "SkUtils.h"
     15 #include "SkString.h"
     16 #include "SkValidationUtils.h"
     17 #include "SkColorMatrixFilter.h"
     18 
     19 bool SkModeColorFilter::asColorMode(SkColor* color, SkXfermode::Mode* mode) const {
     20     if (color) {
     21         *color = fColor;
     22     }
     23     if (mode) {
     24         *mode = fMode;
     25     }
     26     return true;
     27 }
     28 
     29 uint32_t SkModeColorFilter::getFlags() const {
     30     switch (fMode) {
     31         case SkXfermode::kDst_Mode:      //!< [Da, Dc]
     32         case SkXfermode::kSrcATop_Mode:  //!< [Da, Sc * Da + (1 - Sa) * Dc]
     33             return kAlphaUnchanged_Flag;
     34         default:
     35             break;
     36     }
     37     return 0;
     38 }
     39 
     40 void SkModeColorFilter::filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const {
     41     SkPMColor       color = fPMColor;
     42     SkXfermodeProc  proc = fProc;
     43 
     44     for (int i = 0; i < count; i++) {
     45         result[i] = proc(color, shader[i]);
     46     }
     47 }
     48 
     49 void SkModeColorFilter::flatten(SkWriteBuffer& buffer) const {
     50     buffer.writeColor(fColor);
     51     buffer.writeUInt(fMode);
     52 }
     53 
     54 void SkModeColorFilter::updateCache() {
     55     fPMColor = SkPreMultiplyColor(fColor);
     56     fProc = SkXfermode::GetProc(fMode);
     57 }
     58 
     59 SkFlattenable* SkModeColorFilter::CreateProc(SkReadBuffer& buffer) {
     60     SkColor color = buffer.readColor();
     61     SkXfermode::Mode mode = (SkXfermode::Mode)buffer.readUInt();
     62     return SkColorFilter::CreateModeFilter(color, mode);
     63 }
     64 
     65 ///////////////////////////////////////////////////////////////////////////////
     66 #if SK_SUPPORT_GPU
     67 #include "GrBlend.h"
     68 #include "GrFragmentProcessor.h"
     69 #include "GrInvariantOutput.h"
     70 #include "GrProcessorUnitTest.h"
     71 #include "SkGr.h"
     72 #include "gl/GrGLProcessor.h"
     73 #include "gl/builders/GrGLProgramBuilder.h"
     74 
     75 namespace {
     76 /**
     77  * A definition of blend equation for one coefficient. Generates a
     78  * blend_coeff * value "expression".
     79  */
     80 template<typename ColorExpr>
     81 static inline ColorExpr blend_term(SkXfermode::Coeff coeff,
     82                                    const ColorExpr& src,
     83                                    const ColorExpr& dst,
     84                                    const ColorExpr& value) {
     85     switch (coeff) {
     86     default:
     87         SkFAIL("Unexpected xfer coeff.");
     88     case SkXfermode::kZero_Coeff:    /** 0 */
     89         return ColorExpr(0);
     90     case SkXfermode::kOne_Coeff:     /** 1 */
     91         return value;
     92     case SkXfermode::kSC_Coeff:
     93         return src * value;
     94     case SkXfermode::kISC_Coeff:
     95         return (ColorExpr(1) - src) * dst;
     96     case SkXfermode::kDC_Coeff:
     97         return dst * value;
     98     case SkXfermode::kIDC_Coeff:
     99         return (ColorExpr(1) - dst) * value;
    100     case SkXfermode::kSA_Coeff:      /** src alpha */
    101         return src.a() * value;
    102     case SkXfermode::kISA_Coeff:     /** inverse src alpha (i.e. 1 - sa) */
    103         return (typename ColorExpr::AExpr(1) - src.a()) * value;
    104     case SkXfermode::kDA_Coeff:      /** dst alpha */
    105         return dst.a() * value;
    106     case SkXfermode::kIDA_Coeff:     /** inverse dst alpha (i.e. 1 - da) */
    107         return (typename ColorExpr::AExpr(1) - dst.a()) *  value;
    108     }
    109 }
    110 /**
    111  * Creates a color filter expression which modifies the color by
    112  * the specified color filter.
    113  */
    114 template <typename ColorExpr>
    115 static inline ColorExpr color_filter_expression(const SkXfermode::Mode& mode,
    116                                                 const ColorExpr& filterColor,
    117                                                 const ColorExpr& inColor) {
    118     SkXfermode::Coeff colorCoeff;
    119     SkXfermode::Coeff filterColorCoeff;
    120     SkAssertResult(SkXfermode::ModeAsCoeff(mode, &filterColorCoeff, &colorCoeff));
    121     return blend_term(colorCoeff, filterColor, inColor, inColor) +
    122         blend_term(filterColorCoeff, filterColor, inColor, filterColor);
    123 }
    124 
    125 }
    126 
    127 class ModeColorFilterEffect : public GrFragmentProcessor {
    128 public:
    129     static GrFragmentProcessor* Create(const GrColor& c, SkXfermode::Mode mode) {
    130         // TODO: Make the effect take the coeffs rather than mode since we already do the
    131         // conversion here.
    132         SkXfermode::Coeff srcCoeff, dstCoeff;
    133         if (!SkXfermode::ModeAsCoeff(mode, &srcCoeff, &dstCoeff)) {
    134 //            SkDebugf("Failing to create color filter for mode %d\n", mode);
    135             return NULL;
    136         }
    137         return SkNEW_ARGS(ModeColorFilterEffect, (c, mode));
    138     }
    139 
    140     bool willUseFilterColor() const {
    141         SkXfermode::Coeff dstCoeff;
    142         SkXfermode::Coeff srcCoeff;
    143         SkAssertResult(SkXfermode::ModeAsCoeff(fMode, &srcCoeff, &dstCoeff));
    144         if (SkXfermode::kZero_Coeff == srcCoeff) {
    145             return GrBlendCoeffRefsSrc(sk_blend_to_grblend(dstCoeff));
    146         }
    147         return true;
    148     }
    149 
    150     virtual void getGLProcessorKey(const GrGLSLCaps& caps,
    151                                    GrProcessorKeyBuilder* b) const override {
    152         GLProcessor::GenKey(*this, caps, b);
    153     }
    154 
    155     GrGLFragmentProcessor* createGLInstance() const override {
    156         return SkNEW_ARGS(GLProcessor, (*this));
    157     }
    158 
    159     const char* name() const override { return "ModeColorFilterEffect"; }
    160 
    161     SkXfermode::Mode mode() const { return fMode; }
    162     GrColor color() const { return fColor; }
    163 
    164     class GLProcessor : public GrGLFragmentProcessor {
    165     public:
    166         GLProcessor(const GrProcessor&) {
    167         }
    168 
    169         virtual void emitCode(GrGLFPBuilder* builder,
    170                               const GrFragmentProcessor& fp,
    171                               const char* outputColor,
    172                               const char* inputColor,
    173                               const TransformedCoordsArray&,
    174                               const TextureSamplerArray&) override {
    175             SkXfermode::Mode mode = fp.cast<ModeColorFilterEffect>().mode();
    176 
    177             SkASSERT(SkXfermode::kDst_Mode != mode);
    178             const char* colorFilterColorUniName = NULL;
    179             if (fp.cast<ModeColorFilterEffect>().willUseFilterColor()) {
    180                 fFilterColorUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
    181                                                       kVec4f_GrSLType, kDefault_GrSLPrecision,
    182                                                       "FilterColor",
    183                                                       &colorFilterColorUniName);
    184             }
    185 
    186             GrGLSLExpr4 filter =
    187                 color_filter_expression(mode, GrGLSLExpr4(colorFilterColorUniName),
    188                                         GrGLSLExpr4(inputColor));
    189 
    190             builder->getFragmentShaderBuilder()->
    191                     codeAppendf("\t%s = %s;\n", outputColor, filter.c_str());
    192         }
    193 
    194         static void GenKey(const GrProcessor& fp, const GrGLSLCaps&,
    195                            GrProcessorKeyBuilder* b) {
    196             const ModeColorFilterEffect& colorModeFilter = fp.cast<ModeColorFilterEffect>();
    197             // The SL code does not depend on filter color at the moment, so no need to represent it
    198             // in the key.
    199             b->add32(colorModeFilter.mode());
    200         }
    201 
    202         virtual void setData(const GrGLProgramDataManager& pdman,
    203                              const GrProcessor& fp) override {
    204             if (fFilterColorUni.isValid()) {
    205                 const ModeColorFilterEffect& colorModeFilter = fp.cast<ModeColorFilterEffect>();
    206                 GrGLfloat c[4];
    207                 GrColorToRGBAFloat(colorModeFilter.color(), c);
    208                 pdman.set4fv(fFilterColorUni, 1, c);
    209             }
    210         }
    211 
    212     private:
    213 
    214         GrGLProgramDataManager::UniformHandle fFilterColorUni;
    215         typedef GrGLFragmentProcessor INHERITED;
    216     };
    217 
    218     GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
    219 
    220 private:
    221     ModeColorFilterEffect(GrColor color, SkXfermode::Mode mode)
    222         : fMode(mode),
    223           fColor(color) {
    224         this->initClassID<ModeColorFilterEffect>();
    225     }
    226 
    227     bool onIsEqual(const GrFragmentProcessor& other) const override {
    228         const ModeColorFilterEffect& s = other.cast<ModeColorFilterEffect>();
    229         return fMode == s.fMode && fColor == s.fColor;
    230     }
    231 
    232     void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
    233 
    234     SkXfermode::Mode fMode;
    235     GrColor fColor;
    236 
    237     typedef GrFragmentProcessor INHERITED;
    238 };
    239 
    240 namespace {
    241 
    242 /** Function color_component_to_int tries to reproduce the GLSL rounding. The spec doesn't specify
    243  * to which direction the 0.5 goes.
    244  */
    245 static inline int color_component_to_int(float value) {
    246     return sk_float_round2int(SkTMax(0.f, SkTMin(1.f, value)) * 255.f);
    247 }
    248 
    249 /** MaskedColorExpr is used to evaluate the color and valid color component flags through the
    250  * blending equation. It has members similar to GrGLSLExpr so that it can be used with the
    251  * templated helpers above.
    252  */
    253 class MaskedColorExpr {
    254 public:
    255     MaskedColorExpr(const float color[], uint32_t flags)
    256         : fFlags(flags) {
    257         fColor[0] = color[0];
    258         fColor[1] = color[1];
    259         fColor[2] = color[2];
    260         fColor[3] = color[3];
    261     }
    262 
    263     MaskedColorExpr(float v, uint32_t flags = kRGBA_GrColorComponentFlags)
    264         : fFlags(flags) {
    265         fColor[0] = v;
    266         fColor[1] = v;
    267         fColor[2] = v;
    268         fColor[3] = v;
    269     }
    270 
    271     MaskedColorExpr operator*(const MaskedColorExpr& other) const {
    272         float tmp[4];
    273         tmp[0] = fColor[0] * other.fColor[0];
    274         tmp[1] = fColor[1] * other.fColor[1];
    275         tmp[2] = fColor[2] * other.fColor[2];
    276         tmp[3] = fColor[3] * other.fColor[3];
    277 
    278         return MaskedColorExpr(tmp, fFlags & other.fFlags);
    279     }
    280 
    281     MaskedColorExpr operator+(const MaskedColorExpr& other) const {
    282         float tmp[4];
    283         tmp[0] = fColor[0] + other.fColor[0];
    284         tmp[1] = fColor[1] + other.fColor[1];
    285         tmp[2] = fColor[2] + other.fColor[2];
    286         tmp[3] = fColor[3] + other.fColor[3];
    287 
    288         return MaskedColorExpr(tmp, fFlags & other.fFlags);
    289     }
    290 
    291     MaskedColorExpr operator-(const MaskedColorExpr& other) const {
    292         float tmp[4];
    293         tmp[0] = fColor[0] - other.fColor[0];
    294         tmp[1] = fColor[1] - other.fColor[1];
    295         tmp[2] = fColor[2] - other.fColor[2];
    296         tmp[3] = fColor[3] - other.fColor[3];
    297 
    298         return MaskedColorExpr(tmp, fFlags & other.fFlags);
    299     }
    300 
    301     MaskedColorExpr a() const {
    302         uint32_t flags = (fFlags & kA_GrColorComponentFlag) ? kRGBA_GrColorComponentFlags : 0;
    303         return MaskedColorExpr(fColor[3], flags);
    304     }
    305 
    306     GrColor getColor() const {
    307         return GrColorPackRGBA(color_component_to_int(fColor[0]),
    308                                color_component_to_int(fColor[1]),
    309                                color_component_to_int(fColor[2]),
    310                                color_component_to_int(fColor[3]));
    311     }
    312 
    313     uint32_t getValidComponents() const  { return fFlags; }
    314 
    315     typedef MaskedColorExpr AExpr;
    316 private:
    317     float fColor[4];
    318     uint32_t fFlags;
    319 };
    320 
    321 }
    322 
    323 void ModeColorFilterEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
    324     float inputColor[4];
    325     GrColorToRGBAFloat(inout->color(), inputColor);
    326     float filterColor[4];
    327     GrColorToRGBAFloat(fColor, filterColor);
    328     MaskedColorExpr result =
    329         color_filter_expression(fMode,
    330                                 MaskedColorExpr(filterColor, kRGBA_GrColorComponentFlags),
    331                                 MaskedColorExpr(inputColor, inout->validFlags()));
    332 
    333     // Check if we will use the input color
    334     SkXfermode::Coeff dstCoeff;
    335     SkXfermode::Coeff srcCoeff;
    336     SkAssertResult(SkXfermode::ModeAsCoeff(fMode, &srcCoeff, &dstCoeff));
    337     GrInvariantOutput::ReadInput readInput = GrInvariantOutput::kWill_ReadInput;
    338     // These could be calculated from the blend equation with template trickery..
    339     if (SkXfermode::kZero_Coeff == dstCoeff &&
    340         !GrBlendCoeffRefsDst(sk_blend_to_grblend(srcCoeff))) {
    341         readInput = GrInvariantOutput::kWillNot_ReadInput;
    342     }
    343     inout->setToOther(result.getValidComponents(), result.getColor(), readInput);
    344 }
    345 
    346 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ModeColorFilterEffect);
    347 GrFragmentProcessor* ModeColorFilterEffect::TestCreate(SkRandom* rand,
    348                                                        GrContext*,
    349                                                        const GrDrawTargetCaps&,
    350                                                        GrTexture*[]) {
    351     SkXfermode::Mode mode = SkXfermode::kDst_Mode;
    352     while (SkXfermode::kDst_Mode == mode) {
    353         mode = static_cast<SkXfermode::Mode>(rand->nextRangeU(0, SkXfermode::kLastCoeffMode));
    354     }
    355 
    356     // pick a random premul color
    357     uint8_t alpha = rand->nextULessThan(256);
    358     GrColor color = GrColorPackRGBA(rand->nextRangeU(0, alpha),
    359                                     rand->nextRangeU(0, alpha),
    360                                     rand->nextRangeU(0, alpha),
    361                                     alpha);
    362     return ModeColorFilterEffect::Create(color, mode);
    363 }
    364 
    365 bool SkModeColorFilter::asFragmentProcessors(GrContext*,
    366                                              SkTDArray<GrFragmentProcessor*>* array) const {
    367     if (SkXfermode::kDst_Mode != fMode) {
    368         GrFragmentProcessor* frag = ModeColorFilterEffect::Create(SkColor2GrColor(fColor), fMode);
    369         if (frag) {
    370             if (array) {
    371                 *array->append() = frag;
    372             }
    373             return true;
    374         }
    375     }
    376     return false;
    377 }
    378 
    379 #endif
    380 
    381 ///////////////////////////////////////////////////////////////////////////////
    382 
    383 class Src_SkModeColorFilter : public SkModeColorFilter {
    384 public:
    385     Src_SkModeColorFilter(SkColor color) : INHERITED(color, SkXfermode::kSrc_Mode) {}
    386 
    387     void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const override {
    388         sk_memset32(result, this->getPMColor(), count);
    389     }
    390 
    391 private:
    392     typedef SkModeColorFilter INHERITED;
    393 };
    394 
    395 class SrcOver_SkModeColorFilter : public SkModeColorFilter {
    396 public:
    397     SrcOver_SkModeColorFilter(SkColor color) : INHERITED(color, SkXfermode::kSrcOver_Mode) { }
    398 
    399     void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const override {
    400         SkBlitRow::Color32(result, shader, count, this->getPMColor());
    401     }
    402 
    403 private:
    404     typedef SkModeColorFilter INHERITED;
    405 };
    406 
    407 ///////////////////////////////////////////////////////////////////////////////
    408 
    409 SkColorFilter* SkColorFilter::CreateModeFilter(SkColor color, SkXfermode::Mode mode) {
    410     if (!SkIsValidMode(mode)) {
    411         return NULL;
    412     }
    413 
    414     unsigned alpha = SkColorGetA(color);
    415 
    416     // first collaps some modes if possible
    417 
    418     if (SkXfermode::kClear_Mode == mode) {
    419         color = 0;
    420         mode = SkXfermode::kSrc_Mode;
    421     } else if (SkXfermode::kSrcOver_Mode == mode) {
    422         if (0 == alpha) {
    423             mode = SkXfermode::kDst_Mode;
    424         } else if (255 == alpha) {
    425             mode = SkXfermode::kSrc_Mode;
    426         }
    427         // else just stay srcover
    428     }
    429 
    430     // weed out combinations that are noops, and just return null
    431     if (SkXfermode::kDst_Mode == mode ||
    432         (0 == alpha && (SkXfermode::kSrcOver_Mode == mode ||
    433                         SkXfermode::kDstOver_Mode == mode ||
    434                         SkXfermode::kDstOut_Mode == mode ||
    435                         SkXfermode::kSrcATop_Mode == mode ||
    436                         SkXfermode::kXor_Mode == mode ||
    437                         SkXfermode::kDarken_Mode == mode)) ||
    438             (0xFF == alpha && SkXfermode::kDstIn_Mode == mode)) {
    439         return NULL;
    440     }
    441 
    442     switch (mode) {
    443         case SkXfermode::kSrc_Mode:
    444             return SkNEW_ARGS(Src_SkModeColorFilter, (color));
    445         case SkXfermode::kSrcOver_Mode:
    446             return SkNEW_ARGS(SrcOver_SkModeColorFilter, (color));
    447         default:
    448             return SkNEW_ARGS(SkModeColorFilter, (color, mode));
    449     }
    450 }
    451 
    452 ///////////////////////////////////////////////////////////////////////////////
    453 
    454 static SkScalar byte_to_scale(U8CPU byte) {
    455     if (0xFF == byte) {
    456         // want to get this exact
    457         return 1;
    458     } else {
    459         return byte * 0.00392156862745f;
    460     }
    461 }
    462 
    463 SkColorFilter* SkColorFilter::CreateLightingFilter(SkColor mul, SkColor add) {
    464     SkColorMatrix matrix;
    465     matrix.setScale(byte_to_scale(SkColorGetR(mul)),
    466                     byte_to_scale(SkColorGetG(mul)),
    467                     byte_to_scale(SkColorGetB(mul)),
    468                     1);
    469     matrix.postTranslate(SkIntToScalar(SkColorGetR(add)),
    470                          SkIntToScalar(SkColorGetG(add)),
    471                          SkIntToScalar(SkColorGetB(add)),
    472                          0);
    473     return SkColorMatrixFilter::Create(matrix);
    474 }
    475 
    476