Don't use GrRRectBlurEffect for large rects when highp is not full float

Change-Id: Idf12e0a1fba2d9bd2fab8100bd9319c6ec6115b9
Reviewed-on: https://skia-review.googlesource.com/127049
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/core/SkBlurMF.cpp b/src/core/SkBlurMF.cpp
index 8bae1f0..b75fd16 100644
--- a/src/core/SkBlurMF.cpp
+++ b/src/core/SkBlurMF.cpp
@@ -758,7 +758,8 @@
         SkScalar pad = 3.0f * xformedSigma;
         rect.outset(pad, pad);
 
-        fp = GrRectBlurEffect::Make(proxyProvider, rect, xformedSigma);
+        fp = GrRectBlurEffect::Make(proxyProvider, *context->caps()->shaderCaps(), rect,
+                                    xformedSigma);
     } else if (path.isOval(&rect) && SkScalarNearlyEqual(rect.width(), rect.height())) {
         fp = GrCircleBlurFragmentProcessor::Make(proxyProvider, rect, xformedSigma);
 
@@ -811,7 +812,8 @@
             SkScalar pad = 3.0f * xformedSigma;
             const SkRect dstCoverageRect = devRRect.rect().makeOutset(pad, pad);
 
-            fp = GrRectBlurEffect::Make(proxyProvider, dstCoverageRect, xformedSigma);
+            fp = GrRectBlurEffect::Make(proxyProvider, *context->caps()->shaderCaps(),
+                                        dstCoverageRect, xformedSigma);
         } else {
             fp = GrCircleBlurFragmentProcessor::Make(proxyProvider,
                                                      devRRect.rect(), xformedSigma);
diff --git a/src/gpu/effects/GrRectBlurEffect.cpp b/src/gpu/effects/GrRectBlurEffect.cpp
index f537361..219fefa 100644
--- a/src/gpu/effects/GrRectBlurEffect.cpp
+++ b/src/gpu/effects/GrRectBlurEffect.cpp
@@ -160,6 +160,7 @@
     float sigma = data->fRandom->nextRangeF(3, 8);
     float width = data->fRandom->nextRangeF(200, 300);
     float height = data->fRandom->nextRangeF(200, 300);
-    return GrRectBlurEffect::Make(data->proxyProvider(), SkRect::MakeWH(width, height), sigma);
+    return GrRectBlurEffect::Make(data->proxyProvider(), *data->caps()->shaderCaps(),
+                                  SkRect::MakeWH(width, height), sigma);
 }
 #endif
diff --git a/src/gpu/effects/GrRectBlurEffect.fp b/src/gpu/effects/GrRectBlurEffect.fp
index ed9a1e7..e5a5aad 100644
--- a/src/gpu/effects/GrRectBlurEffect.fp
+++ b/src/gpu/effects/GrRectBlurEffect.fp
@@ -84,7 +84,17 @@
 
 @make {
      static std::unique_ptr<GrFragmentProcessor> Make(GrProxyProvider* proxyProvider,
+                                                      const GrShaderCaps& caps,
                                                       const SkRect& rect, float sigma) {
+         if (!caps.floatIs32Bits()) {
+             // We promote the rect uniform from half to float when it has large values for
+             // precision. If we don't have full float then fail.
+             if (abs(rect.fLeft) > 16000 || abs(rect.fTop) > 16000 ||
+                 abs(rect.fRight) > 16000 || abs(rect.fBottom) > 16000 ||
+                 abs(rect.width()) > 16000 || abs(rect.height()) > 16000) {
+                 return nullptr;
+             }
+         }
          int doubleProfileSize = SkScalarCeilToInt(12*sigma);
 
          if (doubleProfileSize >= rect.width() || doubleProfileSize >= rect.height()) {
@@ -142,5 +152,6 @@
     float sigma = data->fRandom->nextRangeF(3,8);
     float width = data->fRandom->nextRangeF(200,300);
     float height = data->fRandom->nextRangeF(200,300);
-    return GrRectBlurEffect::Make(data->proxyProvider(), SkRect::MakeWH(width, height), sigma);
+    return GrRectBlurEffect::Make(data->proxyProvider(), *data->caps()->shaderCaps(),
+                                  SkRect::MakeWH(width, height), sigma);
 }
diff --git a/src/gpu/effects/GrRectBlurEffect.h b/src/gpu/effects/GrRectBlurEffect.h
index 47e9dc3..42c2829 100644
--- a/src/gpu/effects/GrRectBlurEffect.h
+++ b/src/gpu/effects/GrRectBlurEffect.h
@@ -63,7 +63,17 @@
     float sigma() const { return fSigma; }
 
     static std::unique_ptr<GrFragmentProcessor> Make(GrProxyProvider* proxyProvider,
-                                                     const SkRect& rect, float sigma) {
+                                                     const GrShaderCaps& caps, const SkRect& rect,
+                                                     float sigma) {
+        if (!caps.floatIs32Bits()) {
+            // We promote the rect uniform from half to float when it has large values for
+            // precision. If we don't have full float then fail.
+            if (abs(rect.fLeft) > 16000 || abs(rect.fTop) > 16000 || abs(rect.fRight) > 16000 ||
+                abs(rect.fBottom) > 16000 || abs(rect.width()) > 16000 ||
+                abs(rect.height()) > 16000) {
+                return nullptr;
+            }
+        }
         int doubleProfileSize = SkScalarCeilToInt(12 * sigma);
 
         if (doubleProfileSize >= rect.width() || doubleProfileSize >= rect.height()) {