• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <unordered_map>
17 #include <string>
18 
19 static std::unordered_map<std::string, std::string> extModuleData = {
20     {"sksl_frag.sksl", R"(
21 // defines built-in interfaces supported by SkiaSL fragment shaders
22 
23 // See "enum SpvBuiltIn_" in ./spirv.h
24 layout(builtin=15) in float4 sk_FragCoord;
25 layout(builtin=17) in bool sk_Clockwise;  // Similar to gl_FrontFacing, but defined in device space.
26 
27 layout(location=0,index=0,builtin=10001) out half4 sk_FragColor;
28 layout(builtin=10008) half4 sk_LastFragColor;
29 layout(builtin=10012) out half4 sk_SecondaryFragColor;
30 )"},
31     {"sksl_vert.sksl", R"(
32 // defines built-in interfaces supported by SkiaSL vertex shaders
33 
34 out sk_PerVertex {
35     layout(builtin=0) float4 sk_Position;
36     layout(builtin=1) float sk_PointSize;
37 };
38 
39 layout(builtin=42) in int sk_VertexID;
40 layout(builtin=43) in int sk_InstanceID;
41 )"},
42     {"sksl_gpu.sksl", R"(
43 // defines built-in functions supported by SkSL when running on a GPU
44 
45 $genType radians($genType degrees);
46 $genType degrees($genType radians);
47 $genType sin($genType angle);
48 $genType cos($genType angle);
49 $genType tan($genType angle);
50 $genType asin($genType x);
51 $genType acos($genType x);
52 $genType atan($genType y, $genType x);
53 $genType atan($genType y_over_x);
54 $genType sinh($genType x);
55 $genType cosh($genType x);
56 $genType tanh($genType x);
57 $genType asinh($genType x);
58 $genType acosh($genType x);
59 $genType atanh($genType x);
60 $genType pow($genType x, $genType y);
61 $genType exp($genType x);
62 $genType log($genType x);
63 $genType exp2($genType x);
64 $genType log2($genType x);
65 $genType sqrt($genType x);
66 $genHType radians($genHType degrees);
67 $genHType degrees($genHType radians);
68 $genHType sin($genHType angle);
69 $genHType cos($genHType angle);
70 $genHType tan($genHType angle);
71 $genHType asin($genHType x);
72 $genHType acos($genHType x);
73 $genHType atan($genHType y, $genHType x);
74 $genHType atan($genHType y_over_x);
75 $genHType sinh($genHType x);
76 $genHType cosh($genHType x);
77 $genHType tanh($genHType x);
78 $genHType asinh($genHType x);
79 $genHType acosh($genHType x);
80 $genHType atanh($genHType x);
81 $genHType pow($genHType x, $genHType y);
82 $genHType exp($genHType x);
83 $genHType log($genHType x);
84 $genHType exp2($genHType x);
85 $genHType log2($genHType x);
86 $genHType sqrt($genHType x);
87 $genType inversesqrt($genType x);
88 $genHType inversesqrt($genHType x);
89 $genType abs($genType x);
90 $genHType abs($genHType x);
91 $genIType abs($genIType x);
92 $genType sign($genType x);
93 $genHType sign($genHType x);
94 $genIType sign($genIType x);
95 $genType floor($genType x);
96 $genHType floor($genHType x);
97 $genType trunc($genType x);
98 $genHType trunc($genHType x);
99 $genType round($genType x);
100 $genHType round($genHType x);
101 $genType roundEven($genType x);
102 $genHType roundEven($genHType x);
103 $genType ceil($genType x);
104 $genHType ceil($genHType x);
105 $genType fract($genType x);
106 $genHType fract($genHType x);
107 $genType mod($genType x, float y);
108 $genType mod($genType x, $genType y);
109 $genHType mod($genHType x, half y);
110 $genHType mod($genHType x, $genHType y);
111 $genType modf($genType x, out $genType i);
112 $genHType modf($genHType x, out $genHType i);
113 $genType min($genType x, $genType y);
114 $genType min($genType x, float y);
115 $genHType min($genHType x, $genHType y);
116 $genHType min($genHType x, half y);
117 $genIType min($genIType x, $genIType y);
118 $genIType min($genIType x, int y);
119 $genType max($genType x, $genType y);
120 $genType max($genType x, float y);
121 $genHType max($genHType x, $genHType y);
122 $genHType max($genHType x, half y);
123 $genIType max($genIType x, $genIType y);
124 $genIType max($genIType x, int y);
125 $genType clamp($genType x, $genType minVal, $genType maxVal);
126 $genType clamp($genType x, float minVal, float maxVal);
127 $genHType clamp($genHType x, $genHType minVal, $genHType maxVal);
128 $genHType clamp($genHType x, half minVal, half maxVal);
129 $genIType clamp($genIType x, $genIType minVal, $genIType maxVal);
130 $genIType clamp($genIType x, int minVal, int maxVal);
131 $genUType clamp($genUType x, $genUType minVal, $genUType maxVal);
132 $genUType clamp($genUType x, uint minVal, uint maxVal);
133 $genType saturate($genType x);
134 $genHType saturate($genHType x);
135 $genType mix($genType x, $genType y, $genType a);
136 $genType mix($genType x, $genType y, float a);
137 $genHType mix($genHType x, $genHType y, $genHType a);
138 $genHType mix($genHType x, $genHType y, half a);
139 $genType mix($genType x, $genType y, $genBType a);
140 $genHType mix($genHType x, $genHType y, $genBType a);
141 $genIType mix($genIType x, $genIType y, $genBType a);
142 $genBType mix($genBType x, $genBType y, $genBType a);
143 $genType step($genType edge, $genType x);
144 $genType step(float edge, $genType x);
145 $genHType step($genHType edge, $genHType x);
146 $genHType step(half edge, $genHType x);
147 $genType smoothstep($genType edge0, $genType edge1, $genType x);
148 $genType smoothstep(float edge0, float edge1, $genType x);
149 $genHType smoothstep($genHType edge0, $genHType edge1, $genHType x);
150 $genHType smoothstep(half edge0, half edge1, $genHType x);
151 $genBType isnan($genType x);
152 $genBType isinf($genType x);
153 $genIType floatBitsToInt($genType value);
154 $genUType floatBitsToUint($genType value);
155 $genType intBitsToFloat($genIType value);
156 $genType uintBitsToFloat($genUType value);
157 $genType fma($genType a, $genType b, $genType c);
158 $genHType fma($genHType a, $genHType b, $genHType c);
159 sk_has_side_effects $genType frexp($genType x, out $genIType exp);
160 sk_has_side_effects $genHType frexp($genHType x, out $genIType exp);
161 $genType ldexp($genType x, in $genIType exp);
162 $genHType ldexp($genHType x, in $genIType exp);
163 uint packUnorm2x16(float2 v);
164 uint packSnorm2x16(float2 v);
165 uint packUnorm4x8(float4 v);
166 uint packSnorm4x8(float4 v);
167 float2 unpackUnorm2x16(uint p);
168 float2 unpackSnorm2x16(uint p);
169 float4 unpackUnorm4x8(uint p);
170 float4 unpackSnorm4x8(uint p);
171 uint packHalf2x16(float2 v);
172 float2 unpackHalf2x16(uint v);
173 float length($genType x);
174 half length($genHType x);
175 float distance($genType p0, $genType p1);
176 half distance($genHType p0, $genHType p1);
177 float dot($genType x, $genType y);
178 half dot($genHType x, $genHType y);
179 float3 cross(float3 x, float3 y);
180 half3 cross(half3 x, half3 y);
181 $genType normalize($genType x);
182 $genHType normalize($genHType x);
183 $genType faceforward($genType N, $genType I, $genType Nref);
184 $genHType faceforward($genHType N, $genHType I, $genHType Nref);
185 $genType reflect($genType I, $genType N);
186 $genHType reflect($genHType I, $genHType N);
187 $genType refract($genType I, $genType N, float eta);
188 $genHType refract($genHType I, $genHType N, half eta);
189 $mat matrixCompMult($mat x, $mat y);
190 $hmat matrixCompMult($hmat x, $hmat y);
191 $squareMat outerProduct($vec c, $vec r);
192 float2x3 outerProduct(float3 c, float2 r);
193 float3x2 outerProduct(float2 c, float3 r);
194 float2x4 outerProduct(float4 c, float2 r);
195 float4x2 outerProduct(float2 c, float4 r);
196 float3x4 outerProduct(float4 c, float3 r);
197 float4x3 outerProduct(float3 c, float4 r);
198 $squareHMat outerProduct($hvec c, $hvec r);
199 half2x3 outerProduct(half3 c, half2 r);
200 half3x2 outerProduct(half2 c, half3 r);
201 half2x4 outerProduct(half4 c, half2 r);
202 half4x2 outerProduct(half2 c, half4 r);
203 half3x4 outerProduct(half4 c, half3 r);
204 half4x3 outerProduct(half3 c, half4 r);
205 $squareMat transpose($squareMat m);
206 float2x3 transpose(float3x2 m);
207 float3x2 transpose(float2x3 m);
208 float2x4 transpose(float4x2 m);
209 float4x2 transpose(float2x4 m);
210 float3x4 transpose(float4x3 m);
211 float4x3 transpose(float3x4 m);
212 $squareHMat transpose($squareHMat m);
213 half2x3 transpose(half3x2 m);
214 half3x2 transpose(half2x3 m);
215 half2x4 transpose(half4x2 m);
216 half4x2 transpose(half2x4 m);
217 half3x4 transpose(half4x3 m);
218 half4x3 transpose(half3x4 m);
219 float determinant($squareMat m);
220 half determinant($squareHMat m);
221 $squareMat inverse($squareMat m);
222 $squareHMat inverse($squareHMat m);
223 $bvec lessThan($vec x, $vec y);
224 $bvec lessThan($hvec x, $hvec y);
225 $bvec lessThan($ivec x, $ivec y);
226 $bvec lessThan($svec x, $svec y);
227 $bvec lessThan($usvec x, $usvec y);
228 $bvec lessThan($uvec x, $uvec y);
229 $bvec lessThanEqual($vec x, $vec y);
230 $bvec lessThanEqual($hvec x, $hvec y);
231 $bvec lessThanEqual($ivec x, $ivec y);
232 $bvec lessThanEqual($uvec x, $uvec y);
233 $bvec lessThanEqual($svec x, $svec y);
234 $bvec lessThanEqual($usvec x, $usvec y);
235 $bvec greaterThan($vec x, $vec y);
236 $bvec greaterThan($hvec x, $hvec y);
237 $bvec greaterThan($ivec x, $ivec y);
238 $bvec greaterThan($uvec x, $uvec y);
239 $bvec greaterThan($svec x, $svec y);
240 $bvec greaterThan($usvec x, $usvec y);
241 $bvec greaterThanEqual($vec x, $vec y);
242 $bvec greaterThanEqual($hvec x, $hvec y);
243 $bvec greaterThanEqual($ivec x, $ivec y);
244 $bvec greaterThanEqual($uvec x, $uvec y);
245 $bvec greaterThanEqual($svec x, $svec y);
246 $bvec greaterThanEqual($usvec x, $usvec y);
247 $bvec equal($vec x, $vec y);
248 $bvec equal($hvec x, $hvec y);
249 $bvec equal($ivec x, $ivec y);
250 $bvec equal($uvec x, $uvec y);
251 $bvec equal($svec x, $svec y);
252 $bvec equal($usvec x, $usvec y);
253 $bvec equal($bvec x, $bvec y);
254 $bvec notEqual($vec x, $vec y);
255 $bvec notEqual($hvec x, $hvec y);
256 $bvec notEqual($ivec x, $ivec y);
257 $bvec notEqual($uvec x, $uvec y);
258 $bvec notEqual($svec x, $svec y);
259 $bvec notEqual($usvec x, $usvec y);
260 $bvec notEqual($bvec x, $bvec y);
261 bool any($bvec x);
262 bool all($bvec x);
263 $bvec not($bvec x);
264 
265 $genIType bitCount($genIType value);
266 $genIType bitCount($genUType value);
267 $genIType findLSB($genIType value);
268 $genIType findLSB($genUType value);
269 $genIType findMSB($genIType value);
270 $genIType findMSB($genUType value);
271 
272 sampler2D makeSampler2D(texture2D texture, sampler s);
273 int2 textureSize(sampler2DRect s);
274 
275 half4 sample(sampler1D s, float P);
276 half4 sample(sampler1D s, float P, float bias);
277 half4 sample(sampler2D s, float2 P);
278 int4 sample(isampler2D s, float2 P);
279 half4 sample(samplerExternalOES s, float2 P, float bias);
280 half4 sample(samplerExternalOES s, float2 P);
281 
282 half4 sample(sampler2DRect s, float2 P);
283 half4 sample(sampler2DRect s, float3 P);
284 
285 // Currently we do not support the generic types of loading subpassInput so we have some explicit
286 // versions that we currently use
287 half4 subpassLoad(subpassInput subpass);
288 half4 subpassLoad(subpassInputMS subpass, int sample);
289 
290 half4 sample(sampler1D s, float2 P);
291 half4 sample(sampler1D s, float2 P, float bias);
292 half4 sample(sampler2D s, float3 P);
293 half4 sample(sampler2D s, float3 P, float bias);
294 
295 $genType dFdx($genType p);
296 $genType dFdy($genType p);
297 $genHType dFdx($genHType p);
298 $genHType dFdy($genHType p);
299 $genType fwidth($genType p);
300 $genHType fwidth($genHType p);
301 float interpolateAtSample(float interpolant, int sample);
302 float2 interpolateAtSample(float2 interpolant, int sample);
303 float3 interpolateAtSample(float3 interpolant, int sample);
304 float4 interpolateAtSample(float4 interpolant, int sample);
305 float interpolateAtOffset(float interpolant, float2 offset);
306 float2 interpolateAtOffset(float2 interpolant, float2 offset);
307 float3 interpolateAtOffset(float3 interpolant, float2 offset);
308 float4 interpolateAtOffset(float4 interpolant, float2 offset);
309 
310 // Definitions of functions implementing all of the SkBlendMode blends.
311 
312 half4 blend_clear(half4 src, half4 dst) { return half4(0); }
313 
314 half4 blend_src(half4 src, half4 dst) { return src; }
315 
316 half4 blend_dst(half4 src, half4 dst) { return dst; }
317 
318 half4 blend_src_over(half4 src, half4 dst) { return src + (1 - src.a)*dst; }
319 
320 half4 blend_dst_over(half4 src, half4 dst) { return (1 - dst.a)*src + dst; }
321 
322 half4 blend_src_in(half4 src, half4 dst) { return src*dst.a; }
323 
324 half4 blend_dst_in(half4 src, half4 dst) { return dst*src.a; }
325 
326 half4 blend_src_out(half4 src, half4 dst) { return (1 - dst.a)*src; }
327 
328 half4 blend_dst_out(half4 src, half4 dst) { return (1 - src.a)*dst; }
329 
330 half4 blend_src_atop(half4 src, half4 dst) { return dst.a*src + (1 - src.a)*dst; }
331 
332 half4 blend_dst_atop(half4 src, half4 dst)  { return  (1 - dst.a) * src + src.a*dst; }
333 
334 half4 blend_xor(half4 src, half4 dst) { return (1 - dst.a)*src + (1 - src.a)*dst; }
335 
336 half4 blend_plus(half4 src, half4 dst) { return min(src + dst, 1); }
337 
338 half4 blend_modulate(half4 src, half4 dst) { return src*dst; }
339 
340 half4 blend_screen(half4 src, half4 dst) { return src + (1 - src)*dst; }
341 
342 half _blend_overlay_component(half2 s, half2 d) {
343     return (2*d.x <= d.y)
344             ? 2*s.x*d.x
345             : s.y*d.y - 2*(d.y - d.x)*(s.y - s.x);
346 }
347 
348 half4 blend_overlay(half4 src, half4 dst) {
349     half4 result = half4(_blend_overlay_component(src.ra, dst.ra),
350                          _blend_overlay_component(src.ga, dst.ga),
351                          _blend_overlay_component(src.ba, dst.ba),
352                          src.a + (1 - src.a)*dst.a);
353     result.rgb += dst.rgb*(1 - src.a) + src.rgb*(1 - dst.a);
354     return result;
355 }
356 
357 half4 blend_darken(half4 src, half4 dst) {
358    half4 result = blend_src_over(src, dst);
359    result.rgb = min(result.rgb, (1 - dst.a)*src.rgb + dst.rgb);
360    return result;
361 }
362 
363 half4 blend_lighten(half4 src, half4 dst) {
364     half4 result = blend_src_over(src, dst);
365     result.rgb = max(result.rgb, (1 - dst.a)*src.rgb + dst.rgb);
366     return result;
367 }
368 
369 half _guarded_divide(half n, half d) {
370     return sk_Caps.mustGuardDivisionEvenAfterExplicitZeroCheck
371             ? n/(d + 0.00000001)
372             : n/d;
373 }
374 
375 half3 _guarded_divide(half3 n, half d) {
376     return sk_Caps.mustGuardDivisionEvenAfterExplicitZeroCheck
377             ? n/(d + 0.00000001)
378             : n/d;
379 }
380 
381 half _color_dodge_component(half2 s, half2 d) {
382     if (d.x == 0) {
383         return s.x*(1 - d.y);
384     } else {
385         half delta = s.y - s.x;
386         if (delta == 0) {
387              return s.y*d.y + s.x*(1 - d.y) + d.x*(1 - s.y);
388         } else {
389             delta = min(d.y, _guarded_divide(d.x*s.y, delta));
390             return delta*s.y + s.x*(1 - d.y) + d.x*(1 - s.y);
391         }
392     }
393 }
394 
395 half4 blend_color_dodge(half4 src, half4 dst) {
396     return half4(_color_dodge_component(src.ra, dst.ra),
397                  _color_dodge_component(src.ga, dst.ga),
398                  _color_dodge_component(src.ba, dst.ba),
399                  src.a + (1 - src.a)*dst.a);
400 }
401 
402 half _color_burn_component(half2 s, half2 d) {
403     if (d.y == d.x) {
404         return s.y*d.y + s.x*(1 - d.y) + d.x*(1 - s.y);
405     } else if (s.x == 0) {
406         return d.x*(1 - s.y);
407     } else {
408         half delta = max(0, d.y - _guarded_divide((d.y - d.x)*s.y, s.x));
409         return delta*s.y + s.x*(1 - d.y) + d.x*(1 - s.y);
410     }
411 }
412 
413 half4 blend_color_burn(half4 src, half4 dst) {
414     return half4(_color_burn_component(src.ra, dst.ra),
415                  _color_burn_component(src.ga, dst.ga),
416                  _color_burn_component(src.ba, dst.ba),
417                  src.a + (1 - src.a)*dst.a);
418 }
419 
420 half4 blend_hard_light(half4 src, half4 dst) { return blend_overlay(dst, src); }
421 
422 half _soft_light_component(half2 s, half2 d) {
423     if (2*s.x <= s.y) {
424         return _guarded_divide(d.x*d.x*(s.y - 2*s.x), d.y) + (1 - d.y)*s.x + d.x*(-s.y + 2*s.x + 1);
425     } else if (4.0 * d.x <= d.y) {
426         half DSqd = d.x*d.x;
427         half DCub = DSqd*d.x;
428         half DaSqd = d.y*d.y;
429         half DaCub = DaSqd*d.y;
430         return _guarded_divide(DaSqd*(s.x - d.x*(3*s.y - 6*s.x - 1)) + 12*d.y*DSqd*(s.y - 2*s.x)
431                                - 16*DCub * (s.y - 2*s.x) - DaCub*s.x, DaSqd);
432     } else {
433         return d.x*(s.y - 2*s.x + 1) + s.x - sqrt(d.y*d.x)*(s.y - 2*s.x) - d.y*s.x;
434     }
435 }
436 
437 half4 blend_soft_light(half4 src, half4 dst) {
438     return (dst.a == 0) ? src : half4(_soft_light_component(src.ra, dst.ra),
439                                       _soft_light_component(src.ga, dst.ga),
440                                       _soft_light_component(src.ba, dst.ba),
441                                       src.a + (1 - src.a)*dst.a);
442 }
443 
444 half4 blend_difference(half4 src, half4 dst) {
445     return half4(src.rgb + dst.rgb - 2*min(src.rgb*dst.a, dst.rgb*src.a),
446                  src.a + (1 - src.a)*dst.a);
447 }
448 
449 half4 blend_exclusion(half4 src, half4 dst) {
450     return half4(dst.rgb + src.rgb - 2*dst.rgb*src.rgb, src.a + (1 - src.a)*dst.a);
451 }
452 
453 half4 blend_multiply(half4 src, half4 dst) {
454     return half4((1 - src.a)*dst.rgb + (1 - dst.a)*src.rgb + src.rgb*dst.rgb,
455                  src.a + (1 - src.a)*dst.a);
456 }
457 
458 half _blend_color_luminance(half3 color) { return dot(half3(0.3, 0.59, 0.11), color); }
459 
460 half3 _blend_set_color_luminance(half3 hueSatColor, half alpha, half3 lumColor) {
461     half lum = _blend_color_luminance(lumColor);
462     half3 result = lum - _blend_color_luminance(hueSatColor) + hueSatColor;
463     half minComp = min(min(result.r, result.g), result.b);
464     half maxComp = max(max(result.r, result.g), result.b);
465     if (minComp < 0 && lum != minComp) {
466         result = lum + (result - lum) * _guarded_divide(lum, (lum - minComp));
467     }
468     if (maxComp > alpha && maxComp != lum) {
469         return lum + _guarded_divide((result - lum) * (alpha - lum), (maxComp - lum));
470     } else {
471         return result;
472     }
473 }
474 
475 half _blend_color_saturation(half3 color) {
476     return max(max(color.r, color.g), color.b) - min(min(color.r, color.g), color.b);
477 }
478 
479 half3 _blend_set_color_saturation_helper(half3 minMidMax, half sat) {
480     if (minMidMax.r < minMidMax.b) {
481         return half3(0,
482                     _guarded_divide(sat*(minMidMax.g - minMidMax.r), (minMidMax.b - minMidMax.r)),
483                     sat);
484     } else {
485         return half3(0);
486     }
487 }
488 
489 half3 _blend_set_color_saturation(half3 hueLumColor, half3 satColor) {
490     half sat = _blend_color_saturation(satColor);
491     if (hueLumColor.r <= hueLumColor.g) {
492         if (hueLumColor.g <= hueLumColor.b) {
493             return _blend_set_color_saturation_helper(hueLumColor.rgb, sat);
494         } else if (hueLumColor.r <= hueLumColor.b) {
495             return _blend_set_color_saturation_helper(hueLumColor.rbg, sat).rbg;
496         } else {
497             return _blend_set_color_saturation_helper(hueLumColor.brg, sat).gbr;
498         }
499     } else if (hueLumColor.r <= hueLumColor.b) {
500        return _blend_set_color_saturation_helper(hueLumColor.grb, sat).grb;
501     } else if (hueLumColor.g <= hueLumColor.b) {
502        return _blend_set_color_saturation_helper(hueLumColor.gbr, sat).brg;
503     } else {
504        return _blend_set_color_saturation_helper(hueLumColor.bgr, sat).bgr;
505     }
506 }
507 
508 half4 blend_hue(half4 src, half4 dst) {
509     half alpha = dst.a*src.a;
510     half3 sda = src.rgb*dst.a;
511     half3 dsa = dst.rgb*src.a;
512     return half4(_blend_set_color_luminance(_blend_set_color_saturation(sda, dsa), alpha, dsa) +
513                  dst.rgb - dsa + src.rgb - sda,
514                  src.a + dst.a - alpha);
515 }
516 
517 half4 blend_saturation(half4 src, half4 dst) {
518     half alpha = dst.a*src.a;
519     half3 sda = src.rgb*dst.a;
520     half3 dsa = dst.rgb*src.a;
521     return half4(_blend_set_color_luminance(_blend_set_color_saturation(dsa, sda), alpha, dsa) +
522                  dst.rgb - dsa + src.rgb - sda,
523                  src.a + dst.a - alpha);
524 }
525 
526 half4 blend_color(half4 src, half4 dst)  {
527     half alpha = dst.a*src.a;
528     half3 sda = src.rgb*dst.a;
529     half3 dsa = dst.rgb*src.a;
530     return half4(_blend_set_color_luminance(sda, alpha, dsa) + dst.rgb - dsa + src.rgb - sda,
531                  src.a + dst.a - alpha);
532 }
533 
534 half4 blend_luminosity(half4 src, half4 dst) {
535     half alpha = dst.a*src.a;
536     half3 sda = src.rgb*dst.a;
537     half3 dsa = dst.rgb*src.a;
538     return half4(_blend_set_color_luminance(dsa, alpha, sda) + dst.rgb - dsa + src.rgb - sda,
539                  src.a + dst.a - alpha);
540 }
541 
542 // The max() guards against division by zero when the incoming color is transparent black
543 half4  unpremul(half4 color)  { return half4(color.rgb / max(color.a, 0.0001), color.a); }
544 float4 unpremul(float4 color) { return float4(color.rgb / max(color.a, 0.0001), color.a); }
545 
546 float2 proj(float3 p) { return p.xy / p.z; }
547 
548 // Implement cross() as a determinant to communicate our intent more clearly to the compiler.
549 // NOTE: Due to precision issues, it might be the case that cross(a, a) != 0.
550 float cross(float2 a, float2 b) {
551     return sk_Caps.builtinDeterminantSupport ? determinant(float2x2(a, b))
552                                              : a.x*b.y - a.y*b.x;
553 }
554 
555 half cross(half2 a, half2 b) {
556     return sk_Caps.builtinDeterminantSupport ? determinant(half2x2(a, b))
557                                              : a.x*b.y - a.y*b.x;
558 }
559 
560 // add the support of textureSize
561 int2 textureSize(sampler2D x, int y);
562 
563 // add the support of nonuniformEXT
564 uint nonuniformEXT(uint x);
565 )"}
566 };