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