Coverage Report

Created: 2024-09-14 07:19

/src/skia/src/core/SkKnownRuntimeEffects.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2024 Google LLC
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 "src/core/SkKnownRuntimeEffects.h"
9
10
#include "include/core/SkString.h"
11
#include "include/effects/SkRuntimeEffect.h"
12
#include "src/core/SkRuntimeEffectPriv.h"
13
#include "src/effects/imagefilters/SkMatrixConvolutionImageFilter.h"
14
15
namespace SkKnownRuntimeEffects {
16
17
namespace {
18
19
// This must be kept in sync w/ the version in BlurUtils.h
20
static constexpr int kMaxBlurSamples = 28;
21
22
12
SkRuntimeEffect* make_blur_1D_effect(int kernelWidth, const SkRuntimeEffect::Options& options) {
23
12
    SkASSERT(kernelWidth <= kMaxBlurSamples);
24
    // The SkSL structure performs two kernel taps; if the kernel has an odd width the last
25
    // sample will be skipped with the current loop limit calculation.
26
12
    SkASSERT(kernelWidth % 2 == 0);
27
12
    return SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader,
28
12
            SkStringPrintf(
29
                    // The coefficients are always stored for the max radius to keep the
30
                    // uniform block consistent across all effects.
31
12
                    "const int kMaxUniformKernelSize = %d / 2;"
32
                    // But we generate an exact loop over the kernel size. Note that this
33
                    // program can be used for kernels smaller than the constructed max as long
34
                    // as the kernel weights for excess entries are set to 0.
35
12
                    "const int kMaxLoopLimit = %d / 2;"
36
37
12
                    "uniform half4 offsetsAndKernel[kMaxUniformKernelSize];"
38
12
                    "uniform half2 dir;"
39
40
12
                    "uniform shader child;"
41
42
12
                    "half4 main(float2 coord) {"
43
12
                        "half4 sum = half4(0);"
44
12
                        "for (int i = 0; i < kMaxLoopLimit; ++i) {"
45
12
                            "half4 s = offsetsAndKernel[i];"
46
12
                            "sum += s.y * child.eval(coord + s.x*dir);"
47
12
                            "sum += s.w * child.eval(coord + s.z*dir);"
48
12
                        "}"
49
12
                        "return sum;"
50
12
                    "}", kMaxBlurSamples, kernelWidth).c_str(),
51
12
                    options);
52
12
}
53
54
13
SkRuntimeEffect* make_blur_2D_effect(int maxKernelSize, const SkRuntimeEffect::Options& options) {
55
13
    SkASSERT(maxKernelSize % 4 == 0);
56
13
    return SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader,
57
13
            SkStringPrintf(
58
                    // The coefficients are always stored for the max radius to keep the
59
                    // uniform block consistent across all effects.
60
13
                    "const int kMaxUniformKernelSize = %d / 4;"
61
13
                    "const int kMaxUniformOffsetsSize = 2*kMaxUniformKernelSize;"
62
                    // But we generate an exact loop over the kernel size. Note that this
63
                    // program can be used for kernels smaller than the constructed max as long
64
                    // as the kernel weights for excess entries are set to 0.
65
13
                    "const int kMaxLoopLimit = %d / 4;"
66
67
                    // Pack scalar coefficients into half4 for better packing on std140, and
68
                    // upload offsets to avoid having to transform the 1D index into a 2D coord
69
13
                    "uniform half4 kernel[kMaxUniformKernelSize];"
70
13
                    "uniform half4 offsets[kMaxUniformOffsetsSize];"
71
72
13
                    "uniform shader child;"
73
74
13
                    "half4 main(float2 coord) {"
75
13
                        "half4 sum = half4(0);"
76
77
13
                        "for (int i = 0; i < kMaxLoopLimit; ++i) {"
78
13
                            "half4 k = kernel[i];"
79
13
                            "half4 o = offsets[2*i];"
80
13
                            "sum += k.x * child.eval(coord + o.xy);"
81
13
                            "sum += k.y * child.eval(coord + o.zw);"
82
13
                            "o = offsets[2*i + 1];"
83
13
                            "sum += k.z * child.eval(coord + o.xy);"
84
13
                            "sum += k.w * child.eval(coord + o.zw);"
85
13
                        "}"
86
13
                        "return sum;"
87
13
                    "}", kMaxBlurSamples, maxKernelSize).c_str(),
88
13
                    options);
89
13
}
90
91
enum class MatrixConvolutionImpl {
92
    kUniformBased,
93
    kTextureBasedSm,
94
    kTextureBasedLg,
95
};
96
97
// There are three shader variants:
98
//    a smaller kernel version that stores the matrix in uniforms and iterates in 1D
99
//    a larger kernel version that stores the matrix in a 1D texture. The texture version has small
100
//    and large variants w/ the actual kernel size uploaded as a uniform.
101
SkRuntimeEffect* make_matrix_conv_effect(MatrixConvolutionImpl impl,
102
6
                                         const SkRuntimeEffect::Options& options) {
103
    // While the uniforms and kernel access are different, pieces of the algorithm are common and
104
    // defined statically for re-use in the two shaders:
105
6
    static const char* kHeaderAndBeginLoopSkSL =
106
6
        "uniform int2 size;"
107
6
        "uniform int2 offset;"
108
6
        "uniform half2 gainAndBias;"
109
6
        "uniform int convolveAlpha;" // FIXME not a full  int? Put in a half3 w/ gainAndBias?
110
111
6
        "uniform shader child;"
112
113
6
        "half4 main(float2 coord) {"
114
6
            "half4 sum = half4(0);"
115
6
            "half origAlpha = 0;"
116
6
            "int2 kernelPos = int2(0);"
117
6
            "for (int i = 0; i < kMaxKernelSize; ++i) {"
118
6
                "if (kernelPos.y >= size.y) { break; }";
119
120
    // Used in the inner loop to accumulate convolution sum and increment the kernel position
121
6
    static const char* kAccumulateAndIncrementSkSL =
122
6
                "half4 c = child.eval(coord + half2(kernelPos) - half2(offset));"
123
6
                "if (convolveAlpha == 0) {"
124
                    // When not convolving alpha, remember the original alpha for actual sample
125
                    // coord, and perform accumulation on unpremul colors.
126
6
                    "if (kernelPos == offset) {"
127
6
                        "origAlpha = c.a;"
128
6
                    "}"
129
6
                    "c = unpremul(c);"
130
6
                "}"
131
6
                "sum += c*k;"
132
6
                "kernelPos.x += 1;"
133
6
                "if (kernelPos.x >= size.x) {"
134
6
                    "kernelPos.x = 0;"
135
6
                    "kernelPos.y += 1;"
136
6
                "}";
137
138
    // Closes the loop and calculates final color
139
6
    static const char* kCloseLoopAndFooterSkSL =
140
6
            "}"
141
6
            "half4 color = sum*gainAndBias.x + gainAndBias.y;"
142
6
            "if (convolveAlpha == 0) {"
143
                // Reset the alpha to the original and convert to premul RGB
144
6
                "color = half4(color.rgb*origAlpha, origAlpha);"
145
6
            "} else {"
146
                // Ensure convolved alpha is within [0, 1]
147
6
                "color.a = saturate(color.a);"
148
6
            "}"
149
            // Make RGB valid premul w/ respect to the alpha (either original or convolved)
150
6
            "color.rgb = clamp(color.rgb, 0, color.a);"
151
6
            "return color;"
152
6
        "}";
153
154
6
    static const auto makeTextureEffect = [](int maxTextureKernelSize,
155
6
                                             const SkRuntimeEffect::Options& options) {
156
1
        return SkMakeRuntimeEffect(
157
1
                        SkRuntimeEffect::MakeForShader,
158
1
                        SkStringPrintf("const int kMaxKernelSize = %d;"
159
1
                                       "uniform shader kernel;"
160
1
                                       "uniform half2 innerGainAndBias;"
161
1
                                       "%s" // kHeaderAndBeginLoopSkSL
162
1
                                               "half k = kernel.eval(half2(half(i) + 0.5, 0.5)).a;"
163
1
                                               "k = k * innerGainAndBias.x + innerGainAndBias.y;"
164
1
                                               "%s" // kAccumulateAndIncrementSkSL
165
1
                                       "%s", // kCloseLoopAndFooterSkSL
166
1
                                       maxTextureKernelSize,
167
1
                                       kHeaderAndBeginLoopSkSL,
168
1
                                       kAccumulateAndIncrementSkSL,
169
1
                                       kCloseLoopAndFooterSkSL).c_str(),
170
1
                        options);
171
1
    };
172
173
6
    switch (impl) {
174
5
        case MatrixConvolutionImpl::kUniformBased: {
175
5
            return SkMakeRuntimeEffect(
176
5
                        SkRuntimeEffect::MakeForShader,
177
5
                        SkStringPrintf("const int kMaxKernelSize = %d / 4;"
178
5
                                       "uniform half4 kernel[kMaxKernelSize];"
179
5
                                       "%s" // kHeaderAndBeginLoopSkSL
180
5
                                                "half4 k4 = kernel[i];"
181
5
                                                "for (int j = 0; j < 4; ++j) {"
182
5
                                                    "if (kernelPos.y >= size.y) { break; }"
183
5
                                                    "half k = k4[j];"
184
5
                                                    "%s" // kAccumulateAndIncrementSkSL
185
5
                                                "}"
186
5
                                       "%s", // kCloseLoopAndFooterSkSL
187
5
                                       MatrixConvolutionImageFilter::kMaxUniformKernelSize,
188
5
                                       kHeaderAndBeginLoopSkSL,
189
5
                                       kAccumulateAndIncrementSkSL,
190
5
                                       kCloseLoopAndFooterSkSL).c_str(),
191
5
                        options);
192
0
        }
193
0
        case MatrixConvolutionImpl::kTextureBasedSm:
194
0
            return makeTextureEffect(MatrixConvolutionImageFilter::kSmallKernelSize, options);
195
1
        case MatrixConvolutionImpl::kTextureBasedLg:
196
1
            return makeTextureEffect(MatrixConvolutionImageFilter::kLargeKernelSize, options);
197
6
    }
198
199
6
    SkUNREACHABLE;
200
6
}
201
202
} // anonymous namespace
203
204
65.8k
const SkRuntimeEffect* GetKnownRuntimeEffect(StableKey stableKey) {
205
65.8k
    SkRuntimeEffect::Options options;
206
65.8k
    SkRuntimeEffectPriv::SetStableKey(&options, static_cast<uint32_t>(stableKey));
207
65.8k
    SkRuntimeEffectPriv::AllowPrivateAccess(&options);
208
209
65.8k
    switch (stableKey) {
210
0
        case StableKey::kInvalid:
211
0
            return nullptr;
212
213
        // Shaders
214
647
        case StableKey::k1DBlur4: {
215
647
            static SkRuntimeEffect* s1DBlurEffect = make_blur_1D_effect(4, options);
216
647
            return s1DBlurEffect;
217
0
        }
218
1.10k
        case StableKey::k1DBlur8: {
219
1.10k
            static SkRuntimeEffect* s1DBlurEffect = make_blur_1D_effect(8, options);
220
1.10k
            return s1DBlurEffect;
221
0
        }
222
393
        case StableKey::k1DBlur12: {
223
393
            static SkRuntimeEffect* s1DBlurEffect = make_blur_1D_effect(12, options);
224
393
            return s1DBlurEffect;
225
0
        }
226
16.5k
        case StableKey::k1DBlur16: {
227
16.5k
            static SkRuntimeEffect* s1DBlurEffect = make_blur_1D_effect(16, options);
228
16.5k
            return s1DBlurEffect;
229
0
        }
230
0
        case StableKey::k1DBlur20: {
231
0
            static SkRuntimeEffect* s1DBlurEffect = make_blur_1D_effect(20, options);
232
0
            return s1DBlurEffect;
233
0
        }
234
0
        case StableKey::k1DBlur28: {
235
0
            static SkRuntimeEffect* s1DBlurEffect = make_blur_1D_effect(28, options);
236
0
            return s1DBlurEffect;
237
0
        }
238
0
        case StableKey::k2DBlur4: {
239
0
            static SkRuntimeEffect* s2DBlurEffect = make_blur_2D_effect(4, options);
240
0
            return s2DBlurEffect;
241
0
        }
242
0
        case StableKey::k2DBlur8: {
243
0
            static SkRuntimeEffect* s2DBlurEffect = make_blur_2D_effect(8, options);
244
0
            return s2DBlurEffect;
245
0
        }
246
282
        case StableKey::k2DBlur12: {
247
282
            static SkRuntimeEffect* s2DBlurEffect = make_blur_2D_effect(12, options);
248
282
            return s2DBlurEffect;
249
0
        }
250
20
        case StableKey::k2DBlur16: {
251
20
            static SkRuntimeEffect* s2DBlurEffect = make_blur_2D_effect(16, options);
252
20
            return s2DBlurEffect;
253
0
        }
254
0
        case StableKey::k2DBlur20: {
255
0
            static SkRuntimeEffect* s2DBlurEffect = make_blur_2D_effect(20, options);
256
0
            return s2DBlurEffect;
257
0
        }
258
87
        case StableKey::k2DBlur28: {
259
87
            static SkRuntimeEffect* s2DBlurEffect = make_blur_2D_effect(28, options);
260
87
            return s2DBlurEffect;
261
0
        }
262
1.27k
        case StableKey::kBlend: {
263
1.27k
            static constexpr char kBlendShaderCode[] =
264
1.27k
                "uniform shader s, d;"
265
1.27k
                "uniform blender b;"
266
1.27k
                "half4 main(float2 xy) {"
267
1.27k
                    "return b.eval(s.eval(xy), d.eval(xy));"
268
1.27k
                "}";
269
270
1.27k
            static const SkRuntimeEffect* sBlendEffect =
271
1.27k
                    SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader,
272
1.27k
                                        kBlendShaderCode,
273
1.27k
                                        options);
274
1.27k
            return sBlendEffect;
275
0
        }
276
7.23k
        case StableKey::kLerp: {
277
7.23k
            static constexpr char kLerpFilterCode[] =
278
7.23k
                "uniform colorFilter cf0;"
279
7.23k
                "uniform colorFilter cf1;"
280
7.23k
                "uniform half weight;"
281
282
7.23k
                "half4 main(half4 color) {"
283
7.23k
                    "return mix(cf0.eval(color), cf1.eval(color), weight);"
284
7.23k
                "}";
285
286
7.23k
            static const SkRuntimeEffect* sLerpEffect =
287
7.23k
                    SkMakeRuntimeEffect(SkRuntimeEffect::MakeForColorFilter,
288
7.23k
                                        kLerpFilterCode,
289
7.23k
                                        options);
290
7.23k
            return sLerpEffect;
291
0
        }
292
2.61k
        case StableKey::kMatrixConvUniforms: {
293
2.61k
            static const SkRuntimeEffect* sMatrixConvUniformsEffect =
294
2.61k
                    make_matrix_conv_effect(MatrixConvolutionImpl::kUniformBased, options);
295
2.61k
            return sMatrixConvUniformsEffect;
296
0
        }
297
298
0
        case StableKey::kMatrixConvTexSm: {
299
0
            static const SkRuntimeEffect* sMatrixConvTexSmEffect =
300
0
                    make_matrix_conv_effect(MatrixConvolutionImpl::kTextureBasedSm, options);
301
0
            return sMatrixConvTexSmEffect;
302
0
        }
303
304
24
        case StableKey::kMatrixConvTexLg: {
305
24
            static const SkRuntimeEffect* sMatrixConvTexMaxEffect =
306
24
                    make_matrix_conv_effect(MatrixConvolutionImpl::kTextureBasedLg, options);
307
24
            return sMatrixConvTexMaxEffect;
308
0
        }
309
1.28k
        case StableKey::kDecal: {
310
1.28k
            static constexpr char kDecalShaderCode[] =
311
1.28k
                "uniform shader image;"
312
1.28k
                "uniform float4 decalBounds;"
313
314
1.28k
                "half4 main(float2 coord) {"
315
1.28k
                    "return sk_decal(image, coord, decalBounds);"
316
1.28k
                "}";
317
318
1.28k
            static const SkRuntimeEffect* sDecalEffect =
319
1.28k
                    SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader,
320
1.28k
                                        kDecalShaderCode,
321
1.28k
                                        options);
322
1.28k
            return sDecalEffect;
323
0
        }
