123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651 |
- /*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #include "src/sksl/SkSLCompiler.h"
- #include "src/sksl/SkSLStringStream.h"
- #include "tests/Test.h"
- static void test(skiatest::Reporter* r, const char* src, const GrShaderCaps& caps,
- std::vector<const char*> expectedH, std::vector<const char*> expectedCPP) {
- SkSL::Program::Settings settings;
- settings.fCaps = ∩︀
- SkSL::Compiler compiler;
- SkSL::StringStream output;
- std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
- SkSL::Program::kFragmentProcessor_Kind,
- SkSL::String(src),
- settings);
- if (!program) {
- SkDebugf("Unexpected error compiling %s\n%s", src, compiler.errorText().c_str());
- return;
- }
- REPORTER_ASSERT(r, program);
- bool success = compiler.toH(*program, "Test", output);
- if (!success) {
- SkDebugf("Unexpected error compiling %s\n%s", src, compiler.errorText().c_str());
- }
- REPORTER_ASSERT(r, success);
- if (success) {
- for (const char* expected : expectedH) {
- bool found = strstr(output.str().c_str(), expected);
- if (!found) {
- SkDebugf("HEADER MISMATCH:\nsource:\n%s\n\nexpected:\n'%s'\n\nreceived:\n'%s'", src,
- expected, output.str().c_str());
- }
- REPORTER_ASSERT(r, found);
- }
- }
- output.reset();
- success = compiler.toCPP(*program, "Test", output);
- if (!success) {
- SkDebugf("Unexpected error compiling %s\n%s", src, compiler.errorText().c_str());
- }
- REPORTER_ASSERT(r, success);
- if (success) {
- for (const char* expected : expectedCPP) {
- bool found = strstr(output.str().c_str(), expected);
- if (!found) {
- SkDebugf("CPP MISMATCH:\nsource:\n%s\n\nexpected:\n'%s'\n\nreceived:\n'%s'", src,
- expected, output.str().c_str());
- }
- REPORTER_ASSERT(r, found);
- }
- }
- }
- DEF_TEST(SkSLFPHelloWorld, r) {
- test(r,
- "/* HEADER */"
- "void main() {"
- "sk_OutColor = half4(1);"
- "}",
- *SkSL::ShaderCapsFactory::Default(),
- {
- "/* HEADER */\n"
- "\n"
- "/**************************************************************************************************\n"
- " *** This file was autogenerated from GrTest.fp; do not modify.\n"
- " **************************************************************************************************/\n"
- "#ifndef GrTest_DEFINED\n"
- "#define GrTest_DEFINED\n"
- "#include \"include/core/SkTypes.h\"\n\n"
- "#include \"src/gpu/GrCoordTransform.h\"\n"
- "#include \"src/gpu/GrFragmentProcessor.h\"\n"
- "class GrTest : public GrFragmentProcessor {\n"
- "public:\n"
- " static std::unique_ptr<GrFragmentProcessor> Make() {\n"
- " return std::unique_ptr<GrFragmentProcessor>(new GrTest());\n"
- " }\n"
- " GrTest(const GrTest& src);\n"
- " std::unique_ptr<GrFragmentProcessor> clone() const override;\n"
- " const char* name() const override { return \"Test\"; }\n"
- "private:\n"
- " GrTest()\n"
- " : INHERITED(kGrTest_ClassID, kNone_OptimizationFlags) {\n"
- " }\n"
- " GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;\n"
- " void onGetGLSLProcessorKey(const GrShaderCaps&,GrProcessorKeyBuilder*) const "
- "override;\n"
- " bool onIsEqual(const GrFragmentProcessor&) const override;\n"
- " GR_DECLARE_FRAGMENT_PROCESSOR_TEST\n"
- " typedef GrFragmentProcessor INHERITED;\n"
- "};\n"
- "#endif\n"
- },
- {
- "/**************************************************************************************************\n"
- " *** This file was autogenerated from GrTest.fp; do not modify.\n"
- " **************************************************************************************************/\n"
- "#include \"GrTest.h\"\n\n"
- "#include \"include/gpu/GrTexture.h\"\n"
- "#include \"src/gpu/glsl/GrGLSLFragmentProcessor.h\"\n"
- "#include \"src/gpu/glsl/GrGLSLFragmentShaderBuilder.h\"\n"
- "#include \"src/gpu/glsl/GrGLSLProgramBuilder.h\"\n"
- "#include \"src/sksl/SkSLCPP.h\"\n"
- "#include \"src/sksl/SkSLUtil.h\"\n"
- "class GrGLSLTest : public GrGLSLFragmentProcessor {\n"
- "public:\n"
- " GrGLSLTest() {}\n"
- " void emitCode(EmitArgs& args) override {\n"
- " GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;\n"
- " const GrTest& _outer = args.fFp.cast<GrTest>();\n"
- " (void) _outer;\n"
- " fragBuilder->codeAppendf(\"%s = half4(1.0);\\n\", args.fOutputColor);\n"
- " }\n"
- "private:\n"
- " void onSetData(const GrGLSLProgramDataManager& pdman, "
- "const GrFragmentProcessor& _proc) override {\n"
- " }\n"
- "};\n"
- "GrGLSLFragmentProcessor* GrTest::onCreateGLSLInstance() const {\n"
- " return new GrGLSLTest();\n"
- "}\n"
- "void GrTest::onGetGLSLProcessorKey(const GrShaderCaps& caps, "
- "GrProcessorKeyBuilder* b) const {\n"
- "}\n"
- "bool GrTest::onIsEqual(const GrFragmentProcessor& other) const {\n"
- " const GrTest& that = other.cast<GrTest>();\n"
- " (void) that;\n"
- " return true;\n"
- "}\n"
- "GrTest::GrTest(const GrTest& src)\n"
- ": INHERITED(kGrTest_ClassID, src.optimizationFlags()) {\n"
- "}\n"
- "std::unique_ptr<GrFragmentProcessor> GrTest::clone() const {\n"
- " return std::unique_ptr<GrFragmentProcessor>(new GrTest(*this));\n"
- "}\n"
- });
- }
- DEF_TEST(SkSLFPInput, r) {
- test(r,
- "in half2 point;"
- "void main() {"
- "sk_OutColor = half4(point, point);"
- "}",
- *SkSL::ShaderCapsFactory::Default(),
- {
- "static std::unique_ptr<GrFragmentProcessor> Make(SkPoint point) {",
- "return std::unique_ptr<GrFragmentProcessor>(new GrTest(point));",
- "GrTest(SkPoint point)",
- ", point(point)"
- },
- {
- "fragBuilder->codeAppendf(\"%s = half4(half2(%f, %f), half2(%f, %f));\\n\", "
- "args.fOutputColor, _outer.point.fX, _outer.point.fY, "
- "_outer.point.fX, _outer.point.fY);",
- "if (point != that.point) return false;"
- });
- }
- DEF_TEST(SkSLFPUniform, r) {
- test(r,
- "uniform half4 color;"
- "void main() {"
- "sk_OutColor = color;"
- "}",
- *SkSL::ShaderCapsFactory::Default(),
- {
- "static std::unique_ptr<GrFragmentProcessor> Make()"
- },
- {
- "colorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "
- "\"color\");",
- });
- }
- // SkSLFPInUniform tests the simplest plumbing case, default type, no tracking
- // with a setUniform template that supports inlining the value call with no
- // local variable.
- DEF_TEST(SkSLFPInUniform, r) {
- test(r,
- "in uniform half4 color;"
- "void main() {"
- "sk_OutColor = color;"
- "}",
- *SkSL::ShaderCapsFactory::Default(),
- {
- "static std::unique_ptr<GrFragmentProcessor> Make(SkRect color) {",
- },
- {
- "colorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "
- "\"color\");",
- "pdman.set4fv(colorVar, 1, reinterpret_cast<const float*>(&(_outer.color)));"
- });
- }
- // As above, but tests in uniform's ability to override the default ctype.
- DEF_TEST(SkSLFPInUniformCType, r) {
- test(r,
- "layout(ctype=SkPMColor4f) in uniform half4 color;"
- "void main() {"
- "sk_OutColor = color;"
- "}",
- *SkSL::ShaderCapsFactory::Default(),
- {
- "static std::unique_ptr<GrFragmentProcessor> Make(SkPMColor4f color) {",
- },
- {
- "colorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "
- "\"color\");",
- "pdman.set4fv(colorVar, 1, (_outer.color).vec());"
- });
- }
- // Add state tracking to the default typed SkRect <-> half4 uniform. But since
- // it now has to track state, the value inlining previously done for the
- // setUniform call is removed in favor of a local variable.
- DEF_TEST(SkSLFPTrackedInUniform, r) {
- test(r,
- "layout(tracked) in uniform half4 color;"
- "void main() {"
- "sk_OutColor = color;"
- "}",
- *SkSL::ShaderCapsFactory::Default(),
- {
- "static std::unique_ptr<GrFragmentProcessor> Make(SkRect color) {",
- },
- {
- "SkRect colorPrev = SkRect::MakeEmpty();",
- "colorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "
- "\"color\");",
- "const SkRect& colorValue = _outer.color;",
- "if (colorPrev.isEmpty() || colorPrev != colorValue) {",
- "colorPrev = colorValue;",
- "pdman.set4fv(colorVar, 1, reinterpret_cast<const float*>(&colorValue));"
- });
- }
- // Test the case where the template does not support variable inlining in
- // setUniform (i.e. it references the value multiple times).
- DEF_TEST(SkSLFPNonInlinedInUniform, r) {
- test(r,
- "in uniform half2 point;"
- "void main() {"
- "sk_OutColor = half4(point, point);"
- "}",
- *SkSL::ShaderCapsFactory::Default(),
- {
- "static std::unique_ptr<GrFragmentProcessor> Make(SkPoint point) {",
- },
- {
- "pointVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType, "
- "\"point\");",
- "const SkPoint& pointValue = _outer.point;",
- "pdman.set2f(pointVar, pointValue.fX, pointValue.fY);"
- });
- }
- // Test handling conditional uniforms (that use when= in layout), combined with
- // state tracking and custom ctypes to really put the code generation through its paces.
- DEF_TEST(SkSLFPConditionalInUniform, r) {
- test(r,
- "in bool test;"
- "layout(ctype=SkPMColor4f, tracked, when=test) in uniform half4 color;"
- "void main() {"
- " if (test) {"
- " sk_OutColor = color;"
- " } else {"
- " sk_OutColor = half4(1);"
- " }"
- "}",
- *SkSL::ShaderCapsFactory::Default(),
- {
- "static std::unique_ptr<GrFragmentProcessor> Make(bool test, SkPMColor4f color) {",
- },
- {
- "SkPMColor4f colorPrev = {SK_FloatNaN, SK_FloatNaN, SK_FloatNaN, SK_FloatNaN}",
- "auto test = _outer.test;",
- "if (test) {",
- "colorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "
- "\"color\");",
- "if (colorVar.isValid()) {",
- "const SkPMColor4f& colorValue = _outer.color;",
- "if (colorPrev != colorValue) {",
- "colorPrev = colorValue;",
- "pdman.set4fv(colorVar, 1, colorValue.vec());"
- });
- }
- DEF_TEST(SkSLFPSections, r) {
- test(r,
- "@header { header section }"
- "void main() {"
- "sk_OutColor = half4(1);"
- "}",
- *SkSL::ShaderCapsFactory::Default(),
- {
- "header section"
- },
- {});
- test(r,
- "@class { class section }"
- "void main() {"
- "sk_OutColor = half4(1);"
- "}",
- *SkSL::ShaderCapsFactory::Default(),
- {
- "class GrTest : public GrFragmentProcessor {\n"
- "public:\n"
- " class section"
- },
- {});
- test(r,
- "@cpp { cpp section }"
- "void main() {"
- "sk_OutColor = half4(1);"
- "}",
- *SkSL::ShaderCapsFactory::Default(),
- {},
- {"cpp section"});
- test(r,
- "@constructorParams { int x, float y, std::vector<float> z }"
- "in float w;"
- "void main() {"
- "sk_OutColor = half4(1);"
- "}",
- *SkSL::ShaderCapsFactory::Default(),
- {
- "Make(float w, int x, float y, std::vector<float> z )",
- "return std::unique_ptr<GrFragmentProcessor>(new GrTest(w, x, y, z));",
- "GrTest(float w, int x, float y, std::vector<float> z )",
- ", w(w) {"
- },
- {});
- test(r,
- "@constructor { constructor section }"
- "void main() {"
- "sk_OutColor = half4(1);"
- "}",
- *SkSL::ShaderCapsFactory::Default(),
- {
- "private:\n constructor section"
- },
- {});
- test(r,
- "@initializers { initializers section }"
- "void main() {"
- "sk_OutColor = half4(1);"
- "}",
- *SkSL::ShaderCapsFactory::Default(),
- {
- ": INHERITED(kGrTest_ClassID, kNone_OptimizationFlags)\n , initializers section"
- },
- {});
- test(r,
- "half x = 10;"
- "@emitCode { fragBuilder->codeAppendf(\"half y = %d\\n\", x * 2); }"
- "void main() {"
- "sk_OutColor = half4(1);"
- "}",
- *SkSL::ShaderCapsFactory::Default(),
- {},
- {
- "x = 10.0;\n"
- " fragBuilder->codeAppendf(\"half y = %d\\n\", x * 2);"
- });
- test(r,
- "@fields { fields section }"
- "@clone { }"
- "void main() {"
- "sk_OutColor = half4(1);"
- "}",
- *SkSL::ShaderCapsFactory::Default(),
- {
- "const char* name() const override { return \"Test\"; }\n"
- " fields section private:"
- },
- {});
- test(r,
- "@make { make section }"
- "void main() {"
- "sk_OutColor = half4(1);"
- "}",
- *SkSL::ShaderCapsFactory::Default(),
- {
- "public:\n"
- " make section"
- },
- {});
- test(r,
- "uniform half calculated;"
- "in half provided;"
- "@setData(varName) { varName.set1f(calculated, provided * 2); }"
- "void main() {"
- "sk_OutColor = half4(1);"
- "}",
- *SkSL::ShaderCapsFactory::Default(),
- {},
- {
- "void onSetData(const GrGLSLProgramDataManager& varName, "
- "const GrFragmentProcessor& _proc) override {\n",
- "UniformHandle& calculated = calculatedVar;",
- "auto provided = _outer.provided;",
- "varName.set1f(calculated, provided * 2);"
- });
- test(r,
- "@test(testDataName) { testDataName section }"
- "void main() {"
- "sk_OutColor = half4(1);"
- "}",
- *SkSL::ShaderCapsFactory::Default(),
- {},
- {
- "#if GR_TEST_UTILS\n"
- "std::unique_ptr<GrFragmentProcessor> GrTest::TestCreate(GrProcessorTestData* testDataName) {\n"
- " testDataName section }\n"
- "#endif"
- });
- }
- DEF_TEST(SkSLFPTransformedCoords, r) {
- test(r,
- "void main() {"
- "sk_OutColor = half4(sk_TransformedCoords2D[0], sk_TransformedCoords2D[0]);"
- "}",
- *SkSL::ShaderCapsFactory::Default(),
- {},
- {
- "SkString sk_TransformedCoords2D_0 = "
- "fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);",
- "fragBuilder->codeAppendf(\"%s = half4(%s, %s);\\n\", args.fOutputColor, "
- "sk_TransformedCoords2D_0.c_str(), sk_TransformedCoords2D_0.c_str());"
- });
- }
- DEF_TEST(SkSLFPLayoutWhen, r) {
- test(r,
- "layout(when=someExpression(someOtherExpression())) uniform half sometimes;"
- "void main() {"
- "}",
- *SkSL::ShaderCapsFactory::Default(),
- {},
- {
- "if (someExpression(someOtherExpression())) {\n"
- " sometimesVar = args.fUniformHandler->addUniform"
- });
- }
- DEF_TEST(SkSLFPChildProcessors, r) {
- test(r,
- "in fragmentProcessor child1;"
- "in fragmentProcessor child2;"
- "void main() {"
- " sk_OutColor = process(child1) * process(child2);"
- "}",
- *SkSL::ShaderCapsFactory::Default(),
- {
- "this->registerChildProcessor(std::move(child1));",
- "this->registerChildProcessor(std::move(child2));"
- },
- {
- "SkString _child0(\"_child0\");",
- "this->emitChild(_outer.child1_index, &_child0, args);",
- "SkString _child1(\"_child1\");",
- "this->emitChild(_outer.child2_index, &_child1, args);",
- "this->registerChildProcessor(src.childProcessor(child1_index).clone());",
- "this->registerChildProcessor(src.childProcessor(child2_index).clone());"
- });
- }
- DEF_TEST(SkSLFPChildProcessorsWithInput, r) {
- test(r,
- "in fragmentProcessor child1;"
- "in fragmentProcessor child2;"
- "void main() {"
- " half4 childIn = sk_InColor;"
- " half4 childOut1 = process(child1, childIn);"
- " half4 childOut2 = process(child2, childOut1);"
- " sk_OutColor = childOut2;"
- "}",
- *SkSL::ShaderCapsFactory::Default(),
- {
- "this->registerChildProcessor(std::move(child1));",
- "this->registerChildProcessor(std::move(child2));"
- },
- {
- "SkString _input0(\"childIn\");",
- "SkString _child0(\"_child0\");",
- "this->emitChild(_outer.child1_index, _input0.c_str(), &_child0, args);",
- "SkString _input1(\"childOut1\");",
- "SkString _child1(\"_child1\");",
- "this->emitChild(_outer.child2_index, _input1.c_str(), &_child1, args);",
- "this->registerChildProcessor(src.childProcessor(child1_index).clone());",
- "this->registerChildProcessor(src.childProcessor(child2_index).clone());"
- });
- }
- DEF_TEST(SkSLFPChildProcessorWithInputExpression, r) {
- test(r,
- "in fragmentProcessor child;"
- "void main() {"
- " sk_OutColor = process(child, sk_InColor * half4(0.5));"
- "}",
- *SkSL::ShaderCapsFactory::Default(),
- {
- "this->registerChildProcessor(std::move(child));",
- },
- {
- "SkString _input0 = SkStringPrintf(\"%s * half4(0.5)\", args.fInputColor);",
- "SkString _child0(\"_child0\");",
- "this->emitChild(_outer.child_index, _input0.c_str(), &_child0, args);",
- "this->registerChildProcessor(src.childProcessor(child_index).clone());",
- });
- }
- DEF_TEST(SkSLFPNestedChildProcessors, r) {
- test(r,
- "in fragmentProcessor child1;"
- "in fragmentProcessor child2;"
- "void main() {"
- " sk_OutColor = process(child2, sk_InColor * process(child1, sk_InColor * half4(0.5)));"
- "}",
- *SkSL::ShaderCapsFactory::Default(),
- {
- "this->registerChildProcessor(std::move(child1));",
- "this->registerChildProcessor(std::move(child2));"
- },
- {
- "SkString _input0 = SkStringPrintf(\"%s * half4(0.5)\", args.fInputColor);",
- "SkString _child0(\"_child0\");",
- "this->emitChild(_outer.child1_index, _input0.c_str(), &_child0, args);",
- "SkString _input1 = SkStringPrintf(\"%s * %s\", args.fInputColor, _child0.c_str());",
- "SkString _child1(\"_child1\");",
- "this->emitChild(_outer.child2_index, _input1.c_str(), &_child1, args);",
- "this->registerChildProcessor(src.childProcessor(child1_index).clone());",
- "this->registerChildProcessor(src.childProcessor(child2_index).clone());"
- });
- }
- DEF_TEST(SkSLFPChildFPAndGlobal, r) {
- test(r,
- "in fragmentProcessor child;"
- "bool hasCap = sk_Caps.externalTextureSupport;"
- "void main() {"
- " if (hasCap) {"
- " sk_OutColor = process(child, sk_InColor);"
- " } else {"
- " sk_OutColor = half4(1);"
- " }"
- "}",
- *SkSL::ShaderCapsFactory::Default(),
- {
- "this->registerChildProcessor(std::move(child));"
- },
- {
- "hasCap = sk_Caps.externalTextureSupport;",
- "fragBuilder->codeAppendf(\"bool hasCap = %s;\\nif (hasCap) {\", "
- "(hasCap ? \"true\" : \"false\"));",
- "SkString _input0 = SkStringPrintf(\"%s\", args.fInputColor);",
- "SkString _child0(\"_child0\");",
- "this->emitChild(_outer.child_index, _input0.c_str(), &_child0, args);",
- "fragBuilder->codeAppendf(\"\\n %s = %s;\\n} else {\\n %s = half4(1.0);\\n}"
- "\\n\", args.fOutputColor, _child0.c_str(), args.fOutputColor);",
- "this->registerChildProcessor(src.childProcessor(child_index).clone());"
- });
- }
- DEF_TEST(SkSLFPChildProcessorInlineFieldAccess, r) {
- test(r,
- "in fragmentProcessor child;"
- "void main() {"
- " if (child.preservesOpaqueInput) {"
- " sk_OutColor = process(child, sk_InColor);"
- " } else {"
- " sk_OutColor = half4(1);"
- " }"
- "}",
- *SkSL::ShaderCapsFactory::Default(),
- {
- "this->registerChildProcessor(std::move(child));"
- },
- {
- "fragBuilder->codeAppendf(\"if (%s) {\", "
- "(_outer.childProcessor(_outer.child_index).preservesOpaqueInput() ? "
- "\"true\" : \"false\"));",
- "SkString _input0 = SkStringPrintf(\"%s\", args.fInputColor);",
- "SkString _child0(\"_child0\");",
- "this->emitChild(_outer.child_index, _input0.c_str(), &_child0, args);",
- "fragBuilder->codeAppendf(\"\\n %s = %s;\\n} else {\\n %s = half4(1.0);\\n}\\n\""
- ", args.fOutputColor, _child0.c_str(), args.fOutputColor);",
- "this->registerChildProcessor(src.childProcessor(child_index).clone());"
- });
- }
- DEF_TEST(SkSLFPChildProcessorFieldAccess, r) {
- test(r,
- "in fragmentProcessor child;"
- "bool opaque = child.preservesOpaqueInput;"
- "void main() {"
- " if (opaque) {"
- " sk_OutColor = process(child);"
- " } else {"
- " sk_OutColor = half4(0.5);"
- " }"
- "}",
- *SkSL::ShaderCapsFactory::Default(),
- {
- "this->registerChildProcessor(std::move(child));"
- },
- {
- "opaque = _outer.childProcessor(_outer.child_index).preservesOpaqueInput();",
- "fragBuilder->codeAppendf(\"bool opaque = %s;\\nif (opaque) {\", "
- "(opaque ? \"true\" : \"false\"));",
- "SkString _child0(\"_child0\");",
- "this->emitChild(_outer.child_index, &_child0, args);",
- "fragBuilder->codeAppendf(\"\\n %s = %s;\\n} else {\\n %s = half4(0.5);\\n}\\n\""
- ", args.fOutputColor, _child0.c_str(), args.fOutputColor);",
- "this->registerChildProcessor(src.childProcessor(child_index).clone());"
- });
- }
- DEF_TEST(SkSLFPNullableChildProcessor, r) {
- test(r,
- "in fragmentProcessor? child;"
- "void main() {"
- " if (child != null) {"
- " sk_OutColor = process(child);"
- " } else {"
- " sk_OutColor = half4(0.5);"
- " }"
- "}",
- *SkSL::ShaderCapsFactory::Default(),
- {},
- {
- "SkString _child0(\"_child0\");",
- "if (_outer.child_index >= 0) {",
- "this->emitChild(_outer.child_index, &_child0, args);",
- "} else {",
- "fragBuilder->codeAppendf(\"half4 %s;\", _child0.c_str());",
- "}",
- "fragBuilder->codeAppendf(\"\\n %s = %s;\\n} else {\\n %s = half4(0.5);\\n}\\n\""
- ", args.fOutputColor, _child0.c_str(), args.fOutputColor);",
- });
- }
|