Add a makeDrawContextWithFallback that handles config fallback

This fixes a bug in find_or_create_rrect_blur_mask where an A8-based drawContext was desired but creation was failing b.c. A8 wasn't renderable.

GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2296193005

Review-Url: https://codereview.chromium.org/2296193005
diff --git a/src/effects/SkAlphaThresholdFilter.cpp b/src/effects/SkAlphaThresholdFilter.cpp
index 5170a3d..1f9a9cc 100644
--- a/src/effects/SkAlphaThresholdFilter.cpp
+++ b/src/effects/SkAlphaThresholdFilter.cpp
@@ -96,16 +96,12 @@
 sk_sp<GrTexture> SkAlphaThresholdFilterImpl::createMaskTexture(GrContext* context,
                                                                const SkMatrix& inMatrix,
                                                                const SkIRect& bounds) const {
-    GrPixelConfig config;
-    if (context->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
-        config = kAlpha_8_GrPixelConfig;
-    } else {
-        config = kRGBA_8888_GrPixelConfig;
-    }
 
-    sk_sp<GrDrawContext> drawContext(context->makeDrawContext(SkBackingFit::kApprox,
-                                                              bounds.width(), bounds.height(),
-                                                              config, nullptr));
+    sk_sp<GrDrawContext> drawContext(context->makeDrawContextWithFallback(SkBackingFit::kApprox,
+                                                                          bounds.width(),
+                                                                          bounds.height(),
+                                                                          kAlpha_8_GrPixelConfig,
+                                                                          nullptr));
     if (!drawContext) {
         return nullptr;
     }
diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp
index d2781db..9d6600f 100644
--- a/src/effects/SkBlurMaskFilter.cpp
+++ b/src/effects/SkBlurMaskFilter.cpp
@@ -1121,9 +1121,10 @@
     sk_sp<GrTexture> mask(context->textureProvider()->findAndRefTextureByUniqueKey(key));
     if (!mask) {
         // TODO: this could be approx but the texture coords will need to be updated
-        sk_sp<GrDrawContext> dc(context->makeDrawContext(SkBackingFit::kExact,
-                                                         size.fWidth, size.fHeight,
-                                                         kAlpha_8_GrPixelConfig, nullptr));
+        sk_sp<GrDrawContext> dc(context->makeDrawContextWithFallback(SkBackingFit::kExact,
+                                                                     size.fWidth, size.fHeight,
+                                                                     kAlpha_8_GrPixelConfig,
+                                                                     nullptr));
         if (!dc) {
             return nullptr;
         }
diff --git a/src/gpu/GrBlurUtils.cpp b/src/gpu/GrBlurUtils.cpp
index 2b7540d..383652d 100644
--- a/src/gpu/GrBlurUtils.cpp
+++ b/src/gpu/GrBlurUtils.cpp
@@ -104,19 +104,12 @@
         sampleCnt = 0;
     }
 
-    // We actually only need A8, but it often isn't supported as a
-    // render target so default to RGBA_8888
-    GrPixelConfig config = kRGBA_8888_GrPixelConfig;
-    if (context->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, sampleCnt > 0)) {
-        config = kAlpha_8_GrPixelConfig;
-    }
-
-    sk_sp<GrDrawContext> drawContext(context->makeDrawContext(SkBackingFit::kApprox,
-                                                              maskRect.width(), 
-                                                              maskRect.height(),
-                                                              config,
-                                                              nullptr,
-                                                              sampleCnt));
+    sk_sp<GrDrawContext> drawContext(context->makeDrawContextWithFallback(SkBackingFit::kApprox,
+                                                                          maskRect.width(), 
+                                                                          maskRect.height(),
+                                                                          kAlpha_8_GrPixelConfig,
+                                                                          nullptr,
+                                                                          sampleCnt));
     if (!drawContext) {
         return nullptr;
     }
diff --git a/src/gpu/GrClipStackClip.cpp b/src/gpu/GrClipStackClip.cpp
index ff5c860..d6ad1d9 100644
--- a/src/gpu/GrClipStackClip.cpp
+++ b/src/gpu/GrClipStackClip.cpp
@@ -407,16 +407,11 @@
         return sk_sp<GrTexture>(texture);
     }
 