324
4.49k
        case StableKey::kDisplacement: {
325
            // NOTE: This uses dot product selection to work on all GLES2 hardware (enforced by
326
            // public runtime effect restrictions). Otherwise, this would use a "uniform ivec2"
327
            // and component indexing to convert the displacement color into a vector.
328
4.49k
            static constexpr char kDisplacementShaderCode[] =
329
4.49k
                "uniform shader displMap;"
330
4.49k
                "uniform shader colorMap;"
331
4.49k
                "uniform half2 scale;"
332
4.49k
                "uniform half4 xSelect;" // Only one of RGBA will be 1, the rest are 0
333
4.49k
                "uniform half4 ySelect;"
334
335
4.49k
                "half4 main(float2 coord) {"
336
4.49k
                    "return sk_displacement(displMap, colorMap, coord, scale, xSelect, ySelect);"
337
4.49k
                "}";
338
339
4.49k
            static const SkRuntimeEffect* sDisplacementEffect =
340
4.49k
                    SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader,
341
4.49k
                                        kDisplacementShaderCode,
342
4.49k
                                        options);
343
4.49k
            return sDisplacementEffect;
344
0
        }
345
2.92k
        case StableKey::kLighting: {
346
2.92k
            static constexpr char kLightingShaderCode[] =
347
2.92k
                "uniform shader normalMap;"
348
349
                // Packs surface depth, shininess, material type (0 == diffuse) and light type
350
                // (< 0 = distant, 0 = point, > 0 = spot)
351
2.92k
                "uniform half4 materialAndLightType;"
352
353
2.92k
                "uniform half4 lightPosAndSpotFalloff;" // (x,y,z) are lightPos, w is spot falloff
354
                                                        // exponent
355
2.92k
                "uniform half4 lightDirAndSpotCutoff;" // (x,y,z) are lightDir,
356
                                                       // w is spot cos(cutoffAngle)
357
2.92k
                "uniform half3 lightColor;" // Material's k has already been multiplied in
358
359
2.92k
                "half4 main(float2 coord) {"
360
2.92k
                    "return sk_lighting(normalMap, coord,"
361
2.92k
                                        /*depth=*/"materialAndLightType.x,"
362
2.92k
                                        /*shininess=*/"materialAndLightType.y,"
363
2.92k
                                        /*materialType=*/"materialAndLightType.z,"
364
2.92k
                                        /*lightType=*/"materialAndLightType.w,"
365
2.92k
                                        /*lightPos=*/"lightPosAndSpotFalloff.xyz,"
366
2.92k
                                        /*spotFalloff=*/"lightPosAndSpotFalloff.w,"
367
2.92k
                                        /*lightDir=*/"lightDirAndSpotCutoff.xyz,"
368
2.92k
                                        /*cosCutoffAngle=*/"lightDirAndSpotCutoff.w,"
369
2.92k
                                        "lightColor);"
370
2.92k
                "}";
371
372
2.92k
            static const SkRuntimeEffect* sLightingEffect =
373
2.92k
                    SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader,
374
2.92k
                                        kLightingShaderCode,
375
2.92k
                                        options);
