1845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
3845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
6845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com */
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com#include "SkBlitRow.h"
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorFilter.h"
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h"
118b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h"
128b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h"
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h"
141202c2ac563cdeb07406872825706b83e335c977robertphillips@google.com#include "SkString.h"
15c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org#include "SkValidationUtils.h"
1631b3044af4e97c662076147d119ba233a163b769reed@google.com#include "SkColorMatrixFilter.h"
1731b3044af4e97c662076147d119ba233a163b769reed@google.com
1843c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com#define ILLEGAL_XFERMODE_MODE   ((SkXfermode::Mode)-1)
1943c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com
2043c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com// baseclass for filters that store a color and mode
2143c50c8c77df82c5cffb55cae2d386e59802b88freed@google.comclass SkModeColorFilter : public SkColorFilter {
2243c50c8c77df82c5cffb55cae2d386e59802b88freed@google.compublic:
2343c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    SkModeColorFilter(SkColor color) {
2443c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        fColor = color;
2543c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        fMode = ILLEGAL_XFERMODE_MODE;
268b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com        this->updateCache();
2743c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    }
2843c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com
2943c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    SkModeColorFilter(SkColor color, SkXfermode::Mode mode) {
3043c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        fColor = color;
3143c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        fMode = mode;
328b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com        this->updateCache();
3343c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    };
341447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
358b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com    SkColor getColor() const { return fColor; }
368b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com    SkXfermode::Mode getMode() const { return fMode; }
378b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com    bool isModeValid() const { return ILLEGAL_XFERMODE_MODE != fMode; }
388b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com    SkPMColor getPMColor() const { return fPMColor; }
39fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
40bada64428a52b4fc1f31a0a1982c2301ec57601creed@google.com    virtual bool asColorMode(SkColor* color, SkXfermode::Mode* mode) const SK_OVERRIDE {
4143c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        if (ILLEGAL_XFERMODE_MODE == fMode) {
4243c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com            return false;
4343c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        }
4443c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com
4543c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        if (color) {
4643c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com            *color = fColor;
4743c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        }
4843c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        if (mode) {
4943c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com            *mode = fMode;
5043c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        }
5143c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        return true;
5243c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    }
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
54bada64428a52b4fc1f31a0a1982c2301ec57601creed@google.com    virtual uint32_t getFlags() const SK_OVERRIDE {
558b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com        return fProc16 ? (kAlphaUnchanged_Flag | kHasFilter16_Flag) : 0;
568b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com    }
57fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
588b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com    virtual void filterSpan(const SkPMColor shader[], int count,
59bada64428a52b4fc1f31a0a1982c2301ec57601creed@google.com                            SkPMColor result[]) const SK_OVERRIDE {
608b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com        SkPMColor       color = fPMColor;
618b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com        SkXfermodeProc  proc = fProc;
62fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
638b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com        for (int i = 0; i < count; i++) {
648b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com            result[i] = proc(color, shader[i]);
658b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com        }
668b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com    }
67fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
688b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com    virtual void filterSpan16(const uint16_t shader[], int count,
69bada64428a52b4fc1f31a0a1982c2301ec57601creed@google.com                              uint16_t result[]) const SK_OVERRIDE {
708b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com        SkASSERT(this->getFlags() & kHasFilter16_Flag);
71fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
728b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com        SkPMColor        color = fPMColor;
738b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com        SkXfermodeProc16 proc16 = fProc16;
74fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
758b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com        for (int i = 0; i < count; i++) {
768b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com            result[i] = proc16(color, shader[i]);
778b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com        }
788b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com    }
79fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
800f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING
811202c2ac563cdeb07406872825706b83e335c977robertphillips@google.com    virtual void toString(SkString* str) const SK_OVERRIDE {
821202c2ac563cdeb07406872825706b83e335c977robertphillips@google.com        str->append("SkModeColorFilter: color: 0x");
831202c2ac563cdeb07406872825706b83e335c977robertphillips@google.com        str->appendHex(fColor);
841202c2ac563cdeb07406872825706b83e335c977robertphillips@google.com        str->append(" mode: ");
851202c2ac563cdeb07406872825706b83e335c977robertphillips@google.com        str->append(SkXfermode::ModeName(fMode));
861202c2ac563cdeb07406872825706b83e335c977robertphillips@google.com    }
871202c2ac563cdeb07406872825706b83e335c977robertphillips@google.com#endif
881202c2ac563cdeb07406872825706b83e335c977robertphillips@google.com
89a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org#if SK_SUPPORT_GPU
90a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    virtual GrEffectRef* asNewEffect(GrContext*) const SK_OVERRIDE;
91a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org#endif
928b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkModeColorFilter)
9343c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com
9443c50c8c77df82c5cffb55cae2d386e59802b88freed@google.comprotected:
958b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE {
961447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com        this->INHERITED::flatten(buffer);
97c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com        buffer.writeColor(fColor);
98c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com        buffer.writeUInt(fMode);
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1001447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
1018b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    SkModeColorFilter(SkReadBuffer& buffer) {
102c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com        fColor = buffer.readColor();
103c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com        fMode = (SkXfermode::Mode)buffer.readUInt();
104c2e9db30d393862bd3485cfe57b4ac06433f2f32commit-bot@chromium.org        if (buffer.isValid()) {
105c2e9db30d393862bd3485cfe57b4ac06433f2f32commit-bot@chromium.org            this->updateCache();
106c2e9db30d393862bd3485cfe57b4ac06433f2f32commit-bot@chromium.org            buffer.validate(SkIsValidMode(fMode));
107c2e9db30d393862bd3485cfe57b4ac06433f2f32commit-bot@chromium.org        }
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
109845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com
11043c50c8c77df82c5cffb55cae2d386e59802b88freed@google.comprivate:
11143c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    SkColor             fColor;
11243c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    SkXfermode::Mode    fMode;
1138b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com    // cache
1148b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com    SkPMColor           fPMColor;
1158b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com    SkXfermodeProc      fProc;
1168b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com    SkXfermodeProc16    fProc16;
117fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1188b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com    void updateCache() {
1198b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com        fPMColor = SkPreMultiplyColor(fColor);
1208b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com        fProc = SkXfermode::GetProc(fMode);
1218b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com        fProc16 = SkXfermode::GetProc16(fMode, fColor);
1228b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com    }
123fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1241447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com    typedef SkColorFilter INHERITED;
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
127a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
128a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org#if SK_SUPPORT_GPU
129a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org#include "GrBlend.h"
130a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org#include "GrEffect.h"
131a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org#include "GrEffectUnitTest.h"
132a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org#include "GrTBackendEffectFactory.h"
133a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org#include "gl/GrGLEffect.h"
134a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org#include "SkGr.h"
135a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
136a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.orgnamespace {
137a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org/**
138a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org * A definition of blend equation for one coefficient. Generates a
139a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org * blend_coeff * value "expression".
140a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org */
141a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.orgtemplate<typename ColorExpr>
142a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.orgstatic inline ColorExpr blend_term(SkXfermode::Coeff coeff,
143a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org                                   const ColorExpr& src,
144a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org                                   const ColorExpr& dst,
145a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org                                   const ColorExpr& value) {
146a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    switch (coeff) {
147a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    default:
14888cb22b6b4816c7a9ca6c5b795965b4606f9eb7bcommit-bot@chromium.org        SkFAIL("Unexpected xfer coeff.");
149a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    case SkXfermode::kZero_Coeff:    /** 0 */
150a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        return ColorExpr(0);
151a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    case SkXfermode::kOne_Coeff:     /** 1 */
152a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        return value;
153a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    case SkXfermode::kSC_Coeff:
154a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        return src * value;
155a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    case SkXfermode::kISC_Coeff:
156a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        return (ColorExpr(1) - src) * dst;
157a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    case SkXfermode::kDC_Coeff:
158a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        return dst * value;
159a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    case SkXfermode::kIDC_Coeff:
160a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        return (ColorExpr(1) - dst) * value;
161a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    case SkXfermode::kSA_Coeff:      /** src alpha */
162a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        return src.a() * value;
163a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    case SkXfermode::kISA_Coeff:     /** inverse src alpha (i.e. 1 - sa) */
164a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        return (typename ColorExpr::AExpr(1) - src.a()) * value;
165a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    case SkXfermode::kDA_Coeff:      /** dst alpha */
166a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        return dst.a() * value;
167a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    case SkXfermode::kIDA_Coeff:     /** inverse dst alpha (i.e. 1 - da) */
168a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        return (typename ColorExpr::AExpr(1) - dst.a()) *  value;
169a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    }
170a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org}
171a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org/**
172a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org * Creates a color filter expression which modifies the color by
173a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org * the specified color filter.
174a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org */
175a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.orgtemplate <typename ColorExpr>
176a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.orgstatic inline ColorExpr color_filter_expression(const SkXfermode::Mode& mode,
177a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org                                                const ColorExpr& filterColor,
178a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org                                                const ColorExpr& inColor) {
179a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    SkXfermode::Coeff colorCoeff;
180a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    SkXfermode::Coeff filterColorCoeff;
181a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    SkAssertResult(SkXfermode::ModeAsCoeff(mode, &filterColorCoeff, &colorCoeff));
182a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    return blend_term(colorCoeff, filterColor, inColor, inColor) +
183a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        blend_term(filterColorCoeff, filterColor, inColor, filterColor);
184a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org}
185a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
186a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org}
187a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
188a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.orgclass ModeColorFilterEffect : public GrEffect {
189a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.orgpublic:
190a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    static GrEffectRef* Create(const GrColor& c, SkXfermode::Mode mode) {
191a93f4e770f22f913197bef82dc19078e12bee76bcommit-bot@chromium.org        // TODO: Make the effect take the coeffs rather than mode since we already do the
192a93f4e770f22f913197bef82dc19078e12bee76bcommit-bot@chromium.org        // conversion here.
193a93f4e770f22f913197bef82dc19078e12bee76bcommit-bot@chromium.org        SkXfermode::Coeff srcCoeff, dstCoeff;
194a93f4e770f22f913197bef82dc19078e12bee76bcommit-bot@chromium.org        if (!SkXfermode::ModeAsCoeff(mode, &srcCoeff, &dstCoeff)) {
195a93f4e770f22f913197bef82dc19078e12bee76bcommit-bot@chromium.org            SkDebugf("Failing to create color filter for mode %d\n", mode);
196a93f4e770f22f913197bef82dc19078e12bee76bcommit-bot@chromium.org            return NULL;
197a93f4e770f22f913197bef82dc19078e12bee76bcommit-bot@chromium.org        }
198a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        AutoEffectUnref effect(SkNEW_ARGS(ModeColorFilterEffect, (c, mode)));
199a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        return CreateEffectRef(effect);
200a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    }
201a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
202a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
203a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
204a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    bool willUseFilterColor() const {
205a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        SkXfermode::Coeff dstCoeff;
206a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        SkXfermode::Coeff srcCoeff;
207a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        SkAssertResult(SkXfermode::ModeAsCoeff(fMode, &srcCoeff, &dstCoeff));
208a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        if (SkXfermode::kZero_Coeff == srcCoeff) {
209a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org            return GrBlendCoeffRefsSrc(sk_blend_to_grblend(dstCoeff));
210a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        }
211a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        return true;
212a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    }
213a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
214a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
215a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        return GrTBackendEffectFactory<ModeColorFilterEffect>::getInstance();
216a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    }
217a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
218a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    static const char* Name() { return "ModeColorFilterEffect"; }
219a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
220a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    SkXfermode::Mode mode() const { return fMode; }
221a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    GrColor color() const { return fColor; }
222a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
223a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    class GLEffect : public GrGLEffect {
224a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    public:
225a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
226a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org            : INHERITED(factory) {
227a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        }
228a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
229a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        virtual void emitCode(GrGLShaderBuilder* builder,
230a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org                              const GrDrawEffect& drawEffect,
231a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org                              EffectKey key,
232a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org                              const char* outputColor,
233a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org                              const char* inputColor,
234a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org                              const TransformedCoordsArray& coords,
235a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org                              const TextureSamplerArray& samplers) SK_OVERRIDE {
236a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org            SkXfermode::Mode mode = drawEffect.castEffect<ModeColorFilterEffect>().mode();
237a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
238a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org            SkASSERT(SkXfermode::kDst_Mode != mode);
239a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org            const char* colorFilterColorUniName = NULL;
240a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org            if (drawEffect.castEffect<ModeColorFilterEffect>().willUseFilterColor()) {
241a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org                fFilterColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
242a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org                                                      kVec4f_GrSLType, "FilterColor",
243a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org                                                      &colorFilterColorUniName);
244a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org            }
245a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
246a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org            GrGLSLExpr4 filter =
247a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org                color_filter_expression(mode, GrGLSLExpr4(colorFilterColorUniName), GrGLSLExpr4(inputColor));
248a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
249a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org            builder->fsCodeAppendf("\t%s = %s;\n", outputColor, filter.c_str());
250a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        }
251a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
252a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
253a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org            const ModeColorFilterEffect& colorModeFilter = drawEffect.castEffect<ModeColorFilterEffect>();
254a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org            // The SL code does not depend on filter color at the moment, so no need to represent it
255a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org            // in the key.
256a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org            EffectKey modeKey = colorModeFilter.mode();
257a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org            return modeKey;
258a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        }
259a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
260a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        virtual void setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) SK_OVERRIDE {
261a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org            if (fFilterColorUni.isValid()) {
262a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org                const ModeColorFilterEffect& colorModeFilter = drawEffect.castEffect<ModeColorFilterEffect>();
263a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org                GrGLfloat c[4];
264a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org                GrColorToRGBAFloat(colorModeFilter.color(), c);
265d3baf20dd1de9940717dd50b5c9ff6061561342ecommit-bot@chromium.org                uman.set4fv(fFilterColorUni, 1, c);
266a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org            }
267a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        }
268a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
269a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    private:
270a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
271a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        GrGLUniformManager::UniformHandle fFilterColorUni;
272a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        typedef GrGLEffect INHERITED;
273a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    };
274a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
275a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    GR_DECLARE_EFFECT_TEST;
276a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
277a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.orgprivate:
278a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    ModeColorFilterEffect(GrColor color, SkXfermode::Mode mode)
279a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        : fMode(mode),
280a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org          fColor(color) {
281a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
282a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        SkXfermode::Coeff dstCoeff;
283a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        SkXfermode::Coeff srcCoeff;
284a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        SkAssertResult(SkXfermode::ModeAsCoeff(fMode, &srcCoeff, &dstCoeff));
285a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        // These could be calculated from the blend equation with template trickery..
286a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        if (SkXfermode::kZero_Coeff == dstCoeff && !GrBlendCoeffRefsDst(sk_blend_to_grblend(srcCoeff))) {
287a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org            this->setWillNotUseInputColor();
288a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        }
289a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    }
290a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
291a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
292a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        const ModeColorFilterEffect& s = CastEffect<ModeColorFilterEffect>(other);
293a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        return fMode == s.fMode && fColor == s.fColor;
294a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    }
295a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
296a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    SkXfermode::Mode fMode;
297a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    GrColor fColor;
298a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
299a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    typedef GrEffect INHERITED;
300a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org};
301a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
302a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.orgnamespace {
303a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
304a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org/** Function color_component_to_int tries to reproduce the GLSL rounding. The spec doesn't specify
305a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org * to which direction the 0.5 goes.
306a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org */
307a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.orgstatic inline int color_component_to_int(float value) {
308972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org    return sk_float_round2int(SkTMax(0.f, SkTMin(1.f, value)) * 255.f);
309a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org}
310a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
311a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org/** MaskedColorExpr is used to evaluate the color and valid color component flags through the
312a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org * blending equation. It has members similar to GrGLSLExpr so that it can be used with the
313a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org * templated helpers above.
314a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org */
315a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.orgclass MaskedColorExpr {
316a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.orgpublic:
317a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    MaskedColorExpr(const float color[], uint32_t flags)
318a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        : fFlags(flags) {
319a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        fColor[0] = color[0];
320a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        fColor[1] = color[1];
321a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        fColor[2] = color[2];
322a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        fColor[3] = color[3];
323a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    }
324a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
325a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    MaskedColorExpr(float v, uint32_t flags = kRGBA_GrColorComponentFlags)
326a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        : fFlags(flags) {
327a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        fColor[0] = v;
328a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        fColor[1] = v;
329a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        fColor[2] = v;
330a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        fColor[3] = v;
331a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    }
332a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
333a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    MaskedColorExpr operator*(const MaskedColorExpr& other) const {
334a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        float tmp[4];
335a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        tmp[0] = fColor[0] * other.fColor[0];
336a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        tmp[1] = fColor[1] * other.fColor[1];
337a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        tmp[2] = fColor[2] * other.fColor[2];
338a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        tmp[3] = fColor[3] * other.fColor[3];
339a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
340a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        return MaskedColorExpr(tmp, fFlags & other.fFlags);
341a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    }
342a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
343a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    MaskedColorExpr operator+(const MaskedColorExpr& other) const {
344a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        float tmp[4];
345a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        tmp[0] = fColor[0] + other.fColor[0];
346a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        tmp[1] = fColor[1] + other.fColor[1];
347a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        tmp[2] = fColor[2] + other.fColor[2];
348a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        tmp[3] = fColor[3] + other.fColor[3];
349a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
350a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        return MaskedColorExpr(tmp, fFlags & other.fFlags);
351a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    }
352a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
353a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    MaskedColorExpr operator-(const MaskedColorExpr& other) const {
354a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        float tmp[4];
355a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        tmp[0] = fColor[0] - other.fColor[0];
356a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        tmp[1] = fColor[1] - other.fColor[1];
357a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        tmp[2] = fColor[2] - other.fColor[2];
358a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        tmp[3] = fColor[3] - other.fColor[3];
359a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
360a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        return MaskedColorExpr(tmp, fFlags & other.fFlags);
361a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    }
362a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
363a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    MaskedColorExpr a() const {
364a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        uint32_t flags = (fFlags & kA_GrColorComponentFlag) ? kRGBA_GrColorComponentFlags : 0;
365a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        return MaskedColorExpr(fColor[3], flags);
366a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    }
367a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
368a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    GrColor getColor() const {
369a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        return GrColorPackRGBA(color_component_to_int(fColor[0]),
370a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org                               color_component_to_int(fColor[1]),
371a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org                               color_component_to_int(fColor[2]),
372a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org                               color_component_to_int(fColor[3]));
373a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    }
374a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
375a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    uint32_t getValidComponents() const  { return fFlags; }
376a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
377a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    typedef MaskedColorExpr AExpr;
378a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.orgprivate:
379a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    float fColor[4];
380a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    uint32_t fFlags;
381a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org};
382a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
383a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org}
384a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
385a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.orgvoid ModeColorFilterEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
386a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    float inputColor[4];
387a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    GrColorToRGBAFloat(*color, inputColor);
388a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    float filterColor[4];
389a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    GrColorToRGBAFloat(fColor, filterColor);
390a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    MaskedColorExpr result =
391a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        color_filter_expression(fMode,
392a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org                                MaskedColorExpr(filterColor, kRGBA_GrColorComponentFlags),
393a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org                                MaskedColorExpr(inputColor, *validFlags));
394a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
395a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    *color = result.getColor();
396a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    *validFlags = result.getValidComponents();
397a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org}
398a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
399a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.orgGR_DEFINE_EFFECT_TEST(ModeColorFilterEffect);
400a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.orgGrEffectRef* ModeColorFilterEffect::TestCreate(SkRandom* rand,
401a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org                                    GrContext*,
402a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org                                    const GrDrawTargetCaps&,
403a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org                                    GrTexture*[]) {
40423267ceca27aab4c29271e9ecd5ee5a87740ffb9commit-bot@chromium.org    SkXfermode::Mode mode = SkXfermode::kDst_Mode;
40523267ceca27aab4c29271e9ecd5ee5a87740ffb9commit-bot@chromium.org    while (SkXfermode::kDst_Mode == mode) {
40623267ceca27aab4c29271e9ecd5ee5a87740ffb9commit-bot@chromium.org        mode = static_cast<SkXfermode::Mode>(rand->nextRangeU(0, SkXfermode::kLastCoeffMode));
40723267ceca27aab4c29271e9ecd5ee5a87740ffb9commit-bot@chromium.org    }
408a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    GrColor color = rand->nextU();
40923267ceca27aab4c29271e9ecd5ee5a87740ffb9commit-bot@chromium.org    return ModeColorFilterEffect::Create(color, mode);
410a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org}
411a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
412a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.orgGrEffectRef* SkModeColorFilter::asNewEffect(GrContext*) const {
413a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    if (SkXfermode::kDst_Mode != fMode) {
414a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org        return ModeColorFilterEffect::Create(SkColor2GrColor(fColor), fMode);
415a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    }
416a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org    return NULL;
417a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org}
418a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
419a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org#endif
420a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
421a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
422a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org
42343c50c8c77df82c5cffb55cae2d386e59802b88freed@google.comclass Src_SkModeColorFilter : public SkModeColorFilter {
4248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
42543c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    Src_SkModeColorFilter(SkColor color) : INHERITED(color, SkXfermode::kSrc_Mode) {}
4268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4273eafe9b22141b348d9ebdba21215f02181a27d48mike@reedtribe.org    virtual uint32_t getFlags() const SK_OVERRIDE {
4288b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com        if (SkGetPackedA32(this->getPMColor()) == 0xFF) {
4298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return kAlphaUnchanged_Flag | kHasFilter16_Flag;
430845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        } else {
4318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return 0;
432845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        }
4338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
435845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual void filterSpan(const SkPMColor shader[], int count,
4363eafe9b22141b348d9ebdba21215f02181a27d48mike@reedtribe.org                            SkPMColor result[]) const SK_OVERRIDE {
4378b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com        sk_memset32(result, this->getPMColor(), count);
4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
440845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual void filterSpan16(const uint16_t shader[], int count,
4413eafe9b22141b348d9ebdba21215f02181a27d48mike@reedtribe.org                              uint16_t result[]) const SK_OVERRIDE {
4428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(this->getFlags() & kHasFilter16_Flag);
4438b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com        sk_memset16(result, SkPixel32ToPixel16(this->getPMColor()), count);
4448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
446ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Src_SkModeColorFilter)
4471447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
4488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected:
4498b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    Src_SkModeColorFilter(SkReadBuffer& buffer)
450845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        : INHERITED(buffer) {}
451845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com
4521447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.comprivate:
45343c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    typedef SkModeColorFilter INHERITED;
4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
45643c50c8c77df82c5cffb55cae2d386e59802b88freed@google.comclass SrcOver_SkModeColorFilter : public SkModeColorFilter {
4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
45843c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    SrcOver_SkModeColorFilter(SkColor color)
45943c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com            : INHERITED(color, SkXfermode::kSrcOver_Mode) {
4603eafe9b22141b348d9ebdba21215f02181a27d48mike@reedtribe.org        fColor32Proc = SkBlitRow::ColorProcFactory();
46143c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    }
4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4633eafe9b22141b348d9ebdba21215f02181a27d48mike@reedtribe.org    virtual uint32_t getFlags() const SK_OVERRIDE {
4648b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com        if (SkGetPackedA32(this->getPMColor()) == 0xFF) {
4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return kAlphaUnchanged_Flag | kHasFilter16_Flag;
466845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        } else {
4678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return 0;
468845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        }
4698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4701447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
471845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual void filterSpan(const SkPMColor shader[], int count,
4723eafe9b22141b348d9ebdba21215f02181a27d48mike@reedtribe.org                            SkPMColor result[]) const SK_OVERRIDE {
4738b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com        fColor32Proc(result, shader, count, this->getPMColor());
4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
476845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual void filterSpan16(const uint16_t shader[], int count,
4773eafe9b22141b348d9ebdba21215f02181a27d48mike@reedtribe.org                              uint16_t result[]) const SK_OVERRIDE {
4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(this->getFlags() & kHasFilter16_Flag);
4798b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com        sk_memset16(result, SkPixel32ToPixel16(this->getPMColor()), count);
4808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4811447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
482ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SrcOver_SkModeColorFilter)
4831447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected:
4858b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    SrcOver_SkModeColorFilter(SkReadBuffer& buffer)
4863eafe9b22141b348d9ebdba21215f02181a27d48mike@reedtribe.org        : INHERITED(buffer) {
4873eafe9b22141b348d9ebdba21215f02181a27d48mike@reedtribe.org            fColor32Proc = SkBlitRow::ColorProcFactory();
4883eafe9b22141b348d9ebdba21215f02181a27d48mike@reedtribe.org        }
4891447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
4908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
4911447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
49229e5054dd07c97c2195c5f64bf67aaa6b5afa204senorblanco@chromium.org    SkBlitRow::ColorProc fColor32Proc;
49343c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com
49443c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    typedef SkModeColorFilter INHERITED;
4958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
4968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
49743c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com///////////////////////////////////////////////////////////////////////////////
4988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
499845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comSkColorFilter* SkColorFilter::CreateModeFilter(SkColor color,
500845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                                               SkXfermode::Mode mode) {
5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned alpha = SkColorGetA(color);
5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // first collaps some modes if possible
5048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
505845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (SkXfermode::kClear_Mode == mode) {
5068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        color = 0;
507845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        mode = SkXfermode::kSrc_Mode;
508845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    } else if (SkXfermode::kSrcOver_Mode == mode) {
509845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        if (0 == alpha) {
510845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com            mode = SkXfermode::kDst_Mode;
511845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        } else if (255 == alpha) {
512845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com            mode = SkXfermode::kSrc_Mode;
5138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
5148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // else just stay srcover
5158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // weed out combinations that are noops, and just return null
518845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (SkXfermode::kDst_Mode == mode ||
519845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        (0 == alpha && (SkXfermode::kSrcOver_Mode == mode ||
520845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                        SkXfermode::kDstOver_Mode == mode ||
521845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                        SkXfermode::kDstOut_Mode == mode ||
522845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                        SkXfermode::kSrcATop_Mode == mode ||
523845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                        SkXfermode::kXor_Mode == mode ||
524845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                        SkXfermode::kDarken_Mode == mode)) ||
525845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com            (0xFF == alpha && SkXfermode::kDstIn_Mode == mode)) {
5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return NULL;
5278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5281447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    switch (mode) {
53043c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        case SkXfermode::kSrc_Mode:
53143c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com            return SkNEW_ARGS(Src_SkModeColorFilter, (color));
53243c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        case SkXfermode::kSrcOver_Mode:
53343c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com            return SkNEW_ARGS(SrcOver_SkModeColorFilter, (color));
53443c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        default:
5358b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com            return SkNEW_ARGS(SkModeColorFilter, (color, mode));
5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
539845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com///////////////////////////////////////////////////////////////////////////////
5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
54131b3044af4e97c662076147d119ba233a163b769reed@google.comstatic SkScalar byte_to_scale(U8CPU byte) {
54231b3044af4e97c662076147d119ba233a163b769reed@google.com    if (0xFF == byte) {
54331b3044af4e97c662076147d119ba233a163b769reed@google.com        // want to get this exact
54431b3044af4e97c662076147d119ba233a163b769reed@google.com        return 1;
54531b3044af4e97c662076147d119ba233a163b769reed@google.com    } else {
54631b3044af4e97c662076147d119ba233a163b769reed@google.com        return byte * 0.00392156862745f;
54731b3044af4e97c662076147d119ba233a163b769reed@google.com    }
54831b3044af4e97c662076147d119ba233a163b769reed@google.com}
54931b3044af4e97c662076147d119ba233a163b769reed@google.com
550845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comSkColorFilter* SkColorFilter::CreateLightingFilter(SkColor mul, SkColor add) {
55131b3044af4e97c662076147d119ba233a163b769reed@google.com    SkColorMatrix matrix;
55231b3044af4e97c662076147d119ba233a163b769reed@google.com    matrix.setScale(byte_to_scale(SkColorGetR(mul)),
55331b3044af4e97c662076147d119ba233a163b769reed@google.com                    byte_to_scale(SkColorGetG(mul)),
55431b3044af4e97c662076147d119ba233a163b769reed@google.com                    byte_to_scale(SkColorGetB(mul)),
55531b3044af4e97c662076147d119ba233a163b769reed@google.com                    1);
55631b3044af4e97c662076147d119ba233a163b769reed@google.com    matrix.postTranslate(SkIntToScalar(SkColorGetR(add)),
55731b3044af4e97c662076147d119ba233a163b769reed@google.com                         SkIntToScalar(SkColorGetG(add)),
55831b3044af4e97c662076147d119ba233a163b769reed@google.com                         SkIntToScalar(SkColorGetB(add)),
55931b3044af4e97c662076147d119ba233a163b769reed@google.com                         0);
560727a352f7412753d2a3e4d30eab6500a1a4de135commit-bot@chromium.org    return SkColorMatrixFilter::Create(matrix);
5618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
563d26147adbbdca85f07dff432025afee0c8614387caryclark@google.comSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkColorFilter)
5648b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkModeColorFilter)
565d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(Src_SkModeColorFilter)
566d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SrcOver_SkModeColorFilter)
567d26147adbbdca85f07dff432025afee0c8614387caryclark@google.comSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
568