158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger/*
258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * Copyright 2013 Google Inc.
358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger *
458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * found in the LICENSE file.
658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger */
758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "BenchTimer.h"
958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "LazyDecodeBitmap.h"
1058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "PictureBenchmark.h"
1158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "PictureRenderer.h"
1258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "SkBenchmark.h"
1358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "SkForceLinking.h"
1458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "SkGraphics.h"
1558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "SkStream.h"
1658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "SkString.h"
1758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "SkTArray.h"
1858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "TimerData.h"
1958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
200a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenbergerstatic const int kNumNormalRecordings = 10;
210a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenbergerstatic const int kNumRTreeRecordings = 10;
220a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenbergerstatic const int kNumPlaybacks = 1;
2358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic const size_t kNumBaseBenchmarks = 3;
2458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic const size_t kNumTileSizes = 3;
2558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic const size_t kNumBbhPlaybackBenchmarks = 3;
2658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic const size_t kNumBenchmarks = kNumBaseBenchmarks + kNumBbhPlaybackBenchmarks;
2758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
2858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerenum BenchmarkType {
2958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    kNormal_BenchmarkType = 0,
3058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    kRTree_BenchmarkType,
3158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger};
3258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
3358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstruct Histogram {
3458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    Histogram() {
3558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        // Make fCpuTime negative so that we don't mess with stats:
3658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        fCpuTime = SkIntToScalar(-1);
3758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
3858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkScalar fCpuTime;
3958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkString fPath;
4058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger};
4158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
4258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
430a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger////////////////////////////////////////////////////////////////////////////////
4458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger// Defined below.
450a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenbergerstruct BenchmarkControl;
460a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
470a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenbergertypedef void (*BenchmarkFunction)
480a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    (const BenchmarkControl&, const SkString&, SkPicture*, BenchTimer*);
490a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
5058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic void benchmark_playback(
510a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    const BenchmarkControl&, const SkString&, SkPicture*, BenchTimer*);
5258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic void benchmark_recording(
530a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    const BenchmarkControl&, const SkString&, SkPicture*, BenchTimer*);
540a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger////////////////////////////////////////////////////////////////////////////////
5558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
5658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger/**
5758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * Acts as a POD containing information needed to run a benchmark.
5858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * Provides static methods to poll benchmark info from an index.
5958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger */
6058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstruct BenchmarkControl {
6158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkISize fTileSize;
6258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    BenchmarkType fType;
6358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    BenchmarkFunction fFunction;
6458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkString fName;
6558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
6658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    /**
6758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger     * Will construct a BenchmarkControl instance from an index between 0 an kNumBenchmarks.
6858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger     */
6958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    static BenchmarkControl Make(size_t i) {
7058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkASSERT(kNumBenchmarks > i);
7158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        BenchmarkControl benchControl;
720a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        benchControl.fTileSize = GetTileSize(i);
730a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        benchControl.fType = GetBenchmarkType(i);
740a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        benchControl.fFunction = GetBenchmarkFunc(i);
750a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        benchControl.fName = GetBenchmarkName(i);
7658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        return benchControl;
7758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
7858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
7958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    enum BaseBenchmarks {
8058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        kNormalRecord = 0,
8158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        kRTreeRecord,
8258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        kNormalPlayback,
8358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    };
8458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
8558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    static SkISize fTileSizes[kNumTileSizes];
8658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
870a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    static SkISize GetTileSize(size_t i) {
8858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        // Two of the base benchmarks don't need a tile size. But to maintain simplicity
8958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        // down the pipeline we have to let a couple of values unused.
9058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        if (i < kNumBaseBenchmarks) {
9158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            return SkISize::Make(256, 256);
9258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        }
9358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        if (i >= kNumBaseBenchmarks && i < kNumBenchmarks) {
9458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            return fTileSizes[i - kNumBaseBenchmarks];
9558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        }
9658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkASSERT(0);
9758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        return SkISize::Make(0, 0);
9858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
9958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
1000a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    static BenchmarkType GetBenchmarkType(size_t i) {
10158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        if (i < kNumBaseBenchmarks) {
10258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            switch (i) {
1030a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger            case kNormalRecord:
1040a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger                return kNormal_BenchmarkType;
1050a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger            case kNormalPlayback:
1060a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger                return kNormal_BenchmarkType;
1070a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger            case kRTreeRecord:
1080a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger                return kRTree_BenchmarkType;
10958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            }
11058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        }
11158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        if (i < kNumBenchmarks) {
11258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            return kRTree_BenchmarkType;
11358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        }
11458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkASSERT(0);
11558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        return kRTree_BenchmarkType;
11658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
11758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
1180a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    static BenchmarkFunction GetBenchmarkFunc(size_t i) {
11958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        // Base functions.
12058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        switch (i) {
12158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            case kNormalRecord:
12258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                return benchmark_recording;
12358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            case kNormalPlayback:
12458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                return benchmark_playback;
12558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            case kRTreeRecord:
12658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                return benchmark_recording;
12758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        }
12858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        // RTree playbacks
12958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        if (i < kNumBenchmarks) {
13058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            return benchmark_playback;
13158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        }
13258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkASSERT(0);
13358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        return NULL;
13458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
13558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
1360a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    static SkString GetBenchmarkName(size_t i) {
13758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        // Base benchmark names
13858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        switch (i) {
13958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            case kNormalRecord:
14058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                return SkString("normal_recording");
14158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            case kNormalPlayback:
14258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                return SkString("normal_playback");
14358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            case kRTreeRecord:
14458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                return SkString("rtree_recording");
14558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        }
14658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        // RTree benchmark names.
14758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        if (i < kNumBenchmarks) {
14858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            SkASSERT(i >= kNumBaseBenchmarks);
14958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            SkString name;
15058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            name.printf("rtree_playback_%dx%d",
15158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                    fTileSizes[i - kNumBaseBenchmarks].fWidth,
15258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                    fTileSizes[i - kNumBaseBenchmarks].fHeight);
15358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            return name;
15458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
15558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        } else {
15658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            SkASSERT(0);
15758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        }
15858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        return SkString("");
15958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
16058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
16158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger};
16258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
16358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek SollenbergerSkISize BenchmarkControl::fTileSizes[kNumTileSizes] = {
16458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkISize::Make(256, 256),
16558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkISize::Make(512, 512),
16658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkISize::Make(1024, 1024),
16758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger};
16858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
16958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic SkPicture* pic_from_path(const char path[]) {
17058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkFILEStream stream(path);
17158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (!stream.isValid()) {
17258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkDebugf("-- Can't open '%s'\n", path);
17358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        return NULL;
17458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
17558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    return SkPicture::CreateFromStream(&stream, &sk_tools::LazyDecodeBitmap);
17658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
17758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
17858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger/**
1790a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger * Returns true when a tiled renderer with no bounding box hierarchy produces the given bitmap.
1800a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger */
1810a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenbergerstatic bool compare_picture(const SkString& path, const SkBitmap& inBitmap, SkPicture* pic) {
1820a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    SkBitmap* bitmap;
1830a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    sk_tools::TiledPictureRenderer renderer;
1840a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    renderer.setBBoxHierarchyType(sk_tools::PictureRenderer::kNone_BBoxHierarchyType);
1850a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    renderer.init(pic);
1860a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    renderer.setup();
1870a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    renderer.render(&path, &bitmap);
1880a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    SkAutoTDelete<SkBitmap> bmDeleter(bitmap);
1890a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    renderer.end();
1900a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
1910a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    if (bitmap->getSize() != inBitmap.getSize()) {
1920a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        return false;
1930a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    }
1940a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    return !memcmp(bitmap->getPixels(), inBitmap.getPixels(), bitmap->getSize());
1950a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger}
1960a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
1970a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger/**
19858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * This function is the sink to which all work ends up going.
19958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * Renders the picture into the renderer. It may or may not use an RTree.
20058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * The renderer is chosen upstream. If we want to measure recording, we will
2010a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger * use a RecordPictureRenderer. If we want to measure rendering, we will use a
20258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * TiledPictureRenderer.
20358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger */
20458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic void do_benchmark_work(sk_tools::PictureRenderer* renderer,
20558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        int benchmarkType, const SkString& path, SkPicture* pic,
20658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        const int numRepeats, const char *msg, BenchTimer* timer) {
20758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkString msgPrefix;
20858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
20958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    switch (benchmarkType){
21058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        case kNormal_BenchmarkType:
21158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            msgPrefix.set("Normal");
21258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            renderer->setBBoxHierarchyType(sk_tools::PictureRenderer::kNone_BBoxHierarchyType);
21358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            break;
21458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        case kRTree_BenchmarkType:
21558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            msgPrefix.set("RTree");
21658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            renderer->setBBoxHierarchyType(sk_tools::PictureRenderer::kRTree_BBoxHierarchyType);
21758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            break;
21858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        default:
21958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            SkASSERT(0);
22058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            break;
22158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
22258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
22358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    renderer->init(pic);
22458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
22558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    /**
22658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger     * If the renderer is not tiled, assume we are measuring recording.
22758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger     */
22858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    bool isPlayback = (NULL != renderer->getTiledRenderer());
2290a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    // Will be non-null during RTree picture playback. For correctness test.
2300a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    SkBitmap* bitmap = NULL;
23158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
23258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkDebugf("%s %s %s %d times...\n", msgPrefix.c_str(), msg, path.c_str(), numRepeats);
23358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    for (int i = 0; i < numRepeats; ++i) {
2340a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        // Set up the bitmap.
2350a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        SkBitmap** out = NULL;
2360a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        if (i == 0 && kRTree_BenchmarkType == benchmarkType && isPlayback) {
2370a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger            out = &bitmap;
2380a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        }
2390a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
24058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        renderer->setup();
2410a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        // Render once to fill caches. Fill bitmap during the first iteration.
2420a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        renderer->render(NULL, out);
24358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        // Render again to measure
24458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        timer->start();
24558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        bool result = renderer->render(NULL);
24658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        timer->end();
2470a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
24858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        // We only care about a false result on playback. RecordPictureRenderer::render will always
24958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        // return false because we are passing a NULL file name on purpose; which is fine.
2500a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        if (isPlayback && !result) {
25158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            SkDebugf("Error rendering during playback.\n");
25258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        }
25358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
2540a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    if (bitmap) {
2550a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        SkAutoTDelete<SkBitmap> bmDeleter(bitmap);
2560a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        if (!compare_picture(path, *bitmap, pic)) {
2570a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger            SkDebugf("Error: RTree produced different bitmap\n");
2580a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        }
2590a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    }
26058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
26158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
26258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger/**
26358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * Call do_benchmark_work with a tiled renderer using the default tile dimensions.
26458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger */
26558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic void benchmark_playback(
2660a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        const BenchmarkControl& benchControl,
26758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        const SkString& path, SkPicture* pic, BenchTimer* timer) {
26858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    sk_tools::TiledPictureRenderer renderer;
26958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
27058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkString message("tiled_playback");
2710a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    message.appendf("_%dx%d", benchControl.fTileSize.fWidth, benchControl.fTileSize.fHeight);
2720a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    do_benchmark_work(&renderer, benchControl.fType,
27358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            path, pic, kNumPlaybacks, message.c_str(), timer);
27458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
27558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
27658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger/**
27758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * Call do_benchmark_work with a RecordPictureRenderer.
27858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger */
27958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic void benchmark_recording(
2800a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        const BenchmarkControl& benchControl,
28158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        const SkString& path, SkPicture* pic, BenchTimer* timer) {
28258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    sk_tools::RecordPictureRenderer renderer;
28358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    int numRecordings = 0;
2840a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    switch(benchControl.fType) {
28558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        case kRTree_BenchmarkType:
28658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            numRecordings = kNumRTreeRecordings;
28758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            break;
28858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        case kNormal_BenchmarkType:
28958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            numRecordings = kNumNormalRecordings;
29058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            break;
29158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
2920a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    do_benchmark_work(&renderer, benchControl.fType,
2930a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger            path, pic, numRecordings, "recording", timer);
29458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
29558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
29658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger/**
29758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * Takes argc,argv along with one of the benchmark functions defined above.
29858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * Will loop along all skp files and perform measurments.
29958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger *
30058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * Returns a SkScalar representing CPU time taken during benchmark.
30158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * As a side effect, it spits the timer result to stdout.
30258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * Will return -1.0 on error.
30358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger */
30458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic bool benchmark_loop(
30558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        int argc,
30658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        char **argv,
30758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        const BenchmarkControl& benchControl,
30858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkTArray<Histogram>& histogram) {
30958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    static const SkString timeFormat("%f");
310e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    TimerData timerData(argc - 1);
31158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    for (int index = 1; index < argc; ++index) {
31258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        BenchTimer timer;
31358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkString path(argv[index]);
31458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkAutoTUnref<SkPicture> pic(pic_from_path(path.c_str()));
31558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        if (NULL == pic) {
31658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            SkDebugf("Couldn't create picture. Ignoring path: %s\n", path.c_str());
31758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            continue;
31858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        }
3190a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        benchControl.fFunction(benchControl, path, pic, &timer);
32058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
32158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        histogram[index - 1].fPath = path;
32258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        histogram[index - 1].fCpuTime = SkDoubleToScalar(timer.fCpu);
32358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
32458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
32558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    const SkString timerResult = timerData.getResult(
326e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            /*doubleFormat = */ timeFormat.c_str(),
327e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            /*result = */ TimerData::kAvg_Result,
32858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            /*configName = */ benchControl.fName.c_str(),
329e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            /*timerFlags = */ TimerData::kCpu_Flag);
33058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
33158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    const char findStr[] = "= ";
33258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    int pos = timerResult.find(findStr);
33358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (-1 == pos) {
3340a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        SkDebugf("Unexpected output from TimerData::getResult(...). Unable to parse.\n");
33558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        return false;
33658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
33758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
33858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkScalar cpuTime = SkDoubleToScalar(atof(timerResult.c_str() + pos + sizeof(findStr) - 1));
33958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (cpuTime == 0) {  // atof returns 0.0 on error.
34058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkDebugf("Unable to read value from timer result.\n");
34158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        return false;
34258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
34358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    return true;
34458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
34558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
34658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerint tool_main(int argc, char** argv);
34758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerint tool_main(int argc, char** argv) {
34858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkAutoGraphics ag;
34958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkString usage;
35058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    usage.printf("Usage: filename [filename]*\n");
35158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
35258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (argc < 2) {
35358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkDebugf("%s\n", usage.c_str());
35458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        return -1;
35558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
35658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
35758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkTArray<Histogram> histograms[kNumBenchmarks];
35858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
35958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    for (size_t i = 0; i < kNumBenchmarks; ++i) {
36058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        histograms[i].reset(argc - 1);
36158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        bool success = benchmark_loop(
36258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                argc, argv,
36358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                BenchmarkControl::Make(i),
36458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                histograms[i]);
36558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        if (!success) {
3660a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger            SkDebugf("benchmark_loop failed at index %d\n", i);
36758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        }
36858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
36958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
37058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    // Output gnuplot readable histogram data..
37158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    const char* pbTitle = "bbh_shootout_playback.dat";
37258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    const char* recTitle = "bbh_shootout_record.dat";
37358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkFILEWStream playbackOut(pbTitle);
37458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkFILEWStream recordOut(recTitle);
37558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    recordOut.writeText("# ");
37658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    playbackOut.writeText("# ");
37758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    for (size_t i = 0; i < kNumBenchmarks; ++i) {
37858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkString out;
3790a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        out.printf("%s ", BenchmarkControl::GetBenchmarkName(i).c_str());
3800a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        if (BenchmarkControl::GetBenchmarkFunc(i) == &benchmark_recording) {
38158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            recordOut.writeText(out.c_str());
38258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        }
3830a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        if (BenchmarkControl::GetBenchmarkFunc(i) == &benchmark_playback) {
38458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            playbackOut.writeText(out.c_str());
38558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        }
38658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
38758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    recordOut.writeText("\n");
38858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    playbackOut.writeText("\n");
3890a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    // Write to file, and save recording averages.
3900a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    SkScalar avgRecord = SkIntToScalar(0);
3910a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    SkScalar avgPlayback = SkIntToScalar(0);
3920a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    SkScalar avgRecordRTree = SkIntToScalar(0);
3930a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    SkScalar avgPlaybackRTree = SkIntToScalar(0);
39458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    for (int i = 0; i < argc - 1; ++i) {
39558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkString pbLine;
39658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkString recLine;
39758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        // ==== Write record info
39858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        recLine.printf("%d ", i);
3990a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        SkScalar cpuTime = histograms[BenchmarkControl::kNormalRecord][i].fCpuTime;
4000a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        recLine.appendf("%f ", cpuTime);
4010a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        avgRecord += cpuTime;
4020a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        cpuTime = histograms[BenchmarkControl::kRTreeRecord][i].fCpuTime;
4030a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        recLine.appendf("%f", cpuTime);
4040a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        avgRecordRTree += cpuTime;
4050a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        avgPlaybackRTree += cpuTime;
40658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
40758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        // ==== Write playback info
40858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        pbLine.printf("%d ", i);
40958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        pbLine.appendf("%f ", histograms[2][i].fCpuTime);  // Start with normal playback time.
4100a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        avgPlayback += histograms[kNumBbhPlaybackBenchmarks - 1][i].fCpuTime;
4110a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        avgPlaybackRTree += histograms[kNumBbhPlaybackBenchmarks][i].fCpuTime;
41258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        // Append all playback benchmark times.
41358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        for (size_t j = kNumBbhPlaybackBenchmarks; j < kNumBenchmarks; ++j) {
41458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            pbLine.appendf("%f ", histograms[j][i].fCpuTime);
41558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        }
41658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        pbLine.remove(pbLine.size() - 1, 1);  // Remove trailing space from line.
41758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        pbLine.appendf("\n");
41858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        recLine.appendf("\n");
41958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        playbackOut.writeText(pbLine.c_str());
42058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        recordOut.writeText(recLine.c_str());
42158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
4220a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    avgRecord /= argc - 1;
4230a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    avgRecordRTree /= argc - 1;
4240a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    avgPlayback /= argc - 1;
4250a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    avgPlaybackRTree /= argc - 1;
4260a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    SkDebugf("Average base recording time: %.3fms\n", avgRecord);
4270a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    SkDebugf("Average recording time with rtree: %.3fms\n", avgRecordRTree);
4280a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    SkDebugf("Average base playback time: %.3fms\n", avgPlayback);
4290a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    SkDebugf("Average playback time with rtree: %.3fms\n", avgPlaybackRTree);
4300a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
43158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkDebugf("\nWrote data to gnuplot-readable files: %s %s\n", pbTitle, recTitle);
43258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
43358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    return 0;
43458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
43558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
43658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL)
43758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerint main(int argc, char** argv) {
43858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    return tool_main(argc, argv);
43958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
44058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#endif
441