376
2.92k
            return sLightingEffect;
377
0
        }
378
3.00k
        case StableKey::kLinearMorphology: {
379
3.00k
            static constexpr char kLinearMorphologyShaderCode[] =
380
3.00k
                "uniform shader child;"
381
3.00k
                "uniform half2 offset;"
382
3.00k
                "uniform half flip;" // -1 converts the max() calls to min()
383
3.00k
                "uniform int radius;"
384
385
3.00k
                "half4 main(float2 coord) {"
386
3.00k
                    "return sk_linear_morphology(child, coord, offset, flip, radius);"
387
3.00k
                "}";
388
389
3.00k
            static const SkRuntimeEffect* sLinearMorphologyEffect =
390
3.00k
                    SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader,
391
3.00k
                                        kLinearMorphologyShaderCode,
392
3.00k
                                        options);
393
3.00k
            return sLinearMorphologyEffect;
394
0
        }
395
396
223
        case StableKey::kMagnifier: {
397
223
            static constexpr char kMagnifierShaderCode[] =
398
223
                "uniform shader src;"
399
223
                "uniform float4 lensBounds;"
400
223
                "uniform float4 zoomXform;"
401
223
                "uniform float2 invInset;"
402
403
223
                "half4 main(float2 coord) {"
404
223
                    "return sk_magnifier(src, coord, lensBounds, zoomXform, invInset);"
405
223
                "}";
406
407
223
            static const SkRuntimeEffect* sMagnifierEffect =
408
223
                    SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader,
409
223
                                        kMagnifierShaderCode,
410
223
                                        options);
