benchmain.cpp revision 770963f23f4fc313db0fa3bac18b1b8aafb55f17
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
7971d0c8049c6bfc7a58f0b41f8f59f9ec9ca077bbsalomon@google.com
8c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com#include "BenchTimer.h"
9e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org#include "ResultsWriter.h"
109a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com#include "SkBenchLogger.h"
11971d0c8049c6bfc7a58f0b41f8f59f9ec9ca077bbsalomon@google.com#include "SkBenchmark.h"
1273672254a3e498081967d00d27b17ada443e2ab2robertphillips@google.com#include "SkBitmapDevice.h"
13bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com#include "SkCanvas.h"
1478d0379dcc777b4bc4965cff0c2b3fc44ccaef56mtklein@google.com#include "SkColorPriv.h"
15586db93c447b753364d50fadc5426de4fef9a759sglez@google.com#include "SkCommandLineFlags.h"
161bc6c6aa7e1e0fd6a1b80f654a27a7638018f4e7reed@google.com#include "SkData.h"
1782a7bfcb2dbd4f8845a85fc8bddf2c1e59528582bsalomon@google.com#include "SkDeferredCanvas.h"
186adce6783c5d7cbef276d04cc08a2b19789a0156commit-bot@chromium.org#include "SkGMBench.h"
193a859a00342ed078af683fd1901fd26c93dd40f0reed@android.com#include "SkGraphics.h"
20b398fe863860b072306b5297c8095c6d973aba06reed@android.com#include "SkImageEncoder.h"
21c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com#include "SkOSFile.h"
226c924ad46c89955e78e071c792ef00df9910b42freed@android.com#include "SkPicture.h"
23770963f23f4fc313db0fa3bac18b1b8aafb55f17robertphillips@google.com#include "SkPictureRecorder.h"
24bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com#include "SkString.h"
251bc6c6aa7e1e0fd6a1b80f654a27a7638018f4e7reed@google.com#include "SkSurface.h"
26fdd909ca000801aced49881558760170b5f1eb97keyar@chromium.org
27db490e99715c000ed15fd8211698f3e50ee2dc30djsollen@google.com#if SK_SUPPORT_GPU
28db490e99715c000ed15fd8211698f3e50ee2dc30djsollen@google.com#include "GrContext.h"
29db490e99715c000ed15fd8211698f3e50ee2dc30djsollen@google.com#include "GrContextFactory.h"
30db490e99715c000ed15fd8211698f3e50ee2dc30djsollen@google.com#include "GrRenderTarget.h"
31db490e99715c000ed15fd8211698f3e50ee2dc30djsollen@google.com#include "SkGpuDevice.h"
32db490e99715c000ed15fd8211698f3e50ee2dc30djsollen@google.com#include "gl/GrGLDefines.h"
33db490e99715c000ed15fd8211698f3e50ee2dc30djsollen@google.com#else
34db490e99715c000ed15fd8211698f3e50ee2dc30djsollen@google.comclass GrContext;
35db490e99715c000ed15fd8211698f3e50ee2dc30djsollen@google.com#endif // SK_SUPPORT_GPU
36db490e99715c000ed15fd8211698f3e50ee2dc30djsollen@google.com
379ef1d21dc8edd167ebbf1ec35f25769f9f6b683bmtklein@google.com#include <limits>
389ef1d21dc8edd167ebbf1ec35f25769f9f6b683bmtklein@google.com
39c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comenum BenchMode {
40c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    kNormal_BenchMode,
41c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    kDeferred_BenchMode,
42c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    kDeferredSilent_BenchMode,
43c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    kRecord_BenchMode,
44c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    kPictureRecord_BenchMode
45c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com};
46dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.comconst char* BenchMode_Name[] = {
47dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com    "normal", "deferred", "deferredSilent", "record", "picturerecord"
48dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com};
49515dcd36032997ce335daa0163c6d67e851bcad1commit-bot@chromium.org
504e061d3f1594e7cfa243d73e0eea0b649dead904borenet@google.comstatic const char kDefaultsConfigStr[] = "defaults";
514e061d3f1594e7cfa243d73e0eea0b649dead904borenet@google.com
52fdd909ca000801aced49881558760170b5f1eb97keyar@chromium.org///////////////////////////////////////////////////////////////////////////////
53fdd909ca000801aced49881558760170b5f1eb97keyar@chromium.org
54bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.comclass Iter {
55bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.compublic:
56575d9cd27032f6a43d30d9ddb4bc5b2f8091ba5dcommit-bot@chromium.org    Iter() : fBenches(BenchRegistry::Head()), fGMs(skiagm::GMRegistry::Head()) {}
57fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
58bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com    SkBenchmark* next() {
59575d9cd27032f6a43d30d9ddb4bc5b2f8091ba5dcommit-bot@chromium.org        if (fBenches) {
60575d9cd27032f6a43d30d9ddb4bc5b2f8091ba5dcommit-bot@chromium.org            BenchRegistry::Factory f = fBenches->factory();
61575d9cd27032f6a43d30d9ddb4bc5b2f8091ba5dcommit-bot@chromium.org            fBenches = fBenches->next();
6238aeb0fd7a2bdab5e44531d96045dffe25c8e2b0commit-bot@chromium.org            return (*f)(NULL);
63bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com        }
64575d9cd27032f6a43d30d9ddb4bc5b2f8091ba5dcommit-bot@chromium.org
65575d9cd27032f6a43d30d9ddb4bc5b2f8091ba5dcommit-bot@chromium.org        while (fGMs) {
66575d9cd27032f6a43d30d9ddb4bc5b2f8091ba5dcommit-bot@chromium.org            SkAutoTDelete<skiagm::GM> gm(fGMs->factory()(NULL));
67575d9cd27032f6a43d30d9ddb4bc5b2f8091ba5dcommit-bot@chromium.org            fGMs = fGMs->next();
68575d9cd27032f6a43d30d9ddb4bc5b2f8091ba5dcommit-bot@chromium.org            if (gm->getFlags() & skiagm::GM::kAsBench_Flag) {
69575d9cd27032f6a43d30d9ddb4bc5b2f8091ba5dcommit-bot@chromium.org                return SkNEW_ARGS(SkGMBench, (gm.detach()));
70575d9cd27032f6a43d30d9ddb4bc5b2f8091ba5dcommit-bot@chromium.org            }
71575d9cd27032f6a43d30d9ddb4bc5b2f8091ba5dcommit-bot@chromium.org        }
72575d9cd27032f6a43d30d9ddb4bc5b2f8091ba5dcommit-bot@chromium.org
73bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com        return NULL;
74bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com    }
75d1a416a97cac1769c1616cd3b092876dc6077e59bungeman@google.com
76bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.comprivate:
77575d9cd27032f6a43d30d9ddb4bc5b2f8091ba5dcommit-bot@chromium.org    const BenchRegistry* fBenches;
78575d9cd27032f6a43d30d9ddb4bc5b2f8091ba5dcommit-bot@chromium.org    const skiagm::GMRegistry* fGMs;
79bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com};
80bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com
8130e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.comclass AutoPrePostDraw {
8230e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.compublic:
8330e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com    AutoPrePostDraw(SkBenchmark* bench) : fBench(bench) {
8430e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com        fBench->preDraw();
8530e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com    }
8630e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com    ~AutoPrePostDraw() {
8730e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com        fBench->postDraw();
8830e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com    }
8930e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.comprivate:
9030e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com    SkBenchmark* fBench;
9130e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com};
9230e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com
93bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.comstatic void make_filename(const char name[], SkString* path) {
94bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com    path->set(name);
95bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com    for (int i = 0; name[i]; i++) {
96bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com        switch (name[i]) {
97bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com            case '/':
98bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com            case '\\':
99bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com            case ' ':
100bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com            case ':':
101bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com                path->writable_str()[i] = '-';
102bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com                break;
103bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com            default:
104bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com                break;
105bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com        }
106bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com    }
107bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com}
108bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com
1094c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.comstatic void saveFile(const char name[], const char config[], const char dir[],
1101bc6c6aa7e1e0fd6a1b80f654a27a7638018f4e7reed@google.com                     const SkImage* image) {
1111bc6c6aa7e1e0fd6a1b80f654a27a7638018f4e7reed@google.com    SkAutoTUnref<SkData> data(image->encode(SkImageEncoder::kPNG_Type, 100));
1121bc6c6aa7e1e0fd6a1b80f654a27a7638018f4e7reed@google.com    if (NULL == data.get()) {
1134c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com        return;
1144c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com    }
115fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
116c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    SkString filename;
117c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    make_filename(name, &filename);
118c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    filename.appendf("_%s.png", config);
119c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    SkString path = SkOSPath::SkPathJoin(dir, filename.c_str());
120c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    ::remove(path.c_str());
1211bc6c6aa7e1e0fd6a1b80f654a27a7638018f4e7reed@google.com
122ace135453db02cfe83d7c7bbeaa679f98d18fbe2reed@google.com    SkFILEWStream   stream(path.c_str());
1231bc6c6aa7e1e0fd6a1b80f654a27a7638018f4e7reed@google.com    stream.write(data->data(), data->size());
1244c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com}
1254c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com
12684b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.comstatic void perform_clip(SkCanvas* canvas, int w, int h) {
1274c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com    SkRect r;
128fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1294c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com    r.set(SkIntToScalar(10), SkIntToScalar(10),
1304c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com          SkIntToScalar(w*2/3), SkIntToScalar(h*2/3));
1314c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com    canvas->clipRect(r, SkRegion::kIntersect_Op);
132fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1334c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com    r.set(SkIntToScalar(w/3), SkIntToScalar(h/3),
1344c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com          SkIntToScalar(w-10), SkIntToScalar(h-10));
1354c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com    canvas->clipRect(r, SkRegion::kXOR_Op);
1364c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com}
1374c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com
13884b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.comstatic void perform_rotate(SkCanvas* canvas, int w, int h) {
1394c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com    const SkScalar x = SkIntToScalar(w) / 2;
1404c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com    const SkScalar y = SkIntToScalar(h) / 2;
141fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1424c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com    canvas->translate(x, y);
1434c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com    canvas->rotate(SkIntToScalar(35));
1444c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com    canvas->translate(-x, -y);
1454c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com}
1464c7d3d6828b103ada10201608bd6e116d0ac7e61reed@android.com
14784b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.comstatic void perform_scale(SkCanvas* canvas, int w, int h) {
148387359e3483056a7ae7e4cf50347b71b4e3b2d60reed@android.com    const SkScalar x = SkIntToScalar(w) / 2;
149387359e3483056a7ae7e4cf50347b71b4e3b2d60reed@android.com    const SkScalar y = SkIntToScalar(h) / 2;
150fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
151387359e3483056a7ae7e4cf50347b71b4e3b2d60reed@android.com    canvas->translate(x, y);
152387359e3483056a7ae7e4cf50347b71b4e3b2d60reed@android.com    // just enough so we can't take the sprite case
153387359e3483056a7ae7e4cf50347b71b4e3b2d60reed@android.com    canvas->scale(SK_Scalar1 * 99/100, SK_Scalar1 * 99/100);
154387359e3483056a7ae7e4cf50347b71b4e3b2d60reed@android.com    canvas->translate(-x, -y);
155387359e3483056a7ae7e4cf50347b71b4e3b2d60reed@android.com}
156387359e3483056a7ae7e4cf50347b71b4e3b2d60reed@android.com
1571bc6c6aa7e1e0fd6a1b80f654a27a7638018f4e7reed@google.comstatic SkSurface* make_surface(SkColorType colorType, const SkIPoint& size,
1581bc6c6aa7e1e0fd6a1b80f654a27a7638018f4e7reed@google.com                               SkBenchmark::Backend backend, int sampleCount,
1591bc6c6aa7e1e0fd6a1b80f654a27a7638018f4e7reed@google.com                               GrContext* context) {
1601bc6c6aa7e1e0fd6a1b80f654a27a7638018f4e7reed@google.com    SkSurface* surface = NULL;
1611bc6c6aa7e1e0fd6a1b80f654a27a7638018f4e7reed@google.com    SkImageInfo info = SkImageInfo::Make(size.fX, size.fY, colorType,
1621bc6c6aa7e1e0fd6a1b80f654a27a7638018f4e7reed@google.com                                         kPremul_SkAlphaType);
163fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
164a9015f897cd32f549349994e8163ead1db442088mike@reedtribe.org    switch (backend) {
165644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org        case SkBenchmark::kRaster_Backend:
1661bc6c6aa7e1e0fd6a1b80f654a27a7638018f4e7reed@google.com            surface = SkSurface::NewRaster(info);
1671bc6c6aa7e1e0fd6a1b80f654a27a7638018f4e7reed@google.com            surface->getCanvas()->clear(SK_ColorWHITE);
168a9015f897cd32f549349994e8163ead1db442088mike@reedtribe.org            break;
169cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
170644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org        case SkBenchmark::kGPU_Backend: {
1711bc6c6aa7e1e0fd6a1b80f654a27a7638018f4e7reed@google.com            surface = SkSurface::NewRenderTarget(context, info, sampleCount);
172a9015f897cd32f549349994e8163ead1db442088mike@reedtribe.org            break;
173cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com        }
174cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif
175644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org        case SkBenchmark::kPDF_Backend:
176a9015f897cd32f549349994e8163ead1db442088mike@reedtribe.org        default:
177330313a8a8343876ee596da39da06a5d69badd9cmtklein@google.com            SkDEBUGFAIL("unsupported");
178a9015f897cd32f549349994e8163ead1db442088mike@reedtribe.org    }
1791bc6c6aa7e1e0fd6a1b80f654a27a7638018f4e7reed@google.com    return surface;
180a9015f897cd32f549349994e8163ead1db442088mike@reedtribe.org}
181a9015f897cd32f549349994e8163ead1db442088mike@reedtribe.org
182cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com#if SK_SUPPORT_GPU
183cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.comGrContextFactory gContextFactory;
184cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.comtypedef GrContextFactory::GLContextType GLContextType;
185c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comstatic const GLContextType kNative = GrContextFactory::kNative_GLContextType;
186e8989578cd05d4bf6ebe35f0d49afbc3d3bef2edcommit-bot@chromium.orgstatic const GLContextType kNVPR   = GrContextFactory::kNVPR_GLContextType;
187c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com#if SK_ANGLE
188c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comstatic const GLContextType kANGLE  = GrContextFactory::kANGLE_GLContextType;
189c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com#endif
190c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comstatic const GLContextType kDebug  = GrContextFactory::kDebug_GLContextType;
191c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comstatic const GLContextType kNull   = GrContextFactory::kNull_GLContextType;
192cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com#else
193cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.comtypedef int GLContextType;
194c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comstatic const GLContextType kNative = 0, kANGLE = 0, kDebug = 0, kNull = 0;
195c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com#endif
196c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
197c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com#ifdef SK_DEBUG
198c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comstatic const bool kIsDebug = true;
199c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com#else
200c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comstatic const bool kIsDebug = false;
201cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com#endif
202cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com
203c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comstatic const struct Config {
2041bc6c6aa7e1e0fd6a1b80f654a27a7638018f4e7reed@google.com    SkColorType         fColorType;
205c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    const char*         name;
206c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    int                 sampleCount;
207644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    SkBenchmark::Backend backend;
208c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    GLContextType       contextType;
209c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    bool                runByDefault;
2104bc1983e01d756ae9c91fd380758457f579d26eareed@android.com} gConfigs[] = {
21128fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org    { kN32_SkColorType,     "NONRENDERING", 0, SkBenchmark::kNonRendering_Backend, kNative, true},
21228fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org    { kN32_SkColorType,     "8888",         0, SkBenchmark::kRaster_Backend,       kNative, true},
2131bc6c6aa7e1e0fd6a1b80f654a27a7638018f4e7reed@google.com    { kRGB_565_SkColorType, "565",          0, SkBenchmark::kRaster_Backend,       kNative, true},
214cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
21528fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org    { kN32_SkColorType,     "GPU",          0, SkBenchmark::kGPU_Backend,          kNative, true},
21628fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org    { kN32_SkColorType,     "MSAA4",        4, SkBenchmark::kGPU_Backend,          kNative, false},
21728fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org    { kN32_SkColorType,     "MSAA16",      16, SkBenchmark::kGPU_Backend,          kNative, false},
21828fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org    { kN32_SkColorType,     "NVPRMSAA4",    4, SkBenchmark::kGPU_Backend,          kNVPR,   true},
21928fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org    { kN32_SkColorType,     "NVPRMSAA16",  16, SkBenchmark::kGPU_Backend,          kNVPR,   false},
220d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com#if SK_ANGLE
22128fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org    { kN32_SkColorType,     "ANGLE",        0, SkBenchmark::kGPU_Backend,          kANGLE,  true},
222cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif // SK_ANGLE
22328fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org    { kN32_SkColorType,     "Debug",        0, SkBenchmark::kGPU_Backend,          kDebug,  kIsDebug},
22428fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org    { kN32_SkColorType,     "NULLGPU",      0, SkBenchmark::kGPU_Backend,          kNull,   true},
225cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif // SK_SUPPORT_GPU
2264bc1983e01d756ae9c91fd380758457f579d26eareed@android.com};
2274bc1983e01d756ae9c91fd380758457f579d26eareed@android.com
228c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comDEFINE_string(outDir, "", "If given, image of each bench will be put in outDir.");
229c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comDEFINE_string(timers, "cg", "Timers to display. "
230c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com              "Options: w(all) W(all, truncated) c(pu) C(pu, truncated) g(pu)");
231c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
232c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comDEFINE_bool(rotate, false,  "Rotate canvas before bench run?");
233c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comDEFINE_bool(scale,  false,  "Scale canvas before bench run?");
234c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comDEFINE_bool(clip,   false,  "Clip canvas before bench run?");
235c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
236c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comDEFINE_bool(forceAA,        true,     "Force anti-aliasing?");
237c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comDEFINE_bool(forceFilter,    false,    "Force bitmap filtering?");
238c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comDEFINE_string(forceDither, "default", "Force dithering: true, false, or default?");
239c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comDEFINE_bool(forceBlend,     false,    "Force alpha blending?");
240c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
241c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comDEFINE_int32(gpuCacheBytes, -1, "GPU cache size limit in bytes.  0 to disable cache.");
242c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comDEFINE_int32(gpuCacheCount, -1, "GPU cache size limit in object count.  0 to disable cache.");
243c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
2446dda827913a3dbdb84934f4f1d79c0b702169e5ccommit-bot@chromium.orgDEFINE_bool2(leaks, l, false, "show leaked ref cnt'd objects.");
245c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comDEFINE_string(match, "",  "[~][^]substring[$] [...] of test name to run.\n"
246c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                          "Multiple matches may be separated by spaces.\n"
247c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                          "~ causes a matching test to always be skipped\n"
248c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                          "^ requires the start of the test to match\n"
249c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                          "$ requires the end of the test to match\n"
250c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                          "^ and $ requires an exact match\n"
251c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                          "If a test does not match any list entry,\n"
252c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                          "it is skipped unless some list entry starts with ~\n");
253c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comDEFINE_string(mode, "normal",
254c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com             "normal:         draw to a normal canvas;\n"
255c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com             "deferred:       draw to a deferred canvas;\n"
256c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com             "deferredSilent: deferred with silent playback;\n"
257c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com             "record:         draw to an SkPicture;\n"
258c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com             "picturerecord:  draw from an SkPicture to an SkPicture.\n");
2594e061d3f1594e7cfa243d73e0eea0b649dead904borenet@google.comDEFINE_string(config, kDefaultsConfigStr,
2604e061d3f1594e7cfa243d73e0eea0b649dead904borenet@google.com              "Run configs given.  By default, runs the configs marked \"runByDefault\" in gConfigs.");
261c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comDEFINE_string(logFile, "", "Also write stdout here.");
262dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.comDEFINE_int32(minMs, 20,  "Shortest time we'll allow a benchmark to run.");
263dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.comDEFINE_int32(maxMs, 4000, "Longest time we'll allow a benchmark to run.");
264dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.comDEFINE_double(error, 0.01,
265dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com              "Ratio of subsequent bench measurements must drop within 1±error to converge.");
266c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.comDEFINE_string(timeFormat, "%9.2f", "Format to print results, in milliseconds per 1000 loops.");
267dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.comDEFINE_bool2(verbose, v, false, "Print more.");
268725a64cf89605680ebb0f56cd6727f29d8b9899btfarina@chromium.orgDEFINE_string2(resourcePath, i, "resources", "directory for test resources.");
269e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.orgDEFINE_string(outResultsFile, "", "If given, the results will be written to the file in JSON format.");
270dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com
27156b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.orgDEFINE_bool(dryRun, false, "Don't actually run the tests, just print what would have been done.");
27256b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org
273dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com// Has this bench converged?  First arguments are milliseconds / loop iteration,
274dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com// last is overall runtime in milliseconds.
275dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.comstatic bool HasConverged(double prevPerLoop, double currPerLoop, double currRaw) {
276dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com    if (currRaw < FLAGS_minMs) {
277dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com        return false;
278dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com    }
279dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com    const double low = 1 - FLAGS_error, high = 1 + FLAGS_error;
280dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com    const double ratio = currPerLoop / prevPerLoop;
281dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com    return low < ratio && ratio < high;
282dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com}
28386bb9b73a00d16eb13a6db13c5d2f775040caf13tomhudson@google.com
2845987f58036574ccf23049b5fe71f29a441d0641dcaryclark@google.comint tool_main(int argc, char** argv);
2855987f58036574ccf23049b5fe71f29a441d0641dcaryclark@google.comint tool_main(int argc, char** argv) {
2866dda827913a3dbdb84934f4f1d79c0b702169e5ccommit-bot@chromium.org    SkCommandLineFlags::Parse(argc, argv);
2874e23068b374023d43c4c725138d523721d975892bsalomon@google.com#if SK_ENABLE_INST_COUNT
2886dda827913a3dbdb84934f4f1d79c0b702169e5ccommit-bot@chromium.org    if (FLAGS_leaks) {
2896dda827913a3dbdb84934f4f1d79c0b702169e5ccommit-bot@chromium.org        gPrintInstCount = true;
2906dda827913a3dbdb84934f4f1d79c0b702169e5ccommit-bot@chromium.org    }
29165a87cc13d6babcf12844cca244ca7cc5258cadcbsalomon@google.com#endif
2923a859a00342ed078af683fd1901fd26c93dd40f0reed@android.com    SkAutoGraphics ag;
29365a87cc13d6babcf12844cca244ca7cc5258cadcbsalomon@google.com
294c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    // First, parse some flags.
295c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    SkBenchLogger logger;
296c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    if (FLAGS_logFile.count()) {
297c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        logger.SetLogFile(FLAGS_logFile[0]);
298c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    }
29955fd612adfd08f5c64fb728bc37a2cb4ae224656commit-bot@chromium.org
300e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org    LoggerResultsWriter logWriter(logger, FLAGS_timeFormat[0]);
301e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org    MultiResultsWriter writer;
302e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org    writer.add(&logWriter);
303e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org    SkAutoTDelete<JSONResultsWriter> jsonWriter;
304e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org    if (FLAGS_outResultsFile.count()) {
305e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org        jsonWriter.reset(SkNEW(JSONResultsWriter(FLAGS_outResultsFile[0])));
306e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org        writer.add(jsonWriter.get());
307e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org    }
308e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org    // Instantiate after all the writers have been added to writer so that we
309e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org    // call close() before their destructors are called on the way out.
310e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org    CallEnd<MultiResultsWriter> ender(writer);
311e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org
312c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    const uint8_t alpha = FLAGS_forceBlend ? 0x80 : 0xFF;
313c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    SkTriState::State dither = SkTriState::kDefault;
314c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    for (size_t i = 0; i < 3; i++) {
315c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        if (strcmp(SkTriState::Name[i], FLAGS_forceDither[0]) == 0) {
316c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            dither = static_cast<SkTriState::State>(i);
317c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        }
318c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    }
319c732f259fa9cb0045623f3e0e3f033c20f06be8cbsalomon@google.com
320c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    BenchMode benchMode = kNormal_BenchMode;
321c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    for (size_t i = 0; i < SK_ARRAY_COUNT(BenchMode_Name); i++) {
322c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        if (strcmp(FLAGS_mode[0], BenchMode_Name[i]) == 0) {
323c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            benchMode = static_cast<BenchMode>(i);
324c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        }
325c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    }
326c732f259fa9cb0045623f3e0e3f033c20f06be8cbsalomon@google.com
32713eaaaa75a16fa300fa212ec910107f77530ef2ctomhudson@google.com    SkTDArray<int> configs;
3284e061d3f1594e7cfa243d73e0eea0b649dead904borenet@google.com    bool runDefaultConfigs = false;
329c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    // Try user-given configs first.
330c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    for (int i = 0; i < FLAGS_config.count(); i++) {
331e9cd27d4a3c92393cc6c79d4d6f93d266411d95erobertphillips@google.com        for (int j = 0; j < static_cast<int>(SK_ARRAY_COUNT(gConfigs)); ++j) {
332c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            if (0 == strcmp(FLAGS_config[i], gConfigs[j].name)) {
333c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                *configs.append() = j;
3344e061d3f1594e7cfa243d73e0eea0b649dead904borenet@google.com            } else if (0 == strcmp(FLAGS_config[i], kDefaultsConfigStr)) {
3354e061d3f1594e7cfa243d73e0eea0b649dead904borenet@google.com                runDefaultConfigs = true;
336e9d0060f4d7b5a07a220182d83aae3a140784c4breed@android.com            }
337b398fe863860b072306b5297c8095c6d973aba06reed@android.com        }
338b398fe863860b072306b5297c8095c6d973aba06reed@android.com    }
339c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    // If there weren't any, fill in with defaults.
3404e061d3f1594e7cfa243d73e0eea0b649dead904borenet@google.com    if (runDefaultConfigs) {
341e9cd27d4a3c92393cc6c79d4d6f93d266411d95erobertphillips@google.com        for (int i = 0; i < static_cast<int>(SK_ARRAY_COUNT(gConfigs)); ++i) {
342c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            if (gConfigs[i].runByDefault) {
3438a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com                *configs.append() = i;
3448a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com            }
34513eaaaa75a16fa300fa212ec910107f77530ef2ctomhudson@google.com        }
34613eaaaa75a16fa300fa212ec910107f77530ef2ctomhudson@google.com    }
347c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    // Filter out things we can't run.
348c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    if (kNormal_BenchMode != benchMode) {
349604a56ad4201cc66a85d7bf20efe201ec14b2c1fbsalomon@google.com        // Non-rendering configs only run in normal mode
350604a56ad4201cc66a85d7bf20efe201ec14b2c1fbsalomon@google.com        for (int i = 0; i < configs.count(); ++i) {
351c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            const Config& config = gConfigs[configs[i]];
352644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org            if (SkBenchmark::kNonRendering_Backend == config.backend) {
353604a56ad4201cc66a85d7bf20efe201ec14b2c1fbsalomon@google.com                configs.remove(i, 1);
354604a56ad4201cc66a85d7bf20efe201ec14b2c1fbsalomon@google.com                --i;
355604a56ad4201cc66a85d7bf20efe201ec14b2c1fbsalomon@google.com            }
356604a56ad4201cc66a85d7bf20efe201ec14b2c1fbsalomon@google.com        }
357604a56ad4201cc66a85d7bf20efe201ec14b2c1fbsalomon@google.com    }
358111fd11e11cbc296c97225ea16b7ff174a4bcdb5scroggo@google.com    // Set the resource path.
359111fd11e11cbc296c97225ea16b7ff174a4bcdb5scroggo@google.com    if (!FLAGS_resourcePath.isEmpty()) {
360111fd11e11cbc296c97225ea16b7ff174a4bcdb5scroggo@google.com        SkBenchmark::SetResourcePath(FLAGS_resourcePath[0]);
361111fd11e11cbc296c97225ea16b7ff174a4bcdb5scroggo@google.com    }
362111fd11e11cbc296c97225ea16b7ff174a4bcdb5scroggo@google.com
3638a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com#if SK_SUPPORT_GPU
3648a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com    for (int i = 0; i < configs.count(); ++i) {
365c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        const Config& config = gConfigs[configs[i]];
3668a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com
367644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org        if (SkBenchmark::kGPU_Backend == config.backend) {
368c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            GrContext* context = gContextFactory.get(config.contextType);
3698a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com            if (NULL == context) {
370dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com                logger.logError(SkStringPrintf(
371dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com                    "Error creating GrContext for config %s. Config will be skipped.\n",
372dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com                    config.name));
3738a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com                configs.remove(i);
3748a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com                --i;
3758a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com                continue;
3768a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com            }
377c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            if (config.sampleCount > context->getMaxSampleCount()){
378dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com                logger.logError(SkStringPrintf(
379dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com                    "Sample count (%d) for config %s is unsupported. Config will be skipped.\n",
380dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com                    config.sampleCount, config.name));
3818a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com                configs.remove(i);
3828a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com                --i;
3838a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com                continue;
3848a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com            }
3858a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com        }
3868a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com    }
3878a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com#endif
3888a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com
389c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    // All flags should be parsed now.  Report our settings.
390c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    if (kIsDebug) {
391c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        logger.logError("bench was built in Debug mode, so we're going to hide the times."
392c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                        "  It's for your own good!\n");
393c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    }
394e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org    writer.option("mode", FLAGS_mode[0]);
395e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org    writer.option("alpha", SkStringPrintf("0x%02X", alpha).c_str());
396e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org    writer.option("antialias", SkStringPrintf("%d", FLAGS_forceAA).c_str());
397e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org    writer.option("filter", SkStringPrintf("%d", FLAGS_forceFilter).c_str());
398e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org    writer.option("dither",  SkTriState::Name[dither]);
399e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org
400e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org    writer.option("rotate", SkStringPrintf("%d", FLAGS_rotate).c_str());
401e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org    writer.option("scale", SkStringPrintf("%d", FLAGS_scale).c_str());
402e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org    writer.option("clip", SkStringPrintf("%d", FLAGS_clip).c_str());
403c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
404a5d48414249b7df5387ac572d178a1b6550880a5bungeman@google.com#if defined(SK_BUILD_FOR_WIN32)
405e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org    writer.option("system", "WIN32");
406a5d48414249b7df5387ac572d178a1b6550880a5bungeman@google.com#elif defined(SK_BUILD_FOR_MAC)
407e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org    writer.option("system", "MAC");
408a5d48414249b7df5387ac572d178a1b6550880a5bungeman@google.com#elif defined(SK_BUILD_FOR_ANDROID)
409e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org    writer.option("system", "ANDROID");
410a5d48414249b7df5387ac572d178a1b6550880a5bungeman@google.com#elif defined(SK_BUILD_FOR_UNIX)
411e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org    writer.option("system", "UNIX");
412a5d48414249b7df5387ac572d178a1b6550880a5bungeman@google.com#else
413e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org    writer.option("system", "other");
414a5d48414249b7df5387ac572d178a1b6550880a5bungeman@google.com#endif
415a5d48414249b7df5387ac572d178a1b6550880a5bungeman@google.com
416a5d48414249b7df5387ac572d178a1b6550880a5bungeman@google.com#if defined(SK_DEBUG)
417e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org    writer.option("build", "DEBUG");
418e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org#else
419e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org    writer.option("build", "RELEASE");
420a5d48414249b7df5387ac572d178a1b6550880a5bungeman@google.com#endif
421508824bd4b944a77cefad527006e687e5cd927d2bsalomon@google.com
422c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    // Set texture cache limits if non-default.
4235c90e291425b2788f47679266d9584845ceefc2ebsalomon@google.com    for (size_t i = 0; i < SK_ARRAY_COUNT(gConfigs); ++i) {
424cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com#if SK_SUPPORT_GPU
425c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        const Config& config = gConfigs[i];
426644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org        if (SkBenchmark::kGPU_Backend != config.backend) {
427c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            continue;
428cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com        }
429c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        GrContext* context = gContextFactory.get(config.contextType);
430c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        if (NULL == context) {
431c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            continue;
432c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        }
433c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
434c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        size_t bytes;
435c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        int count;
436c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        context->getTextureCacheLimits(&count, &bytes);
437c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        if (-1 != FLAGS_gpuCacheBytes) {
438c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            bytes = static_cast<size_t>(FLAGS_gpuCacheBytes);
439c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        }
440c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        if (-1 != FLAGS_gpuCacheCount) {
441c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            count = FLAGS_gpuCacheCount;
442c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        }
443c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        context->setTextureCacheLimits(count, bytes);
444cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com#endif
445cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com    }
44674913722bfe5e4b6810545891958e3d8e9c63791bsalomon@google.com
447c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    // Run each bench in each configuration it supports and we asked for.
448c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    Iter iter;
449e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org    SkBenchmark* bench;
450c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    while ((bench = iter.next()) != NULL) {
451c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        SkAutoTUnref<SkBenchmark> benchUnref(bench);
452c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        if (SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getName())) {
453387359e3483056a7ae7e4cf50347b71b4e3b2d60reed@android.com            continue;
454387359e3483056a7ae7e4cf50347b71b4e3b2d60reed@android.com        }
455fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
456c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        bench->setForceAlpha(alpha);
457c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        bench->setForceAA(FLAGS_forceAA);
458c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        bench->setForceFilter(FLAGS_forceFilter);
459c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        bench->setDither(dither);
46030e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com        AutoPrePostDraw appd(bench);
46130e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com
462c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        bool loggedBenchName = false;
463c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com        for (int i = 0; i < configs.count(); ++i) {
464c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            const int configIndex = configs[i];
465c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            const Config& config = gConfigs[configIndex];
4667495f59d39f869deaba13ba5218e42dc3a7ddbaecommit-bot@chromium.org
467644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org            if (!bench->isSuitableFor(config.backend)) {
468c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                continue;
469604a56ad4201cc66a85d7bf20efe201ec14b2c1fbsalomon@google.com            }
470604a56ad4201cc66a85d7bf20efe201ec14b2c1fbsalomon@google.com
471cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com            GrContext* context = NULL;
472cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
4739c55f801a35b0d6c39f007fae432bd13094f3c52sugoi@google.com            SkGLContextHelper* glContext = NULL;
474644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org            if (SkBenchmark::kGPU_Backend == config.backend) {
475c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                context = gContextFactory.get(config.contextType);
476cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com                if (NULL == context) {
477cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com                    continue;
478cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com                }
479c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                glContext = gContextFactory.getGLContext(config.contextType);
4804bc1983e01d756ae9c91fd380758457f579d26eareed@android.com            }
481cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif
4821bc6c6aa7e1e0fd6a1b80f654a27a7638018f4e7reed@google.com
483c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            SkAutoTUnref<SkCanvas> canvas;
48484b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com            SkAutoTUnref<SkPicture> recordFrom;
48584b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com            SkPictureRecorder recorderTo;
486c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            const SkIPoint dim = bench->getSize();
487c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
488c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            const SkPicture::RecordingFlags kRecordFlags =
489c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                SkPicture::kUsePathBoundsForClip_RecordingFlag;
490c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
4911bc6c6aa7e1e0fd6a1b80f654a27a7638018f4e7reed@google.com            SkAutoTUnref<SkSurface> surface;
492644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org            if (SkBenchmark::kNonRendering_Backend != config.backend) {
4931bc6c6aa7e1e0fd6a1b80f654a27a7638018f4e7reed@google.com                surface.reset(make_surface(config.fColorType,
4941bc6c6aa7e1e0fd6a1b80f654a27a7638018f4e7reed@google.com                                           dim,
4951bc6c6aa7e1e0fd6a1b80f654a27a7638018f4e7reed@google.com                                           config.backend,
4961bc6c6aa7e1e0fd6a1b80f654a27a7638018f4e7reed@google.com                                           config.sampleCount,
4971bc6c6aa7e1e0fd6a1b80f654a27a7638018f4e7reed@google.com                                           context));
4981bc6c6aa7e1e0fd6a1b80f654a27a7638018f4e7reed@google.com                if (!surface.get()) {
499dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com                    logger.logError(SkStringPrintf(
500dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com                        "Device creation failure for config %s. Will skip.\n", config.name));
501c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                    continue;
502604a56ad4201cc66a85d7bf20efe201ec14b2c1fbsalomon@google.com                }
503604a56ad4201cc66a85d7bf20efe201ec14b2c1fbsalomon@google.com
504c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                switch(benchMode) {
505c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                    case kDeferredSilent_BenchMode:
506c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                    case kDeferred_BenchMode:
5071bc6c6aa7e1e0fd6a1b80f654a27a7638018f4e7reed@google.com                        canvas.reset(SkDeferredCanvas::Create(surface.get()));
508c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                        break;
509c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                    case kRecord_BenchMode:
51060bd7519a9db4ddddd95e490f93165e5676f90f5skia.committer@gmail.com                        canvas.reset(SkRef(recorderTo.beginRecording(dim.fX, dim.fY,
5115fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org                                                                     NULL, kRecordFlags)));
512c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                        break;
51384b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com                    case kPictureRecord_BenchMode: {
51484b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com                        SkPictureRecorder recorderFrom;
51560bd7519a9db4ddddd95e490f93165e5676f90f5skia.committer@gmail.com                        bench->draw(1, recorderFrom.beginRecording(dim.fX, dim.fY,
5165fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org                                                                   NULL, kRecordFlags));
51784b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com                        recordFrom.reset(recorderFrom.endRecording());
51860bd7519a9db4ddddd95e490f93165e5676f90f5skia.committer@gmail.com                        canvas.reset(SkRef(recorderTo.beginRecording(dim.fX, dim.fY,
5195fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org                                                                     NULL, kRecordFlags)));
520c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                        break;
52184b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com                    }
522c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                    case kNormal_BenchMode:
5231bc6c6aa7e1e0fd6a1b80f654a27a7638018f4e7reed@google.com                        canvas.reset(SkRef(surface->getCanvas()));
524c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                        break;
525c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                    default:
526c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                        SkASSERT(false);
5277495f59d39f869deaba13ba5218e42dc3a7ddbaecommit-bot@chromium.org                }
528c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            }
529508824bd4b944a77cefad527006e687e5cd927d2bsalomon@google.com
530c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            if (NULL != canvas) {
531c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                canvas->clear(SK_ColorWHITE);
5325199701acbf386cdc315de440eeafcc10fd0cdc3skia.committer@gmail.com                if (FLAGS_clip)   {
5335199701acbf386cdc315de440eeafcc10fd0cdc3skia.committer@gmail.com                    perform_clip(canvas, dim.fX, dim.fY);
53484b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com                }
5355199701acbf386cdc315de440eeafcc10fd0cdc3skia.committer@gmail.com                if (FLAGS_scale)  {
5365199701acbf386cdc315de440eeafcc10fd0cdc3skia.committer@gmail.com                    perform_scale(canvas, dim.fX, dim.fY);
53784b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com                }
5385199701acbf386cdc315de440eeafcc10fd0cdc3skia.committer@gmail.com                if (FLAGS_rotate) {
5395199701acbf386cdc315de440eeafcc10fd0cdc3skia.committer@gmail.com                    perform_rotate(canvas, dim.fX, dim.fY);
54084b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com                }
541c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            }
542c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
543c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            if (!loggedBenchName) {
544c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                loggedBenchName = true;
545e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org                writer.bench(bench->getName(), dim.fX, dim.fY);
546c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            }
547fdd909ca000801aced49881558760170b5f1eb97keyar@chromium.org
548cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
549c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            SkGLContextHelper* contextHelper = NULL;
550644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org            if (SkBenchmark::kGPU_Backend == config.backend) {
551c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                contextHelper = gContextFactory.getGLContext(config.contextType);
552c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            }
553c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            BenchTimer timer(contextHelper);
554c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com#else
555c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            BenchTimer timer;
556cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif
557af3d79a8c81f3f224a5eff53b0ca8615b884f922bensong@google.com
5589ef1d21dc8edd167ebbf1ec35f25769f9f6b683bmtklein@google.com            double previous = std::numeric_limits<double>::infinity();
559dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com            bool converged = false;
56070de4da331b70fed227de795a7464dd6f0f0a8d7djsollen@google.com
56170de4da331b70fed227de795a7464dd6f0f0a8d7djsollen@google.com            // variables used to compute loopsPerFrame
56270de4da331b70fed227de795a7464dd6f0f0a8d7djsollen@google.com            double frameIntervalTime = 0.0f;
56370de4da331b70fed227de795a7464dd6f0f0a8d7djsollen@google.com            int frameIntervalTotalLoops = 0;
56470de4da331b70fed227de795a7464dd6f0f0a8d7djsollen@google.com
56570de4da331b70fed227de795a7464dd6f0f0a8d7djsollen@google.com            bool frameIntervalComputed = false;
56670de4da331b70fed227de795a7464dd6f0f0a8d7djsollen@google.com            int loopsPerFrame = 0;
56770de4da331b70fed227de795a7464dd6f0f0a8d7djsollen@google.com            int loopsPerIter = 0;
568dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com            if (FLAGS_verbose) { SkDebugf("%s %s: ", bench->getName(), config.name); }
56956b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org            if (!FLAGS_dryRun) {
57056b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                do {
57156b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                    // Ramp up 1 -> 2 -> 4 -> 8 -> 16 -> ... -> ~1 billion.
57256b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                    loopsPerIter = (loopsPerIter == 0) ? 1 : loopsPerIter * 2;
57356b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                    if (loopsPerIter >= (1<<30) || timer.fWall > FLAGS_maxMs) {
57456b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                        // If you find it takes more than a billion loops to get up to 20ms of runtime,
57556b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                        // you've got a computer clocked at several THz or have a broken benchmark.  ;)
57656b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                        //     "1B ought to be enough for anybody."
57756b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                        logger.logError(SkStringPrintf(
57856b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                            "\nCan't get %s %s to converge in %dms (%d loops)",
57956b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                             bench->getName(), config.name, FLAGS_maxMs, loopsPerIter));
58056b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                        break;
58170de4da331b70fed227de795a7464dd6f0f0a8d7djsollen@google.com                    }
58270de4da331b70fed227de795a7464dd6f0f0a8d7djsollen@google.com
58356b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                    if ((benchMode == kRecord_BenchMode || benchMode == kPictureRecord_BenchMode)) {
58456b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                        // Clear the recorded commands so that they do not accumulate.
58560bd7519a9db4ddddd95e490f93165e5676f90f5skia.committer@gmail.com                        canvas.reset(SkRef(recorderTo.beginRecording(dim.fX, dim.fY,
5865fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org                                                                     NULL, kRecordFlags)));
58770de4da331b70fed227de795a7464dd6f0f0a8d7djsollen@google.com                    }
58870de4da331b70fed227de795a7464dd6f0f0a8d7djsollen@google.com
58956b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                    timer.start();
59056b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                    // Inner loop that allows us to break the run into smaller
59156b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                    // chunks (e.g. frames). This is especially useful for the GPU
59256b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                    // as we can flush and/or swap buffers to keep the GPU from
59356b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                    // queuing up too much work.
59456b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                    for (int loopCount = loopsPerIter; loopCount > 0; ) {
59556b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                        // Save and restore around each call to draw() to guarantee a pristine canvas.
59656b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                        SkAutoCanvasRestore saveRestore(canvas, true/*also save*/);
59756b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org
59856b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                        int loops;
59956b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                        if (frameIntervalComputed && loopCount > loopsPerFrame) {
60056b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                            loops = loopsPerFrame;
60156b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                            loopCount -= loopsPerFrame;
60256b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                        } else {
60356b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                            loops = loopCount;
60456b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                            loopCount = 0;
60556b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                        }
60670de4da331b70fed227de795a7464dd6f0f0a8d7djsollen@google.com
60756b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                        if (benchMode == kPictureRecord_BenchMode) {
60884b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com                            recordFrom->draw(canvas);
60956b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                        } else {
61056b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                            bench->draw(loops, canvas);
61156b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                        }
61256b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org
61356b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                        if (kDeferredSilent_BenchMode == benchMode) {
61456b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                            static_cast<SkDeferredCanvas*>(canvas.get())->silentFlush();
61556b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                        } else if (NULL != canvas) {
61656b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                            canvas->flush();
61756b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                        }
61856b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org
61956b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org    #if SK_SUPPORT_GPU
62056b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                        // swap drawing buffers on each frame to prevent the GPU
62156b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                        // from queuing up too much work
62256b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                        if (NULL != glContext) {
62356b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                            glContext->swapBuffers();
62456b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                        }
62556b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org    #endif
62670de4da331b70fed227de795a7464dd6f0f0a8d7djsollen@google.com                    }
627c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
628c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
629c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
63056b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                    // Stop truncated timers before GL calls complete, and stop the full timers after.
63156b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                    timer.truncatedEnd();
63256b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org    #if SK_SUPPORT_GPU
63356b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                    if (NULL != glContext) {
63456b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                        context->flush();
63556b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                        SK_GL(*glContext, Finish());
63656b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                    }
63756b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org    #endif
63856b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                    timer.end();
63956b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org
64056b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                    // setup the frame interval for subsequent iterations
64156b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                    if (!frameIntervalComputed) {
64256b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                        frameIntervalTime += timer.fWall;
64356b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                        frameIntervalTotalLoops += loopsPerIter;
64456b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                        if (frameIntervalTime >= FLAGS_minMs) {
64556b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                            frameIntervalComputed = true;
64656b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                            loopsPerFrame =
64756b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                              (int)(((double)frameIntervalTotalLoops / frameIntervalTime) * FLAGS_minMs);
64856b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                            if (loopsPerFrame < 1) {
64956b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                                loopsPerFrame = 1;
65056b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                            }
65156b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org    //                        SkDebugf("  %s has %d loops in %f ms (normalized to %d)\n",
65256b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org    //                                 bench->getName(), frameIntervalTotalLoops,
65356b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org    //                                 timer.fWall, loopsPerFrame);
65470de4da331b70fed227de795a7464dd6f0f0a8d7djsollen@google.com                        }
65570de4da331b70fed227de795a7464dd6f0f0a8d7djsollen@google.com                    }
656dcfed6cecfde7a6e4983c1caf7ffb417c891667fdjsollen@google.com
65756b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                    const double current = timer.fWall / loopsPerIter;
65856b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                    if (FLAGS_verbose && current > previous) { SkDebugf("↑"); }
65956b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                    if (FLAGS_verbose) { SkDebugf("%.3g ", current); }
66056b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                    converged = HasConverged(previous, current, timer.fWall);
66156b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                    previous = current;
66256b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org                } while (!kIsDebug && !converged);
66356b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org            }
664dbd41c885768f9fec3bd9e216518f9ea1b181a96mtklein@google.com            if (FLAGS_verbose) { SkDebugf("\n"); }
665c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
66656b7a6d52ceaed3927ec4346f431495c32f519e2commit-bot@chromium.org            if (!FLAGS_dryRun && FLAGS_outDir.count() && SkBenchmark::kNonRendering_Backend != config.backend) {
6671bc6c6aa7e1e0fd6a1b80f654a27a7638018f4e7reed@google.com                SkAutoTUnref<SkImage> image(surface->newImageSnapshot());
6681bc6c6aa7e1e0fd6a1b80f654a27a7638018f4e7reed@google.com                if (image.get()) {
6691bc6c6aa7e1e0fd6a1b80f654a27a7638018f4e7reed@google.com                    saveFile(bench->getName(), config.name, FLAGS_outDir[0],
6701bc6c6aa7e1e0fd6a1b80f654a27a7638018f4e7reed@google.com                             image);
6711bc6c6aa7e1e0fd6a1b80f654a27a7638018f4e7reed@google.com                }
672c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            }
673c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
674c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            if (kIsDebug) {
675c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                // Let's not mislead ourselves by looking at Debug build bench times!
676c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                continue;
677c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            }
678c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
679c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            // Normalize to ms per 1000 iterations.
68070de4da331b70fed227de795a7464dd6f0f0a8d7djsollen@google.com            const double normalize = 1000.0 / loopsPerIter;
681c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            const struct { char shortName; const char* longName; double ms; } times[] = {
682c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                {'w', "msecs",  normalize * timer.fWall},
683c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                {'W', "Wmsecs", normalize * timer.fTruncatedWall},
684c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                {'c', "cmsecs", normalize * timer.fCpu},
685c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                {'C', "Cmsecs", normalize * timer.fTruncatedCpu},
686c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                {'g', "gmsecs", normalize * timer.fGpu},
687c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            };
688c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
689e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org            writer.config(config.name);
690c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com            for (size_t i = 0; i < SK_ARRAY_COUNT(times); i++) {
691c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com                if (strchr(FLAGS_timers[0], times[i].shortName) && times[i].ms > 0) {
692e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org                    writer.timer(times[i].longName, times[i].ms);
6937495f59d39f869deaba13ba5218e42dc3a7ddbaecommit-bot@chromium.org                }
69425df8884bb616f8acf1ddbfb15d800a215c5ac65reed@google.com            }
6954bc1983e01d756ae9c91fd380758457f579d26eareed@android.com        }
696bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com    }
697cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
698cb26535ff71fc323278892d6b90546b3b1c54649bsalomon@google.com    gContextFactory.destroyContexts();
699cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif
700bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com    return 0;
701bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com}
7025987f58036574ccf23049b5fe71f29a441d0641dcaryclark@google.com
7037158e6acca1b1ecc321d4d514a31cba11b5ead60borenet@google.com#if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL)
7045987f58036574ccf23049b5fe71f29a441d0641dcaryclark@google.comint main(int argc, char * const argv[]) {
7055987f58036574ccf23049b5fe71f29a441d0641dcaryclark@google.com    return tool_main(argc, (char**) argv);
7065987f58036574ccf23049b5fe71f29a441d0641dcaryclark@google.com}
7075987f58036574ccf23049b5fe71f29a441d0641dcaryclark@google.com#endif
708