1*c8dee2aaSAndroid Build Coastguard Worker// Intrinsics that are available to public SkSL (SkRuntimeEffect) 2*c8dee2aaSAndroid Build Coastguard Worker 3*c8dee2aaSAndroid Build Coastguard Worker// See "The OpenGL ES Shading Language, Section 8" 4*c8dee2aaSAndroid Build Coastguard Worker 5*c8dee2aaSAndroid Build Coastguard Worker// 8.1 : Angle and Trigonometry Functions 6*c8dee2aaSAndroid Build Coastguard Worker$pure $genType radians($genType degrees); 7*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType radians($genHType degrees); 8*c8dee2aaSAndroid Build Coastguard Worker$pure $genType degrees($genType radians); 9*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType degrees($genHType radians); 10*c8dee2aaSAndroid Build Coastguard Worker 11*c8dee2aaSAndroid Build Coastguard Worker$pure $genType sin($genType angle); 12*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType sin($genHType angle); 13*c8dee2aaSAndroid Build Coastguard Worker$pure $genType cos($genType angle); 14*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType cos($genHType angle); 15*c8dee2aaSAndroid Build Coastguard Worker$pure $genType tan($genType angle); 16*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType tan($genHType angle); 17*c8dee2aaSAndroid Build Coastguard Worker 18*c8dee2aaSAndroid Build Coastguard Worker$pure $genType asin($genType x); 19*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType asin($genHType x); 20*c8dee2aaSAndroid Build Coastguard Worker$pure $genType acos($genType x); 21*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType acos($genHType x); 22*c8dee2aaSAndroid Build Coastguard Worker$pure $genType atan($genType y, $genType x); 23*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType atan($genHType y, $genHType x); 24*c8dee2aaSAndroid Build Coastguard Worker$pure $genType atan($genType y_over_x); 25*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType atan($genHType y_over_x); 26*c8dee2aaSAndroid Build Coastguard Worker 27*c8dee2aaSAndroid Build Coastguard Worker// 8.1 : Angle and Trigonometry Functions (GLSL ES 3.0) 28*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genType sinh($genType x); 29*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genHType sinh($genHType x); 30*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genType cosh($genType x); 31*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genHType cosh($genHType x); 32*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genType tanh($genType x); 33*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genHType tanh($genHType x); 34*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genType asinh($genType x); 35*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genHType asinh($genHType x); 36*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genType acosh($genType x); 37*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genHType acosh($genHType x); 38*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genType atanh($genType x); 39*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genHType atanh($genHType x); 40*c8dee2aaSAndroid Build Coastguard Worker 41*c8dee2aaSAndroid Build Coastguard Worker// 8.2 : Exponential Functions 42*c8dee2aaSAndroid Build Coastguard Worker$pure $genType pow($genType x, $genType y); 43*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType pow($genHType x, $genHType y); 44*c8dee2aaSAndroid Build Coastguard Worker$pure $genType exp($genType x); 45*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType exp($genHType x); 46*c8dee2aaSAndroid Build Coastguard Worker$pure $genType log($genType x); 47*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType log($genHType x); 48*c8dee2aaSAndroid Build Coastguard Worker$pure $genType exp2($genType x); 49*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType exp2($genHType x); 50*c8dee2aaSAndroid Build Coastguard Worker$pure $genType log2($genType x); 51*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType log2($genHType x); 52*c8dee2aaSAndroid Build Coastguard Worker 53*c8dee2aaSAndroid Build Coastguard Worker$pure $genType sqrt($genType x); 54*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType sqrt($genHType x); 55*c8dee2aaSAndroid Build Coastguard Worker$pure $genType inversesqrt($genType x); 56*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType inversesqrt($genHType x); 57*c8dee2aaSAndroid Build Coastguard Worker 58*c8dee2aaSAndroid Build Coastguard Worker// 8.3 : Common Functions 59*c8dee2aaSAndroid Build Coastguard Worker$pure $genType abs($genType x); 60*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType abs($genHType x); 61*c8dee2aaSAndroid Build Coastguard Worker$pure $genType sign($genType x); 62*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType sign($genHType x); 63*c8dee2aaSAndroid Build Coastguard Worker$pure $genType floor($genType x); 64*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType floor($genHType x); 65*c8dee2aaSAndroid Build Coastguard Worker$pure $genType ceil($genType x); 66*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType ceil($genHType x); 67*c8dee2aaSAndroid Build Coastguard Worker$pure $genType fract($genType x); 68*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType fract($genHType x); 69*c8dee2aaSAndroid Build Coastguard Worker$pure $genType mod($genType x, float y); 70*c8dee2aaSAndroid Build Coastguard Worker$pure $genType mod($genType x, $genType y); 71*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType mod($genHType x, half y); 72*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType mod($genHType x, $genHType y); 73*c8dee2aaSAndroid Build Coastguard Worker 74*c8dee2aaSAndroid Build Coastguard Worker$pure $genType min($genType x, $genType y); 75*c8dee2aaSAndroid Build Coastguard Worker$pure $genType min($genType x, float y); 76*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType min($genHType x, $genHType y); 77*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType min($genHType x, half y); 78*c8dee2aaSAndroid Build Coastguard Worker$pure $genType max($genType x, $genType y); 79*c8dee2aaSAndroid Build Coastguard Worker$pure $genType max($genType x, float y); 80*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType max($genHType x, $genHType y); 81*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType max($genHType x, half y); 82*c8dee2aaSAndroid Build Coastguard Worker$pure $genType clamp($genType x, $genType minVal, $genType maxVal); 83*c8dee2aaSAndroid Build Coastguard Worker$pure $genType clamp($genType x, float minVal, float maxVal); 84*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType clamp($genHType x, $genHType minVal, $genHType maxVal); 85*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType clamp($genHType x, half minVal, half maxVal); 86*c8dee2aaSAndroid Build Coastguard Worker$pure $genType saturate($genType x); // SkSL extension 87*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType saturate($genHType x); // SkSL extension 88*c8dee2aaSAndroid Build Coastguard Worker$pure $genType mix($genType x, $genType y, $genType a); 89*c8dee2aaSAndroid Build Coastguard Worker$pure $genType mix($genType x, $genType y, float a); 90*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType mix($genHType x, $genHType y, $genHType a); 91*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType mix($genHType x, $genHType y, half a); 92*c8dee2aaSAndroid Build Coastguard Worker$pure $genType step($genType edge, $genType x); 93*c8dee2aaSAndroid Build Coastguard Worker$pure $genType step(float edge, $genType x); 94*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType step($genHType edge, $genHType x); 95*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType step(half edge, $genHType x); 96*c8dee2aaSAndroid Build Coastguard Worker$pure $genType smoothstep($genType edge0, $genType edge1, $genType x); 97*c8dee2aaSAndroid Build Coastguard Worker$pure $genType smoothstep(float edge0, float edge1, $genType x); 98*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType smoothstep($genHType edge0, $genHType edge1, $genHType x); 99*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType smoothstep(half edge0, half edge1, $genHType x); 100*c8dee2aaSAndroid Build Coastguard Worker 101*c8dee2aaSAndroid Build Coastguard Worker// 8.3 : Common Functions (GLSL ES 3.0) 102*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genIType abs($genIType x); 103*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genIType sign($genIType x); 104*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genIType floatBitsToInt ($genType value); 105*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genUType floatBitsToUint($genType value); 106*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genType intBitsToFloat ($genIType value); 107*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genType uintBitsToFloat($genUType value); 108*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genType trunc($genType x); 109*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genHType trunc($genHType x); 110*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genType round($genType x); 111*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genHType round($genHType x); 112*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genType roundEven($genType x); 113*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genHType roundEven($genHType x); 114*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genIType min($genIType x, $genIType y); 115*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genIType min($genIType x, int y); 116*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genUType min($genUType x, $genUType y); 117*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genUType min($genUType x, uint y); 118*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genIType max($genIType x, $genIType y); 119*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genIType max($genIType x, int y); 120*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genUType max($genUType x, $genUType y); 121*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genUType max($genUType x, uint y); 122*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genIType clamp($genIType x, $genIType minVal, $genIType maxVal); 123*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genIType clamp($genIType x, int minVal, int maxVal); 124*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genUType clamp($genUType x, $genUType minVal, $genUType maxVal); 125*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genUType clamp($genUType x, uint minVal, uint maxVal); 126*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genType mix($genType x, $genType y, $genBType a); 127*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genHType mix($genHType x, $genHType y, $genBType a); 128*c8dee2aaSAndroid Build Coastguard Worker 129*c8dee2aaSAndroid Build Coastguard Worker// 8.3 : Common Functions (GLSL ES 3.0) -- cannot be used in constant-expressions 130*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genBType isnan($genType x); 131*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genBType isnan($genHType x); 132*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genBType isinf($genType x); 133*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genBType isinf($genHType x); 134*c8dee2aaSAndroid Build Coastguard Worker $es3 $genType modf($genType x, out $genType i); 135*c8dee2aaSAndroid Build Coastguard Worker $es3 $genHType modf($genHType x, out $genHType i); 136*c8dee2aaSAndroid Build Coastguard Worker 137*c8dee2aaSAndroid Build Coastguard Worker// 8.4 : Floating-Point Pack and Unpack Functions (GLSL ES 3.0) 138*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 uint packUnorm2x16(float2 v); 139*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 float2 unpackUnorm2x16(uint p); 140*c8dee2aaSAndroid Build Coastguard Worker 141*c8dee2aaSAndroid Build Coastguard Worker// 8.5 : Geometric Functions 142*c8dee2aaSAndroid Build Coastguard Worker$pure float length($genType x); 143*c8dee2aaSAndroid Build Coastguard Worker$pure half length($genHType x); 144*c8dee2aaSAndroid Build Coastguard Worker$pure float distance($genType p0, $genType p1); 145*c8dee2aaSAndroid Build Coastguard Worker$pure half distance($genHType p0, $genHType p1); 146*c8dee2aaSAndroid Build Coastguard Worker$pure float dot($genType x, $genType y); 147*c8dee2aaSAndroid Build Coastguard Worker$pure half dot($genHType x, $genHType y); 148*c8dee2aaSAndroid Build Coastguard Worker$pure float3 cross(float3 x, float3 y); 149*c8dee2aaSAndroid Build Coastguard Worker$pure half3 cross(half3 x, half3 y); 150*c8dee2aaSAndroid Build Coastguard Worker$pure $genType normalize($genType x); 151*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType normalize($genHType x); 152*c8dee2aaSAndroid Build Coastguard Worker$pure $genType faceforward($genType N, $genType I, $genType Nref); 153*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType faceforward($genHType N, $genHType I, $genHType Nref); 154*c8dee2aaSAndroid Build Coastguard Worker$pure $genType reflect($genType I, $genType N); 155*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType reflect($genHType I, $genHType N); 156*c8dee2aaSAndroid Build Coastguard Worker$pure $genType refract($genType I, $genType N, float eta); 157*c8dee2aaSAndroid Build Coastguard Worker$pure $genHType refract($genHType I, $genHType N, half eta); 158*c8dee2aaSAndroid Build Coastguard Worker 159*c8dee2aaSAndroid Build Coastguard Worker// 8.6 : Matrix Functions 160*c8dee2aaSAndroid Build Coastguard Worker$pure $squareMat matrixCompMult($squareMat x, $squareMat y); 161*c8dee2aaSAndroid Build Coastguard Worker$pure $squareHMat matrixCompMult($squareHMat x, $squareHMat y); 162*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $mat matrixCompMult($mat x, $mat y); 163*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $hmat matrixCompMult($hmat x, $hmat y); 164*c8dee2aaSAndroid Build Coastguard Worker 165*c8dee2aaSAndroid Build Coastguard Worker// 8.6 : Matrix Functions (GLSL 1.4, poly-filled by SkSL as needed) 166*c8dee2aaSAndroid Build Coastguard Worker$pure $squareMat inverse($squareMat m); 167*c8dee2aaSAndroid Build Coastguard Worker$pure $squareHMat inverse($squareHMat m); 168*c8dee2aaSAndroid Build Coastguard Worker 169*c8dee2aaSAndroid Build Coastguard Worker// 8.6 : Matrix Functions (GLSL ES 3.0) 170*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 float determinant($squareMat m); 171*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 half determinant($squareHMat m); 172*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $squareMat transpose($squareMat m); 173*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $squareHMat transpose($squareHMat m); 174*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 float2x3 transpose(float3x2 m); 175*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 half2x3 transpose(half3x2 m); 176*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 float2x4 transpose(float4x2 m); 177*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 half2x4 transpose(half4x2 m); 178*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 float3x2 transpose(float2x3 m); 179*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 half3x2 transpose(half2x3 m); 180*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 float3x4 transpose(float4x3 m); 181*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 half3x4 transpose(half4x3 m); 182*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 float4x2 transpose(float2x4 m); 183*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 half4x2 transpose(half2x4 m); 184*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 float4x3 transpose(float3x4 m); 185*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 half4x3 transpose(half3x4 m); 186*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $squareMat outerProduct($vec c, $vec r); 187*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $squareHMat outerProduct($hvec c, $hvec r); 188*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 float2x3 outerProduct(float3 c, float2 r); 189*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 half2x3 outerProduct(half3 c, half2 r); 190*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 float3x2 outerProduct(float2 c, float3 r); 191*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 half3x2 outerProduct(half2 c, half3 r); 192*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 float2x4 outerProduct(float4 c, float2 r); 193*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 half2x4 outerProduct(half4 c, half2 r); 194*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 float4x2 outerProduct(float2 c, float4 r); 195*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 half4x2 outerProduct(half2 c, half4 r); 196*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 float3x4 outerProduct(float4 c, float3 r); 197*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 half3x4 outerProduct(half4 c, half3 r); 198*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 float4x3 outerProduct(float3 c, float4 r); 199*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 half4x3 outerProduct(half3 c, half4 r); 200*c8dee2aaSAndroid Build Coastguard Worker 201*c8dee2aaSAndroid Build Coastguard Worker// 8.7 : Vector Relational Functions 202*c8dee2aaSAndroid Build Coastguard Worker$pure $bvec lessThan($vec x, $vec y); 203*c8dee2aaSAndroid Build Coastguard Worker$pure $bvec lessThan($hvec x, $hvec y); 204*c8dee2aaSAndroid Build Coastguard Worker$pure $bvec lessThan($ivec x, $ivec y); 205*c8dee2aaSAndroid Build Coastguard Worker$pure $bvec lessThan($svec x, $svec y); 206*c8dee2aaSAndroid Build Coastguard Worker$pure $bvec lessThanEqual($vec x, $vec y); 207*c8dee2aaSAndroid Build Coastguard Worker$pure $bvec lessThanEqual($hvec x, $hvec y); 208*c8dee2aaSAndroid Build Coastguard Worker$pure $bvec lessThanEqual($ivec x, $ivec y); 209*c8dee2aaSAndroid Build Coastguard Worker$pure $bvec lessThanEqual($svec x, $svec y); 210*c8dee2aaSAndroid Build Coastguard Worker$pure $bvec greaterThan($vec x, $vec y); 211*c8dee2aaSAndroid Build Coastguard Worker$pure $bvec greaterThan($hvec x, $hvec y); 212*c8dee2aaSAndroid Build Coastguard Worker$pure $bvec greaterThan($ivec x, $ivec y); 213*c8dee2aaSAndroid Build Coastguard Worker$pure $bvec greaterThan($svec x, $svec y); 214*c8dee2aaSAndroid Build Coastguard Worker$pure $bvec greaterThanEqual($vec x, $vec y); 215*c8dee2aaSAndroid Build Coastguard Worker$pure $bvec greaterThanEqual($hvec x, $hvec y); 216*c8dee2aaSAndroid Build Coastguard Worker$pure $bvec greaterThanEqual($ivec x, $ivec y); 217*c8dee2aaSAndroid Build Coastguard Worker$pure $bvec greaterThanEqual($svec x, $svec y); 218*c8dee2aaSAndroid Build Coastguard Worker$pure $bvec equal($vec x, $vec y); 219*c8dee2aaSAndroid Build Coastguard Worker$pure $bvec equal($hvec x, $hvec y); 220*c8dee2aaSAndroid Build Coastguard Worker$pure $bvec equal($ivec x, $ivec y); 221*c8dee2aaSAndroid Build Coastguard Worker$pure $bvec equal($svec x, $svec y); 222*c8dee2aaSAndroid Build Coastguard Worker$pure $bvec equal($bvec x, $bvec y); 223*c8dee2aaSAndroid Build Coastguard Worker$pure $bvec notEqual($vec x, $vec y); 224*c8dee2aaSAndroid Build Coastguard Worker$pure $bvec notEqual($hvec x, $hvec y); 225*c8dee2aaSAndroid Build Coastguard Worker$pure $bvec notEqual($ivec x, $ivec y); 226*c8dee2aaSAndroid Build Coastguard Worker$pure $bvec notEqual($svec x, $svec y); 227*c8dee2aaSAndroid Build Coastguard Worker$pure $bvec notEqual($bvec x, $bvec y); 228*c8dee2aaSAndroid Build Coastguard Worker 229*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $bvec lessThan($usvec x, $usvec y); 230*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $bvec lessThan($uvec x, $uvec y); 231*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $bvec lessThanEqual($uvec x, $uvec y); 232*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $bvec lessThanEqual($usvec x, $usvec y); 233*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $bvec greaterThan($uvec x, $uvec y); 234*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $bvec greaterThan($usvec x, $usvec y); 235*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $bvec greaterThanEqual($uvec x, $uvec y); 236*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $bvec greaterThanEqual($usvec x, $usvec y); 237*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $bvec equal($uvec x, $uvec y); 238*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $bvec equal($usvec x, $usvec y); 239*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $bvec notEqual($uvec x, $uvec y); 240*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $bvec notEqual($usvec x, $usvec y); 241*c8dee2aaSAndroid Build Coastguard Worker 242*c8dee2aaSAndroid Build Coastguard Worker$pure bool any($bvec x); 243*c8dee2aaSAndroid Build Coastguard Worker$pure bool all($bvec x); 244*c8dee2aaSAndroid Build Coastguard Worker$pure $bvec not($bvec x); 245*c8dee2aaSAndroid Build Coastguard Worker 246*c8dee2aaSAndroid Build Coastguard Worker// 8.9 : Fragment Processing Functions (GLSL ES 3.0) 247*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genType dFdx($genType p); 248*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genType dFdy($genType p); 249*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genHType dFdx($genHType p); 250*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genHType dFdy($genHType p); 251*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genType fwidth($genType p); 252*c8dee2aaSAndroid Build Coastguard Worker$pure $es3 $genHType fwidth($genHType p); 253*c8dee2aaSAndroid Build Coastguard Worker 254*c8dee2aaSAndroid Build Coastguard Worker 255*c8dee2aaSAndroid Build Coastguard Worker// SkSL utility functions 256*c8dee2aaSAndroid Build Coastguard Worker 257*c8dee2aaSAndroid Build Coastguard Worker// The max() guards against division by zero when the incoming color is transparent black 258*c8dee2aaSAndroid Build Coastguard Worker$pure half4 unpremul(half4 color) { return half4 (color.rgb / max(color.a, 0.0001), color.a); } 259*c8dee2aaSAndroid Build Coastguard Worker$pure float4 unpremul(float4 color) { return float4(color.rgb / max(color.a, 0.0001), color.a); } 260*c8dee2aaSAndroid Build Coastguard Worker 261*c8dee2aaSAndroid Build Coastguard Worker// Similar, but used for polar-space CSS colors 262*c8dee2aaSAndroid Build Coastguard Worker$export $pure half4 $unpremul_polar(half4 color) { 263*c8dee2aaSAndroid Build Coastguard Worker return half4(color.r, color.gb / max(color.a, 0.0001), color.a); 264*c8dee2aaSAndroid Build Coastguard Worker} 265*c8dee2aaSAndroid Build Coastguard Worker 266*c8dee2aaSAndroid Build Coastguard Worker// Convert RGBA -> HSLA (including unpremul). 267*c8dee2aaSAndroid Build Coastguard Worker// 268*c8dee2aaSAndroid Build Coastguard Worker// Based on work by Sam Hocevar, Emil Persson, and Ian Taylor [1][2][3]. High-level ideas: 269*c8dee2aaSAndroid Build Coastguard Worker// 270*c8dee2aaSAndroid Build Coastguard Worker// - minimize the number of branches by sorting and computing the hue phase in parallel (vec4s) 271*c8dee2aaSAndroid Build Coastguard Worker// 272*c8dee2aaSAndroid Build Coastguard Worker// - trade the third sorting branch for a potentially faster std::min and leaving 2nd/3rd 273*c8dee2aaSAndroid Build Coastguard Worker// channels unsorted (based on the observation that swapping both the channels and the bias sign 274*c8dee2aaSAndroid Build Coastguard Worker// has no effect under abs) 275*c8dee2aaSAndroid Build Coastguard Worker// 276*c8dee2aaSAndroid Build Coastguard Worker// - use epsilon offsets for denominators, to avoid explicit zero-checks 277*c8dee2aaSAndroid Build Coastguard Worker// 278*c8dee2aaSAndroid Build Coastguard Worker// An additional trick we employ is deferring premul->unpremul conversion until the very end: the 279*c8dee2aaSAndroid Build Coastguard Worker// alpha factor gets naturally simplified for H and S, and only L requires a dedicated unpremul 280*c8dee2aaSAndroid Build Coastguard Worker// division (so we trade three divs for one). 281*c8dee2aaSAndroid Build Coastguard Worker// 282*c8dee2aaSAndroid Build Coastguard Worker// [1] http://lolengine.net/blog/2013/01/13/fast-rgb-to-hsv 283*c8dee2aaSAndroid Build Coastguard Worker// [2] http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl 284*c8dee2aaSAndroid Build Coastguard Worker// [3] http://www.chilliant.com/rgb2hsv.html 285*c8dee2aaSAndroid Build Coastguard Worker 286*c8dee2aaSAndroid Build Coastguard Worker$export $pure half4 $rgb_to_hsl(half3 c, half a) { 287*c8dee2aaSAndroid Build Coastguard Worker half4 p = (c.g < c.b) ? half4(c.bg, -1, 2/3.0) 288*c8dee2aaSAndroid Build Coastguard Worker : half4(c.gb, 0, -1/3.0); 289*c8dee2aaSAndroid Build Coastguard Worker half4 q = (c.r < p.x) ? half4(p.x, c.r, p.yw) 290*c8dee2aaSAndroid Build Coastguard Worker : half4(c.r, p.x, p.yz); 291*c8dee2aaSAndroid Build Coastguard Worker 292*c8dee2aaSAndroid Build Coastguard Worker // q.x -> max channel value 293*c8dee2aaSAndroid Build Coastguard Worker // q.yz -> 2nd/3rd channel values (unsorted) 294*c8dee2aaSAndroid Build Coastguard Worker // q.w -> bias value dependent on max channel selection 295*c8dee2aaSAndroid Build Coastguard Worker 296*c8dee2aaSAndroid Build Coastguard Worker const half kEps = 0.0001; 297*c8dee2aaSAndroid Build Coastguard Worker half pmV = q.x; 298*c8dee2aaSAndroid Build Coastguard Worker half pmC = pmV - min(q.y, q.z); 299*c8dee2aaSAndroid Build Coastguard Worker half pmL = pmV - pmC * 0.5; 300*c8dee2aaSAndroid Build Coastguard Worker half H = abs(q.w + (q.y - q.z) / (pmC * 6 + kEps)); 301*c8dee2aaSAndroid Build Coastguard Worker half S = pmC / (a + kEps - abs(pmL * 2 - a)); 302*c8dee2aaSAndroid Build Coastguard Worker half L = pmL / (a + kEps); 303*c8dee2aaSAndroid Build Coastguard Worker 304*c8dee2aaSAndroid Build Coastguard Worker return half4(H, S, L, a); 305*c8dee2aaSAndroid Build Coastguard Worker} 306*c8dee2aaSAndroid Build Coastguard Worker 307*c8dee2aaSAndroid Build Coastguard Worker// Convert HSLA -> RGBA (including clamp and premul). 308*c8dee2aaSAndroid Build Coastguard Worker// 309*c8dee2aaSAndroid Build Coastguard Worker// Based on work by Sam Hocevar, Emil Persson, and Ian Taylor [1][2][3]. 310*c8dee2aaSAndroid Build Coastguard Worker// 311*c8dee2aaSAndroid Build Coastguard Worker// [1] http://lolengine.net/blog/2013/01/13/fast-rgb-to-hsv 312*c8dee2aaSAndroid Build Coastguard Worker// [2] http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl 313*c8dee2aaSAndroid Build Coastguard Worker// [3] http://www.chilliant.com/rgb2hsv.html 314*c8dee2aaSAndroid Build Coastguard Worker 315*c8dee2aaSAndroid Build Coastguard Worker$export $pure half3 $hsl_to_rgb(half3 hsl) { 316*c8dee2aaSAndroid Build Coastguard Worker half C = (1 - abs(2 * hsl.z - 1)) * hsl.y; 317*c8dee2aaSAndroid Build Coastguard Worker half3 p = hsl.xxx + half3(0, 2/3.0, 1/3.0); 318*c8dee2aaSAndroid Build Coastguard Worker half3 q = saturate(abs(fract(p) * 6 - 3) - 1); 319*c8dee2aaSAndroid Build Coastguard Worker 320*c8dee2aaSAndroid Build Coastguard Worker return (q - 0.5) * C + hsl.z; 321*c8dee2aaSAndroid Build Coastguard Worker} 322*c8dee2aaSAndroid Build Coastguard Worker 323*c8dee2aaSAndroid Build Coastguard Worker$export $pure half4 $hsl_to_rgb(half3 hsl, half a) { 324*c8dee2aaSAndroid Build Coastguard Worker return saturate(half4($hsl_to_rgb(hsl) * a, a)); 325*c8dee2aaSAndroid Build Coastguard Worker} 326*c8dee2aaSAndroid Build Coastguard Worker 327*c8dee2aaSAndroid Build Coastguard Worker// Color conversion functions used in gradient interpolation, based on 328*c8dee2aaSAndroid Build Coastguard Worker// https://www.w3.org/TR/css-color-4/#color-conversion-code 329*c8dee2aaSAndroid Build Coastguard Worker// TODO(skia:13108): For all of these, we can eliminate any linear math at the beginning 330*c8dee2aaSAndroid Build Coastguard Worker// (by removing the corresponding linear math at the end of the CPU code). 331*c8dee2aaSAndroid Build Coastguard Worker$export $pure half3 $css_lab_to_xyz(half3 lab) { 332*c8dee2aaSAndroid Build Coastguard Worker const half k = 24389 / 27.0; 333*c8dee2aaSAndroid Build Coastguard Worker const half e = 216 / 24389.0; 334*c8dee2aaSAndroid Build Coastguard Worker 335*c8dee2aaSAndroid Build Coastguard Worker half3 f; 336*c8dee2aaSAndroid Build Coastguard Worker f[1] = (lab[0] + 16) / 116; 337*c8dee2aaSAndroid Build Coastguard Worker f[0] = (lab[1] / 500) + f[1]; 338*c8dee2aaSAndroid Build Coastguard Worker f[2] = f[1] - (lab[2] / 200); 339*c8dee2aaSAndroid Build Coastguard Worker 340*c8dee2aaSAndroid Build Coastguard Worker half3 f_cubed = pow(f, half3(3)); 341*c8dee2aaSAndroid Build Coastguard Worker 342*c8dee2aaSAndroid Build Coastguard Worker half3 xyz = half3( 343*c8dee2aaSAndroid Build Coastguard Worker f_cubed[0] > e ? f_cubed[0] : (116 * f[0] - 16) / k, 344*c8dee2aaSAndroid Build Coastguard Worker lab[0] > k * e ? f_cubed[1] : lab[0] / k, 345*c8dee2aaSAndroid Build Coastguard Worker f_cubed[2] > e ? f_cubed[2] : (116 * f[2] - 16) / k 346*c8dee2aaSAndroid Build Coastguard Worker ); 347*c8dee2aaSAndroid Build Coastguard Worker 348*c8dee2aaSAndroid Build Coastguard Worker const half3 D50 = half3(0.3457 / 0.3585, 1.0, (1.0 - 0.3457 - 0.3585) / 0.3585); 349*c8dee2aaSAndroid Build Coastguard Worker return xyz * D50; 350*c8dee2aaSAndroid Build Coastguard Worker} 351*c8dee2aaSAndroid Build Coastguard Worker 352*c8dee2aaSAndroid Build Coastguard Worker// Skia stores all polar colors with hue in the first component, so this "LCH -> Lab" transform 353*c8dee2aaSAndroid Build Coastguard Worker// actually takes "HCL". This is also used to do the same polar transform for OkHCL to OkLAB. 354*c8dee2aaSAndroid Build Coastguard Worker// See similar comments & logic in SkGradientShaderBase.cpp. 355*c8dee2aaSAndroid Build Coastguard Worker$pure half3 $css_hcl_to_lab(half3 hcl) { 356*c8dee2aaSAndroid Build Coastguard Worker return half3( 357*c8dee2aaSAndroid Build Coastguard Worker hcl[2], 358*c8dee2aaSAndroid Build Coastguard Worker hcl[1] * cos(radians(hcl[0])), 359*c8dee2aaSAndroid Build Coastguard Worker hcl[1] * sin(radians(hcl[0])) 360*c8dee2aaSAndroid Build Coastguard Worker ); 361*c8dee2aaSAndroid Build Coastguard Worker} 362*c8dee2aaSAndroid Build Coastguard Worker 363*c8dee2aaSAndroid Build Coastguard Worker$export $pure half3 $css_hcl_to_xyz(half3 hcl) { 364*c8dee2aaSAndroid Build Coastguard Worker return $css_lab_to_xyz($css_hcl_to_lab(hcl)); 365*c8dee2aaSAndroid Build Coastguard Worker} 366*c8dee2aaSAndroid Build Coastguard Worker 367*c8dee2aaSAndroid Build Coastguard Worker$export $pure half3 $css_oklab_to_linear_srgb(half3 oklab) { 368*c8dee2aaSAndroid Build Coastguard Worker half l_ = oklab.x + 0.3963377774 * oklab.y + 0.2158037573 * oklab.z, 369*c8dee2aaSAndroid Build Coastguard Worker m_ = oklab.x - 0.1055613458 * oklab.y - 0.0638541728 * oklab.z, 370*c8dee2aaSAndroid Build Coastguard Worker s_ = oklab.x - 0.0894841775 * oklab.y - 1.2914855480 * oklab.z; 371*c8dee2aaSAndroid Build Coastguard Worker 372*c8dee2aaSAndroid Build Coastguard Worker half l = l_*l_*l_, 373*c8dee2aaSAndroid Build Coastguard Worker m = m_*m_*m_, 374*c8dee2aaSAndroid Build Coastguard Worker s = s_*s_*s_; 375*c8dee2aaSAndroid Build Coastguard Worker 376*c8dee2aaSAndroid Build Coastguard Worker return half3( 377*c8dee2aaSAndroid Build Coastguard Worker +4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s, 378*c8dee2aaSAndroid Build Coastguard Worker -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s, 379*c8dee2aaSAndroid Build Coastguard Worker -0.0041960863 * l - 0.7034186147 * m + 1.7076147010 * s 380*c8dee2aaSAndroid Build Coastguard Worker ); 381*c8dee2aaSAndroid Build Coastguard Worker} 382*c8dee2aaSAndroid Build Coastguard Worker 383*c8dee2aaSAndroid Build Coastguard Worker$export $pure half3 $css_okhcl_to_linear_srgb(half3 okhcl) { 384*c8dee2aaSAndroid Build Coastguard Worker return $css_oklab_to_linear_srgb($css_hcl_to_lab(okhcl)); 385*c8dee2aaSAndroid Build Coastguard Worker} 386*c8dee2aaSAndroid Build Coastguard Worker 387*c8dee2aaSAndroid Build Coastguard Worker$export $pure half3 $css_oklab_gamut_map_to_linear_srgb(half3 oklab) { 388*c8dee2aaSAndroid Build Coastguard Worker // Constants for the normal vector of the plane formed by white, black, and 389*c8dee2aaSAndroid Build Coastguard Worker // the specified vertex of the gamut. 390*c8dee2aaSAndroid Build Coastguard Worker const half2 normal_R = half2(0.409702, -0.912219); 391*c8dee2aaSAndroid Build Coastguard Worker const half2 normal_M = half2(-0.397919, -0.917421); 392*c8dee2aaSAndroid Build Coastguard Worker const half2 normal_B = half2(-0.906800, 0.421562); 393*c8dee2aaSAndroid Build Coastguard Worker const half2 normal_C = half2(-0.171122, 0.985250); 394*c8dee2aaSAndroid Build Coastguard Worker const half2 normal_G = half2(0.460276, 0.887776); 395*c8dee2aaSAndroid Build Coastguard Worker const half2 normal_Y = half2(0.947925, 0.318495); 396*c8dee2aaSAndroid Build Coastguard Worker 397*c8dee2aaSAndroid Build Coastguard Worker // For the triangles formed by white (W) or black (K) with the vertices 398*c8dee2aaSAndroid Build Coastguard Worker // of Yellow and Red (YR), Red and Magenta (RM), etc, the constants to be 399*c8dee2aaSAndroid Build Coastguard Worker // used to compute the intersection of a line of constant hue and luminance 400*c8dee2aaSAndroid Build Coastguard Worker // with that plane. 401*c8dee2aaSAndroid Build Coastguard Worker const half c0_YR = 0.091132; 402*c8dee2aaSAndroid Build Coastguard Worker const half2 cW_YR = half2(0.070370, 0.034139); 403*c8dee2aaSAndroid Build Coastguard Worker const half2 cK_YR = half2(0.018170, 0.378550); 404*c8dee2aaSAndroid Build Coastguard Worker const half c0_RM = 0.113902; 405*c8dee2aaSAndroid Build Coastguard Worker const half2 cW_RM = half2(0.090836, 0.036251); 406*c8dee2aaSAndroid Build Coastguard Worker const half2 cK_RM = half2(0.226781, 0.018764); 407*c8dee2aaSAndroid Build Coastguard Worker const half c0_MB = 0.161739; 408*c8dee2aaSAndroid Build Coastguard Worker const half2 cW_MB = half2(-0.008202, -0.264819); 409*c8dee2aaSAndroid Build Coastguard Worker const half2 cK_MB = half2( 0.187156, -0.284304); 410*c8dee2aaSAndroid Build Coastguard Worker const half c0_BC = 0.102047; 411*c8dee2aaSAndroid Build Coastguard Worker const half2 cW_BC = half2(-0.014804, -0.162608); 412*c8dee2aaSAndroid Build Coastguard Worker const half2 cK_BC = half2(-0.276786, 0.004193); 413*c8dee2aaSAndroid Build Coastguard Worker const half c0_CG = 0.092029; 414*c8dee2aaSAndroid Build Coastguard Worker const half2 cW_CG = half2(-0.038533, -0.001650); 415*c8dee2aaSAndroid Build Coastguard Worker const half2 cK_CG = half2(-0.232572, -0.094331); 416*c8dee2aaSAndroid Build Coastguard Worker const half c0_GY = 0.081709; 417*c8dee2aaSAndroid Build Coastguard Worker const half2 cW_GY = half2(-0.034601, -0.002215); 418*c8dee2aaSAndroid Build Coastguard Worker const half2 cK_GY = half2( 0.012185, 0.338031); 419*c8dee2aaSAndroid Build Coastguard Worker 420*c8dee2aaSAndroid Build Coastguard Worker half2 ab = oklab.yz; 421*c8dee2aaSAndroid Build Coastguard Worker 422*c8dee2aaSAndroid Build Coastguard Worker // Find the planes to intersect with and set the constants based on those 423*c8dee2aaSAndroid Build Coastguard Worker // planes. 424*c8dee2aaSAndroid Build Coastguard Worker half c0; 425*c8dee2aaSAndroid Build Coastguard Worker half2 cW; 426*c8dee2aaSAndroid Build Coastguard Worker half2 cK; 427*c8dee2aaSAndroid Build Coastguard Worker if (dot(ab, normal_R) < 0.0) { 428*c8dee2aaSAndroid Build Coastguard Worker if (dot(ab, normal_G) < 0.0) { 429*c8dee2aaSAndroid Build Coastguard Worker if (dot(ab, normal_C) < 0.0) { 430*c8dee2aaSAndroid Build Coastguard Worker c0 = c0_BC; cW = cW_BC; cK = cK_BC; 431*c8dee2aaSAndroid Build Coastguard Worker } else { 432*c8dee2aaSAndroid Build Coastguard Worker c0 = c0_CG; cW = cW_CG; cK = cK_CG; 433*c8dee2aaSAndroid Build Coastguard Worker } 434*c8dee2aaSAndroid Build Coastguard Worker } else { 435*c8dee2aaSAndroid Build Coastguard Worker if (dot(ab, normal_Y) < 0.0) { 436*c8dee2aaSAndroid Build Coastguard Worker c0 = c0_GY; cW = cW_GY; cK = cK_GY; 437*c8dee2aaSAndroid Build Coastguard Worker } else { 438*c8dee2aaSAndroid Build Coastguard Worker c0 = c0_YR; cW = cW_YR; cK = cK_YR; 439*c8dee2aaSAndroid Build Coastguard Worker } 440*c8dee2aaSAndroid Build Coastguard Worker } 441*c8dee2aaSAndroid Build Coastguard Worker } else { 442*c8dee2aaSAndroid Build Coastguard Worker if (dot(ab, normal_B) < 0.0) { 443*c8dee2aaSAndroid Build Coastguard Worker if (dot(ab, normal_M) < 0.0) { 444*c8dee2aaSAndroid Build Coastguard Worker c0 = c0_RM; cW = cW_RM; cK = cK_RM; 445*c8dee2aaSAndroid Build Coastguard Worker } else { 446*c8dee2aaSAndroid Build Coastguard Worker c0 = c0_MB; cW = cW_MB; cK = cK_MB; 447*c8dee2aaSAndroid Build Coastguard Worker } 448*c8dee2aaSAndroid Build Coastguard Worker } else { 449*c8dee2aaSAndroid Build Coastguard Worker c0 = c0_BC; cW = cW_BC; cK = cK_BC; 450*c8dee2aaSAndroid Build Coastguard Worker } 451*c8dee2aaSAndroid Build Coastguard Worker } 452*c8dee2aaSAndroid Build Coastguard Worker 453*c8dee2aaSAndroid Build Coastguard Worker // Perform the intersection. 454*c8dee2aaSAndroid Build Coastguard Worker half alpha = 1.0; 455*c8dee2aaSAndroid Build Coastguard Worker 456*c8dee2aaSAndroid Build Coastguard Worker // Intersect with the plane with white. 457*c8dee2aaSAndroid Build Coastguard Worker half w_denom = dot(cW, ab); 458*c8dee2aaSAndroid Build Coastguard Worker if (w_denom > 0.0) { 459*c8dee2aaSAndroid Build Coastguard Worker half one_minus_L = 1.0 - oklab.r; 460*c8dee2aaSAndroid Build Coastguard Worker half w_num = c0*one_minus_L; 461*c8dee2aaSAndroid Build Coastguard Worker if (w_num < w_denom) { 462*c8dee2aaSAndroid Build Coastguard Worker alpha = min(alpha, w_num / w_denom); 463*c8dee2aaSAndroid Build Coastguard Worker } 464*c8dee2aaSAndroid Build Coastguard Worker } 465*c8dee2aaSAndroid Build Coastguard Worker 466*c8dee2aaSAndroid Build Coastguard Worker // Intersect with the plane with black. 467*c8dee2aaSAndroid Build Coastguard Worker half k_denom = dot(cK, ab); 468*c8dee2aaSAndroid Build Coastguard Worker if (k_denom > 0.0) { 469*c8dee2aaSAndroid Build Coastguard Worker half L = oklab.r; 470*c8dee2aaSAndroid Build Coastguard Worker half k_num = c0*L; 471*c8dee2aaSAndroid Build Coastguard Worker if (k_num < k_denom) { 472*c8dee2aaSAndroid Build Coastguard Worker alpha = min(alpha, k_num / k_denom); 473*c8dee2aaSAndroid Build Coastguard Worker } 474*c8dee2aaSAndroid Build Coastguard Worker } 475*c8dee2aaSAndroid Build Coastguard Worker 476*c8dee2aaSAndroid Build Coastguard Worker // Attenuate the ab coordinate by alpha. 477*c8dee2aaSAndroid Build Coastguard Worker oklab.yz *= alpha; 478*c8dee2aaSAndroid Build Coastguard Worker 479*c8dee2aaSAndroid Build Coastguard Worker return $css_oklab_to_linear_srgb(oklab); 480*c8dee2aaSAndroid Build Coastguard Worker} 481*c8dee2aaSAndroid Build Coastguard Worker 482*c8dee2aaSAndroid Build Coastguard Worker$export $pure half3 $css_okhcl_gamut_map_to_linear_srgb(half3 okhcl) { 483*c8dee2aaSAndroid Build Coastguard Worker return $css_oklab_gamut_map_to_linear_srgb($css_hcl_to_lab(okhcl)); 484*c8dee2aaSAndroid Build Coastguard Worker} 485*c8dee2aaSAndroid Build Coastguard Worker 486*c8dee2aaSAndroid Build Coastguard Worker// TODO(skia:13108): Use our optimized version (though it has different range) 487*c8dee2aaSAndroid Build Coastguard Worker// Doing so might require fixing (re-deriving?) the math for the HWB version below 488*c8dee2aaSAndroid Build Coastguard Worker$export $pure half3 $css_hsl_to_srgb(half3 hsl) { 489*c8dee2aaSAndroid Build Coastguard Worker hsl.x = mod(hsl.x, 360); 490*c8dee2aaSAndroid Build Coastguard Worker if (hsl.x < 0) { 491*c8dee2aaSAndroid Build Coastguard Worker hsl.x += 360; 492*c8dee2aaSAndroid Build Coastguard Worker } 493*c8dee2aaSAndroid Build Coastguard Worker 494*c8dee2aaSAndroid Build Coastguard Worker hsl.yz /= 100; 495*c8dee2aaSAndroid Build Coastguard Worker 496*c8dee2aaSAndroid Build Coastguard Worker half3 k = mod(half3(0, 8, 4) + hsl.x/30, 12); 497*c8dee2aaSAndroid Build Coastguard Worker half a = hsl.y * min(hsl.z, 1 - hsl.z); 498*c8dee2aaSAndroid Build Coastguard Worker return hsl.z - a * clamp(min(k - 3, 9 - k), -1, 1); 499*c8dee2aaSAndroid Build Coastguard Worker} 500*c8dee2aaSAndroid Build Coastguard Worker 501*c8dee2aaSAndroid Build Coastguard Worker$export $pure half3 $css_hwb_to_srgb(half3 hwb) { 502*c8dee2aaSAndroid Build Coastguard Worker half3 rgb; 503*c8dee2aaSAndroid Build Coastguard Worker hwb.yz /= 100; 504*c8dee2aaSAndroid Build Coastguard Worker if (hwb.y + hwb.z >= 1) { 505*c8dee2aaSAndroid Build Coastguard Worker // Emit grayscale 506*c8dee2aaSAndroid Build Coastguard Worker rgb = half3(hwb.y / (hwb.y + hwb.z)); 507*c8dee2aaSAndroid Build Coastguard Worker } else { 508*c8dee2aaSAndroid Build Coastguard Worker rgb = $css_hsl_to_srgb(half3(hwb.x, 100, 50)); 509*c8dee2aaSAndroid Build Coastguard Worker rgb *= (1 - hwb.y - hwb.z); 510*c8dee2aaSAndroid Build Coastguard Worker rgb += hwb.y; 511*c8dee2aaSAndroid Build Coastguard Worker } 512*c8dee2aaSAndroid Build Coastguard Worker return rgb; 513*c8dee2aaSAndroid Build Coastguard Worker} 514*c8dee2aaSAndroid Build Coastguard Worker 515*c8dee2aaSAndroid Build Coastguard Worker/* 516*c8dee2aaSAndroid Build Coastguard Worker * The actual output color space of this function depends on the input color space 517*c8dee2aaSAndroid Build Coastguard Worker * (it might be sRGB, linear sRGB, or linear XYZ). The actual space is what's stored 518*c8dee2aaSAndroid Build Coastguard Worker * in the gradient/SkColor4fXformer's fIntermediateColorSpace. 519*c8dee2aaSAndroid Build Coastguard Worker */ 520*c8dee2aaSAndroid Build Coastguard Worker$export $pure half4 $interpolated_to_rgb_unpremul(half4 color, int colorSpace, int doUnpremul) { 521*c8dee2aaSAndroid Build Coastguard Worker const int kDestination = 0; 522*c8dee2aaSAndroid Build Coastguard Worker const int kSRGBLinear = 1; 523*c8dee2aaSAndroid Build Coastguard Worker const int kLab = 2; 524*c8dee2aaSAndroid Build Coastguard Worker const int kOKLab = 3; 525*c8dee2aaSAndroid Build Coastguard Worker const int kOKLabGamutMap = 4; 526*c8dee2aaSAndroid Build Coastguard Worker const int kLCH = 5; 527*c8dee2aaSAndroid Build Coastguard Worker const int kOKLCH = 6; 528*c8dee2aaSAndroid Build Coastguard Worker const int kOKLCHGamutMap = 7; 529*c8dee2aaSAndroid Build Coastguard Worker const int kSRGB = 8; 530*c8dee2aaSAndroid Build Coastguard Worker const int kHSL = 9; 531*c8dee2aaSAndroid Build Coastguard Worker const int kHWB = 10; 532*c8dee2aaSAndroid Build Coastguard Worker 533*c8dee2aaSAndroid Build Coastguard Worker if (bool(doUnpremul)) { 534*c8dee2aaSAndroid Build Coastguard Worker switch (colorSpace) { 535*c8dee2aaSAndroid Build Coastguard Worker case kLab: 536*c8dee2aaSAndroid Build Coastguard Worker case kOKLab: 537*c8dee2aaSAndroid Build Coastguard Worker case kOKLabGamutMap: color = unpremul(color); break; 538*c8dee2aaSAndroid Build Coastguard Worker case kLCH: 539*c8dee2aaSAndroid Build Coastguard Worker case kOKLCH: 540*c8dee2aaSAndroid Build Coastguard Worker case kOKLCHGamutMap: 541*c8dee2aaSAndroid Build Coastguard Worker case kHSL: 542*c8dee2aaSAndroid Build Coastguard Worker case kHWB: color = $unpremul_polar(color); break; 543*c8dee2aaSAndroid Build Coastguard Worker } 544*c8dee2aaSAndroid Build Coastguard Worker } 545*c8dee2aaSAndroid Build Coastguard Worker switch (colorSpace) { 546*c8dee2aaSAndroid Build Coastguard Worker case kLab: color.rgb = $css_lab_to_xyz(color.rgb); break; 547*c8dee2aaSAndroid Build Coastguard Worker case kOKLab: color.rgb = $css_oklab_to_linear_srgb(color.rgb); break; 548*c8dee2aaSAndroid Build Coastguard Worker case kOKLabGamutMap: color.rgb = $css_oklab_gamut_map_to_linear_srgb(color.rgb); break; 549*c8dee2aaSAndroid Build Coastguard Worker case kLCH: color.rgb = $css_hcl_to_xyz(color.rgb); break; 550*c8dee2aaSAndroid Build Coastguard Worker case kOKLCH: color.rgb = $css_okhcl_to_linear_srgb(color.rgb); break; 551*c8dee2aaSAndroid Build Coastguard Worker case kOKLCHGamutMap: color.rgb = $css_okhcl_gamut_map_to_linear_srgb(color.rgb); break; 552*c8dee2aaSAndroid Build Coastguard Worker case kHSL: color.rgb = $css_hsl_to_srgb(color.rgb); break; 553*c8dee2aaSAndroid Build Coastguard Worker case kHWB: color.rgb = $css_hwb_to_srgb(color.rgb); break; 554*c8dee2aaSAndroid Build Coastguard Worker } 555*c8dee2aaSAndroid Build Coastguard Worker return color; 556*c8dee2aaSAndroid Build Coastguard Worker} 557