411
223
            return sMagnifierEffect;
412
0
        }
413
2.92k
        case StableKey::kNormal: {
414
2.92k
            static constexpr char kNormalShaderCode[] =
415
2.92k
                "uniform shader alphaMap;"
416
2.92k
                "uniform float4 edgeBounds;"
417
2.92k
                "uniform half negSurfaceDepth;"
418
419
2.92k
                "half4 main(float2 coord) {"
420
2.92k
                   "return sk_normal(alphaMap, coord, edgeBounds, negSurfaceDepth);"
421
2.92k
                "}";
422
423
2.92k
            static const SkRuntimeEffect* sNormalEffect =
424
2.92k
                    SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader,
425
2.92k
                                        kNormalShaderCode,
426
2.92k
                                        options);
427
2.92k
            return sNormalEffect;
428
0
        }
429
8.76k
        case StableKey::kSparseMorphology: {
430
8.76k
            static constexpr char kSparseMorphologyShaderCode[] =
431
8.76k
                "uniform shader child;"
432
8.76k
                "uniform half2 offset;"
433
8.76k
                "uniform half flip;"
434
435
8.76k
                "half4 main(float2 coord) {"
436
8.76k
                    "return sk_sparse_morphology(child, coord, offset, flip);"
437
8.76k
                "}";
438
439
8.76k
            static const SkRuntimeEffect* sSparseMorphologyEffect =
440
8.76k
                    SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader,
441
8.76k
                                        kSparseMorphologyShaderCode,
442
8.76k
                                        options);
