Make sure random unit test processors use an alpha type compatible with
texture data.

It'd probably be good to provide an opaque texture that has an alpha
channel and widen the range of color types that are present in the
future.

Change-Id: I5587a479f7e2f3991f8ae27a4cd44afc533324e8
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/260696
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/src/effects/imagefilters/SkDisplacementMapEffect.cpp b/src/effects/imagefilters/SkDisplacementMapEffect.cpp
index 73d6af4..7ee871b 100644
--- a/src/effects/imagefilters/SkDisplacementMapEffect.cpp
+++ b/src/effects/imagefilters/SkDisplacementMapEffect.cpp
@@ -545,12 +545,8 @@
 
 #if GR_TEST_UTILS
 std::unique_ptr<GrFragmentProcessor> GrDisplacementMapEffect::TestCreate(GrProcessorTestData* d) {
-    int texIdxDispl = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
-                                               GrProcessorUnitTest::kAlphaTextureIdx;
-    int texIdxColor = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
-                                               GrProcessorUnitTest::kAlphaTextureIdx;
-    sk_sp<GrTextureProxy> dispProxy = d->textureProxy(texIdxDispl);
-    sk_sp<GrTextureProxy> colorProxy = d->textureProxy(texIdxColor);
+    auto [dispProxy,  ct1, at1] = d->randomProxy();
+    auto [colorProxy, ct2, at2] = d->randomProxy();
     static const int kMaxComponent = static_cast<int>(SkColorChannel::kLastEnum);
     SkColorChannel xChannelSelector =
         static_cast<SkColorChannel>(d->fRandom->nextRangeU(1, kMaxComponent));
diff --git a/src/effects/imagefilters/SkLightingImageFilter.cpp b/src/effects/imagefilters/SkLightingImageFilter.cpp
index 6733b0d..7e10917 100644
--- a/src/effects/imagefilters/SkLightingImageFilter.cpp
+++ b/src/effects/imagefilters/SkLightingImageFilter.cpp
@@ -1705,9 +1705,7 @@
 }
 
 std::unique_ptr<GrFragmentProcessor> GrDiffuseLightingEffect::TestCreate(GrProcessorTestData* d) {
-    int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
-                                        : GrProcessorUnitTest::kAlphaTextureIdx;
-    sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
+    auto [proxy, ct, at] = d->randomProxy();
     SkScalar surfaceScale = d->fRandom->nextSScalar1();
     SkScalar kd = d->fRandom->nextUScalar1();
     sk_sp<SkImageFilterLight> light(create_random_light(d->fRandom));
@@ -1923,9 +1921,7 @@
 
 #if GR_TEST_UTILS
 std::unique_ptr<GrFragmentProcessor> GrSpecularLightingEffect::TestCreate(GrProcessorTestData* d) {
-    int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
-                                        : GrProcessorUnitTest::kAlphaTextureIdx;
-    sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
+    auto [proxy, ct, at] = d->randomProxy();
     SkScalar surfaceScale = d->fRandom->nextSScalar1();
     SkScalar ks = d->fRandom->nextUScalar1();
     SkScalar shininess = d->fRandom->nextUScalar1();
diff --git a/src/effects/imagefilters/SkMorphologyImageFilter.cpp b/src/effects/imagefilters/SkMorphologyImageFilter.cpp
index 79b5559..8f2ff82 100644
--- a/src/effects/imagefilters/SkMorphologyImageFilter.cpp
+++ b/src/effects/imagefilters/SkMorphologyImageFilter.cpp
@@ -455,17 +455,13 @@
 
 #if GR_TEST_UTILS
 std::unique_ptr<GrFragmentProcessor> GrMorphologyEffect::TestCreate(GrProcessorTestData* d) {
-    int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
-                                        : GrProcessorUnitTest::kAlphaTextureIdx;
-    sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
+    auto [proxy, ct, at] = d->randomProxy();
 
     MorphDirection dir = d->fRandom->nextBool() ? MorphDirection::kX : MorphDirection::kY;
     static const int kMaxRadius = 10;
     int radius = d->fRandom->nextRangeU(1, kMaxRadius);
     MorphType type = d->fRandom->nextBool() ? MorphType::kErode : MorphType::kDilate;
-    auto alphaType = static_cast<SkAlphaType>(
-            d->fRandom->nextRangeU(kUnknown_SkAlphaType + 1, kLastEnum_SkAlphaType));
-    return GrMorphologyEffect::Make(std::move(proxy), alphaType, dir, radius, type);
+    return GrMorphologyEffect::Make(std::move(proxy), at, dir, radius, type);
 }
 #endif
 
diff --git a/src/gpu/GrProcessor.cpp b/src/gpu/GrProcessor.cpp
index 4b7b2b1..fa98746 100644
--- a/src/gpu/GrProcessor.cpp
+++ b/src/gpu/GrProcessor.cpp
@@ -15,86 +15,6 @@
 #include "src/gpu/GrTextureProxy.h"
 #include "src/gpu/GrXferProcessor.h"
 
-#if GR_TEST_UTILS
-
-GrResourceProvider* GrProcessorTestData::resourceProvider() {
-    return fContext->priv().resourceProvider();
-}
-
-GrProxyProvider* GrProcessorTestData::proxyProvider() {
-    return fContext->priv().proxyProvider();
-}
-
-const GrCaps* GrProcessorTestData::caps() { return fContext->priv().caps(); }
-
-class GrFragmentProcessor;
-class GrGeometryProcessor;
-
-/*
- * Originally these were both in the processor unit test header, but then it seemed to cause linker
- * problems on android.
- */
-template <>
-SkTArray<GrFragmentProcessorTestFactory*, true>* GrFragmentProcessorTestFactory::GetFactories() {
-    static SkTArray<GrFragmentProcessorTestFactory*, true> gFactories;
-    return &gFactories;
-}
-
-template <>
-SkTArray<GrGeometryProcessorTestFactory*, true>* GrGeometryProcessorTestFactory::GetFactories() {
-    static SkTArray<GrGeometryProcessorTestFactory*, true> gFactories;
-    return &gFactories;
-}
-
-SkTArray<GrXPFactoryTestFactory*, true>* GrXPFactoryTestFactory::GetFactories() {
-    static SkTArray<GrXPFactoryTestFactory*, true> gFactories;
-    return &gFactories;
-}
-
-/*
- * To ensure we always have successful static initialization, before creating from the factories
- * we verify the count is as expected.  If a new factory is added, then these numbers must be
- * manually adjusted.
- */
-#if SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
-static const int kFPFactoryCount = 37;
-static const int kGPFactoryCount = 14;
-static const int kXPFactoryCount = 4;
-#else
-static const int kFPFactoryCount = 0;
-static const int kGPFactoryCount = 0;
-static const int kXPFactoryCount = 0;
-#endif
-
-template <>
-void GrFragmentProcessorTestFactory::VerifyFactoryCount() {
-    if (kFPFactoryCount != GetFactories()->count()) {
-        SkDebugf("\nExpected %d fragment processor factories, found %d.\n",
-                 kFPFactoryCount, GetFactories()->count());
-        SK_ABORT("Wrong number of fragment processor factories!");
-    }
-}
-
-template <>
-void GrGeometryProcessorTestFactory::VerifyFactoryCount() {
-    if (kGPFactoryCount != GetFactories()->count()) {
-        SkDebugf("\nExpected %d geometry processor factories, found %d.\n",
-                 kGPFactoryCount, GetFactories()->count());
-        SK_ABORT("Wrong number of geometry processor factories!");
-    }
-}
-
-void GrXPFactoryTestFactory::VerifyFactoryCount() {
-    if (kXPFactoryCount != GetFactories()->count()) {
-        SkDebugf("\nExpected %d xp factory factories, found %d.\n",
-                 kXPFactoryCount, GetFactories()->count());
-        SK_ABORT("Wrong number of xp factory factories!");
-    }
-}
-
-#endif
-
-
 // We use a global pool protected by a mutex(spinlock). Chrome may use the same GrContext on
 // different threads. The GrContext is not used concurrently on different threads and there is a
 // memory barrier between accesses of a context on different threads. Also, there may be multiple
diff --git a/src/gpu/GrProcessorUnitTest.cpp b/src/gpu/GrProcessorUnitTest.cpp
index 8d8efa7..afd79ed 100644
--- a/src/gpu/GrProcessorUnitTest.cpp
+++ b/src/gpu/GrProcessorUnitTest.cpp
@@ -5,21 +5,116 @@
  * found in the LICENSE file.
  */
 
-#include "src/gpu/GrFragmentProcessor.h"
 #include "src/gpu/GrProcessorUnitTest.h"
 
+#include "include/gpu/GrContext.h"
+#include "src/gpu/GrContextPriv.h"
+#include "src/gpu/GrFragmentProcessor.h"
+
 #if GR_TEST_UTILS
 
+GrProcessorTestData::GrProcessorTestData(SkRandom* random,
+                                         GrContext* context,
+                                         int numProxies,
+                                         const ProxyInfo proxies[])
+        : fRandom(random), fContext(context) {
+    fProxies.reset(proxies, numProxies);
+    fArena = std::unique_ptr<SkArenaAlloc>(new SkArenaAlloc(1000));
+}
+
+GrResourceProvider* GrProcessorTestData::resourceProvider() {
+    return fContext->priv().resourceProvider();
+}
+
+GrProxyProvider* GrProcessorTestData::proxyProvider() { return fContext->priv().proxyProvider(); }
+
+const GrCaps* GrProcessorTestData::caps() { return fContext->priv().caps(); }
+
+GrProcessorTestData::ProxyInfo GrProcessorTestData::randomProxy() {
+    SkASSERT(!fProxies.empty());
+    return fProxies[fRandom->nextULessThan(fProxies.count())];
+}
+
+GrProcessorTestData::ProxyInfo GrProcessorTestData::randomAlphaOnlyProxy() {
+    int numAlphaOnly = 0;
+    for (const auto& [p, ct, at] : fProxies) {
+        if (GrColorTypeIsAlphaOnly(ct)) {
+            ++numAlphaOnly;
+        }
+    }
+    SkASSERT(numAlphaOnly);
+    int idx = fRandom->nextULessThan(numAlphaOnly);
+    for (const auto& [p, ct, at] : fProxies) {
+        if (GrColorTypeIsAlphaOnly(ct) && !idx--) {
+            return {p, ct, at};
+        }
+    }
+    SkUNREACHABLE;
+}
+
+class GrFragmentProcessor;
+class GrGeometryProcessor;
+
+/*
+ * Originally these were both in the processor unit test header, but then it seemed to cause linker
+ * problems on android.
+ */
+template <>
+SkTArray<GrFragmentProcessorTestFactory*, true>* GrFragmentProcessorTestFactory::GetFactories() {
+    static SkTArray<GrFragmentProcessorTestFactory*, true> gFactories;
+    return &gFactories;
+}
+
+template <>
+SkTArray<GrGeometryProcessorTestFactory*, true>* GrGeometryProcessorTestFactory::GetFactories() {
+    static SkTArray<GrGeometryProcessorTestFactory*, true> gFactories;
+    return &gFactories;
+}
+
+SkTArray<GrXPFactoryTestFactory*, true>* GrXPFactoryTestFactory::GetFactories() {
+    static SkTArray<GrXPFactoryTestFactory*, true> gFactories;
+    return &gFactories;
+}
+
+/*
+ * To ensure we always have successful static initialization, before creating from the factories
+ * we verify the count is as expected.  If a new factory is added, then these numbers must be
+ * manually adjusted.
+ */
+static const int kFPFactoryCount = 37;
+static const int kGPFactoryCount = 14;
+static const int kXPFactoryCount = 4;
+
+template <> void GrFragmentProcessorTestFactory::VerifyFactoryCount() {
+    if (kFPFactoryCount != GetFactories()->count()) {
+        SkDebugf("\nExpected %d fragment processor factories, found %d.\n", kFPFactoryCount,
+                 GetFactories()->count());
+        SK_ABORT("Wrong number of fragment processor factories!");
+    }
+}
+
+template <> void GrGeometryProcessorTestFactory::VerifyFactoryCount() {
+    if (kGPFactoryCount != GetFactories()->count()) {
+        SkDebugf("\nExpected %d geometry processor factories, found %d.\n", kGPFactoryCount,
+                 GetFactories()->count());
+        SK_ABORT("Wrong number of geometry processor factories!");
+    }
+}
+
+void GrXPFactoryTestFactory::VerifyFactoryCount() {
+    if (kXPFactoryCount != GetFactories()->count()) {
+        SkDebugf("\nExpected %d xp factory factories, found %d.\n", kXPFactoryCount,
+                 GetFactories()->count());
+        SK_ABORT("Wrong number of xp factory factories!");
+    }
+}
+
 std::unique_ptr<GrFragmentProcessor> GrProcessorUnitTest::MakeChildFP(GrProcessorTestData* data) {
-#if SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
     std::unique_ptr<GrFragmentProcessor> fp;
     do {
         fp = GrFragmentProcessorTestFactory::Make(data);
         SkASSERT(fp);
     } while (fp->numChildProcessors() != 0);
     return fp;
-#else
-    SK_ABORT("Should not be called if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS");
-#endif
 }
 #endif
diff --git a/src/gpu/GrProcessorUnitTest.h b/src/gpu/GrProcessorUnitTest.h
index d10f5c1..563bbf9 100644
--- a/src/gpu/GrProcessorUnitTest.h
+++ b/src/gpu/GrProcessorUnitTest.h
@@ -17,12 +17,14 @@
 #include "src/gpu/GrTestUtils.h"
 #include "src/gpu/GrTextureProxy.h"
 
+#include <tuple>
+
 class SkMatrix;
 class GrCaps;
 class GrContext;
 class GrProxyProvider;
 class GrRenderTargetContext;
-struct GrProcessorTestData;
+class GrProcessorTestData;
 class GrTexture;
 class GrXPFactory;
 class GrGeometryProcessor;
@@ -48,33 +50,25 @@
  * kAlpha_8_GrPixelConfig. TestCreate functions are also free to create additional textures using
  * the GrContext.
  */
-struct GrProcessorTestData {
-    GrProcessorTestData(SkRandom* random,
-                        GrContext* context,
-                        const GrRenderTargetContext* renderTargetContext,
-                        sk_sp<GrTextureProxy> proxies[2])
-            : fRandom(random), fRenderTargetContext(renderTargetContext), fContext(context) {
-        SkASSERT(proxies[0] && proxies[1]);
-        fProxies[0] = proxies[0];
-        fProxies[1] = proxies[1];
-
-        fArena = std::unique_ptr<SkArenaAlloc>(new SkArenaAlloc(1000));
-    }
-
-    SkRandom* fRandom;
-    const GrRenderTargetContext* fRenderTargetContext;
+class GrProcessorTestData {
+public:
+    using ProxyInfo = std::tuple<sk_sp<GrTextureProxy>, GrColorType, SkAlphaType>;
+    GrProcessorTestData(SkRandom* random, GrContext* context, int numProxies, const ProxyInfo[]);
 
     GrContext* context() { return fContext; }
     GrResourceProvider* resourceProvider();
     GrProxyProvider* proxyProvider();
     const GrCaps* caps();
-    sk_sp<GrTextureProxy> textureProxy(int index) { return fProxies[index]; }
     SkArenaAlloc* allocator() { return fArena.get(); }
 
+    ProxyInfo randomProxy();
+    ProxyInfo randomAlphaOnlyProxy();
+
+    SkRandom* fRandom;
+
 private:
     GrContext* fContext;
-    sk_sp<GrTextureProxy> fProxies[2];
-
+    SkTArray<ProxyInfo> fProxies;
     std::unique_ptr<SkArenaAlloc> fArena;
 };
 
diff --git a/src/gpu/GrTestUtils.h b/src/gpu/GrTestUtils.h
index b3e71a2..e4b691b 100644
--- a/src/gpu/GrTestUtils.h
+++ b/src/gpu/GrTestUtils.h
@@ -24,7 +24,7 @@
 
 class GrColorInfo;
 class GrColorSpaceXform;
-struct GrProcessorTestData;
+class GrProcessorTestData;
 class GrStyle;
 class SkMatrix;
 class SkPath;
diff --git a/src/gpu/effects/GrAlphaThresholdFragmentProcessor.fp b/src/gpu/effects/GrAlphaThresholdFragmentProcessor.fp
index d9d1933..ad8251e 100644
--- a/src/gpu/effects/GrAlphaThresholdFragmentProcessor.fp
+++ b/src/gpu/effects/GrAlphaThresholdFragmentProcessor.fp
@@ -61,7 +61,7 @@
 }
 
 @test(testData) {
-    sk_sp<GrTextureProxy> maskProxy = testData->textureProxy(GrProcessorUnitTest::kAlphaTextureIdx);
+    auto [maskProxy, ct, at] = testData->randomAlphaOnlyProxy();
     // Make the inner and outer thresholds be in (0, 1) exclusive and be sorted correctly.
     float innerThresh = testData->fRandom->nextUScalar1() * .99f + 0.005f;
     float outerThresh = testData->fRandom->nextUScalar1() * .99f + 0.005f;
diff --git a/src/gpu/effects/GrBicubicEffect.cpp b/src/gpu/effects/GrBicubicEffect.cpp
index 9235bd3..9902e84 100644
--- a/src/gpu/effects/GrBicubicEffect.cpp
+++ b/src/gpu/effects/GrBicubicEffect.cpp
@@ -208,11 +208,8 @@
 
 #if GR_TEST_UTILS
 std::unique_ptr<GrFragmentProcessor> GrBicubicEffect::TestCreate(GrProcessorTestData* d) {
-    int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
-                                        : GrProcessorUnitTest::kAlphaTextureIdx;
     static const GrSamplerState::WrapMode kClampClamp[] = {GrSamplerState::WrapMode::kClamp,
                                                            GrSamplerState::WrapMode::kClamp};
-    SkAlphaType alphaType = d->fRandom->nextBool() ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
     Direction direction = Direction::kX;
     switch (d->fRandom->nextULessThan(3)) {
         case 0:
@@ -225,8 +222,8 @@
             direction = Direction::kXY;
             break;
     }
-    return GrBicubicEffect::Make(d->textureProxy(texIdx), SkMatrix::I(), kClampClamp, direction,
-                                 alphaType);
+    auto [proxy, ct, at] = d->randomProxy();
+    return GrBicubicEffect::Make(proxy, SkMatrix::I(), kClampClamp, direction, at);
 }
 #endif
 
diff --git a/src/gpu/effects/GrBitmapTextGeoProc.cpp b/src/gpu/effects/GrBitmapTextGeoProc.cpp
index 6927157..cfb205d 100644
--- a/src/gpu/effects/GrBitmapTextGeoProc.cpp
+++ b/src/gpu/effects/GrBitmapTextGeoProc.cpp
@@ -199,9 +199,7 @@
 #if GR_TEST_UTILS
 
 GrGeometryProcessor* GrBitmapTextGeoProc::TestCreate(GrProcessorTestData* d) {
-    int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
-                                        : GrProcessorUnitTest::kAlphaTextureIdx;
-    sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
+    auto [proxy, ct, at] = d->randomProxy();
 
     GrSamplerState::WrapMode wrapModes[2];
     GrTest::TestWrapModes(d->fRandom, wrapModes);
@@ -209,15 +207,16 @@
                                                    ? GrSamplerState::Filter::kBilerp
                                                    : GrSamplerState::Filter::kNearest);
 
-    GrMaskFormat format = kARGB_GrMaskFormat; // init to avoid warning
-    switch (d->fRandom->nextULessThan(3)) {
-        case 0:
+    GrMaskFormat format;
+    switch (ct) {
+        case GrColorType::kAlpha_8:
             format = kA8_GrMaskFormat;
             break;
-        case 1:
+        case GrColorType::kBGR_565:
             format = kA565_GrMaskFormat;
             break;
-        case 2:
+        case GrColorType::kRGBA_8888:
+        default:  // It doesn't really matter that color type and mask format agree.
             format = kARGB_GrMaskFormat;
             break;
     }
diff --git a/src/gpu/effects/GrDistanceFieldGeoProc.cpp b/src/gpu/effects/GrDistanceFieldGeoProc.cpp
index 2ecbdce..f828e50 100644
--- a/src/gpu/effects/GrDistanceFieldGeoProc.cpp
+++ b/src/gpu/effects/GrDistanceFieldGeoProc.cpp
@@ -287,9 +287,7 @@
 
 #if GR_TEST_UTILS
 GrGeometryProcessor* GrDistanceFieldA8TextGeoProc::TestCreate(GrProcessorTestData* d) {
-    int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
-                                        : GrProcessorUnitTest::kAlphaTextureIdx;
-    sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
+    auto [proxy, ct, at] = d->randomAlphaOnlyProxy();
 
     GrSamplerState::WrapMode wrapModes[2];
     GrTest::TestWrapModes(d->fRandom, wrapModes);
@@ -582,9 +580,7 @@
 
 #if GR_TEST_UTILS
 GrGeometryProcessor* GrDistanceFieldPathGeoProc::TestCreate(GrProcessorTestData* d) {
-    int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
-                                        : GrProcessorUnitTest::kAlphaTextureIdx;
-    sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
+    auto [proxy, ct, at] = d->randomAlphaOnlyProxy();
 
     GrSamplerState::WrapMode wrapModes[2];
     GrTest::TestWrapModes(d->fRandom, wrapModes);
@@ -906,9 +902,7 @@
 
 #if GR_TEST_UTILS
 GrGeometryProcessor* GrDistanceFieldLCDTextGeoProc::TestCreate(GrProcessorTestData* d) {
-    int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
-                                          GrProcessorUnitTest::kAlphaTextureIdx;
-    sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
+    auto [proxy, ct, at] = d->randomProxy();
 
     GrSamplerState::WrapMode wrapModes[2];
     GrTest::TestWrapModes(d->fRandom, wrapModes);
diff --git a/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp b/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp
index 80bc165..9a66a07 100644
--- a/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp
+++ b/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp
@@ -280,9 +280,7 @@
 #if GR_TEST_UTILS
 std::unique_ptr<GrFragmentProcessor> GrGaussianConvolutionFragmentProcessor::TestCreate(
         GrProcessorTestData* d) {
-    int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
-                                        : GrProcessorUnitTest::kAlphaTextureIdx;
-    sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
+    auto [proxy, ct, at] = d->randomProxy();
 
     int bounds[2];
     int modeIdx = d->fRandom->nextRangeU(0, GrTextureDomain::kModeCount-1);
@@ -301,10 +299,8 @@
     int radius = d->fRandom->nextRangeU(1, kMaxKernelRadius);
     float sigma = radius / 3.f;
 
-    auto alphaType = static_cast<SkAlphaType>(
-            d->fRandom->nextRangeU(kUnknown_SkAlphaType + 1, kLastEnum_SkAlphaType));
-    return GrGaussianConvolutionFragmentProcessor::Make(
-            std::move(proxy), alphaType, dir, radius, sigma,
-            static_cast<GrTextureDomain::Mode>(modeIdx), bounds);
+    return GrGaussianConvolutionFragmentProcessor::Make(std::move(proxy), at, dir, radius, sigma,
+                                                        static_cast<GrTextureDomain::Mode>(modeIdx),
+                                                        bounds);
 }
 #endif
diff --git a/src/gpu/effects/GrMagnifierEffect.fp b/src/gpu/effects/GrMagnifierEffect.fp
index fba7807..e9f8317 100644
--- a/src/gpu/effects/GrMagnifierEffect.fp
+++ b/src/gpu/effects/GrMagnifierEffect.fp
@@ -71,7 +71,7 @@
 }
 
 @test(d) {
-    sk_sp<GrTextureProxy> proxy = d->textureProxy(0);
+    auto [proxy, ct, at] = d->randomProxy();
     const int kMaxWidth = 200;
     const int kMaxHeight = 200;
     const SkScalar kMaxInset = 20.0f;
diff --git a/src/gpu/effects/GrMatrixConvolutionEffect.cpp b/src/gpu/effects/GrMatrixConvolutionEffect.cpp
index 12decaf..4369bb0 100644
--- a/src/gpu/effects/GrMatrixConvolutionEffect.cpp
+++ b/src/gpu/effects/GrMatrixConvolutionEffect.cpp
@@ -317,9 +317,7 @@
 
 #if GR_TEST_UTILS
 std::unique_ptr<GrFragmentProcessor> GrMatrixConvolutionEffect::TestCreate(GrProcessorTestData* d) {
-    int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
-                                        : GrProcessorUnitTest::kAlphaTextureIdx;
-    sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
+    auto [proxy, ct, at] = d->randomProxy();
 
     int width = d->fRandom->nextRangeU(1, MAX_KERNEL_SIZE);
     int height = d->fRandom->nextRangeU(1, MAX_KERNEL_SIZE / width);
diff --git a/src/gpu/effects/GrShadowGeoProc.cpp b/src/gpu/effects/GrShadowGeoProc.cpp
index a914dda..c30e6e0 100644
--- a/src/gpu/effects/GrShadowGeoProc.cpp
+++ b/src/gpu/effects/GrShadowGeoProc.cpp
@@ -85,7 +85,7 @@
 
 #if GR_TEST_UTILS
 GrGeometryProcessor* GrRRectShadowGeoProc::TestCreate(GrProcessorTestData* d) {
-    sk_sp<GrSurfaceProxy> proxy = d->textureProxy(GrProcessorUnitTest::kAlphaTextureIdx);
+    auto [proxy, ct, at] = d->randomAlphaOnlyProxy();
     GrSurfaceOrigin origin = proxy->origin();
     const GrSwizzle& swizzle = proxy->textureSwizzle();
     GrSurfaceProxyView view(std::move(proxy), origin, swizzle);
diff --git a/src/gpu/effects/GrSimpleTextureEffect.fp b/src/gpu/effects/GrSimpleTextureEffect.fp
index cf4dd31..88fe6da 100644
--- a/src/gpu/effects/GrSimpleTextureEffect.fp
+++ b/src/gpu/effects/GrSimpleTextureEffect.fp
@@ -60,8 +60,7 @@
 }
 
 @test(testData) {
-    int texIdx = testData->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
-                                               : GrProcessorUnitTest::kAlphaTextureIdx;
+    auto [proxy, ct, at] = testData->randomProxy();
     GrSamplerState::WrapMode wrapModes[2];
     GrTest::TestWrapModes(testData->fRandom, wrapModes);
     if (!testData->caps()->npotTextureTileSupport()) {
@@ -76,7 +75,5 @@
                                                                : GrSamplerState::Filter::kNearest);
 
     const SkMatrix& matrix = GrTest::TestMatrix(testData->fRandom);
-    auto alphaType = static_cast<SkAlphaType>(
-            testData->fRandom->nextRangeU(kUnknown_SkAlphaType + 1, kLastEnum_SkAlphaType));
-    return GrSimpleTextureEffect::Make(testData->textureProxy(texIdx),
-                                       alphaType, matrix, params);}
+    return GrSimpleTextureEffect::Make(std::move(proxy), at, matrix, params);
+}
diff --git a/src/gpu/effects/GrTextureDomain.cpp b/src/gpu/effects/GrTextureDomain.cpp
index d090cbd..ef97201 100644
--- a/src/gpu/effects/GrTextureDomain.cpp
+++ b/src/gpu/effects/GrTextureDomain.cpp
@@ -607,9 +607,7 @@
 #if GR_TEST_UTILS
 std::unique_ptr<GrFragmentProcessor> GrDeviceSpaceTextureDecalFragmentProcessor::TestCreate(
         GrProcessorTestData* d) {
-    int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
-                                        : GrProcessorUnitTest::kAlphaTextureIdx;
-    sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
+    auto [proxy, at, ct] = d->randomProxy();
     SkIRect subset;
     subset.fLeft = d->fRandom->nextULessThan(proxy->width() - 1);
     subset.fRight = d->fRandom->nextRangeU(subset.fLeft, proxy->width());
diff --git a/src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.cpp b/src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.cpp
index ffcaca1..40a81f1 100644
--- a/src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.cpp
+++ b/src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.cpp
@@ -111,7 +111,7 @@
 #if GR_TEST_UTILS
 std::unique_ptr<GrFragmentProcessor> GrAlphaThresholdFragmentProcessor::TestCreate(
         GrProcessorTestData* testData) {
-    sk_sp<GrTextureProxy> maskProxy = testData->textureProxy(GrProcessorUnitTest::kAlphaTextureIdx);
+    auto [maskProxy, ct, at] = testData->randomAlphaOnlyProxy();
     // Make the inner and outer thresholds be in (0, 1) exclusive and be sorted correctly.
     float innerThresh = testData->fRandom->nextUScalar1() * .99f + 0.005f;
     float outerThresh = testData->fRandom->nextUScalar1() * .99f + 0.005f;
diff --git a/src/gpu/effects/generated/GrMagnifierEffect.cpp b/src/gpu/effects/generated/GrMagnifierEffect.cpp
index a6522b5..c1fa4aa 100644
--- a/src/gpu/effects/generated/GrMagnifierEffect.cpp
+++ b/src/gpu/effects/generated/GrMagnifierEffect.cpp
@@ -178,7 +178,7 @@
 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrMagnifierEffect);
 #if GR_TEST_UTILS
 std::unique_ptr<GrFragmentProcessor> GrMagnifierEffect::TestCreate(GrProcessorTestData* d) {
-    sk_sp<GrTextureProxy> proxy = d->textureProxy(0);
+    auto [proxy, ct, at] = d->randomProxy();
     const int kMaxWidth = 200;
     const int kMaxHeight = 200;
     const SkScalar kMaxInset = 20.0f;
diff --git a/src/gpu/effects/generated/GrSimpleTextureEffect.cpp b/src/gpu/effects/generated/GrSimpleTextureEffect.cpp
index 9c1ad14..af1be6d 100644
--- a/src/gpu/effects/generated/GrSimpleTextureEffect.cpp
+++ b/src/gpu/effects/generated/GrSimpleTextureEffect.cpp
@@ -72,8 +72,7 @@
 #if GR_TEST_UTILS
 std::unique_ptr<GrFragmentProcessor> GrSimpleTextureEffect::TestCreate(
         GrProcessorTestData* testData) {
-    int texIdx = testData->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
-                                               : GrProcessorUnitTest::kAlphaTextureIdx;
+    auto [proxy, ct, at] = testData->randomProxy();
     GrSamplerState::WrapMode wrapModes[2];
     GrTest::TestWrapModes(testData->fRandom, wrapModes);
     if (!testData->caps()->npotTextureTileSupport()) {
@@ -88,8 +87,6 @@
                                              : GrSamplerState::Filter::kNearest);
 
     const SkMatrix& matrix = GrTest::TestMatrix(testData->fRandom);
-    auto alphaType = static_cast<SkAlphaType>(
-            testData->fRandom->nextRangeU(kUnknown_SkAlphaType + 1, kLastEnum_SkAlphaType));
-    return GrSimpleTextureEffect::Make(testData->textureProxy(texIdx), alphaType, matrix, params);
+    return GrSimpleTextureEffect::Make(std::move(proxy), at, matrix, params);
 }
 #endif
diff --git a/tests/ProcessorTest.cpp b/tests/ProcessorTest.cpp
index 978f7ef..e7a650b 100644
--- a/tests/ProcessorTest.cpp
+++ b/tests/ProcessorTest.cpp
@@ -257,7 +257,7 @@
 bool init_test_textures(GrResourceProvider* resourceProvider,
                         GrProxyProvider* proxyProvider,
                         SkRandom* random,
-                        sk_sp<GrTextureProxy> proxies[2]) {
+                        GrProcessorTestData::ProxyInfo proxies[2]) {
     static const int kTestTextureSize = 256;
 
     {
@@ -274,9 +274,12 @@
                                            kRGBA_8888_SkColorType, kPremul_SkAlphaType);
         SkPixmap pixmap(ii, rgbaData.get(), ii.minRowBytes());
         sk_sp<SkImage> img = SkImage::MakeRasterCopy(pixmap);
-        proxies[0] =
+        auto proxy =
                 proxyProvider->createTextureProxy(img, 1, SkBudgeted::kYes, SkBackingFit::kExact);
-        proxies[0]->instantiate(resourceProvider);
+        if (!proxy || !proxy->instantiate(resourceProvider)) {
+            return false;
+        }
+        proxies[0] = {std::move(proxy), GrColorType::kRGBA_8888, kPremul_SkAlphaType};
     }
 
     {
@@ -292,12 +295,15 @@
                                            kAlpha_8_SkColorType, kPremul_SkAlphaType);
         SkPixmap pixmap(ii, alphaData.get(), ii.minRowBytes());
         sk_sp<SkImage> img = SkImage::MakeRasterCopy(pixmap);
-        proxies[1] =
+        auto proxy =
                 proxyProvider->createTextureProxy(img, 1, SkBudgeted::kYes, SkBackingFit::kExact);
-        proxies[1]->instantiate(resourceProvider);
+        if (!proxy || !proxy->instantiate(resourceProvider)) {
+            return false;
+        }
+        proxies[1] = {std::move(proxy), GrColorType::kAlpha_8, kPremul_SkAlphaType};
     }
 
-    return proxies[0] && proxies[1];
+    return true;
 }
 
 // Creates a texture of premul colors used as the output of the fragment processor that precedes
@@ -427,12 +433,12 @@
     auto rtc = context->priv().makeDeferredRenderTargetContext(
             SkBackingFit::kExact, kRenderSize, kRenderSize, GrColorType::kRGBA_8888, nullptr);
 
-    sk_sp<GrTextureProxy> proxies[2];
+    GrProcessorTestData::ProxyInfo proxies[2];
     if (!init_test_textures(resourceProvider, proxyProvider, &random, proxies)) {
         ERRORF(reporter, "Could not create test textures");
         return;
     }
-    GrProcessorTestData testData(&random, context, rtc.get(), proxies);
+    GrProcessorTestData testData(&random, context, 2, proxies);
 
     // Coverage optimization uses three frames with a linearly transformed input texture.  The first
     // frame has no offset, second frames add .2 and .4, which should then be present as a fixed
@@ -664,12 +670,12 @@
     auto rtc = context->priv().makeDeferredRenderTargetContext(
             SkBackingFit::kExact, kRenderSize, kRenderSize, GrColorType::kRGBA_8888, nullptr);
 
-    sk_sp<GrTextureProxy> proxies[2];
+    GrProcessorTestData::ProxyInfo proxies[2];
     if (!init_test_textures(resourceProvider, proxyProvider, &random, proxies)) {
         ERRORF(reporter, "Could not create test textures");
         return;
     }
-    GrProcessorTestData testData(&random, context, rtc.get(), proxies);
+    GrProcessorTestData testData(&random, context, 2, proxies);
 
     auto inputTexture = make_input_texture(proxyProvider, kRenderSize, kRenderSize, 0.0f);
     std::unique_ptr<GrColor[]> readData1(new GrColor[kRenderSize * kRenderSize]);
diff --git a/tests/ProgramsTest.cpp b/tests/ProgramsTest.cpp
index d12ba0d..5641e00 100644
--- a/tests/ProgramsTest.cpp
+++ b/tests/ProgramsTest.cpp
@@ -260,7 +260,7 @@
     GrDrawingManager* drawingManager = context->priv().drawingManager();
     GrProxyProvider* proxyProvider = context->priv().proxyProvider();
 
-    sk_sp<GrTextureProxy> proxies[2];
+    GrProcessorTestData::ProxyInfo proxies[2];
 
     // setup dummy textures
     GrMipMapped mipMapped = GrMipMapped(context->priv().caps()->mipMapSupport());
@@ -272,10 +272,13 @@
         const GrBackendFormat format =
             context->priv().caps()->getDefaultBackendFormat(GrColorType::kRGBA_8888,
                                                             GrRenderable::kYes);
-        proxies[0] = proxyProvider->createProxy(format, dummyDesc, GrRenderable::kYes, 1,
-                                                kBottomLeft_GrSurfaceOrigin, mipMapped,
-                                                SkBackingFit::kExact, SkBudgeted::kNo,
-                                                GrProtected::kNo, GrInternalSurfaceFlags::kNone);
+        proxies[0] = {proxyProvider->createProxy(format, dummyDesc, GrRenderable::kYes, 1,
+                                                 kBottomLeft_GrSurfaceOrigin, mipMapped,
+                                                 SkBackingFit::kExact, SkBudgeted::kNo,
+                                                 GrProtected::kNo, GrInternalSurfaceFlags::kNone),
+                      GrColorType::kRGBA_8888,
+                      kPremul_SkAlphaType
+        };
     }
     {
         GrSurfaceDesc dummyDesc;
@@ -285,13 +288,16 @@
         const GrBackendFormat format =
             context->priv().caps()->getDefaultBackendFormat(GrColorType::kAlpha_8,
                                                             GrRenderable::kNo);
-        proxies[1] = proxyProvider->createProxy(format, dummyDesc, GrRenderable::kNo, 1,
-                                                kTopLeft_GrSurfaceOrigin, mipMapped,
-                                                SkBackingFit::kExact, SkBudgeted::kNo,
-                                                GrProtected::kNo, GrInternalSurfaceFlags::kNone);
+        proxies[1] = {proxyProvider->createProxy(format, dummyDesc, GrRenderable::kNo, 1,
+                                                 kTopLeft_GrSurfaceOrigin, mipMapped,
+                                                 SkBackingFit::kExact, SkBudgeted::kNo,
+                                                 GrProtected::kNo, GrInternalSurfaceFlags::kNone),
+                      GrColorType::kAlpha_8,
+                      kPremul_SkAlphaType
+        };
     }
 
-    if (!proxies[0] || !proxies[1]) {
+    if (!std::get<0>(proxies[0]) || !std::get<0>(proxies[1])) {
         SkDebugf("Could not allocate dummy textures");
         return false;
     }
@@ -308,7 +314,7 @@
         }
 
         GrPaint paint;
-        GrProcessorTestData ptd(&random, context, renderTargetContext.get(), proxies);
+        GrProcessorTestData ptd(&random, context, 2, proxies);
         set_random_color_coverage_stages(&paint, &ptd, maxStages, maxLevels);
         set_random_xpf(&paint, &ptd);
         GrDrawRandomOp(&random, renderTargetContext.get(), std::move(paint));
@@ -333,7 +339,7 @@
     for (int i = 0; i < fpFactoryCnt; ++i) {
         // Since FP factories internally randomize, call each 10 times.
         for (int j = 0; j < 10; ++j) {
-            GrProcessorTestData ptd(&random, context, renderTargetContext.get(), proxies);
+            GrProcessorTestData ptd(&random, context, 2, proxies);
 
             GrPaint paint;
             paint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));