Revert "Revert "Use a dst size threshold for multitexturing images.""

This reverts commit be85ef25111ac59275b1642350ffb608141c404f.

Change-Id: Icc22eb5841fabc53232b360efaac2d6ebf72e358
Reviewed-on: https://skia-review.googlesource.com/79081
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/GrShaderCaps.cpp b/src/gpu/GrShaderCaps.cpp
index 2d9cd0a..65721ee 100644
--- a/src/gpu/GrShaderCaps.cpp
+++ b/src/gpu/GrShaderCaps.cpp
@@ -68,11 +68,9 @@
     fMaxCombinedSamplers = 0;
     fAdvBlendEqInteraction = kNotSupported_AdvBlendEqInteraction;
 
-#if GR_TEST_UTILS
-    fDisableImageMultitexturing = options.fDisableImageMultitexturing;
-#else
-    fDisableImageMultitexturing = false;
-#endif
+    // TODO: Default this to 0 and only enable image multitexturing when a "safe" threshold is
+    // known for a GPU class.
+    fDisableImageMultitexturingDstRectAreaThreshold = std::numeric_limits<size_t>::max();
 }
 
 void GrShaderCaps::dumpJSON(SkJSONWriter* writer) const {
@@ -130,7 +128,8 @@
     writer->appendS32("Max Combined Samplers", fMaxFragmentSamplers);
     writer->appendString("Advanced blend equation interaction",
                          kAdvBlendEqInteractionStr[fAdvBlendEqInteraction]);
-    writer->appendBool("Disable image multitexturing", fDisableImageMultitexturing);
+    writer->appendU64("Disable image multitexturing dst area threshold",
+                      fDisableImageMultitexturingDstRectAreaThreshold);
 
     writer->endObject();
 }
@@ -138,5 +137,8 @@
 void GrShaderCaps::applyOptionsOverrides(const GrContextOptions& options) {
 #if GR_TEST_UTILS
     fDualSourceBlendingSupport = fDualSourceBlendingSupport && !options.fSuppressDualSourceBlending;
+    if (options.fDisableImageMultitexturing) {
+        fDisableImageMultitexturingDstRectAreaThreshold = 0;
+    }
 #endif
 }
diff --git a/src/gpu/ops/GrTextureOp.cpp b/src/gpu/ops/GrTextureOp.cpp
index 410257c..be37bd3 100644
--- a/src/gpu/ops/GrTextureOp.cpp
+++ b/src/gpu/ops/GrTextureOp.cpp
@@ -55,7 +55,7 @@
 #endif
 
     static int SupportsMultitexture(const GrShaderCaps& caps) {
-        return caps.integerSupport() && !caps.disableImageMultitexturingSupport();
+        return caps.integerSupport() && caps.maxFragmentSamplers() > 1;
     }
 
     static sk_sp<GrGeometryProcessor> Make(sk_sp<GrTextureProxy> proxies[], int proxyCnt,
@@ -293,6 +293,16 @@
     DEFINE_OP_CLASS_ID
 
 private:
+
+    // This is used in a heursitic for choosing a code path. We don't care what happens with
+    // really large rects, infs, nans, etc.
+#if defined(__clang__) && (__clang_major__ * 1000 + __clang_minor__) >= 3007
+__attribute__((no_sanitize("float-cast-overflow")))
+#endif
+    size_t RectSizeAsSizeT(const SkRect &rect) {;
+        return static_cast<size_t>(SkTMax(rect.width(), 1.f) * SkTMax(rect.height(), 1.f));
+    }
+
     static constexpr int kMaxTextures = TextureGeometryProcessor::kMaxTextures;
 
     TextureOp(sk_sp<GrTextureProxy> proxy, GrSamplerState::Filter filter, GrColor color,
@@ -313,6 +323,8 @@
         SkRect bounds;
         bounds.setBounds(draw.fQuad.points(), 4);
         this->setBounds(bounds, HasAABloat::kNo, IsZeroArea::kNo);
+
+        fMaxApproxDstPixelArea = RectSizeAsSizeT(bounds);
     }
 
     void onPrepareDraws(Target* target) override {
@@ -431,15 +443,18 @@
 
     bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
         const auto* that = t->cast<TextureOp>();
+        const auto& shaderCaps = *caps.shaderCaps();
         if (!GrColorSpaceXform::Equals(fColorSpaceXform.get(), that->fColorSpaceXform.get())) {
             return false;
         }
         // Because of an issue where GrColorSpaceXform adds the same function every time it is used
         // in a texture lookup, we only allow multiple textures when there is no transform.
-        if (TextureGeometryProcessor::SupportsMultitexture(*caps.shaderCaps()) &&
-            !fColorSpaceXform) {
+        if (TextureGeometryProcessor::SupportsMultitexture(shaderCaps) && !fColorSpaceXform &&
+            fMaxApproxDstPixelArea <= shaderCaps.disableImageMultitexturingDstRectAreaThreshold() &&
+            that->fMaxApproxDstPixelArea <=
+                    shaderCaps.disableImageMultitexturingDstRectAreaThreshold()) {
             int map[kMaxTextures];
-            int numNewProxies = this->mergeProxies(that, map, *caps.shaderCaps());
+            int numNewProxies = this->mergeProxies(that, map, shaderCaps);
             if (numNewProxies < 0) {
                 return false;
             }
@@ -479,6 +494,7 @@
             fDraws.push_back_n(that->fDraws.count(), that->fDraws.begin());
         }
         this->joinBounds(*that);
+        fMaxApproxDstPixelArea = SkTMax(that->fMaxApproxDstPixelArea, fMaxApproxDstPixelArea);
         return true;
     }
 
@@ -570,6 +586,7 @@
     // Used to track whether fProxy is ref'ed or has a pending IO after finalize() is called.
     uint8_t fFinalized;
     uint8_t fAllowSRGBInputs;
+    size_t fMaxApproxDstPixelArea;
 
     typedef GrMeshDrawOp INHERITED;
 };