nanobench.cpp revision 762286309545c8a1e4bbc05dcd1fe3085d2a1f47
1f372321de3d4183de5b9ca436e677e471e358f31mtklein/*
2f372321de3d4183de5b9ca436e677e471e358f31mtklein * Copyright 2014 Google Inc.
3f372321de3d4183de5b9ca436e677e471e358f31mtklein *
4f372321de3d4183de5b9ca436e677e471e358f31mtklein * Use of this source code is governed by a BSD-style license that can be
5f372321de3d4183de5b9ca436e677e471e358f31mtklein * found in the LICENSE file.
6f372321de3d4183de5b9ca436e677e471e358f31mtklein */
7f372321de3d4183de5b9ca436e677e471e358f31mtklein
8bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#include <ctype.h>
9bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
10d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson#include "nanobench.h"
11d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
12f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "Benchmark.h"
1360869a42a133942f852dd0f1696444c2a5c9ad83scroggo#include "CodecBench.h"
14f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "CrashHandler.h"
1595f192d19938b98a45dd1fa4112d965f60d10516msarett#include "DecodingBench.h"
1695f192d19938b98a45dd1fa4112d965f60d10516msarett#include "DecodingSubsetBench.h"
17e714e75c725c987fe682a1f5473224fe3e80380dmtklein#include "GMBench.h"
18afb4379dbca4d4d3824ace183a7348d24bc1589fmtklein#include "ProcStats.h"
1960317d0ffb5053df7b08a627d6decd11b684e80dmtklein#include "ResultsWriter.h"
20fd731ce804cd3223318f3feee2c98404890b65f2mtklein#include "RecordingBench.h"
21261c3ad7fde95748da92550735decc949dc73bf2joshualitt#include "SKPAnimationBench.h"
2292007583e43115998412ac8b0a06cc2780eb025cmtklein#include "SKPBench.h"
23f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "Stats.h"
24f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "Timer.h"
25f372321de3d4183de5b9ca436e677e471e358f31mtklein
266838d854a87e79f1fbb7b89b9f395155ad44dc0amtklein#include "SkBBoxHierarchy.h"
27f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "SkCanvas.h"
2860869a42a133942f852dd0f1696444c2a5c9ad83scroggo#include "SkCodec.h"
2917f0b6df7248b9bbdaddacc3a6c9c6efe4ae278ecaryclark#include "SkCommonFlags.h"
3095f192d19938b98a45dd1fa4112d965f60d10516msarett#include "SkData.h"
31f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "SkForceLinking.h"
32f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "SkGraphics.h"
332084050a33ae139d0fe9bb680f7905f91139a39fmtklein#include "SkOSFile.h"
342084050a33ae139d0fe9bb680f7905f91139a39fmtklein#include "SkPictureRecorder.h"
35051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein#include "SkPictureUtils.h"
36f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "SkString.h"
37f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "SkSurface.h"
385b69377507478623dcf5b11f3ecb010f87c4794frobertphillips#include "SkTaskGroup.h"
39f372321de3d4183de5b9ca436e677e471e358f31mtklein
40d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
41d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    #include "nanobenchAndroid.h"
42d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson#endif
43d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
44bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#if SK_SUPPORT_GPU
45bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    #include "gl/GrGLDefines.h"
46762286309545c8a1e4bbc05dcd1fe3085d2a1f47bsalomon    #include "GrCaps.h"
47bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    #include "GrContextFactory.h"
4869a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski    SkAutoTDelete<GrContextFactory> gGrFactory;
49bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#endif
50bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
51682c269a1511200322916af83053e26004c0ec40bsalomon    struct GrContextOptions;
52682c269a1511200322916af83053e26004c0ec40bsalomon
53f372321de3d4183de5b9ca436e677e471e358f31mtklein__SK_FORCE_IMAGE_DECODER_LINKING;
54f372321de3d4183de5b9ca436e677e471e358f31mtklein
555324978a88677ac6b758324321816427814e7793reedstatic const int kAutoTuneLoops = 0;
566eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
57b511042bb07a6a289b0d1146cb57f6e8b80580d6mtkleinstatic const int kDefaultLoops =
586eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon#ifdef SK_DEBUG
596eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    1;
60a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein#else
616eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    kAutoTuneLoops;
62a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein#endif
63a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein
646eb03cc06d0bc60da5277a83aa0251a475794b04bsalomonstatic SkString loops_help_txt() {
656eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    SkString help;
666eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    help.printf("Number of times to run each bench. Set this to %d to auto-"
676eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                "tune for each bench. Timings are only reported when auto-tuning.",
686eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                kAutoTuneLoops);
696eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    return help;
706eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon}
716eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
726eb03cc06d0bc60da5277a83aa0251a475794b04bsalomonDEFINE_int32(loops, kDefaultLoops, loops_help_txt().c_str());
736eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
74f372321de3d4183de5b9ca436e677e471e358f31mtkleinDEFINE_int32(samples, 10, "Number of samples to measure for each bench.");
75f372321de3d4183de5b9ca436e677e471e358f31mtkleinDEFINE_int32(overheadLoops, 100000, "Loops to estimate timer overhead.");
76f372321de3d4183de5b9ca436e677e471e358f31mtkleinDEFINE_double(overheadGoal, 0.0001,
77f372321de3d4183de5b9ca436e677e471e358f31mtklein              "Loop until timer overhead is at most this fraction of our measurments.");
78bb6a02823929584231c8e080ee69e7fb1178cbfbmtkleinDEFINE_double(gpuMs, 5, "Target bench time in millseconds for GPU.");
79bb6a02823929584231c8e080ee69e7fb1178cbfbmtkleinDEFINE_int32(gpuFrameLag, 5, "Overestimate of maximum number of frames GPU allows to lag.");
8012b3544028e74712c6c095ed3a2e8a78de6b2ed8krajcevskiDEFINE_bool(gpuCompressAlphaMasks, false, "Compress masks generated from falling back to "
8112b3544028e74712c6c095ed3a2e8a78de6b2ed8krajcevski                                          "software path rendering.");
82f372321de3d4183de5b9ca436e677e471e358f31mtklein
8360317d0ffb5053df7b08a627d6decd11b684e80dmtkleinDEFINE_string(outResultsFile, "", "If given, write results here as JSON.");
8455b0ffc4861e940d8bcf767ff9abf44ff18545eamtkleinDEFINE_int32(maxCalibrationAttempts, 3,
8555b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein             "Try up to this many times to guess loops for a bench, or skip the bench.");
8655b0ffc4861e940d8bcf767ff9abf44ff18545eamtkleinDEFINE_int32(maxLoops, 1000000, "Never run a bench more times than this.");
8792007583e43115998412ac8b0a06cc2780eb025cmtkleinDEFINE_string(clip, "0,0,1000,1000", "Clip for SKPs.");
8892007583e43115998412ac8b0a06cc2780eb025cmtkleinDEFINE_string(scales, "1.0", "Space-separated scales for SKPs.");
89261c3ad7fde95748da92550735decc949dc73bf2joshualittDEFINE_string(zoom, "1.0,1", "Comma-separated scale,step zoom factors for SKPs.");
902084050a33ae139d0fe9bb680f7905f91139a39fmtkleinDEFINE_bool(bbh, true, "Build a BBH for SKPs?");
915b69377507478623dcf5b11f3ecb010f87c4794frobertphillipsDEFINE_bool(mpd, true, "Use MultiPictureDraw for the SKPs?");
92e070c2bf54c451f0126d4ffb3a48bffe1fbfa437mtkleinDEFINE_int32(flushEvery, 10, "Flush --outResultsFile every Nth run.");
9355e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtkleinDEFINE_bool(resetGpuContext, true, "Reset the GrContext before running each test.");
94b12ea41286ce36e085c5a14711da0cf9f240fdf1bsalomonDEFINE_bool(gpuStats, false, "Print GPU stats after each gpu benchmark?");
9592007583e43115998412ac8b0a06cc2780eb025cmtklein
96f372321de3d4183de5b9ca436e677e471e358f31mtkleinstatic SkString humanize(double ms) {
97dc5bbab138bfffc85d6ba525d990aad09c322ff6mtklein    if (FLAGS_verbose) return SkStringPrintf("%llu", (uint64_t)(ms*1e6));
98748ca3bf2d170708f263693e8579e6722389d0efmtklein    return HumanizeMs(ms);
99f372321de3d4183de5b9ca436e677e471e358f31mtklein}
10055b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein#define HUMANIZE(ms) humanize(ms).c_str()
101f372321de3d4183de5b9ca436e677e471e358f31mtklein
102d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudsonbool Target::init(SkImageInfo info, Benchmark* bench) {
103d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    if (Benchmark::kRaster_Backend == config.backend) {
104d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        this->surface.reset(SkSurface::NewRaster(info));
105d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        if (!this->surface.get()) {
106d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson            return false;
107d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        }
108d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
109d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    return true;
110d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson}
111d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudsonbool Target::capturePixels(SkBitmap* bmp) {
11275a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson    SkCanvas* canvas = this->getCanvas();
113d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    if (!canvas) {
114d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        return false;
115d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
116d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    bmp->setInfo(canvas->imageInfo());
117d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    if (!canvas->readPixels(bmp, 0, 0)) {
118d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        SkDebugf("Can't read canvas pixels.\n");
119d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        return false;
120d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
121d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    return true;
122d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson}
123d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
124d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson#if SK_SUPPORT_GPU
125d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudsonstruct GPUTarget : public Target {
126d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    explicit GPUTarget(const Config& c) : Target(c), gl(NULL) { }
127d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    SkGLContext* gl;
128d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
129d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    void setup() override {
130d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        this->gl->makeCurrent();
131d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        // Make sure we're done with whatever came before.
132d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        SK_GL(*this->gl, Finish());
133d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
134d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    void endTiming() override {
135d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        if (this->gl) {
136d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson            SK_GL(*this->gl, Flush());
137d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson            this->gl->swapBuffers();
138d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        }
139d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
140d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    void fence() override {
141d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        SK_GL(*this->gl, Finish());
142d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
143d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein
144d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    bool needsFrameTiming() const override { return true; }
145d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    bool init(SkImageInfo info, Benchmark* bench) override {
146d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        uint32_t flags = this->config.useDFText ? SkSurfaceProps::kUseDistanceFieldFonts_Flag : 0;
147d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType);
148d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        this->surface.reset(SkSurface::NewRenderTarget(gGrFactory->get(this->config.ctxType),
149d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson                                                         SkSurface::kNo_Budgeted, info,
150d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson                                                         this->config.samples, &props));
151d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        this->gl = gGrFactory->getGLContext(this->config.ctxType);
152d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        if (!this->surface.get()) {
153d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson            return false;
154d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        }
155d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        return true;
156d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
157d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    void fillOptions(ResultsWriter* log) override {
158d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        const GrGLubyte* version;
159d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        SK_GL_RET(*this->gl, version, GetString(GR_GL_VERSION));
160d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        log->configOption("GL_VERSION", (const char*)(version));
161d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
162d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        SK_GL_RET(*this->gl, version, GetString(GR_GL_RENDERER));
163d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        log->configOption("GL_RENDERER", (const char*) version);
164d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
165d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        SK_GL_RET(*this->gl, version, GetString(GR_GL_VENDOR));
166d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        log->configOption("GL_VENDOR", (const char*) version);
167d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
168d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        SK_GL_RET(*this->gl, version, GetString(GR_GL_SHADING_LANGUAGE_VERSION));
169d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        log->configOption("GL_SHADING_LANGUAGE_VERSION", (const char*) version);
170d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
171d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson};
172d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein
173d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson#endif
174d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
17575a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudsonstatic double time(int loops, Benchmark* bench, Target* target) {
17675a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson    SkCanvas* canvas = target->getCanvas();
1776eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (canvas) {
1786eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        canvas->clear(SK_ColorWHITE);
1796eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
180f372321de3d4183de5b9ca436e677e471e358f31mtklein    WallTimer timer;
181bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    timer.start();
18275a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson    canvas = target->beginTiming(canvas);
18375a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson    bench->draw(loops, canvas);
184f372321de3d4183de5b9ca436e677e471e358f31mtklein    if (canvas) {
185f372321de3d4183de5b9ca436e677e471e358f31mtklein        canvas->flush();
186f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
18775a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson    target->endTiming();
188bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    timer.end();
189bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    return timer.fWall;
190f372321de3d4183de5b9ca436e677e471e358f31mtklein}
191f372321de3d4183de5b9ca436e677e471e358f31mtklein
192bb6a02823929584231c8e080ee69e7fb1178cbfbmtkleinstatic double estimate_timer_overhead() {
193bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    double overhead = 0;
194bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    for (int i = 0; i < FLAGS_overheadLoops; i++) {
19575a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson        WallTimer timer;
19675a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson        timer.start();
19775a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson        timer.end();
19875a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson        overhead += timer.fWall;
199bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    }
200bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    return overhead / FLAGS_overheadLoops;
201bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein}
202f372321de3d4183de5b9ca436e677e471e358f31mtklein
2035324978a88677ac6b758324321816427814e7793reedstatic int detect_forever_loops(int loops) {
2045324978a88677ac6b758324321816427814e7793reed    // look for a magic run-forever value
2055324978a88677ac6b758324321816427814e7793reed    if (loops < 0) {
2065324978a88677ac6b758324321816427814e7793reed        loops = SK_MaxS32;
2075324978a88677ac6b758324321816427814e7793reed    }
2085324978a88677ac6b758324321816427814e7793reed    return loops;
2095324978a88677ac6b758324321816427814e7793reed}
2105324978a88677ac6b758324321816427814e7793reed
21155b0ffc4861e940d8bcf767ff9abf44ff18545eamtkleinstatic int clamp_loops(int loops) {
21255b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    if (loops < 1) {
213527930fdbbba2a20f98b43821c6b72367e7b2d64mtklein        SkDebugf("ERROR: clamping loops from %d to 1. "
214527930fdbbba2a20f98b43821c6b72367e7b2d64mtklein                 "There's probably something wrong with the bench.\n", loops);
21555b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein        return 1;
21655b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    }
21755b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    if (loops > FLAGS_maxLoops) {
21855b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein        SkDebugf("WARNING: clamping loops from %d to FLAGS_maxLoops, %d.\n", loops, FLAGS_maxLoops);
21955b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein        return FLAGS_maxLoops;
22055b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    }
22155b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    return loops;
22255b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein}
22355b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein
224d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudsonstatic bool write_canvas_png(Target* target, const SkString& filename) {
225d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
2266eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (filename.isEmpty()) {
2276eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
2286eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
22975a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson    if (target->getCanvas() &&
23075a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson        kUnknown_SkColorType == target->getCanvas()->imageInfo().colorType()) {
2316eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
2326eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
233d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
2346eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    SkBitmap bmp;
235d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
236d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    if (!target->capturePixels(&bmp)) {
2376eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
2386eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
239d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
2406eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    SkString dir = SkOSPath::Dirname(filename.c_str());
2416eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (!sk_mkdir(dir.c_str())) {
2426eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Can't make dir %s.\n", dir.c_str());
2436eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
2446eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
2456eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    SkFILEWStream stream(filename.c_str());
2466eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (!stream.isValid()) {
2476eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Can't write %s.\n", filename.c_str());
2486eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
2496eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
2506eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (!SkImageEncoder::EncodeStream(&stream, bmp, SkImageEncoder::kPNG_Type, 100)) {
2516eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Can't encode a PNG.\n");
2526eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
2536eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
2546eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    return true;
2556eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon}
2566eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
2576eb03cc06d0bc60da5277a83aa0251a475794b04bsalomonstatic int kFailedLoops = -2;
25875a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudsonstatic int cpu_bench(const double overhead, Target* target, Benchmark* bench, double* samples) {
259bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // First figure out approximately how many loops of bench it takes to make overhead negligible.
2602069e220034f09aad2f68b262f395e7c25b3d178mtklein    double bench_plus_overhead = 0.0;
26155b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    int round = 0;
2626eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (kAutoTuneLoops == FLAGS_loops) {
2636eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        while (bench_plus_overhead < overhead) {
2646eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            if (round++ == FLAGS_maxCalibrationAttempts) {
2656eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                SkDebugf("WARNING: Can't estimate loops for %s (%s vs. %s); skipping.\n",
266962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein                         bench->getUniqueName(), HUMANIZE(bench_plus_overhead), HUMANIZE(overhead));
2676eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                return kFailedLoops;
2686eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            }
26975a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson            bench_plus_overhead = time(1, bench, target);
27055b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein        }
2712069e220034f09aad2f68b262f395e7c25b3d178mtklein    }
272f372321de3d4183de5b9ca436e677e471e358f31mtklein
273bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // Later we'll just start and stop the timer once but loop N times.
274f372321de3d4183de5b9ca436e677e471e358f31mtklein    // We'll pick N to make timer overhead negligible:
275f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
276bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //          overhead
277bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //  -------------------------  < FLAGS_overheadGoal
278bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //  overhead + N * Bench Time
279f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
280bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // where bench_plus_overhead ≈ overhead + Bench Time.
281f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
282f372321de3d4183de5b9ca436e677e471e358f31mtklein    // Doing some math, we get:
283f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
284bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //  (overhead / FLAGS_overheadGoal) - overhead
285bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //  ------------------------------------------  < N
286bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //       bench_plus_overhead - overhead)
287f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
288f372321de3d4183de5b9ca436e677e471e358f31mtklein    // Luckily, this also works well in practice. :)
2896eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    int loops = FLAGS_loops;
2906eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (kAutoTuneLoops == loops) {
2916eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        const double numer = overhead / FLAGS_overheadGoal - overhead;
2926eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        const double denom = bench_plus_overhead - overhead;
2936eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        loops = (int)ceil(numer / denom);
2945324978a88677ac6b758324321816427814e7793reed        loops = clamp_loops(loops);
2955324978a88677ac6b758324321816427814e7793reed    } else {
2965324978a88677ac6b758324321816427814e7793reed        loops = detect_forever_loops(loops);
2976eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
298bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
299bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    for (int i = 0; i < FLAGS_samples; i++) {
30075a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson        samples[i] = time(loops, bench, target) / loops;
301bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    }
302bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    return loops;
303f372321de3d4183de5b9ca436e677e471e358f31mtklein}
304f372321de3d4183de5b9ca436e677e471e358f31mtklein
305d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudsonstatic int gpu_bench(Target* target,
3065b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                     Benchmark* bench,
3075b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                     double* samples) {
308bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // First, figure out how many loops it'll take to get a frame up to FLAGS_gpuMs.
3096eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    int loops = FLAGS_loops;
3106eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (kAutoTuneLoops == loops) {
3116eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        loops = 1;
312a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        double elapsed = 0;
313a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        do {
314527930fdbbba2a20f98b43821c6b72367e7b2d64mtklein            if (1<<30 == loops) {
315527930fdbbba2a20f98b43821c6b72367e7b2d64mtklein                // We're about to wrap.  Something's wrong with the bench.
316527930fdbbba2a20f98b43821c6b72367e7b2d64mtklein                loops = 0;
317527930fdbbba2a20f98b43821c6b72367e7b2d64mtklein                break;
318527930fdbbba2a20f98b43821c6b72367e7b2d64mtklein            }
319a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            loops *= 2;
320a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            // If the GPU lets frames lag at all, we need to make sure we're timing
321a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            // _this_ round, not still timing last round.  We force this by looping
322a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            // more times than any reasonable GPU will allow frames to lag.
323a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            for (int i = 0; i < FLAGS_gpuFrameLag; i++) {
32475a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson                elapsed = time(loops, bench, target);
325a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            }
326a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        } while (elapsed < FLAGS_gpuMs);
327a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein
328a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        // We've overshot at least a little.  Scale back linearly.
329a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        loops = (int)ceil(loops * FLAGS_gpuMs / elapsed);
3305324978a88677ac6b758324321816427814e7793reed        loops = clamp_loops(loops);
331a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein
332d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        // Make sure we're not still timing our calibration.
333d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        target->fence();
3345324978a88677ac6b758324321816427814e7793reed    } else {
3355324978a88677ac6b758324321816427814e7793reed        loops = detect_forever_loops(loops);
336a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein    }
337bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
338bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // Pretty much the same deal as the calibration: do some warmup to make
339bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // sure we're timing steady-state pipelined frames.
340bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    for (int i = 0; i < FLAGS_gpuFrameLag; i++) {
34175a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson        time(loops, bench, target);
342f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
343bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
344bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // Now, actually do the timing!
345bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    for (int i = 0; i < FLAGS_samples; i++) {
34675a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson        samples[i] = time(loops, bench, target) / loops;
347bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    }
348d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
349bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    return loops;
350f372321de3d4183de5b9ca436e677e471e358f31mtklein}
351bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
352bb6a02823929584231c8e080ee69e7fb1178cbfbmtkleinstatic SkString to_lower(const char* str) {
353bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    SkString lower(str);
354bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    for (size_t i = 0; i < lower.size(); i++) {
355bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        lower[i] = tolower(lower[i]);
356bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    }
357bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    return lower;
358bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein}
359bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
360c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstatic bool is_cpu_config_allowed(const char* name) {
361bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    for (int i = 0; i < FLAGS_config.count(); i++) {
362c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        if (to_lower(FLAGS_config[i]).equals(name)) {
363c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            return true;
364bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        }
365f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
366c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    return false;
367bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein}
368f372321de3d4183de5b9ca436e677e471e358f31mtklein
369c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#if SK_SUPPORT_GPU
370c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstatic bool is_gpu_config_allowed(const char* name, GrContextFactory::GLContextType ctxType,
371c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                                  int sampleCnt) {
372c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    if (!is_cpu_config_allowed(name)) {
373c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        return false;
374c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
37569a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski    if (const GrContext* ctx = gGrFactory->get(ctxType)) {
376762286309545c8a1e4bbc05dcd1fe3085d2a1f47bsalomon        return sampleCnt <= ctx->caps()->maxSampleCount();
377c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
378c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    return false;
379c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon}
380c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#endif
381c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
382c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#if SK_SUPPORT_GPU
383c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#define kBogusGLContextType GrContextFactory::kNative_GLContextType
384c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#else
385c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#define kBogusGLContextType 0
386e714e75c725c987fe682a1f5473224fe3e80380dmtklein#endif
387c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
388c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon// Append all configs that are enabled and supported.
389c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstatic void create_configs(SkTDArray<Config>* configs) {
3904736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth    #define CPU_CONFIG(name, backend, color, alpha)                       \
3914736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth        if (is_cpu_config_allowed(#name)) {                               \
3924736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth            Config config = { #name, Benchmark::backend, color, alpha, 0, \
3934736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth                              kBogusGLContextType, false };               \
3944736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth            configs->push(config);                                        \
395f372321de3d4183de5b9ca436e677e471e358f31mtklein        }
396e714e75c725c987fe682a1f5473224fe3e80380dmtklein
39740b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein    if (FLAGS_cpu) {
398c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        CPU_CONFIG(nonrendering, kNonRendering_Backend, kUnknown_SkColorType, kUnpremul_SkAlphaType)
399c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        CPU_CONFIG(8888, kRaster_Backend, kN32_SkColorType, kPremul_SkAlphaType)
400c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        CPU_CONFIG(565, kRaster_Backend, kRGB_565_SkColorType, kOpaque_SkAlphaType)
40140b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein    }
402f372321de3d4183de5b9ca436e677e471e358f31mtklein
403bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#if SK_SUPPORT_GPU
4044736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth    #define GPU_CONFIG(name, ctxType, samples, useDFText)                        \
405c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        if (is_gpu_config_allowed(#name, GrContextFactory::ctxType, samples)) {  \
406c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            Config config = {                                                    \
407c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                #name,                                                           \
408c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                Benchmark::kGPU_Backend,                                         \
409c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                kN32_SkColorType,                                                \
410c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                kPremul_SkAlphaType,                                             \
411c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                samples,                                                         \
4124736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth                GrContextFactory::ctxType,                                       \
4134736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth                useDFText };                                                     \
414c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            configs->push(config);                                               \
415f372321de3d4183de5b9ca436e677e471e358f31mtklein        }
416e714e75c725c987fe682a1f5473224fe3e80380dmtklein
41740b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein    if (FLAGS_gpu) {
4184736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth        GPU_CONFIG(gpu, kNative_GLContextType, 0, false)
4194736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth        GPU_CONFIG(msaa4, kNative_GLContextType, 4, false)
4204736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth        GPU_CONFIG(msaa16, kNative_GLContextType, 16, false)
4214736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth        GPU_CONFIG(nvprmsaa4, kNVPR_GLContextType, 4, false)
4224736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth        GPU_CONFIG(nvprmsaa16, kNVPR_GLContextType, 16, false)
4234736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth        GPU_CONFIG(gpudft, kNative_GLContextType, 0, true)
4244736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth        GPU_CONFIG(debug, kDebug_GLContextType, 0, false)
4254736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth        GPU_CONFIG(nullgpu, kNull_GLContextType, 0, false)
4263b4d077fba1ad037536db198608a940c47d91888bsalomon#ifdef SK_ANGLE
4274736e1434ae329e3a737dfd9504c22b3fc13dc72jvanverth        GPU_CONFIG(angle, kANGLE_GLContextType, 0, false)
4283b4d077fba1ad037536db198608a940c47d91888bsalomon#endif
42940b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein    }
430bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#endif
431d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson
432d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
433d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    if (is_cpu_config_allowed("hwui")) {
434d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        Config config = { "hwui", Benchmark::kHWUI_Backend, kRGBA_8888_SkColorType,
435d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson                          kPremul_SkAlphaType, 0, kBogusGLContextType, false };
436d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        configs->push(config);
437d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
438d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson#endif
439f372321de3d4183de5b9ca436e677e471e358f31mtklein}
440f372321de3d4183de5b9ca436e677e471e358f31mtklein
441c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon// If bench is enabled for config, returns a Target* for it, otherwise NULL.
442c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstatic Target* is_enabled(Benchmark* bench, const Config& config) {
443c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    if (!bench->isSuitableFor(config.backend)) {
444c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        return NULL;
445c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
446c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
447e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    SkImageInfo info = SkImageInfo::Make(bench->getSize().fX, bench->getSize().fY,
448e5ea500d4714a7d84de2bf913e81be3b65d2de68reed                                         config.color, config.alpha);
449c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
450d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    Target* target = NULL;
451c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
452d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    switch (config.backend) {
453c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#if SK_SUPPORT_GPU
454d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    case Benchmark::kGPU_Backend:
455d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        target = new GPUTarget(config);
456d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        break;
457d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson#endif
458d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
459d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    case Benchmark::kHWUI_Backend:
460d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        target = new HWUITarget(config, bench);
461d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        break;
462c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#endif
463d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    default:
464d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        target = new Target(config);
465d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson        break;
466d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    }
467c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
468d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson    if (!target->init(info, bench)) {
469c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        delete target;
470c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        return NULL;
471c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
472c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    return target;
473c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon}
474c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
475c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon// Creates targets for a benchmark and a set of configs.
476c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstatic void create_targets(SkTDArray<Target*>* targets, Benchmark* b,
477c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                           const SkTDArray<Config>& configs) {
478c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    for (int i = 0; i < configs.count(); ++i) {
479c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        if (Target* t = is_enabled(b, configs[i])) {
480c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            targets->push(t);
481c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        }
482e714e75c725c987fe682a1f5473224fe3e80380dmtklein
483c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
484c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon}
485c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
486bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio
487e714e75c725c987fe682a1f5473224fe3e80380dmtkleinclass BenchmarkStream {
488e714e75c725c987fe682a1f5473224fe3e80380dmtkleinpublic:
48992007583e43115998412ac8b0a06cc2780eb025cmtklein    BenchmarkStream() : fBenches(BenchRegistry::Head())
49092007583e43115998412ac8b0a06cc2780eb025cmtklein                      , fGMs(skiagm::GMRegistry::Head())
491fd731ce804cd3223318f3feee2c98404890b65f2mtklein                      , fCurrentRecording(0)
49292007583e43115998412ac8b0a06cc2780eb025cmtklein                      , fCurrentScale(0)
4935b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                      , fCurrentSKP(0)
49495f192d19938b98a45dd1fa4112d965f60d10516msarett                      , fCurrentUseMPD(0)
49560869a42a133942f852dd0f1696444c2a5c9ad83scroggo                      , fCurrentCodec(0)
49695f192d19938b98a45dd1fa4112d965f60d10516msarett                      , fCurrentImage(0)
49795f192d19938b98a45dd1fa4112d965f60d10516msarett                      , fCurrentSubsetImage(0)
49895f192d19938b98a45dd1fa4112d965f60d10516msarett                      , fCurrentColorType(0)
499261c3ad7fde95748da92550735decc949dc73bf2joshualitt                      , fCurrentAnimSKP(0)
50095f192d19938b98a45dd1fa4112d965f60d10516msarett                      , fDivisor(2) {
50192007583e43115998412ac8b0a06cc2780eb025cmtklein        for (int i = 0; i < FLAGS_skps.count(); i++) {
50292007583e43115998412ac8b0a06cc2780eb025cmtklein            if (SkStrEndsWith(FLAGS_skps[i], ".skp")) {
50392007583e43115998412ac8b0a06cc2780eb025cmtklein                fSKPs.push_back() = FLAGS_skps[i];
50492007583e43115998412ac8b0a06cc2780eb025cmtklein            } else {
50592007583e43115998412ac8b0a06cc2780eb025cmtklein                SkOSFile::Iter it(FLAGS_skps[i], ".skp");
50692007583e43115998412ac8b0a06cc2780eb025cmtklein                SkString path;
50792007583e43115998412ac8b0a06cc2780eb025cmtklein                while (it.next(&path)) {
50892007583e43115998412ac8b0a06cc2780eb025cmtklein                    fSKPs.push_back() = SkOSPath::Join(FLAGS_skps[0], path.c_str());
50992007583e43115998412ac8b0a06cc2780eb025cmtklein                }
51092007583e43115998412ac8b0a06cc2780eb025cmtklein            }
51192007583e43115998412ac8b0a06cc2780eb025cmtklein        }
51292007583e43115998412ac8b0a06cc2780eb025cmtklein
51392007583e43115998412ac8b0a06cc2780eb025cmtklein        if (4 != sscanf(FLAGS_clip[0], "%d,%d,%d,%d",
51492007583e43115998412ac8b0a06cc2780eb025cmtklein                        &fClip.fLeft, &fClip.fTop, &fClip.fRight, &fClip.fBottom)) {
51592007583e43115998412ac8b0a06cc2780eb025cmtklein            SkDebugf("Can't parse %s from --clip as an SkIRect.\n", FLAGS_clip[0]);
51692007583e43115998412ac8b0a06cc2780eb025cmtklein            exit(1);
51792007583e43115998412ac8b0a06cc2780eb025cmtklein        }
51892007583e43115998412ac8b0a06cc2780eb025cmtklein
51992007583e43115998412ac8b0a06cc2780eb025cmtklein        for (int i = 0; i < FLAGS_scales.count(); i++) {
52092007583e43115998412ac8b0a06cc2780eb025cmtklein            if (1 != sscanf(FLAGS_scales[i], "%f", &fScales.push_back())) {
52192007583e43115998412ac8b0a06cc2780eb025cmtklein                SkDebugf("Can't parse %s from --scales as an SkScalar.\n", FLAGS_scales[i]);
52292007583e43115998412ac8b0a06cc2780eb025cmtklein                exit(1);
52392007583e43115998412ac8b0a06cc2780eb025cmtklein            }
52492007583e43115998412ac8b0a06cc2780eb025cmtklein        }
5255b69377507478623dcf5b11f3ecb010f87c4794frobertphillips
526261c3ad7fde95748da92550735decc949dc73bf2joshualitt        if (2 != sscanf(FLAGS_zoom[0], "%f,%d", &fZoomScale, &fZoomSteps)) {
527261c3ad7fde95748da92550735decc949dc73bf2joshualitt            SkDebugf("Can't parse %s from --zoom as a scale,step.\n", FLAGS_zoom[0]);
528261c3ad7fde95748da92550735decc949dc73bf2joshualitt            exit(1);
529261c3ad7fde95748da92550735decc949dc73bf2joshualitt        }
530261c3ad7fde95748da92550735decc949dc73bf2joshualitt
5315b69377507478623dcf5b11f3ecb010f87c4794frobertphillips        fUseMPDs.push_back() = false;
5325b69377507478623dcf5b11f3ecb010f87c4794frobertphillips        if (FLAGS_mpd) {
5335b69377507478623dcf5b11f3ecb010f87c4794frobertphillips            fUseMPDs.push_back() = true;
5345b69377507478623dcf5b11f3ecb010f87c4794frobertphillips        }
53595553d917c73ef333ede967521560957a5b6a0admtklein
53695f192d19938b98a45dd1fa4112d965f60d10516msarett        // Prepare the images for decoding
53795f192d19938b98a45dd1fa4112d965f60d10516msarett        for (int i = 0; i < FLAGS_images.count(); i++) {
53895f192d19938b98a45dd1fa4112d965f60d10516msarett            const char* flag = FLAGS_images[i];
53995f192d19938b98a45dd1fa4112d965f60d10516msarett            if (sk_isdir(flag)) {
54095f192d19938b98a45dd1fa4112d965f60d10516msarett                // If the value passed in is a directory, add all the images
54195f192d19938b98a45dd1fa4112d965f60d10516msarett                SkOSFile::Iter it(flag);
54295f192d19938b98a45dd1fa4112d965f60d10516msarett                SkString file;
54395f192d19938b98a45dd1fa4112d965f60d10516msarett                while (it.next(&file)) {
54495f192d19938b98a45dd1fa4112d965f60d10516msarett                    fImages.push_back() = SkOSPath::Join(flag, file.c_str());
54595f192d19938b98a45dd1fa4112d965f60d10516msarett                }
54695f192d19938b98a45dd1fa4112d965f60d10516msarett            } else if (sk_exists(flag)) {
54795f192d19938b98a45dd1fa4112d965f60d10516msarett                // Also add the value if it is a single image
54895f192d19938b98a45dd1fa4112d965f60d10516msarett                fImages.push_back() = flag;
54995f192d19938b98a45dd1fa4112d965f60d10516msarett            }
55095f192d19938b98a45dd1fa4112d965f60d10516msarett        }
55195553d917c73ef333ede967521560957a5b6a0admtklein
55295f192d19938b98a45dd1fa4112d965f60d10516msarett        // Choose the candidate color types for image decoding
55395f192d19938b98a45dd1fa4112d965f60d10516msarett        const SkColorType colorTypes[] =
55421027994192f395bbd1507558b84f59b3c7cf0dascroggo            { kN32_SkColorType, kRGB_565_SkColorType, kAlpha_8_SkColorType, kIndex_8_SkColorType };
55595f192d19938b98a45dd1fa4112d965f60d10516msarett        fColorTypes.push_back_n(SK_ARRAY_COUNT(colorTypes), colorTypes);
55692007583e43115998412ac8b0a06cc2780eb025cmtklein    }
557e714e75c725c987fe682a1f5473224fe3e80380dmtklein
558fd731ce804cd3223318f3feee2c98404890b65f2mtklein    static bool ReadPicture(const char* path, SkAutoTUnref<SkPicture>* pic) {
559fd731ce804cd3223318f3feee2c98404890b65f2mtklein        // Not strictly necessary, as it will be checked again later,
560fd731ce804cd3223318f3feee2c98404890b65f2mtklein        // but helps to avoid a lot of pointless work if we're going to skip it.
561fd731ce804cd3223318f3feee2c98404890b65f2mtklein        if (SkCommandLineFlags::ShouldSkip(FLAGS_match, path)) {
562fd731ce804cd3223318f3feee2c98404890b65f2mtklein            return false;
563fd731ce804cd3223318f3feee2c98404890b65f2mtklein        }
564fd731ce804cd3223318f3feee2c98404890b65f2mtklein
565a1193e4b0e34a7e4e1bd33e9708d7341679f8321scroggo        SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(path));
566fd731ce804cd3223318f3feee2c98404890b65f2mtklein        if (stream.get() == NULL) {
567fd731ce804cd3223318f3feee2c98404890b65f2mtklein            SkDebugf("Could not read %s.\n", path);
568fd731ce804cd3223318f3feee2c98404890b65f2mtklein            return false;
569fd731ce804cd3223318f3feee2c98404890b65f2mtklein        }
570fd731ce804cd3223318f3feee2c98404890b65f2mtklein
57157f27bdcbd328491a121918b4ab9301fbcdec642mtklein        pic->reset(SkPicture::CreateFromStream(stream.get()));
572fd731ce804cd3223318f3feee2c98404890b65f2mtklein        if (pic->get() == NULL) {
573fd731ce804cd3223318f3feee2c98404890b65f2mtklein            SkDebugf("Could not read %s as an SkPicture.\n", path);
574fd731ce804cd3223318f3feee2c98404890b65f2mtklein            return false;
575fd731ce804cd3223318f3feee2c98404890b65f2mtklein        }
576fd731ce804cd3223318f3feee2c98404890b65f2mtklein        return true;
577fd731ce804cd3223318f3feee2c98404890b65f2mtklein    }
578fd731ce804cd3223318f3feee2c98404890b65f2mtklein
57992007583e43115998412ac8b0a06cc2780eb025cmtklein    Benchmark* next() {
580e714e75c725c987fe682a1f5473224fe3e80380dmtklein        if (fBenches) {
581e714e75c725c987fe682a1f5473224fe3e80380dmtklein            Benchmark* bench = fBenches->factory()(NULL);
582e714e75c725c987fe682a1f5473224fe3e80380dmtklein            fBenches = fBenches->next();
58392007583e43115998412ac8b0a06cc2780eb025cmtklein            fSourceType = "bench";
584fd731ce804cd3223318f3feee2c98404890b65f2mtklein            fBenchType  = "micro";
585e714e75c725c987fe682a1f5473224fe3e80380dmtklein            return bench;
586e714e75c725c987fe682a1f5473224fe3e80380dmtklein        }
58792007583e43115998412ac8b0a06cc2780eb025cmtklein
588e714e75c725c987fe682a1f5473224fe3e80380dmtklein        while (fGMs) {
589e714e75c725c987fe682a1f5473224fe3e80380dmtklein            SkAutoTDelete<skiagm::GM> gm(fGMs->factory()(NULL));
590e714e75c725c987fe682a1f5473224fe3e80380dmtklein            fGMs = fGMs->next();
591cf5d9c993dcbd75d4cefe2d1de25c2b9645f6957mtklein            if (gm->runAsBench()) {
59292007583e43115998412ac8b0a06cc2780eb025cmtklein                fSourceType = "gm";
593fd731ce804cd3223318f3feee2c98404890b65f2mtklein                fBenchType  = "micro";
594e714e75c725c987fe682a1f5473224fe3e80380dmtklein                return SkNEW_ARGS(GMBench, (gm.detach()));
595e714e75c725c987fe682a1f5473224fe3e80380dmtklein            }
596e714e75c725c987fe682a1f5473224fe3e80380dmtklein        }
59792007583e43115998412ac8b0a06cc2780eb025cmtklein
598fd731ce804cd3223318f3feee2c98404890b65f2mtklein        // First add all .skps as RecordingBenches.
599fd731ce804cd3223318f3feee2c98404890b65f2mtklein        while (fCurrentRecording < fSKPs.count()) {
600fd731ce804cd3223318f3feee2c98404890b65f2mtklein            const SkString& path = fSKPs[fCurrentRecording++];
601fd731ce804cd3223318f3feee2c98404890b65f2mtklein            SkAutoTUnref<SkPicture> pic;
602fd731ce804cd3223318f3feee2c98404890b65f2mtklein            if (!ReadPicture(path.c_str(), &pic)) {
603fd731ce804cd3223318f3feee2c98404890b65f2mtklein                continue;
604fd731ce804cd3223318f3feee2c98404890b65f2mtklein            }
605fd731ce804cd3223318f3feee2c98404890b65f2mtklein            SkString name = SkOSPath::Basename(path.c_str());
606fd731ce804cd3223318f3feee2c98404890b65f2mtklein            fSourceType = "skp";
607fd731ce804cd3223318f3feee2c98404890b65f2mtklein            fBenchType  = "recording";
6080aa5cea8694d3686b6742a36eab81ab9001de954bsalomon            fSKPBytes = static_cast<double>(SkPictureUtils::ApproximateBytesUsed(pic));
609051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein            fSKPOps   = pic->approximateOpCount();
610fd731ce804cd3223318f3feee2c98404890b65f2mtklein            return SkNEW_ARGS(RecordingBench, (name.c_str(), pic.get(), FLAGS_bbh));
611fd731ce804cd3223318f3feee2c98404890b65f2mtklein        }
612fd731ce804cd3223318f3feee2c98404890b65f2mtklein
613fd731ce804cd3223318f3feee2c98404890b65f2mtklein        // Then once each for each scale as SKPBenches (playback).
61492007583e43115998412ac8b0a06cc2780eb025cmtklein        while (fCurrentScale < fScales.count()) {
61592007583e43115998412ac8b0a06cc2780eb025cmtklein            while (fCurrentSKP < fSKPs.count()) {
6165b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                const SkString& path = fSKPs[fCurrentSKP];
617fd731ce804cd3223318f3feee2c98404890b65f2mtklein                SkAutoTUnref<SkPicture> pic;
618fd731ce804cd3223318f3feee2c98404890b65f2mtklein                if (!ReadPicture(path.c_str(), &pic)) {
6195b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                    fCurrentSKP++;
62092007583e43115998412ac8b0a06cc2780eb025cmtklein                    continue;
62192007583e43115998412ac8b0a06cc2780eb025cmtklein                }
6225b69377507478623dcf5b11f3ecb010f87c4794frobertphillips
6235b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                while (fCurrentUseMPD < fUseMPDs.count()) {
6245b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                    if (FLAGS_bbh) {
6255b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                        // The SKP we read off disk doesn't have a BBH.  Re-record so it grows one.
6265b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                        SkRTreeFactory factory;
6275b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                        SkPictureRecorder recorder;
6285b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                        static const int kFlags = SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag;
6295b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                        pic->playback(recorder.beginRecording(pic->cullRect().width(),
6305b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                                                              pic->cullRect().height(),
631748ca3bf2d170708f263693e8579e6722389d0efmtklein                                                              &factory,
632e451c4df7369c5e253ef9c9e0a8713beda25f34brobertphillips                                                              fUseMPDs[fCurrentUseMPD] ? kFlags : 0));
6335b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                        pic.reset(recorder.endRecording());
6345b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                    }
6355b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                    SkString name = SkOSPath::Basename(path.c_str());
6365b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                    fSourceType = "skp";
6375b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                    fBenchType = "playback";
6385b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                    return SkNEW_ARGS(SKPBench,
639261c3ad7fde95748da92550735decc949dc73bf2joshualitt                                      (name.c_str(), pic.get(), fClip,
640261c3ad7fde95748da92550735decc949dc73bf2joshualitt                                       fScales[fCurrentScale], fUseMPDs[fCurrentUseMPD++]));
641261c3ad7fde95748da92550735decc949dc73bf2joshualitt
6422084050a33ae139d0fe9bb680f7905f91139a39fmtklein                }
6435b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                fCurrentUseMPD = 0;
6445b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                fCurrentSKP++;
64592007583e43115998412ac8b0a06cc2780eb025cmtklein            }
64692007583e43115998412ac8b0a06cc2780eb025cmtklein            fCurrentSKP = 0;
64792007583e43115998412ac8b0a06cc2780eb025cmtklein            fCurrentScale++;
64892007583e43115998412ac8b0a06cc2780eb025cmtklein        }
64992007583e43115998412ac8b0a06cc2780eb025cmtklein
650261c3ad7fde95748da92550735decc949dc73bf2joshualitt        // Now loop over each skp again if we have an animation
651261c3ad7fde95748da92550735decc949dc73bf2joshualitt        if (fZoomScale != 1.0f && fZoomSteps != 1) {
652261c3ad7fde95748da92550735decc949dc73bf2joshualitt            while (fCurrentAnimSKP < fSKPs.count()) {
653261c3ad7fde95748da92550735decc949dc73bf2joshualitt                const SkString& path = fSKPs[fCurrentAnimSKP];
654261c3ad7fde95748da92550735decc949dc73bf2joshualitt                SkAutoTUnref<SkPicture> pic;
655261c3ad7fde95748da92550735decc949dc73bf2joshualitt                if (!ReadPicture(path.c_str(), &pic)) {
656261c3ad7fde95748da92550735decc949dc73bf2joshualitt                    fCurrentAnimSKP++;
657261c3ad7fde95748da92550735decc949dc73bf2joshualitt                    continue;
658261c3ad7fde95748da92550735decc949dc73bf2joshualitt                }
659261c3ad7fde95748da92550735decc949dc73bf2joshualitt
660261c3ad7fde95748da92550735decc949dc73bf2joshualitt                fCurrentAnimSKP++;
661261c3ad7fde95748da92550735decc949dc73bf2joshualitt                SkString name = SkOSPath::Basename(path.c_str());
662261c3ad7fde95748da92550735decc949dc73bf2joshualitt                SkMatrix anim = SkMatrix::I();
663261c3ad7fde95748da92550735decc949dc73bf2joshualitt                anim.setScale(fZoomScale, fZoomScale);
664261c3ad7fde95748da92550735decc949dc73bf2joshualitt                return SkNEW_ARGS(SKPAnimationBench, (name.c_str(), pic.get(), fClip, anim,
665261c3ad7fde95748da92550735decc949dc73bf2joshualitt                                  fZoomSteps));
666261c3ad7fde95748da92550735decc949dc73bf2joshualitt            }
667261c3ad7fde95748da92550735decc949dc73bf2joshualitt        }
668261c3ad7fde95748da92550735decc949dc73bf2joshualitt
669261c3ad7fde95748da92550735decc949dc73bf2joshualitt
67060869a42a133942f852dd0f1696444c2a5c9ad83scroggo        for (; fCurrentCodec < fImages.count(); fCurrentCodec++) {
67160869a42a133942f852dd0f1696444c2a5c9ad83scroggo            const SkString& path = fImages[fCurrentCodec];
67260869a42a133942f852dd0f1696444c2a5c9ad83scroggo            SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(path.c_str()));
67360869a42a133942f852dd0f1696444c2a5c9ad83scroggo            SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded));
67460869a42a133942f852dd0f1696444c2a5c9ad83scroggo            if (!codec) {
67560869a42a133942f852dd0f1696444c2a5c9ad83scroggo                // Nothing to time.
6769d9725c892743cf8fc66ea6cdd5ce21fe2df6d14msarett                SkDebugf("Cannot find codec for %s\n", path.c_str());
67760869a42a133942f852dd0f1696444c2a5c9ad83scroggo                continue;
67860869a42a133942f852dd0f1696444c2a5c9ad83scroggo            }
67921027994192f395bbd1507558b84f59b3c7cf0dascroggo
68060869a42a133942f852dd0f1696444c2a5c9ad83scroggo            while (fCurrentColorType < fColorTypes.count()) {
68121027994192f395bbd1507558b84f59b3c7cf0dascroggo                const SkColorType colorType = fColorTypes[fCurrentColorType];
68260869a42a133942f852dd0f1696444c2a5c9ad83scroggo                fCurrentColorType++;
68321027994192f395bbd1507558b84f59b3c7cf0dascroggo
68460869a42a133942f852dd0f1696444c2a5c9ad83scroggo                // Make sure we can decode to this color type.
68560869a42a133942f852dd0f1696444c2a5c9ad83scroggo                SkImageInfo info = codec->getInfo().makeColorType(colorType);
68621027994192f395bbd1507558b84f59b3c7cf0dascroggo                SkAlphaType alphaType;
68721027994192f395bbd1507558b84f59b3c7cf0dascroggo                if (!SkColorTypeValidateAlphaType(colorType, info.alphaType(),
68821027994192f395bbd1507558b84f59b3c7cf0dascroggo                                                  &alphaType)) {
68921027994192f395bbd1507558b84f59b3c7cf0dascroggo                    continue;
69021027994192f395bbd1507558b84f59b3c7cf0dascroggo                }
69121027994192f395bbd1507558b84f59b3c7cf0dascroggo                if (alphaType != info.alphaType()) {
69221027994192f395bbd1507558b84f59b3c7cf0dascroggo                    info = info.makeAlphaType(alphaType);
69321027994192f395bbd1507558b84f59b3c7cf0dascroggo                }
69421027994192f395bbd1507558b84f59b3c7cf0dascroggo
69521027994192f395bbd1507558b84f59b3c7cf0dascroggo                const size_t rowBytes = info.minRowBytes();
69621027994192f395bbd1507558b84f59b3c7cf0dascroggo                SkAutoMalloc storage(info.getSafeSize(rowBytes));
69721027994192f395bbd1507558b84f59b3c7cf0dascroggo
69821027994192f395bbd1507558b84f59b3c7cf0dascroggo                // Used if fCurrentColorType is kIndex_8_SkColorType
69921027994192f395bbd1507558b84f59b3c7cf0dascroggo                int colorCount = 256;
70021027994192f395bbd1507558b84f59b3c7cf0dascroggo                SkPMColor colors[256];
70121027994192f395bbd1507558b84f59b3c7cf0dascroggo
70260869a42a133942f852dd0f1696444c2a5c9ad83scroggo                const SkImageGenerator::Result result = codec->getPixels(
70321027994192f395bbd1507558b84f59b3c7cf0dascroggo                        info, storage.get(), rowBytes, NULL, colors,
70421027994192f395bbd1507558b84f59b3c7cf0dascroggo                        &colorCount);
70560869a42a133942f852dd0f1696444c2a5c9ad83scroggo                switch (result) {
70660869a42a133942f852dd0f1696444c2a5c9ad83scroggo                    case SkImageGenerator::kSuccess:
70760869a42a133942f852dd0f1696444c2a5c9ad83scroggo                    case SkImageGenerator::kIncompleteInput:
70860869a42a133942f852dd0f1696444c2a5c9ad83scroggo                        return new CodecBench(SkOSPath::Basename(path.c_str()),
70960869a42a133942f852dd0f1696444c2a5c9ad83scroggo                                encoded, colorType);
71060869a42a133942f852dd0f1696444c2a5c9ad83scroggo                    case SkImageGenerator::kInvalidConversion:
71160869a42a133942f852dd0f1696444c2a5c9ad83scroggo                        // This is okay. Not all conversions are valid.
71260869a42a133942f852dd0f1696444c2a5c9ad83scroggo                        break;
71360869a42a133942f852dd0f1696444c2a5c9ad83scroggo                    default:
71460869a42a133942f852dd0f1696444c2a5c9ad83scroggo                        // This represents some sort of failure.
71560869a42a133942f852dd0f1696444c2a5c9ad83scroggo                        SkASSERT(false);
71660869a42a133942f852dd0f1696444c2a5c9ad83scroggo                        break;
71760869a42a133942f852dd0f1696444c2a5c9ad83scroggo                }
71860869a42a133942f852dd0f1696444c2a5c9ad83scroggo            }
71960869a42a133942f852dd0f1696444c2a5c9ad83scroggo            fCurrentColorType = 0;
72060869a42a133942f852dd0f1696444c2a5c9ad83scroggo        }
72160869a42a133942f852dd0f1696444c2a5c9ad83scroggo
72295f192d19938b98a45dd1fa4112d965f60d10516msarett        // Run the DecodingBenches
72395f192d19938b98a45dd1fa4112d965f60d10516msarett        while (fCurrentImage < fImages.count()) {
72495f192d19938b98a45dd1fa4112d965f60d10516msarett            while (fCurrentColorType < fColorTypes.count()) {
72595f192d19938b98a45dd1fa4112d965f60d10516msarett                const SkString& path = fImages[fCurrentImage];
72695f192d19938b98a45dd1fa4112d965f60d10516msarett                SkColorType colorType = fColorTypes[fCurrentColorType];
72795f192d19938b98a45dd1fa4112d965f60d10516msarett                fCurrentColorType++;
72860869a42a133942f852dd0f1696444c2a5c9ad83scroggo                // Check if the image decodes to the right color type
72960869a42a133942f852dd0f1696444c2a5c9ad83scroggo                // before creating the benchmark
73095f192d19938b98a45dd1fa4112d965f60d10516msarett                SkBitmap bitmap;
73195f192d19938b98a45dd1fa4112d965f60d10516msarett                if (SkImageDecoder::DecodeFile(path.c_str(), &bitmap,
73260869a42a133942f852dd0f1696444c2a5c9ad83scroggo                        colorType, SkImageDecoder::kDecodePixels_Mode)
73360869a42a133942f852dd0f1696444c2a5c9ad83scroggo                        && bitmap.colorType() == colorType) {
73495f192d19938b98a45dd1fa4112d965f60d10516msarett                    return new DecodingBench(path, colorType);
73595f192d19938b98a45dd1fa4112d965f60d10516msarett                }
73695f192d19938b98a45dd1fa4112d965f60d10516msarett            }
73795f192d19938b98a45dd1fa4112d965f60d10516msarett            fCurrentColorType = 0;
73895f192d19938b98a45dd1fa4112d965f60d10516msarett            fCurrentImage++;
73995f192d19938b98a45dd1fa4112d965f60d10516msarett        }
74095f192d19938b98a45dd1fa4112d965f60d10516msarett
74195f192d19938b98a45dd1fa4112d965f60d10516msarett        // Run the DecodingSubsetBenches
74295f192d19938b98a45dd1fa4112d965f60d10516msarett        while (fCurrentSubsetImage < fImages.count()) {
74395f192d19938b98a45dd1fa4112d965f60d10516msarett            while (fCurrentColorType < fColorTypes.count()) {
74495f192d19938b98a45dd1fa4112d965f60d10516msarett                const SkString& path = fImages[fCurrentSubsetImage];
74595f192d19938b98a45dd1fa4112d965f60d10516msarett                SkColorType colorType = fColorTypes[fCurrentColorType];
74695f192d19938b98a45dd1fa4112d965f60d10516msarett                fCurrentColorType++;
74795f192d19938b98a45dd1fa4112d965f60d10516msarett                // Check if the image decodes before creating the benchmark
74895f192d19938b98a45dd1fa4112d965f60d10516msarett                SkAutoTUnref<SkData> encoded(
74995f192d19938b98a45dd1fa4112d965f60d10516msarett                        SkData::NewFromFileName(path.c_str()));
75095f192d19938b98a45dd1fa4112d965f60d10516msarett                SkAutoTDelete<SkMemoryStream> stream(
75195f192d19938b98a45dd1fa4112d965f60d10516msarett                        new SkMemoryStream(encoded));
75295f192d19938b98a45dd1fa4112d965f60d10516msarett                SkAutoTDelete<SkImageDecoder>
75395f192d19938b98a45dd1fa4112d965f60d10516msarett                    decoder(SkImageDecoder::Factory(stream.get()));
75495f192d19938b98a45dd1fa4112d965f60d10516msarett                if (!decoder) {
75595f192d19938b98a45dd1fa4112d965f60d10516msarett                    SkDebugf("Cannot find decoder for %s\n", path.c_str());
75695f192d19938b98a45dd1fa4112d965f60d10516msarett                } else {
75795f192d19938b98a45dd1fa4112d965f60d10516msarett                    stream->rewind();
75895f192d19938b98a45dd1fa4112d965f60d10516msarett                    int w, h;
75995f192d19938b98a45dd1fa4112d965f60d10516msarett                    bool success;
76095f192d19938b98a45dd1fa4112d965f60d10516msarett                    if (!decoder->buildTileIndex(stream.detach(), &w, &h)
76195f192d19938b98a45dd1fa4112d965f60d10516msarett                            || w*h == 1) {
76295f192d19938b98a45dd1fa4112d965f60d10516msarett                        // This is not an error, but in this case we still
76395f192d19938b98a45dd1fa4112d965f60d10516msarett                        // do not want to run the benchmark.
76495f192d19938b98a45dd1fa4112d965f60d10516msarett                        success = false;
76595f192d19938b98a45dd1fa4112d965f60d10516msarett                    } else if (fDivisor > w || fDivisor > h) {
76695f192d19938b98a45dd1fa4112d965f60d10516msarett                        SkDebugf("Divisor %d is too big for %s %dx%d\n",
76795f192d19938b98a45dd1fa4112d965f60d10516msarett                                fDivisor, path.c_str(), w, h);
76895f192d19938b98a45dd1fa4112d965f60d10516msarett                        success = false;
76995f192d19938b98a45dd1fa4112d965f60d10516msarett                    } else {
77095f192d19938b98a45dd1fa4112d965f60d10516msarett                        const int sW  = w / fDivisor;
77195f192d19938b98a45dd1fa4112d965f60d10516msarett                        const int sH = h / fDivisor;
77295f192d19938b98a45dd1fa4112d965f60d10516msarett                        SkBitmap bitmap;
77395f192d19938b98a45dd1fa4112d965f60d10516msarett                        success = true;
77495f192d19938b98a45dd1fa4112d965f60d10516msarett                        for (int y = 0; y < h; y += sH) {
77595f192d19938b98a45dd1fa4112d965f60d10516msarett                            for (int x = 0; x < w; x += sW) {
77695f192d19938b98a45dd1fa4112d965f60d10516msarett                                SkIRect rect = SkIRect::MakeXYWH(x, y, sW, sH);
77795f192d19938b98a45dd1fa4112d965f60d10516msarett                                success &= decoder->decodeSubset(&bitmap, rect,
77895f192d19938b98a45dd1fa4112d965f60d10516msarett                                                                 colorType);
77995f192d19938b98a45dd1fa4112d965f60d10516msarett                            }
78095f192d19938b98a45dd1fa4112d965f60d10516msarett                        }
78195f192d19938b98a45dd1fa4112d965f60d10516msarett                    }
78295f192d19938b98a45dd1fa4112d965f60d10516msarett                    // Create the benchmark if successful
78395f192d19938b98a45dd1fa4112d965f60d10516msarett                    if (success) {
78495f192d19938b98a45dd1fa4112d965f60d10516msarett                        return new DecodingSubsetBench(path, colorType,
78595f192d19938b98a45dd1fa4112d965f60d10516msarett                                                       fDivisor);
78695f192d19938b98a45dd1fa4112d965f60d10516msarett                    }
78795f192d19938b98a45dd1fa4112d965f60d10516msarett                }
78895f192d19938b98a45dd1fa4112d965f60d10516msarett            }
78995f192d19938b98a45dd1fa4112d965f60d10516msarett            fCurrentColorType = 0;
79095f192d19938b98a45dd1fa4112d965f60d10516msarett            fCurrentSubsetImage++;
79195f192d19938b98a45dd1fa4112d965f60d10516msarett        }
79295f192d19938b98a45dd1fa4112d965f60d10516msarett
793e714e75c725c987fe682a1f5473224fe3e80380dmtklein        return NULL;
794e714e75c725c987fe682a1f5473224fe3e80380dmtklein    }
79592007583e43115998412ac8b0a06cc2780eb025cmtklein
79692007583e43115998412ac8b0a06cc2780eb025cmtklein    void fillCurrentOptions(ResultsWriter* log) const {
79792007583e43115998412ac8b0a06cc2780eb025cmtklein        log->configOption("source_type", fSourceType);
798fd731ce804cd3223318f3feee2c98404890b65f2mtklein        log->configOption("bench_type",  fBenchType);
79992007583e43115998412ac8b0a06cc2780eb025cmtklein        if (0 == strcmp(fSourceType, "skp")) {
80092007583e43115998412ac8b0a06cc2780eb025cmtklein            log->configOption("clip",
80192007583e43115998412ac8b0a06cc2780eb025cmtklein                    SkStringPrintf("%d %d %d %d", fClip.fLeft, fClip.fTop,
80292007583e43115998412ac8b0a06cc2780eb025cmtklein                                                  fClip.fRight, fClip.fBottom).c_str());
80392007583e43115998412ac8b0a06cc2780eb025cmtklein            log->configOption("scale", SkStringPrintf("%.2g", fScales[fCurrentScale]).c_str());
8045b69377507478623dcf5b11f3ecb010f87c4794frobertphillips            if (fCurrentUseMPD > 0) {
8055b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                SkASSERT(1 == fCurrentUseMPD || 2 == fCurrentUseMPD);
8065b69377507478623dcf5b11f3ecb010f87c4794frobertphillips                log->configOption("multi_picture_draw", fUseMPDs[fCurrentUseMPD-1] ? "true" : "false");
8075b69377507478623dcf5b11f3ecb010f87c4794frobertphillips            }
80892007583e43115998412ac8b0a06cc2780eb025cmtklein        }
809051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein        if (0 == strcmp(fBenchType, "recording")) {
810051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein            log->metric("bytes", fSKPBytes);
811051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein            log->metric("ops",   fSKPOps);
812051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein        }
81392007583e43115998412ac8b0a06cc2780eb025cmtklein    }
81492007583e43115998412ac8b0a06cc2780eb025cmtklein
815e714e75c725c987fe682a1f5473224fe3e80380dmtkleinprivate:
816e714e75c725c987fe682a1f5473224fe3e80380dmtklein    const BenchRegistry* fBenches;
817e714e75c725c987fe682a1f5473224fe3e80380dmtklein    const skiagm::GMRegistry* fGMs;
81892007583e43115998412ac8b0a06cc2780eb025cmtklein    SkIRect            fClip;
81992007583e43115998412ac8b0a06cc2780eb025cmtklein    SkTArray<SkScalar> fScales;
82092007583e43115998412ac8b0a06cc2780eb025cmtklein    SkTArray<SkString> fSKPs;
8215b69377507478623dcf5b11f3ecb010f87c4794frobertphillips    SkTArray<bool>     fUseMPDs;
82295f192d19938b98a45dd1fa4112d965f60d10516msarett    SkTArray<SkString> fImages;
82395f192d19938b98a45dd1fa4112d965f60d10516msarett    SkTArray<SkColorType> fColorTypes;
824261c3ad7fde95748da92550735decc949dc73bf2joshualitt    SkScalar           fZoomScale;
825261c3ad7fde95748da92550735decc949dc73bf2joshualitt    int                fZoomSteps;
82692007583e43115998412ac8b0a06cc2780eb025cmtklein
827051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein    double fSKPBytes, fSKPOps;
828051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein
829fd731ce804cd3223318f3feee2c98404890b65f2mtklein    const char* fSourceType;  // What we're benching: bench, GM, SKP, ...
830fd731ce804cd3223318f3feee2c98404890b65f2mtklein    const char* fBenchType;   // How we bench it: micro, recording, playback, ...
831fd731ce804cd3223318f3feee2c98404890b65f2mtklein    int fCurrentRecording;
83292007583e43115998412ac8b0a06cc2780eb025cmtklein    int fCurrentScale;
83392007583e43115998412ac8b0a06cc2780eb025cmtklein    int fCurrentSKP;
8345b69377507478623dcf5b11f3ecb010f87c4794frobertphillips    int fCurrentUseMPD;
83560869a42a133942f852dd0f1696444c2a5c9ad83scroggo    int fCurrentCodec;
83695f192d19938b98a45dd1fa4112d965f60d10516msarett    int fCurrentImage;
83795f192d19938b98a45dd1fa4112d965f60d10516msarett    int fCurrentSubsetImage;
83895f192d19938b98a45dd1fa4112d965f60d10516msarett    int fCurrentColorType;
839261c3ad7fde95748da92550735decc949dc73bf2joshualitt    int fCurrentAnimSKP;
84095f192d19938b98a45dd1fa4112d965f60d10516msarett    const int fDivisor;
841e714e75c725c987fe682a1f5473224fe3e80380dmtklein};
842e714e75c725c987fe682a1f5473224fe3e80380dmtklein
8433b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorioint nanobench_main();
84417f0b6df7248b9bbdaddacc3a6c9c6efe4ae278ecaryclarkint nanobench_main() {
8453b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorio    SetupCrashHandler();
846f372321de3d4183de5b9ca436e677e471e358f31mtklein    SkAutoGraphics ag;
8474f10844149bbc05f0259a1b3199c2f995756ed60mtklein    SkTaskGroup::Enabler enabled;
848f372321de3d4183de5b9ca436e677e471e358f31mtklein
84969a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski#if SK_SUPPORT_GPU
850682c269a1511200322916af83053e26004c0ec40bsalomon    GrContextOptions grContextOpts;
85112b3544028e74712c6c095ed3a2e8a78de6b2ed8krajcevski    grContextOpts.fDrawPathToCompressedTexture = FLAGS_gpuCompressAlphaMasks;
85212b3544028e74712c6c095ed3a2e8a78de6b2ed8krajcevski    gGrFactory.reset(SkNEW_ARGS(GrContextFactory, (grContextOpts)));
85369a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski#endif
85469a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski
85506cddec8570cbf29f89e89736afb0487b5b95abdbsalomon    if (FLAGS_veryVerbose) {
85606cddec8570cbf29f89e89736afb0487b5b95abdbsalomon        FLAGS_verbose = true;
85706cddec8570cbf29f89e89736afb0487b5b95abdbsalomon    }
85806cddec8570cbf29f89e89736afb0487b5b95abdbsalomon
8596eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (kAutoTuneLoops != FLAGS_loops) {
860a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        FLAGS_samples     = 1;
861a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        FLAGS_gpuFrameLag = 0;
862a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein    }
863a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein
8646eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (!FLAGS_writePath.isEmpty()) {
8656eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Writing files to %s.\n", FLAGS_writePath[0]);
8666eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        if (!sk_mkdir(FLAGS_writePath[0])) {
8676eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            SkDebugf("Could not create %s. Files won't be written.\n", FLAGS_writePath[0]);
8686eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            FLAGS_writePath.set(0, NULL);
8696eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        }
8706eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
8716eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
8721915b62637bea20e1471a8a358b22e9e47a4a385mtklein    SkAutoTDelete<ResultsWriter> log(SkNEW(ResultsWriter));
87360317d0ffb5053df7b08a627d6decd11b684e80dmtklein    if (!FLAGS_outResultsFile.isEmpty()) {
8741915b62637bea20e1471a8a358b22e9e47a4a385mtklein        log.reset(SkNEW(NanoJSONResultsWriter(FLAGS_outResultsFile[0])));
87560317d0ffb5053df7b08a627d6decd11b684e80dmtklein    }
876bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio
8771915b62637bea20e1471a8a358b22e9e47a4a385mtklein    if (1 == FLAGS_properties.count() % 2) {
8781915b62637bea20e1471a8a358b22e9e47a4a385mtklein        SkDebugf("ERROR: --properties must be passed with an even number of arguments.\n");
879bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio        return 1;
880bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    }
8811915b62637bea20e1471a8a358b22e9e47a4a385mtklein    for (int i = 1; i < FLAGS_properties.count(); i += 2) {
8821915b62637bea20e1471a8a358b22e9e47a4a385mtklein        log->property(FLAGS_properties[i-1], FLAGS_properties[i]);
883bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    }
88494e51567dd691c3e1e8dfa6005a301d72cecf48emtklein
8851915b62637bea20e1471a8a358b22e9e47a4a385mtklein    if (1 == FLAGS_key.count() % 2) {
8861915b62637bea20e1471a8a358b22e9e47a4a385mtklein        SkDebugf("ERROR: --key must be passed with an even number of arguments.\n");
88794e51567dd691c3e1e8dfa6005a301d72cecf48emtklein        return 1;
88894e51567dd691c3e1e8dfa6005a301d72cecf48emtklein    }
8891915b62637bea20e1471a8a358b22e9e47a4a385mtklein    for (int i = 1; i < FLAGS_key.count(); i += 2) {
8901915b62637bea20e1471a8a358b22e9e47a4a385mtklein        log->key(FLAGS_key[i-1], FLAGS_key[i]);
89194e51567dd691c3e1e8dfa6005a301d72cecf48emtklein    }
89260317d0ffb5053df7b08a627d6decd11b684e80dmtklein
893f372321de3d4183de5b9ca436e677e471e358f31mtklein    const double overhead = estimate_timer_overhead();
89455b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    SkDebugf("Timer overhead: %s\n", HUMANIZE(overhead));
895912947737a973421f4c58682b6171cb5ee00ad3aMike Klein
896bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    SkAutoTMalloc<double> samples(FLAGS_samples);
897bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
8986eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (kAutoTuneLoops != FLAGS_loops) {
8996eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Fixed number of loops; times would only be misleading so we won't print them.\n");
900a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein    } else if (FLAGS_verbose) {
901f372321de3d4183de5b9ca436e677e471e358f31mtklein        // No header.
902f372321de3d4183de5b9ca436e677e471e358f31mtklein    } else if (FLAGS_quiet) {
90340b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein        SkDebugf("median\tbench\tconfig\n");
904f372321de3d4183de5b9ca436e677e471e358f31mtklein    } else {
905d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein        SkDebugf("curr/maxrss\tloops\tmin\tmedian\tmean\tmax\tstddev\t%-*s\tconfig\tbench\n",
9068247ec313d87afcdd4da59b1f2f0d24e0983e359qiankun.miao                 FLAGS_samples, "samples");
907f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
908f372321de3d4183de5b9ca436e677e471e358f31mtklein
909c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    SkTDArray<Config> configs;
910c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    create_configs(&configs);
911c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
912e070c2bf54c451f0126d4ffb3a48bffe1fbfa437mtklein    int runs = 0;
91392007583e43115998412ac8b0a06cc2780eb025cmtklein    BenchmarkStream benchStream;
91492007583e43115998412ac8b0a06cc2780eb025cmtklein    while (Benchmark* b = benchStream.next()) {
915e714e75c725c987fe682a1f5473224fe3e80380dmtklein        SkAutoTDelete<Benchmark> bench(b);
916962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein        if (SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getUniqueName())) {
917f372321de3d4183de5b9ca436e677e471e358f31mtklein            continue;
918f372321de3d4183de5b9ca436e677e471e358f31mtklein        }
919f372321de3d4183de5b9ca436e677e471e358f31mtklein
920bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        SkTDArray<Target*> targets;
921c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        create_targets(&targets, bench.get(), configs);
922f372321de3d4183de5b9ca436e677e471e358f31mtklein
923bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio        if (!targets.isEmpty()) {
924962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein            log->bench(bench->getUniqueName(), bench->getSize().fX, bench->getSize().fY);
925bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio            bench->preDraw();
926bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio        }
927bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        for (int j = 0; j < targets.count(); j++) {
928d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson            // During HWUI output this canvas may be NULL.
92975a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson            SkCanvas* canvas = targets[j]->getCanvas();
930c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            const char* config = targets[j]->config.name;
931bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
932d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson            targets[j]->setup();
9335b69377507478623dcf5b11f3ecb010f87c4794frobertphillips            bench->perCanvasPreDraw(canvas);
9345b69377507478623dcf5b11f3ecb010f87c4794frobertphillips
935bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein            const int loops =
936d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson                targets[j]->needsFrameTiming()
93775a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson                ? gpu_bench(targets[j], bench.get(), samples.get())
93875a0ebb0d0bd852e3b068bf14370c6689242a89ctomhudson                : cpu_bench(overhead, targets[j], bench.get(), samples.get());
939f372321de3d4183de5b9ca436e677e471e358f31mtklein
9405b69377507478623dcf5b11f3ecb010f87c4794frobertphillips            bench->perCanvasPostDraw(canvas);
9415b69377507478623dcf5b11f3ecb010f87c4794frobertphillips
942d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson            if (Benchmark::kNonRendering_Backend != targets[j]->config.backend &&
943d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson                !FLAGS_writePath.isEmpty() && FLAGS_writePath[0]) {
9446eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                SkString pngFilename = SkOSPath::Join(FLAGS_writePath[0], config);
945962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein                pngFilename = SkOSPath::Join(pngFilename.c_str(), bench->getUniqueName());
9466eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                pngFilename.append(".png");
947d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson                write_canvas_png(targets[j], pngFilename);
9486eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            }
9496eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
9506eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            if (kFailedLoops == loops) {
9512069e220034f09aad2f68b262f395e7c25b3d178mtklein                // Can't be timed.  A warning note has already been printed.
952e3631364e93ee9164f3ce322778d5a50c33f63a6Mike Klein                continue;
953e3631364e93ee9164f3ce322778d5a50c33f63a6Mike Klein            }
95460317d0ffb5053df7b08a627d6decd11b684e80dmtklein
955e3631364e93ee9164f3ce322778d5a50c33f63a6Mike Klein            Stats stats(samples.get(), FLAGS_samples);
9561915b62637bea20e1471a8a358b22e9e47a4a385mtklein            log->config(config);
957962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein            log->configOption("name", bench->getName());
9581915b62637bea20e1471a8a358b22e9e47a4a385mtklein            benchStream.fillCurrentOptions(log.get());
959d968a6f29e92230ee118ec9cdfff0329bf83d602tomhudson            targets[j]->fillOptions(log.get());
960051e56df8f14fae68f0e990f78b85494c2ce4a6bmtklein            log->metric("min_ms",    stats.min);
961e070c2bf54c451f0126d4ffb3a48bffe1fbfa437mtklein            if (runs++ % FLAGS_flushEvery == 0) {
962e070c2bf54c451f0126d4ffb3a48bffe1fbfa437mtklein                log->flush();
963e070c2bf54c451f0126d4ffb3a48bffe1fbfa437mtklein            }
96460317d0ffb5053df7b08a627d6decd11b684e80dmtklein
9656eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            if (kAutoTuneLoops != FLAGS_loops) {
966a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein                if (targets.count() == 1) {
967a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein                    config = ""; // Only print the config if we run the same bench on more than one.
968a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein                }
969d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein                SkDebugf("%4d/%-4dMB\t%s\t%s\n"
970d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein                         , sk_tools::getCurrResidentSetSizeMB()
971d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein                         , sk_tools::getMaxResidentSetSizeMB()
97253d2562006ee371222963750009a706cfd1a94f7mtklein                         , bench->getUniqueName()
97353d2562006ee371222963750009a706cfd1a94f7mtklein                         , config);
974a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            } else if (FLAGS_verbose) {
975f372321de3d4183de5b9ca436e677e471e358f31mtklein                for (int i = 0; i < FLAGS_samples; i++) {
97655b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein                    SkDebugf("%s  ", HUMANIZE(samples[i]));
977f372321de3d4183de5b9ca436e677e471e358f31mtklein                }
978962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein                SkDebugf("%s\n", bench->getUniqueName());
979f372321de3d4183de5b9ca436e677e471e358f31mtklein            } else if (FLAGS_quiet) {
980bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein                if (targets.count() == 1) {
981f372321de3d4183de5b9ca436e677e471e358f31mtklein                    config = ""; // Only print the config if we run the same bench on more than one.
982f372321de3d4183de5b9ca436e677e471e358f31mtklein                }
983962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein                SkDebugf("%s\t%s\t%s\n", HUMANIZE(stats.median), bench->getUniqueName(), config);
984f372321de3d4183de5b9ca436e677e471e358f31mtklein            } else {
985f372321de3d4183de5b9ca436e677e471e358f31mtklein                const double stddev_percent = 100 * sqrt(stats.var) / stats.mean;
986d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein                SkDebugf("%4d/%-4dMB\t%d\t%s\t%s\t%s\t%s\t%.0f%%\t%s\t%s\t%s\n"
987d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein                        , sk_tools::getCurrResidentSetSizeMB()
988d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein                        , sk_tools::getMaxResidentSetSizeMB()
989f372321de3d4183de5b9ca436e677e471e358f31mtklein                        , loops
99055b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein                        , HUMANIZE(stats.min)
99155b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein                        , HUMANIZE(stats.median)
99255b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein                        , HUMANIZE(stats.mean)
99355b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein                        , HUMANIZE(stats.max)
994f372321de3d4183de5b9ca436e677e471e358f31mtklein                        , stddev_percent
9955d9d10e8217d2138b5514a4d4216f95373240942mtklein                        , stats.plot.c_str()
996f372321de3d4183de5b9ca436e677e471e358f31mtklein                        , config
997962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein                        , bench->getUniqueName()
998f372321de3d4183de5b9ca436e677e471e358f31mtklein                        );
999f372321de3d4183de5b9ca436e677e471e358f31mtklein            }
1000b12ea41286ce36e085c5a14711da0cf9f240fdf1bsalomon#if SK_SUPPORT_GPU
1001b12ea41286ce36e085c5a14711da0cf9f240fdf1bsalomon            if (FLAGS_gpuStats &&
100206cddec8570cbf29f89e89736afb0487b5b95abdbsalomon                Benchmark::kGPU_Backend == targets[j]->config.backend) {
10036838d854a87e79f1fbb7b89b9f395155ad44dc0amtklein                gGrFactory->get(targets[j]->config.ctxType)->printCacheStats();
1004b12ea41286ce36e085c5a14711da0cf9f240fdf1bsalomon                gGrFactory->get(targets[j]->config.ctxType)->printGpuStats();
100506cddec8570cbf29f89e89736afb0487b5b95abdbsalomon            }
100606cddec8570cbf29f89e89736afb0487b5b95abdbsalomon#endif
1007f372321de3d4183de5b9ca436e677e471e358f31mtklein        }
1008bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        targets.deleteAll();
10093944a1d2374d2de8622b0192aa080dba6fb92c76Mike Klein
101006cddec8570cbf29f89e89736afb0487b5b95abdbsalomon#if SK_SUPPORT_GPU
10112354f8432a7205571f04f9638a0018fb0b1fb282bsalomon        if (FLAGS_abandonGpuContext) {
101269a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski            gGrFactory->abandonContexts();
10132354f8432a7205571f04f9638a0018fb0b1fb282bsalomon        }
10142354f8432a7205571f04f9638a0018fb0b1fb282bsalomon        if (FLAGS_resetGpuContext || FLAGS_abandonGpuContext) {
101569a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski            gGrFactory->destroyContexts();
10163944a1d2374d2de8622b0192aa080dba6fb92c76Mike Klein        }
101706cddec8570cbf29f89e89736afb0487b5b95abdbsalomon#endif
1018f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
1019f372321de3d4183de5b9ca436e677e471e358f31mtklein
1020e109145bf31d63963b3f78c6af6e404d5464a55bmtklein    log->bench("memory_usage", 0,0);
1021e109145bf31d63963b3f78c6af6e404d5464a55bmtklein    log->config("meta");
1022e109145bf31d63963b3f78c6af6e404d5464a55bmtklein    log->metric("max_rss_mb", sk_tools::getMaxResidentSetSizeMB());
1023e109145bf31d63963b3f78c6af6e404d5464a55bmtklein
1024e0b19d4985846d64bb581013828a9dc5af401a5djoshualitt#if SK_SUPPORT_GPU
1025e0b19d4985846d64bb581013828a9dc5af401a5djoshualitt    // Make sure we clean up the global GrContextFactory here, otherwise we might race with the
1026e0b19d4985846d64bb581013828a9dc5af401a5djoshualitt    // SkEventTracer destructor
1027e0b19d4985846d64bb581013828a9dc5af401a5djoshualitt    gGrFactory.reset(NULL);
1028e0b19d4985846d64bb581013828a9dc5af401a5djoshualitt#endif
1029e0b19d4985846d64bb581013828a9dc5af401a5djoshualitt
1030f372321de3d4183de5b9ca436e677e471e358f31mtklein    return 0;
1031f372321de3d4183de5b9ca436e677e471e358f31mtklein}
1032f372321de3d4183de5b9ca436e677e471e358f31mtklein
10333b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorio#if !defined SK_BUILD_FOR_IOS
10343b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorioint main(int argc, char** argv) {
10353b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorio    SkCommandLineFlags::Parse(argc, argv);
10363b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorio    return nanobench_main();
10373b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorio}
10383b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorio#endif
1039