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#define ILLEGAL_XFERMODE_MODE   ((SkXfermode::Mode)-1)
19
20// baseclass for filters that store a color and mode
21class SkModeColorFilter : public SkColorFilter {
22public:
23    SkModeColorFilter(SkColor color) {
24        fColor = color;
25        fMode = ILLEGAL_XFERMODE_MODE;
26        this->updateCache();
27    }
28
29    SkModeColorFilter(SkColor color, SkXfermode::Mode mode) {
30        fColor = color;
31        fMode = mode;
32        this->updateCache();
33    };
34
35    SkColor getColor() const { return fColor; }
36    SkXfermode::Mode getMode() const { return fMode; }
37    bool isModeValid() const { return ILLEGAL_XFERMODE_MODE != fMode; }
38    SkPMColor getPMColor() const { return fPMColor; }
39
40    virtual bool asColorMode(SkColor* color, SkXfermode::Mode* mode) const SK_OVERRIDE {
41        if (ILLEGAL_XFERMODE_MODE == fMode) {
42            return false;
43        }
44
45        if (color) {
46            *color = fColor;
47        }
48        if (mode) {
49            *mode = fMode;
50        }
51        return true;
52    }
53
54    virtual uint32_t getFlags() const SK_OVERRIDE {
55        return fProc16 ? (kAlphaUnchanged_Flag | kHasFilter16_Flag) : 0;
56    }
57
58    virtual void filterSpan(const SkPMColor shader[], int count,
59                            SkPMColor result[]) const SK_OVERRIDE {
60        SkPMColor       color = fPMColor;
61        SkXfermodeProc  proc = fProc;
62
63        for (int i = 0; i < count; i++) {
64            result[i] = proc(color, shader[i]);
65        }
66    }
67
68    virtual void filterSpan16(const uint16_t shader[], int count,
69                              uint16_t result[]) const SK_OVERRIDE {
70        SkASSERT(this->getFlags() & kHasFilter16_Flag);
71
72        SkPMColor        color = fPMColor;
73        SkXfermodeProc16 proc16 = fProc16;
74
75        for (int i = 0; i < count; i++) {
76            result[i] = proc16(color, shader[i]);
77        }
78    }
79
80#ifndef SK_IGNORE_TO_STRING
81    virtual void toString(SkString* str) const SK_OVERRIDE {
82        str->append("SkModeColorFilter: color: 0x");
83        str->appendHex(fColor);
84        str->append(" mode: ");
85        str->append(SkXfermode::ModeName(fMode));
86    }
87#endif
88
89#if SK_SUPPORT_GPU
90    virtual GrEffectRef* asNewEffect(GrContext*) const SK_OVERRIDE;
91#endif
92    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkModeColorFilter)
93
94protected:
95    virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE {
96        this->INHERITED::flatten(buffer);
97        buffer.writeColor(fColor);
98        buffer.writeUInt(fMode);
99    }
100
101    SkModeColorFilter(SkReadBuffer& buffer) {
102        fColor = buffer.readColor();
103        fMode = (SkXfermode::Mode)buffer.readUInt();
104        if (buffer.isValid()) {
105            this->updateCache();
106            buffer.validate(SkIsValidMode(fMode));
107        }
108    }
109
110private:
111    SkColor             fColor;
112    SkXfermode::Mode    fMode;
113    // cache
114    SkPMColor           fPMColor;
115    SkXfermodeProc      fProc;
116    SkXfermodeProc16    fProc16;
117
118    void updateCache() {
119        fPMColor = SkPreMultiplyColor(fColor);
120        fProc = SkXfermode::GetProc(fMode);
121        fProc16 = SkXfermode::GetProc16(fMode, fColor);
122    }
123
124    typedef SkColorFilter INHERITED;
125};
126
127///////////////////////////////////////////////////////////////////////////////
128#if SK_SUPPORT_GPU
129#include "GrBlend.h"
130#include "GrEffect.h"
131#include "GrEffectUnitTest.h"
132#include "GrTBackendEffectFactory.h"
133#include "gl/GrGLEffect.h"
134#include "SkGr.h"
135
136namespace {
137/**
138 * A definition of blend equation for one coefficient. Generates a
139 * blend_coeff * value "expression".
140 */
141template<typename ColorExpr>
142static inline ColorExpr blend_term(SkXfermode::Coeff coeff,
143                                   const ColorExpr& src,
144                                   const ColorExpr& dst,
145                                   const ColorExpr& value) {
146    switch (coeff) {
147    default:
148        SkFAIL("Unexpected xfer coeff.");
149    case SkXfermode::kZero_Coeff:    /** 0 */
150        return ColorExpr(0);
151    case SkXfermode::kOne_Coeff:     /** 1 */
152        return value;
153    case SkXfermode::kSC_Coeff:
154        return src * value;
155    case SkXfermode::kISC_Coeff:
156        return (ColorExpr(1) - src) * dst;
157    case SkXfermode::kDC_Coeff:
158        return dst * value;
159    case SkXfermode::kIDC_Coeff:
160        return (ColorExpr(1) - dst) * value;
161    case SkXfermode::kSA_Coeff:      /** src alpha */
162        return src.a() * value;
163    case SkXfermode::kISA_Coeff:     /** inverse src alpha (i.e. 1 - sa) */
164        return (typename ColorExpr::AExpr(1) - src.a()) * value;
165    case SkXfermode::kDA_Coeff:      /** dst alpha */
166        return dst.a() * value;
167    case SkXfermode::kIDA_Coeff:     /** inverse dst alpha (i.e. 1 - da) */
168        return (typename ColorExpr::AExpr(1) - dst.a()) *  value;
169    }
170}
171/**
172 * Creates a color filter expression which modifies the color by
173 * the specified color filter.
174 */
175template <typename ColorExpr>
176static inline ColorExpr color_filter_expression(const SkXfermode::Mode& mode,
177                                                const ColorExpr& filterColor,
178                                                const ColorExpr& inColor) {
179    SkXfermode::Coeff colorCoeff;
180    SkXfermode::Coeff filterColorCoeff;
181    SkAssertResult(SkXfermode::ModeAsCoeff(mode, &filterColorCoeff, &colorCoeff));
182    return blend_term(colorCoeff, filterColor, inColor, inColor) +
183        blend_term(filterColorCoeff, filterColor, inColor, filterColor);
184}
185
186}
187
188class ModeColorFilterEffect : public GrEffect {
189public:
190    static GrEffectRef* Create(const GrColor& c, SkXfermode::Mode mode) {
191        // TODO: Make the effect take the coeffs rather than mode since we already do the
192        // conversion here.
193        SkXfermode::Coeff srcCoeff, dstCoeff;
194        if (!SkXfermode::ModeAsCoeff(mode, &srcCoeff, &dstCoeff)) {
195            SkDebugf("Failing to create color filter for mode %d\n", mode);
196            return NULL;
197        }
198        AutoEffectUnref effect(SkNEW_ARGS(ModeColorFilterEffect, (c, mode)));
199        return CreateEffectRef(effect);
200    }
201
202    virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
203
204    bool willUseFilterColor() const {
205        SkXfermode::Coeff dstCoeff;
206        SkXfermode::Coeff srcCoeff;
207        SkAssertResult(SkXfermode::ModeAsCoeff(fMode, &srcCoeff, &dstCoeff));
208        if (SkXfermode::kZero_Coeff == srcCoeff) {
209            return GrBlendCoeffRefsSrc(sk_blend_to_grblend(dstCoeff));
210        }
211        return true;
212    }
213
214    virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
215        return GrTBackendEffectFactory<ModeColorFilterEffect>::getInstance();
216    }
217
218    static const char* Name() { return "ModeColorFilterEffect"; }
219
220    SkXfermode::Mode mode() const { return fMode; }
221    GrColor color() const { return fColor; }
222
223    class GLEffect : public GrGLEffect {
224    public:
225        GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
226            : INHERITED(factory) {
227        }
228
229        virtual void emitCode(GrGLShaderBuilder* builder,
230                              const GrDrawEffect& drawEffect,
231                              EffectKey key,
232                              const char* outputColor,
233                              const char* inputColor,
234                              const TransformedCoordsArray& coords,
235                              const TextureSamplerArray& samplers) SK_OVERRIDE {
236            SkXfermode::Mode mode = drawEffect.castEffect<ModeColorFilterEffect>().mode();
237
238            SkASSERT(SkXfermode::kDst_Mode != mode);
239            const char* colorFilterColorUniName = NULL;
240            if (drawEffect.castEffect<ModeColorFilterEffect>().willUseFilterColor()) {
241                fFilterColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
242                                                      kVec4f_GrSLType, "FilterColor",
243                                                      &colorFilterColorUniName);
244            }
245
246            GrGLSLExpr4 filter =
247                color_filter_expression(mode, GrGLSLExpr4(colorFilterColorUniName), GrGLSLExpr4(inputColor));
248
249            builder->fsCodeAppendf("\t%s = %s;\n", outputColor, filter.c_str());
250        }
251
252        static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
253            const ModeColorFilterEffect& colorModeFilter = drawEffect.castEffect<ModeColorFilterEffect>();
254            // The SL code does not depend on filter color at the moment, so no need to represent it
255            // in the key.
256            EffectKey modeKey = colorModeFilter.mode();
257            return modeKey;
258        }
259
260        virtual void setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) SK_OVERRIDE {
261            if (fFilterColorUni.isValid()) {
262                const ModeColorFilterEffect& colorModeFilter = drawEffect.castEffect<ModeColorFilterEffect>();
263                GrGLfloat c[4];
264                GrColorToRGBAFloat(colorModeFilter.color(), c);
265                uman.set4fv(fFilterColorUni, 1, c);
266            }
267        }
268
269    private:
270
271        GrGLUniformManager::UniformHandle fFilterColorUni;
272        typedef GrGLEffect INHERITED;
273    };
274
275    GR_DECLARE_EFFECT_TEST;
276
277private:
278    ModeColorFilterEffect(GrColor color, SkXfermode::Mode mode)
279        : fMode(mode),
280          fColor(color) {
281
282        SkXfermode::Coeff dstCoeff;
283        SkXfermode::Coeff srcCoeff;
284        SkAssertResult(SkXfermode::ModeAsCoeff(fMode, &srcCoeff, &dstCoeff));
285        // These could be calculated from the blend equation with template trickery..
286        if (SkXfermode::kZero_Coeff == dstCoeff && !GrBlendCoeffRefsDst(sk_blend_to_grblend(srcCoeff))) {
287            this->setWillNotUseInputColor();
288        }
289    }
290
291    virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
292        const ModeColorFilterEffect& s = CastEffect<ModeColorFilterEffect>(other);
293        return fMode == s.fMode && fColor == s.fColor;
294    }
295
296    SkXfermode::Mode fMode;
297    GrColor fColor;
298
299    typedef GrEffect 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_EFFECT_TEST(ModeColorFilterEffect);
400GrEffectRef* 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
412GrEffectRef* SkModeColorFilter::asNewEffect(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
446    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Src_SkModeColorFilter)
447
448protected:
449    Src_SkModeColorFilter(SkReadBuffer& buffer)
450        : INHERITED(buffer) {}
451
452private:
453    typedef SkModeColorFilter INHERITED;
454};
455
456class SrcOver_SkModeColorFilter : public SkModeColorFilter {
457public:
458    SrcOver_SkModeColorFilter(SkColor color)
459            : INHERITED(color, SkXfermode::kSrcOver_Mode) {
460        fColor32Proc = SkBlitRow::ColorProcFactory();
461    }
462
463    virtual uint32_t getFlags() const SK_OVERRIDE {
464        if (SkGetPackedA32(this->getPMColor()) == 0xFF) {
465            return kAlphaUnchanged_Flag | kHasFilter16_Flag;
466        } else {
467            return 0;
468        }
469    }
470
471    virtual void filterSpan(const SkPMColor shader[], int count,
472                            SkPMColor result[]) const SK_OVERRIDE {
473        fColor32Proc(result, shader, count, this->getPMColor());
474    }
475
476    virtual void filterSpan16(const uint16_t shader[], int count,
477                              uint16_t result[]) const SK_OVERRIDE {
478        SkASSERT(this->getFlags() & kHasFilter16_Flag);
479        sk_memset16(result, SkPixel32ToPixel16(this->getPMColor()), count);
480    }
481
482    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SrcOver_SkModeColorFilter)
483
484protected:
485    SrcOver_SkModeColorFilter(SkReadBuffer& buffer)
486        : INHERITED(buffer) {
487            fColor32Proc = SkBlitRow::ColorProcFactory();
488        }
489
490private:
491
492    SkBlitRow::ColorProc fColor32Proc;
493
494    typedef SkModeColorFilter INHERITED;
495};
496
497///////////////////////////////////////////////////////////////////////////////
498
499SkColorFilter* SkColorFilter::CreateModeFilter(SkColor color,
500                                               SkXfermode::Mode mode) {
501    unsigned alpha = SkColorGetA(color);
502
503    // first collaps some modes if possible
504
505    if (SkXfermode::kClear_Mode == mode) {
506        color = 0;
507        mode = SkXfermode::kSrc_Mode;
508    } else if (SkXfermode::kSrcOver_Mode == mode) {
509        if (0 == alpha) {
510            mode = SkXfermode::kDst_Mode;
511        } else if (255 == alpha) {
512            mode = SkXfermode::kSrc_Mode;
513        }
514        // else just stay srcover
515    }
516
517    // weed out combinations that are noops, and just return null
518    if (SkXfermode::kDst_Mode == mode ||
519        (0 == alpha && (SkXfermode::kSrcOver_Mode == mode ||
520                        SkXfermode::kDstOver_Mode == mode ||
521                        SkXfermode::kDstOut_Mode == mode ||
522                        SkXfermode::kSrcATop_Mode == mode ||
523                        SkXfermode::kXor_Mode == mode ||
524                        SkXfermode::kDarken_Mode == mode)) ||
525            (0xFF == alpha && SkXfermode::kDstIn_Mode == mode)) {
526        return NULL;
527    }
528
529    switch (mode) {
530        case SkXfermode::kSrc_Mode:
531            return SkNEW_ARGS(Src_SkModeColorFilter, (color));
532        case SkXfermode::kSrcOver_Mode:
533            return SkNEW_ARGS(SrcOver_SkModeColorFilter, (color));
534        default:
535            return SkNEW_ARGS(SkModeColorFilter, (color, mode));
536    }
537}
538
539///////////////////////////////////////////////////////////////////////////////
540
541static SkScalar byte_to_scale(U8CPU byte) {
542    if (0xFF == byte) {
543        // want to get this exact
544        return 1;
545    } else {
546        return byte * 0.00392156862745f;
547    }
548}
549
550SkColorFilter* SkColorFilter::CreateLightingFilter(SkColor mul, SkColor add) {
551    SkColorMatrix matrix;
552    matrix.setScale(byte_to_scale(SkColorGetR(mul)),
553                    byte_to_scale(SkColorGetG(mul)),
554                    byte_to_scale(SkColorGetB(mul)),
555                    1);
556    matrix.postTranslate(SkIntToScalar(SkColorGetR(add)),
557                         SkIntToScalar(SkColorGetG(add)),
558                         SkIntToScalar(SkColorGetB(add)),
559                         0);
560    return SkColorMatrixFilter::Create(matrix);
561}
562
563SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkColorFilter)
564    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkModeColorFilter)
565    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(Src_SkModeColorFilter)
566    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SrcOver_SkModeColorFilter)
567SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
568