-    // There's no texture in the cache. Let's try to allocate it then.
-    GrPixelConfig config = kRGBA_8888_GrPixelConfig;
-    if (context->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
-        config = kAlpha_8_GrPixelConfig;
-    }
-
-    sk_sp<GrDrawContext> dc(context->makeDrawContext(SkBackingFit::kApprox,
-                                                     reducedClip.width(),
-                                                     reducedClip.height(),
-                                                     config, nullptr));
+    sk_sp<GrDrawContext> dc(context->makeDrawContextWithFallback(SkBackingFit::kApprox,
+                                                                 reducedClip.width(),
+                                                                 reducedClip.height(),
+                                                                 kAlpha_8_GrPixelConfig,
+                                                                 nullptr));
     if (!dc) {
         return nullptr;
     }
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 0157760..3f4d2fa 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -681,6 +681,62 @@
                                                    surfaceProps);
 }
 
+static inline GrPixelConfig GrPixelConfigFallback(GrPixelConfig config) {
+    static const GrPixelConfig kFallback[] = {
+        kUnknown_GrPixelConfig,        // kUnknown_GrPixelConfig
+        kRGBA_8888_GrPixelConfig,      // kAlpha_8_GrPixelConfig
+        kUnknown_GrPixelConfig,        // kIndex_8_GrPixelConfig
+        kRGBA_8888_GrPixelConfig,      // kRGB_565_GrPixelConfig
+        kRGBA_8888_GrPixelConfig,      // kRGBA_4444_GrPixelConfig
+        kUnknown_GrPixelConfig,        // kRGBA_8888_GrPixelConfig
+        kRGBA_8888_GrPixelConfig,      // kBGRA_8888_GrPixelConfig
+        kUnknown_GrPixelConfig,        // kSRGBA_8888_GrPixelConfig
+        kSRGBA_8888_GrPixelConfig,     // kSBGRA_8888_GrPixelConfig
+        kUnknown_GrPixelConfig,        // kETC1_GrPixelConfig
+        kUnknown_GrPixelConfig,        // kLATC_GrPixelConfig
+        kUnknown_GrPixelConfig,        // kR11_EAC_GrPixelConfig
+        kUnknown_GrPixelConfig,        // kASTC_12x12_GrPixelConfig
+        kUnknown_GrPixelConfig,        // kRGBA_float_GrPixelConfig
+        kRGBA_half_GrPixelConfig,      // kAlpha_half_GrPixelConfig
+        kUnknown_GrPixelConfig,        // kRGBA_half_GrPixelConfig
+    };
+    return kFallback[config];
+
+    GR_STATIC_ASSERT(0  == kUnknown_GrPixelConfig);
+    GR_STATIC_ASSERT(1  == kAlpha_8_GrPixelConfig);
+    GR_STATIC_ASSERT(2  == kIndex_8_GrPixelConfig);
+    GR_STATIC_ASSERT(3  == kRGB_565_GrPixelConfig);
+    GR_STATIC_ASSERT(4  == kRGBA_4444_GrPixelConfig);
+    GR_STATIC_ASSERT(5  == kRGBA_8888_GrPixelConfig);
+    GR_STATIC_ASSERT(6  == kBGRA_8888_GrPixelConfig);
+    GR_STATIC_ASSERT(7  == kSRGBA_8888_GrPixelConfig);
+    GR_STATIC_ASSERT(8  == kSBGRA_8888_GrPixelConfig);
+    GR_STATIC_ASSERT(9  == kETC1_GrPixelConfig);
+    GR_STATIC_ASSERT(10  == kLATC_GrPixelConfig);
+    GR_STATIC_ASSERT(11  == kR11_EAC_GrPixelConfig);
+    GR_STATIC_ASSERT(12 == kASTC_12x12_GrPixelConfig);
+    GR_STATIC_ASSERT(13 == kRGBA_float_GrPixelConfig);
+    GR_STATIC_ASSERT(14 == kAlpha_half_GrPixelConfig);
+    GR_STATIC_ASSERT(15 == kRGBA_half_GrPixelConfig);
+    GR_STATIC_ASSERT(SK_ARRAY_COUNT(kFallback) == kGrPixelConfigCnt);
+}
+
+sk_sp<GrDrawContext> GrContext::makeDrawContextWithFallback(SkBackingFit fit,
+                                                            int width, int height,
+                                                            GrPixelConfig config,
+                                                            sk_sp<SkColorSpace> colorSpace,
+                                                            int sampleCnt,
+                                                            GrSurfaceOrigin origin,
+                                                            const SkSurfaceProps* surfaceProps,
+                                                            SkBudgeted budgeted) {
+    if (!this->caps()->isConfigRenderable(config, sampleCnt > 0)) {
+        config = GrPixelConfigFallback(config);
+    }
+
+    return this->makeDrawContext(fit, width, height, config, std::move(colorSpace),
+                                 sampleCnt, origin, surfaceProps, budgeted);
+}
+
 sk_sp<GrDrawContext> GrContext::makeDrawContext(SkBackingFit fit,
                                                 int width, int height,
                                                 GrPixelConfig config,
@@ -689,6 +745,10 @@
                                                 GrSurfaceOrigin origin,
                                                 const SkSurfaceProps* surfaceProps,
                                                 SkBudgeted budgeted) {
+    if (!this->caps()->isConfigRenderable(config, sampleCnt > 0)) {
+        return nullptr;
+    }
+
     GrSurfaceDesc desc;
     desc.fFlags = kRenderTarget_GrSurfaceFlag;
     desc.fOrigin = origin;
diff --git a/src/gpu/GrTextureParamsAdjuster.cpp b/src/gpu/GrTextureParamsAdjuster.cpp
index 68a6f99..3ca90f5 100644
--- a/src/gpu/GrTextureParamsAdjuster.cpp
+++ b/src/gpu/GrTextureParamsAdjuster.cpp
@@ -33,35 +33,13 @@
     SkASSERT(!subset || !subset->isEmpty());
     GrContext* context = inputTexture->getContext();
     SkASSERT(context);
-    const GrCaps* caps = context->caps();
 
     GrPixelConfig config = GrMakePixelConfigUncompressed(inputTexture->config());
 
-    // If the config isn't renderable try converting to either A8 or an 32 bit config. Otherwise,
-    // fail.
-    if (!caps->isConfigRenderable(config, false)) {
-        if (GrPixelConfigIsAlphaOnly(config)) {
-            if (caps->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
-                config = kAlpha_8_GrPixelConfig;
-            } else if (caps->isConfigRenderable(kSkia8888_GrPixelConfig, false)) {
-                config = kSkia8888_GrPixelConfig;
-            } else {
-                return nullptr;
-            }
-        } else if (kRGB_GrColorComponentFlags ==
-                (kRGB_GrColorComponentFlags & GrPixelConfigComponentMask(config))) {
-            if (caps->isConfigRenderable(kSkia8888_GrPixelConfig, false)) {
-                config = kSkia8888_GrPixelConfig;
-            } else {
-                return nullptr;
-            }
-        } else {
-            return nullptr;
-        }
-    }
-
-    sk_sp<GrDrawContext> copyDC = context->makeDrawContext(SkBackingFit::kExact, copyParams.fWidth,
-                                                           copyParams.fHeight, config, nullptr);
+    sk_sp<GrDrawContext> copyDC = context->makeDrawContextWithFallback(SkBackingFit::kExact,
+                                                                       copyParams.fWidth,
+                                                                       copyParams.fHeight,
+                                                                       config, nullptr);
     if (!copyDC) {
         return nullptr;
     }
diff --git a/src/gpu/GrTextureToYUVPlanes.cpp b/src/gpu/GrTextureToYUVPlanes.cpp
index 7a8647a..5e7dafe 100644
--- a/src/gpu/GrTextureToYUVPlanes.cpp
+++ b/src/gpu/GrTextureToYUVPlanes.cpp
@@ -58,45 +58,48 @@
         sk_sp<GrDrawContext> uDrawContext;
         sk_sp<GrDrawContext> vDrawContext;
 
-        GrPixelConfig singleChannelPixelConfig;
-        if (context->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
-            singleChannelPixelConfig = kAlpha_8_GrPixelConfig;
-        } else {
-            singleChannelPixelConfig = kRGBA_8888_GrPixelConfig;
-        }
-
         // We issue draw(s) to convert from RGBA to Y, U, and V. All three planes may have different
         // sizes however we optimize for two other cases - all planes are the same (1 draw to YUV),
         // and U and V are the same but Y differs (2 draws, one for Y, one for UV).
         if (sizes[0] == sizes[1] && sizes[1] == sizes[2]) {
-            yuvDrawContext = context->makeDrawContext(SkBackingFit::kApprox,
-                                                      sizes[0].fWidth, sizes[0].fHeight,
-                                                      kRGBA_8888_GrPixelConfig, nullptr);
+            yuvDrawContext = context->makeDrawContextWithFallback(SkBackingFit::kApprox,
+                                                                  sizes[0].fWidth,
+                                                                  sizes[0].fHeight,
+                                                                  kRGBA_8888_GrPixelConfig,
+                                                                  nullptr);
             if (!yuvDrawContext) {
                 return false;
             }
         } else {
-            yDrawContext = context->makeDrawContext(SkBackingFit::kApprox,
-                                                    sizes[0].fWidth, sizes[0].fHeight,
-                                                    singleChannelPixelConfig, nullptr);
+            yDrawContext = context->makeDrawContextWithFallback(SkBackingFit::kApprox,
+                                                                sizes[0].fWidth,
+                                                                sizes[0].fHeight,
+                                                                kAlpha_8_GrPixelConfig,
+                                                                nullptr);
             if (!yDrawContext) {
                 return false;
             }
             if (sizes[1] == sizes[2]) {
                 // TODO: Add support for GL_RG when available.
-                uvDrawContext = context->makeDrawContext(SkBackingFit::kApprox,
-                                                         sizes[1].fWidth, sizes[1].fHeight,
-                                                         kRGBA_8888_GrPixelConfig, nullptr);
+                uvDrawContext = context->makeDrawContextWithFallback(SkBackingFit::kApprox,
+                                                                     sizes[1].fWidth,
+                                                                     sizes[1].fHeight,
+                                                                     kRGBA_8888_GrPixelConfig,
+                                                                     nullptr);
                 if (!uvDrawContext) {
                     return false;
                 }
             } else {
-                uDrawContext = context->makeDrawContext(SkBackingFit::kApprox,
-                                                        sizes[1].fWidth, sizes[1].fHeight,
-                                                        singleChannelPixelConfig, nullptr);
-                vDrawContext = context->makeDrawContext(SkBackingFit::kApprox,
-                                                        sizes[2].fWidth, sizes[2].fHeight,
-                                                        singleChannelPixelConfig, nullptr);
+                uDrawContext = context->makeDrawContextWithFallback(SkBackingFit::kApprox,
+                                                                    sizes[1].fWidth,
+                                                                    sizes[1].fHeight,
+                                                                    kAlpha_8_GrPixelConfig,
+                                                                    nullptr);
+                vDrawContext = context->makeDrawContextWithFallback(SkBackingFit::kApprox,
+                                                                    sizes[2].fWidth,
+                                                                    sizes[2].fHeight,
+                                                                    kAlpha_8_GrPixelConfig,
+                                                                    nullptr);
                 if (!uDrawContext || !vDrawContext) {
                     return false;
                 }
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index a59f9d7..64df998 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -172,9 +172,6 @@
     }
 
     GrPixelConfig config = SkImageInfo2GrPixelConfig(ct, at, cs, *context->caps());
-    if (!context->caps()->isConfigRenderable(config, sampleCount > 0)) {
-        return nullptr;
-    }
 
     return context->makeDrawContext(SkBackingFit::kExact,               // Why exact?
                                     origInfo.width(), origInfo.height(),