443
8.76k
            return sSparseMorphologyEffect;
444
0
        }
445
446
        // Blenders
447
2.49k
        case StableKey::kArithmetic: {
448
2.49k
            static constexpr char kArithmeticBlenderCode[] =
449
2.49k
                "uniform half4 k;"
450
2.49k
                "uniform half pmClamp;"
451
452
2.49k
                "half4 main(half4 src, half4 dst) {"
453
2.49k
                    "return sk_arithmetic_blend(src, dst, k, pmClamp);"
454
2.49k
                "}";
455
456
2.49k
            static const SkRuntimeEffect* sArithmeticEffect =
457
2.49k
                    SkMakeRuntimeEffect(SkRuntimeEffect::MakeForBlender,
458
2.49k
                                        kArithmeticBlenderCode,
459
2.49k
                                        options);
460
2.49k
            return sArithmeticEffect;
461
0
        }
462
463
        // Color Filters
464
2.62k
        case StableKey::kHighContrast: {
465
2.62k
            static constexpr char kHighContrastFilterCode[] =
466
2.62k
                "uniform half grayscale, invertStyle, contrast;"
467
2.62k
                "half4 main(half4 color) {"
468
2.62k
                    "return half4(sk_high_contrast(color.rgb, grayscale, invertStyle, contrast),"
469
2.62k
                                 "color.a);"
470
2.62k
                "}";
471
472
2.62k
            static const SkRuntimeEffect* sHighContrastEffect =
473
2.62k
                    SkMakeRuntimeEffect(SkRuntimeEffect::MakeForColorFilter,
474
2.62k
                                        kHighContrastFilterCode,
475
2.62k
                                        options);
476
2.62k
            return sHighContrastEffect;
477
0
        }
