2 * Copyright 2020 Google LLC
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #ifndef SkRuntimeEffectPriv_DEFINED
9 #define SkRuntimeEffectPriv_DEFINED
11 #include "include/effects/SkRuntimeEffect.h"
12 #include "include/private/SkColorData.h"
13 #include "src/core/SkVM.h"
19 class SkRuntimeEffectPriv {
21 // Helper function when creating an effect for a GrSkSLFP that verifies an effect will
22 // implement the constant output for constant input optimization flag.
23 static bool SupportsConstantOutputForConstantInput(sk_sp<SkRuntimeEffect> effect) {
24 return effect->getFilterColorProgram();
27 static SkRuntimeEffect::Options ES3Options() {
28 SkRuntimeEffect::Options options;
29 options.enforceES2Restrictions = false;
33 static void UsePrivateRTShaderModule(SkRuntimeEffect::Options* options) {
34 options->usePrivateRTShaderModule = true;
38 // These internal APIs for creating runtime effects vary from the public API in two ways:
40 // 1) they're used in contexts where it's not useful to receive an error message;
43 // Users of the public SkRuntimeEffect::Make*() can of course cache however they like themselves;
44 // keeping these APIs private means users will not be forced into our cache or cache policy.
46 sk_sp<SkRuntimeEffect> SkMakeCachedRuntimeEffect(SkRuntimeEffect::Result (*make)(SkString sksl),
49 inline sk_sp<SkRuntimeEffect> SkMakeCachedRuntimeEffect(SkRuntimeEffect::Result (*make)(SkString),
51 return SkMakeCachedRuntimeEffect(make, SkString{sksl});
54 // Internal API that assumes (and asserts) that the shader code is valid, but does no internal
55 // caching. Used when the caller will cache the result in a static variable.
56 inline sk_sp<SkRuntimeEffect> SkMakeRuntimeEffect(
57 SkRuntimeEffect::Result (*make)(SkString, const SkRuntimeEffect::Options&),
59 SkRuntimeEffect::Options options = SkRuntimeEffect::Options{}) {
60 SkRuntimeEffectPriv::UsePrivateRTShaderModule(&options);
61 auto result = make(SkString{sksl}, options);
62 SkASSERTF(result.effect, "%s", result.errorText.c_str());
66 // This is mostly from skvm's rgb->hsl code, with some GPU-related finesse pulled from
67 // GrHighContrastFilterEffect.fp, see next comment.
68 inline constexpr char kRGB_to_HSL_sksl[] =
69 "half3 rgb_to_hsl(half3 c) {"
70 "half mx = max(max(c.r,c.g),c.b),"
71 " mn = min(min(c.r,c.g),c.b),"
74 " g_lt_b = c.g < c.b ? 6.0 : 0.0;"
76 // We'd prefer to write these tests like `mx == c.r`, but on some GPUs max(x,y) is
77 // not always equal to either x or y. So we use long form, c.r >= c.g && c.r >= c.b.
78 "half h = (1/6.0) * (mx == mn ? 0.0 :"
79 " /*mx==c.r*/ c.r >= c.g && c.r >= c.b ? invd * (c.g - c.b) + g_lt_b :"
80 " /*mx==c.g*/ c.g >= c.b ? invd * (c.b - c.r) + 2.0 "
81 " /*mx==c.b*/ : invd * (c.r - c.g) + 4.0);"
86 " : d / (l > 0.5 ? 2.0 - sum : sum);"
87 "return half3(h,s,l);"
90 //This is straight out of GrHSLToRGBFilterEffect.fp.
91 inline constexpr char kHSL_to_RGB_sksl[] =
92 "half3 hsl_to_rgb(half3 hsl) {"
93 "half C = (1 - abs(2 * hsl.z - 1)) * hsl.y;"
94 "half3 p = hsl.xxx + half3(0, 2/3.0, 1/3.0);"
95 "half3 q = saturate(abs(fract(p) * 6 - 3) - 1);"
96 "return (q - 0.5) * C + hsl.z;"
100 * Runtime effects are often long lived & cached. Individual color filters or FPs created from them
101 * and are often short-lived. However, color filters and FPs may need to operate on a single color
102 * (on the CPU). This may be done at the paint level (eg, filter the paint color), or as part of
105 * SkFilterColorProgram is an skvm program representing a (color filter) SkRuntimeEffect. It can
106 * process a single color, without knowing the details of a particular instance (uniform values or
109 class SkFilterColorProgram {
111 static std::unique_ptr<SkFilterColorProgram> Make(const SkRuntimeEffect* effect);
113 SkPMColor4f eval(const SkPMColor4f& inColor,
114 const void* uniformData,
115 std::function<SkPMColor4f(int, SkPMColor4f)> evalChild) const;
117 bool isAlphaUnchanged() const { return fAlphaUnchanged; }
122 kInputColor, // eg child.eval(inputColor)
123 kImmediate, // eg child.eval(half4(1))
124 kPrevious, // eg child1.eval(child2.eval(...))
125 kUniform, // eg uniform half4 color; ... child.eval(color)
131 SkPMColor4f fImm; // for kImmediate
132 int fPrevious; // for kPrevious
133 int fOffset; // for kUniform
137 SkFilterColorProgram(skvm::Program program,
138 std::vector<SampleCall> sampleCalls,
139 bool alphaUnchanged);
141 skvm::Program fProgram;
142 std::vector<SampleCall> fSampleCalls;
143 bool fAlphaUnchanged;
146 #endif // SK_ENABLE_SKSL
148 #endif // SkRuntimeEffectPriv_DEFINED