DM: also run benches once.

Also:
  - make GrMemoryPoolBenches threadsafe
  - some tweaks to various DM code
  - rename GM::shortName() to getName() to match benches and tests

On my desktop, (289 GMs, 617 benches) x 4 configs, 227 tests takes 46s in Debug, 14s in Release.  (Still minutes faster than running tests && bench && gm.)  GPU singlethreading is definitely the limiting factor again; going to reexamine whether that's helpful to thread it again.

BUG=skia:
R=reed@google.com, bsalomon@google.com, mtklein@google.com

Author: mtklein@chromium.org

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

git-svn-id: http://skia.googlecode.com/svn/trunk@13603 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/dm/DM.cpp b/dm/DM.cpp
index ee53e9d..bf37d20 100644
--- a/dm/DM.cpp
+++ b/dm/DM.cpp
@@ -3,6 +3,7 @@
 
 #include "GrContext.h"
 #include "GrContextFactory.h"
+#include "SkBenchmark.h"
 #include "SkCommandLineFlags.h"
 #include "SkForceLinking.h"
 #include "SkGraphics.h"
@@ -10,6 +11,7 @@
 #include "Test.h"
 #include "gm.h"
 
+#include "DMBenchTask.h"
 #include "DMCpuTask.h"
 #include "DMGpuTask.h"
 #include "DMReporter.h"
@@ -38,11 +40,12 @@
                           "^ and $ requires an exact match\n"
                           "If a GM does not match any list entry,\n"
                           "it is skipped unless some list entry starts with ~");
-DEFINE_string(config, "565 8888 gpu",
-        "Options: 565 8888 gpu msaa4 msaa16 gpunull gpudebug angle mesa"); // TODO(mtklein): pdf
+DEFINE_string(config, "565 8888 gpu nonrendering",
+              "Options: 565 8888 gpu nonrendering msaa4 msaa16 gpunull gpudebug angle mesa");
 DEFINE_bool(leaks, false, "Print leaked instance-counted objects at exit?");
 
 DEFINE_bool(gms, true, "Run GMs?");
+DEFINE_bool(benches, true, "Run benches?  Does not run GMs-as-benches.");
 DEFINE_bool(tests, true, "Run tests?");
 
 __SK_FORCE_IMAGE_DECODER_LINKING;
@@ -55,46 +58,68 @@
     return s;
 }
 
