SkColorFilter.cpp revision ff723af8b6bc7179132052fbab7d77ec2a20eba2
1b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com/*
2b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com * Copyright 2006 The Android Open Source Project
3b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com *
4b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com * Use of this source code is governed by a BSD-style license that can be
5b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com * found in the LICENSE file.
6b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com */
7b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com
8b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com#include "SkColorFilter.h"
94c21dc5ddf3b482293ed34eead876d8d61a662c3reed#include "SkReadBuffer.h"
1046596ae50559e89a0a2462573ac9448cf309cf56Mike Reed#include "SkRefCnt.h"
11b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com#include "SkString.h"
12e8f3062a36d3682f4019309a32b5b84dc9eddf8creed#include "SkTDArray.h"
134c21dc5ddf3b482293ed34eead876d8d61a662c3reed#include "SkUnPreMultiply.h"
1446596ae50559e89a0a2462573ac9448cf309cf56Mike Reed#include "SkWriteBuffer.h"
154c21dc5ddf3b482293ed34eead876d8d61a662c3reed#include "SkPM4f.h"
164c21dc5ddf3b482293ed34eead876d8d61a662c3reed#include "SkNx.h"
179ce9d6772df650ceb0511f275e1a83dffa78ff72reed
18b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com#if SK_SUPPORT_GPU
19b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com#include "GrFragmentProcessor.h"
20b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com#endif
21cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com
22e8f3062a36d3682f4019309a32b5b84dc9eddf8creedbool SkColorFilter::asColorMode(SkColor* color, SkXfermode::Mode* mode) const {
234c21dc5ddf3b482293ed34eead876d8d61a662c3reed    return false;
24d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com}
25b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com
26b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.combool SkColorFilter::asColorMatrix(SkScalar matrix[20]) const {
27b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com    return false;
28d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com}
29b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com
30d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.combool SkColorFilter::asComponentTable(SkBitmap*) const {
31b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com    return false;
32b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com}
33d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
34b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com#if SK_SUPPORT_GPU
354c21dc5ddf3b482293ed34eead876d8d61a662c3reedsk_sp<GrFragmentProcessor> SkColorFilter::asFragmentProcessor(GrContext*) const {
36b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com    return nullptr;
37b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com}
384c21dc5ddf3b482293ed34eead876d8d61a662c3reed#endif
39b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com
40b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.comvoid SkColorFilter::filterSpan4f(const SkPM4f src[], int count, SkPM4f result[]) const {
414c21dc5ddf3b482293ed34eead876d8d61a662c3reed    const int N = 128;
424c21dc5ddf3b482293ed34eead876d8d61a662c3reed    SkPMColor tmp[N];
439ce9d6772df650ceb0511f275e1a83dffa78ff72reed    while (count > 0) {
44b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com        int n = SkTMin(count, N);
45b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com        for (int i = 0; i < n; ++i) {
464c21dc5ddf3b482293ed34eead876d8d61a662c3reed            SkNx_cast<uint8_t>(Sk4f::Load(src[i].fVec) * Sk4f(255) + Sk4f(0.5f)).store(&tmp[i]);
474c21dc5ddf3b482293ed34eead876d8d61a662c3reed        }
484c21dc5ddf3b482293ed34eead876d8d61a662c3reed        this->filterSpan(tmp, n, tmp);
494c21dc5ddf3b482293ed34eead876d8d61a662c3reed        for (int i = 0; i < n; ++i) {
504c21dc5ddf3b482293ed34eead876d8d61a662c3reed            result[i] = SkPM4f::FromPMColor(tmp[i]);
51d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com        }
524c21dc5ddf3b482293ed34eead876d8d61a662c3reed        src += n;
53b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com        result += n;
549ce9d6772df650ceb0511f275e1a83dffa78ff72reed        count -= n;
559ce9d6772df650ceb0511f275e1a83dffa78ff72reed    }
569ce9d6772df650ceb0511f275e1a83dffa78ff72reed}
57b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com
58d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.comSkColor SkColorFilter::filterColor(SkColor c) const {
59b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com    SkPMColor dst, src = SkPreMultiplyColor(c);
60b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com    this->filterSpan(&src, 1, &dst);
614c21dc5ddf3b482293ed34eead876d8d61a662c3reed    return SkUnPreMultiply::PMColorToColor(dst);
62b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com}
63b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com
64b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.comSkColor4f SkColorFilter::filterColor4f(const SkColor4f& c) const {
654c21dc5ddf3b482293ed34eead876d8d61a662c3reed    SkPM4f dst, src = c.premul();
6633a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt    this->filterSpan4f(&src, 1, &dst);
67b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com    return dst.unpremul();
68b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com}
694c21dc5ddf3b482293ed34eead876d8d61a662c3reed
7096fcdcc219d2a0d3579719b84b28bede76efba64halcanary///////////////////////////////////////////////////////////////////////////////////////////////////
719ce9d6772df650ceb0511f275e1a83dffa78ff72reed
729ce9d6772df650ceb0511f275e1a83dffa78ff72reed/*
734c21dc5ddf3b482293ed34eead876d8d61a662c3reed *  Since colorfilters may be used on the GPU backend, and in that case we may string together
74d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com *  many GrFragmentProcessors, we might exceed some internal instruction/resource limit.
75b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com *
764c21dc5ddf3b482293ed34eead876d8d61a662c3reed *  Since we don't yet know *what* those limits might be when we construct the final shader,
77d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com *  we just set an arbitrary limit during construction. If later we find smarter ways to know what
78fafe135349bd34961a12bfd8185733709cd0e45eHal Canary *  the limnits are, we can change this constant (or remove it).
79b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com */
80b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com#define SK_MAX_COMPOSE_COLORFILTER_COUNT    4
81b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com
82b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.comclass SkComposeColorFilter : public SkColorFilter {
83b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.compublic:
84d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    uint32_t getFlags() const override {
8596fcdcc219d2a0d3579719b84b28bede76efba64halcanary        // Can only claim alphaunchanged and SkPM4f support if both our proxys do.
86d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com        return fOuter->getFlags() & fInner->getFlags();
87b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com    }
88b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com
89d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const override {
90b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com        fInner->filterSpan(shader, count, result);
9133a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt        fOuter->filterSpan(result, count, result);
9233a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt    }
9333a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt
9433a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt    void filterSpan4f(const SkPM4f shader[], int count, SkPM4f result[]) const override {
9533a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt        fInner->filterSpan4f(shader, count, result);
9633a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt        fOuter->filterSpan4f(result, count, result);
9733a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt    }
9833a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt
9933a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt#ifndef SK_IGNORE_TO_STRING
1009ce9d6772df650ceb0511f275e1a83dffa78ff72reed    void toString(SkString* str) const override {
10133a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt        SkString outerS, innerS;
102b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com        fOuter->toString(&outerS);
103b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com        fInner->toString(&innerS);
104b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com        str->appendf("SkComposeColorFilter: outer(%s) inner(%s)", outerS.c_str(), innerS.c_str());
105d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    }
106b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com#endif
1074c21dc5ddf3b482293ed34eead876d8d61a662c3reed
108b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com#if SK_SUPPORT_GPU
1094c21dc5ddf3b482293ed34eead876d8d61a662c3reed    sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext* context) const override {
110        sk_sp<GrFragmentProcessor> innerFP(fInner->asFragmentProcessor(context));
111        sk_sp<GrFragmentProcessor> outerFP(fOuter->asFragmentProcessor(context));
112        if (!innerFP || !outerFP) {
113            return nullptr;
114        }
115        sk_sp<GrFragmentProcessor> series[] = { std::move(innerFP), std::move(outerFP) };
116        return GrFragmentProcessor::RunInSeries(series, 2);
117    }
118#endif
119
120    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposeColorFilter)
121
122protected:
123    void flatten(SkWriteBuffer& buffer) const override {
124        buffer.writeFlattenable(fOuter.get());
125        buffer.writeFlattenable(fInner.get());
126    }
127
128private:
129    SkComposeColorFilter(sk_sp<SkColorFilter> outer, sk_sp<SkColorFilter> inner,
130                         int composedFilterCount)
131        : fOuter(std::move(outer))
132        , fInner(std::move(inner))
133        , fComposedFilterCount(composedFilterCount)
134    {
135        SkASSERT(composedFilterCount >= 2);
136        SkASSERT(composedFilterCount <= SK_MAX_COMPOSE_COLORFILTER_COUNT);
137    }
138
139    int privateComposedFilterCount() const override {
140        return fComposedFilterCount;
141    }
142
143    sk_sp<SkColorFilter> fOuter;
144    sk_sp<SkColorFilter> fInner;
145    const int            fComposedFilterCount;
146
147    friend class SkColorFilter;
148
149    typedef SkColorFilter INHERITED;
150};
151
152sk_sp<SkFlattenable> SkComposeColorFilter::CreateProc(SkReadBuffer& buffer) {
153    sk_sp<SkColorFilter> outer(buffer.readColorFilter());
154    sk_sp<SkColorFilter> inner(buffer.readColorFilter());
155    return MakeComposeFilter(std::move(outer), std::move(inner));
156}
157
158///////////////////////////////////////////////////////////////////////////////////////////////////
159
160sk_sp<SkColorFilter> SkColorFilter::MakeComposeFilter(sk_sp<SkColorFilter> outer,
161                                                      sk_sp<SkColorFilter> inner) {
162    if (!outer) {
163        return inner;
164    }
165    if (!inner) {
166        return outer;
167    }
168
169    // Give the subclass a shot at a more optimal composition...
170    auto composition = outer->makeComposed(inner);
171    if (composition) {
172        return composition;
173    }
174
175    int count = inner->privateComposedFilterCount() + outer->privateComposedFilterCount();
176    if (count > SK_MAX_COMPOSE_COLORFILTER_COUNT) {
177        return nullptr;
178    }
179    return sk_sp<SkColorFilter>(new SkComposeColorFilter(std::move(outer), std::move(inner),count));
180}
181
182#include "SkModeColorFilter.h"
183
184SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkColorFilter)
185SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkComposeColorFilter)
186SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkModeColorFilter)
187SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
188