nanobench.cpp revision 5cb4885b4cd1ac5eb3fc92dac5f5509d7c810464
1f372321de3d4183de5b9ca436e677e471e358f31mtklein/*
2f372321de3d4183de5b9ca436e677e471e358f31mtklein * Copyright 2014 Google Inc.
3f372321de3d4183de5b9ca436e677e471e358f31mtklein *
4f372321de3d4183de5b9ca436e677e471e358f31mtklein * Use of this source code is governed by a BSD-style license that can be
5f372321de3d4183de5b9ca436e677e471e358f31mtklein * found in the LICENSE file.
6f372321de3d4183de5b9ca436e677e471e358f31mtklein */
7f372321de3d4183de5b9ca436e677e471e358f31mtklein
8bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#include <ctype.h>
9bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
10d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson#include "nanobench.h"
11d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
12f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "Benchmark.h"
137f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett#include "BitmapRegionDecoderBench.h"
1460869a42a133942f852dd0f1696444c2a5c9ad83scroggo#include "CodecBench.h"
157f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett#include "CodecBenchPriv.h"
16f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "CrashHandler.h"
1795f192d19938b98a45dd1fa4112d965f60d10516msarett#include "DecodingBench.h"
18e714e75c725c987fe682a1f5473224fe3e80380dmtklein#include "GMBench.h"
19afb4379dbca4d4d3824ace183a7348d24bc1589fmtklein#include "ProcStats.h"
2060317d0ffb5053df7b08a627d6decd11b684e80dmtklein#include "ResultsWriter.h"
21fd731ce804cd3223318f3feee2c98404890b65f2mtklein#include "RecordingBench.h"
22261c3ad7fde95748da92550735decc949dc73bf2joshualitt#include "SKPAnimationBench.h"
2392007583e43115998412ac8b0a06cc2780eb025cmtklein#include "SKPBench.h"
24b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett#include "SubsetSingleBench.h"
25b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett#include "SubsetTranslateBench.h"
26b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett#include "SubsetZoomBench.h"
27f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "Stats.h"
28f372321de3d4183de5b9ca436e677e471e358f31mtklein
295cb4885b4cd1ac5eb3fc92dac5f5509d7c810464msarett#include "SkBitmapRegionDecoder.h"
306838d854a87e79f1fbb7b89b9f395155ad44dc0amtklein#include "SkBBoxHierarchy.h"
31f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "SkCanvas.h"
3260869a42a133942f852dd0f1696444c2a5c9ad83scroggo#include "SkCodec.h"
3317f0b6df7248b9bbdaddacc3a6c9c6efe4ae278ecaryclark#include "SkCommonFlags.h"
3495f192d19938b98a45dd1fa4112d965f60d10516msarett#include "SkData.h"
35f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "SkForceLinking.h"
36f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "SkGraphics.h"
372084050a33ae139d0fe9bb680f7905f91139a39fmtklein#include "SkOSFile.h"
382084050a33ae139d0fe9bb680f7905f91139a39fmtklein#include "SkPictureRecorder.h"
39051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein#include "SkPictureUtils.h"
40f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "SkString.h"
41f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "SkSurface.h"
425b69377507478623dcf5b11f3ecb010f87c4794frobertphillips#include "SkTaskGroup.h"
43f372321de3d4183de5b9ca436e677e471e358f31mtklein
4460e0fee6d4acff638ccc9670c4055aced529a7a0bungeman#include <stdlib.h>
4560e0fee6d4acff638ccc9670c4055aced529a7a0bungeman
46d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
47d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    #include "nanobenchAndroid.h"
48d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson#endif
49d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
50bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#if SK_SUPPORT_GPU
51bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    #include "gl/GrGLDefines.h"
52762286309545c8a1e4bbc05dcd1fe3085d2a1f47bsalomon    #include "GrCaps.h"
53bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    #include "GrContextFactory.h"
5469a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski    SkAutoTDelete<GrContextFactory> gGrFactory;
55bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#endif
56bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
57682c269a1511200322916af83053e26004c0ec40bsalomon    struct GrContextOptions;
58682c269a1511200322916af83053e26004c0ec40bsalomon
59f372321de3d4183de5b9ca436e677e471e358f31mtklein__SK_FORCE_IMAGE_DECODER_LINKING;
60f372321de3d4183de5b9ca436e677e471e358f31mtklein
615324978a88677ac6b758324321816427814e7793reedstatic const int kAutoTuneLoops = 0;
626eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
63b511042bb07a6a289b0d1146cb57f6e8b80580d6mtkleinstatic const int kDefaultLoops =
646eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon#ifdef SK_DEBUG
656eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    1;
66a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein#else
676eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    kAutoTuneLoops;
68a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein#endif
69a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein
706eb03cc06d0bc60da5277a83aa0251a475794b04bsalomonstatic SkString loops_help_txt() {
716eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    SkString help;
726eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    help.printf("Number of times to run each bench. Set this to %d to auto-"
736eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                "tune for each bench. Timings are only reported when auto-tuning.",
746eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                kAutoTuneLoops);
756eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    return help;
766eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon}
776eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
78e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdaltonstatic SkString to_string(int n) {
79e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton    SkString str;
80e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton    str.appendS32(n);
81e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton    return str;
82e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton}
83e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton
846eb03cc06d0bc60da5277a83aa0251a475794b04bsalomonDEFINE_int32(loops, kDefaultLoops, loops_help_txt().c_str());
856eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
86f372321de3d4183de5b9ca436e677e471e358f31mtkleinDEFINE_int32(samples, 10, "Number of samples to measure for each bench.");
87bbba16878f343b232d844281fbdf056c00e20fb6mtkleinDEFINE_int32(ms, 0, "If >0, run each bench for this many ms instead of obeying --samples.");
88f372321de3d4183de5b9ca436e677e471e358f31mtkleinDEFINE_int32(overheadLoops, 100000, "Loops to estimate timer overhead.");
89f372321de3d4183de5b9ca436e677e471e358f31mtkleinDEFINE_double(overheadGoal, 0.0001,
90f372321de3d4183de5b9ca436e677e471e358f31mtklein              "Loop until timer overhead is at most this fraction of our measurments.");
91bb6a02823929584231c8e080ee69e7fb1178cbfbmtkleinDEFINE_double(gpuMs, 5, "Target bench time in millseconds for GPU.");
92d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdaltonDEFINE_int32(gpuFrameLag, 5, "If unknown, estimated maximum number of frames GPU allows to lag.");
9312b3544028e74712c6c095ed3a2e8a78de6b2ed8krajcevskiDEFINE_bool(gpuCompressAlphaMasks, false, "Compress masks generated from falling back to "
9412b3544028e74712c6c095ed3a2e8a78de6b2ed8krajcevski                                          "software path rendering.");
95f372321de3d4183de5b9ca436e677e471e358f31mtklein
9660317d0ffb5053df7b08a627d6decd11b684e80dmtkleinDEFINE_string(outResultsFile, "", "If given, write results here as JSON.");
9755b0ffc4861e940d8bcf767ff9abf44ff18545eamtkleinDEFINE_int32(maxCalibrationAttempts, 3,
9855b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein             "Try up to this many times to guess loops for a bench, or skip the bench.");
9955b0ffc4861e940d8bcf767ff9abf44ff18545eamtkleinDEFINE_int32(maxLoops, 1000000, "Never run a bench more times than this.");
10092007583e43115998412ac8b0a06cc2780eb025cmtkleinDEFINE_string(clip, "0,0,1000,1000", "Clip for SKPs.");
10192007583e43115998412ac8b0a06cc2780eb025cmtkleinDEFINE_string(scales, "1.0", "Space-separated scales for SKPs.");
10263a82855b1f0b83952b65fca330954c50ebe7a4bcdaltonDEFINE_string(zoom, "1.0,0", "Comma-separated zoomMax,zoomPeriodMs factors for a periodic SKP zoom "
10363a82855b1f0b83952b65fca330954c50ebe7a4bcdalton                             "function that ping-pongs between 1.0 and zoomMax.");
1042084050a33ae139d0fe9bb680f7905f91139a39fmtkleinDEFINE_bool(bbh, true, "Build a BBH for SKPs?");
1055b69377507478623dcf5b11f3ecb010f87c4794frobertphillipsDEFINE_bool(mpd, true, "Use MultiPictureDraw for the SKPs?");
106b4022965a280dd1ed64d6103dd29e2189abe6e00cdaltonDEFINE_bool(loopSKP, true, "Loop SKPs like we do for micro benches?");
107e070c2bf54c451f0126d4ffb3a48bffe1fbfa437mtkleinDEFINE_int32(flushEvery, 10, "Flush --outResultsFile every Nth run.");
10855e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtkleinDEFINE_bool(resetGpuContext, true, "Reset the GrContext before running each test.");
109b12ea41286ce36e085c5a14711da0cf9f240fdf1bsalomonDEFINE_bool(gpuStats, false, "Print GPU stats after each gpu benchmark?");
1102da1a854b0836001533aa29ade89d87f420cbbc3scroggoDEFINE_bool(pngBuildTileIndex, false, "If supported, use png buildTileIndex/decodeSubset.");
111860e8a67190e024b7375e52e270e6bd0a17af86escroggoDEFINE_bool(jpgBuildTileIndex, false, "If supported, use jpg buildTileIndex/decodeSubset.");
11292007583e43115998412ac8b0a06cc2780eb025cmtklein
113bbba16878f343b232d844281fbdf056c00e20fb6mtkleinstatic double now_ms() { return SkTime::GetNSecs() * 1e-6; }
114bbba16878f343b232d844281fbdf056c00e20fb6mtklein
115f372321de3d4183de5b9ca436e677e471e358f31mtkleinstatic SkString humanize(double ms) {
116dc5bbab138bfffc85d6ba525d990aad09c322ff6mtklein    if (FLAGS_verbose) return SkStringPrintf("%llu", (uint64_t)(ms*1e6));
117748ca3bf2d170708f263693e8579e6722389d0efmtklein    return HumanizeMs(ms);
118f372321de3d4183de5b9ca436e677e471e358f31mtklein}
11955b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein#define HUMANIZE(ms) humanize(ms).c_str()
120f372321de3d4183de5b9ca436e677e471e358f31mtklein
121d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudsonbool Target::init(SkImageInfo info, Benchmark* bench) {
122d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    if (Benchmark::kRaster_Backend == config.backend) {
123d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        this->surface.reset(SkSurface::NewRaster(info));
124d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        if (!this->surface.get()) {
125d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson            return false;
126d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        }
127d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
128d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    return true;
129d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson}
130d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudsonbool Target::capturePixels(SkBitmap* bmp) {
13175a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson    SkCanvas* canvas = this->getCanvas();
132d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    if (!canvas) {
133d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        return false;
134d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
135d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    bmp->setInfo(canvas->imageInfo());
136d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    if (!canvas->readPixels(bmp, 0, 0)) {
137d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        SkDebugf("Can't read canvas pixels.\n");
138d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        return false;
139d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
140d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    return true;
141d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson}
142d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
143d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson#if SK_SUPPORT_GPU
144d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudsonstruct GPUTarget : public Target {
14596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    explicit GPUTarget(const Config& c) : Target(c), gl(nullptr) { }
146d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    SkGLContext* gl;
147d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
148d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    void setup() override {
149d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        this->gl->makeCurrent();
150d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        // Make sure we're done with whatever came before.
151d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        SK_GL(*this->gl, Finish());
152d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
153d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    void endTiming() override {
154d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        if (this->gl) {
155d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson            SK_GL(*this->gl, Flush());
156d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson            this->gl->swapBuffers();
157d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        }
158d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
159d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    void fence() override {
160d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        SK_GL(*this->gl, Finish());
161d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
162d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein
163d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton    bool needsFrameTiming(int* maxFrameLag) const override {
164d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton        if (!this->gl->getMaxGpuFrameLag(maxFrameLag)) {
165d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton            // Frame lag is unknown.
166d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton            *maxFrameLag = FLAGS_gpuFrameLag;
167d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton        }
168d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton        return true;
169d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton    }
170d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    bool init(SkImageInfo info, Benchmark* bench) override {
171afcd7cd32497cc79035e61fd64b0baa03ed04bccbsalomon        uint32_t flags = this->config.useDFText ? SkSurfaceProps::kUseDeviceIndependentFonts_Flag :
172afcd7cd32497cc79035e61fd64b0baa03ed04bccbsalomon                                                  0;
173d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType);
174d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        this->surface.reset(SkSurface::NewRenderTarget(gGrFactory->get(this->config.ctxType),
175d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson                                                         SkSurface::kNo_Budgeted, info,
176d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson                                                         this->config.samples, &props));
177d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        this->gl = gGrFactory->getGLContext(this->config.ctxType);
178d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        if (!this->surface.get()) {
179d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson            return false;
180d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        }
181d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton        if (!this->gl->fenceSyncSupport()) {
182d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton            SkDebugf("WARNING: GL context for config \"%s\" does not support fence sync. "
183d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton                     "Timings might not be accurate.\n", this->config.name);
184d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton        }
185d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        return true;
186d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
187d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    void fillOptions(ResultsWriter* log) override {
188d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        const GrGLubyte* version;
189d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        SK_GL_RET(*this->gl, version, GetString(GR_GL_VERSION));
190d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        log->configOption("GL_VERSION", (const char*)(version));
191d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
192d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        SK_GL_RET(*this->gl, version, GetString(GR_GL_RENDERER));
193d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        log->configOption("GL_RENDERER", (const char*) version);
194d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
195d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        SK_GL_RET(*this->gl, version, GetString(GR_GL_VENDOR));
196d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        log->configOption("GL_VENDOR", (const char*) version);
197d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
198d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        SK_GL_RET(*this->gl, version, GetString(GR_GL_SHADING_LANGUAGE_VERSION));
199d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        log->configOption("GL_SHADING_LANGUAGE_VERSION", (const char*) version);
200d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
201d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson};
202d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein
203d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson#endif
204d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
20575a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudsonstatic double time(int loops, Benchmark* bench, Target* target) {
20675a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson    SkCanvas* canvas = target->getCanvas();
2076eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (canvas) {
2086eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        canvas->clear(SK_ColorWHITE);
2096eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
2108a6697af95b340aad6dee7e6228048fa305c1e59joshualitt    bench->preDraw(canvas);
211bbba16878f343b232d844281fbdf056c00e20fb6mtklein    double start = now_ms();
21275a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson    canvas = target->beginTiming(canvas);
21375a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson    bench->draw(loops, canvas);
214f372321de3d4183de5b9ca436e677e471e358f31mtklein    if (canvas) {
215f372321de3d4183de5b9ca436e677e471e358f31mtklein        canvas->flush();
216f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
21775a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson    target->endTiming();
218bbba16878f343b232d844281fbdf056c00e20fb6mtklein    double elapsed = now_ms() - start;
2198a6697af95b340aad6dee7e6228048fa305c1e59joshualitt    bench->postDraw(canvas);
220bbba16878f343b232d844281fbdf056c00e20fb6mtklein    return elapsed;
221f372321de3d4183de5b9ca436e677e471e358f31mtklein}
222f372321de3d4183de5b9ca436e677e471e358f31mtklein
223bb6a02823929584231c8e080ee69e7fb1178cbfbmtkleinstatic double estimate_timer_overhead() {
224bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    double overhead = 0;
225bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    for (int i = 0; i < FLAGS_overheadLoops; i++) {
226bbba16878f343b232d844281fbdf056c00e20fb6mtklein        double start = now_ms();
227bbba16878f343b232d844281fbdf056c00e20fb6mtklein        overhead += now_ms() - start;
228bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    }
229bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    return overhead / FLAGS_overheadLoops;
230bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein}
231f372321de3d4183de5b9ca436e677e471e358f31mtklein
2325324978a88677ac6b758324321816427814e7793reedstatic int detect_forever_loops(int loops) {
2335324978a88677ac6b758324321816427814e7793reed    // look for a magic run-forever value
2345324978a88677ac6b758324321816427814e7793reed    if (loops < 0) {
2355324978a88677ac6b758324321816427814e7793reed        loops = SK_MaxS32;
2365324978a88677ac6b758324321816427814e7793reed    }
2375324978a88677ac6b758324321816427814e7793reed    return loops;
2385324978a88677ac6b758324321816427814e7793reed}
2395324978a88677ac6b758324321816427814e7793reed
24055b0ffc4861e940d8bcf767ff9abf44ff18545eamtkleinstatic int clamp_loops(int loops) {
24155b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    if (loops < 1) {
242527930fdbbba2a20f98b43821c6b72367e7b2d64mtklein        SkDebugf("ERROR: clamping loops from %d to 1. "
243527930fdbbba2a20f98b43821c6b72367e7b2d64mtklein                 "There's probably something wrong with the bench.\n", loops);
24455b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein        return 1;
24555b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    }
24655b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    if (loops > FLAGS_maxLoops) {
24755b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein        SkDebugf("WARNING: clamping loops from %d to FLAGS_maxLoops, %d.\n", loops, FLAGS_maxLoops);
24855b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein        return FLAGS_maxLoops;
24955b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    }
25055b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    return loops;
25155b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein}
25255b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein
253d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudsonstatic bool write_canvas_png(Target* target, const SkString& filename) {
254d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
2556eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (filename.isEmpty()) {
2566eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
2576eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
25875a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson    if (target->getCanvas() &&
25975a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson        kUnknown_SkColorType == target->getCanvas()->imageInfo().colorType()) {
2606eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
2616eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
262d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
2636eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    SkBitmap bmp;
264d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
265d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    if (!target->capturePixels(&bmp)) {
2666eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
2676eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
268d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
2696eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    SkString dir = SkOSPath::Dirname(filename.c_str());
2706eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (!sk_mkdir(dir.c_str())) {
2716eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Can't make dir %s.\n", dir.c_str());
2726eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
2736eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
2746eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    SkFILEWStream stream(filename.c_str());
2756eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (!stream.isValid()) {
2766eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Can't write %s.\n", filename.c_str());
2776eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
2786eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
2796eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (!SkImageEncoder::EncodeStream(&stream, bmp, SkImageEncoder::kPNG_Type, 100)) {
2806eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Can't encode a PNG.\n");
2816eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
2826eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
2836eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    return true;
2846eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon}
2856eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
2866eb03cc06d0bc60da5277a83aa0251a475794b04bsalomonstatic int kFailedLoops = -2;
287e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdaltonstatic int setup_cpu_bench(const double overhead, Target* target, Benchmark* bench) {
288bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // First figure out approximately how many loops of bench it takes to make overhead negligible.
2892069e220034f09aad2f68b262f395e7c25b3d178mtklein    double bench_plus_overhead = 0.0;
29055b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    int round = 0;
291b4022965a280dd1ed64d6103dd29e2189abe6e00cdalton    int loops = bench->calculateLoops(FLAGS_loops);
292b4022965a280dd1ed64d6103dd29e2189abe6e00cdalton    if (kAutoTuneLoops == loops) {
2936eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        while (bench_plus_overhead < overhead) {
2946eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            if (round++ == FLAGS_maxCalibrationAttempts) {
2956eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                SkDebugf("WARNING: Can't estimate loops for %s (%s vs. %s); skipping.\n",
296962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein                         bench->getUniqueName(), HUMANIZE(bench_plus_overhead), HUMANIZE(overhead));
2976eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                return kFailedLoops;
2986eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            }
29975a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson            bench_plus_overhead = time(1, bench, target);
30055b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein        }
3012069e220034f09aad2f68b262f395e7c25b3d178mtklein    }
302f372321de3d4183de5b9ca436e677e471e358f31mtklein
303bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // Later we'll just start and stop the timer once but loop N times.
304f372321de3d4183de5b9ca436e677e471e358f31mtklein    // We'll pick N to make timer overhead negligible:
305f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
306bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //          overhead
307bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //  -------------------------  < FLAGS_overheadGoal
308bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //  overhead + N * Bench Time
309f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
310bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // where bench_plus_overhead ≈ overhead + Bench Time.
311f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
312f372321de3d4183de5b9ca436e677e471e358f31mtklein    // Doing some math, we get:
313f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
314bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //  (overhead / FLAGS_overheadGoal) - overhead
315bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //  ------------------------------------------  < N
316bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //       bench_plus_overhead - overhead)
317f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
318f372321de3d4183de5b9ca436e677e471e358f31mtklein    // Luckily, this also works well in practice. :)
3196eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (kAutoTuneLoops == loops) {
3206eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        const double numer = overhead / FLAGS_overheadGoal - overhead;
3216eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        const double denom = bench_plus_overhead - overhead;
3226eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        loops = (int)ceil(numer / denom);
3235324978a88677ac6b758324321816427814e7793reed        loops = clamp_loops(loops);
3245324978a88677ac6b758324321816427814e7793reed    } else {
3255324978a88677ac6b758324321816427814e7793reed        loops = detect_forever_loops(loops);
3266eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
327bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
328bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    return loops;
329f372321de3d4183de5b9ca436e677e471e358f31mtklein}
330f372321de3d4183de5b9ca436e677e471e358f31mtklein
331e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdaltonstatic int setup_gpu_bench(Target* target, Benchmark* bench, int maxGpuFrameLag) {
332bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // First, figure out how many loops it'll take to get a frame up to FLAGS_gpuMs.
333b4022965a280dd1ed64d6103dd29e2189abe6e00cdalton    int loops = bench->calculateLoops(FLAGS_loops);
3346eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (kAutoTuneLoops == loops) {
3356eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        loops = 1;
336a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        double elapsed = 0;
337a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        do {
338527930fdbbba2a20f98b43821c6b72367e7b2d64mtklein            if (1<<30 == loops) {
339527930fdbbba2a20f98b43821c6b72367e7b2d64mtklein                // We're about to wrap.  Something's wrong with the bench.
340527930fdbbba2a20f98b43821c6b72367e7b2d64mtklein                loops = 0;
341527930fdbbba2a20f98b43821c6b72367e7b2d64mtklein                break;
342527930fdbbba2a20f98b43821c6b72367e7b2d64mtklein            }
343a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            loops *= 2;
344a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            // If the GPU lets frames lag at all, we need to make sure we're timing
345d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton            // _this_ round, not still timing last round.
346d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton            for (int i = 0; i < maxGpuFrameLag; i++) {
34775a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson                elapsed = time(loops, bench, target);
348a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            }
349a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        } while (elapsed < FLAGS_gpuMs);
350a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein
351a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        // We've overshot at least a little.  Scale back linearly.
352a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        loops = (int)ceil(loops * FLAGS_gpuMs / elapsed);
3535324978a88677ac6b758324321816427814e7793reed        loops = clamp_loops(loops);
354a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein
355d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        // Make sure we're not still timing our calibration.
356d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        target->fence();
3575324978a88677ac6b758324321816427814e7793reed    } else {
3585324978a88677ac6b758324321816427814e7793reed        loops = detect_forever_loops(loops);
359a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein    }
360bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
361bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // Pretty much the same deal as the calibration: do some warmup to make
362bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // sure we're timing steady-state pipelined frames.
363d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton    for (int i = 0; i < maxGpuFrameLag - 1; i++) {
36475a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson        time(loops, bench, target);
365f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
366bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
367bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    return loops;
368f372321de3d4183de5b9ca436e677e471e358f31mtklein}
369bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
370bb6a02823929584231c8e080ee69e7fb1178cbfbmtkleinstatic SkString to_lower(const char* str) {
371bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    SkString lower(str);
372bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    for (size_t i = 0; i < lower.size(); i++) {
373bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        lower[i] = tolower(lower[i]);
374bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    }
375bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    return lower;
376bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein}
377bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
378c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstatic bool is_cpu_config_allowed(const char* name) {
379bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    for (int i = 0; i < FLAGS_config.count(); i++) {
380c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        if (to_lower(FLAGS_config[i]).equals(name)) {
381c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            return true;
382bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        }
383f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
384c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    return false;
385bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein}
386f372321de3d4183de5b9ca436e677e471e358f31mtklein
387c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#if SK_SUPPORT_GPU
388c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstatic bool is_gpu_config_allowed(const char* name, GrContextFactory::GLContextType ctxType,
389c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                                  int sampleCnt) {
390c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    if (!is_cpu_config_allowed(name)) {
391c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        return false;
392c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
39369a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski    if (const GrContext* ctx = gGrFactory->get(ctxType)) {
394762286309545c8a1e4bbc05dcd1fe3085d2a1f47bsalomon        return sampleCnt <= ctx->caps()->maxSampleCount();
395c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
396c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    return false;
397c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon}
398c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#endif
399c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
400c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#if SK_SUPPORT_GPU
401c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#define kBogusGLContextType GrContextFactory::kNative_GLContextType
402c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#else
403c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#define kBogusGLContextType 0
404e714e75c725c987fe682a1f5473224fe3e80380dmtklein#endif
405c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
406c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon// Append all configs that are enabled and supported.
407c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstatic void create_configs(SkTDArray<Config>* configs) {
4084736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth    #define CPU_CONFIG(name, backend, color, alpha)                       \
4094736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth        if (is_cpu_config_allowed(#name)) {                               \
4104736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth            Config config = { #name, Benchmark::backend, color, alpha, 0, \
4114736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth                              kBogusGLContextType, false };               \
4124736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth            configs->push(config);                                        \
413f372321de3d4183de5b9ca436e677e471e358f31mtklein        }
414e714e75c725c987fe682a1f5473224fe3e80380dmtklein
41540b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein    if (FLAGS_cpu) {
416c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        CPU_CONFIG(nonrendering, kNonRendering_Backend, kUnknown_SkColorType, kUnpremul_SkAlphaType)
417c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        CPU_CONFIG(8888, kRaster_Backend, kN32_SkColorType, kPremul_SkAlphaType)
418c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        CPU_CONFIG(565, kRaster_Backend, kRGB_565_SkColorType, kOpaque_SkAlphaType)
41940b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein    }
420f372321de3d4183de5b9ca436e677e471e358f31mtklein
421bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#if SK_SUPPORT_GPU
4224736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth    #define GPU_CONFIG(name, ctxType, samples, useDFText)                        \
423c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        if (is_gpu_config_allowed(#name, GrContextFactory::ctxType, samples)) {  \
424c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            Config config = {                                                    \
425c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                #name,                                                           \
426c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                Benchmark::kGPU_Backend,                                         \
427c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                kN32_SkColorType,                                                \
428c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                kPremul_SkAlphaType,                                             \
429c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                samples,                                                         \
4304736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth                GrContextFactory::ctxType,                                       \
4314736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth                useDFText };                                                     \
432c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            configs->push(config);                                               \
433f372321de3d4183de5b9ca436e677e471e358f31mtklein        }
434e714e75c725c987fe682a1f5473224fe3e80380dmtklein
43540b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein    if (FLAGS_gpu) {
4364736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth        GPU_CONFIG(gpu, kNative_GLContextType, 0, false)
4374736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth        GPU_CONFIG(msaa4, kNative_GLContextType, 4, false)
4384736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth        GPU_CONFIG(msaa16, kNative_GLContextType, 16, false)
4394736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth        GPU_CONFIG(nvprmsaa4, kNVPR_GLContextType, 4, false)
4404736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth        GPU_CONFIG(nvprmsaa16, kNVPR_GLContextType, 16, false)
4414736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth        GPU_CONFIG(gpudft, kNative_GLContextType, 0, true)
4424736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth        GPU_CONFIG(debug, kDebug_GLContextType, 0, false)
4434736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth        GPU_CONFIG(nullgpu, kNull_GLContextType, 0, false)
4443b4d077fba1ad037536db198608a940c47d91888bsalomon#ifdef SK_ANGLE
4454736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth        GPU_CONFIG(angle, kANGLE_GLContextType, 0, false)
446eddbefb4a5794b1d9f4e58a7cdf4e768b837c17fhendrikw        GPU_CONFIG(angle-gl, kANGLE_GL_GLContextType, 0, false)
4473b4d077fba1ad037536db198608a940c47d91888bsalomon#endif
448885bf0925514b9dfe3365bab227d36897d866b5dhendrikw#ifdef SK_COMMAND_BUFFER
449885bf0925514b9dfe3365bab227d36897d866b5dhendrikw        GPU_CONFIG(commandbuffer, kCommandBuffer_GLContextType, 0, false)
450885bf0925514b9dfe3365bab227d36897d866b5dhendrikw#endif
451d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton#if SK_MESA
452d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton        GPU_CONFIG(mesa, kMESA_GLContextType, 0, false)
453d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton#endif
45440b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein    }
455bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#endif
456d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
457d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
458d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    if (is_cpu_config_allowed("hwui")) {
459d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        Config config = { "hwui", Benchmark::kHWUI_Backend, kRGBA_8888_SkColorType,
460d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson                          kPremul_SkAlphaType, 0, kBogusGLContextType, false };
461d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        configs->push(config);
462d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
463d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson#endif
464f372321de3d4183de5b9ca436e677e471e358f31mtklein}
465f372321de3d4183de5b9ca436e677e471e358f31mtklein
46696fcdcc219d2a0d3579719b84b28bede76efba64halcanary// If bench is enabled for config, returns a Target* for it, otherwise nullptr.
467c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstatic Target* is_enabled(Benchmark* bench, const Config& config) {
468c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    if (!bench->isSuitableFor(config.backend)) {
46996fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
470c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
471c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
472e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    SkImageInfo info = SkImageInfo::Make(bench->getSize().fX, bench->getSize().fY,
473e5ea500d4714a7d84de2bf913e81be3b65d2de68reed                                         config.color, config.alpha);
474c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
47596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    Target* target = nullptr;
476c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
477d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    switch (config.backend) {
478c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#if SK_SUPPORT_GPU
479d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    case Benchmark::kGPU_Backend:
480d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        target = new GPUTarget(config);
481d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        break;
482d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson#endif
483d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
484d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    case Benchmark::kHWUI_Backend:
485d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        target = new HWUITarget(config, bench);
486d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        break;
487c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#endif
488d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    default:
489d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        target = new Target(config);
490d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        break;
491d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
492c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
493d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    if (!target->init(info, bench)) {
494c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        delete target;
49596fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
496c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
497c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    return target;
498c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon}
499c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
500b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett/*
501ab12c2715886e7f04c415028a7db49fb0b1e67f3scroggo * We only run our subset benches on files that are supported by BitmapRegionDecoder:
502ab12c2715886e7f04c415028a7db49fb0b1e67f3scroggo * i.e. PNG, JPEG, and WEBP. We do *not* test WEBP when using codec, since we do not
503ab12c2715886e7f04c415028a7db49fb0b1e67f3scroggo * have a scanline decoder for WEBP, which is necessary for running the subset bench.
504ab12c2715886e7f04c415028a7db49fb0b1e67f3scroggo * (Another bench must be used to test WEBP, which decodes subsets natively.)
505ab12c2715886e7f04c415028a7db49fb0b1e67f3scroggo */
506ab12c2715886e7f04c415028a7db49fb0b1e67f3scroggostatic bool run_subset_bench(const SkString& path, bool useCodec) {
507ab12c2715886e7f04c415028a7db49fb0b1e67f3scroggo    static const char* const exts[] = {
5082da1a854b0836001533aa29ade89d87f420cbbc3scroggo        "jpg", "jpeg",
5092da1a854b0836001533aa29ade89d87f420cbbc3scroggo        "JPG", "JPEG",
510ab12c2715886e7f04c415028a7db49fb0b1e67f3scroggo    };
511ab12c2715886e7f04c415028a7db49fb0b1e67f3scroggo
512860e8a67190e024b7375e52e270e6bd0a17af86escroggo    if (useCodec || FLAGS_jpgBuildTileIndex) {
513860e8a67190e024b7375e52e270e6bd0a17af86escroggo        for (uint32_t i = 0; i < SK_ARRAY_COUNT(exts); i++) {
514860e8a67190e024b7375e52e270e6bd0a17af86escroggo            if (path.endsWith(exts[i])) {
515860e8a67190e024b7375e52e270e6bd0a17af86escroggo                return true;
516860e8a67190e024b7375e52e270e6bd0a17af86escroggo            }
517ab12c2715886e7f04c415028a7db49fb0b1e67f3scroggo        }
518ab12c2715886e7f04c415028a7db49fb0b1e67f3scroggo    }
519ab12c2715886e7f04c415028a7db49fb0b1e67f3scroggo
5202da1a854b0836001533aa29ade89d87f420cbbc3scroggo    // Test png in SkCodec, and optionally on SkImageDecoder. SkImageDecoder is
5212da1a854b0836001533aa29ade89d87f420cbbc3scroggo    // disabled by default because it leaks memory.
5222da1a854b0836001533aa29ade89d87f420cbbc3scroggo    // skbug.com/4360
5232da1a854b0836001533aa29ade89d87f420cbbc3scroggo    if ((useCodec || FLAGS_pngBuildTileIndex) && (path.endsWith("png") || path.endsWith("PNG"))) {
5242da1a854b0836001533aa29ade89d87f420cbbc3scroggo        return true;
5252da1a854b0836001533aa29ade89d87f420cbbc3scroggo    }
5262da1a854b0836001533aa29ade89d87f420cbbc3scroggo
5272da1a854b0836001533aa29ade89d87f420cbbc3scroggo    if (!useCodec && (path.endsWith("webp") || path.endsWith("WEBP"))) {
5282da1a854b0836001533aa29ade89d87f420cbbc3scroggo        return true;
5292da1a854b0836001533aa29ade89d87f420cbbc3scroggo    }
5302da1a854b0836001533aa29ade89d87f420cbbc3scroggo
5312da1a854b0836001533aa29ade89d87f420cbbc3scroggo    return false;
532ab12c2715886e7f04c415028a7db49fb0b1e67f3scroggo}
533ab12c2715886e7f04c415028a7db49fb0b1e67f3scroggo
534ab12c2715886e7f04c415028a7db49fb0b1e67f3scroggo/*
535b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett * Returns true if set up for a subset decode succeeds, false otherwise
536b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett * If the set-up succeeds, the width and height parameters will be set
537b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett */
538b23e6aa6767816ac4bc6c191e78ef62d6e765671msarettstatic bool valid_subset_bench(const SkString& path, SkColorType colorType, bool useCodec,
539b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett        int* width, int* height) {
540b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett    SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(path.c_str()));
541b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett    SkAutoTDelete<SkMemoryStream> stream(new SkMemoryStream(encoded));
542b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett
543ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett    // Check that we can create a codec or image decoder.
544b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett    if (useCodec) {
545b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett        SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.detach()));
54696fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr == codec) {
547b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett            SkDebugf("Could not create codec for %s.  Skipping bench.\n", path.c_str());
548b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett            return false;
549b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett        }
550b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett
551b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett        // These will be initialized by SkCodec if the color type is kIndex8 and
552b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett        // unused otherwise.
553b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett        SkPMColor colors[256];
554b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett        int colorCount;
555b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett        const SkImageInfo info = codec->getInfo().makeColorType(colorType);
55646c574725676b26ada63ac15e42cda309dcd5090scroggo        if (codec->startScanlineDecode(info, nullptr, colors, &colorCount) != SkCodec::kSuccess)
5571c005e4a38e29d648ecebada25d3a718155043a3scroggo        {
558b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett            SkDebugf("Could not create scanline decoder for %s with color type %s.  "
5597f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                    "Skipping bench.\n", path.c_str(), color_type_to_str(colorType));
560b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett            return false;
561b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett        }
562b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett        *width = info.width();
563b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett        *height = info.height();
564b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett    } else {
565b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett        SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(stream));
56696fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr == decoder) {
567b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett            SkDebugf("Could not create decoder for %s.  Skipping bench.\n", path.c_str());
568b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett            return false;
569b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett        }
570b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett        //FIXME: See skbug.com/3921
571b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett        if (kIndex_8_SkColorType == colorType || kGray_8_SkColorType == colorType) {
572b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett            SkDebugf("Cannot use image subset decoder for %s with color type %s.  "
5737f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                    "Skipping bench.\n", path.c_str(), color_type_to_str(colorType));
574b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett            return false;
575b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett        }
576b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett        if (!decoder->buildTileIndex(stream.detach(), width, height)) {
577b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett            SkDebugf("Could not build tile index for %s.  Skipping bench.\n", path.c_str());
578b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett            return false;
579b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett        }
580b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett    }
581ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett
582ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett    // Check if the image is large enough for a meaningful subset benchmark.
583ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett    if (*width <= 512 && *height <= 512) {
584ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett        // This should not print a message since it is not an error.
585ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett        return false;
586ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett    }
587ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett
588b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett    return true;
589b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett}
590bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio
5915cb4885b4cd1ac5eb3fc92dac5f5509d7c810464msarettstatic bool valid_brd_bench(SkData* encoded, SkBitmapRegionDecoder::Strategy strategy,
5927f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        SkColorType colorType, uint32_t sampleSize, uint32_t minOutputSize, int* width,
5937f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        int* height) {
5945cb4885b4cd1ac5eb3fc92dac5f5509d7c810464msarett    SkAutoTDelete<SkBitmapRegionDecoder> brd(
5955cb4885b4cd1ac5eb3fc92dac5f5509d7c810464msarett            SkBitmapRegionDecoder::Create(encoded, strategy));
5967f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett    if (nullptr == brd.get()) {
5977f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // This is indicates that subset decoding is not supported for a particular image format.
5987f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        return false;
5997f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett    }
6007f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett
60135e5d1b4495478ca3bede66914ae07f50a447c4dmsarett    SkBitmap bitmap;
60235e5d1b4495478ca3bede66914ae07f50a447c4dmsarett    if (!brd->decodeRegion(&bitmap, nullptr, SkIRect::MakeXYWH(0, 0, brd->width(), brd->height()),
60335e5d1b4495478ca3bede66914ae07f50a447c4dmsarett            1, colorType, false)) {
60435e5d1b4495478ca3bede66914ae07f50a447c4dmsarett        return false;
60535e5d1b4495478ca3bede66914ae07f50a447c4dmsarett    }
60635e5d1b4495478ca3bede66914ae07f50a447c4dmsarett    if (colorType != bitmap.colorType()) {
6077f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // This indicates that conversion to the requested color type is not supported for the
6087f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // particular image.
6097f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        return false;
6107f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett    }
6117f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett
6127f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett    if (sampleSize * minOutputSize > (uint32_t) brd->width() || sampleSize * minOutputSize >
6137f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett            (uint32_t) brd->height()) {
6147f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // This indicates that the image is not large enough to decode a
6157f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // minOutputSize x minOutputSize subset at the given sampleSize.
6167f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        return false;
6177f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett    }
6187f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett
6197f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett    // Set the image width and height.  The calling code will use this to choose subsets to decode.
6207f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett    *width = brd->width();
6217f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett    *height = brd->height();
6227f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett    return true;
6237f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett}
6247f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett
6253bf9206ada256277a39988c263f0379d544fc27begdanielstatic void cleanup_run(Target* target) {
626385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    delete target;
6273bf9206ada256277a39988c263f0379d544fc27begdaniel#if SK_SUPPORT_GPU
6283bf9206ada256277a39988c263f0379d544fc27begdaniel    if (FLAGS_abandonGpuContext) {
6293bf9206ada256277a39988c263f0379d544fc27begdaniel        gGrFactory->abandonContexts();
6303bf9206ada256277a39988c263f0379d544fc27begdaniel    }
6313bf9206ada256277a39988c263f0379d544fc27begdaniel    if (FLAGS_resetGpuContext || FLAGS_abandonGpuContext) {
6323bf9206ada256277a39988c263f0379d544fc27begdaniel        gGrFactory->destroyContexts();
6333bf9206ada256277a39988c263f0379d544fc27begdaniel    }
6343bf9206ada256277a39988c263f0379d544fc27begdaniel#endif
6353bf9206ada256277a39988c263f0379d544fc27begdaniel}
6363bf9206ada256277a39988c263f0379d544fc27begdaniel
637e714e75c725c987fe682a1f5473224fe3e80380dmtkleinclass BenchmarkStream {
638e714e75c725c987fe682a1f5473224fe3e80380dmtkleinpublic:
63992007583e43115998412ac8b0a06cc2780eb025cmtklein    BenchmarkStream() : fBenches(BenchRegistry::Head())
64092007583e43115998412ac8b0a06cc2780eb025cmtklein                      , fGMs(skiagm::GMRegistry::Head())
641fd731ce804cd3223318f3feee2c98404890b65f2mtklein                      , fCurrentRecording(0)
64292007583e43115998412ac8b0a06cc2780eb025cmtklein                      , fCurrentScale(0)
6435b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                      , fCurrentSKP(0)
64495f192d19938b98a45dd1fa4112d965f60d10516msarett                      , fCurrentUseMPD(0)
64560869a42a133942f852dd0f1696444c2a5c9ad83scroggo                      , fCurrentCodec(0)
64695f192d19938b98a45dd1fa4112d965f60d10516msarett                      , fCurrentImage(0)
64795f192d19938b98a45dd1fa4112d965f60d10516msarett                      , fCurrentSubsetImage(0)
6487f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                      , fCurrentBRDImage(0)
64995f192d19938b98a45dd1fa4112d965f60d10516msarett                      , fCurrentColorType(0)
650b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett                      , fCurrentSubsetType(0)
651b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett                      , fUseCodec(0)
6527f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                      , fCurrentBRDStrategy(0)
6537f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                      , fCurrentBRDSampleSize(0)
654b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett                      , fCurrentAnimSKP(0) {
65592007583e43115998412ac8b0a06cc2780eb025cmtklein        for (int i = 0; i < FLAGS_skps.count(); i++) {
65692007583e43115998412ac8b0a06cc2780eb025cmtklein            if (SkStrEndsWith(FLAGS_skps[i], ".skp")) {
65792007583e43115998412ac8b0a06cc2780eb025cmtklein                fSKPs.push_back() = FLAGS_skps[i];
65892007583e43115998412ac8b0a06cc2780eb025cmtklein            } else {
65992007583e43115998412ac8b0a06cc2780eb025cmtklein                SkOSFile::Iter it(FLAGS_skps[i], ".skp");
66092007583e43115998412ac8b0a06cc2780eb025cmtklein                SkString path;
66192007583e43115998412ac8b0a06cc2780eb025cmtklein                while (it.next(&path)) {
66292007583e43115998412ac8b0a06cc2780eb025cmtklein                    fSKPs.push_back() = SkOSPath::Join(FLAGS_skps[0], path.c_str());
66392007583e43115998412ac8b0a06cc2780eb025cmtklein                }
66492007583e43115998412ac8b0a06cc2780eb025cmtklein            }
66592007583e43115998412ac8b0a06cc2780eb025cmtklein        }
66692007583e43115998412ac8b0a06cc2780eb025cmtklein
66792007583e43115998412ac8b0a06cc2780eb025cmtklein        if (4 != sscanf(FLAGS_clip[0], "%d,%d,%d,%d",
66892007583e43115998412ac8b0a06cc2780eb025cmtklein                        &fClip.fLeft, &fClip.fTop, &fClip.fRight, &fClip.fBottom)) {
66992007583e43115998412ac8b0a06cc2780eb025cmtklein            SkDebugf("Can't parse %s from --clip as an SkIRect.\n", FLAGS_clip[0]);
67092007583e43115998412ac8b0a06cc2780eb025cmtklein            exit(1);
67192007583e43115998412ac8b0a06cc2780eb025cmtklein        }
67292007583e43115998412ac8b0a06cc2780eb025cmtklein
67392007583e43115998412ac8b0a06cc2780eb025cmtklein        for (int i = 0; i < FLAGS_scales.count(); i++) {
67492007583e43115998412ac8b0a06cc2780eb025cmtklein            if (1 != sscanf(FLAGS_scales[i], "%f", &fScales.push_back())) {
67592007583e43115998412ac8b0a06cc2780eb025cmtklein                SkDebugf("Can't parse %s from --scales as an SkScalar.\n", FLAGS_scales[i]);
67692007583e43115998412ac8b0a06cc2780eb025cmtklein                exit(1);
67792007583e43115998412ac8b0a06cc2780eb025cmtklein            }
67892007583e43115998412ac8b0a06cc2780eb025cmtklein        }
6795b69377507478623dcf5b11f3ecb010f87c4794frobertphillips
68063a82855b1f0b83952b65fca330954c50ebe7a4bcdalton        if (2 != sscanf(FLAGS_zoom[0], "%f,%lf", &fZoomMax, &fZoomPeriodMs)) {
68163a82855b1f0b83952b65fca330954c50ebe7a4bcdalton            SkDebugf("Can't parse %s from --zoom as a zoomMax,zoomPeriodMs.\n", FLAGS_zoom[0]);
682261c3ad7fde95748da92550735decc949dc73bf2joshualitt            exit(1);
683261c3ad7fde95748da92550735decc949dc73bf2joshualitt        }
684261c3ad7fde95748da92550735decc949dc73bf2joshualitt
6855b69377507478623dcf5b11f3ecb010f87c4794frobertphillips        if (FLAGS_mpd) {
6865b69377507478623dcf5b11f3ecb010f87c4794frobertphillips            fUseMPDs.push_back() = true;
6875b69377507478623dcf5b11f3ecb010f87c4794frobertphillips        }
688c751ecb3681072fda53dd3cebeb2eb41fc73b314mtklein        fUseMPDs.push_back() = false;
68995553d917c73ef333ede967521560957a5b6a0admtklein
69095f192d19938b98a45dd1fa4112d965f60d10516msarett        // Prepare the images for decoding
69195f192d19938b98a45dd1fa4112d965f60d10516msarett        for (int i = 0; i < FLAGS_images.count(); i++) {
69295f192d19938b98a45dd1fa4112d965f60d10516msarett            const char* flag = FLAGS_images[i];
69395f192d19938b98a45dd1fa4112d965f60d10516msarett            if (sk_isdir(flag)) {
69495f192d19938b98a45dd1fa4112d965f60d10516msarett                // If the value passed in is a directory, add all the images
69595f192d19938b98a45dd1fa4112d965f60d10516msarett                SkOSFile::Iter it(flag);
69695f192d19938b98a45dd1fa4112d965f60d10516msarett                SkString file;
69795f192d19938b98a45dd1fa4112d965f60d10516msarett                while (it.next(&file)) {
69895f192d19938b98a45dd1fa4112d965f60d10516msarett                    fImages.push_back() = SkOSPath::Join(flag, file.c_str());
69995f192d19938b98a45dd1fa4112d965f60d10516msarett                }
70095f192d19938b98a45dd1fa4112d965f60d10516msarett            } else if (sk_exists(flag)) {
70195f192d19938b98a45dd1fa4112d965f60d10516msarett                // Also add the value if it is a single image
70295f192d19938b98a45dd1fa4112d965f60d10516msarett                fImages.push_back() = flag;
70395f192d19938b98a45dd1fa4112d965f60d10516msarett            }
70495f192d19938b98a45dd1fa4112d965f60d10516msarett        }
70595553d917c73ef333ede967521560957a5b6a0admtklein
70695f192d19938b98a45dd1fa4112d965f60d10516msarett        // Choose the candidate color types for image decoding
70795f192d19938b98a45dd1fa4112d965f60d10516msarett        const SkColorType colorTypes[] =
708b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett            { kN32_SkColorType,
709b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett              kRGB_565_SkColorType,
710b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett              kAlpha_8_SkColorType,
711b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett              kIndex_8_SkColorType,
712b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett              kGray_8_SkColorType };
71374deb981d5e9c11c88fe431e78166d6cf8dacc1amsarett        fColorTypes.reset(colorTypes, SK_ARRAY_COUNT(colorTypes));
71492007583e43115998412ac8b0a06cc2780eb025cmtklein    }
715e714e75c725c987fe682a1f5473224fe3e80380dmtklein
716fd731ce804cd3223318f3feee2c98404890b65f2mtklein    static bool ReadPicture(const char* path, SkAutoTUnref<SkPicture>* pic) {
717fd731ce804cd3223318f3feee2c98404890b65f2mtklein        // Not strictly necessary, as it will be checked again later,
718fd731ce804cd3223318f3feee2c98404890b65f2mtklein        // but helps to avoid a lot of pointless work if we're going to skip it.
719fd731ce804cd3223318f3feee2c98404890b65f2mtklein        if (SkCommandLineFlags::ShouldSkip(FLAGS_match, path)) {
720fd731ce804cd3223318f3feee2c98404890b65f2mtklein            return false;
721fd731ce804cd3223318f3feee2c98404890b65f2mtklein        }
722fd731ce804cd3223318f3feee2c98404890b65f2mtklein
723a1193e4b0e34a7e4e1bd33e9708d7341679f8321scroggo        SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(path));
72496fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (stream.get() == nullptr) {
725fd731ce804cd3223318f3feee2c98404890b65f2mtklein            SkDebugf("Could not read %s.\n", path);
726fd731ce804cd3223318f3feee2c98404890b65f2mtklein            return false;
727fd731ce804cd3223318f3feee2c98404890b65f2mtklein        }
728fd731ce804cd3223318f3feee2c98404890b65f2mtklein
72957f27bdcbd328491a121918b4ab9301fbcdec642mtklein        pic->reset(SkPicture::CreateFromStream(stream.get()));
73096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (pic->get() == nullptr) {
731fd731ce804cd3223318f3feee2c98404890b65f2mtklein            SkDebugf("Could not read %s as an SkPicture.\n", path);
732fd731ce804cd3223318f3feee2c98404890b65f2mtklein            return false;
733fd731ce804cd3223318f3feee2c98404890b65f2mtklein        }
734fd731ce804cd3223318f3feee2c98404890b65f2mtklein        return true;
735fd731ce804cd3223318f3feee2c98404890b65f2mtklein    }
736fd731ce804cd3223318f3feee2c98404890b65f2mtklein
73792007583e43115998412ac8b0a06cc2780eb025cmtklein    Benchmark* next() {
738e714e75c725c987fe682a1f5473224fe3e80380dmtklein        if (fBenches) {
73996fcdcc219d2a0d3579719b84b28bede76efba64halcanary            Benchmark* bench = fBenches->factory()(nullptr);
740e714e75c725c987fe682a1f5473224fe3e80380dmtklein            fBenches = fBenches->next();
74192007583e43115998412ac8b0a06cc2780eb025cmtklein            fSourceType = "bench";
742fd731ce804cd3223318f3feee2c98404890b65f2mtklein            fBenchType  = "micro";
743e714e75c725c987fe682a1f5473224fe3e80380dmtklein            return bench;
744e714e75c725c987fe682a1f5473224fe3e80380dmtklein        }
74592007583e43115998412ac8b0a06cc2780eb025cmtklein
746e714e75c725c987fe682a1f5473224fe3e80380dmtklein        while (fGMs) {
74796fcdcc219d2a0d3579719b84b28bede76efba64halcanary            SkAutoTDelete<skiagm::GM> gm(fGMs->factory()(nullptr));
748e714e75c725c987fe682a1f5473224fe3e80380dmtklein            fGMs = fGMs->next();
749cf5d9c993dcbd75d4cefe2d1de25c2b9645f6957mtklein            if (gm->runAsBench()) {
75092007583e43115998412ac8b0a06cc2780eb025cmtklein                fSourceType = "gm";
751fd731ce804cd3223318f3feee2c98404890b65f2mtklein                fBenchType  = "micro";
752385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary                return new GMBench(gm.detach());
753e714e75c725c987fe682a1f5473224fe3e80380dmtklein            }
754e714e75c725c987fe682a1f5473224fe3e80380dmtklein        }
75592007583e43115998412ac8b0a06cc2780eb025cmtklein
756fd731ce804cd3223318f3feee2c98404890b65f2mtklein        // First add all .skps as RecordingBenches.
757fd731ce804cd3223318f3feee2c98404890b65f2mtklein        while (fCurrentRecording < fSKPs.count()) {
758fd731ce804cd3223318f3feee2c98404890b65f2mtklein            const SkString& path = fSKPs[fCurrentRecording++];
759fd731ce804cd3223318f3feee2c98404890b65f2mtklein            SkAutoTUnref<SkPicture> pic;
760fd731ce804cd3223318f3feee2c98404890b65f2mtklein            if (!ReadPicture(path.c_str(), &pic)) {
761fd731ce804cd3223318f3feee2c98404890b65f2mtklein                continue;
762fd731ce804cd3223318f3feee2c98404890b65f2mtklein            }
763fd731ce804cd3223318f3feee2c98404890b65f2mtklein            SkString name = SkOSPath::Basename(path.c_str());
764fd731ce804cd3223318f3feee2c98404890b65f2mtklein            fSourceType = "skp";
765fd731ce804cd3223318f3feee2c98404890b65f2mtklein            fBenchType  = "recording";
7660aa5cea8694d3686b6742a36eab81ab9001de954bsalomon            fSKPBytes = static_cast<double>(SkPictureUtils::ApproximateBytesUsed(pic));
767051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein            fSKPOps   = pic->approximateOpCount();
768385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary            return new RecordingBench(name.c_str(), pic.get(), FLAGS_bbh);
769fd731ce804cd3223318f3feee2c98404890b65f2mtklein        }
770fd731ce804cd3223318f3feee2c98404890b65f2mtklein
771fd731ce804cd3223318f3feee2c98404890b65f2mtklein        // Then once each for each scale as SKPBenches (playback).
77292007583e43115998412ac8b0a06cc2780eb025cmtklein        while (fCurrentScale < fScales.count()) {
77392007583e43115998412ac8b0a06cc2780eb025cmtklein            while (fCurrentSKP < fSKPs.count()) {
7745b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                const SkString& path = fSKPs[fCurrentSKP];
775fd731ce804cd3223318f3feee2c98404890b65f2mtklein                SkAutoTUnref<SkPicture> pic;
776fd731ce804cd3223318f3feee2c98404890b65f2mtklein                if (!ReadPicture(path.c_str(), &pic)) {
7775b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                    fCurrentSKP++;
77892007583e43115998412ac8b0a06cc2780eb025cmtklein                    continue;
77992007583e43115998412ac8b0a06cc2780eb025cmtklein                }
7805b69377507478623dcf5b11f3ecb010f87c4794frobertphillips
7815b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                while (fCurrentUseMPD < fUseMPDs.count()) {
7825b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                    if (FLAGS_bbh) {
7835b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                        // The SKP we read off disk doesn't have a BBH.  Re-record so it grows one.
7845b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                        SkRTreeFactory factory;
7855b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                        SkPictureRecorder recorder;
7865b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                        static const int kFlags = SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag;
7875b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                        pic->playback(recorder.beginRecording(pic->cullRect().width(),
7885b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                                                              pic->cullRect().height(),
789748ca3bf2d170708f263693e8579e6722389d0efmtklein                                                              &factory,
790e451c4df7369c5e253ef9c9e0a8713beda25f34brobertphillips                                                              fUseMPDs[fCurrentUseMPD] ? kFlags : 0));
7915b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                        pic.reset(recorder.endRecording());
7925b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                    }
7935b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                    SkString name = SkOSPath::Basename(path.c_str());
7945b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                    fSourceType = "skp";
7955b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                    fBenchType = "playback";
796385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary                    return new SKPBench(name.c_str(), pic.get(), fClip, fScales[fCurrentScale],
797385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary                                        fUseMPDs[fCurrentUseMPD++], FLAGS_loopSKP);
7982084050a33ae139d0fe9bb680f7905f91139a39fmtklein                }
7995b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                fCurrentUseMPD = 0;
8005b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                fCurrentSKP++;
80192007583e43115998412ac8b0a06cc2780eb025cmtklein            }
80292007583e43115998412ac8b0a06cc2780eb025cmtklein            fCurrentSKP = 0;
80392007583e43115998412ac8b0a06cc2780eb025cmtklein            fCurrentScale++;
80492007583e43115998412ac8b0a06cc2780eb025cmtklein        }
80592007583e43115998412ac8b0a06cc2780eb025cmtklein
806261c3ad7fde95748da92550735decc949dc73bf2joshualitt        // Now loop over each skp again if we have an animation
80763a82855b1f0b83952b65fca330954c50ebe7a4bcdalton        if (fZoomMax != 1.0f && fZoomPeriodMs > 0) {
808261c3ad7fde95748da92550735decc949dc73bf2joshualitt            while (fCurrentAnimSKP < fSKPs.count()) {
809261c3ad7fde95748da92550735decc949dc73bf2joshualitt                const SkString& path = fSKPs[fCurrentAnimSKP];
810261c3ad7fde95748da92550735decc949dc73bf2joshualitt                SkAutoTUnref<SkPicture> pic;
811261c3ad7fde95748da92550735decc949dc73bf2joshualitt                if (!ReadPicture(path.c_str(), &pic)) {
812261c3ad7fde95748da92550735decc949dc73bf2joshualitt                    fCurrentAnimSKP++;
813261c3ad7fde95748da92550735decc949dc73bf2joshualitt                    continue;
814261c3ad7fde95748da92550735decc949dc73bf2joshualitt                }
815261c3ad7fde95748da92550735decc949dc73bf2joshualitt
816261c3ad7fde95748da92550735decc949dc73bf2joshualitt                fCurrentAnimSKP++;
817261c3ad7fde95748da92550735decc949dc73bf2joshualitt                SkString name = SkOSPath::Basename(path.c_str());
81863a82855b1f0b83952b65fca330954c50ebe7a4bcdalton                SkAutoTUnref<SKPAnimationBench::Animation> animation(
81963a82855b1f0b83952b65fca330954c50ebe7a4bcdalton                    SKPAnimationBench::CreateZoomAnimation(fZoomMax, fZoomPeriodMs));
820385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary                return new SKPAnimationBench(name.c_str(), pic.get(), fClip, animation,
821385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary                                             FLAGS_loopSKP);
822261c3ad7fde95748da92550735decc949dc73bf2joshualitt            }
823261c3ad7fde95748da92550735decc949dc73bf2joshualitt        }
824261c3ad7fde95748da92550735decc949dc73bf2joshualitt
82560869a42a133942f852dd0f1696444c2a5c9ad83scroggo        for (; fCurrentCodec < fImages.count(); fCurrentCodec++) {
826303fa350125f372bbfc29bec1235885493dab9b4scroggo            fSourceType = "image";
827303fa350125f372bbfc29bec1235885493dab9b4scroggo            fBenchType = "skcodec";
82860869a42a133942f852dd0f1696444c2a5c9ad83scroggo            const SkString& path = fImages[fCurrentCodec];
82960869a42a133942f852dd0f1696444c2a5c9ad83scroggo            SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(path.c_str()));
83060869a42a133942f852dd0f1696444c2a5c9ad83scroggo            SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded));
83160869a42a133942f852dd0f1696444c2a5c9ad83scroggo            if (!codec) {
83260869a42a133942f852dd0f1696444c2a5c9ad83scroggo                // Nothing to time.
8339d9725c892743cf8fc66ea6cdd5ce21fe2df6d14msarett                SkDebugf("Cannot find codec for %s\n", path.c_str());
83460869a42a133942f852dd0f1696444c2a5c9ad83scroggo                continue;
83560869a42a133942f852dd0f1696444c2a5c9ad83scroggo            }
83621027994192f395bbd1507558b84f59b3c7cf0dascroggo
83760869a42a133942f852dd0f1696444c2a5c9ad83scroggo            while (fCurrentColorType < fColorTypes.count()) {
83821027994192f395bbd1507558b84f59b3c7cf0dascroggo                const SkColorType colorType = fColorTypes[fCurrentColorType];
83960869a42a133942f852dd0f1696444c2a5c9ad83scroggo                fCurrentColorType++;
84021027994192f395bbd1507558b84f59b3c7cf0dascroggo
84160869a42a133942f852dd0f1696444c2a5c9ad83scroggo                // Make sure we can decode to this color type.
84260869a42a133942f852dd0f1696444c2a5c9ad83scroggo                SkImageInfo info = codec->getInfo().makeColorType(colorType);
84321027994192f395bbd1507558b84f59b3c7cf0dascroggo                SkAlphaType alphaType;
84421027994192f395bbd1507558b84f59b3c7cf0dascroggo                if (!SkColorTypeValidateAlphaType(colorType, info.alphaType(),
84521027994192f395bbd1507558b84f59b3c7cf0dascroggo                                                  &alphaType)) {
84621027994192f395bbd1507558b84f59b3c7cf0dascroggo                    continue;
84721027994192f395bbd1507558b84f59b3c7cf0dascroggo                }
84821027994192f395bbd1507558b84f59b3c7cf0dascroggo                if (alphaType != info.alphaType()) {
84921027994192f395bbd1507558b84f59b3c7cf0dascroggo                    info = info.makeAlphaType(alphaType);
85021027994192f395bbd1507558b84f59b3c7cf0dascroggo                }
85121027994192f395bbd1507558b84f59b3c7cf0dascroggo
85221027994192f395bbd1507558b84f59b3c7cf0dascroggo                const size_t rowBytes = info.minRowBytes();
85321027994192f395bbd1507558b84f59b3c7cf0dascroggo                SkAutoMalloc storage(info.getSafeSize(rowBytes));
85421027994192f395bbd1507558b84f59b3c7cf0dascroggo
85521027994192f395bbd1507558b84f59b3c7cf0dascroggo                // Used if fCurrentColorType is kIndex_8_SkColorType
85621027994192f395bbd1507558b84f59b3c7cf0dascroggo                int colorCount = 256;
85721027994192f395bbd1507558b84f59b3c7cf0dascroggo                SkPMColor colors[256];
85821027994192f395bbd1507558b84f59b3c7cf0dascroggo
859eb602a5c94078fb2956c9bdc64bbf47a31b9c0e5scroggo                const SkCodec::Result result = codec->getPixels(
86096fcdcc219d2a0d3579719b84b28bede76efba64halcanary                        info, storage.get(), rowBytes, nullptr, colors,
86121027994192f395bbd1507558b84f59b3c7cf0dascroggo                        &colorCount);
86260869a42a133942f852dd0f1696444c2a5c9ad83scroggo                switch (result) {
863eb602a5c94078fb2956c9bdc64bbf47a31b9c0e5scroggo                    case SkCodec::kSuccess:
864eb602a5c94078fb2956c9bdc64bbf47a31b9c0e5scroggo                    case SkCodec::kIncompleteInput:
86560869a42a133942f852dd0f1696444c2a5c9ad83scroggo                        return new CodecBench(SkOSPath::Basename(path.c_str()),
86660869a42a133942f852dd0f1696444c2a5c9ad83scroggo                                encoded, colorType);
867eb602a5c94078fb2956c9bdc64bbf47a31b9c0e5scroggo                    case SkCodec::kInvalidConversion:
86860869a42a133942f852dd0f1696444c2a5c9ad83scroggo                        // This is okay. Not all conversions are valid.
86960869a42a133942f852dd0f1696444c2a5c9ad83scroggo                        break;
87060869a42a133942f852dd0f1696444c2a5c9ad83scroggo                    default:
87160869a42a133942f852dd0f1696444c2a5c9ad83scroggo                        // This represents some sort of failure.
87260869a42a133942f852dd0f1696444c2a5c9ad83scroggo                        SkASSERT(false);
87360869a42a133942f852dd0f1696444c2a5c9ad83scroggo                        break;
87460869a42a133942f852dd0f1696444c2a5c9ad83scroggo                }
87560869a42a133942f852dd0f1696444c2a5c9ad83scroggo            }
87660869a42a133942f852dd0f1696444c2a5c9ad83scroggo            fCurrentColorType = 0;
87760869a42a133942f852dd0f1696444c2a5c9ad83scroggo        }
87860869a42a133942f852dd0f1696444c2a5c9ad83scroggo
87995f192d19938b98a45dd1fa4112d965f60d10516msarett        // Run the DecodingBenches
88095f192d19938b98a45dd1fa4112d965f60d10516msarett        while (fCurrentImage < fImages.count()) {
881303fa350125f372bbfc29bec1235885493dab9b4scroggo            fSourceType = "image";
882303fa350125f372bbfc29bec1235885493dab9b4scroggo            fBenchType = "skimagedecoder";
88395f192d19938b98a45dd1fa4112d965f60d10516msarett            while (fCurrentColorType < fColorTypes.count()) {
88495f192d19938b98a45dd1fa4112d965f60d10516msarett                const SkString& path = fImages[fCurrentImage];
88595f192d19938b98a45dd1fa4112d965f60d10516msarett                SkColorType colorType = fColorTypes[fCurrentColorType];
88695f192d19938b98a45dd1fa4112d965f60d10516msarett                fCurrentColorType++;
88760869a42a133942f852dd0f1696444c2a5c9ad83scroggo                // Check if the image decodes to the right color type
88860869a42a133942f852dd0f1696444c2a5c9ad83scroggo                // before creating the benchmark
88995f192d19938b98a45dd1fa4112d965f60d10516msarett                SkBitmap bitmap;
89095f192d19938b98a45dd1fa4112d965f60d10516msarett                if (SkImageDecoder::DecodeFile(path.c_str(), &bitmap,
89160869a42a133942f852dd0f1696444c2a5c9ad83scroggo                        colorType, SkImageDecoder::kDecodePixels_Mode)
89260869a42a133942f852dd0f1696444c2a5c9ad83scroggo                        && bitmap.colorType() == colorType) {
89395f192d19938b98a45dd1fa4112d965f60d10516msarett                    return new DecodingBench(path, colorType);
89495f192d19938b98a45dd1fa4112d965f60d10516msarett                }
89595f192d19938b98a45dd1fa4112d965f60d10516msarett            }
89695f192d19938b98a45dd1fa4112d965f60d10516msarett            fCurrentColorType = 0;
89795f192d19938b98a45dd1fa4112d965f60d10516msarett            fCurrentImage++;
89895f192d19938b98a45dd1fa4112d965f60d10516msarett        }
89995f192d19938b98a45dd1fa4112d965f60d10516msarett
900b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett        // Run the SubsetBenches
901b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett        bool useCodecOpts[] = { true, false };
902b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett        while (fUseCodec < 2) {
903b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett            bool useCodec = useCodecOpts[fUseCodec];
904303fa350125f372bbfc29bec1235885493dab9b4scroggo            fSourceType = "image";
905303fa350125f372bbfc29bec1235885493dab9b4scroggo            fBenchType = useCodec ? "skcodec" : "skimagedecoder";
906b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett            while (fCurrentSubsetImage < fImages.count()) {
907ab12c2715886e7f04c415028a7db49fb0b1e67f3scroggo                const SkString& path = fImages[fCurrentSubsetImage];
908ab12c2715886e7f04c415028a7db49fb0b1e67f3scroggo                if (!run_subset_bench(path, useCodec)) {
909ab12c2715886e7f04c415028a7db49fb0b1e67f3scroggo                    fCurrentSubsetImage++;
910ab12c2715886e7f04c415028a7db49fb0b1e67f3scroggo                    continue;
911ab12c2715886e7f04c415028a7db49fb0b1e67f3scroggo                }
912b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett                while (fCurrentColorType < fColorTypes.count()) {
913b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett                    SkColorType colorType = fColorTypes[fCurrentColorType];
914b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett                    while (fCurrentSubsetType <= kLast_SubsetType) {
915b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett                        int width = 0;
916b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett                        int height = 0;
917b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett                        int currentSubsetType = fCurrentSubsetType++;
918b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett                        if (valid_subset_bench(path, colorType, useCodec, &width, &height)) {
919b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett                            switch (currentSubsetType) {
920b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett                                case kTopLeft_SubsetType:
921ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett                                    return new SubsetSingleBench(path, colorType, width/3,
922ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett                                            height/3, 0, 0, useCodec);
923b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett                                case kTopRight_SubsetType:
924ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett                                    return new SubsetSingleBench(path, colorType, width/3,
925ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett                                            height/3, 2*width/3, 0, useCodec);
926ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett                                case kMiddle_SubsetType:
927ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett                                    return new SubsetSingleBench(path, colorType, width/3,
928ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett                                            height/3, width/3, height/3, useCodec);
929b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett                                case kBottomLeft_SubsetType:
930ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett                                    return new SubsetSingleBench(path, colorType, width/3,
931ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett                                            height/3, 0, 2*height/3, useCodec);
932b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett                                case kBottomRight_SubsetType:
933ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett                                    return new SubsetSingleBench(path, colorType, width/3,
934ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett                                            height/3, 2*width/3, 2*height/3, useCodec);
935b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett                                case kTranslate_SubsetType:
936b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett                                    return new SubsetTranslateBench(path, colorType, 512, 512,
937b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett                                            useCodec);
938b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett                                case kZoom_SubsetType:
939b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett                                    return new SubsetZoomBench(path, colorType, 512, 512,
940b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett                                            useCodec);
94195f192d19938b98a45dd1fa4112d965f60d10516msarett                            }
942b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett                        } else {
943b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett                            break;
94495f192d19938b98a45dd1fa4112d965f60d10516msarett                        }
94595f192d19938b98a45dd1fa4112d965f60d10516msarett                    }
946b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett                    fCurrentSubsetType = 0;
947b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett                    fCurrentColorType++;
94895f192d19938b98a45dd1fa4112d965f60d10516msarett                }
949b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett                fCurrentColorType = 0;
950b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett                fCurrentSubsetImage++;
95195f192d19938b98a45dd1fa4112d965f60d10516msarett            }
952b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett            fCurrentSubsetImage = 0;
953b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett            fUseCodec++;
95495f192d19938b98a45dd1fa4112d965f60d10516msarett        }
95595f192d19938b98a45dd1fa4112d965f60d10516msarett
9567f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // Run the BRDBenches
9577f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // We will benchmark multiple BRD strategies.
958303fa350125f372bbfc29bec1235885493dab9b4scroggo        static const struct {
9595cb4885b4cd1ac5eb3fc92dac5f5509d7c810464msarett            SkBitmapRegionDecoder::Strategy    fStrategy;
960303fa350125f372bbfc29bec1235885493dab9b4scroggo            const char*                                 fName;
961303fa350125f372bbfc29bec1235885493dab9b4scroggo        } strategies[] = {
9625cb4885b4cd1ac5eb3fc92dac5f5509d7c810464msarett            { SkBitmapRegionDecoder::kOriginal_Strategy,    "BRD" },
9635cb4885b4cd1ac5eb3fc92dac5f5509d7c810464msarett            { SkBitmapRegionDecoder::kCanvas_Strategy,      "BRD_canvas" },
9645cb4885b4cd1ac5eb3fc92dac5f5509d7c810464msarett            { SkBitmapRegionDecoder::kAndroidCodec_Strategy, "BRD_android_codec" },
9657f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        };
9667f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett
9677f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // We intend to create benchmarks that model the use cases in
9687f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // android/libraries/social/tiledimage.  In this library, an image is decoded in 512x512
9697f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // tiles.  The image can be translated freely, so the location of a tile may be anywhere in
9707f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // the image.  For that reason, we will benchmark decodes in five representative locations
9717f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // in the image.  Additionally, this use case utilizes power of two scaling, so we will
9727f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // test on power of two sample sizes.  The output tile is always 512x512, so, when a
9737f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // sampleSize is used, the size of the subset that is decoded is always
9747f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // (sampleSize*512)x(sampleSize*512).
9757f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // There are a few good reasons to only test on power of two sample sizes at this time:
9767f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        //     JPEG decodes using kOriginal_Strategy are broken for non-powers of two.
9777f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        //         skbug.com/4319
9787f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        //     All use cases we are aware of only scale by powers of two.
9797f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        //     PNG decodes use the indicated sampling strategy regardless of the sample size, so
9807f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        //         these tests are sufficient to provide good coverage of our scaling options.
981501b7344f116ccc821d437d324aa7883d7ce97bfscroggo        const uint32_t sampleSizes[] = { 1, 2, 4, 8, 16, 32, 64 };
9827f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        const uint32_t minOutputSize = 512;
9837f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        while (fCurrentBRDImage < fImages.count()) {
9847f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett            while (fCurrentBRDStrategy < (int) SK_ARRAY_COUNT(strategies)) {
985303fa350125f372bbfc29bec1235885493dab9b4scroggo                fSourceType = "image";
986303fa350125f372bbfc29bec1235885493dab9b4scroggo                fBenchType = strategies[fCurrentBRDStrategy].fName;
987860e8a67190e024b7375e52e270e6bd0a17af86escroggo
988860e8a67190e024b7375e52e270e6bd0a17af86escroggo                const SkString& path = fImages[fCurrentBRDImage];
9895cb4885b4cd1ac5eb3fc92dac5f5509d7c810464msarett                const SkBitmapRegionDecoder::Strategy strategy =
990860e8a67190e024b7375e52e270e6bd0a17af86escroggo                        strategies[fCurrentBRDStrategy].fStrategy;
991860e8a67190e024b7375e52e270e6bd0a17af86escroggo
9925cb4885b4cd1ac5eb3fc92dac5f5509d7c810464msarett                if (SkBitmapRegionDecoder::kOriginal_Strategy == strategy) {
993860e8a67190e024b7375e52e270e6bd0a17af86escroggo                    // Disable png and jpeg for SkImageDecoder:
994860e8a67190e024b7375e52e270e6bd0a17af86escroggo                    if (!FLAGS_jpgBuildTileIndex) {
995860e8a67190e024b7375e52e270e6bd0a17af86escroggo                        if (path.endsWith("JPEG") || path.endsWith("JPG") ||
996860e8a67190e024b7375e52e270e6bd0a17af86escroggo                            path.endsWith("jpeg") || path.endsWith("jpg"))
997860e8a67190e024b7375e52e270e6bd0a17af86escroggo                        {
998860e8a67190e024b7375e52e270e6bd0a17af86escroggo                            fCurrentBRDStrategy++;
999860e8a67190e024b7375e52e270e6bd0a17af86escroggo                            continue;
1000860e8a67190e024b7375e52e270e6bd0a17af86escroggo                        }
1001860e8a67190e024b7375e52e270e6bd0a17af86escroggo                    }
1002860e8a67190e024b7375e52e270e6bd0a17af86escroggo                    if (!FLAGS_pngBuildTileIndex) {
1003860e8a67190e024b7375e52e270e6bd0a17af86escroggo                        if (path.endsWith("PNG") || path.endsWith("png")) {
1004860e8a67190e024b7375e52e270e6bd0a17af86escroggo                            fCurrentBRDStrategy++;
1005860e8a67190e024b7375e52e270e6bd0a17af86escroggo                            continue;
1006860e8a67190e024b7375e52e270e6bd0a17af86escroggo                        }
1007860e8a67190e024b7375e52e270e6bd0a17af86escroggo                    }
1008860e8a67190e024b7375e52e270e6bd0a17af86escroggo                }
1009860e8a67190e024b7375e52e270e6bd0a17af86escroggo
10107f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                while (fCurrentColorType < fColorTypes.count()) {
10117f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                    while (fCurrentBRDSampleSize < (int) SK_ARRAY_COUNT(sampleSizes)) {
10127f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                        while (fCurrentSubsetType <= kLastSingle_SubsetType) {
1013860e8a67190e024b7375e52e270e6bd0a17af86escroggo
1014860e8a67190e024b7375e52e270e6bd0a17af86escroggo
10157f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(path.c_str()));
10167f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            const SkColorType colorType = fColorTypes[fCurrentColorType];
10177f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            uint32_t sampleSize = sampleSizes[fCurrentBRDSampleSize];
10187f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            int currentSubsetType = fCurrentSubsetType++;
10197f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett
10207f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            int width = 0;
10217f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            int height = 0;
10227f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            if (!valid_brd_bench(encoded.get(), strategy, colorType, sampleSize,
10237f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    minOutputSize, &width, &height)) {
10247f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                break;
10257f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            }
10267f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett
10277f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            SkString basename = SkOSPath::Basename(path.c_str());
10287f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            SkIRect subset;
10297f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            const uint32_t subsetSize = sampleSize * minOutputSize;
10307f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            switch (currentSubsetType) {
10317f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                case kTopLeft_SubsetType:
10327f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    basename.append("_TopLeft");
10337f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    subset = SkIRect::MakeXYWH(0, 0, subsetSize, subsetSize);
10347f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    break;
10357f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                case kTopRight_SubsetType:
10367f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    basename.append("_TopRight");
10377f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    subset = SkIRect::MakeXYWH(width - subsetSize, 0, subsetSize,
10387f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                            subsetSize);
10397f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    break;
10407f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                case kMiddle_SubsetType:
10417f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    basename.append("_Middle");
10427f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    subset = SkIRect::MakeXYWH((width - subsetSize) / 2,
10437f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                            (height - subsetSize) / 2, subsetSize, subsetSize);
10447f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    break;
10457f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                case kBottomLeft_SubsetType:
10467f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    basename.append("_BottomLeft");
10477f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    subset = SkIRect::MakeXYWH(0, height - subsetSize, subsetSize,
10487f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                            subsetSize);
10497f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    break;
10507f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                case kBottomRight_SubsetType:
10517f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    basename.append("_BottomRight");
10527f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    subset = SkIRect::MakeXYWH(width - subsetSize,
10537f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                            height - subsetSize, subsetSize, subsetSize);
10547f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    break;
10557f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                default:
10567f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    SkASSERT(false);
10577f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            }
10587f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett
10597f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            return new BitmapRegionDecoderBench(basename.c_str(), encoded.get(),
10607f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    strategy, colorType, sampleSize, subset);
10617f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                        }
10627f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                        fCurrentSubsetType = 0;
10637f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                        fCurrentBRDSampleSize++;
10647f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                    }
10657f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                    fCurrentBRDSampleSize = 0;
10667f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                    fCurrentColorType++;
10677f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                }
10687f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                fCurrentColorType = 0;
10697f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                fCurrentBRDStrategy++;
10707f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett            }
10717f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett            fCurrentBRDStrategy = 0;
10727f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett            fCurrentBRDImage++;
10737f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        }
10747f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett
107596fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
1076e714e75c725c987fe682a1f5473224fe3e80380dmtklein    }
107792007583e43115998412ac8b0a06cc2780eb025cmtklein
107892007583e43115998412ac8b0a06cc2780eb025cmtklein    void fillCurrentOptions(ResultsWriter* log) const {
107992007583e43115998412ac8b0a06cc2780eb025cmtklein        log->configOption("source_type", fSourceType);
1080fd731ce804cd3223318f3feee2c98404890b65f2mtklein        log->configOption("bench_type",  fBenchType);
108192007583e43115998412ac8b0a06cc2780eb025cmtklein        if (0 == strcmp(fSourceType, "skp")) {
108292007583e43115998412ac8b0a06cc2780eb025cmtklein            log->configOption("clip",
108392007583e43115998412ac8b0a06cc2780eb025cmtklein                    SkStringPrintf("%d %d %d %d", fClip.fLeft, fClip.fTop,
108492007583e43115998412ac8b0a06cc2780eb025cmtklein                                                  fClip.fRight, fClip.fBottom).c_str());
10854dfdbb19ba861bbd5e1a306bb23f32464ea5e2c5mtklein            SK_ALWAYSBREAK(fCurrentScale < fScales.count());  // debugging paranoia
108692007583e43115998412ac8b0a06cc2780eb025cmtklein            log->configOption("scale", SkStringPrintf("%.2g", fScales[fCurrentScale]).c_str());
10875b69377507478623dcf5b11f3ecb010f87c4794frobertphillips            if (fCurrentUseMPD > 0) {
10885b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                SkASSERT(1 == fCurrentUseMPD || 2 == fCurrentUseMPD);
10895b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                log->configOption("multi_picture_draw", fUseMPDs[fCurrentUseMPD-1] ? "true" : "false");
10905b69377507478623dcf5b11f3ecb010f87c4794frobertphillips            }
109192007583e43115998412ac8b0a06cc2780eb025cmtklein        }
1092051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein        if (0 == strcmp(fBenchType, "recording")) {
1093051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein            log->metric("bytes", fSKPBytes);
1094051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein            log->metric("ops",   fSKPOps);
1095051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein        }
109692007583e43115998412ac8b0a06cc2780eb025cmtklein    }
109792007583e43115998412ac8b0a06cc2780eb025cmtklein
1098e714e75c725c987fe682a1f5473224fe3e80380dmtkleinprivate:
1099b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett    enum SubsetType {
1100b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett        kTopLeft_SubsetType     = 0,
1101b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett        kTopRight_SubsetType    = 1,
1102ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett        kMiddle_SubsetType      = 2,
1103ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett        kBottomLeft_SubsetType  = 3,
1104ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett        kBottomRight_SubsetType = 4,
1105ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett        kTranslate_SubsetType   = 5,
1106ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett        kZoom_SubsetType        = 6,
11077f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        kLast_SubsetType        = kZoom_SubsetType,
11087f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        kLastSingle_SubsetType  = kBottomRight_SubsetType,
1109b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett    };
1110b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett
1111e714e75c725c987fe682a1f5473224fe3e80380dmtklein    const BenchRegistry* fBenches;
1112e714e75c725c987fe682a1f5473224fe3e80380dmtklein    const skiagm::GMRegistry* fGMs;
111392007583e43115998412ac8b0a06cc2780eb025cmtklein    SkIRect            fClip;
111492007583e43115998412ac8b0a06cc2780eb025cmtklein    SkTArray<SkScalar> fScales;
111592007583e43115998412ac8b0a06cc2780eb025cmtklein    SkTArray<SkString> fSKPs;
11165b69377507478623dcf5b11f3ecb010f87c4794frobertphillips    SkTArray<bool>     fUseMPDs;
111795f192d19938b98a45dd1fa4112d965f60d10516msarett    SkTArray<SkString> fImages;
111874deb981d5e9c11c88fe431e78166d6cf8dacc1amsarett    SkTArray<SkColorType, true> fColorTypes;
111963a82855b1f0b83952b65fca330954c50ebe7a4bcdalton    SkScalar           fZoomMax;
112063a82855b1f0b83952b65fca330954c50ebe7a4bcdalton    double             fZoomPeriodMs;
112192007583e43115998412ac8b0a06cc2780eb025cmtklein
1122051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein    double fSKPBytes, fSKPOps;
1123051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein
1124fd731ce804cd3223318f3feee2c98404890b65f2mtklein    const char* fSourceType;  // What we're benching: bench, GM, SKP, ...
1125fd731ce804cd3223318f3feee2c98404890b65f2mtklein    const char* fBenchType;   // How we bench it: micro, recording, playback, ...
1126fd731ce804cd3223318f3feee2c98404890b65f2mtklein    int fCurrentRecording;
112792007583e43115998412ac8b0a06cc2780eb025cmtklein    int fCurrentScale;
112892007583e43115998412ac8b0a06cc2780eb025cmtklein    int fCurrentSKP;
11295b69377507478623dcf5b11f3ecb010f87c4794frobertphillips    int fCurrentUseMPD;
113060869a42a133942f852dd0f1696444c2a5c9ad83scroggo    int fCurrentCodec;
113195f192d19938b98a45dd1fa4112d965f60d10516msarett    int fCurrentImage;
113295f192d19938b98a45dd1fa4112d965f60d10516msarett    int fCurrentSubsetImage;
11337f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett    int fCurrentBRDImage;
113495f192d19938b98a45dd1fa4112d965f60d10516msarett    int fCurrentColorType;
1135b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett    int fCurrentSubsetType;
1136b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett    int fUseCodec;
11377f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett    int fCurrentBRDStrategy;
11387f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett    int fCurrentBRDSampleSize;
1139261c3ad7fde95748da92550735decc949dc73bf2joshualitt    int fCurrentAnimSKP;
1140e714e75c725c987fe682a1f5473224fe3e80380dmtklein};
1141e714e75c725c987fe682a1f5473224fe3e80380dmtklein
11423b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorioint nanobench_main();
114317f0b6df7248b9bbdaddacc3a6c9c6efe4ae278ecaryclarkint nanobench_main() {
11443b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorio    SetupCrashHandler();
1145f372321de3d4183de5b9ca436e677e471e358f31mtklein    SkAutoGraphics ag;
1146cc29d26f5742449eb2a2bafa7bbb6ec5ee701aefmtklein    SkTaskGroup::Enabler enabled(FLAGS_threads);
1147f372321de3d4183de5b9ca436e677e471e358f31mtklein
114869a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski#if SK_SUPPORT_GPU
1149682c269a1511200322916af83053e26004c0ec40bsalomon    GrContextOptions grContextOpts;
115012b3544028e74712c6c095ed3a2e8a78de6b2ed8krajcevski    grContextOpts.fDrawPathToCompressedTexture = FLAGS_gpuCompressAlphaMasks;
1151385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    gGrFactory.reset(new GrContextFactory(grContextOpts));
115269a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski#endif
115369a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski
115406cddec8570cbf29f89e89736afb0487b5b95abdbsalomon    if (FLAGS_veryVerbose) {
115506cddec8570cbf29f89e89736afb0487b5b95abdbsalomon        FLAGS_verbose = true;
115606cddec8570cbf29f89e89736afb0487b5b95abdbsalomon    }
115706cddec8570cbf29f89e89736afb0487b5b95abdbsalomon
11586eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (kAutoTuneLoops != FLAGS_loops) {
1159a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        FLAGS_samples     = 1;
1160a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        FLAGS_gpuFrameLag = 0;
1161a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein    }
1162a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein
11636eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (!FLAGS_writePath.isEmpty()) {
11646eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Writing files to %s.\n", FLAGS_writePath[0]);
11656eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        if (!sk_mkdir(FLAGS_writePath[0])) {
11666eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            SkDebugf("Could not create %s. Files won't be written.\n", FLAGS_writePath[0]);
116796fcdcc219d2a0d3579719b84b28bede76efba64halcanary            FLAGS_writePath.set(0, nullptr);
11686eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        }
11696eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
11706eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
1171385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    SkAutoTDelete<ResultsWriter> log(new ResultsWriter);
117260317d0ffb5053df7b08a627d6decd11b684e80dmtklein    if (!FLAGS_outResultsFile.isEmpty()) {
1173385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        log.reset(new NanoJSONResultsWriter(FLAGS_outResultsFile[0]));
117460317d0ffb5053df7b08a627d6decd11b684e80dmtklein    }
1175bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio
11761915b62637bea20e1471a8a358b22e9e47a4a385mtklein    if (1 == FLAGS_properties.count() % 2) {
11771915b62637bea20e1471a8a358b22e9e47a4a385mtklein        SkDebugf("ERROR: --properties must be passed with an even number of arguments.\n");
1178bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio        return 1;
1179bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    }
11801915b62637bea20e1471a8a358b22e9e47a4a385mtklein    for (int i = 1; i < FLAGS_properties.count(); i += 2) {
11811915b62637bea20e1471a8a358b22e9e47a4a385mtklein        log->property(FLAGS_properties[i-1], FLAGS_properties[i]);
1182bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    }
118394e51567dd691c3e1e8dfa6005a301d72cecf48emtklein
11841915b62637bea20e1471a8a358b22e9e47a4a385mtklein    if (1 == FLAGS_key.count() % 2) {
11851915b62637bea20e1471a8a358b22e9e47a4a385mtklein        SkDebugf("ERROR: --key must be passed with an even number of arguments.\n");
118694e51567dd691c3e1e8dfa6005a301d72cecf48emtklein        return 1;
118794e51567dd691c3e1e8dfa6005a301d72cecf48emtklein    }
11881915b62637bea20e1471a8a358b22e9e47a4a385mtklein    for (int i = 1; i < FLAGS_key.count(); i += 2) {
11891915b62637bea20e1471a8a358b22e9e47a4a385mtklein        log->key(FLAGS_key[i-1], FLAGS_key[i]);
119094e51567dd691c3e1e8dfa6005a301d72cecf48emtklein    }
119160317d0ffb5053df7b08a627d6decd11b684e80dmtklein
1192f372321de3d4183de5b9ca436e677e471e358f31mtklein    const double overhead = estimate_timer_overhead();
119355b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    SkDebugf("Timer overhead: %s\n", HUMANIZE(overhead));
1194912947737a973421f4c58682b6171cb5ee00ad3aMike Klein
1195e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton    SkTArray<double> samples;
1196bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
11976eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (kAutoTuneLoops != FLAGS_loops) {
11986eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Fixed number of loops; times would only be misleading so we won't print them.\n");
1199f372321de3d4183de5b9ca436e677e471e358f31mtklein    } else if (FLAGS_quiet) {
120040b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein        SkDebugf("median\tbench\tconfig\n");
1201bbba16878f343b232d844281fbdf056c00e20fb6mtklein    } else if (FLAGS_ms) {
1202e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton        SkDebugf("curr/maxrss\tloops\tmin\tmedian\tmean\tmax\tstddev\tsamples\tconfig\tbench\n");
1203f372321de3d4183de5b9ca436e677e471e358f31mtklein    } else {
1204d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein        SkDebugf("curr/maxrss\tloops\tmin\tmedian\tmean\tmax\tstddev\t%-*s\tconfig\tbench\n",
12058247ec313d87afcdd4da59b1f2f0d24e0983e359qiankun.miao                 FLAGS_samples, "samples");
1206f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
1207f372321de3d4183de5b9ca436e677e471e358f31mtklein
1208c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    SkTDArray<Config> configs;
1209c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    create_configs(&configs);
1210c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
1211e070c2bf54c451f0126d4ffb3a48bffe1fbfa437mtklein    int runs = 0;
121292007583e43115998412ac8b0a06cc2780eb025cmtklein    BenchmarkStream benchStream;
121392007583e43115998412ac8b0a06cc2780eb025cmtklein    while (Benchmark* b = benchStream.next()) {
1214e714e75c725c987fe682a1f5473224fe3e80380dmtklein        SkAutoTDelete<Benchmark> bench(b);
1215962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein        if (SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getUniqueName())) {
1216f372321de3d4183de5b9ca436e677e471e358f31mtklein            continue;
1217f372321de3d4183de5b9ca436e677e471e358f31mtklein        }
1218f372321de3d4183de5b9ca436e677e471e358f31mtklein
12193bf9206ada256277a39988c263f0379d544fc27begdaniel        if (!configs.isEmpty()) {
1220962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein            log->bench(bench->getUniqueName(), bench->getSize().fX, bench->getSize().fY);
12218a6697af95b340aad6dee7e6228048fa305c1e59joshualitt            bench->delayedSetup();
1222bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio        }
12233bf9206ada256277a39988c263f0379d544fc27begdaniel        for (int i = 0; i < configs.count(); ++i) {
12243bf9206ada256277a39988c263f0379d544fc27begdaniel            Target* target = is_enabled(b, configs[i]);
12253bf9206ada256277a39988c263f0379d544fc27begdaniel            if (!target) {
12263bf9206ada256277a39988c263f0379d544fc27begdaniel                continue;
12273bf9206ada256277a39988c263f0379d544fc27begdaniel            }
12283bf9206ada256277a39988c263f0379d544fc27begdaniel
122996fcdcc219d2a0d3579719b84b28bede76efba64halcanary            // During HWUI output this canvas may be nullptr.
12303bf9206ada256277a39988c263f0379d544fc27begdaniel            SkCanvas* canvas = target->getCanvas();
12313bf9206ada256277a39988c263f0379d544fc27begdaniel            const char* config = target->config.name;
1232bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
12333bf9206ada256277a39988c263f0379d544fc27begdaniel            target->setup();
12345b69377507478623dcf5b11f3ecb010f87c4794frobertphillips            bench->perCanvasPreDraw(canvas);
12355b69377507478623dcf5b11f3ecb010f87c4794frobertphillips
1236e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton            int maxFrameLag;
1237a1ebeb25e9acfcd801e089e063311d716b83b8a5mtklein            int loops = target->needsFrameTiming(&maxFrameLag)
12383bf9206ada256277a39988c263f0379d544fc27begdaniel                ? setup_gpu_bench(target, bench.get(), maxFrameLag)
12393bf9206ada256277a39988c263f0379d544fc27begdaniel                : setup_cpu_bench(overhead, target, bench.get());
1240e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton
1241bbba16878f343b232d844281fbdf056c00e20fb6mtklein            if (FLAGS_ms) {
1242bbba16878f343b232d844281fbdf056c00e20fb6mtklein                samples.reset();
1243bbba16878f343b232d844281fbdf056c00e20fb6mtklein                auto stop = now_ms() + FLAGS_ms;
1244bbba16878f343b232d844281fbdf056c00e20fb6mtklein                do {
1245bbba16878f343b232d844281fbdf056c00e20fb6mtklein                    samples.push_back(time(loops, bench, target) / loops);
1246bbba16878f343b232d844281fbdf056c00e20fb6mtklein                } while (now_ms() < stop);
1247bbba16878f343b232d844281fbdf056c00e20fb6mtklein            } else {
1248e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton                samples.reset(FLAGS_samples);
1249e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton                for (int s = 0; s < FLAGS_samples; s++) {
12503bf9206ada256277a39988c263f0379d544fc27begdaniel                    samples[s] = time(loops, bench, target) / loops;
1251e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton                }
1252e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton            }
1253f372321de3d4183de5b9ca436e677e471e358f31mtklein
12545b69377507478623dcf5b11f3ecb010f87c4794frobertphillips            bench->perCanvasPostDraw(canvas);
12555b69377507478623dcf5b11f3ecb010f87c4794frobertphillips
12563bf9206ada256277a39988c263f0379d544fc27begdaniel            if (Benchmark::kNonRendering_Backend != target->config.backend &&
1257d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson                !FLAGS_writePath.isEmpty() && FLAGS_writePath[0]) {
12586eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                SkString pngFilename = SkOSPath::Join(FLAGS_writePath[0], config);
1259962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein                pngFilename = SkOSPath::Join(pngFilename.c_str(), bench->getUniqueName());
12606eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                pngFilename.append(".png");
12613bf9206ada256277a39988c263f0379d544fc27begdaniel                write_canvas_png(target, pngFilename);
12626eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            }
12636eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
12646eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            if (kFailedLoops == loops) {
12652069e220034f09aad2f68b262f395e7c25b3d178mtklein                // Can't be timed.  A warning note has already been printed.
12663bf9206ada256277a39988c263f0379d544fc27begdaniel                cleanup_run(target);
1267e3631364e93ee9164f3ce322778d5a50c33f63a6Mike Klein                continue;
1268e3631364e93ee9164f3ce322778d5a50c33f63a6Mike Klein            }
126960317d0ffb5053df7b08a627d6decd11b684e80dmtklein
1270e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton            Stats stats(samples);
12711915b62637bea20e1471a8a358b22e9e47a4a385mtklein            log->config(config);
1272962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein            log->configOption("name", bench->getName());
12731915b62637bea20e1471a8a358b22e9e47a4a385mtklein            benchStream.fillCurrentOptions(log.get());
12743bf9206ada256277a39988c263f0379d544fc27begdaniel            target->fillOptions(log.get());
1275051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein            log->metric("min_ms",    stats.min);
1276e070c2bf54c451f0126d4ffb3a48bffe1fbfa437mtklein            if (runs++ % FLAGS_flushEvery == 0) {
1277e070c2bf54c451f0126d4ffb3a48bffe1fbfa437mtklein                log->flush();
1278e070c2bf54c451f0126d4ffb3a48bffe1fbfa437mtklein            }
127960317d0ffb5053df7b08a627d6decd11b684e80dmtklein
12806eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            if (kAutoTuneLoops != FLAGS_loops) {
12813bf9206ada256277a39988c263f0379d544fc27begdaniel                if (configs.count() == 1) {
1282a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein                    config = ""; // Only print the config if we run the same bench on more than one.
1283a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein                }
1284d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein                SkDebugf("%4d/%-4dMB\t%s\t%s\n"
1285d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein                         , sk_tools::getCurrResidentSetSizeMB()
1286d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein                         , sk_tools::getMaxResidentSetSizeMB()
128753d2562006ee371222963750009a706cfd1a94f7mtklein                         , bench->getUniqueName()
128853d2562006ee371222963750009a706cfd1a94f7mtklein                         , config);
1289f372321de3d4183de5b9ca436e677e471e358f31mtklein            } else if (FLAGS_quiet) {
12903bf9206ada256277a39988c263f0379d544fc27begdaniel                if (configs.count() == 1) {
1291f372321de3d4183de5b9ca436e677e471e358f31mtklein                    config = ""; // Only print the config if we run the same bench on more than one.
1292f372321de3d4183de5b9ca436e677e471e358f31mtklein                }
1293962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein                SkDebugf("%s\t%s\t%s\n", HUMANIZE(stats.median), bench->getUniqueName(), config);
1294f372321de3d4183de5b9ca436e677e471e358f31mtklein            } else {
1295f372321de3d4183de5b9ca436e677e471e358f31mtklein                const double stddev_percent = 100 * sqrt(stats.var) / stats.mean;
1296d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein                SkDebugf("%4d/%-4dMB\t%d\t%s\t%s\t%s\t%s\t%.0f%%\t%s\t%s\t%s\n"
1297d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein                        , sk_tools::getCurrResidentSetSizeMB()
1298d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein                        , sk_tools::getMaxResidentSetSizeMB()
1299f372321de3d4183de5b9ca436e677e471e358f31mtklein                        , loops
130055b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein                        , HUMANIZE(stats.min)
130155b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein                        , HUMANIZE(stats.median)
130255b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein                        , HUMANIZE(stats.mean)
130355b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein                        , HUMANIZE(stats.max)
1304f372321de3d4183de5b9ca436e677e471e358f31mtklein                        , stddev_percent
1305bbba16878f343b232d844281fbdf056c00e20fb6mtklein                        , FLAGS_ms ? to_string(samples.count()).c_str() : stats.plot.c_str()
1306f372321de3d4183de5b9ca436e677e471e358f31mtklein                        , config
1307962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein                        , bench->getUniqueName()
1308f372321de3d4183de5b9ca436e677e471e358f31mtklein                        );
1309f372321de3d4183de5b9ca436e677e471e358f31mtklein            }
1310b12ea41286ce36e085c5a14711da0cf9f240fdf1bsalomon#if SK_SUPPORT_GPU
1311b12ea41286ce36e085c5a14711da0cf9f240fdf1bsalomon            if (FLAGS_gpuStats &&
13123bf9206ada256277a39988c263f0379d544fc27begdaniel                Benchmark::kGPU_Backend == configs[i].backend) {
13133bf9206ada256277a39988c263f0379d544fc27begdaniel                gGrFactory->get(configs[i].ctxType)->printCacheStats();
13143bf9206ada256277a39988c263f0379d544fc27begdaniel                gGrFactory->get(configs[i].ctxType)->printGpuStats();
131506cddec8570cbf29f89e89736afb0487b5b95abdbsalomon            }
131606cddec8570cbf29f89e89736afb0487b5b95abdbsalomon#endif
13172c56ba5cde25a5cdbeca2afd660b497b428e8f07cdalton            if (FLAGS_verbose) {
13182c56ba5cde25a5cdbeca2afd660b497b428e8f07cdalton                SkDebugf("Samples:  ");
13192c56ba5cde25a5cdbeca2afd660b497b428e8f07cdalton                for (int i = 0; i < samples.count(); i++) {
13202c56ba5cde25a5cdbeca2afd660b497b428e8f07cdalton                    SkDebugf("%s  ", HUMANIZE(samples[i]));
13212c56ba5cde25a5cdbeca2afd660b497b428e8f07cdalton                }
13222c56ba5cde25a5cdbeca2afd660b497b428e8f07cdalton                SkDebugf("%s\n", bench->getUniqueName());
13232c56ba5cde25a5cdbeca2afd660b497b428e8f07cdalton            }
13243bf9206ada256277a39988c263f0379d544fc27begdaniel            cleanup_run(target);
1325f372321de3d4183de5b9ca436e677e471e358f31mtklein        }
1326f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
1327f372321de3d4183de5b9ca436e677e471e358f31mtklein
1328e109145bf31d63963b3f78c6af6e404d5464a55bmtklein    log->bench("memory_usage", 0,0);
1329e109145bf31d63963b3f78c6af6e404d5464a55bmtklein    log->config("meta");
1330e109145bf31d63963b3f78c6af6e404d5464a55bmtklein    log->metric("max_rss_mb", sk_tools::getMaxResidentSetSizeMB());
1331e109145bf31d63963b3f78c6af6e404d5464a55bmtklein
1332e0b19d4985846d64bb581013828a9dc5af401a5djoshualitt#if SK_SUPPORT_GPU
1333e0b19d4985846d64bb581013828a9dc5af401a5djoshualitt    // Make sure we clean up the global GrContextFactory here, otherwise we might race with the
1334e0b19d4985846d64bb581013828a9dc5af401a5djoshualitt    // SkEventTracer destructor
133596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    gGrFactory.reset(nullptr);
1336e0b19d4985846d64bb581013828a9dc5af401a5djoshualitt#endif
1337e0b19d4985846d64bb581013828a9dc5af401a5djoshualitt
1338f372321de3d4183de5b9ca436e677e471e358f31mtklein    return 0;
1339f372321de3d4183de5b9ca436e677e471e358f31mtklein}
1340f372321de3d4183de5b9ca436e677e471e358f31mtklein
13413b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorio#if !defined SK_BUILD_FOR_IOS
13423b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorioint main(int argc, char** argv) {
13433b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorio    SkCommandLineFlags::Parse(argc, argv);
13443b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorio    return nanobench_main();
13453b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorio}
13463b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorio#endif
1347