+static const GrContextFactory::GLContextType native = GrContextFactory::kNative_GLContextType;
+static const GrContextFactory::GLContextType null   = GrContextFactory::kNull_GLContextType;
+static const GrContextFactory::GLContextType debug  = GrContextFactory::kDebug_GLContextType;
+static const GrContextFactory::GLContextType angle  =
+#if SK_ANGLE
+GrContextFactory::kANGLE_GLContextType;
+#else
+native;
+#endif
+static const GrContextFactory::GLContextType mesa   =
+#if SK_MESA
+GLContextFactory::kMESA_GLContextType;
+#else
+native;
+#endif
+
 static void kick_off_gms(const SkTDArray<GMRegistry::Factory>& gms,
                          const SkTArray<SkString>& configs,
                          const DM::Expectations& expectations,
                          DM::Reporter* reporter,
                          DM::TaskRunner* tasks) {
-    const SkColorType _565 = kRGB_565_SkColorType;
-    const SkColorType _8888 = kPMColor_SkColorType;
-    const GrContextFactory::GLContextType native = GrContextFactory::kNative_GLContextType;
-    const GrContextFactory::GLContextType null   = GrContextFactory::kNull_GLContextType;
-    const GrContextFactory::GLContextType debug  = GrContextFactory::kDebug_GLContextType;
-    const GrContextFactory::GLContextType angle  =
-    #if SK_ANGLE
-        GrContextFactory::kANGLE_GLContextType;
-    #else
-        native;
-    #endif
-    const GrContextFactory::GLContextType mesa   =
-    #if SK_MESA
-        GLContextFactory::kMESA_GLContextType;
-    #else
-        native;
-    #endif
-
-    for (int i = 0; i < gms.count(); i++) {
-#define START(name, type, ...)                                                     \
-    if (lowercase(configs[j]).equals(name)) {                                      \
-        tasks->add(SkNEW_ARGS(DM::type,                                            \
-                    (name, reporter, tasks, expectations, gms[i], __VA_ARGS__)));  \
+#define START(name, type, ...)                                                        \
+    if (lowercase(configs[j]).equals(name)) {                                         \
+        tasks->add(SkNEW_ARGS(DM::type,                                               \
+                    (name, reporter, tasks, expectations, gms[i], ## __VA_ARGS__)));  \
     }
+    for (int i = 0; i < gms.count(); i++) {
         for (int j = 0; j < configs.count(); j++) {
-            START("565",      CpuTask, _565);
-            START("8888",     CpuTask, _8888);
-            START("gpu",      GpuTask, _8888, native, 0);
-            START("msaa4",    GpuTask, _8888, native, 4);
-            START("msaa16",   GpuTask, _8888, native, 16);
-            START("gpunull",  GpuTask, _8888, null,   0);
-            START("gpudebug", GpuTask, _8888, debug,  0);
-            START("angle",    GpuTask, _8888, angle,  0);
-            START("mesa",     GpuTask, _8888, mesa,   0);
-            //START("pdf",      PdfTask, _8888);
+            START("565",      CpuTask, kRGB_565_SkColorType);
+            START("8888",     CpuTask, kPMColor_SkColorType);
+            START("gpu",      GpuTask, native, 0);
+            START("msaa4",    GpuTask, native, 4);
+            START("msaa16",   GpuTask, native, 16);
+            START("gpunull",  GpuTask, null,   0);
+            START("gpudebug", GpuTask, debug,  0);
+            START("angle",    GpuTask, angle,  0);
+            START("mesa",     GpuTask, mesa,   0);
+        }
+    }
+#undef START
+}
+
+static void kick_off_benches(const SkTDArray<BenchRegistry::Factory>& benches,
+                             const SkTArray<SkString>& configs,
+                             DM::Reporter* reporter,
+                             DM::TaskRunner* tasks) {
+#define START(name, type, ...)                                                                 \
+    if (lowercase(configs[j]).equals(name)) {                                                  \
+        tasks->add(SkNEW_ARGS(DM::type, (name, reporter, tasks, benches[i], ## __VA_ARGS__))); \
+    }
+    for (int i = 0; i < benches.count(); i++) {
+        for (int j = 0; j < configs.count(); j++) {
+            START("nonrendering", NonRenderingBenchTask);
+            START("565",          CpuBenchTask, kRGB_565_SkColorType);
+            START("8888",         CpuBenchTask, kPMColor_SkColorType);
+            START("gpu",          GpuBenchTask, native, 0);
+            START("msaa4",        GpuBenchTask, native, 4);
+            START("msaa16",       GpuBenchTask, native, 16);
+            START("gpunull",      GpuBenchTask, null,   0);
+            START("gpudebug",     GpuBenchTask, debug,  0);
+            START("angle",        GpuBenchTask, angle,  0);
+            START("mesa",         GpuBenchTask, mesa,   0);
         }
     }
 #undef START
@@ -122,31 +147,36 @@
     }
 }
 
+template <typename T, typename Registry>
+static void append_matching_factories(Registry* head, SkTDArray<typename Registry::Factory>* out) {
+    for (const Registry* reg = head; reg != NULL; reg = reg->next()) {
+        SkAutoTDelete<T> forName(reg->factory()(NULL));
+        if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, forName->getName())) {
+            *out->append() = reg->factory();
+        }
+    }
+}
+
 int tool_main(int argc, char** argv);
 int tool_main(int argc, char** argv) {
+    SkGraphics::Init();
+    SkCommandLineFlags::Parse(argc, argv);
 #if SK_ENABLE_INST_COUNT
     gPrintInstCount = FLAGS_leaks;
 #endif
-    SkGraphics::Init();
-    SkCommandLineFlags::Parse(argc, argv);
     GM::SetResourcePath(FLAGS_resources[0]);
+    SkBenchmark::SetResourcePath(FLAGS_resources[0]);
     Test::SetResourcePath(FLAGS_resources[0]);
 
     SkTArray<SkString> configs;
+    for (int i = 0; i < FLAGS_config.count(); i++) {
+        SkStrSplit(FLAGS_config[i], ", ", &configs);
+    }
+
     SkTDArray<GMRegistry::Factory> gms;
     SkAutoTDelete<DM::Expectations> expectations(SkNEW(DM::NoExpectations));
-
     if (FLAGS_gms) {
-        for (int i = 0; i < FLAGS_config.count(); i++) {
-            SkStrSplit(FLAGS_config[i], ", ", &configs);
-        }
-
-        for (const GMRegistry* reg = GMRegistry::Head(); reg != NULL; reg = reg->next()) {
-            SkAutoTDelete<GM> gmForName(reg->factory()(NULL));
-            if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, gmForName->shortName())) {
-                *gms.append() = reg->factory();
-            }
-        }
+        append_matching_factories<GM>(GMRegistry::Head(), &gms);
 
         if (FLAGS_expectations.count() > 0) {
             const char* path = FLAGS_expectations[0];
@@ -158,20 +188,22 @@
         }
     }
 
-    SkTDArray<TestRegistry::Factory> tests;
-    if (FLAGS_tests) {
-        for (const TestRegistry* reg = TestRegistry::Head(); reg != NULL; reg = reg->next()) {
-            SkAutoTDelete<Test> testForName(reg->factory()(NULL));
-            if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, testForName->getName())) {
-                *tests.append() = reg->factory();
-            }
-        }
+    SkTDArray<BenchRegistry::Factory> benches;
+    if (FLAGS_benches) {
+        append_matching_factories<SkBenchmark>(BenchRegistry::Head(), &benches);
     }
 
-    SkDebugf("%d GMs x %d configs, %d tests\n", gms.count(), configs.count(), tests.count());
+    SkTDArray<TestRegistry::Factory> tests;
+    if (FLAGS_tests) {
+        append_matching_factories<Test>(TestRegistry::Head(), &tests);
+    }
+
+    SkDebugf("(%d GMs, %d benches) x %d configs, %d tests\n",
+             gms.count(), benches.count(), configs.count(), tests.count());
     DM::Reporter reporter;
     DM::TaskRunner tasks(FLAGS_threads);
     kick_off_gms(gms, configs, *expectations, &reporter, &tasks);
+    kick_off_benches(benches, configs, &reporter, &tasks);
     kick_off_tests(tests, &reporter, &tasks);
     tasks.wait();
 
diff --git a/dm/DMBenchTask.cpp b/dm/DMBenchTask.cpp
new file mode 100644
index 0000000..4e251de
--- /dev/null
+++ b/dm/DMBenchTask.cpp
@@ -0,0 +1,86 @@
+#include "DMBenchTask.h"
+#include "DMUtil.h"
+#include "SkSurface.h"
+
+namespace DM {
+
+static SkString bench_name(const char* name, const char* config) {
+    SkString result("bench ");
+    result.appendf("%s_%s", name, config);
+    return result;
+}
+
+NonRenderingBenchTask::NonRenderingBenchTask(const char* config,
+                                             Reporter* reporter,
+                                             TaskRunner* tasks,
+                                             BenchRegistry::Factory factory)
+    : Task(reporter, tasks)
+    , fBench(factory(NULL))
+    , fName(bench_name(fBench->getName(), config)) {}
+
+CpuBenchTask::CpuBenchTask(const char* config,
+                           Reporter* reporter,
+                           TaskRunner* tasks,
+                           BenchRegistry::Factory factory,
+                           SkColorType colorType)
+    : Task(reporter, tasks)
+    , fBench(factory(NULL))
+    , fName(bench_name(fBench->getName(), config))
+    , fColorType(colorType) {}
+
+GpuBenchTask::GpuBenchTask(const char* config,
+                           Reporter* reporter,
+                           TaskRunner* tasks,
+                           BenchRegistry::Factory factory,
+                           GrContextFactory::GLContextType contextType,
+                           int sampleCount)
+    : Task(reporter, tasks)
+    , fBench(factory(NULL))
+    , fName(bench_name(fBench->getName(), config))
+    , fContextType(contextType)
+    , fSampleCount(sampleCount) {}
+
+bool NonRenderingBenchTask::shouldSkip() const {
+    return !fBench->isSuitableFor(SkBenchmark::kNonRendering_Backend);
+}
+
+bool CpuBenchTask::shouldSkip() const {
+    return !fBench->isSuitableFor(SkBenchmark::kRaster_Backend);
+}
+
+bool GpuBenchTask::shouldSkip() const {
+    return !fBench->isSuitableFor(SkBenchmark::kGPU_Backend);
+}
+
+static void draw_raster(SkBenchmark* bench, SkColorType colorType) {
+    SkBitmap bitmap;
+    SetupBitmap(colorType, bench, &bitmap);
+    SkCanvas canvas(bitmap);
+
+    bench->preDraw();
+    bench->draw(1, &canvas);
+    bench->postDraw();
+}
+
+void NonRenderingBenchTask::draw() {
+    draw_raster(fBench.get(), kPMColor_SkColorType);
+}
+
+void CpuBenchTask::draw() {
+    draw_raster(fBench.get(), fColorType);
+}
+
+void GpuBenchTask::draw() {
+    SkImageInfo info = SkImageInfo::Make(fBench->getSize().x(),
+                                         fBench->getSize().y(),
+                                         kPMColor_SkColorType,
+                                         kPremul_SkAlphaType);
+    SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(
+            this->getGrContextFactory()->get(fContextType), info, fSampleCount));
+
+    fBench->preDraw();
+    fBench->draw(1, surface->getCanvas());
+    fBench->postDraw();
+}
+
+}  // namespace DM
diff --git a/dm/DMBenchTask.h b/dm/DMBenchTask.h
new file mode 100644
index 0000000..1e9bc99
--- /dev/null
+++ b/dm/DMBenchTask.h
@@ -0,0 +1,67 @@
+#ifndef DMBenchTask_DEFINED
+#define DMBenchTask_DEFINED
+
+#include "DMReporter.h"
+#include "DMTask.h"
+#include "DMTaskRunner.h"
+#include "SkBenchmark.h"
+#include "SkString.h"
+#include "SkTemplates.h"
+
+// Tasks that run an SkBenchmark once as a check that it doesn't crash.
+
+namespace DM {
+
+class NonRenderingBenchTask : public Task {
+public:
+    NonRenderingBenchTask(const char* config, Reporter*, TaskRunner*, BenchRegistry::Factory);
+
+    virtual void draw() SK_OVERRIDE;
+    virtual bool usesGpu() const SK_OVERRIDE { return false; }
+    virtual bool shouldSkip() const SK_OVERRIDE;
+    virtual SkString name() const SK_OVERRIDE { return fName; }
+
+private:
+    SkAutoTDelete<SkBenchmark> fBench;
+    const SkString fName;
+};
+
+class CpuBenchTask : public Task {
+public:
+    CpuBenchTask(const char* config, Reporter*, TaskRunner*, BenchRegistry::Factory, SkColorType);
+
+    virtual void draw() SK_OVERRIDE;
+    virtual bool usesGpu() const SK_OVERRIDE { return false; }
+    virtual bool shouldSkip() const SK_OVERRIDE;
+    virtual SkString name() const SK_OVERRIDE { return fName; }
+
+private:
+    SkAutoTDelete<SkBenchmark> fBench;
+    const SkString fName;
+    const SkColorType fColorType;
+};
+
+class GpuBenchTask : public Task {
+public:
+    GpuBenchTask(const char* config,
+                 Reporter*,
+                 TaskRunner*,
+                 BenchRegistry::Factory,
+                 GrContextFactory::GLContextType,
+                 int sampleCount);
+
+    virtual void draw() SK_OVERRIDE;
+    virtual bool usesGpu() const SK_OVERRIDE { return true; }
+    virtual bool shouldSkip() const SK_OVERRIDE;
+    virtual SkString name() const SK_OVERRIDE { return fName; }
+
+private:
+    SkAutoTDelete<SkBenchmark> fBench;
+    const SkString fName;
+    const GrContextFactory::GLContextType fContextType;
+    int fSampleCount;
+};
+
+}  // namespace DM
+
+#endif // DMBenchTask_DEFINED
diff --git a/dm/DMCpuTask.cpp b/dm/DMCpuTask.cpp
index 7a82a75..acbe8d2 100644
--- a/dm/DMCpuTask.cpp
+++ b/dm/DMCpuTask.cpp
@@ -9,7 +9,7 @@
 
 namespace DM {
 
-CpuTask::CpuTask(const char* name,
+CpuTask::CpuTask(const char* config,
                  Reporter* reporter,
                  TaskRunner* taskRunner,
                  const Expectations& expectations,
@@ -18,7 +18,7 @@
     : Task(reporter, taskRunner)
     , fGMFactory(gmFactory)
     , fGM(fGMFactory(NULL))
-    , fName(UnderJoin(fGM->shortName(), name))
+    , fName(UnderJoin(fGM->getName(), config))
     , fExpectations(expectations)
     , fColorType(colorType)
     {}
diff --git a/dm/DMCpuTask.h b/dm/DMCpuTask.h
index 8e7f531..0ae112f 100644
--- a/dm/DMCpuTask.h
+++ b/dm/DMCpuTask.h
@@ -17,7 +17,7 @@
 
 class CpuTask : public Task {
 public:
-    CpuTask(const char* name,
+    CpuTask(const char* config,
             Reporter*,
             TaskRunner*,
             const Expectations&,
diff --git a/dm/DMGpuTask.cpp b/dm/DMGpuTask.cpp
index 3a4708b..c285d88 100644
--- a/dm/DMGpuTask.cpp
+++ b/dm/DMGpuTask.cpp
@@ -9,20 +9,17 @@
 
 namespace DM {
 
-GpuTask::GpuTask(const char* name,
+GpuTask::GpuTask(const char* config,
                  Reporter* reporter,
                  TaskRunner* taskRunner,
                  const Expectations& expectations,
                  skiagm::GMRegistry::Factory gmFactory,
-                 SkColorType colorType,
                  GrContextFactory::GLContextType contextType,
                  int sampleCount)
     : Task(reporter, taskRunner)
-    , fTaskRunner(taskRunner)
     , fGM(gmFactory(NULL))
-    , fName(UnderJoin(fGM->shortName(), name))
+    , fName(UnderJoin(fGM->getName(), config))
     , fExpectations(expectations)
-    , fColorType(colorType)
     , fContextType(contextType)
     , fSampleCount(sampleCount)
     {}
@@ -30,10 +27,10 @@
 void GpuTask::draw() {
     SkImageInfo info = SkImageInfo::Make(SkScalarCeilToInt(fGM->width()),
                                          SkScalarCeilToInt(fGM->height()),
-                                         fColorType,
+                                         kPMColor_SkColorType,
                                          kPremul_SkAlphaType);
-    GrContext* gr = fTaskRunner->getGrContextFactory()->get(fContextType);  // Owned by surface.
-    SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(gr, info, fSampleCount));
+    SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(
+            this->getGrContextFactory()->get(fContextType), info, fSampleCount));
     SkCanvas* canvas = surface->getCanvas();
 
     canvas->concat(fGM->getInitialTransform());
diff --git a/dm/DMGpuTask.h b/dm/DMGpuTask.h
index 1380e44..f74950c 100644
--- a/dm/DMGpuTask.h
+++ b/dm/DMGpuTask.h
@@ -17,12 +17,11 @@
 
 class GpuTask : public Task {
 public:
-    GpuTask(const char* name,
+    GpuTask(const char* config,
             Reporter*,
             TaskRunner*,
             const Expectations&,
             skiagm::GMRegistry::Factory,
-            SkColorType,
             GrContextFactory::GLContextType,
             int sampleCount);
 
@@ -32,11 +31,9 @@
     virtual SkString name() const SK_OVERRIDE { return fName; }
 
 private:
-    TaskRunner* fTaskRunner;
     SkAutoTDelete<skiagm::GM> fGM;
     const SkString fName;
     const Expectations& fExpectations;
-    const SkColorType fColorType;
     const GrContextFactory::GLContextType fContextType;
     const int fSampleCount;
 };
diff --git a/dm/DMTask.cpp b/dm/DMTask.cpp
index 2f009f0..d26971c 100644
--- a/dm/DMTask.cpp
+++ b/dm/DMTask.cpp
@@ -46,4 +46,8 @@
     fReporter->fail(failure);
 }
 
+GrContextFactory* Task::getGrContextFactory() const {
+    return fTaskRunner->getGrContextFactory();
+}
+
 }  // namespace DM
diff --git a/dm/DMTask.h b/dm/DMTask.h
index 638a939..e8598df 100644
--- a/dm/DMTask.h
+++ b/dm/DMTask.h
@@ -2,6 +2,7 @@
 #define DMTask_DEFINED
 
 #include "DMReporter.h"
+#include "GrContextFactory.h"
 #include "SkRunnable.h"
 #include "SkThreadPool.h"
 
@@ -36,6 +37,9 @@
     void spawnChild(Task* task);
     void fail(const char* msg = NULL);
 
+    // This can only be safely called from a GPU task's draw() method.
+    GrContextFactory* getGrContextFactory() const;
+
 private:
     // Both unowned.
     Reporter* fReporter;
diff --git a/dm/DMTestTask.cpp b/dm/DMTestTask.cpp
index 7a5f8cf..32a698c 100644
--- a/dm/DMTestTask.cpp
+++ b/dm/DMTestTask.cpp
@@ -8,17 +8,22 @@
 
 namespace DM {
 
+static SkString test_name(const char* name) {
+    SkString result("test ");
+    result.append(name);
+    return result;
+}
+
 TestTask::TestTask(Reporter* reporter,
                    TaskRunner* taskRunner,
                    skiatest::TestRegistry::Factory factory)
     : Task(reporter, taskRunner)
-    , fTaskRunner(taskRunner)
     , fTest(factory(NULL))
-    , fName(UnderJoin("test", fTest->getName())) {}
+    , fName(test_name(fTest->getName())) {}
 
 void TestTask::draw() {
     if (this->usesGpu()) {
-        fTest->setGrContextFactory(fTaskRunner->getGrContextFactory());
+        fTest->setGrContextFactory(this->getGrContextFactory());
     }
     fTest->setReporter(&fTestReporter);
     fTest->run();
diff --git a/dm/DMTestTask.h b/dm/DMTestTask.h
index a4903ee..49a8e77 100644
--- a/dm/DMTestTask.h
+++ b/dm/DMTestTask.h
@@ -39,7 +39,6 @@
       SkString fFailure;
     };
 
-    TaskRunner* fTaskRunner;
     TestReporter fTestReporter;
     SkAutoTDelete<skiatest::Test> fTest;
     const SkString fName;
diff --git a/dm/DMUtil.cpp b/dm/DMUtil.cpp
index 849d1bf..5a849fb 100644
--- a/dm/DMUtil.cpp
+++ b/dm/DMUtil.cpp
@@ -19,13 +19,19 @@
     picture->endRecording();
 }
 
-void SetupBitmap(const SkColorType ct, skiagm::GM* gm, SkBitmap* bitmap) {
-    const SkISize size = gm->getISize();
-    bitmap->allocPixels(SkImageInfo::Make(size.width(), size.height(),
-                                          ct, kPremul_SkAlphaType));
+static void setup_bitmap(SkColorType ct, int width, int height, SkBitmap* bitmap) {
+    bitmap->allocPixels(SkImageInfo::Make(width, height, ct, kPremul_SkAlphaType));
     bitmap->eraseColor(0x00000000);
 }
 
+void SetupBitmap(const SkColorType ct, skiagm::GM* gm, SkBitmap* bitmap) {
+    setup_bitmap(ct, gm->getISize().width(), gm->getISize().height(), bitmap);
+}
+
+void SetupBitmap(const SkColorType ct, SkBenchmark* bench, SkBitmap* bitmap) {
+    setup_bitmap(ct, bench->getSize().x(), bench->getSize().y(), bitmap);
+}
+
 void DrawPicture(SkPicture* picture, SkBitmap* bitmap) {
     SkASSERT(picture != NULL);
     SkASSERT(bitmap != NULL);
diff --git a/dm/DMUtil.h b/dm/DMUtil.h
index a791649..faa4e39 100644
--- a/dm/DMUtil.h
+++ b/dm/DMUtil.h
@@ -1,6 +1,7 @@
 #ifndef DMUtil_DEFINED
 #define DMUtil_DEFINED
 
+#include "SkBenchmark.h"
 #include "SkBitmap.h"
 #include "SkString.h"
 #include "gm_expectations.h"
@@ -15,8 +16,10 @@
 // Draw gm to picture.  Passes recordFlags to SkPicture::beginRecording().
 void RecordPicture(skiagm::GM* gm, SkPicture* picture, uint32_t recordFlags = 0);
 
-// Prepare bitmap to have gm draw into it with this config.
+// Prepare bitmap to have gm or bench draw into it with this config.
+// TODO(mtklein): make SkBenchmark::getSize()/GM::getISize() const.
 void SetupBitmap(const SkColorType, skiagm::GM* gm, SkBitmap* bitmap);
+void SetupBitmap(const SkColorType, SkBenchmark* bench, SkBitmap* bitmap);
 
 // Draw picture to bitmap.
 void DrawPicture(SkPicture* picture, SkBitmap* bitmap);