1 | /* |
2 | * Copyright 2013 Google Inc. |
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 "include/core/SkShader.h" |
9 | #include "include/core/SkString.h" |
10 | #include "src/core/SkArenaAlloc.h" |
11 | #include "src/core/SkRasterPipeline.h" |
12 | #include "src/core/SkReadBuffer.h" |
13 | #include "src/core/SkVM.h" |
14 | #include "src/core/SkWriteBuffer.h" |
15 | #include "src/shaders/SkColorFilterShader.h" |
16 | |
17 | #if SK_SUPPORT_GPU |
18 | #include "src/gpu/GrFragmentProcessor.h" |
19 | #endif |
20 | |
21 | SkColorFilterShader::SkColorFilterShader(sk_sp<SkShader> shader, |
22 | float alpha, |
23 | sk_sp<SkColorFilter> filter) |
24 | : fShader(std::move(shader)) |
25 | , fFilter(std::move(filter)) |
26 | , fAlpha (alpha) |
27 | { |
28 | SkASSERT(fShader); |
29 | SkASSERT(fFilter); |
30 | } |
31 | |
32 | sk_sp<SkFlattenable> SkColorFilterShader::CreateProc(SkReadBuffer& buffer) { |
33 | auto shader = buffer.readShader(); |
34 | auto filter = buffer.readColorFilter(); |
35 | if (!shader || !filter) { |
36 | return nullptr; |
37 | } |
38 | return sk_make_sp<SkColorFilterShader>(shader, 1.0f, filter); |
39 | } |
40 | |
41 | bool SkColorFilterShader::isOpaque() const { |
42 | return fShader->isOpaque() |
43 | && fAlpha == 1.0f |
44 | && (fFilter->getFlags() & SkColorFilter::kAlphaUnchanged_Flag) != 0; |
45 | } |
46 | |
47 | void SkColorFilterShader::flatten(SkWriteBuffer& buffer) const { |
48 | buffer.writeFlattenable(fShader.get()); |
49 | SkASSERT(fAlpha == 1.0f); // Not exposed in public API SkShader::makeWithColorFilter(). |
50 | buffer.writeFlattenable(fFilter.get()); |
51 | } |
52 | |
53 | bool SkColorFilterShader::onAppendStages(const SkStageRec& rec) const { |
54 | if (!as_SB(fShader)->appendStages(rec)) { |
55 | return false; |
56 | } |
57 | if (fAlpha != 1.0f) { |
58 | rec.fPipeline->append(SkRasterPipeline::scale_1_float, rec.fAlloc->make<float>(fAlpha)); |
59 | } |
60 | fFilter->appendStages(rec, fShader->isOpaque()); |
61 | return true; |
62 | } |
63 | |
64 | skvm::Color SkColorFilterShader::onProgram(skvm::Builder* p, |
65 | skvm::F32 x, skvm::F32 y, skvm::Color paint, |
66 | const SkMatrix& ctm, const SkMatrix* localM, |
67 | SkFilterQuality quality, const SkColorInfo& dst, |
68 | skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const { |
69 | // Run the shader. |
70 | skvm::Color c = as_SB(fShader)->program(p, x,y, paint, ctm,localM, quality,dst, uniforms,alloc); |
71 | if (!c) { |
72 | return {}; |
73 | } |
74 | // Scale that by alpha. |
75 | if (fAlpha != 1.0f) { |
76 | skvm::F32 A = p->uniformF(uniforms->pushF(fAlpha)); |
77 | c.r *= A; |
78 | c.g *= A; |
79 | c.b *= A; |
80 | c.a *= A; |
81 | } |
82 | |
83 | // Finally run that through the color filter. |
84 | return fFilter->program(p,c, dst.colorSpace(), uniforms,alloc); |
85 | } |
86 | |
87 | #if SK_SUPPORT_GPU |
88 | ///////////////////////////////////////////////////////////////////// |
89 | |
90 | #include "include/gpu/GrContext.h" |
91 | |
92 | std::unique_ptr<GrFragmentProcessor> SkColorFilterShader::asFragmentProcessor( |
93 | const GrFPArgs& args) const { |
94 | auto fp1 = as_SB(fShader)->asFragmentProcessor(args); |
95 | if (!fp1) { |
96 | return nullptr; |
97 | } |
98 | |
99 | // TODO I guess, but it shouldn't come up as used today. |
100 | SkASSERT(fAlpha == 1.0f); |
101 | |
102 | auto fp2 = fFilter->asFragmentProcessor(args.fContext, *args.fDstColorInfo); |
103 | if (!fp2) { |
104 | return fp1; |
105 | } |
106 | |
107 | std::unique_ptr<GrFragmentProcessor> fpSeries[] = { std::move(fp1), std::move(fp2) }; |
108 | return GrFragmentProcessor::RunInSeries(fpSeries, 2); |
109 | } |
110 | #endif |
111 | |
112 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
113 | |
114 | sk_sp<SkShader> SkShader::makeWithColorFilter(sk_sp<SkColorFilter> filter) const { |
115 | SkShader* base = const_cast<SkShader*>(this); |
116 | if (!filter) { |
117 | return sk_ref_sp(base); |
118 | } |
119 | return sk_make_sp<SkColorFilterShader>(sk_ref_sp(base), 1.0f, filter); |
120 | } |
121 | |