benchmain.cpp revision 9ef1d21dc8edd167ebbf1ec35f25769f9f6b683b
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
8971d0c8049c6bfc7a58f0b41f8f59f9ec9ca077bbsalomon@google.com
9cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
10971d0c8049c6bfc7a58f0b41f8f59f9ec9ca077bbsalomon@google.com#include "GrContext.h"
11cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com#include "GrContextFactory.h"
12971d0c8049c6bfc7a58f0b41f8f59f9ec9ca077bbsalomon@google.com#include "GrRenderTarget.h"
13cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#include "SkGpuDevice.h"
14c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com#include "gl/GrGLDefines.h"
1541809934d77a486ac30e36baadc519cbb11c4c05bsalomon@google.com#else
1641809934d77a486ac30e36baadc519cbb11c4c05bsalomon@google.comclass GrContext;
17cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif // SK_SUPPORT_GPU
18971d0c8049c6bfc7a58f0b41f8f59f9ec9ca077bbsalomon@google.com
19c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com#include "BenchTimer.h"
209a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com#include "SkBenchLogger.h"
21971d0c8049c6bfc7a58f0b41f8f59f9ec9ca077bbsalomon@google.com#include "SkBenchmark.h"
2273672254a3e498081967d00d27b17ada443e2ab2robertphillips@google.com#include "SkBitmapDevice.h"
23bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com#include "SkCanvas.h"
2478d0379dcc777b4bc4965cff0c2b3fc44ccaef56mtklein@google.com#include "SkColorPriv.h"
25586db93c447b753364d50fadc5426de4fef9a759sglez@google.com#include "SkCommandLineFlags.h"
2682a7bfcb2dbd4f8845a85fc8bddf2c1e59528582bsalomon@google.com#include "SkDeferredCanvas.h"
273a859a00342ed078af683fd1901fd26c93dd40f0reed@android.com#include "SkGraphics.h"
28b398fe863860b072306b5297c8095c6d973aba06reed@android.com#include "SkImageEncoder.h"
29c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com#include "SkOSFile.h"
306c924ad46c89955e78e071c792ef00df9910b42freed@android.com#include "SkPicture.h"
31bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com#include "SkString.h"
32fdd909ca000801aced49881558760170b5f1eb97keyar@chromium.org
339ef1d21dc8edd167ebbf1ec35f25769f9f6b683bmtklein@google.com#include <limits>
349ef1d21dc8edd167ebbf1ec35f25769f9f6b683bmtklein@google.com
35c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comenum BenchMode {
36c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    kNormal_BenchMode,
37c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    kDeferred_BenchMode,
38c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    kDeferredSilent_BenchMode,
39c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    kRecord_BenchMode,
40c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    kPictureRecord_BenchMode
41c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com};
42dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.comconst char* BenchMode_Name[] = {
43dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com    "normal", "deferred", "deferredSilent", "record", "picturerecord"
44dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com};
45515dcd36032997ce335daa0163c6d67e851bcad1commit-bot@chromium.org
46fdd909ca000801aced49881558760170b5f1eb97keyar@chromium.org///////////////////////////////////////////////////////////////////////////////
47fdd909ca000801aced49881558760170b5f1eb97keyar@chromium.org
486c924ad46c89955e78e071c792ef00df9910b42freed@android.comstatic void erase(SkBitmap& bm) {
496c924ad46c89955e78e071c792ef00df9910b42freed@android.com    if (bm.config() == SkBitmap::kA8_Config) {
50dbfac8a72393eaf01670aeb3244de0e18d8faf98junov@google.com        bm.eraseColor(SK_ColorTRANSPARENT);
516c924ad46c89955e78e071c792ef00df9910b42freed@android.com    } else {
526c924ad46c89955e78e071c792ef00df9910b42freed@android.com        bm.eraseColor(SK_ColorWHITE);
536c924ad46c89955e78e071c792ef00df9910b42freed@android.com    }
546c924ad46c89955e78e071c792ef00df9910b42freed@android.com}
556c924ad46c89955e78e071c792ef00df9910b42freed@android.com
56bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.comclass Iter {
57bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.compublic:
58c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    Iter() : fBench(BenchRegistry::Head()) {}
59fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
60bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com    SkBenchmark* next() {
61bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com        if (fBench) {
62bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com            BenchRegistry::Factory f = fBench->factory();
63bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com            fBench = fBench->next();
64410e6e80f00a6c660675c80904807a041c7b7d2amtklein@google.com            return f();
65bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com        }
66bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com        return NULL;
67bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com    }
68d1a416a97cac1769c1616cd3b092876dc6077e59bungeman@google.com
69bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.comprivate:
70bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com    const BenchRegistry* fBench;
71bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com};
72bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com
7330e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.comclass AutoPrePostDraw {
7430e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.compublic:
7530e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com    AutoPrePostDraw(SkBenchmark* bench) : fBench(bench) {
7630e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com        fBench->preDraw();
7730e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com    }
7830e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com    ~AutoPrePostDraw() {
7930e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com        fBench->postDraw();
8030e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com    }
8130e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.comprivate:
8230e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com    SkBenchmark* fBench;
8330e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com};
8430e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com
85bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.comstatic void make_filename(const char name[], SkString* path) {
86bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com    path->set(name);
87bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com    for (int i = 0; name[i]; i++) {
88bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com        switch (name[i]) {
89bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com            case '/':
90bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com            case '\\':
91bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com            case ' ':
92bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com            case ':':
93bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com                path->writable_str()[i] = '-';
94bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com                break;
95bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com            default:
96bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com                break;
97bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com        }
98bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com    }
99bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com}
100bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com
1014c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.comstatic void saveFile(const char name[], const char config[], const char dir[],
1024c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com                     const SkBitmap& bm) {
1034c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com    SkBitmap copy;
1044c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com    if (!bm.copyTo(&copy, SkBitmap::kARGB_8888_Config)) {
1054c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com        return;
1064c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com    }
107fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
108f523e25da069e3e1af2cb73d37073a34f3bb9ea2reed@android.com    if (bm.config() == SkBitmap::kA8_Config) {
109f523e25da069e3e1af2cb73d37073a34f3bb9ea2reed@android.com        // turn alpha into gray-scale
110f523e25da069e3e1af2cb73d37073a34f3bb9ea2reed@android.com        size_t size = copy.getSize() >> 2;
111f523e25da069e3e1af2cb73d37073a34f3bb9ea2reed@android.com        SkPMColor* p = copy.getAddr32(0, 0);
112f523e25da069e3e1af2cb73d37073a34f3bb9ea2reed@android.com        for (size_t i = 0; i < size; i++) {
113f523e25da069e3e1af2cb73d37073a34f3bb9ea2reed@android.com            int c = (*p >> SK_A32_SHIFT) & 0xFF;
114f523e25da069e3e1af2cb73d37073a34f3bb9ea2reed@android.com            c = 255 - c;
115f523e25da069e3e1af2cb73d37073a34f3bb9ea2reed@android.com            c |= (c << 24) | (c << 16) | (c << 8);
116f523e25da069e3e1af2cb73d37073a34f3bb9ea2reed@android.com            *p++ = c | (SK_A32_MASK << SK_A32_SHIFT);
117f523e25da069e3e1af2cb73d37073a34f3bb9ea2reed@android.com        }
118f523e25da069e3e1af2cb73d37073a34f3bb9ea2reed@android.com    }
119fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
120c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    SkString filename;
121c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    make_filename(name, &filename);
122c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    filename.appendf("_%s.png", config);
123c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    SkString path = SkOSPath::SkPathJoin(dir, filename.c_str());
124c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    ::remove(path.c_str());
125c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    SkImageEncoder::EncodeFile(path.c_str(), copy, SkImageEncoder::kPNG_Type, 100);
1264c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com}
1274c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com
1284c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.comstatic void performClip(SkCanvas* canvas, int w, int h) {
1294c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com    SkRect r;
130fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1314c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com    r.set(SkIntToScalar(10), SkIntToScalar(10),
1324c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com          SkIntToScalar(w*2/3), SkIntToScalar(h*2/3));
1334c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com    canvas->clipRect(r, SkRegion::kIntersect_Op);
134fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1354c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com    r.set(SkIntToScalar(w/3), SkIntToScalar(h/3),
1364c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com          SkIntToScalar(w-10), SkIntToScalar(h-10));
1374c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com    canvas->clipRect(r, SkRegion::kXOR_Op);
1384c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com}
1394c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com
1404c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.comstatic void performRotate(SkCanvas* canvas, int w, int h) {
1414c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com    const SkScalar x = SkIntToScalar(w) / 2;
1424c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com    const SkScalar y = SkIntToScalar(h) / 2;
143fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1444c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com    canvas->translate(x, y);
1454c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com    canvas->rotate(SkIntToScalar(35));
1464c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com    canvas->translate(-x, -y);
1474c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com}
1484c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com
149387359e3483056a7ae7e4cf50347b71b4e3b2d60reed@android.comstatic void performScale(SkCanvas* canvas, int w, int h) {
150387359e3483056a7ae7e4cf50347b71b4e3b2d60reed@android.com    const SkScalar x = SkIntToScalar(w) / 2;
151387359e3483056a7ae7e4cf50347b71b4e3b2d60reed@android.com    const SkScalar y = SkIntToScalar(h) / 2;
152fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
153387359e3483056a7ae7e4cf50347b71b4e3b2d60reed@android.com    canvas->translate(x, y);
154387359e3483056a7ae7e4cf50347b71b4e3b2d60reed@android.com    // just enough so we can't take the sprite case
155387359e3483056a7ae7e4cf50347b71b4e3b2d60reed@android.com    canvas->scale(SK_Scalar1 * 99/100, SK_Scalar1 * 99/100);
156387359e3483056a7ae7e4cf50347b71b4e3b2d60reed@android.com    canvas->translate(-x, -y);
157387359e3483056a7ae7e4cf50347b71b4e3b2d60reed@android.com}
158387359e3483056a7ae7e4cf50347b71b4e3b2d60reed@android.com
159a9015f897cd32f549349994e8163ead1db442088mike@reedtribe.orgenum Backend {
160604a56ad4201cc66a85d7bf20efe201ec14b2c1fbsalomon@google.com    kNonRendering_Backend,
161a9015f897cd32f549349994e8163ead1db442088mike@reedtribe.org    kRaster_Backend,
162a9015f897cd32f549349994e8163ead1db442088mike@reedtribe.org    kGPU_Backend,
163a9015f897cd32f549349994e8163ead1db442088mike@reedtribe.org    kPDF_Backend,
164a9015f897cd32f549349994e8163ead1db442088mike@reedtribe.org};
165a9015f897cd32f549349994e8163ead1db442088mike@reedtribe.org
1661f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comstatic SkBaseDevice* make_device(SkBitmap::Config config, const SkIPoint& size,
1671f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com                                 Backend backend, int sampleCount, GrContext* context) {
1681f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* device = NULL;
169a9015f897cd32f549349994e8163ead1db442088mike@reedtribe.org    SkBitmap bitmap;
170a9015f897cd32f549349994e8163ead1db442088mike@reedtribe.org    bitmap.setConfig(config, size.fX, size.fY);
171fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
172a9015f897cd32f549349994e8163ead1db442088mike@reedtribe.org    switch (backend) {
173a9015f897cd32f549349994e8163ead1db442088mike@reedtribe.org        case kRaster_Backend:
174a9015f897cd32f549349994e8163ead1db442088mike@reedtribe.org            bitmap.allocPixels();
175a9015f897cd32f549349994e8163ead1db442088mike@reedtribe.org            erase(bitmap);
1761f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com            device = SkNEW_ARGS(SkBitmapDevice, (bitmap));
177a9015f897cd32f549349994e8163ead1db442088mike@reedtribe.org            break;
178cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
179cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com        case kGPU_Backend: {
180cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com            GrTextureDesc desc;
181cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com            desc.fConfig = kSkia8888_GrPixelConfig;
182cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com            desc.fFlags = kRenderTarget_GrTextureFlagBit;
183cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com            desc.fWidth = size.fX;
184cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com            desc.fHeight = size.fY;
1858a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com            desc.fSampleCnt = sampleCount;
186cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com            SkAutoTUnref<GrTexture> texture(context->createUncachedTexture(desc, NULL, 0));
187cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com            if (!texture) {
188cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com                return NULL;
189cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com            }
190cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com            device = SkNEW_ARGS(SkGpuDevice, (context, texture.get()));
191a9015f897cd32f549349994e8163ead1db442088mike@reedtribe.org            break;
192cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com        }
193cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif
194a9015f897cd32f549349994e8163ead1db442088mike@reedtribe.org        case kPDF_Backend:
195a9015f897cd32f549349994e8163ead1db442088mike@reedtribe.org        default:
196330313a8a8343876ee596da39da06a5d69badd9cmtklein@google.com            SkDEBUGFAIL("unsupported");
197a9015f897cd32f549349994e8163ead1db442088mike@reedtribe.org    }
198a9015f897cd32f549349994e8163ead1db442088mike@reedtribe.org    return device;
199a9015f897cd32f549349994e8163ead1db442088mike@reedtribe.org}
200a9015f897cd32f549349994e8163ead1db442088mike@reedtribe.org
201cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com#if SK_SUPPORT_GPU
202cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.comGrContextFactory gContextFactory;
203cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.comtypedef GrContextFactory::GLContextType GLContextType;
204c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comstatic const GLContextType kNative = GrContextFactory::kNative_GLContextType;
205c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com#if SK_ANGLE
206c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comstatic const GLContextType kANGLE  = GrContextFactory::kANGLE_GLContextType;
207c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com#else
208c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comstatic const GLContextType kANGLE  = kNative;
209c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com#endif
210c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comstatic const GLContextType kDebug  = GrContextFactory::kDebug_GLContextType;
211c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comstatic const GLContextType kNull   = GrContextFactory::kNull_GLContextType;
212cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com#else
213cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.comtypedef int GLContextType;
214c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comstatic const GLContextType kNative = 0, kANGLE = 0, kDebug = 0, kNull = 0;
215c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com#endif
216c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
217c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com#ifdef SK_DEBUG
218c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comstatic const bool kIsDebug = true;
219c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com#else
220c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comstatic const bool kIsDebug = false;
221cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com#endif
222cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com
223c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comstatic const struct Config {
224c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    SkBitmap::Config    config;
225c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    const char*         name;
226c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    int                 sampleCount;
227c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    Backend             backend;
228c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    GLContextType       contextType;
229c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    bool                runByDefault;
2304bc1983e01d756ae9c91fd380758457f579d26eareed@android.com} gConfigs[] = {
231c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    { SkBitmap::kNo_Config,        "NONRENDERING", 0, kNonRendering_Backend, kNative, true},
232c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    { SkBitmap::kARGB_8888_Config, "8888",         0, kRaster_Backend,       kNative, true},
233c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    { SkBitmap::kRGB_565_Config,   "565",          0, kRaster_Backend,       kNative, true},
234cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
235c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    { SkBitmap::kARGB_8888_Config, "GPU",          0, kGPU_Backend,          kNative, true},
236c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    { SkBitmap::kARGB_8888_Config, "MSAA4",        4, kGPU_Backend,          kNative, false},
237c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    { SkBitmap::kARGB_8888_Config, "MSAA16",      16, kGPU_Backend,          kNative, false},
238d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com#if SK_ANGLE
239c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    { SkBitmap::kARGB_8888_Config, "ANGLE",        0, kGPU_Backend,          kANGLE,  true},
240cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif // SK_ANGLE
241c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    { SkBitmap::kARGB_8888_Config, "Debug",        0, kGPU_Backend,          kDebug,  kIsDebug},
242c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    { SkBitmap::kARGB_8888_Config, "NULLGPU",      0, kGPU_Backend,          kNull,   true},
243cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif // SK_SUPPORT_GPU
2444bc1983e01d756ae9c91fd380758457f579d26eareed@android.com};
2454bc1983e01d756ae9c91fd380758457f579d26eareed@android.com
246c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comDEFINE_string(outDir, "", "If given, image of each bench will be put in outDir.");
247c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comDEFINE_string(timers, "cg", "Timers to display. "
248c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com              "Options: w(all) W(all, truncated) c(pu) C(pu, truncated) g(pu)");
249c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
250c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comDEFINE_bool(rotate, false,  "Rotate canvas before bench run?");
251c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comDEFINE_bool(scale,  false,  "Scale canvas before bench run?");
252c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comDEFINE_bool(clip,   false,  "Clip canvas before bench run?");
253c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
254c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comDEFINE_bool(forceAA,        true,     "Force anti-aliasing?");
255c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comDEFINE_bool(forceFilter,    false,    "Force bitmap filtering?");
256c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comDEFINE_string(forceDither, "default", "Force dithering: true, false, or default?");
257c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comDEFINE_bool(forceBlend,     false,    "Force alpha blending?");
258c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
259c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comDEFINE_int32(gpuCacheBytes, -1, "GPU cache size limit in bytes.  0 to disable cache.");
260c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comDEFINE_int32(gpuCacheCount, -1, "GPU cache size limit in object count.  0 to disable cache.");
261c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
262c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comDEFINE_string(match, "",  "[~][^]substring[$] [...] of test name to run.\n"
263c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                          "Multiple matches may be separated by spaces.\n"
264c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                          "~ causes a matching test to always be skipped\n"
265c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                          "^ requires the start of the test to match\n"
266c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                          "$ requires the end of the test to match\n"
267c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                          "^ and $ requires an exact match\n"
268c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                          "If a test does not match any list entry,\n"
269c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                          "it is skipped unless some list entry starts with ~\n");
270c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comDEFINE_string(mode, "normal",
271c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com             "normal:         draw to a normal canvas;\n"
272c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com             "deferred:       draw to a deferred canvas;\n"
273c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com             "deferredSilent: deferred with silent playback;\n"
274c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com             "record:         draw to an SkPicture;\n"
275c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com             "picturerecord:  draw from an SkPicture to an SkPicture.\n");
276c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comDEFINE_string(config, "", "Run configs given.  If empty, runs the defaults set in gConfigs.");
277c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comDEFINE_string(logFile, "", "Also write stdout here.");
278dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.comDEFINE_int32(minMs, 20,  "Shortest time we'll allow a benchmark to run.");
279dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.comDEFINE_int32(maxMs, 4000, "Longest time we'll allow a benchmark to run.");
280dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.comDEFINE_double(error, 0.01,
281dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com              "Ratio of subsequent bench measurements must drop within 1±error to converge.");
282c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comDEFINE_string(timeFormat, "%9.2f", "Format to print results, in milliseconds per 1000 loops.");
283dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.comDEFINE_bool2(verbose, v, false, "Print more.");
284dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com
285dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com// Has this bench converged?  First arguments are milliseconds / loop iteration,
286dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com// last is overall runtime in milliseconds.
287dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.comstatic bool HasConverged(double prevPerLoop, double currPerLoop, double currRaw) {
288dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com    if (currRaw < FLAGS_minMs) {
289dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com        return false;
290dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com    }
291dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com    const double low = 1 - FLAGS_error, high = 1 + FLAGS_error;
292dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com    const double ratio = currPerLoop / prevPerLoop;
293dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com    return low < ratio && ratio < high;
294dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com}
29586bb9b73a00d16eb13a6db13c5d2f775040caf13tomhudson@google.com
2965987f58036574ccf23049b5fe71f29a441d0641dcaryclark@google.comint tool_main(int argc, char** argv);
2975987f58036574ccf23049b5fe71f29a441d0641dcaryclark@google.comint tool_main(int argc, char** argv) {
2984e23068b374023d43c4c725138d523721d975892bsalomon@google.com#if SK_ENABLE_INST_COUNT
29965a87cc13d6babcf12844cca244ca7cc5258cadcbsalomon@google.com    gPrintInstCount = true;
30065a87cc13d6babcf12844cca244ca7cc5258cadcbsalomon@google.com#endif
3013a859a00342ed078af683fd1901fd26c93dd40f0reed@android.com    SkAutoGraphics ag;
302c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    SkCommandLineFlags::Parse(argc, argv);
30365a87cc13d6babcf12844cca244ca7cc5258cadcbsalomon@google.com
304c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    // First, parse some flags.
30555fd612adfd08f5c64fb728bc37a2cb4ae224656commit-bot@chromium.org
306c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    SkBenchLogger logger;
307c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    if (FLAGS_logFile.count()) {
308c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        logger.SetLogFile(FLAGS_logFile[0]);
309c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    }
31055fd612adfd08f5c64fb728bc37a2cb4ae224656commit-bot@chromium.org
311c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    const uint8_t alpha = FLAGS_forceBlend ? 0x80 : 0xFF;
312c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    SkTriState::State dither = SkTriState::kDefault;
313c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    for (size_t i = 0; i < 3; i++) {
314c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        if (strcmp(SkTriState::Name[i], FLAGS_forceDither[0]) == 0) {
315c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            dither = static_cast<SkTriState::State>(i);
316c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        }
317c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    }
318c732f259fa9cb0045623f3e0e3f033c20f06be8cbsalomon@google.com
319c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    BenchMode benchMode = kNormal_BenchMode;
320c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    for (size_t i = 0; i < SK_ARRAY_COUNT(BenchMode_Name); i++) {
321c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        if (strcmp(FLAGS_mode[0], BenchMode_Name[i]) == 0) {
322c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            benchMode = static_cast<BenchMode>(i);
323c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        }
324c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    }
325c732f259fa9cb0045623f3e0e3f033c20f06be8cbsalomon@google.com
32613eaaaa75a16fa300fa212ec910107f77530ef2ctomhudson@google.com    SkTDArray<int> configs;
327c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    // Try user-given configs first.
328c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    for (int i = 0; i < FLAGS_config.count(); i++) {
329c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        for (size_t j = 0; j < SK_ARRAY_COUNT(gConfigs); j++) {
330c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            if (0 == strcmp(FLAGS_config[i], gConfigs[j].name)) {
331c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                *configs.append() = j;
332e9d0060f4d7b5a07a220182d83aae3a140784c4breed@android.com            }
333b398fe863860b072306b5297c8095c6d973aba06reed@android.com        }
334b398fe863860b072306b5297c8095c6d973aba06reed@android.com    }
335c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    // If there weren't any, fill in with defaults.
336c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    if (configs.count() == 0) {
337c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        for (size_t i = 0; i < SK_ARRAY_COUNT(gConfigs); ++i) {
338c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            if (gConfigs[i].runByDefault) {
3398a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com                *configs.append() = i;
3408a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com            }
34113eaaaa75a16fa300fa212ec910107f77530ef2ctomhudson@google.com        }
34213eaaaa75a16fa300fa212ec910107f77530ef2ctomhudson@google.com    }
343c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    // Filter out things we can't run.
344c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    if (kNormal_BenchMode != benchMode) {
345604a56ad4201cc66a85d7bf20efe201ec14b2c1fbsalomon@google.com        // Non-rendering configs only run in normal mode
346604a56ad4201cc66a85d7bf20efe201ec14b2c1fbsalomon@google.com        for (int i = 0; i < configs.count(); ++i) {
347c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            const Config& config = gConfigs[configs[i]];
348c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            if (kNonRendering_Backend == config.backend) {
349604a56ad4201cc66a85d7bf20efe201ec14b2c1fbsalomon@google.com                configs.remove(i, 1);
350604a56ad4201cc66a85d7bf20efe201ec14b2c1fbsalomon@google.com                --i;
351604a56ad4201cc66a85d7bf20efe201ec14b2c1fbsalomon@google.com            }
352604a56ad4201cc66a85d7bf20efe201ec14b2c1fbsalomon@google.com        }
353604a56ad4201cc66a85d7bf20efe201ec14b2c1fbsalomon@google.com    }
3548a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com#if SK_SUPPORT_GPU
3558a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com    for (int i = 0; i < configs.count(); ++i) {
356c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        const Config& config = gConfigs[configs[i]];
3578a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com
358c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        if (kGPU_Backend == config.backend) {
359c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            GrContext* context = gContextFactory.get(config.contextType);
3608a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com            if (NULL == context) {
361dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com                logger.logError(SkStringPrintf(
362dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com                    "Error creating GrContext for config %s. Config will be skipped.\n",
363dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com                    config.name));
3648a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com                configs.remove(i);
3658a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com                --i;
3668a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com                continue;
3678a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com            }
368c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            if (config.sampleCount > context->getMaxSampleCount()){
369dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com                logger.logError(SkStringPrintf(
370dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com                    "Sample count (%d) for config %s is unsupported. Config will be skipped.\n",
371dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com                    config.sampleCount, config.name));
3728a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com                configs.remove(i);
3738a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com                --i;
3748a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com                continue;
3758a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com            }
3768a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com        }
3778a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com    }
3788a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com#endif
3798a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com
380c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    // All flags should be parsed now.  Report our settings.
381c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    if (kIsDebug) {
382c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        logger.logError("bench was built in Debug mode, so we're going to hide the times."
383c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                        "  It's for your own good!\n");
384c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    }
385c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    SkString str("skia bench:");
386c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    str.appendf(" mode=%s", FLAGS_mode[0]);
387c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    str.appendf(" alpha=0x%02X antialias=%d filter=%d dither=%s",
388c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                alpha, FLAGS_forceAA, FLAGS_forceFilter, SkTriState::Name[dither]);
389c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    str.appendf(" rotate=%d scale=%d clip=%d", FLAGS_rotate, FLAGS_scale, FLAGS_clip);
390c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
391c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com#if defined(SK_SCALAR_IS_FIXED)
392c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    str.append(" scalar=fixed");
393c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com#else
394c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    str.append(" scalar=float");
395a5d48414249b7df5387ac572d178a1b6550880a5bungeman@google.com#endif
396a5d48414249b7df5387ac572d178a1b6550880a5bungeman@google.com
397a5d48414249b7df5387ac572d178a1b6550880a5bungeman@google.com#if defined(SK_BUILD_FOR_WIN32)
398c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    str.append(" system=WIN32");
399a5d48414249b7df5387ac572d178a1b6550880a5bungeman@google.com#elif defined(SK_BUILD_FOR_MAC)
400c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    str.append(" system=MAC");
401a5d48414249b7df5387ac572d178a1b6550880a5bungeman@google.com#elif defined(SK_BUILD_FOR_ANDROID)
402c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    str.append(" system=ANDROID");
403a5d48414249b7df5387ac572d178a1b6550880a5bungeman@google.com#elif defined(SK_BUILD_FOR_UNIX)
404c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    str.append(" system=UNIX");
405a5d48414249b7df5387ac572d178a1b6550880a5bungeman@google.com#else
406c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    str.append(" system=other");
407a5d48414249b7df5387ac572d178a1b6550880a5bungeman@google.com#endif
408a5d48414249b7df5387ac572d178a1b6550880a5bungeman@google.com
409a5d48414249b7df5387ac572d178a1b6550880a5bungeman@google.com#if defined(SK_DEBUG)
410c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    str.append(" DEBUG");
411a5d48414249b7df5387ac572d178a1b6550880a5bungeman@google.com#endif
412c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    str.append("\n");
413c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    logger.logProgress(str);
414c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
415508824bd4b944a77cefad527006e687e5cd927d2bsalomon@google.com
416c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    // Set texture cache limits if non-default.
4175c90e291425b2788f47679266d9584845ceefc2ebsalomon@google.com    for (size_t i = 0; i < SK_ARRAY_COUNT(gConfigs); ++i) {
418cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com#if SK_SUPPORT_GPU
419c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        const Config& config = gConfigs[i];
420c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        if (kGPU_Backend != config.backend) {
421c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            continue;
422cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com        }
423c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        GrContext* context = gContextFactory.get(config.contextType);
424c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        if (NULL == context) {
425c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            continue;
426c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        }
427c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
428c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        size_t bytes;
429c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        int count;
430c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        context->getTextureCacheLimits(&count, &bytes);
431c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        if (-1 != FLAGS_gpuCacheBytes) {
432c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            bytes = static_cast<size_t>(FLAGS_gpuCacheBytes);
433c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        }
434c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        if (-1 != FLAGS_gpuCacheCount) {
435c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            count = FLAGS_gpuCacheCount;
436c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        }
437c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        context->setTextureCacheLimits(count, bytes);
438cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com#endif
439cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com    }
44074913722bfe5e4b6810545891958e3d8e9c63791bsalomon@google.com
441c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    // Find the longest name of the benches we're going to run to make the output pretty.
442c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    Iter names;
443bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com    SkBenchmark* bench;
444c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    int longestName = 0;
445c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    while ((bench = names.next()) != NULL) {
4467fbc6048b1cacbf11852e25b838edc8fe9433dcdbsalomon@google.com        SkAutoTUnref<SkBenchmark> benchUnref(bench);
447c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        if (SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getName())) {
448b398fe863860b072306b5297c8095c6d973aba06reed@android.com            continue;
449b398fe863860b072306b5297c8095c6d973aba06reed@android.com        }
450c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        const int length = strlen(bench->getName());
451c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        longestName = length > longestName ? length : longestName;
452c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    }
453fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
454c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    // Run each bench in each configuration it supports and we asked for.
455c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    Iter iter;
456c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    while ((bench = iter.next()) != NULL) {
457c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        SkAutoTUnref<SkBenchmark> benchUnref(bench);
458c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        if (SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getName())) {
459387359e3483056a7ae7e4cf50347b71b4e3b2d60reed@android.com            continue;
460387359e3483056a7ae7e4cf50347b71b4e3b2d60reed@android.com        }
461fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
462c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        bench->setForceAlpha(alpha);
463c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        bench->setForceAA(FLAGS_forceAA);
464c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        bench->setForceFilter(FLAGS_forceFilter);
465c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        bench->setDither(dither);
46630e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com        AutoPrePostDraw appd(bench);
46730e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com
468c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        bool loggedBenchName = false;
469c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        for (int i = 0; i < configs.count(); ++i) {
470c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            const int configIndex = configs[i];
471c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            const Config& config = gConfigs[configIndex];
4727495f59d39f869deaba13ba5218e42dc3a7ddbaecommit-bot@chromium.org
473c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            if ((kNonRendering_Backend == config.backend) == bench->isRendering()) {
474c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                continue;
475604a56ad4201cc66a85d7bf20efe201ec14b2c1fbsalomon@google.com            }
476604a56ad4201cc66a85d7bf20efe201ec14b2c1fbsalomon@google.com
477cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com            GrContext* context = NULL;
478cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
4799c55f801a35b0d6c39f007fae432bd13094f3c52sugoi@google.com            SkGLContextHelper* glContext = NULL;
480c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            if (kGPU_Backend == config.backend) {
481c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                context = gContextFactory.get(config.contextType);
482cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com                if (NULL == context) {
483cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com                    continue;
484cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com                }
485c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                glContext = gContextFactory.getGLContext(config.contextType);
4864bc1983e01d756ae9c91fd380758457f579d26eareed@android.com            }
487cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif
488c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            SkAutoTUnref<SkBaseDevice> device;
489c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            SkAutoTUnref<SkCanvas> canvas;
490c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            SkPicture recordFrom, recordTo;
491c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            const SkIPoint dim = bench->getSize();
492c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
493c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            const SkPicture::RecordingFlags kRecordFlags =
494c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                SkPicture::kUsePathBoundsForClip_RecordingFlag;
495c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
496c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            if (kNonRendering_Backend != config.backend) {
497c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                device.reset(make_device(config.config,
498c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                                         dim,
499c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                                         config.backend,
500c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                                         config.sampleCount,
501c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                                         context));
502c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                if (!device.get()) {
503dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com                    logger.logError(SkStringPrintf(
504dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com                        "Device creation failure for config %s. Will skip.\n", config.name));
505c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                    continue;
506604a56ad4201cc66a85d7bf20efe201ec14b2c1fbsalomon@google.com                }
507604a56ad4201cc66a85d7bf20efe201ec14b2c1fbsalomon@google.com
508c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                switch(benchMode) {
509c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                    case kDeferredSilent_BenchMode:
510c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                    case kDeferred_BenchMode:
511c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                        canvas.reset(SkDeferredCanvas::Create(device.get()));
512c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                        break;
513c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                    case kRecord_BenchMode:
514c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                        canvas.reset(SkRef(recordTo.beginRecording(dim.fX, dim.fY, kRecordFlags)));
515c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                        break;
516c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                    case kPictureRecord_BenchMode:
517c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                        bench->draw(recordFrom.beginRecording(dim.fX, dim.fY, kRecordFlags));
518c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                        recordFrom.endRecording();
519c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                        canvas.reset(SkRef(recordTo.beginRecording(dim.fX, dim.fY, kRecordFlags)));
520c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                        break;
521c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                    case kNormal_BenchMode:
522c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                        canvas.reset(new SkCanvas(device.get()));
523c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                        break;
524c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                    default:
525c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                        SkASSERT(false);
5267495f59d39f869deaba13ba5218e42dc3a7ddbaecommit-bot@chromium.org                }
527c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            }
528508824bd4b944a77cefad527006e687e5cd927d2bsalomon@google.com
529c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            if (NULL != canvas) {
530c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                canvas->clear(SK_ColorWHITE);
531c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                if (FLAGS_clip)   {   performClip(canvas, dim.fX, dim.fY); }
532c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                if (FLAGS_scale)  {  performScale(canvas, dim.fX, dim.fY); }
533c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                if (FLAGS_rotate) { performRotate(canvas, dim.fX, dim.fY); }
534c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            }
535c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
536c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            if (!loggedBenchName) {
537c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                loggedBenchName = true;
538c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                SkString str;
539c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                str.printf("running bench [%3d %3d] %*s ",
540c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                           dim.fX, dim.fY, longestName, bench->getName());
541c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                logger.logProgress(str);
542c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            }
543fdd909ca000801aced49881558760170b5f1eb97keyar@chromium.org
544cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
545c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            SkGLContextHelper* contextHelper = NULL;
546c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            if (kGPU_Backend == config.backend) {
547c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                contextHelper = gContextFactory.getGLContext(config.contextType);
548c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            }
549c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            BenchTimer timer(contextHelper);
550c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com#else
551c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            BenchTimer timer;
552cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif
553af3d79a8c81f3f224a5eff53b0ca8615b884f922bensong@google.com
5549ef1d21dc8edd167ebbf1ec35f25769f9f6b683bmtklein@google.com            double previous = std::numeric_limits<double>::infinity();
555dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com            bool converged = false;
556c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            bench->setLoops(0);
557dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com            if (FLAGS_verbose) { SkDebugf("%s %s: ", bench->getName(), config.name); }
558c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            do {
559c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                // Ramp up 1 -> 4 -> 16 -> ... -> ~1 billion.
560c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                const int loops = bench->getLoops();
561dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com                if (loops >= (1<<30) || timer.fWall > FLAGS_maxMs) {
562c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                    // If you find it takes more than a billion loops to get up to 20ms of runtime,
563c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                    // you've got a computer clocked at several THz or have a broken benchmark.  ;)
564c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                    //     "1B ought to be enough for anybody."
565dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com                    logger.logError(SkStringPrintf(
566dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com                        "Can't get %s %s to converge in %dms.\n",
567dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com                         bench->getName(), config.name, FLAGS_maxMs));
568c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                    break;
569c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                }
570dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com                bench->setLoops(loops == 0 ? 1 : loops * 2);
571c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
572c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                if ((benchMode == kRecord_BenchMode || benchMode == kPictureRecord_BenchMode)) {
573c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                    // Clear the recorded commands so that they do not accumulate.
574c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                    canvas.reset(recordTo.beginRecording(dim.fX, dim.fY, kRecordFlags));
575c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                }
5762abed834789bb64c7da740df4c47efc142b7311arobertphillips@google.com
577c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                timer.start();
578c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                if (NULL != canvas) {
579c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                    canvas->save();
5807495f59d39f869deaba13ba5218e42dc3a7ddbaecommit-bot@chromium.org                }
581c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                if (benchMode == kPictureRecord_BenchMode) {
582c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                    recordFrom.draw(canvas);
5838ad29cea429e5b6f5b37f647a0eacadd7c9cf86aborenet@google.com                } else {
584c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                    bench->draw(canvas);
5857495f59d39f869deaba13ba5218e42dc3a7ddbaecommit-bot@chromium.org                }
586c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
587c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                if (kDeferredSilent_BenchMode == benchMode) {
588c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                    static_cast<SkDeferredCanvas*>(canvas.get())->silentFlush();
589c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                } else if (NULL != canvas) {
590c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                    canvas->flush();
591c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                }
592c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
593c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                if (NULL != canvas) {
594c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                    canvas->restore();
595c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                }
596c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
597c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
598c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                // Stop truncated timers before GL calls complete, and stop the full timers after.
599c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                timer.truncatedEnd();
600c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com#if SK_SUPPORT_GPU
601c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                if (NULL != glContext) {
602c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                    context->flush();
603c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                    SK_GL(*glContext, Finish());
6048ad29cea429e5b6f5b37f647a0eacadd7c9cf86aborenet@google.com                }
605c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com#endif
606c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                timer.end();
607dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com                const double current = timer.fWall / bench->getLoops();
608dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com                if (FLAGS_verbose && current > previous) { SkDebugf("↑"); }
609dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com                if (FLAGS_verbose) { SkDebugf("%.3g ", current); }
610dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com                converged = HasConverged(previous, current, timer.fWall);
611dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com                previous = current;
612dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com            } while (!kIsDebug && !converged);
613dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com            if (FLAGS_verbose) { SkDebugf("\n"); }
614c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
615c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            if (FLAGS_outDir.count() && kNonRendering_Backend != config.backend) {
616c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                saveFile(bench->getName(),
617c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                         config.name,
618c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                         FLAGS_outDir[0],
619c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                         device->accessBitmap(false));
620c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            }
621c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
622c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            if (kIsDebug) {
623c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                // Let's not mislead ourselves by looking at Debug build bench times!
624c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                continue;
625c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            }
626c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
627c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            // Normalize to ms per 1000 iterations.
628c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            const double normalize = 1000.0 / bench->getLoops();
629c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            const struct { char shortName; const char* longName; double ms; } times[] = {
630c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                {'w', "msecs",  normalize * timer.fWall},
631c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                {'W', "Wmsecs", normalize * timer.fTruncatedWall},
632c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                {'c', "cmsecs", normalize * timer.fCpu},
633c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                {'C', "Cmsecs", normalize * timer.fTruncatedCpu},
634c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                {'g', "gmsecs", normalize * timer.fGpu},
635c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            };
636c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
637c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            SkString result;
638c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            result.appendf("   %s:", config.name);
639c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            for (size_t i = 0; i < SK_ARRAY_COUNT(times); i++) {
640c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                if (strchr(FLAGS_timers[0], times[i].shortName) && times[i].ms > 0) {
641c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                    result.appendf(" %s = ", times[i].longName);
642c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                    result.appendf(FLAGS_timeFormat[0], times[i].ms);
6437495f59d39f869deaba13ba5218e42dc3a7ddbaecommit-bot@chromium.org                }
64425df8884bb616f8acf1ddbfb15d800a215c5ac65reed@google.com            }
645c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            logger.logProgress(result);
64624ed8d721979d891b5fbdfd59dfdd0902778b912bensong@google.com        }
647c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        if (loggedBenchName) {
648c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            logger.logProgress("\n");
6494bc1983e01d756ae9c91fd380758457f579d26eareed@android.com        }
650bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com    }
651cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
652cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com    gContextFactory.destroyContexts();
653cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif
654bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com    return 0;
655bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com}
6565987f58036574ccf23049b5fe71f29a441d0641dcaryclark@google.com
6577158e6acca1b1ecc321d4d514a31cba11b5ead60borenet@google.com#if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL)
6585987f58036574ccf23049b5fe71f29a441d0641dcaryclark@google.comint main(int argc, char * const argv[]) {
6595987f58036574ccf23049b5fe71f29a441d0641dcaryclark@google.com    return tool_main(argc, (char**) argv);
6605987f58036574ccf23049b5fe71f29a441d0641dcaryclark@google.com}
6615987f58036574ccf23049b5fe71f29a441d0641dcaryclark@google.com#endif
662