@@ -39,6 +39,25 @@ static constexpr char kRuntimeShaderName[] = "RuntimeEffect";
3939
4040static_assert (static_cast <int >(BuiltInCodeSnippetID::kLast ) < kSkiaBuiltInReservedCnt );
4141
42+ // The toLinearSrgb and fromLinearSrgb RuntimeEffect intrinsics need to be able to map to and
43+ // from the dst color space and linearSRGB. These are the 10 uniforms needed to allow that.
44+ // These boil down to two copies of the kColorSpaceTransformUniforms uniforms. The first set
45+ // for mapping to LinearSRGB and the second set for mapping from LinearSRGB.
46+ static constexpr Uniform kRuntimeEffectColorSpaceTransformUniforms [] = {
47+ // to LinearSRGB
48+ { " flags_toLinear" , SkSLType::kInt },
49+ { " srcKind_toLinear" , SkSLType::kInt },
50+ { " gamutTransform_toLinear" , SkSLType::kHalf3x3 },
51+ { " dstKind_toLinear" , SkSLType::kInt },
52+ { " csXformCoeffs_toLinear" , SkSLType::kHalf4x4 },
53+ // from LinearSRGB
54+ { " flags_fromLinear" , SkSLType::kInt },
55+ { " srcKind_fromLinear" , SkSLType::kInt },
56+ { " gamutTransform_fromLinear" , SkSLType::kHalf3x3 },
57+ { " dstKind_fromLinear" , SkSLType::kInt },
58+ { " csXformCoeffs_fromLinear" , SkSLType::kHalf4x4 },
59+ };
60+
4261namespace {
4362
4463std::string get_mangled_name (const std::string& baseName, int manglingSuffix) {
@@ -1151,10 +1170,12 @@ class GraphitePipelineCallbacks : public SkSL::PipelineStage::Callbacks {
11511170public:
11521171 GraphitePipelineCallbacks (const ShaderInfo& shaderInfo,
11531172 const ShaderNode* node,
1154- std::string* preamble)
1173+ std::string* preamble,
1174+ const SkRuntimeEffect* effect)
11551175 : fShaderInfo (shaderInfo)
11561176 , fNode (node)
1157- , fPreamble (preamble) {}
1177+ , fPreamble (preamble)
1178+ , fEffect (effect) {}
11581179
11591180 std::string declareUniform (const SkSL::VarDeclaration* decl) override {
11601181 std::string result = get_mangled_name (std::string (decl->var ()->name ()), fNode ->keyIndex ());
@@ -1206,12 +1227,30 @@ class GraphitePipelineCallbacks : public SkSL::PipelineStage::Callbacks {
12061227 }
12071228
12081229 std::string toLinearSrgb (std::string color) override {
1209- // TODO(skia:13508): implement to-linear-SRGB child effect
1210- return color;
1230+ if (!SkRuntimeEffectPriv::UsesColorTransform (fEffect )) {
1231+ return color;
1232+ }
1233+
1234+ color = SkSL::String::printf (" (%s).rgb1" , color.c_str ());
1235+ std::string helper = get_mangled_name (" toLinearSRGB" , fNode ->keyIndex ());
1236+ std::string xformedColor = SkSL::String::printf (" %s(%s)" ,
1237+ helper.c_str (),
1238+ color.c_str ());
1239+ return SkSL::String::printf (" (%s).rgb" , xformedColor.c_str ());
12111240 }
1241+
1242+
12121243 std::string fromLinearSrgb (std::string color) override {
1213- // TODO(skia:13508): implement from-linear-SRGB child effect
1214- return color;
1244+ if (!SkRuntimeEffectPriv::UsesColorTransform (fEffect )) {
1245+ return color;
1246+ }
1247+
1248+ color = SkSL::String::printf (" (%s).rgb1" , color.c_str ());
1249+ std::string helper = get_mangled_name (" fromLinearSRGB" , fNode ->keyIndex ());
1250+ std::string xformedColor = SkSL::String::printf (" %s(%s)" ,
1251+ helper.c_str (),
1252+ color.c_str ());
1253+ return SkSL::String::printf (" (%s).rgb" , xformedColor.c_str ());
12151254 }
12161255
12171256 std::string getMangledName (const char * name) override {
@@ -1222,6 +1261,7 @@ class GraphitePipelineCallbacks : public SkSL::PipelineStage::Callbacks {
12221261 const ShaderInfo& fShaderInfo ;
12231262 const ShaderNode* fNode ;
12241263 std::string* fPreamble ;
1264+ const SkRuntimeEffect* fEffect ;
12251265};
12261266
12271267std::string GenerateRuntimeShaderPreamble (const ShaderInfo& shaderInfo,
@@ -1240,7 +1280,42 @@ std::string GenerateRuntimeShaderPreamble(const ShaderInfo& shaderInfo,
12401280 const SkSL::Program& program = SkRuntimeEffectPriv::Program (*effect);
12411281
12421282 std::string preamble;
1243- GraphitePipelineCallbacks callbacks{shaderInfo, node, &preamble};
1283+ if (SkRuntimeEffectPriv::UsesColorTransform (effect)) {
1284+ SkSL::String::appendf (
1285+ &preamble,
1286+ " half4 %s(half4 inColor) {"
1287+ " return sk_color_space_transform(inColor, %s, %s, %s, %s, %s);"
1288+ " }" ,
1289+ get_mangled_name (" toLinearSRGB" , node->keyIndex ()).c_str (),
1290+ get_mangled_uniform_name (shaderInfo, kRuntimeEffectColorSpaceTransformUniforms [0 ],
1291+ node->keyIndex ()).c_str (),
1292+ get_mangled_uniform_name (shaderInfo, kRuntimeEffectColorSpaceTransformUniforms [1 ],
1293+ node->keyIndex ()).c_str (),
1294+ get_mangled_uniform_name (shaderInfo, kRuntimeEffectColorSpaceTransformUniforms [2 ],
1295+ node->keyIndex ()).c_str (),
1296+ get_mangled_uniform_name (shaderInfo, kRuntimeEffectColorSpaceTransformUniforms [3 ],
1297+ node->keyIndex ()).c_str (),
1298+ get_mangled_uniform_name (shaderInfo, kRuntimeEffectColorSpaceTransformUniforms [4 ],
1299+ node->keyIndex ()).c_str ());
1300+ SkSL::String::appendf (
1301+ &preamble,
1302+ " half4 %s(half4 inColor) {"
1303+ " return sk_color_space_transform(inColor, %s, %s, %s, %s, %s);"
1304+ " }" ,
1305+ get_mangled_name (" fromLinearSRGB" , node->keyIndex ()).c_str (),
1306+ get_mangled_uniform_name (shaderInfo, kRuntimeEffectColorSpaceTransformUniforms [5 ],
1307+ node->keyIndex ()).c_str (),
1308+ get_mangled_uniform_name (shaderInfo, kRuntimeEffectColorSpaceTransformUniforms [6 ],
1309+ node->keyIndex ()).c_str (),
1310+ get_mangled_uniform_name (shaderInfo, kRuntimeEffectColorSpaceTransformUniforms [7 ],
1311+ node->keyIndex ()).c_str (),
1312+ get_mangled_uniform_name (shaderInfo, kRuntimeEffectColorSpaceTransformUniforms [8 ],
1313+ node->keyIndex ()).c_str (),
1314+ get_mangled_uniform_name (shaderInfo, kRuntimeEffectColorSpaceTransformUniforms [9 ],
1315+ node->keyIndex ()).c_str ());
1316+ }
1317+
1318+ GraphitePipelineCallbacks callbacks{shaderInfo, node, &preamble, effect};
12441319 SkSL::PipelineStage::ConvertProgram (program, " coords" , " inColor" , " destColor" , &callbacks);
12451320 return preamble;
12461321}
@@ -1449,9 +1524,19 @@ SkSpan<const Uniform> ShaderCodeDictionary::convertUniforms(const SkRuntimeEffec
14491524 using rteUniform = SkRuntimeEffect::Uniform;
14501525 SkSpan<const rteUniform> uniforms = effect->uniforms ();
14511526
1527+ int numBaseUniforms = uniforms.size ();
1528+ int xtraUniforms = 0 ;
1529+ if (SkRuntimeEffectPriv::UsesColorTransform (effect)) {
1530+ xtraUniforms += std::size (kRuntimeEffectColorSpaceTransformUniforms );
1531+ }
1532+
14521533 // Convert the SkRuntimeEffect::Uniform array into its Uniform equivalent.
1453- int numUniforms = uniforms. size () ;
1534+ int numUniforms = numBaseUniforms + xtraUniforms ;
14541535 Uniform* uniformArray = fArena .makeInitializedArray <Uniform>(numUniforms, [&](int index) {
1536+ if (index >= numBaseUniforms) {
1537+ return kRuntimeEffectColorSpaceTransformUniforms [index - numBaseUniforms];
1538+ }
1539+
14551540 const rteUniform* u;
14561541 u = &uniforms[index];
14571542
0 commit comments