extend SkBenchmark to allow a bench to return a durationScale, which allows it to perform fewer actual interations, but report a scale factor to account for that. Thus a very slow bench can be compared head-to-head with a faster one, w/o actually forcing the tool to run for the full duration of the slower test.

Extend BitmapBench to time bicubic filtering, and use this durationScale for it.

Extend SkBenchmark to have setBitmapFlags(or, clear), allowing it to request a set of paint flags to be cleared, and set to be set.

BUG=
R=robertphillips@google.com

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

git-svn-id: http://skia.googlecode.com/svn/trunk@9315 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/bench/BitmapBench.cpp b/bench/BitmapBench.cpp
index eba55f5..a6d2096 100644
--- a/bench/BitmapBench.cpp
+++ b/bench/BitmapBench.cpp
@@ -13,10 +13,6 @@
 #include "SkRandom.h"
 #include "SkString.h"
 
-static const char* gTileName[] = {
-    "clamp", "repeat", "mirror"
-};
-
 static const char* gConfigName[] = {
     "ERROR", "a1", "a8", "index8", "565", "4444", "8888"
 };
@@ -82,22 +78,19 @@
     SkPaint     fPaint;
     bool        fIsOpaque;
     bool        fForceUpdate; //bitmap marked as dirty before each draw. forces bitmap to be updated on device cache
-    int         fTileX, fTileY; // -1 means don't use shader
     bool        fIsVolatile;
     SkBitmap::Config fConfig;
     SkString    fName;
-    enum { N = SkBENCHLOOP(300) };
+    enum { BICUBIC_DUR_SCALE = 20 };
+    enum { N = SkBENCHLOOP(15 * BICUBIC_DUR_SCALE) };
     enum { W = 128 };
     enum { H = 128 };
 public:
     BitmapBench(void* param, bool isOpaque, SkBitmap::Config c,
-                bool forceUpdate = false, bool bitmapVolatile = false,
-                int tx = -1, int ty = -1)
+                bool forceUpdate = false, bool bitmapVolatile = false)
         : INHERITED(param)
         , fIsOpaque(isOpaque)
         , fForceUpdate(forceUpdate)
-        , fTileX(tx)
-        , fTileY(ty)
         , fIsVolatile(bitmapVolatile)
         , fConfig(c) {
     }
