Make GMs aware of what tool they're being run in.

Add a saveLayer set of draws to convex_poly_clip and fix GPU bug where polygon clips don't account for the translation between clip and device space.

BUG=skia:2051
R=robertphillips@google.com, reed@google.com

Author: bsalomon@google.com

Review URL: https://codereview.chromium.org/148283017

git-svn-id: http://skia.googlecode.com/svn/trunk@13371 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gm/convexpolyclip.cpp b/gm/convexpolyclip.cpp
index 0822f4c..a8037aa 100644
--- a/gm/convexpolyclip.cpp
+++ b/gm/convexpolyclip.cpp
@@ -83,7 +83,12 @@
     }
 
     virtual SkISize onISize() SK_OVERRIDE {
-        return make_isize(435, 540);
+        // When benchmarking the saveLayer set of draws is skipped.
+        int w = 435;
+        if (kBench_Mode != this->getMode()) {
+            w *= 2;
+        }
+        return make_isize(w, 540);
     }
 
     virtual void onOnceBeforeDraw() SK_OVERRIDE {
@@ -140,47 +145,70 @@
                                         SkIntToScalar(size.fHeight));
         canvas->drawBitmapRectToRect(fBmp, NULL, dstRect, &bgPaint);
 
-        for (SkTLList<Clip>::Iter iter(fClips, SkTLList<Clip>::Iter::kHead_IterStart);
-             NULL != iter.get();
-             iter.next()) {
-            const Clip* clip = iter.get();
-            SkScalar x = 0;
-            for (int aa = 0; aa < 2; ++aa) {
-                canvas->save();
-                canvas->translate(x, y);
-                clip->setOnCanvas(canvas, SkRegion::kIntersect_Op, SkToBool(aa));
-                canvas->drawBitmap(fBmp, 0, 0);
-                canvas->restore();
-                x += fBmp.width() + kMargin;
+        static const char kTxt[] = "Clip Me!";
+        SkPaint txtPaint;
+        txtPaint.setTextSize(23.f);
+        txtPaint.setAntiAlias(true);
+        txtPaint.setColor(SK_ColorDKGRAY);
+        SkScalar textW = txtPaint.measureText(kTxt, SK_ARRAY_COUNT(kTxt)-1);
+
+        SkScalar startX = 0;
+        int testLayers = kBench_Mode != this->getMode();
+        for (int doLayer = 0; doLayer <= testLayers; ++doLayer) {
+            for (SkTLList<Clip>::Iter iter(fClips, SkTLList<Clip>::Iter::kHead_IterStart);
+                 NULL != iter.get();
+                 iter.next()) {
+                const Clip* clip = iter.get();
+                SkScalar x = startX;
+                for (int aa = 0; aa < 2; ++aa) {
+                    if (doLayer) {
+                        SkRect bounds;
+                        clip->getBounds(&bounds);
+                        bounds.outset(2, 2);
+                        bounds.offset(x, y);
+                        canvas->saveLayer(&bounds, NULL);
+                    } else {
+                        canvas->save();
+                    }
+                    canvas->translate(x, y);
+                    clip->setOnCanvas(canvas, SkRegion::kIntersect_Op, SkToBool(aa));
+                    canvas->drawBitmap(fBmp, 0, 0);
+                    canvas->restore();
+                    x += fBmp.width() + kMargin;
+                }
+                for (int aa = 0; aa < 2; ++aa) {
+
+                    SkPaint clipOutlinePaint;
+                    clipOutlinePaint.setAntiAlias(true);
+                    clipOutlinePaint.setColor(0x50505050);
+                    clipOutlinePaint.setStyle(SkPaint::kStroke_Style);
+                    clipOutlinePaint.setStrokeWidth(0);
+
+                    if (doLayer) {
+                        SkRect bounds;
+                        clip->getBounds(&bounds);
+                        bounds.outset(2, 2);
+                        bounds.offset(x, y);
+                        canvas->saveLayer(&bounds, NULL);
+                    } else {
+                        canvas->save();
+                    }
+                    canvas->translate(x, y);
+                    SkPath closedClipPath;
+                    clip->asClosedPath(&closedClipPath);
+                    canvas->drawPath(closedClipPath, clipOutlinePaint);
+                    clip->setOnCanvas(canvas, SkRegion::kIntersect_Op, SkToBool(aa));
+                    canvas->scale(1.f, 1.8f);
+                    canvas->drawText(kTxt, SK_ARRAY_COUNT(kTxt)-1,
+                                     0, 1.5f * txtPaint.getTextSize(),
+                                     txtPaint);
+                    canvas->restore();
+                    x += textW + 2 * kMargin;
+                }
+                y += fBmp.height() + kMargin;
             }
-            for (int aa = 0; aa < 2; ++aa) {
-                static const char kTxt[] = "Clip Me!";
-                SkPaint txtPaint;
-                txtPaint.setTextSize(23.f);
-                txtPaint.setAntiAlias(true);
-                txtPaint.setColor(SK_ColorDKGRAY);
-
-                SkPaint clipOutlinePaint;
-                clipOutlinePaint.setAntiAlias(true);
-                clipOutlinePaint.setColor(0x50505050);
-                clipOutlinePaint.setStyle(SkPaint::kStroke_Style);
-                clipOutlinePaint.setStrokeWidth(0);
-
-                canvas->save();
-                canvas->translate(x, y);
-                SkPath closedClipPath;
-                clip->asClosedPath(&closedClipPath);
-                canvas->drawPath(closedClipPath, clipOutlinePaint);
-                clip->setOnCanvas(canvas, SkRegion::kIntersect_Op, SkToBool(aa));
-                canvas->scale(1.f, 1.8f);
-                canvas->drawText(kTxt, SK_ARRAY_COUNT(kTxt)-1,
-                                 0, 1.5f * txtPaint.getTextSize(),
-                                 txtPaint);
-                canvas->restore();
-                x += fBmp.width() + kMargin;
-            }
-
-            y += fBmp.height() + kMargin;
+            y = 0;
+            startX += 2 * fBmp.width() + SkScalarCeilToInt(2 * textW) + 6 * kMargin;
         }
     }
 
@@ -242,6 +270,20 @@
 
         ClipType getType() const { return fClipType; }
 
+        void getBounds(SkRect* bounds) const {
+            switch (fClipType) {
+                case kPath_ClipType:
+                    *bounds = fPath.getBounds();
+                    break;
+                case kRect_ClipType:
+                    *bounds = fRect;
+                    break;
+                case kNone_ClipType:
+                    SkDEBUGFAIL("Uninitialized Clip.");
+                    break;
+            }
+        }
+
     private:
         ClipType fClipType;
         SkPath fPath;
diff --git a/gm/gm.cpp b/gm/gm.cpp
index 29d02d1..82dd476 100644
--- a/gm/gm.cpp
+++ b/gm/gm.cpp
@@ -11,6 +11,7 @@
 SkString GM::gResourcePath;
 
 GM::GM() {
+    fMode = kGM_Mode;
     fBGColor = SK_ColorWHITE;
     fCanvasIsDeferred = false;
     fHaveCalledOnceBeforeDraw = false;
diff --git a/gm/gm.h b/gm/gm.h
index bb20c9c..4da688c 100644
--- a/gm/gm.h
+++ b/gm/gm.h
@@ -53,6 +53,15 @@
             kAsBench_Flag               = 1 << 10, // Run the GM as a benchmark in the bench tool
         };
 
+        enum Mode {
+            kGM_Mode,
+            kSample_Mode,
+            kBench_Mode,
+        };
+
+        void setMode(Mode mode) { fMode = mode; }
+        Mode getMode() const { return fMode; }
+
         void draw(SkCanvas*);
         void drawBackground(SkCanvas*);
         void drawContent(SkCanvas*);
@@ -101,10 +110,10 @@
             fCanvasIsDeferred = isDeferred;
         }
 
-    const SkMatrix& getStarterMatrix() { return fStarterMatrix; }
-    void setStarterMatrix(const SkMatrix& matrix) {
-        fStarterMatrix = matrix;
-    }
+        const SkMatrix& getStarterMatrix() { return fStarterMatrix; }
+        void setStarterMatrix(const SkMatrix& matrix) {
+            fStarterMatrix = matrix;
+        }
 
     protected:
         static SkString gResourcePath;
@@ -118,6 +127,7 @@
         virtual SkMatrix onGetInitialTransform() const { return SkMatrix::I(); }
 
     private:
+        Mode     fMode;
         SkString fShortName;
         SkColor  fBGColor;
         bool     fCanvasIsDeferred; // work-around problem in srcmode.cpp