blob: 289d5cb0a24a03e4264b215244865b44dc920385 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
bsalomon@google.com971d0c82011-08-19 17:22:05 +00008
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +00009#if SK_SUPPORT_GPU
bsalomon@google.com971d0c82011-08-19 17:22:05 +000010#include "GrContext.h"
bsalomon@google.comcb265352013-02-22 16:13:16 +000011#include "GrContextFactory.h"
bsalomon@google.com971d0c82011-08-19 17:22:05 +000012#include "GrRenderTarget.h"
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +000013#include "SkGpuDevice.h"
mtklein@google.comc2897432013-09-10 19:23:38 +000014#include "gl/GrGLDefines.h"
bsalomon@google.com41809932013-02-22 16:25:28 +000015#else
16class GrContext;
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +000017#endif // SK_SUPPORT_GPU
bsalomon@google.com971d0c82011-08-19 17:22:05 +000018
mtklein@google.comc2897432013-09-10 19:23:38 +000019#include "BenchTimer.h"
scroggo@google.com9a412522012-09-07 15:21:18 +000020#include "SkBenchLogger.h"
bsalomon@google.com971d0c82011-08-19 17:22:05 +000021#include "SkBenchmark.h"
robertphillips@google.com73672252013-08-29 12:40:26 +000022#include "SkBitmapDevice.h"
reed@android.combd700c32009-01-05 03:34:50 +000023#include "SkCanvas.h"
sglez@google.com586db932013-07-24 17:24:23 +000024#include "SkCommandLineFlags.h"
bsalomon@google.com82a7bfc2012-04-16 19:11:17 +000025#include "SkDeferredCanvas.h"
reed@android.com3a859a02009-01-28 00:56:29 +000026#include "SkGraphics.h"
reed@android.comb398fe82009-01-07 11:47:57 +000027#include "SkImageEncoder.h"
mtklein@google.comc2897432013-09-10 19:23:38 +000028#include "SkOSFile.h"
reed@android.com6c924ad2009-03-31 03:48:49 +000029#include "SkPicture.h"
reed@android.combd700c32009-01-05 03:34:50 +000030#include "SkString.h"
reed@android.com29348cb2009-08-04 18:17:15 +000031
mtklein@google.comc2897432013-09-10 19:23:38 +000032enum BenchMode {
33 kNormal_BenchMode,
34 kDeferred_BenchMode,
35 kDeferredSilent_BenchMode,
36 kRecord_BenchMode,
37 kPictureRecord_BenchMode
keyar@chromium.orgfdd909c2012-07-20 23:03:42 +000038};
mtklein@google.comc2897432013-09-10 19:23:38 +000039const char* BenchMode_Name[] = { "normal", "deferred", "deferredSilent", "record", "picturerecord" };
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +000040
keyar@chromium.orgfdd909c2012-07-20 23:03:42 +000041///////////////////////////////////////////////////////////////////////////////
42
reed@android.com6c924ad2009-03-31 03:48:49 +000043static void erase(SkBitmap& bm) {
44 if (bm.config() == SkBitmap::kA8_Config) {
junov@google.comdbfac8a2012-12-06 21:47:40 +000045 bm.eraseColor(SK_ColorTRANSPARENT);
reed@android.com6c924ad2009-03-31 03:48:49 +000046 } else {
47 bm.eraseColor(SK_ColorWHITE);
48 }
49}
50
reed@android.combd700c32009-01-05 03:34:50 +000051class Iter {
52public:
mtklein@google.comc2897432013-09-10 19:23:38 +000053 Iter() : fBench(BenchRegistry::Head()) {}
rmistry@google.comfbfcd562012-08-23 18:09:54 +000054
reed@android.combd700c32009-01-05 03:34:50 +000055 SkBenchmark* next() {
56 if (fBench) {
57 BenchRegistry::Factory f = fBench->factory();
58 fBench = fBench->next();
mtklein@google.comc2897432013-09-10 19:23:38 +000059 return f(NULL);
reed@android.combd700c32009-01-05 03:34:50 +000060 }
61 return NULL;
62 }
bungeman@google.comd1a416a2011-05-18 18:37:07 +000063
reed@android.combd700c32009-01-05 03:34:50 +000064private:
65 const BenchRegistry* fBench;
66};
67
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +000068class AutoPrePostDraw {
69public:
70 AutoPrePostDraw(SkBenchmark* bench) : fBench(bench) {
71 fBench->preDraw();
72 }
73 ~AutoPrePostDraw() {
74 fBench->postDraw();
75 }
76private:
77 SkBenchmark* fBench;
78};
79
reed@android.combd700c32009-01-05 03:34:50 +000080static void make_filename(const char name[], SkString* path) {
81 path->set(name);
82 for (int i = 0; name[i]; i++) {
83 switch (name[i]) {
84 case '/':
85 case '\\':
86 case ' ':
87 case ':':
88 path->writable_str()[i] = '-';
89 break;
90 default:
91 break;
92 }
93 }
94}
95
reed@android.com4c7d3d62009-01-21 03:15:13 +000096static void saveFile(const char name[], const char config[], const char dir[],
97 const SkBitmap& bm) {
reed@android.com4c7d3d62009-01-21 03:15:13 +000098 SkBitmap copy;
99 if (!bm.copyTo(&copy, SkBitmap::kARGB_8888_Config)) {
100 return;
101 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000102
reed@android.comf523e252009-01-26 23:15:37 +0000103 if (bm.config() == SkBitmap::kA8_Config) {
104 // turn alpha into gray-scale
105 size_t size = copy.getSize() >> 2;
106 SkPMColor* p = copy.getAddr32(0, 0);
107 for (size_t i = 0; i < size; i++) {
108 int c = (*p >> SK_A32_SHIFT) & 0xFF;
109 c = 255 - c;
110 c |= (c << 24) | (c << 16) | (c << 8);
111 *p++ = c | (SK_A32_MASK << SK_A32_SHIFT);
112 }
113 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000114
mtklein@google.comc2897432013-09-10 19:23:38 +0000115 SkString filename;
116 make_filename(name, &filename);
117 filename.appendf("_%s.png", config);
118 SkString path = SkOSPath::SkPathJoin(dir, filename.c_str());
119 ::remove(path.c_str());
120 SkImageEncoder::EncodeFile(path.c_str(), copy, SkImageEncoder::kPNG_Type, 100);
reed@android.com4c7d3d62009-01-21 03:15:13 +0000121}
122
123static void performClip(SkCanvas* canvas, int w, int h) {
124 SkRect r;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000125
reed@android.com4c7d3d62009-01-21 03:15:13 +0000126 r.set(SkIntToScalar(10), SkIntToScalar(10),
127 SkIntToScalar(w*2/3), SkIntToScalar(h*2/3));
128 canvas->clipRect(r, SkRegion::kIntersect_Op);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000129
reed@android.com4c7d3d62009-01-21 03:15:13 +0000130 r.set(SkIntToScalar(w/3), SkIntToScalar(h/3),
131 SkIntToScalar(w-10), SkIntToScalar(h-10));
132 canvas->clipRect(r, SkRegion::kXOR_Op);
133}
134
135static void performRotate(SkCanvas* canvas, int w, int h) {
136 const SkScalar x = SkIntToScalar(w) / 2;
137 const SkScalar y = SkIntToScalar(h) / 2;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000138
reed@android.com4c7d3d62009-01-21 03:15:13 +0000139 canvas->translate(x, y);
140 canvas->rotate(SkIntToScalar(35));
141 canvas->translate(-x, -y);
142}
143
reed@android.com387359e2009-08-04 01:51:09 +0000144static void performScale(SkCanvas* canvas, int w, int h) {
145 const SkScalar x = SkIntToScalar(w) / 2;
146 const SkScalar y = SkIntToScalar(h) / 2;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000147
reed@android.com387359e2009-08-04 01:51:09 +0000148 canvas->translate(x, y);
149 // just enough so we can't take the sprite case
150 canvas->scale(SK_Scalar1 * 99/100, SK_Scalar1 * 99/100);
151 canvas->translate(-x, -y);
152}
153
mike@reedtribe.orga9015f82011-05-17 02:25:05 +0000154enum Backend {
bsalomon@google.com604a56a2013-03-15 15:42:15 +0000155 kNonRendering_Backend,
mike@reedtribe.orga9015f82011-05-17 02:25:05 +0000156 kRaster_Backend,
157 kGPU_Backend,
158 kPDF_Backend,
159};
160
robertphillips@google.com1f2f3382013-08-29 11:54:56 +0000161static SkBaseDevice* make_device(SkBitmap::Config config, const SkIPoint& size,
162 Backend backend, int sampleCount, GrContext* context) {
163 SkBaseDevice* device = NULL;
mike@reedtribe.orga9015f82011-05-17 02:25:05 +0000164 SkBitmap bitmap;
165 bitmap.setConfig(config, size.fX, size.fY);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000166
mike@reedtribe.orga9015f82011-05-17 02:25:05 +0000167 switch (backend) {
168 case kRaster_Backend:
169 bitmap.allocPixels();
170 erase(bitmap);
robertphillips@google.com1f2f3382013-08-29 11:54:56 +0000171 device = SkNEW_ARGS(SkBitmapDevice, (bitmap));
mike@reedtribe.orga9015f82011-05-17 02:25:05 +0000172 break;
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000173#if SK_SUPPORT_GPU
bsalomon@google.comcb265352013-02-22 16:13:16 +0000174 case kGPU_Backend: {
175 GrTextureDesc desc;
176 desc.fConfig = kSkia8888_GrPixelConfig;
177 desc.fFlags = kRenderTarget_GrTextureFlagBit;
178 desc.fWidth = size.fX;
179 desc.fHeight = size.fY;
bsalomon@google.com8a70eef2013-03-19 13:58:55 +0000180 desc.fSampleCnt = sampleCount;
bsalomon@google.comcb265352013-02-22 16:13:16 +0000181 SkAutoTUnref<GrTexture> texture(context->createUncachedTexture(desc, NULL, 0));
182 if (!texture) {
183 return NULL;
184 }
185 device = SkNEW_ARGS(SkGpuDevice, (context, texture.get()));
mike@reedtribe.orga9015f82011-05-17 02:25:05 +0000186 break;
bsalomon@google.comcb265352013-02-22 16:13:16 +0000187 }
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000188#endif
mike@reedtribe.orga9015f82011-05-17 02:25:05 +0000189 case kPDF_Backend:
190 default:
mtklein@google.com330313a2013-08-22 15:37:26 +0000191 SkDEBUGFAIL("unsupported");
mike@reedtribe.orga9015f82011-05-17 02:25:05 +0000192 }
193 return device;
194}
195
bsalomon@google.comcb265352013-02-22 16:13:16 +0000196#if SK_SUPPORT_GPU
197GrContextFactory gContextFactory;
198typedef GrContextFactory::GLContextType GLContextType;
mtklein@google.comc2897432013-09-10 19:23:38 +0000199static const GLContextType kNative = GrContextFactory::kNative_GLContextType;
200#if SK_ANGLE
201static const GLContextType kANGLE = GrContextFactory::kANGLE_GLContextType;
202#else
203static const GLContextType kANGLE = kNative;
204#endif
205static const GLContextType kDebug = GrContextFactory::kDebug_GLContextType;
206static const GLContextType kNull = GrContextFactory::kNull_GLContextType;
bsalomon@google.comcb265352013-02-22 16:13:16 +0000207#else
208typedef int GLContextType;
mtklein@google.comc2897432013-09-10 19:23:38 +0000209static const GLContextType kNative = 0, kANGLE = 0, kDebug = 0, kNull = 0;
bsalomon@google.comcb265352013-02-22 16:13:16 +0000210#endif
211
mtklein@google.comc2897432013-09-10 19:23:38 +0000212#ifdef SK_DEBUG
213static const bool kIsDebug = true;
214#else
215static const bool kIsDebug = false;
216#endif
217
218static const struct Config {
219 SkBitmap::Config config;
220 const char* name;
221 int sampleCount;
222 Backend backend;
223 GLContextType contextType;
224 bool runByDefault;
reed@android.com4bc19832009-01-19 20:08:35 +0000225} gConfigs[] = {
mtklein@google.comc2897432013-09-10 19:23:38 +0000226 { SkBitmap::kNo_Config, "NONRENDERING", 0, kNonRendering_Backend, kNative, true},
227 { SkBitmap::kARGB_8888_Config, "8888", 0, kRaster_Backend, kNative, true},
228 { SkBitmap::kRGB_565_Config, "565", 0, kRaster_Backend, kNative, true},
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000229#if SK_SUPPORT_GPU
mtklein@google.comc2897432013-09-10 19:23:38 +0000230 { SkBitmap::kARGB_8888_Config, "GPU", 0, kGPU_Backend, kNative, true},
231 { SkBitmap::kARGB_8888_Config, "MSAA4", 4, kGPU_Backend, kNative, false},
232 { SkBitmap::kARGB_8888_Config, "MSAA16", 16, kGPU_Backend, kNative, false},
robertphillips@google.comd3b9fbb2012-03-28 16:19:11 +0000233#if SK_ANGLE
mtklein@google.comc2897432013-09-10 19:23:38 +0000234 { SkBitmap::kARGB_8888_Config, "ANGLE", 0, kGPU_Backend, kANGLE, true},
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000235#endif // SK_ANGLE
mtklein@google.comc2897432013-09-10 19:23:38 +0000236 { SkBitmap::kARGB_8888_Config, "Debug", 0, kGPU_Backend, kDebug, kIsDebug},
237 { SkBitmap::kARGB_8888_Config, "NULLGPU", 0, kGPU_Backend, kNull, true},
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000238#endif // SK_SUPPORT_GPU
reed@android.com4bc19832009-01-19 20:08:35 +0000239};
240
mtklein@google.comc2897432013-09-10 19:23:38 +0000241DEFINE_string(outDir, "", "If given, image of each bench will be put in outDir.");
242DEFINE_string(timers, "cg", "Timers to display. "
243 "Options: w(all) W(all, truncated) c(pu) C(pu, truncated) g(pu)");
reed@android.com4c7d3d62009-01-21 03:15:13 +0000244
mtklein@google.comc2897432013-09-10 19:23:38 +0000245DEFINE_bool(rotate, false, "Rotate canvas before bench run?");
246DEFINE_bool(scale, false, "Scale canvas before bench run?");
247DEFINE_bool(clip, false, "Clip canvas before bench run?");
bsalomon@google.com8a70eef2013-03-19 13:58:55 +0000248
mtklein@google.comc2897432013-09-10 19:23:38 +0000249DEFINE_bool(forceAA, true, "Force anti-aliasing?");
250DEFINE_bool(forceFilter, false, "Force bitmap filtering?");
251DEFINE_string(forceDither, "default", "Force dithering: true, false, or default?");
252DEFINE_bool(forceBlend, false, "Force alpha blending?");
253
254DEFINE_int32(gpuCacheBytes, -1, "GPU cache size limit in bytes. 0 to disable cache.");
255DEFINE_int32(gpuCacheCount, -1, "GPU cache size limit in object count. 0 to disable cache.");
256
257DEFINE_string(match, "", "[~][^]substring[$] [...] of test name to run.\n"
258 "Multiple matches may be separated by spaces.\n"
259 "~ causes a matching test to always be skipped\n"
260 "^ requires the start of the test to match\n"
261 "$ requires the end of the test to match\n"
262 "^ and $ requires an exact match\n"
263 "If a test does not match any list entry,\n"
264 "it is skipped unless some list entry starts with ~\n");
265DEFINE_string(mode, "normal",
266 "normal: draw to a normal canvas;\n"
267 "deferred: draw to a deferred canvas;\n"
268 "deferredSilent: deferred with silent playback;\n"
269 "record: draw to an SkPicture;\n"
270 "picturerecord: draw from an SkPicture to an SkPicture.\n");
271DEFINE_string(config, "", "Run configs given. If empty, runs the defaults set in gConfigs.");
272DEFINE_string(logFile, "", "Also write stdout here.");
273DEFINE_int32(benchMs, 20, "Target time in ms to run each benchmark config.");
274DEFINE_string(timeFormat, "%9.2f", "Format to print results, in milliseconds per 1000 loops.");
tomhudson@google.com86bb9b72012-04-03 13:28:57 +0000275
caryclark@google.com5987f582012-10-02 18:33:14 +0000276int tool_main(int argc, char** argv);
277int tool_main(int argc, char** argv) {
bsalomon@google.com4e230682013-01-15 20:37:04 +0000278#if SK_ENABLE_INST_COUNT
bsalomon@google.com65a87cc2012-08-14 13:15:44 +0000279 gPrintInstCount = true;
280#endif
reed@android.com3a859a02009-01-28 00:56:29 +0000281 SkAutoGraphics ag;
mtklein@google.comc2897432013-09-10 19:23:38 +0000282 SkCommandLineFlags::Parse(argc, argv);
bsalomon@google.com65a87cc2012-08-14 13:15:44 +0000283
mtklein@google.comc2897432013-09-10 19:23:38 +0000284 // First, parse some flags.
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000285
scroggo@google.com9a412522012-09-07 15:21:18 +0000286 SkBenchLogger logger;
mtklein@google.comc2897432013-09-10 19:23:38 +0000287 if (FLAGS_logFile.count()) {
288 logger.SetLogFile(FLAGS_logFile[0]);
289 }
scroggo@google.com9a412522012-09-07 15:21:18 +0000290
mtklein@google.comc2897432013-09-10 19:23:38 +0000291 const uint8_t alpha = FLAGS_forceBlend ? 0x80 : 0xFF;
292 SkTriState::State dither = SkTriState::kDefault;
293 for (size_t i = 0; i < 3; i++) {
294 if (strcmp(SkTriState::Name[i], FLAGS_forceDither[0]) == 0) {
295 dither = static_cast<SkTriState::State>(i);
reed@android.comb398fe82009-01-07 11:47:57 +0000296 }
297 }
mtklein@google.comc2897432013-09-10 19:23:38 +0000298
299 BenchMode benchMode = kNormal_BenchMode;
300 for (size_t i = 0; i < SK_ARRAY_COUNT(BenchMode_Name); i++) {
301 if (strcmp(FLAGS_mode[0], BenchMode_Name[i]) == 0) {
302 benchMode = static_cast<BenchMode>(i);
303 }
keyar@chromium.orgfdd909c2012-07-20 23:03:42 +0000304 }
mtklein@google.comc2897432013-09-10 19:23:38 +0000305
306 SkTDArray<int> configs;
307 // Try user-given configs first.
308 for (int i = 0; i < FLAGS_config.count(); i++) {
309 for (size_t j = 0; j < SK_ARRAY_COUNT(gConfigs); j++) {
310 if (0 == strcmp(FLAGS_config[i], gConfigs[j].name)) {
311 *configs.append() = j;
312 }
313 }
keyar@chromium.orgfdd909c2012-07-20 23:03:42 +0000314 }
mtklein@google.comc2897432013-09-10 19:23:38 +0000315 // If there weren't any, fill in with defaults.
316 if (configs.count() == 0) {
317 for (size_t i = 0; i < SK_ARRAY_COUNT(gConfigs); ++i) {
318 if (gConfigs[i].runByDefault) {
bsalomon@google.com8a70eef2013-03-19 13:58:55 +0000319 *configs.append() = i;
320 }
tomhudson@google.com13eaaaa2012-04-16 18:00:40 +0000321 }
322 }
mtklein@google.comc2897432013-09-10 19:23:38 +0000323 // Filter out things we can't run.
324 if (kNormal_BenchMode != benchMode) {
bsalomon@google.com604a56a2013-03-15 15:42:15 +0000325 // Non-rendering configs only run in normal mode
326 for (int i = 0; i < configs.count(); ++i) {
mtklein@google.comc2897432013-09-10 19:23:38 +0000327 const Config& config = gConfigs[configs[i]];
328 if (kNonRendering_Backend == config.backend) {
bsalomon@google.com604a56a2013-03-15 15:42:15 +0000329 configs.remove(i, 1);
330 --i;
331 }
332 }
333 }
bsalomon@google.com8a70eef2013-03-19 13:58:55 +0000334#if SK_SUPPORT_GPU
335 for (int i = 0; i < configs.count(); ++i) {
mtklein@google.comc2897432013-09-10 19:23:38 +0000336 const Config& config = gConfigs[configs[i]];
bsalomon@google.com8a70eef2013-03-19 13:58:55 +0000337
mtklein@google.comc2897432013-09-10 19:23:38 +0000338 if (kGPU_Backend == config.backend) {
339 GrContext* context = gContextFactory.get(config.contextType);
bsalomon@google.com8a70eef2013-03-19 13:58:55 +0000340 if (NULL == context) {
341 SkString error;
342 error.printf("Error creating GrContext for config %s. Config will be skipped.\n",
mtklein@google.comc2897432013-09-10 19:23:38 +0000343 config.name);
344 logger.logError(error);
bsalomon@google.com8a70eef2013-03-19 13:58:55 +0000345 configs.remove(i);
346 --i;
347 continue;
348 }
mtklein@google.comc2897432013-09-10 19:23:38 +0000349 if (config.sampleCount > context->getMaxSampleCount()){
bsalomon@google.com8a70eef2013-03-19 13:58:55 +0000350 SkString error;
351 error.printf("Sample count (%d) for config %s is unsupported. "
352 "Config will be skipped.\n",
mtklein@google.comc2897432013-09-10 19:23:38 +0000353 config.sampleCount, config.name);
354 logger.logError(error);
bsalomon@google.com8a70eef2013-03-19 13:58:55 +0000355 configs.remove(i);
356 --i;
357 continue;
358 }
359 }
360 }
361#endif
362
mtklein@google.comc2897432013-09-10 19:23:38 +0000363 // All flags should be parsed now. Report our settings.
364 if (kIsDebug) {
365 logger.logError("bench was built in Debug mode, so we're going to hide the times."
366 " It's for your own good!\n");
367 }
368 SkString str("skia bench:");
369 str.appendf(" mode=%s", FLAGS_mode[0]);
370 str.appendf(" alpha=0x%02X antialias=%d filter=%d dither=%s",
371 alpha, FLAGS_forceAA, FLAGS_forceFilter, SkTriState::Name[dither]);
372 str.appendf(" rotate=%d scale=%d clip=%d", FLAGS_rotate, FLAGS_scale, FLAGS_clip);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000373
mtklein@google.comc2897432013-09-10 19:23:38 +0000374#if defined(SK_SCALAR_IS_FIXED)
375 str.append(" scalar=fixed");
376#else
377 str.append(" scalar=float");
bungeman@google.coma5d48412011-06-15 17:25:46 +0000378#endif
379
380#if defined(SK_BUILD_FOR_WIN32)
mtklein@google.comc2897432013-09-10 19:23:38 +0000381 str.append(" system=WIN32");
bungeman@google.coma5d48412011-06-15 17:25:46 +0000382#elif defined(SK_BUILD_FOR_MAC)
mtklein@google.comc2897432013-09-10 19:23:38 +0000383 str.append(" system=MAC");
bungeman@google.coma5d48412011-06-15 17:25:46 +0000384#elif defined(SK_BUILD_FOR_ANDROID)
mtklein@google.comc2897432013-09-10 19:23:38 +0000385 str.append(" system=ANDROID");
bungeman@google.coma5d48412011-06-15 17:25:46 +0000386#elif defined(SK_BUILD_FOR_UNIX)
mtklein@google.comc2897432013-09-10 19:23:38 +0000387 str.append(" system=UNIX");
bungeman@google.coma5d48412011-06-15 17:25:46 +0000388#else
mtklein@google.comc2897432013-09-10 19:23:38 +0000389 str.append(" system=other");
bungeman@google.coma5d48412011-06-15 17:25:46 +0000390#endif
391
392#if defined(SK_DEBUG)
mtklein@google.comc2897432013-09-10 19:23:38 +0000393 str.append(" DEBUG");
bungeman@google.coma5d48412011-06-15 17:25:46 +0000394#endif
mtklein@google.comc2897432013-09-10 19:23:38 +0000395 str.append("\n");
396 logger.logProgress(str);
bsalomon@google.com508824b2011-12-13 16:49:49 +0000397
mtklein@google.comc2897432013-09-10 19:23:38 +0000398
399 // Set texture cache limits if non-default.
bsalomon@google.com5c90e292013-02-22 19:17:13 +0000400 for (size_t i = 0; i < SK_ARRAY_COUNT(gConfigs); ++i) {
bsalomon@google.comcb265352013-02-22 16:13:16 +0000401#if SK_SUPPORT_GPU
mtklein@google.comc2897432013-09-10 19:23:38 +0000402 const Config& config = gConfigs[i];
403 if (kGPU_Backend != config.backend) {
404 continue;
bsalomon@google.comcb265352013-02-22 16:13:16 +0000405 }
mtklein@google.comc2897432013-09-10 19:23:38 +0000406 GrContext* context = gContextFactory.get(config.contextType);
407 if (NULL == context) {
408 continue;
409 }
410
411 size_t bytes;
412 int count;
413 context->getTextureCacheLimits(&count, &bytes);
414 if (-1 != FLAGS_gpuCacheBytes) {
415 bytes = static_cast<size_t>(FLAGS_gpuCacheBytes);
416 }
417 if (-1 != FLAGS_gpuCacheCount) {
418 count = FLAGS_gpuCacheCount;
419 }
420 context->setTextureCacheLimits(count, bytes);
bsalomon@google.comcb265352013-02-22 16:13:16 +0000421#endif
422 }
bsalomon@google.com74913722011-10-27 20:44:19 +0000423
mtklein@google.comc2897432013-09-10 19:23:38 +0000424 // Find the longest name of the benches we're going to run to make the output pretty.
425 Iter names;
reed@android.combd700c32009-01-05 03:34:50 +0000426 SkBenchmark* bench;
mtklein@google.comc2897432013-09-10 19:23:38 +0000427 int longestName = 0;
428 while ((bench = names.next()) != NULL) {
429 SkAutoTUnref<SkBenchmark> benchUnref(bench);
430 if (SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getName())) {
431 continue;
432 }
433 const int length = strlen(bench->getName());
434 longestName = length > longestName ? length : longestName;
435 }
436
437 // Run each bench in each configuration it supports and we asked for.
438 Iter iter;
reed@android.combd700c32009-01-05 03:34:50 +0000439 while ((bench = iter.next()) != NULL) {
bsalomon@google.com7fbc6042012-08-13 22:10:05 +0000440 SkAutoTUnref<SkBenchmark> benchUnref(bench);
mtklein@google.comc2897432013-09-10 19:23:38 +0000441 if (SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getName())) {
reed@android.comb398fe82009-01-07 11:47:57 +0000442 continue;
443 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000444
mtklein@google.comc2897432013-09-10 19:23:38 +0000445 bench->setForceAlpha(alpha);
446 bench->setForceAA(FLAGS_forceAA);
447 bench->setForceFilter(FLAGS_forceFilter);
448 bench->setDither(dither);
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000449 AutoPrePostDraw appd(bench);
450
mtklein@google.comc2897432013-09-10 19:23:38 +0000451 bool loggedBenchName = false;
452 for (int i = 0; i < configs.count(); ++i) {
453 const int configIndex = configs[i];
454 const Config& config = gConfigs[configIndex];
tomhudson@google.com13eaaaa2012-04-16 18:00:40 +0000455
mtklein@google.comc2897432013-09-10 19:23:38 +0000456 if ((kNonRendering_Backend == config.backend) == bench->isRendering()) {
457 continue;
bsalomon@google.com604a56a2013-03-15 15:42:15 +0000458 }
459
bsalomon@google.comcb265352013-02-22 16:13:16 +0000460 GrContext* context = NULL;
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000461#if SK_SUPPORT_GPU
sugoi@google.com9c55f802013-03-07 20:52:59 +0000462 SkGLContextHelper* glContext = NULL;
mtklein@google.comc2897432013-09-10 19:23:38 +0000463 if (kGPU_Backend == config.backend) {
464 context = gContextFactory.get(config.contextType);
bsalomon@google.comcb265352013-02-22 16:13:16 +0000465 if (NULL == context) {
466 continue;
467 }
mtklein@google.comc2897432013-09-10 19:23:38 +0000468 glContext = gContextFactory.getGLContext(config.contextType);
mike@reedtribe.orga9015f82011-05-17 02:25:05 +0000469 }
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000470#endif
mtklein@google.comc2897432013-09-10 19:23:38 +0000471 SkAutoTUnref<SkBaseDevice> device;
472 SkAutoTUnref<SkCanvas> canvas;
473 SkPicture recordFrom, recordTo;
474 const SkIPoint dim = bench->getSize();
bsalomon@google.com604a56a2013-03-15 15:42:15 +0000475
mtklein@google.comc2897432013-09-10 19:23:38 +0000476 const SkPicture::RecordingFlags kRecordFlags =
477 SkPicture::kUsePathBoundsForClip_RecordingFlag;
478
479 if (kNonRendering_Backend != config.backend) {
480 device.reset(make_device(config.config,
481 dim,
482 config.backend,
483 config.sampleCount,
484 context));
485 if (!device.get()) {
commit-bot@chromium.org7495f592013-06-03 19:31:07 +0000486 SkString error;
mtklein@google.comc2897432013-09-10 19:23:38 +0000487 error.printf("Device creation failure for config %s. Will skip.\n", config.name);
488 logger.logError(error);
489 continue;
keyar@chromium.orgfdd909c2012-07-20 23:03:42 +0000490 }
junov@chromium.orgfb103892012-09-20 19:35:43 +0000491
mtklein@google.comc2897432013-09-10 19:23:38 +0000492 switch(benchMode) {
493 case kDeferredSilent_BenchMode:
494 case kDeferred_BenchMode:
495 canvas.reset(SkDeferredCanvas::Create(device.get()));
496 break;
497 case kRecord_BenchMode:
498 canvas.reset(SkRef(recordTo.beginRecording(dim.fX, dim.fY, kRecordFlags)));
499 break;
500 case kPictureRecord_BenchMode:
501 bench->draw(recordFrom.beginRecording(dim.fX, dim.fY, kRecordFlags));
502 recordFrom.endRecording();
503 canvas.reset(SkRef(recordTo.beginRecording(dim.fX, dim.fY, kRecordFlags)));
504 break;
505 case kNormal_BenchMode:
506 canvas.reset(new SkCanvas(device.get()));
507 break;
508 default:
509 SkASSERT(false);
510 }
511 }
512
513 if (NULL != canvas) {
514 canvas->clear(SK_ColorWHITE);
515 if (FLAGS_clip) { performClip(canvas, dim.fX, dim.fY); }
516 if (FLAGS_scale) { performScale(canvas, dim.fX, dim.fY); }
517 if (FLAGS_rotate) { performRotate(canvas, dim.fX, dim.fY); }
518 }
519
520 if (!loggedBenchName) {
521 loggedBenchName = true;
522 SkString str;
523 str.printf("running bench [%3d %3d] %*s ",
524 dim.fX, dim.fY, longestName, bench->getName());
525 logger.logProgress(str);
526 }
527
528#if SK_SUPPORT_GPU
529 SkGLContextHelper* contextHelper = NULL;
530 if (kGPU_Backend == config.backend) {
531 contextHelper = gContextFactory.getGLContext(config.contextType);
532 }
533 BenchTimer timer(contextHelper);
534#else
535 BenchTimer timer;
536#endif
537
538 bench->setLoops(0);
539 do {
540 // Ramp up 1 -> 4 -> 16 -> ... -> ~1 billion.
541 const int loops = bench->getLoops();
542 if (loops >= (1<<30)) {
543 // If you find it takes more than a billion loops to get up to 20ms of runtime,
544 // you've got a computer clocked at several THz or have a broken benchmark. ;)
545 // "1B ought to be enough for anybody."
commit-bot@chromium.org7495f592013-06-03 19:31:07 +0000546 SkString str;
mtklein@google.comc2897432013-09-10 19:23:38 +0000547 str.printf("Can't ramp %s to %dms.\n", bench->getName(), FLAGS_benchMs);
548 logger.logError(str);
549 break;
550 }
551 bench->setLoops(loops == 0 ? 1 : loops * 4);
552
553 if ((benchMode == kRecord_BenchMode || benchMode == kPictureRecord_BenchMode)) {
554 // Clear the recorded commands so that they do not accumulate.
555 canvas.reset(recordTo.beginRecording(dim.fX, dim.fY, kRecordFlags));
junov@chromium.orgfb103892012-09-20 19:35:43 +0000556 }
robertphillips@google.com91ee3a12012-08-28 12:18:40 +0000557
mtklein@google.comc2897432013-09-10 19:23:38 +0000558 timer.start();
559 if (NULL != canvas) {
560 canvas->save();
commit-bot@chromium.org7495f592013-06-03 19:31:07 +0000561 }
mtklein@google.comc2897432013-09-10 19:23:38 +0000562 if (benchMode == kPictureRecord_BenchMode) {
563 recordFrom.draw(canvas);
borenet@google.com8ad29ce2013-09-10 17:22:43 +0000564 } else {
mtklein@google.comc2897432013-09-10 19:23:38 +0000565 bench->draw(canvas);
commit-bot@chromium.org7495f592013-06-03 19:31:07 +0000566 }
borenet@google.com8ad29ce2013-09-10 17:22:43 +0000567
mtklein@google.comc2897432013-09-10 19:23:38 +0000568 if (kDeferredSilent_BenchMode == benchMode) {
569 static_cast<SkDeferredCanvas*>(canvas.get())->silentFlush();
570 } else if (NULL != canvas) {
571 canvas->flush();
572 }
573
574 if (NULL != canvas) {
575 canvas->restore();
576 }
577
578
579 // Stop truncated timers before GL calls complete, and stop the full timers after.
580 timer.truncatedEnd();
581#if SK_SUPPORT_GPU
582 if (NULL != glContext) {
583 context->flush();
584 SK_GL(*glContext, Finish());
585 }
586#endif
587 timer.end();
588 } while (!kIsDebug && timer.fWall < FLAGS_benchMs); // One loop only in debug mode.
589
590 if (FLAGS_outDir.count() && kNonRendering_Backend != config.backend) {
591 saveFile(bench->getName(),
592 config.name,
593 FLAGS_outDir[0],
594 device->accessBitmap(false));
595 }
596
597 if (kIsDebug) {
598 // Let's not mislead ourselves by looking at Debug build bench times!
599 continue;
600 }
601
602 // Normalize to ms per 1000 iterations.
603 const double normalize = 1000.0 / bench->getLoops();
604 const struct { char shortName; const char* longName; double ms; } times[] = {
605 {'w', "msecs", normalize * timer.fWall},
606 {'W', "Wmsecs", normalize * timer.fTruncatedWall},
607 {'c', "cmsecs", normalize * timer.fCpu},
608 {'C', "Cmsecs", normalize * timer.fTruncatedCpu},
609 {'g', "gmsecs", normalize * timer.fGpu},
610 };
611
612 SkString result;
613 result.appendf(" %s:", config.name);
614 for (size_t i = 0; i < SK_ARRAY_COUNT(times); i++) {
615 if (strchr(FLAGS_timers[0], times[i].shortName) && times[i].ms > 0) {
616 result.appendf(" %s = ", times[i].longName);
617 result.appendf(FLAGS_timeFormat[0], times[i].ms);
commit-bot@chromium.org7495f592013-06-03 19:31:07 +0000618 }
reed@google.com25df8882011-07-14 19:03:58 +0000619 }
mtklein@google.comc2897432013-09-10 19:23:38 +0000620 logger.logProgress(result);
bensong@google.com24ed8d72013-06-12 14:45:03 +0000621 }
mtklein@google.comc2897432013-09-10 19:23:38 +0000622 if (loggedBenchName) {
623 logger.logProgress("\n");
bsalomon@google.com604a56a2013-03-15 15:42:15 +0000624 }
reed@android.combd700c32009-01-05 03:34:50 +0000625 }
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000626#if SK_SUPPORT_GPU
bsalomon@google.comcb265352013-02-22 16:13:16 +0000627 gContextFactory.destroyContexts();
robertphillips@google.com9d594202012-09-13 14:05:00 +0000628#endif
reed@android.combd700c32009-01-05 03:34:50 +0000629 return 0;
630}
caryclark@google.com5987f582012-10-02 18:33:14 +0000631
borenet@google.com7158e6a2012-11-01 17:43:44 +0000632#if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL)
caryclark@google.com5987f582012-10-02 18:33:14 +0000633int main(int argc, char * const argv[]) {
634 return tool_main(argc, (char**) argv);
635}
636#endif