@@ -105,12 +98,6 @@
 protected:
     virtual const char* onGetName() {
         fName.set("bitmap");
-        if (fTileX >= 0) {
-            fName.appendf("_%s", gTileName[fTileX]);
-            if (fTileY != fTileX) {
-                fName.appendf("_%s", gTileName[fTileY]);
-            }
-        }
         fName.appendf("_%s%s", gConfigName[fConfig],
                       fIsOpaque ? "" : "_A");
         if (fForceUpdate)
@@ -159,7 +146,14 @@
         const SkScalar x0 = SkIntToScalar(-bitmap.width() / 2);
         const SkScalar y0 = SkIntToScalar(-bitmap.height() / 2);
 
-        for (int i = 0; i < N; i++) {
+        int count = N;
+#ifdef SK_RELEASE
+        // in DEBUG, N is always 1
+        if (paint.getFlags() & SkPaint::kBicubicFilterBitmap_Flag) {
+            count /= BICUBIC_DUR_SCALE;
+        }
+#endif
+        for (int i = 0; i < count; i++) {
             SkScalar x = x0 + rand.nextUScalar1() * dim.fX;
             SkScalar y = y0 + rand.nextUScalar1() * dim.fY;
 
@@ -170,6 +164,17 @@
         }
     }
 
+    virtual float onGetDurationScale() SK_OVERRIDE {
+        SkPaint paint;
+        this->setupPaint(&paint);
+#ifdef SK_DEBUG
+        return 1;
+#else
+        return (paint.getFlags() & SkPaint::kBicubicFilterBitmap_Flag) ?
+                BICUBIC_DUR_SCALE : 1;
+#endif
+    }
+
     virtual void onDrawIntoBitmap(const SkBitmap& bm) {
         const int w = bm.width();
         const int h = bm.height();
@@ -196,38 +201,53 @@
 /** Explicitly invoke some filter types to improve coverage of acceleration
     procs. */
 
+enum Flags {
+    kScale_Flag             = 1 << 0,
+    kRotate_Flag            = 1 << 1,
+    kBilerp_Flag            = 1 << 2,
+    kBicubic_Flag           = 1 << 3,
+};
+
+static bool isBilerp(uint32_t flags) {
+    return (flags & (kBilerp_Flag | kBicubic_Flag)) == (kBilerp_Flag);
+}
+
+static bool isBicubic(uint32_t flags) {
+    return (flags & (kBilerp_Flag | kBicubic_Flag)) == (kBilerp_Flag | kBicubic_Flag);
+}
+
 class FilterBitmapBench : public BitmapBench {
-    bool        fScale;
-    bool        fRotate;
-    bool        fFilter;
+    uint32_t    fFlags;
     SkString    fFullName;
     enum { N = SkBENCHLOOP(300) };
 public:
     FilterBitmapBench(void* param, bool isOpaque, SkBitmap::Config c,
-                bool forceUpdate = false, bool bitmapVolatile = false,
-                int tx = -1, int ty = -1, bool addScale = false,
-                bool addRotate = false, bool addFilter = false)
-        : INHERITED(param, isOpaque, c, forceUpdate, bitmapVolatile, tx, ty)
-        , fScale(addScale), fRotate(addRotate), fFilter(addFilter) {
-
+                      bool forceUpdate, bool isVolitile, uint32_t flags)
+        : INHERITED(param, isOpaque, c, forceUpdate, isVolitile)
+        , fFlags(flags) {
     }
 
 protected:
     virtual const char* onGetName() {
         fFullName.set(INHERITED::onGetName());
-        if (fScale)
+        if (fFlags & kScale_Flag) {
             fFullName.append("_scale");
-        if (fRotate)
+        }
+        if (fFlags & kRotate_Flag) {
             fFullName.append("_rotate");
-        if (fFilter)
-            fFullName.append("_filter");
+        }
+        if (isBilerp(fFlags)) {
+            fFullName.append("_bilerp");
+        } else if (isBicubic(fFlags)) {
+            fFullName.append("_bicubic");
+        }
 
         return fFullName.c_str();
     }
 
     virtual void onDraw(SkCanvas* canvas) {
         SkISize dim = canvas->getDeviceSize();
-        if (fScale) {
+        if (fFlags & kScale_Flag) {
             const SkScalar x = SkIntToScalar(dim.fWidth) / 2;
             const SkScalar y = SkIntToScalar(dim.fHeight) / 2;
 
@@ -236,7 +256,7 @@
             canvas->scale(SK_Scalar1 * 99/100, SK_Scalar1 * 99/100);
             canvas->translate(-x, -y);
         }
-        if (fRotate) {
+        if (fFlags & kRotate_Flag) {
             const SkScalar x = SkIntToScalar(dim.fWidth) / 2;
             const SkScalar y = SkIntToScalar(dim.fHeight) / 2;
 
@@ -245,7 +265,16 @@
             canvas->translate(-x, -y);
         }
 
-        this->setForceFilter(fFilter);
+        uint32_t orMask = 0;
+        uint32_t clearMask = SkPaint::kFilterBitmap_Flag | SkPaint::kBicubicFilterBitmap_Flag;
+        if (fFlags & kBilerp_Flag) {
+            orMask |= SkPaint::kFilterBitmap_Flag;
+        }
+        if (fFlags & kBicubic_Flag) {
+            orMask |= SkPaint::kBicubicFilterBitmap_Flag;
+        }
+        this->setPaintMasks(orMask, clearMask);
+
         INHERITED::onDraw(canvas);
     }
 
@@ -264,9 +293,8 @@
     SourceAlpha fSourceAlpha;
 public:
     SourceAlphaBitmapBench(void* param, SourceAlpha alpha, SkBitmap::Config c,
-                bool forceUpdate = false, bool bitmapVolatile = false,
-                int tx = -1, int ty = -1)
-        : INHERITED(param, false, c, forceUpdate, bitmapVolatile, tx, ty)
+                bool forceUpdate = false, bool bitmapVolatile = false)
+        : INHERITED(param, false, c, forceUpdate, bitmapVolatile)
         , fSourceAlpha(alpha) {
     }
 
@@ -354,16 +382,19 @@
 DEF_BENCH( return new BitmapBench(p, true, SkBitmap::kARGB_8888_Config, true, false); )
 
 // scale filter -> S32_opaque_D32_filter_DX_{SSE2,SSSE3} and Fact9 is also for S32_D16_filter_DX_SSE2
-DEF_BENCH( return new FilterBitmapBench(p, false, SkBitmap::kARGB_8888_Config, false, false, -1, -1, true, false, true); )
-DEF_BENCH( return new FilterBitmapBench(p, true, SkBitmap::kARGB_8888_Config, false, false, -1, -1, true, false, true); )
-DEF_BENCH( return new FilterBitmapBench(p, true, SkBitmap::kARGB_8888_Config, true, true, -1, -1, true, false, true); )
-DEF_BENCH( return new FilterBitmapBench(p, true, SkBitmap::kARGB_8888_Config, true, false, -1, -1, true, false, true); )
+DEF_BENCH( return new FilterBitmapBench(p, false, SkBitmap::kARGB_8888_Config, false, false, kScale_Flag | kBilerp_Flag); )
+DEF_BENCH( return new FilterBitmapBench(p, true, SkBitmap::kARGB_8888_Config, false, false, kScale_Flag | kBilerp_Flag); )
+DEF_BENCH( return new FilterBitmapBench(p, true, SkBitmap::kARGB_8888_Config, true, true, kScale_Flag | kBilerp_Flag); )
+DEF_BENCH( return new FilterBitmapBench(p, true, SkBitmap::kARGB_8888_Config, true, false, kScale_Flag | kBilerp_Flag); )
 
 // scale rotate filter -> S32_opaque_D32_filter_DXDY_{SSE2,SSSE3}
-DEF_BENCH( return new FilterBitmapBench(p, false, SkBitmap::kARGB_8888_Config, false, false, -1, -1, true, true, true); )
-DEF_BENCH( return new FilterBitmapBench(p, true, SkBitmap::kARGB_8888_Config, false, false, -1, -1, true, true, true); )
-DEF_BENCH( return new FilterBitmapBench(p, true, SkBitmap::kARGB_8888_Config, true, true, -1, -1, true, true, true); )
-DEF_BENCH( return new FilterBitmapBench(p, true, SkBitmap::kARGB_8888_Config, true, false, -1, -1, true, true, true); )
+DEF_BENCH( return new FilterBitmapBench(p, false, SkBitmap::kARGB_8888_Config, false, false, kScale_Flag | kRotate_Flag | kBilerp_Flag); )
+DEF_BENCH( return new FilterBitmapBench(p, true, SkBitmap::kARGB_8888_Config, false, false, kScale_Flag | kRotate_Flag | kBilerp_Flag); )
+DEF_BENCH( return new FilterBitmapBench(p, true, SkBitmap::kARGB_8888_Config, true, true, kScale_Flag | kRotate_Flag | kBilerp_Flag); )
+DEF_BENCH( return new FilterBitmapBench(p, true, SkBitmap::kARGB_8888_Config, true, false, kScale_Flag | kRotate_Flag | kBilerp_Flag); )
+
+DEF_BENCH( return new FilterBitmapBench(p, false, SkBitmap::kARGB_8888_Config, false, false, kScale_Flag | kBilerp_Flag | kBicubic_Flag); )
+DEF_BENCH( return new FilterBitmapBench(p, false, SkBitmap::kARGB_8888_Config, false, false, kScale_Flag | kRotate_Flag | kBilerp_Flag | kBicubic_Flag); )
 
 // source alpha tests -> S32A_Opaque_BlitRow32_{arm,neon}
 DEF_BENCH( return new SourceAlphaBitmapBench(p, SourceAlphaBitmapBench::kOpaque_SourceAlpha, SkBitmap::kARGB_8888_Config); )