SkSLFPTest.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651
  1. /*
  2. * Copyright 2017 Google Inc.
  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. #include "src/sksl/SkSLCompiler.h"
  8. #include "src/sksl/SkSLStringStream.h"
  9. #include "tests/Test.h"
  10. static void test(skiatest::Reporter* r, const char* src, const GrShaderCaps& caps,
  11. std::vector<const char*> expectedH, std::vector<const char*> expectedCPP) {
  12. SkSL::Program::Settings settings;
  13. settings.fCaps = &caps;
  14. SkSL::Compiler compiler;
  15. SkSL::StringStream output;
  16. std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
  17. SkSL::Program::kFragmentProcessor_Kind,
  18. SkSL::String(src),
  19. settings);
  20. if (!program) {
  21. SkDebugf("Unexpected error compiling %s\n%s", src, compiler.errorText().c_str());
  22. return;
  23. }
  24. REPORTER_ASSERT(r, program);
  25. bool success = compiler.toH(*program, "Test", output);
  26. if (!success) {
  27. SkDebugf("Unexpected error compiling %s\n%s", src, compiler.errorText().c_str());
  28. }
  29. REPORTER_ASSERT(r, success);
  30. if (success) {
  31. for (const char* expected : expectedH) {
  32. bool found = strstr(output.str().c_str(), expected);
  33. if (!found) {
  34. SkDebugf("HEADER MISMATCH:\nsource:\n%s\n\nexpected:\n'%s'\n\nreceived:\n'%s'", src,
  35. expected, output.str().c_str());
  36. }
  37. REPORTER_ASSERT(r, found);
  38. }
  39. }
  40. output.reset();
  41. success = compiler.toCPP(*program, "Test", output);
  42. if (!success) {
  43. SkDebugf("Unexpected error compiling %s\n%s", src, compiler.errorText().c_str());
  44. }
  45. REPORTER_ASSERT(r, success);
  46. if (success) {
  47. for (const char* expected : expectedCPP) {
  48. bool found = strstr(output.str().c_str(), expected);
  49. if (!found) {
  50. SkDebugf("CPP MISMATCH:\nsource:\n%s\n\nexpected:\n'%s'\n\nreceived:\n'%s'", src,
  51. expected, output.str().c_str());
  52. }
  53. REPORTER_ASSERT(r, found);
  54. }
  55. }
  56. }
  57. DEF_TEST(SkSLFPHelloWorld, r) {
  58. test(r,
  59. "/* HEADER */"
  60. "void main() {"
  61. "sk_OutColor = half4(1);"
  62. "}",
  63. *SkSL::ShaderCapsFactory::Default(),
  64. {
  65. "/* HEADER */\n"
  66. "\n"
  67. "/**************************************************************************************************\n"
  68. " *** This file was autogenerated from GrTest.fp; do not modify.\n"
  69. " **************************************************************************************************/\n"
  70. "#ifndef GrTest_DEFINED\n"
  71. "#define GrTest_DEFINED\n"
  72. "#include \"include/core/SkTypes.h\"\n\n"
  73. "#include \"src/gpu/GrCoordTransform.h\"\n"
  74. "#include \"src/gpu/GrFragmentProcessor.h\"\n"
  75. "class GrTest : public GrFragmentProcessor {\n"
  76. "public:\n"
  77. " static std::unique_ptr<GrFragmentProcessor> Make() {\n"
  78. " return std::unique_ptr<GrFragmentProcessor>(new GrTest());\n"
  79. " }\n"
  80. " GrTest(const GrTest& src);\n"
  81. " std::unique_ptr<GrFragmentProcessor> clone() const override;\n"
  82. " const char* name() const override { return \"Test\"; }\n"
  83. "private:\n"
  84. " GrTest()\n"
  85. " : INHERITED(kGrTest_ClassID, kNone_OptimizationFlags) {\n"
  86. " }\n"
  87. " GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;\n"
  88. " void onGetGLSLProcessorKey(const GrShaderCaps&,GrProcessorKeyBuilder*) const "
  89. "override;\n"
  90. " bool onIsEqual(const GrFragmentProcessor&) const override;\n"
  91. " GR_DECLARE_FRAGMENT_PROCESSOR_TEST\n"
  92. " typedef GrFragmentProcessor INHERITED;\n"
  93. "};\n"
  94. "#endif\n"
  95. },
  96. {
  97. "/**************************************************************************************************\n"
  98. " *** This file was autogenerated from GrTest.fp; do not modify.\n"
  99. " **************************************************************************************************/\n"
  100. "#include \"GrTest.h\"\n\n"
  101. "#include \"include/gpu/GrTexture.h\"\n"
  102. "#include \"src/gpu/glsl/GrGLSLFragmentProcessor.h\"\n"
  103. "#include \"src/gpu/glsl/GrGLSLFragmentShaderBuilder.h\"\n"
  104. "#include \"src/gpu/glsl/GrGLSLProgramBuilder.h\"\n"
  105. "#include \"src/sksl/SkSLCPP.h\"\n"
  106. "#include \"src/sksl/SkSLUtil.h\"\n"
  107. "class GrGLSLTest : public GrGLSLFragmentProcessor {\n"
  108. "public:\n"
  109. " GrGLSLTest() {}\n"
  110. " void emitCode(EmitArgs& args) override {\n"
  111. " GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;\n"
  112. " const GrTest& _outer = args.fFp.cast<GrTest>();\n"
  113. " (void) _outer;\n"
  114. " fragBuilder->codeAppendf(\"%s = half4(1.0);\\n\", args.fOutputColor);\n"
  115. " }\n"
  116. "private:\n"
  117. " void onSetData(const GrGLSLProgramDataManager& pdman, "
  118. "const GrFragmentProcessor& _proc) override {\n"
  119. " }\n"
  120. "};\n"
  121. "GrGLSLFragmentProcessor* GrTest::onCreateGLSLInstance() const {\n"
  122. " return new GrGLSLTest();\n"
  123. "}\n"
  124. "void GrTest::onGetGLSLProcessorKey(const GrShaderCaps& caps, "
  125. "GrProcessorKeyBuilder* b) const {\n"
  126. "}\n"
  127. "bool GrTest::onIsEqual(const GrFragmentProcessor& other) const {\n"
  128. " const GrTest& that = other.cast<GrTest>();\n"
  129. " (void) that;\n"
  130. " return true;\n"
  131. "}\n"
  132. "GrTest::GrTest(const GrTest& src)\n"
  133. ": INHERITED(kGrTest_ClassID, src.optimizationFlags()) {\n"
  134. "}\n"
  135. "std::unique_ptr<GrFragmentProcessor> GrTest::clone() const {\n"
  136. " return std::unique_ptr<GrFragmentProcessor>(new GrTest(*this));\n"
  137. "}\n"
  138. });
  139. }
  140. DEF_TEST(SkSLFPInput, r) {
  141. test(r,
  142. "in half2 point;"
  143. "void main() {"
  144. "sk_OutColor = half4(point, point);"
  145. "}",
  146. *SkSL::ShaderCapsFactory::Default(),
  147. {
  148. "static std::unique_ptr<GrFragmentProcessor> Make(SkPoint point) {",
  149. "return std::unique_ptr<GrFragmentProcessor>(new GrTest(point));",
  150. "GrTest(SkPoint point)",
  151. ", point(point)"
  152. },
  153. {
  154. "fragBuilder->codeAppendf(\"%s = half4(half2(%f, %f), half2(%f, %f));\\n\", "
  155. "args.fOutputColor, _outer.point.fX, _outer.point.fY, "
  156. "_outer.point.fX, _outer.point.fY);",
  157. "if (point != that.point) return false;"
  158. });
  159. }
  160. DEF_TEST(SkSLFPUniform, r) {
  161. test(r,
  162. "uniform half4 color;"
  163. "void main() {"
  164. "sk_OutColor = color;"
  165. "}",
  166. *SkSL::ShaderCapsFactory::Default(),
  167. {
  168. "static std::unique_ptr<GrFragmentProcessor> Make()"
  169. },
  170. {
  171. "colorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "
  172. "\"color\");",
  173. });
  174. }
  175. // SkSLFPInUniform tests the simplest plumbing case, default type, no tracking
  176. // with a setUniform template that supports inlining the value call with no
  177. // local variable.
  178. DEF_TEST(SkSLFPInUniform, r) {
  179. test(r,
  180. "in uniform half4 color;"
  181. "void main() {"
  182. "sk_OutColor = color;"
  183. "}",
  184. *SkSL::ShaderCapsFactory::Default(),
  185. {
  186. "static std::unique_ptr<GrFragmentProcessor> Make(SkRect color) {",
  187. },
  188. {
  189. "colorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "
  190. "\"color\");",
  191. "pdman.set4fv(colorVar, 1, reinterpret_cast<const float*>(&(_outer.color)));"
  192. });
  193. }
  194. // As above, but tests in uniform's ability to override the default ctype.
  195. DEF_TEST(SkSLFPInUniformCType, r) {
  196. test(r,
  197. "layout(ctype=SkPMColor4f) in uniform half4 color;"
  198. "void main() {"
  199. "sk_OutColor = color;"
  200. "}",
  201. *SkSL::ShaderCapsFactory::Default(),
  202. {
  203. "static std::unique_ptr<GrFragmentProcessor> Make(SkPMColor4f color) {",
  204. },
  205. {
  206. "colorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "
  207. "\"color\");",
  208. "pdman.set4fv(colorVar, 1, (_outer.color).vec());"
  209. });
  210. }
  211. // Add state tracking to the default typed SkRect <-> half4 uniform. But since
  212. // it now has to track state, the value inlining previously done for the
  213. // setUniform call is removed in favor of a local variable.
  214. DEF_TEST(SkSLFPTrackedInUniform, r) {
  215. test(r,
  216. "layout(tracked) in uniform half4 color;"
  217. "void main() {"
  218. "sk_OutColor = color;"
  219. "}",
  220. *SkSL::ShaderCapsFactory::Default(),
  221. {
  222. "static std::unique_ptr<GrFragmentProcessor> Make(SkRect color) {",
  223. },
  224. {
  225. "SkRect colorPrev = SkRect::MakeEmpty();",
  226. "colorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "
  227. "\"color\");",
  228. "const SkRect& colorValue = _outer.color;",
  229. "if (colorPrev.isEmpty() || colorPrev != colorValue) {",
  230. "colorPrev = colorValue;",
  231. "pdman.set4fv(colorVar, 1, reinterpret_cast<const float*>(&colorValue));"
  232. });
  233. }
  234. // Test the case where the template does not support variable inlining in
  235. // setUniform (i.e. it references the value multiple times).
  236. DEF_TEST(SkSLFPNonInlinedInUniform, r) {
  237. test(r,
  238. "in uniform half2 point;"
  239. "void main() {"
  240. "sk_OutColor = half4(point, point);"
  241. "}",
  242. *SkSL::ShaderCapsFactory::Default(),
  243. {
  244. "static std::unique_ptr<GrFragmentProcessor> Make(SkPoint point) {",
  245. },
  246. {
  247. "pointVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType, "
  248. "\"point\");",
  249. "const SkPoint& pointValue = _outer.point;",
  250. "pdman.set2f(pointVar, pointValue.fX, pointValue.fY);"
  251. });
  252. }
  253. // Test handling conditional uniforms (that use when= in layout), combined with
  254. // state tracking and custom ctypes to really put the code generation through its paces.
  255. DEF_TEST(SkSLFPConditionalInUniform, r) {
  256. test(r,
  257. "in bool test;"
  258. "layout(ctype=SkPMColor4f, tracked, when=test) in uniform half4 color;"
  259. "void main() {"
  260. " if (test) {"
  261. " sk_OutColor = color;"
  262. " } else {"
  263. " sk_OutColor = half4(1);"
  264. " }"
  265. "}",
  266. *SkSL::ShaderCapsFactory::Default(),
  267. {
  268. "static std::unique_ptr<GrFragmentProcessor> Make(bool test, SkPMColor4f color) {",
  269. },
  270. {
  271. "SkPMColor4f colorPrev = {SK_FloatNaN, SK_FloatNaN, SK_FloatNaN, SK_FloatNaN}",
  272. "auto test = _outer.test;",
  273. "if (test) {",
  274. "colorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "
  275. "\"color\");",
  276. "if (colorVar.isValid()) {",
  277. "const SkPMColor4f& colorValue = _outer.color;",
  278. "if (colorPrev != colorValue) {",
  279. "colorPrev = colorValue;",
  280. "pdman.set4fv(colorVar, 1, colorValue.vec());"
  281. });
  282. }
  283. DEF_TEST(SkSLFPSections, r) {
  284. test(r,
  285. "@header { header section }"
  286. "void main() {"
  287. "sk_OutColor = half4(1);"
  288. "}",
  289. *SkSL::ShaderCapsFactory::Default(),
  290. {
  291. "header section"
  292. },
  293. {});
  294. test(r,
  295. "@class { class section }"
  296. "void main() {"
  297. "sk_OutColor = half4(1);"
  298. "}",
  299. *SkSL::ShaderCapsFactory::Default(),
  300. {
  301. "class GrTest : public GrFragmentProcessor {\n"
  302. "public:\n"
  303. " class section"
  304. },
  305. {});
  306. test(r,
  307. "@cpp { cpp section }"
  308. "void main() {"
  309. "sk_OutColor = half4(1);"
  310. "}",
  311. *SkSL::ShaderCapsFactory::Default(),
  312. {},
  313. {"cpp section"});
  314. test(r,
  315. "@constructorParams { int x, float y, std::vector<float> z }"
  316. "in float w;"
  317. "void main() {"
  318. "sk_OutColor = half4(1);"
  319. "}",
  320. *SkSL::ShaderCapsFactory::Default(),
  321. {
  322. "Make(float w, int x, float y, std::vector<float> z )",
  323. "return std::unique_ptr<GrFragmentProcessor>(new GrTest(w, x, y, z));",
  324. "GrTest(float w, int x, float y, std::vector<float> z )",
  325. ", w(w) {"
  326. },
  327. {});
  328. test(r,
  329. "@constructor { constructor section }"
  330. "void main() {"
  331. "sk_OutColor = half4(1);"
  332. "}",
  333. *SkSL::ShaderCapsFactory::Default(),
  334. {
  335. "private:\n constructor section"
  336. },
  337. {});
  338. test(r,
  339. "@initializers { initializers section }"
  340. "void main() {"
  341. "sk_OutColor = half4(1);"
  342. "}",
  343. *SkSL::ShaderCapsFactory::Default(),
  344. {
  345. ": INHERITED(kGrTest_ClassID, kNone_OptimizationFlags)\n , initializers section"
  346. },
  347. {});
  348. test(r,
  349. "half x = 10;"
  350. "@emitCode { fragBuilder->codeAppendf(\"half y = %d\\n\", x * 2); }"
  351. "void main() {"
  352. "sk_OutColor = half4(1);"
  353. "}",
  354. *SkSL::ShaderCapsFactory::Default(),
  355. {},
  356. {
  357. "x = 10.0;\n"
  358. " fragBuilder->codeAppendf(\"half y = %d\\n\", x * 2);"
  359. });
  360. test(r,
  361. "@fields { fields section }"
  362. "@clone { }"
  363. "void main() {"
  364. "sk_OutColor = half4(1);"
  365. "}",
  366. *SkSL::ShaderCapsFactory::Default(),
  367. {
  368. "const char* name() const override { return \"Test\"; }\n"
  369. " fields section private:"
  370. },
  371. {});
  372. test(r,
  373. "@make { make section }"
  374. "void main() {"
  375. "sk_OutColor = half4(1);"
  376. "}",
  377. *SkSL::ShaderCapsFactory::Default(),
  378. {
  379. "public:\n"
  380. " make section"
  381. },
  382. {});
  383. test(r,
  384. "uniform half calculated;"
  385. "in half provided;"
  386. "@setData(varName) { varName.set1f(calculated, provided * 2); }"
  387. "void main() {"
  388. "sk_OutColor = half4(1);"
  389. "}",
  390. *SkSL::ShaderCapsFactory::Default(),
  391. {},
  392. {
  393. "void onSetData(const GrGLSLProgramDataManager& varName, "
  394. "const GrFragmentProcessor& _proc) override {\n",
  395. "UniformHandle& calculated = calculatedVar;",
  396. "auto provided = _outer.provided;",
  397. "varName.set1f(calculated, provided * 2);"
  398. });
  399. test(r,
  400. "@test(testDataName) { testDataName section }"
  401. "void main() {"
  402. "sk_OutColor = half4(1);"
  403. "}",
  404. *SkSL::ShaderCapsFactory::Default(),
  405. {},
  406. {
  407. "#if GR_TEST_UTILS\n"
  408. "std::unique_ptr<GrFragmentProcessor> GrTest::TestCreate(GrProcessorTestData* testDataName) {\n"
  409. " testDataName section }\n"
  410. "#endif"
  411. });
  412. }
  413. DEF_TEST(SkSLFPTransformedCoords, r) {
  414. test(r,
  415. "void main() {"
  416. "sk_OutColor = half4(sk_TransformedCoords2D[0], sk_TransformedCoords2D[0]);"
  417. "}",
  418. *SkSL::ShaderCapsFactory::Default(),
  419. {},
  420. {
  421. "SkString sk_TransformedCoords2D_0 = "
  422. "fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);",
  423. "fragBuilder->codeAppendf(\"%s = half4(%s, %s);\\n\", args.fOutputColor, "
  424. "sk_TransformedCoords2D_0.c_str(), sk_TransformedCoords2D_0.c_str());"
  425. });
  426. }
  427. DEF_TEST(SkSLFPLayoutWhen, r) {
  428. test(r,
  429. "layout(when=someExpression(someOtherExpression())) uniform half sometimes;"
  430. "void main() {"
  431. "}",
  432. *SkSL::ShaderCapsFactory::Default(),
  433. {},
  434. {
  435. "if (someExpression(someOtherExpression())) {\n"
  436. " sometimesVar = args.fUniformHandler->addUniform"
  437. });
  438. }
  439. DEF_TEST(SkSLFPChildProcessors, r) {
  440. test(r,
  441. "in fragmentProcessor child1;"
  442. "in fragmentProcessor child2;"
  443. "void main() {"
  444. " sk_OutColor = process(child1) * process(child2);"
  445. "}",
  446. *SkSL::ShaderCapsFactory::Default(),
  447. {
  448. "this->registerChildProcessor(std::move(child1));",
  449. "this->registerChildProcessor(std::move(child2));"
  450. },
  451. {
  452. "SkString _child0(\"_child0\");",
  453. "this->emitChild(_outer.child1_index, &_child0, args);",
  454. "SkString _child1(\"_child1\");",
  455. "this->emitChild(_outer.child2_index, &_child1, args);",
  456. "this->registerChildProcessor(src.childProcessor(child1_index).clone());",
  457. "this->registerChildProcessor(src.childProcessor(child2_index).clone());"
  458. });
  459. }
  460. DEF_TEST(SkSLFPChildProcessorsWithInput, r) {
  461. test(r,
  462. "in fragmentProcessor child1;"
  463. "in fragmentProcessor child2;"
  464. "void main() {"
  465. " half4 childIn = sk_InColor;"
  466. " half4 childOut1 = process(child1, childIn);"
  467. " half4 childOut2 = process(child2, childOut1);"
  468. " sk_OutColor = childOut2;"
  469. "}",
  470. *SkSL::ShaderCapsFactory::Default(),
  471. {
  472. "this->registerChildProcessor(std::move(child1));",
  473. "this->registerChildProcessor(std::move(child2));"
  474. },
  475. {
  476. "SkString _input0(\"childIn\");",
  477. "SkString _child0(\"_child0\");",
  478. "this->emitChild(_outer.child1_index, _input0.c_str(), &_child0, args);",
  479. "SkString _input1(\"childOut1\");",
  480. "SkString _child1(\"_child1\");",
  481. "this->emitChild(_outer.child2_index, _input1.c_str(), &_child1, args);",
  482. "this->registerChildProcessor(src.childProcessor(child1_index).clone());",
  483. "this->registerChildProcessor(src.childProcessor(child2_index).clone());"
  484. });
  485. }
  486. DEF_TEST(SkSLFPChildProcessorWithInputExpression, r) {
  487. test(r,
  488. "in fragmentProcessor child;"
  489. "void main() {"
  490. " sk_OutColor = process(child, sk_InColor * half4(0.5));"
  491. "}",
  492. *SkSL::ShaderCapsFactory::Default(),
  493. {
  494. "this->registerChildProcessor(std::move(child));",
  495. },
  496. {
  497. "SkString _input0 = SkStringPrintf(\"%s * half4(0.5)\", args.fInputColor);",
  498. "SkString _child0(\"_child0\");",
  499. "this->emitChild(_outer.child_index, _input0.c_str(), &_child0, args);",
  500. "this->registerChildProcessor(src.childProcessor(child_index).clone());",
  501. });
  502. }
  503. DEF_TEST(SkSLFPNestedChildProcessors, r) {
  504. test(r,
  505. "in fragmentProcessor child1;"
  506. "in fragmentProcessor child2;"
  507. "void main() {"
  508. " sk_OutColor = process(child2, sk_InColor * process(child1, sk_InColor * half4(0.5)));"
  509. "}",
  510. *SkSL::ShaderCapsFactory::Default(),
  511. {
  512. "this->registerChildProcessor(std::move(child1));",
  513. "this->registerChildProcessor(std::move(child2));"
  514. },
  515. {
  516. "SkString _input0 = SkStringPrintf(\"%s * half4(0.5)\", args.fInputColor);",
  517. "SkString _child0(\"_child0\");",
  518. "this->emitChild(_outer.child1_index, _input0.c_str(), &_child0, args);",
  519. "SkString _input1 = SkStringPrintf(\"%s * %s\", args.fInputColor, _child0.c_str());",
  520. "SkString _child1(\"_child1\");",
  521. "this->emitChild(_outer.child2_index, _input1.c_str(), &_child1, args);",
  522. "this->registerChildProcessor(src.childProcessor(child1_index).clone());",
  523. "this->registerChildProcessor(src.childProcessor(child2_index).clone());"
  524. });
  525. }
  526. DEF_TEST(SkSLFPChildFPAndGlobal, r) {
  527. test(r,
  528. "in fragmentProcessor child;"
  529. "bool hasCap = sk_Caps.externalTextureSupport;"
  530. "void main() {"
  531. " if (hasCap) {"
  532. " sk_OutColor = process(child, sk_InColor);"
  533. " } else {"
  534. " sk_OutColor = half4(1);"
  535. " }"
  536. "}",
  537. *SkSL::ShaderCapsFactory::Default(),
  538. {
  539. "this->registerChildProcessor(std::move(child));"
  540. },
  541. {
  542. "hasCap = sk_Caps.externalTextureSupport;",
  543. "fragBuilder->codeAppendf(\"bool hasCap = %s;\\nif (hasCap) {\", "
  544. "(hasCap ? \"true\" : \"false\"));",
  545. "SkString _input0 = SkStringPrintf(\"%s\", args.fInputColor);",
  546. "SkString _child0(\"_child0\");",
  547. "this->emitChild(_outer.child_index, _input0.c_str(), &_child0, args);",
  548. "fragBuilder->codeAppendf(\"\\n %s = %s;\\n} else {\\n %s = half4(1.0);\\n}"
  549. "\\n\", args.fOutputColor, _child0.c_str(), args.fOutputColor);",
  550. "this->registerChildProcessor(src.childProcessor(child_index).clone());"
  551. });
  552. }
  553. DEF_TEST(SkSLFPChildProcessorInlineFieldAccess, r) {
  554. test(r,
  555. "in fragmentProcessor child;"
  556. "void main() {"
  557. " if (child.preservesOpaqueInput) {"
  558. " sk_OutColor = process(child, sk_InColor);"
  559. " } else {"
  560. " sk_OutColor = half4(1);"
  561. " }"
  562. "}",
  563. *SkSL::ShaderCapsFactory::Default(),
  564. {
  565. "this->registerChildProcessor(std::move(child));"
  566. },
  567. {
  568. "fragBuilder->codeAppendf(\"if (%s) {\", "
  569. "(_outer.childProcessor(_outer.child_index).preservesOpaqueInput() ? "
  570. "\"true\" : \"false\"));",
  571. "SkString _input0 = SkStringPrintf(\"%s\", args.fInputColor);",
  572. "SkString _child0(\"_child0\");",
  573. "this->emitChild(_outer.child_index, _input0.c_str(), &_child0, args);",
  574. "fragBuilder->codeAppendf(\"\\n %s = %s;\\n} else {\\n %s = half4(1.0);\\n}\\n\""
  575. ", args.fOutputColor, _child0.c_str(), args.fOutputColor);",
  576. "this->registerChildProcessor(src.childProcessor(child_index).clone());"
  577. });
  578. }
  579. DEF_TEST(SkSLFPChildProcessorFieldAccess, r) {
  580. test(r,
  581. "in fragmentProcessor child;"
  582. "bool opaque = child.preservesOpaqueInput;"
  583. "void main() {"
  584. " if (opaque) {"
  585. " sk_OutColor = process(child);"
  586. " } else {"
  587. " sk_OutColor = half4(0.5);"
  588. " }"
  589. "}",
  590. *SkSL::ShaderCapsFactory::Default(),
  591. {
  592. "this->registerChildProcessor(std::move(child));"
  593. },
  594. {
  595. "opaque = _outer.childProcessor(_outer.child_index).preservesOpaqueInput();",
  596. "fragBuilder->codeAppendf(\"bool opaque = %s;\\nif (opaque) {\", "
  597. "(opaque ? \"true\" : \"false\"));",
  598. "SkString _child0(\"_child0\");",
  599. "this->emitChild(_outer.child_index, &_child0, args);",
  600. "fragBuilder->codeAppendf(\"\\n %s = %s;\\n} else {\\n %s = half4(0.5);\\n}\\n\""
  601. ", args.fOutputColor, _child0.c_str(), args.fOutputColor);",
  602. "this->registerChildProcessor(src.childProcessor(child_index).clone());"
  603. });
  604. }
  605. DEF_TEST(SkSLFPNullableChildProcessor, r) {
  606. test(r,
  607. "in fragmentProcessor? child;"
  608. "void main() {"
  609. " if (child != null) {"
  610. " sk_OutColor = process(child);"
  611. " } else {"
  612. " sk_OutColor = half4(0.5);"
  613. " }"
  614. "}",
  615. *SkSL::ShaderCapsFactory::Default(),
  616. {},
  617. {
  618. "SkString _child0(\"_child0\");",
  619. "if (_outer.child_index >= 0) {",
  620. "this->emitChild(_outer.child_index, &_child0, args);",
  621. "} else {",
  622. "fragBuilder->codeAppendf(\"half4 %s;\", _child0.c_str());",
  623. "}",
  624. "fragBuilder->codeAppendf(\"\\n %s = %s;\\n} else {\\n %s = half4(0.5);\\n}\\n\""
  625. ", args.fOutputColor, _child0.c_str(), args.fOutputColor);",
  626. });
  627. }