Split big rrect aa effect up into separate images

Needed to enlarge radii to surface bugs without exceeding max texture size on low end devices.

BUG=chromium:477684

Review URL: https://codereview.chromium.org/1508003008
diff --git a/gm/bigrrectaaeffect.cpp b/gm/bigrrectaaeffect.cpp
index 18a0c6e..c3f47f9 100644
--- a/gm/bigrrectaaeffect.cpp
+++ b/gm/bigrrectaaeffect.cpp
@@ -18,17 +18,32 @@
 
 class BigRRectAAEffectGM : public GM {
 public:
-    BigRRectAAEffectGM() {
-        this->setBGColor(sk_tool_utils::color_to_565(0xFFDDDDDD));
-        this->setUpRRects();
+    BigRRectAAEffectGM(const SkRRect& rrect, const char* name)
+        : fRRect(rrect)
+        , fName(name) {
+        this->setBGColor(sk_tool_utils::color_to_565(SK_ColorBLUE));
+        // Each test case draws the rrect with gaps around it.
+        fTestWidth = SkScalarCeilToInt(rrect.width()) + 2 * kGap;
+        fTestHeight = SkScalarCeilToInt(rrect.height()) + 2 * kGap;
+
+        // Add a pad between test cases.
+        fTestOffsetX = fTestWidth + kPad;
+        fTestOffsetY = fTestHeight + kPad;
+
+        // We draw two tests in x (fill and inv-fill) and pad around
+        // all four sides of the image.
+        fWidth = 2 * fTestOffsetX + kPad;
+        fHeight = fTestOffsetY + kPad;
     }
 
 protected:
     SkString onShortName() override {
-        return SkString("big_rrect_aa_effect");
+        SkString name;
+        name.printf("big_rrect_%s_aa_effect", fName);
+        return name;
     }
 
-    SkISize onISize() override { return SkISize::Make(kImageWidth, kImageHeight); }
+    SkISize onISize() override { return SkISize::Make(fWidth, fHeight); }
 
     void onDraw(SkCanvas* canvas) override {
         GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget();
@@ -40,95 +55,82 @@
 
         SkPaint paint;
 
-#ifdef SK_DEBUG
-        static const SkRect kMaxRRectBound = SkRect::MakeWH(SkIntToScalar(kMaxSize),
-                                                            SkIntToScalar(kMaxSize));
-        static const SkRect kMaxImageBound = SkRect::MakeWH(SkIntToScalar(kImageWidth),
-                                                            SkIntToScalar(kImageHeight));
-#endif
-
         int y = kPad;
         int x = kPad;
         static const GrPrimitiveEdgeType kEdgeTypes[] = {
             kFillAA_GrProcessorEdgeType,
             kInverseFillAA_GrProcessorEdgeType,
         };
+        SkRect testBounds = SkRect::MakeIWH(fTestWidth, fTestHeight);
         for (size_t et = 0; et < SK_ARRAY_COUNT(kEdgeTypes); ++et) {
             GrPrimitiveEdgeType edgeType = kEdgeTypes[et];
-            for (int curRRect = 0; curRRect < fRRects.count(); ++curRRect) {
-#ifdef SK_DEBUG
-                SkASSERT(kMaxRRectBound.contains(fRRects[curRRect].getBounds()));
-                SkRect imageSpaceBounds = fRRects[curRRect].getBounds();
-                imageSpaceBounds.offset(SkIntToScalar(x), SkIntToScalar(y));
-                SkASSERT(kMaxImageBound.contains(imageSpaceBounds));
-#endif
-                canvas->save();
-                    canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
-                    GrTestTarget tt;
-                    context->getTestTarget(&tt, rt);
-                    if (nullptr == tt.target()) {
-                        SkDEBUGFAIL("Couldn't get Gr test target.");
-                        return;
-                    }
-                    GrPipelineBuilder pipelineBuilder;
-                    pipelineBuilder.setXPFactory(
-                        GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
+            canvas->save();
+                canvas->translate(SkIntToScalar(x), SkIntToScalar(y));                
 
-                    SkRRect rrect = fRRects[curRRect];
-                    rrect.offset(SkIntToScalar(x), SkIntToScalar(y));
-                    SkAutoTUnref<GrFragmentProcessor> fp(GrRRectEffect::Create(edgeType, rrect));
-                    SkASSERT(fp);
-                    if (fp) {
-                        pipelineBuilder.addCoverageFragmentProcessor(fp);
-                        pipelineBuilder.setRenderTarget(rt);
+                // Draw a background for the test case
+                SkPaint paint;
+                paint.setColor(SK_ColorWHITE);
+                canvas->drawRect(testBounds, paint);
 
-                        SkRect bounds = SkRect::MakeWH(SkIntToScalar(kMaxSize),
-                                                       SkIntToScalar(kMaxSize));
-                        bounds.outset(2.f, 2.f);
-                        bounds.offset(SkIntToScalar(x), SkIntToScalar(y));
-
-                        tt.target()->drawNonAARect(pipelineBuilder,
-                                                   0xff000000,
-                                                   SkMatrix::I(),
-                                                   bounds);
-                    }
-                canvas->restore();
-                x = x + kDrawOffset;
-                if (x + kMaxSize> kImageWidth) {
-                    x = kPad;
-                    y += kDrawOffset;
+                GrTestTarget tt;
+                context->getTestTarget(&tt, rt);
+                if (!tt.target()) {
+                    SkDEBUGFAIL("Couldn't get Gr test target.");
+                    return;
                 }
-            }
+                GrPipelineBuilder pipelineBuilder;
+                pipelineBuilder.setXPFactory(
+                    GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
+
+                SkRRect rrect = fRRect;
+                rrect.offset(SkIntToScalar(x + kGap), SkIntToScalar(y + kGap));
+                SkAutoTUnref<GrFragmentProcessor> fp(GrRRectEffect::Create(edgeType, rrect));
+                SkASSERT(fp);
+                if (fp) {
+                    pipelineBuilder.addCoverageFragmentProcessor(fp);
+                    pipelineBuilder.setRenderTarget(rt);
+
+                    SkRect bounds = testBounds;
+                    bounds.offset(SkIntToScalar(x), SkIntToScalar(y));
+
+                    tt.target()->drawNonAARect(pipelineBuilder,
+                                               0xff000000,
+                                               SkMatrix::I(),
+                                               bounds);
+                }
+            canvas->restore();
+            x = x + fTestOffsetX;
         }
     }
 
-    void setUpRRects() {
-        SkScalar maxSize = SkIntToScalar(kMaxSize);
-        fRRects.push()->setRect(SkRect::MakeWH(maxSize, maxSize));
-        fRRects.push()->setOval(SkRect::MakeWH(maxSize, maxSize));
-        fRRects.push()->setOval(SkRect::MakeWH(maxSize - 1.f, maxSize - 10.f));
-        fRRects.push()->setRectXY(SkRect::MakeWH(maxSize - 1.f, maxSize - 10.f),
-                                  maxSize/2.f - 10.f, maxSize/2.f - 10.f);
-        fRRects.push()->setRectXY(SkRect::MakeWH(maxSize - 1.f, maxSize - 10),
-                                  maxSize/2.f - 10.f, maxSize/2.f - 20.f);
-    }
-
 private:
-    static const int kPad = 5;
-    static const int kMaxSize = 300;
-    static const int kDrawOffset = kMaxSize + kPad;
+    // pad between test cases
+    static const int kPad = 7;
+    // gap between rect for each case that is rendered and exterior of rrect
+    static const int kGap = 3;
 
-    static const int kImageWidth = 4 * kDrawOffset + kPad;
-    static const int kImageHeight = 3 * kDrawOffset + kPad;
-
-
-    SkTDArray<SkRRect> fRRects;
+    SkRRect fRRect;
+    int fWidth;
+    int fHeight;
+    int fTestWidth;
+    int fTestHeight;
+    int fTestOffsetX;
+    int fTestOffsetY;
+    const char* fName;
     typedef GM INHERITED;
 };
 
 ///////////////////////////////////////////////////////////////////////////////
+// This value is motivated by bug chromium:477684. It has to be large to cause overflow in
+// the shader
+static const int kSize = 700;
 
-DEF_GM( return new BigRRectAAEffectGM (); )
+DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeRect(SkRect::MakeIWH(kSize, kSize)), "rect"); )
+DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeOval(SkRect::MakeIWH(kSize, kSize)), "circle"); )
+DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeOval(SkRect::MakeIWH(kSize - 1, kSize - 10)), "ellipse"); )
+// The next two have small linear segments between the corners
+DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeRectXY(SkRect::MakeIWH(kSize - 1, kSize - 10), kSize/2.f - 10.f, kSize/2.f - 10.f), "circular_corner"); )
+DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeRectXY(SkRect::MakeIWH(kSize - 1, kSize - 10), kSize/2.f - 10.f, kSize/2.f - 15.f), "elliptical_corner"); )
 
 }
 #endif