/src/skia/src/shaders/SkColorFilterShader.cpp
Line | Count | Source (jump to first uncovered line) |
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/SkColorFilterBase.h" |
12 | | #include "src/core/SkRasterPipeline.h" |
13 | | #include "src/core/SkReadBuffer.h" |
14 | | #include "src/core/SkVM.h" |
15 | | #include "src/core/SkWriteBuffer.h" |
16 | | #include "src/shaders/SkColorFilterShader.h" |
17 | | |
18 | | #if SK_SUPPORT_GPU |
19 | | #include "src/gpu/GrFragmentProcessor.h" |
20 | | #endif |
21 | | |
22 | | SkColorFilterShader::SkColorFilterShader(sk_sp<SkShader> shader, |
23 | | float alpha, |
24 | | sk_sp<SkColorFilter> filter) |
25 | | : fShader(std::move(shader)) |
26 | | , fFilter(as_CFB_sp(std::move(filter))) |
27 | | , fAlpha (alpha) |
28 | 55.3k | { |
29 | 55.3k | SkASSERT(fShader); |
30 | 55.3k | SkASSERT(fFilter); |
31 | 55.3k | } |
32 | | |
33 | 141 | sk_sp<SkFlattenable> SkColorFilterShader::CreateProc(SkReadBuffer& buffer) { |
34 | 141 | auto shader = buffer.readShader(); |
35 | 141 | auto filter = buffer.readColorFilter(); |
36 | 141 | if (!shader || !filter) { |
37 | 141 | return nullptr; |
38 | 141 | } |
39 | 0 | return sk_make_sp<SkColorFilterShader>(shader, 1.0f, filter); |
40 | 0 | } |
41 | | |
42 | 53.3k | bool SkColorFilterShader::isOpaque() const { |
43 | 53.3k | return fShader->isOpaque() && fAlpha == 1.0f && as_CFB(fFilter)->isAlphaUnchanged(); |
44 | 53.3k | } |
45 | | |
46 | 0 | void SkColorFilterShader::flatten(SkWriteBuffer& buffer) const { |
47 | 0 | buffer.writeFlattenable(fShader.get()); |
48 | 0 | SkASSERT(fAlpha == 1.0f); // Not exposed in public API SkShader::makeWithColorFilter(). |
49 | 0 | buffer.writeFlattenable(fFilter.get()); |
50 | 0 | } Unexecuted instantiation: SkColorFilterShader::flatten(SkWriteBuffer&) const Unexecuted instantiation: SkColorFilterShader::flatten(SkWriteBuffer&) const |
51 | | |
52 | 5.64k | bool SkColorFilterShader::onAppendStages(const SkStageRec& rec) const { |
53 | 5.64k | if (!as_SB(fShader)->appendStages(rec)) { |
54 | 294 | return false; |
55 | 294 | } |
56 | 5.35k | if (fAlpha != 1.0f) { |
57 | 3.37k | rec.fPipeline->append(SkRasterPipeline::scale_1_float, rec.fAlloc->make<float>(fAlpha)); |
58 | 3.37k | } |
59 | 5.35k | if (!fFilter->appendStages(rec, fShader->isOpaque())) { |
60 | 340 | return false; |
61 | 340 | } |
62 | 5.01k | return true; |
63 | 5.01k | } |
64 | | |
65 | | skvm::Color SkColorFilterShader::onProgram(skvm::Builder* p, |
66 | | skvm::Coord device, skvm::Coord local, skvm::Color paint, |
67 | | const SkMatrixProvider& matrices, const SkMatrix* localM, |
68 | | const SkColorInfo& dst, |
69 | 50.0k | skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const { |
70 | | // Run the shader. |
71 | 50.0k | skvm::Color c = as_SB(fShader)->program(p, device,local, paint, |
72 | 50.0k | matrices,localM, dst, |
73 | 50.0k | uniforms,alloc); |
74 | 50.0k | if (!c) { |
75 | 49.8k | return {}; |
76 | 49.8k | } |
77 | | // Scale that by alpha. |
78 | 233 | if (fAlpha != 1.0f) { |
79 | 216 | skvm::F32 A = p->uniformF(uniforms->pushF(fAlpha)); |
80 | 216 | c.r *= A; |
81 | 216 | c.g *= A; |
82 | 216 | c.b *= A; |
83 | 216 | c.a *= A; |
84 | 216 | } |
85 | | |
86 | | // Finally run that through the color filter. |
87 | 233 | return fFilter->program(p,c, dst, uniforms,alloc); |
88 | 233 | } |
89 | | |
90 | | #if SK_SUPPORT_GPU |
91 | | ///////////////////////////////////////////////////////////////////// |
92 | | |
93 | | |
94 | | std::unique_ptr<GrFragmentProcessor> SkColorFilterShader::asFragmentProcessor( |
95 | 134 | const GrFPArgs& args) const { |
96 | 134 | auto shaderFP = as_SB(fShader)->asFragmentProcessor(args); |
97 | 134 | if (!shaderFP) { |
98 | 0 | return nullptr; |
99 | 0 | } |
100 | | |
101 | | // TODO I guess, but it shouldn't come up as used today. |
102 | 134 | SkASSERT(fAlpha == 1.0f); |
103 | | |
104 | 134 | auto [success, fp] = fFilter->asFragmentProcessor(std::move(shaderFP), args.fContext, |
105 | 134 | *args.fDstColorInfo); |
106 | | // If the filter FP could not be created, we still want to return the shader FP, so checking |
107 | | // success can be omitted here. |
108 | 134 | return std::move(fp); |
109 | 134 | } |
110 | | #endif |
111 | | |
112 | | /////////////////////////////////////////////////////////////////////////////////////////////////// |
113 | | |
114 | 645 | sk_sp<SkShader> SkShader::makeWithColorFilter(sk_sp<SkColorFilter> filter) const { |
115 | 645 | SkShader* base = const_cast<SkShader*>(this); |
116 | 645 | if (!filter) { |
117 | 307 | return sk_ref_sp(base); |
118 | 307 | } |
119 | 338 | return sk_make_sp<SkColorFilterShader>(sk_ref_sp(base), 1.0f, filter); |
120 | 338 | } |