• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "SkArenaAlloc.h"
9 #include "SkColorFilter.h"
10 #include "SkColorSpaceXformer.h"
11 #include "SkNx.h"
12 #include "SkPM4f.h"
13 #include "SkRasterPipeline.h"
14 #include "SkReadBuffer.h"
15 #include "SkRefCnt.h"
16 #include "SkString.h"
17 #include "SkTDArray.h"
18 #include "SkUnPreMultiply.h"
19 #include "SkWriteBuffer.h"
20 #include "../jumper/SkJumper.h"
21 
22 #if SK_SUPPORT_GPU
23 #include "GrFragmentProcessor.h"
24 #endif
25 
asColorMode(SkColor *,SkBlendMode *) const26 bool SkColorFilter::asColorMode(SkColor*, SkBlendMode*) const {
27     return false;
28 }
29 
asColorMatrix(SkScalar matrix[20]) const30 bool SkColorFilter::asColorMatrix(SkScalar matrix[20]) const {
31     return false;
32 }
33 
asComponentTable(SkBitmap *) const34 bool SkColorFilter::asComponentTable(SkBitmap*) const {
35     return false;
36 }
37 
38 #if SK_SUPPORT_GPU
asFragmentProcessor(GrContext *,SkColorSpace *) const39 sk_sp<GrFragmentProcessor> SkColorFilter::asFragmentProcessor(GrContext*, SkColorSpace*) const {
40     return nullptr;
41 }
42 #endif
43 
appendStages(SkRasterPipeline * p,SkColorSpace * dstCS,SkArenaAlloc * alloc,bool shaderIsOpaque) const44 void SkColorFilter::appendStages(SkRasterPipeline* p,
45                                  SkColorSpace* dstCS,
46                                  SkArenaAlloc* alloc,
47                                  bool shaderIsOpaque) const {
48     this->onAppendStages(p, dstCS, alloc, shaderIsOpaque);
49 }
50 
filterColor(SkColor c) const51 SkColor SkColorFilter::filterColor(SkColor c) const {
52     const float inv255 = 1.0f / 255;
53     SkColor4f c4 = this->filterColor4f({
54         SkColorGetR(c) * inv255,
55         SkColorGetG(c) * inv255,
56         SkColorGetB(c) * inv255,
57         SkColorGetA(c) * inv255,
58     });
59     return SkColorSetARGB(sk_float_round2int(c4.fA*255),
60                           sk_float_round2int(c4.fR*255),
61                           sk_float_round2int(c4.fG*255),
62                           sk_float_round2int(c4.fB*255));
63 }
64 
65 #include "SkRasterPipeline.h"
filterColor4f(const SkColor4f & c) const66 SkColor4f SkColorFilter::filterColor4f(const SkColor4f& c) const {
67     SkPM4f dst, src = c.premul();
68 
69     SkSTArenaAlloc<128> alloc;
70     SkRasterPipeline    pipeline(&alloc);
71 
72     pipeline.append_uniform_color(&alloc, src);
73     this->onAppendStages(&pipeline, nullptr, &alloc, c.fA == 1);
74     SkPM4f* dstPtr = &dst;
75     pipeline.append(SkRasterPipeline::store_f32, &dstPtr);
76     pipeline.run(0,0, 1);
77 
78     return dst.unpremul();
79 }
80 
81 ///////////////////////////////////////////////////////////////////////////////////////////////////
82 
83 /*
84  *  Since colorfilters may be used on the GPU backend, and in that case we may string together
85  *  many GrFragmentProcessors, we might exceed some internal instruction/resource limit.
86  *
87  *  Since we don't yet know *what* those limits might be when we construct the final shader,
88  *  we just set an arbitrary limit during construction. If later we find smarter ways to know what
89  *  the limnits are, we can change this constant (or remove it).
90  */
91 #define SK_MAX_COMPOSE_COLORFILTER_COUNT    4
92 
93 class SkComposeColorFilter : public SkColorFilter {
94 public:
getFlags() const95     uint32_t getFlags() const override {
96         // Can only claim alphaunchanged and SkPM4f support if both our proxys do.
97         return fOuter->getFlags() & fInner->getFlags();
98     }
99 
100 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const101     void toString(SkString* str) const override {
102         SkString outerS, innerS;
103         fOuter->toString(&outerS);
104         fInner->toString(&innerS);
105         // These strings can be long.  SkString::appendf has limitations.
106         str->append(SkStringPrintf("SkComposeColorFilter: outer(%s) inner(%s)", outerS.c_str(),
107                                    innerS.c_str()));
108     }
109 #endif
110 
onAppendStages(SkRasterPipeline * p,SkColorSpace * dst,SkArenaAlloc * scratch,bool shaderIsOpaque) const111     void onAppendStages(SkRasterPipeline* p, SkColorSpace* dst, SkArenaAlloc* scratch,
112                         bool shaderIsOpaque) const override {
113         bool innerIsOpaque = shaderIsOpaque;
114         if (!(fInner->getFlags() & kAlphaUnchanged_Flag)) {
115             innerIsOpaque = false;
116         }
117         fInner->appendStages(p, dst, scratch, shaderIsOpaque);
118         fOuter->appendStages(p, dst, scratch, innerIsOpaque);
119     }
120 
121 #if SK_SUPPORT_GPU
asFragmentProcessor(GrContext * context,SkColorSpace * dstColorSpace) const122     sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext* context,
123                                                    SkColorSpace* dstColorSpace) const override {
124         sk_sp<GrFragmentProcessor> innerFP(fInner->asFragmentProcessor(context, dstColorSpace));
125         sk_sp<GrFragmentProcessor> outerFP(fOuter->asFragmentProcessor(context, dstColorSpace));
126         if (!innerFP || !outerFP) {
127             return nullptr;
128         }
129         sk_sp<GrFragmentProcessor> series[] = { std::move(innerFP), std::move(outerFP) };
130         return GrFragmentProcessor::RunInSeries(series, 2);
131     }
132 #endif
133 
134     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposeColorFilter)
135 
136 protected:
flatten(SkWriteBuffer & buffer) const137     void flatten(SkWriteBuffer& buffer) const override {
138         buffer.writeFlattenable(fOuter.get());
139         buffer.writeFlattenable(fInner.get());
140     }
141 
142 private:
SkComposeColorFilter(sk_sp<SkColorFilter> outer,sk_sp<SkColorFilter> inner,int composedFilterCount)143     SkComposeColorFilter(sk_sp<SkColorFilter> outer, sk_sp<SkColorFilter> inner,
144                          int composedFilterCount)
145         : fOuter(std::move(outer))
146         , fInner(std::move(inner))
147         , fComposedFilterCount(composedFilterCount)
148     {
149         SkASSERT(composedFilterCount >= 2);
150         SkASSERT(composedFilterCount <= SK_MAX_COMPOSE_COLORFILTER_COUNT);
151     }
152 
privateComposedFilterCount() const153     int privateComposedFilterCount() const override {
154         return fComposedFilterCount;
155     }
156 
onMakeColorSpace(SkColorSpaceXformer * xformer) const157     sk_sp<SkColorFilter> onMakeColorSpace(SkColorSpaceXformer* xformer) const override {
158         auto outer = xformer->apply(fOuter.get());
159         auto inner = xformer->apply(fInner.get());
160         if (outer != fOuter || inner != fInner) {
161             return SkColorFilter::MakeComposeFilter(outer, inner);
162         }
163         return this->INHERITED::onMakeColorSpace(xformer);
164     }
165 
166     sk_sp<SkColorFilter> fOuter;
167     sk_sp<SkColorFilter> fInner;
168     const int            fComposedFilterCount;
169 
170     friend class SkColorFilter;
171 
172     typedef SkColorFilter INHERITED;
173 };
174 
CreateProc(SkReadBuffer & buffer)175 sk_sp<SkFlattenable> SkComposeColorFilter::CreateProc(SkReadBuffer& buffer) {
176     sk_sp<SkColorFilter> outer(buffer.readColorFilter());
177     sk_sp<SkColorFilter> inner(buffer.readColorFilter());
178     return MakeComposeFilter(std::move(outer), std::move(inner));
179 }
180 
MakeComposeFilter(sk_sp<SkColorFilter> outer,sk_sp<SkColorFilter> inner)181 sk_sp<SkColorFilter> SkColorFilter::MakeComposeFilter(sk_sp<SkColorFilter> outer,
182                                                       sk_sp<SkColorFilter> inner) {
183     if (!outer) {
184         return inner;
185     }
186     if (!inner) {
187         return outer;
188     }
189 
190     // Give the subclass a shot at a more optimal composition...
191     auto composition = outer->makeComposed(inner);
192     if (composition) {
193         return composition;
194     }
195 
196     int count = inner->privateComposedFilterCount() + outer->privateComposedFilterCount();
197     if (count > SK_MAX_COMPOSE_COLORFILTER_COUNT) {
198         return nullptr;
199     }
200     return sk_sp<SkColorFilter>(new SkComposeColorFilter(std::move(outer), std::move(inner),count));
201 }
202 
203 ///////////////////////////////////////////////////////////////////////////////////////////////////
204 
205 #if SK_SUPPORT_GPU
206 #include "../gpu/effects/GrSRGBEffect.h"
207 #endif
208 
209 class SkSRGBGammaColorFilter : public SkColorFilter {
210 public:
211     enum class Direction {
212         kLinearToSRGB,
213         kSRGBToLinear,
214     };
SkSRGBGammaColorFilter(Direction dir)215     SkSRGBGammaColorFilter(Direction dir) : fDir(dir) {}
216 
217 #if SK_SUPPORT_GPU
asFragmentProcessor(GrContext * x,SkColorSpace * cs) const218     sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext* x, SkColorSpace* cs) const override {
219         // wish our caller would let us know if our input was opaque...
220         GrSRGBEffect::Alpha alpha = GrSRGBEffect::Alpha::kPremul;
221         switch (fDir) {
222             case Direction::kLinearToSRGB:
223                 return GrSRGBEffect::Make(GrSRGBEffect::Mode::kLinearToSRGB, alpha);
224             case Direction::kSRGBToLinear:
225                 return GrSRGBEffect::Make(GrSRGBEffect::Mode::kSRGBToLinear, alpha);
226         }
227         return nullptr;
228     }
229 #endif
230 
231     SK_TO_STRING_OVERRIDE()
232 
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSRGBGammaColorFilter)233     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSRGBGammaColorFilter)
234 
235     void onAppendStages(SkRasterPipeline* p, SkColorSpace*, SkArenaAlloc* alloc,
236                         bool shaderIsOpaque) const override {
237         if (!shaderIsOpaque) {
238             p->append(SkRasterPipeline::unpremul);
239         }
240         switch (fDir) {
241             case Direction::kLinearToSRGB:
242                 p->append(SkRasterPipeline::to_srgb);
243                 break;
244             case Direction::kSRGBToLinear:
245                 p->append_from_srgb(shaderIsOpaque ? kOpaque_SkAlphaType : kUnpremul_SkAlphaType);
246                 break;
247         }
248         if (!shaderIsOpaque) {
249             p->append(SkRasterPipeline::premul);
250         }
251     }
252 
253 protected:
flatten(SkWriteBuffer & buffer) const254     void flatten(SkWriteBuffer& buffer) const override {
255         buffer.write32(static_cast<uint32_t>(fDir));
256     }
257 
258 private:
259     const Direction fDir;
260 
261     friend class SkColorFilter;
262     typedef SkColorFilter INHERITED;
263 };
264 
CreateProc(SkReadBuffer & buffer)265 sk_sp<SkFlattenable> SkSRGBGammaColorFilter::CreateProc(SkReadBuffer& buffer) {
266     uint32_t dir = buffer.read32();
267     if (dir <= 1) {
268         return sk_sp<SkFlattenable>(new SkSRGBGammaColorFilter(static_cast<Direction>(dir)));
269     }
270     buffer.validate(false);
271     return nullptr;
272 }
273 
274 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const275 void SkSRGBGammaColorFilter::toString(SkString* str) const {
276     str->append("srgbgamma");
277 }
278 #endif
279 
280 template <SkSRGBGammaColorFilter::Direction dir>
MakeSRGBGammaCF()281 sk_sp<SkColorFilter> MakeSRGBGammaCF() {
282     static SkColorFilter* gSingleton = new SkSRGBGammaColorFilter(dir);
283     return sk_ref_sp(gSingleton);
284 }
285 
MakeLinearToSRGBGamma()286 sk_sp<SkColorFilter> SkColorFilter::MakeLinearToSRGBGamma() {
287     return MakeSRGBGammaCF<SkSRGBGammaColorFilter::Direction::kLinearToSRGB>();
288 }
289 
MakeSRGBToLinearGamma()290 sk_sp<SkColorFilter> SkColorFilter::MakeSRGBToLinearGamma() {
291     return MakeSRGBGammaCF<SkSRGBGammaColorFilter::Direction::kSRGBToLinear>();
292 }
293 
294 ///////////////////////////////////////////////////////////////////////////////////////////////////
295 
296 #include "SkModeColorFilter.h"
297 
298 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkColorFilter)
299 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkComposeColorFilter)
300 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkModeColorFilter)
301 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSRGBGammaColorFilter)
302 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
303