478
479
6.81k
        case StableKey::kLuma: {
480
6.81k
            static constexpr char kLumaFilterCode[] =
481
6.81k
                "half4 main(half4 color) {"
482
6.81k
                    "return sk_luma(color.rgb);"
483
6.81k
                "}";
484
485
6.81k
            static const SkRuntimeEffect* sLumaEffect =
486
6.81k
                    SkMakeRuntimeEffect(SkRuntimeEffect::MakeForColorFilter,
487
6.81k
                                        kLumaFilterCode,
488
6.81k
                                        options);
489
6.81k
            return sLumaEffect;
490
0
        }
491
492
0
        case StableKey::kOverdraw: {
493
0
            static constexpr char kOverdrawFilterCode[] =
494
0
                "uniform half4 color0, color1, color2, color3, color4, color5;"
495
496
0
                "half4 main(half4 color) {"
497
0
                    "return sk_overdraw(color.a, color0, color1, color2, color3, color4, color5);"
498
0
                "}";
499
500
0
            static const SkRuntimeEffect* sOverdrawEffect =
501
0
                    SkMakeRuntimeEffect(SkRuntimeEffect::MakeForColorFilter,
502
0
                                        kOverdrawFilterCode,
503
0
                                        options);
504
0
            return sOverdrawEffect;
505
0
        }
506
65.8k
    }
507
508
0
    SkUNREACHABLE;
509
65.8k
}
510
511
} // namespace SkKnownRuntimeEffects