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
1284451024bfe06d138629dd7c27cf2ec0f9774dbemsarett#include "AndroidCodecBench.h"
13f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "Benchmark.h"
147f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett#include "BitmapRegionDecoderBench.h"
1560869a42a133942f852dd0f1696444c2a5c9ad83scroggo#include "CodecBench.h"
167f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett#include "CodecBenchPriv.h"
17f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "CrashHandler.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"
24f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "Stats.h"
25f372321de3d4183de5b9ca436e677e471e358f31mtklein
2684451024bfe06d138629dd7c27cf2ec0f9774dbemsarett#include "SkAndroidCodec.h"
275cb4885b4cd1ac5eb3fc92dac5f5509d7c810464msarett#include "SkBitmapRegionDecoder.h"
286838d854a87e79f1fbb7b89b9f395155ad44dc0amtklein#include "SkBBoxHierarchy.h"
29f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "SkCanvas.h"
3060869a42a133942f852dd0f1696444c2a5c9ad83scroggo#include "SkCodec.h"
3117f0b6df7248b9bbdaddacc3a6c9c6efe4ae278ecaryclark#include "SkCommonFlags.h"
323e980c3d88fbc509b79e7ccef16ca38f5bbfb180kkinnunen#include "SkCommonFlagsConfig.h"
3395f192d19938b98a45dd1fa4112d965f60d10516msarett#include "SkData.h"
34f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "SkForceLinking.h"
35f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "SkGraphics.h"
362084050a33ae139d0fe9bb680f7905f91139a39fmtklein#include "SkOSFile.h"
372084050a33ae139d0fe9bb680f7905f91139a39fmtklein#include "SkPictureRecorder.h"
38051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein#include "SkPictureUtils.h"
39f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "SkString.h"
40f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "SkSurface.h"
415b69377507478623dcf5b11f3ecb010f87c4794frobertphillips#include "SkTaskGroup.h"
42c149f0e36e0ca0ff35ec6e2f79419b58d529db40msarett#include "SkThreadUtils.h"
433ebd050be551e9d1364dbd115708e8f86397cd6fjoshualitt#include "ThermalManager.h"
44f372321de3d4183de5b9ca436e677e471e358f31mtklein
4560e0fee6d4acff638ccc9670c4055aced529a7a0bungeman#include <stdlib.h>
4660e0fee6d4acff638ccc9670c4055aced529a7a0bungeman
4738ce0a7fe93444aa9184f1492656ceefdd75e74bscroggo#ifndef SK_BUILD_FOR_WIN32
4838ce0a7fe93444aa9184f1492656ceefdd75e74bscroggo    #include <unistd.h>
4938ce0a7fe93444aa9184f1492656ceefdd75e74bscroggo#endif
5038ce0a7fe93444aa9184f1492656ceefdd75e74bscroggo
51d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
52d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    #include "nanobenchAndroid.h"
53d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson#endif
54d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
55bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#if SK_SUPPORT_GPU
56bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    #include "gl/GrGLDefines.h"
57762286309545c8a1e4bbc05dcd1fe3085d2a1f47bsalomon    #include "GrCaps.h"
58bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    #include "GrContextFactory.h"
5969a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski    SkAutoTDelete<GrContextFactory> gGrFactory;
60bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#endif
61bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
62682c269a1511200322916af83053e26004c0ec40bsalomon    struct GrContextOptions;
63682c269a1511200322916af83053e26004c0ec40bsalomon
64f372321de3d4183de5b9ca436e677e471e358f31mtklein__SK_FORCE_IMAGE_DECODER_LINKING;
65f372321de3d4183de5b9ca436e677e471e358f31mtklein
665324978a88677ac6b758324321816427814e7793reedstatic const int kAutoTuneLoops = 0;
676eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
68b511042bb07a6a289b0d1146cb57f6e8b80580d6mtkleinstatic const int kDefaultLoops =
696eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon#ifdef SK_DEBUG
706eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    1;
71a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein#else
726eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    kAutoTuneLoops;
73a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein#endif
74a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein
756eb03cc06d0bc60da5277a83aa0251a475794b04bsalomonstatic SkString loops_help_txt() {
766eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    SkString help;
776eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    help.printf("Number of times to run each bench. Set this to %d to auto-"
786eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                "tune for each bench. Timings are only reported when auto-tuning.",
796eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                kAutoTuneLoops);
806eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    return help;
816eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon}
826eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
83e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdaltonstatic SkString to_string(int n) {
84e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton    SkString str;
85e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton    str.appendS32(n);
86e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton    return str;
87e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton}
88e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton
896eb03cc06d0bc60da5277a83aa0251a475794b04bsalomonDEFINE_int32(loops, kDefaultLoops, loops_help_txt().c_str());
906eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
91f372321de3d4183de5b9ca436e677e471e358f31mtkleinDEFINE_int32(samples, 10, "Number of samples to measure for each bench.");
92bbba16878f343b232d844281fbdf056c00e20fb6mtkleinDEFINE_int32(ms, 0, "If >0, run each bench for this many ms instead of obeying --samples.");
93f372321de3d4183de5b9ca436e677e471e358f31mtkleinDEFINE_int32(overheadLoops, 100000, "Loops to estimate timer overhead.");
94f372321de3d4183de5b9ca436e677e471e358f31mtkleinDEFINE_double(overheadGoal, 0.0001,
95f372321de3d4183de5b9ca436e677e471e358f31mtklein              "Loop until timer overhead is at most this fraction of our measurments.");
96bb6a02823929584231c8e080ee69e7fb1178cbfbmtkleinDEFINE_double(gpuMs, 5, "Target bench time in millseconds for GPU.");
97d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdaltonDEFINE_int32(gpuFrameLag, 5, "If unknown, estimated maximum number of frames GPU allows to lag.");
9812b3544028e74712c6c095ed3a2e8a78de6b2ed8krajcevskiDEFINE_bool(gpuCompressAlphaMasks, false, "Compress masks generated from falling back to "
9912b3544028e74712c6c095ed3a2e8a78de6b2ed8krajcevski                                          "software path rendering.");
100f372321de3d4183de5b9ca436e677e471e358f31mtklein
10160317d0ffb5053df7b08a627d6decd11b684e80dmtkleinDEFINE_string(outResultsFile, "", "If given, write results here as JSON.");
10255b0ffc4861e940d8bcf767ff9abf44ff18545eamtkleinDEFINE_int32(maxCalibrationAttempts, 3,
10355b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein             "Try up to this many times to guess loops for a bench, or skip the bench.");
10455b0ffc4861e940d8bcf767ff9abf44ff18545eamtkleinDEFINE_int32(maxLoops, 1000000, "Never run a bench more times than this.");
10592007583e43115998412ac8b0a06cc2780eb025cmtkleinDEFINE_string(clip, "0,0,1000,1000", "Clip for SKPs.");
10692007583e43115998412ac8b0a06cc2780eb025cmtkleinDEFINE_string(scales, "1.0", "Space-separated scales for SKPs.");
10763a82855b1f0b83952b65fca330954c50ebe7a4bcdaltonDEFINE_string(zoom, "1.0,0", "Comma-separated zoomMax,zoomPeriodMs factors for a periodic SKP zoom "
10863a82855b1f0b83952b65fca330954c50ebe7a4bcdalton                             "function that ping-pongs between 1.0 and zoomMax.");
1092084050a33ae139d0fe9bb680f7905f91139a39fmtkleinDEFINE_bool(bbh, true, "Build a BBH for SKPs?");
1105b69377507478623dcf5b11f3ecb010f87c4794frobertphillipsDEFINE_bool(mpd, true, "Use MultiPictureDraw for the SKPs?");
111b4022965a280dd1ed64d6103dd29e2189abe6e00cdaltonDEFINE_bool(loopSKP, true, "Loop SKPs like we do for micro benches?");
112e070c2bf54c451f0126d4ffb3a48bffe1fbfa437mtkleinDEFINE_int32(flushEvery, 10, "Flush --outResultsFile every Nth run.");
11355e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtkleinDEFINE_bool(resetGpuContext, true, "Reset the GrContext before running each test.");
114b12ea41286ce36e085c5a14711da0cf9f240fdf1bsalomonDEFINE_bool(gpuStats, false, "Print GPU stats after each gpu benchmark?");
115e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualittDEFINE_bool(gpuStatsDump, false, "Dump GPU states after each benchmark to json");
116c149f0e36e0ca0ff35ec6e2f79419b58d529db40msarettDEFINE_bool(keepAlive, false, "Print a message every so often so that we don't time out");
1173ebd050be551e9d1364dbd115708e8f86397cd6fjoshualittDEFINE_string(useThermalManager, "0,1,10,1000", "enabled,threshold,sleepTimeMs,TimeoutMs for "
1183ebd050be551e9d1364dbd115708e8f86397cd6fjoshualitt                                                "thermalManager\n");
11992007583e43115998412ac8b0a06cc2780eb025cmtklein
12065dfd2fe5d93d63b655663707c7233917e293accmtkleinDEFINE_string(sourceType, "",
12165dfd2fe5d93d63b655663707c7233917e293accmtklein        "Apply usual --match rules to source type: bench, gm, skp, image, etc.");
12265dfd2fe5d93d63b655663707c7233917e293accmtkleinDEFINE_string(benchType,  "",
12365dfd2fe5d93d63b655663707c7233917e293accmtklein        "Apply usual --match rules to bench type: micro, recording, playback, skcodec, etc.");
12465dfd2fe5d93d63b655663707c7233917e293accmtklein
125bbba16878f343b232d844281fbdf056c00e20fb6mtkleinstatic double now_ms() { return SkTime::GetNSecs() * 1e-6; }
126bbba16878f343b232d844281fbdf056c00e20fb6mtklein
127f372321de3d4183de5b9ca436e677e471e358f31mtkleinstatic SkString humanize(double ms) {
128dc5bbab138bfffc85d6ba525d990aad09c322ff6mtklein    if (FLAGS_verbose) return SkStringPrintf("%llu", (uint64_t)(ms*1e6));
129748ca3bf2d170708f263693e8579e6722389d0efmtklein    return HumanizeMs(ms);
130f372321de3d4183de5b9ca436e677e471e358f31mtklein}
13155b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein#define HUMANIZE(ms) humanize(ms).c_str()
132f372321de3d4183de5b9ca436e677e471e358f31mtklein
133d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudsonbool Target::init(SkImageInfo info, Benchmark* bench) {
134d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    if (Benchmark::kRaster_Backend == config.backend) {
135d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        this->surface.reset(SkSurface::NewRaster(info));
136d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        if (!this->surface.get()) {
137d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson            return false;
138d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        }
139d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
140d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    return true;
141d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson}
142d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudsonbool Target::capturePixels(SkBitmap* bmp) {
14375a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson    SkCanvas* canvas = this->getCanvas();
144d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    if (!canvas) {
145d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        return false;
146d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
147d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    bmp->setInfo(canvas->imageInfo());
148d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    if (!canvas->readPixels(bmp, 0, 0)) {
149d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        SkDebugf("Can't read canvas pixels.\n");
150d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        return false;
151d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
152d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    return true;
153d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson}
154d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
155d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson#if SK_SUPPORT_GPU
156d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudsonstruct GPUTarget : public Target {
15796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    explicit GPUTarget(const Config& c) : Target(c), gl(nullptr) { }
158d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    SkGLContext* gl;
159d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
160d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    void setup() override {
161d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        this->gl->makeCurrent();
162d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        // Make sure we're done with whatever came before.
163d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        SK_GL(*this->gl, Finish());
164d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
165d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    void endTiming() override {
166d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        if (this->gl) {
167d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson            SK_GL(*this->gl, Flush());
16801836add2ab778ed085735fa8a206b54d5fc4f23joshualitt            this->gl->waitOnSyncOrSwap();
169d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        }
170d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
171d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    void fence() override {
172d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        SK_GL(*this->gl, Finish());
173d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
174d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein
175d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton    bool needsFrameTiming(int* maxFrameLag) const override {
176d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton        if (!this->gl->getMaxGpuFrameLag(maxFrameLag)) {
177d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton            // Frame lag is unknown.
178d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton            *maxFrameLag = FLAGS_gpuFrameLag;
179d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton        }
180d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton        return true;
181d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton    }
182d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    bool init(SkImageInfo info, Benchmark* bench) override {
183afcd7cd32497cc79035e61fd64b0baa03ed04bccbsalomon        uint32_t flags = this->config.useDFText ? SkSurfaceProps::kUseDeviceIndependentFonts_Flag :
184afcd7cd32497cc79035e61fd64b0baa03ed04bccbsalomon                                                  0;
185d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType);
1865219fd9ff7aa6ebf64c905ad40f5e0027a39962bkkinnunen        this->surface.reset(SkSurface::NewRenderTarget(gGrFactory->get(this->config.ctxType,
1875219fd9ff7aa6ebf64c905ad40f5e0027a39962bkkinnunen                                                                       this->config.ctxOptions),
1885ec26ae9bfca635ccc98283aad5deda11519d826bsalomon                                                         SkBudgeted::kNo, info,
189d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson                                                         this->config.samples, &props));
1903e980c3d88fbc509b79e7ccef16ca38f5bbfb180kkinnunen        this->gl = gGrFactory->getContextInfo(this->config.ctxType,
1913405800d7a5407365143eed93e300fd5896caceekkinnunen                                              this->config.ctxOptions).fGLContext;
192d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        if (!this->surface.get()) {
193d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson            return false;
194d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        }
195d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton        if (!this->gl->fenceSyncSupport()) {
196d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton            SkDebugf("WARNING: GL context for config \"%s\" does not support fence sync. "
197c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen                     "Timings might not be accurate.\n", this->config.name.c_str());
198d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton        }
199d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        return true;
200d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
201d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    void fillOptions(ResultsWriter* log) override {
202d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        const GrGLubyte* version;
203d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        SK_GL_RET(*this->gl, version, GetString(GR_GL_VERSION));
204d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        log->configOption("GL_VERSION", (const char*)(version));
205d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
206d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        SK_GL_RET(*this->gl, version, GetString(GR_GL_RENDERER));
207d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        log->configOption("GL_RENDERER", (const char*) version);
208d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
209d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        SK_GL_RET(*this->gl, version, GetString(GR_GL_VENDOR));
210d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        log->configOption("GL_VENDOR", (const char*) version);
211d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
212d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        SK_GL_RET(*this->gl, version, GetString(GR_GL_SHADING_LANGUAGE_VERSION));
213d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        log->configOption("GL_SHADING_LANGUAGE_VERSION", (const char*) version);
214d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
215d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson};
216d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein
217d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson#endif
218d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
21975a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudsonstatic double time(int loops, Benchmark* bench, Target* target) {
22075a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson    SkCanvas* canvas = target->getCanvas();
2216eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (canvas) {
2226eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        canvas->clear(SK_ColorWHITE);
2236eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
2248a6697af95b340aad6dee7e6228048fa305c1e59joshualitt    bench->preDraw(canvas);
225bbba16878f343b232d844281fbdf056c00e20fb6mtklein    double start = now_ms();
22675a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson    canvas = target->beginTiming(canvas);
22775a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson    bench->draw(loops, canvas);
228f372321de3d4183de5b9ca436e677e471e358f31mtklein    if (canvas) {
229f372321de3d4183de5b9ca436e677e471e358f31mtklein        canvas->flush();
230f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
23175a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson    target->endTiming();
232bbba16878f343b232d844281fbdf056c00e20fb6mtklein    double elapsed = now_ms() - start;
2338a6697af95b340aad6dee7e6228048fa305c1e59joshualitt    bench->postDraw(canvas);
234bbba16878f343b232d844281fbdf056c00e20fb6mtklein    return elapsed;
235f372321de3d4183de5b9ca436e677e471e358f31mtklein}
236f372321de3d4183de5b9ca436e677e471e358f31mtklein
237bb6a02823929584231c8e080ee69e7fb1178cbfbmtkleinstatic double estimate_timer_overhead() {
238bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    double overhead = 0;
239bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    for (int i = 0; i < FLAGS_overheadLoops; i++) {
240bbba16878f343b232d844281fbdf056c00e20fb6mtklein        double start = now_ms();
241bbba16878f343b232d844281fbdf056c00e20fb6mtklein        overhead += now_ms() - start;
242bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    }
243bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    return overhead / FLAGS_overheadLoops;
244bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein}
245f372321de3d4183de5b9ca436e677e471e358f31mtklein
2465324978a88677ac6b758324321816427814e7793reedstatic int detect_forever_loops(int loops) {
2475324978a88677ac6b758324321816427814e7793reed    // look for a magic run-forever value
2485324978a88677ac6b758324321816427814e7793reed    if (loops < 0) {
2495324978a88677ac6b758324321816427814e7793reed        loops = SK_MaxS32;
2505324978a88677ac6b758324321816427814e7793reed    }
2515324978a88677ac6b758324321816427814e7793reed    return loops;
2525324978a88677ac6b758324321816427814e7793reed}
2535324978a88677ac6b758324321816427814e7793reed
25455b0ffc4861e940d8bcf767ff9abf44ff18545eamtkleinstatic int clamp_loops(int loops) {
25555b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    if (loops < 1) {
256527930fdbbba2a20f98b43821c6b72367e7b2d64mtklein        SkDebugf("ERROR: clamping loops from %d to 1. "
257527930fdbbba2a20f98b43821c6b72367e7b2d64mtklein                 "There's probably something wrong with the bench.\n", loops);
25855b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein        return 1;
25955b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    }
26055b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    if (loops > FLAGS_maxLoops) {
26155b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein        SkDebugf("WARNING: clamping loops from %d to FLAGS_maxLoops, %d.\n", loops, FLAGS_maxLoops);
26255b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein        return FLAGS_maxLoops;
26355b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    }
26455b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    return loops;
26555b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein}
26655b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein
267d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudsonstatic bool write_canvas_png(Target* target, const SkString& filename) {
268d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
2696eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (filename.isEmpty()) {
2706eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
2716eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
27275a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson    if (target->getCanvas() &&
27375a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson        kUnknown_SkColorType == target->getCanvas()->imageInfo().colorType()) {
2746eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
2756eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
276d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
2776eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    SkBitmap bmp;
278d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
279d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    if (!target->capturePixels(&bmp)) {
2806eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
2816eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
282d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
2836eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    SkString dir = SkOSPath::Dirname(filename.c_str());
2846eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (!sk_mkdir(dir.c_str())) {
2856eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Can't make dir %s.\n", dir.c_str());
2866eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
2876eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
2886eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    SkFILEWStream stream(filename.c_str());
2896eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (!stream.isValid()) {
2906eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Can't write %s.\n", filename.c_str());
2916eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
2926eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
2936eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (!SkImageEncoder::EncodeStream(&stream, bmp, SkImageEncoder::kPNG_Type, 100)) {
2946eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Can't encode a PNG.\n");
2956eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
2966eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
2976eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    return true;
2986eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon}
2996eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
3006eb03cc06d0bc60da5277a83aa0251a475794b04bsalomonstatic int kFailedLoops = -2;
301e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdaltonstatic int setup_cpu_bench(const double overhead, Target* target, Benchmark* bench) {
302bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // First figure out approximately how many loops of bench it takes to make overhead negligible.
3032069e220034f09aad2f68b262f395e7c25b3d178mtklein    double bench_plus_overhead = 0.0;
30455b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    int round = 0;
305b4022965a280dd1ed64d6103dd29e2189abe6e00cdalton    int loops = bench->calculateLoops(FLAGS_loops);
306b4022965a280dd1ed64d6103dd29e2189abe6e00cdalton    if (kAutoTuneLoops == loops) {
3076eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        while (bench_plus_overhead < overhead) {
3086eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            if (round++ == FLAGS_maxCalibrationAttempts) {
3096eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                SkDebugf("WARNING: Can't estimate loops for %s (%s vs. %s); skipping.\n",
310962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein                         bench->getUniqueName(), HUMANIZE(bench_plus_overhead), HUMANIZE(overhead));
3116eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                return kFailedLoops;
3126eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            }
31375a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson            bench_plus_overhead = time(1, bench, target);
31455b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein        }
3152069e220034f09aad2f68b262f395e7c25b3d178mtklein    }
316f372321de3d4183de5b9ca436e677e471e358f31mtklein
317bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // Later we'll just start and stop the timer once but loop N times.
318f372321de3d4183de5b9ca436e677e471e358f31mtklein    // We'll pick N to make timer overhead negligible:
319f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
320bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //          overhead
321bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //  -------------------------  < FLAGS_overheadGoal
322bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //  overhead + N * Bench Time
323f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
324bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // where bench_plus_overhead ≈ overhead + Bench Time.
325f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
326f372321de3d4183de5b9ca436e677e471e358f31mtklein    // Doing some math, we get:
327f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
328bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //  (overhead / FLAGS_overheadGoal) - overhead
329bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //  ------------------------------------------  < N
330bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //       bench_plus_overhead - overhead)
331f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
332f372321de3d4183de5b9ca436e677e471e358f31mtklein    // Luckily, this also works well in practice. :)
3336eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (kAutoTuneLoops == loops) {
3346eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        const double numer = overhead / FLAGS_overheadGoal - overhead;
3356eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        const double denom = bench_plus_overhead - overhead;
3366eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        loops = (int)ceil(numer / denom);
3375324978a88677ac6b758324321816427814e7793reed        loops = clamp_loops(loops);
3385324978a88677ac6b758324321816427814e7793reed    } else {
3395324978a88677ac6b758324321816427814e7793reed        loops = detect_forever_loops(loops);
3406eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
341bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
342bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    return loops;
343f372321de3d4183de5b9ca436e677e471e358f31mtklein}
344f372321de3d4183de5b9ca436e677e471e358f31mtklein
345e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdaltonstatic int setup_gpu_bench(Target* target, Benchmark* bench, int maxGpuFrameLag) {
346bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // First, figure out how many loops it'll take to get a frame up to FLAGS_gpuMs.
347b4022965a280dd1ed64d6103dd29e2189abe6e00cdalton    int loops = bench->calculateLoops(FLAGS_loops);
3486eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (kAutoTuneLoops == loops) {
3496eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        loops = 1;
350a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        double elapsed = 0;
351a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        do {
352527930fdbbba2a20f98b43821c6b72367e7b2d64mtklein            if (1<<30 == loops) {
353527930fdbbba2a20f98b43821c6b72367e7b2d64mtklein                // We're about to wrap.  Something's wrong with the bench.
354527930fdbbba2a20f98b43821c6b72367e7b2d64mtklein                loops = 0;
355527930fdbbba2a20f98b43821c6b72367e7b2d64mtklein                break;
356527930fdbbba2a20f98b43821c6b72367e7b2d64mtklein            }
357a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            loops *= 2;
358a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            // If the GPU lets frames lag at all, we need to make sure we're timing
359d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton            // _this_ round, not still timing last round.
360d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton            for (int i = 0; i < maxGpuFrameLag; i++) {
36175a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson                elapsed = time(loops, bench, target);
362a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            }
363a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        } while (elapsed < FLAGS_gpuMs);
364a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein
365a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        // We've overshot at least a little.  Scale back linearly.
366a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        loops = (int)ceil(loops * FLAGS_gpuMs / elapsed);
3675324978a88677ac6b758324321816427814e7793reed        loops = clamp_loops(loops);
368a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein
369d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        // Make sure we're not still timing our calibration.
370d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        target->fence();
3715324978a88677ac6b758324321816427814e7793reed    } else {
3725324978a88677ac6b758324321816427814e7793reed        loops = detect_forever_loops(loops);
373a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein    }
374bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
375bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // Pretty much the same deal as the calibration: do some warmup to make
376bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // sure we're timing steady-state pipelined frames.
377d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton    for (int i = 0; i < maxGpuFrameLag - 1; i++) {
37875a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson        time(loops, bench, target);
379f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
380bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
381bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    return loops;
382f372321de3d4183de5b9ca436e677e471e358f31mtklein}
383bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
384c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#if SK_SUPPORT_GPU
385c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#define kBogusGLContextType GrContextFactory::kNative_GLContextType
3865219fd9ff7aa6ebf64c905ad40f5e0027a39962bkkinnunen#define kBogusGLContextOptions GrContextFactory::kNone_GLContextOptions
387c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#else
388c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#define kBogusGLContextType 0
3895219fd9ff7aa6ebf64c905ad40f5e0027a39962bkkinnunen#define kBogusGLContextOptions 0
390e714e75c725c987fe682a1f5473224fe3e80380dmtklein#endif
391c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
392c47635e0ed52970fa40a16ffb280071e6b838a52svaisanenstatic void create_config(const SkCommandLineConfig* config, SkTArray<Config>* configs) {
393c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen
394c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen#if SK_SUPPORT_GPU
395c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen    if (const auto* gpuConfig = config->asConfigGpu()) {
396c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen        if (!FLAGS_gpu)
397c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen            return;
398c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen
399c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen        const auto ctxOptions = gpuConfig->getUseNVPR() ? GrContextFactory::kEnableNVPR_GLContextOptions
400c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen                                                        : GrContextFactory::kNone_GLContextOptions;
401c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen        const auto ctxType = gpuConfig->getContextType();
402c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen        const auto sampleCount = gpuConfig->getSamples();
403c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen
404c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen        if (const GrContext* ctx = gGrFactory->get(ctxType, ctxOptions)) {
405c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen            const auto maxSampleCount = ctx->caps()->maxSampleCount();
406c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen            if (sampleCount > ctx->caps()->maxSampleCount()) {
407c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen                SkDebugf("Configuration sample count %d exceeds maximum %d.\n",
408c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen                    sampleCount, maxSampleCount);
409c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen                return;
410c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen            }
411c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen        } else {
412c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen            SkDebugf("No context was available matching config type and options.\n");
413c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen            return;
414c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen        }
415c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen
416c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen        Config target = {
417c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen            config->getTag(),
418c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen            Benchmark::kGPU_Backend,
419c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen            kN32_SkColorType,
420c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen            kPremul_SkAlphaType,
421c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen            sampleCount,
422c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen            ctxType,
423c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen            ctxOptions,
424c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen            false };
425c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen
426c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen        configs->push_back(target);
427c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen        return;
428c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen    }
429c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen#endif
430c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen
431c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen    #define CPU_CONFIG(name, backend, color, alpha)                                  \
432c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen        if (config->getTag().equals(#name)) {                                        \
433c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen            Config config = { SkString(#name), Benchmark::backend, color, alpha, 0,  \
434c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen                              kBogusGLContextType, kBogusGLContextOptions,           \
435c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen                              false };                                               \
436c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen            configs->push_back(config);                                              \
437c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen            return;                                                                  \
438f372321de3d4183de5b9ca436e677e471e358f31mtklein        }
439e714e75c725c987fe682a1f5473224fe3e80380dmtklein
44040b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein    if (FLAGS_cpu) {
441c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        CPU_CONFIG(nonrendering, kNonRendering_Backend, kUnknown_SkColorType, kUnpremul_SkAlphaType)
442c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        CPU_CONFIG(8888, kRaster_Backend, kN32_SkColorType, kPremul_SkAlphaType)
443c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        CPU_CONFIG(565, kRaster_Backend, kRGB_565_SkColorType, kOpaque_SkAlphaType)
44440b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein    }
445f372321de3d4183de5b9ca436e677e471e358f31mtklein
446c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen    #undef CPU_CONFIG
447d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
448d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
449817c72ad40bfbb42824010837c0bcc572a9eb9bcdjsollen    if (config->getTag().equals("hwui")) {
450817c72ad40bfbb42824010837c0bcc572a9eb9bcdjsollen        Config config = { SkString("hwui"), Benchmark::kHWUI_Backend, kRGBA_8888_SkColorType,
4515219fd9ff7aa6ebf64c905ad40f5e0027a39962bkkinnunen                          kPremul_SkAlphaType, 0, kBogusGLContextType, kBogusGLContextOptions,
4525219fd9ff7aa6ebf64c905ad40f5e0027a39962bkkinnunen                          false };
453c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen        configs->push_back(config);
454d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
455d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson#endif
456f372321de3d4183de5b9ca436e677e471e358f31mtklein}
457f372321de3d4183de5b9ca436e677e471e358f31mtklein
458c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen// Append all configs that are enabled and supported.
459c47635e0ed52970fa40a16ffb280071e6b838a52svaisanenvoid create_configs(SkTArray<Config>* configs) {
460c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen    SkCommandLineConfigArray array;
461c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen    ParseConfigs(FLAGS_config, &array);
462c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen    for (int i = 0; i < array.count(); ++i) {
463c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen        create_config(array[i], configs);
464c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen    }
465c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen}
466c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen
46796fcdcc219d2a0d3579719b84b28bede76efba64halcanary// If bench is enabled for config, returns a Target* for it, otherwise nullptr.
468c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstatic Target* is_enabled(Benchmark* bench, const Config& config) {
469c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    if (!bench->isSuitableFor(config.backend)) {
47096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
471c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
472c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
473e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    SkImageInfo info = SkImageInfo::Make(bench->getSize().fX, bench->getSize().fY,
474e5ea500d4714a7d84de2bf913e81be3b65d2de68reed                                         config.color, config.alpha);
475c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
47696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    Target* target = nullptr;
477c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
478d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    switch (config.backend) {
479c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#if SK_SUPPORT_GPU
480d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    case Benchmark::kGPU_Backend:
481d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        target = new GPUTarget(config);
482d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        break;
483d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson#endif
484d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
485d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    case Benchmark::kHWUI_Backend:
486d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        target = new HWUITarget(config, bench);
487d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        break;
488c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#endif
489d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    default:
490d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        target = new Target(config);
491d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        break;
492d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
493c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
494d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    if (!target->init(info, bench)) {
495c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        delete target;
49696fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
497c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
498c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    return target;
499c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon}
500c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
5015cb4885b4cd1ac5eb3fc92dac5f5509d7c810464msarettstatic bool valid_brd_bench(SkData* encoded, SkBitmapRegionDecoder::Strategy strategy,
5027f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        SkColorType colorType, uint32_t sampleSize, uint32_t minOutputSize, int* width,
5037f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        int* height) {
5045cb4885b4cd1ac5eb3fc92dac5f5509d7c810464msarett    SkAutoTDelete<SkBitmapRegionDecoder> brd(
5055cb4885b4cd1ac5eb3fc92dac5f5509d7c810464msarett            SkBitmapRegionDecoder::Create(encoded, strategy));
5067f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett    if (nullptr == brd.get()) {
5077f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // This is indicates that subset decoding is not supported for a particular image format.
5087f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        return false;
5097f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett    }
5107f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett
51135e5d1b4495478ca3bede66914ae07f50a447c4dmsarett    SkBitmap bitmap;
51235e5d1b4495478ca3bede66914ae07f50a447c4dmsarett    if (!brd->decodeRegion(&bitmap, nullptr, SkIRect::MakeXYWH(0, 0, brd->width(), brd->height()),
51335e5d1b4495478ca3bede66914ae07f50a447c4dmsarett            1, colorType, false)) {
51435e5d1b4495478ca3bede66914ae07f50a447c4dmsarett        return false;
51535e5d1b4495478ca3bede66914ae07f50a447c4dmsarett    }
5167f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett
5177f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett    if (sampleSize * minOutputSize > (uint32_t) brd->width() || sampleSize * minOutputSize >
5187f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett            (uint32_t) brd->height()) {
5197f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // This indicates that the image is not large enough to decode a
5207f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // minOutputSize x minOutputSize subset at the given sampleSize.
5217f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        return false;
5227f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett    }
5237f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett
5247f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett    // Set the image width and height.  The calling code will use this to choose subsets to decode.
5257f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett    *width = brd->width();
5267f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett    *height = brd->height();
5277f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett    return true;
5287f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett}
5297f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett
5303bf9206ada256277a39988c263f0379d544fc27begdanielstatic void cleanup_run(Target* target) {
531385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    delete target;
5323bf9206ada256277a39988c263f0379d544fc27begdaniel#if SK_SUPPORT_GPU
5333bf9206ada256277a39988c263f0379d544fc27begdaniel    if (FLAGS_abandonGpuContext) {
5343bf9206ada256277a39988c263f0379d544fc27begdaniel        gGrFactory->abandonContexts();
5353bf9206ada256277a39988c263f0379d544fc27begdaniel    }
5363bf9206ada256277a39988c263f0379d544fc27begdaniel    if (FLAGS_resetGpuContext || FLAGS_abandonGpuContext) {
5373bf9206ada256277a39988c263f0379d544fc27begdaniel        gGrFactory->destroyContexts();
5383bf9206ada256277a39988c263f0379d544fc27begdaniel    }
5393bf9206ada256277a39988c263f0379d544fc27begdaniel#endif
5403bf9206ada256277a39988c263f0379d544fc27begdaniel}
5413bf9206ada256277a39988c263f0379d544fc27begdaniel
542e714e75c725c987fe682a1f5473224fe3e80380dmtkleinclass BenchmarkStream {
543e714e75c725c987fe682a1f5473224fe3e80380dmtkleinpublic:
54492007583e43115998412ac8b0a06cc2780eb025cmtklein    BenchmarkStream() : fBenches(BenchRegistry::Head())
54592007583e43115998412ac8b0a06cc2780eb025cmtklein                      , fGMs(skiagm::GMRegistry::Head())
546fd731ce804cd3223318f3feee2c98404890b65f2mtklein                      , fCurrentRecording(0)
54792007583e43115998412ac8b0a06cc2780eb025cmtklein                      , fCurrentScale(0)
5485b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                      , fCurrentSKP(0)
54995f192d19938b98a45dd1fa4112d965f60d10516msarett                      , fCurrentUseMPD(0)
55060869a42a133942f852dd0f1696444c2a5c9ad83scroggo                      , fCurrentCodec(0)
55184451024bfe06d138629dd7c27cf2ec0f9774dbemsarett                      , fCurrentAndroidCodec(0)
5527f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                      , fCurrentBRDImage(0)
55395f192d19938b98a45dd1fa4112d965f60d10516msarett                      , fCurrentColorType(0)
554c7796b93f02e736df967301d3c46cec46dd02d5cmsarett                      , fCurrentAlphaType(0)
555b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett                      , fCurrentSubsetType(0)
5567f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                      , fCurrentBRDStrategy(0)
55784451024bfe06d138629dd7c27cf2ec0f9774dbemsarett                      , fCurrentSampleSize(0)
558b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett                      , fCurrentAnimSKP(0) {
55992007583e43115998412ac8b0a06cc2780eb025cmtklein        for (int i = 0; i < FLAGS_skps.count(); i++) {
56092007583e43115998412ac8b0a06cc2780eb025cmtklein            if (SkStrEndsWith(FLAGS_skps[i], ".skp")) {
56192007583e43115998412ac8b0a06cc2780eb025cmtklein                fSKPs.push_back() = FLAGS_skps[i];
56292007583e43115998412ac8b0a06cc2780eb025cmtklein            } else {
56392007583e43115998412ac8b0a06cc2780eb025cmtklein                SkOSFile::Iter it(FLAGS_skps[i], ".skp");
56492007583e43115998412ac8b0a06cc2780eb025cmtklein                SkString path;
56592007583e43115998412ac8b0a06cc2780eb025cmtklein                while (it.next(&path)) {
56692007583e43115998412ac8b0a06cc2780eb025cmtklein                    fSKPs.push_back() = SkOSPath::Join(FLAGS_skps[0], path.c_str());
56792007583e43115998412ac8b0a06cc2780eb025cmtklein                }
56892007583e43115998412ac8b0a06cc2780eb025cmtklein            }
56992007583e43115998412ac8b0a06cc2780eb025cmtklein        }
57092007583e43115998412ac8b0a06cc2780eb025cmtklein
57192007583e43115998412ac8b0a06cc2780eb025cmtklein        if (4 != sscanf(FLAGS_clip[0], "%d,%d,%d,%d",
57292007583e43115998412ac8b0a06cc2780eb025cmtklein                        &fClip.fLeft, &fClip.fTop, &fClip.fRight, &fClip.fBottom)) {
57392007583e43115998412ac8b0a06cc2780eb025cmtklein            SkDebugf("Can't parse %s from --clip as an SkIRect.\n", FLAGS_clip[0]);
57492007583e43115998412ac8b0a06cc2780eb025cmtklein            exit(1);
57592007583e43115998412ac8b0a06cc2780eb025cmtklein        }
57692007583e43115998412ac8b0a06cc2780eb025cmtklein
57792007583e43115998412ac8b0a06cc2780eb025cmtklein        for (int i = 0; i < FLAGS_scales.count(); i++) {
57892007583e43115998412ac8b0a06cc2780eb025cmtklein            if (1 != sscanf(FLAGS_scales[i], "%f", &fScales.push_back())) {
57992007583e43115998412ac8b0a06cc2780eb025cmtklein                SkDebugf("Can't parse %s from --scales as an SkScalar.\n", FLAGS_scales[i]);
58092007583e43115998412ac8b0a06cc2780eb025cmtklein                exit(1);
58192007583e43115998412ac8b0a06cc2780eb025cmtklein            }
58292007583e43115998412ac8b0a06cc2780eb025cmtklein        }
5835b69377507478623dcf5b11f3ecb010f87c4794frobertphillips
58463a82855b1f0b83952b65fca330954c50ebe7a4bcdalton        if (2 != sscanf(FLAGS_zoom[0], "%f,%lf", &fZoomMax, &fZoomPeriodMs)) {
58563a82855b1f0b83952b65fca330954c50ebe7a4bcdalton            SkDebugf("Can't parse %s from --zoom as a zoomMax,zoomPeriodMs.\n", FLAGS_zoom[0]);
586261c3ad7fde95748da92550735decc949dc73bf2joshualitt            exit(1);
587261c3ad7fde95748da92550735decc949dc73bf2joshualitt        }
588261c3ad7fde95748da92550735decc949dc73bf2joshualitt
5895b69377507478623dcf5b11f3ecb010f87c4794frobertphillips        if (FLAGS_mpd) {
5905b69377507478623dcf5b11f3ecb010f87c4794frobertphillips            fUseMPDs.push_back() = true;
5915b69377507478623dcf5b11f3ecb010f87c4794frobertphillips        }
592c751ecb3681072fda53dd3cebeb2eb41fc73b314mtklein        fUseMPDs.push_back() = false;
59395553d917c73ef333ede967521560957a5b6a0admtklein
59495f192d19938b98a45dd1fa4112d965f60d10516msarett        // Prepare the images for decoding
5958673714d75ff1020f78217ff8839f1e18c3591e4scroggo        if (!CollectImages(&fImages)) {
5968673714d75ff1020f78217ff8839f1e18c3591e4scroggo            exit(1);
59795f192d19938b98a45dd1fa4112d965f60d10516msarett        }
59895553d917c73ef333ede967521560957a5b6a0admtklein
59995f192d19938b98a45dd1fa4112d965f60d10516msarett        // Choose the candidate color types for image decoding
60095f192d19938b98a45dd1fa4112d965f60d10516msarett        const SkColorType colorTypes[] =
601b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett            { kN32_SkColorType,
602b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett              kRGB_565_SkColorType,
603b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett              kAlpha_8_SkColorType,
604b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett              kIndex_8_SkColorType,
605b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett              kGray_8_SkColorType };
60674deb981d5e9c11c88fe431e78166d6cf8dacc1amsarett        fColorTypes.reset(colorTypes, SK_ARRAY_COUNT(colorTypes));
60792007583e43115998412ac8b0a06cc2780eb025cmtklein    }
608e714e75c725c987fe682a1f5473224fe3e80380dmtklein
609fd731ce804cd3223318f3feee2c98404890b65f2mtklein    static bool ReadPicture(const char* path, SkAutoTUnref<SkPicture>* pic) {
610fd731ce804cd3223318f3feee2c98404890b65f2mtklein        // Not strictly necessary, as it will be checked again later,
611fd731ce804cd3223318f3feee2c98404890b65f2mtklein        // but helps to avoid a lot of pointless work if we're going to skip it.
61291e457d17f8c6c06de33eb2bb430a90ba472eda5cdalton        if (SkCommandLineFlags::ShouldSkip(FLAGS_match, SkOSPath::Basename(path).c_str())) {
613fd731ce804cd3223318f3feee2c98404890b65f2mtklein            return false;
614fd731ce804cd3223318f3feee2c98404890b65f2mtklein        }
615fd731ce804cd3223318f3feee2c98404890b65f2mtklein
616a1193e4b0e34a7e4e1bd33e9708d7341679f8321scroggo        SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(path));
61796fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (stream.get() == nullptr) {
618fd731ce804cd3223318f3feee2c98404890b65f2mtklein            SkDebugf("Could not read %s.\n", path);
619fd731ce804cd3223318f3feee2c98404890b65f2mtklein            return false;
620fd731ce804cd3223318f3feee2c98404890b65f2mtklein        }
621fd731ce804cd3223318f3feee2c98404890b65f2mtklein
62257f27bdcbd328491a121918b4ab9301fbcdec642mtklein        pic->reset(SkPicture::CreateFromStream(stream.get()));
62396fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (pic->get() == nullptr) {
624fd731ce804cd3223318f3feee2c98404890b65f2mtklein            SkDebugf("Could not read %s as an SkPicture.\n", path);
625fd731ce804cd3223318f3feee2c98404890b65f2mtklein            return false;
626fd731ce804cd3223318f3feee2c98404890b65f2mtklein        }
627fd731ce804cd3223318f3feee2c98404890b65f2mtklein        return true;
628fd731ce804cd3223318f3feee2c98404890b65f2mtklein    }
629fd731ce804cd3223318f3feee2c98404890b65f2mtklein
63092007583e43115998412ac8b0a06cc2780eb025cmtklein    Benchmark* next() {
63165dfd2fe5d93d63b655663707c7233917e293accmtklein        SkAutoTDelete<Benchmark> bench;
63265dfd2fe5d93d63b655663707c7233917e293accmtklein        do {
63365dfd2fe5d93d63b655663707c7233917e293accmtklein            bench.reset(this->rawNext());
63465dfd2fe5d93d63b655663707c7233917e293accmtklein            if (!bench) {
63565dfd2fe5d93d63b655663707c7233917e293accmtklein                return nullptr;
63665dfd2fe5d93d63b655663707c7233917e293accmtklein            }
63765dfd2fe5d93d63b655663707c7233917e293accmtklein        } while(SkCommandLineFlags::ShouldSkip(FLAGS_sourceType, fSourceType) ||
63865dfd2fe5d93d63b655663707c7233917e293accmtklein                SkCommandLineFlags::ShouldSkip(FLAGS_benchType,  fBenchType));
63965dfd2fe5d93d63b655663707c7233917e293accmtklein        return bench.detach();
64065dfd2fe5d93d63b655663707c7233917e293accmtklein    }
64165dfd2fe5d93d63b655663707c7233917e293accmtklein
64265dfd2fe5d93d63b655663707c7233917e293accmtklein    Benchmark* rawNext() {
643e714e75c725c987fe682a1f5473224fe3e80380dmtklein        if (fBenches) {
64496fcdcc219d2a0d3579719b84b28bede76efba64halcanary            Benchmark* bench = fBenches->factory()(nullptr);
645e714e75c725c987fe682a1f5473224fe3e80380dmtklein            fBenches = fBenches->next();
64692007583e43115998412ac8b0a06cc2780eb025cmtklein            fSourceType = "bench";
647fd731ce804cd3223318f3feee2c98404890b65f2mtklein            fBenchType  = "micro";
648e714e75c725c987fe682a1f5473224fe3e80380dmtklein            return bench;
649e714e75c725c987fe682a1f5473224fe3e80380dmtklein        }
65092007583e43115998412ac8b0a06cc2780eb025cmtklein
651e714e75c725c987fe682a1f5473224fe3e80380dmtklein        while (fGMs) {
65296fcdcc219d2a0d3579719b84b28bede76efba64halcanary            SkAutoTDelete<skiagm::GM> gm(fGMs->factory()(nullptr));
653e714e75c725c987fe682a1f5473224fe3e80380dmtklein            fGMs = fGMs->next();
654cf5d9c993dcbd75d4cefe2d1de25c2b9645f6957mtklein            if (gm->runAsBench()) {
65592007583e43115998412ac8b0a06cc2780eb025cmtklein                fSourceType = "gm";
656fd731ce804cd3223318f3feee2c98404890b65f2mtklein                fBenchType  = "micro";
657385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary                return new GMBench(gm.detach());
658e714e75c725c987fe682a1f5473224fe3e80380dmtklein            }
659e714e75c725c987fe682a1f5473224fe3e80380dmtklein        }
66092007583e43115998412ac8b0a06cc2780eb025cmtklein
661fd731ce804cd3223318f3feee2c98404890b65f2mtklein        // First add all .skps as RecordingBenches.
662fd731ce804cd3223318f3feee2c98404890b65f2mtklein        while (fCurrentRecording < fSKPs.count()) {
663fd731ce804cd3223318f3feee2c98404890b65f2mtklein            const SkString& path = fSKPs[fCurrentRecording++];
664fd731ce804cd3223318f3feee2c98404890b65f2mtklein            SkAutoTUnref<SkPicture> pic;
665fd731ce804cd3223318f3feee2c98404890b65f2mtklein            if (!ReadPicture(path.c_str(), &pic)) {
666fd731ce804cd3223318f3feee2c98404890b65f2mtklein                continue;
667fd731ce804cd3223318f3feee2c98404890b65f2mtklein            }
668fd731ce804cd3223318f3feee2c98404890b65f2mtklein            SkString name = SkOSPath::Basename(path.c_str());
669fd731ce804cd3223318f3feee2c98404890b65f2mtklein            fSourceType = "skp";
670fd731ce804cd3223318f3feee2c98404890b65f2mtklein            fBenchType  = "recording";
6710aa5cea8694d3686b6742a36eab81ab9001de954bsalomon            fSKPBytes = static_cast<double>(SkPictureUtils::ApproximateBytesUsed(pic));
672051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein            fSKPOps   = pic->approximateOpCount();
673385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary            return new RecordingBench(name.c_str(), pic.get(), FLAGS_bbh);
674fd731ce804cd3223318f3feee2c98404890b65f2mtklein        }
675fd731ce804cd3223318f3feee2c98404890b65f2mtklein
676fd731ce804cd3223318f3feee2c98404890b65f2mtklein        // Then once each for each scale as SKPBenches (playback).
67792007583e43115998412ac8b0a06cc2780eb025cmtklein        while (fCurrentScale < fScales.count()) {
67892007583e43115998412ac8b0a06cc2780eb025cmtklein            while (fCurrentSKP < fSKPs.count()) {
6795b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                const SkString& path = fSKPs[fCurrentSKP];
680fd731ce804cd3223318f3feee2c98404890b65f2mtklein                SkAutoTUnref<SkPicture> pic;
681fd731ce804cd3223318f3feee2c98404890b65f2mtklein                if (!ReadPicture(path.c_str(), &pic)) {
6825b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                    fCurrentSKP++;
68392007583e43115998412ac8b0a06cc2780eb025cmtklein                    continue;
68492007583e43115998412ac8b0a06cc2780eb025cmtklein                }
6855b69377507478623dcf5b11f3ecb010f87c4794frobertphillips
6865b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                while (fCurrentUseMPD < fUseMPDs.count()) {
6875b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                    if (FLAGS_bbh) {
6885b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                        // The SKP we read off disk doesn't have a BBH.  Re-record so it grows one.
6895b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                        SkRTreeFactory factory;
6905b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                        SkPictureRecorder recorder;
6915b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                        static const int kFlags = SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag;
6925b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                        pic->playback(recorder.beginRecording(pic->cullRect().width(),
6935b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                                                              pic->cullRect().height(),
694748ca3bf2d170708f263693e8579e6722389d0efmtklein                                                              &factory,
695e451c4df7369c5e253ef9c9e0a8713beda25f34brobertphillips                                                              fUseMPDs[fCurrentUseMPD] ? kFlags : 0));
6965b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                        pic.reset(recorder.endRecording());
6975b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                    }
6985b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                    SkString name = SkOSPath::Basename(path.c_str());
6995b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                    fSourceType = "skp";
7005b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                    fBenchType = "playback";
701385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary                    return new SKPBench(name.c_str(), pic.get(), fClip, fScales[fCurrentScale],
702385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary                                        fUseMPDs[fCurrentUseMPD++], FLAGS_loopSKP);
7032084050a33ae139d0fe9bb680f7905f91139a39fmtklein                }
7045b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                fCurrentUseMPD = 0;
7055b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                fCurrentSKP++;
70692007583e43115998412ac8b0a06cc2780eb025cmtklein            }
70792007583e43115998412ac8b0a06cc2780eb025cmtklein            fCurrentSKP = 0;
70892007583e43115998412ac8b0a06cc2780eb025cmtklein            fCurrentScale++;
70992007583e43115998412ac8b0a06cc2780eb025cmtklein        }
71092007583e43115998412ac8b0a06cc2780eb025cmtklein
711261c3ad7fde95748da92550735decc949dc73bf2joshualitt        // Now loop over each skp again if we have an animation
71263a82855b1f0b83952b65fca330954c50ebe7a4bcdalton        if (fZoomMax != 1.0f && fZoomPeriodMs > 0) {
713261c3ad7fde95748da92550735decc949dc73bf2joshualitt            while (fCurrentAnimSKP < fSKPs.count()) {
714261c3ad7fde95748da92550735decc949dc73bf2joshualitt                const SkString& path = fSKPs[fCurrentAnimSKP];
715261c3ad7fde95748da92550735decc949dc73bf2joshualitt                SkAutoTUnref<SkPicture> pic;
716261c3ad7fde95748da92550735decc949dc73bf2joshualitt                if (!ReadPicture(path.c_str(), &pic)) {
717261c3ad7fde95748da92550735decc949dc73bf2joshualitt                    fCurrentAnimSKP++;
718261c3ad7fde95748da92550735decc949dc73bf2joshualitt                    continue;
719261c3ad7fde95748da92550735decc949dc73bf2joshualitt                }
720261c3ad7fde95748da92550735decc949dc73bf2joshualitt
721261c3ad7fde95748da92550735decc949dc73bf2joshualitt                fCurrentAnimSKP++;
722261c3ad7fde95748da92550735decc949dc73bf2joshualitt                SkString name = SkOSPath::Basename(path.c_str());
72363a82855b1f0b83952b65fca330954c50ebe7a4bcdalton                SkAutoTUnref<SKPAnimationBench::Animation> animation(
72463a82855b1f0b83952b65fca330954c50ebe7a4bcdalton                    SKPAnimationBench::CreateZoomAnimation(fZoomMax, fZoomPeriodMs));
725385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary                return new SKPAnimationBench(name.c_str(), pic.get(), fClip, animation,
726385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary                                             FLAGS_loopSKP);
727261c3ad7fde95748da92550735decc949dc73bf2joshualitt            }
728261c3ad7fde95748da92550735decc949dc73bf2joshualitt        }
729261c3ad7fde95748da92550735decc949dc73bf2joshualitt
73060869a42a133942f852dd0f1696444c2a5c9ad83scroggo        for (; fCurrentCodec < fImages.count(); fCurrentCodec++) {
731303fa350125f372bbfc29bec1235885493dab9b4scroggo            fSourceType = "image";
732303fa350125f372bbfc29bec1235885493dab9b4scroggo            fBenchType = "skcodec";
73360869a42a133942f852dd0f1696444c2a5c9ad83scroggo            const SkString& path = fImages[fCurrentCodec];
7346f0ff91c6561549a1ea8de3e8896b80a584c45b9mtklein            if (SkCommandLineFlags::ShouldSkip(FLAGS_match, path.c_str())) {
7356f0ff91c6561549a1ea8de3e8896b80a584c45b9mtklein                continue;
7366f0ff91c6561549a1ea8de3e8896b80a584c45b9mtklein            }
73760869a42a133942f852dd0f1696444c2a5c9ad83scroggo            SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(path.c_str()));
73860869a42a133942f852dd0f1696444c2a5c9ad83scroggo            SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded));
73960869a42a133942f852dd0f1696444c2a5c9ad83scroggo            if (!codec) {
74060869a42a133942f852dd0f1696444c2a5c9ad83scroggo                // Nothing to time.
7419d9725c892743cf8fc66ea6cdd5ce21fe2df6d14msarett                SkDebugf("Cannot find codec for %s\n", path.c_str());
74260869a42a133942f852dd0f1696444c2a5c9ad83scroggo                continue;
74360869a42a133942f852dd0f1696444c2a5c9ad83scroggo            }
74421027994192f395bbd1507558b84f59b3c7cf0dascroggo
74560869a42a133942f852dd0f1696444c2a5c9ad83scroggo            while (fCurrentColorType < fColorTypes.count()) {
74621027994192f395bbd1507558b84f59b3c7cf0dascroggo                const SkColorType colorType = fColorTypes[fCurrentColorType];
74721027994192f395bbd1507558b84f59b3c7cf0dascroggo
748c7796b93f02e736df967301d3c46cec46dd02d5cmsarett                SkAlphaType alphaType = codec->getInfo().alphaType();
749c7796b93f02e736df967301d3c46cec46dd02d5cmsarett                switch (alphaType) {
750c7796b93f02e736df967301d3c46cec46dd02d5cmsarett                    case kOpaque_SkAlphaType:
751c7796b93f02e736df967301d3c46cec46dd02d5cmsarett                        // We only need to test one alpha type (opaque).
752c7796b93f02e736df967301d3c46cec46dd02d5cmsarett                        fCurrentColorType++;
753c7796b93f02e736df967301d3c46cec46dd02d5cmsarett                        break;
754c7796b93f02e736df967301d3c46cec46dd02d5cmsarett                    case kUnpremul_SkAlphaType:
755c7796b93f02e736df967301d3c46cec46dd02d5cmsarett                    case kPremul_SkAlphaType:
756c7796b93f02e736df967301d3c46cec46dd02d5cmsarett                        if (0 == fCurrentAlphaType) {
757c7796b93f02e736df967301d3c46cec46dd02d5cmsarett                            // Test unpremul first.
758c7796b93f02e736df967301d3c46cec46dd02d5cmsarett                            alphaType = kUnpremul_SkAlphaType;
759c7796b93f02e736df967301d3c46cec46dd02d5cmsarett                            fCurrentAlphaType++;
760c7796b93f02e736df967301d3c46cec46dd02d5cmsarett                        } else {
761c7796b93f02e736df967301d3c46cec46dd02d5cmsarett                            // Test premul.
762c7796b93f02e736df967301d3c46cec46dd02d5cmsarett                            alphaType = kPremul_SkAlphaType;
763c7796b93f02e736df967301d3c46cec46dd02d5cmsarett                            fCurrentAlphaType = 0;
764c7796b93f02e736df967301d3c46cec46dd02d5cmsarett                            fCurrentColorType++;
765c7796b93f02e736df967301d3c46cec46dd02d5cmsarett                        }
766c7796b93f02e736df967301d3c46cec46dd02d5cmsarett                        break;
767c7796b93f02e736df967301d3c46cec46dd02d5cmsarett                    default:
768c7796b93f02e736df967301d3c46cec46dd02d5cmsarett                        SkASSERT(false);
769c7796b93f02e736df967301d3c46cec46dd02d5cmsarett                        fCurrentColorType++;
770c7796b93f02e736df967301d3c46cec46dd02d5cmsarett                        break;
77121027994192f395bbd1507558b84f59b3c7cf0dascroggo                }
77221027994192f395bbd1507558b84f59b3c7cf0dascroggo
773c7796b93f02e736df967301d3c46cec46dd02d5cmsarett                // Make sure we can decode to this color type and alpha type.
774c7796b93f02e736df967301d3c46cec46dd02d5cmsarett                SkImageInfo info =
775c7796b93f02e736df967301d3c46cec46dd02d5cmsarett                        codec->getInfo().makeColorType(colorType).makeAlphaType(alphaType);
77621027994192f395bbd1507558b84f59b3c7cf0dascroggo                const size_t rowBytes = info.minRowBytes();
77721027994192f395bbd1507558b84f59b3c7cf0dascroggo                SkAutoMalloc storage(info.getSafeSize(rowBytes));
77821027994192f395bbd1507558b84f59b3c7cf0dascroggo
77921027994192f395bbd1507558b84f59b3c7cf0dascroggo                // Used if fCurrentColorType is kIndex_8_SkColorType
78021027994192f395bbd1507558b84f59b3c7cf0dascroggo                int colorCount = 256;
78121027994192f395bbd1507558b84f59b3c7cf0dascroggo                SkPMColor colors[256];
78221027994192f395bbd1507558b84f59b3c7cf0dascroggo
783eb602a5c94078fb2956c9bdc64bbf47a31b9c0e5scroggo                const SkCodec::Result result = codec->getPixels(
78496fcdcc219d2a0d3579719b84b28bede76efba64halcanary                        info, storage.get(), rowBytes, nullptr, colors,
78521027994192f395bbd1507558b84f59b3c7cf0dascroggo                        &colorCount);
78660869a42a133942f852dd0f1696444c2a5c9ad83scroggo                switch (result) {
787eb602a5c94078fb2956c9bdc64bbf47a31b9c0e5scroggo                    case SkCodec::kSuccess:
788eb602a5c94078fb2956c9bdc64bbf47a31b9c0e5scroggo                    case SkCodec::kIncompleteInput:
78960869a42a133942f852dd0f1696444c2a5c9ad83scroggo                        return new CodecBench(SkOSPath::Basename(path.c_str()),
790c7796b93f02e736df967301d3c46cec46dd02d5cmsarett                                encoded, colorType, alphaType);
791eb602a5c94078fb2956c9bdc64bbf47a31b9c0e5scroggo                    case SkCodec::kInvalidConversion:
79260869a42a133942f852dd0f1696444c2a5c9ad83scroggo                        // This is okay. Not all conversions are valid.
79360869a42a133942f852dd0f1696444c2a5c9ad83scroggo                        break;
79460869a42a133942f852dd0f1696444c2a5c9ad83scroggo                    default:
79560869a42a133942f852dd0f1696444c2a5c9ad83scroggo                        // This represents some sort of failure.
79660869a42a133942f852dd0f1696444c2a5c9ad83scroggo                        SkASSERT(false);
79760869a42a133942f852dd0f1696444c2a5c9ad83scroggo                        break;
79860869a42a133942f852dd0f1696444c2a5c9ad83scroggo                }
79960869a42a133942f852dd0f1696444c2a5c9ad83scroggo            }
80060869a42a133942f852dd0f1696444c2a5c9ad83scroggo            fCurrentColorType = 0;
80160869a42a133942f852dd0f1696444c2a5c9ad83scroggo        }
80260869a42a133942f852dd0f1696444c2a5c9ad83scroggo
80384451024bfe06d138629dd7c27cf2ec0f9774dbemsarett        // Run AndroidCodecBenches
80484451024bfe06d138629dd7c27cf2ec0f9774dbemsarett        const int sampleSizes[] = { 2, 4, 8 };
80584451024bfe06d138629dd7c27cf2ec0f9774dbemsarett        for (; fCurrentAndroidCodec < fImages.count(); fCurrentAndroidCodec++) {
80684451024bfe06d138629dd7c27cf2ec0f9774dbemsarett            fSourceType = "image";
80784451024bfe06d138629dd7c27cf2ec0f9774dbemsarett            fBenchType = "skandroidcodec";
80884451024bfe06d138629dd7c27cf2ec0f9774dbemsarett
80984451024bfe06d138629dd7c27cf2ec0f9774dbemsarett            const SkString& path = fImages[fCurrentAndroidCodec];
81084451024bfe06d138629dd7c27cf2ec0f9774dbemsarett            if (SkCommandLineFlags::ShouldSkip(FLAGS_match, path.c_str())) {
81184451024bfe06d138629dd7c27cf2ec0f9774dbemsarett                continue;
81284451024bfe06d138629dd7c27cf2ec0f9774dbemsarett            }
81384451024bfe06d138629dd7c27cf2ec0f9774dbemsarett            SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(path.c_str()));
81484451024bfe06d138629dd7c27cf2ec0f9774dbemsarett            SkAutoTDelete<SkAndroidCodec> codec(SkAndroidCodec::NewFromData(encoded));
81584451024bfe06d138629dd7c27cf2ec0f9774dbemsarett            if (!codec) {
81684451024bfe06d138629dd7c27cf2ec0f9774dbemsarett                // Nothing to time.
81784451024bfe06d138629dd7c27cf2ec0f9774dbemsarett                SkDebugf("Cannot find codec for %s\n", path.c_str());
81884451024bfe06d138629dd7c27cf2ec0f9774dbemsarett                continue;
81984451024bfe06d138629dd7c27cf2ec0f9774dbemsarett            }
82084451024bfe06d138629dd7c27cf2ec0f9774dbemsarett
82184451024bfe06d138629dd7c27cf2ec0f9774dbemsarett            while (fCurrentSampleSize < (int) SK_ARRAY_COUNT(sampleSizes)) {
82284451024bfe06d138629dd7c27cf2ec0f9774dbemsarett                int sampleSize = sampleSizes[fCurrentSampleSize];
82384451024bfe06d138629dd7c27cf2ec0f9774dbemsarett                fCurrentSampleSize++;
82484451024bfe06d138629dd7c27cf2ec0f9774dbemsarett                if (10 * sampleSize > SkTMin(codec->getInfo().width(), codec->getInfo().height())) {
82584451024bfe06d138629dd7c27cf2ec0f9774dbemsarett                    // Avoid benchmarking scaled decodes of already small images.
82684451024bfe06d138629dd7c27cf2ec0f9774dbemsarett                    break;
82784451024bfe06d138629dd7c27cf2ec0f9774dbemsarett                }
82884451024bfe06d138629dd7c27cf2ec0f9774dbemsarett
82984451024bfe06d138629dd7c27cf2ec0f9774dbemsarett                return new AndroidCodecBench(SkOSPath::Basename(path.c_str()), encoded, sampleSize);
83084451024bfe06d138629dd7c27cf2ec0f9774dbemsarett            }
83184451024bfe06d138629dd7c27cf2ec0f9774dbemsarett            fCurrentSampleSize = 0;
83284451024bfe06d138629dd7c27cf2ec0f9774dbemsarett        }
83384451024bfe06d138629dd7c27cf2ec0f9774dbemsarett
8347f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // Run the BRDBenches
8357f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // We will benchmark multiple BRD strategies.
836303fa350125f372bbfc29bec1235885493dab9b4scroggo        static const struct {
8375cb4885b4cd1ac5eb3fc92dac5f5509d7c810464msarett            SkBitmapRegionDecoder::Strategy    fStrategy;
8380459c9425f567b6d11ca534fb13a05de9f37b7eemsarett            const char*                        fName;
839303fa350125f372bbfc29bec1235885493dab9b4scroggo        } strategies[] = {
8400459c9425f567b6d11ca534fb13a05de9f37b7eemsarett            { SkBitmapRegionDecoder::kCanvas_Strategy,       "BRD_canvas" },
8415cb4885b4cd1ac5eb3fc92dac5f5509d7c810464msarett            { SkBitmapRegionDecoder::kAndroidCodec_Strategy, "BRD_android_codec" },
8427f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        };
8437f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett
8447f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // We intend to create benchmarks that model the use cases in
8457f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // android/libraries/social/tiledimage.  In this library, an image is decoded in 512x512
8467f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // tiles.  The image can be translated freely, so the location of a tile may be anywhere in
8477f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // the image.  For that reason, we will benchmark decodes in five representative locations
8487f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // in the image.  Additionally, this use case utilizes power of two scaling, so we will
8497f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // test on power of two sample sizes.  The output tile is always 512x512, so, when a
8507f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // sampleSize is used, the size of the subset that is decoded is always
8517f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // (sampleSize*512)x(sampleSize*512).
8527f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        // There are a few good reasons to only test on power of two sample sizes at this time:
8537f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        //     All use cases we are aware of only scale by powers of two.
8547f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        //     PNG decodes use the indicated sampling strategy regardless of the sample size, so
8557f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        //         these tests are sufficient to provide good coverage of our scaling options.
85684451024bfe06d138629dd7c27cf2ec0f9774dbemsarett        const uint32_t brdSampleSizes[] = { 1, 2, 4, 8, 16 };
8577f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        const uint32_t minOutputSize = 512;
8586f0ff91c6561549a1ea8de3e8896b80a584c45b9mtklein        for (; fCurrentBRDImage < fImages.count(); fCurrentBRDImage++) {
8596f0ff91c6561549a1ea8de3e8896b80a584c45b9mtklein            const SkString& path = fImages[fCurrentBRDImage];
8606f0ff91c6561549a1ea8de3e8896b80a584c45b9mtklein            if (SkCommandLineFlags::ShouldSkip(FLAGS_match, path.c_str())) {
8616f0ff91c6561549a1ea8de3e8896b80a584c45b9mtklein                continue;
8626f0ff91c6561549a1ea8de3e8896b80a584c45b9mtklein            }
8637f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett            while (fCurrentBRDStrategy < (int) SK_ARRAY_COUNT(strategies)) {
864303fa350125f372bbfc29bec1235885493dab9b4scroggo                fSourceType = "image";
865303fa350125f372bbfc29bec1235885493dab9b4scroggo                fBenchType = strategies[fCurrentBRDStrategy].fName;
866860e8a67190e024b7375e52e270e6bd0a17af86escroggo
8675cb4885b4cd1ac5eb3fc92dac5f5509d7c810464msarett                const SkBitmapRegionDecoder::Strategy strategy =
868860e8a67190e024b7375e52e270e6bd0a17af86escroggo                        strategies[fCurrentBRDStrategy].fStrategy;
869860e8a67190e024b7375e52e270e6bd0a17af86escroggo
8707f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                while (fCurrentColorType < fColorTypes.count()) {
87184451024bfe06d138629dd7c27cf2ec0f9774dbemsarett                    while (fCurrentSampleSize < (int) SK_ARRAY_COUNT(brdSampleSizes)) {
8727f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                        while (fCurrentSubsetType <= kLastSingle_SubsetType) {
873860e8a67190e024b7375e52e270e6bd0a17af86escroggo
8747f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(path.c_str()));
8757f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            const SkColorType colorType = fColorTypes[fCurrentColorType];
87684451024bfe06d138629dd7c27cf2ec0f9774dbemsarett                            uint32_t sampleSize = brdSampleSizes[fCurrentSampleSize];
8777f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            int currentSubsetType = fCurrentSubsetType++;
8787f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett
8797f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            int width = 0;
8807f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            int height = 0;
8817f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            if (!valid_brd_bench(encoded.get(), strategy, colorType, sampleSize,
8827f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    minOutputSize, &width, &height)) {
8837f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                break;
8847f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            }
8857f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett
8867f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            SkString basename = SkOSPath::Basename(path.c_str());
8877f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            SkIRect subset;
8887f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            const uint32_t subsetSize = sampleSize * minOutputSize;
8897f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            switch (currentSubsetType) {
8907f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                case kTopLeft_SubsetType:
8917f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    basename.append("_TopLeft");
8927f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    subset = SkIRect::MakeXYWH(0, 0, subsetSize, subsetSize);
8937f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    break;
8947f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                case kTopRight_SubsetType:
8957f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    basename.append("_TopRight");
8967f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    subset = SkIRect::MakeXYWH(width - subsetSize, 0, subsetSize,
8977f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                            subsetSize);
8987f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    break;
8997f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                case kMiddle_SubsetType:
9007f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    basename.append("_Middle");
9017f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    subset = SkIRect::MakeXYWH((width - subsetSize) / 2,
9027f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                            (height - subsetSize) / 2, subsetSize, subsetSize);
9037f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    break;
9047f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                case kBottomLeft_SubsetType:
9057f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    basename.append("_BottomLeft");
9067f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    subset = SkIRect::MakeXYWH(0, height - subsetSize, subsetSize,
9077f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                            subsetSize);
9087f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    break;
9097f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                case kBottomRight_SubsetType:
9107f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    basename.append("_BottomRight");
9117f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    subset = SkIRect::MakeXYWH(width - subsetSize,
9127f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                            height - subsetSize, subsetSize, subsetSize);
9137f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    break;
9147f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                default:
9157f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    SkASSERT(false);
9167f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            }
9177f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett
9187f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                            return new BitmapRegionDecoderBench(basename.c_str(), encoded.get(),
9197f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                                    strategy, colorType, sampleSize, subset);
9207f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                        }
9217f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                        fCurrentSubsetType = 0;
92284451024bfe06d138629dd7c27cf2ec0f9774dbemsarett                        fCurrentSampleSize++;
9237f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                    }
92484451024bfe06d138629dd7c27cf2ec0f9774dbemsarett                    fCurrentSampleSize = 0;
9257f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                    fCurrentColorType++;
9267f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                }
9277f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                fCurrentColorType = 0;
9287f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett                fCurrentBRDStrategy++;
9297f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett            }
9307f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett            fCurrentBRDStrategy = 0;
9317f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        }
9327f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett
93396fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
934e714e75c725c987fe682a1f5473224fe3e80380dmtklein    }
93592007583e43115998412ac8b0a06cc2780eb025cmtklein
93692007583e43115998412ac8b0a06cc2780eb025cmtklein    void fillCurrentOptions(ResultsWriter* log) const {
93792007583e43115998412ac8b0a06cc2780eb025cmtklein        log->configOption("source_type", fSourceType);
938fd731ce804cd3223318f3feee2c98404890b65f2mtklein        log->configOption("bench_type",  fBenchType);
93992007583e43115998412ac8b0a06cc2780eb025cmtklein        if (0 == strcmp(fSourceType, "skp")) {
94092007583e43115998412ac8b0a06cc2780eb025cmtklein            log->configOption("clip",
94192007583e43115998412ac8b0a06cc2780eb025cmtklein                    SkStringPrintf("%d %d %d %d", fClip.fLeft, fClip.fTop,
94292007583e43115998412ac8b0a06cc2780eb025cmtklein                                                  fClip.fRight, fClip.fBottom).c_str());
943f2b340fc885ad2a12d2d73974eff9c8f4c94192cdjsollen            SkASSERT_RELEASE(fCurrentScale < fScales.count());  // debugging paranoia
94492007583e43115998412ac8b0a06cc2780eb025cmtklein            log->configOption("scale", SkStringPrintf("%.2g", fScales[fCurrentScale]).c_str());
9455b69377507478623dcf5b11f3ecb010f87c4794frobertphillips            if (fCurrentUseMPD > 0) {
9465b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                SkASSERT(1 == fCurrentUseMPD || 2 == fCurrentUseMPD);
9475b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                log->configOption("multi_picture_draw", fUseMPDs[fCurrentUseMPD-1] ? "true" : "false");
9485b69377507478623dcf5b11f3ecb010f87c4794frobertphillips            }
94992007583e43115998412ac8b0a06cc2780eb025cmtklein        }
950051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein        if (0 == strcmp(fBenchType, "recording")) {
951051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein            log->metric("bytes", fSKPBytes);
952051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein            log->metric("ops",   fSKPOps);
953051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein        }
95492007583e43115998412ac8b0a06cc2780eb025cmtklein    }
95592007583e43115998412ac8b0a06cc2780eb025cmtklein
956e714e75c725c987fe682a1f5473224fe3e80380dmtkleinprivate:
957b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett    enum SubsetType {
958b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett        kTopLeft_SubsetType     = 0,
959b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett        kTopRight_SubsetType    = 1,
960ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett        kMiddle_SubsetType      = 2,
961ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett        kBottomLeft_SubsetType  = 3,
962ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett        kBottomRight_SubsetType = 4,
963ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett        kTranslate_SubsetType   = 5,
964ab80e35fbddd5b534b486cf9d331b5da00e5aa4fmsarett        kZoom_SubsetType        = 6,
9657f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        kLast_SubsetType        = kZoom_SubsetType,
9667f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett        kLastSingle_SubsetType  = kBottomRight_SubsetType,
967b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett    };
968b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett
969e714e75c725c987fe682a1f5473224fe3e80380dmtklein    const BenchRegistry* fBenches;
970e714e75c725c987fe682a1f5473224fe3e80380dmtklein    const skiagm::GMRegistry* fGMs;
97192007583e43115998412ac8b0a06cc2780eb025cmtklein    SkIRect            fClip;
97292007583e43115998412ac8b0a06cc2780eb025cmtklein    SkTArray<SkScalar> fScales;
97392007583e43115998412ac8b0a06cc2780eb025cmtklein    SkTArray<SkString> fSKPs;
9745b69377507478623dcf5b11f3ecb010f87c4794frobertphillips    SkTArray<bool>     fUseMPDs;
97595f192d19938b98a45dd1fa4112d965f60d10516msarett    SkTArray<SkString> fImages;
97674deb981d5e9c11c88fe431e78166d6cf8dacc1amsarett    SkTArray<SkColorType, true> fColorTypes;
97763a82855b1f0b83952b65fca330954c50ebe7a4bcdalton    SkScalar           fZoomMax;
97863a82855b1f0b83952b65fca330954c50ebe7a4bcdalton    double             fZoomPeriodMs;
97992007583e43115998412ac8b0a06cc2780eb025cmtklein
980051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein    double fSKPBytes, fSKPOps;
981051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein
982fd731ce804cd3223318f3feee2c98404890b65f2mtklein    const char* fSourceType;  // What we're benching: bench, GM, SKP, ...
983fd731ce804cd3223318f3feee2c98404890b65f2mtklein    const char* fBenchType;   // How we bench it: micro, recording, playback, ...
984fd731ce804cd3223318f3feee2c98404890b65f2mtklein    int fCurrentRecording;
98592007583e43115998412ac8b0a06cc2780eb025cmtklein    int fCurrentScale;
98692007583e43115998412ac8b0a06cc2780eb025cmtklein    int fCurrentSKP;
9875b69377507478623dcf5b11f3ecb010f87c4794frobertphillips    int fCurrentUseMPD;
98860869a42a133942f852dd0f1696444c2a5c9ad83scroggo    int fCurrentCodec;
98984451024bfe06d138629dd7c27cf2ec0f9774dbemsarett    int fCurrentAndroidCodec;
9907f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett    int fCurrentBRDImage;
99195f192d19938b98a45dd1fa4112d965f60d10516msarett    int fCurrentColorType;
992c7796b93f02e736df967301d3c46cec46dd02d5cmsarett    int fCurrentAlphaType;
993b23e6aa6767816ac4bc6c191e78ef62d6e765671msarett    int fCurrentSubsetType;
9947f69144aaabbedf51ad2a1feddc9e0689f2c5ee9msarett    int fCurrentBRDStrategy;
99584451024bfe06d138629dd7c27cf2ec0f9774dbemsarett    int fCurrentSampleSize;
996261c3ad7fde95748da92550735decc949dc73bf2joshualitt    int fCurrentAnimSKP;
997e714e75c725c987fe682a1f5473224fe3e80380dmtklein};
998e714e75c725c987fe682a1f5473224fe3e80380dmtklein
999c149f0e36e0ca0ff35ec6e2f79419b58d529db40msarett// Some runs (mostly, Valgrind) are so slow that the bot framework thinks we've hung.
1000c149f0e36e0ca0ff35ec6e2f79419b58d529db40msarett// This prints something every once in a while so that it knows we're still working.
1001c149f0e36e0ca0ff35ec6e2f79419b58d529db40msarettstatic void start_keepalive() {
1002c149f0e36e0ca0ff35ec6e2f79419b58d529db40msarett    struct Loop {
1003c149f0e36e0ca0ff35ec6e2f79419b58d529db40msarett        static void forever(void*) {
1004c149f0e36e0ca0ff35ec6e2f79419b58d529db40msarett            for (;;) {
1005c149f0e36e0ca0ff35ec6e2f79419b58d529db40msarett                static const int kSec = 1200;
1006c149f0e36e0ca0ff35ec6e2f79419b58d529db40msarett            #if defined(SK_BUILD_FOR_WIN)
1007c149f0e36e0ca0ff35ec6e2f79419b58d529db40msarett                Sleep(kSec * 1000);
1008c149f0e36e0ca0ff35ec6e2f79419b58d529db40msarett            #else
1009c149f0e36e0ca0ff35ec6e2f79419b58d529db40msarett                sleep(kSec);
1010c149f0e36e0ca0ff35ec6e2f79419b58d529db40msarett            #endif
1011c149f0e36e0ca0ff35ec6e2f79419b58d529db40msarett                SkDebugf("\nBenchmarks still running...\n");
1012c149f0e36e0ca0ff35ec6e2f79419b58d529db40msarett            }
1013c149f0e36e0ca0ff35ec6e2f79419b58d529db40msarett        }
1014c149f0e36e0ca0ff35ec6e2f79419b58d529db40msarett    };
1015c149f0e36e0ca0ff35ec6e2f79419b58d529db40msarett    static SkThread* intentionallyLeaked = new SkThread(Loop::forever);
1016c149f0e36e0ca0ff35ec6e2f79419b58d529db40msarett    intentionallyLeaked->start();
1017c149f0e36e0ca0ff35ec6e2f79419b58d529db40msarett}
1018c149f0e36e0ca0ff35ec6e2f79419b58d529db40msarett
10193b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorioint nanobench_main();
102017f0b6df7248b9bbdaddacc3a6c9c6efe4ae278ecaryclarkint nanobench_main() {
10213b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorio    SetupCrashHandler();
1022f372321de3d4183de5b9ca436e677e471e358f31mtklein    SkAutoGraphics ag;
1023cc29d26f5742449eb2a2bafa7bbb6ec5ee701aefmtklein    SkTaskGroup::Enabler enabled(FLAGS_threads);
1024f372321de3d4183de5b9ca436e677e471e358f31mtklein
102569a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski#if SK_SUPPORT_GPU
1026682c269a1511200322916af83053e26004c0ec40bsalomon    GrContextOptions grContextOpts;
102712b3544028e74712c6c095ed3a2e8a78de6b2ed8krajcevski    grContextOpts.fDrawPathToCompressedTexture = FLAGS_gpuCompressAlphaMasks;
1028385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    gGrFactory.reset(new GrContextFactory(grContextOpts));
102969a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski#endif
103069a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski
103106cddec8570cbf29f89e89736afb0487b5b95abdbsalomon    if (FLAGS_veryVerbose) {
103206cddec8570cbf29f89e89736afb0487b5b95abdbsalomon        FLAGS_verbose = true;
103306cddec8570cbf29f89e89736afb0487b5b95abdbsalomon    }
103406cddec8570cbf29f89e89736afb0487b5b95abdbsalomon
10356eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (kAutoTuneLoops != FLAGS_loops) {
1036a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        FLAGS_samples     = 1;
1037a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        FLAGS_gpuFrameLag = 0;
1038a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein    }
1039a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein
10406eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (!FLAGS_writePath.isEmpty()) {
10416eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Writing files to %s.\n", FLAGS_writePath[0]);
10426eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        if (!sk_mkdir(FLAGS_writePath[0])) {
10436eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            SkDebugf("Could not create %s. Files won't be written.\n", FLAGS_writePath[0]);
104496fcdcc219d2a0d3579719b84b28bede76efba64halcanary            FLAGS_writePath.set(0, nullptr);
10456eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        }
10466eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
10476eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
1048385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    SkAutoTDelete<ResultsWriter> log(new ResultsWriter);
104960317d0ffb5053df7b08a627d6decd11b684e80dmtklein    if (!FLAGS_outResultsFile.isEmpty()) {
10505352015fa318fc6c25b789cb0a81d2d586d6121fmtklein#if defined(SK_RELEASE)
1051385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        log.reset(new NanoJSONResultsWriter(FLAGS_outResultsFile[0]));
10525352015fa318fc6c25b789cb0a81d2d586d6121fmtklein#else
10535352015fa318fc6c25b789cb0a81d2d586d6121fmtklein        SkDebugf("I'm ignoring --outResultsFile because this is a Debug build.");
10545352015fa318fc6c25b789cb0a81d2d586d6121fmtklein        return 1;
10555352015fa318fc6c25b789cb0a81d2d586d6121fmtklein#endif
105660317d0ffb5053df7b08a627d6decd11b684e80dmtklein    }
1057bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio
10581915b62637bea20e1471a8a358b22e9e47a4a385mtklein    if (1 == FLAGS_properties.count() % 2) {
10591915b62637bea20e1471a8a358b22e9e47a4a385mtklein        SkDebugf("ERROR: --properties must be passed with an even number of arguments.\n");
1060bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio        return 1;
1061bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    }
10621915b62637bea20e1471a8a358b22e9e47a4a385mtklein    for (int i = 1; i < FLAGS_properties.count(); i += 2) {
10631915b62637bea20e1471a8a358b22e9e47a4a385mtklein        log->property(FLAGS_properties[i-1], FLAGS_properties[i]);
1064bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    }
106594e51567dd691c3e1e8dfa6005a301d72cecf48emtklein
10661915b62637bea20e1471a8a358b22e9e47a4a385mtklein    if (1 == FLAGS_key.count() % 2) {
10671915b62637bea20e1471a8a358b22e9e47a4a385mtklein        SkDebugf("ERROR: --key must be passed with an even number of arguments.\n");
106894e51567dd691c3e1e8dfa6005a301d72cecf48emtklein        return 1;
106994e51567dd691c3e1e8dfa6005a301d72cecf48emtklein    }
10701915b62637bea20e1471a8a358b22e9e47a4a385mtklein    for (int i = 1; i < FLAGS_key.count(); i += 2) {
10711915b62637bea20e1471a8a358b22e9e47a4a385mtklein        log->key(FLAGS_key[i-1], FLAGS_key[i]);
107294e51567dd691c3e1e8dfa6005a301d72cecf48emtklein    }
107360317d0ffb5053df7b08a627d6decd11b684e80dmtklein
1074f372321de3d4183de5b9ca436e677e471e358f31mtklein    const double overhead = estimate_timer_overhead();
107555b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    SkDebugf("Timer overhead: %s\n", HUMANIZE(overhead));
1076912947737a973421f4c58682b6171cb5ee00ad3aMike Klein
1077e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton    SkTArray<double> samples;
1078bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
10796eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (kAutoTuneLoops != FLAGS_loops) {
10806eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Fixed number of loops; times would only be misleading so we won't print them.\n");
1081f372321de3d4183de5b9ca436e677e471e358f31mtklein    } else if (FLAGS_quiet) {
108266cfcffd5d0a430f00bf0e36bedb088a25957183mtklein        SkDebugf("! -> high variance, ? -> moderate variance\n");
108366cfcffd5d0a430f00bf0e36bedb088a25957183mtklein        SkDebugf("    micros   \tbench\n");
1084bbba16878f343b232d844281fbdf056c00e20fb6mtklein    } else if (FLAGS_ms) {
1085e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton        SkDebugf("curr/maxrss\tloops\tmin\tmedian\tmean\tmax\tstddev\tsamples\tconfig\tbench\n");
1086f372321de3d4183de5b9ca436e677e471e358f31mtklein    } else {
1087d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein        SkDebugf("curr/maxrss\tloops\tmin\tmedian\tmean\tmax\tstddev\t%-*s\tconfig\tbench\n",
10888247ec313d87afcdd4da59b1f2f0d24e0983e359qiankun.miao                 FLAGS_samples, "samples");
1089f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
1090f372321de3d4183de5b9ca436e677e471e358f31mtklein
1091c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen    SkTArray<Config> configs;
1092c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    create_configs(&configs);
1093c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
10943ebd050be551e9d1364dbd115708e8f86397cd6fjoshualitt#ifdef THERMAL_MANAGER_SUPPORTED
10953ebd050be551e9d1364dbd115708e8f86397cd6fjoshualitt    int tmEnabled, tmThreshold, tmSleepTimeMs, tmTimeoutMs;
10963ebd050be551e9d1364dbd115708e8f86397cd6fjoshualitt    if (4 != sscanf(FLAGS_useThermalManager[0], "%d,%d,%d,%d",
10973ebd050be551e9d1364dbd115708e8f86397cd6fjoshualitt                    &tmEnabled, &tmThreshold, &tmSleepTimeMs, &tmTimeoutMs)) {
10983ebd050be551e9d1364dbd115708e8f86397cd6fjoshualitt        SkDebugf("Can't parse %s from --useThermalManager.\n", FLAGS_useThermalManager[0]);
10993ebd050be551e9d1364dbd115708e8f86397cd6fjoshualitt        exit(1);
11003ebd050be551e9d1364dbd115708e8f86397cd6fjoshualitt    }
11013ebd050be551e9d1364dbd115708e8f86397cd6fjoshualitt    ThermalManager tm(tmThreshold, tmSleepTimeMs, tmTimeoutMs);
11023ebd050be551e9d1364dbd115708e8f86397cd6fjoshualitt#endif
11033ebd050be551e9d1364dbd115708e8f86397cd6fjoshualitt
1104c149f0e36e0ca0ff35ec6e2f79419b58d529db40msarett    if (FLAGS_keepAlive) {
1105c149f0e36e0ca0ff35ec6e2f79419b58d529db40msarett        start_keepalive();
1106c149f0e36e0ca0ff35ec6e2f79419b58d529db40msarett    }
1107c149f0e36e0ca0ff35ec6e2f79419b58d529db40msarett
1108e070c2bf54c451f0126d4ffb3a48bffe1fbfa437mtklein    int runs = 0;
110992007583e43115998412ac8b0a06cc2780eb025cmtklein    BenchmarkStream benchStream;
111092007583e43115998412ac8b0a06cc2780eb025cmtklein    while (Benchmark* b = benchStream.next()) {
1111e714e75c725c987fe682a1f5473224fe3e80380dmtklein        SkAutoTDelete<Benchmark> bench(b);
1112962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein        if (SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getUniqueName())) {
1113f372321de3d4183de5b9ca436e677e471e358f31mtklein            continue;
1114f372321de3d4183de5b9ca436e677e471e358f31mtklein        }
1115f372321de3d4183de5b9ca436e677e471e358f31mtklein
1116c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen        if (!configs.empty()) {
1117962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein            log->bench(bench->getUniqueName(), bench->getSize().fX, bench->getSize().fY);
11188a6697af95b340aad6dee7e6228048fa305c1e59joshualitt            bench->delayedSetup();
1119bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio        }
11203bf9206ada256277a39988c263f0379d544fc27begdaniel        for (int i = 0; i < configs.count(); ++i) {
11213ebd050be551e9d1364dbd115708e8f86397cd6fjoshualitt#ifdef THERMAL_MANAGER_SUPPORTED
11223ebd050be551e9d1364dbd115708e8f86397cd6fjoshualitt            if (tmEnabled && !tm.coolOffIfNecessary()) {
11233ebd050be551e9d1364dbd115708e8f86397cd6fjoshualitt                SkDebugf("Could not cool off, timings will be throttled\n");
11243ebd050be551e9d1364dbd115708e8f86397cd6fjoshualitt            }
11253ebd050be551e9d1364dbd115708e8f86397cd6fjoshualitt#endif
11263bf9206ada256277a39988c263f0379d544fc27begdaniel            Target* target = is_enabled(b, configs[i]);
11273bf9206ada256277a39988c263f0379d544fc27begdaniel            if (!target) {
11283bf9206ada256277a39988c263f0379d544fc27begdaniel                continue;
11293bf9206ada256277a39988c263f0379d544fc27begdaniel            }
11303bf9206ada256277a39988c263f0379d544fc27begdaniel
113196fcdcc219d2a0d3579719b84b28bede76efba64halcanary            // During HWUI output this canvas may be nullptr.
11323bf9206ada256277a39988c263f0379d544fc27begdaniel            SkCanvas* canvas = target->getCanvas();
1133c47635e0ed52970fa40a16ffb280071e6b838a52svaisanen            const char* config = target->config.name.c_str();
1134bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
11357a5ada8c429b99b6ea061d7ea710d3c8349502acbrianosman            if (FLAGS_pre_log || FLAGS_dryRun) {
11368d61f0dd1b6fde5202a14dfafcc1bceccf0d74adbenjaminwagner                SkDebugf("Running %s\t%s\n"
11378d61f0dd1b6fde5202a14dfafcc1bceccf0d74adbenjaminwagner                         , bench->getUniqueName()
11388d61f0dd1b6fde5202a14dfafcc1bceccf0d74adbenjaminwagner                         , config);
11397a5ada8c429b99b6ea061d7ea710d3c8349502acbrianosman                if (FLAGS_dryRun) {
11407a5ada8c429b99b6ea061d7ea710d3c8349502acbrianosman                    continue;
11417a5ada8c429b99b6ea061d7ea710d3c8349502acbrianosman                }
11428d61f0dd1b6fde5202a14dfafcc1bceccf0d74adbenjaminwagner            }
11438d61f0dd1b6fde5202a14dfafcc1bceccf0d74adbenjaminwagner
11443bf9206ada256277a39988c263f0379d544fc27begdaniel            target->setup();
11455b69377507478623dcf5b11f3ecb010f87c4794frobertphillips            bench->perCanvasPreDraw(canvas);
11465b69377507478623dcf5b11f3ecb010f87c4794frobertphillips
1147e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton            int maxFrameLag;
1148a1ebeb25e9acfcd801e089e063311d716b83b8a5mtklein            int loops = target->needsFrameTiming(&maxFrameLag)
11493bf9206ada256277a39988c263f0379d544fc27begdaniel                ? setup_gpu_bench(target, bench.get(), maxFrameLag)
11503bf9206ada256277a39988c263f0379d544fc27begdaniel                : setup_cpu_bench(overhead, target, bench.get());
1151e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton
1152bbba16878f343b232d844281fbdf056c00e20fb6mtklein            if (FLAGS_ms) {
1153bbba16878f343b232d844281fbdf056c00e20fb6mtklein                samples.reset();
1154bbba16878f343b232d844281fbdf056c00e20fb6mtklein                auto stop = now_ms() + FLAGS_ms;
1155bbba16878f343b232d844281fbdf056c00e20fb6mtklein                do {
1156bbba16878f343b232d844281fbdf056c00e20fb6mtklein                    samples.push_back(time(loops, bench, target) / loops);
1157bbba16878f343b232d844281fbdf056c00e20fb6mtklein                } while (now_ms() < stop);
1158bbba16878f343b232d844281fbdf056c00e20fb6mtklein            } else {
1159e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton                samples.reset(FLAGS_samples);
1160e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton                for (int s = 0; s < FLAGS_samples; s++) {
11613bf9206ada256277a39988c263f0379d544fc27begdaniel                    samples[s] = time(loops, bench, target) / loops;
1162e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton                }
1163e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton            }
1164f372321de3d4183de5b9ca436e677e471e358f31mtklein
1165e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt#if SK_SUPPORT_GPU
1166e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt            SkTArray<SkString> keys;
1167e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt            SkTArray<double> values;
1168e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt            bool gpuStatsDump = FLAGS_gpuStatsDump && Benchmark::kGPU_Backend == configs[i].backend;
1169e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt            if (gpuStatsDump) {
1170e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt                // TODO cache stats
1171e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt                bench->getGpuStats(canvas, &keys, &values);
1172e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt            }
1173e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt#endif
1174e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt
11755b69377507478623dcf5b11f3ecb010f87c4794frobertphillips            bench->perCanvasPostDraw(canvas);
11765b69377507478623dcf5b11f3ecb010f87c4794frobertphillips
11773bf9206ada256277a39988c263f0379d544fc27begdaniel            if (Benchmark::kNonRendering_Backend != target->config.backend &&
1178d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson                !FLAGS_writePath.isEmpty() && FLAGS_writePath[0]) {
11796eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                SkString pngFilename = SkOSPath::Join(FLAGS_writePath[0], config);
1180962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein                pngFilename = SkOSPath::Join(pngFilename.c_str(), bench->getUniqueName());
11816eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                pngFilename.append(".png");
11823bf9206ada256277a39988c263f0379d544fc27begdaniel                write_canvas_png(target, pngFilename);
11836eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            }
11846eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
11856eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            if (kFailedLoops == loops) {
11862069e220034f09aad2f68b262f395e7c25b3d178mtklein                // Can't be timed.  A warning note has already been printed.
11873bf9206ada256277a39988c263f0379d544fc27begdaniel                cleanup_run(target);
1188e3631364e93ee9164f3ce322778d5a50c33f63a6Mike Klein                continue;
1189e3631364e93ee9164f3ce322778d5a50c33f63a6Mike Klein            }
119060317d0ffb5053df7b08a627d6decd11b684e80dmtklein
1191e1b8958877a512bf83cbc2c72bb31e7d71b06f43cdalton            Stats stats(samples);
11921915b62637bea20e1471a8a358b22e9e47a4a385mtklein            log->config(config);
1193962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein            log->configOption("name", bench->getName());
11941915b62637bea20e1471a8a358b22e9e47a4a385mtklein            benchStream.fillCurrentOptions(log.get());
11953bf9206ada256277a39988c263f0379d544fc27begdaniel            target->fillOptions(log.get());
1196051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein            log->metric("min_ms",    stats.min);
1197e5cf2c6d940fa6a1d7c3016f631c734d3d29dec2mtklein            log->metric("median_ms", stats.median);
1198e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt#if SK_SUPPORT_GPU
1199e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt            if (gpuStatsDump) {
1200e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt                // dump to json, only SKPBench currently returns valid keys / values
1201e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt                SkASSERT(keys.count() == values.count());
1202e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt                for (int i = 0; i < keys.count(); i++) {
1203e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt                    log->metric(keys[i].c_str(), values[i]);
1204e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt                }
1205e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt            }
1206e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt#endif
1207e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt
1208e070c2bf54c451f0126d4ffb3a48bffe1fbfa437mtklein            if (runs++ % FLAGS_flushEvery == 0) {
1209e070c2bf54c451f0126d4ffb3a48bffe1fbfa437mtklein                log->flush();
1210e070c2bf54c451f0126d4ffb3a48bffe1fbfa437mtklein            }
121160317d0ffb5053df7b08a627d6decd11b684e80dmtklein
12126eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            if (kAutoTuneLoops != FLAGS_loops) {
12133bf9206ada256277a39988c263f0379d544fc27begdaniel                if (configs.count() == 1) {
1214a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein                    config = ""; // Only print the config if we run the same bench on more than one.
1215a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein                }
1216d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein                SkDebugf("%4d/%-4dMB\t%s\t%s\n"
1217d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein                         , sk_tools::getCurrResidentSetSizeMB()
1218d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein                         , sk_tools::getMaxResidentSetSizeMB()
121953d2562006ee371222963750009a706cfd1a94f7mtklein                         , bench->getUniqueName()
122053d2562006ee371222963750009a706cfd1a94f7mtklein                         , config);
1221f372321de3d4183de5b9ca436e677e471e358f31mtklein            } else if (FLAGS_quiet) {
122266cfcffd5d0a430f00bf0e36bedb088a25957183mtklein                const char* mark = " ";
122366cfcffd5d0a430f00bf0e36bedb088a25957183mtklein                const double stddev_percent = 100 * sqrt(stats.var) / stats.mean;
122466cfcffd5d0a430f00bf0e36bedb088a25957183mtklein                if (stddev_percent >  5) mark = "?";
122566cfcffd5d0a430f00bf0e36bedb088a25957183mtklein                if (stddev_percent > 10) mark = "!";
122666cfcffd5d0a430f00bf0e36bedb088a25957183mtklein
122766cfcffd5d0a430f00bf0e36bedb088a25957183mtklein                SkDebugf("%10.2f %s\t%s\t%s\n",
122866cfcffd5d0a430f00bf0e36bedb088a25957183mtklein                         stats.median*1e3, mark, bench->getUniqueName(), config);
1229f372321de3d4183de5b9ca436e677e471e358f31mtklein            } else {
1230f372321de3d4183de5b9ca436e677e471e358f31mtklein                const double stddev_percent = 100 * sqrt(stats.var) / stats.mean;
1231d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein                SkDebugf("%4d/%-4dMB\t%d\t%s\t%s\t%s\t%s\t%.0f%%\t%s\t%s\t%s\n"
1232d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein                        , sk_tools::getCurrResidentSetSizeMB()
1233d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein                        , sk_tools::getMaxResidentSetSizeMB()
1234f372321de3d4183de5b9ca436e677e471e358f31mtklein                        , loops
123555b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein                        , HUMANIZE(stats.min)
123655b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein                        , HUMANIZE(stats.median)
123755b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein                        , HUMANIZE(stats.mean)
123855b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein                        , HUMANIZE(stats.max)
1239f372321de3d4183de5b9ca436e677e471e358f31mtklein                        , stddev_percent
1240bbba16878f343b232d844281fbdf056c00e20fb6mtklein                        , FLAGS_ms ? to_string(samples.count()).c_str() : stats.plot.c_str()
1241f372321de3d4183de5b9ca436e677e471e358f31mtklein                        , config
1242962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein                        , bench->getUniqueName()
1243f372321de3d4183de5b9ca436e677e471e358f31mtklein                        );
1244f372321de3d4183de5b9ca436e677e471e358f31mtklein            }
1245e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt
1246b12ea41286ce36e085c5a14711da0cf9f240fdf1bsalomon#if SK_SUPPORT_GPU
1247e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt            if (FLAGS_gpuStats && Benchmark::kGPU_Backend == configs[i].backend) {
12485219fd9ff7aa6ebf64c905ad40f5e0027a39962bkkinnunen                GrContext* context = gGrFactory->get(configs[i].ctxType,
12493e980c3d88fbc509b79e7ccef16ca38f5bbfb180kkinnunen                                                     configs[i].ctxOptions);
12505219fd9ff7aa6ebf64c905ad40f5e0027a39962bkkinnunen                context->printCacheStats();
12515219fd9ff7aa6ebf64c905ad40f5e0027a39962bkkinnunen                context->printGpuStats();
125206cddec8570cbf29f89e89736afb0487b5b95abdbsalomon            }
125306cddec8570cbf29f89e89736afb0487b5b95abdbsalomon#endif
1254e45c81c8f3bb62e45f2ff3b8772b4b23f1ddc6cajoshualitt
12552c56ba5cde25a5cdbeca2afd660b497b428e8f07cdalton            if (FLAGS_verbose) {
12562c56ba5cde25a5cdbeca2afd660b497b428e8f07cdalton                SkDebugf("Samples:  ");
12572c56ba5cde25a5cdbeca2afd660b497b428e8f07cdalton                for (int i = 0; i < samples.count(); i++) {
12582c56ba5cde25a5cdbeca2afd660b497b428e8f07cdalton                    SkDebugf("%s  ", HUMANIZE(samples[i]));
12592c56ba5cde25a5cdbeca2afd660b497b428e8f07cdalton                }
12602c56ba5cde25a5cdbeca2afd660b497b428e8f07cdalton                SkDebugf("%s\n", bench->getUniqueName());
12612c56ba5cde25a5cdbeca2afd660b497b428e8f07cdalton            }
12623bf9206ada256277a39988c263f0379d544fc27begdaniel            cleanup_run(target);
1263f372321de3d4183de5b9ca436e677e471e358f31mtklein        }
1264f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
1265f372321de3d4183de5b9ca436e677e471e358f31mtklein
1266e109145bf31d63963b3f78c6af6e404d5464a55bmtklein    log->bench("memory_usage", 0,0);
1267e109145bf31d63963b3f78c6af6e404d5464a55bmtklein    log->config("meta");
1268e109145bf31d63963b3f78c6af6e404d5464a55bmtklein    log->metric("max_rss_mb", sk_tools::getMaxResidentSetSizeMB());
1269e109145bf31d63963b3f78c6af6e404d5464a55bmtklein
1270e0b19d4985846d64bb581013828a9dc5af401a5djoshualitt#if SK_SUPPORT_GPU
1271e0b19d4985846d64bb581013828a9dc5af401a5djoshualitt    // Make sure we clean up the global GrContextFactory here, otherwise we might race with the
1272e0b19d4985846d64bb581013828a9dc5af401a5djoshualitt    // SkEventTracer destructor
127396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    gGrFactory.reset(nullptr);
1274e0b19d4985846d64bb581013828a9dc5af401a5djoshualitt#endif
1275e0b19d4985846d64bb581013828a9dc5af401a5djoshualitt
1276f372321de3d4183de5b9ca436e677e471e358f31mtklein    return 0;
1277f372321de3d4183de5b9ca436e677e471e358f31mtklein}
1278f372321de3d4183de5b9ca436e677e471e358f31mtklein
12793b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorio#if !defined SK_BUILD_FOR_IOS
12803b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorioint main(int argc, char** argv) {
12813b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorio    SkCommandLineFlags::Parse(argc, argv);
12823b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorio    return nanobench_main();
12833b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorio}
12843b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorio#endif
1285