GrXfermodeFragmentProcessor.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. /*
  2. * Copyright 2015 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/gpu/effects/GrXfermodeFragmentProcessor.h"
  8. #include "src/core/SkXfermodePriv.h"
  9. #include "src/gpu/GrFragmentProcessor.h"
  10. #include "src/gpu/SkGr.h"
  11. #include "src/gpu/effects/generated/GrConstColorProcessor.h"
  12. #include "src/gpu/glsl/GrGLSLBlend.h"
  13. #include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
  14. #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
  15. // Some of the cpu implementations of blend modes differ too much from the GPU enough that
  16. // we can't use the cpu implementation to implement constantOutputForConstantInput.
  17. static inline bool does_cpu_blend_impl_match_gpu(SkBlendMode mode) {
  18. // The non-seperable modes differ too much. So does SoftLight. ColorBurn differs too much on our
  19. // test iOS device (but we just disable it across the aboard since it may happen on untested
  20. // GPUs).
  21. return mode <= SkBlendMode::kLastSeparableMode && mode != SkBlendMode::kSoftLight &&
  22. mode != SkBlendMode::kColorBurn;
  23. }
  24. //////////////////////////////////////////////////////////////////////////////
  25. class ComposeTwoFragmentProcessor : public GrFragmentProcessor {
  26. public:
  27. static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> src,
  28. std::unique_ptr<GrFragmentProcessor> dst,
  29. SkBlendMode mode) {
  30. return std::unique_ptr<GrFragmentProcessor>(
  31. new ComposeTwoFragmentProcessor(std::move(src), std::move(dst), mode));
  32. }
  33. const char* name() const override { return "ComposeTwo"; }
  34. #ifdef SK_DEBUG
  35. SkString dumpInfo() const override {
  36. SkString str;
  37. str.appendf("Mode: %s", SkBlendMode_Name(fMode));
  38. for (int i = 0; i < this->numChildProcessors(); ++i) {
  39. str.appendf(" [%s %s]",
  40. this->childProcessor(i).name(), this->childProcessor(i).dumpInfo().c_str());
  41. }
  42. return str;
  43. }
  44. #endif
  45. std::unique_ptr<GrFragmentProcessor> clone() const override;
  46. SkBlendMode getMode() const { return fMode; }
  47. private:
  48. ComposeTwoFragmentProcessor(std::unique_ptr<GrFragmentProcessor> src,
  49. std::unique_ptr<GrFragmentProcessor> dst,
  50. SkBlendMode mode)
  51. : INHERITED(kComposeTwoFragmentProcessor_ClassID, OptFlags(src.get(), dst.get(), mode))
  52. , fMode(mode) {
  53. SkDEBUGCODE(int shaderAChildIndex = )this->registerChildProcessor(std::move(src));
  54. SkDEBUGCODE(int shaderBChildIndex = )this->registerChildProcessor(std::move(dst));
  55. SkASSERT(0 == shaderAChildIndex);
  56. SkASSERT(1 == shaderBChildIndex);
  57. }
  58. static OptimizationFlags OptFlags(const GrFragmentProcessor* src,
  59. const GrFragmentProcessor* dst, SkBlendMode mode) {
  60. OptimizationFlags flags;
  61. switch (mode) {
  62. case SkBlendMode::kClear:
  63. case SkBlendMode::kSrc:
  64. case SkBlendMode::kDst:
  65. SK_ABORT("Should never create clear, src, or dst compose two FP.");
  66. flags = kNone_OptimizationFlags;
  67. break;
  68. // Produces opaque if both src and dst are opaque.
  69. case SkBlendMode::kSrcIn:
  70. case SkBlendMode::kDstIn:
  71. case SkBlendMode::kModulate:
  72. flags = src->preservesOpaqueInput() && dst->preservesOpaqueInput()
  73. ? kPreservesOpaqueInput_OptimizationFlag
  74. : kNone_OptimizationFlags;
  75. break;
  76. // Produces zero when both are opaque, indeterminate if one is opaque.
  77. case SkBlendMode::kSrcOut:
  78. case SkBlendMode::kDstOut:
  79. case SkBlendMode::kXor:
  80. flags = kNone_OptimizationFlags;
  81. break;
  82. // Is opaque if the dst is opaque.
  83. case SkBlendMode::kSrcATop:
  84. flags = dst->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
  85. : kNone_OptimizationFlags;
  86. break;
  87. // DstATop is the converse of kSrcATop. Screen is also opaque if the src is a opaque.
  88. case SkBlendMode::kDstATop:
  89. case SkBlendMode::kScreen:
  90. flags = src->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
  91. : kNone_OptimizationFlags;
  92. break;
  93. // These modes are all opaque if either src or dst is opaque. All the advanced modes
  94. // compute alpha as src-over.
  95. case SkBlendMode::kSrcOver:
  96. case SkBlendMode::kDstOver:
  97. case SkBlendMode::kPlus:
  98. case SkBlendMode::kOverlay:
  99. case SkBlendMode::kDarken:
  100. case SkBlendMode::kLighten:
  101. case SkBlendMode::kColorDodge:
  102. case SkBlendMode::kColorBurn:
  103. case SkBlendMode::kHardLight:
  104. case SkBlendMode::kSoftLight:
  105. case SkBlendMode::kDifference:
  106. case SkBlendMode::kExclusion:
  107. case SkBlendMode::kMultiply:
  108. case SkBlendMode::kHue:
  109. case SkBlendMode::kSaturation:
  110. case SkBlendMode::kColor:
  111. case SkBlendMode::kLuminosity:
  112. flags = src->preservesOpaqueInput() || dst->preservesOpaqueInput()
  113. ? kPreservesOpaqueInput_OptimizationFlag
  114. : kNone_OptimizationFlags;
  115. break;
  116. }
  117. if (does_cpu_blend_impl_match_gpu(mode) && src->hasConstantOutputForConstantInput() &&
  118. dst->hasConstantOutputForConstantInput()) {
  119. flags |= kConstantOutputForConstantInput_OptimizationFlag;
  120. }
  121. return flags;
  122. }
  123. void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
  124. b->add32((int)fMode);
  125. }
  126. bool onIsEqual(const GrFragmentProcessor& other) const override {
  127. const ComposeTwoFragmentProcessor& cs = other.cast<ComposeTwoFragmentProcessor>();
  128. return fMode == cs.fMode;
  129. }
  130. SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override {
  131. SkPMColor4f opaqueInput = { input.fR, input.fG, input.fB, 1 };
  132. SkPMColor4f src = ConstantOutputForConstantInput(this->childProcessor(0), opaqueInput);
  133. SkPMColor4f dst = ConstantOutputForConstantInput(this->childProcessor(1), opaqueInput);
  134. SkPMColor4f res = SkBlendMode_Apply(fMode, src, dst);
  135. return res * input.fA;
  136. }
  137. GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
  138. SkBlendMode fMode;
  139. GR_DECLARE_FRAGMENT_PROCESSOR_TEST
  140. typedef GrFragmentProcessor INHERITED;
  141. };
  142. /////////////////////////////////////////////////////////////////////
  143. class GLComposeTwoFragmentProcessor : public GrGLSLFragmentProcessor {
  144. public:
  145. void emitCode(EmitArgs&) override;
  146. private:
  147. typedef GrGLSLFragmentProcessor INHERITED;
  148. };
  149. /////////////////////////////////////////////////////////////////////
  150. GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeTwoFragmentProcessor);
  151. #if GR_TEST_UTILS
  152. std::unique_ptr<GrFragmentProcessor> ComposeTwoFragmentProcessor::TestCreate(
  153. GrProcessorTestData* d) {
  154. // Create two random frag procs.
  155. std::unique_ptr<GrFragmentProcessor> fpA(GrProcessorUnitTest::MakeChildFP(d));
  156. std::unique_ptr<GrFragmentProcessor> fpB(GrProcessorUnitTest::MakeChildFP(d));
  157. SkBlendMode mode;
  158. do {
  159. mode = static_cast<SkBlendMode>(d->fRandom->nextRangeU(0, (int)SkBlendMode::kLastMode));
  160. } while (SkBlendMode::kClear == mode || SkBlendMode::kSrc == mode || SkBlendMode::kDst == mode);
  161. return std::unique_ptr<GrFragmentProcessor>(
  162. new ComposeTwoFragmentProcessor(std::move(fpA), std::move(fpB), mode));
  163. }
  164. #endif
  165. std::unique_ptr<GrFragmentProcessor> ComposeTwoFragmentProcessor::clone() const {
  166. auto src = this->childProcessor(0).clone();
  167. auto dst = this->childProcessor(1).clone();
  168. return std::unique_ptr<GrFragmentProcessor>(
  169. new ComposeTwoFragmentProcessor(std::move(src), std::move(dst), fMode));
  170. }
  171. GrGLSLFragmentProcessor* ComposeTwoFragmentProcessor::onCreateGLSLInstance() const{
  172. return new GLComposeTwoFragmentProcessor;
  173. }
  174. /////////////////////////////////////////////////////////////////////
  175. void GLComposeTwoFragmentProcessor::emitCode(EmitArgs& args) {
  176. GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
  177. const ComposeTwoFragmentProcessor& cs = args.fFp.cast<ComposeTwoFragmentProcessor>();
  178. const char* inputColor = nullptr;
  179. if (args.fInputColor) {
  180. inputColor = "inputColor";
  181. fragBuilder->codeAppendf("half4 inputColor = half4(%s.rgb, 1.0);", args.fInputColor);
  182. }
  183. // declare outputColor and emit the code for each of the two children
  184. SkString srcColor("xfer_src");
  185. this->emitChild(0, inputColor, &srcColor, args);
  186. SkString dstColor("xfer_dst");
  187. this->emitChild(1, inputColor, &dstColor, args);
  188. // emit blend code
  189. SkBlendMode mode = cs.getMode();
  190. fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkBlendMode_Name(mode));
  191. GrGLSLBlend::AppendMode(fragBuilder,
  192. srcColor.c_str(),
  193. dstColor.c_str(),
  194. args.fOutputColor,
  195. mode);
  196. // re-multiply the output color by the input color's alpha
  197. if (args.fInputColor) {
  198. fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
  199. }
  200. }
  201. std::unique_ptr<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromTwoProcessors(
  202. std::unique_ptr<GrFragmentProcessor> src,
  203. std::unique_ptr<GrFragmentProcessor> dst,
  204. SkBlendMode mode) {
  205. switch (mode) {
  206. case SkBlendMode::kClear:
  207. return GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT,
  208. GrConstColorProcessor::InputMode::kIgnore);
  209. case SkBlendMode::kSrc:
  210. return src;
  211. case SkBlendMode::kDst:
  212. return dst;
  213. default:
  214. return ComposeTwoFragmentProcessor::Make(std::move(src), std::move(dst), mode);
  215. }
  216. }
  217. //////////////////////////////////////////////////////////////////////////////
  218. class ComposeOneFragmentProcessor : public GrFragmentProcessor {
  219. public:
  220. enum Child {
  221. kDst_Child,
  222. kSrc_Child,
  223. };
  224. static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> fp,
  225. SkBlendMode mode, Child child) {
  226. if (!fp) {
  227. return nullptr;
  228. }
  229. return std::unique_ptr<GrFragmentProcessor>(
  230. new ComposeOneFragmentProcessor(std::move(fp), mode, child));
  231. }
  232. const char* name() const override { return "ComposeOne"; }
  233. #ifdef SK_DEBUG
  234. SkString dumpInfo() const override {
  235. SkString str;
  236. str.appendf("Mode: %s, Child: %s",
  237. SkBlendMode_Name(fMode), kDst_Child == fChild ? "Dst" : "Src");
  238. for (int i = 0; i < this->numChildProcessors(); ++i) {
  239. str.appendf(" [%s %s]",
  240. this->childProcessor(i).name(), this->childProcessor(i).dumpInfo().c_str());
  241. }
  242. return str;
  243. }
  244. #endif
  245. std::unique_ptr<GrFragmentProcessor> clone() const override;
  246. SkBlendMode mode() const { return fMode; }
  247. Child child() const { return fChild; }
  248. private:
  249. OptimizationFlags OptFlags(const GrFragmentProcessor* fp, SkBlendMode mode, Child child) {
  250. OptimizationFlags flags;
  251. switch (mode) {
  252. case SkBlendMode::kClear:
  253. SK_ABORT("Should never create clear compose one FP.");
  254. flags = kNone_OptimizationFlags;
  255. break;
  256. case SkBlendMode::kSrc:
  257. SkASSERT(child == kSrc_Child);
  258. flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
  259. : kNone_OptimizationFlags;
  260. break;
  261. case SkBlendMode::kDst:
  262. SkASSERT(child == kDst_Child);
  263. flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
  264. : kNone_OptimizationFlags;
  265. break;
  266. // Produces opaque if both src and dst are opaque. These also will modulate the child's
  267. // output by either the input color or alpha. However, if the child is not compatible
  268. // with the coverage as alpha then it may produce a color that is not valid premul.
  269. case SkBlendMode::kSrcIn:
  270. case SkBlendMode::kDstIn:
  271. case SkBlendMode::kModulate:
  272. flags = ProcessorOptimizationFlags(fp) &
  273. ~kConstantOutputForConstantInput_OptimizationFlag;
  274. break;
  275. // Produces zero when both are opaque, indeterminate if one is opaque.
  276. case SkBlendMode::kSrcOut:
  277. case SkBlendMode::kDstOut:
  278. case SkBlendMode::kXor:
  279. flags = kNone_OptimizationFlags;
  280. break;
  281. // Is opaque if the dst is opaque.
  282. case SkBlendMode::kSrcATop:
  283. if (child == kDst_Child) {
  284. flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
  285. : kNone_OptimizationFlags;
  286. } else {
  287. flags = kPreservesOpaqueInput_OptimizationFlag;
  288. }
  289. break;
  290. // DstATop is the converse of kSrcATop. Screen is also opaque if the src is a opaque.
  291. case SkBlendMode::kDstATop:
  292. case SkBlendMode::kScreen:
  293. if (child == kSrc_Child) {
  294. flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
  295. : kNone_OptimizationFlags;
  296. } else {
  297. flags = kPreservesOpaqueInput_OptimizationFlag;
  298. }
  299. break;
  300. // These modes are all opaque if either src or dst is opaque. All the advanced modes
  301. // compute alpha as src-over.
  302. case SkBlendMode::kSrcOver:
  303. case SkBlendMode::kDstOver:
  304. case SkBlendMode::kPlus:
  305. case SkBlendMode::kOverlay:
  306. case SkBlendMode::kDarken:
  307. case SkBlendMode::kLighten:
  308. case SkBlendMode::kColorDodge:
  309. case SkBlendMode::kColorBurn:
  310. case SkBlendMode::kHardLight:
  311. case SkBlendMode::kSoftLight:
  312. case SkBlendMode::kDifference:
  313. case SkBlendMode::kExclusion:
  314. case SkBlendMode::kMultiply:
  315. case SkBlendMode::kHue:
  316. case SkBlendMode::kSaturation:
  317. case SkBlendMode::kColor:
  318. case SkBlendMode::kLuminosity:
  319. flags = kPreservesOpaqueInput_OptimizationFlag;
  320. break;
  321. }
  322. if (does_cpu_blend_impl_match_gpu(mode) && fp->hasConstantOutputForConstantInput()) {
  323. flags |= kConstantOutputForConstantInput_OptimizationFlag;
  324. }
  325. return flags;
  326. }
  327. void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
  328. GR_STATIC_ASSERT(((int)SkBlendMode::kLastMode & UINT16_MAX) == (int)SkBlendMode::kLastMode);
  329. b->add32((int)fMode | (fChild << 16));
  330. }
  331. bool onIsEqual(const GrFragmentProcessor& that) const override {
  332. return fMode == that.cast<ComposeOneFragmentProcessor>().fMode;
  333. }
  334. SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inputColor) const override {
  335. SkPMColor4f childColor = ConstantOutputForConstantInput(this->childProcessor(0),
  336. SK_PMColor4fWHITE);
  337. SkPMColor4f src, dst;
  338. if (kSrc_Child == fChild) {
  339. src = childColor;
  340. dst = inputColor;
  341. } else {
  342. src = inputColor;
  343. dst = childColor;
  344. }
  345. return SkBlendMode_Apply(fMode, src, dst);
  346. }
  347. private:
  348. ComposeOneFragmentProcessor(std::unique_ptr<GrFragmentProcessor> fp, SkBlendMode mode,
  349. Child child)
  350. : INHERITED(kComposeOneFragmentProcessor_ClassID, OptFlags(fp.get(), mode, child))
  351. , fMode(mode)
  352. , fChild(child) {
  353. SkDEBUGCODE(int dstIndex =) this->registerChildProcessor(std::move(fp));
  354. SkASSERT(0 == dstIndex);
  355. }
  356. GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
  357. SkBlendMode fMode;
  358. Child fChild;
  359. GR_DECLARE_FRAGMENT_PROCESSOR_TEST
  360. typedef GrFragmentProcessor INHERITED;
  361. };
  362. //////////////////////////////////////////////////////////////////////////////
  363. class GLComposeOneFragmentProcessor : public GrGLSLFragmentProcessor {
  364. public:
  365. void emitCode(EmitArgs& args) override {
  366. GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
  367. SkBlendMode mode = args.fFp.cast<ComposeOneFragmentProcessor>().mode();
  368. ComposeOneFragmentProcessor::Child child =
  369. args.fFp.cast<ComposeOneFragmentProcessor>().child();
  370. SkString childColor("child");
  371. this->emitChild(0, &childColor, args);
  372. // emit blend code
  373. fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkBlendMode_Name(mode));
  374. const char* childStr = childColor.c_str();
  375. if (ComposeOneFragmentProcessor::kDst_Child == child) {
  376. GrGLSLBlend::AppendMode(fragBuilder, args.fInputColor, childStr, args.fOutputColor, mode);
  377. } else {
  378. GrGLSLBlend::AppendMode(fragBuilder, childStr, args.fInputColor, args.fOutputColor, mode);
  379. }
  380. }
  381. private:
  382. typedef GrGLSLFragmentProcessor INHERITED;
  383. };
  384. /////////////////////////////////////////////////////////////////////
  385. GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeOneFragmentProcessor);
  386. #if GR_TEST_UTILS
  387. std::unique_ptr<GrFragmentProcessor> ComposeOneFragmentProcessor::TestCreate(
  388. GrProcessorTestData* d) {
  389. // Create one random frag procs.
  390. // For now, we'll prevent either children from being a shader with children to prevent the
  391. // possibility of an arbitrarily large tree of procs.
  392. std::unique_ptr<GrFragmentProcessor> dst(GrProcessorUnitTest::MakeChildFP(d));
  393. SkBlendMode mode;
  394. ComposeOneFragmentProcessor::Child child;
  395. do {
  396. mode = static_cast<SkBlendMode>(d->fRandom->nextRangeU(0, (int)SkBlendMode::kLastMode));
  397. child = d->fRandom->nextBool() ? kDst_Child : kSrc_Child;
  398. } while (SkBlendMode::kClear == mode || (SkBlendMode::kDst == mode && child == kSrc_Child) ||
  399. (SkBlendMode::kSrc == mode && child == kDst_Child));
  400. return std::unique_ptr<GrFragmentProcessor>(
  401. new ComposeOneFragmentProcessor(std::move(dst), mode, child));
  402. }
  403. #endif
  404. GrGLSLFragmentProcessor* ComposeOneFragmentProcessor::onCreateGLSLInstance() const {
  405. return new GLComposeOneFragmentProcessor;
  406. }
  407. std::unique_ptr<GrFragmentProcessor> ComposeOneFragmentProcessor::clone() const {
  408. return std::unique_ptr<GrFragmentProcessor>(
  409. new ComposeOneFragmentProcessor(this->childProcessor(0).clone(), fMode, fChild));
  410. }
  411. //////////////////////////////////////////////////////////////////////////////
  412. // It may seems as though when the input FP is the dst and the mode is kDst (or same for src/kSrc)
  413. // that these factories could simply return the input FP. However, that doesn't have quite
  414. // the same effect as the returned compose FP will replace the FP's input with solid white and
  415. // ignore the original input. This could be implemented as:
  416. // RunInSeries(ConstColor(WHITE, kIgnoreInput), inputFP).
  417. std::unique_ptr<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromDstProcessor(
  418. std::unique_ptr<GrFragmentProcessor> dst, SkBlendMode mode) {
  419. switch (mode) {
  420. case SkBlendMode::kClear:
  421. return GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT,
  422. GrConstColorProcessor::InputMode::kIgnore);
  423. case SkBlendMode::kSrc:
  424. return nullptr;
  425. default:
  426. return ComposeOneFragmentProcessor::Make(std::move(dst), mode,
  427. ComposeOneFragmentProcessor::kDst_Child);
  428. }
  429. }
  430. std::unique_ptr<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromSrcProcessor(
  431. std::unique_ptr<GrFragmentProcessor> src, SkBlendMode mode) {
  432. switch (mode) {
  433. case SkBlendMode::kClear:
  434. return GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT,
  435. GrConstColorProcessor::InputMode::kIgnore);
  436. case SkBlendMode::kDst:
  437. return nullptr;
  438. default:
  439. return ComposeOneFragmentProcessor::Make(std::move(src), mode,
  440. ComposeOneFragmentProcessor::kSrc_Child);
  441. }
  442. }