nanobench.cpp revision 66cfcffd5d0a430f00bf0e36bedb088a25957183
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?");
110e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualittDEFINE_bool(gpuStatsDump, false, "Dump GPU states after each benchmark to json");
11192007583e43115998412ac8b0a06cc2780eb025cmtklein
112bbba16878f343b232d844281fbdf056c00e20fb6mtkleinstatic double now_ms() { return SkTime::GetNSecs() * 1e-6; }
113bbba16878f343b232d844281fbdf056c00e20fb6mtklein
114f372321de3d4183de5b9ca436e677e471e358f31mtkleinstatic SkString humanize(double ms) {
115dc5bbab138bfffc85d6ba525d990aad09c322ff6mtklein    if (FLAGS_verbose) return SkStringPrintf("%llu", (uint64_t)(ms*1e6));
116748ca3bf2d170708f263693e8579e6722389d0efmtklein    return HumanizeMs(ms);
117f372321de3d4183de5b9ca436e677e471e358f31mtklein}
11855b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein#define HUMANIZE(ms) humanize(ms).c_str()
119f372321de3d4183de5b9ca436e677e471e358f31mtklein
120d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudsonbool Target::init(SkImageInfo info, Benchmark* bench) {
121d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    if (Benchmark::kRaster_Backend == config.backend) {
122d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        this->surface.reset(SkSurface::NewRaster(info));
123d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        if (!this->surface.get()) {
124d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson            return false;
125d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        }
126d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
127d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    return true;
128d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson}
129d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudsonbool Target::capturePixels(SkBitmap* bmp) {
13075a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson    SkCanvas* canvas = this->getCanvas();
131d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    if (!canvas) {
132d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        return false;
133d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
134d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    bmp->setInfo(canvas->imageInfo());
135d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    if (!canvas->readPixels(bmp, 0, 0)) {
136d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        SkDebugf("Can't read canvas pixels.\n");
137d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        return false;
138d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
139d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    return true;
140d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson}
141d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
142d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson#if SK_SUPPORT_GPU
143d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudsonstruct GPUTarget : public Target {
14496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    explicit GPUTarget(const Config& c) : Target(c), gl(nullptr) { }
145d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    SkGLContext* gl;
146d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
147d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    void setup() override {
148d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        this->gl->makeCurrent();
149d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        // Make sure we're done with whatever came before.
150d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        SK_GL(*this->gl, Finish());
151d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
152d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    void endTiming() override {
153d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        if (this->gl) {
154d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson            SK_GL(*this->gl, Flush());
155d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson            this->gl->swapBuffers();
156d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        }
157d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
158d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    void fence() override {
159d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        SK_GL(*this->gl, Finish());
160d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
161d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein
162d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton    bool needsFrameTiming(int* maxFrameLag) const override {
163d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton        if (!this->gl->getMaxGpuFrameLag(maxFrameLag)) {
164d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton            // Frame lag is unknown.
165d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton            *maxFrameLag = FLAGS_gpuFrameLag;
166d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton        }
167d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton        return true;
168d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton    }
169d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    bool init(SkImageInfo info, Benchmark* bench) override {
170afcd7cd32497cc79035e61fd64b0baa03ed04bccbsalomon        uint32_t flags = this->config.useDFText ? SkSurfaceProps::kUseDeviceIndependentFonts_Flag :
171afcd7cd32497cc79035e61fd64b0baa03ed04bccbsalomon                                                  0;
172d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType);
173a0a024e323ebf73ea4559d4b29f937902703828bbsalomon        this->surface.reset(SkSurface::NewRenderTarget(gGrFactory->get(this->config.ctxType),
174d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson                                                         SkSurface::kNo_Budgeted, info,
175d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson                                                         this->config.samples, &props));
176a0a024e323ebf73ea4559d4b29f937902703828bbsalomon        this->gl = gGrFactory->getContextInfo(this->config.ctxType)->fGLContext;
177d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        if (!this->surface.get()) {
178d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson            return false;
179d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        }
180d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton        if (!this->gl->fenceSyncSupport()) {
181d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton            SkDebugf("WARNING: GL context for config \"%s\" does not support fence sync. "
182d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton                     "Timings might not be accurate.\n", this->config.name);
183d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton        }
184d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        return true;
185d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
186d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    void fillOptions(ResultsWriter* log) override {
187d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        const GrGLubyte* version;
188d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        SK_GL_RET(*this->gl, version, GetString(GR_GL_VERSION));
189d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        log->configOption("GL_VERSION", (const char*)(version));
190d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
191d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        SK_GL_RET(*this->gl, version, GetString(GR_GL_RENDERER));
192d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        log->configOption("GL_RENDERER", (const char*) version);
193d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
194d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        SK_GL_RET(*this->gl, version, GetString(GR_GL_VENDOR));
195d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        log->configOption("GL_VENDOR", (const char*) version);
196d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
197d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        SK_GL_RET(*this->gl, version, GetString(GR_GL_SHADING_LANGUAGE_VERSION));
198d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        log->configOption("GL_SHADING_LANGUAGE_VERSION", (const char*) version);
199d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
200d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson};
201d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein
202d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson#endif
203d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
20475a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudsonstatic double time(int loops, Benchmark* bench, Target* target) {
20575a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson    SkCanvas* canvas = target->getCanvas();
2066eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (canvas) {
2076eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        canvas->clear(SK_ColorWHITE);
2086eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
2098a6697af95b340aad6dee7e6228048fa305c1e59joshualitt    bench->preDraw(canvas);
210bbba16878f343b232d844281fbdf056c00e20fb6mtklein    double start = now_ms();
21175a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson    canvas = target->beginTiming(canvas);
21275a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson    bench->draw(loops, canvas);
213f372321de3d4183de5b9ca436e677e471e358f31mtklein    if (canvas) {
214f372321de3d4183de5b9ca436e677e471e358f31mtklein        canvas->flush();
215f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
21675a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson    target->endTiming();
217bbba16878f343b232d844281fbdf056c00e20fb6mtklein    double elapsed = now_ms() - start;
2188a6697af95b340aad6dee7e6228048fa305c1e59joshualitt    bench->postDraw(canvas);
219bbba16878f343b232d844281fbdf056c00e20fb6mtklein    return elapsed;
220f372321de3d4183de5b9ca436e677e471e358f31mtklein}
221f372321de3d4183de5b9ca436e677e471e358f31mtklein
222bb6a02823929584231c8e080ee69e7fb1178cbfbmtkleinstatic double estimate_timer_overhead() {
223bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    double overhead = 0;
224bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    for (int i = 0; i < FLAGS_overheadLoops; i++) {
225bbba16878f343b232d844281fbdf056c00e20fb6mtklein        double start = now_ms();
226bbba16878f343b232d844281fbdf056c00e20fb6mtklein        overhead += now_ms() - start;
227bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    }
228bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    return overhead / FLAGS_overheadLoops;
229bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein}
230f372321de3d4183de5b9ca436e677e471e358f31mtklein
2315324978a88677ac6b758324321816427814e7793reedstatic int detect_forever_loops(int loops) {
2325324978a88677ac6b758324321816427814e7793reed    // look for a magic run-forever value
2335324978a88677ac6b758324321816427814e7793reed    if (loops < 0) {
2345324978a88677ac6b758324321816427814e7793reed        loops = SK_MaxS32;
2355324978a88677ac6b758324321816427814e7793reed    }
2365324978a88677ac6b758324321816427814e7793reed    return loops;
2375324978a88677ac6b758324321816427814e7793reed}
2385324978a88677ac6b758324321816427814e7793reed
23955b0ffc4861e940d8bcf767ff9abf44ff18545eamtkleinstatic int clamp_loops(int loops) {
24055b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    if (loops < 1) {
241527930fdbbba2a20f98b43821c6b72367e7b2d64mtklein        SkDebugf("ERROR: clamping loops from %d to 1. "
242527930fdbbba2a20f98b43821c6b72367e7b2d64mtklein                 "There's probably something wrong with the bench.\n", loops);
24355b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein        return 1;
24455b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    }
24555b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    if (loops > FLAGS_maxLoops) {
24655b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein        SkDebugf("WARNING: clamping loops from %d to FLAGS_maxLoops, %d.\n", loops, FLAGS_maxLoops);
24755b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein        return FLAGS_maxLoops;
24855b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    }
24955b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    return loops;
25055b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein}
25155b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein
252d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudsonstatic bool write_canvas_png(Target* target, const SkString& filename) {
253d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
2546eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (filename.isEmpty()) {
2556eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
2566eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
25775a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson    if (target->getCanvas() &&
25875a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson        kUnknown_SkColorType == target->getCanvas()->imageInfo().colorType()) {
2596eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
2606eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
261d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
2626eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    SkBitmap bmp;
263d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
264d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    if (!target->capturePixels(&bmp)) {
2656eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
2666eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
267d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
2686eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    SkString dir = SkOSPath::Dirname(filename.c_str());
2696eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (!sk_mkdir(dir.c_str())) {
2706eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Can't make dir %s.\n", dir.c_str());
2716eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
2726eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
2736eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    SkFILEWStream stream(filename.c_str());
2746eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (!stream.isValid()) {
2756eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Can't write %s.\n", filename.c_str());
2766eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
2776eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
2786eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (!SkImageEncoder::EncodeStream(&stream, bmp, SkImageEncoder::kPNG_Type, 100)) {
2796eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Can't encode a PNG.\n");
2806eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
2816eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
2826eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    return true;
2836eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon}
2846eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
2856eb03cc06d0bc60da5277a83aa0251a475794b04bsalomonstatic int kFailedLoops = -2;
286e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdaltonstatic int setup_cpu_bench(const double overhead, Target* target, Benchmark* bench) {
287bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // First figure out approximately how many loops of bench it takes to make overhead negligible.
2882069e220034f09aad2f68b262f395e7c25b3d178mtklein    double bench_plus_overhead = 0.0;
28955b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    int round = 0;
290b4022965a280dd1ed64d6103dd29e2189abe6e00cdalton    int loops = bench->calculateLoops(FLAGS_loops);
291b4022965a280dd1ed64d6103dd29e2189abe6e00cdalton    if (kAutoTuneLoops == loops) {
2926eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        while (bench_plus_overhead < overhead) {
2936eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            if (round++ == FLAGS_maxCalibrationAttempts) {
2946eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                SkDebugf("WARNING: Can't estimate loops for %s (%s vs. %s); skipping.\n",
295962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein                         bench->getUniqueName(), HUMANIZE(bench_plus_overhead), HUMANIZE(overhead));
2966eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                return kFailedLoops;
2976eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            }
29875a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson            bench_plus_overhead = time(1, bench, target);
29955b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein        }
3002069e220034f09aad2f68b262f395e7c25b3d178mtklein    }
301f372321de3d4183de5b9ca436e677e471e358f31mtklein
302bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // Later we'll just start and stop the timer once but loop N times.
303f372321de3d4183de5b9ca436e677e471e358f31mtklein    // We'll pick N to make timer overhead negligible:
304f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
305bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //          overhead
306bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //  -------------------------  < FLAGS_overheadGoal
307bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //  overhead + N * Bench Time
308f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
309bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // where bench_plus_overhead ≈ overhead + Bench Time.
310f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
311f372321de3d4183de5b9ca436e677e471e358f31mtklein    // Doing some math, we get:
312f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
313bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //  (overhead / FLAGS_overheadGoal) - overhead
314bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //  ------------------------------------------  < N
315bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //       bench_plus_overhead - overhead)
316f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
317f372321de3d4183de5b9ca436e677e471e358f31mtklein    // Luckily, this also works well in practice. :)
3186eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (kAutoTuneLoops == loops) {
3196eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        const double numer = overhead / FLAGS_overheadGoal - overhead;
3206eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        const double denom = bench_plus_overhead - overhead;
3216eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        loops = (int)ceil(numer / denom);
3225324978a88677ac6b758324321816427814e7793reed        loops = clamp_loops(loops);
3235324978a88677ac6b758324321816427814e7793reed    } else {
3245324978a88677ac6b758324321816427814e7793reed        loops = detect_forever_loops(loops);
3256eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
326bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
327bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    return loops;
328f372321de3d4183de5b9ca436e677e471e358f31mtklein}
329f372321de3d4183de5b9ca436e677e471e358f31mtklein
330e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdaltonstatic int setup_gpu_bench(Target* target, Benchmark* bench, int maxGpuFrameLag) {
331bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // First, figure out how many loops it'll take to get a frame up to FLAGS_gpuMs.
332b4022965a280dd1ed64d6103dd29e2189abe6e00cdalton    int loops = bench->calculateLoops(FLAGS_loops);
3336eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (kAutoTuneLoops == loops) {
3346eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        loops = 1;
335a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        double elapsed = 0;
336a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        do {
337527930fdbbba2a20f98b43821c6b72367e7b2d64mtklein            if (1<<30 == loops) {
338527930fdbbba2a20f98b43821c6b72367e7b2d64mtklein                // We're about to wrap.  Something's wrong with the bench.
339527930fdbbba2a20f98b43821c6b72367e7b2d64mtklein                loops = 0;
340527930fdbbba2a20f98b43821c6b72367e7b2d64mtklein                break;
341527930fdbbba2a20f98b43821c6b72367e7b2d64mtklein            }
342a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            loops *= 2;
343a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            // If the GPU lets frames lag at all, we need to make sure we're timing
344d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton            // _this_ round, not still timing last round.
345d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton            for (int i = 0; i < maxGpuFrameLag; i++) {
34675a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson                elapsed = time(loops, bench, target);
347a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            }
348a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        } while (elapsed < FLAGS_gpuMs);
349a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein
350a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        // We've overshot at least a little.  Scale back linearly.
351a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        loops = (int)ceil(loops * FLAGS_gpuMs / elapsed);
3525324978a88677ac6b758324321816427814e7793reed        loops = clamp_loops(loops);
353a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein
354d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        // Make sure we're not still timing our calibration.
355d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        target->fence();
3565324978a88677ac6b758324321816427814e7793reed    } else {
3575324978a88677ac6b758324321816427814e7793reed        loops = detect_forever_loops(loops);
358a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein    }
359bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
360bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // Pretty much the same deal as the calibration: do some warmup to make
361bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // sure we're timing steady-state pipelined frames.
362d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton    for (int i = 0; i < maxGpuFrameLag - 1; i++) {
36375a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson        time(loops, bench, target);
364f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
365bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
366bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    return loops;
367f372321de3d4183de5b9ca436e677e471e358f31mtklein}
368bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
369bb6a02823929584231c8e080ee69e7fb1178cbfbmtkleinstatic SkString to_lower(const char* str) {
370bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    SkString lower(str);
371bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    for (size_t i = 0; i < lower.size(); i++) {
372bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        lower[i] = tolower(lower[i]);
373bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    }
374bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    return lower;
375bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein}
376bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
377c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstatic bool is_cpu_config_allowed(const char* name) {
378bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    for (int i = 0; i < FLAGS_config.count(); i++) {
379c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        if (to_lower(FLAGS_config[i]).equals(name)) {
380c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            return true;
381bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        }
382f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
383c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    return false;
384bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein}
385f372321de3d4183de5b9ca436e677e471e358f31mtklein
386c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#if SK_SUPPORT_GPU
387c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstatic bool is_gpu_config_allowed(const char* name, GrContextFactory::GLContextType ctxType,
388c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                                  int sampleCnt) {
389c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    if (!is_cpu_config_allowed(name)) {
390c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        return false;
391c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
392a0a024e323ebf73ea4559d4b29f937902703828bbsalomon    if (const GrContext* ctx = gGrFactory->get(ctxType)) {
393762286309545c8a1e4bbc05dcd1fe3085d2a1f47bsalomon        return sampleCnt <= ctx->caps()->maxSampleCount();
394c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
395c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    return false;
396c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon}
397c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#endif
398c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
399c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#if SK_SUPPORT_GPU
400c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#define kBogusGLContextType GrContextFactory::kNative_GLContextType
401c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#else
402c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#define kBogusGLContextType 0
403e714e75c725c987fe682a1f5473224fe3e80380dmtklein#endif
404c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
405c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon// Append all configs that are enabled and supported.
406c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstatic void create_configs(SkTDArray<Config>* configs) {
407a0a024e323ebf73ea4559d4b29f937902703828bbsalomon    #define CPU_CONFIG(name, backend, color, alpha)                       \
408a0a024e323ebf73ea4559d4b29f937902703828bbsalomon        if (is_cpu_config_allowed(#name)) {                               \
409a0a024e323ebf73ea4559d4b29f937902703828bbsalomon            Config config = { #name, Benchmark::backend, color, alpha, 0, \
410a0a024e323ebf73ea4559d4b29f937902703828bbsalomon                              kBogusGLContextType, false };               \
411a0a024e323ebf73ea4559d4b29f937902703828bbsalomon            configs->push(config);                                        \
412f372321de3d4183de5b9ca436e677e471e358f31mtklein        }
413e714e75c725c987fe682a1f5473224fe3e80380dmtklein
41440b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein    if (FLAGS_cpu) {
415c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        CPU_CONFIG(nonrendering, kNonRendering_Backend, kUnknown_SkColorType, kUnpremul_SkAlphaType)
416c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        CPU_CONFIG(8888, kRaster_Backend, kN32_SkColorType, kPremul_SkAlphaType)
417c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        CPU_CONFIG(565, kRaster_Backend, kRGB_565_SkColorType, kOpaque_SkAlphaType)
41840b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein    }
419f372321de3d4183de5b9ca436e677e471e358f31mtklein
420bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#if SK_SUPPORT_GPU
421a0a024e323ebf73ea4559d4b29f937902703828bbsalomon    #define GPU_CONFIG(name, ctxType, samples, useDFText)                        \
422a0a024e323ebf73ea4559d4b29f937902703828bbsalomon        if (is_gpu_config_allowed(#name, GrContextFactory::ctxType, samples)) {  \
423c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            Config config = {                                                    \
424c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                #name,                                                           \
425c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                Benchmark::kGPU_Backend,                                         \
426c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                kN32_SkColorType,                                                \
427c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                kPremul_SkAlphaType,                                             \
428c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                samples,                                                         \
4294736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth                GrContextFactory::ctxType,                                       \
4304736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth                useDFText };                                                     \
431c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            configs->push(config);                                               \
432f372321de3d4183de5b9ca436e677e471e358f31mtklein        }
433e714e75c725c987fe682a1f5473224fe3e80380dmtklein
43440b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein    if (FLAGS_gpu) {
435a0a024e323ebf73ea4559d4b29f937902703828bbsalomon        GPU_CONFIG(gpu, kNative_GLContextType, 0, false)
436a0a024e323ebf73ea4559d4b29f937902703828bbsalomon        GPU_CONFIG(msaa4, kNative_GLContextType, 4, false)
437a0a024e323ebf73ea4559d4b29f937902703828bbsalomon        GPU_CONFIG(msaa16, kNative_GLContextType, 16, false)
438a0a024e323ebf73ea4559d4b29f937902703828bbsalomon        GPU_CONFIG(nvprmsaa4, kNVPR_GLContextType, 4, false)
439a0a024e323ebf73ea4559d4b29f937902703828bbsalomon        GPU_CONFIG(nvprmsaa16, kNVPR_GLContextType, 16, false)
440a0a024e323ebf73ea4559d4b29f937902703828bbsalomon        GPU_CONFIG(gpudft, kNative_GLContextType, 0, true)
441a0a024e323ebf73ea4559d4b29f937902703828bbsalomon        GPU_CONFIG(debug, kDebug_GLContextType, 0, false)
442a0a024e323ebf73ea4559d4b29f937902703828bbsalomon        GPU_CONFIG(nullgpu, kNull_GLContextType, 0, false)
4433b4d077fba1ad037536db198608a940c47d91888bsalomon#ifdef SK_ANGLE
444a0a024e323ebf73ea4559d4b29f937902703828bbsalomon        GPU_CONFIG(angle, kANGLE_GLContextType, 0, false)
445a0a024e323ebf73ea4559d4b29f937902703828bbsalomon        GPU_CONFIG(angle-gl, kANGLE_GL_GLContextType, 0, false)
4463b4d077fba1ad037536db198608a940c47d91888bsalomon#endif
447885bf0925514b9dfe3365bab227d36897d866b5dhendrikw#ifdef SK_COMMAND_BUFFER
448a0a024e323ebf73ea4559d4b29f937902703828bbsalomon        GPU_CONFIG(commandbuffer, kCommandBuffer_GLContextType, 0, false)
449885bf0925514b9dfe3365bab227d36897d866b5dhendrikw#endif
450d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton#if SK_MESA
451a0a024e323ebf73ea4559d4b29f937902703828bbsalomon        GPU_CONFIG(mesa, kMESA_GLContextType, 0, false)
452d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton#endif
45340b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein    }
454bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#endif
455d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
456d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
457d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    if (is_cpu_config_allowed("hwui")) {
458d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        Config config = { "hwui", Benchmark::kHWUI_Backend, kRGBA_8888_SkColorType,
4599323dc6a72de301f23e1187adc2365395b4b23d8scroggo                          kPremul_SkAlphaType, 0, kBogusGLContextType, false };
460d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        configs->push(config);
461d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
462d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson#endif
463f372321de3d4183de5b9ca436e677e471e358f31mtklein}
464f372321de3d4183de5b9ca436e677e471e358f31mtklein
46596fcdcc219d2a0d3579719b84b28bede76efba64halcanary// If bench is enabled for config, returns a Target* for it, otherwise nullptr.
466c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstatic Target* is_enabled(Benchmark* bench, const Config& config) {
467c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    if (!bench->isSuitableFor(config.backend)) {
46896fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
469c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
470c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
471e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    SkImageInfo info = SkImageInfo::Make(bench->getSize().fX, bench->getSize().fY,
472e5ea500d4714a7d84de2bf913e81be3b65d2de68reed                                         config.color, config.alpha);
473c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
47496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    Target* target = nullptr;
475c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
476d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    switch (config.backend) {
477c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#if SK_SUPPORT_GPU
478d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    case Benchmark::kGPU_Backend:
479d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        target = new GPUTarget(config);
480d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        break;
481d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson#endif
482d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
483d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    case Benchmark::kHWUI_Backend:
484d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        target = new HWUITarget(config, bench);
485d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        break;
486c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#endif
487d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    default:
488d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        target = new Target(config);
489d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        break;
490d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
491c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
492d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    if (!target->init(info, bench)) {
493c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        delete target;
49496fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
495c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
496c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    return target;
497c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon}
498c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
499b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett/*
500ab12c2715886e7f04c415028a7db49fb0b1e67f3scroggo * We only run our subset benches on files that are supported by BitmapRegionDecoder:
5010459c9425f567b6d11ca534fb13a05de9f37b7eemsarett * i.e. PNG, JPEG, and WEBP. We do *not* test WEBP, since we do not have a scanline
5020459c9425f567b6d11ca534fb13a05de9f37b7eemsarett * decoder for WEBP, which is necessary for running the subset bench. (Another bench
5030459c9425f567b6d11ca534fb13a05de9f37b7eemsarett * must be used to test WEBP, which decodes subsets natively.)
504ab12c2715886e7f04c415028a7db49fb0b1e67f3scroggo */
5050459c9425f567b6d11ca534fb13a05de9f37b7eemsarettstatic bool run_subset_bench(const SkString& path) {
506ab12c2715886e7f04c415028a7db49fb0b1e67f3scroggo    static const char* const exts[] = {
5070459c9425f567b6d11ca534fb13a05de9f37b7eemsarett        "jpg", "jpeg", "png",
5080459c9425f567b6d11ca534fb13a05de9f37b7eemsarett        "JPG", "JPEG", "PNG",
509ab12c2715886e7f04c415028a7db49fb0b1e67f3scroggo    };
510ab12c2715886e7f04c415028a7db49fb0b1e67f3scroggo
5110459c9425f567b6d11ca534fb13a05de9f37b7eemsarett    for (uint32_t i = 0; i < SK_ARRAY_COUNT(exts); i++) {
5120459c9425f567b6d11ca534fb13a05de9f37b7eemsarett        if (path.endsWith(exts[i])) {
5130459c9425f567b6d11ca534fb13a05de9f37b7eemsarett            return true;
514ab12c2715886e7f04c415028a7db49fb0b1e67f3scroggo        }
515ab12c2715886e7f04c415028a7db49fb0b1e67f3scroggo    }
516ab12c2715886e7f04c415028a7db49fb0b1e67f3scroggo
5172da1a854b0836001533aa29ade89d87f420cbbc3scroggo    return false;
518ab12c2715886e7f04c415028a7db49fb0b1e67f3scroggo}
519ab12c2715886e7f04c415028a7db49fb0b1e67f3scroggo
520ab12c2715886e7f04c415028a7db49fb0b1e67f3scroggo/*
521b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett * Returns true if set up for a subset decode succeeds, false otherwise
522b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett * If the set-up succeeds, the width and height parameters will be set
523b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett */
5240459c9425f567b6d11ca534fb13a05de9f37b7eemsarettstatic bool valid_subset_bench(const SkString& path, SkColorType colorType,
525b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett        int* width, int* height) {
526b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett    SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(path.c_str()));
527b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett    SkAutoTDelete<SkMemoryStream> stream(new SkMemoryStream(encoded));
528b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett
5290459c9425f567b6d11ca534fb13a05de9f37b7eemsarett    // Check that we can create a codec.
5300459c9425f567b6d11ca534fb13a05de9f37b7eemsarett    SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.detach()));
5310459c9425f567b6d11ca534fb13a05de9f37b7eemsarett    if (nullptr == codec) {
5320459c9425f567b6d11ca534fb13a05de9f37b7eemsarett        SkDebugf("Could not create codec for %s.  Skipping bench.\n", path.c_str());
5330459c9425f567b6d11ca534fb13a05de9f37b7eemsarett        return false;
5340459c9425f567b6d11ca534fb13a05de9f37b7eemsarett    }
535b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett
5360459c9425f567b6d11ca534fb13a05de9f37b7eemsarett    // These will be initialized by SkCodec if the color type is kIndex8 and
5370459c9425f567b6d11ca534fb13a05de9f37b7eemsarett    // unused otherwise.
5380459c9425f567b6d11ca534fb13a05de9f37b7eemsarett    SkPMColor colors[256];
5390459c9425f567b6d11ca534fb13a05de9f37b7eemsarett    int colorCount;
5400459c9425f567b6d11ca534fb13a05de9f37b7eemsarett    const SkImageInfo info = codec->getInfo().makeColorType(colorType);
5410459c9425f567b6d11ca534fb13a05de9f37b7eemsarett    if (codec->startScanlineDecode(info, nullptr, colors, &colorCount) != SkCodec::kSuccess)
5420459c9425f567b6d11ca534fb13a05de9f37b7eemsarett    {
5430459c9425f567b6d11ca534fb13a05de9f37b7eemsarett        SkDebugf("Could not create scanline decoder for %s with color type %s.  "
5440459c9425f567b6d11ca534fb13a05de9f37b7eemsarett                "Skipping bench.\n", path.c_str(), color_type_to_str(colorType));
5450459c9425f567b6d11ca534fb13a05de9f37b7eemsarett        return false;
546b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett    }
5470459c9425f567b6d11ca534fb13a05de9f37b7eemsarett    *width = info.width();
5480459c9425f567b6d11ca534fb13a05de9f37b7eemsarett    *height = info.height();
549ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett
550ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett    // Check if the image is large enough for a meaningful subset benchmark.
551ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett    if (*width <= 512 && *height <= 512) {
552ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett        // This should not print a message since it is not an error.
553ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett        return false;
554ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett    }
555ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett
556b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett    return true;
557b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett}
558bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio
5595cb4885b4cd1ac5eb3fc92dac5f5509d7c810464msarettstatic bool valid_brd_bench(SkData* encoded, SkBitmapRegionDecoder::Strategy strategy,
5607f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        SkColorType colorType, uint32_t sampleSize, uint32_t minOutputSize, int* width,
5617f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        int* height) {
5625cb4885b4cd1ac5eb3fc92dac5f5509d7c810464msarett    SkAutoTDelete<SkBitmapRegionDecoder> brd(
5635cb4885b4cd1ac5eb3fc92dac5f5509d7c810464msarett            SkBitmapRegionDecoder::Create(encoded, strategy));
5647f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett    if (nullptr == brd.get()) {
5657f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // This is indicates that subset decoding is not supported for a particular image format.
5667f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        return false;
5677f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett    }
5687f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett
56935e5d1b4495478ca3bede66914ae07f50a447c4dmsarett    SkBitmap bitmap;
57035e5d1b4495478ca3bede66914ae07f50a447c4dmsarett    if (!brd->decodeRegion(&bitmap, nullptr, SkIRect::MakeXYWH(0, 0, brd->width(), brd->height()),
57135e5d1b4495478ca3bede66914ae07f50a447c4dmsarett            1, colorType, false)) {
57235e5d1b4495478ca3bede66914ae07f50a447c4dmsarett        return false;
57335e5d1b4495478ca3bede66914ae07f50a447c4dmsarett    }
5747f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett
5757f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett    if (sampleSize * minOutputSize > (uint32_t) brd->width() || sampleSize * minOutputSize >
5767f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett            (uint32_t) brd->height()) {
5777f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // This indicates that the image is not large enough to decode a
5787f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // minOutputSize x minOutputSize subset at the given sampleSize.
5797f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        return false;
5807f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett    }
5817f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett
5827f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett    // Set the image width and height.  The calling code will use this to choose subsets to decode.
5837f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett    *width = brd->width();
5847f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett    *height = brd->height();
5857f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett    return true;
5867f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett}
5877f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett
5883bf9206ada256277a39988c263f0379d544fc27begdanielstatic void cleanup_run(Target* target) {
589385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    delete target;
5903bf9206ada256277a39988c263f0379d544fc27begdaniel#if SK_SUPPORT_GPU
5913bf9206ada256277a39988c263f0379d544fc27begdaniel    if (FLAGS_abandonGpuContext) {
5923bf9206ada256277a39988c263f0379d544fc27begdaniel        gGrFactory->abandonContexts();
5933bf9206ada256277a39988c263f0379d544fc27begdaniel    }
5943bf9206ada256277a39988c263f0379d544fc27begdaniel    if (FLAGS_resetGpuContext || FLAGS_abandonGpuContext) {
5953bf9206ada256277a39988c263f0379d544fc27begdaniel        gGrFactory->destroyContexts();
5963bf9206ada256277a39988c263f0379d544fc27begdaniel    }
5973bf9206ada256277a39988c263f0379d544fc27begdaniel#endif
5983bf9206ada256277a39988c263f0379d544fc27begdaniel}
5993bf9206ada256277a39988c263f0379d544fc27begdaniel
600e714e75c725c987fe682a1f5473224fe3e80380dmtkleinclass BenchmarkStream {
601e714e75c725c987fe682a1f5473224fe3e80380dmtkleinpublic:
60292007583e43115998412ac8b0a06cc2780eb025cmtklein    BenchmarkStream() : fBenches(BenchRegistry::Head())
60392007583e43115998412ac8b0a06cc2780eb025cmtklein                      , fGMs(skiagm::GMRegistry::Head())
604fd731ce804cd3223318f3feee2c98404890b65f2mtklein                      , fCurrentRecording(0)
60592007583e43115998412ac8b0a06cc2780eb025cmtklein                      , fCurrentScale(0)
6065b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                      , fCurrentSKP(0)
60795f192d19938b98a45dd1fa4112d965f60d10516msarett                      , fCurrentUseMPD(0)
60860869a42a133942f852dd0f1696444c2a5c9ad83scroggo                      , fCurrentCodec(0)
60995f192d19938b98a45dd1fa4112d965f60d10516msarett                      , fCurrentImage(0)
61095f192d19938b98a45dd1fa4112d965f60d10516msarett                      , fCurrentSubsetImage(0)
6117f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                      , fCurrentBRDImage(0)
61295f192d19938b98a45dd1fa4112d965f60d10516msarett                      , fCurrentColorType(0)
613b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett                      , fCurrentSubsetType(0)
6147f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                      , fCurrentBRDStrategy(0)
6157f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                      , fCurrentBRDSampleSize(0)
616b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett                      , fCurrentAnimSKP(0) {
61792007583e43115998412ac8b0a06cc2780eb025cmtklein        for (int i = 0; i < FLAGS_skps.count(); i++) {
61892007583e43115998412ac8b0a06cc2780eb025cmtklein            if (SkStrEndsWith(FLAGS_skps[i], ".skp")) {
61992007583e43115998412ac8b0a06cc2780eb025cmtklein                fSKPs.push_back() = FLAGS_skps[i];
62092007583e43115998412ac8b0a06cc2780eb025cmtklein            } else {
62192007583e43115998412ac8b0a06cc2780eb025cmtklein                SkOSFile::Iter it(FLAGS_skps[i], ".skp");
62292007583e43115998412ac8b0a06cc2780eb025cmtklein                SkString path;
62392007583e43115998412ac8b0a06cc2780eb025cmtklein                while (it.next(&path)) {
62492007583e43115998412ac8b0a06cc2780eb025cmtklein                    fSKPs.push_back() = SkOSPath::Join(FLAGS_skps[0], path.c_str());
62592007583e43115998412ac8b0a06cc2780eb025cmtklein                }
62692007583e43115998412ac8b0a06cc2780eb025cmtklein            }
62792007583e43115998412ac8b0a06cc2780eb025cmtklein        }
62892007583e43115998412ac8b0a06cc2780eb025cmtklein
62992007583e43115998412ac8b0a06cc2780eb025cmtklein        if (4 != sscanf(FLAGS_clip[0], "%d,%d,%d,%d",
63092007583e43115998412ac8b0a06cc2780eb025cmtklein                        &fClip.fLeft, &fClip.fTop, &fClip.fRight, &fClip.fBottom)) {
63192007583e43115998412ac8b0a06cc2780eb025cmtklein            SkDebugf("Can't parse %s from --clip as an SkIRect.\n", FLAGS_clip[0]);
63292007583e43115998412ac8b0a06cc2780eb025cmtklein            exit(1);
63392007583e43115998412ac8b0a06cc2780eb025cmtklein        }
63492007583e43115998412ac8b0a06cc2780eb025cmtklein
63592007583e43115998412ac8b0a06cc2780eb025cmtklein        for (int i = 0; i < FLAGS_scales.count(); i++) {
63692007583e43115998412ac8b0a06cc2780eb025cmtklein            if (1 != sscanf(FLAGS_scales[i], "%f", &fScales.push_back())) {
63792007583e43115998412ac8b0a06cc2780eb025cmtklein                SkDebugf("Can't parse %s from --scales as an SkScalar.\n", FLAGS_scales[i]);
63892007583e43115998412ac8b0a06cc2780eb025cmtklein                exit(1);
63992007583e43115998412ac8b0a06cc2780eb025cmtklein            }
64092007583e43115998412ac8b0a06cc2780eb025cmtklein        }
6415b69377507478623dcf5b11f3ecb010f87c4794frobertphillips
64263a82855b1f0b83952b65fca330954c50ebe7a4bcdalton        if (2 != sscanf(FLAGS_zoom[0], "%f,%lf", &fZoomMax, &fZoomPeriodMs)) {
64363a82855b1f0b83952b65fca330954c50ebe7a4bcdalton            SkDebugf("Can't parse %s from --zoom as a zoomMax,zoomPeriodMs.\n", FLAGS_zoom[0]);
644261c3ad7fde95748da92550735decc949dc73bf2joshualitt            exit(1);
645261c3ad7fde95748da92550735decc949dc73bf2joshualitt        }
646261c3ad7fde95748da92550735decc949dc73bf2joshualitt
6475b69377507478623dcf5b11f3ecb010f87c4794frobertphillips        if (FLAGS_mpd) {
6485b69377507478623dcf5b11f3ecb010f87c4794frobertphillips            fUseMPDs.push_back() = true;
6495b69377507478623dcf5b11f3ecb010f87c4794frobertphillips        }
650c751ecb3681072fda53dd3cebeb2eb41fc73b314mtklein        fUseMPDs.push_back() = false;
65195553d917c73ef333ede967521560957a5b6a0admtklein
65295f192d19938b98a45dd1fa4112d965f60d10516msarett        // Prepare the images for decoding
65395f192d19938b98a45dd1fa4112d965f60d10516msarett        for (int i = 0; i < FLAGS_images.count(); i++) {
65495f192d19938b98a45dd1fa4112d965f60d10516msarett            const char* flag = FLAGS_images[i];
65595f192d19938b98a45dd1fa4112d965f60d10516msarett            if (sk_isdir(flag)) {
65695f192d19938b98a45dd1fa4112d965f60d10516msarett                // If the value passed in is a directory, add all the images
65795f192d19938b98a45dd1fa4112d965f60d10516msarett                SkOSFile::Iter it(flag);
65895f192d19938b98a45dd1fa4112d965f60d10516msarett                SkString file;
65995f192d19938b98a45dd1fa4112d965f60d10516msarett                while (it.next(&file)) {
66095f192d19938b98a45dd1fa4112d965f60d10516msarett                    fImages.push_back() = SkOSPath::Join(flag, file.c_str());
66195f192d19938b98a45dd1fa4112d965f60d10516msarett                }
66295f192d19938b98a45dd1fa4112d965f60d10516msarett            } else if (sk_exists(flag)) {
66395f192d19938b98a45dd1fa4112d965f60d10516msarett                // Also add the value if it is a single image
66495f192d19938b98a45dd1fa4112d965f60d10516msarett                fImages.push_back() = flag;
66595f192d19938b98a45dd1fa4112d965f60d10516msarett            }
66695f192d19938b98a45dd1fa4112d965f60d10516msarett        }
66795553d917c73ef333ede967521560957a5b6a0admtklein
66895f192d19938b98a45dd1fa4112d965f60d10516msarett        // Choose the candidate color types for image decoding
66995f192d19938b98a45dd1fa4112d965f60d10516msarett        const SkColorType colorTypes[] =
670b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett            { kN32_SkColorType,
671b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett              kRGB_565_SkColorType,
672b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett              kAlpha_8_SkColorType,
673b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett              kIndex_8_SkColorType,
674b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett              kGray_8_SkColorType };
67574deb981d5e9c11c88fe431e78166d6cf8dacc1amsarett        fColorTypes.reset(colorTypes, SK_ARRAY_COUNT(colorTypes));
67692007583e43115998412ac8b0a06cc2780eb025cmtklein    }
677e714e75c725c987fe682a1f5473224fe3e80380dmtklein
678fd731ce804cd3223318f3feee2c98404890b65f2mtklein    static bool ReadPicture(const char* path, SkAutoTUnref<SkPicture>* pic) {
679fd731ce804cd3223318f3feee2c98404890b65f2mtklein        // Not strictly necessary, as it will be checked again later,
680fd731ce804cd3223318f3feee2c98404890b65f2mtklein        // but helps to avoid a lot of pointless work if we're going to skip it.
681fd731ce804cd3223318f3feee2c98404890b65f2mtklein        if (SkCommandLineFlags::ShouldSkip(FLAGS_match, path)) {
682fd731ce804cd3223318f3feee2c98404890b65f2mtklein            return false;
683fd731ce804cd3223318f3feee2c98404890b65f2mtklein        }
684fd731ce804cd3223318f3feee2c98404890b65f2mtklein
685a1193e4b0e34a7e4e1bd33e9708d7341679f8321scroggo        SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(path));
68696fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (stream.get() == nullptr) {
687fd731ce804cd3223318f3feee2c98404890b65f2mtklein            SkDebugf("Could not read %s.\n", path);
688fd731ce804cd3223318f3feee2c98404890b65f2mtklein            return false;
689fd731ce804cd3223318f3feee2c98404890b65f2mtklein        }
690fd731ce804cd3223318f3feee2c98404890b65f2mtklein
69157f27bdcbd328491a121918b4ab9301fbcdec642mtklein        pic->reset(SkPicture::CreateFromStream(stream.get()));
69296fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (pic->get() == nullptr) {
693fd731ce804cd3223318f3feee2c98404890b65f2mtklein            SkDebugf("Could not read %s as an SkPicture.\n", path);
694fd731ce804cd3223318f3feee2c98404890b65f2mtklein            return false;
695fd731ce804cd3223318f3feee2c98404890b65f2mtklein        }
696fd731ce804cd3223318f3feee2c98404890b65f2mtklein        return true;
697fd731ce804cd3223318f3feee2c98404890b65f2mtklein    }
698fd731ce804cd3223318f3feee2c98404890b65f2mtklein
69992007583e43115998412ac8b0a06cc2780eb025cmtklein    Benchmark* next() {
700e714e75c725c987fe682a1f5473224fe3e80380dmtklein        if (fBenches) {
70196fcdcc219d2a0d3579719b84b28bede76efba64halcanary            Benchmark* bench = fBenches->factory()(nullptr);
702e714e75c725c987fe682a1f5473224fe3e80380dmtklein            fBenches = fBenches->next();
70392007583e43115998412ac8b0a06cc2780eb025cmtklein            fSourceType = "bench";
704fd731ce804cd3223318f3feee2c98404890b65f2mtklein            fBenchType  = "micro";
705e714e75c725c987fe682a1f5473224fe3e80380dmtklein            return bench;
706e714e75c725c987fe682a1f5473224fe3e80380dmtklein        }
70792007583e43115998412ac8b0a06cc2780eb025cmtklein
708e714e75c725c987fe682a1f5473224fe3e80380dmtklein        while (fGMs) {
70996fcdcc219d2a0d3579719b84b28bede76efba64halcanary            SkAutoTDelete<skiagm::GM> gm(fGMs->factory()(nullptr));
710e714e75c725c987fe682a1f5473224fe3e80380dmtklein            fGMs = fGMs->next();
711cf5d9c993dcbd75d4cefe2d1de25c2b9645f6957mtklein            if (gm->runAsBench()) {
71292007583e43115998412ac8b0a06cc2780eb025cmtklein                fSourceType = "gm";
713fd731ce804cd3223318f3feee2c98404890b65f2mtklein                fBenchType  = "micro";
714385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary                return new GMBench(gm.detach());
715e714e75c725c987fe682a1f5473224fe3e80380dmtklein            }
716e714e75c725c987fe682a1f5473224fe3e80380dmtklein        }
71792007583e43115998412ac8b0a06cc2780eb025cmtklein
718fd731ce804cd3223318f3feee2c98404890b65f2mtklein        // First add all .skps as RecordingBenches.
719fd731ce804cd3223318f3feee2c98404890b65f2mtklein        while (fCurrentRecording < fSKPs.count()) {
720fd731ce804cd3223318f3feee2c98404890b65f2mtklein            const SkString& path = fSKPs[fCurrentRecording++];
721fd731ce804cd3223318f3feee2c98404890b65f2mtklein            SkAutoTUnref<SkPicture> pic;
722fd731ce804cd3223318f3feee2c98404890b65f2mtklein            if (!ReadPicture(path.c_str(), &pic)) {
723fd731ce804cd3223318f3feee2c98404890b65f2mtklein                continue;
724fd731ce804cd3223318f3feee2c98404890b65f2mtklein            }
725fd731ce804cd3223318f3feee2c98404890b65f2mtklein            SkString name = SkOSPath::Basename(path.c_str());
726fd731ce804cd3223318f3feee2c98404890b65f2mtklein            fSourceType = "skp";
727fd731ce804cd3223318f3feee2c98404890b65f2mtklein            fBenchType  = "recording";
7280aa5cea8694d3686b6742a36eab81ab9001de954bsalomon            fSKPBytes = static_cast<double>(SkPictureUtils::ApproximateBytesUsed(pic));
729051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein            fSKPOps   = pic->approximateOpCount();
730385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary            return new RecordingBench(name.c_str(), pic.get(), FLAGS_bbh);
731fd731ce804cd3223318f3feee2c98404890b65f2mtklein        }
732fd731ce804cd3223318f3feee2c98404890b65f2mtklein
733fd731ce804cd3223318f3feee2c98404890b65f2mtklein        // Then once each for each scale as SKPBenches (playback).
73492007583e43115998412ac8b0a06cc2780eb025cmtklein        while (fCurrentScale < fScales.count()) {
73592007583e43115998412ac8b0a06cc2780eb025cmtklein            while (fCurrentSKP < fSKPs.count()) {
7365b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                const SkString& path = fSKPs[fCurrentSKP];
737fd731ce804cd3223318f3feee2c98404890b65f2mtklein                SkAutoTUnref<SkPicture> pic;
738fd731ce804cd3223318f3feee2c98404890b65f2mtklein                if (!ReadPicture(path.c_str(), &pic)) {
7395b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                    fCurrentSKP++;
74092007583e43115998412ac8b0a06cc2780eb025cmtklein                    continue;
74192007583e43115998412ac8b0a06cc2780eb025cmtklein                }
7425b69377507478623dcf5b11f3ecb010f87c4794frobertphillips
7435b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                while (fCurrentUseMPD < fUseMPDs.count()) {
7445b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                    if (FLAGS_bbh) {
7455b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                        // The SKP we read off disk doesn't have a BBH.  Re-record so it grows one.
7465b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                        SkRTreeFactory factory;
7475b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                        SkPictureRecorder recorder;
7485b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                        static const int kFlags = SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag;
7495b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                        pic->playback(recorder.beginRecording(pic->cullRect().width(),
7505b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                                                              pic->cullRect().height(),
751748ca3bf2d170708f263693e8579e6722389d0efmtklein                                                              &factory,
752e451c4df7369c5e253ef9c9e0a8713beda25f34brobertphillips                                                              fUseMPDs[fCurrentUseMPD] ? kFlags : 0));
7535b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                        pic.reset(recorder.endRecording());
7545b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                    }
7555b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                    SkString name = SkOSPath::Basename(path.c_str());
7565b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                    fSourceType = "skp";
7575b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                    fBenchType = "playback";
758385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary                    return new SKPBench(name.c_str(), pic.get(), fClip, fScales[fCurrentScale],
759385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary                                        fUseMPDs[fCurrentUseMPD++], FLAGS_loopSKP);
7602084050a33ae139d0fe9bb680f7905f91139a39fmtklein                }
7615b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                fCurrentUseMPD = 0;
7625b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                fCurrentSKP++;
76392007583e43115998412ac8b0a06cc2780eb025cmtklein            }
76492007583e43115998412ac8b0a06cc2780eb025cmtklein            fCurrentSKP = 0;
76592007583e43115998412ac8b0a06cc2780eb025cmtklein            fCurrentScale++;
76692007583e43115998412ac8b0a06cc2780eb025cmtklein        }
76792007583e43115998412ac8b0a06cc2780eb025cmtklein
768261c3ad7fde95748da92550735decc949dc73bf2joshualitt        // Now loop over each skp again if we have an animation
76963a82855b1f0b83952b65fca330954c50ebe7a4bcdalton        if (fZoomMax != 1.0f && fZoomPeriodMs > 0) {
770261c3ad7fde95748da92550735decc949dc73bf2joshualitt            while (fCurrentAnimSKP < fSKPs.count()) {
771261c3ad7fde95748da92550735decc949dc73bf2joshualitt                const SkString& path = fSKPs[fCurrentAnimSKP];
772261c3ad7fde95748da92550735decc949dc73bf2joshualitt                SkAutoTUnref<SkPicture> pic;
773261c3ad7fde95748da92550735decc949dc73bf2joshualitt                if (!ReadPicture(path.c_str(), &pic)) {
774261c3ad7fde95748da92550735decc949dc73bf2joshualitt                    fCurrentAnimSKP++;
775261c3ad7fde95748da92550735decc949dc73bf2joshualitt                    continue;
776261c3ad7fde95748da92550735decc949dc73bf2joshualitt                }
777261c3ad7fde95748da92550735decc949dc73bf2joshualitt
778261c3ad7fde95748da92550735decc949dc73bf2joshualitt                fCurrentAnimSKP++;
779261c3ad7fde95748da92550735decc949dc73bf2joshualitt                SkString name = SkOSPath::Basename(path.c_str());
78063a82855b1f0b83952b65fca330954c50ebe7a4bcdalton                SkAutoTUnref<SKPAnimationBench::Animation> animation(
78163a82855b1f0b83952b65fca330954c50ebe7a4bcdalton                    SKPAnimationBench::CreateZoomAnimation(fZoomMax, fZoomPeriodMs));
782385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary                return new SKPAnimationBench(name.c_str(), pic.get(), fClip, animation,
783385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary                                             FLAGS_loopSKP);
784261c3ad7fde95748da92550735decc949dc73bf2joshualitt            }
785261c3ad7fde95748da92550735decc949dc73bf2joshualitt        }
786261c3ad7fde95748da92550735decc949dc73bf2joshualitt
78760869a42a133942f852dd0f1696444c2a5c9ad83scroggo        for (; fCurrentCodec < fImages.count(); fCurrentCodec++) {
788303fa350125f372bbfc29bec1235885493dab9b4scroggo            fSourceType = "image";
789303fa350125f372bbfc29bec1235885493dab9b4scroggo            fBenchType = "skcodec";
79060869a42a133942f852dd0f1696444c2a5c9ad83scroggo            const SkString& path = fImages[fCurrentCodec];
79160869a42a133942f852dd0f1696444c2a5c9ad83scroggo            SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(path.c_str()));
79260869a42a133942f852dd0f1696444c2a5c9ad83scroggo            SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded));
79360869a42a133942f852dd0f1696444c2a5c9ad83scroggo            if (!codec) {
79460869a42a133942f852dd0f1696444c2a5c9ad83scroggo                // Nothing to time.
7959d9725c892743cf8fc66ea6cdd5ce21fe2df6d14msarett                SkDebugf("Cannot find codec for %s\n", path.c_str());
79660869a42a133942f852dd0f1696444c2a5c9ad83scroggo                continue;
79760869a42a133942f852dd0f1696444c2a5c9ad83scroggo            }
79821027994192f395bbd1507558b84f59b3c7cf0dascroggo
79960869a42a133942f852dd0f1696444c2a5c9ad83scroggo            while (fCurrentColorType < fColorTypes.count()) {
80021027994192f395bbd1507558b84f59b3c7cf0dascroggo                const SkColorType colorType = fColorTypes[fCurrentColorType];
80160869a42a133942f852dd0f1696444c2a5c9ad83scroggo                fCurrentColorType++;
80221027994192f395bbd1507558b84f59b3c7cf0dascroggo
80360869a42a133942f852dd0f1696444c2a5c9ad83scroggo                // Make sure we can decode to this color type.
80460869a42a133942f852dd0f1696444c2a5c9ad83scroggo                SkImageInfo info = codec->getInfo().makeColorType(colorType);
80521027994192f395bbd1507558b84f59b3c7cf0dascroggo                SkAlphaType alphaType;
80621027994192f395bbd1507558b84f59b3c7cf0dascroggo                if (!SkColorTypeValidateAlphaType(colorType, info.alphaType(),
80721027994192f395bbd1507558b84f59b3c7cf0dascroggo                                                  &alphaType)) {
80821027994192f395bbd1507558b84f59b3c7cf0dascroggo                    continue;
80921027994192f395bbd1507558b84f59b3c7cf0dascroggo                }
81021027994192f395bbd1507558b84f59b3c7cf0dascroggo                if (alphaType != info.alphaType()) {
81121027994192f395bbd1507558b84f59b3c7cf0dascroggo                    info = info.makeAlphaType(alphaType);
81221027994192f395bbd1507558b84f59b3c7cf0dascroggo                }
81321027994192f395bbd1507558b84f59b3c7cf0dascroggo
81421027994192f395bbd1507558b84f59b3c7cf0dascroggo                const size_t rowBytes = info.minRowBytes();
81521027994192f395bbd1507558b84f59b3c7cf0dascroggo                SkAutoMalloc storage(info.getSafeSize(rowBytes));
81621027994192f395bbd1507558b84f59b3c7cf0dascroggo
81721027994192f395bbd1507558b84f59b3c7cf0dascroggo                // Used if fCurrentColorType is kIndex_8_SkColorType
81821027994192f395bbd1507558b84f59b3c7cf0dascroggo                int colorCount = 256;
81921027994192f395bbd1507558b84f59b3c7cf0dascroggo                SkPMColor colors[256];
82021027994192f395bbd1507558b84f59b3c7cf0dascroggo
821eb602a5c94078fb2956c9bdc64bbf47a31b9c0e5scroggo                const SkCodec::Result result = codec->getPixels(
82296fcdcc219d2a0d3579719b84b28bede76efba64halcanary                        info, storage.get(), rowBytes, nullptr, colors,
82321027994192f395bbd1507558b84f59b3c7cf0dascroggo                        &colorCount);
82460869a42a133942f852dd0f1696444c2a5c9ad83scroggo                switch (result) {
825eb602a5c94078fb2956c9bdc64bbf47a31b9c0e5scroggo                    case SkCodec::kSuccess:
826eb602a5c94078fb2956c9bdc64bbf47a31b9c0e5scroggo                    case SkCodec::kIncompleteInput:
82760869a42a133942f852dd0f1696444c2a5c9ad83scroggo                        return new CodecBench(SkOSPath::Basename(path.c_str()),
82860869a42a133942f852dd0f1696444c2a5c9ad83scroggo                                encoded, colorType);
829eb602a5c94078fb2956c9bdc64bbf47a31b9c0e5scroggo                    case SkCodec::kInvalidConversion:
83060869a42a133942f852dd0f1696444c2a5c9ad83scroggo                        // This is okay. Not all conversions are valid.
83160869a42a133942f852dd0f1696444c2a5c9ad83scroggo                        break;
83260869a42a133942f852dd0f1696444c2a5c9ad83scroggo                    default:
83360869a42a133942f852dd0f1696444c2a5c9ad83scroggo                        // This represents some sort of failure.
83460869a42a133942f852dd0f1696444c2a5c9ad83scroggo                        SkASSERT(false);
83560869a42a133942f852dd0f1696444c2a5c9ad83scroggo                        break;
83660869a42a133942f852dd0f1696444c2a5c9ad83scroggo                }
83760869a42a133942f852dd0f1696444c2a5c9ad83scroggo            }
83860869a42a133942f852dd0f1696444c2a5c9ad83scroggo            fCurrentColorType = 0;
83960869a42a133942f852dd0f1696444c2a5c9ad83scroggo        }
84060869a42a133942f852dd0f1696444c2a5c9ad83scroggo
84195f192d19938b98a45dd1fa4112d965f60d10516msarett        // Run the DecodingBenches
84295f192d19938b98a45dd1fa4112d965f60d10516msarett        while (fCurrentImage < fImages.count()) {
843303fa350125f372bbfc29bec1235885493dab9b4scroggo            fSourceType = "image";
844303fa350125f372bbfc29bec1235885493dab9b4scroggo            fBenchType = "skimagedecoder";
84595f192d19938b98a45dd1fa4112d965f60d10516msarett            while (fCurrentColorType < fColorTypes.count()) {
84695f192d19938b98a45dd1fa4112d965f60d10516msarett                const SkString& path = fImages[fCurrentImage];
84795f192d19938b98a45dd1fa4112d965f60d10516msarett                SkColorType colorType = fColorTypes[fCurrentColorType];
84895f192d19938b98a45dd1fa4112d965f60d10516msarett                fCurrentColorType++;
84960869a42a133942f852dd0f1696444c2a5c9ad83scroggo                // Check if the image decodes to the right color type
85060869a42a133942f852dd0f1696444c2a5c9ad83scroggo                // before creating the benchmark
85195f192d19938b98a45dd1fa4112d965f60d10516msarett                SkBitmap bitmap;
85295f192d19938b98a45dd1fa4112d965f60d10516msarett                if (SkImageDecoder::DecodeFile(path.c_str(), &bitmap,
85360869a42a133942f852dd0f1696444c2a5c9ad83scroggo                        colorType, SkImageDecoder::kDecodePixels_Mode)
85460869a42a133942f852dd0f1696444c2a5c9ad83scroggo                        && bitmap.colorType() == colorType) {
85595f192d19938b98a45dd1fa4112d965f60d10516msarett                    return new DecodingBench(path, colorType);
85695f192d19938b98a45dd1fa4112d965f60d10516msarett                }
85795f192d19938b98a45dd1fa4112d965f60d10516msarett            }
85895f192d19938b98a45dd1fa4112d965f60d10516msarett            fCurrentColorType = 0;
85995f192d19938b98a45dd1fa4112d965f60d10516msarett            fCurrentImage++;
86095f192d19938b98a45dd1fa4112d965f60d10516msarett        }
86195f192d19938b98a45dd1fa4112d965f60d10516msarett
862b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett        // Run the SubsetBenches
8630459c9425f567b6d11ca534fb13a05de9f37b7eemsarett        while (fCurrentSubsetImage < fImages.count()) {
864303fa350125f372bbfc29bec1235885493dab9b4scroggo            fSourceType = "image";
8650459c9425f567b6d11ca534fb13a05de9f37b7eemsarett            fBenchType = "skcodec";
8660459c9425f567b6d11ca534fb13a05de9f37b7eemsarett            const SkString& path = fImages[fCurrentSubsetImage];
8670459c9425f567b6d11ca534fb13a05de9f37b7eemsarett            if (!run_subset_bench(path)) {
8680459c9425f567b6d11ca534fb13a05de9f37b7eemsarett                fCurrentSubsetImage++;
8690459c9425f567b6d11ca534fb13a05de9f37b7eemsarett                continue;
8700459c9425f567b6d11ca534fb13a05de9f37b7eemsarett            }
8710459c9425f567b6d11ca534fb13a05de9f37b7eemsarett            while (fCurrentColorType < fColorTypes.count()) {
8720459c9425f567b6d11ca534fb13a05de9f37b7eemsarett                SkColorType colorType = fColorTypes[fCurrentColorType];
8730459c9425f567b6d11ca534fb13a05de9f37b7eemsarett                while (fCurrentSubsetType <= kLast_SubsetType) {
8740459c9425f567b6d11ca534fb13a05de9f37b7eemsarett                    int width = 0;
8750459c9425f567b6d11ca534fb13a05de9f37b7eemsarett                    int height = 0;
8760459c9425f567b6d11ca534fb13a05de9f37b7eemsarett                    int currentSubsetType = fCurrentSubsetType++;
8770459c9425f567b6d11ca534fb13a05de9f37b7eemsarett                    if (valid_subset_bench(path, colorType, &width, &height)) {
8780459c9425f567b6d11ca534fb13a05de9f37b7eemsarett                        switch (currentSubsetType) {
8790459c9425f567b6d11ca534fb13a05de9f37b7eemsarett                            case kTopLeft_SubsetType:
8800459c9425f567b6d11ca534fb13a05de9f37b7eemsarett                                return new SubsetSingleBench(path, colorType, width/3,
8810459c9425f567b6d11ca534fb13a05de9f37b7eemsarett                                        height/3, 0, 0);
8820459c9425f567b6d11ca534fb13a05de9f37b7eemsarett                            case kTopRight_SubsetType:
8830459c9425f567b6d11ca534fb13a05de9f37b7eemsarett                                return new SubsetSingleBench(path, colorType, width/3,
8840459c9425f567b6d11ca534fb13a05de9f37b7eemsarett                                        height/3, 2*width/3, 0);
8850459c9425f567b6d11ca534fb13a05de9f37b7eemsarett                            case kMiddle_SubsetType:
8860459c9425f567b6d11ca534fb13a05de9f37b7eemsarett                                return new SubsetSingleBench(path, colorType, width/3,
8870459c9425f567b6d11ca534fb13a05de9f37b7eemsarett                                        height/3, width/3, height/3);
8880459c9425f567b6d11ca534fb13a05de9f37b7eemsarett                            case kBottomLeft_SubsetType:
8890459c9425f567b6d11ca534fb13a05de9f37b7eemsarett                                return new SubsetSingleBench(path, colorType, width/3,
8900459c9425f567b6d11ca534fb13a05de9f37b7eemsarett                                        height/3, 0, 2*height/3);
8910459c9425f567b6d11ca534fb13a05de9f37b7eemsarett                            case kBottomRight_SubsetType:
8920459c9425f567b6d11ca534fb13a05de9f37b7eemsarett                                return new SubsetSingleBench(path, colorType, width/3,
8930459c9425f567b6d11ca534fb13a05de9f37b7eemsarett                                        height/3, 2*width/3, 2*height/3);
8940459c9425f567b6d11ca534fb13a05de9f37b7eemsarett                            case kTranslate_SubsetType:
8950459c9425f567b6d11ca534fb13a05de9f37b7eemsarett                                return new SubsetTranslateBench(path, colorType, 512, 512);
8960459c9425f567b6d11ca534fb13a05de9f37b7eemsarett                            case kZoom_SubsetType:
8970459c9425f567b6d11ca534fb13a05de9f37b7eemsarett                                return new SubsetZoomBench(path, colorType, 512, 512);
89895f192d19938b98a45dd1fa4112d965f60d10516msarett                        }
8990459c9425f567b6d11ca534fb13a05de9f37b7eemsarett                    } else {
9000459c9425f567b6d11ca534fb13a05de9f37b7eemsarett                        break;
90195f192d19938b98a45dd1fa4112d965f60d10516msarett                    }
90295f192d19938b98a45dd1fa4112d965f60d10516msarett                }
9030459c9425f567b6d11ca534fb13a05de9f37b7eemsarett                fCurrentSubsetType = 0;
9040459c9425f567b6d11ca534fb13a05de9f37b7eemsarett                fCurrentColorType++;
90595f192d19938b98a45dd1fa4112d965f60d10516msarett            }
9060459c9425f567b6d11ca534fb13a05de9f37b7eemsarett            fCurrentColorType = 0;
9070459c9425f567b6d11ca534fb13a05de9f37b7eemsarett            fCurrentSubsetImage++;
90895f192d19938b98a45dd1fa4112d965f60d10516msarett        }
90995f192d19938b98a45dd1fa4112d965f60d10516msarett
9107f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // Run the BRDBenches
9117f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // We will benchmark multiple BRD strategies.
912303fa350125f372bbfc29bec1235885493dab9b4scroggo        static const struct {
9135cb4885b4cd1ac5eb3fc92dac5f5509d7c810464msarett            SkBitmapRegionDecoder::Strategy    fStrategy;
9140459c9425f567b6d11ca534fb13a05de9f37b7eemsarett            const char*                        fName;
915303fa350125f372bbfc29bec1235885493dab9b4scroggo        } strategies[] = {
9160459c9425f567b6d11ca534fb13a05de9f37b7eemsarett            { SkBitmapRegionDecoder::kCanvas_Strategy,       "BRD_canvas" },
9175cb4885b4cd1ac5eb3fc92dac5f5509d7c810464msarett            { SkBitmapRegionDecoder::kAndroidCodec_Strategy, "BRD_android_codec" },
9187f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        };
9197f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett
9207f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // We intend to create benchmarks that model the use cases in
9217f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // android/libraries/social/tiledimage.  In this library, an image is decoded in 512x512
9227f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // tiles.  The image can be translated freely, so the location of a tile may be anywhere in
9237f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // the image.  For that reason, we will benchmark decodes in five representative locations
9247f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // in the image.  Additionally, this use case utilizes power of two scaling, so we will
9257f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // test on power of two sample sizes.  The output tile is always 512x512, so, when a
9267f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // sampleSize is used, the size of the subset that is decoded is always
9277f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // (sampleSize*512)x(sampleSize*512).
9287f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // There are a few good reasons to only test on power of two sample sizes at this time:
9297f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        //     JPEG decodes using kOriginal_Strategy are broken for non-powers of two.
9306950de6c4166fabb35e6c756fc009e0cf1c47819halcanary        //         https://bug.skia.org/4319
9317f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        //     All use cases we are aware of only scale by powers of two.
9327f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        //     PNG decodes use the indicated sampling strategy regardless of the sample size, so
9337f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        //         these tests are sufficient to provide good coverage of our scaling options.
934501b7344f116ccc821d437d324aa7883d7ce97bfscroggo        const uint32_t sampleSizes[] = { 1, 2, 4, 8, 16, 32, 64 };
9357f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        const uint32_t minOutputSize = 512;
9367f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        while (fCurrentBRDImage < fImages.count()) {
9377f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett            while (fCurrentBRDStrategy < (int) SK_ARRAY_COUNT(strategies)) {
938303fa350125f372bbfc29bec1235885493dab9b4scroggo                fSourceType = "image";
939303fa350125f372bbfc29bec1235885493dab9b4scroggo                fBenchType = strategies[fCurrentBRDStrategy].fName;
940860e8a67190e024b7375e52e270e6bd0a17af86escroggo
941860e8a67190e024b7375e52e270e6bd0a17af86escroggo                const SkString& path = fImages[fCurrentBRDImage];
9425cb4885b4cd1ac5eb3fc92dac5f5509d7c810464msarett                const SkBitmapRegionDecoder::Strategy strategy =
943860e8a67190e024b7375e52e270e6bd0a17af86escroggo                        strategies[fCurrentBRDStrategy].fStrategy;
944860e8a67190e024b7375e52e270e6bd0a17af86escroggo
9457f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                while (fCurrentColorType < fColorTypes.count()) {
9467f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                    while (fCurrentBRDSampleSize < (int) SK_ARRAY_COUNT(sampleSizes)) {
9477f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                        while (fCurrentSubsetType <= kLastSingle_SubsetType) {
948860e8a67190e024b7375e52e270e6bd0a17af86escroggo
949860e8a67190e024b7375e52e270e6bd0a17af86escroggo
9507f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(path.c_str()));
9517f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            const SkColorType colorType = fColorTypes[fCurrentColorType];
9527f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            uint32_t sampleSize = sampleSizes[fCurrentBRDSampleSize];
9537f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            int currentSubsetType = fCurrentSubsetType++;
9547f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett
9557f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            int width = 0;
9567f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            int height = 0;
9577f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            if (!valid_brd_bench(encoded.get(), strategy, colorType, sampleSize,
9587f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    minOutputSize, &width, &height)) {
9597f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                break;
9607f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            }
9617f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett
9627f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            SkString basename = SkOSPath::Basename(path.c_str());
9637f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            SkIRect subset;
9647f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            const uint32_t subsetSize = sampleSize * minOutputSize;
9657f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            switch (currentSubsetType) {
9667f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                case kTopLeft_SubsetType:
9677f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    basename.append("_TopLeft");
9687f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    subset = SkIRect::MakeXYWH(0, 0, subsetSize, subsetSize);
9697f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    break;
9707f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                case kTopRight_SubsetType:
9717f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    basename.append("_TopRight");
9727f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    subset = SkIRect::MakeXYWH(width - subsetSize, 0, subsetSize,
9737f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                            subsetSize);
9747f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    break;
9757f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                case kMiddle_SubsetType:
9767f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    basename.append("_Middle");
9777f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    subset = SkIRect::MakeXYWH((width - subsetSize) / 2,
9787f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                            (height - subsetSize) / 2, subsetSize, subsetSize);
9797f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    break;
9807f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                case kBottomLeft_SubsetType:
9817f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    basename.append("_BottomLeft");
9827f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    subset = SkIRect::MakeXYWH(0, height - subsetSize, subsetSize,
9837f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                            subsetSize);
9847f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    break;
9857f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                case kBottomRight_SubsetType:
9867f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    basename.append("_BottomRight");
9877f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    subset = SkIRect::MakeXYWH(width - subsetSize,
9887f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                            height - subsetSize, subsetSize, subsetSize);
9897f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    break;
9907f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                default:
9917f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    SkASSERT(false);
9927f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            }
9937f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett
9947f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            return new BitmapRegionDecoderBench(basename.c_str(), encoded.get(),
9957f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    strategy, colorType, sampleSize, subset);
9967f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                        }
9977f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                        fCurrentSubsetType = 0;
9987f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                        fCurrentBRDSampleSize++;
9997f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                    }
10007f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                    fCurrentBRDSampleSize = 0;
10017f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                    fCurrentColorType++;
10027f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                }
10037f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                fCurrentColorType = 0;
10047f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                fCurrentBRDStrategy++;
10057f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett            }
10067f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett            fCurrentBRDStrategy = 0;
10077f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett            fCurrentBRDImage++;
10087f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        }
10097f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett
101096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
1011e714e75c725c987fe682a1f5473224fe3e80380dmtklein    }
101292007583e43115998412ac8b0a06cc2780eb025cmtklein
101392007583e43115998412ac8b0a06cc2780eb025cmtklein    void fillCurrentOptions(ResultsWriter* log) const {
101492007583e43115998412ac8b0a06cc2780eb025cmtklein        log->configOption("source_type", fSourceType);
1015fd731ce804cd3223318f3feee2c98404890b65f2mtklein        log->configOption("bench_type",  fBenchType);
101692007583e43115998412ac8b0a06cc2780eb025cmtklein        if (0 == strcmp(fSourceType, "skp")) {
101792007583e43115998412ac8b0a06cc2780eb025cmtklein            log->configOption("clip",
101892007583e43115998412ac8b0a06cc2780eb025cmtklein                    SkStringPrintf("%d %d %d %d", fClip.fLeft, fClip.fTop,
101992007583e43115998412ac8b0a06cc2780eb025cmtklein                                                  fClip.fRight, fClip.fBottom).c_str());
10204dfdbb19ba861bbd5e1a306bb23f32464ea5e2c5mtklein            SK_ALWAYSBREAK(fCurrentScale < fScales.count());  // debugging paranoia
102192007583e43115998412ac8b0a06cc2780eb025cmtklein            log->configOption("scale", SkStringPrintf("%.2g", fScales[fCurrentScale]).c_str());
10225b69377507478623dcf5b11f3ecb010f87c4794frobertphillips            if (fCurrentUseMPD > 0) {
10235b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                SkASSERT(1 == fCurrentUseMPD || 2 == fCurrentUseMPD);
10245b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                log->configOption("multi_picture_draw", fUseMPDs[fCurrentUseMPD-1] ? "true" : "false");
10255b69377507478623dcf5b11f3ecb010f87c4794frobertphillips            }
102692007583e43115998412ac8b0a06cc2780eb025cmtklein        }
1027051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein        if (0 == strcmp(fBenchType, "recording")) {
1028051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein            log->metric("bytes", fSKPBytes);
1029051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein            log->metric("ops",   fSKPOps);
1030051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein        }
103192007583e43115998412ac8b0a06cc2780eb025cmtklein    }
103292007583e43115998412ac8b0a06cc2780eb025cmtklein
1033e714e75c725c987fe682a1f5473224fe3e80380dmtkleinprivate:
1034b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett    enum SubsetType {
1035b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett        kTopLeft_SubsetType     = 0,
1036b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett        kTopRight_SubsetType    = 1,
1037ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett        kMiddle_SubsetType      = 2,
1038ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett        kBottomLeft_SubsetType  = 3,
1039ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett        kBottomRight_SubsetType = 4,
1040ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett        kTranslate_SubsetType   = 5,
1041ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett        kZoom_SubsetType        = 6,
10427f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        kLast_SubsetType        = kZoom_SubsetType,
10437f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        kLastSingle_SubsetType  = kBottomRight_SubsetType,
1044b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett    };
1045b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett
1046e714e75c725c987fe682a1f5473224fe3e80380dmtklein    const BenchRegistry* fBenches;
1047e714e75c725c987fe682a1f5473224fe3e80380dmtklein    const skiagm::GMRegistry* fGMs;
104892007583e43115998412ac8b0a06cc2780eb025cmtklein    SkIRect            fClip;
104992007583e43115998412ac8b0a06cc2780eb025cmtklein    SkTArray<SkScalar> fScales;
105092007583e43115998412ac8b0a06cc2780eb025cmtklein    SkTArray<SkString> fSKPs;
10515b69377507478623dcf5b11f3ecb010f87c4794frobertphillips    SkTArray<bool>     fUseMPDs;
105295f192d19938b98a45dd1fa4112d965f60d10516msarett    SkTArray<SkString> fImages;
105374deb981d5e9c11c88fe431e78166d6cf8dacc1amsarett    SkTArray<SkColorType, true> fColorTypes;
105463a82855b1f0b83952b65fca330954c50ebe7a4bcdalton    SkScalar           fZoomMax;
105563a82855b1f0b83952b65fca330954c50ebe7a4bcdalton    double             fZoomPeriodMs;
105692007583e43115998412ac8b0a06cc2780eb025cmtklein
1057051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein    double fSKPBytes, fSKPOps;
1058051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein
1059fd731ce804cd3223318f3feee2c98404890b65f2mtklein    const char* fSourceType;  // What we're benching: bench, GM, SKP, ...
1060fd731ce804cd3223318f3feee2c98404890b65f2mtklein    const char* fBenchType;   // How we bench it: micro, recording, playback, ...
1061fd731ce804cd3223318f3feee2c98404890b65f2mtklein    int fCurrentRecording;
106292007583e43115998412ac8b0a06cc2780eb025cmtklein    int fCurrentScale;
106392007583e43115998412ac8b0a06cc2780eb025cmtklein    int fCurrentSKP;
10645b69377507478623dcf5b11f3ecb010f87c4794frobertphillips    int fCurrentUseMPD;
106560869a42a133942f852dd0f1696444c2a5c9ad83scroggo    int fCurrentCodec;
106695f192d19938b98a45dd1fa4112d965f60d10516msarett    int fCurrentImage;
106795f192d19938b98a45dd1fa4112d965f60d10516msarett    int fCurrentSubsetImage;
10687f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett    int fCurrentBRDImage;
106995f192d19938b98a45dd1fa4112d965f60d10516msarett    int fCurrentColorType;
1070b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett    int fCurrentSubsetType;
10717f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett    int fCurrentBRDStrategy;
10727f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett    int fCurrentBRDSampleSize;
1073261c3ad7fde95748da92550735decc949dc73bf2joshualitt    int fCurrentAnimSKP;
1074e714e75c725c987fe682a1f5473224fe3e80380dmtklein};
1075e714e75c725c987fe682a1f5473224fe3e80380dmtklein
10763b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorioint nanobench_main();
107717f0b6df7248b9bbdaddacc3a6c9c6efe4ae278ecaryclarkint nanobench_main() {
10783b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorio    SetupCrashHandler();
1079f372321de3d4183de5b9ca436e677e471e358f31mtklein    SkAutoGraphics ag;
1080cc29d26f5742449eb2a2bafa7bbb6ec5ee701aefmtklein    SkTaskGroup::Enabler enabled(FLAGS_threads);
1081f372321de3d4183de5b9ca436e677e471e358f31mtklein
108269a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski#if SK_SUPPORT_GPU
1083682c269a1511200322916af83053e26004c0ec40bsalomon    GrContextOptions grContextOpts;
108412b3544028e74712c6c095ed3a2e8a78de6b2ed8krajcevski    grContextOpts.fDrawPathToCompressedTexture = FLAGS_gpuCompressAlphaMasks;
1085385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    gGrFactory.reset(new GrContextFactory(grContextOpts));
108669a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski#endif
108769a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski
108806cddec8570cbf29f89e89736afb0487b5b95abdbsalomon    if (FLAGS_veryVerbose) {
108906cddec8570cbf29f89e89736afb0487b5b95abdbsalomon        FLAGS_verbose = true;
109006cddec8570cbf29f89e89736afb0487b5b95abdbsalomon    }
109106cddec8570cbf29f89e89736afb0487b5b95abdbsalomon
10926eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (kAutoTuneLoops != FLAGS_loops) {
1093a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        FLAGS_samples     = 1;
1094a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        FLAGS_gpuFrameLag = 0;
1095a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein    }
1096a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein
10976eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (!FLAGS_writePath.isEmpty()) {
10986eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Writing files to %s.\n", FLAGS_writePath[0]);
10996eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        if (!sk_mkdir(FLAGS_writePath[0])) {
11006eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            SkDebugf("Could not create %s. Files won't be written.\n", FLAGS_writePath[0]);
110196fcdcc219d2a0d3579719b84b28bede76efba64halcanary            FLAGS_writePath.set(0, nullptr);
11026eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        }
11036eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
11046eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
1105385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    SkAutoTDelete<ResultsWriter> log(new ResultsWriter);
110660317d0ffb5053df7b08a627d6decd11b684e80dmtklein    if (!FLAGS_outResultsFile.isEmpty()) {
1107385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        log.reset(new NanoJSONResultsWriter(FLAGS_outResultsFile[0]));
110860317d0ffb5053df7b08a627d6decd11b684e80dmtklein    }
1109bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio
11101915b62637bea20e1471a8a358b22e9e47a4a385mtklein    if (1 == FLAGS_properties.count() % 2) {
11111915b62637bea20e1471a8a358b22e9e47a4a385mtklein        SkDebugf("ERROR: --properties must be passed with an even number of arguments.\n");
1112bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio        return 1;
1113bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    }
11141915b62637bea20e1471a8a358b22e9e47a4a385mtklein    for (int i = 1; i < FLAGS_properties.count(); i += 2) {
11151915b62637bea20e1471a8a358b22e9e47a4a385mtklein        log->property(FLAGS_properties[i-1], FLAGS_properties[i]);
1116bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    }
111794e51567dd691c3e1e8dfa6005a301d72cecf48emtklein
11181915b62637bea20e1471a8a358b22e9e47a4a385mtklein    if (1 == FLAGS_key.count() % 2) {
11191915b62637bea20e1471a8a358b22e9e47a4a385mtklein        SkDebugf("ERROR: --key must be passed with an even number of arguments.\n");
112094e51567dd691c3e1e8dfa6005a301d72cecf48emtklein        return 1;
112194e51567dd691c3e1e8dfa6005a301d72cecf48emtklein    }
11221915b62637bea20e1471a8a358b22e9e47a4a385mtklein    for (int i = 1; i < FLAGS_key.count(); i += 2) {
11231915b62637bea20e1471a8a358b22e9e47a4a385mtklein        log->key(FLAGS_key[i-1], FLAGS_key[i]);
112494e51567dd691c3e1e8dfa6005a301d72cecf48emtklein    }
112560317d0ffb5053df7b08a627d6decd11b684e80dmtklein
1126f372321de3d4183de5b9ca436e677e471e358f31mtklein    const double overhead = estimate_timer_overhead();
112755b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    SkDebugf("Timer overhead: %s\n", HUMANIZE(overhead));
1128912947737a973421f4c58682b6171cb5ee00ad3aMike Klein
1129e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton    SkTArray<double> samples;
1130bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
11316eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (kAutoTuneLoops != FLAGS_loops) {
11326eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Fixed number of loops; times would only be misleading so we won't print them.\n");
1133f372321de3d4183de5b9ca436e677e471e358f31mtklein    } else if (FLAGS_quiet) {
113466cfcffd5d0a430f00bf0e36bedb088a25957183mtklein        SkDebugf("! -> high variance, ? -> moderate variance\n");
113566cfcffd5d0a430f00bf0e36bedb088a25957183mtklein        SkDebugf("    micros   \tbench\n");
1136bbba16878f343b232d844281fbdf056c00e20fb6mtklein    } else if (FLAGS_ms) {
1137e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton        SkDebugf("curr/maxrss\tloops\tmin\tmedian\tmean\tmax\tstddev\tsamples\tconfig\tbench\n");
1138f372321de3d4183de5b9ca436e677e471e358f31mtklein    } else {
1139d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein        SkDebugf("curr/maxrss\tloops\tmin\tmedian\tmean\tmax\tstddev\t%-*s\tconfig\tbench\n",
11408247ec313d87afcdd4da59b1f2f0d24e0983e359qiankun.miao                 FLAGS_samples, "samples");
1141f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
1142f372321de3d4183de5b9ca436e677e471e358f31mtklein
1143c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    SkTDArray<Config> configs;
1144c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    create_configs(&configs);
1145c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
1146e070c2bf54c451f0126d4ffb3a48bffe1fbfa437mtklein    int runs = 0;
114792007583e43115998412ac8b0a06cc2780eb025cmtklein    BenchmarkStream benchStream;
114892007583e43115998412ac8b0a06cc2780eb025cmtklein    while (Benchmark* b = benchStream.next()) {
1149e714e75c725c987fe682a1f5473224fe3e80380dmtklein        SkAutoTDelete<Benchmark> bench(b);
1150962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein        if (SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getUniqueName())) {
1151f372321de3d4183de5b9ca436e677e471e358f31mtklein            continue;
1152f372321de3d4183de5b9ca436e677e471e358f31mtklein        }
1153f372321de3d4183de5b9ca436e677e471e358f31mtklein
11543bf9206ada256277a39988c263f0379d544fc27begdaniel        if (!configs.isEmpty()) {
1155962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein            log->bench(bench->getUniqueName(), bench->getSize().fX, bench->getSize().fY);
11568a6697af95b340aad6dee7e6228048fa305c1e59joshualitt            bench->delayedSetup();
1157bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio        }
11583bf9206ada256277a39988c263f0379d544fc27begdaniel        for (int i = 0; i < configs.count(); ++i) {
11593bf9206ada256277a39988c263f0379d544fc27begdaniel            Target* target = is_enabled(b, configs[i]);
11603bf9206ada256277a39988c263f0379d544fc27begdaniel            if (!target) {
11613bf9206ada256277a39988c263f0379d544fc27begdaniel                continue;
11623bf9206ada256277a39988c263f0379d544fc27begdaniel            }
11633bf9206ada256277a39988c263f0379d544fc27begdaniel
116496fcdcc219d2a0d3579719b84b28bede76efba64halcanary            // During HWUI output this canvas may be nullptr.
11653bf9206ada256277a39988c263f0379d544fc27begdaniel            SkCanvas* canvas = target->getCanvas();
11663bf9206ada256277a39988c263f0379d544fc27begdaniel            const char* config = target->config.name;
1167bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
11683bf9206ada256277a39988c263f0379d544fc27begdaniel            target->setup();
11695b69377507478623dcf5b11f3ecb010f87c4794frobertphillips            bench->perCanvasPreDraw(canvas);
11705b69377507478623dcf5b11f3ecb010f87c4794frobertphillips
1171e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton            int maxFrameLag;
1172a1ebeb25e9acfcd801e089e063311d716b83b8a5mtklein            int loops = target->needsFrameTiming(&maxFrameLag)
11733bf9206ada256277a39988c263f0379d544fc27begdaniel                ? setup_gpu_bench(target, bench.get(), maxFrameLag)
11743bf9206ada256277a39988c263f0379d544fc27begdaniel                : setup_cpu_bench(overhead, target, bench.get());
1175e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton
1176bbba16878f343b232d844281fbdf056c00e20fb6mtklein            if (FLAGS_ms) {
1177bbba16878f343b232d844281fbdf056c00e20fb6mtklein                samples.reset();
1178bbba16878f343b232d844281fbdf056c00e20fb6mtklein                auto stop = now_ms() + FLAGS_ms;
1179bbba16878f343b232d844281fbdf056c00e20fb6mtklein                do {
1180bbba16878f343b232d844281fbdf056c00e20fb6mtklein                    samples.push_back(time(loops, bench, target) / loops);
1181bbba16878f343b232d844281fbdf056c00e20fb6mtklein                } while (now_ms() < stop);
1182bbba16878f343b232d844281fbdf056c00e20fb6mtklein            } else {
1183e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton                samples.reset(FLAGS_samples);
1184e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton                for (int s = 0; s < FLAGS_samples; s++) {
11853bf9206ada256277a39988c263f0379d544fc27begdaniel                    samples[s] = time(loops, bench, target) / loops;
1186e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton                }
1187e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton            }
1188f372321de3d4183de5b9ca436e677e471e358f31mtklein
1189e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt#if SK_SUPPORT_GPU
1190e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt            SkTArray<SkString> keys;
1191e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt            SkTArray<double> values;
1192e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt            bool gpuStatsDump = FLAGS_gpuStatsDump && Benchmark::kGPU_Backend == configs[i].backend;
1193e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt            if (gpuStatsDump) {
1194e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt                // TODO cache stats
1195e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt                bench->getGpuStats(canvas, &keys, &values);
1196e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt            }
1197e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt#endif
1198e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt
11995b69377507478623dcf5b11f3ecb010f87c4794frobertphillips            bench->perCanvasPostDraw(canvas);
12005b69377507478623dcf5b11f3ecb010f87c4794frobertphillips
12013bf9206ada256277a39988c263f0379d544fc27begdaniel            if (Benchmark::kNonRendering_Backend != target->config.backend &&
1202d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson                !FLAGS_writePath.isEmpty() && FLAGS_writePath[0]) {
12036eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                SkString pngFilename = SkOSPath::Join(FLAGS_writePath[0], config);
1204962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein                pngFilename = SkOSPath::Join(pngFilename.c_str(), bench->getUniqueName());
12056eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                pngFilename.append(".png");
12063bf9206ada256277a39988c263f0379d544fc27begdaniel                write_canvas_png(target, pngFilename);
12076eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            }
12086eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
12096eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            if (kFailedLoops == loops) {
12102069e220034f09aad2f68b262f395e7c25b3d178mtklein                // Can't be timed.  A warning note has already been printed.
12113bf9206ada256277a39988c263f0379d544fc27begdaniel                cleanup_run(target);
1212e3631364e93ee9164f3ce322778d5a50c33f63a6Mike Klein                continue;
1213e3631364e93ee9164f3ce322778d5a50c33f63a6Mike Klein            }
121460317d0ffb5053df7b08a627d6decd11b684e80dmtklein
1215e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton            Stats stats(samples);
12161915b62637bea20e1471a8a358b22e9e47a4a385mtklein            log->config(config);
1217962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein            log->configOption("name", bench->getName());
12181915b62637bea20e1471a8a358b22e9e47a4a385mtklein            benchStream.fillCurrentOptions(log.get());
12193bf9206ada256277a39988c263f0379d544fc27begdaniel            target->fillOptions(log.get());
1220051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein            log->metric("min_ms",    stats.min);
1221e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt#if SK_SUPPORT_GPU
1222e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt            if (gpuStatsDump) {
1223e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt                // dump to json, only SKPBench currently returns valid keys / values
1224e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt                SkASSERT(keys.count() == values.count());
1225e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt                for (int i = 0; i < keys.count(); i++) {
1226e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt                    log->metric(keys[i].c_str(), values[i]);
1227e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt                }
1228e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt            }
1229e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt#endif
1230e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt
1231e070c2bf54c451f0126d4ffb3a48bffe1fbfa437mtklein            if (runs++ % FLAGS_flushEvery == 0) {
1232e070c2bf54c451f0126d4ffb3a48bffe1fbfa437mtklein                log->flush();
1233e070c2bf54c451f0126d4ffb3a48bffe1fbfa437mtklein            }
123460317d0ffb5053df7b08a627d6decd11b684e80dmtklein
12356eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            if (kAutoTuneLoops != FLAGS_loops) {
12363bf9206ada256277a39988c263f0379d544fc27begdaniel                if (configs.count() == 1) {
1237a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein                    config = ""; // Only print the config if we run the same bench on more than one.
1238a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein                }
1239d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein                SkDebugf("%4d/%-4dMB\t%s\t%s\n"
1240d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein                         , sk_tools::getCurrResidentSetSizeMB()
1241d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein                         , sk_tools::getMaxResidentSetSizeMB()
124253d2562006ee371222963750009a706cfd1a94f7mtklein                         , bench->getUniqueName()
124353d2562006ee371222963750009a706cfd1a94f7mtklein                         , config);
1244f372321de3d4183de5b9ca436e677e471e358f31mtklein            } else if (FLAGS_quiet) {
124566cfcffd5d0a430f00bf0e36bedb088a25957183mtklein                const char* mark = " ";
124666cfcffd5d0a430f00bf0e36bedb088a25957183mtklein                const double stddev_percent = 100 * sqrt(stats.var) / stats.mean;
124766cfcffd5d0a430f00bf0e36bedb088a25957183mtklein                if (stddev_percent >  5) mark = "?";
124866cfcffd5d0a430f00bf0e36bedb088a25957183mtklein                if (stddev_percent > 10) mark = "!";
124966cfcffd5d0a430f00bf0e36bedb088a25957183mtklein
125066cfcffd5d0a430f00bf0e36bedb088a25957183mtklein                SkDebugf("%10.2f %s\t%s\t%s\n",
125166cfcffd5d0a430f00bf0e36bedb088a25957183mtklein                         stats.median*1e3, mark, bench->getUniqueName(), config);
1252f372321de3d4183de5b9ca436e677e471e358f31mtklein            } else {
1253f372321de3d4183de5b9ca436e677e471e358f31mtklein                const double stddev_percent = 100 * sqrt(stats.var) / stats.mean;
1254d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein                SkDebugf("%4d/%-4dMB\t%d\t%s\t%s\t%s\t%s\t%.0f%%\t%s\t%s\t%s\n"
1255d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein                        , sk_tools::getCurrResidentSetSizeMB()
1256d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein                        , sk_tools::getMaxResidentSetSizeMB()
1257f372321de3d4183de5b9ca436e677e471e358f31mtklein                        , loops
125855b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein                        , HUMANIZE(stats.min)
125955b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein                        , HUMANIZE(stats.median)
126055b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein                        , HUMANIZE(stats.mean)
126155b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein                        , HUMANIZE(stats.max)
1262f372321de3d4183de5b9ca436e677e471e358f31mtklein                        , stddev_percent
1263bbba16878f343b232d844281fbdf056c00e20fb6mtklein                        , FLAGS_ms ? to_string(samples.count()).c_str() : stats.plot.c_str()
1264f372321de3d4183de5b9ca436e677e471e358f31mtklein                        , config
1265962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein                        , bench->getUniqueName()
1266f372321de3d4183de5b9ca436e677e471e358f31mtklein                        );
1267f372321de3d4183de5b9ca436e677e471e358f31mtklein            }
1268e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt
1269b12ea41286ce36e085c5a14711da0cf9f240fdf1bsalomon#if SK_SUPPORT_GPU
1270e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt            if (FLAGS_gpuStats && Benchmark::kGPU_Backend == configs[i].backend) {
1271a0a024e323ebf73ea4559d4b29f937902703828bbsalomon                gGrFactory->get(configs[i].ctxType)->printCacheStats();
1272a0a024e323ebf73ea4559d4b29f937902703828bbsalomon                gGrFactory->get(configs[i].ctxType)->printGpuStats();
127306cddec8570cbf29f89e89736afb0487b5b95abdbsalomon            }
127406cddec8570cbf29f89e89736afb0487b5b95abdbsalomon#endif
1275e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt
12762c56ba5cde25a5cdbeca2afd660b497b428e8f07cdalton            if (FLAGS_verbose) {
12772c56ba5cde25a5cdbeca2afd660b497b428e8f07cdalton                SkDebugf("Samples:  ");
12782c56ba5cde25a5cdbeca2afd660b497b428e8f07cdalton                for (int i = 0; i < samples.count(); i++) {
12792c56ba5cde25a5cdbeca2afd660b497b428e8f07cdalton                    SkDebugf("%s  ", HUMANIZE(samples[i]));
12802c56ba5cde25a5cdbeca2afd660b497b428e8f07cdalton                }
12812c56ba5cde25a5cdbeca2afd660b497b428e8f07cdalton                SkDebugf("%s\n", bench->getUniqueName());
12822c56ba5cde25a5cdbeca2afd660b497b428e8f07cdalton            }
12833bf9206ada256277a39988c263f0379d544fc27begdaniel            cleanup_run(target);
1284f372321de3d4183de5b9ca436e677e471e358f31mtklein        }
1285f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
1286f372321de3d4183de5b9ca436e677e471e358f31mtklein
1287e109145bf31d63963b3f78c6af6e404d5464a55bmtklein    log->bench("memory_usage", 0,0);
1288e109145bf31d63963b3f78c6af6e404d5464a55bmtklein    log->config("meta");
1289e109145bf31d63963b3f78c6af6e404d5464a55bmtklein    log->metric("max_rss_mb", sk_tools::getMaxResidentSetSizeMB());
1290e109145bf31d63963b3f78c6af6e404d5464a55bmtklein
1291e0b19d4985846d64bb581013828a9dc5af401a5djoshualitt#if SK_SUPPORT_GPU
1292e0b19d4985846d64bb581013828a9dc5af401a5djoshualitt    // Make sure we clean up the global GrContextFactory here, otherwise we might race with the
1293e0b19d4985846d64bb581013828a9dc5af401a5djoshualitt    // SkEventTracer destructor
129496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    gGrFactory.reset(nullptr);
1295e0b19d4985846d64bb581013828a9dc5af401a5djoshualitt#endif
1296e0b19d4985846d64bb581013828a9dc5af401a5djoshualitt
1297f372321de3d4183de5b9ca436e677e471e358f31mtklein    return 0;
1298f372321de3d4183de5b9ca436e677e471e358f31mtklein}
1299f372321de3d4183de5b9ca436e677e471e358f31mtklein
13003b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorio#if !defined SK_BUILD_FOR_IOS
13013b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorioint main(int argc, char** argv) {
13023b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorio    SkCommandLineFlags::Parse(argc, argv);
13033b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorio    return nanobench_main();
13043b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorio}
13053b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorio#endif
1306