Use input FPs as the base layer for processor tests.

Previously, this test layered its paints by calling
`addColorFragmentProcessor` multiple times. We intend to remove support
for multiple color FPs on a GrPaint in the near future, so we use input
fragment processors instead to generate the same result.

Change-Id: I33e82ce0067183189e69b2af0fe0c228d1d60f14
Bug: skia:10217
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/303479
Commit-Queue: John Stiles <johnstiles@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/tests/ProcessorTest.cpp b/tests/ProcessorTest.cpp
index fff6e08..d337af2 100644
--- a/tests/ProcessorTest.cpp
+++ b/tests/ProcessorTest.cpp
@@ -226,14 +226,9 @@
     return color4f.premul().toBytes_RGBA();
 }
 
-void test_draw_op(GrContext* context,
-                  GrRenderTargetContext* rtc,
-                  std::unique_ptr<GrFragmentProcessor> fp,
-                  GrSurfaceProxyView inputDataView,
-                  SkAlphaType inputAlphaType) {
+void test_draw_op(GrContext* context, GrRenderTargetContext* rtc,
+                  std::unique_ptr<GrFragmentProcessor> fp) {
     GrPaint paint;
-    paint.addColorFragmentProcessor(GrTextureEffect::Make(std::move(inputDataView),
-                                                          inputAlphaType));
     paint.addColorFragmentProcessor(std::move(fp));
     paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
 
@@ -242,19 +237,15 @@
     rtc->priv().testingOnly_addDrawOp(std::move(op));
 }
 
-// This assumes that the output buffer will be the same size as inputDataView
-void render_fp(GrContext* context,
-               GrRenderTargetContext* rtc,
+// The output buffer must be the same size as the render-target context.
+void render_fp(GrContext* context, GrRenderTargetContext* rtc,
                std::unique_ptr<GrFragmentProcessor> fp,
-               GrSurfaceProxyView inputDataView,
-               SkAlphaType inputAlphaType,
-               GrColor* buffer) {
-    test_draw_op(context, rtc, std::move(fp), inputDataView, inputAlphaType);
-    memset(buffer, 0x0,
-           sizeof(GrColor) * inputDataView.proxy()->width() * inputDataView.proxy()->height());
-    rtc->readPixels(SkImageInfo::Make(inputDataView.proxy()->dimensions(), kRGBA_8888_SkColorType,
+               GrColor* outBuffer) {
+    test_draw_op(context, rtc, std::move(fp));
+    std::fill_n(outBuffer, rtc->width() * rtc->height(), 0);
+    rtc->readPixels(SkImageInfo::Make(rtc->width(), rtc->height(), kRGBA_8888_SkColorType,
                                       kPremul_SkAlphaType),
-                    buffer, 0, {0, 0});
+                    outBuffer, /*rowBytes=*/0, /*srcPt=*/{0, 0});
 }
 
 // This class is responsible for reproducibly generating a random fragment processor.
@@ -339,14 +330,21 @@
             fRandomSeed = random.nextU();
         }
 
-        std::unique_ptr<GrFragmentProcessor> make(int type) {
+        std::unique_ptr<GrFragmentProcessor> make(int type,
+                                                  std::unique_ptr<GrFragmentProcessor> inputFP) {
             // This will generate the exact same randomized FP (of each requested type) each time
             // it's called. Call `reroll` to get a different FP.
             SkRandom random{fRandomSeed};
-            GrProcessorTestData testData{&random, fContext, SK_ARRAY_COUNT(fTestViews), fTestViews};
+            GrProcessorTestData testData{&random, fContext, SK_ARRAY_COUNT(fTestViews), fTestViews,
+                                         std::move(inputFP)};
             return GrFragmentProcessorTestFactory::MakeIdx(type, &testData);
         }
 
+        std::unique_ptr<GrFragmentProcessor> make(int type, GrSurfaceProxyView view,
+                                                  SkAlphaType alpha = kPremul_SkAlphaType) {
+            return make(type, GrTextureEffect::Make(view, alpha));
+        }
+
     private:
         static uint32_t synthesizeInitialSeed() {
             if (FLAGS_randomProcessorTest) {
@@ -548,9 +546,11 @@
     // difference between the frame outputs if the FP is properly following the modulation
     // requirements of the coverage optimization.
     static constexpr SkScalar kInputDelta = 0.2f;
-    auto inputTexture1 = make_input_texture(context, kRenderSize, kRenderSize, 0.0f);
-    auto inputTexture2 = make_input_texture(context, kRenderSize, kRenderSize, kInputDelta);
-    auto inputTexture3 = make_input_texture(context, kRenderSize, kRenderSize, 2*kInputDelta);
+    GrSurfaceProxyView inputTexture1 = make_input_texture(context, kRenderSize, kRenderSize, 0.0f);
+    GrSurfaceProxyView inputTexture2 = make_input_texture(context, kRenderSize, kRenderSize,
+                                                          kInputDelta);
+    GrSurfaceProxyView inputTexture3 = make_input_texture(context, kRenderSize, kRenderSize,
+                                                          2 * kInputDelta);
 
     // Encoded images are very verbose and this tests many potential images, so only export the
     // first failure (subsequent failures have a reasonable chance of being related).
@@ -568,7 +568,7 @@
         // Create a temp FP of this type just to see the number of children that it uses. Then
         // increase the number of attempts if the FP has child FPs, since optimizations will depend
         // on child optimizations being present.
-        std::unique_ptr<GrFragmentProcessor> fp = fpGenerator.make(i);
+        std::unique_ptr<GrFragmentProcessor> fp = fpGenerator.make(i, /*inputFP=*/nullptr);
 
         int timesToInvokeFactory = 5;
         for (int j = 0; j < fp->numChildProcessors(); ++j) {
@@ -585,7 +585,7 @@
         for (int j = 0; j < timesToInvokeFactory; ++j) {
             // Create a randomly-configured FP.
             fpGenerator.reroll();
-            fp = fpGenerator.make(i);
+            fp = fpGenerator.make(i, inputTexture1);
 
             // Skip further testing if it has no optimization bits enabled.
             if (!fp->hasConstantOutputForConstantInput() && !fp->preservesOpaqueInput() &&
@@ -595,17 +595,16 @@
 
             // We can make identical copies of the test FP in order to test coverage-as-alpha.
             if (fp->compatibleWithCoverageAsAlpha()) {
-                // 2nd and 3rd frames are only used when checking coverage optimization
-                render_fp(context, rtc.get(), fpGenerator.make(i), inputTexture2,
-                          kPremul_SkAlphaType, readData2.data());
-                render_fp(context, rtc.get(), fpGenerator.make(i), inputTexture3,
-                          kPremul_SkAlphaType, readData3.data());
+                // Create and render two identical versions of this FP, but using different input
+                // textures, to check coverage optimization. We don't need to do this step for
+                // constant-output or preserving-opacity tests.
+                render_fp(context, rtc.get(), fpGenerator.make(i, inputTexture2), readData2.data());
+                render_fp(context, rtc.get(), fpGenerator.make(i, inputTexture3), readData3.data());
             }
 
-            // Draw base frame last so that rtc holds the original FP behavior if we need to
-            // dump the image to the log.
-            render_fp(context, rtc.get(), fp->clone(), inputTexture1, kPremul_SkAlphaType,
-                      readData1.data());
+            // Draw base frame last so that rtc holds the original FP behavior if we need to dump
+            // the image to the log.
+            render_fp(context, rtc.get(), fpGenerator.make(i, inputTexture1), readData1.data());
 
             // This test has a history of being flaky on a number of devices. If an FP is logically
             // violating the optimizations, it's reasonable to expect it to violate requirements on
@@ -790,7 +789,7 @@
             context, GrColorType::kRGBA_8888, nullptr, SkBackingFit::kExact,
             {kRenderSize, kRenderSize});
 
-    auto inputTexture = make_input_texture(context, kRenderSize, kRenderSize, 0.0f);
+    GrSurfaceProxyView inputTexture = make_input_texture(context, kRenderSize, kRenderSize, 0.0f);
 
     // On failure we write out images, but just write the first failing set as the print is very
     // large.
@@ -815,7 +814,7 @@
         static constexpr int kTimesToInvokeFactory = 10;
         for (int j = 0; j < kTimesToInvokeFactory; ++j) {
             fpGenerator.reroll();
-            std::unique_ptr<GrFragmentProcessor> fp = fpGenerator.make(i);
+            std::unique_ptr<GrFragmentProcessor> fp = fpGenerator.make(i, /*inputFP=*/nullptr);
             std::unique_ptr<GrFragmentProcessor> clone = fp->clone();
             if (!clone) {
                 ERRORF(reporter, "Clone of processor %s failed.", fp->name());
@@ -842,12 +841,10 @@
                                       clone->referencesSampleCoords(),
                                       "%s\n", describe_fp(*fp).c_str());
             // Draw with original and read back the results.
-            render_fp(context, rtc.get(), std::move(fp), inputTexture, kPremul_SkAlphaType,
-                      readData1.data());
+            render_fp(context, rtc.get(), std::move(fp), readData1.data());
 
             // Draw with clone and read back the results.
-            render_fp(context, rtc.get(), std::move(clone), inputTexture, kPremul_SkAlphaType,
-                      readData2.data());
+            render_fp(context, rtc.get(), std::move(clone), readData2.data());
 
             // Check that the results are the same.
             bool passing = true;