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
asColorMode(SkColor * color,SkXfermode::Mode * mode) const22 bool SkColorFilter::asColorMode(SkColor* color, SkXfermode::Mode* mode) const {
23 return false;
24 }
25
asColorMatrix(SkScalar matrix[20]) const26 bool SkColorFilter::asColorMatrix(SkScalar matrix[20]) const {
27 return false;
28 }
29
asComponentTable(SkBitmap *) const30 bool SkColorFilter::asComponentTable(SkBitmap*) const {
31 return false;
32 }
33
filterSpan4f(const SkPM4f[],int count,SkPM4f span[]) const34 void 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
filterColor(SkColor c) const51 SkColor SkColorFilter::filterColor(SkColor c) const {
52 SkPMColor dst, src = SkPreMultiplyColor(c);
53 this->filterSpan(&src, 1, &dst);
54 return SkUnPreMultiply::PMColorToColor(dst);
55 }
56
filterColor4f(const SkColor4f & c) const57 SkColor4f 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
75 class SkComposeColorFilter : public SkColorFilter {
76 public:
getFlags() const77 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
filterSpan(const SkPMColor shader[],int count,SkPMColor result[]) const82 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
filterSpan4f(const SkPM4f shader[],int count,SkPM4f result[]) const87 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
toString(SkString * str) const93 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
asFragmentProcessor(GrContext * context) const102 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
115 protected:
flatten(SkWriteBuffer & buffer) const116 void flatten(SkWriteBuffer& buffer) const override {
117 buffer.writeFlattenable(fOuter);
118 buffer.writeFlattenable(fInner);
119 }
120
121 private:
SkComposeColorFilter(SkColorFilter * outer,SkColorFilter * inner,int composedFilterCount)122 SkComposeColorFilter(SkColorFilter* outer, SkColorFilter* inner, int composedFilterCount)
123 : fOuter(SkRef(outer))
124 , fInner(SkRef(inner))
125 , fComposedFilterCount(composedFilterCount)
126 {
127 SkASSERT(composedFilterCount >= 2);
128 SkASSERT(composedFilterCount <= SK_MAX_COMPOSE_COLORFILTER_COUNT);
129 }
130
privateComposedFilterCount() const131 int privateComposedFilterCount() const override {
132 return fComposedFilterCount;
133 }
134
135 SkAutoTUnref<SkColorFilter> fOuter;
136 SkAutoTUnref<SkColorFilter> fInner;
137 const int fComposedFilterCount;
138
139 friend class SkColorFilter;
140
141 typedef SkColorFilter INHERITED;
142 };
143
CreateProc(SkReadBuffer & buffer)144 SkFlattenable* SkComposeColorFilter::CreateProc(SkReadBuffer& buffer) {
145 SkAutoTUnref<SkColorFilter> outer(buffer.readColorFilter());
146 SkAutoTUnref<SkColorFilter> inner(buffer.readColorFilter());
147 return CreateComposeFilter(outer, inner);
148 }
149
150 ///////////////////////////////////////////////////////////////////////////////////////////////////
151
CreateComposeFilter(SkColorFilter * outer,SkColorFilter * inner)152 SkColorFilter* SkColorFilter::CreateComposeFilter(SkColorFilter* outer, SkColorFilter* inner) {
153 if (!outer) {
154 return SkSafeRef(inner);
155 }
156 if (!inner) {
157 return SkSafeRef(outer);
158 }
159
160 // Give the subclass a shot at a more optimal composition...
161 SkColorFilter* composition = outer->newComposed(inner);
162 if (composition) {
163 return composition;
164 }
165
166 int count = inner->privateComposedFilterCount() + outer->privateComposedFilterCount();
167 if (count > SK_MAX_COMPOSE_COLORFILTER_COUNT) {
168 return nullptr;
169 }
170 return new SkComposeColorFilter(outer, inner, count);
171 }
172
173 #include "SkModeColorFilter.h"
174
175 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkColorFilter)
176 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkComposeColorFilter)
177 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkModeColorFilter)
178 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
179
180