SkColorFilter.cpp revision f809d7687a4fb7b88b651b046da2bc0035d6aa09
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 "SkColorFilter.h"
9#include "SkReadBuffer.h"
10#include "SkRefCnt.h"
11#include "SkString.h"
12#include "SkTDArray.h"
13#include "SkUnPreMultiply.h"
14#include "SkWriteBuffer.h"
15#include "SkPM4f.h"
16#include "SkNx.h"
17
18#if SK_SUPPORT_GPU
19#include "GrFragmentProcessor.h"
20#endif
21
22bool SkColorFilter::asColorMode(SkColor* color, SkXfermode::Mode* mode) const {
23    return false;
24}
25
26bool SkColorFilter::asColorMatrix(SkScalar matrix[20]) const {
27    return false;
28}
29
30bool SkColorFilter::asComponentTable(SkBitmap*) const {
31    return false;
32}
33
34void SkColorFilter::filterSpan4f(const SkPM4f[], int count, SkPM4f span[]) const {
35    const int N = 128;
36    SkPMColor tmp[N];
37    while (count > 0) {
38        int n = SkTMin(count, N);
39        for (int i = 0; i < n; ++i) {
40            SkNx_cast<uint8_t>(Sk4f::Load(span[i].fVec) * Sk4f(255) + Sk4f(0.5f)).store(&tmp[i]);
41        }
42        this->filterSpan(tmp, n, tmp);
43        for (int i = 0; i < n; ++i) {
44            span[i] = SkPM4f::FromPMColor(tmp[i]);
45        }
46        span += n;
47        count -= n;
48    }
49}
50
51SkColor SkColorFilter::filterColor(SkColor c) const {
52    SkPMColor dst, src = SkPreMultiplyColor(c);
53    this->filterSpan(&src, 1, &dst);
54    return SkUnPreMultiply::PMColorToColor(dst);
55}
56
57SkColor4f SkColorFilter::filterColor4f(const SkColor4f& c) const {
58    SkPM4f dst, src = c.premul();
59    this->filterSpan4f(&src, 1, &dst);
60    return dst.unpremul();
61}
62
63///////////////////////////////////////////////////////////////////////////////////////////////////
64
65/*
66 *  Since colorfilters may be used on the GPU backend, and in that case we may string together
67 *  many GrFragmentProcessors, we might exceed some internal instruction/resource limit.
68 *
69 *  Since we don't yet know *what* those limits might be when we construct the final shader,
70 *  we just set an arbitrary limit during construction. If later we find smarter ways to know what
71 *  the limnits are, we can change this constant (or remove it).
72 */
73#define SK_MAX_COMPOSE_COLORFILTER_COUNT    4
74
75class SkComposeColorFilter : public SkColorFilter {
76public:
77    uint32_t getFlags() const override {
78        // Can only claim alphaunchanged and SkPM4f support if both our proxys do.
79        return fOuter->getFlags() & fInner->getFlags();
80    }
81
82    void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const override {
83        fInner->filterSpan(shader, count, result);
84        fOuter->filterSpan(result, count, result);
85    }
86
87    void filterSpan4f(const SkPM4f shader[], int count, SkPM4f result[]) const override {
88        fInner->filterSpan4f(shader, count, result);
89        fOuter->filterSpan4f(result, count, result);
90    }
91
92#ifndef SK_IGNORE_TO_STRING
93    void toString(SkString* str) const override {
94        SkString outerS, innerS;
95        fOuter->toString(&outerS);
96        fInner->toString(&innerS);
97        str->appendf("SkComposeColorFilter: outer(%s) inner(%s)", outerS.c_str(), innerS.c_str());
98    }
99#endif
100
101#if SK_SUPPORT_GPU
102    const GrFragmentProcessor* asFragmentProcessor(GrContext* context) const override {
103        SkAutoTUnref<const GrFragmentProcessor> innerFP(fInner->asFragmentProcessor(context));
104        SkAutoTUnref<const GrFragmentProcessor> outerFP(fOuter->asFragmentProcessor(context));
105        if (!innerFP || !outerFP) {
106            return nullptr;
107        }
108        const GrFragmentProcessor* series[] = { innerFP, outerFP };
109        return GrFragmentProcessor::RunInSeries(series, 2);
110    }
111#endif
112
113    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposeColorFilter)
114
115protected:
116    void flatten(SkWriteBuffer& buffer) const override {
117        buffer.writeFlattenable(fOuter.get());
118        buffer.writeFlattenable(fInner.get());
119    }
120
121private:
122    SkComposeColorFilter(sk_sp<SkColorFilter> outer, sk_sp<SkColorFilter> inner,
123                         int composedFilterCount)
124        : fOuter(std::move(outer))
125        , fInner(std::move(inner))
126        , fComposedFilterCount(composedFilterCount)
127    {
128        SkASSERT(composedFilterCount >= 2);
129        SkASSERT(composedFilterCount <= SK_MAX_COMPOSE_COLORFILTER_COUNT);
130    }
131
132    int privateComposedFilterCount() const override {
133        return fComposedFilterCount;
134    }
135
136    sk_sp<SkColorFilter> fOuter;
137    sk_sp<SkColorFilter> fInner;
138    const int            fComposedFilterCount;
139
140    friend class SkColorFilter;
141
142    typedef SkColorFilter INHERITED;
143};
144
145SkFlattenable* SkComposeColorFilter::CreateProc(SkReadBuffer& buffer) {
146    sk_sp<SkColorFilter> outer(buffer.readColorFilter());
147    sk_sp<SkColorFilter> inner(buffer.readColorFilter());
148    return MakeComposeFilter(std::move(outer), std::move(inner)).release();
149}
150
151///////////////////////////////////////////////////////////////////////////////////////////////////
152
153sk_sp<SkColorFilter> SkColorFilter::MakeComposeFilter(sk_sp<SkColorFilter> outer,
154                                                      sk_sp<SkColorFilter> inner) {
155    if (!outer) {
156        return inner;
157    }
158    if (!inner) {
159        return outer;
160    }
161
162    // Give the subclass a shot at a more optimal composition...
163    auto composition = outer->makeComposed(inner);
164    if (composition) {
165        return composition;
166    }
167
168    int count = inner->privateComposedFilterCount() + outer->privateComposedFilterCount();
169    if (count > SK_MAX_COMPOSE_COLORFILTER_COUNT) {
170        return nullptr;
171    }
172    return sk_sp<SkColorFilter>(new SkComposeColorFilter(std::move(outer), std::move(inner),count));
173}
174
175#include "SkModeColorFilter.h"
176
177SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkColorFilter)
178SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkComposeColorFilter)
179SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkModeColorFilter)
180SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
181
182