summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/skia/bench
diff options
context:
space:
mode:
authorJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-08-08 14:30:41 +0200
committerJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-08-12 13:49:54 +0200
commitab0a50979b9eb4dfa3320eff7e187e41efedf7a9 (patch)
tree498dfb8a97ff3361a9f7486863a52bb4e26bb898 /chromium/third_party/skia/bench
parent4ce69f7403811819800e7c5ae1318b2647e778d1 (diff)
Update Chromium to beta version 37.0.2062.68
Change-Id: I188e3b5aff1bec75566014291b654eb19f5bc8ca Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'chromium/third_party/skia/bench')
-rw-r--r--chromium/third_party/skia/bench/AAClipBench.cpp257
-rw-r--r--chromium/third_party/skia/bench/BenchGpuTimer_gl.cpp74
-rw-r--r--chromium/third_party/skia/bench/BenchGpuTimer_gl.h26
-rw-r--r--chromium/third_party/skia/bench/BenchLogger.cpp30
-rw-r--r--chromium/third_party/skia/bench/BenchLogger.h76
-rw-r--r--chromium/third_party/skia/bench/BenchSysTimer_c.cpp27
-rw-r--r--chromium/third_party/skia/bench/BenchSysTimer_c.h26
-rw-r--r--chromium/third_party/skia/bench/BenchSysTimer_mach.cpp76
-rw-r--r--chromium/third_party/skia/bench/BenchSysTimer_mach.h26
-rw-r--r--chromium/third_party/skia/bench/BenchSysTimer_posix.cpp57
-rw-r--r--chromium/third_party/skia/bench/BenchSysTimer_posix.h25
-rw-r--r--chromium/third_party/skia/bench/BenchSysTimer_windows.cpp64
-rw-r--r--chromium/third_party/skia/bench/BenchSysTimer_windows.h26
-rw-r--r--chromium/third_party/skia/bench/BenchTimer.cpp94
-rw-r--r--chromium/third_party/skia/bench/BenchTimer.h67
-rw-r--r--chromium/third_party/skia/bench/BenchTool/BenchTool.xcodeproj/project.pbxproj324
-rw-r--r--chromium/third_party/skia/bench/Benchmark.cpp56
-rw-r--r--chromium/third_party/skia/bench/Benchmark.h128
-rw-r--r--chromium/third_party/skia/bench/BicubicBench.cpp58
-rw-r--r--chromium/third_party/skia/bench/BitmapBench.cpp381
-rw-r--r--chromium/third_party/skia/bench/BitmapRectBench.cpp113
-rw-r--r--chromium/third_party/skia/bench/BitmapScaleBench.cpp111
-rw-r--r--chromium/third_party/skia/bench/BlurBench.cpp109
-rw-r--r--chromium/third_party/skia/bench/BlurImageFilterBench.cpp95
-rw-r--r--chromium/third_party/skia/bench/BlurRectBench.cpp228
-rw-r--r--chromium/third_party/skia/bench/BlurRoundRectBench.cpp93
-rw-r--r--chromium/third_party/skia/bench/ChartBench.cpp192
-rw-r--r--chromium/third_party/skia/bench/ChecksumBench.cpp97
-rw-r--r--chromium/third_party/skia/bench/ChromeBench.cpp496
-rw-r--r--chromium/third_party/skia/bench/CmapBench.cpp102
-rw-r--r--chromium/third_party/skia/bench/ColorFilterBench.cpp367
-rw-r--r--chromium/third_party/skia/bench/ColorPrivBench.cpp81
-rw-r--r--chromium/third_party/skia/bench/CoverageBench.cpp70
-rw-r--r--chromium/third_party/skia/bench/DashBench.cpp489
-rw-r--r--chromium/third_party/skia/bench/DecodeBench.cpp50
-rw-r--r--chromium/third_party/skia/bench/DeferredCanvasBench.cpp106
-rw-r--r--chromium/third_party/skia/bench/DeferredSurfaceCopyBench.cpp82
-rw-r--r--chromium/third_party/skia/bench/DisplacementBench.cpp174
-rw-r--r--chromium/third_party/skia/bench/ETCBitmapBench.cpp235
-rw-r--r--chromium/third_party/skia/bench/FSRectBench.cpp63
-rw-r--r--chromium/third_party/skia/bench/FontCacheBench.cpp158
-rw-r--r--chromium/third_party/skia/bench/FontScalerBench.cpp52
-rw-r--r--chromium/third_party/skia/bench/GMBench.cpp51
-rw-r--r--chromium/third_party/skia/bench/GMBench.h31
-rw-r--r--chromium/third_party/skia/bench/GameBench.cpp334
-rw-r--r--chromium/third_party/skia/bench/GrMemoryPoolBench.cpp178
-rw-r--r--chromium/third_party/skia/bench/GrOrderedSetBench.cpp148
-rw-r--r--chromium/third_party/skia/bench/GrResourceCacheBench.cpp239
-rw-r--r--chromium/third_party/skia/bench/GradientBench.cpp390
-rw-r--r--chromium/third_party/skia/bench/HairlinePathBench.cpp258
-rw-r--r--chromium/third_party/skia/bench/ImageCacheBench.cpp57
-rw-r--r--chromium/third_party/skia/bench/ImageDecodeBench.cpp93
-rw-r--r--chromium/third_party/skia/bench/ImageFilterDAGBench.cpp46
-rw-r--r--chromium/third_party/skia/bench/InterpBench.cpp163
-rw-r--r--chromium/third_party/skia/bench/LightingBench.cpp246
-rw-r--r--chromium/third_party/skia/bench/LineBench.cpp66
-rw-r--r--chromium/third_party/skia/bench/MagnifierBench.cpp85
-rw-r--r--chromium/third_party/skia/bench/MathBench.cpp611
-rw-r--r--chromium/third_party/skia/bench/Matrix44Bench.cpp304
-rw-r--r--chromium/third_party/skia/bench/MatrixBench.cpp472
-rw-r--r--chromium/third_party/skia/bench/MatrixConvolutionBench.cpp60
-rw-r--r--chromium/third_party/skia/bench/MemcpyBench.cpp160
-rw-r--r--chromium/third_party/skia/bench/MemoryBench.cpp165
-rw-r--r--chromium/third_party/skia/bench/MemsetBench.cpp116
-rw-r--r--chromium/third_party/skia/bench/MergeBench.cpp97
-rw-r--r--chromium/third_party/skia/bench/MorphologyBench.cpp96
-rw-r--r--chromium/third_party/skia/bench/MutexBench.cpp35
-rw-r--r--chromium/third_party/skia/bench/PathBench.cpp1019
-rw-r--r--chromium/third_party/skia/bench/PathIterBench.cpp95
-rw-r--r--chromium/third_party/skia/bench/PathUtilsBench.cpp72
-rw-r--r--chromium/third_party/skia/bench/PerlinNoiseBench.cpp62
-rw-r--r--chromium/third_party/skia/bench/PicturePlaybackBench.cpp141
-rw-r--r--chromium/third_party/skia/bench/PictureRecordBench.cpp178
-rw-r--r--chromium/third_party/skia/bench/PremulAndUnpremulAlphaOpsBench.cpp66
-rw-r--r--chromium/third_party/skia/bench/QuadTreeBench.cpp216
-rw-r--r--chromium/third_party/skia/bench/RTreeBench.cpp269
-rw-r--r--chromium/third_party/skia/bench/ReadPixBench.cpp67
-rw-r--r--chromium/third_party/skia/bench/RectBench.cpp345
-rw-r--r--chromium/third_party/skia/bench/RectanizerBench.cpp138
-rw-r--r--chromium/third_party/skia/bench/RectoriBench.cpp104
-rw-r--r--chromium/third_party/skia/bench/RefCntBench.cpp200
-rw-r--r--chromium/third_party/skia/bench/RegionBench.cpp188
-rw-r--r--chromium/third_party/skia/bench/RegionContainBench.cpp67
-rw-r--r--chromium/third_party/skia/bench/RepeatTileBench.cpp146
-rw-r--r--chromium/third_party/skia/bench/ResultsWriter.cpp30
-rw-r--r--chromium/third_party/skia/bench/ResultsWriter.h198
-rw-r--r--chromium/third_party/skia/bench/ScalarBench.cpp168
-rw-r--r--chromium/third_party/skia/bench/ShaderMaskBench.cpp98
-rw-r--r--chromium/third_party/skia/bench/SkipZeroesBench.cpp118
-rw-r--r--chromium/third_party/skia/bench/SortBench.cpp172
-rw-r--r--chromium/third_party/skia/bench/StackBench.cpp179
-rw-r--r--chromium/third_party/skia/bench/StrokeBench.cpp104
-rw-r--r--chromium/third_party/skia/bench/TableBench.cpp72
-rw-r--r--chromium/third_party/skia/bench/TextBench.cpp145
-rw-r--r--chromium/third_party/skia/bench/TileBench.cpp131
-rw-r--r--chromium/third_party/skia/bench/TimerData.cpp224
-rw-r--r--chromium/third_party/skia/bench/TimerData.h86
-rw-r--r--chromium/third_party/skia/bench/VertBench.cpp95
-rw-r--r--chromium/third_party/skia/bench/WritePixelsBench.cpp77
-rw-r--r--chromium/third_party/skia/bench/WriterBench.cpp41
-rw-r--r--chromium/third_party/skia/bench/XfermodeBench.cpp127
-rwxr-xr-xchromium/third_party/skia/bench/bench_compare.py193
-rw-r--r--chromium/third_party/skia/bench/bench_util.py356
-rw-r--r--chromium/third_party/skia/bench/benchmain.cpp686
-rw-r--r--chromium/third_party/skia/bench/check_bench_regressions.py244
-rw-r--r--chromium/third_party/skia/bench/gUniqueGlyphIDs.h468
-rw-r--r--chromium/third_party/skia/bench/gen_bench_expectations.py223
-rwxr-xr-xchromium/third_party/skia/bench/tile_analyze.py279
108 files changed, 17849 insertions, 0 deletions
diff --git a/chromium/third_party/skia/bench/AAClipBench.cpp b/chromium/third_party/skia/bench/AAClipBench.cpp
new file mode 100644
index 00000000000..4cc9abe9fc9
--- /dev/null
+++ b/chromium/third_party/skia/bench/AAClipBench.cpp
@@ -0,0 +1,257 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkAAClip.h"
+#include "SkCanvas.h"
+#include "SkPath.h"
+#include "SkRandom.h"
+#include "SkRegion.h"
+#include "SkString.h"
+
+////////////////////////////////////////////////////////////////////////////////
+// This bench tests out AA/BW clipping via canvas' clipPath and clipRect calls
+class AAClipBench : public Benchmark {
+ SkString fName;
+ SkPath fClipPath;
+ SkRect fClipRect;
+ SkRect fDrawRect;
+ bool fDoPath;
+ bool fDoAA;
+
+public:
+ AAClipBench(bool doPath, bool doAA)
+ : fDoPath(doPath)
+ , fDoAA(doAA) {
+
+ fName.printf("aaclip_%s_%s",
+ doPath ? "path" : "rect",
+ doAA ? "AA" : "BW");
+
+ fClipRect.set(10.5f, 10.5f,
+ 50.5f, 50.5f);
+ fClipPath.addRoundRect(fClipRect, SkIntToScalar(10), SkIntToScalar(10));
+ fDrawRect.set(SkIntToScalar(0), SkIntToScalar(0),
+ SkIntToScalar(100), SkIntToScalar(100));
+
+ SkASSERT(fClipPath.isConvex());
+ }
+
+protected:
+ virtual const char* onGetName() { return fName.c_str(); }
+ virtual void onDraw(const int loops, SkCanvas* canvas) {
+
+ SkPaint paint;
+ this->setupPaint(&paint);
+
+ for (int i = 0; i < loops; ++i) {
+ // jostle the clip regions each time to prevent caching
+ fClipRect.offset((i % 2) == 0 ? SkIntToScalar(10) : SkIntToScalar(-10), 0);
+ fClipPath.reset();
+ fClipPath.addRoundRect(fClipRect,
+ SkIntToScalar(5), SkIntToScalar(5));
+ SkASSERT(fClipPath.isConvex());
+
+ canvas->save();
+#if 1
+ if (fDoPath) {
+ canvas->clipPath(fClipPath, SkRegion::kReplace_Op, fDoAA);
+ } else {
+ canvas->clipRect(fClipRect, SkRegion::kReplace_Op, fDoAA);
+ }
+
+ canvas->drawRect(fDrawRect, paint);
+#else
+ // this path tests out directly draw the clip primitive
+ // use it to comparing just drawing the clip vs. drawing using
+ // the clip
+ if (fDoPath) {
+ canvas->drawPath(fClipPath, paint);
+ } else {
+ canvas->drawRect(fClipRect, paint);
+ }
+#endif
+ canvas->restore();
+ }
+ }
+private:
+ typedef Benchmark INHERITED;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// This bench tests out nested clip stacks. It is intended to simulate
+// how WebKit nests clips.
+class NestedAAClipBench : public Benchmark {
+ SkString fName;
+ bool fDoAA;
+ SkRect fDrawRect;
+ SkRandom fRandom;
+
+ static const int kNestingDepth = 3;
+ static const int kImageSize = 400;
+
+ SkPoint fSizes[kNestingDepth+1];
+
+public:
+ NestedAAClipBench(bool doAA) : fDoAA(doAA) {
+ fName.printf("nested_aaclip_%s", doAA ? "AA" : "BW");
+
+ fDrawRect = SkRect::MakeLTRB(0, 0,
+ SkIntToScalar(kImageSize),
+ SkIntToScalar(kImageSize));
+
+ fSizes[0].set(SkIntToScalar(kImageSize), SkIntToScalar(kImageSize));
+
+ for (int i = 1; i < kNestingDepth+1; ++i) {
+ fSizes[i].set(fSizes[i-1].fX/2, fSizes[i-1].fY/2);
+ }
+ }
+
+protected:
+ virtual const char* onGetName() { return fName.c_str(); }
+
+
+ void recurse(SkCanvas* canvas,
+ int depth,
+ const SkPoint& offset) {
+
+ canvas->save();
+
+ SkRect temp = SkRect::MakeLTRB(0, 0,
+ fSizes[depth].fX, fSizes[depth].fY);
+ temp.offset(offset);
+
+ SkPath path;
+ path.addRoundRect(temp, SkIntToScalar(3), SkIntToScalar(3));
+ SkASSERT(path.isConvex());
+
+ canvas->clipPath(path,
+ 0 == depth ? SkRegion::kReplace_Op :
+ SkRegion::kIntersect_Op,
+ fDoAA);
+
+ if (kNestingDepth == depth) {
+ // we only draw the draw rect at the lowest nesting level
+ SkPaint paint;
+ paint.setColor(0xff000000 | fRandom.nextU());
+ canvas->drawRect(fDrawRect, paint);
+ } else {
+ SkPoint childOffset = offset;
+ this->recurse(canvas, depth+1, childOffset);
+
+ childOffset += fSizes[depth+1];
+ this->recurse(canvas, depth+1, childOffset);
+
+ childOffset.fX = offset.fX + fSizes[depth+1].fX;
+ childOffset.fY = offset.fY;
+ this->recurse(canvas, depth+1, childOffset);
+
+ childOffset.fX = offset.fX;
+ childOffset.fY = offset.fY + fSizes[depth+1].fY;
+ this->recurse(canvas, depth+1, childOffset);
+ }
+
+ canvas->restore();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) {
+
+ for (int i = 0; i < loops; ++i) {
+ SkPoint offset = SkPoint::Make(0, 0);
+ this->recurse(canvas, 0, offset);
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+class AAClipBuilderBench : public Benchmark {
+ SkString fName;
+ SkPath fPath;
+ SkRect fRect;
+ SkRegion fRegion;
+ bool fDoPath;
+ bool fDoAA;
+
+public:
+ AAClipBuilderBench(bool doPath, bool doAA) {
+ fDoPath = doPath;
+ fDoAA = doAA;
+
+ fName.printf("aaclip_build_%s_%s", doPath ? "path" : "rect",
+ doAA ? "AA" : "BW");
+
+ fRegion.setRect(0, 0, 640, 480);
+ fRect.set(fRegion.getBounds());
+ fRect.inset(SK_Scalar1/4, SK_Scalar1/4);
+ fPath.addRoundRect(fRect, SkIntToScalar(20), SkIntToScalar(20));
+ }
+
+protected:
+ virtual const char* onGetName() { return fName.c_str(); }
+ virtual void onDraw(const int loops, SkCanvas*) {
+ SkPaint paint;
+ this->setupPaint(&paint);
+
+ for (int i = 0; i < loops; ++i) {
+ SkAAClip clip;
+ if (fDoPath) {
+ clip.setPath(fPath, &fRegion, fDoAA);
+ } else {
+ clip.setRect(fRect, fDoAA);
+ }
+ }
+ }
+private:
+ typedef Benchmark INHERITED;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+class AAClipRegionBench : public Benchmark {
+public:
+ AAClipRegionBench() {
+ SkPath path;
+ // test conversion of a complex clip to a aaclip
+ path.addCircle(0, 0, SkIntToScalar(200));
+ path.addCircle(0, 0, SkIntToScalar(180));
+ // evenodd means we've constructed basically a stroked circle
+ path.setFillType(SkPath::kEvenOdd_FillType);
+
+ SkIRect bounds;
+ path.getBounds().roundOut(&bounds);
+ fRegion.setPath(path, SkRegion(bounds));
+ }
+
+protected:
+ virtual const char* onGetName() { return "aaclip_setregion"; }
+ virtual void onDraw(const int loops, SkCanvas*) {
+ for (int i = 0; i < loops; ++i) {
+ SkAAClip clip;
+ clip.setRegion(fRegion);
+ }
+ }
+
+private:
+ SkRegion fRegion;
+ typedef Benchmark INHERITED;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH( return SkNEW_ARGS(AAClipBuilderBench, (false, false)); )
+DEF_BENCH( return SkNEW_ARGS(AAClipBuilderBench, (false, true)); )
+DEF_BENCH( return SkNEW_ARGS(AAClipBuilderBench, (true, false)); )
+DEF_BENCH( return SkNEW_ARGS(AAClipBuilderBench, (true, true)); )
+DEF_BENCH( return SkNEW_ARGS(AAClipRegionBench, ()); )
+DEF_BENCH( return SkNEW_ARGS(AAClipBench, (false, false)); )
+DEF_BENCH( return SkNEW_ARGS(AAClipBench, (false, true)); )
+DEF_BENCH( return SkNEW_ARGS(AAClipBench, (true, false)); )
+DEF_BENCH( return SkNEW_ARGS(AAClipBench, (true, true)); )
+DEF_BENCH( return SkNEW_ARGS(NestedAAClipBench, (false)); )
+DEF_BENCH( return SkNEW_ARGS(NestedAAClipBench, (true)); )
diff --git a/chromium/third_party/skia/bench/BenchGpuTimer_gl.cpp b/chromium/third_party/skia/bench/BenchGpuTimer_gl.cpp
new file mode 100644
index 00000000000..349fc1529de
--- /dev/null
+++ b/chromium/third_party/skia/bench/BenchGpuTimer_gl.cpp
@@ -0,0 +1,74 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "BenchGpuTimer_gl.h"
+#include "gl/SkGLContextHelper.h"
+#include "gl/GrGLUtil.h"
+
+BenchGpuTimer::BenchGpuTimer(const SkGLContextHelper* glctx) {
+ fContext = glctx;
+ glctx->ref();
+ glctx->makeCurrent();
+ fStarted = false;
+ fSupported = GrGLGetVersion(glctx->gl()) > GR_GL_VER(3,3) ||
+ glctx->hasExtension("GL_ARB_timer_query") ||
+ glctx->hasExtension("GL_EXT_timer_query");
+
+ if (fSupported) {
+ SK_GL(*glctx, GenQueries(1, &fQuery));
+ }
+}
+
+BenchGpuTimer::~BenchGpuTimer() {
+ if (fSupported) {
+ fContext->makeCurrent();
+ SK_GL(*fContext, DeleteQueries(1, &fQuery));
+ }
+ fContext->unref();
+}
+
+void BenchGpuTimer::startGpu() {
+ if (fSupported) {
+ fContext->makeCurrent();
+ fStarted = true;
+ SK_GL(*fContext, BeginQuery(GR_GL_TIME_ELAPSED, fQuery));
+ }
+}
+
+/**
+ * It is important to stop the cpu clocks first,
+ * as this will cpu wait for the gpu to finish.
+ */
+double BenchGpuTimer::endGpu() {
+ if (fSupported) {
+ fStarted = false;
+ fContext->makeCurrent();
+ SK_GL(*fContext, EndQuery(GR_GL_TIME_ELAPSED));
+
+ GrGLint available = 0;
+ while (!available) {
+ SK_GL_NOERRCHECK(*fContext, GetQueryObjectiv(fQuery,
+ GR_GL_QUERY_RESULT_AVAILABLE,
+ &available));
+ // If GetQueryObjectiv is erroring out we need some alternative
+ // means of breaking out of this loop
+ GrGLenum error;
+ SK_GL_RET_NOERRCHECK(*fContext, error, GetError());
+ if (GR_GL_NO_ERROR != error) {
+ break;
+ }
+ }
+ GrGLuint64 totalGPUTimeElapsed = 0;
+ SK_GL(*fContext, GetQueryObjectui64v(fQuery,
+ GR_GL_QUERY_RESULT,
+ &totalGPUTimeElapsed));
+
+ return totalGPUTimeElapsed / 1000000.0;
+ } else {
+ return 0;
+ }
+}
diff --git a/chromium/third_party/skia/bench/BenchGpuTimer_gl.h b/chromium/third_party/skia/bench/BenchGpuTimer_gl.h
new file mode 100644
index 00000000000..e472a4c5144
--- /dev/null
+++ b/chromium/third_party/skia/bench/BenchGpuTimer_gl.h
@@ -0,0 +1,26 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SkBenchGpuTimer_DEFINED
+#define SkBenchGpuTimer_DEFINED
+
+class SkGLContextHelper;
+
+class BenchGpuTimer {
+public:
+ BenchGpuTimer(const SkGLContextHelper* glctx);
+ ~BenchGpuTimer();
+ void startGpu();
+ double endGpu();
+private:
+ unsigned fQuery;
+ int fStarted;
+ const SkGLContextHelper* fContext;
+ bool fSupported;
+};
+
+#endif
diff --git a/chromium/third_party/skia/bench/BenchLogger.cpp b/chromium/third_party/skia/bench/BenchLogger.cpp
new file mode 100644
index 00000000000..98423d01507
--- /dev/null
+++ b/chromium/third_party/skia/bench/BenchLogger.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "BenchLogger.h"
+
+#include "SkStream.h"
+
+BenchLogger::BenchLogger()
+: fFileStream(NULL) {}
+
+BenchLogger::~BenchLogger() {
+ if (fFileStream) {
+ SkDELETE(fFileStream);
+ }
+}
+
+bool BenchLogger::SetLogFile(const char *file) {
+ fFileStream = SkNEW_ARGS(SkFILEWStream, (file));
+ return fFileStream->isValid();
+}
+
+void BenchLogger::fileWrite(const char msg[], size_t size) {
+ if (fFileStream && fFileStream->isValid()) {
+ fFileStream->write(msg, size);
+ }
+}
diff --git a/chromium/third_party/skia/bench/BenchLogger.h b/chromium/third_party/skia/bench/BenchLogger.h
new file mode 100644
index 00000000000..a7c283ad505
--- /dev/null
+++ b/chromium/third_party/skia/bench/BenchLogger.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef BenchLogger_DEFINED
+#define BenchLogger_DEFINED
+
+#include <stdio.h>
+#include "SkString.h"
+#include "SkTypes.h"
+
+class SkFILEWStream;
+
+/**
+ * Class that allows logging to a file while simultaneously logging to stdout/stderr.
+ */
+class BenchLogger {
+public:
+ BenchLogger();
+
+ /**
+ * Not virtual, since this class is not intended to be subclassed.
+ */
+ ~BenchLogger();
+
+ /**
+ * Specify a file to write progress logs to. Unless this is called with a valid file path,
+ * BenchLogger will only write to stdout/stderr.
+ */
+ bool SetLogFile(const char file[]);
+
+ /**
+ * Log an error to stderr, taking a C style string as input.
+ */
+ void logError(const char msg[]) { this->nativeLogError(msg); }
+
+ /**
+ * Log an error to stderr, taking an SkString as input.
+ */
+ void logError(const SkString& str) { this->nativeLogError(str.c_str()); }
+
+ /**
+ * Log the progress of the bench tool to both stdout and the log file specified by SetLogFile,
+ * if any, taking a C style string as input.
+ */
+ void logProgress(const char msg[]) {
+ this->nativeLogProgress(msg);
+ this->fileWrite(msg, strlen(msg));
+ }
+
+ /**
+ * Log the progress of the bench tool to both stdout and the log file specified by SetLogFile,
+ * if any, taking an SkString as input.
+ */
+ void logProgress(const SkString& str) {
+ this->nativeLogProgress(str.c_str());
+ this->fileWrite(str.c_str(), str.size());
+ }
+
+private:
+#ifdef SK_BUILD_FOR_ANDROID
+ void nativeLogError(const char msg[]) { SkDebugf("%s", msg); }
+#else
+ void nativeLogError(const char msg[]) { fprintf(stderr, "%s", msg); }
+#endif
+ void nativeLogProgress(const char msg[]) { SkDebugf("%s", msg); }
+
+ void fileWrite(const char msg[], size_t size);
+
+ SkFILEWStream* fFileStream;
+};
+
+#endif // BenchLogger_DEFINED
diff --git a/chromium/third_party/skia/bench/BenchSysTimer_c.cpp b/chromium/third_party/skia/bench/BenchSysTimer_c.cpp
new file mode 100644
index 00000000000..f4cbd39d737
--- /dev/null
+++ b/chromium/third_party/skia/bench/BenchSysTimer_c.cpp
@@ -0,0 +1,27 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "BenchSysTimer_c.h"
+
+//Time
+#include <time.h>
+
+void BenchSysTimer::startWall() {
+ this->fStartWall = time();
+}
+void BenchSysTimer::startCpu() {
+ this->fStartCpu = clock();
+}
+
+double BenchSysTimer::endCpu() {
+ clock_t end_cpu = clock();
+ this->fCpu = (end_cpu - this->fStartCpu) * CLOCKS_PER_SEC / 1000.0;
+}
+double BenchSysTimer::endWall() {
+ time_t end_wall = time();
+ this->fWall = difftime(end_wall, this->fstartWall) / 1000.0;
+}
diff --git a/chromium/third_party/skia/bench/BenchSysTimer_c.h b/chromium/third_party/skia/bench/BenchSysTimer_c.h
new file mode 100644
index 00000000000..586f0b4ff09
--- /dev/null
+++ b/chromium/third_party/skia/bench/BenchSysTimer_c.h
@@ -0,0 +1,26 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SkBenchSysTimer_DEFINED
+#define SkBenchSysTimer_DEFINED
+
+//Time
+#include <time.h>
+
+// Beware: this timer uses standard (as opposed to high precision) clocks
+class BenchSysTimer {
+public:
+ void startWall();
+ void startCpu();
+ double endCpu();
+ double endWall();
+private:
+ clock_t start_cpu;
+ time_t fStartWall;
+};
+
+#endif
diff --git a/chromium/third_party/skia/bench/BenchSysTimer_mach.cpp b/chromium/third_party/skia/bench/BenchSysTimer_mach.cpp
new file mode 100644
index 00000000000..1f0a6b98615
--- /dev/null
+++ b/chromium/third_party/skia/bench/BenchSysTimer_mach.cpp
@@ -0,0 +1,76 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "BenchSysTimer_mach.h"
+
+//Time
+#include <mach/mach.h>
+#include <mach/mach_time.h>
+
+static time_value_t macCpuTime() {
+ mach_port_t task = mach_task_self();
+ if (task == MACH_PORT_NULL) {
+ time_value_t none = {0, 0};
+ return none;
+ }
+
+ task_thread_times_info thread_info_data;
+ mach_msg_type_number_t thread_info_count = TASK_THREAD_TIMES_INFO_COUNT;
+ if (KERN_SUCCESS != task_info(task,
+ TASK_THREAD_TIMES_INFO,
+ reinterpret_cast<task_info_t>(&thread_info_data),
+ &thread_info_count))
+ {
+ time_value_t none = {0, 0};
+ return none;
+ }
+
+ time_value_add(&thread_info_data.user_time, &thread_info_data.system_time)
+ return thread_info_data.user_time;
+}
+
+static double intervalInMSec(const time_value_t start_clock
+ , const time_value_t end_clock)
+{
+ double duration_clock;
+ if ((end_clock.microseconds - start_clock.microseconds) < 0) {
+ duration_clock = (end_clock.seconds - start_clock.seconds-1)*1000;
+ duration_clock += (1000000
+ + end_clock.microseconds
+ - start_clock.microseconds) / 1000.0;
+ } else {
+ duration_clock = (end_clock.seconds - start_clock.seconds)*1000;
+ duration_clock += (end_clock.microseconds - start_clock.microseconds)
+ / 1000.0;
+ }
+ return duration_clock;
+}
+
+void BenchSysTimer::startWall() {
+ this->fStartWall = mach_absolute_time();
+}
+void BenchSysTimer::startCpu() {
+ this->fStartCpu = macCpuTime();
+}
+
+double BenchSysTimer::endCpu() {
+ time_value_t end_cpu = macCpuTime();
+ return intervalInMSec(this->fStartCpu, end_cpu);
+}
+double BenchSysTimer::endWall() {
+ uint64_t end_wall = mach_absolute_time();
+
+ uint64_t elapsed = end_wall - this->fStartWall;
+ mach_timebase_info_data_t sTimebaseInfo;
+ if (KERN_SUCCESS != mach_timebase_info(&sTimebaseInfo)) {
+ return 0;
+ } else {
+ uint64_t elapsedNano = elapsed * sTimebaseInfo.numer
+ / sTimebaseInfo.denom;
+ return elapsedNano / 1000000.0;
+ }
+}
diff --git a/chromium/third_party/skia/bench/BenchSysTimer_mach.h b/chromium/third_party/skia/bench/BenchSysTimer_mach.h
new file mode 100644
index 00000000000..44d0e5eb49a
--- /dev/null
+++ b/chromium/third_party/skia/bench/BenchSysTimer_mach.h
@@ -0,0 +1,26 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SkBenchSysTimer_DEFINED
+#define SkBenchSysTimer_DEFINED
+
+//Time
+#include <mach/mach.h>
+#include <mach/mach_time.h>
+
+class BenchSysTimer {
+public:
+ void startWall();
+ void startCpu();
+ double endCpu();
+ double endWall();
+private:
+ time_value_t fStartCpu;
+ uint64_t fStartWall;
+};
+
+#endif
diff --git a/chromium/third_party/skia/bench/BenchSysTimer_posix.cpp b/chromium/third_party/skia/bench/BenchSysTimer_posix.cpp
new file mode 100644
index 00000000000..e6767e5af22
--- /dev/null
+++ b/chromium/third_party/skia/bench/BenchSysTimer_posix.cpp
@@ -0,0 +1,57 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "BenchSysTimer_posix.h"
+
+//Time
+#include <time.h>
+
+static double intervalInMSec(const timespec start_clock
+ , const timespec end_clock)
+{
+ double duration_clock;
+ if ((end_clock.tv_nsec - start_clock.tv_nsec) < 0) {
+ duration_clock = (end_clock.tv_sec - start_clock.tv_sec-1)*1000;
+ duration_clock += (1000000000 + end_clock.tv_nsec - start_clock.tv_nsec)
+ / 1000000.0;
+ } else {
+ duration_clock = (end_clock.tv_sec - start_clock.tv_sec)*1000;
+ duration_clock += (end_clock.tv_nsec - start_clock.tv_nsec) / 1000000.0;
+ }
+ return duration_clock;
+}
+
+void BenchSysTimer::startWall() {
+ if (-1 == clock_gettime(CLOCK_MONOTONIC, &this->fWall)) {
+ timespec none = {0, 0};
+ this->fWall = none;
+ }
+}
+void BenchSysTimer::startCpu() {
+ if (-1 == clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &this->fCpu)) {
+ timespec none = {0, 0};
+ this->fCpu = none;
+ }
+}
+
+double BenchSysTimer::endCpu() {
+ timespec end_cpu;
+ if (-1 == clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end_cpu)) {
+ timespec none = {0, 0};
+ end_cpu = none;
+ }
+ return intervalInMSec(this->fCpu, end_cpu);
+}
+
+double BenchSysTimer::endWall() {
+ timespec end_wall;
+ if (-1 == clock_gettime(CLOCK_MONOTONIC, &end_wall)) {
+ timespec none = {0, 0};
+ end_wall = none;
+ }
+ return intervalInMSec(this->fWall, end_wall);
+}
diff --git a/chromium/third_party/skia/bench/BenchSysTimer_posix.h b/chromium/third_party/skia/bench/BenchSysTimer_posix.h
new file mode 100644
index 00000000000..8fd97061b6c
--- /dev/null
+++ b/chromium/third_party/skia/bench/BenchSysTimer_posix.h
@@ -0,0 +1,25 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SkBenchSysTimer_DEFINED
+#define SkBenchSysTimer_DEFINED
+
+//Time
+#include <time.h>
+
+class BenchSysTimer {
+public:
+ void startWall();
+ void startCpu();
+ double endCpu();
+ double endWall();
+private:
+ timespec fCpu;
+ timespec fWall;
+};
+
+#endif
diff --git a/chromium/third_party/skia/bench/BenchSysTimer_windows.cpp b/chromium/third_party/skia/bench/BenchSysTimer_windows.cpp
new file mode 100644
index 00000000000..fab657a8c36
--- /dev/null
+++ b/chromium/third_party/skia/bench/BenchSysTimer_windows.cpp
@@ -0,0 +1,64 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "BenchSysTimer_windows.h"
+
+//Time
+#define WIN32_LEAN_AND_MEAN 1
+#include <windows.h>
+
+static ULONGLONG winCpuTime() {
+ FILETIME createTime;
+ FILETIME exitTime;
+ FILETIME usrTime;
+ FILETIME sysTime;
+ if (0 == GetProcessTimes(GetCurrentProcess()
+ , &createTime, &exitTime
+ , &sysTime, &usrTime))
+ {
+ return 0;
+ }
+ ULARGE_INTEGER start_cpu_sys;
+ ULARGE_INTEGER start_cpu_usr;
+ start_cpu_sys.LowPart = sysTime.dwLowDateTime;
+ start_cpu_sys.HighPart = sysTime.dwHighDateTime;
+ start_cpu_usr.LowPart = usrTime.dwLowDateTime;
+ start_cpu_usr.HighPart = usrTime.dwHighDateTime;
+ return start_cpu_sys.QuadPart + start_cpu_usr.QuadPart;
+}
+
+void BenchSysTimer::startWall() {
+ if (0 == ::QueryPerformanceCounter(&this->fStartWall)) {
+ this->fStartWall.QuadPart = 0;
+ }
+}
+void BenchSysTimer::startCpu() {
+ this->fStartCpu = winCpuTime();
+}
+
+double BenchSysTimer::endCpu() {
+ ULONGLONG end_cpu = winCpuTime();
+ return static_cast<double>((end_cpu - this->fStartCpu)) / 10000.0L;
+}
+double BenchSysTimer::endWall() {
+ LARGE_INTEGER end_wall;
+ if (0 == ::QueryPerformanceCounter(&end_wall)) {
+ end_wall.QuadPart = 0;
+ }
+
+ LARGE_INTEGER ticks_elapsed;
+ ticks_elapsed.QuadPart = end_wall.QuadPart - this->fStartWall.QuadPart;
+
+ LARGE_INTEGER frequency;
+ if (0 == ::QueryPerformanceFrequency(&frequency)) {
+ return 0.0L;
+ } else {
+ return static_cast<double>(ticks_elapsed.QuadPart)
+ / static_cast<double>(frequency.QuadPart)
+ * 1000.0L;
+ }
+}
diff --git a/chromium/third_party/skia/bench/BenchSysTimer_windows.h b/chromium/third_party/skia/bench/BenchSysTimer_windows.h
new file mode 100644
index 00000000000..469332e4ed0
--- /dev/null
+++ b/chromium/third_party/skia/bench/BenchSysTimer_windows.h
@@ -0,0 +1,26 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SkBenchSysTimer_DEFINED
+#define SkBenchSysTimer_DEFINED
+
+//Time
+#define WIN32_LEAN_AND_MEAN 1
+#include <windows.h>
+
+class BenchSysTimer {
+public:
+ void startWall();
+ void startCpu();
+ double endCpu();
+ double endWall();
+private:
+ ULONGLONG fStartCpu;
+ LARGE_INTEGER fStartWall;
+};
+
+#endif
diff --git a/chromium/third_party/skia/bench/BenchTimer.cpp b/chromium/third_party/skia/bench/BenchTimer.cpp
new file mode 100644
index 00000000000..f3e8e3b0ec6
--- /dev/null
+++ b/chromium/third_party/skia/bench/BenchTimer.cpp
@@ -0,0 +1,94 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "BenchTimer.h"
+#if defined(SK_BUILD_FOR_WIN32)
+ #include "BenchSysTimer_windows.h"
+#elif defined(SK_BUILD_FOR_MAC)
+ #include "BenchSysTimer_mach.h"
+#elif defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_ANDROID)
+ #include "BenchSysTimer_posix.h"
+#else
+ #include "BenchSysTimer_c.h"
+#endif
+
+#if SK_SUPPORT_GPU
+#include "BenchGpuTimer_gl.h"
+#endif
+
+BenchTimer::BenchTimer(SkGLContextHelper* gl)
+ : fCpu(-1.0)
+ , fWall(-1.0)
+ , fTruncatedCpu(-1.0)
+ , fTruncatedWall(-1.0)
+ , fGpu(-1.0)
+{
+ fSysTimer = new BenchSysTimer();
+ fTruncatedSysTimer = new BenchSysTimer();
+#if SK_SUPPORT_GPU
+ if (gl) {
+ fGpuTimer = new BenchGpuTimer(gl);
+ } else {
+ fGpuTimer = NULL;
+ }
+#endif
+}
+
+BenchTimer::~BenchTimer() {
+ delete fSysTimer;
+ delete fTruncatedSysTimer;
+#if SK_SUPPORT_GPU
+ delete fGpuTimer;
+#endif
+}
+
+void BenchTimer::start(double durationScale) {
+ fDurationScale = durationScale;
+
+ fSysTimer->startWall();
+ fTruncatedSysTimer->startWall();
+#if SK_SUPPORT_GPU
+ if (fGpuTimer) {
+ fGpuTimer->startGpu();
+ }
+#endif
+ fSysTimer->startCpu();
+ fTruncatedSysTimer->startCpu();
+}
+
+void BenchTimer::end() {
+ fCpu = fSysTimer->endCpu() * fDurationScale;
+#if SK_SUPPORT_GPU
+ //It is important to stop the cpu clocks first,
+ //as the following will cpu wait for the gpu to finish.
+ if (fGpuTimer) {
+ fGpu = fGpuTimer->endGpu() * fDurationScale;
+ }
+#endif
+ fWall = fSysTimer->endWall() * fDurationScale;
+}
+
+void BenchTimer::truncatedEnd() {
+ fTruncatedCpu = fTruncatedSysTimer->endCpu() * fDurationScale;
+ fTruncatedWall = fTruncatedSysTimer->endWall() * fDurationScale;
+}
+
+WallTimer::WallTimer() : fWall(-1.0), fSysTimer(new BenchSysTimer) {}
+
+WallTimer::~WallTimer() {
+ delete fSysTimer;
+}
+
+void WallTimer::start(double durationScale) {
+ fDurationScale = durationScale;
+ fSysTimer->startWall();
+}
+
+void WallTimer::end() {
+ fWall = fSysTimer->endWall() * fDurationScale;
+}
+
diff --git a/chromium/third_party/skia/bench/BenchTimer.h b/chromium/third_party/skia/bench/BenchTimer.h
new file mode 100644
index 00000000000..2abf10b80f9
--- /dev/null
+++ b/chromium/third_party/skia/bench/BenchTimer.h
@@ -0,0 +1,67 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SkBenchTimer_DEFINED
+#define SkBenchTimer_DEFINED
+
+#include <SkTypes.h>
+
+
+class BenchSysTimer;
+class BenchGpuTimer;
+
+class SkGLContextHelper;
+
+/**
+ * SysTimers and GpuTimers are implemented orthogonally.
+ * This class combines 2 SysTimers and a GpuTimer into one single,
+ * platform specific Timer with a simple interface. The truncated
+ * timer doesn't include the time required for the GPU to finish
+ * its rendering. It should always be <= the un-truncated system
+ * times and (for GPU configurations) can be used to roughly (very
+ * roughly) gauge the GPU load/backlog.
+ */
+class BenchTimer {
+public:
+ BenchTimer(SkGLContextHelper* gl = NULL);
+ ~BenchTimer();
+ void start(double durationScale = 1);
+ void end();
+ void truncatedEnd();
+ double fCpu;
+ double fWall;
+ double fTruncatedCpu;
+ double fTruncatedWall;
+ double fGpu;
+
+private:
+ BenchSysTimer* fSysTimer;
+ BenchSysTimer* fTruncatedSysTimer;
+#if SK_SUPPORT_GPU
+ BenchGpuTimer* fGpuTimer;
+#endif
+ double fDurationScale; // for this start/end session
+};
+
+// Same as BenchTimer above, supporting only fWall but with much lower overhead.
+// (Typically, ~30ns instead of BenchTimer's ~1us.)
+class WallTimer {
+public:
+ WallTimer();
+ ~WallTimer();
+
+ void start(double durationScale = 1);
+ void end();
+
+ double fWall;
+
+private:
+ BenchSysTimer* fSysTimer;
+ double fDurationScale;
+};
+
+#endif
diff --git a/chromium/third_party/skia/bench/BenchTool/BenchTool.xcodeproj/project.pbxproj b/chromium/third_party/skia/bench/BenchTool/BenchTool.xcodeproj/project.pbxproj
new file mode 100644
index 00000000000..4bb4b9cdc49
--- /dev/null
+++ b/chromium/third_party/skia/bench/BenchTool/BenchTool.xcodeproj/project.pbxproj
@@ -0,0 +1,324 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 45;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 272FB43A0F11A19C00CA935D /* RectBench.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 272FB4390F11A19C00CA935D /* RectBench.cpp */; };
+ 272FB4F30F11B40300CA935D /* Benchmark.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 272FB4F20F11B40300CA935D /* Benchmark.cpp */; };
+ 2752A08A0F14CE1300BBDC03 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2752A0890F14CE1300BBDC03 /* main.cpp */; };
+ 27739F4D0F11439200F233EA /* libmaccore.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 27739F240F11404A00F233EA /* libmaccore.a */; };
+ 27739F4E0F11439300F233EA /* libcore.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 27739F1A0F11403B00F233EA /* libcore.a */; };
+ 27739F520F1143C000F233EA /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27739F510F1143C000F233EA /* Carbon.framework */; };
+ 8DD76F6A0486A84900D96B5E /* BenchTool.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6859E8B029090EE04C91782 /* BenchTool.1 */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 27739F190F11403B00F233EA /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 27739F120F11403B00F233EA /* core.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = D2AAC046055464E500DB518D;
+ remoteInfo = core;
+ };
+ 27739F230F11404A00F233EA /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 27739F1C0F11404A00F233EA /* maccore.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = D2AAC046055464E500DB518D;
+ remoteInfo = maccore;
+ };
+ 27739F3C0F11424800F233EA /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 27739F1C0F11404A00F233EA /* maccore.xcodeproj */;
+ proxyType = 1;
+ remoteGlobalIDString = D2AAC045055464E500DB518D;
+ remoteInfo = maccore;
+ };
+ 27739F3E0F11424C00F233EA /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 27739F120F11403B00F233EA /* core.xcodeproj */;
+ proxyType = 1;
+ remoteGlobalIDString = D2AAC045055464E500DB518D;
+ remoteInfo = core;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 8DD76F690486A84900D96B5E /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 8;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ 8DD76F6A0486A84900D96B5E /* BenchTool.1 in CopyFiles */,
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 272FB4390F11A19C00CA935D /* RectBench.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RectBench.cpp; path = ../RectBench.cpp; sourceTree = SOURCE_ROOT; };
+ 272FB4F20F11B40300CA935D /* Benchmark.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Benchmark.cpp; path = ../Benchmark.cpp; sourceTree = SOURCE_ROOT; };
+ 2752A0890F14CE1300BBDC03 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = main.cpp; path = ../main.cpp; sourceTree = SOURCE_ROOT; };
+ 27739F120F11403B00F233EA /* core.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = core.xcodeproj; path = ../../xcode/core/core.xcodeproj; sourceTree = SOURCE_ROOT; };
+ 27739F1C0F11404A00F233EA /* maccore.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = maccore.xcodeproj; path = ../../xcode/maccore/maccore.xcodeproj; sourceTree = SOURCE_ROOT; };
+ 27739F510F1143C000F233EA /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = "<absolute>"; };
+ 8DD76F6C0486A84900D96B5E /* BenchTool */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = BenchTool; sourceTree = BUILT_PRODUCTS_DIR; };
+ C6859E8B029090EE04C91782 /* BenchTool.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = BenchTool.1; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 8DD76F660486A84900D96B5E /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 27739F4D0F11439200F233EA /* libmaccore.a in Frameworks */,
+ 27739F4E0F11439300F233EA /* libcore.a in Frameworks */,
+ 27739F520F1143C000F233EA /* Carbon.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 08FB7794FE84155DC02AAC07 /* BenchTool */ = {
+ isa = PBXGroup;
+ children = (
+ 27739F510F1143C000F233EA /* Carbon.framework */,
+ 27739F1C0F11404A00F233EA /* maccore.xcodeproj */,
+ 27739F120F11403B00F233EA /* core.xcodeproj */,
+ 08FB7795FE84155DC02AAC07 /* Source */,
+ C6859E8C029090F304C91782 /* Documentation */,
+ 1AB674ADFE9D54B511CA2CBB /* Products */,
+ );
+ name = BenchTool;
+ sourceTree = "<group>";
+ };
+ 08FB7795FE84155DC02AAC07 /* Source */ = {
+ isa = PBXGroup;
+ children = (
+ 2752A0890F14CE1300BBDC03 /* main.cpp */,
+ 272FB4F20F11B40300CA935D /* Benchmark.cpp */,
+ 272FB4390F11A19C00CA935D /* RectBench.cpp */,
+ );
+ name = Source;
+ sourceTree = "<group>";
+ };
+ 1AB674ADFE9D54B511CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 8DD76F6C0486A84900D96B5E /* BenchTool */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 27739F130F11403B00F233EA /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 27739F1A0F11403B00F233EA /* libcore.a */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 27739F1D0F11404A00F233EA /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 27739F240F11404A00F233EA /* libmaccore.a */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ C6859E8C029090F304C91782 /* Documentation */ = {
+ isa = PBXGroup;
+ children = (
+ C6859E8B029090EE04C91782 /* BenchTool.1 */,
+ );
+ name = Documentation;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 8DD76F620486A84900D96B5E /* BenchTool */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "BenchTool" */;
+ buildPhases = (
+ 8DD76F640486A84900D96B5E /* Sources */,
+ 8DD76F660486A84900D96B5E /* Frameworks */,
+ 8DD76F690486A84900D96B5E /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 27739F3D0F11424800F233EA /* PBXTargetDependency */,
+ 27739F3F0F11424C00F233EA /* PBXTargetDependency */,
+ );
+ name = BenchTool;
+ productInstallPath = "$(HOME)/bin";
+ productName = BenchTool;
+ productReference = 8DD76F6C0486A84900D96B5E /* BenchTool */;
+ productType = "com.apple.product-type.tool";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 08FB7793FE84155DC02AAC07 /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "BenchTool" */;
+ compatibilityVersion = "Xcode 3.1";
+ hasScannedForEncodings = 1;
+ mainGroup = 08FB7794FE84155DC02AAC07 /* BenchTool */;
+ projectDirPath = "";
+ projectReferences = (
+ {
+ ProductGroup = 27739F130F11403B00F233EA /* Products */;
+ ProjectRef = 27739F120F11403B00F233EA /* core.xcodeproj */;
+ },
+ {
+ ProductGroup = 27739F1D0F11404A00F233EA /* Products */;
+ ProjectRef = 27739F1C0F11404A00F233EA /* maccore.xcodeproj */;
+ },
+ );
+ projectRoot = "";
+ targets = (
+ 8DD76F620486A84900D96B5E /* BenchTool */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXReferenceProxy section */
+ 27739F1A0F11403B00F233EA /* libcore.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libcore.a;
+ remoteRef = 27739F190F11403B00F233EA /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 27739F240F11404A00F233EA /* libmaccore.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libmaccore.a;
+ remoteRef = 27739F230F11404A00F233EA /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+/* End PBXReferenceProxy section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 8DD76F640486A84900D96B5E /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 272FB43A0F11A19C00CA935D /* RectBench.cpp in Sources */,
+ 272FB4F30F11B40300CA935D /* Benchmark.cpp in Sources */,
+ 2752A08A0F14CE1300BBDC03 /* main.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 27739F3D0F11424800F233EA /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ name = maccore;
+ targetProxy = 27739F3C0F11424800F233EA /* PBXContainerItemProxy */;
+ };
+ 27739F3F0F11424C00F233EA /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ name = core;
+ targetProxy = 27739F3E0F11424C00F233EA /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+ 1DEB923208733DC60010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "_GLIBCXX_DEBUG=1",
+ "_GLIBCXX_DEBUG_PEDANTIC=1",
+ );
+ INSTALL_PATH = /usr/local/bin;
+ PRODUCT_NAME = BenchTool;
+ };
+ name = Debug;
+ };
+ 1DEB923308733DC60010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_MODEL_TUNING = G5;
+ INSTALL_PATH = /usr/local/bin;
+ PRODUCT_NAME = BenchTool;
+ };
+ name = Release;
+ };
+ 1DEB923608733DC60010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ GCC_C_LANGUAGE_STANDARD = c99;
+ GCC_ENABLE_CPP_EXCEPTIONS = NO;
+ GCC_ENABLE_CPP_RTTI = NO;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_THREADSAFE_STATICS = NO;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ PREBINDING = NO;
+ SDKROOT = macosx10.5;
+ USER_HEADER_SEARCH_PATHS = ".. ../../include/**";
+ };
+ name = Debug;
+ };
+ 1DEB923708733DC60010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ GCC_C_LANGUAGE_STANDARD = c99;
+ GCC_ENABLE_CPP_EXCEPTIONS = NO;
+ GCC_ENABLE_CPP_RTTI = NO;
+ GCC_THREADSAFE_STATICS = NO;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ PREBINDING = NO;
+ SDKROOT = macosx10.5;
+ USER_HEADER_SEARCH_PATHS = ".. ../../include/**";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "BenchTool" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB923208733DC60010E9CD /* Debug */,
+ 1DEB923308733DC60010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "BenchTool" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB923608733DC60010E9CD /* Debug */,
+ 1DEB923708733DC60010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
+}
diff --git a/chromium/third_party/skia/bench/Benchmark.cpp b/chromium/third_party/skia/bench/Benchmark.cpp
new file mode 100644
index 00000000000..ae614f04f9c
--- /dev/null
+++ b/chromium/third_party/skia/bench/Benchmark.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+
+#include "SkPaint.h"
+#include "SkParse.h"
+
+const char* SkTriState::Name[] = { "default", "true", "false" };
+
+template BenchRegistry* BenchRegistry::gHead;
+
+Benchmark::Benchmark() {
+ fForceAlpha = 0xFF;
+ fForceAA = true;
+ fForceFilter = false;
+ fDither = SkTriState::kDefault;
+ fOrMask = fClearMask = 0;
+}
+
+const char* Benchmark::getName() {
+ return this->onGetName();
+}
+
+SkIPoint Benchmark::getSize() {
+ return this->onGetSize();
+}
+
+void Benchmark::preDraw() {
+ this->onPreDraw();
+}
+
+void Benchmark::draw(const int loops, SkCanvas* canvas) {
+ this->onDraw(loops, canvas);
+}
+
+void Benchmark::setupPaint(SkPaint* paint) {
+ paint->setAlpha(fForceAlpha);
+ paint->setAntiAlias(fForceAA);
+ paint->setFilterLevel(fForceFilter ? SkPaint::kLow_FilterLevel
+ : SkPaint::kNone_FilterLevel);
+
+ paint->setFlags((paint->getFlags() & ~fClearMask) | fOrMask);
+
+ if (SkTriState::kDefault != fDither) {
+ paint->setDither(SkTriState::kTrue == fDither);
+ }
+}
+
+SkIPoint Benchmark::onGetSize() {
+ return SkIPoint::Make(640, 480);
+}
diff --git a/chromium/third_party/skia/bench/Benchmark.h b/chromium/third_party/skia/bench/Benchmark.h
new file mode 100644
index 00000000000..db70bbe49ca
--- /dev/null
+++ b/chromium/third_party/skia/bench/Benchmark.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef Benchmark_DEFINED
+#define Benchmark_DEFINED
+
+#include "SkPoint.h"
+#include "SkRefCnt.h"
+#include "SkString.h"
+#include "SkTRegistry.h"
+
+#define DEF_BENCH(code) \
+namespace { \
+static Benchmark* SK_MACRO_APPEND_LINE(factory)(void*) { code; } \
+BenchRegistry SK_MACRO_APPEND_LINE(g_R_)(SK_MACRO_APPEND_LINE(factory)); \
+}
+
+/*
+ * With the above macros, you can register benches as follows (at the bottom
+ * of your .cpp)
+ *
+ * DEF_BENCH(return new MyBenchmark(...))
+ * DEF_BENCH(return new MyBenchmark(...))
+ * DEF_BENCH(return new MyBenchmark(...))
+ */
+
+
+class SkCanvas;
+class SkPaint;
+
+class SkTriState {
+public:
+ enum State {
+ kDefault,
+ kTrue,
+ kFalse
+ };
+ static const char* Name[];
+};
+
+class Benchmark : public SkRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(Benchmark)
+
+ Benchmark();
+
+ const char* getName();
+ SkIPoint getSize();
+
+ enum Backend {
+ kNonRendering_Backend,
+ kRaster_Backend,
+ kGPU_Backend,
+ kPDF_Backend,
+ };
+
+ // Call to determine whether the benchmark is intended for
+ // the rendering mode.
+ virtual bool isSuitableFor(Backend backend) {
+ return backend != kNonRendering_Backend;
+ }
+
+ // Call before draw, allows the benchmark to do setup work outside of the
+ // timer. When a benchmark is repeatedly drawn, this should be called once
+ // before the initial draw.
+ void preDraw();
+
+ // Bench framework can tune loops to be large enough for stable timing.
+ void draw(const int loops, SkCanvas*);
+
+ void setForceAlpha(int alpha) {
+ fForceAlpha = alpha;
+ }
+
+ void setForceAA(bool aa) {
+ fForceAA = aa;
+ }
+
+ void setForceFilter(bool filter) {
+ fForceFilter = filter;
+ }
+
+ void setDither(SkTriState::State state) {
+ fDither = state;
+ }
+
+ /** Assign masks for paint-flags. These will be applied when setupPaint()
+ * is called.
+ *
+ * Performs the following on the paint:
+ * uint32_t flags = paint.getFlags();
+ * flags &= ~clearMask;
+ * flags |= orMask;
+ * paint.setFlags(flags);
+ */
+ void setPaintMasks(uint32_t orMask, uint32_t clearMask) {
+ fOrMask = orMask;
+ fClearMask = clearMask;
+ }
+
+protected:
+ virtual void setupPaint(SkPaint* paint);
+
+ virtual const char* onGetName() = 0;
+ virtual void onPreDraw() {}
+ // Each bench should do its main work in a loop like this:
+ // for (int i = 0; i < loops; i++) { <work here> }
+ virtual void onDraw(const int loops, SkCanvas*) = 0;
+
+ virtual SkIPoint onGetSize();
+
+private:
+ int fForceAlpha;
+ bool fForceAA;
+ bool fForceFilter;
+ SkTriState::State fDither;
+ uint32_t fOrMask, fClearMask;
+
+ typedef SkRefCnt INHERITED;
+};
+
+typedef SkTRegistry<Benchmark*(*)(void*)> BenchRegistry;
+
+#endif
diff --git a/chromium/third_party/skia/bench/BicubicBench.cpp b/chromium/third_party/skia/bench/BicubicBench.cpp
new file mode 100644
index 00000000000..9d03dd15740
--- /dev/null
+++ b/chromium/third_party/skia/bench/BicubicBench.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkBicubicImageFilter.h"
+#include "SkCanvas.h"
+#include "SkShader.h"
+#include "SkString.h"
+
+// This bench exercises SkBicubicImageFilter, upsampling a 40x40 input to
+// 100x100, 400x100, 100x400, and 400x400.
+
+class BicubicBench : public Benchmark {
+ SkSize fScale;
+ SkString fName;
+
+public:
+ BicubicBench(float x, float y)
+ : fScale(SkSize::Make(x, y)) {
+ fName.printf("bicubic_%gx%g",
+ SkScalarToFloat(fScale.fWidth), SkScalarToFloat(fScale.fHeight));
+ }
+
+protected:
+ virtual const char* onGetName() {
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) {
+ SkPaint paint;
+ this->setupPaint(&paint);
+
+ paint.setAntiAlias(true);
+
+ SkRect r = SkRect::MakeWH(40, 40);
+ SkAutoTUnref<SkImageFilter> bicubic(SkBicubicImageFilter::CreateMitchell(fScale));
+ paint.setImageFilter(bicubic);
+
+ for (int i = 0; i < loops; i++) {
+ canvas->save();
+ canvas->clipRect(r);
+ canvas->drawOval(r, paint);
+ canvas->restore();
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+DEF_BENCH( return new BicubicBench(10.0f, 10.0f); )
+DEF_BENCH( return new BicubicBench(2.5f, 10.0f); )
+DEF_BENCH( return new BicubicBench(10.0f, 2.5f); )
+DEF_BENCH( return new BicubicBench(2.5f, 2.5f); )
diff --git a/chromium/third_party/skia/bench/BitmapBench.cpp b/chromium/third_party/skia/bench/BitmapBench.cpp
new file mode 100644
index 00000000000..a269e906f6c
--- /dev/null
+++ b/chromium/third_party/skia/bench/BitmapBench.cpp
@@ -0,0 +1,381 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkBitmap.h"
+#include "SkCanvas.h"
+#include "SkColorPriv.h"
+#include "SkPaint.h"
+#include "SkRandom.h"
+#include "SkString.h"
+#include "sk_tool_utils.h"
+
+static int conv6ToByte(int x) {
+ return x * 0xFF / 5;
+}
+
+static int convByteTo6(int x) {
+ return x * 5 / 255;
+}
+
+static uint8_t compute666Index(SkPMColor c) {
+ int r = SkGetPackedR32(c);
+ int g = SkGetPackedG32(c);
+ int b = SkGetPackedB32(c);
+
+ return convByteTo6(r) * 36 + convByteTo6(g) * 6 + convByteTo6(b);
+}
+
+static void convertToIndex666(const SkBitmap& src, SkBitmap* dst, SkAlphaType aType) {
+ SkPMColor storage[216];
+ SkPMColor* colors = storage;
+ // rrr ggg bbb
+ for (int r = 0; r < 6; r++) {
+ int rr = conv6ToByte(r);
+ for (int g = 0; g < 6; g++) {
+ int gg = conv6ToByte(g);
+ for (int b = 0; b < 6; b++) {
+ int bb = conv6ToByte(b);
+ *colors++ = SkPreMultiplyARGB(0xFF, rr, gg, bb);
+ }
+ }
+ }
+ SkColorTable* ctable = new SkColorTable(storage, 216, aType);
+ dst->allocPixels(SkImageInfo::Make(src.width(), src.height(), kIndex_8_SkColorType, aType),
+ NULL, ctable);
+ ctable->unref();
+
+ SkAutoLockPixels alps(src);
+ SkAutoLockPixels alpd(*dst);
+
+ for (int y = 0; y < src.height(); y++) {
+ const SkPMColor* srcP = src.getAddr32(0, y);
+ uint8_t* dstP = dst->getAddr8(0, y);
+ for (int x = src.width() - 1; x >= 0; --x) {
+ *dstP++ = compute666Index(*srcP++);
+ }
+ }
+}
+
+/* Variants for bitmaps
+
+ - src depth (32 w+w/o alpha), 565, 4444, index, a8
+ - paint options: filtering, dither, alpha
+ - matrix options: translate, scale, rotate, persp
+ - tiling: none, repeat, mirror, clamp
+
+ */
+
+class BitmapBench : public Benchmark {
+ const SkColorType fColorType;
+ const SkAlphaType fAlphaType;
+ const bool fForceUpdate; //bitmap marked as dirty before each draw. forces bitmap to be updated on device cache
+ const bool fIsVolatile;
+
+ SkBitmap fBitmap;
+ SkPaint fPaint;
+ SkString fName;
+
+ enum { W = 128 };
+ enum { H = 128 };
+public:
+ BitmapBench(SkColorType ct, SkAlphaType at, bool forceUpdate = false, bool isVolatile = false)
+ : fColorType(ct)
+ , fAlphaType(at)
+ , fForceUpdate(forceUpdate)
+ , fIsVolatile(isVolatile)
+ {}
+
+protected:
+ virtual const char* onGetName() {
+ fName.set("bitmap");
+ fName.appendf("_%s%s", sk_tool_utils::colortype_name(fColorType),
+ kOpaque_SkAlphaType == fAlphaType ? "" : "_A");
+ if (fForceUpdate)
+ fName.append("_update");
+ if (fIsVolatile)
+ fName.append("_volatile");
+
+ return fName.c_str();
+ }
+
+ virtual void onPreDraw() {
+ SkBitmap bm;
+
+ if (kIndex_8_SkColorType == fColorType) {
+ bm.setInfo(SkImageInfo::MakeN32(W, H, fAlphaType));
+ } else {
+ bm.setInfo(SkImageInfo::Make(W, H, fColorType, fAlphaType));
+ }
+
+ bm.allocPixels();
+ bm.eraseColor(kOpaque_SkAlphaType == fAlphaType ? SK_ColorBLACK : 0);
+
+ onDrawIntoBitmap(bm);
+
+ if (kIndex_8_SkColorType == fColorType) {
+ convertToIndex666(bm, &fBitmap, fAlphaType);
+ } else {
+ fBitmap = bm;
+ }
+
+ fBitmap.setIsVolatile(fIsVolatile);
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) {
+ SkIPoint dim = this->getSize();
+ SkRandom rand;
+
+ SkPaint paint(fPaint);
+ this->setupPaint(&paint);
+
+ const SkBitmap& bitmap = fBitmap;
+ const SkScalar x0 = SkIntToScalar(-bitmap.width() / 2);
+ const SkScalar y0 = SkIntToScalar(-bitmap.height() / 2);
+
+ for (int i = 0; i < loops; i++) {
+ SkScalar x = x0 + rand.nextUScalar1() * dim.fX;
+ SkScalar y = y0 + rand.nextUScalar1() * dim.fY;
+
+ if (fForceUpdate)
+ bitmap.notifyPixelsChanged();
+
+ canvas->drawBitmap(bitmap, x, y, &paint);
+ }
+ }
+
+ virtual void onDrawIntoBitmap(const SkBitmap& bm) {
+ const int w = bm.width();
+ const int h = bm.height();
+
+ SkCanvas canvas(bm);
+ SkPaint p;
+ p.setAntiAlias(true);
+ p.setColor(SK_ColorRED);
+ canvas.drawCircle(SkIntToScalar(w)/2, SkIntToScalar(h)/2,
+ SkIntToScalar(SkMin32(w, h))*3/8, p);
+
+ SkRect r;
+ r.set(0, 0, SkIntToScalar(w), SkIntToScalar(h));
+ p.setStyle(SkPaint::kStroke_Style);
+ p.setStrokeWidth(SkIntToScalar(4));
+ p.setColor(SK_ColorBLUE);
+ canvas.drawRect(r, p);
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+/** Explicitly invoke some filter types to improve coverage of acceleration
+ procs. */
+
+enum Flags {
+ kScale_Flag = 1 << 0,
+ kRotate_Flag = 1 << 1,
+ kBilerp_Flag = 1 << 2,
+ kBicubic_Flag = 1 << 3,
+};
+
+static bool isBilerp(uint32_t flags) {
+ return (flags & (kBilerp_Flag | kBicubic_Flag)) == (kBilerp_Flag);
+}
+
+static bool isBicubic(uint32_t flags) {
+ return (flags & (kBilerp_Flag | kBicubic_Flag)) == (kBilerp_Flag | kBicubic_Flag);
+}
+
+class FilterBitmapBench : public BitmapBench {
+ uint32_t fFlags;
+ SkString fFullName;
+public:
+ FilterBitmapBench(SkColorType ct, SkAlphaType at,
+ bool forceUpdate, bool isVolitile, uint32_t flags)
+ : INHERITED(ct, at, forceUpdate, isVolitile)
+ , fFlags(flags) {
+ }
+
+protected:
+ virtual const char* onGetName() {
+ fFullName.set(INHERITED::onGetName());
+ if (fFlags & kScale_Flag) {
+ fFullName.append("_scale");
+ }
+ if (fFlags & kRotate_Flag) {
+ fFullName.append("_rotate");
+ }
+ if (isBilerp(fFlags)) {
+ fFullName.append("_bilerp");
+ } else if (isBicubic(fFlags)) {
+ fFullName.append("_bicubic");
+ }
+
+ return fFullName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) {
+ SkISize dim = canvas->getDeviceSize();
+ if (fFlags & kScale_Flag) {
+ const SkScalar x = SkIntToScalar(dim.fWidth) / 2;
+ const SkScalar y = SkIntToScalar(dim.fHeight) / 2;
+
+ canvas->translate(x, y);
+ // just enough so we can't take the sprite case
+ canvas->scale(SK_Scalar1 * 99/100, SK_Scalar1 * 99/100);
+ canvas->translate(-x, -y);
+ }
+ if (fFlags & kRotate_Flag) {
+ const SkScalar x = SkIntToScalar(dim.fWidth) / 2;
+ const SkScalar y = SkIntToScalar(dim.fHeight) / 2;
+
+ canvas->translate(x, y);
+ canvas->rotate(SkIntToScalar(35));
+ canvas->translate(-x, -y);
+ }
+ INHERITED::onDraw(loops, canvas);
+ }
+
+ virtual void setupPaint(SkPaint* paint) SK_OVERRIDE {
+ this->INHERITED::setupPaint(paint);
+
+ int index = 0;
+ if (fFlags & kBilerp_Flag) {
+ index |= 1;
+ }
+ if (fFlags & kBicubic_Flag) {
+ index |= 2;
+ }
+ static const SkPaint::FilterLevel gLevels[] = {
+ SkPaint::kNone_FilterLevel,
+ SkPaint::kLow_FilterLevel,
+ SkPaint::kMedium_FilterLevel,
+ SkPaint::kHigh_FilterLevel
+ };
+ paint->setFilterLevel(gLevels[index]);
+}
+
+private:
+ typedef BitmapBench INHERITED;
+};
+
+/** Verify optimizations that test source alpha values. */
+
+class SourceAlphaBitmapBench : public BitmapBench {
+public:
+ enum SourceAlpha { kOpaque_SourceAlpha, kTransparent_SourceAlpha,
+ kTwoStripes_SourceAlpha, kThreeStripes_SourceAlpha};
+private:
+ SkString fFullName;
+ SourceAlpha fSourceAlpha;
+public:
+ SourceAlphaBitmapBench(SourceAlpha alpha, SkColorType ct,
+ bool forceUpdate = false, bool bitmapVolatile = false)
+ : INHERITED(ct, kPremul_SkAlphaType, forceUpdate, bitmapVolatile)
+ , fSourceAlpha(alpha) {
+ }
+
+protected:
+ virtual const char* onGetName() {
+ fFullName.set(INHERITED::onGetName());
+
+ if (fSourceAlpha == kOpaque_SourceAlpha) {
+ fFullName.append("_source_opaque");
+ } else if (fSourceAlpha == kTransparent_SourceAlpha) {
+ fFullName.append("_source_transparent");
+ } else if (fSourceAlpha == kTwoStripes_SourceAlpha) {
+ fFullName.append("_source_stripes_two");
+ } else if (fSourceAlpha == kThreeStripes_SourceAlpha) {
+ fFullName.append("_source_stripes_three");
+ }
+
+ return fFullName.c_str();
+ }
+
+ virtual void onDrawIntoBitmap(const SkBitmap& bm) SK_OVERRIDE {
+ const int w = bm.width();
+ const int h = bm.height();
+
+ if (kOpaque_SourceAlpha == fSourceAlpha) {
+ bm.eraseColor(SK_ColorBLACK);
+ } else if (kTransparent_SourceAlpha == fSourceAlpha) {
+ bm.eraseColor(0);
+ } else if (kTwoStripes_SourceAlpha == fSourceAlpha) {
+ bm.eraseColor(0);
+
+ SkCanvas canvas(bm);
+ SkPaint p;
+ p.setAntiAlias(false);
+ p.setStyle(SkPaint::kFill_Style);
+ p.setColor(SK_ColorRED);
+
+ // Draw red vertical stripes on transparent background
+ SkRect r;
+ for (int x = 0; x < w; x+=2)
+ {
+ r.set(SkIntToScalar(x), 0, SkIntToScalar(x+1), SkIntToScalar(h));
+ canvas.drawRect(r, p);
+ }
+
+ } else if (kThreeStripes_SourceAlpha == fSourceAlpha) {
+ bm.eraseColor(0);
+
+ SkCanvas canvas(bm);
+ SkPaint p;
+ p.setAntiAlias(false);
+ p.setStyle(SkPaint::kFill_Style);
+
+ // Draw vertical stripes on transparent background with a pattern
+ // where the first pixel is fully transparent, the next is semi-transparent
+ // and the third is fully opaque.
+ SkRect r;
+ for (int x = 0; x < w; x++)
+ {
+ if (x % 3 == 0) {
+ continue; // Keep transparent
+ } else if (x % 3 == 1) {
+ p.setColor(SkColorSetARGB(127, 127, 127, 127)); // Semi-transparent
+ } else if (x % 3 == 2) {
+ p.setColor(SK_ColorRED); // Opaque
+ }
+ r.set(SkIntToScalar(x), 0, SkIntToScalar(x+1), SkIntToScalar(h));
+ canvas.drawRect(r, p);
+ }
+ }
+ }
+
+private:
+ typedef BitmapBench INHERITED;
+};
+
+DEF_BENCH( return new BitmapBench(kN32_SkColorType, kPremul_SkAlphaType); )
+DEF_BENCH( return new BitmapBench(kN32_SkColorType, kOpaque_SkAlphaType); )
+DEF_BENCH( return new BitmapBench(kRGB_565_SkColorType, kOpaque_SkAlphaType); )
+DEF_BENCH( return new BitmapBench(kIndex_8_SkColorType, kPremul_SkAlphaType); )
+DEF_BENCH( return new BitmapBench(kIndex_8_SkColorType, kOpaque_SkAlphaType); )
+DEF_BENCH( return new BitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, true, true); )
+DEF_BENCH( return new BitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, true, false); )
+
+// scale filter -> S32_opaque_D32_filter_DX_{SSE2,SSSE3} and Fact9 is also for S32_D16_filter_DX_SSE2
+DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kPremul_SkAlphaType, false, false, kScale_Flag | kBilerp_Flag); )
+DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, false, false, kScale_Flag | kBilerp_Flag); )
+DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, true, true, kScale_Flag | kBilerp_Flag); )
+DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, true, false, kScale_Flag | kBilerp_Flag); )
+
+// scale rotate filter -> S32_opaque_D32_filter_DXDY_{SSE2,SSSE3}
+DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kPremul_SkAlphaType, false, false, kScale_Flag | kRotate_Flag | kBilerp_Flag); )
+DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, false, false, kScale_Flag | kRotate_Flag | kBilerp_Flag); )
+DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, true, true, kScale_Flag | kRotate_Flag | kBilerp_Flag); )
+DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, true, false, kScale_Flag | kRotate_Flag | kBilerp_Flag); )
+
+DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kPremul_SkAlphaType, false, false, kScale_Flag | kBilerp_Flag | kBicubic_Flag); )
+DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kPremul_SkAlphaType, false, false, kScale_Flag | kRotate_Flag | kBilerp_Flag | kBicubic_Flag); )
+
+// source alpha tests -> S32A_Opaque_BlitRow32_{arm,neon}
+DEF_BENCH( return new SourceAlphaBitmapBench(SourceAlphaBitmapBench::kOpaque_SourceAlpha, kN32_SkColorType); )
+DEF_BENCH( return new SourceAlphaBitmapBench(SourceAlphaBitmapBench::kTransparent_SourceAlpha, kN32_SkColorType); )
+DEF_BENCH( return new SourceAlphaBitmapBench(SourceAlphaBitmapBench::kTwoStripes_SourceAlpha, kN32_SkColorType); )
+DEF_BENCH( return new SourceAlphaBitmapBench(SourceAlphaBitmapBench::kThreeStripes_SourceAlpha, kN32_SkColorType); )
diff --git a/chromium/third_party/skia/bench/BitmapRectBench.cpp b/chromium/third_party/skia/bench/BitmapRectBench.cpp
new file mode 100644
index 00000000000..2ad7bdf9b5f
--- /dev/null
+++ b/chromium/third_party/skia/bench/BitmapRectBench.cpp
@@ -0,0 +1,113 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "Benchmark.h"
+#include "SkBitmap.h"
+#include "SkCanvas.h"
+#include "SkColorPriv.h"
+#include "SkPaint.h"
+#include "SkRandom.h"
+#include "SkString.h"
+
+static void draw_into_bitmap(const SkBitmap& bm) {
+ const int w = bm.width();
+ const int h = bm.height();
+
+ SkCanvas canvas(bm);
+ SkPaint p;
+ p.setAntiAlias(true);
+ p.setColor(SK_ColorRED);
+ canvas.drawCircle(SkIntToScalar(w)/2, SkIntToScalar(h)/2,
+ SkIntToScalar(SkMin32(w, h))*3/8, p);
+
+ SkRect r;
+ r.set(0, 0, SkIntToScalar(w), SkIntToScalar(h));
+ p.setStyle(SkPaint::kStroke_Style);
+ p.setStrokeWidth(SkIntToScalar(4));
+ p.setColor(SK_ColorBLUE);
+ canvas.drawRect(r, p);
+}
+
+/* Variants for bitmaprect
+ src : entire bitmap, subset, fractional subset
+ dst : same size as src, diff size
+ paint : filter-p
+ */
+
+class BitmapRectBench : public Benchmark {
+ SkBitmap fBitmap;
+ bool fSlightMatrix;
+ uint8_t fAlpha;
+ SkPaint::FilterLevel fFilterLevel;
+ SkString fName;
+ SkRect fSrcR, fDstR;
+
+ static const int kWidth = 128;
+ static const int kHeight = 128;
+public:
+ BitmapRectBench(U8CPU alpha, SkPaint::FilterLevel filterLevel,
+ bool slightMatrix) {
+ fAlpha = SkToU8(alpha);
+ fFilterLevel = filterLevel;
+ fSlightMatrix = slightMatrix;
+
+ fBitmap.setInfo(SkImageInfo::MakeN32Premul(kWidth, kHeight));
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ fName.printf("bitmaprect_%02X_%sfilter_%s",
+ fAlpha,
+ SkPaint::kNone_FilterLevel == fFilterLevel ? "no" : "",
+ fSlightMatrix ? "trans" : "identity");
+ return fName.c_str();
+ }
+
+ virtual void onPreDraw() SK_OVERRIDE {
+ fBitmap.allocPixels();
+ fBitmap.setAlphaType(kOpaque_SkAlphaType);
+ fBitmap.eraseColor(SK_ColorBLACK);
+ draw_into_bitmap(fBitmap);
+
+ fSrcR.iset(0, 0, kWidth, kHeight);
+ fDstR.iset(0, 0, kWidth, kHeight);
+
+ if (fSlightMatrix) {
+ // want fractional translate
+ fDstR.offset(SK_Scalar1 / 3, SK_Scalar1 * 5 / 7);
+ // want enough to create a scale matrix, but not enough to scare
+ // off our sniffer which tries to see if the matrix is "effectively"
+ // translate-only.
+ fDstR.fRight += SK_Scalar1 / (kWidth * 60);
+ }
+ }
+
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkRandom rand;
+
+ SkPaint paint;
+ this->setupPaint(&paint);
+ paint.setFilterLevel(fFilterLevel);
+ paint.setAlpha(fAlpha);
+
+ for (int i = 0; i < loops; i++) {
+ canvas->drawBitmapRectToRect(fBitmap, &fSrcR, fDstR, &paint);
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+DEF_BENCH(return new BitmapRectBench(0xFF, SkPaint::kNone_FilterLevel, false))
+DEF_BENCH(return new BitmapRectBench(0x80, SkPaint::kNone_FilterLevel, false))
+DEF_BENCH(return new BitmapRectBench(0xFF, SkPaint::kLow_FilterLevel, false))
+DEF_BENCH(return new BitmapRectBench(0x80, SkPaint::kLow_FilterLevel, false))
+
+DEF_BENCH(return new BitmapRectBench(0xFF, SkPaint::kNone_FilterLevel, true))
+DEF_BENCH(return new BitmapRectBench(0xFF, SkPaint::kLow_FilterLevel, true))
diff --git a/chromium/third_party/skia/bench/BitmapScaleBench.cpp b/chromium/third_party/skia/bench/BitmapScaleBench.cpp
new file mode 100644
index 00000000000..fad741aebc7
--- /dev/null
+++ b/chromium/third_party/skia/bench/BitmapScaleBench.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkBlurMask.h"
+#include "SkCanvas.h"
+#include "SkPaint.h"
+#include "SkRandom.h"
+#include "SkShader.h"
+#include "SkString.h"
+
+class BitmapScaleBench: public Benchmark {
+ int fLoopCount;
+ int fInputSize;
+ int fOutputSize;
+ SkString fName;
+
+public:
+ BitmapScaleBench( int is, int os) {
+ fInputSize = is;
+ fOutputSize = os;
+
+ fLoopCount = 20;
+ }
+
+protected:
+
+ SkBitmap fInputBitmap, fOutputBitmap;
+ SkMatrix fMatrix;
+
+ virtual const char* onGetName() {
+ return fName.c_str();
+ }
+
+ int inputSize() const {
+ return fInputSize;
+ }
+
+ int outputSize() const {
+ return fOutputSize;
+ }
+
+ float scale() const {
+ return float(outputSize())/inputSize();
+ }
+
+ SkIPoint onGetSize() SK_OVERRIDE {
+ return SkIPoint::Make( fOutputSize, fOutputSize );
+ }
+
+ void setName(const char * name) {
+ fName.printf( "bitmap_scale_%s_%d_%d", name, fInputSize, fOutputSize );
+ }
+
+ virtual void onPreDraw() {
+ fInputBitmap.allocN32Pixels(fInputSize, fInputSize, true);
+ fInputBitmap.eraseColor(SK_ColorWHITE);
+
+ fOutputBitmap.allocN32Pixels(fOutputSize, fOutputSize, true);
+
+ fMatrix.setScale( scale(), scale() );
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) {
+ SkPaint paint;
+ this->setupPaint(&paint);
+
+ preBenchSetup();
+
+ for (int i = 0; i < loops; i++) {
+ doScaleImage();
+ }
+ }
+
+ virtual void doScaleImage() = 0;
+ virtual void preBenchSetup() {}
+private:
+ typedef Benchmark INHERITED;
+};
+
+class BitmapFilterScaleBench: public BitmapScaleBench {
+ public:
+ BitmapFilterScaleBench( int is, int os) : INHERITED(is, os) {
+ setName( "filter" );
+ }
+protected:
+ virtual void doScaleImage() SK_OVERRIDE {
+ SkCanvas canvas( fOutputBitmap );
+ SkPaint paint;
+
+ paint.setFilterLevel(SkPaint::kHigh_FilterLevel);
+ fInputBitmap.notifyPixelsChanged();
+ canvas.drawBitmapMatrix( fInputBitmap, fMatrix, &paint );
+ }
+private:
+ typedef BitmapScaleBench INHERITED;
+};
+
+DEF_BENCH(return new BitmapFilterScaleBench(10, 90);)
+DEF_BENCH(return new BitmapFilterScaleBench(30, 90);)
+DEF_BENCH(return new BitmapFilterScaleBench(80, 90);)
+DEF_BENCH(return new BitmapFilterScaleBench(90, 90);)
+DEF_BENCH(return new BitmapFilterScaleBench(90, 80);)
+DEF_BENCH(return new BitmapFilterScaleBench(90, 30);)
+DEF_BENCH(return new BitmapFilterScaleBench(90, 10);)
+DEF_BENCH(return new BitmapFilterScaleBench(256, 64);)
+DEF_BENCH(return new BitmapFilterScaleBench(64, 256);)
diff --git a/chromium/third_party/skia/bench/BlurBench.cpp b/chromium/third_party/skia/bench/BlurBench.cpp
new file mode 100644
index 00000000000..cafc6f3a2a3
--- /dev/null
+++ b/chromium/third_party/skia/bench/BlurBench.cpp
@@ -0,0 +1,109 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "Benchmark.h"
+#include "SkBlurMask.h"
+#include "SkBlurMaskFilter.h"
+#include "SkCanvas.h"
+#include "SkPaint.h"
+#include "SkRandom.h"
+#include "SkShader.h"
+#include "SkString.h"
+
+#define SMALL SkIntToScalar(2)
+#define REAL 1.5f
+#define BIG SkIntToScalar(10)
+#define REALBIG 100.5f
+
+static const char* gStyleName[] = {
+ "normal",
+ "solid",
+ "outer",
+ "inner"
+};
+
+class BlurBench : public Benchmark {
+ SkScalar fRadius;
+ SkBlurStyle fStyle;
+ uint32_t fFlags;
+ SkString fName;
+
+public:
+ BlurBench(SkScalar rad, SkBlurStyle bs, uint32_t flags = 0) {
+ fRadius = rad;
+ fStyle = bs;
+ fFlags = flags;
+ const char* name = rad > 0 ? gStyleName[bs] : "none";
+ const char* quality = flags & SkBlurMaskFilter::kHighQuality_BlurFlag ? "high_quality"
+ : "low_quality";
+ if (SkScalarFraction(rad) != 0) {
+ fName.printf("blur_%.2f_%s_%s", SkScalarToFloat(rad), name, quality);
+ } else {
+ fName.printf("blur_%d_%s_%s", SkScalarRoundToInt(rad), name, quality);
+ }
+ }
+
+protected:
+ virtual const char* onGetName() {
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) {
+ SkPaint paint;
+ this->setupPaint(&paint);
+
+ paint.setAntiAlias(true);
+
+ SkRandom rand;
+ for (int i = 0; i < loops; i++) {
+ SkRect r = SkRect::MakeWH(rand.nextUScalar1() * 400,
+ rand.nextUScalar1() * 400);
+ r.offset(fRadius, fRadius);
+
+ if (fRadius > 0) {
+ SkMaskFilter* mf = SkBlurMaskFilter::Create(fStyle,
+ SkBlurMask::ConvertRadiusToSigma(fRadius),
+ fFlags);
+ paint.setMaskFilter(mf)->unref();
+ }
+ canvas->drawOval(r, paint);
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+DEF_BENCH(return new BlurBench(SMALL, kNormal_SkBlurStyle);)
+DEF_BENCH(return new BlurBench(SMALL, kSolid_SkBlurStyle);)
+DEF_BENCH(return new BlurBench(SMALL, kOuter_SkBlurStyle);)
+DEF_BENCH(return new BlurBench(SMALL, kInner_SkBlurStyle);)
+
+DEF_BENCH(return new BlurBench(BIG, kNormal_SkBlurStyle);)
+DEF_BENCH(return new BlurBench(BIG, kSolid_SkBlurStyle);)
+DEF_BENCH(return new BlurBench(BIG, kOuter_SkBlurStyle);)
+DEF_BENCH(return new BlurBench(BIG, kInner_SkBlurStyle);)
+
+DEF_BENCH(return new BlurBench(REALBIG, kNormal_SkBlurStyle);)
+DEF_BENCH(return new BlurBench(REALBIG, kSolid_SkBlurStyle);)
+DEF_BENCH(return new BlurBench(REALBIG, kOuter_SkBlurStyle);)
+DEF_BENCH(return new BlurBench(REALBIG, kInner_SkBlurStyle);)
+
+DEF_BENCH(return new BlurBench(REAL, kNormal_SkBlurStyle);)
+DEF_BENCH(return new BlurBench(REAL, kSolid_SkBlurStyle);)
+DEF_BENCH(return new BlurBench(REAL, kOuter_SkBlurStyle);)
+DEF_BENCH(return new BlurBench(REAL, kInner_SkBlurStyle);)
+
+DEF_BENCH(return new BlurBench(SMALL, kNormal_SkBlurStyle, SkBlurMaskFilter::kHighQuality_BlurFlag);)
+
+DEF_BENCH(return new BlurBench(BIG, kNormal_SkBlurStyle, SkBlurMaskFilter::kHighQuality_BlurFlag);)
+
+DEF_BENCH(return new BlurBench(REALBIG, kNormal_SkBlurStyle, SkBlurMaskFilter::kHighQuality_BlurFlag);)
+
+DEF_BENCH(return new BlurBench(REAL, kNormal_SkBlurStyle, SkBlurMaskFilter::kHighQuality_BlurFlag);)
+
+DEF_BENCH(return new BlurBench(0, kNormal_SkBlurStyle);)
diff --git a/chromium/third_party/skia/bench/BlurImageFilterBench.cpp b/chromium/third_party/skia/bench/BlurImageFilterBench.cpp
new file mode 100644
index 00000000000..786611b1504
--- /dev/null
+++ b/chromium/third_party/skia/bench/BlurImageFilterBench.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkBitmapDevice.h"
+#include "SkBlurImageFilter.h"
+#include "SkCanvas.h"
+#include "SkPaint.h"
+#include "SkRandom.h"
+#include "SkShader.h"
+#include "SkString.h"
+
+#define FILTER_WIDTH_SMALL 32
+#define FILTER_HEIGHT_SMALL 32
+#define FILTER_WIDTH_LARGE 256
+#define FILTER_HEIGHT_LARGE 256
+#define BLUR_SIGMA_SMALL 1.0f
+#define BLUR_SIGMA_LARGE 10.0f
+#define BLUR_SIGMA_HUGE 80.0f
+
+class BlurImageFilterBench : public Benchmark {
+public:
+ BlurImageFilterBench(SkScalar sigmaX, SkScalar sigmaY, bool small) :
+ fIsSmall(small), fInitialized(false), fSigmaX(sigmaX), fSigmaY(sigmaY) {
+ fName.printf("blur_image_filter_%s_%.2f_%.2f", fIsSmall ? "small" : "large",
+ SkScalarToFloat(sigmaX), SkScalarToFloat(sigmaY));
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+
+ virtual void onPreDraw() SK_OVERRIDE {
+ if (!fInitialized) {
+ make_checkerboard();
+ fInitialized = true;
+ }
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkPaint paint;
+ paint.setImageFilter(SkBlurImageFilter::Create(fSigmaX, fSigmaY))->unref();
+
+ for (int i = 0; i < loops; i++) {
+ canvas->drawBitmap(fCheckerboard, 0, 0, &paint);
+ }
+ }
+
+private:
+ void make_checkerboard() {
+ const int w = fIsSmall ? FILTER_WIDTH_SMALL : FILTER_WIDTH_LARGE;
+ const int h = fIsSmall ? FILTER_HEIGHT_LARGE : FILTER_HEIGHT_LARGE;
+ fCheckerboard.allocN32Pixels(w, h);
+ SkCanvas canvas(fCheckerboard);
+ canvas.clear(0x00000000);
+ SkPaint darkPaint;
+ darkPaint.setColor(0xFF804020);
+ SkPaint lightPaint;
+ lightPaint.setColor(0xFF244484);
+ for (int y = 0; y < h; y += 16) {
+ for (int x = 0; x < w; x += 16) {
+ canvas.save();
+ canvas.translate(SkIntToScalar(x), SkIntToScalar(y));
+ canvas.drawRect(SkRect::MakeXYWH(0, 0, 8, 8), darkPaint);
+ canvas.drawRect(SkRect::MakeXYWH(8, 0, 8, 8), lightPaint);
+ canvas.drawRect(SkRect::MakeXYWH(0, 8, 8, 8), lightPaint);
+ canvas.drawRect(SkRect::MakeXYWH(8, 8, 8, 8), darkPaint);
+ canvas.restore();
+ }
+ }
+ }
+
+ SkString fName;
+ bool fIsSmall;
+ bool fInitialized;
+ SkBitmap fCheckerboard;
+ SkScalar fSigmaX, fSigmaY;
+ typedef Benchmark INHERITED;
+};
+
+DEF_BENCH(return new BlurImageFilterBench(BLUR_SIGMA_LARGE, 0, false);)
+DEF_BENCH(return new BlurImageFilterBench(BLUR_SIGMA_SMALL, 0, false);)
+DEF_BENCH(return new BlurImageFilterBench(0, BLUR_SIGMA_LARGE, false);)
+DEF_BENCH(return new BlurImageFilterBench(0, BLUR_SIGMA_SMALL, false);)
+DEF_BENCH(return new BlurImageFilterBench(BLUR_SIGMA_SMALL, BLUR_SIGMA_SMALL, true);)
+DEF_BENCH(return new BlurImageFilterBench(BLUR_SIGMA_SMALL, BLUR_SIGMA_SMALL, false);)
+DEF_BENCH(return new BlurImageFilterBench(BLUR_SIGMA_LARGE, BLUR_SIGMA_LARGE, true);)
+DEF_BENCH(return new BlurImageFilterBench(BLUR_SIGMA_LARGE, BLUR_SIGMA_LARGE, false);)
+DEF_BENCH(return new BlurImageFilterBench(BLUR_SIGMA_HUGE, BLUR_SIGMA_HUGE, true);)
+DEF_BENCH(return new BlurImageFilterBench(BLUR_SIGMA_HUGE, BLUR_SIGMA_HUGE, false);)
diff --git a/chromium/third_party/skia/bench/BlurRectBench.cpp b/chromium/third_party/skia/bench/BlurRectBench.cpp
new file mode 100644
index 00000000000..cdcdfe57f34
--- /dev/null
+++ b/chromium/third_party/skia/bench/BlurRectBench.cpp
@@ -0,0 +1,228 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkBlurMask.h"
+#include "SkCanvas.h"
+#include "SkPaint.h"
+#include "SkRandom.h"
+#include "SkShader.h"
+#include "SkString.h"
+
+#define SMALL SkIntToScalar(2)
+#define REAL 1.5f
+static const SkScalar kMedium = SkIntToScalar(5);
+#define BIG SkIntToScalar(10)
+static const SkScalar kMedBig = SkIntToScalar(20);
+#define REALBIG 30.5f
+
+class BlurRectBench: public Benchmark {
+ int fLoopCount;
+ SkScalar fRadius;
+ SkString fName;
+
+public:
+ BlurRectBench(SkScalar rad) {
+ fRadius = rad;
+
+ if (fRadius > SkIntToScalar(25)) {
+ fLoopCount = 100;
+ } else if (fRadius > SkIntToScalar(5)) {
+ fLoopCount = 1000;
+ } else {
+ fLoopCount = 10000;
+ }
+ }
+
+protected:
+ virtual const char* onGetName() {
+ return fName.c_str();
+ }
+
+ SkScalar radius() const {
+ return fRadius;
+ }
+
+ void setName(const SkString& name) {
+ fName = name;
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) {
+ SkPaint paint;
+ this->setupPaint(&paint);
+
+ paint.setAntiAlias(true);
+
+ SkScalar pad = fRadius*3/2 + SK_Scalar1;
+ SkRect r = SkRect::MakeWH(2 * pad + SK_Scalar1, 2 * pad + SK_Scalar1);
+
+ preBenchSetup(r);
+
+ for (int i = 0; i < loops; i++) {
+ makeBlurryRect(r);
+ }
+ }
+
+ virtual void makeBlurryRect(const SkRect&) = 0;
+ virtual void preBenchSetup(const SkRect&) {}
+private:
+ typedef Benchmark INHERITED;
+};
+
+
+class BlurRectDirectBench: public BlurRectBench {
+ public:
+ BlurRectDirectBench(SkScalar rad) : INHERITED(rad) {
+ SkString name;
+
+ if (SkScalarFraction(rad) != 0) {
+ name.printf("blurrect_direct_%.2f", SkScalarToFloat(rad));
+ } else {
+ name.printf("blurrect_direct_%d", SkScalarRoundToInt(rad));
+ }
+
+ this->setName(name);
+ }
+protected:
+ virtual void makeBlurryRect(const SkRect& r) SK_OVERRIDE {
+ SkMask mask;
+ SkBlurMask::BlurRect(SkBlurMask::ConvertRadiusToSigma(this->radius()),
+ &mask, r, kNormal_SkBlurStyle);
+ SkMask::FreeImage(mask.fImage);
+ }
+private:
+ typedef BlurRectBench INHERITED;
+};
+
+class BlurRectSeparableBench: public BlurRectBench {
+
+public:
+ BlurRectSeparableBench(SkScalar rad) : INHERITED(rad) {
+ fSrcMask.fImage = NULL;
+ }
+
+ ~BlurRectSeparableBench() {
+ SkMask::FreeImage(fSrcMask.fImage);
+ }
+
+protected:
+ virtual void preBenchSetup(const SkRect& r) SK_OVERRIDE {
+ SkMask::FreeImage(fSrcMask.fImage);
+
+ r.roundOut(&fSrcMask.fBounds);
+ fSrcMask.fFormat = SkMask::kA8_Format;
+ fSrcMask.fRowBytes = fSrcMask.fBounds.width();
+ fSrcMask.fImage = SkMask::AllocImage(fSrcMask.computeTotalImageSize());
+
+ memset(fSrcMask.fImage, 0xff, fSrcMask.computeTotalImageSize());
+ }
+
+ SkMask fSrcMask;
+private:
+ typedef BlurRectBench INHERITED;
+};
+
+class BlurRectBoxFilterBench: public BlurRectSeparableBench {
+public:
+ BlurRectBoxFilterBench(SkScalar rad) : INHERITED(rad) {
+ SkString name;
+
+ if (SkScalarFraction(rad) != 0) {
+ name.printf("blurrect_boxfilter_%.2f", SkScalarToFloat(rad));
+ } else {
+ name.printf("blurrect_boxfilter_%d", SkScalarRoundToInt(rad));
+ }
+
+ this->setName(name);
+ }
+
+protected:
+
+ virtual void makeBlurryRect(const SkRect&) SK_OVERRIDE {
+ SkMask mask;
+ mask.fImage = NULL;
+ SkBlurMask::BoxBlur(&mask, fSrcMask, SkBlurMask::ConvertRadiusToSigma(this->radius()),
+ kNormal_SkBlurStyle, kHigh_SkBlurQuality);
+ SkMask::FreeImage(mask.fImage);
+ }
+private:
+ typedef BlurRectSeparableBench INHERITED;
+};
+
+class BlurRectGaussianBench: public BlurRectSeparableBench {
+public:
+ BlurRectGaussianBench(SkScalar rad) : INHERITED(rad) {
+ SkString name;
+
+ if (SkScalarFraction(rad) != 0) {
+ name.printf("blurrect_gaussian_%.2f", SkScalarToFloat(rad));
+ } else {
+ name.printf("blurrect_gaussian_%d", SkScalarRoundToInt(rad));
+ }
+
+ this->setName(name);
+ }
+
+protected:
+
+ virtual void makeBlurryRect(const SkRect&) SK_OVERRIDE {
+ SkMask mask;
+ mask.fImage = NULL;
+ SkBlurMask::BlurGroundTruth(SkBlurMask::ConvertRadiusToSigma(this->radius()),
+ &mask, fSrcMask, kNormal_SkBlurStyle);
+ SkMask::FreeImage(mask.fImage);
+ }
+private:
+ typedef BlurRectSeparableBench INHERITED;
+};
+
+DEF_BENCH(return new BlurRectBoxFilterBench(SMALL);)
+DEF_BENCH(return new BlurRectBoxFilterBench(BIG);)
+DEF_BENCH(return new BlurRectBoxFilterBench(REALBIG);)
+DEF_BENCH(return new BlurRectBoxFilterBench(REAL);)
+DEF_BENCH(return new BlurRectGaussianBench(SMALL);)
+DEF_BENCH(return new BlurRectGaussianBench(BIG);)
+DEF_BENCH(return new BlurRectGaussianBench(REALBIG);)
+DEF_BENCH(return new BlurRectGaussianBench(REAL);)
+DEF_BENCH(return new BlurRectDirectBench(SMALL);)
+DEF_BENCH(return new BlurRectDirectBench(BIG);)
+DEF_BENCH(return new BlurRectDirectBench(REALBIG);)
+DEF_BENCH(return new BlurRectDirectBench(REAL);)
+
+DEF_BENCH(return new BlurRectDirectBench(kMedium);)
+DEF_BENCH(return new BlurRectDirectBench(kMedBig);)
+
+DEF_BENCH(return new BlurRectBoxFilterBench(kMedium);)
+DEF_BENCH(return new BlurRectBoxFilterBench(kMedBig);)
+
+#if 0
+// disable Gaussian benchmarks; the algorithm works well enough
+// and serves as a baseline for ground truth, but it's too slow
+// to use in production for non-trivial radii, so no real point
+// in having the bots benchmark it all the time.
+
+DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(1));)
+DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(2));)
+DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(3));)
+DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(4));)
+DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(5));)
+DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(6));)
+DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(7));)
+DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(8));)
+DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(9));)
+DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(10));)
+DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(11));)
+DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(12));)
+DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(13));)
+DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(14));)
+DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(15));)
+DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(16));)
+DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(17));)
+DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(18));)
+DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(19));)
+DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(20));)
+#endif
diff --git a/chromium/third_party/skia/bench/BlurRoundRectBench.cpp b/chromium/third_party/skia/bench/BlurRoundRectBench.cpp
new file mode 100644
index 00000000000..52de22a4dc0
--- /dev/null
+++ b/chromium/third_party/skia/bench/BlurRoundRectBench.cpp
@@ -0,0 +1,93 @@
+/*
+* Copyright 2013 Google Inc.
+*
+* Use of this source code is governed by a BSD-style license that can be
+* found in the LICENSE file.
+*/
+
+#include "Benchmark.h"
+#include "SkBlurMask.h"
+#include "SkBlurMaskFilter.h"
+#include "SkCanvas.h"
+#include "SkColorFilter.h"
+#include "SkLayerDrawLooper.h"
+#include "SkPaint.h"
+#include "SkPath.h"
+#include "SkPoint.h"
+#include "SkRRect.h"
+#include "SkRect.h"
+#include "SkString.h"
+#include "SkXfermode.h"
+
+// Large blurred RR appear frequently on web pages. This benchmark measures our
+// performance in this case.
+class BlurRoundRectBench : public Benchmark {
+public:
+ BlurRoundRectBench(int width, int height, int cornerRadius)
+ : fName("blurroundrect") {
+ fName.appendf("_WH[%ix%i]_cr[%i]", width, height, cornerRadius);
+ SkRect r = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
+ fRRect.setRectXY(r, SkIntToScalar(cornerRadius), SkIntToScalar(cornerRadius));
+ }
+
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+
+ virtual SkIPoint onGetSize() SK_OVERRIDE {
+ return SkIPoint::Make(SkScalarCeilToInt(fRRect.rect().width()),
+ SkScalarCeilToInt(fRRect.rect().height()));
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkLayerDrawLooper::Builder looperBuilder;
+ {
+ SkLayerDrawLooper::LayerInfo info;
+ info.fPaintBits = SkLayerDrawLooper::kMaskFilter_Bit
+ | SkLayerDrawLooper::kColorFilter_Bit;
+ info.fColorMode = SkXfermode::kSrc_Mode;
+ info.fOffset = SkPoint::Make(SkIntToScalar(-1), SkIntToScalar(0));
+ info.fPostTranslate = false;
+ SkPaint* paint = looperBuilder.addLayerOnTop(info);
+ SkMaskFilter* maskFilter = SkBlurMaskFilter::Create(
+ kNormal_SkBlurStyle,
+ SkBlurMask::ConvertRadiusToSigma(SK_ScalarHalf),
+ SkBlurMaskFilter::kHighQuality_BlurFlag);
+ paint->setMaskFilter(maskFilter)->unref();
+ SkColorFilter* colorFilter = SkColorFilter::CreateModeFilter(SK_ColorLTGRAY,
+ SkXfermode::kSrcIn_Mode);
+ paint->setColorFilter(colorFilter)->unref();
+ paint->setColor(SK_ColorGRAY);
+ }
+ {
+ SkLayerDrawLooper::LayerInfo info;
+ looperBuilder.addLayerOnTop(info);
+ }
+ SkPaint dullPaint;
+ dullPaint.setAntiAlias(true);
+
+ SkPaint loopedPaint;
+ loopedPaint.setLooper(looperBuilder.detachLooper())->unref();
+ loopedPaint.setAntiAlias(true);
+ loopedPaint.setColor(SK_ColorCYAN);
+
+ for (int i = 0; i < loops; i++) {
+ canvas->drawRect(fRRect.rect(), dullPaint);
+ canvas->drawRRect(fRRect, loopedPaint);
+ }
+ }
+
+private:
+ SkString fName;
+ SkRRect fRRect;
+
+ typedef Benchmark INHERITED;
+};
+
+// Create one with dimensions/rounded corners based on the skp
+DEF_BENCH(return new BlurRoundRectBench(600, 5514, 6);)
+// Same radii, much smaller rectangle
+DEF_BENCH(return new BlurRoundRectBench(100, 100, 6);)
+// Other radii options
+DEF_BENCH(return new BlurRoundRectBench(100, 100, 30);)
+DEF_BENCH(return new BlurRoundRectBench(100, 100, 90);)
diff --git a/chromium/third_party/skia/bench/ChartBench.cpp b/chromium/third_party/skia/bench/ChartBench.cpp
new file mode 100644
index 00000000000..f33d2da3985
--- /dev/null
+++ b/chromium/third_party/skia/bench/ChartBench.cpp
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkCanvas.h"
+#include "SkPaint.h"
+#include "SkRandom.h"
+
+/**
+ * This is a conversion of samplecode/SampleChart.cpp into a bench. It sure would be nice to be able
+ * to write one subclass that can be a GM, bench, and/or Sample.
+ */
+
+// Generates y values for the chart plots.
+static void gen_data(SkScalar yAvg, SkScalar ySpread, int count,
+ SkRandom* random, SkTDArray<SkScalar>* dataPts) {
+ dataPts->setCount(count);
+ for (int i = 0; i < count; ++i) {
+ (*dataPts)[i] = random->nextRangeScalar(yAvg - SkScalarHalf(ySpread),
+ yAvg + SkScalarHalf(ySpread));
+ }
+}
+
+// Generates a path to stroke along the top of each plot and a fill path for the area below each
+// plot. The fill path is bounded below by the bottomData plot points or a horizontal line at
+// yBase if bottomData == NULL.
+// The plots are animated by rotating the data points by leftShift.
+static void gen_paths(const SkTDArray<SkScalar>& topData,
+ const SkTDArray<SkScalar>* bottomData,
+ SkScalar yBase,
+ SkScalar xLeft, SkScalar xDelta,
+ int leftShift,
+ SkPath* plot, SkPath* fill) {
+ plot->rewind();
+ fill->rewind();
+ plot->incReserve(topData.count());
+ if (NULL == bottomData) {
+ fill->incReserve(topData.count() + 2);
+ } else {
+ fill->incReserve(2 * topData.count());
+ }
+
+ leftShift %= topData.count();
+ SkScalar x = xLeft;
+
+ // Account for the leftShift using two loops
+ int shiftToEndCount = topData.count() - leftShift;
+ plot->moveTo(x, topData[leftShift]);
+ fill->moveTo(x, topData[leftShift]);
+
+ for (int i = 1; i < shiftToEndCount; ++i) {
+ plot->lineTo(x, topData[i + leftShift]);
+ fill->lineTo(x, topData[i + leftShift]);
+ x += xDelta;
+ }
+
+ for (int i = 0; i < leftShift; ++i) {
+ plot->lineTo(x, topData[i]);
+ fill->lineTo(x, topData[i]);
+ x += xDelta;
+ }
+
+ if (NULL != bottomData) {
+ SkASSERT(bottomData->count() == topData.count());
+ // iterate backwards over the previous graph's data to generate the bottom of the filled
+ // area (and account for leftShift).
+ for (int i = 0; i < leftShift; ++i) {
+ x -= xDelta;
+ fill->lineTo(x, (*bottomData)[leftShift - 1 - i]);
+ }
+ for (int i = 0; i < shiftToEndCount; ++i) {
+ x -= xDelta;
+ fill->lineTo(x, (*bottomData)[bottomData->count() - 1 - i]);
+ }
+ } else {
+ fill->lineTo(x - xDelta, yBase);
+ fill->lineTo(xLeft, yBase);
+ }
+}
+
+// A set of scrolling line plots with the area between each plot filled. Stresses out GPU path
+// filling
+class ChartBench : public Benchmark {
+public:
+ ChartBench(bool aa) {
+ fShift = 0;
+ fAA = aa;
+ fSize.fWidth = -1;
+ fSize.fHeight = -1;
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ if (fAA) {
+ return "chart_aa";
+ } else {
+ return "chart_bw";
+ }
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ bool sizeChanged = false;
+ if (canvas->getDeviceSize() != fSize) {
+ fSize = canvas->getDeviceSize();
+ sizeChanged = true;
+ }
+
+ SkScalar ySpread = SkIntToScalar(fSize.fHeight / 20);
+
+ SkScalar height = SkIntToScalar(fSize.fHeight);
+ if (sizeChanged) {
+ int dataPointCount = SkMax32(fSize.fWidth / kPixelsPerTick + 1, 2);
+
+ SkRandom random;
+ for (int i = 0; i < kNumGraphs; ++i) {
+ SkScalar y = (kNumGraphs - i) * (height - ySpread) / (kNumGraphs + 1);
+ fData[i].reset();
+ gen_data(y, ySpread, dataPointCount, &random, fData + i);
+ }
+ }
+
+ SkRandom colorRand;
+ SkColor colors[kNumGraphs];
+ for (int i = 0; i < kNumGraphs; ++i) {
+ colors[i] = colorRand.nextU() | 0xff000000;
+ }
+
+ for (int frame = 0; frame < loops; ++frame) {
+
+ canvas->clear(0xFFE0F0E0);
+
+ SkPath plotPath;
+ SkPath fillPath;
+
+ static const SkScalar kStrokeWidth = SkIntToScalar(2);
+ SkPaint plotPaint;
+ SkPaint fillPaint;
+ plotPaint.setAntiAlias(fAA);
+ plotPaint.setStyle(SkPaint::kStroke_Style);
+ plotPaint.setStrokeWidth(kStrokeWidth);
+ plotPaint.setStrokeCap(SkPaint::kRound_Cap);
+ plotPaint.setStrokeJoin(SkPaint::kRound_Join);
+ fillPaint.setAntiAlias(fAA);
+ fillPaint.setStyle(SkPaint::kFill_Style);
+
+ SkTDArray<SkScalar>* prevData = NULL;
+ for (int i = 0; i < kNumGraphs; ++i) {
+ gen_paths(fData[i],
+ prevData,
+ height,
+ 0,
+ SkIntToScalar(kPixelsPerTick),
+ fShift,
+ &plotPath,
+ &fillPath);
+
+ // Make the fills partially transparent
+ fillPaint.setColor((colors[i] & 0x00ffffff) | 0x80000000);
+ canvas->drawPath(fillPath, fillPaint);
+
+ plotPaint.setColor(colors[i]);
+ canvas->drawPath(plotPath, plotPaint);
+
+ prevData = fData + i;
+ }
+
+ fShift += kShiftPerFrame;
+ }
+ }
+
+private:
+ enum {
+ kNumGraphs = 5,
+ kPixelsPerTick = 3,
+ kShiftPerFrame = 1,
+ };
+ int fShift;
+ SkISize fSize;
+ SkTDArray<SkScalar> fData[kNumGraphs];
+ bool fAA;
+
+ typedef Benchmark INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH( return new ChartBench(true); )
+DEF_BENCH( return new ChartBench(false); )
diff --git a/chromium/third_party/skia/bench/ChecksumBench.cpp b/chromium/third_party/skia/bench/ChecksumBench.cpp
new file mode 100644
index 00000000000..7d3ec9ff9f4
--- /dev/null
+++ b/chromium/third_party/skia/bench/ChecksumBench.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "Benchmark.h"
+#include "SkCanvas.h"
+#include "SkChecksum.h"
+#include "SkMD5.h"
+#include "SkRandom.h"
+#include "SkSHA1.h"
+#include "SkTemplates.h"
+
+enum ChecksumType {
+ kChecksum_ChecksumType,
+ kMD5_ChecksumType,
+ kSHA1_ChecksumType,
+ kMurmur3_ChecksumType,
+};
+
+class ComputeChecksumBench : public Benchmark {
+ enum {
+ U32COUNT = 256,
+ SIZE = U32COUNT * 4,
+ };
+ uint32_t fData[U32COUNT];
+ ChecksumType fType;
+
+public:
+ ComputeChecksumBench(ChecksumType type) : fType(type) {
+ SkRandom rand;
+ for (int i = 0; i < U32COUNT; ++i) {
+ fData[i] = rand.nextU();
+ }
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+protected:
+ virtual const char* onGetName() {
+ switch (fType) {
+ case kChecksum_ChecksumType: return "compute_checksum";
+ case kMD5_ChecksumType: return "compute_md5";
+ case kSHA1_ChecksumType: return "compute_sha1";
+ case kMurmur3_ChecksumType: return "compute_murmur3";
+
+ default: SK_CRASH(); return "";
+ }
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) {
+ switch (fType) {
+ case kChecksum_ChecksumType: {
+ for (int i = 0; i < loops; i++) {
+ volatile uint32_t result = SkChecksum::Compute(fData, sizeof(fData));
+ sk_ignore_unused_variable(result);
+ }
+ } break;
+ case kMD5_ChecksumType: {
+ for (int i = 0; i < loops; i++) {
+ SkMD5 md5;
+ md5.update(reinterpret_cast<uint8_t*>(fData), sizeof(fData));
+ SkMD5::Digest digest;
+ md5.finish(digest);
+ }
+ } break;
+ case kSHA1_ChecksumType: {
+ for (int i = 0; i < loops; i++) {
+ SkSHA1 sha1;
+ sha1.update(reinterpret_cast<uint8_t*>(fData), sizeof(fData));
+ SkSHA1::Digest digest;
+ sha1.finish(digest);
+ }
+ } break;
+ case kMurmur3_ChecksumType: {
+ for (int i = 0; i < loops; i++) {
+ volatile uint32_t result = SkChecksum::Murmur3(fData, sizeof(fData));
+ sk_ignore_unused_variable(result);
+ }
+ }break;
+ }
+
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH( return new ComputeChecksumBench(kChecksum_ChecksumType); )
+DEF_BENCH( return new ComputeChecksumBench(kMD5_ChecksumType); )
+DEF_BENCH( return new ComputeChecksumBench(kSHA1_ChecksumType); )
+DEF_BENCH( return new ComputeChecksumBench(kMurmur3_ChecksumType); )
diff --git a/chromium/third_party/skia/bench/ChromeBench.cpp b/chromium/third_party/skia/bench/ChromeBench.cpp
new file mode 100644
index 00000000000..493878526a5
--- /dev/null
+++ b/chromium/third_party/skia/bench/ChromeBench.cpp
@@ -0,0 +1,496 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "Benchmark.h"
+#include "SkCanvas.h"
+#include "SkPaint.h"
+#include "SkString.h"
+
+/**
+ Benchmarks that try to emulate a particular Skia call pattern observed in Chrome.
+*/
+
+/// blitRect() calls emitted by Chrome while scrolling through gmail: count, width, height.
+int gmailScrollingRectSpec [431*3] = {
+ 1, 1254, 1160,
+ 1, 64, 112,
+ 1, 1034, 261,
+ 1, 1166, 1,
+ 1, 1166, 20,
+ 1, 1254, 40,
+ 1, 140, 20,
+ 1, 22, 30,
+ 1, 22, 39,
+ 1, 294, 29,
+ 1, 336, 25,
+ 1, 336, 5,
+ 1, 37, 3,
+ 1, 37, 4,
+ 1, 37, 5,
+ 1, 41, 29,
+ 1, 57, 15,
+ 1, 72, 5,
+ 1, 72, 8,
+ 1, 76, 29,
+ 1, 981, 88,
+ 1, 990, 2,
+ 1, 990, 6,
+ 2, 220, 88,
+ 2, 294, 1,
+ 2, 37, 6,
+ 2, 391, 55,
+ 2, 57, 11,
+ 2, 57, 14,
+ 2, 57, 7,
+ 2, 981, 30,
+ 2, 990, 15,
+ 2, 990, 19,
+ 3, 114, 16,
+ 3, 1166, 39,
+ 3, 1254, 154,
+ 3, 12, 12,
+ 3, 162, 7,
+ 3, 164, 479,
+ 3, 167, 449,
+ 3, 16, 24,
+ 3, 204, 497,
+ 3, 205, 434,
+ 3, 220, 1127,
+ 3, 220, 1132,
+ 3, 220, 931,
+ 3, 220, 933,
+ 3, 220, 934,
+ 3, 297, 8,
+ 3, 72, 25,
+ 3, 87, 30,
+ 3, 981, 1,
+ 3, 981, 126,
+ 3, 990, 27,
+ 3, 990, 36,
+ 3, 991, 29,
+ 4, 1254, 306,
+ 4, 1254, 36,
+ 4, 1, 1,
+ 4, 1, 14,
+ 4, 1, 19,
+ 4, 1, 7,
+ 4, 21, 21,
+ 4, 220, 30,
+ 4, 46, 949,
+ 4, 509, 30,
+ 4, 57, 2,
+ 4, 57, 6,
+ 4, 990, 11,
+ 5, 13, 8,
+ 5, 198, 24,
+ 5, 24, 24,
+ 5, 25, 24,
+ 5, 2, 24,
+ 5, 37, 33,
+ 5, 57, 4,
+ 5, 599, 24,
+ 5, 90, 24,
+ 5, 981, 19,
+ 5, 990, 23,
+ 5, 990, 8,
+ 6, 101, 29,
+ 6, 117, 29,
+ 6, 1254, 88,
+ 6, 139, 29,
+ 6, 13, 12,
+ 6, 15, 15,
+ 6, 164, 25,
+ 6, 16, 16,
+ 6, 198, 7,
+ 6, 1, 12,
+ 6, 1, 15,
+ 6, 1, 27,
+ 6, 220, 936,
+ 6, 24, 7,
+ 6, 25, 7,
+ 6, 2, 7,
+ 6, 326, 29,
+ 6, 336, 29,
+ 6, 599, 7,
+ 6, 86, 29,
+ 6, 90, 7,
+ 6, 96, 29,
+ 6, 991, 31,
+ 7, 198, 12,
+ 7, 198, 20,
+ 7, 198, 33,
+ 7, 198, 35,
+ 7, 24, 12,
+ 7, 24, 20,
+ 7, 24, 33,
+ 7, 24, 35,
+ 7, 25, 12,
+ 7, 25, 20,
+ 7, 25, 33,
+ 7, 25, 35,
+ 7, 2, 12,
+ 7, 2, 20,
+ 7, 2, 33,
+ 7, 2, 35,
+ 7, 304, 1,
+ 7, 38, 29,
+ 7, 51, 29,
+ 7, 599, 12,
+ 7, 599, 20,
+ 7, 599, 33,
+ 7, 599, 35,
+ 7, 90, 12,
+ 7, 90, 20,
+ 7, 90, 33,
+ 7, 90, 35,
+ 8, 13, 5,
+ 8, 198, 13,
+ 8, 198, 23,
+ 8, 220, 1,
+ 8, 24, 13,
+ 8, 24, 23,
+ 8, 25, 13,
+ 8, 25, 23,
+ 8, 2, 13,
+ 8, 2, 23,
+ 8, 329, 28,
+ 8, 57, 10,
+ 8, 599, 13,
+ 8, 599, 23,
+ 8, 90, 13,
+ 8, 90, 23,
+ 9, 198, 17,
+ 9, 198, 19,
+ 9, 198, 37,
+ 9, 198, 5,
+ 9, 198, 8,
+ 9, 24, 17,
+ 9, 24, 19,
+ 9, 24, 37,
+ 9, 24, 5,
+ 9, 24, 8,
+ 9, 25, 17,
+ 9, 25, 19,
+ 9, 25, 37,
+ 9, 25, 5,
+ 9, 25, 8,
+ 9, 2, 17,
+ 9, 2, 19,
+ 9, 2, 37,
+ 9, 2, 5,
+ 9, 2, 8,
+ 9, 599, 17,
+ 9, 599, 19,
+ 9, 599, 37,
+ 9, 599, 5,
+ 9, 599, 8,
+ 9, 72, 29,
+ 9, 90, 17,
+ 9, 90, 19,
+ 9, 90, 37,
+ 9, 90, 5,
+ 9, 90, 8,
+ 10, 13, 11,
+ 10, 13, 9,
+ 10, 198, 26,
+ 10, 198, 28,
+ 10, 1, 23,
+ 10, 1, 4,
+ 10, 1, 6,
+ 10, 24, 26,
+ 10, 24, 28,
+ 10, 25, 26,
+ 10, 25, 28,
+ 10, 26, 24,
+ 10, 2, 26,
+ 10, 2, 28,
+ 10, 599, 26,
+ 10, 599, 28,
+ 10, 90, 26,
+ 10, 90, 28,
+ 11, 198, 27,
+ 11, 24, 27,
+ 11, 25, 27,
+ 11, 2, 27,
+ 11, 599, 27,
+ 11, 90, 27,
+ 12, 198, 14,
+ 12, 198, 21,
+ 12, 198, 3,
+ 12, 1, 11,
+ 12, 1, 2,
+ 12, 1, 8,
+ 12, 24, 14,
+ 12, 24, 21,
+ 12, 24, 3,
+ 12, 25, 14,
+ 12, 25, 21,
+ 12, 25, 3,
+ 12, 26, 7,
+ 12, 2, 14,
+ 12, 2, 21,
+ 12, 2, 3,
+ 12, 329, 14,
+ 12, 38, 2,
+ 12, 599, 14,
+ 12, 599, 21,
+ 12, 599, 3,
+ 12, 90, 14,
+ 12, 90, 21,
+ 12, 90, 3,
+ 13, 198, 11,
+ 13, 198, 15,
+ 13, 198, 31,
+ 13, 24, 11,
+ 13, 24, 15,
+ 13, 24, 31,
+ 13, 25, 11,
+ 13, 25, 15,
+ 13, 25, 31,
+ 13, 2, 11,
+ 13, 2, 15,
+ 13, 2, 31,
+ 13, 57, 13,
+ 13, 599, 11,
+ 13, 599, 15,
+ 13, 599, 31,
+ 13, 71, 29,
+ 13, 90, 11,
+ 13, 90, 15,
+ 13, 90, 31,
+ 14, 13, 2,
+ 14, 198, 10,
+ 14, 24, 10,
+ 14, 25, 10,
+ 14, 26, 12,
+ 14, 26, 20,
+ 14, 26, 33,
+ 14, 26, 35,
+ 14, 2, 10,
+ 14, 336, 1,
+ 14, 45, 29,
+ 14, 599, 10,
+ 14, 63, 29,
+ 14, 90, 10,
+ 15, 13, 3,
+ 15, 198, 2,
+ 15, 198, 29,
+ 15, 198, 34,
+ 15, 24, 2,
+ 15, 24, 29,
+ 15, 24, 34,
+ 15, 25, 2,
+ 15, 25, 29,
+ 15, 25, 34,
+ 15, 2, 2,
+ 15, 2, 29,
+ 15, 2, 34,
+ 15, 599, 2,
+ 15, 599, 29,
+ 15, 599, 34,
+ 15, 90, 2,
+ 15, 90, 29,
+ 15, 90, 34,
+ 16, 13, 4,
+ 16, 13, 6,
+ 16, 198, 16,
+ 16, 198, 9,
+ 16, 1, 10,
+ 16, 24, 16,
+ 16, 24, 9,
+ 16, 25, 16,
+ 16, 25, 9,
+ 16, 26, 13,
+ 16, 26, 23,
+ 16, 2, 16,
+ 16, 2, 9,
+ 16, 599, 16,
+ 16, 599, 9,
+ 16, 90, 16,
+ 16, 90, 9,
+ 17, 13, 7,
+ 17, 198, 18,
+ 17, 24, 18,
+ 17, 25, 18,
+ 17, 2, 18,
+ 17, 599, 18,
+ 17, 90, 18,
+ 18, 198, 22,
+ 18, 198, 32,
+ 18, 198, 36,
+ 18, 198, 4,
+ 18, 24, 22,
+ 18, 24, 32,
+ 18, 24, 36,
+ 18, 24, 4,
+ 18, 25, 22,
+ 18, 25, 32,
+ 18, 25, 36,
+ 18, 25, 4,
+ 18, 26, 17,
+ 18, 26, 19,
+ 18, 26, 37,
+ 18, 26, 5,
+ 18, 26, 8,
+ 18, 2, 22,
+ 18, 2, 32,
+ 18, 2, 36,
+ 18, 2, 4,
+ 18, 599, 22,
+ 18, 599, 32,
+ 18, 599, 36,
+ 18, 599, 4,
+ 18, 90, 22,
+ 18, 90, 32,
+ 18, 90, 36,
+ 18, 90, 4,
+ 19, 13, 10,
+ 20, 1254, 30,
+ 20, 16, 1007,
+ 20, 26, 26,
+ 20, 26, 28,
+ 21, 198, 6,
+ 21, 24, 6,
+ 21, 25, 6,
+ 21, 2, 6,
+ 21, 599, 6,
+ 21, 90, 6,
+ 22, 198, 38,
+ 22, 22, 40,
+ 22, 24, 38,
+ 22, 25, 38,
+ 22, 26, 27,
+ 22, 2, 38,
+ 22, 599, 38,
+ 22, 90, 38,
+ 23, 1254, 1160,
+ 24, 220, 930,
+ 24, 26, 14,
+ 24, 26, 21,
+ 24, 26, 3,
+ 26, 11, 11,
+ 26, 1, 13,
+ 26, 26, 11,
+ 26, 26, 15,
+ 26, 26, 31,
+ 28, 26, 10,
+ 30, 176, 60,
+ 30, 26, 2,
+ 30, 26, 29,
+ 30, 26, 34,
+ 32, 26, 16,
+ 32, 26, 9,
+ 34, 26, 18,
+ 36, 26, 22,
+ 36, 26, 32,
+ 36, 26, 36,
+ 36, 26, 4,
+ 36, 37, 26,
+ 42, 26, 6,
+ 43, 115, 29,
+ 44, 198, 25,
+ 44, 24, 25,
+ 44, 25, 25,
+ 44, 26, 38,
+ 44, 2, 25,
+ 44, 599, 25,
+ 44, 90, 25,
+ 46, 22, 1,
+ 47, 198, 30,
+ 47, 25, 30,
+ 47, 2, 30,
+ 47, 599, 30,
+ 47, 90, 30,
+ 48, 24, 30,
+ 52, 176, 30,
+ 58, 140, 24,
+ 58, 4, 30,
+ 63, 990, 29,
+ 64, 1254, 1,
+ 88, 26, 25,
+ 92, 198, 39,
+ 92, 25, 39,
+ 92, 2, 39,
+ 92, 599, 39,
+ 92, 90, 39,
+ 93, 24, 39,
+ 94, 26, 30,
+ 108, 1254, 1051,
+ 117, 140, 1,
+ 119, 160, 1,
+ 126, 1, 29,
+ 132, 135, 16,
+ 147, 72, 16,
+ 184, 26, 39,
+ 238, 990, 1,
+ 376, 11, 1007,
+ 380, 11, 487,
+ 1389, 1034, 1007,
+ 1870, 57, 16,
+ 4034, 1, 16,
+ 8521, 198, 40,
+ 8521, 25, 40,
+ 8521, 2, 40,
+ 8521, 599, 40,
+ 8521, 90, 40,
+ 8543, 24, 40,
+ 8883, 13, 13,
+ 17042, 26, 40,
+ 17664, 198, 1,
+ 17664, 25, 1,
+ 17664, 2, 1,
+ 17664, 599, 1,
+ 17664, 90, 1,
+ 17710, 24, 1,
+ 35328, 26, 1,
+};
+
+/// Emulates the mix of rects blitted by gmail during scrolling
+class ScrollGmailBench : public Benchmark {
+ enum {
+ W = 1254,
+ H = 1160,
+ N = 431
+ };
+public:
+ ScrollGmailBench() { }
+
+protected:
+
+ virtual const char* onGetName() { return "chrome_scrollGmail"; }
+ virtual void onDraw(const int loops, SkCanvas* canvas) {
+ SkDEBUGCODE(this->validateBounds(canvas));
+ SkPaint paint;
+ this->setupPaint(&paint);
+ for (int i = 0; i < N; i++) {
+ SkRect current;
+ setRectangle(current, i);
+ for (int j = 0; j < loops * gmailScrollingRectSpec[i*3]; j++) {
+ canvas->drawRect(current, paint);
+ }
+ }
+ }
+ virtual SkIPoint onGetSize() { return SkIPoint::Make(W, H); }
+
+ void setRectangle(SkRect& current, int i) {
+ current.set(0, 0,
+ SkIntToScalar(gmailScrollingRectSpec[i*3+1]), SkIntToScalar(gmailScrollingRectSpec[i*3+2]));
+ }
+ void validateBounds(SkCanvas* canvas) {
+ SkIRect bounds;
+ canvas->getClipDeviceBounds(&bounds);
+ SkASSERT(bounds.right()-bounds.left() >= W);
+ SkASSERT(bounds.bottom()-bounds.top() >= H);
+ }
+
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+// Disabled this benchmark: it takes 15x longer than any other benchmark
+// and is probably not giving us important information.
+// DEF_BENCH(return SkNEW(ScrollGmailBench));
diff --git a/chromium/third_party/skia/bench/CmapBench.cpp b/chromium/third_party/skia/bench/CmapBench.cpp
new file mode 100644
index 00000000000..db4ed74951b
--- /dev/null
+++ b/chromium/third_party/skia/bench/CmapBench.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkCanvas.h"
+#include "SkPaint.h"
+#include "SkTypeface.h"
+
+enum {
+ NGLYPHS = 100
+};
+
+static SkTypeface::Encoding paint2Encoding(const SkPaint& paint) {
+ SkPaint::TextEncoding enc = paint.getTextEncoding();
+ SkASSERT(SkPaint::kGlyphID_TextEncoding != enc);
+ return (SkTypeface::Encoding)enc;
+}
+
+typedef void (*TypefaceProc)(int loops, const SkPaint&, const void* text, size_t len,
+ int glyphCount);
+
+static void containsText_proc(int loops, const SkPaint& paint, const void* text, size_t len,
+ int glyphCount) {
+ for (int i = 0; i < loops; ++i) {
+ paint.containsText(text, len);
+ }
+}
+
+static void textToGlyphs_proc(int loops, const SkPaint& paint, const void* text, size_t len,
+ int glyphCount) {
+ uint16_t glyphs[NGLYPHS];
+ SkASSERT(glyphCount <= NGLYPHS);
+
+ for (int i = 0; i < loops; ++i) {
+ paint.textToGlyphs(text, len, glyphs);
+ }
+}
+
+static void charsToGlyphs_proc(int loops, const SkPaint& paint, const void* text,
+ size_t len, int glyphCount) {
+ SkTypeface::Encoding encoding = paint2Encoding(paint);
+ uint16_t glyphs[NGLYPHS];
+ SkASSERT(glyphCount <= NGLYPHS);
+
+ SkTypeface* face = paint.getTypeface();
+ for (int i = 0; i < loops; ++i) {
+ face->charsToGlyphs(text, encoding, glyphs, glyphCount);
+ }
+}
+
+static void charsToGlyphsNull_proc(int loops, const SkPaint& paint, const void* text,
+ size_t len, int glyphCount) {
+ SkTypeface::Encoding encoding = paint2Encoding(paint);
+
+ SkTypeface* face = paint.getTypeface();
+ for (int i = 0; i < loops; ++i) {
+ face->charsToGlyphs(text, encoding, NULL, glyphCount);
+ }
+}
+
+class CMAPBench : public Benchmark {
+ TypefaceProc fProc;
+ SkString fName;
+ char fText[NGLYPHS];
+ SkPaint fPaint;
+
+public:
+ CMAPBench(TypefaceProc proc, const char name[]) {
+ fProc = proc;
+ fName.printf("cmap_%s", name);
+
+ for (int i = 0; i < NGLYPHS; ++i) {
+ // we're jamming values into utf8, so we must keep it legal utf8
+ fText[i] = 'A' + (i & 31);
+ }
+ fPaint.setTypeface(SkTypeface::RefDefault())->unref();
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ fProc(loops, fPaint, fText, sizeof(fText), NGLYPHS);
+ }
+
+private:
+
+ typedef Benchmark INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH( return new CMAPBench(containsText_proc, "paint_containsText"); )
+DEF_BENCH( return new CMAPBench(textToGlyphs_proc, "paint_textToGlyphs"); )
+DEF_BENCH( return new CMAPBench(charsToGlyphs_proc, "face_charsToGlyphs"); )
+DEF_BENCH( return new CMAPBench(charsToGlyphsNull_proc, "face_charsToGlyphs_null"); )
diff --git a/chromium/third_party/skia/bench/ColorFilterBench.cpp b/chromium/third_party/skia/bench/ColorFilterBench.cpp
new file mode 100644
index 00000000000..7eae21aa757
--- /dev/null
+++ b/chromium/third_party/skia/bench/ColorFilterBench.cpp
@@ -0,0 +1,367 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "Benchmark.h"
+#include "SkCanvas.h"
+#include "SkColorFilterImageFilter.h"
+#include "SkColorMatrixFilter.h"
+#include "SkLumaColorFilter.h"
+#include "SkTableColorFilter.h"
+
+#define FILTER_WIDTH_SMALL SkIntToScalar(32)
+#define FILTER_HEIGHT_SMALL SkIntToScalar(32)
+#define FILTER_WIDTH_LARGE SkIntToScalar(256)
+#define FILTER_HEIGHT_LARGE SkIntToScalar(256)
+
+class ColorFilterBaseBench : public Benchmark {
+
+public:
+ ColorFilterBaseBench(bool small) : fIsSmall(small) { }
+
+protected:
+ SkRect getFilterRect() const {
+ return isSmall() ? SkRect::MakeWH(FILTER_WIDTH_SMALL, FILTER_HEIGHT_SMALL) :
+ SkRect::MakeWH(FILTER_WIDTH_LARGE, FILTER_HEIGHT_LARGE);
+ }
+
+ static SkImageFilter* make_brightness(float amount, SkImageFilter* input = NULL) {
+ SkScalar amount255 = SkScalarMul(amount, SkIntToScalar(255));
+ SkScalar matrix[20] = { 1, 0, 0, 0, amount255,
+ 0, 1, 0, 0, amount255,
+ 0, 0, 1, 0, amount255,
+ 0, 0, 0, 1, 0 };
+ SkAutoTUnref<SkColorFilter> filter(SkColorMatrixFilter::Create(matrix));
+ return SkColorFilterImageFilter::Create(filter, input);
+ }
+
+ static SkImageFilter* make_grayscale(SkImageFilter* input = NULL) {
+ SkScalar matrix[20];
+ memset(matrix, 0, 20 * sizeof(SkScalar));
+ matrix[0] = matrix[5] = matrix[10] = 0.2126f;
+ matrix[1] = matrix[6] = matrix[11] = 0.7152f;
+ matrix[2] = matrix[7] = matrix[12] = 0.0722f;
+ matrix[18] = 1.0f;
+ SkAutoTUnref<SkColorFilter> filter(SkColorMatrixFilter::Create(matrix));
+ return SkColorFilterImageFilter::Create(filter, input);
+ }
+
+ static SkImageFilter* make_mode_blue(SkImageFilter* input = NULL) {
+ SkAutoTUnref<SkColorFilter> filter(
+ SkColorFilter::CreateModeFilter(SK_ColorBLUE, SkXfermode::kSrcIn_Mode));
+ return SkColorFilterImageFilter::Create(filter, input);
+ }
+
+ inline bool isSmall() const { return fIsSmall; }
+private:
+ bool fIsSmall;
+
+ typedef Benchmark INHERITED;
+};
+
+class ColorFilterDimBrightBench : public ColorFilterBaseBench {
+
+public:
+ ColorFilterDimBrightBench(bool small) : INHERITED(small) {
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return isSmall() ? "colorfilter_dim_bright_small" : "colorfilter_dim_bright_large";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkRect r = getFilterRect();
+ SkPaint paint;
+ paint.setColor(SK_ColorRED);
+
+ for (int i = 0; i < loops; i++) {
+ for (float brightness = -1.0f; brightness <= 1.0f; brightness += 0.4f) {
+ SkAutoTUnref<SkImageFilter> dim(make_brightness(-brightness));
+ SkAutoTUnref<SkImageFilter> bright(make_brightness(brightness, dim));
+ paint.setImageFilter(bright);
+ canvas->drawRect(r, paint);
+ }
+ }
+ }
+
+private:
+ typedef ColorFilterBaseBench INHERITED;
+};
+
+class ColorFilterBrightGrayBench : public ColorFilterBaseBench {
+
+public:
+ ColorFilterBrightGrayBench(bool small) : INHERITED(small) {
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return isSmall() ? "colorfilter_bright_gray_small" : "colorfilter_bright_gray_large";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkRect r = getFilterRect();
+ SkPaint paint;
+ paint.setColor(SK_ColorRED);
+ for (int i = 0; i < loops; i++) {
+ SkAutoTUnref<SkImageFilter> brightness(make_brightness(0.9f));
+ SkAutoTUnref<SkImageFilter> grayscale(make_grayscale(brightness));
+ paint.setImageFilter(grayscale);
+ canvas->drawRect(r, paint);
+ }
+ }
+
+private:
+ typedef ColorFilterBaseBench INHERITED;
+};
+
+class ColorFilterGrayBrightBench : public ColorFilterBaseBench {
+
+public:
+ ColorFilterGrayBrightBench(bool small) : INHERITED(small) {
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return isSmall() ? "colorfilter_gray_bright_small" : "colorfilter_gray_bright_large";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkRect r = getFilterRect();
+ SkPaint paint;
+ paint.setColor(SK_ColorRED);
+ for (int i = 0; i < loops; i++) {
+ SkAutoTUnref<SkImageFilter> grayscale(make_grayscale());
+ SkAutoTUnref<SkImageFilter> brightness(make_brightness(0.9f, grayscale));
+ paint.setImageFilter(brightness);
+ canvas->drawRect(r, paint);
+ }
+ }
+
+private:
+ typedef ColorFilterBaseBench INHERITED;
+};
+
+class ColorFilterBlueBrightBench : public ColorFilterBaseBench {
+
+public:
+ ColorFilterBlueBrightBench(bool small) : INHERITED(small) {
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return isSmall() ? "colorfilter_blue_bright_small" : "colorfilter_blue_bright_large";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkRect r = getFilterRect();
+ SkPaint paint;
+ paint.setColor(SK_ColorRED);
+ for (int i = 0; i < loops; i++) {
+ SkAutoTUnref<SkImageFilter> blue(make_mode_blue());
+ SkAutoTUnref<SkImageFilter> brightness(make_brightness(1.0f, blue));
+ paint.setImageFilter(brightness);
+ canvas->drawRect(r, paint);
+ }
+ }
+
+private:
+ typedef ColorFilterBaseBench INHERITED;
+};
+
+class ColorFilterBrightBlueBench : public ColorFilterBaseBench {
+
+public:
+ ColorFilterBrightBlueBench(bool small) : INHERITED(small) {
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return isSmall() ? "colorfilter_bright_blue_small" : "colorfilter_bright_blue_large";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkRect r = getFilterRect();
+ SkPaint paint;
+ paint.setColor(SK_ColorRED);
+ for (int i = 0; i < loops; i++) {
+ SkAutoTUnref<SkImageFilter> brightness(make_brightness(1.0f));
+ SkAutoTUnref<SkImageFilter> blue(make_mode_blue(brightness));
+ paint.setImageFilter(blue);
+ canvas->drawRect(r, paint);
+ }
+ }
+
+private:
+ typedef ColorFilterBaseBench INHERITED;
+};
+
+class ColorFilterBrightBench : public ColorFilterBaseBench {
+
+public:
+ ColorFilterBrightBench(bool small) : INHERITED(small) {
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return isSmall() ? "colorfilter_bright_small" : "colorfilter_bright_large";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkRect r = getFilterRect();
+ SkPaint paint;
+ paint.setColor(SK_ColorRED);
+ for (int i = 0; i < loops; i++) {
+ SkAutoTUnref<SkImageFilter> brightness(make_brightness(1.0f));
+ paint.setImageFilter(brightness);
+ canvas->drawRect(r, paint);
+ }
+ }
+
+private:
+ typedef ColorFilterBaseBench INHERITED;
+};
+
+class ColorFilterBlueBench : public ColorFilterBaseBench {
+
+public:
+ ColorFilterBlueBench(bool small) : INHERITED(small) {
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return isSmall() ? "colorfilter_blue_small" : "colorfilter_blue_large";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkRect r = getFilterRect();
+ SkPaint paint;
+ paint.setColor(SK_ColorRED);
+ for (int i = 0; i < loops; i++) {
+ SkAutoTUnref<SkImageFilter> blue(make_mode_blue());
+ paint.setImageFilter(blue);
+ canvas->drawRect(r, paint);
+ }
+ }
+
+private:
+ typedef ColorFilterBaseBench INHERITED;
+};
+
+class ColorFilterGrayBench : public ColorFilterBaseBench {
+
+public:
+ ColorFilterGrayBench(bool small) : INHERITED(small) {
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return isSmall() ? "colorfilter_gray_small" : "colorfilter_gray_large";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkRect r = getFilterRect();
+ SkPaint paint;
+ paint.setColor(SK_ColorRED);
+ for (int i = 0; i < loops; i++) {
+ SkAutoTUnref<SkImageFilter> grayscale(make_grayscale());
+ paint.setImageFilter(grayscale);
+ canvas->drawRect(r, paint);
+ }
+ }
+
+private:
+ typedef ColorFilterBaseBench INHERITED;
+};
+
+class TableColorFilterBench : public ColorFilterBaseBench {
+
+public:
+ TableColorFilterBench(bool small) : INHERITED(small) {
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return isSmall() ? "table_colorfilter_small" : "table_colorfilter_large";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkRect r = getFilterRect();
+ SkPaint paint;
+ paint.setColor(SK_ColorRED);
+ for (int i = 0; i < loops; i++) {
+ SkAutoTUnref<SkColorFilter> table_filter(make_table_filter());
+ paint.setColorFilter(table_filter);
+ canvas->drawRect(r, paint);
+ }
+ }
+
+private:
+ static void fill_table_data(uint8_t table[]) {
+ for (int i = 0; i < 256; ++i) {
+ int n = i >> 5;
+ table[i] = (n << 5) | (n << 2) | (n >> 1);
+ }
+ }
+
+ static SkColorFilter* make_table_filter() {
+ uint8_t table[256]; fill_table_data(table);
+ return SkTableColorFilter::Create(table);
+ }
+
+ typedef ColorFilterBaseBench INHERITED;
+};
+
+class LumaColorFilterBench : public ColorFilterBaseBench {
+
+public:
+ LumaColorFilterBench(bool small) : INHERITED(small) {
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return isSmall() ? "luma_colorfilter_small" : "luma_colorfilter_large";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkRect r = getFilterRect();
+ SkPaint paint;
+ paint.setColor(SK_ColorRED);
+
+ for (int i = 0; i < loops; i++) {
+ SkAutoTUnref<SkColorFilter> luma_filter(SkLumaColorFilter::Create());
+ paint.setColorFilter(luma_filter);
+ canvas->drawRect(r, paint);
+ }
+ }
+
+private:
+ typedef ColorFilterBaseBench INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH( return new ColorFilterDimBrightBench(true); )
+DEF_BENCH( return new ColorFilterBrightGrayBench(true); )
+DEF_BENCH( return new ColorFilterGrayBrightBench(true); )
+DEF_BENCH( return new ColorFilterBlueBrightBench(true); )
+DEF_BENCH( return new ColorFilterBrightBlueBench(true); )
+DEF_BENCH( return new ColorFilterBrightBench(true); )
+DEF_BENCH( return new ColorFilterBlueBench(true); )
+DEF_BENCH( return new ColorFilterGrayBench(true); )
+DEF_BENCH( return new TableColorFilterBench(true); )
+DEF_BENCH( return new LumaColorFilterBench(true); )
+
+DEF_BENCH( return new ColorFilterDimBrightBench(false); )
+DEF_BENCH( return new ColorFilterBrightGrayBench(false); )
+DEF_BENCH( return new ColorFilterGrayBrightBench(false); )
+DEF_BENCH( return new ColorFilterBlueBrightBench(false); )
+DEF_BENCH( return new ColorFilterBrightBlueBench(false); )
+DEF_BENCH( return new ColorFilterBrightBench(false); )
+DEF_BENCH( return new ColorFilterBlueBench(false); )
+DEF_BENCH( return new ColorFilterGrayBench(false); )
+DEF_BENCH( return new TableColorFilterBench(false); )
+DEF_BENCH( return new LumaColorFilterBench(false); )
diff --git a/chromium/third_party/skia/bench/ColorPrivBench.cpp b/chromium/third_party/skia/bench/ColorPrivBench.cpp
new file mode 100644
index 00000000000..01810ed2399
--- /dev/null
+++ b/chromium/third_party/skia/bench/ColorPrivBench.cpp
@@ -0,0 +1,81 @@
+#include "Benchmark.h"
+#include "SkColorPriv.h"
+#include "SkRandom.h"
+#include "SkString.h"
+
+template <bool kFast, bool kScale>
+class FourByteInterpBench : public Benchmark {
+public:
+ FourByteInterpBench() {
+ fName.set("four_byte_interp");
+ fName.append(kFast ? "_fast" : "_slow");
+ fName.append(kScale ? "_255" : "_256");
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+ virtual const char* onGetName() SK_OVERRIDE { return fName.c_str(); }
+
+ virtual void onPreDraw() SK_OVERRIDE {
+ // A handful of random srcs and dsts.
+ SkRandom rand;
+ for (int i = 0; i < kInputs; i++) {
+ fSrcs[i] = SkPreMultiplyColor(rand.nextU());
+ fDsts[i] = SkPreMultiplyColor(rand.nextU());
+ }
+
+ // We'll exhaustively test all scales instead of using random numbers.
+ for (int i = 0; i <= 256; i++) {
+ fScales[i] = i;
+ }
+ if (kScale) fScales[256] = 255; // We'll just do 255 twice if we're limited to [0,255].
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
+ // We xor results of FourByteInterp into junk to make sure the function runs.
+ volatile SkPMColor junk = 0;
+
+ for (int loop = 0; loop < loops; loop++) {
+ for (int i = 0; i < kInputs; i++) {
+ for (size_t j = 0; j <= 256; j++) {
+ // Note: we really want to load src and dst here and not outside in the i-loop.
+ // If we put the loads there, a clever compiler will do the not-insignificant
+ // work in the FourByteInterps that depends only on src and dst outside this
+ // loop, so we'd only be benchmarking the back half of those functions that also
+ // depends on scale. Even here, these must be volatile arrays to prevent that
+ // clever compiler from hoisting the loads out of the loop on its own.
+ const SkPMColor src = fSrcs[i];
+ const SkPMColor dst = fDsts[i];
+
+ const unsigned scale = fScales[j];
+
+ if (kFast && kScale) {
+ junk ^= SkFastFourByteInterp(src, dst, scale);
+ } else if (kFast) {
+ junk ^= SkFastFourByteInterp256(src, dst, scale);
+ } else if (kScale) {
+ junk ^= SkFourByteInterp(src, dst, scale);
+ } else {
+ junk ^= SkFourByteInterp256(src, dst, scale);
+ }
+ }
+ }
+ }
+ }
+
+private:
+ SkString fName;
+ static const int kInputs = 10; // Arbitrary.
+ volatile unsigned fSrcs[kInputs];
+ volatile unsigned fDsts[kInputs];
+ unsigned fScales[257]; // We need space for [0, 256].
+};
+
+#define COMMA ,
+DEF_BENCH( return SkNEW(FourByteInterpBench<true COMMA true>); )
+DEF_BENCH( return SkNEW(FourByteInterpBench<true COMMA false>); )
+DEF_BENCH( return SkNEW(FourByteInterpBench<false COMMA true>); )
+DEF_BENCH( return SkNEW(FourByteInterpBench<false COMMA false>); )
+#undef COMMA
diff --git a/chromium/third_party/skia/bench/CoverageBench.cpp b/chromium/third_party/skia/bench/CoverageBench.cpp
new file mode 100644
index 00000000000..ecb0ee6fa7c
--- /dev/null
+++ b/chromium/third_party/skia/bench/CoverageBench.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkBitmap.h"
+#include "SkCanvas.h"
+#include "SkColorPriv.h"
+#include "SkDraw.h"
+#include "SkMatrix.h"
+#include "SkPath.h"
+#include "SkRasterClip.h"
+
+class DrawPathBench : public Benchmark {
+ SkPaint fPaint;
+ SkString fName;
+ SkPath fPath;
+ SkRasterClip fRC;
+ SkBitmap fBitmap;
+ SkMatrix fIdentity;
+ SkDraw fDraw;
+ bool fDrawCoverage;
+public:
+ DrawPathBench(bool drawCoverage) : fDrawCoverage(drawCoverage) {
+ fPaint.setAntiAlias(true);
+ fName.printf("draw_coverage_%s", drawCoverage ? "true" : "false");
+
+ fPath.moveTo(0, 0);
+ fPath.quadTo(500, 0, 500, 500);
+ fPath.quadTo(250, 0, 0, 500);
+
+ fBitmap.allocPixels(SkImageInfo::MakeA8(500, 500));
+
+ fIdentity.setIdentity();
+ fRC.setRect(fPath.getBounds().round());
+
+ fDraw.fBitmap = &fBitmap;
+ fDraw.fMatrix = &fIdentity;
+ fDraw.fClip = &fRC.bwRgn();
+ fDraw.fRC = &fRC;
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ if (fDrawCoverage) {
+ for (int i = 0; i < loops; ++i) {
+ fDraw.drawPathCoverage(fPath, fPaint);
+ }
+ } else {
+ for (int i = 0; i < loops; ++i) {
+ fDraw.drawPath(fPath, fPaint);
+ }
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH( return new DrawPathBench(false) )
+DEF_BENCH( return new DrawPathBench(true) )
diff --git a/chromium/third_party/skia/bench/DashBench.cpp b/chromium/third_party/skia/bench/DashBench.cpp
new file mode 100644
index 00000000000..f4d09c66f2e
--- /dev/null
+++ b/chromium/third_party/skia/bench/DashBench.cpp
@@ -0,0 +1,489 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "Benchmark.h"
+#include "SkBitmap.h"
+#include "SkCanvas.h"
+#include "SkDashPathEffect.h"
+#include "SkPaint.h"
+#include "SkPath.h"
+#include "SkRandom.h"
+#include "SkString.h"
+#include "SkTDArray.h"
+
+
+/*
+ * Cases to consider:
+ *
+ * 1. antialiasing on/off (esp. width <= 1)
+ * 2. strokewidth == 0, 1, 2
+ * 3. hline, vline, diagonal, rect, oval
+ * 4. dots [1,1] ([N,N] where N=strokeWidth?) or arbitrary (e.g. [2,1] or [1,2,3,2])
+ */
+static void path_hline(SkPath* path) {
+ path->moveTo(SkIntToScalar(10), SkIntToScalar(10));
+ path->lineTo(SkIntToScalar(600), SkIntToScalar(10));
+}
+
+class DashBench : public Benchmark {
+protected:
+ SkString fName;
+ SkTDArray<SkScalar> fIntervals;
+ int fWidth;
+ SkPoint fPts[2];
+ bool fDoClip;
+
+public:
+ DashBench(const SkScalar intervals[], int count, int width,
+ bool doClip = false) {
+ fIntervals.append(count, intervals);
+ for (int i = 0; i < count; ++i) {
+ fIntervals[i] *= width;
+ }
+ fWidth = width;
+ fName.printf("dash_%d_%s", width, doClip ? "clipped" : "noclip");
+ fDoClip = doClip;
+
+ fPts[0].set(SkIntToScalar(10), SkIntToScalar(10));
+ fPts[1].set(SkIntToScalar(600), SkIntToScalar(10));
+ }
+
+ virtual void makePath(SkPath* path) {
+ path_hline(path);
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkPaint paint;
+ this->setupPaint(&paint);
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(SkIntToScalar(fWidth));
+ paint.setAntiAlias(false);
+
+ SkPath path;
+ this->makePath(&path);
+
+ paint.setPathEffect(SkDashPathEffect::Create(fIntervals.begin(),
+ fIntervals.count(), 0))->unref();
+
+ if (fDoClip) {
+ SkRect r = path.getBounds();
+ r.inset(-SkIntToScalar(20), -SkIntToScalar(20));
+ // now move it so we don't intersect
+ r.offset(0, r.height() * 3 / 2);
+ canvas->clipRect(r);
+ }
+
+ this->handlePath(canvas, path, paint, loops);
+ }
+
+ virtual void handlePath(SkCanvas* canvas, const SkPath& path,
+ const SkPaint& paint, int N) {
+ for (int i = 0; i < N; ++i) {
+// canvas->drawPoints(SkCanvas::kLines_PointMode, 2, fPts, paint);
+ canvas->drawPath(path, paint);
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+class RectDashBench : public DashBench {
+public:
+ RectDashBench(const SkScalar intervals[], int count, int width)
+ : INHERITED(intervals, count, width) {
+ fName.append("_rect");
+ }
+
+protected:
+ virtual void handlePath(SkCanvas* canvas, const SkPath& path,
+ const SkPaint& paint, int N) SK_OVERRIDE {
+ SkPoint pts[2];
+ if (!path.isLine(pts) || pts[0].fY != pts[1].fY) {
+ this->INHERITED::handlePath(canvas, path, paint, N);
+ } else {
+ SkRect rect;
+ rect.fLeft = pts[0].fX;
+ rect.fTop = pts[0].fY - paint.getStrokeWidth() / 2;
+ rect.fRight = rect.fLeft + SkIntToScalar(fWidth);
+ rect.fBottom = rect.fTop + paint.getStrokeWidth();
+
+ SkPaint p(paint);
+ p.setStyle(SkPaint::kFill_Style);
+ p.setPathEffect(NULL);
+
+ int count = SkScalarRoundToInt((pts[1].fX - pts[0].fX) / (2*fWidth));
+ SkScalar dx = SkIntToScalar(2 * fWidth);
+
+ for (int i = 0; i < N*10; ++i) {
+ SkRect r = rect;
+ for (int j = 0; j < count; ++j) {
+ canvas->drawRect(r, p);
+ r.offset(dx, 0);
+ }
+ }
+ }
+ }
+
+private:
+ typedef DashBench INHERITED;
+};
+
+static void make_unit_star(SkPath* path, int n) {
+ SkScalar rad = -SK_ScalarPI / 2;
+ const SkScalar drad = (n >> 1) * SK_ScalarPI * 2 / n;
+
+ path->moveTo(0, -SK_Scalar1);
+ for (int i = 1; i < n; i++) {
+ rad += drad;
+ SkScalar cosV, sinV = SkScalarSinCos(rad, &cosV);
+ path->lineTo(cosV, sinV);
+ }
+ path->close();
+}
+
+static void make_poly(SkPath* path) {
+ make_unit_star(path, 9);
+ SkMatrix matrix;
+ matrix.setScale(SkIntToScalar(100), SkIntToScalar(100));
+ path->transform(matrix);
+}
+
+static void make_quad(SkPath* path) {
+ SkScalar x0 = SkIntToScalar(10);
+ SkScalar y0 = SkIntToScalar(10);
+ path->moveTo(x0, y0);
+ path->quadTo(x0, y0 + 400 * SK_Scalar1,
+ x0 + 600 * SK_Scalar1, y0 + 400 * SK_Scalar1);
+}
+
+static void make_cubic(SkPath* path) {
+ SkScalar x0 = SkIntToScalar(10);
+ SkScalar y0 = SkIntToScalar(10);
+ path->moveTo(x0, y0);
+ path->cubicTo(x0, y0 + 400 * SK_Scalar1,
+ x0 + 600 * SK_Scalar1, y0 + 400 * SK_Scalar1,
+ x0 + 600 * SK_Scalar1, y0);
+}
+
+class MakeDashBench : public Benchmark {
+ SkString fName;
+ SkPath fPath;
+ SkAutoTUnref<SkPathEffect> fPE;
+
+public:
+ MakeDashBench(void (*proc)(SkPath*), const char name[]) {
+ fName.printf("makedash_%s", name);
+ proc(&fPath);
+
+ SkScalar vals[] = { SkIntToScalar(4), SkIntToScalar(4) };
+ fPE.reset(SkDashPathEffect::Create(vals, 2, 0));
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
+ SkPath dst;
+ for (int i = 0; i < loops; ++i) {
+ SkStrokeRec rec(SkStrokeRec::kHairline_InitStyle);
+
+ fPE->filterPath(&dst, fPath, &rec, NULL);
+ dst.rewind();
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+/*
+ * We try to special case square dashes (intervals are equal to strokewidth).
+ */
+class DashLineBench : public Benchmark {
+ SkString fName;
+ SkScalar fStrokeWidth;
+ bool fIsRound;
+ SkAutoTUnref<SkPathEffect> fPE;
+
+public:
+ DashLineBench(SkScalar width, bool isRound) {
+ fName.printf("dashline_%g_%s", SkScalarToFloat(width), isRound ? "circle" : "square");
+ fStrokeWidth = width;
+ fIsRound = isRound;
+
+ SkScalar vals[] = { SK_Scalar1, SK_Scalar1 };
+ fPE.reset(SkDashPathEffect::Create(vals, 2, 0));
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkPaint paint;
+ this->setupPaint(&paint);
+ paint.setStrokeWidth(fStrokeWidth);
+ paint.setStrokeCap(fIsRound ? SkPaint::kRound_Cap : SkPaint::kSquare_Cap);
+ paint.setPathEffect(fPE);
+ for (int i = 0; i < loops; ++i) {
+ canvas->drawLine(10 * SK_Scalar1, 10 * SK_Scalar1,
+ 640 * SK_Scalar1, 10 * SK_Scalar1, paint);
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+class DrawPointsDashingBench : public Benchmark {
+ SkString fName;
+ int fStrokeWidth;
+ bool fDoAA;
+
+ SkAutoTUnref<SkPathEffect> fPathEffect;
+
+public:
+ DrawPointsDashingBench(int dashLength, int strokeWidth, bool doAA)
+ {
+ fName.printf("drawpointsdash_%d_%d%s", dashLength, strokeWidth, doAA ? "_aa" : "_bw");
+ fStrokeWidth = strokeWidth;
+ fDoAA = doAA;
+
+ SkScalar vals[] = { SkIntToScalar(dashLength), SkIntToScalar(dashLength) };
+ fPathEffect.reset(SkDashPathEffect::Create(vals, 2, SK_Scalar1));
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkPaint p;
+ this->setupPaint(&p);
+ p.setColor(SK_ColorBLACK);
+ p.setStyle(SkPaint::kStroke_Style);
+ p.setStrokeWidth(SkIntToScalar(fStrokeWidth));
+ p.setPathEffect(fPathEffect);
+ p.setAntiAlias(fDoAA);
+
+ SkPoint pts[2] = {
+ { SkIntToScalar(10), 0 },
+ { SkIntToScalar(640), 0 }
+ };
+
+ for (int i = 0; i < loops; ++i) {
+ pts[0].fY = pts[1].fY = SkIntToScalar(i % 480);
+ canvas->drawPoints(SkCanvas::kLines_PointMode, 2, pts, p);
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+// Want to test how we handle dashing when 99% of the dash is clipped out
+class GiantDashBench : public Benchmark {
+ SkString fName;
+ SkScalar fStrokeWidth;
+ SkPoint fPts[2];
+ SkAutoTUnref<SkPathEffect> fPathEffect;
+
+public:
+ enum LineType {
+ kHori_LineType,
+ kVert_LineType,
+ kDiag_LineType,
+ kLineTypeCount
+ };
+
+ static const char* LineTypeName(LineType lt) {
+ static const char* gNames[] = { "hori", "vert", "diag" };
+ SK_COMPILE_ASSERT(kLineTypeCount == SK_ARRAY_COUNT(gNames), names_wrong_size);
+ return gNames[lt];
+ }
+
+ GiantDashBench(LineType lt, SkScalar width) {
+ fName.printf("giantdashline_%s_%g", LineTypeName(lt), width);
+ fStrokeWidth = width;
+
+ // deliberately pick intervals that won't be caught by asPoints(), so
+ // we can test the filterPath code-path.
+ const SkScalar intervals[] = { 20, 10, 10, 10 };
+ fPathEffect.reset(SkDashPathEffect::Create(intervals,
+ SK_ARRAY_COUNT(intervals), 0));
+
+ SkScalar cx = 640 / 2; // center X
+ SkScalar cy = 480 / 2; // center Y
+ SkMatrix matrix;
+
+ switch (lt) {
+ case kHori_LineType:
+ matrix.setIdentity();
+ break;
+ case kVert_LineType:
+ matrix.setRotate(90, cx, cy);
+ break;
+ case kDiag_LineType:
+ matrix.setRotate(45, cx, cy);
+ break;
+ case kLineTypeCount:
+ // Not a real enum value.
+ break;
+ }
+
+ const SkScalar overshoot = 100*1000;
+ const SkPoint pts[2] = {
+ { -overshoot, cy }, { 640 + overshoot, cy }
+ };
+ matrix.mapPoints(fPts, pts, 2);
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkPaint p;
+ this->setupPaint(&p);
+ p.setStyle(SkPaint::kStroke_Style);
+ p.setStrokeWidth(fStrokeWidth);
+ p.setPathEffect(fPathEffect);
+
+ for (int i = 0; i < loops; i++) {
+ canvas->drawPoints(SkCanvas::kLines_PointMode, 2, fPts, p);
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+// Want to test how we draw a dashed grid (like what is used in spreadsheets) of many
+// small dashed lines switching back and forth between horizontal and vertical
+class DashGridBench : public Benchmark {
+ SkString fName;
+ int fStrokeWidth;
+ bool fDoAA;
+
+ SkAutoTUnref<SkPathEffect> fPathEffect;
+
+public:
+ DashGridBench(int dashLength, int strokeWidth, bool doAA) {
+ fName.printf("dashgrid_%d_%d%s", dashLength, strokeWidth, doAA ? "_aa" : "_bw");
+ fStrokeWidth = strokeWidth;
+ fDoAA = doAA;
+
+ SkScalar vals[] = { SkIntToScalar(dashLength), SkIntToScalar(dashLength) };
+ fPathEffect.reset(SkDashPathEffect::Create(vals, 2, SK_Scalar1));
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkPaint p;
+ this->setupPaint(&p);
+ p.setColor(SK_ColorBLACK);
+ p.setStyle(SkPaint::kStroke_Style);
+ p.setStrokeWidth(SkIntToScalar(fStrokeWidth));
+ p.setPathEffect(fPathEffect);
+ p.setAntiAlias(fDoAA);
+
+ SkPoint pts[4] = {
+ { SkIntToScalar(0), 20.5f },
+ { SkIntToScalar(20), 20.5f },
+ { 20.5f, SkIntToScalar(0) },
+ { 20.5f, SkIntToScalar(20) }
+ };
+
+ for (int i = 0; i < loops; ++i) {
+ for (int j = 0; j < 10; ++j) {
+ for (int k = 0; k < 10; ++k) {
+ // Horizontal line
+ SkPoint horPts[2];
+ horPts[0].fX = pts[0].fX + k * 22.f;
+ horPts[0].fY = pts[0].fY + j * 22.f;
+ horPts[1].fX = pts[1].fX + k * 22.f;
+ horPts[1].fY = pts[1].fY + j * 22.f;
+ canvas->drawPoints(SkCanvas::kLines_PointMode, 2, horPts, p);
+
+ // Vertical line
+ SkPoint vertPts[2];
+ vertPts[0].fX = pts[2].fX + k * 22.f;
+ vertPts[0].fY = pts[2].fY + j * 22.f;
+ vertPts[1].fX = pts[3].fX + k * 22.f;
+ vertPts[1].fY = pts[3].fY + j * 22.f;
+ canvas->drawPoints(SkCanvas::kLines_PointMode, 2, vertPts, p);
+ }
+ }
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+static const SkScalar gDots[] = { SK_Scalar1, SK_Scalar1 };
+
+#define PARAM(array) array, SK_ARRAY_COUNT(array)
+
+DEF_BENCH( return new DashBench(PARAM(gDots), 0); )
+DEF_BENCH( return new DashBench(PARAM(gDots), 1); )
+DEF_BENCH( return new DashBench(PARAM(gDots), 1, true); )
+DEF_BENCH( return new DashBench(PARAM(gDots), 4); )
+DEF_BENCH( return new MakeDashBench(make_poly, "poly"); )
+DEF_BENCH( return new MakeDashBench(make_quad, "quad"); )
+DEF_BENCH( return new MakeDashBench(make_cubic, "cubic"); )
+DEF_BENCH( return new DashLineBench(0, false); )
+DEF_BENCH( return new DashLineBench(SK_Scalar1, false); )
+DEF_BENCH( return new DashLineBench(2 * SK_Scalar1, false); )
+DEF_BENCH( return new DashLineBench(0, true); )
+DEF_BENCH( return new DashLineBench(SK_Scalar1, true); )
+DEF_BENCH( return new DashLineBench(2 * SK_Scalar1, true); )
+
+DEF_BENCH( return new DrawPointsDashingBench(1, 1, false); )
+DEF_BENCH( return new DrawPointsDashingBench(1, 1, true); )
+DEF_BENCH( return new DrawPointsDashingBench(3, 1, false); )
+DEF_BENCH( return new DrawPointsDashingBench(3, 1, true); )
+DEF_BENCH( return new DrawPointsDashingBench(5, 5, false); )
+DEF_BENCH( return new DrawPointsDashingBench(5, 5, true); )
+
+/* Disable the GiantDashBench for Android devices until we can better control
+ * the memory usage. (https://code.google.com/p/skia/issues/detail?id=1430)
+ */
+#ifndef SK_BUILD_FOR_ANDROID
+DEF_BENCH( return new GiantDashBench(GiantDashBench::kHori_LineType, 0); )
+DEF_BENCH( return new GiantDashBench(GiantDashBench::kVert_LineType, 0); )
+DEF_BENCH( return new GiantDashBench(GiantDashBench::kDiag_LineType, 0); )
+
+// pass 2 to explicitly avoid any 1-is-the-same-as-hairline special casing
+
+// hori_2 is just too slow to enable at the moment
+DEF_BENCH( return new GiantDashBench(GiantDashBench::kHori_LineType, 2); )
+DEF_BENCH( return new GiantDashBench(GiantDashBench::kVert_LineType, 2); )
+DEF_BENCH( return new GiantDashBench(GiantDashBench::kDiag_LineType, 2); )
+
+DEF_BENCH( return new DashGridBench(1, 1, true); )
+DEF_BENCH( return new DashGridBench(1, 1, false); )
+DEF_BENCH( return new DashGridBench(3, 1, true); )
+DEF_BENCH( return new DashGridBench(3, 1, false); )
+#endif
diff --git a/chromium/third_party/skia/bench/DecodeBench.cpp b/chromium/third_party/skia/bench/DecodeBench.cpp
new file mode 100644
index 00000000000..a4717f8eb7f
--- /dev/null
+++ b/chromium/third_party/skia/bench/DecodeBench.cpp
@@ -0,0 +1,50 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "Benchmark.h"
+#include "SkBitmap.h"
+#include "SkCommandLineFlags.h"
+#include "SkImageDecoder.h"
+#include "SkOSFile.h"
+#include "SkString.h"
+#include "sk_tool_utils.h"
+
+DEFINE_string(decodeBenchFilename, "resources/CMYK.jpeg", "Path to image for DecodeBench.");
+
+class DecodeBench : public Benchmark {
+ const SkColorType fPrefColorType;
+ SkString fName;
+public:
+ DecodeBench(SkColorType ct) : fPrefColorType(ct) {
+ SkString fname = SkOSPath::SkBasename(FLAGS_decodeBenchFilename[0]);
+ fName.printf("decode_%s_%s", sk_tool_utils::colortype_name(ct), fname.c_str());
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+protected:
+ virtual const char* onGetName() {
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) {
+ for (int i = 0; i < loops; i++) {
+ SkBitmap bm;
+ SkImageDecoder::DecodeFile(FLAGS_decodeBenchFilename[0], &bm, fPrefColorType,
+ SkImageDecoder::kDecodePixels_Mode);
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+DEF_BENCH( return new DecodeBench(kN32_SkColorType); )
+DEF_BENCH( return new DecodeBench(kRGB_565_SkColorType); )
+DEF_BENCH( return new DecodeBench(kARGB_4444_SkColorType); )
diff --git a/chromium/third_party/skia/bench/DeferredCanvasBench.cpp b/chromium/third_party/skia/bench/DeferredCanvasBench.cpp
new file mode 100644
index 00000000000..667895c22f7
--- /dev/null
+++ b/chromium/third_party/skia/bench/DeferredCanvasBench.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "Benchmark.h"
+#include "SkDeferredCanvas.h"
+#include "SkDevice.h"
+#include "SkString.h"
+
+class DeferredCanvasBench : public Benchmark {
+public:
+ DeferredCanvasBench(const char name[]) {
+ fName.printf("deferred_canvas_%s", name);
+ }
+
+ enum {
+ CANVAS_WIDTH = 200,
+ CANVAS_HEIGHT = 200,
+ };
+protected:
+ virtual const char* onGetName() {
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) {
+#if 0 // what specifically are we interested in timing here?
+ SkBaseDevice *device = canvas->getDevice()->createCompatibleDevice(
+ SkBitmap::kARGB_8888_Config, CANVAS_WIDTH, CANVAS_HEIGHT, false);
+
+ SkAutoTUnref<SkDeferredCanvas> deferredCanvas(SkDeferredCanvas::Create(device));
+ device->unref();
+
+ initDeferredCanvas(deferredCanvas);
+ drawInDeferredCanvas(loops, deferredCanvas);
+ finalizeDeferredCanvas(deferredCanvas);
+ deferredCanvas->flush();
+#endif
+ }
+
+ virtual void initDeferredCanvas(SkDeferredCanvas* canvas) = 0;
+ virtual void drawInDeferredCanvas(const int loops, SkDeferredCanvas* canvas) = 0;
+ virtual void finalizeDeferredCanvas(SkDeferredCanvas* canvas) = 0;
+
+ SkString fName;
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+class SimpleNotificationClient : public SkDeferredCanvas::NotificationClient {
+public:
+ SimpleNotificationClient() : fDummy(false) {}
+
+ //bogus virtual implementations that just do something small
+ virtual void prepareForDraw() SK_OVERRIDE {fDummy = true;}
+ virtual void storageAllocatedForRecordingChanged(size_t) SK_OVERRIDE {fDummy = false;}
+ virtual void flushedDrawCommands() SK_OVERRIDE {fDummy = !fDummy;}
+private:
+ bool fDummy;
+
+ typedef SkDeferredCanvas::NotificationClient INHERITED;
+};
+
+// Test that records very simple draw operations.
+// This benchmark aims to capture performance fluctuations in the recording
+// overhead of SkDeferredCanvas
+class DeferredRecordBench : public DeferredCanvasBench {
+public:
+ DeferredRecordBench()
+ : INHERITED("record") {
+ }
+
+protected:
+
+ virtual void initDeferredCanvas(SkDeferredCanvas* canvas) SK_OVERRIDE {
+ canvas->setNotificationClient(&fNotificationClient);
+ }
+
+ virtual void drawInDeferredCanvas(const int loops, SkDeferredCanvas* canvas) SK_OVERRIDE {
+ SkRect rect;
+ rect.setXYWH(0, 0, 10, 10);
+ SkPaint paint;
+ for (int i = 0; i < loops; i++) {
+ canvas->save();
+ canvas->translate(SkIntToScalar(i * 27 % CANVAS_WIDTH), SkIntToScalar(i * 13 % CANVAS_HEIGHT));
+ canvas->drawRect(rect, paint);
+ canvas->restore();
+ }
+ }
+
+ virtual void finalizeDeferredCanvas(SkDeferredCanvas* canvas) SK_OVERRIDE {
+ canvas->clear(0x0);
+ canvas->setNotificationClient(NULL);
+ }
+
+private:
+ typedef DeferredCanvasBench INHERITED;
+ SimpleNotificationClient fNotificationClient;
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH( return new DeferredRecordBench(); )
diff --git a/chromium/third_party/skia/bench/DeferredSurfaceCopyBench.cpp b/chromium/third_party/skia/bench/DeferredSurfaceCopyBench.cpp
new file mode 100644
index 00000000000..f4002b87be4
--- /dev/null
+++ b/chromium/third_party/skia/bench/DeferredSurfaceCopyBench.cpp
@@ -0,0 +1,82 @@
+
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkDeferredCanvas.h"
+#include "SkDevice.h"
+#include "SkImage.h"
+#include "SkSurface.h"
+#if SK_SUPPORT_GPU
+#include "GrRenderTarget.h"
+#endif
+
+class DeferredSurfaceCopyBench : public Benchmark {
+ enum {
+ kSurfaceWidth = 1000,
+ kSurfaceHeight = 1000,
+ };
+public:
+ DeferredSurfaceCopyBench(bool discardableContents) {
+ fDiscardableContents = discardableContents;
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fDiscardableContents ? "DeferredSurfaceCopy_discardable" :
+ "DeferredSurfaceCopy_nonDiscardable";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ // The canvas is not actually used for this test except to provide
+ // configuration information: gpu, multisampling, size, etc?
+ SkImageInfo info;
+ info.fWidth = kSurfaceWidth;
+ info.fHeight = kSurfaceHeight;
+ info.fColorType = kN32_SkColorType;
+ info.fAlphaType = kPremul_SkAlphaType;
+ const SkRect fullCanvasRect = SkRect::MakeWH(
+ SkIntToScalar(kSurfaceWidth), SkIntToScalar(kSurfaceHeight));
+ SkSurface* surface;
+#if SK_SUPPORT_GPU
+ GrRenderTarget* rt = reinterpret_cast<GrRenderTarget*>(
+ canvas->getDevice()->accessRenderTarget());
+ if (NULL != rt) {
+ surface = SkSurface::NewRenderTarget(rt->getContext(), info, rt->numSamples());
+ } else
+#endif
+ {
+ surface = SkSurface::NewRaster(info);
+ }
+ SkAutoTUnref<SkDeferredCanvas> drawingCanvas(SkDeferredCanvas::Create(surface));
+ surface->unref();
+
+ for (int iteration = 0; iteration < loops; iteration++) {
+ drawingCanvas->clear(0);
+ SkAutoTUnref<SkImage> image(drawingCanvas->newImageSnapshot());
+ SkPaint paint;
+ if (!fDiscardableContents) {
+ // If paint is not opaque, prior canvas contents are
+ // not discardable because they are needed for compositing.
+ paint.setAlpha(127);
+ }
+ drawingCanvas->drawRect(fullCanvasRect, paint);
+ // Trigger copy on write, which should be faster in the discardable case.
+ drawingCanvas->flush();
+ }
+ }
+
+private:
+ bool fDiscardableContents;
+
+ typedef Benchmark INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH( return new DeferredSurfaceCopyBench(false); )
+DEF_BENCH( return new DeferredSurfaceCopyBench(true); )
diff --git a/chromium/third_party/skia/bench/DisplacementBench.cpp b/chromium/third_party/skia/bench/DisplacementBench.cpp
new file mode 100644
index 00000000000..881ba33b246
--- /dev/null
+++ b/chromium/third_party/skia/bench/DisplacementBench.cpp
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "Benchmark.h"
+#include "SkBitmapDevice.h"
+#include "SkBitmapSource.h"
+#include "SkCanvas.h"
+#include "SkDisplacementMapEffect.h"
+
+#define FILTER_WIDTH_SMALL 32
+#define FILTER_HEIGHT_SMALL 32
+#define FILTER_WIDTH_LARGE 256
+#define FILTER_HEIGHT_LARGE 256
+
+class DisplacementBaseBench : public Benchmark {
+public:
+ DisplacementBaseBench(bool small) :
+ fInitialized(false), fIsSmall(small) {
+ }
+
+protected:
+ virtual void onPreDraw() SK_OVERRIDE {
+ if (!fInitialized) {
+ this->makeBitmap();
+ this->makeCheckerboard();
+ fInitialized = true;
+ }
+ }
+
+ void makeBitmap() {
+ const int w = this->isSmall() ? FILTER_WIDTH_SMALL : FILTER_WIDTH_LARGE;
+ const int h = this->isSmall() ? FILTER_HEIGHT_LARGE : FILTER_HEIGHT_LARGE;
+ fBitmap.allocN32Pixels(w, h);
+ SkCanvas canvas(fBitmap);
+ canvas.clear(0x00000000);
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setColor(0xFF884422);
+ paint.setTextSize(SkIntToScalar(96));
+ const char* str = "g";
+ canvas.drawText(str, strlen(str), SkIntToScalar(15), SkIntToScalar(55), paint);
+ }
+
+ void makeCheckerboard() {
+ const int w = this->isSmall() ? FILTER_WIDTH_SMALL : FILTER_WIDTH_LARGE;
+ const int h = this->isSmall() ? FILTER_HEIGHT_LARGE : FILTER_HEIGHT_LARGE;
+ fCheckerboard.allocN32Pixels(w, h);
+ SkCanvas canvas(fCheckerboard);
+ canvas.clear(0x00000000);
+ SkPaint darkPaint;
+ darkPaint.setColor(0xFF804020);
+ SkPaint lightPaint;
+ lightPaint.setColor(0xFF244484);
+ for (int y = 0; y < h; y += 16) {
+ for (int x = 0; x < w; x += 16) {
+ canvas.save();
+ canvas.translate(SkIntToScalar(x), SkIntToScalar(y));
+ canvas.drawRect(SkRect::MakeXYWH(0, 0, 8, 8), darkPaint);
+ canvas.drawRect(SkRect::MakeXYWH(8, 0, 8, 8), lightPaint);
+ canvas.drawRect(SkRect::MakeXYWH(0, 8, 8, 8), lightPaint);
+ canvas.drawRect(SkRect::MakeXYWH(8, 8, 8, 8), darkPaint);
+ canvas.restore();
+ }
+ }
+ }
+
+ void drawClippedBitmap(SkCanvas* canvas, int x, int y, const SkPaint& paint) {
+ canvas->save();
+ canvas->clipRect(SkRect::MakeXYWH(SkIntToScalar(x), SkIntToScalar(y),
+ SkIntToScalar(fBitmap.width()),
+ SkIntToScalar(fBitmap.height())));
+ canvas->drawBitmap(fBitmap, SkIntToScalar(x), SkIntToScalar(y), &paint);
+ canvas->restore();
+ }
+
+ inline bool isSmall() const { return fIsSmall; }
+
+ SkBitmap fBitmap, fCheckerboard;
+private:
+ bool fInitialized;
+ bool fIsSmall;
+ typedef Benchmark INHERITED;
+};
+
+class DisplacementZeroBench : public DisplacementBaseBench {
+public:
+ DisplacementZeroBench(bool small) : INHERITED(small) {
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return this->isSmall() ? "displacement_zero_small" : "displacement_zero_large";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkPaint paint;
+ SkAutoTUnref<SkImageFilter> displ(SkBitmapSource::Create(fCheckerboard));
+ // No displacement effect
+ paint.setImageFilter(SkDisplacementMapEffect::Create(
+ SkDisplacementMapEffect::kR_ChannelSelectorType,
+ SkDisplacementMapEffect::kG_ChannelSelectorType, 0.0f, displ))->unref();
+
+ for (int i = 0; i < loops; i++) {
+ this->drawClippedBitmap(canvas, 0, 0, paint);
+ }
+ }
+
+private:
+ typedef DisplacementBaseBench INHERITED;
+};
+
+class DisplacementAlphaBench : public DisplacementBaseBench {
+public:
+ DisplacementAlphaBench(bool small) : INHERITED(small) {
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return isSmall() ? "displacement_alpha_small" : "displacement_alpha_large";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkPaint paint;
+ SkAutoTUnref<SkImageFilter> displ(SkBitmapSource::Create(fCheckerboard));
+ // Displacement, with 1 alpha component (which isn't pre-multiplied)
+ paint.setImageFilter(SkDisplacementMapEffect::Create(
+ SkDisplacementMapEffect::kB_ChannelSelectorType,
+ SkDisplacementMapEffect::kA_ChannelSelectorType, 16.0f, displ))->unref();
+ for (int i = 0; i < loops; i++) {
+ drawClippedBitmap(canvas, 100, 0, paint);
+ }
+ }
+
+private:
+ typedef DisplacementBaseBench INHERITED;
+};
+
+class DisplacementFullBench : public DisplacementBaseBench {
+public:
+ DisplacementFullBench(bool small) : INHERITED(small) {
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return isSmall() ? "displacement_full_small" : "displacement_full_large";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkPaint paint;
+ SkAutoTUnref<SkImageFilter> displ(SkBitmapSource::Create(fCheckerboard));
+ // Displacement, with 2 non-alpha components
+ paint.setImageFilter(SkDisplacementMapEffect::Create(
+ SkDisplacementMapEffect::kR_ChannelSelectorType,
+ SkDisplacementMapEffect::kB_ChannelSelectorType, 32.0f, displ))->unref();
+ for (int i = 0; i < loops; ++i) {
+ this->drawClippedBitmap(canvas, 200, 0, paint);
+ }
+ }
+
+private:
+ typedef DisplacementBaseBench INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH( return new DisplacementZeroBench(true); )
+DEF_BENCH( return new DisplacementAlphaBench(true); )
+DEF_BENCH( return new DisplacementFullBench(true); )
+DEF_BENCH( return new DisplacementZeroBench(false); )
+DEF_BENCH( return new DisplacementAlphaBench(false); )
+DEF_BENCH( return new DisplacementFullBench(false); )
diff --git a/chromium/third_party/skia/bench/ETCBitmapBench.cpp b/chromium/third_party/skia/bench/ETCBitmapBench.cpp
new file mode 100644
index 00000000000..aaa2ce7a660
--- /dev/null
+++ b/chromium/third_party/skia/bench/ETCBitmapBench.cpp
@@ -0,0 +1,235 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "Resources.h"
+#include "SkCanvas.h"
+#include "SkData.h"
+#include "SkDecodingImageGenerator.h"
+#include "SkImageDecoder.h"
+#include "SkOSFile.h"
+#include "SkPixelRef.h"
+
+#ifndef SK_IGNORE_ETC1_SUPPORT
+
+#include "etc1.h"
+
+// This takes the etc1 data pointed to by orig, and copies it `factor` times in each
+// dimension. The return value is the new data or NULL on error.
+static etc1_byte* create_expanded_etc1_bitmap(const uint8_t* orig, int factor) {
+ SkASSERT(NULL != orig);
+ SkASSERT(factor > 1);
+
+ const etc1_byte* origData = reinterpret_cast<const etc1_byte*>(orig);
+ if (!etc1_pkm_is_valid(orig)) {
+ return NULL;
+ }
+
+ etc1_uint32 origWidth = etc1_pkm_get_width(origData);
+ etc1_uint32 origHeight = etc1_pkm_get_height(origData);
+
+ // The width and height must be aligned along block boundaries
+ static const etc1_uint32 kETC1BlockWidth = 4;
+ static const etc1_uint32 kETC1BlockHeight = 4;
+ if ((origWidth % kETC1BlockWidth) != 0 ||
+ (origHeight % kETC1BlockHeight) != 0) {
+ return NULL;
+ }
+
+ // The picture must be at least as large as a block.
+ if (origWidth <= kETC1BlockWidth || origHeight <= kETC1BlockHeight) {
+ return NULL;
+ }
+
+ etc1_uint32 newWidth = origWidth * factor;
+ etc1_uint32 newHeight = origHeight * factor;
+
+ etc1_uint32 newDataSz = etc1_get_encoded_data_size(newWidth, newHeight);
+ etc1_byte* newData = reinterpret_cast<etc1_byte *>(
+ sk_malloc_throw(newDataSz + ETC_PKM_HEADER_SIZE));
+ etc1_pkm_format_header(newData, newWidth, newHeight);
+
+ etc1_byte* copyInto = newData;
+
+ copyInto += ETC_PKM_HEADER_SIZE;
+ origData += ETC_PKM_HEADER_SIZE;
+
+ etc1_uint32 origBlocksX = (origWidth >> 2);
+ etc1_uint32 origBlocksY = (origHeight >> 2);
+ etc1_uint32 newBlocksY = (newHeight >> 2);
+ etc1_uint32 origRowSzInBytes = origBlocksX * ETC1_ENCODED_BLOCK_SIZE;
+
+ for (etc1_uint32 j = 0; j < newBlocksY; ++j) {
+ const etc1_byte* rowStart = origData + ((j % origBlocksY) * origRowSzInBytes);
+ for(etc1_uint32 i = 0; i < newWidth; i += origWidth) {
+ memcpy(copyInto, rowStart, origRowSzInBytes);
+ copyInto += origRowSzInBytes;
+ }
+ }
+ return newData;
+}
+
+// This is the base class for all of the benches in this file. In general
+// the ETC1 benches should all be working on the same data. Due to the
+// simplicity of the PKM file, that data is the 128x128 mandrill etc1
+// compressed texture repeated by some factor (currently 8 -> 1024x1024)
+class ETCBitmapBenchBase : public Benchmark {
+public:
+ ETCBitmapBenchBase() : fPKMData(loadPKM()) {
+ if (NULL == fPKMData) {
+ SkDebugf("Could not load PKM data!");
+ }
+ }
+
+protected:
+ SkAutoDataUnref fPKMData;
+
+private:
+ SkData *loadPKM() {
+ SkString resourcePath = GetResourcePath();
+ SkString filename = SkOSPath::SkPathJoin(resourcePath.c_str(),
+ "mandrill_128.pkm");
+
+ // Expand the data
+ SkAutoDataUnref fileData(SkData::NewFromFileName(filename.c_str()));
+ if (NULL == fileData) {
+ SkDebugf("Could not open the file. Did you forget to set the resourcePath?\n");
+ return NULL;
+ }
+
+ const etc1_uint32 kExpansionFactor = 8;
+ etc1_byte* expandedETC1 =
+ create_expanded_etc1_bitmap(fileData->bytes(), kExpansionFactor);
+ if (NULL == expandedETC1) {
+ SkDebugf("Error expanding ETC1 data by factor of %d\n", kExpansionFactor);
+ return NULL;
+ }
+
+ etc1_uint32 width = etc1_pkm_get_width(expandedETC1);
+ etc1_uint32 height = etc1_pkm_get_width(expandedETC1);
+ etc1_uint32 dataSz = ETC_PKM_HEADER_SIZE + etc1_get_encoded_data_size(width, height);
+ return SkData::NewFromMalloc(expandedETC1, dataSz);
+ }
+
+ typedef Benchmark INHERITED;
+};
+
+// This is the rendering benchmark. Prior to rendering the data, create a
+// bitmap using the etc1 data.
+class ETCBitmapBench : public ETCBitmapBenchBase {
+public:
+ ETCBitmapBench(bool decompress, Backend backend)
+ : fDecompress(decompress), fBackend(backend) { }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == this->fBackend;
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ if (kGPU_Backend == this->fBackend) {
+ if (this->fDecompress) {
+ return "etc1bitmap_render_gpu_decompressed";
+ } else {
+ return "etc1bitmap_render_gpu_compressed";
+ }
+ } else {
+ SkASSERT(kRaster_Backend == this->fBackend);
+ if (this->fDecompress) {
+ return "etc1bitmap_render_raster_decompressed";
+ } else {
+ return "etc1bitmap_render_raster_compressed";
+ }
+ }
+ }
+
+ virtual void onPreDraw() SK_OVERRIDE {
+ if (NULL == fPKMData) {
+ SkDebugf("Failed to load PKM data!\n");
+ return;
+ }
+
+ // Install pixel ref
+ if (!SkInstallDiscardablePixelRef(
+ SkDecodingImageGenerator::Create(
+ fPKMData, SkDecodingImageGenerator::Options()), &(this->fBitmap))) {
+ SkDebugf("Could not install discardable pixel ref.\n");
+ return;
+ }
+
+ // Decompress it if necessary
+ if (this->fDecompress) {
+ this->fBitmap.lockPixels();
+ }
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ for (int i = 0; i < loops; ++i) {
+ canvas->drawBitmap(this->fBitmap, 0, 0, NULL);
+ }
+ }
+
+protected:
+ SkBitmap fBitmap;
+ bool decompress() const { return fDecompress; }
+ Backend backend() const { return fBackend; }
+private:
+ const bool fDecompress;
+ const Backend fBackend;
+ typedef ETCBitmapBenchBase INHERITED;
+};
+
+// This benchmark is identical to the previous benchmark, but it explicitly forces
+// an upload to the GPU before each draw call. We do this by notifying the bitmap
+// that the pixels have changed (even though they haven't).
+class ETCBitmapUploadBench : public ETCBitmapBench {
+public:
+ ETCBitmapUploadBench(bool decompress, Backend backend)
+ : ETCBitmapBench(decompress, backend) { }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ if (kGPU_Backend == this->backend()) {
+ if (this->decompress()) {
+ return "etc1bitmap_upload_gpu_decompressed";
+ } else {
+ return "etc1bitmap_upload_gpu_compressed";
+ }
+ } else {
+ SkASSERT(kRaster_Backend == this->backend());
+ if (this->decompress()) {
+ return "etc1bitmap_upload_raster_decompressed";
+ } else {
+ return "etc1bitmap_upload_raster_compressed";
+ }
+ }
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ for (int i = 0; i < loops; ++i) {
+ this->fBitmap.pixelRef()->notifyPixelsChanged();
+ canvas->drawBitmap(this->fBitmap, 0, 0, NULL);
+ }
+ }
+
+private:
+ typedef ETCBitmapBench INHERITED;
+};
+
+DEF_BENCH(return new ETCBitmapBench(false, Benchmark::kRaster_Backend);)
+DEF_BENCH(return new ETCBitmapBench(true, Benchmark::kRaster_Backend);)
+
+DEF_BENCH(return new ETCBitmapBench(false, Benchmark::kGPU_Backend);)
+DEF_BENCH(return new ETCBitmapBench(true, Benchmark::kGPU_Backend);)
+
+DEF_BENCH(return new ETCBitmapUploadBench(false, Benchmark::kRaster_Backend);)
+DEF_BENCH(return new ETCBitmapUploadBench(true, Benchmark::kRaster_Backend);)
+
+DEF_BENCH(return new ETCBitmapUploadBench(false, Benchmark::kGPU_Backend);)
+DEF_BENCH(return new ETCBitmapUploadBench(true, Benchmark::kGPU_Backend);)
+
+#endif // SK_IGNORE_ETC1_SUPPORT
diff --git a/chromium/third_party/skia/bench/FSRectBench.cpp b/chromium/third_party/skia/bench/FSRectBench.cpp
new file mode 100644
index 00000000000..3c5304294d1
--- /dev/null
+++ b/chromium/third_party/skia/bench/FSRectBench.cpp
@@ -0,0 +1,63 @@
+
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkCanvas.h"
+#include "SkPaint.h"
+#include "SkRandom.h"
+
+/**
+ * Draws full screen opaque rectangles. It is designed to test any optimizations in the GPU backend
+ * to turn such draws into clears.
+ */
+class FSRectBench : public Benchmark {
+public:
+ FSRectBench() : fInit(false) { }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE { return "fullscreen_rects"; }
+
+ virtual void onPreDraw() SK_OVERRIDE {
+ if (!fInit) {
+ SkRandom rand;
+ static const SkScalar kMinOffset = 0;
+ static const SkScalar kMaxOffset = 100 * SK_Scalar1;
+ static const SkScalar kOffsetRange = kMaxOffset - kMinOffset;
+ for (int i = 0; i < N; ++i) {
+ fRects[i].fLeft = -kMinOffset - SkScalarMul(rand.nextUScalar1(), kOffsetRange);
+ fRects[i].fTop = -kMinOffset - SkScalarMul(rand.nextUScalar1(), kOffsetRange);
+ fRects[i].fRight = W + kMinOffset + SkScalarMul(rand.nextUScalar1(), kOffsetRange);
+ fRects[i].fBottom = H + kMinOffset + SkScalarMul(rand.nextUScalar1(), kOffsetRange);
+ fColors[i] = rand.nextU() | 0xFF000000;
+ }
+ fInit = true;
+ }
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkPaint paint;
+ for (int i = 0; i < loops; ++i) {
+ paint.setColor(fColors[i % N]);
+ canvas->drawRect(fRects[i % N], paint);
+ }
+ }
+
+private:
+ enum {
+ W = 640,
+ H = 480,
+ N = 300,
+ };
+ SkRect fRects[N];
+ SkColor fColors[N];
+ bool fInit;
+
+ typedef Benchmark INHERITED;
+};
+
+DEF_BENCH( return SkNEW_ARGS(FSRectBench, ()); )
diff --git a/chromium/third_party/skia/bench/FontCacheBench.cpp b/chromium/third_party/skia/bench/FontCacheBench.cpp
new file mode 100644
index 00000000000..0e75c9cb174
--- /dev/null
+++ b/chromium/third_party/skia/bench/FontCacheBench.cpp
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkCanvas.h"
+#include "SkFontHost.h"
+#include "SkPaint.h"
+#include "SkString.h"
+#include "SkTemplates.h"
+
+#include "gUniqueGlyphIDs.h"
+#define gUniqueGlyphIDs_Sentinel 0xFFFF
+
+static int count_glyphs(const uint16_t start[]) {
+ const uint16_t* curr = start;
+ while (*curr != gUniqueGlyphIDs_Sentinel) {
+ curr += 1;
+ }
+ return static_cast<int>(curr - start);
+}
+
+class FontCacheBench : public Benchmark {
+public:
+ FontCacheBench() {}
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return "fontcache";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkPaint paint;
+ this->setupPaint(&paint);
+ paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+
+ const uint16_t* array = gUniqueGlyphIDs;
+ while (*array != gUniqueGlyphIDs_Sentinel) {
+ int count = count_glyphs(array);
+ for (int i = 0; i < loops; ++i) {
+ paint.measureText(array, count * sizeof(uint16_t));
+ }
+ array += count + 1; // skip the sentinel
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+static uint32_t rotr(uint32_t value, unsigned bits) {
+ return (value >> bits) | (value << (32 - bits));
+}
+
+typedef uint32_t (*HasherProc)(uint32_t);
+
+static uint32_t hasher0(uint32_t value) {
+ value = value ^ (value >> 16);
+ return value ^ (value >> 8);
+}
+
+static uint32_t hasher2(uint32_t h) {
+ h ^= h >> 16;
+ h *= 0x85ebca6b;
+ h ^= h >> 13;
+ h *= 0xc2b2ae35;
+ h ^= h >> 16;
+
+ h ^= (h >> 8);
+ return h;
+}
+
+static const struct {
+ const char* fName;
+ HasherProc fHasher;
+} gRec[] = {
+ { "hasher0", hasher0 },
+ { "hasher2", hasher2 },
+};
+
+#define kMaxHashBits 12
+#define kMaxHashCount (1 << kMaxHashBits)
+
+static int count_collisions(const uint16_t array[], int count, HasherProc proc,
+ unsigned hashMask) {
+ char table[kMaxHashCount];
+ sk_bzero(table, sizeof(table));
+
+ int collisions = 0;
+ for (int i = 0; i < count; ++i) {
+ int index = proc(array[i]) & hashMask;
+ collisions += table[index];
+ table[index] = 1;
+ }
+ return collisions;
+}
+
+static void dump_array(const uint16_t array[], int count) {
+ for (int i = 0; i < count; ++i) {
+ SkDebugf(" %d,", array[i]);
+ }
+ SkDebugf("\n");
+}
+
+class FontCacheEfficiency : public Benchmark {
+public:
+ FontCacheEfficiency() {
+ if (false) dump_array(NULL, 0);
+ if (false) rotr(0, 0);
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return "fontefficiency";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ static bool gDone;
+ if (gDone) {
+ return;
+ }
+ gDone = true;
+
+ for (int hashBits = 6; hashBits <= 12; hashBits += 1) {
+ int hashMask = ((1 << hashBits) - 1);
+ for (int limit = 32; limit <= 1024; limit <<= 1) {
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) {
+ int collisions = 0;
+ int glyphs = 0;
+ const uint16_t* array = gUniqueGlyphIDs;
+ while (*array != gUniqueGlyphIDs_Sentinel) {
+ int count = SkMin32(count_glyphs(array), limit);
+ collisions += count_collisions(array, count, gRec[i].fHasher, hashMask);
+ glyphs += count;
+ array += count + 1; // skip the sentinel
+ }
+ SkDebugf("hashBits [%d] limit [%d] collisions [%d / %d = %1.2g%%] using %s\n", hashBits, limit, collisions, glyphs,
+ collisions * 100.0 / glyphs, gRec[i].fName);
+ }
+ }
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH( return new FontCacheBench(); )
+
+// undefine this to run the efficiency test
+//DEF_BENCH( return new FontCacheEfficiency(); )
diff --git a/chromium/third_party/skia/bench/FontScalerBench.cpp b/chromium/third_party/skia/bench/FontScalerBench.cpp
new file mode 100644
index 00000000000..0326a0cce6a
--- /dev/null
+++ b/chromium/third_party/skia/bench/FontScalerBench.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkCanvas.h"
+#include "SkGraphics.h"
+#include "SkPaint.h"
+#include "SkRandom.h"
+#include "SkString.h"
+
+class FontScalerBench : public Benchmark {
+ SkString fName;
+ SkString fText;
+ bool fDoLCD;
+public:
+ FontScalerBench(bool doLCD) {
+ fName.printf("fontscaler_%s", doLCD ? "lcd" : "aa");
+ fText.set("abcdefghijklmnopqrstuvwxyz01234567890");
+ fDoLCD = doLCD;
+ }
+
+protected:
+ virtual const char* onGetName() { return fName.c_str(); }
+ virtual void onDraw(const int loops, SkCanvas* canvas) {
+ SkPaint paint;
+ this->setupPaint(&paint);
+ paint.setLCDRenderText(fDoLCD);
+
+ for (int i = 0; i < loops; i++) {
+ // this is critical - we want to time the creation process, so we
+ // explicitly flush our cache before each run
+ SkGraphics::PurgeFontCache();
+
+ for (int ps = 9; ps <= 24; ps += 2) {
+ paint.setTextSize(SkIntToScalar(ps));
+ canvas->drawText(fText.c_str(), fText.size(),
+ 0, SkIntToScalar(20), paint);
+ }
+ }
+ }
+private:
+ typedef Benchmark INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH( return SkNEW_ARGS(FontScalerBench, (false)); )
+DEF_BENCH( return SkNEW_ARGS(FontScalerBench, (true)); )
diff --git a/chromium/third_party/skia/bench/GMBench.cpp b/chromium/third_party/skia/bench/GMBench.cpp
new file mode 100644
index 00000000000..41a8e8c5f4c
--- /dev/null
+++ b/chromium/third_party/skia/bench/GMBench.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GMBench.h"
+
+GMBench::GMBench(skiagm::GM* gm) : fGM(gm) {
+ fName.printf("GM:%s", gm->getName());
+}
+
+GMBench::~GMBench() { delete fGM; }
+
+const char* GMBench::onGetName() {
+ return fName.c_str();
+}
+
+bool GMBench::isSuitableFor(Backend backend) {
+ uint32_t flags = fGM->getFlags();
+ switch (backend) {
+ case kGPU_Backend:
+ return !(skiagm::GM::kSkipGPU_Flag & flags);
+ case kPDF_Backend:
+ return !(skiagm::GM::kSkipPDF_Flag & flags);
+ case kRaster_Backend:
+ // GM doesn't have an equivalent flag. If the GM has known issues with 565 then
+ // we skip it for ALL raster configs in bench.
+ return !(skiagm::GM::kSkip565_Flag & flags);
+ case kNonRendering_Backend:
+ return false;
+ default:
+ SkDEBUGFAIL("Unexpected backend type.");
+ return false;
+ }
+}
+
+void GMBench::onDraw(const int loops, SkCanvas* canvas) {
+ // Do we care about timing the draw of the background (once)?
+ // Does the GM ever rely on drawBackground to lazily compute something?
+ fGM->drawBackground(canvas);
+ for (int i = 0; i < loops; ++i) {
+ fGM->drawContent(canvas);
+ }
+}
+
+SkIPoint GMBench::onGetSize() {
+ SkISize size = fGM->getISize();
+ return SkIPoint::Make(size.fWidth, size.fHeight);
+}
diff --git a/chromium/third_party/skia/bench/GMBench.h b/chromium/third_party/skia/bench/GMBench.h
new file mode 100644
index 00000000000..75cee6c0639
--- /dev/null
+++ b/chromium/third_party/skia/bench/GMBench.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkCanvas.h"
+#include "gm.h"
+
+/**
+ * Runs a GM as a benchmark by repeatedly drawing the GM.
+ */
+class GMBench : public Benchmark {
+public:
+ // Constructor takes ownership of the GM param.
+ GMBench(skiagm::GM* gm);
+ virtual ~GMBench();
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE;
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE;
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE;
+ virtual SkIPoint onGetSize() SK_OVERRIDE;
+
+private:
+ skiagm::GM* fGM;
+ SkString fName;
+ typedef Benchmark INHERITED;
+};
diff --git a/chromium/third_party/skia/bench/GameBench.cpp b/chromium/third_party/skia/bench/GameBench.cpp
new file mode 100644
index 00000000000..c37f46df302
--- /dev/null
+++ b/chromium/third_party/skia/bench/GameBench.cpp
@@ -0,0 +1,334 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkCanvas.h"
+#include "SkPaint.h"
+#include "SkRandom.h"
+#include "SkShader.h"
+#include "SkString.h"
+
+// This bench simulates the calls Skia sees from various HTML5 canvas
+// game bench marks
+class GameBench : public Benchmark {
+public:
+ enum Type {
+ kScale_Type,
+ kTranslate_Type,
+ kRotate_Type
+ };
+
+ enum Clear {
+ kFull_Clear,
+ kPartial_Clear
+ };
+
+ GameBench(Type type, Clear clear,
+ bool aligned = false, bool useAtlas = false,
+ bool useDrawVertices = false)
+ : fType(type)
+ , fClear(clear)
+ , fAligned(aligned)
+ , fUseAtlas(useAtlas)
+ , fUseDrawVertices(useDrawVertices)
+ , fName("game")
+ , fNumSaved(0)
+ , fInitialized(false) {
+
+ switch (fType) {
+ case kScale_Type:
+ fName.append("_scale");
+ break;
+ case kTranslate_Type:
+ fName.append("_trans");
+ break;
+ case kRotate_Type:
+ fName.append("_rot");
+ break;
+ };
+
+ if (aligned) {
+ fName.append("_aligned");
+ }
+
+ if (kPartial_Clear == clear) {
+ fName.append("_partial");
+ } else {
+ fName.append("_full");
+ }
+
+ if (useAtlas) {
+ fName.append("_atlas");
+ }
+
+ if (useDrawVertices) {
+ fName.append("_drawVerts");
+ }
+
+ // It's HTML 5 canvas, so always AA
+ fName.append("_aa");
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+
+ virtual void onPreDraw() SK_OVERRIDE {
+ if (!fInitialized) {
+ this->makeCheckerboard();
+ this->makeAtlas();
+ fInitialized = true;
+ }
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkRandom scaleRand;
+ SkRandom transRand;
+ SkRandom rotRand;
+
+ int width, height;
+ if (fUseAtlas) {
+ width = kAtlasCellWidth;
+ height = kAtlasCellHeight;
+ } else {
+ width = kCheckerboardWidth;
+ height = kCheckerboardHeight;
+ }
+
+ SkPaint clearPaint;
+ clearPaint.setColor(0xFF000000);
+ clearPaint.setAntiAlias(true);
+
+ SkISize size = canvas->getDeviceSize();
+
+ SkScalar maxTransX, maxTransY;
+
+ if (kScale_Type == fType) {
+ maxTransX = size.fWidth - (1.5f * width);
+ maxTransY = size.fHeight - (1.5f * height);
+ } else if (kTranslate_Type == fType) {
+ maxTransX = SkIntToScalar(size.fWidth - width);
+ maxTransY = SkIntToScalar(size.fHeight - height);
+ } else {
+ SkASSERT(kRotate_Type == fType);
+ // Yes, some rotations will be off the top and left sides
+ maxTransX = size.fWidth - SK_ScalarSqrt2 * height;
+ maxTransY = size.fHeight - SK_ScalarSqrt2 * height;
+ }
+
+ SkMatrix mat;
+ SkRect dst = { 0, 0, SkIntToScalar(width), SkIntToScalar(height) };
+ SkRect clearRect = { -1.0f, -1.0f, width+1.0f, height+1.0f };
+ SkPoint verts[4] = { // for drawVertices path
+ { 0, 0 },
+ { 0, SkIntToScalar(height) },
+ { SkIntToScalar(width), SkIntToScalar(height) },
+ { SkIntToScalar(width), 0 }
+ };
+ uint16_t indices[6] = { 0, 1, 2, 0, 2, 3 };
+
+ SkPaint p;
+ p.setColor(0xFF000000);
+ p.setFilterLevel(SkPaint::kLow_FilterLevel);
+
+ SkPaint p2; // for drawVertices path
+ p2.setColor(0xFF000000);
+ p2.setFilterLevel(SkPaint::kLow_FilterLevel);
+ p2.setShader(SkShader::CreateBitmapShader(fAtlas,
+ SkShader::kClamp_TileMode,
+ SkShader::kClamp_TileMode))->unref();
+
+ for (int i = 0; i < loops; ++i, ++fNumSaved) {
+ if (0 == i % kNumBeforeClear) {
+ if (kPartial_Clear == fClear) {
+ for (int j = 0; j < fNumSaved; ++j) {
+ canvas->setMatrix(SkMatrix::I());
+ mat.setTranslate(fSaved[j][0], fSaved[j][1]);
+
+ if (kScale_Type == fType) {
+ mat.preScale(fSaved[j][2], fSaved[j][2]);
+ } else if (kRotate_Type == fType) {
+ mat.preRotate(fSaved[j][2]);
+ }
+
+ canvas->concat(mat);
+ canvas->drawRect(clearRect, clearPaint);
+ }
+ } else {
+ canvas->clear(0xFF000000);
+ }
+
+ fNumSaved = 0;
+ }
+
+ SkASSERT(fNumSaved < kNumBeforeClear);
+
+ canvas->setMatrix(SkMatrix::I());
+
+ fSaved[fNumSaved][0] = transRand.nextRangeScalar(0.0f, maxTransX);
+ fSaved[fNumSaved][1] = transRand.nextRangeScalar(0.0f, maxTransY);
+ if (fAligned) {
+ // make the translations integer aligned
+ fSaved[fNumSaved][0] = SkScalarFloorToScalar(fSaved[fNumSaved][0]);
+ fSaved[fNumSaved][1] = SkScalarFloorToScalar(fSaved[fNumSaved][1]);
+ }
+
+ mat.setTranslate(fSaved[fNumSaved][0], fSaved[fNumSaved][1]);
+
+ if (kScale_Type == fType) {
+ fSaved[fNumSaved][2] = scaleRand.nextRangeScalar(0.5f, 1.5f);
+ mat.preScale(fSaved[fNumSaved][2], fSaved[fNumSaved][2]);
+ } else if (kRotate_Type == fType) {
+ fSaved[fNumSaved][2] = rotRand.nextRangeScalar(0.0f, 360.0f);
+ mat.preRotate(fSaved[fNumSaved][2]);
+ }
+
+ canvas->concat(mat);
+ if (fUseAtlas) {
+ const int curCell = i % (kNumAtlasedX * kNumAtlasedY);
+ SkIRect src = fAtlasRects[curCell % (kNumAtlasedX)][curCell / (kNumAtlasedX)];
+
+ if (fUseDrawVertices) {
+ SkPoint uvs[4] = {
+ { SkIntToScalar(src.fLeft), SkIntToScalar(src.fBottom) },
+ { SkIntToScalar(src.fLeft), SkIntToScalar(src.fTop) },
+ { SkIntToScalar(src.fRight), SkIntToScalar(src.fTop) },
+ { SkIntToScalar(src.fRight), SkIntToScalar(src.fBottom) },
+ };
+ canvas->drawVertices(SkCanvas::kTriangles_VertexMode,
+ 4, verts, uvs, NULL, NULL,
+ indices, 6, p2);
+ } else {
+ canvas->drawBitmapRect(fAtlas, &src, dst, &p,
+ SkCanvas::kBleed_DrawBitmapRectFlag);
+ }
+ } else {
+ canvas->drawBitmapRect(fCheckerboard, NULL, dst, &p);
+ }
+ }
+ }
+
+private:
+ static const int kCheckerboardWidth = 64;
+ static const int kCheckerboardHeight = 128;
+
+ static const int kAtlasCellWidth = 48;
+ static const int kAtlasCellHeight = 36;
+ static const int kNumAtlasedX = 5;
+ static const int kNumAtlasedY = 5;
+ static const int kAtlasSpacer = 2;
+ static const int kTotAtlasWidth = kNumAtlasedX * kAtlasCellWidth +
+ (kNumAtlasedX+1) * kAtlasSpacer;
+ static const int kTotAtlasHeight = kNumAtlasedY * kAtlasCellHeight +
+ (kNumAtlasedY+1) * kAtlasSpacer;
+ static const int kNumBeforeClear = 100;
+
+ Type fType;
+ Clear fClear;
+ bool fAligned;
+ bool fUseAtlas;
+ bool fUseDrawVertices;
+ SkString fName;
+ int fNumSaved; // num draws stored in 'fSaved'
+ bool fInitialized;
+
+ // 0 & 1 are always x & y translate. 2 is either scale or rotate.
+ SkScalar fSaved[kNumBeforeClear][3];
+
+ SkBitmap fCheckerboard;
+ SkBitmap fAtlas;
+ SkIRect fAtlasRects[kNumAtlasedX][kNumAtlasedY];
+
+ // Note: the resulting checker board has transparency
+ void makeCheckerboard() {
+ static int kCheckSize = 16;
+
+ fCheckerboard.allocN32Pixels(kCheckerboardWidth, kCheckerboardHeight);
+ SkAutoLockPixels lock(fCheckerboard);
+ for (int y = 0; y < kCheckerboardHeight; ++y) {
+ int even = (y / kCheckSize) % 2;
+
+ SkPMColor* scanline = fCheckerboard.getAddr32(0, y);
+
+ for (int x = 0; x < kCheckerboardWidth; ++x) {
+ if (even == (x / kCheckSize) % 2) {
+ *scanline++ = 0xFFFF0000;
+ } else {
+ *scanline++ = 0x00000000;
+ }
+ }
+ }
+ }
+
+ // Note: the resulting atlas has transparency
+ void makeAtlas() {
+ SkRandom rand;
+
+ SkColor colors[kNumAtlasedX][kNumAtlasedY];
+
+ for (int y = 0; y < kNumAtlasedY; ++y) {
+ for (int x = 0; x < kNumAtlasedX; ++x) {
+ colors[x][y] = rand.nextU() | 0xff000000;
+ fAtlasRects[x][y] = SkIRect::MakeXYWH(kAtlasSpacer + x * (kAtlasCellWidth + kAtlasSpacer),
+ kAtlasSpacer + y * (kAtlasCellHeight + kAtlasSpacer),
+ kAtlasCellWidth,
+ kAtlasCellHeight);
+ }
+ }
+
+ fAtlas.allocN32Pixels(kTotAtlasWidth, kTotAtlasHeight);
+ SkAutoLockPixels lock(fAtlas);
+
+ for (int y = 0; y < kTotAtlasHeight; ++y) {
+ int colorY = y / (kAtlasCellHeight + kAtlasSpacer);
+ bool inColorY = (y % (kAtlasCellHeight + kAtlasSpacer)) >= kAtlasSpacer;
+
+ SkPMColor* scanline = fAtlas.getAddr32(0, y);
+
+ for (int x = 0; x < kTotAtlasWidth; ++x, ++scanline) {
+ int colorX = x / (kAtlasCellWidth + kAtlasSpacer);
+ bool inColorX = (x % (kAtlasCellWidth + kAtlasSpacer)) >= kAtlasSpacer;
+
+ if (inColorX && inColorY) {
+ SkASSERT(colorX < kNumAtlasedX && colorY < kNumAtlasedY);
+ *scanline = colors[colorX][colorY];
+ } else {
+ *scanline = 0x00000000;
+ }
+ }
+ }
+ }
+
+ typedef Benchmark INHERITED;
+};
+
+// Partial clear
+DEF_BENCH( return SkNEW_ARGS(GameBench, (GameBench::kScale_Type,
+ GameBench::kPartial_Clear)); )
+DEF_BENCH( return SkNEW_ARGS(GameBench, (GameBench::kTranslate_Type,
+ GameBench::kPartial_Clear)); )
+DEF_BENCH( return SkNEW_ARGS(GameBench, (GameBench::kTranslate_Type,
+ GameBench::kPartial_Clear, true)); )
+DEF_BENCH( return SkNEW_ARGS(GameBench, (GameBench::kRotate_Type,
+ GameBench::kPartial_Clear)); )
+
+// Full clear
+DEF_BENCH( return SkNEW_ARGS(GameBench, (GameBench::kScale_Type,
+ GameBench::kFull_Clear)); )
+DEF_BENCH( return SkNEW_ARGS(GameBench, (GameBench::kTranslate_Type,
+ GameBench::kFull_Clear)); )
+DEF_BENCH( return SkNEW_ARGS(GameBench, (GameBench::kTranslate_Type,
+ GameBench::kFull_Clear, true)); )
+DEF_BENCH( return SkNEW_ARGS(GameBench, (GameBench::kRotate_Type,
+ GameBench::kFull_Clear)); )
+
+// Atlased
+DEF_BENCH( return SkNEW_ARGS(GameBench, (GameBench::kTranslate_Type,
+ GameBench::kFull_Clear, false, true)); )
+DEF_BENCH( return SkNEW_ARGS(GameBench, (GameBench::kTranslate_Type,
+ GameBench::kFull_Clear, false, true, true)); )
diff --git a/chromium/third_party/skia/bench/GrMemoryPoolBench.cpp b/chromium/third_party/skia/bench/GrMemoryPoolBench.cpp
new file mode 100644
index 00000000000..6e6a37e76c8
--- /dev/null
+++ b/chromium/third_party/skia/bench/GrMemoryPoolBench.cpp
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// This tests a Gr class
+#if SK_SUPPORT_GPU
+
+#include "Benchmark.h"
+#include "GrMemoryPool.h"
+#include "SkRandom.h"
+#include "SkTDArray.h"
+#include "SkTemplates.h"
+
+// change this to 0 to compare GrMemoryPool to default new / delete
+#define OVERRIDE_NEW 1
+
+struct A {
+ int gStuff[10];
+#if OVERRIDE_NEW
+ void* operator new (size_t size) { return gBenchPool.allocate(size); }
+ void operator delete (void* mem) { if (mem) { return gBenchPool.release(mem); } }
+#endif
+ static GrMemoryPool gBenchPool;
+};
+GrMemoryPool A::gBenchPool(10 * (1 << 10), 10 * (1 << 10));
+
+/**
+ * This benchmark creates and deletes objects in stack order
+ */
+class GrMemoryPoolBenchStack : public Benchmark {
+public:
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+protected:
+ virtual const char* onGetName() {
+ return "grmemorypool_stack";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) {
+ SkRandom r;
+ enum {
+ kMaxObjects = 4 * (1 << 10),
+ };
+ A* objects[kMaxObjects];
+
+ // We delete if a random [-1, 1] fixed pt is < the thresh. Otherwise,
+ // we allocate. We start allocate-biased and ping-pong to delete-biased
+ SkFixed delThresh = -SK_FixedHalf;
+ const int kSwitchThreshPeriod = loops / (2 * kMaxObjects);
+ int s = 0;
+
+ int count = 0;
+ for (int i = 0; i < loops; i++, ++s) {
+ if (kSwitchThreshPeriod == s) {
+ delThresh = -delThresh;
+ s = 0;
+ }
+ SkFixed del = r.nextSFixed1();
+ if (count &&
+ (kMaxObjects == count || del < delThresh)) {
+ delete objects[count-1];
+ --count;
+ } else {
+ objects[count] = new A;
+ ++count;
+ }
+ }
+ for (int i = 0; i < count; ++i) {
+ delete objects[i];
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+struct B {
+ int gStuff[10];
+#if OVERRIDE_NEW
+ void* operator new (size_t size) { return gBenchPool.allocate(size); }
+ void operator delete (void* mem) { if (mem) { return gBenchPool.release(mem); } }
+#endif
+ static GrMemoryPool gBenchPool;
+};
+GrMemoryPool B::gBenchPool(10 * (1 << 10), 10 * (1 << 10));
+
+/**
+ * This benchmark creates objects and deletes them in random order
+ */
+class GrMemoryPoolBenchRandom : public Benchmark {
+public:
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+protected:
+ virtual const char* onGetName() {
+ return "grmemorypool_random";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) {
+ SkRandom r;
+ enum {
+ kMaxObjects = 4 * (1 << 10),
+ };
+ SkAutoTDelete<B> objects[kMaxObjects];
+
+ for (int i = 0; i < loops; i++) {
+ uint32_t idx = r.nextRangeU(0, kMaxObjects-1);
+ if (NULL == objects[idx].get()) {
+ objects[idx].reset(new B);
+ } else {
+ objects[idx].free();
+ }
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+struct C {
+ int gStuff[10];
+#if OVERRIDE_NEW
+ void* operator new (size_t size) { return gBenchPool.allocate(size); }
+ void operator delete (void* mem) { if (mem) { return gBenchPool.release(mem); } }
+#endif
+ static GrMemoryPool gBenchPool;
+};
+GrMemoryPool C::gBenchPool(10 * (1 << 10), 10 * (1 << 10));
+
+/**
+ * This benchmark creates objects and deletes them in queue order
+ */
+class GrMemoryPoolBenchQueue : public Benchmark {
+ enum {
+ M = 4 * (1 << 10),
+ };
+public:
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+protected:
+ virtual const char* onGetName() {
+ return "grmemorypool_queue";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) {
+ SkRandom r;
+ C* objects[M];
+ for (int i = 0; i < loops; i++) {
+ uint32_t count = r.nextRangeU(0, M-1);
+ for (uint32_t i = 0; i < count; i++) {
+ objects[i] = new C;
+ }
+ for (uint32_t i = 0; i < count; i++) {
+ delete objects[i];
+ }
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH( return new GrMemoryPoolBenchStack(); )
+DEF_BENCH( return new GrMemoryPoolBenchRandom(); )
+DEF_BENCH( return new GrMemoryPoolBenchQueue(); )
+
+#endif
diff --git a/chromium/third_party/skia/bench/GrOrderedSetBench.cpp b/chromium/third_party/skia/bench/GrOrderedSetBench.cpp
new file mode 100644
index 00000000000..dde1c4a3f0d
--- /dev/null
+++ b/chromium/third_party/skia/bench/GrOrderedSetBench.cpp
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkCanvas.h"
+#include "SkRandom.h"
+#include "SkString.h"
+#if SK_SUPPORT_GPU
+#include "GrOrderedSet.h"
+
+static const int NUM_ELEMENTS = 1000;
+
+// Time how long it takes to build a set
+class GrOrderedSetBuildBench : public Benchmark {
+public:
+ GrOrderedSetBuildBench() {
+ fName.append("ordered_set_build");
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return kNonRendering_Backend == backend;
+ }
+
+ virtual ~GrOrderedSetBuildBench() {}
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+
+ virtual void onPreDraw() SK_OVERRIDE {
+ SkRandom rand;
+ for (int j = 0; j < NUM_ELEMENTS; ++j) {
+ fData[j] = rand.nextU() % NUM_ELEMENTS;
+ }
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ for (int i = 0; i < loops; ++i) {
+ GrOrderedSet<int> set;
+ for (int j = 0; j < NUM_ELEMENTS; ++j) {
+ set.insert(fData[j]);
+ }
+ set.reset();
+ }
+ }
+
+private:
+ SkString fName;
+ int fData[NUM_ELEMENTS];
+ typedef Benchmark INHERITED;
+};
+
+// Time how long it takes to find elements in a set
+class GrOrderedSetFindBench : public Benchmark {
+public:
+ GrOrderedSetFindBench() {
+ fName.append("ordered_set_find");
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return kNonRendering_Backend == backend;
+ }
+
+ virtual ~GrOrderedSetFindBench() {}
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+
+ virtual void onPreDraw() SK_OVERRIDE {
+ SkRandom rand;
+ for (int j = 0; j < NUM_ELEMENTS; ++j) {
+ fData[j] = rand.nextU() % 1500;
+ fSet.insert(rand.nextU() % NUM_ELEMENTS);
+ }
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ for (int i = 0; i < loops; ++i) {
+ for (int j = 0; j < NUM_ELEMENTS; ++j) {
+ fSet.find(fData[j]);
+ }
+ }
+ }
+
+private:
+ SkString fName;
+ int fData[NUM_ELEMENTS];
+ GrOrderedSet<int> fSet;
+ typedef Benchmark INHERITED;
+};
+
+// Time how long it takes to iterate over and remove all elements from set
+class GrOrderedSetRemoveBench : public Benchmark {
+public:
+ GrOrderedSetRemoveBench() {
+ fName.append("ordered_set_remove");
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return kNonRendering_Backend == backend;
+ }
+
+ virtual ~GrOrderedSetRemoveBench() {}
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+
+ virtual void onPreDraw() SK_OVERRIDE {
+ SkRandom rand;
+ for (int j = 0; j < NUM_ELEMENTS; ++j) {
+ fSet.insert(rand.nextU() % NUM_ELEMENTS);
+ }
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ typedef GrOrderedSet<int>::Iter SetIter;
+ for (int i = 0; i < loops; ++i) {
+ GrOrderedSet<int> testSet;
+ for (SetIter s = fSet.begin(); fSet.end() != s; ++s) {
+ testSet.insert(*s);
+ }
+ for (int j = 0; j < NUM_ELEMENTS; ++j) {
+ testSet.remove(testSet.find(j));
+ }
+ }
+ }
+
+private:
+ SkString fName;
+ GrOrderedSet<int> fSet;
+ typedef Benchmark INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH(return SkNEW_ARGS(GrOrderedSetBuildBench, ());)
+DEF_BENCH(return SkNEW_ARGS(GrOrderedSetFindBench, ());)
+DEF_BENCH(return SkNEW_ARGS(GrOrderedSetRemoveBench, ());)
+#endif
diff --git a/chromium/third_party/skia/bench/GrResourceCacheBench.cpp b/chromium/third_party/skia/bench/GrResourceCacheBench.cpp
new file mode 100644
index 00000000000..93ae356a4c1
--- /dev/null
+++ b/chromium/third_party/skia/bench/GrResourceCacheBench.cpp
@@ -0,0 +1,239 @@
+
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#if SK_SUPPORT_GPU
+
+#include "Benchmark.h"
+#include "GrCacheable.h"
+#include "GrContext.h"
+#include "GrResourceCache.h"
+#include "GrStencilBuffer.h"
+#include "GrTexture.h"
+#include "SkCanvas.h"
+
+enum {
+ CACHE_SIZE_COUNT = 2048,
+ CACHE_SIZE_BYTES = 2 * 1024 * 1024,
+};
+
+class StencilResource : public GrCacheable {
+public:
+ SK_DECLARE_INST_COUNT(StencilResource);
+ StencilResource(int id)
+ : fID(id) {
+ }
+
+ virtual size_t gpuMemorySize() const SK_OVERRIDE {
+ return 100 + ((fID % 1 == 0) ? -5 : 6);
+ }
+
+ virtual bool isValidOnGpu() const SK_OVERRIDE {
+ return true;
+ }
+
+ static GrResourceKey ComputeKey(int width, int height, int sampleCnt) {
+ return GrStencilBuffer::ComputeKey(width, height, sampleCnt);
+ }
+
+ int fID;
+
+private:
+ typedef GrCacheable INHERITED;
+};
+
+class TextureResource : public GrCacheable {
+public:
+ SK_DECLARE_INST_COUNT(TextureResource);
+ TextureResource(int id)
+ : fID(id) {
+ }
+
+ virtual size_t gpuMemorySize() const SK_OVERRIDE {
+ return 100 + ((fID % 1 == 0) ? -40 : 33);
+ }
+
+ virtual bool isValidOnGpu() const SK_OVERRIDE {
+ return true;
+ }
+
+ static GrResourceKey ComputeKey(const GrTextureDesc& desc) {
+ return GrTextureImpl::ComputeScratchKey(desc);
+ }
+
+ int fID;
+
+private:
+ typedef GrCacheable INHERITED;
+};
+
+static void get_stencil(int i, int* w, int* h, int* s) {
+ *w = i % 1024;
+ *h = i * 2 % 1024;
+ *s = i % 1 == 0 ? 0 : 4;
+}
+
+static void get_texture_desc(int i, GrTextureDesc* desc) {
+ desc->fFlags = kRenderTarget_GrTextureFlagBit |
+ kNoStencil_GrTextureFlagBit;
+ desc->fWidth = i % 1024;
+ desc->fHeight = i * 2 % 1024;
+ desc->fConfig = static_cast<GrPixelConfig>(i % (kLast_GrPixelConfig + 1));
+ desc->fSampleCnt = i % 1 == 0 ? 0 : 4;
+}
+
+static void populate_cache(GrResourceCache* cache, GrGpu* gpu, int resourceCount) {
+ for (int i = 0; i < resourceCount; ++i) {
+ int w, h, s;
+ get_stencil(i, &w, &h, &s);
+ GrResourceKey key = GrStencilBuffer::ComputeKey(w, h, s);
+ GrCacheable* resource = SkNEW_ARGS(StencilResource, (i));
+ cache->purgeAsNeeded(1, resource->gpuMemorySize());
+ cache->addResource(key, resource);
+ resource->unref();
+ }
+
+ for (int i = 0; i < resourceCount; ++i) {
+ GrTextureDesc desc;
+ get_texture_desc(i, &desc);
+ GrResourceKey key = TextureResource::ComputeKey(desc);
+ GrCacheable* resource = SkNEW_ARGS(TextureResource, (i));
+ cache->purgeAsNeeded(1, resource->gpuMemorySize());
+ cache->addResource(key, resource);
+ resource->unref();
+ }
+}
+
+static void check_cache_contents_or_die(GrResourceCache* cache, int k) {
+ // Benchmark find calls that succeed.
+ {
+ GrTextureDesc desc;
+ get_texture_desc(k, &desc);
+ GrResourceKey key = TextureResource::ComputeKey(desc);
+ GrCacheable* item = cache->find(key);
+ if (NULL == item) {
+ SkFAIL("cache add does not work as expected");
+ return;
+ }
+ if (static_cast<TextureResource*>(item)->fID != k) {
+ SkFAIL("cache add does not work as expected");
+ return;
+ }
+ }
+ {
+ int w, h, s;
+ get_stencil(k, &w, &h, &s);
+ GrResourceKey key = StencilResource::ComputeKey(w, h, s);
+ GrCacheable* item = cache->find(key);
+ if (NULL == item) {
+ SkFAIL("cache add does not work as expected");
+ return;
+ }
+ if (static_cast<TextureResource*>(item)->fID != k) {
+ SkFAIL("cache add does not work as expected");
+ return;
+ }
+ }
+
+ // Benchmark also find calls that always fail.
+ {
+ GrTextureDesc desc;
+ get_texture_desc(k, &desc);
+ desc.fHeight |= 1;
+ GrResourceKey key = TextureResource::ComputeKey(desc);
+ GrCacheable* item = cache->find(key);
+ if (NULL != item) {
+ SkFAIL("cache add does not work as expected");
+ return;
+ }
+ }
+ {
+ int w, h, s;
+ get_stencil(k, &w, &h, &s);
+ h |= 1;
+ GrResourceKey key = StencilResource::ComputeKey(w, h, s);
+ GrCacheable* item = cache->find(key);
+ if (NULL != item) {
+ SkFAIL("cache add does not work as expected");
+ return;
+ }
+ }
+}
+
+class GrResourceCacheBenchAdd : public Benchmark {
+ enum {
+ RESOURCE_COUNT = CACHE_SIZE_COUNT / 2,
+ DUPLICATE_COUNT = CACHE_SIZE_COUNT / 4,
+ };
+
+public:
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kGPU_Backend;
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return "grresourcecache_add";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ GrGpu* gpu = canvas->getGrContext()->getGpu();
+
+ for (int i = 0; i < loops; ++i) {
+ GrResourceCache cache(CACHE_SIZE_COUNT, CACHE_SIZE_BYTES);
+ populate_cache(&cache, gpu, DUPLICATE_COUNT);
+ populate_cache(&cache, gpu, RESOURCE_COUNT);
+
+ // Check that cache works.
+ for (int k = 0; k < RESOURCE_COUNT; k += 33) {
+ check_cache_contents_or_die(&cache, k);
+ }
+ cache.purgeAllUnlocked();
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+class GrResourceCacheBenchFind : public Benchmark {
+ enum {
+ RESOURCE_COUNT = (CACHE_SIZE_COUNT / 2) - 100,
+ DUPLICATE_COUNT = 100
+ };
+
+public:
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kGPU_Backend;
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return "grresourcecache_find";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ GrGpu* gpu = canvas->getGrContext()->getGpu();
+ GrResourceCache cache(CACHE_SIZE_COUNT, CACHE_SIZE_BYTES);
+ populate_cache(&cache, gpu, DUPLICATE_COUNT);
+ populate_cache(&cache, gpu, RESOURCE_COUNT);
+
+ for (int i = 0; i < loops; ++i) {
+ for (int k = 0; k < RESOURCE_COUNT; ++k) {
+ check_cache_contents_or_die(&cache, k);
+ }
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+DEF_BENCH( return new GrResourceCacheBenchAdd(); )
+DEF_BENCH( return new GrResourceCacheBenchFind(); )
+
+#endif
diff --git a/chromium/third_party/skia/bench/GradientBench.cpp b/chromium/third_party/skia/bench/GradientBench.cpp
new file mode 100644
index 00000000000..f3e783e78fd
--- /dev/null
+++ b/chromium/third_party/skia/bench/GradientBench.cpp
@@ -0,0 +1,390 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "Benchmark.h"
+#include "SkBitmap.h"
+#include "SkCanvas.h"
+#include "SkColorPriv.h"
+#include "SkGradientShader.h"
+#include "SkPaint.h"
+#include "SkShader.h"
+#include "SkString.h"
+
+struct GradData {
+ int fCount;
+ const SkColor* fColors;
+ const SkScalar* fPos;
+ const char* fName;
+};
+
+static const SkColor gColors[] = {
+ SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK,
+ SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK,
+ SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK,
+ SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK,
+ SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK,
+ SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK,
+ SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK,
+ SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK,
+ SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK,
+ SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK, // 10 lines, 50 colors
+};
+
+static const SkColor gShallowColors[] = { 0xFF555555, 0xFF444444 };
+
+// We have several special-cases depending on the number (and spacing) of colors, so
+// try to exercise those here.
+static const GradData gGradData[] = {
+ { 2, gColors, NULL, "" },
+ { 50, gColors, NULL, "_hicolor" }, // many color gradient
+ { 3, gColors, NULL, "_3color" },
+ { 2, gShallowColors, NULL, "_shallow" },
+};
+
+/// Ignores scale
+static SkShader* MakeLinear(const SkPoint pts[2], const GradData& data,
+ SkShader::TileMode tm, float scale) {
+ return SkGradientShader::CreateLinear(pts, data.fColors, data.fPos, data.fCount, tm);
+}
+
+static SkShader* MakeRadial(const SkPoint pts[2], const GradData& data,
+ SkShader::TileMode tm, float scale) {
+ SkPoint center;
+ center.set(SkScalarAve(pts[0].fX, pts[1].fX),
+ SkScalarAve(pts[0].fY, pts[1].fY));
+ return SkGradientShader::CreateRadial(center, center.fX * scale,
+ data.fColors,
+ data.fPos, data.fCount, tm);
+}
+
+/// Ignores scale
+static SkShader* MakeSweep(const SkPoint pts[2], const GradData& data,
+ SkShader::TileMode tm, float scale) {
+ SkPoint center;
+ center.set(SkScalarAve(pts[0].fX, pts[1].fX),
+ SkScalarAve(pts[0].fY, pts[1].fY));
+ return SkGradientShader::CreateSweep(center.fX, center.fY, data.fColors,
+ data.fPos, data.fCount);
+}
+
+/// Ignores scale
+static SkShader* Make2Radial(const SkPoint pts[2], const GradData& data,
+ SkShader::TileMode tm, float scale) {
+ SkPoint center0, center1;
+ center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
+ SkScalarAve(pts[0].fY, pts[1].fY));
+ center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
+ SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
+ return SkGradientShader::CreateTwoPointRadial(
+ center1, (pts[1].fX - pts[0].fX) / 7,
+ center0, (pts[1].fX - pts[0].fX) / 2,
+ data.fColors, data.fPos, data.fCount, tm);
+}
+
+/// Ignores scale
+static SkShader* MakeConical(const SkPoint pts[2], const GradData& data,
+ SkShader::TileMode tm, float scale) {
+ SkPoint center0, center1;
+ center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
+ SkScalarAve(pts[0].fY, pts[1].fY));
+ center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
+ SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
+ return SkGradientShader::CreateTwoPointConical(center1, (pts[1].fX - pts[0].fX) / 7,
+ center0, (pts[1].fX - pts[0].fX) / 2,
+ data.fColors, data.fPos, data.fCount, tm);
+}
+
+/// Ignores scale
+static SkShader* MakeConicalZeroRad(const SkPoint pts[2], const GradData& data,
+ SkShader::TileMode tm, float scale) {
+ SkPoint center0, center1;
+ center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
+ SkScalarAve(pts[0].fY, pts[1].fY));
+ center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
+ SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
+ return SkGradientShader::CreateTwoPointConical(center1, 0.0,
+ center0, (pts[1].fX - pts[0].fX) / 2,
+ data.fColors, data.fPos, data.fCount, tm);
+}
+
+/// Ignores scale
+static SkShader* MakeConicalOutside(const SkPoint pts[2], const GradData& data,
+ SkShader::TileMode tm, float scale) {
+ SkPoint center0, center1;
+ SkScalar radius0 = SkScalarDiv(pts[1].fX - pts[0].fX, 10);
+ SkScalar radius1 = SkScalarDiv(pts[1].fX - pts[0].fX, 3);
+ center0.set(pts[0].fX + radius0, pts[0].fY + radius0);
+ center1.set(pts[1].fX - radius1, pts[1].fY - radius1);
+ return SkGradientShader::CreateTwoPointConical(center0, radius0,
+ center1, radius1,
+ data.fColors, data.fPos,
+ data.fCount, tm);
+}
+
+/// Ignores scale
+static SkShader* MakeConicalOutsideZeroRad(const SkPoint pts[2], const GradData& data,
+ SkShader::TileMode tm, float scale) {
+ SkPoint center0, center1;
+ SkScalar radius0 = SkScalarDiv(pts[1].fX - pts[0].fX, 10);
+ SkScalar radius1 = SkScalarDiv(pts[1].fX - pts[0].fX, 3);
+ center0.set(pts[0].fX + radius0, pts[0].fY + radius0);
+ center1.set(pts[1].fX - radius1, pts[1].fY - radius1);
+ return SkGradientShader::CreateTwoPointConical(center0, 0.0,
+ center1, radius1,
+ data.fColors, data.fPos,
+ data.fCount, tm);
+}
+
+typedef SkShader* (*GradMaker)(const SkPoint pts[2], const GradData& data,
+ SkShader::TileMode tm, float scale);
+
+static const struct {
+ GradMaker fMaker;
+ const char* fName;
+} gGrads[] = {
+ { MakeLinear, "linear" },
+ { MakeRadial, "radial1" },
+ { MakeSweep, "sweep" },
+ { Make2Radial, "radial2" },
+ { MakeConical, "conical" },
+ { MakeConicalZeroRad, "conicalZero" },
+ { MakeConicalOutside, "conicalOut" },
+ { MakeConicalOutsideZeroRad, "conicalOutZero" },
+};
+
+enum GradType { // these must match the order in gGrads
+ kLinear_GradType,
+ kRadial_GradType,
+ kSweep_GradType,
+ kRadial2_GradType,
+ kConical_GradType,
+ kConicalZero_GradType,
+ kConicalOut_GradType,
+ kConicalOutZero_GradType
+};
+
+enum GeomType {
+ kRect_GeomType,
+ kOval_GeomType
+};
+
+static const char* tilemodename(SkShader::TileMode tm) {
+ switch (tm) {
+ case SkShader::kClamp_TileMode:
+ return "clamp";
+ case SkShader::kRepeat_TileMode:
+ return "repeat";
+ case SkShader::kMirror_TileMode:
+ return "mirror";
+ default:
+ SkDEBUGFAIL("unknown tilemode");
+ return "error";
+ }
+}
+
+static const char* geomtypename(GeomType gt) {
+ switch (gt) {
+ case kRect_GeomType:
+ return "rectangle";
+ case kOval_GeomType:
+ return "oval";
+ default:
+ SkDEBUGFAIL("unknown geometry type");
+ return "error";
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+class GradientBench : public Benchmark {
+ SkString fName;
+ SkShader* fShader;
+ bool fDither;
+ enum {
+ W = 400,
+ H = 400,
+ kRepeat = 15,
+ };
+public:
+ SkShader* makeShader(GradType gradType, GradData data, SkShader::TileMode tm, float scale) {
+ const SkPoint pts[2] = {
+ { 0, 0 },
+ { SkIntToScalar(W), SkIntToScalar(H) }
+ };
+
+ return gGrads[gradType].fMaker(pts, data, tm, scale);
+ }
+
+ GradientBench(GradType gradType,
+ GradData data = gGradData[0],
+ SkShader::TileMode tm = SkShader::kClamp_TileMode,
+ GeomType geomType = kRect_GeomType,
+ float scale = 1.0f) {
+ fName.printf("gradient_%s_%s", gGrads[gradType].fName,
+ tilemodename(tm));
+ if (geomType != kRect_GeomType) {
+ fName.append("_");
+ fName.append(geomtypename(geomType));
+ }
+
+ if (scale != 1.f) {
+ fName.appendf("_scale_%g", scale);
+ }
+
+ fName.append(data.fName);
+
+ fDither = false;
+ fShader = this->makeShader(gradType, data, tm, scale);
+ fGeomType = geomType;
+ }
+
+ GradientBench(GradType gradType, GradData data, bool dither) {
+ const char *tmname = tilemodename(SkShader::kClamp_TileMode);
+ fName.printf("gradient_%s_%s", gGrads[gradType].fName, tmname);
+ fName.append(data.fName);
+
+ fDither = dither;
+ if (dither) {
+ fName.appendf("_dither");
+ }
+
+ fShader = this->makeShader(gradType, data, SkShader::kClamp_TileMode, 1.0f);
+ fGeomType = kRect_GeomType;
+ }
+
+ virtual ~GradientBench() {
+ fShader->unref();
+ }
+
+protected:
+ virtual const char* onGetName() {
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) {
+ SkPaint paint;
+ this->setupPaint(&paint);
+
+ paint.setShader(fShader);
+ if (fDither) {
+ paint.setDither(true);
+ }
+
+ SkRect r = { 0, 0, SkIntToScalar(W), SkIntToScalar(H) };
+ for (int i = 0; i < loops * kRepeat; i++) {
+ switch (fGeomType) {
+ case kRect_GeomType:
+ canvas->drawRect(r, paint);
+ break;
+ case kOval_GeomType:
+ canvas->drawOval(r, paint);
+ break;
+ }
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+
+ GeomType fGeomType;
+};
+
+DEF_BENCH( return new GradientBench(kLinear_GradType); )
+DEF_BENCH( return new GradientBench(kLinear_GradType, gGradData[1]); )
+DEF_BENCH( return new GradientBench(kLinear_GradType, gGradData[2]); )
+DEF_BENCH( return new GradientBench(kLinear_GradType, gGradData[0], SkShader::kMirror_TileMode); )
+
+DEF_BENCH( return new GradientBench(kRadial_GradType, gGradData[0]); )
+DEF_BENCH( return new GradientBench(kRadial_GradType, gGradData[1]); )
+DEF_BENCH( return new GradientBench(kRadial_GradType, gGradData[2]); )
+// Draw a radial gradient of radius 1/2 on a rectangle; half the lines should
+// be completely pinned, the other half should pe partially pinned
+DEF_BENCH( return new GradientBench(kRadial_GradType, gGradData[0], SkShader::kClamp_TileMode, kRect_GeomType, 0.5f); )
+
+// Draw a radial gradient on a circle of equal size; all the lines should
+// hit the unpinned fast path (so long as GradientBench.W == H)
+DEF_BENCH( return new GradientBench(kRadial_GradType, gGradData[0], SkShader::kClamp_TileMode, kOval_GeomType); )
+
+DEF_BENCH( return new GradientBench(kRadial_GradType, gGradData[0], SkShader::kMirror_TileMode); )
+DEF_BENCH( return new GradientBench(kRadial_GradType, gGradData[0], SkShader::kRepeat_TileMode); )
+DEF_BENCH( return new GradientBench(kSweep_GradType); )
+DEF_BENCH( return new GradientBench(kSweep_GradType, gGradData[1]); )
+DEF_BENCH( return new GradientBench(kSweep_GradType, gGradData[2]); )
+DEF_BENCH( return new GradientBench(kRadial2_GradType); )
+DEF_BENCH( return new GradientBench(kRadial2_GradType, gGradData[1]); )
+DEF_BENCH( return new GradientBench(kRadial2_GradType, gGradData[0], SkShader::kMirror_TileMode); )
+DEF_BENCH( return new GradientBench(kConical_GradType); )
+DEF_BENCH( return new GradientBench(kConical_GradType, gGradData[1]); )
+DEF_BENCH( return new GradientBench(kConical_GradType, gGradData[2]); )
+DEF_BENCH( return new GradientBench(kConicalZero_GradType); )
+DEF_BENCH( return new GradientBench(kConicalZero_GradType, gGradData[1]); )
+DEF_BENCH( return new GradientBench(kConicalZero_GradType, gGradData[2]); )
+DEF_BENCH( return new GradientBench(kConicalOut_GradType); )
+DEF_BENCH( return new GradientBench(kConicalOut_GradType, gGradData[1]); )
+DEF_BENCH( return new GradientBench(kConicalOut_GradType, gGradData[2]); )
+DEF_BENCH( return new GradientBench(kConicalOutZero_GradType); )
+DEF_BENCH( return new GradientBench(kConicalOutZero_GradType, gGradData[1]); )
+DEF_BENCH( return new GradientBench(kConicalOutZero_GradType, gGradData[2]); )
+
+// Dithering
+DEF_BENCH( return new GradientBench(kLinear_GradType, gGradData[3], true); )
+DEF_BENCH( return new GradientBench(kLinear_GradType, gGradData[3], false); )
+DEF_BENCH( return new GradientBench(kRadial_GradType, gGradData[3], true); )
+DEF_BENCH( return new GradientBench(kRadial_GradType, gGradData[3], false); )
+DEF_BENCH( return new GradientBench(kSweep_GradType, gGradData[3], true); )
+DEF_BENCH( return new GradientBench(kSweep_GradType, gGradData[3], false); )
+DEF_BENCH( return new GradientBench(kConical_GradType, gGradData[3], true); )
+DEF_BENCH( return new GradientBench(kConical_GradType, gGradData[3], false); )
+
+///////////////////////////////////////////////////////////////////////////////
+
+class Gradient2Bench : public Benchmark {
+ SkString fName;
+ bool fHasAlpha;
+
+public:
+ Gradient2Bench(bool hasAlpha) {
+ fName.printf("gradient_create_%s", hasAlpha ? "alpha" : "opaque");
+ fHasAlpha = hasAlpha;
+ }
+
+protected:
+ virtual const char* onGetName() {
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) {
+ SkPaint paint;
+ this->setupPaint(&paint);
+
+ const SkRect r = { 0, 0, SkIntToScalar(4), SkIntToScalar(4) };
+ const SkPoint pts[] = {
+ { 0, 0 },
+ { SkIntToScalar(100), SkIntToScalar(100) },
+ };
+
+ for (int i = 0; i < loops; i++) {
+ const int gray = i % 256;
+ const int alpha = fHasAlpha ? gray : 0xFF;
+ SkColor colors[] = {
+ SK_ColorBLACK,
+ SkColorSetARGB(alpha, gray, gray, gray),
+ SK_ColorWHITE };
+ SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL,
+ SK_ARRAY_COUNT(colors),
+ SkShader::kClamp_TileMode);
+ paint.setShader(s)->unref();
+ canvas->drawRect(r, paint);
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+DEF_BENCH( return new Gradient2Bench(false); )
+DEF_BENCH( return new Gradient2Bench(true); )
diff --git a/chromium/third_party/skia/bench/HairlinePathBench.cpp b/chromium/third_party/skia/bench/HairlinePathBench.cpp
new file mode 100644
index 00000000000..e7e2b428e8f
--- /dev/null
+++ b/chromium/third_party/skia/bench/HairlinePathBench.cpp
@@ -0,0 +1,258 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkCanvas.h"
+#include "SkPaint.h"
+#include "SkRandom.h"
+#include "SkShader.h"
+#include "SkString.h"
+
+#if SK_SUPPORT_GPU
+#include "GrDrawTargetCaps.h"
+#include "GrTest.h"
+#endif
+
+enum Flags {
+ kBig_Flag = 1 << 0,
+ kAA_Flag = 1 << 1
+};
+
+#define FLAGS00 Flags(0)
+#define FLAGS01 Flags(kBig_Flag)
+#define FLAGS10 Flags(kAA_Flag)
+#define FLAGS11 Flags(kBig_Flag | kAA_Flag)
+
+static const int points[] = {
+ 10, 10, 15, 5, 20, 20,
+ 30, 5, 25, 20, 15, 12,
+ 21, 21, 30, 30, 12, 4,
+ 32, 28, 20, 18, 12, 10
+};
+
+static const int kMaxPathSize = 10;
+
+class HairlinePathBench : public Benchmark {
+public:
+ HairlinePathBench(Flags flags) : fFlags(flags) {
+ fPaint.setStyle(SkPaint::kStroke_Style);
+ fPaint.setStrokeWidth(SkIntToScalar(0));
+ }
+
+ virtual void appendName(SkString*) = 0;
+ virtual void makePath(SkPath*) = 0;
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ fName.printf("path_hairline_%s_%s_",
+ fFlags & kBig_Flag ? "big" : "small",
+ fFlags & kAA_Flag ? "AA" : "noAA");
+ this->appendName(&fName);
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkPaint paint(fPaint);
+ this->setupPaint(&paint);
+
+ paint.setAntiAlias(fFlags & kAA_Flag ? true : false);
+
+ SkPath path;
+ this->makePath(&path);
+ if (fFlags & kBig_Flag) {
+ SkMatrix m;
+ m.setScale(SkIntToScalar(3), SkIntToScalar(3));
+ path.transform(m);
+ }
+
+ for (int i = 0; i < loops; i++) {
+ canvas->drawPath(path, paint);
+ }
+ }
+
+private:
+ SkPaint fPaint;
+ SkString fName;
+ Flags fFlags;
+ typedef Benchmark INHERITED;
+};
+
+class LinePathBench : public HairlinePathBench {
+public:
+ LinePathBench(Flags flags) : INHERITED(flags) {}
+
+ virtual void appendName(SkString* name) SK_OVERRIDE {
+ name->append("line");
+ }
+ virtual void makePath(SkPath* path) SK_OVERRIDE {
+ SkRandom rand;
+ int size = SK_ARRAY_COUNT(points);
+ int hSize = size / 2;
+ for (int i = 0; i < kMaxPathSize; ++i) {
+ int xTrans = 10 + 40 * (i%(kMaxPathSize/2));
+ int yTrans = 0;
+ if (i > kMaxPathSize/2 - 1) {
+ yTrans = 40;
+ }
+ int base1 = 2 * rand.nextULessThan(hSize);
+ int base2 = 2 * rand.nextULessThan(hSize);
+ int base3 = 2 * rand.nextULessThan(hSize);
+ path->moveTo(SkIntToScalar(points[base1] + xTrans),
+ SkIntToScalar(points[base1+1] + yTrans));
+ path->lineTo(SkIntToScalar(points[base2] + xTrans),
+ SkIntToScalar(points[base2+1] + yTrans));
+ path->lineTo(SkIntToScalar(points[base3] + xTrans),
+ SkIntToScalar(points[base3+1] + yTrans));
+ }
+ }
+private:
+ typedef HairlinePathBench INHERITED;
+};
+
+class QuadPathBench : public HairlinePathBench {
+public:
+ QuadPathBench(Flags flags) : INHERITED(flags) {}
+
+ virtual void appendName(SkString* name) SK_OVERRIDE {
+ name->append("quad");
+ }
+ virtual void makePath(SkPath* path) SK_OVERRIDE {
+ SkRandom rand;
+ int size = SK_ARRAY_COUNT(points);
+ int hSize = size / 2;
+ for (int i = 0; i < kMaxPathSize; ++i) {
+ int xTrans = 10 + 40 * (i%(kMaxPathSize/2));
+ int yTrans = 0;
+ if (i > kMaxPathSize/2 - 1) {
+ yTrans = 40;
+ }
+ int base1 = 2 * rand.nextULessThan(hSize);
+ int base2 = 2 * rand.nextULessThan(hSize);
+ int base3 = 2 * rand.nextULessThan(hSize);
+ path->moveTo(SkIntToScalar(points[base1] + xTrans),
+ SkIntToScalar(points[base1+1] + yTrans));
+ path->quadTo(SkIntToScalar(points[base2] + xTrans),
+ SkIntToScalar(points[base2+1] + yTrans),
+ SkIntToScalar(points[base3] + xTrans),
+ SkIntToScalar(points[base3+1] + yTrans));
+ }
+ }
+private:
+ typedef HairlinePathBench INHERITED;
+};
+
+class ConicPathBench : public HairlinePathBench {
+public:
+ ConicPathBench(Flags flags) : INHERITED(flags) {}
+
+ virtual void appendName(SkString* name) SK_OVERRIDE {
+ name->append("conic");
+ }
+ virtual void makePath(SkPath* path) SK_OVERRIDE {
+ SkRandom rand;
+ SkRandom randWeight;
+ int size = SK_ARRAY_COUNT(points);
+ int hSize = size / 2;
+ for (int i = 0; i < kMaxPathSize; ++i) {
+ int xTrans = 10 + 40 * (i%(kMaxPathSize/2));
+ int yTrans = 0;
+ if (i > kMaxPathSize/2 - 1) {
+ yTrans = 40;
+ }
+ int base1 = 2 * rand.nextULessThan(hSize);
+ int base2 = 2 * rand.nextULessThan(hSize);
+ int base3 = 2 * rand.nextULessThan(hSize);
+ float weight = randWeight.nextRangeF(0.0f, 2.0f);
+ path->moveTo(SkIntToScalar(points[base1] + xTrans),
+ SkIntToScalar(points[base1+1] + yTrans));
+ path->conicTo(SkIntToScalar(points[base2] + xTrans),
+ SkIntToScalar(points[base2+1] + yTrans),
+ SkIntToScalar(points[base3] + xTrans),
+ SkIntToScalar(points[base3+1] + yTrans),
+ weight);
+ }
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+#if SK_SUPPORT_GPU
+ GrContext* context = canvas->getGrContext();
+ // This is a workaround for skbug.com/2078. See also skbug.com/2033.
+ if (NULL != context) {
+ GrTestTarget tt;
+ context->getTestTarget(&tt);
+ if (tt.target()->caps()->pathRenderingSupport()) {
+ return;
+ }
+ }
+#endif
+ INHERITED::onDraw(loops, canvas);
+ }
+
+private:
+ typedef HairlinePathBench INHERITED;
+};
+
+class CubicPathBench : public HairlinePathBench {
+public:
+ CubicPathBench(Flags flags) : INHERITED(flags) {}
+
+ virtual void appendName(SkString* name) SK_OVERRIDE {
+ name->append("cubic");
+ }
+ virtual void makePath(SkPath* path) SK_OVERRIDE {
+ SkRandom rand;
+ int size = SK_ARRAY_COUNT(points);
+ int hSize = size / 2;
+ for (int i = 0; i < kMaxPathSize; ++i) {
+ int xTrans = 10 + 40 * (i%(kMaxPathSize/2));
+ int yTrans = 0;
+ if (i > kMaxPathSize/2 - 1) {
+ yTrans = 40;
+ }
+ int base1 = 2 * rand.nextULessThan(hSize);
+ int base2 = 2 * rand.nextULessThan(hSize);
+ int base3 = 2 * rand.nextULessThan(hSize);
+ int base4 = 2 * rand.nextULessThan(hSize);
+ path->moveTo(SkIntToScalar(points[base1] + xTrans),
+ SkIntToScalar(points[base1+1] + yTrans));
+ path->cubicTo(SkIntToScalar(points[base2] + xTrans),
+ SkIntToScalar(points[base2+1] + yTrans),
+ SkIntToScalar(points[base3] + xTrans),
+ SkIntToScalar(points[base3+1] + yTrans),
+ SkIntToScalar(points[base4] + xTrans),
+ SkIntToScalar(points[base4+1] + yTrans));
+ }
+ }
+private:
+ typedef HairlinePathBench INHERITED;
+};
+
+// FLAG00 - no AA, small
+// FLAG01 - no AA, small
+// FLAG10 - AA, big
+// FLAG11 - AA, big
+
+DEF_BENCH( return new LinePathBench(FLAGS00); )
+DEF_BENCH( return new LinePathBench(FLAGS01); )
+DEF_BENCH( return new LinePathBench(FLAGS10); )
+DEF_BENCH( return new LinePathBench(FLAGS11); )
+
+DEF_BENCH( return new QuadPathBench(FLAGS00); )
+DEF_BENCH( return new QuadPathBench(FLAGS01); )
+DEF_BENCH( return new QuadPathBench(FLAGS10); )
+DEF_BENCH( return new QuadPathBench(FLAGS11); )
+
+// Don't have default path renderer for conics yet on GPU, so must use AA
+// DEF_BENCH( return new ConicPathBench(FLAGS00); )
+// DEF_BENCH( return new ConicPathBench(FLAGS01); )
+DEF_BENCH( return new ConicPathBench(FLAGS10); )
+DEF_BENCH( return new ConicPathBench(FLAGS11); )
+
+DEF_BENCH( return new CubicPathBench(FLAGS00); )
+DEF_BENCH( return new CubicPathBench(FLAGS01); )
+DEF_BENCH( return new CubicPathBench(FLAGS10); )
+DEF_BENCH( return new CubicPathBench(FLAGS11); )
diff --git a/chromium/third_party/skia/bench/ImageCacheBench.cpp b/chromium/third_party/skia/bench/ImageCacheBench.cpp
new file mode 100644
index 00000000000..5f1715fc318
--- /dev/null
+++ b/chromium/third_party/skia/bench/ImageCacheBench.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkScaledImageCache.h"
+
+class ImageCacheBench : public Benchmark {
+ SkScaledImageCache fCache;
+ SkBitmap fBM;
+
+ enum {
+ DIM = 1,
+ CACHE_COUNT = 500
+ };
+public:
+ ImageCacheBench() : fCache(CACHE_COUNT * 100) {
+ fBM.allocN32Pixels(DIM, DIM);
+ }
+
+ void populateCache() {
+ SkScalar scale = 1;
+ for (int i = 0; i < CACHE_COUNT; ++i) {
+ SkBitmap tmp;
+ tmp.allocN32Pixels(1, 1);
+ fCache.unlock(fCache.addAndLock(fBM, scale, scale, tmp));
+ scale += 1;
+ }
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return "imagecache";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
+ if (fCache.getBytesUsed() == 0) {
+ this->populateCache();
+ }
+
+ SkBitmap tmp;
+ // search for a miss (-1 scale)
+ for (int i = 0; i < loops; ++i) {
+ (void)fCache.findAndLock(fBM, -1, -1, &tmp);
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH( return new ImageCacheBench(); )
diff --git a/chromium/third_party/skia/bench/ImageDecodeBench.cpp b/chromium/third_party/skia/bench/ImageDecodeBench.cpp
new file mode 100644
index 00000000000..47993cfa7db
--- /dev/null
+++ b/chromium/third_party/skia/bench/ImageDecodeBench.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkBitmap.h"
+#include "SkData.h"
+#include "SkForceLinking.h"
+#include "SkImageDecoder.h"
+#include "SkOSFile.h"
+#include "SkStream.h"
+#include "SkString.h"
+
+__SK_FORCE_IMAGE_DECODER_LINKING;
+
+class SkCanvas;
+
+class ImageDecodeBench : public Benchmark {
+public:
+ ImageDecodeBench(void* p, const char* filename)
+ : fName("image_decode_")
+ , fFilename(filename)
+ , fStream()
+ , fValid(false) {
+ fName.append(SkOSPath::SkBasename(filename));
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+
+ virtual void onPreDraw() SK_OVERRIDE {
+ SkFILEStream fileStream(fFilename.c_str());
+ fValid = fileStream.isValid() && fileStream.getLength() > 0;
+ if (fValid) {
+ const size_t size = fileStream.getLength();
+ void* data = sk_malloc_throw(size);
+ if (fileStream.read(data, size) < size) {
+ fValid = false;
+ } else {
+ SkAutoTUnref<SkData> skdata(SkData::NewFromMalloc(data, size));
+ fStream.setData(skdata.get());
+ }
+ }
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
+#ifdef SK_DEBUG
+ if (!fValid) {
+ SkDebugf("stream was invalid: %s\n", fName.c_str());
+ return;
+ }
+#endif
+ // Decode a bunch of times
+ SkBitmap bm;
+ for (int i = 0; i < loops; ++i) {
+ SkDEBUGCODE(bool success =) SkImageDecoder::DecodeStream(&fStream, &bm);
+#ifdef SK_DEBUG
+ if (!success) {
+ SkDebugf("failed to decode %s\n", fName.c_str());
+ return;
+ }
+#endif
+ SkDEBUGCODE(success =) fStream.rewind();
+#ifdef SK_DEBUG
+ if (!success) {
+ SkDebugf("failed to rewind %s\n", fName.c_str());
+ return;
+ }
+#endif
+ }
+ }
+
+private:
+ SkString fName;
+ const SkString fFilename;
+ SkMemoryStream fStream;
+ bool fValid;
+
+ typedef Benchmark INHERITED;
+};
+
+// These are files which call decodePalette
+//DEF_BENCH( return SkNEW_ARGS(ImageDecodeBench, ("/usr/local/google/home/scroggo/Downloads/images/hal_163x90.png")); )
+//DEF_BENCH( return SkNEW_ARGS(ImageDecodeBench, ("/usr/local/google/home/scroggo/Downloads/images/box_19_top-left.png")); )
diff --git a/chromium/third_party/skia/bench/ImageFilterDAGBench.cpp b/chromium/third_party/skia/bench/ImageFilterDAGBench.cpp
new file mode 100644
index 00000000000..29d1da1a612
--- /dev/null
+++ b/chromium/third_party/skia/bench/ImageFilterDAGBench.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkBlurImageFilter.h"
+#include "SkCanvas.h"
+#include "SkMergeImageFilter.h"
+
+enum { kNumInputs = 5 };
+
+// Exercise a blur filter connected to 5 inputs of the same merge filter.
+// This bench shows an improvement in performance once cacheing of re-used
+// nodes is implemented, since the DAG is no longer flattened to a tree.
+
+class ImageFilterDAGBench : public Benchmark {
+public:
+ ImageFilterDAGBench() {
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return "image_filter_dag";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create(20.0f, 20.0f));
+ SkImageFilter* inputs[kNumInputs];
+ for (int i = 0; i < kNumInputs; ++i) {
+ inputs[i] = blur.get();
+ }
+ SkAutoTUnref<SkImageFilter> merge(SkMergeImageFilter::Create(inputs, kNumInputs));
+ SkPaint paint;
+ paint.setImageFilter(merge);
+ SkRect rect = SkRect::Make(SkIRect::MakeWH(400, 400));
+ canvas->drawRect(rect, paint);
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+DEF_BENCH(return new ImageFilterDAGBench;)
diff --git a/chromium/third_party/skia/bench/InterpBench.cpp b/chromium/third_party/skia/bench/InterpBench.cpp
new file mode 100644
index 00000000000..b19af8f35fa
--- /dev/null
+++ b/chromium/third_party/skia/bench/InterpBench.cpp
@@ -0,0 +1,163 @@
+#include "Benchmark.h"
+#include "SkColorPriv.h"
+#include "SkMatrix.h"
+#include "SkPaint.h"
+#include "SkRandom.h"
+#include "SkString.h"
+
+#define TILE(x, width) (((x) & 0xFFFF) * width >> 16)
+
+class InterpBench : public Benchmark {
+ enum {
+ kBuffer = 128,
+ kLoop = 20000
+ };
+ SkString fName;
+ int16_t fDst[kBuffer];
+ float fFx, fDx;
+public:
+ InterpBench(const char name[]) {
+ fName.printf("interp_%s", name);
+ fFx = 3.3f;
+ fDx = 0.1257f;
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+ virtual void performTest(int16_t dst[], float x, float dx, int count) = 0;
+
+protected:
+ virtual int mulLoopCount() const { return 1; }
+
+ virtual const char* onGetName() {
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) {
+ int n = loops * this->mulLoopCount();
+ for (int i = 0; i < n; i++) {
+ this->performTest(fDst, fFx, fDx, kBuffer);
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+class Fixed16D16Interp : public InterpBench {
+public:
+ Fixed16D16Interp() : INHERITED("16.16") {}
+
+protected:
+ virtual void performTest(int16_t dst[], float fx, float dx, int count) SK_OVERRIDE {
+ SkFixed curr = SkFloatToFixed(fx);
+ SkFixed step = SkFloatToFixed(dx);
+ for (int i = 0; i < count; i += 4) {
+ dst[i + 0] = TILE(curr, count); curr += step;
+ dst[i + 1] = TILE(curr, count); curr += step;
+ dst[i + 2] = TILE(curr, count); curr += step;
+ dst[i + 3] = TILE(curr, count); curr += step;
+ }
+ }
+private:
+ typedef InterpBench INHERITED;
+};
+
+class Fixed32D32Interp : public InterpBench {
+public:
+ Fixed32D32Interp() : INHERITED("32.32") {}
+
+protected:
+ virtual void performTest(int16_t dst[], float fx, float dx, int count) SK_OVERRIDE {
+ int64_t curr = (int64_t)(fx * 65536 * 655536);
+ int64_t step = (int64_t)(dx * 65536 * 655536);
+ SkFixed tmp;
+ for (int i = 0; i < count; i += 4) {
+ tmp = (SkFixed)(curr >> 16);
+ dst[i + 0] = TILE(tmp, count);
+ curr += step;
+
+ tmp = (SkFixed)(curr >> 16);
+ dst[i + 1] = TILE(tmp, count);
+ curr += step;
+
+ tmp = (SkFixed)(curr >> 16);
+ dst[i + 2] = TILE(tmp, count);
+ curr += step;
+
+ tmp = (SkFixed)(curr >> 16);
+ dst[i + 3] = TILE(tmp, count);
+ curr += step;
+ }
+ }
+private:
+ typedef InterpBench INHERITED;
+};
+
+class Fixed16D48Interp : public InterpBench {
+public:
+ Fixed16D48Interp() : INHERITED("16.48") {}
+
+protected:
+ virtual void performTest(int16_t dst[], float fx, float dx, int count) SK_OVERRIDE {
+ int64_t curr = (int64_t)(fx * 65536 * 655536 * 65536);
+ int64_t step = (int64_t)(dx * 65536 * 655536 * 65536);
+ SkFixed tmp;
+ for (int i = 0; i < count; i += 4) {
+ tmp = (SkFixed) (curr >> 32); dst[i + 0] = TILE(tmp, count); curr += step;
+ tmp = (SkFixed) (curr >> 32); dst[i + 1] = TILE(tmp, count); curr += step;
+ tmp = (SkFixed) (curr >> 32); dst[i + 2] = TILE(tmp, count); curr += step;
+ tmp = (SkFixed) (curr >> 32); dst[i + 3] = TILE(tmp, count); curr += step;
+ }
+ }
+private:
+ typedef InterpBench INHERITED;
+};
+
+class FloatInterp : public InterpBench {
+public:
+ FloatInterp() : INHERITED("float") {}
+
+protected:
+ virtual void performTest(int16_t dst[], float fx, float dx, int count) SK_OVERRIDE {
+ SkFixed tmp;
+ for (int i = 0; i < count; i += 4) {
+ tmp = SkFloatToFixed(fx); dst[i + 0] = TILE(tmp, count); fx += dx;
+ tmp = SkFloatToFixed(fx); dst[i + 1] = TILE(tmp, count); fx += dx;
+ tmp = SkFloatToFixed(fx); dst[i + 2] = TILE(tmp, count); fx += dx;
+ tmp = SkFloatToFixed(fx); dst[i + 3] = TILE(tmp, count); fx += dx;
+ }
+ }
+private:
+ typedef InterpBench INHERITED;
+};
+
+class DoubleInterp : public InterpBench {
+public:
+ DoubleInterp() : INHERITED("double") {}
+
+protected:
+ virtual void performTest(int16_t dst[], float fx, float dx, int count) SK_OVERRIDE {
+ double ffx = fx;
+ double ddx = dx;
+ SkFixed tmp;
+ for (int i = 0; i < count; i += 4) {
+ tmp = SkDoubleToFixed(ffx); dst[i + 0] = TILE(tmp, count); ffx += ddx;
+ tmp = SkDoubleToFixed(ffx); dst[i + 1] = TILE(tmp, count); ffx += ddx;
+ tmp = SkDoubleToFixed(ffx); dst[i + 2] = TILE(tmp, count); ffx += ddx;
+ tmp = SkDoubleToFixed(ffx); dst[i + 3] = TILE(tmp, count); ffx += ddx;
+ }
+ }
+private:
+ typedef InterpBench INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH( return new Fixed16D16Interp(); )
+DEF_BENCH( return new Fixed32D32Interp(); )
+DEF_BENCH( return new Fixed16D48Interp(); )
+DEF_BENCH( return new FloatInterp(); )
+DEF_BENCH( return new DoubleInterp(); )
diff --git a/chromium/third_party/skia/bench/LightingBench.cpp b/chromium/third_party/skia/bench/LightingBench.cpp
new file mode 100644
index 00000000000..4d234b951f6
--- /dev/null
+++ b/chromium/third_party/skia/bench/LightingBench.cpp
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "Benchmark.h"
+#include "SkBitmapSource.h"
+#include "SkCanvas.h"
+#include "SkDevice.h"
+#include "SkLightingImageFilter.h"
+
+#define FILTER_WIDTH_SMALL SkIntToScalar(32)
+#define FILTER_HEIGHT_SMALL SkIntToScalar(32)
+#define FILTER_WIDTH_LARGE SkIntToScalar(256)
+#define FILTER_HEIGHT_LARGE SkIntToScalar(256)
+
+class LightingBaseBench : public Benchmark {
+public:
+ LightingBaseBench(bool small) : fIsSmall(small) { }
+
+protected:
+ void draw(const int loops, SkCanvas* canvas, SkImageFilter* imageFilter) const {
+ SkRect r = fIsSmall ? SkRect::MakeWH(FILTER_WIDTH_SMALL, FILTER_HEIGHT_SMALL) :
+ SkRect::MakeWH(FILTER_WIDTH_LARGE, FILTER_HEIGHT_LARGE);
+ SkPaint paint;
+ paint.setImageFilter(imageFilter)->unref();
+ for (int i = 0; i < loops; i++) {
+ canvas->drawRect(r, paint);
+ }
+ }
+
+ static SkPoint3 getPointLocation() {
+ static SkPoint3 pointLocation(0, 0, SkIntToScalar(10));
+ return pointLocation;
+ }
+
+ static SkPoint3 getDistantDirection() {
+ static SkScalar azimuthRad = SkDegreesToRadians(SkIntToScalar(225));
+ static SkScalar elevationRad = SkDegreesToRadians(SkIntToScalar(5));
+ static SkPoint3 distantDirection(SkScalarMul(SkScalarCos(azimuthRad),
+ SkScalarCos(elevationRad)),
+ SkScalarMul(SkScalarSin(azimuthRad),
+ SkScalarCos(elevationRad)),
+ SkScalarSin(elevationRad));
+ return distantDirection;
+ }
+
+ static SkPoint3 getSpotLocation() {
+ static SkPoint3 spotLocation(SkIntToScalar(-10), SkIntToScalar(-10), SkIntToScalar(20));
+ return spotLocation;
+ }
+
+ static SkPoint3 getSpotTarget() {
+ static SkPoint3 spotTarget(SkIntToScalar(40), SkIntToScalar(40), 0);
+ return spotTarget;
+ }
+
+ static SkScalar getSpotExponent() {
+ static SkScalar spotExponent = SK_Scalar1;
+ return spotExponent;
+ }
+
+ static SkScalar getCutoffAngle() {
+ static SkScalar cutoffAngle = SkIntToScalar(15);
+ return cutoffAngle;
+ }
+
+ static SkScalar getKd() {
+ static SkScalar kd = SkIntToScalar(2);
+ return kd;
+ }
+
+ static SkScalar getKs() {
+ static SkScalar ks = SkIntToScalar(1);
+ return ks;
+ }
+
+ static SkScalar getShininess() {
+ static SkScalar shininess = SkIntToScalar(8);
+ return shininess;
+ }
+
+ static SkScalar getSurfaceScale() {
+ static SkScalar surfaceScale = SkIntToScalar(1);
+ return surfaceScale;
+ }
+
+ static SkColor getWhite() {
+ static SkColor white(0xFFFFFFFF);
+ return white;
+ }
+
+ bool fIsSmall;
+ typedef Benchmark INHERITED;
+};
+
+class LightingPointLitDiffuseBench : public LightingBaseBench {
+public:
+ LightingPointLitDiffuseBench(bool small) : INHERITED(small) {
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fIsSmall ? "lightingpointlitdiffuse_small" : "lightingpointlitdiffuse_large";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ draw(loops, canvas, SkLightingImageFilter::CreatePointLitDiffuse(getPointLocation(),
+ getWhite(),
+ getSurfaceScale(),
+ getKd()));
+ }
+
+private:
+ typedef LightingBaseBench INHERITED;
+};
+
+class LightingDistantLitDiffuseBench : public LightingBaseBench {
+public:
+ LightingDistantLitDiffuseBench(bool small) : INHERITED(small) {
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fIsSmall ? "lightingdistantlitdiffuse_small" : "lightingdistantlitdiffuse_large";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ draw(loops, canvas, SkLightingImageFilter::CreateDistantLitDiffuse(getDistantDirection(),
+ getWhite(),
+ getSurfaceScale(),
+ getKd()));
+ }
+
+private:
+ typedef LightingBaseBench INHERITED;
+};
+
+class LightingSpotLitDiffuseBench : public LightingBaseBench {
+public:
+ LightingSpotLitDiffuseBench(bool small) : INHERITED(small) {
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fIsSmall ? "lightingspotlitdiffuse_small" : "lightingspotlitdiffuse_large";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ draw(loops, canvas, SkLightingImageFilter::CreateSpotLitDiffuse(getSpotLocation(),
+ getSpotTarget(),
+ getSpotExponent(),
+ getCutoffAngle(),
+ getWhite(),
+ getSurfaceScale(),
+ getKd()));
+ }
+
+private:
+ typedef LightingBaseBench INHERITED;
+};
+
+class LightingPointLitSpecularBench : public LightingBaseBench {
+public:
+ LightingPointLitSpecularBench(bool small) : INHERITED(small) {
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fIsSmall ? "lightingpointlitspecular_small" : "lightingpointlitspecular_large";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ draw(loops, canvas, SkLightingImageFilter::CreatePointLitSpecular(getPointLocation(),
+ getWhite(),
+ getSurfaceScale(),
+ getKs(),
+ getShininess()));
+ }
+
+private:
+ typedef LightingBaseBench INHERITED;
+};
+
+class LightingDistantLitSpecularBench : public LightingBaseBench {
+public:
+ LightingDistantLitSpecularBench(bool small) : INHERITED(small) {
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fIsSmall ? "lightingdistantlitspecular_small" : "lightingdistantlitspecular_large";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ draw(loops, canvas, SkLightingImageFilter::CreateDistantLitSpecular(getDistantDirection(),
+ getWhite(),
+ getSurfaceScale(),
+ getKs(),
+ getShininess()));
+ }
+
+private:
+ typedef LightingBaseBench INHERITED;
+};
+
+class LightingSpotLitSpecularBench : public LightingBaseBench {
+public:
+ LightingSpotLitSpecularBench(bool small) : INHERITED(small) {
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fIsSmall ? "lightingspotlitspecular_small" : "lightingspotlitspecular_large";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ draw(loops, canvas, SkLightingImageFilter::CreateSpotLitSpecular(getSpotLocation(),
+ getSpotTarget(),
+ getSpotExponent(),
+ getCutoffAngle(),
+ getWhite(),
+ getSurfaceScale(),
+ getKs(),
+ getShininess()));
+ }
+
+private:
+ typedef LightingBaseBench INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH( return new LightingPointLitDiffuseBench(true); )
+DEF_BENCH( return new LightingPointLitDiffuseBench(false); )
+DEF_BENCH( return new LightingDistantLitDiffuseBench(true); )
+DEF_BENCH( return new LightingDistantLitDiffuseBench(false); )
+DEF_BENCH( return new LightingSpotLitDiffuseBench(true); )
+DEF_BENCH( return new LightingSpotLitDiffuseBench(false); )
+DEF_BENCH( return new LightingPointLitSpecularBench(true); )
+DEF_BENCH( return new LightingPointLitSpecularBench(false); )
+DEF_BENCH( return new LightingDistantLitSpecularBench(true); )
+DEF_BENCH( return new LightingDistantLitSpecularBench(false); )
+DEF_BENCH( return new LightingSpotLitSpecularBench(true); )
+DEF_BENCH( return new LightingSpotLitSpecularBench(false); )
diff --git a/chromium/third_party/skia/bench/LineBench.cpp b/chromium/third_party/skia/bench/LineBench.cpp
new file mode 100644
index 00000000000..bb6215b03fd
--- /dev/null
+++ b/chromium/third_party/skia/bench/LineBench.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkBitmap.h"
+#include "SkCanvas.h"
+#include "SkColorPriv.h"
+#include "SkPaint.h"
+#include "SkRandom.h"
+#include "SkShader.h"
+#include "SkString.h"
+#include "SkTArray.h"
+
+
+class LineBench : public Benchmark {
+ SkScalar fStrokeWidth;
+ bool fDoAA;
+ SkString fName;
+ enum {
+ PTS = 500,
+ };
+ SkPoint fPts[PTS];
+
+public:
+ LineBench(SkScalar width, bool doAA) {
+ fStrokeWidth = width;
+ fDoAA = doAA;
+ fName.printf("lines_%g_%s", width, doAA ? "AA" : "BW");
+
+ SkRandom rand;
+ for (int i = 0; i < PTS; ++i) {
+ fPts[i].set(rand.nextUScalar1() * 640, rand.nextUScalar1() * 480);
+ }
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkPaint paint;
+ this->setupPaint(&paint);
+
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setAntiAlias(fDoAA);
+ paint.setStrokeWidth(fStrokeWidth);
+
+ for (int i = 0; i < loops; i++) {
+ canvas->drawPoints(SkCanvas::kLines_PointMode, PTS, fPts, paint);
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+DEF_BENCH(return new LineBench(0, false);)
+DEF_BENCH(return new LineBench(SK_Scalar1, false);)
+DEF_BENCH(return new LineBench(0, true);)
+DEF_BENCH(return new LineBench(SK_Scalar1/2, true);)
+DEF_BENCH(return new LineBench(SK_Scalar1, true);)
diff --git a/chromium/third_party/skia/bench/MagnifierBench.cpp b/chromium/third_party/skia/bench/MagnifierBench.cpp
new file mode 100644
index 00000000000..875ec4f465f
--- /dev/null
+++ b/chromium/third_party/skia/bench/MagnifierBench.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "Benchmark.h"
+#include "SkBitmapDevice.h"
+#include "SkCanvas.h"
+#include "SkMagnifierImageFilter.h"
+#include "SkRandom.h"
+
+#define FILTER_WIDTH_SMALL 32
+#define FILTER_HEIGHT_SMALL 32
+#define FILTER_WIDTH_LARGE 256
+#define FILTER_HEIGHT_LARGE 256
+
+class MagnifierBench : public Benchmark {
+public:
+ MagnifierBench(bool small) :
+ fIsSmall(small), fInitialized(false) {
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fIsSmall ? "magnifier_small" : "magnifier_large";
+ }
+
+ virtual void onPreDraw() SK_OVERRIDE {
+ if (!fInitialized) {
+ make_checkerboard();
+ fInitialized = true;
+ }
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ const int w = fIsSmall ? FILTER_WIDTH_SMALL : FILTER_WIDTH_LARGE;
+ const int h = fIsSmall ? FILTER_HEIGHT_SMALL : FILTER_HEIGHT_LARGE;
+ SkPaint paint;
+ paint.setImageFilter(
+ SkMagnifierImageFilter::Create(
+ SkRect::MakeXYWH(SkIntToScalar(w / 4),
+ SkIntToScalar(h / 4),
+ SkIntToScalar(w / 2),
+ SkIntToScalar(h / 2)), 100))->unref();
+
+ for (int i = 0; i < loops; i++) {
+ canvas->drawBitmap(fCheckerboard, 0, 0, &paint);
+ }
+ }
+
+private:
+ void make_checkerboard() {
+ const int w = fIsSmall ? FILTER_WIDTH_SMALL : FILTER_WIDTH_LARGE;
+ const int h = fIsSmall ? FILTER_HEIGHT_LARGE : FILTER_HEIGHT_LARGE;
+ fCheckerboard.allocN32Pixels(w, h);
+ SkCanvas canvas(fCheckerboard);
+ canvas.clear(0x00000000);
+ SkPaint darkPaint;
+ darkPaint.setColor(0xFF804020);
+ SkPaint lightPaint;
+ lightPaint.setColor(0xFF244484);
+ for (int y = 0; y < h; y += 16) {
+ for (int x = 0; x < w; x += 16) {
+ canvas.save();
+ canvas.translate(SkIntToScalar(x), SkIntToScalar(y));
+ canvas.drawRect(SkRect::MakeXYWH(0, 0, 8, 8), darkPaint);
+ canvas.drawRect(SkRect::MakeXYWH(8, 0, 8, 8), lightPaint);
+ canvas.drawRect(SkRect::MakeXYWH(0, 8, 8, 8), lightPaint);
+ canvas.drawRect(SkRect::MakeXYWH(8, 8, 8, 8), darkPaint);
+ canvas.restore();
+ }
+ }
+ }
+
+ bool fIsSmall;
+ bool fInitialized;
+ SkBitmap fCheckerboard;
+ typedef Benchmark INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH( return new MagnifierBench(true); )
+DEF_BENCH( return new MagnifierBench(false); )
diff --git a/chromium/third_party/skia/bench/MathBench.cpp b/chromium/third_party/skia/bench/MathBench.cpp
new file mode 100644
index 00000000000..dbd661f8d38
--- /dev/null
+++ b/chromium/third_party/skia/bench/MathBench.cpp
@@ -0,0 +1,611 @@
+#include "Benchmark.h"
+#include "SkColorPriv.h"
+#include "SkMatrix.h"
+#include "SkPaint.h"
+#include "SkRandom.h"
+#include "SkString.h"
+
+static float sk_fsel(float pred, float result_ge, float result_lt) {
+ return pred >= 0 ? result_ge : result_lt;
+}
+
+static float fast_floor(float x) {
+// float big = sk_fsel(x, 0x1.0p+23, -0x1.0p+23);
+ float big = sk_fsel(x, (float)(1 << 23), -(float)(1 << 23));
+ return (x + big) - big;
+}
+
+class MathBench : public Benchmark {
+ enum {
+ kBuffer = 100,
+ };
+ SkString fName;
+ float fSrc[kBuffer], fDst[kBuffer];
+public:
+ MathBench(const char name[]) {
+ fName.printf("math_%s", name);
+
+ SkRandom rand;
+ for (int i = 0; i < kBuffer; ++i) {
+ fSrc[i] = rand.nextSScalar1();
+ }
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+ virtual void performTest(float* SK_RESTRICT dst,
+ const float* SK_RESTRICT src,
+ int count) = 0;
+
+protected:
+ virtual int mulLoopCount() const { return 1; }
+
+ virtual const char* onGetName() {
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) {
+ int n = loops * this->mulLoopCount();
+ for (int i = 0; i < n; i++) {
+ this->performTest(fDst, fSrc, kBuffer);
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+class MathBenchU32 : public MathBench {
+public:
+ MathBenchU32(const char name[]) : INHERITED(name) {}
+
+protected:
+ virtual void performITest(uint32_t* SK_RESTRICT dst,
+ const uint32_t* SK_RESTRICT src,
+ int count) = 0;
+
+ virtual void performTest(float* SK_RESTRICT dst,
+ const float* SK_RESTRICT src,
+ int count) SK_OVERRIDE {
+ uint32_t* d = SkTCast<uint32_t*>(dst);
+ const uint32_t* s = SkTCast<const uint32_t*>(src);
+ this->performITest(d, s, count);
+ }
+private:
+ typedef MathBench INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class NoOpMathBench : public MathBench {
+public:
+ NoOpMathBench() : INHERITED("noOp") {}
+protected:
+ virtual void performTest(float* SK_RESTRICT dst,
+ const float* SK_RESTRICT src,
+ int count) {
+ for (int i = 0; i < count; ++i) {
+ dst[i] = src[i] + 1;
+ }
+ }
+private:
+ typedef MathBench INHERITED;
+};
+
+class SkRSqrtMathBench : public MathBench {
+public:
+ SkRSqrtMathBench() : INHERITED("sk_float_rsqrt") {}
+protected:
+ virtual void performTest(float* SK_RESTRICT dst,
+ const float* SK_RESTRICT src,
+ int count) {
+ for (int i = 0; i < count; ++i) {
+ dst[i] = sk_float_rsqrt(src[i]);
+ }
+ }
+private:
+ typedef MathBench INHERITED;
+};
+
+
+class SlowISqrtMathBench : public MathBench {
+public:
+ SlowISqrtMathBench() : INHERITED("slowIsqrt") {}
+protected:
+ virtual void performTest(float* SK_RESTRICT dst,
+ const float* SK_RESTRICT src,
+ int count) {
+ for (int i = 0; i < count; ++i) {
+ dst[i] = 1.0f / sk_float_sqrt(src[i]);
+ }
+ }
+private:
+ typedef MathBench INHERITED;
+};
+
+static inline float SkFastInvSqrt(float x) {
+ float xhalf = 0.5f*x;
+ int i = *SkTCast<int*>(&x);
+ i = 0x5f3759df - (i>>1);
+ x = *SkTCast<float*>(&i);
+ x = x*(1.5f-xhalf*x*x);
+// x = x*(1.5f-xhalf*x*x); // this line takes err from 10^-3 to 10^-6
+ return x;
+}
+
+class FastISqrtMathBench : public MathBench {
+public:
+ FastISqrtMathBench() : INHERITED("fastIsqrt") {}
+protected:
+ virtual void performTest(float* SK_RESTRICT dst,
+ const float* SK_RESTRICT src,
+ int count) {
+ for (int i = 0; i < count; ++i) {
+ dst[i] = SkFastInvSqrt(src[i]);
+ }
+ }
+private:
+ typedef MathBench INHERITED;
+};
+
+static inline uint32_t QMul64(uint32_t value, U8CPU alpha) {
+ SkASSERT((uint8_t)alpha == alpha);
+ const uint32_t mask = 0xFF00FF;
+
+ uint64_t tmp = value;
+ tmp = (tmp & mask) | ((tmp & ~mask) << 24);
+ tmp *= alpha;
+ return (uint32_t) (((tmp >> 8) & mask) | ((tmp >> 32) & ~mask));
+}
+
+class QMul64Bench : public MathBenchU32 {
+public:
+ QMul64Bench() : INHERITED("qmul64") {}
+protected:
+ virtual void performITest(uint32_t* SK_RESTRICT dst,
+ const uint32_t* SK_RESTRICT src,
+ int count) SK_OVERRIDE {
+ for (int i = 0; i < count; ++i) {
+ dst[i] = QMul64(src[i], (uint8_t)i);
+ }
+ }
+private:
+ typedef MathBenchU32 INHERITED;
+};
+
+class QMul32Bench : public MathBenchU32 {
+public:
+ QMul32Bench() : INHERITED("qmul32") {}
+protected:
+ virtual void performITest(uint32_t* SK_RESTRICT dst,
+ const uint32_t* SK_RESTRICT src,
+ int count) SK_OVERRIDE {
+ for (int i = 0; i < count; ++i) {
+ dst[i] = SkAlphaMulQ(src[i], (uint8_t)i);
+ }
+ }
+private:
+ typedef MathBenchU32 INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+static bool isFinite_int(float x) {
+ uint32_t bits = SkFloat2Bits(x); // need unsigned for our shifts
+ int exponent = bits << 1 >> 24;
+ return exponent != 0xFF;
+}
+
+static bool isFinite_float(float x) {
+ return SkToBool(sk_float_isfinite(x));
+}
+
+static bool isFinite_mulzero(float x) {
+ float y = x * 0;
+ return y == y;
+}
+
+static bool isfinite_and_int(const float data[4]) {
+ return isFinite_int(data[0]) && isFinite_int(data[1]) && isFinite_int(data[2]) && isFinite_int(data[3]);
+}
+
+static bool isfinite_and_float(const float data[4]) {
+ return isFinite_float(data[0]) && isFinite_float(data[1]) && isFinite_float(data[2]) && isFinite_float(data[3]);
+}
+
+static bool isfinite_and_mulzero(const float data[4]) {
+ return isFinite_mulzero(data[0]) && isFinite_mulzero(data[1]) && isFinite_mulzero(data[2]) && isFinite_mulzero(data[3]);
+}
+
+#define mulzeroadd(data) (data[0]*0 + data[1]*0 + data[2]*0 + data[3]*0)
+
+static bool isfinite_plus_int(const float data[4]) {
+ return isFinite_int(mulzeroadd(data));
+}
+
+static bool isfinite_plus_float(const float data[4]) {
+ return !sk_float_isnan(mulzeroadd(data));
+}
+
+static bool isfinite_plus_mulzero(const float data[4]) {
+ float x = mulzeroadd(data);
+ return x == x;
+}
+
+typedef bool (*IsFiniteProc)(const float[]);
+
+#define MAKEREC(name) { name, #name }
+
+static const struct {
+ IsFiniteProc fProc;
+ const char* fName;
+} gRec[] = {
+ MAKEREC(isfinite_and_int),
+ MAKEREC(isfinite_and_float),
+ MAKEREC(isfinite_and_mulzero),
+ MAKEREC(isfinite_plus_int),
+ MAKEREC(isfinite_plus_float),
+ MAKEREC(isfinite_plus_mulzero),
+};
+
+#undef MAKEREC
+
+static bool isFinite(const SkRect& r) {
+ // x * 0 will be NaN iff x is infinity or NaN.
+ // a + b will be NaN iff either a or b is NaN.
+ float value = r.fLeft * 0 + r.fTop * 0 + r.fRight * 0 + r.fBottom * 0;
+
+ // value is either NaN or it is finite (zero).
+ // value==value will be true iff value is not NaN
+ return value == value;
+}
+
+class IsFiniteBench : public Benchmark {
+ enum {
+ N = 1000,
+ };
+ float fData[N];
+public:
+
+ IsFiniteBench(int index) {
+ SkRandom rand;
+
+ for (int i = 0; i < N; ++i) {
+ fData[i] = rand.nextSScalar1();
+ }
+
+ if (index < 0) {
+ fProc = NULL;
+ fName = "isfinite_rect";
+ } else {
+ fProc = gRec[index].fProc;
+ fName = gRec[index].fName;
+ }
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+protected:
+ virtual void onDraw(const int loops, SkCanvas*) {
+ IsFiniteProc proc = fProc;
+ const float* data = fData;
+ // do this so the compiler won't throw away the function call
+ int counter = 0;
+
+ if (proc) {
+ for (int j = 0; j < loops; ++j) {
+ for (int i = 0; i < N - 4; ++i) {
+ counter += proc(&data[i]);
+ }
+ }
+ } else {
+ for (int j = 0; j < loops; ++j) {
+ for (int i = 0; i < N - 4; ++i) {
+ const SkRect* r = reinterpret_cast<const SkRect*>(&data[i]);
+ if (false) { // avoid bit rot, suppress warning
+ isFinite(*r);
+ }
+ counter += r->isFinite();
+ }
+ }
+ }
+
+ SkPaint paint;
+ if (paint.getAlpha() == 0) {
+ SkDebugf("%d\n", counter);
+ }
+ }
+
+ virtual const char* onGetName() {
+ return fName;
+ }
+
+private:
+ IsFiniteProc fProc;
+ const char* fName;
+
+ typedef Benchmark INHERITED;
+};
+
+class FloorBench : public Benchmark {
+ enum {
+ ARRAY = 1000,
+ };
+ float fData[ARRAY];
+ bool fFast;
+public:
+
+ FloorBench(bool fast) : fFast(fast) {
+ SkRandom rand;
+
+ for (int i = 0; i < ARRAY; ++i) {
+ fData[i] = rand.nextSScalar1();
+ }
+
+ if (fast) {
+ fName = "floor_fast";
+ } else {
+ fName = "floor_std";
+ }
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+ virtual void process(float) {}
+
+protected:
+ virtual void onDraw(const int loops, SkCanvas*) {
+ SkRandom rand;
+ float accum = 0;
+ const float* data = fData;
+
+ if (fFast) {
+ for (int j = 0; j < loops; ++j) {
+ for (int i = 0; i < ARRAY; ++i) {
+ accum += fast_floor(data[i]);
+ }
+ this->process(accum);
+ }
+ } else {
+ for (int j = 0; j < loops; ++j) {
+ for (int i = 0; i < ARRAY; ++i) {
+ accum += sk_float_floor(data[i]);
+ }
+ this->process(accum);
+ }
+ }
+ }
+
+ virtual const char* onGetName() {
+ return fName;
+ }
+
+private:
+ const char* fName;
+
+ typedef Benchmark INHERITED;
+};
+
+class CLZBench : public Benchmark {
+ enum {
+ ARRAY = 1000,
+ };
+ uint32_t fData[ARRAY];
+ bool fUsePortable;
+
+public:
+ CLZBench(bool usePortable) : fUsePortable(usePortable) {
+
+ SkRandom rand;
+ for (int i = 0; i < ARRAY; ++i) {
+ fData[i] = rand.nextU();
+ }
+
+ if (fUsePortable) {
+ fName = "clz_portable";
+ } else {
+ fName = "clz_intrinsic";
+ }
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+ // just so the compiler doesn't remove our loops
+ virtual void process(int) {}
+
+protected:
+ virtual void onDraw(const int loops, SkCanvas*) {
+ int accum = 0;
+
+ if (fUsePortable) {
+ for (int j = 0; j < loops; ++j) {
+ for (int i = 0; i < ARRAY; ++i) {
+ accum += SkCLZ_portable(fData[i]);
+ }
+ this->process(accum);
+ }
+ } else {
+ for (int j = 0; j < loops; ++j) {
+ for (int i = 0; i < ARRAY; ++i) {
+ accum += SkCLZ(fData[i]);
+ }
+ this->process(accum);
+ }
+ }
+ }
+
+ virtual const char* onGetName() {
+ return fName;
+ }
+
+private:
+ const char* fName;
+
+ typedef Benchmark INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class NormalizeBench : public Benchmark {
+ enum {
+ ARRAY =1000,
+ };
+ SkVector fVec[ARRAY];
+
+public:
+ NormalizeBench() {
+ SkRandom rand;
+ for (int i = 0; i < ARRAY; ++i) {
+ fVec[i].set(rand.nextSScalar1(), rand.nextSScalar1());
+ }
+
+ fName = "point_normalize";
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+ // just so the compiler doesn't remove our loops
+ virtual void process(int) {}
+
+protected:
+ virtual void onDraw(const int loops, SkCanvas*) {
+ int accum = 0;
+
+ for (int j = 0; j < loops; ++j) {
+ for (int i = 0; i < ARRAY; ++i) {
+ accum += fVec[i].normalize();
+ }
+ this->process(accum);
+ }
+ }
+
+ virtual const char* onGetName() {
+ return fName;
+ }
+
+private:
+ const char* fName;
+
+ typedef Benchmark INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class FixedMathBench : public Benchmark {
+ enum {
+ N = 1000,
+ };
+ float fData[N];
+ SkFixed fResult[N];
+public:
+
+ FixedMathBench() {
+ SkRandom rand;
+ for (int i = 0; i < N; ++i) {
+ fData[i] = rand.nextSScalar1();
+ }
+
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+protected:
+ virtual void onDraw(const int loops, SkCanvas*) {
+ for (int j = 0; j < loops; ++j) {
+ for (int i = 0; i < N - 4; ++i) {
+ fResult[i] = SkFloatToFixed(fData[i]);
+ }
+ }
+
+ SkPaint paint;
+ if (paint.getAlpha() == 0) {
+ SkDebugf("%d\n", fResult[0]);
+ }
+ }
+
+ virtual const char* onGetName() {
+ return "float_to_fixed";
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+template <typename T>
+class DivModBench : public Benchmark {
+ SkString fName;
+public:
+ explicit DivModBench(const char* name) {
+ fName.printf("divmod_%s", name);
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+protected:
+ virtual const char* onGetName() {
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) {
+ volatile T a = 0, b = 0;
+ T div = 0, mod = 0;
+ for (int i = 0; i < loops; i++) {
+ if ((T)i == 0) continue; // Small T will wrap around.
+ SkTDivMod((T)(i+1), (T)i, &div, &mod);
+ a ^= div;
+ b ^= mod;
+ }
+ }
+};
+DEF_BENCH(return new DivModBench<uint8_t>("uint8_t"))
+DEF_BENCH(return new DivModBench<uint16_t>("uint16_t"))
+DEF_BENCH(return new DivModBench<uint32_t>("uint32_t"))
+DEF_BENCH(return new DivModBench<uint64_t>("uint64_t"))
+
+DEF_BENCH(return new DivModBench<int8_t>("int8_t"))
+DEF_BENCH(return new DivModBench<int16_t>("int16_t"))
+DEF_BENCH(return new DivModBench<int32_t>("int32_t"))
+DEF_BENCH(return new DivModBench<int64_t>("int64_t"))
+
+///////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH( return new NoOpMathBench(); )
+DEF_BENCH( return new SkRSqrtMathBench(); )
+DEF_BENCH( return new SlowISqrtMathBench(); )
+DEF_BENCH( return new FastISqrtMathBench(); )
+DEF_BENCH( return new QMul64Bench(); )
+DEF_BENCH( return new QMul32Bench(); )
+
+DEF_BENCH( return new IsFiniteBench(-1); )
+DEF_BENCH( return new IsFiniteBench(0); )
+DEF_BENCH( return new IsFiniteBench(1); )
+DEF_BENCH( return new IsFiniteBench(2); )
+DEF_BENCH( return new IsFiniteBench(3); )
+DEF_BENCH( return new IsFiniteBench(4); )
+DEF_BENCH( return new IsFiniteBench(5); )
+
+DEF_BENCH( return new FloorBench(false); )
+DEF_BENCH( return new FloorBench(true); )
+
+DEF_BENCH( return new CLZBench(false); )
+DEF_BENCH( return new CLZBench(true); )
+
+DEF_BENCH( return new NormalizeBench(); )
+
+DEF_BENCH( return new FixedMathBench(); )
diff --git a/chromium/third_party/skia/bench/Matrix44Bench.cpp b/chromium/third_party/skia/bench/Matrix44Bench.cpp
new file mode 100644
index 00000000000..8a7c50e6068
--- /dev/null
+++ b/chromium/third_party/skia/bench/Matrix44Bench.cpp
@@ -0,0 +1,304 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkMatrix44.h"
+#include "SkRandom.h"
+#include "SkString.h"
+
+class Matrix44Bench : public Benchmark {
+ SkString fName;
+public:
+ Matrix44Bench(const char name[]) {
+ fName.printf("matrix44_%s", name);
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+ virtual void performTest() = 0;
+
+protected:
+ virtual int mulLoopCount() const { return 1; }
+
+ virtual const char* onGetName() {
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) {
+ for (int i = 0; i < loops; i++) {
+ this->performTest();
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+class EqualsMatrix44Bench : public Matrix44Bench {
+public:
+ EqualsMatrix44Bench()
+ : INHERITED("equals")
+ , fM0(SkMatrix44::kIdentity_Constructor)
+ , fM1(SkMatrix44::kIdentity_Constructor)
+ , fM2(SkMatrix44::kIdentity_Constructor)
+ {
+ fM1.set(0, 0, 0);
+ fM2.set(3, 3, 0);
+ }
+protected:
+ virtual void performTest() {
+ for (int i = 0; i < 10; ++i) {
+ (void) (fM0 == fM1);
+ (void) (fM1 == fM2);
+ (void) (fM2 == fM0);
+ }
+ }
+private:
+ SkMatrix44 fM0, fM1, fM2;
+ typedef Matrix44Bench INHERITED;
+};
+
+class SetIdentityMatrix44Bench : public Matrix44Bench {
+public:
+ SetIdentityMatrix44Bench()
+ : INHERITED("setidentity")
+ , mat(SkMatrix44::kIdentity_Constructor)
+ {
+ double rowMajor[16] =
+ { 1, 2, 3, 4,
+ 5, 6, 7, 8,
+ 9, 10, 11, 12,
+ 13, 14, 15, 16};
+ mat.setRowMajord(rowMajor);
+ }
+protected:
+ virtual void performTest() {
+ for (int i = 0; i < 10; ++i) {
+ mat.setIdentity();
+ }
+ }
+private:
+ SkMatrix44 mat;
+ typedef Matrix44Bench INHERITED;
+};
+
+class PreScaleMatrix44Bench : public Matrix44Bench {
+public:
+ PreScaleMatrix44Bench()
+ : INHERITED("prescale")
+ , fM0(SkMatrix44::kUninitialized_Constructor)
+ {
+ fX = fY = fZ = SkDoubleToMScalar(1.5);
+ }
+protected:
+ virtual void performTest() {
+ fM0.reset();
+ for (int i = 0; i < 10; ++i) {
+ fM0.preScale(fX, fY, fZ);
+ }
+ }
+private:
+ SkMatrix44 fM0;
+ SkMScalar fX, fY, fZ;
+ typedef Matrix44Bench INHERITED;
+};
+
+class InvertMatrix44Bench : public Matrix44Bench {
+public:
+ InvertMatrix44Bench()
+ : INHERITED("invert")
+ , fM0(SkMatrix44::kUninitialized_Constructor)
+ , fM1(SkMatrix44::kUninitialized_Constructor)
+ {
+ fM0.set(0, 0, -1.1);
+ fM0.set(0, 1, 2.1);
+ fM0.set(0, 2, -3.1);
+ fM0.set(0, 3, 4.1);
+ fM0.set(1, 0, 5.1);
+ fM0.set(1, 1, -6.1);
+ fM0.set(1, 2, 7.1);
+ fM0.set(1, 3, 8.1);
+ fM0.set(2, 0, -9.1);
+ fM0.set(2, 1, 10.1);
+ fM0.set(2, 2, 11.1);
+ fM0.set(2, 3, -12.1);
+ fM0.set(3, 0, -13.1);
+ fM0.set(3, 1, 14.1);
+ fM0.set(3, 2, -15.1);
+ fM0.set(3, 3, 16.1);
+ }
+protected:
+ virtual void performTest() {
+ for (int i = 0; i < 10; ++i) {
+ fM0.invert(&fM1);
+ }
+ }
+private:
+ SkMatrix44 fM0, fM1;
+ typedef Matrix44Bench INHERITED;
+};
+
+class InvertAffineMatrix44Bench : public Matrix44Bench {
+public:
+ InvertAffineMatrix44Bench()
+ : INHERITED("invertaffine")
+ , fM0(SkMatrix44::kIdentity_Constructor)
+ , fM1(SkMatrix44::kUninitialized_Constructor)
+ {
+ fM0.set(0, 0, -1.1);
+ fM0.set(0, 1, 2.1);
+ fM0.set(0, 2, -3.1);
+ fM0.set(0, 3, 4.1);
+ fM0.set(1, 0, 5.1);
+ fM0.set(1, 1, -6.1);
+ fM0.set(1, 2, 7.1);
+ fM0.set(1, 3, 8.1);
+ fM0.set(2, 0, -9.1);
+ fM0.set(2, 1, 10.1);
+ fM0.set(2, 2, 11.1);
+ fM0.set(2, 3, -12.1);
+ // bottom row (perspective component) remains (0, 0, 0, 1).
+ }
+protected:
+ virtual void performTest() {
+ for (int i = 0; i < 10; ++i) {
+ fM0.invert(&fM1);
+ }
+ }
+private:
+ SkMatrix44 fM0, fM1;
+ typedef Matrix44Bench INHERITED;
+};
+
+class InvertScaleTranslateMatrix44Bench : public Matrix44Bench {
+public:
+ InvertScaleTranslateMatrix44Bench()
+ : INHERITED("invertscaletranslate")
+ , fM0(SkMatrix44::kIdentity_Constructor)
+ , fM1(SkMatrix44::kUninitialized_Constructor)
+ {
+ fM0.set(0, 0, -1.1);
+ fM0.set(0, 3, 4.1);
+
+ fM0.set(1, 1, -6.1);
+ fM0.set(1, 3, 8.1);
+
+ fM0.set(2, 2, 11.1);
+ fM0.set(2, 3, -12.1);
+ }
+protected:
+ virtual void performTest() {
+ for (int i = 0; i < 10; ++i) {
+ fM0.invert(&fM1);
+ }
+ }
+private:
+ SkMatrix44 fM0, fM1;
+ typedef Matrix44Bench INHERITED;
+};
+
+class InvertTranslateMatrix44Bench : public Matrix44Bench {
+public:
+ InvertTranslateMatrix44Bench()
+ : INHERITED("inverttranslate")
+ , fM0(SkMatrix44::kIdentity_Constructor)
+ , fM1(SkMatrix44::kUninitialized_Constructor)
+ {
+ fM0.set(0, 3, 4.1);
+ fM0.set(1, 3, 8.1);
+ fM0.set(2, 3, -12.1);
+ }
+protected:
+ virtual void performTest() {
+ for (int i = 0; i < 10; ++i) {
+ fM0.invert(&fM1);
+ }
+ }
+private:
+ SkMatrix44 fM0, fM1;
+ typedef Matrix44Bench INHERITED;
+};
+
+class PostScaleMatrix44Bench : public Matrix44Bench {
+public:
+ PostScaleMatrix44Bench()
+ : INHERITED("postscale")
+ , fM0(SkMatrix44::kUninitialized_Constructor)
+ {
+ fX = fY = fZ = SkDoubleToMScalar(1.5);
+ }
+protected:
+ virtual void performTest() {
+ fM0.reset();
+ for (int i = 0; i < 10; ++i) {
+ fM0.postScale(fX, fY, fZ);
+ }
+ }
+private:
+ SkMatrix44 fM0;
+ SkMScalar fX, fY, fZ;
+ typedef Matrix44Bench INHERITED;
+};
+
+class SetConcatMatrix44Bench : public Matrix44Bench {
+public:
+ SetConcatMatrix44Bench()
+ : INHERITED("setconcat")
+ , fM0(SkMatrix44::kUninitialized_Constructor)
+ , fM1(SkMatrix44::kUninitialized_Constructor)
+ , fM2(SkMatrix44::kUninitialized_Constructor)
+{
+ fX = fY = fZ = SkDoubleToMScalar(1.5);
+ fM1.setScale(fX, fY, fZ);
+ fM2.setTranslate(fX, fY, fZ);
+ }
+protected:
+ virtual void performTest() {
+ fM0.reset(); // just to normalize this test with prescale/postscale
+ for (int i = 0; i < 10; ++i) {
+ fM0.setConcat(fM1, fM2);
+ }
+ }
+private:
+ SkMatrix44 fM0, fM1, fM2;
+ SkMScalar fX, fY, fZ;
+ typedef Matrix44Bench INHERITED;
+};
+
+class GetTypeMatrix44Bench : public Matrix44Bench {
+public:
+ GetTypeMatrix44Bench()
+ : INHERITED("gettype")
+ , fMatrix(SkMatrix44::kIdentity_Constructor)
+ {}
+protected:
+ // Putting random generation of the matrix inside performTest()
+ // would help us avoid anomalous runs, but takes up 25% or
+ // more of the function time.
+ virtual void performTest() {
+ for (int i = 0; i < 20; ++i) {
+ fMatrix.set(1, 2, 1); // to invalidate the type-cache
+ fMatrix.getType();
+ }
+ }
+private:
+ SkMatrix44 fMatrix;
+ typedef Matrix44Bench INHERITED;
+};
+
+DEF_BENCH( return new SetIdentityMatrix44Bench(); )
+DEF_BENCH( return new EqualsMatrix44Bench(); )
+DEF_BENCH( return new PreScaleMatrix44Bench(); )
+DEF_BENCH( return new PostScaleMatrix44Bench(); )
+DEF_BENCH( return new InvertMatrix44Bench(); )
+DEF_BENCH( return new InvertAffineMatrix44Bench(); )
+DEF_BENCH( return new InvertScaleTranslateMatrix44Bench(); )
+DEF_BENCH( return new InvertTranslateMatrix44Bench(); )
+DEF_BENCH( return new SetConcatMatrix44Bench(); )
+DEF_BENCH( return new GetTypeMatrix44Bench(); )
diff --git a/chromium/third_party/skia/bench/MatrixBench.cpp b/chromium/third_party/skia/bench/MatrixBench.cpp
new file mode 100644
index 00000000000..78482d963d4
--- /dev/null
+++ b/chromium/third_party/skia/bench/MatrixBench.cpp
@@ -0,0 +1,472 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "Benchmark.h"
+#include "SkMatrix.h"
+#include "SkMatrixUtils.h"
+#include "SkRandom.h"
+#include "SkString.h"
+
+class MatrixBench : public Benchmark {
+ SkString fName;
+public:
+ MatrixBench(const char name[]) {
+ fName.printf("matrix_%s", name);
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+ virtual void performTest() = 0;
+
+protected:
+ virtual int mulLoopCount() const { return 1; }
+
+ virtual const char* onGetName() {
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) {
+ for (int i = 0; i < loops; i++) {
+ this->performTest();
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+
+class EqualsMatrixBench : public MatrixBench {
+public:
+ EqualsMatrixBench() : INHERITED("equals") {}
+protected:
+ virtual void performTest() {
+ SkMatrix m0, m1, m2;
+
+ m0.reset();
+ m1.reset();
+ m2.reset();
+
+ // xor into a volatile prevents these comparisons from being optimized away.
+ volatile bool junk = false;
+ junk ^= (m0 == m1);
+ junk ^= (m1 == m2);
+ junk ^= (m2 == m0);
+ }
+private:
+ typedef MatrixBench INHERITED;
+};
+
+class ScaleMatrixBench : public MatrixBench {
+public:
+ ScaleMatrixBench() : INHERITED("scale") {
+ fSX = fSY = 1.5f;
+ fM0.reset();
+ fM1.setScale(fSX, fSY);
+ fM2.setTranslate(fSX, fSY);
+ }
+protected:
+ virtual void performTest() {
+ SkMatrix m;
+ m = fM0; m.preScale(fSX, fSY);
+ m = fM1; m.preScale(fSX, fSY);
+ m = fM2; m.preScale(fSX, fSY);
+ }
+private:
+ SkMatrix fM0, fM1, fM2;
+ SkScalar fSX, fSY;
+ typedef MatrixBench INHERITED;
+};
+
+// having unknown values in our arrays can throw off the timing a lot, perhaps
+// handling NaN values is a lot slower. Anyway, this guy is just meant to put
+// reasonable values in our arrays.
+template <typename T> void init9(T array[9]) {
+ SkRandom rand;
+ for (int i = 0; i < 9; i++) {
+ array[i] = rand.nextSScalar1();
+ }
+}
+
+// Test the performance of setConcat() non-perspective case:
+// using floating point precision only.
+class FloatConcatMatrixBench : public MatrixBench {
+public:
+ FloatConcatMatrixBench() : INHERITED("concat_floatfloat") {
+ init9(mya);
+ init9(myb);
+ init9(myr);
+ }
+protected:
+ virtual int mulLoopCount() const { return 4; }
+
+ static inline void muladdmul(float a, float b, float c, float d,
+ float* result) {
+ *result = a * b + c * d;
+ }
+ virtual void performTest() {
+ const float* a = mya;
+ const float* b = myb;
+ float* r = myr;
+ muladdmul(a[0], b[0], a[1], b[3], &r[0]);
+ muladdmul(a[0], b[1], a[1], b[4], &r[1]);
+ muladdmul(a[0], b[2], a[1], b[5], &r[2]);
+ r[2] += a[2];
+ muladdmul(a[3], b[0], a[4], b[3], &r[3]);
+ muladdmul(a[3], b[1], a[4], b[4], &r[4]);
+ muladdmul(a[3], b[2], a[4], b[5], &r[5]);
+ r[5] += a[5];
+ r[6] = r[7] = 0.0f;
+ r[8] = 1.0f;
+ }
+private:
+ float mya [9];
+ float myb [9];
+ float myr [9];
+ typedef MatrixBench INHERITED;
+};
+
+static inline float SkDoubleToFloat(double x) {
+ return static_cast<float>(x);
+}
+
+// Test the performance of setConcat() non-perspective case:
+// using floating point precision but casting up to float for
+// intermediate results during computations.
+class FloatDoubleConcatMatrixBench : public MatrixBench {
+public:
+ FloatDoubleConcatMatrixBench() : INHERITED("concat_floatdouble") {
+ init9(mya);
+ init9(myb);
+ init9(myr);
+ }
+protected:
+ virtual int mulLoopCount() const { return 4; }
+
+ static inline void muladdmul(float a, float b, float c, float d,
+ float* result) {
+ *result = SkDoubleToFloat((double)a * b + (double)c * d);
+ }
+ virtual void performTest() {
+ const float* a = mya;
+ const float* b = myb;
+ float* r = myr;
+ muladdmul(a[0], b[0], a[1], b[3], &r[0]);
+ muladdmul(a[0], b[1], a[1], b[4], &r[1]);
+ muladdmul(a[0], b[2], a[1], b[5], &r[2]);
+ r[2] += a[2];
+ muladdmul(a[3], b[0], a[4], b[3], &r[3]);
+ muladdmul(a[3], b[1], a[4], b[4], &r[4]);
+ muladdmul(a[3], b[2], a[4], b[5], &r[5]);
+ r[5] += a[5];
+ r[6] = r[7] = 0.0f;
+ r[8] = 1.0f;
+ }
+private:
+ float mya [9];
+ float myb [9];
+ float myr [9];
+ typedef MatrixBench INHERITED;
+};
+
+// Test the performance of setConcat() non-perspective case:
+// using double precision only.
+class DoubleConcatMatrixBench : public MatrixBench {
+public:
+ DoubleConcatMatrixBench() : INHERITED("concat_double") {
+ init9(mya);
+ init9(myb);
+ init9(myr);
+ }
+protected:
+ virtual int mulLoopCount() const { return 4; }
+
+ static inline void muladdmul(double a, double b, double c, double d,
+ double* result) {
+ *result = a * b + c * d;
+ }
+ virtual void performTest() {
+ const double* a = mya;
+ const double* b = myb;
+ double* r = myr;
+ muladdmul(a[0], b[0], a[1], b[3], &r[0]);
+ muladdmul(a[0], b[1], a[1], b[4], &r[1]);
+ muladdmul(a[0], b[2], a[1], b[5], &r[2]);
+ r[2] += a[2];
+ muladdmul(a[3], b[0], a[4], b[3], &r[3]);
+ muladdmul(a[3], b[1], a[4], b[4], &r[4]);
+ muladdmul(a[3], b[2], a[4], b[5], &r[5]);
+ r[5] += a[5];
+ r[6] = r[7] = 0.0;
+ r[8] = 1.0;
+ }
+private:
+ double mya [9];
+ double myb [9];
+ double myr [9];
+ typedef MatrixBench INHERITED;
+};
+
+class GetTypeMatrixBench : public MatrixBench {
+public:
+ GetTypeMatrixBench()
+ : INHERITED("gettype") {
+ fArray[0] = (float) fRnd.nextS();
+ fArray[1] = (float) fRnd.nextS();
+ fArray[2] = (float) fRnd.nextS();
+ fArray[3] = (float) fRnd.nextS();
+ fArray[4] = (float) fRnd.nextS();
+ fArray[5] = (float) fRnd.nextS();
+ fArray[6] = (float) fRnd.nextS();
+ fArray[7] = (float) fRnd.nextS();
+ fArray[8] = (float) fRnd.nextS();
+ }
+protected:
+ // Putting random generation of the matrix inside performTest()
+ // would help us avoid anomalous runs, but takes up 25% or
+ // more of the function time.
+ virtual void performTest() {
+ fMatrix.setAll(fArray[0], fArray[1], fArray[2],
+ fArray[3], fArray[4], fArray[5],
+ fArray[6], fArray[7], fArray[8]);
+ // xoring into a volatile prevents the compiler from optimizing these away
+ volatile int junk = 0;
+ junk ^= (fMatrix.getType());
+ fMatrix.dirtyMatrixTypeCache();
+ junk ^= (fMatrix.getType());
+ fMatrix.dirtyMatrixTypeCache();
+ junk ^= (fMatrix.getType());
+ fMatrix.dirtyMatrixTypeCache();
+ junk ^= (fMatrix.getType());
+ fMatrix.dirtyMatrixTypeCache();
+ junk ^= (fMatrix.getType());
+ fMatrix.dirtyMatrixTypeCache();
+ junk ^= (fMatrix.getType());
+ fMatrix.dirtyMatrixTypeCache();
+ junk ^= (fMatrix.getType());
+ fMatrix.dirtyMatrixTypeCache();
+ junk ^= (fMatrix.getType());
+ }
+private:
+ SkMatrix fMatrix;
+ float fArray[9];
+ SkRandom fRnd;
+ typedef MatrixBench INHERITED;
+};
+
+class ScaleTransMixedMatrixBench : public MatrixBench {
+ public:
+ ScaleTransMixedMatrixBench() : INHERITED("scaletrans_mixed") {
+ fMatrix.setAll(fRandom.nextSScalar1(), fRandom.nextSScalar1(), fRandom.nextSScalar1(),
+ fRandom.nextSScalar1(), fRandom.nextSScalar1(), fRandom.nextSScalar1(),
+ fRandom.nextSScalar1(), fRandom.nextSScalar1(), fRandom.nextSScalar1());
+ int i;
+ for (i = 0; i < kCount; i++) {
+ fSrc[i].fX = fRandom.nextSScalar1();
+ fSrc[i].fY = fRandom.nextSScalar1();
+ fDst[i].fX = fRandom.nextSScalar1();
+ fDst[i].fY = fRandom.nextSScalar1();
+ }
+ }
+ protected:
+ virtual void performTest() {
+ SkPoint* dst = fDst;
+ const SkPoint* src = fSrc;
+ int count = kCount;
+ float mx = fMatrix[SkMatrix::kMScaleX];
+ float my = fMatrix[SkMatrix::kMScaleY];
+ float tx = fMatrix[SkMatrix::kMTransX];
+ float ty = fMatrix[SkMatrix::kMTransY];
+ do {
+ dst->fY = SkScalarMulAdd(src->fY, my, ty);
+ dst->fX = SkScalarMulAdd(src->fX, mx, tx);
+ src += 1;
+ dst += 1;
+ } while (--count);
+ }
+ private:
+ enum {
+ kCount = 16
+ };
+ SkMatrix fMatrix;
+ SkPoint fSrc [kCount];
+ SkPoint fDst [kCount];
+ SkRandom fRandom;
+ typedef MatrixBench INHERITED;
+};
+
+class ScaleTransDoubleMatrixBench : public MatrixBench {
+ public:
+ ScaleTransDoubleMatrixBench() : INHERITED("scaletrans_double") {
+ init9(fMatrix);
+ int i;
+ for (i = 0; i < kCount; i++) {
+ fSrc[i].fX = fRandom.nextSScalar1();
+ fSrc[i].fY = fRandom.nextSScalar1();
+ fDst[i].fX = fRandom.nextSScalar1();
+ fDst[i].fY = fRandom.nextSScalar1();
+ }
+ }
+ protected:
+ virtual void performTest() {
+ SkPoint* dst = fDst;
+ const SkPoint* src = fSrc;
+ int count = kCount;
+ // As doubles, on Z600 Linux systems this is 2.5x as expensive as mixed mode
+ float mx = (float) fMatrix[SkMatrix::kMScaleX];
+ float my = (float) fMatrix[SkMatrix::kMScaleY];
+ float tx = (float) fMatrix[SkMatrix::kMTransX];
+ float ty = (float) fMatrix[SkMatrix::kMTransY];
+ do {
+ dst->fY = src->fY * my + ty;
+ dst->fX = src->fX * mx + tx;
+ src += 1;
+ dst += 1;
+ } while (--count);
+ }
+ private:
+ enum {
+ kCount = 16
+ };
+ double fMatrix [9];
+ SkPoint fSrc [kCount];
+ SkPoint fDst [kCount];
+ SkRandom fRandom;
+ typedef MatrixBench INHERITED;
+};
+
+class DecomposeMatrixBench : public MatrixBench {
+public:
+ DecomposeMatrixBench() : INHERITED("decompose") {}
+
+protected:
+ virtual void onPreDraw() {
+ for (int i = 0; i < 10; ++i) {
+ SkScalar rot0 = (fRandom.nextBool()) ? fRandom.nextRangeF(-180, 180) : 0.0f;
+ SkScalar sx = fRandom.nextRangeF(-3000.f, 3000.f);
+ SkScalar sy = (fRandom.nextBool()) ? fRandom.nextRangeF(-3000.f, 3000.f) : sx;
+ SkScalar rot1 = fRandom.nextRangeF(-180, 180);
+ fMatrix[i].setRotate(rot0);
+ fMatrix[i].postScale(sx, sy);
+ fMatrix[i].postRotate(rot1);
+ }
+ }
+ virtual void performTest() {
+ SkPoint rotation1, scale, rotation2;
+ for (int i = 0; i < 10; ++i) {
+ (void) SkDecomposeUpper2x2(fMatrix[i], &rotation1, &scale, &rotation2);
+ }
+ }
+private:
+ SkMatrix fMatrix[10];
+ SkRandom fRandom;
+ typedef MatrixBench INHERITED;
+};
+
+class InvertMapRectMatrixBench : public MatrixBench {
+public:
+ InvertMapRectMatrixBench(const char* name, int flags)
+ : INHERITED(name)
+ , fFlags(flags) {
+ fMatrix.reset();
+ fIteration = 0;
+ if (flags & kScale_Flag) {
+ fMatrix.postScale(1.5f, 2.5f);
+ }
+ if (flags & kTranslate_Flag) {
+ fMatrix.postTranslate(1.5f, 2.5f);
+ }
+ if (flags & kRotate_Flag) {
+ fMatrix.postRotate(45.0f);
+ }
+ if (flags & kPerspective_Flag) {
+ fMatrix.setPerspX(1.5f);
+ fMatrix.setPerspY(2.5f);
+ }
+ if (0 == (flags & kUncachedTypeMask_Flag)) {
+ fMatrix.getType();
+ }
+ }
+ enum Flag {
+ kScale_Flag = 0x01,
+ kTranslate_Flag = 0x02,
+ kRotate_Flag = 0x04,
+ kPerspective_Flag = 0x08,
+ kUncachedTypeMask_Flag = 0x10,
+ };
+protected:
+ virtual void performTest() {
+ if (fFlags & kUncachedTypeMask_Flag) {
+ // This will invalidate the typemask without
+ // changing the matrix.
+ fMatrix.setPerspX(fMatrix.getPerspX());
+ }
+ SkMatrix inv;
+ bool invertible = fMatrix.invert(&inv);
+ SkASSERT(invertible);
+ SkRect transformedRect;
+ // an arbitrary, small, non-zero rect to transform
+ SkRect srcRect = SkRect::MakeWH(SkIntToScalar(10), SkIntToScalar(10));
+ if (invertible) {
+ inv.mapRect(&transformedRect, srcRect);
+ }
+ }
+private:
+ SkMatrix fMatrix;
+ int fFlags;
+ unsigned fIteration;
+ typedef MatrixBench INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH( return new EqualsMatrixBench(); )
+DEF_BENCH( return new ScaleMatrixBench(); )
+DEF_BENCH( return new FloatConcatMatrixBench(); )
+DEF_BENCH( return new FloatDoubleConcatMatrixBench(); )
+DEF_BENCH( return new DoubleConcatMatrixBench(); )
+DEF_BENCH( return new GetTypeMatrixBench(); )
+DEF_BENCH( return new DecomposeMatrixBench(); )
+
+DEF_BENCH( return new InvertMapRectMatrixBench("invert_maprect_identity", 0); )
+
+DEF_BENCH(return new InvertMapRectMatrixBench(
+ "invert_maprect_rectstaysrect",
+ InvertMapRectMatrixBench::kScale_Flag |
+ InvertMapRectMatrixBench::kTranslate_Flag); )
+
+DEF_BENCH(return new InvertMapRectMatrixBench(
+ "invert_maprect_translate",
+ InvertMapRectMatrixBench::kTranslate_Flag); )
+
+DEF_BENCH(return new InvertMapRectMatrixBench(
+ "invert_maprect_nonpersp",
+ InvertMapRectMatrixBench::kScale_Flag |
+ InvertMapRectMatrixBench::kRotate_Flag |
+ InvertMapRectMatrixBench::kTranslate_Flag); )
+
+DEF_BENCH( return new InvertMapRectMatrixBench(
+ "invert_maprect_persp",
+ InvertMapRectMatrixBench::kPerspective_Flag); )
+
+DEF_BENCH( return new InvertMapRectMatrixBench(
+ "invert_maprect_typemask_rectstaysrect",
+ InvertMapRectMatrixBench::kUncachedTypeMask_Flag |
+ InvertMapRectMatrixBench::kScale_Flag |
+ InvertMapRectMatrixBench::kTranslate_Flag); )
+
+DEF_BENCH( return new InvertMapRectMatrixBench(
+ "invert_maprect_typemask_nonpersp",
+ InvertMapRectMatrixBench::kUncachedTypeMask_Flag |
+ InvertMapRectMatrixBench::kScale_Flag |
+ InvertMapRectMatrixBench::kRotate_Flag |
+ InvertMapRectMatrixBench::kTranslate_Flag); )
+
+DEF_BENCH( return new ScaleTransMixedMatrixBench(); )
+DEF_BENCH( return new ScaleTransDoubleMatrixBench(); )
diff --git a/chromium/third_party/skia/bench/MatrixConvolutionBench.cpp b/chromium/third_party/skia/bench/MatrixConvolutionBench.cpp
new file mode 100644
index 00000000000..6593ab02597
--- /dev/null
+++ b/chromium/third_party/skia/bench/MatrixConvolutionBench.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "Benchmark.h"
+#include "SkCanvas.h"
+#include "SkMatrixConvolutionImageFilter.h"
+#include "SkPaint.h"
+#include "SkRandom.h"
+#include "SkString.h"
+
+class MatrixConvolutionBench : public Benchmark {
+public:
+ MatrixConvolutionBench(SkMatrixConvolutionImageFilter::TileMode tileMode, bool convolveAlpha)
+ : fName("matrixconvolution") {
+ SkISize kernelSize = SkISize::Make(3, 3);
+ SkScalar kernel[9] = {
+ SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
+ SkIntToScalar( 1), SkIntToScalar(-7), SkIntToScalar( 1),
+ SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
+ };
+ SkScalar gain = 0.3f, bias = SkIntToScalar(100);
+ SkIPoint kernelOffset = SkIPoint::Make(1, 1);
+ fFilter = SkMatrixConvolutionImageFilter::Create(kernelSize, kernel, gain, bias, kernelOffset, tileMode, convolveAlpha);
+ }
+
+ ~MatrixConvolutionBench() {
+ fFilter->unref();
+ }
+
+protected:
+ virtual const char* onGetName() {
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) {
+ SkPaint paint;
+ this->setupPaint(&paint);
+ paint.setAntiAlias(true);
+ SkRandom rand;
+ for (int i = 0; i < loops; i++) {
+ SkRect r = SkRect::MakeWH(rand.nextUScalar1() * 400,
+ rand.nextUScalar1() * 400);
+ paint.setImageFilter(fFilter);
+ canvas->drawOval(r, paint);
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+ SkMatrixConvolutionImageFilter* fFilter;
+ SkString fName;
+};
+
+DEF_BENCH( return new MatrixConvolutionBench(SkMatrixConvolutionImageFilter::kClamp_TileMode, true); )
+DEF_BENCH( return new MatrixConvolutionBench(SkMatrixConvolutionImageFilter::kRepeat_TileMode, true); )
+DEF_BENCH( return new MatrixConvolutionBench(SkMatrixConvolutionImageFilter::kClampToBlack_TileMode, true); )
+DEF_BENCH( return new MatrixConvolutionBench(SkMatrixConvolutionImageFilter::kClampToBlack_TileMode, false); )
diff --git a/chromium/third_party/skia/bench/MemcpyBench.cpp b/chromium/third_party/skia/bench/MemcpyBench.cpp
new file mode 100644
index 00000000000..f5501927519
--- /dev/null
+++ b/chromium/third_party/skia/bench/MemcpyBench.cpp
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkRandom.h"
+#include "SkTemplates.h"
+#include "SkUtils.h"
+
+template <typename Memcpy32>
+class Memcpy32Bench : public Benchmark {
+public:
+ explicit Memcpy32Bench(int count, Memcpy32 memcpy32, const char* name)
+ : fCount(count)
+ , fMemcpy32(memcpy32)
+ , fName(SkStringPrintf("%s_%d", name, count)) {}
+
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+ virtual void onPreDraw() SK_OVERRIDE {
+ fDst.reset(fCount);
+ fSrc.reset(fCount);
+
+ SkRandom rand;
+ for (int i = 0; i < fCount; i++) {
+ fSrc[i] = rand.nextU();
+ }
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
+ for (int i = 0; i < loops; i++) {
+ fMemcpy32(fDst, fSrc, fCount);
+ }
+ }
+
+private:
+ SkAutoTMalloc<uint32_t> fDst, fSrc;
+
+ int fCount;
+ Memcpy32 fMemcpy32;
+ const SkString fName;
+};
+
+template <typename Memcpy32>
+static Memcpy32Bench<Memcpy32>* Bench(int count, Memcpy32 memcpy32, const char* name) {
+ return new Memcpy32Bench<Memcpy32>(count, memcpy32, name);
+}
+#define BENCH(memcpy32, count) DEF_BENCH(return Bench(count, memcpy32, #memcpy32); )
+
+
+// Let the libc developers do what they think is best.
+static void memcpy32_memcpy(uint32_t* dst, const uint32_t* src, int count) {
+ memcpy(dst, src, sizeof(uint32_t) * count);
+}
+BENCH(memcpy32_memcpy, 10)
+BENCH(memcpy32_memcpy, 100)
+BENCH(memcpy32_memcpy, 1000)
+BENCH(memcpy32_memcpy, 10000)
+BENCH(memcpy32_memcpy, 100000)
+
+// Let the compiler's autovectorizer do what it thinks is best.
+static void memcpy32_autovectorize(uint32_t* dst, const uint32_t* src, int count) {
+ while (count --> 0) {
+ *dst++ = *src++;
+ }
+}
+BENCH(memcpy32_autovectorize, 10)
+BENCH(memcpy32_autovectorize, 100)
+BENCH(memcpy32_autovectorize, 1000)
+BENCH(memcpy32_autovectorize, 10000)
+BENCH(memcpy32_autovectorize, 100000)
+
+#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
+
+// Align dst to 16 bytes, then use aligned stores. src isn't algined, so use unaligned loads.
+static void memcpy32_sse2_align(uint32_t* dst, const uint32_t* src, int count) {
+ if (count >= 16) {
+ while (uintptr_t(dst) & 0xF) {
+ *dst++ = *src++;
+ count--;
+ }
+
+ __m128i* dst128 = reinterpret_cast<__m128i*>(dst);
+ const __m128i* src128 = reinterpret_cast<const __m128i*>(src);
+ dst += 16 * (count / 16);
+ src += 16 * (count / 16);
+ while (count >= 16) {
+ __m128i a = _mm_loadu_si128(src128++);
+ __m128i b = _mm_loadu_si128(src128++);
+ __m128i c = _mm_loadu_si128(src128++);
+ __m128i d = _mm_loadu_si128(src128++);
+
+ _mm_store_si128(dst128++, a);
+ _mm_store_si128(dst128++, b);
+ _mm_store_si128(dst128++, c);
+ _mm_store_si128(dst128++, d);
+
+ count -= 16;
+ }
+ }
+
+ while (count --> 0) {
+ *dst++ = *src++;
+ }
+}
+BENCH(memcpy32_sse2_align, 10)
+BENCH(memcpy32_sse2_align, 100)
+BENCH(memcpy32_sse2_align, 1000)
+BENCH(memcpy32_sse2_align, 10000)
+BENCH(memcpy32_sse2_align, 100000)
+
+// Leave both dst and src unaliged, and so use unaligned stores for dst and unaligned loads for src.
+static void memcpy32_sse2_unalign(uint32_t* dst, const uint32_t* src, int count) {
+ __m128i* dst128 = reinterpret_cast<__m128i*>(dst);
+ const __m128i* src128 = reinterpret_cast<const __m128i*>(src);
+ dst += 16 * (count / 16);
+ src += 16 * (count / 16);
+ while (count >= 16) {
+ __m128i a = _mm_loadu_si128(src128++);
+ __m128i b = _mm_loadu_si128(src128++);
+ __m128i c = _mm_loadu_si128(src128++);
+ __m128i d = _mm_loadu_si128(src128++);
+
+ _mm_storeu_si128(dst128++, a);
+ _mm_storeu_si128(dst128++, b);
+ _mm_storeu_si128(dst128++, c);
+ _mm_storeu_si128(dst128++, d);
+
+ count -= 16;
+ }
+
+ while (count --> 0) {
+ *dst++ = *src++;
+ }
+}
+BENCH(memcpy32_sse2_unalign, 10)
+BENCH(memcpy32_sse2_unalign, 100)
+BENCH(memcpy32_sse2_unalign, 1000)
+BENCH(memcpy32_sse2_unalign, 10000)
+BENCH(memcpy32_sse2_unalign, 100000)
+
+// Test our chosen best, from SkUtils.h
+BENCH(sk_memcpy32, 10)
+BENCH(sk_memcpy32, 100)
+BENCH(sk_memcpy32, 1000)
+BENCH(sk_memcpy32, 10000)
+BENCH(sk_memcpy32, 100000)
+
+#endif // SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
+
+#undef BENCH
diff --git a/chromium/third_party/skia/bench/MemoryBench.cpp b/chromium/third_party/skia/bench/MemoryBench.cpp
new file mode 100644
index 00000000000..3fc46dccf4d
--- /dev/null
+++ b/chromium/third_party/skia/bench/MemoryBench.cpp
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkCanvas.h"
+#include "SkChunkAlloc.h"
+#include "SkPaint.h"
+#include "SkRandom.h"
+#include "SkString.h"
+
+class ChunkAllocBench : public Benchmark {
+ SkString fName;
+ size_t fMinSize;
+public:
+ ChunkAllocBench(size_t minSize) {
+ fMinSize = minSize;
+ fName.printf("chunkalloc_" SK_SIZE_T_SPECIFIER, minSize);
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
+ size_t inc = fMinSize >> 4;
+ SkASSERT(inc > 0);
+ size_t total = fMinSize * 64;
+
+ SkChunkAlloc alloc(fMinSize);
+
+ for (int i = 0; i < loops; ++i) {
+ size_t size = 0;
+ int calls = 0;
+ while (size < total) {
+ alloc.allocThrow(inc);
+ size += inc;
+ calls += 1;
+ }
+ alloc.reset();
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+DEF_BENCH( return new ChunkAllocBench(64); )
+DEF_BENCH( return new ChunkAllocBench(8*1024); )
+
+static int* calloc(size_t num) {
+ return (int*)sk_calloc_throw(num*sizeof(int));
+}
+
+static int* malloc_bzero(size_t num) {
+ const size_t bytes = num*sizeof(int);
+ int* ints = (int*)sk_malloc_throw(bytes);
+ sk_bzero(ints, bytes);
+ return ints;
+}
+
+class ZerosBench : public Benchmark {
+ size_t fNum;
+ bool fRead;
+ bool fWrite;
+ bool fUseCalloc;
+ SkString fName;
+public:
+ ZerosBench(size_t num, bool read, bool write, bool useCalloc)
+ : fNum(num)
+ , fRead(read)
+ , fWrite(write)
+ , fUseCalloc(useCalloc) {
+ fName.printf("memory_%s", useCalloc ? "calloc" : "malloc_bzero");
+ if (read && write) {
+ fName.appendf("_rw");
+ } else if (read) {
+ fName.appendf("_r");
+ } else if (write) {
+ fName.appendf("_w");
+ }
+ fName.appendf("_"SK_SIZE_T_SPECIFIER, num);
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
+ for (int i = 0; i < loops; i++) {
+ int* zeros = fUseCalloc ? calloc(fNum) : malloc_bzero(fNum);
+ if (fRead) {
+ volatile int x = 15;
+ for (size_t j = 0; j < fNum; j++) {
+ x ^= zeros[j];
+ }
+ }
+ if (fWrite) {
+ for (size_t j = 0; j < fNum; j++) {
+ zeros[j] = 15;
+ }
+ }
+ sk_free(zeros);
+ }
+ }
+};
+
+// zero count r w useCalloc?
+DEF_BENCH(return new ZerosBench(1024*1024, 0, 0, 0))
+DEF_BENCH(return new ZerosBench(1024*1024, 0, 0, 1))
+DEF_BENCH(return new ZerosBench(1024*1024, 0, 1, 0))
+DEF_BENCH(return new ZerosBench(1024*1024, 0, 1, 1))
+DEF_BENCH(return new ZerosBench(1024*1024, 1, 0, 0))
+DEF_BENCH(return new ZerosBench(1024*1024, 1, 0, 1))
+DEF_BENCH(return new ZerosBench(1024*1024, 1, 1, 0))
+DEF_BENCH(return new ZerosBench(1024*1024, 1, 1, 1))
+
+DEF_BENCH(return new ZerosBench(256*1024, 0, 0, 0))
+DEF_BENCH(return new ZerosBench(256*1024, 0, 0, 1))
+DEF_BENCH(return new ZerosBench(256*1024, 0, 1, 0))
+DEF_BENCH(return new ZerosBench(256*1024, 0, 1, 1))
+DEF_BENCH(return new ZerosBench(256*1024, 1, 0, 0))
+DEF_BENCH(return new ZerosBench(256*1024, 1, 0, 1))
+DEF_BENCH(return new ZerosBench(256*1024, 1, 1, 0))
+DEF_BENCH(return new ZerosBench(256*1024, 1, 1, 1))
+
+DEF_BENCH(return new ZerosBench(4*1024, 0, 0, 0))
+DEF_BENCH(return new ZerosBench(4*1024, 0, 0, 1))
+DEF_BENCH(return new ZerosBench(4*1024, 0, 1, 0))
+DEF_BENCH(return new ZerosBench(4*1024, 0, 1, 1))
+DEF_BENCH(return new ZerosBench(4*1024, 1, 0, 0))
+DEF_BENCH(return new ZerosBench(4*1024, 1, 0, 1))
+DEF_BENCH(return new ZerosBench(4*1024, 1, 1, 0))
+DEF_BENCH(return new ZerosBench(4*1024, 1, 1, 1))
+
+DEF_BENCH(return new ZerosBench(300, 0, 0, 0))
+DEF_BENCH(return new ZerosBench(300, 0, 0, 1))
+DEF_BENCH(return new ZerosBench(300, 0, 1, 0))
+DEF_BENCH(return new ZerosBench(300, 0, 1, 1))
+DEF_BENCH(return new ZerosBench(300, 1, 0, 0))
+DEF_BENCH(return new ZerosBench(300, 1, 0, 1))
+DEF_BENCH(return new ZerosBench(300, 1, 1, 0))
+DEF_BENCH(return new ZerosBench(300, 1, 1, 1))
+
+DEF_BENCH(return new ZerosBench(4, 0, 0, 0))
+DEF_BENCH(return new ZerosBench(4, 0, 0, 1))
+DEF_BENCH(return new ZerosBench(4, 0, 1, 0))
+DEF_BENCH(return new ZerosBench(4, 0, 1, 1))
+DEF_BENCH(return new ZerosBench(4, 1, 0, 0))
+DEF_BENCH(return new ZerosBench(4, 1, 0, 1))
+DEF_BENCH(return new ZerosBench(4, 1, 1, 0))
+DEF_BENCH(return new ZerosBench(4, 1, 1, 1))
diff --git a/chromium/third_party/skia/bench/MemsetBench.cpp b/chromium/third_party/skia/bench/MemsetBench.cpp
new file mode 100644
index 00000000000..6a1bd24c84c
--- /dev/null
+++ b/chromium/third_party/skia/bench/MemsetBench.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkCanvas.h"
+#include "SkString.h"
+#include "SkUtils.h"
+
+class MemsetBench : public Benchmark {
+ SkString fName;
+
+protected:
+ size_t fMinSize;
+ size_t fMaxSize;
+ enum {
+ kBufferSize = 10000,
+ VALUE32 = 0x12345678,
+ VALUE16 = 0x1234
+ };
+
+ enum MemsetType {
+ MEMSET16 = 16,
+ MEMSET32 = 32
+ };
+
+public:
+ MemsetBench(MemsetType type, size_t minSize, size_t maxSize) {
+ SkASSERT((minSize < maxSize) && (maxSize <= kBufferSize));
+ fMinSize = minSize;
+ fMaxSize = maxSize;
+ fName.printf("memset%d_" SK_SIZE_T_SPECIFIER "_" SK_SIZE_T_SPECIFIER,
+ type, minSize, maxSize);
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+ virtual void performTest() = 0;
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ for (int i = 0; i < loops; ++i) {
+ this->performTest();
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+class Memset32Bench : public MemsetBench {
+ uint32_t kBuffer[kBufferSize + 3];
+public:
+ Memset32Bench(size_t minSize, size_t maxSize)
+ : INHERITED(MEMSET32, minSize, maxSize) {}
+
+protected:
+ virtual void performTest() SK_OVERRIDE {
+ for(size_t j = fMinSize; j < fMaxSize; ++j){
+ sk_memset32(kBuffer, VALUE32, j);
+ sk_memset32(kBuffer + 1, VALUE32, j);
+ sk_memset32(kBuffer + 2, VALUE32, j);
+ sk_memset32(kBuffer + 3, VALUE32, j);
+ }
+ }
+private:
+ typedef MemsetBench INHERITED;
+};
+
+class Memset16Bench : public MemsetBench {
+ uint16_t kBuffer[kBufferSize + 7];
+public:
+ Memset16Bench(size_t minSize, size_t maxSize)
+ : INHERITED(MEMSET16, minSize, maxSize) {}
+
+protected:
+ virtual void performTest() SK_OVERRIDE {
+ for(size_t j = fMinSize; j < fMaxSize; ++j){
+ sk_memset16(kBuffer, VALUE16, j);
+ sk_memset16(kBuffer + 1, VALUE16, j);
+ sk_memset16(kBuffer + 2, VALUE16, j);
+ sk_memset16(kBuffer + 3, VALUE16, j);
+ sk_memset16(kBuffer + 4, VALUE16, j);
+ sk_memset16(kBuffer + 5, VALUE16, j);
+ sk_memset16(kBuffer + 6, VALUE16, j);
+ sk_memset16(kBuffer + 7, VALUE16, j);
+ }
+ }
+private:
+ typedef MemsetBench INHERITED;
+};
+
+DEF_BENCH(return new Memset32Bench(1, 600);)
+DEF_BENCH(return new Memset32Bench(600, 800);)
+DEF_BENCH(return new Memset32Bench(800, 1000);)
+DEF_BENCH(return new Memset32Bench(1000, 2000);)
+DEF_BENCH(return new Memset32Bench(2000, 3000);)
+DEF_BENCH(return new Memset32Bench(3000, 4000);)
+DEF_BENCH(return new Memset32Bench(4000, 5000);)
+
+DEF_BENCH(return new Memset16Bench(1, 600);)
+DEF_BENCH(return new Memset16Bench(600, 800);)
+DEF_BENCH(return new Memset16Bench(800, 1000);)
+DEF_BENCH(return new Memset16Bench(1000, 2000);)
+DEF_BENCH(return new Memset16Bench(2000, 3000);)
+DEF_BENCH(return new Memset16Bench(3000, 4000);)
+DEF_BENCH(return new Memset16Bench(4000, 5000);)
diff --git a/chromium/third_party/skia/bench/MergeBench.cpp b/chromium/third_party/skia/bench/MergeBench.cpp
new file mode 100644
index 00000000000..a6bb3acfb19
--- /dev/null
+++ b/chromium/third_party/skia/bench/MergeBench.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "Benchmark.h"
+#include "SkBitmapDevice.h"
+#include "SkBitmapSource.h"
+#include "SkCanvas.h"
+#include "SkMergeImageFilter.h"
+
+#define FILTER_WIDTH_SMALL SkIntToScalar(32)
+#define FILTER_HEIGHT_SMALL SkIntToScalar(32)
+#define FILTER_WIDTH_LARGE SkIntToScalar(256)
+#define FILTER_HEIGHT_LARGE SkIntToScalar(256)
+
+class MergeBench : public Benchmark {
+public:
+ MergeBench(bool small) : fIsSmall(small), fInitialized(false) { }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fIsSmall ? "merge_small" : "merge_large";
+ }
+
+ virtual void onPreDraw() SK_OVERRIDE {
+ if (!fInitialized) {
+ make_bitmap();
+ make_checkerboard();
+ fInitialized = true;
+ }
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkRect r = fIsSmall ? SkRect::MakeWH(FILTER_WIDTH_SMALL, FILTER_HEIGHT_SMALL) :
+ SkRect::MakeWH(FILTER_WIDTH_LARGE, FILTER_HEIGHT_LARGE);
+ SkPaint paint;
+ paint.setImageFilter(mergeBitmaps())->unref();
+ for (int i = 0; i < loops; i++) {
+ canvas->drawRect(r, paint);
+ }
+ }
+
+private:
+ SkImageFilter* mergeBitmaps() {
+ SkImageFilter* first = SkBitmapSource::Create(fCheckerboard);
+ SkImageFilter* second = SkBitmapSource::Create(fBitmap);
+ SkAutoUnref aur0(first);
+ SkAutoUnref aur1(second);
+ return SkMergeImageFilter::Create(first, second);
+ }
+
+ void make_bitmap() {
+ fBitmap.allocN32Pixels(80, 80);
+ SkCanvas canvas(fBitmap);
+ canvas.clear(0x00000000);
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setColor(0xFF884422);
+ paint.setTextSize(SkIntToScalar(96));
+ const char* str = "g";
+ canvas.drawText(str, strlen(str), SkIntToScalar(15), SkIntToScalar(55), paint);
+ }
+
+ void make_checkerboard() {
+ fCheckerboard.allocN32Pixels(80, 80);
+ SkCanvas canvas(fCheckerboard);
+ canvas.clear(0x00000000);
+ SkPaint darkPaint;
+ darkPaint.setColor(0xFF804020);
+ SkPaint lightPaint;
+ lightPaint.setColor(0xFF244484);
+ for (int y = 0; y < 80; y += 16) {
+ for (int x = 0; x < 80; x += 16) {
+ canvas.save();
+ canvas.translate(SkIntToScalar(x), SkIntToScalar(y));
+ canvas.drawRect(SkRect::MakeXYWH(0, 0, 8, 8), darkPaint);
+ canvas.drawRect(SkRect::MakeXYWH(8, 0, 8, 8), lightPaint);
+ canvas.drawRect(SkRect::MakeXYWH(0, 8, 8, 8), lightPaint);
+ canvas.drawRect(SkRect::MakeXYWH(8, 8, 8, 8), darkPaint);
+ canvas.restore();
+ }
+ }
+ }
+
+ bool fIsSmall;
+ bool fInitialized;
+ SkBitmap fBitmap, fCheckerboard;
+
+ typedef Benchmark INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH( return new MergeBench(true); )
+DEF_BENCH( return new MergeBench(false); )
diff --git a/chromium/third_party/skia/bench/MorphologyBench.cpp b/chromium/third_party/skia/bench/MorphologyBench.cpp
new file mode 100644
index 00000000000..97995e81955
--- /dev/null
+++ b/chromium/third_party/skia/bench/MorphologyBench.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkCanvas.h"
+#include "SkMorphologyImageFilter.h"
+#include "SkPaint.h"
+#include "SkRandom.h"
+#include "SkShader.h"
+#include "SkString.h"
+
+#define SMALL SkIntToScalar(2)
+#define REAL 1.5f
+#define BIG SkIntToScalar(10)
+
+enum MorphologyType {
+ kErode_MT,
+ kDilate_MT
+};
+
+static const char* gStyleName[] = {
+ "erode",
+ "dilate"
+};
+
+class MorphologyBench : public Benchmark {
+ SkScalar fRadius;
+ MorphologyType fStyle;
+ SkString fName;
+
+public:
+ MorphologyBench(SkScalar rad, MorphologyType style)
+ {
+ fRadius = rad;
+ fStyle = style;
+ const char* name = rad > 0 ? gStyleName[style] : "none";
+ if (SkScalarFraction(rad) != 0) {
+ fName.printf("morph_%.2f_%s", SkScalarToFloat(rad), name);
+ } else {
+ fName.printf("morph_%d_%s", SkScalarRoundToInt(rad), name);
+ }
+ }
+
+protected:
+ virtual const char* onGetName() {
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) {
+ SkPaint paint;
+ this->setupPaint(&paint);
+
+ paint.setAntiAlias(true);
+
+ SkRandom rand;
+ for (int i = 0; i < loops; i++) {
+ SkRect r = SkRect::MakeWH(rand.nextUScalar1() * 400,
+ rand.nextUScalar1() * 400);
+ r.offset(fRadius, fRadius);
+
+ if (fRadius > 0) {
+ SkMorphologyImageFilter* mf = NULL;
+ switch (fStyle) {
+ case kDilate_MT:
+ mf = SkDilateImageFilter::Create(SkScalarFloorToInt(fRadius),
+ SkScalarFloorToInt(fRadius));
+ break;
+ case kErode_MT:
+ mf = SkErodeImageFilter::Create(SkScalarFloorToInt(fRadius),
+ SkScalarFloorToInt(fRadius));
+ break;
+ }
+ paint.setImageFilter(mf)->unref();
+ }
+ canvas->drawOval(r, paint);
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+DEF_BENCH( return new MorphologyBench(SMALL, kErode_MT); )
+DEF_BENCH( return new MorphologyBench(SMALL, kDilate_MT); )
+
+DEF_BENCH( return new MorphologyBench(BIG, kErode_MT); )
+DEF_BENCH( return new MorphologyBench(BIG, kDilate_MT); )
+
+DEF_BENCH( return new MorphologyBench(REAL, kErode_MT); )
+DEF_BENCH( return new MorphologyBench(REAL, kDilate_MT); )
+
+DEF_BENCH( return new MorphologyBench(0, kErode_MT); )
diff --git a/chromium/third_party/skia/bench/MutexBench.cpp b/chromium/third_party/skia/bench/MutexBench.cpp
new file mode 100644
index 00000000000..67648b5decf
--- /dev/null
+++ b/chromium/third_party/skia/bench/MutexBench.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "Benchmark.h"
+#include "SkThread.h"
+
+class MutexBench : public Benchmark {
+public:
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+protected:
+ virtual const char* onGetName() {
+ return "mutex";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) {
+ SK_DECLARE_STATIC_MUTEX(mu);
+ for (int i = 0; i < loops; i++) {
+ mu.acquire();
+ mu.release();
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH( return new MutexBench(); )
diff --git a/chromium/third_party/skia/bench/PathBench.cpp b/chromium/third_party/skia/bench/PathBench.cpp
new file mode 100644
index 00000000000..59b3bfa2ef7
--- /dev/null
+++ b/chromium/third_party/skia/bench/PathBench.cpp
@@ -0,0 +1,1019 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "Benchmark.h"
+#include "SkBitmap.h"
+#include "SkCanvas.h"
+#include "SkColorPriv.h"
+#include "SkPaint.h"
+#include "SkRandom.h"
+#include "SkShader.h"
+#include "SkString.h"
+#include "SkTArray.h"
+
+enum Flags {
+ kStroke_Flag = 1 << 0,
+ kBig_Flag = 1 << 1
+};
+
+#define FLAGS00 Flags(0)
+#define FLAGS01 Flags(kStroke_Flag)
+#define FLAGS10 Flags(kBig_Flag)
+#define FLAGS11 Flags(kStroke_Flag | kBig_Flag)
+
+class PathBench : public Benchmark {
+ SkPaint fPaint;
+ SkString fName;
+ Flags fFlags;
+public:
+ PathBench(Flags flags) : fFlags(flags) {
+ fPaint.setStyle(flags & kStroke_Flag ? SkPaint::kStroke_Style :
+ SkPaint::kFill_Style);
+ fPaint.setStrokeWidth(SkIntToScalar(5));
+ fPaint.setStrokeJoin(SkPaint::kBevel_Join);
+ }
+
+ virtual void appendName(SkString*) = 0;
+ virtual void makePath(SkPath*) = 0;
+ virtual int complexity() { return 0; }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ fName.printf("path_%s_%s_",
+ fFlags & kStroke_Flag ? "stroke" : "fill",
+ fFlags & kBig_Flag ? "big" : "small");
+ this->appendName(&fName);
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkPaint paint(fPaint);
+ this->setupPaint(&paint);
+
+ SkPath path;
+ this->makePath(&path);
+ if (fFlags & kBig_Flag) {
+ SkMatrix m;
+ m.setScale(SkIntToScalar(10), SkIntToScalar(10));
+ path.transform(m);
+ }
+
+ int count = loops;
+ if (fFlags & kBig_Flag) {
+ count >>= 2;
+ }
+ count >>= (3 * complexity());
+
+ for (int i = 0; i < count; i++) {
+ canvas->drawPath(path, paint);
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+class TrianglePathBench : public PathBench {
+public:
+ TrianglePathBench(Flags flags) : INHERITED(flags) {}
+
+ virtual void appendName(SkString* name) SK_OVERRIDE {
+ name->append("triangle");
+ }
+ virtual void makePath(SkPath* path) SK_OVERRIDE {
+ static const int gCoord[] = {
+ 10, 10, 15, 5, 20, 20
+ };
+ path->moveTo(SkIntToScalar(gCoord[0]), SkIntToScalar(gCoord[1]));
+ path->lineTo(SkIntToScalar(gCoord[2]), SkIntToScalar(gCoord[3]));
+ path->lineTo(SkIntToScalar(gCoord[4]), SkIntToScalar(gCoord[5]));
+ path->close();
+ }
+private:
+ typedef PathBench INHERITED;
+};
+
+class RectPathBench : public PathBench {
+public:
+ RectPathBench(Flags flags) : INHERITED(flags) {}
+
+ virtual void appendName(SkString* name) SK_OVERRIDE {
+ name->append("rect");
+ }
+ virtual void makePath(SkPath* path) SK_OVERRIDE {
+ SkRect r = { 10, 10, 20, 20 };
+ path->addRect(r);
+ }
+private:
+ typedef PathBench INHERITED;
+};
+
+class OvalPathBench : public PathBench {
+public:
+ OvalPathBench(Flags flags) : INHERITED(flags) {}
+
+ virtual void appendName(SkString* name) SK_OVERRIDE {
+ name->append("oval");
+ }
+ virtual void makePath(SkPath* path) SK_OVERRIDE {
+ SkRect r = { 10, 10, 23, 20 };
+ path->addOval(r);
+ }
+private:
+ typedef PathBench INHERITED;
+};
+
+class CirclePathBench: public PathBench {
+public:
+ CirclePathBench(Flags flags) : INHERITED(flags) {}
+
+ virtual void appendName(SkString* name) SK_OVERRIDE {
+ name->append("circle");
+ }
+ virtual void makePath(SkPath* path) SK_OVERRIDE {
+ path->addCircle(SkIntToScalar(20), SkIntToScalar(20),
+ SkIntToScalar(10));
+ }
+private:
+ typedef PathBench INHERITED;
+};
+
+class SawToothPathBench : public PathBench {
+public:
+ SawToothPathBench(Flags flags) : INHERITED(flags) {}
+
+ virtual void appendName(SkString* name) SK_OVERRIDE {
+ name->append("sawtooth");
+ }
+ virtual void makePath(SkPath* path) {
+ SkScalar x = SkIntToScalar(20);
+ SkScalar y = SkIntToScalar(20);
+ const SkScalar x0 = x;
+ const SkScalar dx = SK_Scalar1 * 5;
+ const SkScalar dy = SK_Scalar1 * 10;
+
+ path->moveTo(x, y);
+ for (int i = 0; i < 32; i++) {
+ x += dx;
+ path->lineTo(x, y - dy);
+ x += dx;
+ path->lineTo(x, y + dy);
+ }
+ path->lineTo(x, y + 2 * dy);
+ path->lineTo(x0, y + 2 * dy);
+ path->close();
+ }
+ virtual int complexity() SK_OVERRIDE { return 1; }
+private:
+ typedef PathBench INHERITED;
+};
+
+class LongCurvedPathBench : public PathBench {
+public:
+ LongCurvedPathBench(Flags flags) : INHERITED(flags) {}
+
+ virtual void appendName(SkString* name) SK_OVERRIDE {
+ name->append("long_curved");
+ }
+ virtual void makePath(SkPath* path) SK_OVERRIDE {
+ SkRandom rand (12);
+ int i;
+ for (i = 0; i < 100; i++) {
+ path->quadTo(SkScalarMul(rand.nextUScalar1(), SkIntToScalar(640)),
+ SkScalarMul(rand.nextUScalar1(), SkIntToScalar(480)),
+ SkScalarMul(rand.nextUScalar1(), SkIntToScalar(640)),
+ SkScalarMul(rand.nextUScalar1(), SkIntToScalar(480)));
+ }
+ path->close();
+ }
+ virtual int complexity() SK_OVERRIDE { return 2; }
+private:
+ typedef PathBench INHERITED;
+};
+
+class LongLinePathBench : public PathBench {
+public:
+ LongLinePathBench(Flags flags) : INHERITED(flags) {}
+
+ virtual void appendName(SkString* name) SK_OVERRIDE {
+ name->append("long_line");
+ }
+ virtual void makePath(SkPath* path) SK_OVERRIDE {
+ SkRandom rand;
+ path->moveTo(rand.nextUScalar1() * 640, rand.nextUScalar1() * 480);
+ for (size_t i = 1; i < 100; i++) {
+ path->lineTo(rand.nextUScalar1() * 640, rand.nextUScalar1() * 480);
+ }
+ }
+ virtual int complexity() SK_OVERRIDE { return 2; }
+private:
+ typedef PathBench INHERITED;
+};
+
+class RandomPathBench : public Benchmark {
+public:
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+protected:
+ void createData(int minVerbs,
+ int maxVerbs,
+ bool allowMoves = true,
+ SkRect* bounds = NULL) {
+ SkRect tempBounds;
+ if (NULL == bounds) {
+ tempBounds.setXYWH(0, 0, SK_Scalar1, SK_Scalar1);
+ bounds = &tempBounds;
+ }
+ fVerbCnts.reset(kNumVerbCnts);
+ for (int i = 0; i < kNumVerbCnts; ++i) {
+ fVerbCnts[i] = fRandom.nextRangeU(minVerbs, maxVerbs + 1);
+ }
+ fVerbs.reset(kNumVerbs);
+ for (int i = 0; i < kNumVerbs; ++i) {
+ do {
+ fVerbs[i] = static_cast<SkPath::Verb>(fRandom.nextULessThan(SkPath::kDone_Verb));
+ } while (!allowMoves && SkPath::kMove_Verb == fVerbs[i]);
+ }
+ fPoints.reset(kNumPoints);
+ for (int i = 0; i < kNumPoints; ++i) {
+ fPoints[i].set(fRandom.nextRangeScalar(bounds->fLeft, bounds->fRight),
+ fRandom.nextRangeScalar(bounds->fTop, bounds->fBottom));
+ }
+ this->restartMakingPaths();
+ }
+
+ void restartMakingPaths() {
+ fCurrPath = 0;
+ fCurrVerb = 0;
+ fCurrPoint = 0;
+ }
+
+ void makePath(SkPath* path) {
+ int vCount = fVerbCnts[(fCurrPath++) & (kNumVerbCnts - 1)];
+ for (int v = 0; v < vCount; ++v) {
+ int verb = fVerbs[(fCurrVerb++) & (kNumVerbs - 1)];
+ switch (verb) {
+ case SkPath::kMove_Verb:
+ path->moveTo(fPoints[(fCurrPoint++) & (kNumPoints - 1)]);
+ break;
+ case SkPath::kLine_Verb:
+ path->lineTo(fPoints[(fCurrPoint++) & (kNumPoints - 1)]);
+ break;
+ case SkPath::kQuad_Verb:
+ path->quadTo(fPoints[(fCurrPoint + 0) & (kNumPoints - 1)],
+ fPoints[(fCurrPoint + 1) & (kNumPoints - 1)]);
+ fCurrPoint += 2;
+ break;
+ case SkPath::kConic_Verb:
+ path->conicTo(fPoints[(fCurrPoint + 0) & (kNumPoints - 1)],
+ fPoints[(fCurrPoint + 1) & (kNumPoints - 1)],
+ SK_ScalarHalf);
+ fCurrPoint += 2;
+ break;
+ case SkPath::kCubic_Verb:
+ path->cubicTo(fPoints[(fCurrPoint + 0) & (kNumPoints - 1)],
+ fPoints[(fCurrPoint + 1) & (kNumPoints - 1)],
+ fPoints[(fCurrPoint + 2) & (kNumPoints - 1)]);
+ fCurrPoint += 3;
+ break;
+ case SkPath::kClose_Verb:
+ path->close();
+ break;
+ default:
+ SkDEBUGFAIL("Unexpected path verb");
+ break;
+ }
+ }
+ }
+
+ void finishedMakingPaths() {
+ fVerbCnts.reset(0);
+ fVerbs.reset(0);
+ fPoints.reset(0);
+ }
+
+private:
+ enum {
+ // these should all be pow 2
+ kNumVerbCnts = 1 << 5,
+ kNumVerbs = 1 << 5,
+ kNumPoints = 1 << 5,
+ };
+ SkAutoTArray<int> fVerbCnts;
+ SkAutoTArray<SkPath::Verb> fVerbs;
+ SkAutoTArray<SkPoint> fPoints;
+ int fCurrPath;
+ int fCurrVerb;
+ int fCurrPoint;
+ SkRandom fRandom;
+ typedef Benchmark INHERITED;
+};
+
+class PathCreateBench : public RandomPathBench {
+public:
+ PathCreateBench() {
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return "path_create";
+ }
+
+ virtual void onPreDraw() SK_OVERRIDE {
+ this->createData(10, 100);
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
+ for (int i = 0; i < loops; ++i) {
+ if (i % 1000 == 0) {
+ fPath.reset(); // PathRef memory can grow without bound otherwise.
+ }
+ this->makePath(&fPath);
+ }
+ this->restartMakingPaths();
+ }
+
+private:
+ SkPath fPath;
+
+ typedef RandomPathBench INHERITED;
+};
+
+class PathCopyBench : public RandomPathBench {
+public:
+ PathCopyBench() {
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return "path_copy";
+ }
+ virtual void onPreDraw() SK_OVERRIDE {
+ this->createData(10, 100);
+ fPaths.reset(kPathCnt);
+ fCopies.reset(kPathCnt);
+ for (int i = 0; i < kPathCnt; ++i) {
+ this->makePath(&fPaths[i]);
+ }
+ this->finishedMakingPaths();
+ }
+ virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
+ for (int i = 0; i < loops; ++i) {
+ int idx = i & (kPathCnt - 1);
+ fCopies[idx] = fPaths[idx];
+ }
+ }
+
+private:
+ enum {
+ // must be a pow 2
+ kPathCnt = 1 << 5,
+ };
+ SkAutoTArray<SkPath> fPaths;
+ SkAutoTArray<SkPath> fCopies;
+
+ typedef RandomPathBench INHERITED;
+};
+
+class PathTransformBench : public RandomPathBench {
+public:
+ PathTransformBench(bool inPlace) : fInPlace(inPlace) {}
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fInPlace ? "path_transform_in_place" : "path_transform_copy";
+ }
+
+ virtual void onPreDraw() SK_OVERRIDE {
+ fMatrix.setScale(5 * SK_Scalar1, 6 * SK_Scalar1);
+ this->createData(10, 100);
+ fPaths.reset(kPathCnt);
+ for (int i = 0; i < kPathCnt; ++i) {
+ this->makePath(&fPaths[i]);
+ }
+ this->finishedMakingPaths();
+ if (!fInPlace) {
+ fTransformed.reset(kPathCnt);
+ }
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
+ if (fInPlace) {
+ for (int i = 0; i < loops; ++i) {
+ fPaths[i & (kPathCnt - 1)].transform(fMatrix);
+ }
+ } else {
+ for (int i = 0; i < loops; ++i) {
+ int idx = i & (kPathCnt - 1);
+ fPaths[idx].transform(fMatrix, &fTransformed[idx]);
+ }
+ }
+ }
+
+private:
+ enum {
+ // must be a pow 2
+ kPathCnt = 1 << 5,
+ };
+ SkAutoTArray<SkPath> fPaths;
+ SkAutoTArray<SkPath> fTransformed;
+
+ SkMatrix fMatrix;
+ bool fInPlace;
+ typedef RandomPathBench INHERITED;
+};
+
+class PathEqualityBench : public RandomPathBench {
+public:
+ PathEqualityBench() { }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return "path_equality_50%";
+ }
+
+ virtual void onPreDraw() SK_OVERRIDE {
+ fParity = 0;
+ this->createData(10, 100);
+ fPaths.reset(kPathCnt);
+ fCopies.reset(kPathCnt);
+ for (int i = 0; i < kPathCnt; ++i) {
+ this->makePath(&fPaths[i]);
+ fCopies[i] = fPaths[i];
+ }
+ this->finishedMakingPaths();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
+ for (int i = 0; i < loops; ++i) {
+ int idx = i & (kPathCnt - 1);
+ fParity ^= (fPaths[idx] == fCopies[idx & ~0x1]);
+ }
+ }
+
+private:
+ bool fParity; // attempt to keep compiler from optimizing out the ==
+ enum {
+ // must be a pow 2
+ kPathCnt = 1 << 5,
+ };
+ SkAutoTArray<SkPath> fPaths;
+ SkAutoTArray<SkPath> fCopies;
+ typedef RandomPathBench INHERITED;
+};
+
+class SkBench_AddPathTest : public RandomPathBench {
+public:
+ enum AddType {
+ kAdd_AddType,
+ kAddTrans_AddType,
+ kAddMatrix_AddType,
+ kReverseAdd_AddType,
+ kReversePathTo_AddType,
+ };
+
+ SkBench_AddPathTest(AddType type) : fType(type) {
+ fMatrix.setRotate(60 * SK_Scalar1);
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ switch (fType) {
+ case kAdd_AddType:
+ return "path_add_path";
+ case kAddTrans_AddType:
+ return "path_add_path_trans";
+ case kAddMatrix_AddType:
+ return "path_add_path_matrix";
+ case kReverseAdd_AddType:
+ return "path_reverse_add_path";
+ case kReversePathTo_AddType:
+ return "path_reverse_path_to";
+ default:
+ SkDEBUGFAIL("Bad add type");
+ return "";
+ }
+ }
+
+ virtual void onPreDraw() SK_OVERRIDE {
+ // reversePathTo assumes a single contour path.
+ bool allowMoves = kReversePathTo_AddType != fType;
+ this->createData(10, 100, allowMoves);
+ fPaths0.reset(kPathCnt);
+ fPaths1.reset(kPathCnt);
+ for (int i = 0; i < kPathCnt; ++i) {
+ this->makePath(&fPaths0[i]);
+ this->makePath(&fPaths1[i]);
+ }
+ this->finishedMakingPaths();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
+ switch (fType) {
+ case kAdd_AddType:
+ for (int i = 0; i < loops; ++i) {
+ int idx = i & (kPathCnt - 1);
+ SkPath result = fPaths0[idx];
+ result.addPath(fPaths1[idx]);
+ }
+ break;
+ case kAddTrans_AddType:
+ for (int i = 0; i < loops; ++i) {
+ int idx = i & (kPathCnt - 1);
+ SkPath result = fPaths0[idx];
+ result.addPath(fPaths1[idx], 2 * SK_Scalar1, 5 * SK_Scalar1);
+ }
+ break;
+ case kAddMatrix_AddType:
+ for (int i = 0; i < loops; ++i) {
+ int idx = i & (kPathCnt - 1);
+ SkPath result = fPaths0[idx];
+ result.addPath(fPaths1[idx], fMatrix);
+ }
+ break;
+ case kReverseAdd_AddType:
+ for (int i = 0; i < loops; ++i) {
+ int idx = i & (kPathCnt - 1);
+ SkPath result = fPaths0[idx];
+ result.reverseAddPath(fPaths1[idx]);
+ }
+ break;
+ case kReversePathTo_AddType:
+ for (int i = 0; i < loops; ++i) {
+ int idx = i & (kPathCnt - 1);
+ SkPath result = fPaths0[idx];
+ result.reversePathTo(fPaths1[idx]);
+ }
+ break;
+ }
+ }
+
+private:
+ AddType fType; // or reverseAddPath
+ enum {
+ // must be a pow 2
+ kPathCnt = 1 << 5,
+ };
+ SkAutoTArray<SkPath> fPaths0;
+ SkAutoTArray<SkPath> fPaths1;
+ SkMatrix fMatrix;
+ typedef RandomPathBench INHERITED;
+};
+
+
+class CirclesBench : public Benchmark {
+protected:
+ SkString fName;
+ Flags fFlags;
+
+public:
+ CirclesBench(Flags flags) : fFlags(flags) {
+ fName.printf("circles_%s", fFlags & kStroke_Flag ? "stroke" : "fill");
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkPaint paint;
+
+ paint.setColor(SK_ColorBLACK);
+ paint.setAntiAlias(true);
+ if (fFlags & kStroke_Flag) {
+ paint.setStyle(SkPaint::kStroke_Style);
+ }
+
+ SkRandom rand;
+
+ SkRect r;
+
+ for (int i = 0; i < loops; ++i) {
+ SkScalar radius = rand.nextUScalar1() * 3;
+ r.fLeft = rand.nextUScalar1() * 300;
+ r.fTop = rand.nextUScalar1() * 300;
+ r.fRight = r.fLeft + 2 * radius;
+ r.fBottom = r.fTop + 2 * radius;
+
+ if (fFlags & kStroke_Flag) {
+ paint.setStrokeWidth(rand.nextUScalar1() * 5.0f);
+ }
+
+ SkPath temp;
+
+ // mimic how Chrome does circles
+ temp.arcTo(r, 0, 0, false);
+ temp.addOval(r, SkPath::kCCW_Direction);
+ temp.arcTo(r, 360, 0, true);
+ temp.close();
+
+ canvas->drawPath(temp, paint);
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+
+// Chrome creates its own round rects with each corner possibly being different.
+// In its "zero radius" incarnation it creates degenerate round rects.
+// Note: PathTest::test_arb_round_rect_is_convex and
+// test_arb_zero_rad_round_rect_is_rect perform almost exactly
+// the same test (but with no drawing)
+class ArbRoundRectBench : public Benchmark {
+protected:
+ SkString fName;
+
+public:
+ ArbRoundRectBench(bool zeroRad) : fZeroRad(zeroRad) {
+ if (zeroRad) {
+ fName.printf("zeroradroundrect");
+ } else {
+ fName.printf("arbroundrect");
+ }
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+
+ static void add_corner_arc(SkPath* path, const SkRect& rect,
+ SkScalar xIn, SkScalar yIn,
+ int startAngle)
+ {
+
+ SkScalar rx = SkMinScalar(rect.width(), xIn);
+ SkScalar ry = SkMinScalar(rect.height(), yIn);
+
+ SkRect arcRect;
+ arcRect.set(-rx, -ry, rx, ry);
+ switch (startAngle) {
+ case 0:
+ arcRect.offset(rect.fRight - arcRect.fRight, rect.fBottom - arcRect.fBottom);
+ break;
+ case 90:
+ arcRect.offset(rect.fLeft - arcRect.fLeft, rect.fBottom - arcRect.fBottom);
+ break;
+ case 180:
+ arcRect.offset(rect.fLeft - arcRect.fLeft, rect.fTop - arcRect.fTop);
+ break;
+ case 270:
+ arcRect.offset(rect.fRight - arcRect.fRight, rect.fTop - arcRect.fTop);
+ break;
+ default:
+ break;
+ }
+
+ path->arcTo(arcRect, SkIntToScalar(startAngle), SkIntToScalar(90), false);
+ }
+
+ static void make_arb_round_rect(SkPath* path, const SkRect& r,
+ SkScalar xCorner, SkScalar yCorner) {
+ // we are lazy here and use the same x & y for each corner
+ add_corner_arc(path, r, xCorner, yCorner, 270);
+ add_corner_arc(path, r, xCorner, yCorner, 0);
+ add_corner_arc(path, r, xCorner, yCorner, 90);
+ add_corner_arc(path, r, xCorner, yCorner, 180);
+ path->close();
+
+ SkASSERT(path->isConvex());
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkRandom rand;
+ SkRect r;
+
+ for (int i = 0; i < loops; ++i) {
+ SkPaint paint;
+ paint.setColor(0xff000000 | rand.nextU());
+ paint.setAntiAlias(true);
+
+ SkScalar size = rand.nextUScalar1() * 30;
+ if (size < SK_Scalar1) {
+ continue;
+ }
+ r.fLeft = rand.nextUScalar1() * 300;
+ r.fTop = rand.nextUScalar1() * 300;
+ r.fRight = r.fLeft + 2 * size;
+ r.fBottom = r.fTop + 2 * size;
+
+ SkPath temp;
+
+ if (fZeroRad) {
+ make_arb_round_rect(&temp, r, 0, 0);
+
+ SkASSERT(temp.isRect(NULL));
+ } else {
+ make_arb_round_rect(&temp, r, r.width() / 10, r.height() / 15);
+ }
+
+ canvas->drawPath(temp, paint);
+ }
+ }
+
+private:
+ bool fZeroRad; // should 0 radius rounds rects be tested?
+
+ typedef Benchmark INHERITED;
+};
+
+class ConservativelyContainsBench : public Benchmark {
+public:
+ enum Type {
+ kRect_Type,
+ kRoundRect_Type,
+ kOval_Type,
+ };
+
+ ConservativelyContainsBench(Type type) {
+ fParity = false;
+ fName = "conservatively_contains_";
+ switch (type) {
+ case kRect_Type:
+ fName.append("rect");
+ fPath.addRect(kBaseRect);
+ break;
+ case kRoundRect_Type:
+ fName.append("round_rect");
+ fPath.addRoundRect(kBaseRect, kRRRadii[0], kRRRadii[1]);
+ break;
+ case kOval_Type:
+ fName.append("oval");
+ fPath.addOval(kBaseRect);
+ break;
+ }
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+private:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
+ for (int i = 0; i < loops; ++i) {
+ const SkRect& rect = fQueryRects[i % kQueryRectCnt];
+ fParity = fParity != fPath.conservativelyContainsRect(rect);
+ }
+ }
+
+ virtual void onPreDraw() SK_OVERRIDE {
+ fQueryRects.setCount(kQueryRectCnt);
+
+ SkRandom rand;
+ for (int i = 0; i < kQueryRectCnt; ++i) {
+ SkSize size;
+ SkPoint xy;
+ size.fWidth = rand.nextRangeScalar(kQueryMin.fWidth, kQueryMax.fWidth);
+ size.fHeight = rand.nextRangeScalar(kQueryMin.fHeight, kQueryMax.fHeight);
+ xy.fX = rand.nextRangeScalar(kBounds.fLeft, kBounds.fRight - size.fWidth);
+ xy.fY = rand.nextRangeScalar(kBounds.fTop, kBounds.fBottom - size.fHeight);
+
+ fQueryRects[i] = SkRect::MakeXYWH(xy.fX, xy.fY, size.fWidth, size.fHeight);
+ }
+ }
+
+ enum {
+ kQueryRectCnt = 400,
+ };
+ static const SkRect kBounds; // bounds for all random query rects
+ static const SkSize kQueryMin; // minimum query rect size, should be <= kQueryMax
+ static const SkSize kQueryMax; // max query rect size, should < kBounds
+ static const SkRect kBaseRect; // rect that is used to construct the path
+ static const SkScalar kRRRadii[2]; // x and y radii for round rect
+
+ SkString fName;
+ SkPath fPath;
+ bool fParity;
+ SkTDArray<SkRect> fQueryRects;
+
+ typedef Benchmark INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+#include "SkGeometry.h"
+
+class ConicBench_Chop5 : public Benchmark {
+ SkConic fRQ;
+public:
+ ConicBench_Chop5() {
+ fRQ.fPts[0].set(0, 0);
+ fRQ.fPts[1].set(100, 0);
+ fRQ.fPts[2].set(100, 100);
+ fRQ.fW = SkScalarCos(SK_ScalarPI/4);
+ }
+
+private:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return "ratquad-chop-0.5";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
+ SkConic dst[2];
+ for (int i = 0; i < loops; ++i) {
+ fRQ.chopAt(0.5f, dst);
+ }
+ }
+
+ typedef Benchmark INHERITED;
+};
+
+class ConicBench_ChopHalf : public Benchmark {
+ SkConic fRQ;
+public:
+ ConicBench_ChopHalf() {
+ fRQ.fPts[0].set(0, 0);
+ fRQ.fPts[1].set(100, 0);
+ fRQ.fPts[2].set(100, 100);
+ fRQ.fW = SkScalarCos(SK_ScalarPI/4);
+ }
+
+private:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return "ratquad-chop-half";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
+ SkConic dst[2];
+ for (int i = 0; i < loops; ++i) {
+ fRQ.chop(dst);
+ }
+ }
+
+ typedef Benchmark INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+static void rand_conic(SkConic* conic, SkRandom& rand) {
+ for (int i = 0; i < 3; ++i) {
+ conic->fPts[i].set(rand.nextUScalar1() * 100, rand.nextUScalar1() * 100);
+ }
+ if (rand.nextUScalar1() > 0.5f) {
+ conic->fW = rand.nextUScalar1();
+ } else {
+ conic->fW = 1 + rand.nextUScalar1() * 4;
+ }
+}
+
+class ConicBench : public Benchmark {
+public:
+ ConicBench() {
+ SkRandom rand;
+ for (int i = 0; i < CONICS; ++i) {
+ rand_conic(&fConics[i], rand);
+ }
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+protected:
+ enum {
+ CONICS = 100
+ };
+ SkConic fConics[CONICS];
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+class ConicBench_ComputeError : public ConicBench {
+public:
+ ConicBench_ComputeError() {}
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return "conic-compute-error";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
+ SkVector err;
+ for (int i = 0; i < loops; ++i) {
+ for (int j = 0; j < CONICS; ++j) {
+ fConics[j].computeAsQuadError(&err);
+ }
+ }
+ }
+
+private:
+ typedef ConicBench INHERITED;
+};
+
+class ConicBench_asQuadTol : public ConicBench {
+public:
+ ConicBench_asQuadTol() {}
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return "conic-asQuadTol";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
+ for (int i = 0; i < loops; ++i) {
+ for (int j = 0; j < CONICS; ++j) {
+ fConics[j].asQuadTol(SK_ScalarHalf);
+ }
+ }
+ }
+
+private:
+ typedef ConicBench INHERITED;
+};
+
+class ConicBench_quadPow2 : public ConicBench {
+public:
+ ConicBench_quadPow2() {}
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return "conic-quadPow2";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
+ for (int i = 0; i < loops; ++i) {
+ for (int j = 0; j < CONICS; ++j) {
+ fConics[j].computeQuadPOW2(SK_ScalarHalf);
+ }
+ }
+ }
+
+private:
+ typedef ConicBench INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+const SkRect ConservativelyContainsBench::kBounds = SkRect::MakeWH(SkIntToScalar(100), SkIntToScalar(100));
+const SkSize ConservativelyContainsBench::kQueryMin = SkSize::Make(SkIntToScalar(1), SkIntToScalar(1));
+const SkSize ConservativelyContainsBench::kQueryMax = SkSize::Make(SkIntToScalar(40), SkIntToScalar(40));
+const SkRect ConservativelyContainsBench::kBaseRect = SkRect::MakeXYWH(SkIntToScalar(25), SkIntToScalar(25), SkIntToScalar(50), SkIntToScalar(50));
+const SkScalar ConservativelyContainsBench::kRRRadii[2] = {SkIntToScalar(5), SkIntToScalar(10)};
+
+DEF_BENCH( return new TrianglePathBench(FLAGS00); )
+DEF_BENCH( return new TrianglePathBench(FLAGS01); )
+DEF_BENCH( return new TrianglePathBench(FLAGS10); )
+DEF_BENCH( return new TrianglePathBench(FLAGS11); )
+
+DEF_BENCH( return new RectPathBench(FLAGS00); )
+DEF_BENCH( return new RectPathBench(FLAGS01); )
+DEF_BENCH( return new RectPathBench(FLAGS10); )
+DEF_BENCH( return new RectPathBench(FLAGS11); )
+
+DEF_BENCH( return new OvalPathBench(FLAGS00); )
+DEF_BENCH( return new OvalPathBench(FLAGS01); )
+DEF_BENCH( return new OvalPathBench(FLAGS10); )
+DEF_BENCH( return new OvalPathBench(FLAGS11); )
+
+DEF_BENCH( return new CirclePathBench(FLAGS00); )
+DEF_BENCH( return new CirclePathBench(FLAGS01); )
+DEF_BENCH( return new CirclePathBench(FLAGS10); )
+DEF_BENCH( return new CirclePathBench(FLAGS11); )
+
+DEF_BENCH( return new SawToothPathBench(FLAGS00); )
+DEF_BENCH( return new SawToothPathBench(FLAGS01); )
+
+DEF_BENCH( return new LongCurvedPathBench(FLAGS00); )
+DEF_BENCH( return new LongCurvedPathBench(FLAGS01); )
+DEF_BENCH( return new LongLinePathBench(FLAGS00); )
+DEF_BENCH( return new LongLinePathBench(FLAGS01); )
+
+DEF_BENCH( return new PathCreateBench(); )
+DEF_BENCH( return new PathCopyBench(); )
+DEF_BENCH( return new PathTransformBench(true); )
+DEF_BENCH( return new PathTransformBench(false); )
+DEF_BENCH( return new PathEqualityBench(); )
+
+DEF_BENCH( return new SkBench_AddPathTest(SkBench_AddPathTest::kAdd_AddType); )
+DEF_BENCH( return new SkBench_AddPathTest(SkBench_AddPathTest::kAddTrans_AddType); )
+DEF_BENCH( return new SkBench_AddPathTest(SkBench_AddPathTest::kAddMatrix_AddType); )
+DEF_BENCH( return new SkBench_AddPathTest(SkBench_AddPathTest::kReverseAdd_AddType); )
+DEF_BENCH( return new SkBench_AddPathTest(SkBench_AddPathTest::kReversePathTo_AddType); )
+
+DEF_BENCH( return new CirclesBench(FLAGS00); )
+DEF_BENCH( return new CirclesBench(FLAGS01); )
+DEF_BENCH( return new ArbRoundRectBench(false); )
+DEF_BENCH( return new ArbRoundRectBench(true); )
+DEF_BENCH( return new ConservativelyContainsBench(ConservativelyContainsBench::kRect_Type); )
+DEF_BENCH( return new ConservativelyContainsBench(ConservativelyContainsBench::kRoundRect_Type); )
+DEF_BENCH( return new ConservativelyContainsBench(ConservativelyContainsBench::kOval_Type); )
+
+DEF_BENCH( return new ConicBench_Chop5() )
+DEF_BENCH( return new ConicBench_ChopHalf() )
+DEF_BENCH( return new ConicBench_ComputeError() )
+DEF_BENCH( return new ConicBench_asQuadTol() )
+DEF_BENCH( return new ConicBench_quadPow2() )
diff --git a/chromium/third_party/skia/bench/PathIterBench.cpp b/chromium/third_party/skia/bench/PathIterBench.cpp
new file mode 100644
index 00000000000..b82146d1b23
--- /dev/null
+++ b/chromium/third_party/skia/bench/PathIterBench.cpp
@@ -0,0 +1,95 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "Benchmark.h"
+#include "SkBitmap.h"
+#include "SkCanvas.h"
+#include "SkColorPriv.h"
+#include "SkPaint.h"
+#include "SkRandom.h"
+#include "SkShader.h"
+#include "SkString.h"
+
+static int rand_pts(SkRandom& rand, SkPoint pts[4]) {
+ int n = rand.nextU() & 3;
+ n += 1;
+
+ for (int i = 0; i < n; ++i) {
+ pts[i].fX = rand.nextSScalar1();
+ pts[i].fY = rand.nextSScalar1();
+ }
+ return n;
+}
+
+class PathIterBench : public Benchmark {
+ SkString fName;
+ SkPath fPath;
+ bool fRaw;
+
+public:
+ PathIterBench(bool raw) {
+ fName.printf("pathiter_%s", raw ? "raw" : "consume");
+ fRaw = raw;
+
+ SkRandom rand;
+ for (int i = 0; i < 1000; ++i) {
+ SkPoint pts[4];
+ int n = rand_pts(rand, pts);
+ switch (n) {
+ case 1:
+ fPath.moveTo(pts[0]);
+ break;
+ case 2:
+ fPath.lineTo(pts[1]);
+ break;
+ case 3:
+ fPath.quadTo(pts[1], pts[2]);
+ break;
+ case 4:
+ fPath.cubicTo(pts[1], pts[2], pts[3]);
+ break;
+ }
+ }
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
+ if (fRaw) {
+ for (int i = 0; i < loops; ++i) {
+ SkPath::RawIter iter(fPath);
+ SkPath::Verb verb;
+ SkPoint pts[4];
+
+ while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { }
+ }
+ } else {
+ for (int i = 0; i < loops; ++i) {
+ SkPath::Iter iter(fPath, false);
+ SkPath::Verb verb;
+ SkPoint pts[4];
+
+ while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { }
+ }
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH( return new PathIterBench(false); )
+DEF_BENCH( return new PathIterBench(true); )
diff --git a/chromium/third_party/skia/bench/PathUtilsBench.cpp b/chromium/third_party/skia/bench/PathUtilsBench.cpp
new file mode 100644
index 00000000000..6c8086fb9df
--- /dev/null
+++ b/chromium/third_party/skia/bench/PathUtilsBench.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "Benchmark.h"
+#include "SkCanvas.h"
+#include "SkPathUtils.h"
+#include "SkRandom.h"
+#include "SkString.h"
+#include "SkTime.h"
+
+#define H 16
+#define W 16
+#define STRIDE 2
+
+//this function is redefined for sample, test, and bench. is there anywhere
+// I can put it to avoid code duplcation?
+static void fillRandomBits( int chars, char* bits ){
+ SkRandom rand(SkTime::GetMSecs());
+
+ for (int i = 0; i < chars; ++i){
+ bits[i] = rand.nextU();
+ }
+}
+
+static void path_proc(char* bits, SkPath* path) {
+ SkPathUtils::BitsToPath_Path(path, bits, H, W, STRIDE);
+}
+
+static void region_proc(char* bits, SkPath* path) {
+ SkPathUtils::BitsToPath_Region(path, bits, H, W, STRIDE);
+}
+
+/// Emulates the mix of rects blitted by gmail during scrolling
+class PathUtilsBench : public Benchmark {
+ typedef void (*Proc)(char*, SkPath*);
+
+ Proc fProc;
+ SkString fName;
+ char* bits[H * STRIDE];
+
+public:
+ PathUtilsBench(Proc proc, const char name[]) {
+ fProc = proc;
+ fName.printf("pathUtils_%s", name);
+
+
+ }
+
+protected:
+ virtual const char* onGetName() { return fName.c_str(); }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) {
+
+ for (int i = 0; i < loops; ++i){
+ //create a random 16x16 bitmap
+ fillRandomBits(H * STRIDE, (char*) &bits);
+
+ //use passed function pointer to handle it
+ SkPath path;
+ fProc( (char*) &bits, &path);
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+DEF_BENCH( return SkNEW_ARGS(PathUtilsBench, (path_proc, "path")); )
+DEF_BENCH( return SkNEW_ARGS(PathUtilsBench, (region_proc, "region")); )
diff --git a/chromium/third_party/skia/bench/PerlinNoiseBench.cpp b/chromium/third_party/skia/bench/PerlinNoiseBench.cpp
new file mode 100644
index 00000000000..560628f4fdd
--- /dev/null
+++ b/chromium/third_party/skia/bench/PerlinNoiseBench.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "Benchmark.h"
+#include "SkCanvas.h"
+#include "SkPerlinNoiseShader.h"
+
+class PerlinNoiseBench : public Benchmark {
+ SkISize fSize;
+
+public:
+ PerlinNoiseBench() {
+ fSize = SkISize::Make(80, 80);
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return "perlinnoise";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ this->test(loops, canvas, 0, 0, SkPerlinNoiseShader::kFractalNoise_Type,
+ 0.1f, 0.1f, 3, 0, false);
+ }
+
+private:
+ void drawClippedRect(SkCanvas* canvas, int x, int y, const SkPaint& paint) {
+ canvas->save();
+ canvas->clipRect(SkRect::MakeXYWH(SkIntToScalar(x), SkIntToScalar(y),
+ SkIntToScalar(fSize.width()), SkIntToScalar(fSize.height())));
+ SkRect r = SkRect::MakeXYWH(SkIntToScalar(x), SkIntToScalar(y),
+ SkIntToScalar(fSize.width()),
+ SkIntToScalar(fSize.height()));
+ canvas->drawRect(r, paint);
+ canvas->restore();
+ }
+
+ void test(const int loops, SkCanvas* canvas, int x, int y, SkPerlinNoiseShader::Type type,
+ float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed,
+ bool stitchTiles) {
+ SkShader* shader = (type == SkPerlinNoiseShader::kFractalNoise_Type) ?
+ SkPerlinNoiseShader::CreateFractalNoise(baseFrequencyX, baseFrequencyY, numOctaves,
+ seed, stitchTiles ? &fSize : NULL) :
+ SkPerlinNoiseShader::CreateTurbulence(baseFrequencyX, baseFrequencyY, numOctaves,
+ seed, stitchTiles ? &fSize : NULL);
+ SkPaint paint;
+ paint.setShader(shader)->unref();
+
+ for (int i = 0; i < loops; i++) {
+ this->drawClippedRect(canvas, x, y, paint);
+ }
+ }
+
+ typedef Benchmark INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH( return new PerlinNoiseBench(); )
diff --git a/chromium/third_party/skia/bench/PicturePlaybackBench.cpp b/chromium/third_party/skia/bench/PicturePlaybackBench.cpp
new file mode 100644
index 00000000000..0109c720fc0
--- /dev/null
+++ b/chromium/third_party/skia/bench/PicturePlaybackBench.cpp
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "Benchmark.h"
+#include "SkCanvas.h"
+#include "SkColor.h"
+#include "SkPaint.h"
+#include "SkPicture.h"
+#include "SkPictureRecorder.h"
+#include "SkPoint.h"
+#include "SkRect.h"
+#include "SkString.h"
+
+// This is designed to emulate about 4 screens of textual content
+
+
+class PicturePlaybackBench : public Benchmark {
+public:
+ PicturePlaybackBench(const char name[]) {
+ fName.printf("picture_playback_%s", name);
+ fPictureWidth = SkIntToScalar(PICTURE_WIDTH);
+ fPictureHeight = SkIntToScalar(PICTURE_HEIGHT);
+ fTextSize = SkIntToScalar(TEXT_SIZE);
+ }
+
+ enum {
+ PICTURE_WIDTH = 1000,
+ PICTURE_HEIGHT = 4000,
+ TEXT_SIZE = 10
+ };
+protected:
+ virtual const char* onGetName() {
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) {
+
+ SkPictureRecorder recorder;
+ SkCanvas* pCanvas = recorder.beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT, NULL, 0);
+ this->recordCanvas(pCanvas);
+ SkAutoTUnref<SkPicture> picture(recorder.endRecording());
+
+ const SkPoint translateDelta = getTranslateDelta(loops);
+
+ for (int i = 0; i < loops; i++) {
+ picture->draw(canvas);
+ canvas->translate(translateDelta.fX, translateDelta.fY);
+ }
+ }
+
+ virtual void recordCanvas(SkCanvas* canvas) = 0;
+ virtual SkPoint getTranslateDelta(int N) {
+ SkIPoint canvasSize = onGetSize();
+ return SkPoint::Make(SkIntToScalar((PICTURE_WIDTH - canvasSize.fX)/N),
+ SkIntToScalar((PICTURE_HEIGHT- canvasSize.fY)/N));
+ }
+
+ SkString fName;
+ SkScalar fPictureWidth;
+ SkScalar fPictureHeight;
+ SkScalar fTextSize;
+private:
+ typedef Benchmark INHERITED;
+};
+
+
+class TextPlaybackBench : public PicturePlaybackBench {
+public:
+ TextPlaybackBench() : INHERITED("drawText") { }
+protected:
+ virtual void recordCanvas(SkCanvas* canvas) SK_OVERRIDE {
+ SkPaint paint;
+ paint.setTextSize(fTextSize);
+ paint.setColor(SK_ColorBLACK);
+
+ const char* text = "Hamburgefons";
+ size_t len = strlen(text);
+ const SkScalar textWidth = paint.measureText(text, len);
+
+ for (SkScalar x = 0; x < fPictureWidth; x += textWidth) {
+ for (SkScalar y = 0; y < fPictureHeight; y += fTextSize) {
+ canvas->drawText(text, len, x, y, paint);
+ }
+ }
+ }
+private:
+ typedef PicturePlaybackBench INHERITED;
+};
+
+class PosTextPlaybackBench : public PicturePlaybackBench {
+public:
+ PosTextPlaybackBench(bool drawPosH)
+ : INHERITED(drawPosH ? "drawPosTextH" : "drawPosText")
+ , fDrawPosH(drawPosH) { }
+protected:
+ virtual void recordCanvas(SkCanvas* canvas) SK_OVERRIDE {
+ SkPaint paint;
+ paint.setTextSize(fTextSize);
+ paint.setColor(SK_ColorBLACK);
+
+ const char* text = "Hamburgefons";
+ size_t len = strlen(text);
+ const SkScalar textWidth = paint.measureText(text, len);
+
+ SkScalar* adv = new SkScalar[len];
+ paint.getTextWidths(text, len, adv);
+
+ for (SkScalar x = 0; x < fPictureWidth; x += textWidth) {
+ for (SkScalar y = 0; y < fPictureHeight; y += fTextSize) {
+
+ SkPoint* pos = new SkPoint[len];
+ SkScalar advX = 0;
+
+ for (size_t i = 0; i < len; i++) {
+ if (fDrawPosH)
+ pos[i].set(x + advX, y);
+ else
+ pos[i].set(x + advX, y + i);
+ advX += adv[i];
+ }
+
+ canvas->drawPosText(text, len, pos, paint);
+ delete[] pos;
+ }
+ }
+ delete[] adv;
+ }
+private:
+ bool fDrawPosH;
+ typedef PicturePlaybackBench INHERITED;
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH( return new TextPlaybackBench(); )
+DEF_BENCH( return new PosTextPlaybackBench(true); )
+DEF_BENCH( return new PosTextPlaybackBench(false); )
diff --git a/chromium/third_party/skia/bench/PictureRecordBench.cpp b/chromium/third_party/skia/bench/PictureRecordBench.cpp
new file mode 100644
index 00000000000..ef5361d20ac
--- /dev/null
+++ b/chromium/third_party/skia/bench/PictureRecordBench.cpp
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "Benchmark.h"
+#include "SkCanvas.h"
+#include "SkColor.h"
+#include "SkPaint.h"
+#include "SkPicture.h"
+#include "SkPictureRecorder.h"
+#include "SkPoint.h"
+#include "SkRandom.h"
+#include "SkRect.h"
+#include "SkString.h"
+
+class PictureRecordBench : public Benchmark {
+public:
+ PictureRecordBench(const char name[]) {
+ fName.printf("picture_record_%s", name);
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+ enum {
+ PICTURE_WIDTH = 1000,
+ PICTURE_HEIGHT = 4000,
+ };
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+private:
+ SkString fName;
+ typedef Benchmark INHERITED;
+};
+
+
+static const int kMaxLoopsPerCanvas = 10000;
+
+/*
+ * An SkPicture has internal dictionaries to store bitmaps, matrices, paints,
+ * and regions. This bench populates those dictionaries to test the speed of
+ * reading and writing to those particular dictionary data structures.
+ */
+class DictionaryRecordBench : public PictureRecordBench {
+public:
+ DictionaryRecordBench() : INHERITED("dictionaries") {}
+
+protected:
+ virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
+ SkPictureRecorder recorder;
+ SkCanvas* canvas = NULL;
+
+ const SkPoint translateDelta = getTranslateDelta(loops);
+
+ for (int i = 0; i < loops; i++) {
+ if (0 == i % kMaxLoopsPerCanvas) {
+ SkAutoTUnref<SkPicture> picture(recorder.endRecording());
+ canvas = recorder.beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT, NULL, 0);
+ }
+
+ SkColor color = SK_ColorYELLOW + (i % 255);
+ SkIRect rect = SkIRect::MakeWH(i % PICTURE_WIDTH, i % PICTURE_HEIGHT);
+
+ canvas->save();
+
+ // set the clip to the given region
+ SkRegion region;
+ region.setRect(rect);
+ canvas->clipRegion(region);
+
+ // fill the clip with a color
+ SkPaint paint;
+ paint.setColor(color);
+ canvas->drawPaint(paint);
+
+ // set a matrix on the canvas
+ SkMatrix matrix;
+ matrix.setRotate(SkIntToScalar(i % 360));
+ canvas->setMatrix(matrix);
+
+ // create a simple bitmap
+ SkBitmap bitmap;
+ bitmap.allocPixels(SkImageInfo::Make(10, 10,
+ kRGB_565_SkColorType, kOpaque_SkAlphaType));
+
+ // draw a single color into the bitmap
+ SkCanvas bitmapCanvas(bitmap);
+ bitmapCanvas.drawColor(SkColorSetA(color, i % 255));
+
+ // draw the bitmap onto the canvas
+ canvas->drawBitmapMatrix(bitmap, matrix);
+
+ canvas->restore();
+ canvas->translate(translateDelta.fX, translateDelta.fY);
+ }
+ }
+
+ SkPoint getTranslateDelta(int M) {
+ SkIPoint canvasSize = onGetSize();
+ return SkPoint::Make(SkIntToScalar((PICTURE_WIDTH - canvasSize.fX)/M),
+ SkIntToScalar((PICTURE_HEIGHT- canvasSize.fY)/M));
+ }
+private:
+ typedef PictureRecordBench INHERITED;
+};
+
+/*
+ * Populates the SkPaint dictionary with a large number of unique paint
+ * objects that differ only by color
+ */
+class UniquePaintDictionaryRecordBench : public PictureRecordBench {
+public:
+ UniquePaintDictionaryRecordBench() : INHERITED("unique_paint_dictionary") { }
+
+protected:
+ virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
+ SkRandom rand;
+ SkPaint paint;
+ SkPictureRecorder recorder;
+ SkCanvas* canvas = NULL;
+ for (int i = 0; i < loops; i++) {
+ if (0 == i % kMaxLoopsPerCanvas) {
+ SkAutoTUnref<SkPicture> picture(recorder.endRecording());
+ canvas = recorder.beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT, NULL, 0);
+ }
+ paint.setColor(rand.nextU());
+ canvas->drawPaint(paint);
+ }
+ }
+
+private:
+ typedef PictureRecordBench INHERITED;
+};
+
+/*
+ * Populates the SkPaint dictionary with a number of unique paint
+ * objects that get reused repeatedly.
+ *
+ * Re-creating the paint objects in the inner loop slows the benchmark down 10%.
+ * Using setColor(i % objCount) instead of a random color creates a very high rate
+ * of hash conflicts, slowing us down 12%.
+ */
+class RecurringPaintDictionaryRecordBench : public PictureRecordBench {
+public:
+ RecurringPaintDictionaryRecordBench() : INHERITED("recurring_paint_dictionary") {
+ SkRandom rand;
+ for (int i = 0; i < ObjCount; i++) {
+ fPaint[i].setColor(rand.nextU());
+ }
+ }
+
+ enum {
+ ObjCount = 100, // number of unique paint objects
+ };
+protected:
+ virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
+ SkPictureRecorder recorder;
+ SkCanvas* canvas = recorder.beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT, NULL, 0);
+ for (int i = 0; i < loops; i++) {
+ canvas->drawPaint(fPaint[i % ObjCount]);
+ }
+ }
+
+private:
+ SkPaint fPaint [ObjCount];
+ typedef PictureRecordBench INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH( return new DictionaryRecordBench(); )
+DEF_BENCH( return new UniquePaintDictionaryRecordBench(); )
+DEF_BENCH( return new RecurringPaintDictionaryRecordBench(); )
diff --git a/chromium/third_party/skia/bench/PremulAndUnpremulAlphaOpsBench.cpp b/chromium/third_party/skia/bench/PremulAndUnpremulAlphaOpsBench.cpp
new file mode 100644
index 00000000000..311bdf2d477
--- /dev/null
+++ b/chromium/third_party/skia/bench/PremulAndUnpremulAlphaOpsBench.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkCanvas.h"
+#include "SkConfig8888.h"
+#include "SkString.h"
+#include "sk_tool_utils.h"
+
+class PremulAndUnpremulAlphaOpsBench : public Benchmark {
+ enum {
+ W = 256,
+ H = 256,
+ };
+ SkBitmap fBmp1, fBmp2;
+
+public:
+ PremulAndUnpremulAlphaOpsBench(SkColorType ct) {
+ fColorType = ct;
+ fName.printf("premul_and_unpremul_alpha_%s", sk_tool_utils::colortype_name(ct));
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+
+ virtual void onPreDraw() {
+ SkImageInfo info = SkImageInfo::Make(W, H, fColorType, kPremul_SkAlphaType);
+ fBmp1.allocPixels(info); // used in writePixels
+
+ for (int h = 0; h < H; ++h) {
+ for (int w = 0; w < W; ++w) {
+ // SkColor places A in the right slot for either RGBA or BGRA
+ *fBmp1.getAddr32(w, h) = SkColorSetARGB(h & 0xFF, w & 0xFF, w & 0xFF, w & 0xFF);
+ }
+ }
+
+ fBmp2.allocPixels(info); // used in readPixels()
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ canvas->clear(SK_ColorBLACK);
+
+ for (int loop = 0; loop < loops; ++loop) {
+ // Unpremul -> Premul
+ canvas->writePixels(fBmp1.info(), fBmp1.getPixels(), fBmp1.rowBytes(), 0, 0);
+ // Premul -> Unpremul
+ canvas->readPixels(fBmp2.info(), fBmp2.getPixels(), fBmp2.rowBytes(), 0, 0);
+ }
+ }
+
+private:
+ SkColorType fColorType;
+ SkString fName;
+
+ typedef Benchmark INHERITED;
+};
+
+
+DEF_BENCH(return new PremulAndUnpremulAlphaOpsBench(kRGBA_8888_SkColorType));
+DEF_BENCH(return new PremulAndUnpremulAlphaOpsBench(kBGRA_8888_SkColorType));
diff --git a/chromium/third_party/skia/bench/QuadTreeBench.cpp b/chromium/third_party/skia/bench/QuadTreeBench.cpp
new file mode 100644
index 00000000000..79078a8ae9b
--- /dev/null
+++ b/chromium/third_party/skia/bench/QuadTreeBench.cpp
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkCanvas.h"
+#include "SkQuadTree.h"
+#include "SkRandom.h"
+#include "SkString.h"
+
+// confine rectangles to a smallish area, so queries generally hit something, and overlap occurs:
+static const int GENERATE_EXTENTS = 1000;
+static const int NUM_BUILD_RECTS = 500;
+static const int NUM_QUERY_RECTS = 5000;
+static const int GRID_WIDTH = 100;
+static const SkIRect QUAD_TREE_BOUNDS = SkIRect::MakeLTRB(
+ -GENERATE_EXTENTS, -GENERATE_EXTENTS, 2 * GENERATE_EXTENTS, 2 * GENERATE_EXTENTS);
+
+typedef SkIRect (*MakeRectProc)(SkRandom&, int, int);
+
+// Time how long it takes to build an QuadTree
+class QuadTreeBuildBench : public Benchmark {
+public:
+ QuadTreeBuildBench(const char* name, MakeRectProc proc, SkBBoxHierarchy* tree)
+ : fTree(tree)
+ , fProc(proc) {
+ fName.append("quadtree_");
+ fName.append(name);
+ fName.append("_build");
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+ virtual ~QuadTreeBuildBench() {
+ fTree->unref();
+ }
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkRandom rand;
+ for (int i = 0; i < loops; ++i) {
+ for (int j = 0; j < NUM_BUILD_RECTS; ++j) {
+ fTree->insert(reinterpret_cast<void*>(j), fProc(rand, j, NUM_BUILD_RECTS),
+ false);
+ }
+ fTree->clear();
+ }
+ }
+private:
+ SkBBoxHierarchy* fTree;
+ MakeRectProc fProc;
+ SkString fName;
+ typedef Benchmark INHERITED;
+};
+
+// Time how long it takes to perform queries on an QuadTree
+class QuadTreeQueryBench : public Benchmark {
+public:
+ enum QueryType {
+ kSmall_QueryType, // small queries
+ kLarge_QueryType, // large queries
+ kRandom_QueryType,// randomly sized queries
+ kFull_QueryType // queries that cover everything
+ };
+
+ QuadTreeQueryBench(const char* name, MakeRectProc proc,
+ QueryType q, SkBBoxHierarchy* tree)
+ : fTree(tree)
+ , fProc(proc)
+ , fQuery(q) {
+ fName.append("quadtree_");
+ fName.append(name);
+ fName.append("_query");
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+ virtual ~QuadTreeQueryBench() {
+ fTree->unref();
+ }
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+ virtual void onPreDraw() SK_OVERRIDE {
+ SkRandom rand;
+ for (int j = 0; j < NUM_QUERY_RECTS; ++j) {
+ fTree->insert(reinterpret_cast<void*>(j),
+ fProc(rand, j, NUM_QUERY_RECTS),
+ false);
+ }
+ fTree->flushDeferredInserts();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkRandom rand;
+ for (int i = 0; i < loops; ++i) {
+ SkTDArray<void*> hits;
+ SkIRect query;
+ switch(fQuery) {
+ case kSmall_QueryType:
+ query.fLeft = rand.nextU() % GENERATE_EXTENTS;
+ query.fTop = rand.nextU() % GENERATE_EXTENTS;
+ query.fRight = query.fLeft + (GENERATE_EXTENTS / 20);
+ query.fBottom = query.fTop + (GENERATE_EXTENTS / 20);
+ break;
+ case kLarge_QueryType:
+ query.fLeft = rand.nextU() % GENERATE_EXTENTS;
+ query.fTop = rand.nextU() % GENERATE_EXTENTS;
+ query.fRight = query.fLeft + (GENERATE_EXTENTS / 2);
+ query.fBottom = query.fTop + (GENERATE_EXTENTS / 2);
+ break;
+ case kFull_QueryType:
+ query.fLeft = -GENERATE_EXTENTS;
+ query.fTop = -GENERATE_EXTENTS;
+ query.fRight = 2 * GENERATE_EXTENTS;
+ query.fBottom = 2 * GENERATE_EXTENTS;
+ break;
+ default: // fallthrough
+ case kRandom_QueryType:
+ query.fLeft = rand.nextU() % GENERATE_EXTENTS;
+ query.fTop = rand.nextU() % GENERATE_EXTENTS;
+ query.fRight = query.fLeft + 1 + rand.nextU() % (GENERATE_EXTENTS / 2);
+ query.fBottom = query.fTop + 1 + rand.nextU() % (GENERATE_EXTENTS / 2);
+ break;
+ };
+ fTree->search(query, &hits);
+ }
+ }
+private:
+ SkBBoxHierarchy* fTree;
+ MakeRectProc fProc;
+ SkString fName;
+ QueryType fQuery;
+ typedef Benchmark INHERITED;
+};
+
+static inline SkIRect make_concentric_rects_increasing(SkRandom&, int index, int numRects) {
+ SkIRect out = {0, 0, index + 1, index + 1};
+ return out;
+}
+
+static inline SkIRect make_XYordered_rects(SkRandom& rand, int index, int numRects) {
+ SkIRect out;
+ out.fLeft = index % GRID_WIDTH;
+ out.fTop = index / GRID_WIDTH;
+ out.fRight = out.fLeft + 1 + rand.nextU() % (GENERATE_EXTENTS / 3);
+ out.fBottom = out.fTop + 1 + rand.nextU() % (GENERATE_EXTENTS / 3);
+ return out;
+}
+
+static inline SkIRect make_YXordered_rects(SkRandom& rand, int index, int numRects) {
+ SkIRect out;
+ out.fLeft = index / GRID_WIDTH;
+ out.fTop = index % GRID_WIDTH;
+ out.fRight = out.fLeft + 1 + rand.nextU() % (GENERATE_EXTENTS / 3);
+ out.fBottom = out.fTop + 1 + rand.nextU() % (GENERATE_EXTENTS / 3);
+ return out;
+}
+
+static inline SkIRect make_random_rects(SkRandom& rand, int index, int numRects) {
+ SkIRect out;
+ out.fLeft = rand.nextS() % GENERATE_EXTENTS;
+ out.fTop = rand.nextS() % GENERATE_EXTENTS;
+ out.fRight = out.fLeft + 1 + rand.nextU() % (GENERATE_EXTENTS / 5);
+ out.fBottom = out.fTop + 1 + rand.nextU() % (GENERATE_EXTENTS / 5);
+ return out;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH(
+ return SkNEW_ARGS(QuadTreeBuildBench, ("XYordered", &make_XYordered_rects,
+ SkNEW_ARGS(SkQuadTree, (QUAD_TREE_BOUNDS))));
+)
+DEF_BENCH(
+ return SkNEW_ARGS(QuadTreeQueryBench, ("XYordered", &make_XYordered_rects,
+ QuadTreeQueryBench::kRandom_QueryType,
+ SkNEW_ARGS(SkQuadTree, (QUAD_TREE_BOUNDS))));
+)
+DEF_BENCH(
+ return SkNEW_ARGS(QuadTreeBuildBench, ("YXordered", &make_YXordered_rects,
+ SkNEW_ARGS(SkQuadTree, (QUAD_TREE_BOUNDS))));
+)
+DEF_BENCH(
+ return SkNEW_ARGS(QuadTreeQueryBench, ("YXordered", &make_YXordered_rects,
+ QuadTreeQueryBench::kRandom_QueryType,
+ SkNEW_ARGS(SkQuadTree, (QUAD_TREE_BOUNDS))));
+)
+DEF_BENCH(
+ return SkNEW_ARGS(QuadTreeBuildBench, ("random", &make_random_rects,
+ SkNEW_ARGS(SkQuadTree, (QUAD_TREE_BOUNDS))));
+)
+DEF_BENCH(
+ return SkNEW_ARGS(QuadTreeQueryBench, ("random", &make_random_rects,
+ QuadTreeQueryBench::kRandom_QueryType,
+ SkNEW_ARGS(SkQuadTree, (QUAD_TREE_BOUNDS))));
+)
+DEF_BENCH(
+ return SkNEW_ARGS(QuadTreeBuildBench, ("concentric", &make_concentric_rects_increasing,
+ SkNEW_ARGS(SkQuadTree, (QUAD_TREE_BOUNDS))));
+)
+DEF_BENCH(
+ return SkNEW_ARGS(QuadTreeQueryBench, ("concentric", &make_concentric_rects_increasing,
+ QuadTreeQueryBench::kRandom_QueryType,
+ SkNEW_ARGS(SkQuadTree, (QUAD_TREE_BOUNDS))));
+)
diff --git a/chromium/third_party/skia/bench/RTreeBench.cpp b/chromium/third_party/skia/bench/RTreeBench.cpp
new file mode 100644
index 00000000000..95f55c9a8f0
--- /dev/null
+++ b/chromium/third_party/skia/bench/RTreeBench.cpp
@@ -0,0 +1,269 @@
+
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkCanvas.h"
+#include "SkRTree.h"
+#include "SkRandom.h"
+#include "SkString.h"
+
+// confine rectangles to a smallish area, so queries generally hit something, and overlap occurs:
+static const int GENERATE_EXTENTS = 1000;
+static const int NUM_BUILD_RECTS = 500;
+static const int NUM_QUERY_RECTS = 5000;
+static const int GRID_WIDTH = 100;
+
+typedef SkIRect (*MakeRectProc)(SkRandom&, int, int);
+
+// Time how long it takes to build an R-Tree either bulk-loaded or not
+class RTreeBuildBench : public Benchmark {
+public:
+ RTreeBuildBench(const char* name, MakeRectProc proc, bool bulkLoad,
+ SkBBoxHierarchy* tree)
+ : fTree(tree)
+ , fProc(proc)
+ , fBulkLoad(bulkLoad) {
+ fName.append("rtree_");
+ fName.append(name);
+ fName.append("_build");
+ if (fBulkLoad) {
+ fName.append("_bulk");
+ }
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+ virtual ~RTreeBuildBench() {
+ fTree->unref();
+ }
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkRandom rand;
+ for (int i = 0; i < loops; ++i) {
+ for (int j = 0; j < NUM_BUILD_RECTS; ++j) {
+ fTree->insert(reinterpret_cast<void*>(j), fProc(rand, j, NUM_BUILD_RECTS),
+ fBulkLoad);
+ }
+ fTree->flushDeferredInserts();
+ fTree->clear();
+ }
+ }
+private:
+ SkBBoxHierarchy* fTree;
+ MakeRectProc fProc;
+ SkString fName;
+ bool fBulkLoad;
+ typedef Benchmark INHERITED;
+};
+
+// Time how long it takes to perform queries on an R-Tree, bulk-loaded or not
+class RTreeQueryBench : public Benchmark {
+public:
+ enum QueryType {
+ kSmall_QueryType, // small queries
+ kLarge_QueryType, // large queries
+ kRandom_QueryType,// randomly sized queries
+ kFull_QueryType // queries that cover everything
+ };
+
+ RTreeQueryBench(const char* name, MakeRectProc proc, bool bulkLoad,
+ QueryType q, SkBBoxHierarchy* tree)
+ : fTree(tree)
+ , fProc(proc)
+ , fBulkLoad(bulkLoad)
+ , fQuery(q) {
+ fName.append("rtree_");
+ fName.append(name);
+ fName.append("_query");
+ if (fBulkLoad) {
+ fName.append("_bulk");
+ }
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+ virtual ~RTreeQueryBench() {
+ fTree->unref();
+ }
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+ virtual void onPreDraw() SK_OVERRIDE {
+ SkRandom rand;
+ for (int j = 0; j < NUM_QUERY_RECTS; ++j) {
+ fTree->insert(reinterpret_cast<void*>(j),
+ fProc(rand, j, NUM_QUERY_RECTS),
+ fBulkLoad);
+ }
+ fTree->flushDeferredInserts();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkRandom rand;
+ for (int i = 0; i < loops; ++i) {
+ SkTDArray<void*> hits;
+ SkIRect query;
+ switch(fQuery) {
+ case kSmall_QueryType:
+ query.fLeft = rand.nextU() % GENERATE_EXTENTS;
+ query.fTop = rand.nextU() % GENERATE_EXTENTS;
+ query.fRight = query.fLeft + (GENERATE_EXTENTS / 20);
+ query.fBottom = query.fTop + (GENERATE_EXTENTS / 20);
+ break;
+ case kLarge_QueryType:
+ query.fLeft = rand.nextU() % GENERATE_EXTENTS;
+ query.fTop = rand.nextU() % GENERATE_EXTENTS;
+ query.fRight = query.fLeft + (GENERATE_EXTENTS / 2);
+ query.fBottom = query.fTop + (GENERATE_EXTENTS / 2);
+ break;
+ case kFull_QueryType:
+ query.fLeft = -GENERATE_EXTENTS;
+ query.fTop = -GENERATE_EXTENTS;
+ query.fRight = 2 * GENERATE_EXTENTS;
+ query.fBottom = 2 * GENERATE_EXTENTS;
+ break;
+ default: // fallthrough
+ case kRandom_QueryType:
+ query.fLeft = rand.nextU() % GENERATE_EXTENTS;
+ query.fTop = rand.nextU() % GENERATE_EXTENTS;
+ query.fRight = query.fLeft + 1 + rand.nextU() % (GENERATE_EXTENTS / 2);
+ query.fBottom = query.fTop + 1 + rand.nextU() % (GENERATE_EXTENTS / 2);
+ break;
+ };
+ fTree->search(query, &hits);
+ }
+ }
+private:
+ SkBBoxHierarchy* fTree;
+ MakeRectProc fProc;
+ SkString fName;
+ bool fBulkLoad;
+ QueryType fQuery;
+ typedef Benchmark INHERITED;
+};
+
+static inline SkIRect make_concentric_rects_increasing(SkRandom&, int index, int numRects) {
+ SkIRect out = {0, 0, index + 1, index + 1};
+ return out;
+}
+
+static inline SkIRect make_XYordered_rects(SkRandom& rand, int index, int numRects) {
+ SkIRect out;
+ out.fLeft = index % GRID_WIDTH;
+ out.fTop = index / GRID_WIDTH;
+ out.fRight = out.fLeft + 1 + rand.nextU() % (GENERATE_EXTENTS / 3);
+ out.fBottom = out.fTop + 1 + rand.nextU() % (GENERATE_EXTENTS / 3);
+ return out;
+}
+static inline SkIRect make_YXordered_rects(SkRandom& rand, int index, int numRects) {
+ SkIRect out;
+ out.fLeft = index / GRID_WIDTH;
+ out.fTop = index % GRID_WIDTH;
+ out.fRight = out.fLeft + 1 + rand.nextU() % (GENERATE_EXTENTS / 3);
+ out.fBottom = out.fTop + 1 + rand.nextU() % (GENERATE_EXTENTS / 3);
+ return out;
+}
+
+static inline SkIRect make_random_rects(SkRandom& rand, int index, int numRects) {
+ SkIRect out;
+ out.fLeft = rand.nextS() % GENERATE_EXTENTS;
+ out.fTop = rand.nextS() % GENERATE_EXTENTS;
+ out.fRight = out.fLeft + 1 + rand.nextU() % (GENERATE_EXTENTS / 5);
+ out.fBottom = out.fTop + 1 + rand.nextU() % (GENERATE_EXTENTS / 5);
+ return out;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH(
+ return SkNEW_ARGS(RTreeBuildBench, ("XYordered", &make_XYordered_rects, false,
+ SkRTree::Create(5, 16)));
+)
+DEF_BENCH(
+ return SkNEW_ARGS(RTreeBuildBench, ("XYordered", &make_XYordered_rects, true,
+ SkRTree::Create(5, 16)));
+)
+DEF_BENCH(
+ return SkNEW_ARGS(RTreeBuildBench, ("(unsorted)XYordered", &make_XYordered_rects, true,
+ SkRTree::Create(5, 16, 1, false)));
+)
+DEF_BENCH(
+ return SkNEW_ARGS(RTreeQueryBench, ("XYordered", &make_XYordered_rects, true,
+ RTreeQueryBench::kRandom_QueryType, SkRTree::Create(5, 16)));
+)
+DEF_BENCH(
+ return SkNEW_ARGS(RTreeQueryBench, ("(unsorted)XYordered", &make_XYordered_rects, true,
+ RTreeQueryBench::kRandom_QueryType, SkRTree::Create(5, 16, 1, false)));
+)
+
+DEF_BENCH(
+ return SkNEW_ARGS(RTreeBuildBench, ("YXordered", &make_YXordered_rects, false,
+ SkRTree::Create(5, 16)));
+)
+DEF_BENCH(
+ return SkNEW_ARGS(RTreeBuildBench, ("YXordered", &make_YXordered_rects, true,
+ SkRTree::Create(5, 16)));
+)
+DEF_BENCH(
+ return SkNEW_ARGS(RTreeBuildBench, ("(unsorted)YXordered", &make_YXordered_rects, true,
+ SkRTree::Create(5, 16, 1, false)));
+)
+DEF_BENCH(
+ return SkNEW_ARGS(RTreeQueryBench, ("YXordered", &make_YXordered_rects, true,
+ RTreeQueryBench::kRandom_QueryType, SkRTree::Create(5, 16)));
+)
+DEF_BENCH(
+ return SkNEW_ARGS(RTreeQueryBench, ("(unsorted)YXordered", &make_YXordered_rects, true,
+ RTreeQueryBench::kRandom_QueryType, SkRTree::Create(5, 16, 1, false)));
+)
+
+DEF_BENCH(
+ return SkNEW_ARGS(RTreeBuildBench, ("random", &make_random_rects, false,
+ SkRTree::Create(5, 16)));
+)
+DEF_BENCH(
+ return SkNEW_ARGS(RTreeBuildBench, ("random", &make_random_rects, true,
+ SkRTree::Create(5, 16)));
+)
+DEF_BENCH(
+ return SkNEW_ARGS(RTreeBuildBench, ("(unsorted)random", &make_random_rects, true,
+ SkRTree::Create(5, 16, 1, false)));
+)
+DEF_BENCH(
+ return SkNEW_ARGS(RTreeQueryBench, ("random", &make_random_rects, true,
+ RTreeQueryBench::kRandom_QueryType, SkRTree::Create(5, 16)));
+)
+DEF_BENCH(
+ return SkNEW_ARGS(RTreeQueryBench, ("(unsorted)random", &make_random_rects, true,
+ RTreeQueryBench::kRandom_QueryType, SkRTree::Create(5, 16, 1, false)));
+)
+
+DEF_BENCH(
+ return SkNEW_ARGS(RTreeBuildBench, ("concentric",
+ &make_concentric_rects_increasing, true, SkRTree::Create(5, 16)));
+)
+DEF_BENCH(
+ return SkNEW_ARGS(RTreeBuildBench, ("(unsorted)concentric",
+ &make_concentric_rects_increasing, true, SkRTree::Create(5, 16, 1, false)));
+)
+DEF_BENCH(
+ return SkNEW_ARGS(RTreeQueryBench, ("concentric", &make_concentric_rects_increasing, true,
+ RTreeQueryBench::kRandom_QueryType, SkRTree::Create(5, 16)));
+)
+DEF_BENCH(
+ return SkNEW_ARGS(RTreeQueryBench, ("(unsorted)concentric", &make_concentric_rects_increasing, true,
+ RTreeQueryBench::kRandom_QueryType, SkRTree::Create(5, 16, 1, false)));
+)
diff --git a/chromium/third_party/skia/bench/ReadPixBench.cpp b/chromium/third_party/skia/bench/ReadPixBench.cpp
new file mode 100644
index 00000000000..7848ebc7576
--- /dev/null
+++ b/chromium/third_party/skia/bench/ReadPixBench.cpp
@@ -0,0 +1,67 @@
+
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkCanvas.h"
+
+
+/**
+ * This bench mark tests the use case where the user writes the a canvas
+ * and then reads small chunks from it repeatedly. This can cause trouble
+ * for the GPU as readbacks are very expensive.
+ */
+class ReadPixBench : public Benchmark {
+public:
+ ReadPixBench() {}
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return "readpix";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ canvas->clear(SK_ColorBLACK);
+
+ SkISize size = canvas->getDeviceSize();
+
+ int offX = (size.width() - kWindowSize) / kNumStepsX;
+ int offY = (size.height() - kWindowSize) / kNumStepsY;
+
+ SkPaint paint;
+
+ paint.setColor(SK_ColorBLUE);
+
+ canvas->drawCircle(SkIntToScalar(size.width()/2),
+ SkIntToScalar(size.height()/2),
+ SkIntToScalar(size.width()/2),
+ paint);
+
+ SkBitmap bitmap;
+
+ bitmap.setInfo(SkImageInfo::MakeN32Premul(kWindowSize, kWindowSize));
+
+ for (int i = 0; i < loops; i++) {
+ for (int x = 0; x < kNumStepsX; ++x) {
+ for (int y = 0; y < kNumStepsY; ++y) {
+ canvas->readPixels(&bitmap, x * offX, y * offY);
+ }
+ }
+ }
+ }
+
+private:
+ static const int kNumStepsX = 30;
+ static const int kNumStepsY = 30;
+ static const int kWindowSize = 5;
+
+ typedef Benchmark INHERITED;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH( return new ReadPixBench(); )
diff --git a/chromium/third_party/skia/bench/RectBench.cpp b/chromium/third_party/skia/bench/RectBench.cpp
new file mode 100644
index 00000000000..f50324a580b
--- /dev/null
+++ b/chromium/third_party/skia/bench/RectBench.cpp
@@ -0,0 +1,345 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "Benchmark.h"
+#include "SkCanvas.h"
+#include "SkCommandLineFlags.h"
+#include "SkPaint.h"
+#include "SkRandom.h"
+#include "SkShader.h"
+#include "SkString.h"
+
+DEFINE_double(strokeWidth, -1.0, "If set, use this stroke width in RectBench.");
+
+class RectBench : public Benchmark {
+public:
+ int fShift, fStroke;
+ enum {
+ W = 640,
+ H = 480,
+ N = 300,
+ };
+ SkRect fRects[N];
+ SkColor fColors[N];
+
+ RectBench(int shift, int stroke = 0)
+ : fShift(shift)
+ , fStroke(stroke) {}
+
+ SkString fName;
+ const char* computeName(const char root[]) {
+ fName.printf("%s_%d", root, fShift);
+ if (fStroke > 0) {
+ fName.appendf("_stroke_%d", fStroke);
+ }
+ return fName.c_str();
+ }
+
+protected:
+ virtual void drawThisRect(SkCanvas* c, const SkRect& r, const SkPaint& p) {
+ c->drawRect(r, p);
+ }
+
+ virtual const char* onGetName() { return computeName("rects"); }
+
+ virtual void onPreDraw() {
+ SkRandom rand;
+ const SkScalar offset = SK_Scalar1/3;
+ for (int i = 0; i < N; i++) {
+ int x = rand.nextU() % W;
+ int y = rand.nextU() % H;
+ int w = rand.nextU() % W;
+ int h = rand.nextU() % H;
+ w >>= fShift;
+ h >>= fShift;
+ x -= w/2;
+ y -= h/2;
+ fRects[i].set(SkIntToScalar(x), SkIntToScalar(y),
+ SkIntToScalar(x+w), SkIntToScalar(y+h));
+ fRects[i].offset(offset, offset);
+ fColors[i] = rand.nextU() | 0xFF808080;
+ }
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) {
+ SkPaint paint;
+ if (fStroke > 0) {
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(SkIntToScalar(fStroke));
+ }
+ for (int i = 0; i < loops; i++) {
+ paint.setColor(fColors[i % N]);
+ this->setupPaint(&paint);
+ this->drawThisRect(canvas, fRects[i % N], paint);
+ }
+ }
+private:
+ typedef Benchmark INHERITED;
+};
+
+class SrcModeRectBench : public RectBench {
+public:
+ SrcModeRectBench() : INHERITED(1, 0) {
+ fMode = SkXfermode::Create(SkXfermode::kSrc_Mode);
+ }
+
+ virtual ~SrcModeRectBench() {
+ SkSafeUnref(fMode);
+ }
+
+protected:
+ virtual void setupPaint(SkPaint* paint) SK_OVERRIDE {
+ this->INHERITED::setupPaint(paint);
+ // srcmode is most interesting when we're not opaque
+ paint->setAlpha(0x80);
+ paint->setXfermode(fMode);
+ }
+
+ virtual const char* onGetName() SK_OVERRIDE {
+ fName.set(this->INHERITED::onGetName());
+ fName.prepend("srcmode_");
+ return fName.c_str();
+ }
+
+private:
+ SkString fName;
+ SkXfermode* fMode;
+
+ typedef RectBench INHERITED;
+};
+
+class OvalBench : public RectBench {
+public:
+ OvalBench(int shift, int stroke = 0) : RectBench(shift, stroke) {}
+protected:
+ virtual void drawThisRect(SkCanvas* c, const SkRect& r, const SkPaint& p) {
+ c->drawOval(r, p);
+ }
+ virtual const char* onGetName() { return computeName("ovals"); }
+};
+
+class RRectBench : public RectBench {
+public:
+ RRectBench(int shift, int stroke = 0) : RectBench(shift, stroke) {}
+protected:
+ virtual void drawThisRect(SkCanvas* c, const SkRect& r, const SkPaint& p) {
+ c->drawRoundRect(r, r.width() / 4, r.height() / 4, p);
+ }
+ virtual const char* onGetName() { return computeName("rrects"); }
+};
+
+class PointsBench : public RectBench {
+public:
+ SkCanvas::PointMode fMode;
+ const char* fName;
+
+ PointsBench(SkCanvas::PointMode mode, const char* name)
+ : RectBench(2)
+ , fMode(mode) {
+ fName = name;
+ }
+
+protected:
+ virtual void onDraw(const int loops, SkCanvas* canvas) {
+ SkScalar gSizes[] = {
+ SkIntToScalar(7), 0
+ };
+ size_t sizes = SK_ARRAY_COUNT(gSizes);
+
+ if (FLAGS_strokeWidth >= 0) {
+ gSizes[0] = (SkScalar)FLAGS_strokeWidth;
+ sizes = 1;
+ }
+
+ SkPaint paint;
+ paint.setStrokeCap(SkPaint::kRound_Cap);
+
+ for (int loop = 0; loop < loops; loop++) {
+ for (size_t i = 0; i < sizes; i++) {
+ paint.setStrokeWidth(gSizes[i]);
+ this->setupPaint(&paint);
+ canvas->drawPoints(fMode, N * 2, SkTCast<SkPoint*>(fRects), paint);
+ paint.setColor(fColors[i % N]);
+ }
+ }
+ }
+ virtual const char* onGetName() { return fName; }
+};
+
+class AARectBench : public Benchmark {
+public:
+ enum {
+ W = 640,
+ H = 480,
+ };
+
+ AARectBench(bool rotate) : fRotate(rotate) {}
+
+protected:
+
+ virtual const char* onGetName() {
+ if (fRotate) {
+ return "aarects_rotated";
+ }
+ return "aarects";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) {
+ static const SkScalar kHalfRectSize = 0.75f;
+
+ SkPaint paint;
+ this->setupPaint(&paint);
+ paint.setAntiAlias(true);
+ paint.setColor(SK_ColorBLACK);
+ SkRect r = { -kHalfRectSize, -kHalfRectSize, kHalfRectSize, kHalfRectSize };
+ int rot = 0;
+
+ for (int i = 0; i < loops; i++) {
+ // Draw small aa rects in a grid across the screen
+ for (SkScalar y = kHalfRectSize+SK_Scalar1; y < H; y += 2*kHalfRectSize+2) {
+ for (SkScalar x = kHalfRectSize+SK_Scalar1; x < W; x += 2*kHalfRectSize+2) {
+ canvas->save();
+ canvas->translate(x, y);
+
+ if (fRotate) {
+ SkMatrix rotate;
+ rotate.setRotate(SkIntToScalar(rot));
+ canvas->concat(rotate);
+ rot += 10;
+ }
+
+ canvas->drawRect(r, paint);
+ canvas->restore();
+ }
+ }
+ }
+
+ }
+private:
+ bool fRotate;
+ typedef Benchmark INHERITED;
+};
+
+/*******************************************************************************
+ * to bench BlitMask [Opaque, Black, color, shader]
+ *******************************************************************************/
+
+class BlitMaskBench : public RectBench {
+public:
+ enum kMaskType {
+ kMaskOpaque = 0,
+ kMaskBlack,
+ kMaskColor,
+ KMaskShader
+ };
+ SkCanvas::PointMode fMode;
+ const char* fName;
+
+ BlitMaskBench(SkCanvas::PointMode mode,
+ BlitMaskBench::kMaskType type, const char* name) :
+ RectBench(2), fMode(mode), _type(type) {
+ fName = name;
+ }
+
+protected:
+ virtual void onDraw(const int loops, SkCanvas* canvas) {
+ SkScalar gSizes[] = {
+ SkIntToScalar(13), SkIntToScalar(24)
+ };
+ size_t sizes = SK_ARRAY_COUNT(gSizes);
+
+ if (FLAGS_strokeWidth >= 0) {
+ gSizes[0] = (SkScalar)FLAGS_strokeWidth;
+ sizes = 1;
+ }
+ SkRandom rand;
+ SkColor color = 0xFF000000;
+ U8CPU alpha = 0xFF;
+ SkPaint paint;
+ paint.setStrokeCap(SkPaint::kRound_Cap);
+ if (_type == KMaskShader) {
+ SkBitmap srcBM;
+ srcBM.allocN32Pixels(10, 1);
+ srcBM.eraseColor(0xFF00FF00);
+
+ SkShader* s;
+ s = SkShader::CreateBitmapShader(srcBM, SkShader::kClamp_TileMode,
+ SkShader::kClamp_TileMode);
+ paint.setShader(s)->unref();
+ }
+ for (int loop = 0; loop < loops; loop++) {
+ for (size_t i = 0; i < sizes; i++) {
+ switch (_type) {
+ case kMaskOpaque:
+ color = fColors[i];
+ alpha = 0xFF;
+ break;
+ case kMaskBlack:
+ alpha = 0xFF;
+ color = 0xFF000000;
+ break;
+ case kMaskColor:
+ color = fColors[i];
+ alpha = rand.nextU() & 255;
+ break;
+ case KMaskShader:
+ break;
+ }
+ paint.setStrokeWidth(gSizes[i]);
+ this->setupPaint(&paint);
+ paint.setColor(color);
+ paint.setAlpha(alpha);
+ canvas->drawPoints(fMode, N * 2, SkTCast<SkPoint*>(fRects), paint);
+ }
+ }
+ }
+ virtual const char* onGetName() { return fName; }
+private:
+ typedef RectBench INHERITED;
+ kMaskType _type;
+};
+
+
+DEF_BENCH( return SkNEW_ARGS(RectBench, (1)); )
+DEF_BENCH( return SkNEW_ARGS(RectBench, (1, 4)); )
+DEF_BENCH( return SkNEW_ARGS(RectBench, (3)); )
+DEF_BENCH( return SkNEW_ARGS(RectBench, (3, 4)); )
+DEF_BENCH( return SkNEW_ARGS(OvalBench, (1)); )
+DEF_BENCH( return SkNEW_ARGS(OvalBench, (3)); )
+DEF_BENCH( return SkNEW_ARGS(OvalBench, (1, 4)); )
+DEF_BENCH( return SkNEW_ARGS(OvalBench, (3, 4)); )
+DEF_BENCH( return SkNEW_ARGS(RRectBench, (1)); )
+DEF_BENCH( return SkNEW_ARGS(RRectBench, (1, 4)); )
+DEF_BENCH( return SkNEW_ARGS(RRectBench, (3)); )
+DEF_BENCH( return SkNEW_ARGS(RRectBench, (3, 4)); )
+DEF_BENCH( return SkNEW_ARGS(PointsBench, (SkCanvas::kPoints_PointMode, "points")); )
+DEF_BENCH( return SkNEW_ARGS(PointsBench, (SkCanvas::kLines_PointMode, "lines")); )
+DEF_BENCH( return SkNEW_ARGS(PointsBench, (SkCanvas::kPolygon_PointMode, "polygon")); )
+
+DEF_BENCH( return SkNEW_ARGS(SrcModeRectBench, ()); )
+
+DEF_BENCH( return SkNEW_ARGS(AARectBench, (false)); )
+DEF_BENCH( return SkNEW_ARGS(AARectBench, (true)); )
+
+/* init the blitmask bench
+ */
+DEF_BENCH( return SkNEW_ARGS(BlitMaskBench,
+ (SkCanvas::kPoints_PointMode,
+ BlitMaskBench::kMaskOpaque, "maskopaque")
+ ); )
+DEF_BENCH( return SkNEW_ARGS(BlitMaskBench,
+ (SkCanvas::kPoints_PointMode,
+ BlitMaskBench::kMaskBlack, "maskblack")
+ ); )
+DEF_BENCH( return SkNEW_ARGS(BlitMaskBench,
+ (SkCanvas::kPoints_PointMode,
+ BlitMaskBench::kMaskColor, "maskcolor")
+ ); )
+DEF_BENCH( return SkNEW_ARGS(BlitMaskBench,
+ (SkCanvas::kPoints_PointMode,
+ BlitMaskBench::KMaskShader, "maskshader")
+ ); )
diff --git a/chromium/third_party/skia/bench/RectanizerBench.cpp b/chromium/third_party/skia/bench/RectanizerBench.cpp
new file mode 100644
index 00000000000..286b681d386
--- /dev/null
+++ b/chromium/third_party/skia/bench/RectanizerBench.cpp
@@ -0,0 +1,138 @@
+/*
+* Copyright 2014 Google Inc.
+*
+* Use of this source code is governed by a BSD-style license that can be
+* found in the LICENSE file.
+*/
+
+#include "Benchmark.h"
+#include "SkRandom.h"
+#include "SkSize.h"
+#include "SkTDArray.h"
+
+#if SK_SUPPORT_GPU
+
+#include "GrRectanizer_pow2.h"
+#include "GrRectanizer_skyline.h"
+
+/**
+ * This bench exercises Ganesh' GrRectanizer classes. It exercises the following
+ * rectanizers:
+ * Pow2 Rectanizer
+ * Skyline Rectanizer
+ * in the following cases:
+ * random rects (e.g., pull-save-layers forward use case)
+ * random power of two rects
+ * small constant sized power of 2 rects (e.g., glyph cache use case)
+ */
+class RectanizerBench : public Benchmark {
+public:
+ static const int kWidth = 1024;
+ static const int kHeight = 1024;
+
+ enum RectanizerType {
+ kPow2_RectanizerType,
+ kSkyline_RectanizerType,
+ };
+
+ enum RectType {
+ kRand_RectType,
+ kRandPow2_RectType,
+ kSmallPow2_RectType
+ };
+
+ RectanizerBench(RectanizerType rectanizerType, RectType rectType)
+ : fName("rectanizer_")
+ , fRectanizerType(rectanizerType)
+ , fRectType(rectType) {
+
+ if (kPow2_RectanizerType == fRectanizerType) {
+ fName.append("pow2_");
+ } else {
+ SkASSERT(kSkyline_RectanizerType == fRectanizerType);
+ fName.append("skyline_");
+ }
+
+ if (kRand_RectType == fRectType) {
+ fName.append("rand");
+ } else if (kRandPow2_RectType == fRectType) {
+ fName.append("rand2");
+ } else {
+ SkASSERT(kSmallPow2_RectType == fRectType);
+ fName.append("sm2");
+ }
+ }
+
+protected:
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return kNonRendering_Backend == backend;
+ }
+
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+
+ virtual void onPreDraw() SK_OVERRIDE {
+ SkASSERT(NULL == fRectanizer.get());
+
+ if (kPow2_RectanizerType == fRectanizerType) {
+ fRectanizer.reset(SkNEW_ARGS(GrRectanizerPow2, (kWidth, kHeight)));
+ } else {
+ SkASSERT(kSkyline_RectanizerType == fRectanizerType);
+ fRectanizer.reset(SkNEW_ARGS(GrRectanizerSkyline, (kWidth, kHeight)));
+ }
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkRandom rand;
+ SkIPoint16 loc;
+ SkISize size;
+
+ for (int i = 0; i < loops; ++i) {
+ if (kRand_RectType == fRectType) {
+ size = SkISize::Make(rand.nextRangeU(1, kWidth / 2),
+ rand.nextRangeU(1, kHeight / 2));
+ } else if (kRandPow2_RectType == fRectType) {
+ size = SkISize::Make(GrNextPow2(rand.nextRangeU(1, kWidth / 2)),
+ GrNextPow2(rand.nextRangeU(1, kHeight / 2)));
+ } else {
+ SkASSERT(kSmallPow2_RectType == fRectType);
+ size = SkISize::Make(128, 128);
+ }
+
+ if (!fRectanizer->addRect(size.fWidth, size.fHeight, &loc)) {
+ // insert failed so clear out the rectanizer and give the
+ // current rect another try
+ fRectanizer->reset();
+ i--;
+ }
+ }
+
+ fRectanizer->reset();
+ }
+
+private:
+ SkString fName;
+ RectanizerType fRectanizerType;
+ RectType fRectType;
+ SkAutoTDelete<GrRectanizer> fRectanizer;
+
+ typedef Benchmark INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH(return new RectanizerBench(RectanizerBench::kPow2_RectanizerType,
+ RectanizerBench::kRand_RectType);)
+DEF_BENCH(return new RectanizerBench(RectanizerBench::kPow2_RectanizerType,
+ RectanizerBench::kRandPow2_RectType);)
+DEF_BENCH(return new RectanizerBench(RectanizerBench::kPow2_RectanizerType,
+ RectanizerBench::kSmallPow2_RectType);)
+DEF_BENCH(return new RectanizerBench(RectanizerBench::kSkyline_RectanizerType,
+ RectanizerBench::kRand_RectType);)
+DEF_BENCH(return new RectanizerBench(RectanizerBench::kSkyline_RectanizerType,
+ RectanizerBench::kRandPow2_RectType);)
+DEF_BENCH(return new RectanizerBench(RectanizerBench::kSkyline_RectanizerType,
+ RectanizerBench::kSmallPow2_RectType);)
+
+#endif
diff --git a/chromium/third_party/skia/bench/RectoriBench.cpp b/chromium/third_party/skia/bench/RectoriBench.cpp
new file mode 100644
index 00000000000..5c115115e3d
--- /dev/null
+++ b/chromium/third_party/skia/bench/RectoriBench.cpp
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkBlurMaskFilter.h"
+#include "SkCanvas.h"
+#include "SkLayerDrawLooper.h"
+#include "SkPaint.h"
+#include "SkRandom.h"
+
+// This bench replicates a problematic use case of a draw looper used
+// to create an inner blurred rect
+class RectoriBench : public Benchmark {
+public:
+ RectoriBench() {}
+
+protected:
+
+ virtual const char* onGetName() {
+ return "rectori";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkRandom Random;
+
+ for (int i = 0; i < loops; i++) {
+ SkScalar blurSigma = Random.nextRangeScalar(1.5f, 25.0f);
+ SkScalar size = Random.nextRangeScalar(20*blurSigma, 50*blurSigma);
+
+ SkScalar x = Random.nextRangeScalar(0.0f, W - size);
+ SkScalar y = Random.nextRangeScalar(0.0f, H - size);
+
+ SkRect inner = { x, y, x + size, y + size };
+
+ SkRect outer(inner);
+ // outer is always outset either 2x or 4x the blur radius (we go with 2x)
+ outer.outset(2*blurSigma, 2*blurSigma);
+
+ SkPath p;
+
+ p.addRect(outer);
+ p.addRect(inner);
+ p.setFillType(SkPath::kEvenOdd_FillType);
+
+ // This will be used to translate the normal draw outside the
+ // clip rect and translate the blurred version back inside
+ SkScalar translate = 2.0f * size;
+
+ SkPaint paint;
+ paint.setLooper(this->createLooper(-translate, blurSigma))->unref();
+ paint.setColor(0xff000000 | Random.nextU());
+ paint.setAntiAlias(true);
+
+ canvas->save();
+ // clip always equals inner rect so we get the inside blur
+ canvas->clipRect(inner);
+ canvas->translate(translate, 0);
+ canvas->drawPath(p, paint);
+ canvas->restore();
+ }
+ }
+
+private:
+ enum {
+ W = 640,
+ H = 480,
+ };
+
+ SkLayerDrawLooper* createLooper(SkScalar xOff, SkScalar sigma) {
+ SkLayerDrawLooper::Builder looperBuilder;
+
+ //-----------------------------------------------
+ SkLayerDrawLooper::LayerInfo info;
+
+ // TODO: add a color filter to better match what is seen in the wild
+ info.fPaintBits = /* SkLayerDrawLooper::kColorFilter_Bit |*/
+ SkLayerDrawLooper::kMaskFilter_Bit;
+ info.fColorMode = SkXfermode::kDst_Mode;
+ info.fOffset.set(xOff, 0);
+ info.fPostTranslate = false;
+
+ SkPaint* paint = looperBuilder.addLayer(info);
+
+ SkMaskFilter* mf = SkBlurMaskFilter::Create(kNormal_SkBlurStyle,
+ sigma,
+ SkBlurMaskFilter::kHighQuality_BlurFlag);
+ paint->setMaskFilter(mf)->unref();
+
+ //-----------------------------------------------
+ info.fPaintBits = 0;
+ info.fOffset.set(0, 0);
+
+ paint = looperBuilder.addLayer(info);
+ return looperBuilder.detachLooper();
+ }
+
+ typedef Benchmark INHERITED;
+};
+
+DEF_BENCH( return SkNEW_ARGS(RectoriBench, ()); )
diff --git a/chromium/third_party/skia/bench/RefCntBench.cpp b/chromium/third_party/skia/bench/RefCntBench.cpp
new file mode 100644
index 00000000000..351513b8318
--- /dev/null
+++ b/chromium/third_party/skia/bench/RefCntBench.cpp
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include <memory>
+#include "Benchmark.h"
+#include "SkRefCnt.h"
+#include "SkThread.h"
+#include "SkWeakRefCnt.h"
+
+enum {
+ M = 2
+};
+
+class RefCntBench_Stack : public Benchmark {
+public:
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+protected:
+ virtual const char* onGetName() {
+ return "ref_cnt_stack";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) {
+ for (int i = 0; i < loops; ++i) {
+ SkRefCnt ref;
+ for (int j = 0; j < M; ++j) {
+ ref.ref();
+ ref.unref();
+ }
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+class PlacedRefCnt : public SkRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(PlacedRefCnt)
+
+ PlacedRefCnt() : SkRefCnt() { }
+ void operator delete(void*) { }
+
+private:
+ typedef SkRefCnt INHERITED;
+};
+
+class RefCntBench_Heap : public Benchmark {
+public:
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+protected:
+ virtual const char* onGetName() {
+ return "ref_cnt_heap";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) {
+ char memory[sizeof(PlacedRefCnt)];
+ for (int i = 0; i < loops; ++i) {
+ PlacedRefCnt* ref = new (memory) PlacedRefCnt();
+ for (int j = 0; j < M; ++j) {
+ ref->ref();
+ ref->unref();
+ }
+ ref->unref();
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+class RefCntBench_New : public Benchmark {
+public:
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+protected:
+ virtual const char* onGetName() {
+ return "ref_cnt_new";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) {
+ for (int i = 0; i < loops; ++i) {
+ SkRefCnt* ref = new SkRefCnt();
+ for (int j = 0; j < M; ++j) {
+ ref->ref();
+ ref->unref();
+ }
+ ref->unref();
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class WeakRefCntBench_Stack : public Benchmark {
+public:
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+protected:
+ virtual const char* onGetName() {
+ return "ref_cnt_stack_weak";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) {
+ for (int i = 0; i < loops; ++i) {
+ SkWeakRefCnt ref;
+ for (int j = 0; j < M; ++j) {
+ ref.ref();
+ ref.unref();
+ }
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+class PlacedWeakRefCnt : public SkWeakRefCnt {
+public:
+ PlacedWeakRefCnt() : SkWeakRefCnt() { }
+ void operator delete(void*) { }
+};
+
+class WeakRefCntBench_Heap : public Benchmark {
+public:
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+protected:
+ virtual const char* onGetName() {
+ return "ref_cnt_heap_weak";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) {
+ char memory[sizeof(PlacedWeakRefCnt)];
+ for (int i = 0; i < loops; ++i) {
+ PlacedWeakRefCnt* ref = new (memory) PlacedWeakRefCnt();
+ for (int j = 0; j < M; ++j) {
+ ref->ref();
+ ref->unref();
+ }
+ ref->unref();
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+class WeakRefCntBench_New : public Benchmark {
+public:
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+protected:
+ virtual const char* onGetName() {
+ return "ref_cnt_new_weak";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) {
+ for (int i = 0; i < loops; ++i) {
+ SkWeakRefCnt* ref = new SkWeakRefCnt();
+ for (int j = 0; j < M; ++j) {
+ ref->ref();
+ ref->unref();
+ }
+ ref->unref();
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH( return new RefCntBench_Stack(); )
+DEF_BENCH( return new RefCntBench_Heap(); )
+DEF_BENCH( return new RefCntBench_New(); )
+
+DEF_BENCH( return new WeakRefCntBench_Stack(); )
+DEF_BENCH( return new WeakRefCntBench_Heap(); )
+DEF_BENCH( return new WeakRefCntBench_New(); )
diff --git a/chromium/third_party/skia/bench/RegionBench.cpp b/chromium/third_party/skia/bench/RegionBench.cpp
new file mode 100644
index 00000000000..b3722d4caa4
--- /dev/null
+++ b/chromium/third_party/skia/bench/RegionBench.cpp
@@ -0,0 +1,188 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "Benchmark.h"
+#include "SkRandom.h"
+#include "SkRegion.h"
+#include "SkString.h"
+
+static bool union_proc(SkRegion& a, SkRegion& b) {
+ SkRegion result;
+ return result.op(a, b, SkRegion::kUnion_Op);
+}
+
+static bool sect_proc(SkRegion& a, SkRegion& b) {
+ SkRegion result;
+ return result.op(a, b, SkRegion::kIntersect_Op);
+}
+
+static bool diff_proc(SkRegion& a, SkRegion& b) {
+ SkRegion result;
+ return result.op(a, b, SkRegion::kDifference_Op);
+}
+
+static bool diffrect_proc(SkRegion& a, SkRegion& b) {
+ SkRegion result;
+ return result.op(a, b.getBounds(), SkRegion::kDifference_Op);
+}
+
+static bool diffrectbig_proc(SkRegion& a, SkRegion& b) {
+ SkRegion result;
+ return result.op(a, a.getBounds(), SkRegion::kDifference_Op);
+}
+
+static bool containsrect_proc(SkRegion& a, SkRegion& b) {
+ SkIRect r = a.getBounds();
+ r.inset(r.width()/4, r.height()/4);
+ (void)a.contains(r);
+
+ r = b.getBounds();
+ r.inset(r.width()/4, r.height()/4);
+ return b.contains(r);
+}
+
+static bool sectsrgn_proc(SkRegion& a, SkRegion& b) {
+ return a.intersects(b);
+}
+
+static bool sectsrect_proc(SkRegion& a, SkRegion& b) {
+ SkIRect r = a.getBounds();
+ r.inset(r.width()/4, r.height()/4);
+ return a.intersects(r);
+}
+
+static bool containsxy_proc(SkRegion& a, SkRegion& b) {
+ const SkIRect& r = a.getBounds();
+ const int dx = r.width() / 8;
+ const int dy = r.height() / 8;
+ for (int y = r.fTop; y < r.fBottom; y += dy) {
+ for (int x = r.fLeft; x < r.fRight; x += dx) {
+ (void)a.contains(x, y);
+ }
+ }
+ return true;
+}
+
+class RegionBench : public Benchmark {
+public:
+ typedef bool (*Proc)(SkRegion& a, SkRegion& b);
+
+ SkRegion fA, fB;
+ Proc fProc;
+ SkString fName;
+
+ enum {
+ W = 1024,
+ H = 768,
+ };
+
+ SkIRect randrect(SkRandom& rand) {
+ int x = rand.nextU() % W;
+ int y = rand.nextU() % H;
+ int w = rand.nextU() % W;
+ int h = rand.nextU() % H;
+ return SkIRect::MakeXYWH(x, y, w >> 1, h >> 1);
+ }
+
+ RegionBench(int count, Proc proc, const char name[]) {
+ fProc = proc;
+ fName.printf("region_%s_%d", name, count);
+
+ SkRandom rand;
+ for (int i = 0; i < count; i++) {
+ fA.op(randrect(rand), SkRegion::kXOR_Op);
+ fB.op(randrect(rand), SkRegion::kXOR_Op);
+ }
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+protected:
+ virtual const char* onGetName() { return fName.c_str(); }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) {
+ Proc proc = fProc;
+ for (int i = 0; i < loops; ++i) {
+ proc(fA, fB);
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+class RectSectBench : public Benchmark {
+ enum {
+ N = 1000
+ };
+ SkRect fArray0[N];
+ SkRect fArray1[N];
+ SkString fName;
+ bool fNewWay;
+
+public:
+ static void RandRect(SkRect* r, SkRandom& rand) {
+ r->set(rand.nextSScalar1(), rand.nextSScalar1(),
+ rand.nextSScalar1(), rand.nextSScalar1());
+ r->sort();
+ }
+
+ RectSectBench(bool newWay) : fNewWay(newWay) {
+ fName.printf("rect_intersect_%s", newWay ? "new" : "old");
+
+ SkRandom rand;
+ for (int i = 0; i < N; i++) {
+ RandRect(&fArray0[i], rand);
+ RandRect(&fArray1[i], rand);
+ }
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+protected:
+ virtual const char* onGetName() { return fName.c_str(); }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) {
+ for (int i = 0; i < loops; ++i) {
+ if (fNewWay) {
+ for (int j = 0; j < N; ++j) {
+ SkRect r = fArray0[j];
+ r.intersect2(fArray1[j]);
+ }
+ } else {
+ for (int j = 0; j < N; ++j) {
+ SkRect r = fArray0[j];
+ r.intersect(fArray1[j]);
+ }
+ }
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+#define SMALL 16
+
+DEF_BENCH( return SkNEW_ARGS(RegionBench, (SMALL, union_proc, "union")); )
+DEF_BENCH( return SkNEW_ARGS(RegionBench, (SMALL, sect_proc, "intersect")); )
+DEF_BENCH( return SkNEW_ARGS(RegionBench, (SMALL, diff_proc, "difference")); )
+DEF_BENCH( return SkNEW_ARGS(RegionBench, (SMALL, diffrect_proc, "differencerect")); )
+DEF_BENCH( return SkNEW_ARGS(RegionBench, (SMALL, diffrectbig_proc, "differencerectbig")); )
+DEF_BENCH( return SkNEW_ARGS(RegionBench, (SMALL, containsrect_proc, "containsrect")); )
+DEF_BENCH( return SkNEW_ARGS(RegionBench, (SMALL, sectsrgn_proc, "intersectsrgn")); )
+DEF_BENCH( return SkNEW_ARGS(RegionBench, (SMALL, sectsrect_proc, "intersectsrect")); )
+DEF_BENCH( return SkNEW_ARGS(RegionBench, (SMALL, containsxy_proc, "containsxy")); )
+
+DEF_BENCH( return SkNEW_ARGS(RectSectBench, (false)); )
+DEF_BENCH( return SkNEW_ARGS(RectSectBench, (true)); )
diff --git a/chromium/third_party/skia/bench/RegionContainBench.cpp b/chromium/third_party/skia/bench/RegionContainBench.cpp
new file mode 100644
index 00000000000..a47ab3395f8
--- /dev/null
+++ b/chromium/third_party/skia/bench/RegionContainBench.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkRandom.h"
+#include "SkRegion.h"
+#include "SkString.h"
+
+static bool sect_proc(SkRegion& a, SkRegion& b) {
+ SkRegion result;
+ return result.op(a, b, SkRegion::kIntersect_Op);
+}
+
+class RegionContainBench : public Benchmark {
+public:
+ typedef bool (*Proc)(SkRegion& a, SkRegion& b);
+ SkRegion fA, fB;
+ Proc fProc;
+ SkString fName;
+
+ enum {
+ W = 200,
+ H = 200,
+ COUNT = 10,
+ };
+
+ SkIRect randrect(SkRandom& rand, int i) {
+ int w = rand.nextU() % W;
+ return SkIRect::MakeXYWH(0, i*H/COUNT, w, H/COUNT);
+ }
+
+ RegionContainBench(Proc proc, const char name[]) {
+ fProc = proc;
+ fName.printf("region_contains_%s", name);
+
+ SkRandom rand;
+ for (int i = 0; i < COUNT; i++) {
+ fA.op(randrect(rand, i), SkRegion::kXOR_Op);
+ }
+
+ fB.setRect(0, 0, H, W);
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+protected:
+ virtual const char* onGetName() { return fName.c_str(); }
+
+ virtual void onDraw(const int loops, SkCanvas*) {
+ Proc proc = fProc;
+
+ for (int i = 0; i < loops; ++i) {
+ proc(fA, fB);
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+DEF_BENCH( return SkNEW_ARGS(RegionContainBench, (sect_proc, "sect")); )
diff --git a/chromium/third_party/skia/bench/RepeatTileBench.cpp b/chromium/third_party/skia/bench/RepeatTileBench.cpp
new file mode 100644
index 00000000000..cf29b6a460e
--- /dev/null
+++ b/chromium/third_party/skia/bench/RepeatTileBench.cpp
@@ -0,0 +1,146 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "Benchmark.h"
+#include "SkBitmap.h"
+#include "SkCanvas.h"
+#include "SkColorPriv.h"
+#include "SkPaint.h"
+#include "SkShader.h"
+#include "SkString.h"
+#include "sk_tool_utils.h"
+
+static void draw_into_bitmap(const SkBitmap& bm) {
+ const int w = bm.width();
+ const int h = bm.height();
+
+ SkCanvas canvas(bm);
+ SkPaint p;
+ p.setAntiAlias(true);
+ p.setColor(SK_ColorRED);
+ canvas.drawCircle(SkIntToScalar(w)/2, SkIntToScalar(h)/2,
+ SkIntToScalar(SkMin32(w, h))*3/8, p);
+
+ SkRect r;
+ r.set(0, 0, SkIntToScalar(w), SkIntToScalar(h));
+ p.setStyle(SkPaint::kStroke_Style);
+ p.setStrokeWidth(SkIntToScalar(4));
+ p.setColor(SK_ColorBLUE);
+ canvas.drawRect(r, p);
+}
+
+static int conv_6_to_byte(int x) {
+ return x * 0xFF / 5;
+}
+
+static int conv_byte_to_6(int x) {
+ return x * 5 / 255;
+}
+
+static uint8_t compute_666_index(SkPMColor c) {
+ int r = SkGetPackedR32(c);
+ int g = SkGetPackedG32(c);
+ int b = SkGetPackedB32(c);
+
+ return conv_byte_to_6(r) * 36 + conv_byte_to_6(g) * 6 + conv_byte_to_6(b);
+}
+
+static void convert_to_index666(const SkBitmap& src, SkBitmap* dst) {
+ SkPMColor storage[216];
+ SkPMColor* colors = storage;
+ // rrr ggg bbb
+ for (int r = 0; r < 6; r++) {
+ int rr = conv_6_to_byte(r);
+ for (int g = 0; g < 6; g++) {
+ int gg = conv_6_to_byte(g);
+ for (int b = 0; b < 6; b++) {
+ int bb = conv_6_to_byte(b);
+ *colors++ = SkPreMultiplyARGB(0xFF, rr, gg, bb);
+ }
+ }
+ }
+ SkColorTable* ctable = new SkColorTable(storage, 216, kOpaque_SkAlphaType);
+ dst->allocPixels(SkImageInfo::Make(src.width(), src.height(),
+ kIndex_8_SkColorType, kOpaque_SkAlphaType),
+ NULL, ctable);
+ ctable->unref();
+
+ SkAutoLockPixels alps(src);
+ SkAutoLockPixels alpd(*dst);
+
+ for (int y = 0; y < src.height(); y++) {
+ const SkPMColor* srcP = src.getAddr32(0, y);
+ uint8_t* dstP = dst->getAddr8(0, y);
+ for (int x = src.width() - 1; x >= 0; --x) {
+ *dstP++ = compute_666_index(*srcP++);
+ }
+ }
+}
+
+class RepeatTileBench : public Benchmark {
+ const SkColorType fColorType;
+ const SkAlphaType fAlphaType;
+ SkPaint fPaint;
+ SkString fName;
+ SkBitmap fBitmap;
+public:
+ RepeatTileBench(SkColorType ct, SkAlphaType at = kPremul_SkAlphaType)
+ : fColorType(ct), fAlphaType(at)
+ {
+ const int w = 50;
+ const int h = 50;
+
+ if (kIndex_8_SkColorType == ct) {
+ fBitmap.setInfo(SkImageInfo::MakeN32(w, h, at));
+ } else {
+ fBitmap.setInfo(SkImageInfo::Make(w, h, ct, at));
+ }
+ fName.printf("repeatTile_%s_%c",
+ sk_tool_utils::colortype_name(ct), kOpaque_SkAlphaType == at ? 'X' : 'A');
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+
+ virtual void onPreDraw() SK_OVERRIDE {
+ fBitmap.allocPixels();
+ fBitmap.eraseColor(kOpaque_SkAlphaType == fAlphaType ? SK_ColorWHITE : 0);
+
+ draw_into_bitmap(fBitmap);
+
+ if (kIndex_8_SkColorType == fColorType) {
+ SkBitmap tmp;
+ convert_to_index666(fBitmap, &tmp);
+ fBitmap = tmp;
+ }
+
+ SkShader* s = SkShader::CreateBitmapShader(fBitmap,
+ SkShader::kRepeat_TileMode,
+ SkShader::kRepeat_TileMode);
+ fPaint.setShader(s)->unref();
+ }
+
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkPaint paint(fPaint);
+ this->setupPaint(&paint);
+
+ for (int i = 0; i < loops; i++) {
+ canvas->drawPaint(paint);
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+DEF_BENCH(return new RepeatTileBench(kN32_SkColorType, kOpaque_SkAlphaType))
+DEF_BENCH(return new RepeatTileBench(kN32_SkColorType, kPremul_SkAlphaType))
+DEF_BENCH(return new RepeatTileBench(kRGB_565_SkColorType, kOpaque_SkAlphaType))
+DEF_BENCH(return new RepeatTileBench(kIndex_8_SkColorType, kPremul_SkAlphaType))
diff --git a/chromium/third_party/skia/bench/ResultsWriter.cpp b/chromium/third_party/skia/bench/ResultsWriter.cpp
new file mode 100644
index 00000000000..08f11c190fb
--- /dev/null
+++ b/chromium/third_party/skia/bench/ResultsWriter.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Helper functions for result writing operations.
+ */
+
+#include "ResultsWriter.h"
+
+Json::Value* SkFindNamedNode(Json::Value* root, const char name[]) {
+ Json::Value* search_results = NULL;
+ for(Json::Value::iterator iter = root->begin();
+ iter!= root->end(); ++iter) {
+ if(SkString(name).equals((*iter)["name"].asCString())) {
+ search_results = &(*iter);
+ break;
+ }
+ }
+
+ if(search_results != NULL) {
+ return search_results;
+ } else {
+ Json::Value* new_val = &(root->append(Json::Value()));
+ (*new_val)["name"] = name;
+ return new_val;
+ }
+}
+
diff --git a/chromium/third_party/skia/bench/ResultsWriter.h b/chromium/third_party/skia/bench/ResultsWriter.h
new file mode 100644
index 00000000000..ed10afa3caa
--- /dev/null
+++ b/chromium/third_party/skia/bench/ResultsWriter.h
@@ -0,0 +1,198 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Classes for writing out bench results in various formats.
+ */
+
+#ifndef SkResultsWriter_DEFINED
+#define SkResultsWriter_DEFINED
+
+#include "BenchLogger.h"
+#include "SkJSONCPP.h"
+#include "SkStream.h"
+#include "SkString.h"
+#include "SkTArray.h"
+#include "SkTypes.h"
+
+/**
+ * Base class for writing out the bench results.
+ *
+ * TODO(jcgregorio) Add info if tests fail to converge?
+ */
+class ResultsWriter : SkNoncopyable {
+public:
+ virtual ~ResultsWriter() {};
+
+ // Records one option set for this run. All options must be set before
+ // calling bench().
+ virtual void option(const char name[], const char value[]) = 0;
+
+ // Denotes the start of a specific benchmark. Once bench is called,
+ // then config and timer can be called multiple times to record runs.
+ virtual void bench(const char name[], int32_t x, int32_t y) = 0;
+
+ // Records the specific configuration a bench is run under, such as "8888".
+ virtual void config(const char name[]) = 0;
+
+ // Records a single test metric.
+ virtual void timer(const char name[], double ms) = 0;
+
+ // Call when all results are finished.
+ virtual void end() = 0;
+};
+
+/**
+ * This ResultsWriter handles writing out the human readable format of the
+ * bench results.
+ */
+class LoggerResultsWriter : public ResultsWriter {
+public:
+ explicit LoggerResultsWriter(BenchLogger& logger, const char* timeFormat)
+ : fLogger(logger)
+ , fTimeFormat(timeFormat) {
+ fLogger.logProgress("skia bench:");
+ }
+ virtual void option(const char name[], const char value[]) {
+ fLogger.logProgress(SkStringPrintf(" %s=%s", name, value));
+ }
+ virtual void bench(const char name[], int32_t x, int32_t y) {
+ fLogger.logProgress(SkStringPrintf(
+ "\nrunning bench [%3d %3d] %40s", x, y, name));
+ }
+ virtual void config(const char name[]) {
+ fLogger.logProgress(SkStringPrintf(" %s:", name));
+ }
+ virtual void timer(const char name[], double ms) {
+ fLogger.logProgress(SkStringPrintf(" %s = ", name));
+ fLogger.logProgress(SkStringPrintf(fTimeFormat, ms));
+ }
+ virtual void end() {
+ fLogger.logProgress("\n");
+ }
+private:
+ BenchLogger& fLogger;
+ const char* fTimeFormat;
+};
+
+/**
+ * This ResultsWriter handles writing out the results in JSON.
+ *
+ * The output looks like (except compressed to a single line):
+ *
+ * {
+ * "options" : {
+ * "alpha" : "0xFF",
+ * "scale" : "0",
+ * ...
+ * "system" : "UNIX"
+ * },
+ * "results" : [
+ * {
+ * "name" : "Xfermode_Luminosity_640_480",
+ * "results" : [
+ * {
+ * "name": "565",
+ * "cmsecs" : 143.188128906250,
+ * "msecs" : 143.835957031250
+ * },
+ * ...
+ */
+
+Json::Value* SkFindNamedNode(Json::Value* root, const char name[]);
+class JSONResultsWriter : public ResultsWriter {
+public:
+ explicit JSONResultsWriter(const char filename[])
+ : fFilename(filename)
+ , fRoot()
+ , fResults(fRoot["results"])
+ , fBench(NULL)
+ , fConfig(NULL) {
+ }
+ virtual void option(const char name[], const char value[]) {
+ fRoot["options"][name] = value;
+ }
+ virtual void bench(const char name[], int32_t x, int32_t y) {
+ SkString sk_name(name);
+ sk_name.append("_");
+ sk_name.appendS32(x);
+ sk_name.append("_");
+ sk_name.appendS32(y);
+ Json::Value* bench_node = SkFindNamedNode(&fResults, sk_name.c_str());
+ fBench = &(*bench_node)["results"];
+ }
+ virtual void config(const char name[]) {
+ SkASSERT(NULL != fBench);
+ fConfig = SkFindNamedNode(fBench, name);
+ }
+ virtual void timer(const char name[], double ms) {
+ SkASSERT(NULL != fConfig);
+ (*fConfig)[name] = ms;
+ }
+ virtual void end() {
+ SkFILEWStream stream(fFilename.c_str());
+ stream.writeText(Json::FastWriter().write(fRoot).c_str());
+ stream.flush();
+ }
+private:
+
+ SkString fFilename;
+ Json::Value fRoot;
+ Json::Value& fResults;
+ Json::Value* fBench;
+ Json::Value* fConfig;
+};
+
+/**
+ * This ResultsWriter writes out to multiple ResultsWriters.
+ */
+class MultiResultsWriter : public ResultsWriter {
+public:
+ MultiResultsWriter() : writers() {
+ };
+ void add(ResultsWriter* writer) {
+ writers.push_back(writer);
+ }
+ virtual void option(const char name[], const char value[]) {
+ for (int i = 0; i < writers.count(); ++i) {
+ writers[i]->option(name, value);
+ }
+ }
+ virtual void bench(const char name[], int32_t x, int32_t y) {
+ for (int i = 0; i < writers.count(); ++i) {
+ writers[i]->bench(name, x, y);
+ }
+ }
+ virtual void config(const char name[]) {
+ for (int i = 0; i < writers.count(); ++i) {
+ writers[i]->config(name);
+ }
+ }
+ virtual void timer(const char name[], double ms) {
+ for (int i = 0; i < writers.count(); ++i) {
+ writers[i]->timer(name, ms);
+ }
+ }
+ virtual void end() {
+ for (int i = 0; i < writers.count(); ++i) {
+ writers[i]->end();
+ }
+ }
+private:
+ SkTArray<ResultsWriter *> writers;
+};
+
+/**
+ * Calls the end() method of T on destruction.
+ */
+template <typename T> class CallEnd : SkNoncopyable {
+public:
+ CallEnd(T& obj) : fObj(obj) {}
+ ~CallEnd() { fObj.end(); }
+private:
+ T& fObj;
+};
+
+#endif
diff --git a/chromium/third_party/skia/bench/ScalarBench.cpp b/chromium/third_party/skia/bench/ScalarBench.cpp
new file mode 100644
index 00000000000..e09fa7533b3
--- /dev/null
+++ b/chromium/third_party/skia/bench/ScalarBench.cpp
@@ -0,0 +1,168 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "Benchmark.h"
+#include "SkFloatBits.h"
+#include "SkRandom.h"
+#include "SkRect.h"
+#include "SkString.h"
+
+class ScalarBench : public Benchmark {
+ SkString fName;
+public:
+ ScalarBench(const char name[]) {
+ fName.printf("scalar_%s", name);
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+ virtual void performTest() = 0;
+
+protected:
+ virtual int mulLoopCount() const { return 1; }
+
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) {
+ for (int i = 0; i < loops; i++) {
+ this->performTest();
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+// having unknown values in our arrays can throw off the timing a lot, perhaps
+// handling NaN values is a lot slower. Anyway, this guy is just meant to put
+// reasonable values in our arrays.
+template <typename T> void init9(T array[9]) {
+ SkRandom rand;
+ for (int i = 0; i < 9; i++) {
+ array[i] = rand.nextSScalar1();
+ }
+}
+
+class FloatComparisonBench : public ScalarBench {
+public:
+ FloatComparisonBench() : INHERITED("compare_float") {
+ init9(fArray);
+ }
+protected:
+ virtual int mulLoopCount() const { return 4; }
+ virtual void performTest() {
+ // xoring into a volatile prevents the compiler from optimizing these checks away.
+ volatile bool junk = false;
+ junk ^= (fArray[6] != 0.0f || fArray[7] != 0.0f || fArray[8] != 1.0f);
+ junk ^= (fArray[2] != 0.0f || fArray[5] != 0.0f);
+ }
+private:
+ float fArray[9];
+ typedef ScalarBench INHERITED;
+};
+
+class ForcedIntComparisonBench : public ScalarBench {
+public:
+ ForcedIntComparisonBench()
+ : INHERITED("compare_forced_int") {
+ init9(fArray);
+ }
+protected:
+ virtual int mulLoopCount() const { return 4; }
+ virtual void performTest() {
+ // xoring into a volatile prevents the compiler from optimizing these checks away.
+ volatile int32_t junk = 0;
+ junk ^= (SkScalarAs2sCompliment(fArray[6]) |
+ SkScalarAs2sCompliment(fArray[7]) |
+ (SkScalarAs2sCompliment(fArray[8]) - kPersp1Int));
+ junk ^= (SkScalarAs2sCompliment(fArray[2]) |
+ SkScalarAs2sCompliment(fArray[5]));
+ }
+private:
+ static const int32_t kPersp1Int = 0x3f800000;
+ SkScalar fArray[9];
+ typedef ScalarBench INHERITED;
+};
+
+class IsFiniteScalarBench : public ScalarBench {
+public:
+ IsFiniteScalarBench() : INHERITED("isfinite") {
+ SkRandom rand;
+ for (size_t i = 0; i < ARRAY_N; ++i) {
+ fArray[i] = rand.nextSScalar1();
+ }
+ }
+protected:
+ virtual int mulLoopCount() const { return 1; }
+ virtual void performTest() SK_OVERRIDE {
+ int sum = 0;
+ for (size_t i = 0; i < ARRAY_N; ++i) {
+ // We pass -fArray[i], so the compiler can't cheat and treat the
+ // value as an int (even though we tell it that it is a float)
+ sum += SkScalarIsFinite(-fArray[i]);
+ }
+ // we do this so the compiler won't optimize our loop away...
+ this->doSomething(fArray, sum);
+ }
+
+ virtual void doSomething(SkScalar array[], int sum) {}
+private:
+ enum {
+ ARRAY_N = 64
+ };
+ SkScalar fArray[ARRAY_N];
+
+ typedef ScalarBench INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class RectBoundsBench : public Benchmark {
+ enum {
+ PTS = 100,
+ };
+ SkPoint fPts[PTS];
+
+public:
+ RectBoundsBench() {
+ SkRandom rand;
+ for (int i = 0; i < PTS; ++i) {
+ fPts[i].fX = rand.nextSScalar1();
+ fPts[i].fY = rand.nextSScalar1();
+ }
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return "rect_bounds";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkRect r;
+ for (int i = 0; i < loops; ++i) {
+ r.set(fPts, PTS);
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH( return new FloatComparisonBench(); )
+DEF_BENCH( return new ForcedIntComparisonBench(); )
+DEF_BENCH( return new RectBoundsBench(); )
+DEF_BENCH( return new IsFiniteScalarBench(); )
diff --git a/chromium/third_party/skia/bench/ShaderMaskBench.cpp b/chromium/third_party/skia/bench/ShaderMaskBench.cpp
new file mode 100644
index 00000000000..aa3dadff2ff
--- /dev/null
+++ b/chromium/third_party/skia/bench/ShaderMaskBench.cpp
@@ -0,0 +1,98 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "Benchmark.h"
+#include "SkCanvas.h"
+#include "SkColorShader.h"
+#include "SkFontHost.h"
+#include "SkPaint.h"
+#include "SkRandom.h"
+#include "SkString.h"
+#include "SkTemplates.h"
+
+#define STR "Hamburgefons"
+
+enum FontQuality {
+ kBW,
+ kAA,
+ kLCD
+};
+
+static const char* fontQualityName(const SkPaint& paint) {
+ if (!paint.isAntiAlias()) {
+ return "BW";
+ }
+ if (paint.isLCDRenderText()) {
+ return "LCD";
+ }
+ return "AA";
+}
+
+class ShaderMaskBench : public Benchmark {
+ SkPaint fPaint;
+ SkString fText;
+ SkString fName;
+ FontQuality fFQ;
+public:
+ ShaderMaskBench(bool isOpaque, FontQuality fq) {
+ fFQ = fq;
+ fText.set(STR);
+
+ fPaint.setAntiAlias(kBW != fq);
+ fPaint.setLCDRenderText(kLCD == fq);
+ fPaint.setShader(new SkColorShader(isOpaque ? 0xFFFFFFFF : 0x80808080))->unref();
+ }
+
+protected:
+ virtual const char* onGetName() {
+ fName.printf("shadermask");
+ fName.appendf("_%s", fontQualityName(fPaint));
+ fName.appendf("_%02X", fPaint.getAlpha());
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) {
+ const SkIPoint dim = this->getSize();
+ SkRandom rand;
+
+ SkPaint paint(fPaint);
+ this->setupPaint(&paint);
+ // explicitly need these
+ paint.setAlpha(fPaint.getAlpha());
+ paint.setAntiAlias(kBW != fFQ);
+ paint.setLCDRenderText(kLCD == fFQ);
+
+ const SkScalar x0 = SkIntToScalar(-10);
+ const SkScalar y0 = SkIntToScalar(-10);
+
+ paint.setTextSize(SkIntToScalar(12));
+ for (int i = 0; i < loops; i++) {
+ SkScalar x = x0 + rand.nextUScalar1() * dim.fX;
+ SkScalar y = y0 + rand.nextUScalar1() * dim.fY;
+ canvas->drawText(fText.c_str(), fText.size(), x, y, paint);
+ }
+
+ paint.setTextSize(SkIntToScalar(48));
+ for (int i = 0; i < loops / 4 ; i++) {
+ SkScalar x = x0 + rand.nextUScalar1() * dim.fX;
+ SkScalar y = y0 + rand.nextUScalar1() * dim.fY;
+ canvas->drawText(fText.c_str(), fText.size(), x, y, paint);
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH( return new ShaderMaskBench(true, kBW); )
+DEF_BENCH( return new ShaderMaskBench(false, kBW); )
+DEF_BENCH( return new ShaderMaskBench(true, kAA); )
+DEF_BENCH( return new ShaderMaskBench(false, kAA); )
+DEF_BENCH( return new ShaderMaskBench(true, kLCD); )
+DEF_BENCH( return new ShaderMaskBench(false, kLCD); )
diff --git a/chromium/third_party/skia/bench/SkipZeroesBench.cpp b/chromium/third_party/skia/bench/SkipZeroesBench.cpp
new file mode 100644
index 00000000000..30d9377a5ef
--- /dev/null
+++ b/chromium/third_party/skia/bench/SkipZeroesBench.cpp
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "Resources.h"
+#include "SkBitmap.h"
+#include "SkData.h"
+#include "SkForceLinking.h"
+#include "SkImageDecoder.h"
+#include "SkOSFile.h"
+#include "SkStream.h"
+#include "SkString.h"
+
+__SK_FORCE_IMAGE_DECODER_LINKING;
+
+class SkCanvas;
+
+class SkipZeroesBench : public Benchmark {
+public:
+ SkipZeroesBench(const char* filename, bool skipZeroes)
+ : fName("SkipZeroes_")
+ , fDecoder(NULL)
+ , fFilename(filename)
+ , fStream()
+ , fSkipZeroes(skipZeroes)
+ , fValid(false) {
+ fName.append(filename);
+ if (skipZeroes) {
+ fName.append("_skip_zeroes");
+ } else {
+ fName.append("_write_zeroes");
+ }
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+
+ virtual void onPreDraw() SK_OVERRIDE {
+ SkString resourcePath = GetResourcePath();
+ if (resourcePath.isEmpty()) {
+ fValid = false;
+ return;
+ }
+
+ SkString fullPath = SkOSPath::SkPathJoin(resourcePath.c_str(),
+ fFilename.c_str());
+ SkFILEStream fileStream(fullPath.c_str());
+ fValid = fileStream.isValid() && fileStream.getLength() > 0;
+ if (fValid) {
+ const size_t size = fileStream.getLength();
+ void* data = sk_malloc_throw(size);
+ if (fileStream.read(data, size) < size) {
+ fValid = false;
+ } else {
+ SkAutoTUnref<SkData> skdata(SkData::NewFromMalloc(data, size));
+ fStream.setData(skdata.get());
+ fDecoder.reset(SkImageDecoder::Factory(&fStream));
+ if (fDecoder.get()) {
+ fDecoder->setSkipWritingZeroes(fSkipZeroes);
+ } else {
+ fValid = false;
+ }
+ }
+ }
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
+ if (!fValid) {
+#ifdef SK_DEBUG
+ SkDebugf("stream was invalid: %s\n", fFilename.c_str());
+#endif
+ return;
+ }
+ // Decode a bunch of times
+ SkBitmap bm;
+ for (int i = 0; i < loops; ++i) {
+ SkDEBUGCODE(bool success =) fDecoder->decode(&fStream, &bm,
+ SkImageDecoder::kDecodePixels_Mode);
+#ifdef SK_DEBUG
+ if (!success) {
+ SkDebugf("failed to decode %s\n", fFilename.c_str());
+ return;
+ }
+#endif
+ SkDEBUGCODE(success =) fStream.rewind();
+#ifdef SK_DEBUG
+ if (!success) {
+ SkDebugf("failed to rewind %s\n", fFilename.c_str());
+ return;
+ }
+#endif
+ }
+ }
+
+private:
+ SkString fName;
+ SkAutoTDelete<SkImageDecoder> fDecoder;
+ const SkString fFilename;
+ SkMemoryStream fStream;
+ bool fSkipZeroes;
+ bool fValid;
+
+ typedef Benchmark INHERITED;
+};
+
+// Enable the true version once the feature is checked in.
+DEF_BENCH( return SkNEW_ARGS(SkipZeroesBench, ("arrow.png", true)));
+DEF_BENCH( return SkNEW_ARGS(SkipZeroesBench, ("arrow.png", false)));
diff --git a/chromium/third_party/skia/bench/SortBench.cpp b/chromium/third_party/skia/bench/SortBench.cpp
new file mode 100644
index 00000000000..a7e8c2cd0bc
--- /dev/null
+++ b/chromium/third_party/skia/bench/SortBench.cpp
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkRandom.h"
+#include "SkString.h"
+#include "SkTSort.h"
+
+static const int N = 1000;
+
+static void rand_proc(int array[N]) {
+ SkRandom rand;
+ for (int i = 0; i < N; ++i) {
+ array[i] = rand.nextS();
+ }
+}
+
+static void randN_proc(int array[N]) {
+ SkRandom rand;
+ int mod = N / 10;
+ for (int i = 0; i < N; ++i) {
+ array[i] = rand.nextU() % mod;
+ }
+}
+
+static void forward_proc(int array[N]) {
+ for (int i = 0; i < N; ++i) {
+ array[i] = i;
+ }
+}
+
+static void backward_proc(int array[N]) {
+ for (int i = 0; i < N; ++i) {
+ array[i] = -i;
+ }
+}
+
+static void same_proc(int array[N]) {
+ for (int i = 0; i < N; ++i) {
+ array[i] = N;
+ }
+}
+
+typedef void (*SortProc)(int array[N]);
+
+enum Type {
+ kRand, kRandN, kFore, kBack, kSame
+};
+
+static const struct {
+ const char* fName;
+ SortProc fProc;
+} gRec[] = {
+ { "rand", rand_proc },
+ { "rand10", randN_proc },
+ { "forward", forward_proc },
+ { "backward", backward_proc },
+ { "repeated", same_proc },
+};
+
+static void skqsort_sort(int array[N]) {
+ // End is inclusive for SkTQSort!
+ SkTQSort<int>(array, array + N - 1);
+}
+
+static void skheap_sort(int array[N]) {
+ SkTHeapSort<int>(array, N);
+}
+
+extern "C" {
+ static int int_compare(const void* a, const void* b) {
+ const int ai = *(const int*)a;
+ const int bi = *(const int*)b;
+ return ai < bi ? -1 : (ai > bi);
+ }
+}
+
+static void qsort_sort(int array[N]) {
+ qsort(array, N, sizeof(int), int_compare);
+}
+
+enum SortType {
+ kSKQSort, kSKHeap, kQSort
+};
+
+static const struct {
+ const char* fName;
+ SortProc fProc;
+} gSorts[] = {
+ { "skqsort", skqsort_sort },
+ { "skheap", skheap_sort },
+ { "qsort", qsort_sort },
+};
+
+class SortBench : public Benchmark {
+ SkString fName;
+ const Type fType;
+ const SortProc fSortProc;
+ SkAutoTMalloc<int> fUnsorted;
+
+public:
+ SortBench(Type t, SortType s) : fType(t), fSortProc(gSorts[s].fProc) {
+ fName.printf("sort_%s_%s", gSorts[s].fName, gRec[t].fName);
+ }
+
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+
+ // Delayed initialization only done if onDraw will be called.
+ virtual void onPreDraw() SK_OVERRIDE {
+ fUnsorted.reset(N);
+ gRec[fType].fProc(fUnsorted.get());
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
+ SkAutoTMalloc<int> sorted(N);
+ for (int i = 0; i < loops; i++) {
+ memcpy(sorted.get(), fUnsorted.get(), N*sizeof(int));
+ fSortProc(sorted.get());
+#ifdef SK_DEBUG
+ for (int j = 1; j < N; ++j) {
+ SkASSERT(sorted[j - 1] <= sorted[j]);
+ }
+#endif
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+static Benchmark* NewSkQSort(Type t) {
+ return new SortBench(t, kSKQSort);
+}
+static Benchmark* NewSkHeap(Type t) {
+ return new SortBench(t, kSKHeap);
+}
+static Benchmark* NewQSort(Type t) {
+ return new SortBench(t, kQSort);
+}
+
+DEF_BENCH( return NewSkQSort(kRand); )
+DEF_BENCH( return NewSkHeap(kRand); )
+DEF_BENCH( return NewQSort(kRand); )
+
+DEF_BENCH( return NewSkQSort(kRandN); )
+DEF_BENCH( return NewSkHeap(kRandN); )
+DEF_BENCH( return NewQSort(kRandN); )
+
+DEF_BENCH( return NewSkQSort(kFore); )
+DEF_BENCH( return NewSkHeap(kFore); )
+DEF_BENCH( return NewQSort(kFore); )
+
+DEF_BENCH( return NewSkQSort(kBack); )
+DEF_BENCH( return NewSkHeap(kBack); )
+DEF_BENCH( return NewQSort(kBack); )
+
+DEF_BENCH( return NewSkQSort(kSame); )
+DEF_BENCH( return NewSkHeap(kSame); )
+DEF_BENCH( return NewQSort(kSame); )
diff --git a/chromium/third_party/skia/bench/StackBench.cpp b/chromium/third_party/skia/bench/StackBench.cpp
new file mode 100644
index 00000000000..3b41cb65ceb
--- /dev/null
+++ b/chromium/third_party/skia/bench/StackBench.cpp
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkRandom.h"
+
+#include "SkChunkAlloc.h"
+#include "SkDeque.h"
+#include "SkTArray.h"
+#include "SkTDArray.h"
+
+// This file has several benchmarks using various data structures to do stack-like things:
+// - push
+// - push, immediately pop
+// - push many, pop all of them
+// - serial access
+// - random access
+// When a data structure doesn't suppport an operation efficiently, we leave that combination out.
+// Where possible we hint to the data structure to allocate in 4K pages.
+//
+// These benchmarks may help you decide which data structure to use for a dynamically allocated
+// ordered list of allocations that grows on one end.
+//
+// Current overall winner (01/2014): SkTDArray.
+// It wins every benchmark on every machine I tried (Desktop, Nexus S, Laptop).
+
+template <typename Impl>
+struct StackBench : public Benchmark {
+ virtual bool isSuitableFor(Backend b) SK_OVERRIDE { return b == kNonRendering_Backend; }
+ virtual const char* onGetName() SK_OVERRIDE { return Impl::kName; }
+ virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE { Impl::bench(loops); }
+};
+
+#define BENCH(name) \
+ struct name { static const char* const kName; static void bench(int); }; \
+ const char* const name::kName = #name; \
+ DEF_BENCH(return new StackBench<name>();) \
+ void name::bench(int loops)
+
+static const int K = 2049;
+
+// Add K items, then iterate through them serially many times.
+
+BENCH(Deque_Serial) {
+ SkDeque s(sizeof(int), 1024);
+ for (int i = 0; i < K; i++) *(int*)s.push_back() = i;
+
+ volatile int junk = 0;
+ for (int j = 0; j < loops; j++) {
+ SkDeque::Iter it(s, SkDeque::Iter::kFront_IterStart);
+ while(void* p = it.next()) {
+ junk += *(int*)p;
+ }
+ }
+}
+
+BENCH(TArray_Serial) {
+ SkTArray<int, true> s;
+ for (int i = 0; i < K; i++) s.push_back(i);
+
+ volatile int junk = 0;
+ for (int j = 0; j < loops; j++) {
+ for (int i = 0; i < s.count(); i++) junk += s[i];
+ }
+}
+
+BENCH(TDArray_Serial) {
+ SkTDArray<int> s;
+ for (int i = 0; i < K; i++) s.push(i);
+
+ volatile int junk = 0;
+ for (int j = 0; j < loops; j++) {
+ for (int i = 0; i < s.count(); i++) junk += s[i];
+ }
+}
+
+// Add K items, then randomly access them many times.
+
+BENCH(TArray_RandomAccess) {
+ SkTArray<int, true> s;
+ for (int i = 0; i < K; i++) s.push_back(i);
+
+ SkRandom rand;
+ volatile int junk = 0;
+ for (int i = 0; i < K*loops; i++) {
+ junk += s[rand.nextULessThan(K)];
+ }
+}
+
+BENCH(TDArray_RandomAccess) {
+ SkTDArray<int> s;
+ for (int i = 0; i < K; i++) s.push(i);
+
+ SkRandom rand;
+ volatile int junk = 0;
+ for (int i = 0; i < K*loops; i++) {
+ junk += s[rand.nextULessThan(K)];
+ }
+}
+
+// Push many times.
+
+BENCH(ChunkAlloc_Push) {
+ SkChunkAlloc s(4096);
+ for (int i = 0; i < K*loops; i++) s.allocThrow(sizeof(int));
+}
+
+BENCH(Deque_Push) {
+ SkDeque s(sizeof(int), 1024);
+ for (int i = 0; i < K*loops; i++) *(int*)s.push_back() = i;
+}
+
+BENCH(TArray_Push) {
+ SkTArray<int, true> s;
+ for (int i = 0; i < K*loops; i++) s.push_back(i);
+}
+
+BENCH(TDArray_Push) {
+ SkTDArray<int> s;
+ for (int i = 0; i < K*loops; i++) s.push(i);
+}
+
+// Push then immediately pop many times.
+
+BENCH(ChunkAlloc_PushPop) {
+ SkChunkAlloc s(4096);
+ for (int i = 0; i < K*loops; i++) {
+ void* p = s.allocThrow(sizeof(int));
+ s.unalloc(p);
+ }
+}
+
+BENCH(Deque_PushPop) {
+ SkDeque s(sizeof(int), 1024);
+ for (int i = 0; i < K*loops; i++) {
+ *(int*)s.push_back() = i;
+ s.pop_back();
+ }
+}
+
+BENCH(TArray_PushPop) {
+ SkTArray<int, true> s;
+ for (int i = 0; i < K*loops; i++) {
+ s.push_back(i);
+ s.pop_back();
+ }
+}
+
+BENCH(TDArray_PushPop) {
+ SkTDArray<int> s;
+ for (int i = 0; i < K*loops; i++) {
+ s.push(i);
+ s.pop();
+ }
+}
+
+// Push many items, then pop them all.
+
+BENCH(Deque_PushAllPopAll) {
+ SkDeque s(sizeof(int), 1024);
+ for (int i = 0; i < K*loops; i++) *(int*)s.push_back() = i;
+ for (int i = 0; i < K*loops; i++) s.pop_back();
+}
+
+BENCH(TArray_PushAllPopAll) {
+ SkTArray<int, true> s;
+ for (int i = 0; i < K*loops; i++) s.push_back(i);
+ for (int i = 0; i < K*loops; i++) s.pop_back();
+}
+
+BENCH(TDArray_PushAllPopAll) {
+ SkTDArray<int> s;
+ for (int i = 0; i < K*loops; i++) s.push(i);
+ for (int i = 0; i < K*loops; i++) s.pop();
+}
diff --git a/chromium/third_party/skia/bench/StrokeBench.cpp b/chromium/third_party/skia/bench/StrokeBench.cpp
new file mode 100644
index 00000000000..24e0cabbb03
--- /dev/null
+++ b/chromium/third_party/skia/bench/StrokeBench.cpp
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkCanvas.h"
+#include "SkPaint.h"
+#include "SkRRect.h"
+#include "SkString.h"
+
+struct RRectRec {
+ SkCanvas* fCanvas;
+ SkRRect fRRect;
+ SkPaint fPaint;
+};
+
+typedef const char* (*DrawProc)(const RRectRec*, int);
+
+static const char* draw_rect(const RRectRec* rec, int count) {
+ if (rec) {
+ const SkRect& r = rec->fRRect.getBounds();
+ for (int i = 0; i < count; ++i) {
+ rec->fCanvas->drawRect(r, rec->fPaint);
+ }
+ }
+ return "rect";
+}
+
+static const char* draw_rrect(const RRectRec* rec, int count) {
+ if (rec) {
+ for (int i = 0; i < count; ++i) {
+ rec->fCanvas->drawRRect(rec->fRRect, rec->fPaint);
+ }
+ }
+ return "rrect";
+}
+
+static const char* draw_oval(const RRectRec* rec, int count) {
+ if (rec) {
+ const SkRect& r = rec->fRRect.getBounds();
+ for (int i = 0; i < count; ++i) {
+ rec->fCanvas->drawOval(r, rec->fPaint);
+ }
+ }
+ return "oval";
+}
+
+// Handles rect, rrect, and oval
+//
+// Test drawing a small stroked version to see the effect of special-casing
+// our stroke code for these convex single-contour shapes.
+//
+class StrokeRRectBench : public Benchmark {
+ SkString fName;
+ SkPaint::Join fJoin;
+ RRectRec fRec;
+ DrawProc fProc;
+public:
+ StrokeRRectBench(SkPaint::Join j, DrawProc proc) {
+ static const char* gJoinName[] = {
+ "miter", "round", "bevel"
+ };
+
+ fJoin = j;
+ fProc = proc;
+ fName.printf("draw_stroke_%s_%s", proc(NULL, 0), gJoinName[j]);
+
+ SkRect r = { 20, 20, 40, 40 };
+ SkScalar rad = 4;
+ fRec.fRRect.setRectXY(r, rad, rad);
+ }
+
+protected:
+ virtual const char* onGetName() {
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) {
+ fRec.fCanvas = canvas;
+ this->setupPaint(&fRec.fPaint);
+ fRec.fPaint.setStyle(SkPaint::kStroke_Style);
+ fRec.fPaint.setStrokeJoin(fJoin);
+ fRec.fPaint.setStrokeWidth(5);
+ fProc(&fRec, loops);
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+DEF_BENCH( return new StrokeRRectBench(SkPaint::kRound_Join, draw_rect); )
+DEF_BENCH( return new StrokeRRectBench(SkPaint::kBevel_Join, draw_rect); )
+DEF_BENCH( return new StrokeRRectBench(SkPaint::kMiter_Join, draw_rect); )
+
+DEF_BENCH( return new StrokeRRectBench(SkPaint::kRound_Join, draw_rrect); )
+DEF_BENCH( return new StrokeRRectBench(SkPaint::kBevel_Join, draw_rrect); )
+DEF_BENCH( return new StrokeRRectBench(SkPaint::kMiter_Join, draw_rrect); )
+
+DEF_BENCH( return new StrokeRRectBench(SkPaint::kRound_Join, draw_oval); )
+DEF_BENCH( return new StrokeRRectBench(SkPaint::kBevel_Join, draw_oval); )
+DEF_BENCH( return new StrokeRRectBench(SkPaint::kMiter_Join, draw_oval); )
diff --git a/chromium/third_party/skia/bench/TableBench.cpp b/chromium/third_party/skia/bench/TableBench.cpp
new file mode 100644
index 00000000000..a99e03b513f
--- /dev/null
+++ b/chromium/third_party/skia/bench/TableBench.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkCanvas.h"
+#include "SkRect.h"
+
+static const SkScalar kCellWidth = SkIntToScalar(20);
+static const SkScalar kCellHeight = SkIntToScalar(10);
+
+// This bench draws a table in the manner of Google spreadsheet and sahadan.com.
+// ____________ ___
+// | 1 | 2 |
+// |____________|___|
+// | 3 | 4 |
+// |____________|___|
+//
+// Areas 1-4 are first all draw white. Areas 3&4 are then drawn grey. Areas
+// 2&4 are then drawn grey. Areas 2&3 are thus double drawn while area 4 is
+// triple drawn.
+// This trio of drawRects is then repeat for the next cell.
+class TableBench : public Benchmark {
+public:
+ static const int kNumRows = 48;
+ static const int kNumCols = 32;
+
+protected:
+ virtual const char* onGetName() {
+ return "tablebench";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) {
+ SkPaint cellPaint;
+ cellPaint.setColor(0xFFFFFFF);
+
+ SkPaint borderPaint;
+ borderPaint.setColor(0xFFCCCCCC);
+
+ for (int i = 0; i < loops; ++i) {
+ for (int row = 0; row < kNumRows; ++row) {
+ for (int col = 0; col < kNumCols; ++col) {
+ SkRect cell = SkRect::MakeLTRB(col * kCellWidth,
+ row * kCellHeight,
+ (col+1) * kCellWidth,
+ (row+1) * kCellHeight);
+ canvas->drawRect(cell, cellPaint);
+
+ SkRect bottom = SkRect::MakeLTRB(col * kCellWidth,
+ row * kCellHeight + (kCellHeight-SK_Scalar1),
+ (col+1) * kCellWidth,
+ (row+1) * kCellHeight);
+ canvas->drawRect(bottom, borderPaint);
+
+ SkRect right = SkRect::MakeLTRB(col * kCellWidth + (kCellWidth-SK_Scalar1),
+ row * kCellHeight,
+ (col+1) * kCellWidth,
+ (row+1) * kCellHeight);
+ canvas->drawRect(right, borderPaint);
+ }
+ }
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+DEF_BENCH( return new TableBench(); )
diff --git a/chromium/third_party/skia/bench/TextBench.cpp b/chromium/third_party/skia/bench/TextBench.cpp
new file mode 100644
index 00000000000..f150be2188d
--- /dev/null
+++ b/chromium/third_party/skia/bench/TextBench.cpp
@@ -0,0 +1,145 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "Benchmark.h"
+#include "SkCanvas.h"
+#include "SkFontHost.h"
+#include "SkPaint.h"
+#include "SkRandom.h"
+#include "SkString.h"
+#include "SkTemplates.h"
+
+enum FontQuality {
+ kBW,
+ kAA,
+ kLCD
+};
+
+static const char* fontQualityName(const SkPaint& paint) {
+ if (!paint.isAntiAlias()) {
+ return "BW";
+ }
+ if (paint.isLCDRenderText()) {
+ return "LCD";
+ }
+ return "AA";
+}
+
+/* Some considerations for performance:
+ short -vs- long strings (measuring overhead)
+ tiny -vs- large pointsize (measure blit -vs- overhead)
+ 1 -vs- many point sizes (measure cache lookup)
+ normal -vs- subpixel -vs- lineartext (minor)
+ force purge after each draw to measure scaler
+ textencoding?
+ text -vs- postext - pathtext
+ */
+class TextBench : public Benchmark {
+ SkPaint fPaint;
+ SkString fText;
+ SkString fName;
+ FontQuality fFQ;
+ bool fDoPos;
+ SkPoint* fPos;
+public:
+ TextBench(const char text[], int ps,
+ SkColor color, FontQuality fq, bool doPos = false) {
+ fPos = NULL;
+ fFQ = fq;
+ fDoPos = doPos;
+ fText.set(text);
+
+ fPaint.setAntiAlias(kBW != fq);
+ fPaint.setLCDRenderText(kLCD == fq);
+ fPaint.setTextSize(SkIntToScalar(ps));
+ fPaint.setColor(color);
+
+ if (doPos) {
+ size_t len = strlen(text);
+ SkScalar* adv = new SkScalar[len];
+ fPaint.getTextWidths(text, len, adv);
+ fPos = new SkPoint[len];
+ SkScalar x = 0;
+ for (size_t i = 0; i < len; ++i) {
+ fPos[i].set(x, SkIntToScalar(50));
+ x += adv[i];
+ }
+ delete[] adv;
+ }
+ }
+
+ virtual ~TextBench() {
+ delete[] fPos;
+ }
+
+protected:
+ virtual const char* onGetName() {
+ fName.printf("text_%g", SkScalarToFloat(fPaint.getTextSize()));
+ if (fDoPos) {
+ fName.append("_pos");
+ }
+ fName.appendf("_%s", fontQualityName(fPaint));
+ if (SK_ColorBLACK != fPaint.getColor()) {
+ fName.appendf("_%02X", fPaint.getAlpha());
+ } else {
+ fName.append("_BK");
+ }
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) {
+ const SkIPoint dim = this->getSize();
+ SkRandom rand;
+
+ SkPaint paint(fPaint);
+ this->setupPaint(&paint);
+ // explicitly need these
+ paint.setColor(fPaint.getColor());
+ paint.setAntiAlias(kBW != fFQ);
+ paint.setLCDRenderText(kLCD == fFQ);
+
+ const SkScalar x0 = SkIntToScalar(-10);
+ const SkScalar y0 = SkIntToScalar(-10);
+
+ if (fDoPos) {
+ // realistically, the matrix is often at least translated, so we
+ // do that since it exercises different code in drawPosText.
+ canvas->translate(SK_Scalar1, SK_Scalar1);
+ }
+
+ for (int i = 0; i < loops; i++) {
+ if (fDoPos) {
+ canvas->drawPosText(fText.c_str(), fText.size(), fPos, paint);
+ } else {
+ SkScalar x = x0 + rand.nextUScalar1() * dim.fX;
+ SkScalar y = y0 + rand.nextUScalar1() * dim.fY;
+ canvas->drawText(fText.c_str(), fText.size(), x, y, paint);
+ }
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+#define STR "Hamburgefons"
+
+DEF_BENCH( return new TextBench(STR, 16, 0xFF000000, kBW); )
+DEF_BENCH( return new TextBench(STR, 16, 0xFFFF0000, kBW); )
+DEF_BENCH( return new TextBench(STR, 16, 0x88FF0000, kBW); )
+
+DEF_BENCH( return new TextBench(STR, 16, 0xFF000000, kAA); )
+DEF_BENCH( return new TextBench(STR, 16, 0xFFFF0000, kAA); )
+DEF_BENCH( return new TextBench(STR, 16, 0x88FF0000, kAA); )
+
+DEF_BENCH( return new TextBench(STR, 16, 0xFF000000, kLCD); )
+DEF_BENCH( return new TextBench(STR, 16, 0xFFFF0000, kLCD); )
+DEF_BENCH( return new TextBench(STR, 16, 0x88FF0000, kLCD); )
+
+DEF_BENCH( return new TextBench(STR, 16, 0xFF000000, kAA, true); )
diff --git a/chromium/third_party/skia/bench/TileBench.cpp b/chromium/third_party/skia/bench/TileBench.cpp
new file mode 100644
index 00000000000..7487b1b8ea6
--- /dev/null
+++ b/chromium/third_party/skia/bench/TileBench.cpp
@@ -0,0 +1,131 @@
+
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkBitmap.h"
+#include "SkCanvas.h"
+#include "SkShader.h"
+#include "SkString.h"
+
+static void create_gradient(SkBitmap* bm) {
+ SkASSERT(1 == bm->width());
+ const int height = bm->height();
+
+ float deltaB = 255.0f / height;
+ float blue = 255.0f;
+
+ SkAutoLockPixels lock(*bm);
+ for (int y = 0; y < height; y++) {
+ *bm->getAddr32(0, y) = SkColorSetRGB(0, 0, (U8CPU) blue);
+ blue -= deltaB;
+ }
+}
+
+// Test out the special case of a tiled 1xN texture. Test out opacity,
+// filtering and the different tiling modes
+class ConstXTileBench : public Benchmark {
+ SkPaint fPaint;
+ SkString fName;
+ bool fDoFilter;
+ bool fDoTrans;
+ bool fDoScale;
+ static const int kWidth = 1;
+ static const int kHeight = 300;
+
+public:
+ ConstXTileBench(SkShader::TileMode xTile,
+ SkShader::TileMode yTile,
+ bool doFilter,
+ bool doTrans,
+ bool doScale)
+ : fDoFilter(doFilter)
+ , fDoTrans(doTrans)
+ , fDoScale(doScale) {
+ SkBitmap bm;
+
+ bm.allocN32Pixels(kWidth, kHeight, true);
+ bm.eraseColor(SK_ColorWHITE);
+
+ create_gradient(&bm);
+
+ SkShader* s = SkShader::CreateBitmapShader(bm, xTile, yTile);
+ fPaint.setShader(s)->unref();
+
+ fName.printf("constXTile_");
+
+ static const char* gTileModeStr[SkShader::kTileModeCount] = { "C", "R", "M" };
+ fName.append(gTileModeStr[xTile]);
+ fName.append(gTileModeStr[yTile]);
+
+ if (doFilter) {
+ fName.append("_filter");
+ }
+
+ if (doTrans) {
+ fName.append("_trans");
+ }
+
+ if (doScale) {
+ fName.append("_scale");
+ }
+ }
+
+protected:
+ virtual const char* onGetName() {
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) {
+ SkPaint paint(fPaint);
+ this->setupPaint(&paint);
+ paint.setFilterLevel(fDoFilter ? SkPaint::kLow_FilterLevel
+ : SkPaint::kNone_FilterLevel);
+ if (fDoTrans) {
+ paint.setColor(SkColorSetARGBMacro(0x80, 0xFF, 0xFF, 0xFF));
+ }
+
+ SkRect r;
+
+ if (fDoScale) {
+ r = SkRect::MakeWH(SkIntToScalar(2 * 640), SkIntToScalar(2 * 480));
+ canvas->scale(SK_ScalarHalf, SK_ScalarHalf);
+ } else {
+ r = SkRect::MakeWH(SkIntToScalar(640), SkIntToScalar(480));
+ }
+
+ SkPaint bgPaint;
+ bgPaint.setColor(SK_ColorWHITE);
+
+ for (int i = 0; i < loops; i++) {
+ if (fDoTrans) {
+ canvas->drawRect(r, bgPaint);
+ }
+
+ canvas->drawRect(r, paint);
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+DEF_BENCH(return new ConstXTileBench(SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, false, false, true))
+DEF_BENCH(return new ConstXTileBench(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, false, false, false))
+DEF_BENCH(return new ConstXTileBench(SkShader::kMirror_TileMode, SkShader::kMirror_TileMode, false, false, true))
+
+DEF_BENCH(return new ConstXTileBench(SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, true, false, false))
+DEF_BENCH(return new ConstXTileBench(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, true, false, true))
+DEF_BENCH(return new ConstXTileBench(SkShader::kMirror_TileMode, SkShader::kMirror_TileMode, true, false, false))
+
+DEF_BENCH(return new ConstXTileBench(SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, false, true, true))
+DEF_BENCH(return new ConstXTileBench(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, false, true, false))
+DEF_BENCH(return new ConstXTileBench(SkShader::kMirror_TileMode, SkShader::kMirror_TileMode, false, true, true))
+
+DEF_BENCH(return new ConstXTileBench(SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, true, true, false))
+DEF_BENCH(return new ConstXTileBench(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, true, true, true))
+DEF_BENCH(return new ConstXTileBench(SkShader::kMirror_TileMode, SkShader::kMirror_TileMode, true, true, false))
diff --git a/chromium/third_party/skia/bench/TimerData.cpp b/chromium/third_party/skia/bench/TimerData.cpp
new file mode 100644
index 00000000000..0cb000280b9
--- /dev/null
+++ b/chromium/third_party/skia/bench/TimerData.cpp
@@ -0,0 +1,224 @@
+
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "TimerData.h"
+
+#include "BenchTimer.h"
+#include <limits>
+
+using namespace std;
+
+TimerData::TimerData(int maxNumTimings)
+: fMaxNumTimings(maxNumTimings)
+, fCurrTiming(0)
+, fWallTimes(maxNumTimings)
+, fTruncatedWallTimes(maxNumTimings)
+, fCpuTimes(maxNumTimings)
+, fTruncatedCpuTimes(maxNumTimings)
+, fGpuTimes(maxNumTimings){
+}
+
+bool TimerData::appendTimes(BenchTimer* timer) {
+ SkASSERT(timer != NULL);
+ if (fCurrTiming >= fMaxNumTimings) {
+ return false;
+ }
+
+ fWallTimes[fCurrTiming] = timer->fWall;
+ fTruncatedWallTimes[fCurrTiming] = timer->fTruncatedWall;
+ fCpuTimes[fCurrTiming] = timer->fCpu;
+ fTruncatedCpuTimes[fCurrTiming] = timer->fTruncatedCpu;
+ fGpuTimes[fCurrTiming] = timer->fGpu;
+
+ ++fCurrTiming;
+
+ return true;
+}
+
+SkString TimerData::getResult(const char* doubleFormat,
+ Result result,
+ const char *configName,
+ uint32_t timerFlags,
+ int itersPerTiming) {
+ SkASSERT(itersPerTiming >= 1);
+
+ if (!fCurrTiming) {
+ return SkString("");
+ }
+
+ int numTimings = fCurrTiming;
+
+ SkString wallStr(" msecs = ");
+ SkString truncWallStr(" Wmsecs = ");
+ SkString cpuStr(" cmsecs = ");
+ SkString truncCpuStr(" Cmsecs = ");
+ SkString gpuStr(" gmsecs = ");
+
+ double wallMin = std::numeric_limits<double>::max();
+ double truncWallMin = std::numeric_limits<double>::max();
+ double cpuMin = std::numeric_limits<double>::max();
+ double truncCpuMin = std::numeric_limits<double>::max();
+ double gpuMin = std::numeric_limits<double>::max();
+
+ double wallSum = 0;
+ double truncWallSum = 0;
+ double cpuSum = 0;
+ double truncCpuSum = 0;
+ double gpuSum = 0;
+
+ for (int i = 0; i < numTimings; ++i) {
+ if (kPerIter_Result == result) {
+ wallStr.appendf(doubleFormat, fWallTimes[i] / itersPerTiming);
+ truncWallStr.appendf(doubleFormat, fTruncatedWallTimes[i] / itersPerTiming);
+ cpuStr.appendf(doubleFormat, fCpuTimes[i] / itersPerTiming);
+ truncCpuStr.appendf(doubleFormat, fTruncatedCpuTimes[i] / itersPerTiming);
+ gpuStr.appendf(doubleFormat, fGpuTimes[i] / itersPerTiming);
+
+ if (i != numTimings - 1) {
+ static const char kSep[] = ", ";
+ wallStr.append(kSep);
+ truncWallStr.append(kSep);
+ cpuStr.append(kSep);
+ truncCpuStr.append(kSep);
+ gpuStr.append(kSep);
+ }
+ } else if (kMin_Result == result) {
+ wallMin = SkTMin(wallMin, fWallTimes[i]);
+ truncWallMin = SkTMin(truncWallMin, fTruncatedWallTimes[i]);
+ cpuMin = SkTMin(cpuMin, fCpuTimes[i]);
+ truncCpuMin = SkTMin(truncCpuMin, fTruncatedCpuTimes[i]);
+ gpuMin = SkTMin(gpuMin, fGpuTimes[i]);
+ } else {
+ SkASSERT(kAvg_Result == result);
+ wallSum += fWallTimes[i];
+ truncWallSum += fTruncatedWallTimes[i];
+ cpuSum += fCpuTimes[i];
+ truncCpuSum += fTruncatedCpuTimes[i];
+ }
+
+ // We always track the GPU sum because whether it is non-zero indicates if valid gpu times
+ // were recorded at all.
+ gpuSum += fGpuTimes[i];
+ }
+
+ if (kMin_Result == result) {
+ wallStr.appendf(doubleFormat, wallMin / itersPerTiming);
+ truncWallStr.appendf(doubleFormat, truncWallMin / itersPerTiming);
+ cpuStr.appendf(doubleFormat, cpuMin / itersPerTiming);
+ truncCpuStr.appendf(doubleFormat, truncCpuMin / itersPerTiming);
+ gpuStr.appendf(doubleFormat, gpuMin / itersPerTiming);
+ } else if (kAvg_Result == result) {
+ int divisor = numTimings * itersPerTiming;
+ wallStr.appendf(doubleFormat, wallSum / divisor);
+ truncWallStr.appendf(doubleFormat, truncWallSum / divisor);
+ cpuStr.appendf(doubleFormat, cpuSum / divisor);
+ truncCpuStr.appendf(doubleFormat, truncCpuSum / divisor);
+ gpuStr.appendf(doubleFormat, gpuSum / divisor);
+ }
+
+ SkString str;
+ str.printf(" %4s:", configName);
+ if (timerFlags & kWall_Flag) {
+ str += wallStr;
+ }
+ if (timerFlags & kTruncatedWall_Flag) {
+ str += truncWallStr;
+ }
+ if (timerFlags & kCpu_Flag) {
+ str += cpuStr;
+ }
+ if (timerFlags & kTruncatedCpu_Flag) {
+ str += truncCpuStr;
+ }
+ if ((timerFlags & kGpu_Flag) && gpuSum > 0) {
+ str += gpuStr;
+ }
+ return str;
+}
+
+Json::Value TimerData::getJSON(uint32_t timerFlags,
+ Result result,
+ int itersPerTiming) {
+ SkASSERT(itersPerTiming >= 1);
+ Json::Value dataNode;
+ Json::Value wallNode, truncWall, cpuNode, truncCpu, gpuNode;
+ if (!fCurrTiming) {
+ return dataNode;
+ }
+
+ int numTimings = fCurrTiming;
+
+ double wallMin = std::numeric_limits<double>::max();
+ double truncWallMin = std::numeric_limits<double>::max();
+ double cpuMin = std::numeric_limits<double>::max();
+ double truncCpuMin = std::numeric_limits<double>::max();
+ double gpuMin = std::numeric_limits<double>::max();
+
+ double wallSum = 0;
+ double truncWallSum = 0;
+ double cpuSum = 0;
+ double truncCpuSum = 0;
+ double gpuSum = 0;
+
+ for (int i = 0; i < numTimings; ++i) {
+ if (kPerIter_Result == result) {
+ wallNode.append(fWallTimes[i] / itersPerTiming);
+ truncWall.append(fTruncatedWallTimes[i] / itersPerTiming);
+ cpuNode.append(fCpuTimes[i] / itersPerTiming);
+ truncCpu.append(fTruncatedCpuTimes[i] / itersPerTiming);
+ gpuNode.append(fGpuTimes[i] / itersPerTiming);
+ } else if (kMin_Result == result) {
+ wallMin = SkTMin(wallMin, fWallTimes[i]);
+ truncWallMin = SkTMin(truncWallMin, fTruncatedWallTimes[i]);
+ cpuMin = SkTMin(cpuMin, fCpuTimes[i]);
+ truncCpuMin = SkTMin(truncCpuMin, fTruncatedCpuTimes[i]);
+ gpuMin = SkTMin(gpuMin, fGpuTimes[i]);
+ } else {
+ SkASSERT(kAvg_Result == result);
+ wallSum += fWallTimes[i];
+ truncWallSum += fTruncatedWallTimes[i];
+ cpuSum += fCpuTimes[i];
+ truncCpuSum += fTruncatedCpuTimes[i];
+ }
+
+ // We always track the GPU sum because whether it is non-zero indicates if valid gpu times
+ // were recorded at all.
+ gpuSum += fGpuTimes[i];
+ }
+
+ if (kMin_Result == result) {
+ wallNode.append(wallMin / itersPerTiming);
+ truncWall.append(truncWallMin / itersPerTiming);
+ cpuNode.append(cpuMin / itersPerTiming);
+ truncCpu.append(truncCpuMin / itersPerTiming);
+ gpuNode.append(gpuMin / itersPerTiming);
+ } else if (kAvg_Result == result) {
+ int divisor = numTimings * itersPerTiming;
+ wallNode.append(wallSum / divisor);
+ truncWall.append(truncWallSum / divisor);
+ cpuNode.append(cpuSum / divisor);
+ truncCpu.append(truncCpuSum / divisor);
+ gpuNode.append(gpuSum / divisor);
+ }
+
+ if (timerFlags & kWall_Flag) {
+ dataNode["wall"] = wallNode;
+ }
+ if (timerFlags & kTruncatedWall_Flag) {
+ dataNode["truncWall"] = truncWall;
+ }
+ if (timerFlags & kCpu_Flag) {
+ dataNode["cpu"] = cpuNode;
+ }
+ if (timerFlags & kTruncatedCpu_Flag) {
+ dataNode["trucCpu"] = truncCpu;
+ }
+ if ((timerFlags & kGpu_Flag) && gpuSum > 0) {
+ dataNode["gpu"] = gpuNode;
+ }
+ return dataNode;
+}
diff --git a/chromium/third_party/skia/bench/TimerData.h b/chromium/third_party/skia/bench/TimerData.h
new file mode 100644
index 00000000000..fb84df1a9eb
--- /dev/null
+++ b/chromium/third_party/skia/bench/TimerData.h
@@ -0,0 +1,86 @@
+
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef TimerData_DEFINED
+#define TimerData_DEFINED
+
+#include "SkString.h"
+#include "SkTemplates.h"
+
+#ifdef SK_BUILD_FOR_WIN
+ #pragma warning(push)
+ #pragma warning(disable : 4530)
+#endif
+
+#include "SkJSONCPP.h"
+
+#ifdef SK_BUILD_FOR_WIN
+ #pragma warning(pop)
+#endif
+
+class BenchTimer;
+
+class TimerData {
+public:
+ /**
+ * Constructs a TimerData to hold at most maxNumTimings sets of elapsed timer values.
+ **/
+ explicit TimerData(int maxNumTimings);
+
+ /**
+ * Collect times from the BenchTimer for an iteration. It will fail if called more often than
+ * indicated in the constructor.
+ *
+ * @param BenchTimer Must not be null.
+ */
+ bool appendTimes(BenchTimer*);
+
+ enum Result {
+ kMin_Result,
+ kAvg_Result,
+ kPerIter_Result
+ };
+
+ enum TimerFlags {
+ kWall_Flag = 0x1,
+ kTruncatedWall_Flag = 0x2,
+ kCpu_Flag = 0x4,
+ kTruncatedCpu_Flag = 0x8,
+ kGpu_Flag = 0x10
+ };
+
+ /**
+ * Gets the timer data results as a string.
+ * @param doubleFormat printf-style format for doubles (e.g. "%02d")
+ * @param result the type of result desired
+ * @param the name of the config being timed (prepended to results string)
+ * @param timerFlags bitfield of TimerFlags values indicating which timers should be reported.
+ * @param itersPerTiming the number of test/bench iterations that correspond to each
+ * appendTimes() call, 1 when appendTimes is called for each iteration.
+ */
+ SkString getResult(const char* doubleFormat,
+ Result result,
+ const char* configName,
+ uint32_t timerFlags,
+ int itersPerTiming = 1);
+ Json::Value getJSON(uint32_t timerFlags,
+ Result result,
+ int itersPerTiming = 1);
+
+private:
+ int fMaxNumTimings;
+ int fCurrTiming;
+
+ SkAutoTArray<double> fWallTimes;
+ SkAutoTArray<double> fTruncatedWallTimes;
+ SkAutoTArray<double> fCpuTimes;
+ SkAutoTArray<double> fTruncatedCpuTimes;
+ SkAutoTArray<double> fGpuTimes;
+};
+
+#endif // TimerData_DEFINED
diff --git a/chromium/third_party/skia/bench/VertBench.cpp b/chromium/third_party/skia/bench/VertBench.cpp
new file mode 100644
index 00000000000..e426ad8a5ef
--- /dev/null
+++ b/chromium/third_party/skia/bench/VertBench.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkCanvas.h"
+#include "SkPaint.h"
+#include "SkRandom.h"
+#include "SkShader.h"
+#include "SkString.h"
+
+enum VertFlags {
+ kColors_VertFlag,
+ kTexture_VertFlag,
+};
+
+class VertBench : public Benchmark {
+ SkString fName;
+ enum {
+ W = 640,
+ H = 480,
+ ROW = 20,
+ COL = 20,
+ PTS = (ROW + 1) * (COL + 1),
+ IDX = ROW * COL * 6,
+ };
+
+ SkPoint fPts[PTS];
+ SkColor fColors[PTS];
+ uint16_t fIdx[IDX];
+
+ static void load_2_tris(uint16_t idx[], int x, int y, int rb) {
+ int n = y * rb + x;
+ idx[0] = n; idx[1] = n + 1; idx[2] = rb + n + 1;
+ idx[3] = n; idx[4] = rb + n + 1; idx[5] = n + rb;
+ }
+
+public:
+ VertBench() {
+ const SkScalar dx = SkIntToScalar(W) / COL;
+ const SkScalar dy = SkIntToScalar(H) / COL;
+
+ SkPoint* pts = fPts;
+ uint16_t* idx = fIdx;
+
+ SkScalar yy = 0;
+ for (int y = 0; y <= ROW; y++) {
+ SkScalar xx = 0;
+ for (int x = 0; x <= COL; ++x) {
+ pts->set(xx, yy);
+ pts += 1;
+ xx += dx;
+
+ if (x < COL && y < ROW) {
+ load_2_tris(idx, x, y, COL + 1);
+ for (int i = 0; i < 6; i++) {
+ SkASSERT(idx[i] < PTS);
+ }
+ idx += 6;
+ }
+ }
+ yy += dy;
+ }
+ SkASSERT(PTS == pts - fPts);
+ SkASSERT(IDX == idx - fIdx);
+
+ SkRandom rand;
+ for (int i = 0; i < PTS; ++i) {
+ fColors[i] = rand.nextU() | (0xFF << 24);
+ }
+
+ fName.set("verts");
+ }
+
+protected:
+ virtual const char* onGetName() { return fName.c_str(); }
+ virtual void onDraw(const int loops, SkCanvas* canvas) {
+ SkPaint paint;
+ this->setupPaint(&paint);
+
+ for (int i = 0; i < loops; i++) {
+ canvas->drawVertices(SkCanvas::kTriangles_VertexMode, PTS,
+ fPts, NULL, fColors, NULL, fIdx, IDX, paint);
+ }
+ }
+private:
+ typedef Benchmark INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH( return SkNEW_ARGS(VertBench, ()); )
diff --git a/chromium/third_party/skia/bench/WritePixelsBench.cpp b/chromium/third_party/skia/bench/WritePixelsBench.cpp
new file mode 100644
index 00000000000..5138375ffba
--- /dev/null
+++ b/chromium/third_party/skia/bench/WritePixelsBench.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkCanvas.h"
+#include "SkString.h"
+
+class WritePixelsBench : public Benchmark {
+public:
+ WritePixelsBench(SkColorType ct, SkAlphaType at)
+ : fColorType(ct)
+ , fAlphaType(at)
+ , fName("writepix")
+ {
+ switch (ct) {
+ case kRGBA_8888_SkColorType:
+ fName.append("_RGBA");
+ break;
+ case kBGRA_8888_SkColorType:
+ fName.append("_BGRA");
+ break;
+ default:
+ SkASSERT(0);
+ break;
+ }
+ switch (at) {
+ case kPremul_SkAlphaType:
+ fName.append("_PM");
+ break;
+ case kUnpremul_SkAlphaType:
+ fName.append("_UPM");
+ break;
+ default:
+ SkASSERT(0);
+ break;
+ }
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();
+ }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkISize size = canvas->getDeviceSize();
+
+ canvas->clear(0xFFFF0000);
+
+ SkBitmap bmp;
+ bmp.allocN32Pixels(size.width(), size.height());
+ canvas->readPixels(&bmp, 0, 0);
+
+ SkImageInfo info = bmp.info();
+ info.fColorType = fColorType;
+ info.fAlphaType = fAlphaType;
+
+ for (int loop = 0; loop < loops; ++loop) {
+ canvas->writePixels(info, bmp.getPixels(), bmp.rowBytes(), 0, 0);
+ }
+ }
+
+private:
+ SkColorType fColorType;
+ SkAlphaType fAlphaType;
+ SkString fName;
+
+ typedef Benchmark INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH( return SkNEW_ARGS(WritePixelsBench, (kRGBA_8888_SkColorType, kPremul_SkAlphaType)); )
+DEF_BENCH( return SkNEW_ARGS(WritePixelsBench, (kRGBA_8888_SkColorType, kUnpremul_SkAlphaType)); )
diff --git a/chromium/third_party/skia/bench/WriterBench.cpp b/chromium/third_party/skia/bench/WriterBench.cpp
new file mode 100644
index 00000000000..906a9d2ee84
--- /dev/null
+++ b/chromium/third_party/skia/bench/WriterBench.cpp
@@ -0,0 +1,41 @@
+
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkCanvas.h"
+#include "SkWriter32.h"
+
+class WriterBench : public Benchmark {
+public:
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return "writer";
+ }
+
+ virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
+ static const char gStr[] = "abcdefghimjklmnopqrstuvwxyz";
+ static const size_t gLen = strlen(gStr);
+ SkWriter32 writer;
+ for (int i = 0; i < loops; i++) {
+ for (size_t j = 0; j <= gLen; j++) {
+ writer.writeString(gStr, j);
+ }
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+DEF_BENCH( return new WriterBench(); )
diff --git a/chromium/third_party/skia/bench/XfermodeBench.cpp b/chromium/third_party/skia/bench/XfermodeBench.cpp
new file mode 100644
index 00000000000..f73943bcf7e
--- /dev/null
+++ b/chromium/third_party/skia/bench/XfermodeBench.cpp
@@ -0,0 +1,127 @@
+
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkCanvas.h"
+#include "SkPaint.h"
+#include "SkRandom.h"
+#include "SkString.h"
+#include "SkXfermode.h"
+
+// Benchmark that draws non-AA rects with an SkXfermode::Mode
+class XfermodeBench : public Benchmark {
+public:
+ XfermodeBench(SkXfermode::Mode mode) {
+ fXfermode.reset(SkXfermode::Create(mode));
+ SkASSERT(NULL != fXfermode.get() || SkXfermode::kSrcOver_Mode == mode);
+ fName.printf("Xfermode_%s", SkXfermode::ModeName(mode));
+ }
+
+ XfermodeBench(SkXfermode* xferMode, const char* name) {
+ SkASSERT(NULL != xferMode);
+ fXfermode.reset(xferMode);
+ fName.printf("Xfermode_%s", name);
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE { return fName.c_str(); }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkISize size = canvas->getDeviceSize();
+ SkRandom random;
+ for (int i = 0; i < loops; ++i) {
+ SkPaint paint;
+ paint.setXfermode(fXfermode.get());
+ paint.setColor(random.nextU());
+ SkScalar w = random.nextRangeScalar(SkIntToScalar(kMinSize), SkIntToScalar(kMaxSize));
+ SkScalar h = random.nextRangeScalar(SkIntToScalar(kMinSize), SkIntToScalar(kMaxSize));
+ SkRect rect = SkRect::MakeXYWH(
+ random.nextUScalar1() * (size.fWidth - w),
+ random.nextUScalar1() * (size.fHeight - h),
+ w,
+ h
+ );
+ canvas->drawRect(rect, paint);
+ }
+ }
+
+private:
+ enum {
+ kMinSize = 50,
+ kMaxSize = 100,
+ };
+ SkAutoTUnref<SkXfermode> fXfermode;
+ SkString fName;
+
+ typedef Benchmark INHERITED;
+};
+
+class XferCreateBench : public Benchmark {
+public:
+ virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
+ return backend == kNonRendering_Backend;
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE { return "xfermode_create"; }
+
+ virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ for (int outer = 0; outer < loops * 10; ++outer) {
+ for (int i = 0; i <= SkXfermode::kLastMode; ++i) {
+ SkXfermode* xfer = SkXfermode::Create(SkXfermode::Mode(i));
+ SkSafeUnref(xfer);
+ }
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+#define CONCAT_I(x, y) x ## y
+#define CONCAT(x, y) CONCAT_I(x, y) // allow for macro expansion
+#define BENCH(...) \
+ DEF_BENCH( return new XfermodeBench(__VA_ARGS__); );\
+
+
+BENCH(SkXfermode::kClear_Mode)
+BENCH(SkXfermode::kSrc_Mode)
+BENCH(SkXfermode::kDst_Mode)
+BENCH(SkXfermode::kSrcOver_Mode)
+BENCH(SkXfermode::kDstOver_Mode)
+BENCH(SkXfermode::kSrcIn_Mode)
+BENCH(SkXfermode::kDstIn_Mode)
+BENCH(SkXfermode::kSrcOut_Mode)
+BENCH(SkXfermode::kDstOut_Mode)
+BENCH(SkXfermode::kSrcATop_Mode)
+BENCH(SkXfermode::kDstATop_Mode)
+BENCH(SkXfermode::kXor_Mode)
+
+BENCH(SkXfermode::kPlus_Mode)
+BENCH(SkXfermode::kModulate_Mode)
+BENCH(SkXfermode::kScreen_Mode)
+
+BENCH(SkXfermode::kOverlay_Mode)
+BENCH(SkXfermode::kDarken_Mode)
+BENCH(SkXfermode::kLighten_Mode)
+BENCH(SkXfermode::kColorDodge_Mode)
+BENCH(SkXfermode::kColorBurn_Mode)
+BENCH(SkXfermode::kHardLight_Mode)
+BENCH(SkXfermode::kSoftLight_Mode)
+BENCH(SkXfermode::kDifference_Mode)
+BENCH(SkXfermode::kExclusion_Mode)
+BENCH(SkXfermode::kMultiply_Mode)
+
+BENCH(SkXfermode::kHue_Mode)
+BENCH(SkXfermode::kSaturation_Mode)
+BENCH(SkXfermode::kColor_Mode)
+BENCH(SkXfermode::kLuminosity_Mode)
+
+DEF_BENCH(return new XferCreateBench;)
diff --git a/chromium/third_party/skia/bench/bench_compare.py b/chromium/third_party/skia/bench/bench_compare.py
new file mode 100755
index 00000000000..f4f773442e7
--- /dev/null
+++ b/chromium/third_party/skia/bench/bench_compare.py
@@ -0,0 +1,193 @@
+#!/usr/bin/env python
+'''
+Created on May 16, 2011
+
+@author: bungeman
+'''
+import sys
+import getopt
+import bench_util
+
+def usage():
+ """Prints simple usage information."""
+
+ print '-o <file> the old bench output file.'
+ print '-n <file> the new bench output file.'
+ print '-h causes headers to be output.'
+ print '-s <stat> the type of statistical analysis used'
+ print ' Not specifying is the same as -s "avg".'
+ print ' avg: average of all data points'
+ print ' min: minimum of all data points'
+ print ' med: median of all data points'
+ print ' 25th: twenty-fifth percentile for all data points'
+ print '-f <fieldSpec> which fields to output and in what order.'
+ print ' Not specifying is the same as -f "bctondp".'
+ print ' b: bench'
+ print ' c: config'
+ print ' t: time type'
+ print ' o: old time'
+ print ' n: new time'
+ print ' d: diff'
+ print ' p: percent diff'
+ print '-t use tab delimited format for output.'
+ print '--match <bench> only matches benches which begin with <bench>.'
+
+class BenchDiff:
+ """A compare between data points produced by bench.
+
+ (BenchDataPoint, BenchDataPoint)"""
+ def __init__(self, old, new):
+ self.old = old
+ self.new = new
+ self.diff = old.time - new.time
+ diffp = 0
+ if old.time != 0:
+ diffp = self.diff / old.time
+ self.diffp = diffp
+
+ def __repr__(self):
+ return "BenchDiff(%s, %s)" % (
+ str(self.new),
+ str(self.old),
+ )
+
+def main():
+ """Parses command line and writes output."""
+
+ try:
+ opts, _ = getopt.getopt(sys.argv[1:], "f:o:n:s:ht", ['match='])
+ except getopt.GetoptError, err:
+ print str(err)
+ usage()
+ sys.exit(2)
+
+ old = None
+ new = None
+ column_format = ""
+ header_format = ""
+ columns = 'bctondp'
+ header = False
+ stat_type = "avg"
+ use_tabs = False
+ match_bench = None;
+
+ for option, value in opts:
+ if option == "-o":
+ old = value
+ elif option == "-n":
+ new = value
+ elif option == "-h":
+ header = True
+ elif option == "-f":
+ columns = value
+ elif option == "-s":
+ stat_type = value
+ elif option == "-t":
+ use_tabs = True
+ elif option == "--match":
+ match_bench = value
+ else:
+ usage()
+ assert False, "unhandled option"
+
+ if old is None or new is None:
+ usage()
+ sys.exit(2)
+
+ old_benches = bench_util.parse({}, open(old, 'r'), stat_type)
+ new_benches = bench_util.parse({}, open(new, 'r'), stat_type)
+
+ bench_diffs = []
+ for old_bench in old_benches:
+ #filter benches by the match criteria
+ if match_bench and not old_bench.bench.startswith(match_bench):
+ continue
+
+ #filter new_benches for benches that match old_bench
+ new_bench_match = [bench for bench in new_benches
+ if old_bench.bench == bench.bench and
+ old_bench.config == bench.config and
+ old_bench.time_type == bench.time_type
+ ]
+ if (len(new_bench_match) < 1):
+ continue
+ bench_diffs.append(BenchDiff(old_bench, new_bench_match[0]))
+
+ if use_tabs:
+ column_formats = {
+ 'b' : '{bench}\t',
+ 'c' : '{config}\t',
+ 't' : '{time_type}\t',
+ 'o' : '{old_time: 0.2f}\t',
+ 'n' : '{new_time: 0.2f}\t',
+ 'd' : '{diff: 0.2f}\t',
+ 'p' : '{diffp: 0.1%}\t',
+ }
+ header_formats = {
+ 'b' : '{bench}\t',
+ 'c' : '{config}\t',
+ 't' : '{time_type}\t',
+ 'o' : '{old_time}\t',
+ 'n' : '{new_time}\t',
+ 'd' : '{diff}\t',
+ 'p' : '{diffp}\t',
+ }
+ else:
+ bench_max_len = max(map(lambda b: len(b.old.bench), bench_diffs))
+ config_max_len = max(map(lambda b: len(b.old.config), bench_diffs))
+ column_formats = {
+ 'b' : '{bench: >%d} ' % (bench_max_len),
+ 'c' : '{config: <%d} ' % (config_max_len),
+ 't' : '{time_type: <4} ',
+ 'o' : '{old_time: >10.2f} ',
+ 'n' : '{new_time: >10.2f} ',
+ 'd' : '{diff: >+10.2f} ',
+ 'p' : '{diffp: >+8.1%} ',
+ }
+ header_formats = {
+ 'b' : '{bench: >%d} ' % (bench_max_len),
+ 'c' : '{config: <%d} ' % (config_max_len),
+ 't' : '{time_type: <4} ',
+ 'o' : '{old_time: >10} ',
+ 'n' : '{new_time: >10} ',
+ 'd' : '{diff: >10} ',
+ 'p' : '{diffp: >8} ',
+ }
+
+ for column_char in columns:
+ if column_formats[column_char]:
+ column_format += column_formats[column_char]
+ header_format += header_formats[column_char]
+ else:
+ usage()
+ sys.exit(2)
+
+ if header:
+ print header_format.format(
+ bench='bench'
+ , config='conf'
+ , time_type='time'
+ , old_time='old'
+ , new_time='new'
+ , diff='diff'
+ , diffp='diffP'
+ )
+
+ bench_diffs.sort(key=lambda d : [d.diffp,
+ d.old.bench,
+ d.old.config,
+ d.old.time_type,
+ ])
+ for bench_diff in bench_diffs:
+ print column_format.format(
+ bench=bench_diff.old.bench.strip()
+ , config=bench_diff.old.config.strip()
+ , time_type=bench_diff.old.time_type
+ , old_time=bench_diff.old.time
+ , new_time=bench_diff.new.time
+ , diff=bench_diff.diff
+ , diffp=bench_diff.diffp
+ )
+
+if __name__ == "__main__":
+ main()
diff --git a/chromium/third_party/skia/bench/bench_util.py b/chromium/third_party/skia/bench/bench_util.py
new file mode 100644
index 00000000000..b6fecb7ca80
--- /dev/null
+++ b/chromium/third_party/skia/bench/bench_util.py
@@ -0,0 +1,356 @@
+'''
+Created on May 19, 2011
+
+@author: bungeman
+'''
+
+import os
+import re
+import math
+
+# bench representation algorithm constant names
+ALGORITHM_AVERAGE = 'avg'
+ALGORITHM_MEDIAN = 'med'
+ALGORITHM_MINIMUM = 'min'
+ALGORITHM_25TH_PERCENTILE = '25th'
+
+# Regular expressions used throughout.
+PER_SETTING_RE = '([^\s=]+)(?:=(\S+))?'
+SETTINGS_RE = 'skia bench:((?:\s+' + PER_SETTING_RE + ')*)'
+BENCH_RE = 'running bench (?:\[\d+ \d+\] )?\s*(\S+)'
+TIME_RE = '(?:(\w*)msecs = )?\s*((?:\d+\.\d+)(?:,\s*\d+\.\d+)*)'
+# non-per-tile benches have configs that don't end with ']' or '>'
+CONFIG_RE = '(\S+[^\]>]):\s+((?:' + TIME_RE + '\s+)+)'
+# per-tile bench lines are in the following format. Note that there are
+# non-averaged bench numbers in separate lines, which we ignore now due to
+# their inaccuracy.
+TILE_RE = (' tile_(\S+): tile \[\d+,\d+\] out of \[\d+,\d+\] <averaged>:'
+ ' ((?:' + TIME_RE + '\s+)+)')
+# for extracting tile layout
+TILE_LAYOUT_RE = ' out of \[(\d+),(\d+)\] <averaged>: '
+
+PER_SETTING_RE_COMPILED = re.compile(PER_SETTING_RE)
+SETTINGS_RE_COMPILED = re.compile(SETTINGS_RE)
+BENCH_RE_COMPILED = re.compile(BENCH_RE)
+TIME_RE_COMPILED = re.compile(TIME_RE)
+CONFIG_RE_COMPILED = re.compile(CONFIG_RE)
+TILE_RE_COMPILED = re.compile(TILE_RE)
+TILE_LAYOUT_RE_COMPILED = re.compile(TILE_LAYOUT_RE)
+
+class BenchDataPoint:
+ """A single data point produced by bench.
+ """
+ def __init__(self, bench, config, time_type, time, settings,
+ tile_layout='', per_tile_values=[], per_iter_time=[]):
+ # string name of the benchmark to measure
+ self.bench = bench
+ # string name of the configurations to run
+ self.config = config
+ # type of the timer in string: '' (walltime), 'c' (cpu) or 'g' (gpu)
+ self.time_type = time_type
+ # float number of the bench time value
+ self.time = time
+ # dictionary of the run settings
+ self.settings = settings
+ # how tiles cover the whole picture: '5x3' means 5 columns and 3 rows
+ self.tile_layout = tile_layout
+ # list of float for per_tile bench values, if applicable
+ self.per_tile_values = per_tile_values
+ # list of float for per-iteration bench time, if applicable
+ self.per_iter_time = per_iter_time
+
+ def __repr__(self):
+ return "BenchDataPoint(%s, %s, %s, %s, %s)" % (
+ str(self.bench),
+ str(self.config),
+ str(self.time_type),
+ str(self.time),
+ str(self.settings),
+ )
+
+class _ExtremeType(object):
+ """Instances of this class compare greater or less than other objects."""
+ def __init__(self, cmpr, rep):
+ object.__init__(self)
+ self._cmpr = cmpr
+ self._rep = rep
+
+ def __cmp__(self, other):
+ if isinstance(other, self.__class__) and other._cmpr == self._cmpr:
+ return 0
+ return self._cmpr
+
+ def __repr__(self):
+ return self._rep
+
+Max = _ExtremeType(1, "Max")
+Min = _ExtremeType(-1, "Min")
+
+class _ListAlgorithm(object):
+ """Algorithm for selecting the representation value from a given list.
+ representation is one of the ALGORITHM_XXX representation types."""
+ def __init__(self, data, representation=None):
+ if not representation:
+ representation = ALGORITHM_AVERAGE # default algorithm
+ self._data = data
+ self._len = len(data)
+ if representation == ALGORITHM_AVERAGE:
+ self._rep = sum(self._data) / self._len
+ else:
+ self._data.sort()
+ if representation == ALGORITHM_MINIMUM:
+ self._rep = self._data[0]
+ else:
+ # for percentiles, we use the value below which x% of values are
+ # found, which allows for better detection of quantum behaviors.
+ if representation == ALGORITHM_MEDIAN:
+ x = int(round(0.5 * self._len + 0.5))
+ elif representation == ALGORITHM_25TH_PERCENTILE:
+ x = int(round(0.25 * self._len + 0.5))
+ else:
+ raise Exception("invalid representation algorithm %s!" %
+ representation)
+ self._rep = self._data[x - 1]
+
+ def compute(self):
+ return self._rep
+
+def _ParseAndStoreTimes(config_re_compiled, is_per_tile, line, bench,
+ value_dic, layout_dic):
+ """Parses given bench time line with regex and adds data to value_dic.
+
+ config_re_compiled: precompiled regular expression for parsing the config
+ line.
+ is_per_tile: boolean indicating whether this is a per-tile bench.
+ If so, we add tile layout into layout_dic as well.
+ line: input string line to parse.
+ bench: name of bench for the time values.
+ value_dic: dictionary to store bench values. See bench_dic in parse() below.
+ layout_dic: dictionary to store tile layouts. See parse() for descriptions.
+ """
+
+ for config in config_re_compiled.finditer(line):
+ current_config = config.group(1)
+ tile_layout = ''
+ if is_per_tile: # per-tile bench, add name prefix
+ current_config = 'tile_' + current_config
+ layouts = TILE_LAYOUT_RE_COMPILED.search(line)
+ if layouts and len(layouts.groups()) == 2:
+ tile_layout = '%sx%s' % layouts.groups()
+ times = config.group(2)
+ for new_time in TIME_RE_COMPILED.finditer(times):
+ current_time_type = new_time.group(1)
+ iters = [float(i) for i in
+ new_time.group(2).strip().split(',')]
+ value_dic.setdefault(bench, {}).setdefault(
+ current_config, {}).setdefault(current_time_type, []).append(
+ iters)
+ layout_dic.setdefault(bench, {}).setdefault(
+ current_config, {}).setdefault(current_time_type, tile_layout)
+
+def parse_skp_bench_data(directory, revision, rep, default_settings=None):
+ """Parses all the skp bench data in the given directory.
+
+ Args:
+ directory: string of path to input data directory.
+ revision: git hash revision that matches the data to process.
+ rep: bench representation algorithm, see bench_util.py.
+ default_settings: dictionary of other run settings. See writer.option() in
+ bench/benchmain.cpp.
+
+ Returns:
+ A list of BenchDataPoint objects.
+ """
+ revision_data_points = []
+ file_list = os.listdir(directory)
+ file_list.sort()
+ for bench_file in file_list:
+ scalar_type = None
+ # Scalar type, if any, is in the bench filename after 'scalar_'.
+ if (bench_file.startswith('bench_' + revision + '_data_')):
+ if bench_file.find('scalar_') > 0:
+ components = bench_file.split('_')
+ scalar_type = components[components.index('scalar') + 1]
+ else: # Skips non skp bench files.
+ continue
+
+ with open('/'.join([directory, bench_file]), 'r') as file_handle:
+ settings = dict(default_settings or {})
+ settings['scalar'] = scalar_type
+ revision_data_points.extend(parse(settings, file_handle, rep))
+
+ return revision_data_points
+
+# TODO(bensong): switch to reading JSON output when available. This way we don't
+# need the RE complexities.
+def parse(settings, lines, representation=None):
+ """Parses bench output into a useful data structure.
+
+ ({str:str}, __iter__ -> str) -> [BenchDataPoint]
+ representation is one of the ALGORITHM_XXX types."""
+
+ benches = []
+ current_bench = None
+ # [bench][config][time_type] -> [[per-iter values]] where per-tile config
+ # has per-iter value list for each tile [[<tile1_iter1>,<tile1_iter2>,...],
+ # [<tile2_iter1>,<tile2_iter2>,...],...], while non-per-tile config only
+ # contains one list of iterations [[iter1, iter2, ...]].
+ bench_dic = {}
+ # [bench][config][time_type] -> tile_layout
+ layout_dic = {}
+
+ for line in lines:
+
+ # see if this line is a settings line
+ settingsMatch = SETTINGS_RE_COMPILED.search(line)
+ if (settingsMatch):
+ settings = dict(settings)
+ for settingMatch in PER_SETTING_RE_COMPILED.finditer(settingsMatch.group(1)):
+ if (settingMatch.group(2)):
+ settings[settingMatch.group(1)] = settingMatch.group(2)
+ else:
+ settings[settingMatch.group(1)] = True
+
+ # see if this line starts a new bench
+ new_bench = BENCH_RE_COMPILED.search(line)
+ if new_bench:
+ current_bench = new_bench.group(1)
+
+ # add configs on this line to the bench_dic
+ if current_bench:
+ if line.startswith(' tile_') :
+ _ParseAndStoreTimes(TILE_RE_COMPILED, True, line, current_bench,
+ bench_dic, layout_dic)
+ else:
+ _ParseAndStoreTimes(CONFIG_RE_COMPILED, False, line,
+ current_bench, bench_dic, layout_dic)
+
+ # append benches to list
+ for bench in bench_dic:
+ for config in bench_dic[bench]:
+ for time_type in bench_dic[bench][config]:
+ tile_layout = ''
+ per_tile_values = [] # empty for non-per-tile configs
+ per_iter_time = [] # empty for per-tile configs
+ bench_summary = None # a single final bench value
+ if len(bench_dic[bench][config][time_type]) > 1:
+ # per-tile config; compute representation for each tile
+ per_tile_values = [
+ _ListAlgorithm(iters, representation).compute()
+ for iters in bench_dic[bench][config][time_type]]
+ # use sum of each tile representation for total bench value
+ bench_summary = sum(per_tile_values)
+ # extract tile layout
+ tile_layout = layout_dic[bench][config][time_type]
+ else:
+ # get the list of per-iteration values
+ per_iter_time = bench_dic[bench][config][time_type][0]
+ bench_summary = _ListAlgorithm(
+ per_iter_time, representation).compute()
+ benches.append(BenchDataPoint(
+ bench,
+ config,
+ time_type,
+ bench_summary,
+ settings,
+ tile_layout,
+ per_tile_values,
+ per_iter_time))
+
+ return benches
+
+class LinearRegression:
+ """Linear regression data based on a set of data points.
+
+ ([(Number,Number)])
+ There must be at least two points for this to make sense."""
+ def __init__(self, points):
+ n = len(points)
+ max_x = Min
+ min_x = Max
+
+ Sx = 0.0
+ Sy = 0.0
+ Sxx = 0.0
+ Sxy = 0.0
+ Syy = 0.0
+ for point in points:
+ x = point[0]
+ y = point[1]
+ max_x = max(max_x, x)
+ min_x = min(min_x, x)
+
+ Sx += x
+ Sy += y
+ Sxx += x*x
+ Sxy += x*y
+ Syy += y*y
+
+ denom = n*Sxx - Sx*Sx
+ if (denom != 0.0):
+ B = (n*Sxy - Sx*Sy) / denom
+ else:
+ B = 0.0
+ a = (1.0/n)*(Sy - B*Sx)
+
+ se2 = 0
+ sB2 = 0
+ sa2 = 0
+ if (n >= 3 and denom != 0.0):
+ se2 = (1.0/(n*(n-2)) * (n*Syy - Sy*Sy - B*B*denom))
+ sB2 = (n*se2) / denom
+ sa2 = sB2 * (1.0/n) * Sxx
+
+
+ self.slope = B
+ self.intercept = a
+ self.serror = math.sqrt(max(0, se2))
+ self.serror_slope = math.sqrt(max(0, sB2))
+ self.serror_intercept = math.sqrt(max(0, sa2))
+ self.max_x = max_x
+ self.min_x = min_x
+
+ def __repr__(self):
+ return "LinearRegression(%s, %s, %s, %s, %s)" % (
+ str(self.slope),
+ str(self.intercept),
+ str(self.serror),
+ str(self.serror_slope),
+ str(self.serror_intercept),
+ )
+
+ def find_min_slope(self):
+ """Finds the minimal slope given one standard deviation."""
+ slope = self.slope
+ intercept = self.intercept
+ error = self.serror
+ regr_start = self.min_x
+ regr_end = self.max_x
+ regr_width = regr_end - regr_start
+
+ if slope < 0:
+ lower_left_y = slope*regr_start + intercept - error
+ upper_right_y = slope*regr_end + intercept + error
+ return min(0, (upper_right_y - lower_left_y) / regr_width)
+
+ elif slope > 0:
+ upper_left_y = slope*regr_start + intercept + error
+ lower_right_y = slope*regr_end + intercept - error
+ return max(0, (lower_right_y - upper_left_y) / regr_width)
+
+ return 0
+
+def CreateRevisionLink(revision_number):
+ """Returns HTML displaying the given revision number and linking to
+ that revision's change page at code.google.com, e.g.
+ http://code.google.com/p/skia/source/detail?r=2056
+ """
+ return '<a href="http://code.google.com/p/skia/source/detail?r=%s">%s</a>'%(
+ revision_number, revision_number)
+
+def main():
+ foo = [[0.0, 0.0], [0.0, 1.0], [0.0, 2.0], [0.0, 3.0]]
+ LinearRegression(foo)
+
+if __name__ == "__main__":
+ main()
diff --git a/chromium/third_party/skia/bench/benchmain.cpp b/chromium/third_party/skia/bench/benchmain.cpp
new file mode 100644
index 00000000000..6b3f5872f2c
--- /dev/null
+++ b/chromium/third_party/skia/bench/benchmain.cpp
@@ -0,0 +1,686 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "BenchLogger.h"
+#include "BenchTimer.h"
+#include "Benchmark.h"
+#include "CrashHandler.h"
+#include "GMBench.h"
+#include "ResultsWriter.h"
+#include "SkBitmapDevice.h"
+#include "SkCanvas.h"
+#include "SkColorPriv.h"
+#include "SkCommandLineFlags.h"
+#include "SkData.h"
+#include "SkDeferredCanvas.h"
+#include "SkGraphics.h"
+#include "SkImageEncoder.h"
+#include "SkOSFile.h"
+#include "SkPicture.h"
+#include "SkPictureRecorder.h"
+#include "SkString.h"
+#include "SkSurface.h"
+
+#if SK_SUPPORT_GPU
+#include "GrContext.h"
+#include "GrContextFactory.h"
+#include "GrRenderTarget.h"
+#include "SkGpuDevice.h"
+#include "gl/GrGLDefines.h"
+#else
+class GrContext;
+#endif // SK_SUPPORT_GPU
+
+#include <limits>
+
+enum BenchMode {
+ kNormal_BenchMode,
+ kDeferred_BenchMode,
+ kDeferredSilent_BenchMode,
+ kRecord_BenchMode,
+ kPictureRecord_BenchMode
+};
+const char* BenchMode_Name[] = {
+ "normal", "deferred", "deferredSilent", "record", "picturerecord"
+};
+
+static const char kDefaultsConfigStr[] = "defaults";
+
+///////////////////////////////////////////////////////////////////////////////
+
+class Iter {
+public:
+ Iter() : fBenches(BenchRegistry::Head()), fGMs(skiagm::GMRegistry::Head()) {}
+
+ Benchmark* next() {
+ if (fBenches) {
+ BenchRegistry::Factory f = fBenches->factory();
+ fBenches = fBenches->next();
+ return (*f)(NULL);
+ }
+
+ while (fGMs) {
+ SkAutoTDelete<skiagm::GM> gm(fGMs->factory()(NULL));
+ fGMs = fGMs->next();
+ if (gm->getFlags() & skiagm::GM::kAsBench_Flag) {
+ return SkNEW_ARGS(GMBench, (gm.detach()));
+ }
+ }
+
+ return NULL;
+ }
+
+private:
+ const BenchRegistry* fBenches;
+ const skiagm::GMRegistry* fGMs;
+};
+
+static void make_filename(const char name[], SkString* path) {
+ path->set(name);
+ for (int i = 0; name[i]; i++) {
+ switch (name[i]) {
+ case '/':
+ case '\\':
+ case ' ':
+ case ':':
+ path->writable_str()[i] = '-';
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void saveFile(const char name[], const char config[], const char dir[],
+ const SkImage* image) {
+ SkAutoTUnref<SkData> data(image->encode(SkImageEncoder::kPNG_Type, 100));
+ if (NULL == data.get()) {
+ return;
+ }
+
+ SkString filename;
+ make_filename(name, &filename);
+ filename.appendf("_%s.png", config);
+ SkString path = SkOSPath::SkPathJoin(dir, filename.c_str());
+ ::remove(path.c_str());
+
+ SkFILEWStream stream(path.c_str());
+ stream.write(data->data(), data->size());
+}
+
+static void perform_clip(SkCanvas* canvas, int w, int h) {
+ SkRect r;
+
+ r.set(SkIntToScalar(10), SkIntToScalar(10),
+ SkIntToScalar(w*2/3), SkIntToScalar(h*2/3));
+ canvas->clipRect(r, SkRegion::kIntersect_Op);
+
+ r.set(SkIntToScalar(w/3), SkIntToScalar(h/3),
+ SkIntToScalar(w-10), SkIntToScalar(h-10));
+ canvas->clipRect(r, SkRegion::kXOR_Op);
+}
+
+static void perform_rotate(SkCanvas* canvas, int w, int h) {
+ const SkScalar x = SkIntToScalar(w) / 2;
+ const SkScalar y = SkIntToScalar(h) / 2;
+
+ canvas->translate(x, y);
+ canvas->rotate(SkIntToScalar(35));
+ canvas->translate(-x, -y);
+}
+
+static void perform_scale(SkCanvas* canvas, int w, int h) {
+ const SkScalar x = SkIntToScalar(w) / 2;
+ const SkScalar y = SkIntToScalar(h) / 2;
+
+ canvas->translate(x, y);
+ // just enough so we can't take the sprite case
+ canvas->scale(SK_Scalar1 * 99/100, SK_Scalar1 * 99/100);
+ canvas->translate(-x, -y);
+}
+
+static SkSurface* make_surface(SkColorType colorType, const SkIPoint& size,
+ Benchmark::Backend backend, int sampleCount,
+ GrContext* context) {
+ SkSurface* surface = NULL;
+ SkImageInfo info = SkImageInfo::Make(size.fX, size.fY, colorType,
+ kPremul_SkAlphaType);
+
+ switch (backend) {
+ case Benchmark::kRaster_Backend:
+ surface = SkSurface::NewRaster(info);
+ surface->getCanvas()->clear(SK_ColorWHITE);
+ break;
+#if SK_SUPPORT_GPU
+ case Benchmark::kGPU_Backend: {
+ surface = SkSurface::NewRenderTarget(context, info, sampleCount);
+ break;
+ }
+#endif
+ case Benchmark::kPDF_Backend:
+ default:
+ SkDEBUGFAIL("unsupported");
+ }
+ return surface;
+}
+
+#if SK_SUPPORT_GPU
+GrContextFactory gContextFactory;
+typedef GrContextFactory::GLContextType GLContextType;
+static const GLContextType kNative = GrContextFactory::kNative_GLContextType;
+static const GLContextType kNVPR = GrContextFactory::kNVPR_GLContextType;
+#if SK_ANGLE
+static const GLContextType kANGLE = GrContextFactory::kANGLE_GLContextType;
+#endif
+static const GLContextType kDebug = GrContextFactory::kDebug_GLContextType;
+static const GLContextType kNull = GrContextFactory::kNull_GLContextType;
+#else
+typedef int GLContextType;
+static const GLContextType kNative = 0, kANGLE = 0, kDebug = 0, kNull = 0;
+#endif
+
+#ifdef SK_DEBUG
+static const bool kIsDebug = true;
+#else
+static const bool kIsDebug = false;
+#endif
+
+static const struct Config {
+ SkColorType fColorType;
+ const char* name;
+ int sampleCount;
+ Benchmark::Backend backend;
+ GLContextType contextType;
+ bool runByDefault;
+} gConfigs[] = {
+ { kN32_SkColorType, "NONRENDERING", 0, Benchmark::kNonRendering_Backend, kNative, true},
+ { kN32_SkColorType, "8888", 0, Benchmark::kRaster_Backend, kNative, true},
+ { kRGB_565_SkColorType, "565", 0, Benchmark::kRaster_Backend, kNative, true},
+#if SK_SUPPORT_GPU
+ { kN32_SkColorType, "GPU", 0, Benchmark::kGPU_Backend, kNative, true},
+ { kN32_SkColorType, "MSAA4", 4, Benchmark::kGPU_Backend, kNative, false},
+ { kN32_SkColorType, "MSAA16", 16, Benchmark::kGPU_Backend, kNative, false},
+ { kN32_SkColorType, "NVPRMSAA4", 4, Benchmark::kGPU_Backend, kNVPR, true},
+ { kN32_SkColorType, "NVPRMSAA16", 16, Benchmark::kGPU_Backend, kNVPR, false},
+#if SK_ANGLE
+ { kN32_SkColorType, "ANGLE", 0, Benchmark::kGPU_Backend, kANGLE, true},
+#endif // SK_ANGLE
+ { kN32_SkColorType, "Debug", 0, Benchmark::kGPU_Backend, kDebug, kIsDebug},
+ { kN32_SkColorType, "NULLGPU", 0, Benchmark::kGPU_Backend, kNull, true},
+#endif // SK_SUPPORT_GPU
+};
+
+DEFINE_string(outDir, "", "If given, image of each bench will be put in outDir.");
+DEFINE_string(timers, "cg", "Timers to display. "
+ "Options: w(all) W(all, truncated) c(pu) C(pu, truncated) g(pu)");
+
+DEFINE_bool(rotate, false, "Rotate canvas before bench run?");
+DEFINE_bool(scale, false, "Scale canvas before bench run?");
+DEFINE_bool(clip, false, "Clip canvas before bench run?");
+
+DEFINE_bool(forceAA, true, "Force anti-aliasing?");
+DEFINE_bool(forceFilter, false, "Force bitmap filtering?");
+DEFINE_string(forceDither, "default", "Force dithering: true, false, or default?");
+DEFINE_bool(forceBlend, false, "Force alpha blending?");
+
+DEFINE_int32(gpuCacheBytes, -1, "GPU cache size limit in bytes. 0 to disable cache.");
+DEFINE_int32(gpuCacheCount, -1, "GPU cache size limit in object count. 0 to disable cache.");
+
+DEFINE_bool2(leaks, l, false, "show leaked ref cnt'd objects.");
+DEFINE_string(match, "", "[~][^]substring[$] [...] of test name to run.\n"
+ "Multiple matches may be separated by spaces.\n"
+ "~ causes a matching test to always be skipped\n"
+ "^ requires the start of the test to match\n"
+ "$ requires the end of the test to match\n"
+ "^ and $ requires an exact match\n"
+ "If a test does not match any list entry,\n"
+ "it is skipped unless some list entry starts with ~\n");
+DEFINE_string(mode, "normal",
+ "normal: draw to a normal canvas;\n"
+ "deferred: draw to a deferred canvas;\n"
+ "deferredSilent: deferred with silent playback;\n"
+ "record: draw to an SkPicture;\n"
+ "picturerecord: draw from an SkPicture to an SkPicture.\n");
+DEFINE_string(config, kDefaultsConfigStr,
+ "Run configs given. By default, runs the configs marked \"runByDefault\" in gConfigs.");
+DEFINE_string(logFile, "", "Also write stdout here.");
+DEFINE_int32(minMs, 20, "Shortest time we'll allow a benchmark to run.");
+DEFINE_int32(maxMs, 4000, "Longest time we'll allow a benchmark to run.");
+DEFINE_bool(runOnce, kIsDebug, "Run each bench exactly once and don't report timings.");
+DEFINE_double(error, 0.01,
+ "Ratio of subsequent bench measurements must drop within 1±error to converge.");
+DEFINE_string(timeFormat, "%9.2f", "Format to print results, in milliseconds per 1000 loops.");
+DEFINE_bool2(verbose, v, false, "Print more.");
+DEFINE_string(outResultsFile, "", "If given, the results will be written to the file in JSON format.");
+DEFINE_bool(dryRun, false, "Don't actually run the tests, just print what would have been done.");
+
+// Has this bench converged? First arguments are milliseconds / loop iteration,
+// last is overall runtime in milliseconds.
+static bool HasConverged(double prevPerLoop, double currPerLoop, double currRaw) {
+ if (currRaw < FLAGS_minMs) {
+ return false;
+ }
+ const double low = 1 - FLAGS_error, high = 1 + FLAGS_error;
+ const double ratio = currPerLoop / prevPerLoop;
+ return low < ratio && ratio < high;
+}
+
+int tool_main(int argc, char** argv);
+int tool_main(int argc, char** argv) {
+ SetupCrashHandler();
+ SkCommandLineFlags::Parse(argc, argv);
+#if SK_ENABLE_INST_COUNT
+ if (FLAGS_leaks) {
+ gPrintInstCount = true;
+ }
+#endif
+ SkAutoGraphics ag;
+
+ // First, parse some flags.
+ BenchLogger logger;
+ if (FLAGS_logFile.count()) {
+ logger.SetLogFile(FLAGS_logFile[0]);
+ }
+
+ LoggerResultsWriter logWriter(logger, FLAGS_timeFormat[0]);
+ MultiResultsWriter writer;
+ writer.add(&logWriter);
+
+ SkAutoTDelete<JSONResultsWriter> jsonWriter;
+ if (FLAGS_outResultsFile.count()) {
+ jsonWriter.reset(SkNEW(JSONResultsWriter(FLAGS_outResultsFile[0])));
+ writer.add(jsonWriter.get());
+ }
+
+ // Instantiate after all the writers have been added to writer so that we
+ // call close() before their destructors are called on the way out.
+ CallEnd<MultiResultsWriter> ender(writer);
+
+ const uint8_t alpha = FLAGS_forceBlend ? 0x80 : 0xFF;
+ SkTriState::State dither = SkTriState::kDefault;
+ for (size_t i = 0; i < 3; i++) {
+ if (strcmp(SkTriState::Name[i], FLAGS_forceDither[0]) == 0) {
+ dither = static_cast<SkTriState::State>(i);
+ }
+ }
+
+ BenchMode benchMode = kNormal_BenchMode;
+ for (size_t i = 0; i < SK_ARRAY_COUNT(BenchMode_Name); i++) {
+ if (strcmp(FLAGS_mode[0], BenchMode_Name[i]) == 0) {
+ benchMode = static_cast<BenchMode>(i);
+ }
+ }
+
+ SkTDArray<int> configs;
+ bool runDefaultConfigs = false;
+ // Try user-given configs first.
+ for (int i = 0; i < FLAGS_config.count(); i++) {
+ for (int j = 0; j < static_cast<int>(SK_ARRAY_COUNT(gConfigs)); ++j) {
+ if (0 == strcmp(FLAGS_config[i], gConfigs[j].name)) {
+ *configs.append() = j;
+ } else if (0 == strcmp(FLAGS_config[i], kDefaultsConfigStr)) {
+ runDefaultConfigs = true;
+ }
+ }
+ }
+ // If there weren't any, fill in with defaults.
+ if (runDefaultConfigs) {
+ for (int i = 0; i < static_cast<int>(SK_ARRAY_COUNT(gConfigs)); ++i) {
+ if (gConfigs[i].runByDefault) {
+ *configs.append() = i;
+ }
+ }
+ }
+ // Filter out things we can't run.
+ if (kNormal_BenchMode != benchMode) {
+ // Non-rendering configs only run in normal mode
+ for (int i = 0; i < configs.count(); ++i) {
+ const Config& config = gConfigs[configs[i]];
+ if (Benchmark::kNonRendering_Backend == config.backend) {
+ configs.remove(i, 1);
+ --i;
+ }
+ }
+ }
+
+#if SK_SUPPORT_GPU
+ for (int i = 0; i < configs.count(); ++i) {
+ const Config& config = gConfigs[configs[i]];
+
+ if (Benchmark::kGPU_Backend == config.backend) {
+ GrContext* context = gContextFactory.get(config.contextType);
+ if (NULL == context) {
+ SkDebugf("GrContext could not be created for config %s. Config will be skipped.\n",
+ config.name);
+ configs.remove(i);
+ --i;
+ continue;
+ }
+ if (config.sampleCount > context->getMaxSampleCount()){
+ SkDebugf(
+ "Sample count (%d) for config %s is not supported. Config will be skipped.\n",
+ config.sampleCount, config.name);
+ configs.remove(i);
+ --i;
+ continue;
+ }
+ }
+ }
+#endif
+
+ // All flags should be parsed now. Report our settings.
+ if (FLAGS_runOnce) {
+ logger.logError("bench was run with --runOnce, so we're going to hide the times."
+ " It's for your own good!\n");
+ }
+ writer.option("mode", FLAGS_mode[0]);
+ writer.option("alpha", SkStringPrintf("0x%02X", alpha).c_str());
+ writer.option("antialias", SkStringPrintf("%d", FLAGS_forceAA).c_str());
+ writer.option("filter", SkStringPrintf("%d", FLAGS_forceFilter).c_str());
+ writer.option("dither", SkTriState::Name[dither]);
+
+ writer.option("rotate", SkStringPrintf("%d", FLAGS_rotate).c_str());
+ writer.option("scale", SkStringPrintf("%d", FLAGS_scale).c_str());
+ writer.option("clip", SkStringPrintf("%d", FLAGS_clip).c_str());
+
+#if defined(SK_BUILD_FOR_WIN32)
+ writer.option("system", "WIN32");
+#elif defined(SK_BUILD_FOR_MAC)
+ writer.option("system", "MAC");
+#elif defined(SK_BUILD_FOR_ANDROID)
+ writer.option("system", "ANDROID");
+#elif defined(SK_BUILD_FOR_UNIX)
+ writer.option("system", "UNIX");
+#else
+ writer.option("system", "other");
+#endif
+
+#if defined(SK_DEBUG)
+ writer.option("build", "DEBUG");
+#else
+ writer.option("build", "RELEASE");
+#endif
+
+ // Set texture cache limits if non-default.
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gConfigs); ++i) {
+#if SK_SUPPORT_GPU
+ const Config& config = gConfigs[i];
+ if (Benchmark::kGPU_Backend != config.backend) {
+ continue;
+ }
+ GrContext* context = gContextFactory.get(config.contextType);
+ if (NULL == context) {
+ continue;
+ }
+
+ size_t bytes;
+ int count;
+ context->getResourceCacheLimits(&count, &bytes);
+ if (-1 != FLAGS_gpuCacheBytes) {
+ bytes = static_cast<size_t>(FLAGS_gpuCacheBytes);
+ }
+ if (-1 != FLAGS_gpuCacheCount) {
+ count = FLAGS_gpuCacheCount;
+ }
+ context->setResourceCacheLimits(count, bytes);
+#endif
+ }
+
+ // Run each bench in each configuration it supports and we asked for.
+ Iter iter;
+ Benchmark* bench;
+ while ((bench = iter.next()) != NULL) {
+ SkAutoTUnref<Benchmark> benchUnref(bench);
+ if (SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getName())) {
+ continue;
+ }
+
+ bench->setForceAlpha(alpha);
+ bench->setForceAA(FLAGS_forceAA);
+ bench->setForceFilter(FLAGS_forceFilter);
+ bench->setDither(dither);
+ bench->preDraw();
+
+ bool loggedBenchName = false;
+ for (int i = 0; i < configs.count(); ++i) {
+ const int configIndex = configs[i];
+ const Config& config = gConfigs[configIndex];
+
+ if (!bench->isSuitableFor(config.backend)) {
+ continue;
+ }
+
+ GrContext* context = NULL;
+#if SK_SUPPORT_GPU
+ SkGLContextHelper* glContext = NULL;
+ if (Benchmark::kGPU_Backend == config.backend) {
+ context = gContextFactory.get(config.contextType);
+ if (NULL == context) {
+ continue;
+ }
+ glContext = gContextFactory.getGLContext(config.contextType);
+ }
+#endif
+
+ SkAutoTUnref<SkCanvas> canvas;
+ SkAutoTUnref<SkPicture> recordFrom;
+ SkPictureRecorder recorderTo;
+ const SkIPoint dim = bench->getSize();
+
+ SkAutoTUnref<SkSurface> surface;
+ if (Benchmark::kNonRendering_Backend != config.backend) {
+ surface.reset(make_surface(config.fColorType,
+ dim,
+ config.backend,
+ config.sampleCount,
+ context));
+ if (!surface.get()) {
+ logger.logError(SkStringPrintf(
+ "Device creation failure for config %s. Will skip.\n", config.name));
+ continue;
+ }
+
+ switch(benchMode) {
+ case kDeferredSilent_BenchMode:
+ case kDeferred_BenchMode:
+ canvas.reset(SkDeferredCanvas::Create(surface.get()));
+ break;
+ case kRecord_BenchMode:
+ canvas.reset(SkRef(recorderTo.beginRecording(dim.fX, dim.fY)));
+ break;
+ case kPictureRecord_BenchMode: {
+ SkPictureRecorder recorderFrom;
+ bench->draw(1, recorderFrom.beginRecording(dim.fX, dim.fY));
+ recordFrom.reset(recorderFrom.endRecording());
+ canvas.reset(SkRef(recorderTo.beginRecording(dim.fX, dim.fY)));
+ break;
+ }
+ case kNormal_BenchMode:
+ canvas.reset(SkRef(surface->getCanvas()));
+ break;
+ default:
+ SkASSERT(false);
+ }
+ }
+
+ if (NULL != canvas) {
+ canvas->clear(SK_ColorWHITE);
+ if (FLAGS_clip) {
+ perform_clip(canvas, dim.fX, dim.fY);
+ }
+ if (FLAGS_scale) {
+ perform_scale(canvas, dim.fX, dim.fY);
+ }
+ if (FLAGS_rotate) {
+ perform_rotate(canvas, dim.fX, dim.fY);
+ }
+ }
+
+ if (!loggedBenchName) {
+ loggedBenchName = true;
+ writer.bench(bench->getName(), dim.fX, dim.fY);
+ }
+
+#if SK_SUPPORT_GPU
+ SkGLContextHelper* contextHelper = NULL;
+ if (Benchmark::kGPU_Backend == config.backend) {
+ contextHelper = gContextFactory.getGLContext(config.contextType);
+ }
+ BenchTimer timer(contextHelper);
+#else
+ BenchTimer timer;
+#endif
+
+ double previous = std::numeric_limits<double>::infinity();
+ bool converged = false;
+
+ // variables used to compute loopsPerFrame
+ double frameIntervalTime = 0.0f;
+ int frameIntervalTotalLoops = 0;
+
+ bool frameIntervalComputed = false;
+ int loopsPerFrame = 0;
+ int loopsPerIter = 0;
+ if (FLAGS_verbose) { SkDebugf("%s %s: ", bench->getName(), config.name); }
+ if (!FLAGS_dryRun) {
+ do {
+ // Ramp up 1 -> 2 -> 4 -> 8 -> 16 -> ... -> ~1 billion.
+ loopsPerIter = (loopsPerIter == 0) ? 1 : loopsPerIter * 2;
+ if (loopsPerIter >= (1<<30) || timer.fWall > FLAGS_maxMs) {
+ // If you find it takes more than a billion loops to get up to 20ms of runtime,
+ // you've got a computer clocked at several THz or have a broken benchmark. ;)
+ // "1B ought to be enough for anybody."
+ logger.logError(SkStringPrintf(
+ "\nCan't get %s %s to converge in %dms (%d loops)",
+ bench->getName(), config.name, FLAGS_maxMs, loopsPerIter));
+ break;
+ }
+
+ if ((benchMode == kRecord_BenchMode || benchMode == kPictureRecord_BenchMode)) {
+ // Clear the recorded commands so that they do not accumulate.
+ canvas.reset(SkRef(recorderTo.beginRecording(dim.fX, dim.fY)));
+ }
+
+ timer.start();
+ // Inner loop that allows us to break the run into smaller
+ // chunks (e.g. frames). This is especially useful for the GPU
+ // as we can flush and/or swap buffers to keep the GPU from
+ // queuing up too much work.
+ for (int loopCount = loopsPerIter; loopCount > 0; ) {
+ // Save and restore around each call to draw() to guarantee a pristine canvas.
+ SkAutoCanvasRestore saveRestore(canvas, true/*also save*/);
+
+ int loops;
+ if (frameIntervalComputed && loopCount > loopsPerFrame) {
+ loops = loopsPerFrame;
+ loopCount -= loopsPerFrame;
+ } else {
+ loops = loopCount;
+ loopCount = 0;
+ }
+
+ if (benchMode == kPictureRecord_BenchMode) {
+ recordFrom->draw(canvas);
+ } else {
+ bench->draw(loops, canvas);
+ }
+
+ if (kDeferredSilent_BenchMode == benchMode) {
+ static_cast<SkDeferredCanvas*>(canvas.get())->silentFlush();
+ } else if (NULL != canvas) {
+ canvas->flush();
+ }
+
+ #if SK_SUPPORT_GPU
+ // swap drawing buffers on each frame to prevent the GPU
+ // from queuing up too much work
+ if (NULL != glContext) {
+ glContext->swapBuffers();
+ }
+ #endif
+ }
+
+
+
+ // Stop truncated timers before GL calls complete, and stop the full timers after.
+ timer.truncatedEnd();
+ #if SK_SUPPORT_GPU
+ if (NULL != glContext) {
+ context->flush();
+ SK_GL(*glContext, Finish());
+ }
+ #endif
+ timer.end();
+
+ // setup the frame interval for subsequent iterations
+ if (!frameIntervalComputed) {
+ frameIntervalTime += timer.fWall;
+ frameIntervalTotalLoops += loopsPerIter;
+ if (frameIntervalTime >= FLAGS_minMs) {
+ frameIntervalComputed = true;
+ loopsPerFrame =
+ (int)(((double)frameIntervalTotalLoops / frameIntervalTime) * FLAGS_minMs);
+ if (loopsPerFrame < 1) {
+ loopsPerFrame = 1;
+ }
+ // SkDebugf(" %s has %d loops in %f ms (normalized to %d)\n",
+ // bench->getName(), frameIntervalTotalLoops,
+ // timer.fWall, loopsPerFrame);
+ }
+ }
+
+ const double current = timer.fWall / loopsPerIter;
+ if (FLAGS_verbose && current > previous) { SkDebugf("↑"); }
+ if (FLAGS_verbose) { SkDebugf("%.3g ", current); }
+ converged = HasConverged(previous, current, timer.fWall);
+ previous = current;
+ } while (!FLAGS_runOnce && !converged);
+ }
+ if (FLAGS_verbose) { SkDebugf("\n"); }
+
+ if (!FLAGS_dryRun && FLAGS_outDir.count() && Benchmark::kNonRendering_Backend != config.backend) {
+ SkAutoTUnref<SkImage> image(surface->newImageSnapshot());
+ if (image.get()) {
+ saveFile(bench->getName(), config.name, FLAGS_outDir[0],
+ image);
+ }
+ }
+
+ if (FLAGS_runOnce) {
+ // Let's not mislead ourselves by looking at Debug build or single iteration bench times!
+ continue;
+ }
+
+ // Normalize to ms per 1000 iterations.
+ const double normalize = 1000.0 / loopsPerIter;
+ const struct { char shortName; const char* longName; double ms; } times[] = {
+ {'w', "msecs", normalize * timer.fWall},
+ {'W', "Wmsecs", normalize * timer.fTruncatedWall},
+ {'c', "cmsecs", normalize * timer.fCpu},
+ {'C', "Cmsecs", normalize * timer.fTruncatedCpu},
+ {'g', "gmsecs", normalize * timer.fGpu},
+ };
+
+ writer.config(config.name);
+ for (size_t i = 0; i < SK_ARRAY_COUNT(times); i++) {
+ if (strchr(FLAGS_timers[0], times[i].shortName) && times[i].ms > 0) {
+ writer.timer(times[i].longName, times[i].ms);
+ }
+ }
+ }
+ }
+#if SK_SUPPORT_GPU
+ gContextFactory.destroyContexts();
+#endif
+ return 0;
+}
+
+#if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL)
+int main(int argc, char * const argv[]) {
+ return tool_main(argc, (char**) argv);
+}
+#endif
diff --git a/chromium/third_party/skia/bench/check_bench_regressions.py b/chromium/third_party/skia/bench/check_bench_regressions.py
new file mode 100644
index 00000000000..ea9146421a0
--- /dev/null
+++ b/chromium/third_party/skia/bench/check_bench_regressions.py
@@ -0,0 +1,244 @@
+'''
+Created on May 16, 2011
+
+@author: bungeman
+'''
+import bench_util
+import getopt
+import httplib
+import itertools
+import json
+import os
+import re
+import sys
+import urllib
+import urllib2
+import xml.sax.saxutils
+
+# Maximum expected number of characters we expect in an svn revision.
+MAX_SVN_REV_LENGTH = 5
+
+# Indices for getting elements from bench expectation files.
+# See bench_expectations_<builder>.txt for details.
+EXPECTED_IDX = -3
+LB_IDX = -2
+UB_IDX = -1
+
+# Indices of the tuple of dictionaries containing slower and faster alerts.
+SLOWER = 0
+FASTER = 1
+
+# URL prefix for the bench dashboard page. Showing recent 15 days of data.
+DASHBOARD_URL_PREFIX = 'http://go/skpdash/#15'
+
+def usage():
+ """Prints simple usage information."""
+
+ print '-a <representation_alg> bench representation algorithm to use. '
+ print ' Defaults to "25th". See bench_util.py for details.'
+ print '-b <builder> name of the builder whose bench data we are checking.'
+ print '-d <dir> a directory containing bench_<revision>_<scalar> files.'
+ print '-e <file> file containing expected bench builder values/ranges.'
+ print ' Will raise exception if actual bench values are out of range.'
+ print ' See bench_expectations_<builder>.txt for data format / examples.'
+ print '-r <revision> the git commit hash or svn revision for checking '
+ print ' bench values.'
+
+
+class Label:
+ """The information in a label.
+
+ (str, str, str, str, {str:str})"""
+ def __init__(self, bench, config, time_type, settings):
+ self.bench = bench
+ self.config = config
+ self.time_type = time_type
+ self.settings = settings
+
+ def __repr__(self):
+ return "Label(%s, %s, %s, %s)" % (
+ str(self.bench),
+ str(self.config),
+ str(self.time_type),
+ str(self.settings),
+ )
+
+ def __str__(self):
+ return "%s_%s_%s_%s" % (
+ str(self.bench),
+ str(self.config),
+ str(self.time_type),
+ str(self.settings),
+ )
+
+ def __eq__(self, other):
+ return (self.bench == other.bench and
+ self.config == other.config and
+ self.time_type == other.time_type and
+ self.settings == other.settings)
+
+ def __hash__(self):
+ return (hash(self.bench) ^
+ hash(self.config) ^
+ hash(self.time_type) ^
+ hash(frozenset(self.settings.iteritems())))
+
+def create_bench_dict(revision_data_points):
+ """Convert current revision data into a dictionary of line data.
+
+ Args:
+ revision_data_points: a list of bench data points
+
+ Returns:
+ a dictionary of this form:
+ keys = Label objects
+ values = the corresponding bench value
+ """
+ bench_dict = {}
+ for point in revision_data_points:
+ point_name = Label(point.bench,point.config,point.time_type,
+ point.settings)
+ if point_name not in bench_dict:
+ bench_dict[point_name] = point.time
+ else:
+ raise Exception('Duplicate expectation entry: ' + str(point_name))
+
+ return bench_dict
+
+def read_expectations(expectations, filename):
+ """Reads expectations data from file and put in expectations dict."""
+ for expectation in open(filename).readlines():
+ elements = expectation.strip().split(',')
+ if not elements[0] or elements[0].startswith('#'):
+ continue
+ if len(elements) != 5:
+ raise Exception("Invalid expectation line format: %s" %
+ expectation)
+ bench_entry = elements[0] + ',' + elements[1]
+ if bench_entry in expectations:
+ raise Exception("Dup entries for bench expectation %s" %
+ bench_entry)
+ # [<Bench_BmpConfig_TimeType>,<Platform-Alg>] -> (LB, UB, EXPECTED)
+ expectations[bench_entry] = (float(elements[LB_IDX]),
+ float(elements[UB_IDX]),
+ float(elements[EXPECTED_IDX]))
+
+def check_expectations(lines, expectations, key_suffix):
+ """Check if any bench results are outside of expected range.
+
+ For each input line in lines, checks the expectations dictionary to see if
+ the bench is out of the given range.
+
+ Args:
+ lines: dictionary mapping Label objects to the bench values.
+ expectations: dictionary returned by read_expectations().
+ key_suffix: string of <Platform>-<Alg> containing the bot platform and the
+ bench representation algorithm.
+
+ Returns:
+ No return value.
+
+ Raises:
+ Exception containing bench data that are out of range, if any.
+ """
+ # The platform for this bot, to pass to the dashboard plot.
+ platform = key_suffix[ : key_suffix.rfind('-')]
+ # Tuple of dictionaries recording exceptions that are slower and faster,
+ # respectively. Each dictionary maps off_ratio (ratio of actual to expected)
+ # to a list of corresponding exception messages.
+ exceptions = ({}, {})
+ for line in lines:
+ line_str = str(line)
+ line_str = line_str[ : line_str.find('_{')]
+ # Extracts bench and config from line_str, which is in the format
+ # <bench-picture-name>.skp_<config>_
+ bench, config = line_str.strip('_').split('.skp_')
+ bench_platform_key = line_str + ',' + key_suffix
+ if bench_platform_key not in expectations:
+ continue
+ this_bench_value = lines[line]
+ this_min, this_max, this_expected = expectations[bench_platform_key]
+ if this_bench_value < this_min or this_bench_value > this_max:
+ off_ratio = this_bench_value / this_expected
+ exception = 'Bench %s out of range [%s, %s] (%s vs %s, %s%%).' % (
+ bench_platform_key, this_min, this_max, this_bench_value,
+ this_expected, (off_ratio - 1) * 100)
+ exception += '\n' + '~'.join([
+ DASHBOARD_URL_PREFIX, bench, platform, config])
+ if off_ratio > 1: # Bench is slower.
+ exceptions[SLOWER].setdefault(off_ratio, []).append(exception)
+ else:
+ exceptions[FASTER].setdefault(off_ratio, []).append(exception)
+ outputs = []
+ for i in [SLOWER, FASTER]:
+ if exceptions[i]:
+ ratios = exceptions[i].keys()
+ ratios.sort(reverse=True)
+ li = []
+ for ratio in ratios:
+ li.extend(exceptions[i][ratio])
+ header = '%s benches got slower (sorted by %% difference):' % len(li)
+ if i == FASTER:
+ header = header.replace('slower', 'faster')
+ outputs.extend(['', header] + li)
+
+ if outputs:
+ # Directly raising Exception will have stderr outputs tied to the line
+ # number of the script, so use sys.stderr.write() instead.
+ # Add a trailing newline to supress new line checking errors.
+ sys.stderr.write('\n'.join(['Exception:'] + outputs + ['\n']))
+ exit(1)
+
+
+def main():
+ """Parses command line and checks bench expectations."""
+ try:
+ opts, _ = getopt.getopt(sys.argv[1:],
+ "a:b:d:e:r:",
+ "default-setting=")
+ except getopt.GetoptError, err:
+ print str(err)
+ usage()
+ sys.exit(2)
+
+ directory = None
+ bench_expectations = {}
+ rep = '25th' # bench representation algorithm, default to 25th
+ rev = None # git commit hash or svn revision number
+ bot = None
+
+ try:
+ for option, value in opts:
+ if option == "-a":
+ rep = value
+ elif option == "-b":
+ bot = value
+ elif option == "-d":
+ directory = value
+ elif option == "-e":
+ read_expectations(bench_expectations, value)
+ elif option == "-r":
+ rev = value
+ else:
+ usage()
+ assert False, "unhandled option"
+ except ValueError:
+ usage()
+ sys.exit(2)
+
+ if directory is None or bot is None or rev is None:
+ usage()
+ sys.exit(2)
+
+ platform_and_alg = bot + '-' + rep
+
+ data_points = bench_util.parse_skp_bench_data(directory, rev, rep)
+
+ bench_dict = create_bench_dict(data_points)
+
+ if bench_expectations:
+ check_expectations(bench_dict, bench_expectations, platform_and_alg)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/chromium/third_party/skia/bench/gUniqueGlyphIDs.h b/chromium/third_party/skia/bench/gUniqueGlyphIDs.h
new file mode 100644
index 00000000000..fe1c67a0950
--- /dev/null
+++ b/chromium/third_party/skia/bench/gUniqueGlyphIDs.h
@@ -0,0 +1,468 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+/* runs of unique glyph IDs, with a 0xFFFF sentinel between different runs
+ *
+ * Test data generated by examining web pages and their calls to drawText.
+ */
+static const uint16_t gUniqueGlyphIDs[] = {
+3, 41, 44, 50, 57, 58, 59, 60, 61, 62, 63, 64, 65, 68, 69, 70, 71, 72, 74, 75, 76, 77, 78, 81, 89, 90, 91, 92, 93, 94, 95, 96, 97, 100, 101, 102, 103, 104, 106, 107, 108, 109, 110, 111, 112, 113, 0xFFFF,
+3, 10, 11, 12, 13, 15, 16, 17, 19, 20, 21, 22, 23, 25, 27, 28, 29, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 50, 51, 53, 54, 55, 56, 57, 58, 60, 61, 66, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 175, 0xFFFF,
+3, 16, 17, 20, 21, 22, 25, 28, 35, 54, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 91, 92, 93, 0xFFFF,
+4, 37, 39, 40, 41, 43, 44, 50, 51, 52, 55, 56, 0xFFFF,
+3, 29, 68, 70, 76, 78, 79, 81, 82, 85, 86, 87, 88, 0xFFFF,
+3, 17, 29, 38, 39, 40, 41, 45, 47, 48, 50, 51, 54, 55, 58, 68, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 92, 0xFFFF,
+3, 15, 16, 18, 19, 28, 36, 40, 56, 68, 70, 71, 72, 73, 74, 75, 76, 77, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 92, 133, 0xFFFF,
+3, 16, 19, 20, 50, 68, 71, 72, 73, 74, 76, 79, 80, 81, 82, 85, 86, 87, 88, 89, 0xFFFF,
+3, 10, 16, 17, 19, 20, 21, 22, 25, 35, 36, 38, 39, 43, 44, 47, 48, 49, 50, 53, 54, 55, 60, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 92, 93, 95, 107, 0xFFFF,
+179, 0xFFFF,
+3, 36, 38, 55, 57, 59, 61, 63, 64, 65, 68, 69, 70, 71, 72, 74, 75, 76, 77, 78, 0xFFFF,
+3, 4, 9, 10, 11, 12, 15, 16, 17, 18, 19, 20, 21, 28, 29, 30, 32, 33, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 60, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 200, 201, 202, 203, 205, 206, 0xFFFF,
+3, 4, 17, 34, 36, 38, 39, 40, 41, 42, 43, 44, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 60, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 92, 0xFFFF,
+3, 40, 53, 54, 68, 70, 71, 72, 73, 74, 75, 76, 78, 79, 81, 82, 83, 85, 86, 87, 88, 89, 90, 91, 0xFFFF,
+3, 4, 11, 12, 15, 16, 17, 18, 29, 30, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 53, 54, 55, 56, 58, 60, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 200, 201, 203, 205, 206, 0xFFFF,
+1707, 3039, 3477, 23264, 29479, 33487, 0xFFFF,
+3, 19, 0xFFFF,
+3, 7, 10, 15, 16, 17, 19, 20, 23, 29, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 53, 54, 55, 56, 58, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 91, 92, 93, 181, 182, 0xFFFF,
+3, 40, 42, 43, 53, 55, 57, 0xFFFF,
+3, 58, 68, 72, 76, 85, 87, 89, 90, 0xFFFF,
+3, 5, 10, 15, 16, 17, 19, 20, 21, 29, 36, 38, 39, 41, 43, 47, 48, 50, 51, 53, 54, 55, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 92, 178, 0xFFFF,
+3, 17, 36, 38, 39, 42, 49, 53, 54, 57, 68, 70, 71, 72, 73, 75, 76, 79, 80, 81, 82, 85, 86, 87, 88, 0xFFFF,
+3, 40, 44, 47, 49, 50, 57, 58, 0xFFFF,
+3, 7, 10, 17, 19, 24, 26, 36, 37, 40, 41, 43, 48, 49, 50, 51, 53, 54, 56, 58, 60, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 92, 0xFFFF,
+3, 10, 38, 40, 41, 42, 43, 44, 48, 60, 68, 71, 72, 74, 75, 76, 80, 81, 82, 85, 86, 87, 88, 0xFFFF,
+3, 10, 54, 68, 73, 76, 81, 85, 88, 0xFFFF,
+3, 4, 6, 8, 11, 12, 13, 15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 28, 29, 30, 32, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 46, 47, 48, 49, 50, 53, 54, 55, 56, 57, 58, 59, 60, 62, 64, 66, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 96, 171, 177, 178, 179, 180, 181, 182, 397, 0xFFFF,
+7, 15, 16, 17, 18, 19, 20, 24, 25, 28, 64, 73, 0xFFFF,
+3, 9, 16, 36, 37, 38, 39, 40, 41, 44, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 60, 0xFFFF,
+3, 37, 50, 68, 69, 70, 78, 80, 85, 0xFFFF,
+3, 9, 36, 37, 39, 40, 43, 44, 46, 47, 48, 49, 50, 53, 54, 55, 56, 57, 58, 0xFFFF,
+3, 15, 19, 21, 22, 23, 25, 26, 28, 38, 42, 54, 68, 71, 72, 76, 81, 85, 86, 87, 0xFFFF,
+38, 45, 72, 74, 81, 82, 85, 86, 87, 0xFFFF,
+68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 0xFFFF,
+3, 47, 71, 72, 73, 76, 82, 83, 86, 87, 0xFFFF,
+3, 41, 49, 68, 72, 85, 86, 87, 88, 90, 0xFFFF,
+19, 20, 21, 23, 25, 26, 0xFFFF,
+3, 37, 57, 58, 59, 60, 61, 63, 64, 65, 68, 69, 70, 71, 72, 74, 75, 76, 77, 78, 79, 0xFFFF,
+41, 68, 72, 85, 86, 87, 88, 0xFFFF,
+3, 39, 41, 54, 68, 69, 70, 71, 72, 76, 79, 81, 82, 85, 86, 87, 88, 90, 0xFFFF,
+3, 5, 9, 10, 11, 12, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 106, 160, 161, 182, 0xFFFF,
+3, 16, 19, 28, 36, 38, 39, 40, 41, 42, 43, 44, 47, 49, 50, 51, 53, 54, 55, 56, 57, 58, 59, 0xFFFF,
+3, 9, 36, 41, 43, 47, 48, 50, 51, 53, 54, 55, 58, 68, 69, 70, 71, 72, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 91, 92, 178, 0xFFFF,
+3, 11, 12, 14, 15, 16, 17, 19, 20, 21, 24, 25, 27, 28, 29, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 53, 54, 55, 57, 58, 60, 61, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 91, 92, 93, 139, 140, 177, 0xFFFF,
+17, 51, 58, 70, 71, 72, 80, 82, 85, 86, 0xFFFF,
+37, 49, 68, 70, 72, 78, 87, 91, 0xFFFF,
+3, 11, 12, 17, 20, 36, 39, 41, 42, 44, 46, 47, 48, 49, 51, 54, 55, 58, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 91, 92, 0xFFFF,
+3, 9, 16, 17, 18, 29, 30, 36, 39, 40, 41, 42, 45, 46, 48, 49, 54, 55, 59, 60, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 0xFFFF,
+3, 16, 47, 68, 71, 72, 73, 75, 76, 78, 79, 81, 82, 83, 86, 87, 166, 0xFFFF,
+3, 9, 15, 17, 36, 45, 51, 55, 58, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 92, 0xFFFF,
+3, 9, 17, 19, 20, 21, 23, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 60, 0xFFFF,
+3, 7, 10, 15, 16, 19, 20, 21, 36, 37, 38, 41, 42, 43, 46, 47, 48, 49, 51, 53, 54, 55, 56, 58, 60, 68, 69, 70, 71, 72, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 91, 92, 93, 0xFFFF,
+17, 51, 58, 70, 71, 72, 80, 82, 85, 86, 0xFFFF,
+19, 20, 21, 22, 23, 24, 0xFFFF,
+3, 5, 10, 11, 12, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 64, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 112, 177, 182, 386, 387, 0xFFFF,
+7, 17, 19, 20, 21, 23, 24, 25, 26, 27, 28, 0xFFFF,
+3, 37, 38, 39, 40, 41, 42, 44, 45, 47, 49, 51, 53, 54, 55, 58, 68, 69, 70, 71, 72, 74, 75, 76, 78, 79, 80, 81, 82, 85, 86, 87, 88, 89, 90, 92, 95, 0xFFFF,
+3, 4, 16, 19, 20, 21, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 60, 0xFFFF,
+3, 4, 5, 6, 7, 9, 10, 11, 12, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 33, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 60, 61, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 135, 140, 171, 178, 179, 180, 182, 392, 393, 0xFFFF,
+3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 64, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 95, 97, 111, 112, 124, 133, 139, 140, 171, 177, 178, 179, 180, 181, 182, 194, 0xFFFF,
+3, 36, 38, 39, 40, 44, 46, 48, 50, 51, 55, 68, 69, 70, 71, 72, 73, 74, 75, 76, 79, 80, 81, 82, 83, 85, 86, 87, 88, 91, 92, 0xFFFF,
+3, 15, 16, 17, 20, 26, 29, 34, 36, 37, 38, 39, 41, 42, 43, 44, 46, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 60, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 92, 203, 0xFFFF,
+15, 19, 20, 23, 24, 25, 28, 0xFFFF,
+3, 11, 12, 15, 16, 17, 19, 21, 26, 28, 38, 39, 40, 41, 43, 45, 46, 49, 51, 53, 54, 56, 58, 60, 68, 69, 70, 71, 72, 73, 74, 75, 76, 79, 80, 81, 82, 83, 85, 86, 87, 90, 92, 131, 179, 180, 0xFFFF,
+3, 4, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 36, 37, 38, 39, 41, 42, 43, 44, 48, 50, 51, 53, 54, 55, 60, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 92, 93, 139, 0xFFFF,
+19, 20, 21, 22, 23, 24, 26, 44, 54, 70, 72, 74, 76, 79, 81, 82, 83, 85, 86, 87, 0xFFFF,
+3, 8, 9, 17, 19, 24, 36, 39, 41, 42, 49, 50, 51, 55, 60, 68, 70, 72, 73, 74, 75, 76, 78, 79, 80, 82, 85, 86, 87, 90, 95, 0xFFFF,
+41, 131, 0xFFFF,
+3, 15, 16, 17, 19, 21, 24, 25, 37, 40, 43, 47, 56, 58, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 92, 194, 0xFFFF,
+3, 19, 20, 21, 29, 36, 40, 41, 51, 70, 71, 72, 73, 74, 75, 76, 78, 79, 82, 85, 86, 87, 88, 92, 182, 0xFFFF,
+3, 5, 9, 10, 11, 12, 14, 15, 16, 17, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 60, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 91, 92, 108, 112, 124, 0xFFFF,
+23, 24, 0xFFFF,
+3, 11, 12, 15, 19, 22, 23, 28, 36, 38, 48, 57, 58, 68, 72, 75, 76, 81, 82, 85, 87, 88, 90, 0xFFFF,
+3, 15, 19, 21, 25, 26, 27, 28, 37, 50, 68, 69, 70, 78, 80, 85, 0xFFFF,
+3, 17, 48, 49, 55, 68, 70, 72, 74, 75, 76, 79, 81, 82, 83, 85, 86, 87, 88, 92, 0xFFFF,
+3, 25, 28, 29, 30, 32, 33, 36, 37, 38, 40, 41, 42, 43, 44, 45, 46, 47, 48, 50, 51, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 200, 201, 202, 203, 204, 0xFFFF,
+3, 5, 15, 16, 19, 20, 21, 22, 27, 29, 34, 36, 37, 39, 40, 41, 43, 44, 45, 46, 47, 48, 49, 50, 51, 53, 54, 55, 57, 59, 60, 61, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 91, 92, 134, 166, 184, 190, 214, 0xFFFF,
+3, 4, 17, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 60, 61, 68, 70, 71, 72, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 91, 92, 93, 170, 0xFFFF,
+3, 10, 16, 17, 19, 20, 21, 22, 29, 34, 36, 37, 38, 41, 42, 44, 46, 47, 48, 49, 50, 53, 54, 55, 56, 58, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 0xFFFF,
+3, 14, 36, 37, 38, 39, 40, 42, 43, 44, 46, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 0xFFFF,
+16, 35, 68, 70, 71, 72, 73, 76, 80, 81, 82, 87, 0xFFFF,
+3, 6, 15, 17, 18, 19, 20, 21, 26, 29, 36, 37, 38, 50, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 0xFFFF,
+17, 48, 60, 76, 78, 82, 85, 86, 88, 503, 522, 525, 528, 534, 536, 537, 538, 544, 551, 0xFFFF,
+3, 11, 12, 15, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 36, 37, 38, 41, 42, 43, 45, 46, 47, 48, 49, 50, 53, 54, 55, 58, 68, 69, 70, 71, 72, 73, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 91, 92, 93, 0xFFFF,
+17, 20, 23, 24, 25, 27, 28, 0xFFFF,
+3, 8, 11, 12, 15, 16, 19, 20, 21, 22, 23, 24, 25, 28, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 90, 91, 92, 0xFFFF,
+3, 4, 6, 7, 8, 9, 10, 11, 12, 15, 17, 19, 20, 25, 29, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 47, 48, 49, 50, 51, 53, 54, 55, 56, 58, 60, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 91, 92, 179, 180, 182, 0xFFFF,
+3, 11, 12, 19, 20, 21, 37, 49, 51, 53, 54, 68, 69, 70, 71, 72, 76, 78, 79, 80, 81, 82, 85, 87, 88, 89, 112, 130, 193, 0xFFFF,
+3, 37, 42, 49, 57, 68, 70, 71, 72, 76, 78, 82, 87, 88, 91, 0xFFFF,
+3, 200, 0xFFFF,
+3, 18, 29, 39, 43, 49, 68, 72, 76, 79, 80, 81, 82, 86, 87, 0xFFFF,
+3, 5, 15, 16, 19, 22, 25, 26, 29, 36, 40, 41, 43, 46, 48, 49, 51, 54, 55, 59, 60, 66, 68, 71, 72, 75, 76, 77, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 92, 166, 184, 214, 0xFFFF,
+4, 5, 11, 16, 20, 21, 22, 23, 24, 27, 28, 29, 30, 37, 38, 39, 40, 41, 42, 44, 45, 50, 52, 54, 55, 56, 57, 59, 69, 70, 71, 72, 73, 74, 75, 76, 77, 79, 80, 81, 82, 83, 84, 86, 87, 88, 89, 90, 91, 92, 93, 0xFFFF,
+3, 40, 53, 54, 68, 69, 70, 71, 72, 75, 76, 79, 80, 81, 82, 85, 86, 87, 88, 89, 92, 0xFFFF,
+38, 51, 68, 72, 74, 76, 78, 79, 81, 82, 85, 86, 87, 0xFFFF,
+3, 11, 12, 48, 72, 82, 85, 170, 0xFFFF,
+3, 29, 36, 38, 39, 49, 53, 54, 68, 69, 70, 71, 72, 73, 74, 75, 76, 79, 80, 81, 82, 83, 85, 86, 87, 88, 0xFFFF,
+3, 6, 15, 20, 36, 53, 54, 55, 56, 68, 70, 71, 72, 73, 76, 79, 80, 81, 82, 85, 86, 87, 88, 89, 92, 0xFFFF,
+3, 4, 10, 16, 19, 20, 21, 22, 23, 29, 34, 36, 37, 38, 39, 40, 41, 42, 43, 47, 49, 53, 54, 55, 57, 58, 60, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 0xFFFF,
+3, 4, 7, 9, 10, 11, 12, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 95, 171, 182, 314, 376, 377, 390, 0xFFFF,
+3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 64, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 98, 105, 106, 107, 110, 111, 112, 114, 116, 117, 121, 122, 123, 124, 126, 127, 170, 171, 179, 180, 182, 190, 213, 255, 259, 264, 458, 533, 1133, 1189, 1191, 1193, 1195, 1197, 1199, 1201, 1203, 1209, 1215, 1219, 1221, 1223, 1227, 1229, 1231, 1233, 1235, 1237, 1239, 1243, 1245, 1247, 1249, 1251, 1255, 1257, 1259, 1261, 1263, 1265, 1267, 1269, 1273, 1275, 0xFFFF,
+3, 4, 5, 6, 8, 9, 10, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 62, 64, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 95, 98, 105, 106, 107, 108, 109, 111, 112, 114, 116, 117, 121, 123, 126, 129, 131, 138, 139, 170, 182, 188, 208, 213, 247, 250, 255, 259, 264, 570, 573, 574, 581, 582, 583, 584, 586, 587, 588, 594, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 627, 629, 630, 633, 1131, 1133, 1189, 1191, 1193, 1195, 1199, 1201, 1211, 1213, 1219, 1221, 1223, 1227, 1231, 1233, 1235, 1237, 1239, 1243, 1245, 1247, 1249, 1255, 1259, 1261, 1265, 1267, 1269, 1275, 0xFFFF,
+3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 66, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 97, 105, 106, 107, 109, 111, 112, 114, 116, 117, 121, 123, 126, 127, 129, 138, 170, 177, 179, 180, 182, 194, 213, 247, 248, 255, 259, 264, 377, 378, 429, 484, 1131, 1133, 1189, 1190, 1191, 1193, 1195, 1201, 1203, 1211, 1215, 1219, 1221, 1223, 1225, 1227, 1231, 1235, 1237, 1239, 1241, 1245, 1247, 1249, 1251, 1255, 1257, 1259, 1261, 1263, 1265, 1267, 1269, 1275, 0xFFFF,
+3, 10, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 33, 36, 37, 38, 39, 40, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 59, 62, 64, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 92, 93, 98, 101, 103, 120, 131, 182, 255, 264, 313, 1133, 1255, 0xFFFF,
+53, 54, 56, 0xFFFF,
+3, 10, 16, 19, 20, 21, 25, 27, 29, 34, 37, 39, 42, 43, 44, 50, 51, 54, 55, 57, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 92, 93, 0xFFFF,
+3, 5, 7, 9, 10, 15, 16, 17, 19, 20, 21, 22, 23, 24, 25, 26, 30, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 60, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 178, 0xFFFF,
+3, 16, 54, 71, 72, 75, 82, 84, 87, 88, 90, 91, 378, 0xFFFF,
+3, 8, 15, 16, 17, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 36, 37, 38, 39, 41, 44, 47, 48, 51, 54, 55, 56, 58, 62, 64, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 91, 92, 93, 112, 130, 138, 193, 0xFFFF,
+23, 41, 131, 0xFFFF,
+3, 40, 41, 49, 54, 68, 72, 74, 76, 79, 80, 81, 82, 83, 85, 86, 87, 88, 90, 0xFFFF,
+3, 9, 68, 70, 71, 72, 76, 79, 81, 82, 83, 85, 86, 87, 88, 92, 0xFFFF,
+40, 49, 55, 68, 70, 72, 73, 76, 80, 81, 82, 85, 86, 0xFFFF,
+3, 0xFFFF,
+3, 5, 9, 10, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 95, 135, 0xFFFF,
+3, 38, 48, 51, 55, 56, 58, 68, 69, 71, 72, 73, 76, 79, 80, 81, 82, 85, 86, 87, 88, 0xFFFF,
+3, 15, 17, 36, 38, 40, 42, 44, 48, 49, 50, 51, 53, 56, 0xFFFF,
+3, 11, 12, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 39, 42, 51, 53, 62, 64, 68, 69, 71, 72, 73, 75, 76, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 0xFFFF,
+388, 418, 882, 883, 885, 886, 910, 913, 917, 921, 923, 925, 928, 929, 934, 936, 938, 939, 940, 944, 952, 954, 955, 964, 966, 969, 974, 984, 1011, 1022, 1032, 1037, 1042, 1046, 1050, 1056, 1060, 1066, 1073, 1082, 1083, 1095, 1096, 1098, 1101, 1102, 1103, 1105, 1106, 1107, 1109, 1111, 1114, 1115, 1117, 1121, 1125, 1128, 1130, 1132, 1135, 1144, 1146, 1150, 1154, 1165, 1166, 1167, 1172, 1175, 1177, 1179, 1180, 1185, 1198, 1199, 1203, 1206, 1207, 1220, 1233, 1235, 1236, 1264, 1270, 1272, 1274, 1281, 1291, 1293, 1297, 1298, 1300, 1307, 1313, 1314, 1318, 1320, 1321, 1322, 1333, 1334, 1347, 1350, 1354, 1362, 1376, 1378, 1390, 1406, 1407, 1409, 1410, 1414, 1418, 1427, 1429, 1430, 1438, 1440, 1442, 1443, 1447, 1453, 1456, 1458, 1461, 1464, 1466, 1478, 1483, 1484, 1491, 1502, 1508, 1509, 1511, 1516, 1528, 1533, 1541, 1554, 1555, 1556, 1568, 1573, 1574, 1579, 1580, 1592, 1599, 1600, 1607, 1614, 1615, 1616, 1625, 1627, 1629, 1652, 1653, 1657, 1659, 1660, 1663, 1667, 1668, 1670, 1673, 1677, 1679, 1691, 1692, 1693, 1694, 1696, 1700, 1706, 1709, 1713, 1719, 1724, 1730, 1733, 1734, 1740, 1744, 1747, 1750, 1752, 1755, 1758, 1762, 1765, 1771, 1775, 1777, 1781, 1788, 1789, 1790, 1791, 1792, 1796, 1800, 1803, 1805, 1808, 1822, 1826, 1831, 1844, 1849, 1853, 1858, 1860, 1863, 1864, 1879, 1880, 1882, 1885, 1897, 1898, 1914, 1919, 1929, 1932, 1953, 1955, 1956, 1958, 1960, 1963, 1965, 1966, 1969, 1972, 1977, 1994, 1999, 2003, 2004, 2005, 2006, 2007, 2010, 2011, 2018, 2030, 2033, 2036, 2057, 2059, 2061, 2063, 2079, 2081, 2085, 2090, 2092, 2096, 2098, 2101, 2104, 2108, 2109, 2110, 2113, 2125, 2127, 2128, 2130, 2138, 2149, 2153, 2154, 2159, 2165, 2174, 2175, 2182, 2188, 2196, 2199, 2201, 2202, 2209, 2211, 2230, 2235, 2237, 2256, 2257, 2264, 2270, 2271, 2274, 2275, 2294, 2296, 2302, 2303, 2304, 2308, 2309, 2310, 2312, 2314, 2318, 2320, 2321, 2327, 2329, 2331, 2332, 2333, 2334, 2339, 2343, 2349, 2357, 2358, 2369, 2378, 2387, 2389, 2390, 2392, 2396, 2397, 2398, 2400, 2407, 2408, 2409, 2410, 2413, 2416, 2430, 2437, 2441, 2446, 2448, 2450, 2456, 2477, 2480, 2482, 2484, 2487, 2493, 2497, 2518, 2522, 2524, 2538, 2539, 2542, 2545, 2555, 2563, 2564, 2565, 2575, 2576, 2579, 2584, 2588, 2589, 2593, 2597, 2598, 2602, 2610, 2623, 2630, 2635, 2640, 2641, 2642, 2643, 2645, 2661, 2665, 2668, 2670, 2693, 2699, 2707, 2708, 2709, 2712, 2715, 2735, 2736, 2742, 2748, 2753, 2759, 2761, 2768, 2771, 2781, 2784, 2786, 2794, 2795, 2797, 2803, 2823, 2826, 2835, 2836, 2837, 2838, 2840, 2841, 2842, 2847, 2848, 2863, 2874, 2876, 2877, 2889, 2890, 2899, 2901, 2904, 2905, 2910, 2914, 2916, 2922, 2927, 2928, 2929, 2938, 2942, 2946, 2947, 2949, 2959, 2963, 2964, 2966, 2968, 2969, 2979, 2982, 3011, 3017, 3025, 3027, 3028, 3030, 3031, 3036, 3039, 3041, 3042, 3045, 3055, 3056, 3069, 3070, 3073, 3076, 3082, 3084, 3088, 3092, 3096, 3100, 3102, 3103, 3108, 3112, 3120, 3123, 3131, 3164, 3166, 3176, 3198, 3200, 3205, 3208, 3210, 3214, 3216, 3217, 3219, 3222, 3229, 3248, 3249, 3257, 3258, 3259, 3263, 3264, 3265, 3271, 3276, 3281, 3282, 3283, 3284, 3286, 3288, 3294, 3296, 3299, 3301, 3313, 3316, 3320, 3323, 3324, 3325, 3333, 3335, 3343, 3347, 3348, 3353, 3354, 3362, 3367, 3371, 3373, 3375, 3384, 3388, 3391, 3399, 3406, 3413, 3415, 3416, 3418, 3429, 3445, 3447, 3450, 3453, 3455, 3458, 3461, 3466, 3469, 3477, 3487, 3501, 3503, 3510, 3528, 3529, 3530, 3531, 3532, 3541, 3543, 3545, 3551, 3555, 3558, 3565, 3567, 3569, 3571, 3582, 3591, 3594, 3598, 3603, 3610, 3612, 3618, 3620, 3628, 3630, 3639, 3651, 3654, 3658, 3660, 3665, 3680, 3681, 3683, 3686, 3691, 3693, 3698, 3705, 3706, 3707, 3712, 3713, 3719, 3722, 3724, 3726, 3733, 3736, 3743, 3750, 3754, 3763, 3764, 3786, 3795, 3802, 3805, 3814, 3816, 3819, 3827, 3828, 3830, 3854, 3856, 3860, 3863, 3875, 3896, 3925, 3926, 3930, 3941, 3946, 3949, 3951, 3965, 3970, 3999, 4047, 4063, 4086, 4104, 4125, 4133, 4146, 4185, 4204, 4222, 4226, 4273, 4285, 4317, 4354, 4366, 4370, 4374, 4378, 4391, 4396, 4397, 4398, 4406, 4412, 4480, 4495, 4504, 4531, 4606, 4666, 4673, 4678, 4695, 4710, 4712, 4721, 4729, 4769, 4770, 4788, 4794, 4804, 4808, 4810, 4816, 4819, 4827, 4830, 4834, 4861, 4895, 4919, 4926, 4985, 5010, 5014, 5033, 5034, 5047, 5065, 5097, 5103, 5136, 5149, 5180, 5224, 5245, 5281, 5306, 5313, 5355, 5398, 5452, 5475, 5478, 5540, 5558, 5563, 5654, 5655, 5681, 5687, 5691, 5695, 5700, 5705, 5757, 5762, 5777, 5838, 5851, 5867, 5902, 5998, 6016, 6054, 6055, 6058, 6076, 6104, 6108, 6129, 6163, 6220, 6221, 6226, 6335, 6403, 6405, 6445, 6472, 6482, 6496, 6522, 6550, 6640, 6678, 6679, 6683, 6684, 6712, 6721, 6753, 6760, 6794, 6809, 6837, 6838, 6853, 6862, 6878, 6881, 6897, 6915, 6989, 7014, 7029, 7141, 7192, 7355, 7362, 7588, 7617, 7760, 8047, 8065, 8078, 8084, 8090, 8097, 8113, 8116, 8118, 8122, 8136, 8178, 8181, 8222, 8327, 8623, 8723, 8852, 8878, 8945, 9364, 9505, 9786, 10296, 12427, 12429, 12430, 12432, 12434, 12435, 12449, 12450, 12459, 12460, 12461, 12462, 13236, 13857, 15066, 16495, 17497, 20320, 22577, 0xFFFF,
+3, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 91, 92, 93, 95, 178, 179, 180, 181, 182, 0xFFFF,
+1, 13, 21, 25, 32, 42, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 83, 84, 85, 86, 88, 89, 0xFFFF,
+1, 8, 13, 14, 25, 27, 34, 36, 45, 48, 49, 51, 52, 53, 55, 56, 66, 67, 68, 69, 70, 71, 72, 73, 74, 76, 77, 78, 79, 80, 81, 83, 84, 85, 86, 87, 88, 90, 0xFFFF,
+3, 10, 55, 68, 74, 75, 76, 78, 81, 83, 84, 86, 87, 88, 92, 106, 121, 1201, 1203, 1219, 1237, 1247, 0xFFFF,
+20, 21, 26, 0xFFFF,
+3, 19, 20, 21, 22, 38, 41, 42, 44, 55, 58, 68, 69, 70, 72, 75, 76, 79, 81, 82, 85, 86, 87, 0xFFFF,
+4, 16, 23, 29, 30, 37, 38, 39, 41, 43, 44, 45, 46, 48, 50, 51, 54, 55, 56, 59, 69, 71, 72, 73, 75, 76, 77, 79, 80, 82, 83, 84, 86, 88, 89, 91, 93, 0xFFFF,
+3, 15, 17, 40, 50, 55, 68, 69, 70, 71, 72, 73, 74, 75, 76, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 0xFFFF,
+68, 72, 73, 76, 79, 82, 83, 85, 87, 89, 90, 92, 0xFFFF,
+40, 49, 55, 68, 70, 72, 73, 76, 80, 81, 82, 85, 86, 0xFFFF,
+16, 68, 69, 71, 72, 74, 76, 78, 81, 85, 87, 90, 0xFFFF,
+3, 16, 17, 18, 27, 28, 35, 42, 45, 51, 58, 68, 70, 71, 72, 73, 75, 76, 79, 80, 81, 82, 83, 85, 86, 87, 89, 171, 0xFFFF,
+3, 51, 53, 71, 72, 78, 80, 81, 82, 112, 0xFFFF,
+3, 4, 16, 19, 20, 21, 38, 51, 55, 68, 69, 70, 71, 72, 73, 74, 75, 76, 80, 81, 82, 83, 85, 86, 87, 90, 92, 139, 0xFFFF,
+3, 36, 38, 39, 40, 41, 43, 44, 47, 49, 51, 53, 54, 55, 57, 58, 68, 69, 70, 71, 72, 75, 76, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 0xFFFF,
+3, 37, 38, 39, 43, 44, 51, 68, 71, 72, 74, 76, 79, 80, 81, 82, 83, 85, 86, 87, 88, 92, 0xFFFF,
+3, 6, 7, 8, 9, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 33, 34, 35, 36, 37, 38, 40, 42, 43, 44, 45, 46, 47, 48, 49, 50, 52, 53, 54, 55, 56, 57, 59, 60, 61, 62, 63, 64, 65, 66, 74, 76, 89, 0xFFFF,
+3, 39, 41, 43, 48, 54, 55, 68, 70, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 92, 93, 0xFFFF,
+3, 11, 12, 16, 17, 38, 70, 72, 73, 75, 76, 78, 79, 81, 82, 83, 85, 86, 87, 88, 89, 93, 0xFFFF,
+3, 17, 18, 29, 40, 41, 51, 55, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 91, 92, 111, 114, 120, 129, 170, 0xFFFF,
+3, 29, 48, 51, 58, 68, 70, 71, 73, 76, 79, 81, 82, 85, 86, 87, 0xFFFF,
+40, 48, 49, 51, 54, 92, 0xFFFF,
+14, 20, 21, 22, 0xFFFF,
+226, 250, 258, 262, 267, 268, 275, 281, 286, 289, 383, 384, 387, 913, 939, 952, 1046, 1065, 1094, 1107, 1109, 1147, 1344, 1724, 1803, 1806, 1858, 1914, 2081, 2125, 2134, 2264, 2303, 2308, 2310, 2312, 2334, 2357, 2397, 2407, 2551, 2580, 2641, 2642, 2711, 2735, 2784, 2826, 2863, 2910, 2974, 3039, 3076, 3229, 3249, 3271, 3354, 3466, 3503, 3528, 3677, 3707, 3723, 3802, 4285, 4496, 4606, 4729, 5033, 6405, 6901, 8623, 10275, 10606, 12465, 12466, 13615, 14453, 14460, 17761, 17813, 17830, 17834, 18124, 20381, 21531, 0xFFFF,
+3, 6, 7, 8, 9, 10, 11, 12, 16, 17, 18, 19, 20, 21, 22, 23, 24, 26, 27, 28, 29, 30, 31, 33, 34, 35, 36, 38, 39, 40, 44, 45, 46, 50, 56, 57, 67, 89, 101, 0xFFFF,
+3, 4, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 25, 27, 29, 34, 36, 37, 38, 40, 41, 42, 43, 44, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 60, 66, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 97, 163, 179, 180, 182, 213, 247, 397, 0xFFFF,
+1, 2, 8, 15, 27, 34, 37, 38, 42, 49, 52, 53, 55, 66, 67, 68, 69, 70, 71, 72, 73, 74, 77, 78, 79, 80, 81, 83, 84, 85, 86, 87, 88, 90, 0xFFFF,
+3, 16, 18, 19, 20, 21, 22, 23, 28, 55, 68, 70, 72, 73, 76, 80, 81, 82, 85, 86, 0xFFFF,
+3, 19, 20, 21, 27, 29, 36, 38, 42, 44, 46, 51, 54, 55, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 92, 182, 0xFFFF,
+3, 4, 6, 17, 20, 22, 23, 24, 29, 38, 40, 42, 43, 44, 48, 49, 51, 54, 55, 57, 60, 68, 70, 71, 72, 73, 74, 75, 76, 79, 80, 81, 82, 85, 86, 87, 88, 89, 90, 177, 179, 180, 182, 0xFFFF,
+3, 10, 38, 39, 40, 43, 44, 46, 50, 51, 53, 54, 55, 0xFFFF,
+3, 82, 85, 0xFFFF,
+3, 38, 42, 45, 46, 55, 60, 66, 101, 0xFFFF,
+4, 10, 15, 17, 20, 21, 22, 23, 26, 37, 38, 39, 40, 41, 42, 43, 44, 45, 48, 50, 51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 69, 70, 72, 73, 74, 75, 77, 79, 80, 82, 83, 84, 86, 87, 88, 89, 90, 91, 92, 93, 0xFFFF,
+54, 68, 70, 72, 75, 85, 0xFFFF,
+20, 21, 22, 23, 24, 25, 26, 27, 0xFFFF,
+3, 5, 11, 12, 13, 15, 16, 17, 21, 29, 36, 37, 38, 39, 40, 41, 42, 43, 44, 47, 48, 49, 50, 51, 53, 54, 55, 57, 58, 60, 61, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 112, 0xFFFF,
+3, 15, 17, 20, 21, 22, 24, 25, 26, 27, 28, 40, 42, 57, 58, 70, 71, 72, 73, 74, 79, 81, 82, 85, 87, 88, 91, 92, 0xFFFF,
+3, 17, 40, 51, 68, 69, 70, 78, 79, 82, 85, 92, 0xFFFF,
+388, 1073, 1083, 1316, 1329, 1458, 1531, 1609, 1612, 1707, 1795, 1806, 1858, 2007, 2079, 2092, 2201, 2224, 2497, 2565, 2643, 2735, 2781, 2833, 2834, 2920, 3039, 3056, 3229, 3347, 3477, 9068, 9093, 9095, 9097, 9100, 9101, 9104, 9106, 9108, 9111, 9112, 9114, 9116, 9120, 9128, 9129, 9132, 9135, 9139, 9160, 9164, 9165, 9166, 9168, 9171, 9172, 9182, 9183, 9184, 9186, 9190, 9193, 9195, 9196, 9197, 9198, 9199, 9201, 9203, 9205, 9206, 9207, 9208, 9211, 9212, 9215, 9220, 9221, 9228, 9229, 9231, 9233, 9235, 9237, 9241, 9244, 9245, 9246, 9247, 9248, 9249, 9251, 9253, 9255, 9256, 9257, 9263, 12435, 12461, 12462, 12468, 12490, 12494, 12495, 12496, 12497, 12498, 12499, 12500, 12501, 12502, 12503, 0xFFFF,
+19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 62, 64, 0xFFFF,
+36, 37, 38, 39, 40, 41, 43, 44, 50, 51, 53, 54, 55, 56, 57, 58, 0xFFFF,
+3, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 33, 68, 72, 74, 80, 86, 0xFFFF,
+3, 19, 20, 21, 24, 38, 54, 68, 71, 74, 75, 76, 80, 81, 82, 85, 88, 169, 170, 183, 0xFFFF,
+3, 15, 19, 21, 22, 23, 27, 37, 39, 54, 61, 68, 69, 72, 74, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 93, 183, 314, 0xFFFF,
+3, 8, 10, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 60, 61, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 105, 106, 107, 109, 111, 114, 116, 117, 121, 122, 123, 124, 126, 127, 129, 139, 181, 213, 247, 248, 250, 255, 259, 264, 458, 1133, 1191, 1193, 1195, 1201, 1211, 1219, 1221, 1225, 1227, 1229, 1231, 1233, 1235, 1237, 1245, 1247, 1249, 1259, 1261, 1263, 1273, 1275, 0xFFFF,
+4, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 61, 69, 70, 71, 72, 73, 75, 76, 77, 79, 80, 81, 82, 83, 84, 86, 87, 88, 89, 180, 0xFFFF,
+3, 0xFFFF,
+21, 23, 0xFFFF,
+1, 7, 52, 66, 68, 69, 70, 73, 74, 77, 80, 81, 83, 84, 85, 86, 0xFFFF,
+3, 54, 70, 72, 80, 81, 82, 85, 87, 0xFFFF,
+3, 38, 40, 42, 50, 53, 54, 57, 0xFFFF,
+17, 19, 20, 26, 27, 28, 0xFFFF,
+3, 5, 16, 29, 34, 488, 489, 491, 492, 496, 498, 500, 501, 505, 506, 507, 509, 512, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 547, 548, 549, 550, 551, 0xFFFF,
+3, 37, 40, 48, 68, 72, 75, 76, 79, 81, 82, 83, 85, 86, 87, 91, 0xFFFF,
+3, 10, 36, 39, 40, 41, 43, 44, 50, 53, 54, 55, 57, 0xFFFF,
+3, 43, 68, 72, 76, 78, 79, 80, 81, 82, 85, 86, 87, 88, 89, 92, 166, 242, 0xFFFF,
+3, 11, 12, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 54, 68, 72, 81, 82, 86, 177, 0xFFFF,
+3, 4, 17, 22, 34, 38, 44, 45, 48, 51, 54, 55, 68, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 92, 93, 0xFFFF,
+3, 10, 11, 12, 16, 17, 19, 20, 23, 24, 25, 26, 27, 28, 29, 36, 37, 38, 40, 42, 43, 44, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 60, 68, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 92, 93, 138, 314, 0xFFFF,
+3, 40, 59, 68, 69, 70, 71, 72, 78, 79, 81, 82, 83, 85, 86, 87, 89, 91, 92, 0xFFFF,
+1, 13, 56, 66, 69, 70, 73, 79, 80, 83, 84, 85, 0xFFFF,
+1, 14, 23, 25, 27, 32, 36, 37, 38, 45, 47, 49, 51, 52, 53, 56, 57, 66, 67, 68, 69, 70, 71, 73, 74, 76, 77, 78, 79, 80, 81, 83, 84, 85, 86, 87, 88, 90, 91, 0xFFFF,
+3, 48, 72, 82, 85, 170, 0xFFFF,
+1, 8, 13, 27, 34, 38, 39, 41, 42, 45, 47, 48, 49, 52, 53, 56, 57, 66, 67, 68, 69, 70, 71, 72, 73, 74, 76, 77, 78, 79, 80, 81, 83, 84, 85, 86, 87, 88, 90, 0xFFFF,
+3, 4, 5, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 29, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 64, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 100, 109, 111, 112, 116, 121, 123, 171, 177, 179, 180, 182, 225, 229, 252, 268, 286, 0xFFFF,
+3, 15, 16, 17, 19, 20, 21, 22, 23, 27, 28, 29, 36, 37, 40, 44, 46, 47, 48, 49, 54, 56, 60, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 111, 213, 0xFFFF,
+3, 15, 20, 21, 39, 41, 55, 68, 70, 71, 72, 76, 85, 86, 87, 90, 92, 0xFFFF,
+3, 16, 28, 37, 38, 42, 46, 51, 53, 54, 55, 57, 59, 68, 70, 71, 72, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 92, 105, 106, 107, 109, 116, 117, 121, 122, 123, 208, 234, 255, 259, 1133, 1189, 1190, 1191, 1193, 1201, 1211, 1219, 1221, 1223, 1233, 1235, 1237, 1241, 1245, 1247, 1249, 1261, 1269, 1273, 0xFFFF,
+3, 20, 29, 39, 41, 42, 50, 55, 68, 72, 73, 74, 75, 76, 78, 79, 80, 81, 85, 86, 87, 1193, 0xFFFF,
+1, 42, 52, 66, 67, 68, 69, 70, 72, 73, 74, 76, 77, 78, 79, 80, 81, 83, 84, 85, 87, 90, 0xFFFF,
+3, 4, 11, 12, 14, 15, 16, 17, 19, 20, 23, 26, 28, 37, 38, 39, 40, 48, 49, 54, 56, 58, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 85, 86, 87, 88, 89, 90, 92, 135, 0xFFFF,
+1, 8, 27, 34, 38, 52, 53, 66, 67, 68, 69, 70, 72, 73, 74, 75, 78, 79, 80, 83, 84, 85, 86, 87, 88, 90, 0xFFFF,
+3, 40, 55, 68, 71, 72, 75, 76, 79, 80, 85, 86, 87, 0xFFFF,
+7, 15, 17, 19, 20, 21, 22, 23, 24, 28, 0xFFFF,
+3, 10, 19, 25, 38, 41, 54, 68, 70, 71, 72, 76, 81, 82, 85, 86, 87, 131, 0xFFFF,
+3, 55, 60, 69, 71, 72, 81, 82, 85, 86, 88, 0xFFFF,
+19, 20, 21, 22, 25, 26, 27, 0xFFFF,
+3, 36, 39, 40, 41, 42, 44, 47, 48, 49, 50, 53, 54, 55, 56, 57, 58, 0xFFFF,
+3, 9, 10, 11, 12, 16, 17, 18, 20, 21, 23, 26, 29, 33, 36, 37, 38, 39, 40, 41, 42, 43, 44, 46, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 61, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 90, 91, 92, 93, 0xFFFF,
+3, 170, 0xFFFF,
+3, 14, 24, 36, 37, 38, 39, 40, 41, 42, 43, 44, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 60, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 92, 93, 0xFFFF,
+3, 47, 51, 73, 76, 78, 80, 81, 82, 86, 87, 112, 0xFFFF,
+1, 7, 12, 17, 18, 19, 34, 35, 36, 37, 38, 39, 40, 41, 43, 45, 46, 49, 51, 52, 53, 54, 55, 56, 58, 66, 67, 68, 69, 70, 71, 72, 73, 74, 76, 77, 78, 79, 80, 81, 83, 84, 85, 86, 87, 88, 90, 0xFFFF,
+3, 16, 20, 24, 27, 28, 34, 35, 0xFFFF,
+3, 17, 34, 37, 41, 53, 58, 68, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 92, 0xFFFF,
+3, 42, 44, 50, 68, 70, 71, 72, 74, 75, 76, 80, 81, 82, 83, 85, 86, 87, 88, 92, 179, 180, 182, 0xFFFF,
+3, 40, 43, 55, 0xFFFF,
+4, 30, 41, 52, 56, 69, 71, 72, 73, 74, 75, 76, 80, 82, 83, 84, 86, 88, 92, 0xFFFF,
+1, 2, 8, 13, 14, 17, 18, 19, 20, 27, 34, 35, 36, 37, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 51, 52, 53, 54, 55, 56, 58, 59, 66, 67, 68, 69, 70, 71, 72, 73, 74, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 0xFFFF,
+1, 14, 18, 25, 37, 53, 66, 69, 70, 72, 73, 74, 77, 78, 79, 80, 83, 84, 85, 86, 88, 0xFFFF,
+3, 17, 29, 37, 42, 47, 48, 50, 51, 54, 57, 58, 68, 70, 71, 72, 73, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 92, 112, 0xFFFF,
+3, 39, 44, 47, 51, 54, 70, 72, 76, 79, 87, 0xFFFF,
+1, 2, 8, 9, 10, 13, 14, 15, 17, 18, 19, 20, 25, 26, 27, 34, 37, 38, 42, 45, 46, 48, 49, 51, 52, 53, 55, 56, 57, 66, 67, 68, 69, 70, 71, 72, 73, 74, 77, 78, 79, 80, 81, 83, 84, 85, 86, 87, 88, 89, 90, 0xFFFF,
+3, 41, 44, 48, 50, 51, 53, 54, 55, 56, 0xFFFF,
+3, 5, 15, 17, 36, 37, 38, 39, 40, 41, 42, 43, 44, 46, 47, 49, 50, 51, 53, 54, 55, 56, 57, 58, 59, 60, 0xFFFF,
+3, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 36, 38, 39, 40, 44, 47, 49, 50, 53, 54, 55, 58, 60, 0xFFFF,
+3, 41, 54, 68, 79, 81, 82, 90, 0xFFFF,
+3, 38, 48, 50, 68, 72, 73, 75, 76, 80, 81, 82, 83, 85, 86, 87, 88, 92, 0xFFFF,
+3, 5, 17, 36, 37, 38, 39, 40, 41, 42, 43, 44, 47, 49, 50, 51, 53, 54, 55, 56, 58, 60, 0xFFFF,
+1, 2, 8, 13, 14, 15, 17, 18, 19, 23, 25, 26, 27, 34, 36, 37, 38, 39, 40, 41, 42, 46, 47, 48, 49, 51, 52, 53, 54, 55, 56, 58, 66, 67, 68, 69, 70, 71, 72, 73, 74, 76, 77, 78, 79, 80, 81, 83, 84, 85, 86, 87, 88, 90, 0xFFFF,
+3, 48, 50, 51, 54, 68, 69, 70, 72, 75, 76, 79, 81, 82, 83, 85, 86, 87, 88, 93, 0xFFFF,
+3, 37, 40, 42, 43, 44, 49, 50, 53, 54, 55, 57, 60, 0xFFFF,
+3, 10, 15, 16, 17, 19, 20, 34, 36, 37, 38, 39, 41, 42, 48, 49, 51, 53, 58, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 92, 182, 0xFFFF,
+3, 15, 16, 17, 40, 41, 44, 47, 58, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 92, 0xFFFF,
+3, 51, 65, 70, 72, 76, 78, 80, 81, 82, 83, 86, 112, 0xFFFF,
+3, 38, 40, 44, 48, 49, 50, 53, 54, 55, 57, 58, 0xFFFF,
+3, 17, 38, 39, 40, 41, 48, 49, 53, 55, 57, 68, 71, 72, 76, 79, 81, 82, 85, 86, 88, 89, 90, 0xFFFF,
+54, 76, 78, 79, 82, 86, 88, 0xFFFF,
+3, 95, 0xFFFF,
+3, 4, 5, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 29, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 64, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 97, 98, 111, 139, 171, 173, 177, 178, 179, 180, 182, 0xFFFF,
+3, 16, 41, 55, 59, 72, 75, 76, 79, 86, 0xFFFF,
+3, 4, 16, 19, 20, 21, 29, 498, 517, 520, 521, 522, 524, 525, 530, 533, 534, 535, 536, 537, 538, 539, 542, 0xFFFF,
+3, 15, 19, 20, 21, 23, 24, 25, 26, 28, 29, 602, 607, 608, 611, 616, 617, 618, 620, 622, 0xFFFF,
+3, 4, 5, 7, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 64, 66, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 95, 133, 138, 139, 140, 170, 177, 178, 179, 180, 182, 188, 314, 378, 581, 585, 602, 605, 610, 612, 613, 615, 616, 618, 619, 630, 0xFFFF,
+3, 14, 15, 17, 19, 20, 21, 24, 40, 41, 42, 44, 47, 48, 51, 55, 68, 69, 70, 71, 72, 74, 75, 76, 78, 79, 80, 81, 82, 85, 86, 87, 90, 0xFFFF,
+3, 26, 36, 41, 42, 44, 47, 49, 50, 51, 54, 55, 56, 58, 68, 69, 71, 72, 73, 76, 78, 79, 81, 82, 83, 85, 86, 87, 88, 93, 0xFFFF,
+3, 0xFFFF,
+44, 69, 71, 72, 81, 91, 0xFFFF,
+135, 0xFFFF,
+46, 51, 72, 76, 81, 83, 86, 87, 88, 0xFFFF,
+3, 49, 58, 68, 72, 75, 86, 87, 90, 178, 182, 0xFFFF,
+3, 7, 10, 15, 16, 17, 19, 20, 21, 22, 25, 29, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 60, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 91, 92, 93, 170, 178, 0xFFFF,
+3, 36, 38, 55, 68, 70, 72, 75, 78, 79, 81, 85, 87, 88, 89, 0xFFFF,
+3, 170, 0xFFFF,
+3, 10, 11, 12, 15, 16, 17, 19, 20, 21, 22, 23, 24, 25, 27, 28, 29, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 60, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 114, 194, 196, 0xFFFF,
+3, 7, 19, 20, 22, 23, 24, 28, 29, 47, 49, 54, 55, 68, 70, 71, 72, 74, 76, 79, 80, 81, 82, 83, 85, 86, 87, 90, 0xFFFF,
+3, 15, 16, 36, 37, 38, 39, 41, 42, 43, 44, 48, 51, 53, 54, 55, 56, 58, 66, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 93, 0xFFFF,
+17, 48, 49, 74, 76, 81, 82, 86, 0xFFFF,
+3, 16, 38, 41, 59, 68, 70, 72, 74, 76, 79, 81, 82, 83, 85, 86, 87, 90, 92, 0xFFFF,
+3, 10, 15, 16, 17, 34, 36, 37, 38, 39, 40, 42, 44, 48, 49, 50, 51, 52, 53, 54, 55, 57, 68, 69, 70, 71, 72, 73, 74, 75, 76, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 91, 92, 93, 170, 171, 172, 176, 189, 202, 0xFFFF,
+3, 4, 11, 12, 15, 16, 17, 18, 19, 24, 29, 34, 37, 38, 39, 40, 41, 44, 47, 48, 49, 50, 51, 53, 54, 56, 58, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 91, 92, 93, 109, 125, 130, 137, 162, 169, 170, 171, 172, 182, 187, 200, 202, 0xFFFF,
+3, 4, 15, 16, 17, 36, 40, 47, 57, 58, 68, 69, 70, 71, 72, 73, 75, 76, 77, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 91, 93, 162, 171, 172, 202, 0xFFFF,
+3, 4, 16, 34, 37, 38, 39, 43, 44, 48, 54, 58, 68, 71, 72, 73, 74, 75, 76, 79, 80, 81, 82, 83, 85, 86, 87, 88, 92, 0xFFFF,
+3, 41, 42, 44, 46, 47, 49, 50, 53, 0xFFFF,
+37, 68, 72, 85, 86, 0xFFFF,
+49, 51, 0xFFFF,
+20, 36, 41, 0xFFFF,
+3, 11, 12, 36, 37, 38, 40, 41, 44, 48, 50, 51, 52, 53, 55, 56, 59, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 79, 80, 81, 82, 85, 86, 87, 88, 91, 93, 0xFFFF,
+3, 16, 29, 37, 41, 44, 55, 58, 59, 68, 72, 75, 76, 79, 81, 82, 86, 87, 89, 0xFFFF,
+1, 34, 35, 37, 38, 39, 42, 43, 44, 45, 46, 47, 48, 49, 51, 52, 53, 143, 0xFFFF,
+51, 56, 68, 70, 74, 76, 79, 80, 81, 82, 83, 85, 88, 0xFFFF,
+36, 40, 41, 44, 50, 53, 54, 55, 57, 0xFFFF,
+3, 15, 16, 17, 18, 19, 20, 21, 23, 24, 25, 27, 28, 35, 36, 38, 42, 48, 51, 52, 54, 68, 69, 70, 72, 73, 76, 79, 80, 81, 82, 84, 85, 87, 88, 170, 171, 0xFFFF,
+2797, 0xFFFF,
+3, 4, 5, 6, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 27, 29, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 53, 54, 55, 56, 58, 60, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 179, 180, 182, 213, 247, 0xFFFF,
+3, 4, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 95, 131, 170, 171, 178, 182, 0xFFFF,
+3, 38, 49, 60, 72, 76, 78, 82, 85, 87, 90, 92, 0xFFFF,
+3, 15, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 39, 41, 48, 54, 55, 58, 68, 69, 70, 71, 72, 75, 76, 80, 81, 82, 85, 86, 87, 88, 92, 0xFFFF,
+3, 17, 36, 37, 38, 39, 40, 41, 42, 43, 44, 46, 47, 48, 49, 50, 51, 53, 55, 56, 57, 58, 59, 61, 0xFFFF,
+3, 17, 55, 68, 69, 70, 71, 72, 75, 76, 79, 81, 82, 85, 86, 87, 88, 89, 92, 0xFFFF,
+17, 35, 70, 73, 76, 79, 80, 81, 82, 88, 0xFFFF,
+3, 17, 28, 42, 46, 50, 52, 53, 54, 55, 56, 59, 62, 66, 74, 0xFFFF,
+3, 16, 17, 20, 24, 27, 28, 31, 33, 34, 35, 37, 38, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 59, 60, 61, 62, 63, 64, 65, 66, 74, 75, 76, 82, 89, 113, 0xFFFF,
+1, 14, 0xFFFF,
+3, 53, 68, 72, 74, 75, 76, 83, 86, 87, 0xFFFF,
+40, 44, 47, 57, 0xFFFF,
+3, 6, 9, 10, 11, 13, 28, 31, 76, 0xFFFF,
+3, 36, 37, 38, 40, 43, 44, 47, 53, 54, 56, 58, 0xFFFF,
+3, 15, 16, 17, 37, 47, 48, 51, 53, 60, 68, 71, 72, 74, 76, 78, 81, 82, 85, 86, 88, 89, 92, 489, 490, 491, 495, 496, 498, 500, 501, 502, 503, 504, 505, 508, 517, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 541, 542, 543, 544, 545, 547, 548, 551, 0xFFFF,
+3, 10, 11, 12, 17, 34, 40, 43, 45, 48, 49, 50, 51, 54, 56, 58, 65, 68, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 91, 112, 651, 0xFFFF,
+226, 232, 246, 250, 251, 255, 259, 260, 262, 274, 275, 277, 281, 282, 295, 874, 913, 1107, 1144, 1167, 1177, 1362, 1419, 1619, 1879, 2003, 2059, 2103, 2175, 2264, 2312, 2387, 2390, 2518, 2610, 2617, 2641, 2642, 2735, 2738, 2863, 2993, 3039, 3088, 3174, 3178, 3241, 3347, 3348, 3354, 3373, 3461, 3492, 3503, 3565, 3618, 3733, 3941, 4226, 4374, 4770, 5034, 5048, 5363, 6629, 12428, 12429, 12432, 12435, 12449, 12450, 12461, 12462, 17497, 0xFFFF,
+3, 17, 29, 36, 37, 38, 41, 45, 47, 49, 51, 54, 66, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 0xFFFF,
+3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 58, 59, 60, 62, 63, 64, 65, 66, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 226, 227, 229, 231, 232, 233, 234, 235, 236, 238, 241, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 262, 264, 265, 266, 267, 268, 270, 271, 273, 274, 275, 277, 278, 279, 280, 281, 282, 286, 287, 288, 289, 290, 293, 294, 295, 299, 383, 384, 386, 387, 531, 588, 650, 658, 917, 923, 927, 929, 939, 952, 954, 955, 967, 969, 1011, 1022, 1046, 1060, 1065, 1094, 1101, 1102, 1105, 1107, 1109, 1125, 1137, 1138, 1144, 1147, 1150, 1154, 1167, 1172, 1203, 1233, 1264, 1271, 1294, 1317, 1344, 1350, 1376, 1406, 1408, 1476, 1484, 1509, 1524, 1568, 1579, 1615, 1619, 1652, 1715, 1724, 1734, 1750, 1758, 1763, 1790, 1803, 1806, 1858, 1880, 1885, 1897, 1905, 1932, 1956, 1959, 1963, 1969, 1972, 1981, 1983, 1999, 2003, 2007, 2010, 2025, 2035, 2040, 2046, 2069, 2078, 2081, 2090, 2101, 2103, 2104, 2105, 2121, 2125, 2127, 2151, 2182, 2201, 2230, 2235, 2264, 2270, 2312, 2331, 2334, 2339, 2357, 2378, 2387, 2397, 2398, 2407, 2410, 2413, 2446, 2483, 2493, 2497, 2551, 2579, 2584, 2602, 2617, 2641, 2642, 2643, 2645, 2668, 2702, 2711, 2712, 2735, 2779, 2781, 2797, 2833, 2836, 2842, 2850, 2863, 2876, 2885, 2890, 2903, 2905, 2910, 2915, 2927, 2929, 2943, 2946, 2963, 2974, 2982, 2994, 3007, 3025, 3030, 3031, 3039, 3045, 3056, 3057, 3076, 3078, 3081, 3097, 3171, 3174, 3178, 3216, 3218, 3229, 3248, 3249, 3277, 3281, 3289, 3313, 3321, 3325, 3335, 3347, 3348, 3350, 3362, 3381, 3384, 3400, 3406, 3416, 3418, 3461, 3477, 3478, 3528, 3541, 3565, 3594, 3612, 3628, 3630, 3654, 3677, 3681, 3682, 3683, 3691, 3696, 3698, 3705, 3706, 3713, 3724, 3726, 3746, 3748, 3763, 3793, 3802, 3806, 3825, 3828, 3848, 3861, 3863, 3883, 3922, 3926, 3999, 4002, 4063, 4126, 4133, 4163, 4222, 4226, 4269, 4362, 4387, 4569, 4698, 4729, 4741, 5034, 5136, 5277, 5306, 5475, 5687, 5838, 5851, 5918, 6054, 6055, 6211, 6220, 6221, 6355, 6513, 6634, 6651, 6712, 6838, 6864, 7029, 7180, 8047, 8048, 8101, 8152, 8596, 8630, 8850, 9744, 10275, 10908, 12427, 12428, 12429, 12432, 12434, 12449, 12450, 13453, 13615, 14446, 14478, 14507, 14843, 17761, 17779, 17792, 17804, 17809, 17812, 17820, 17827, 18124, 18186, 18829, 18872, 20270, 20381, 20387, 21063, 21531, 23123, 24663, 28777, 29479, 29739, 0xFFFF,
+0, 226, 227, 229, 232, 233, 244, 245, 246, 247, 248, 250, 251, 253, 254, 258, 259, 260, 262, 264, 267, 268, 270, 273, 274, 275, 277, 278, 279, 280, 281, 282, 286, 287, 289, 290, 292, 293, 294, 299, 383, 384, 387, 939, 952, 955, 1011, 1046, 1094, 1095, 1107, 1125, 1143, 1167, 1210, 1294, 1363, 1364, 1411, 1462, 1476, 1508, 1604, 1663, 1665, 1677, 1724, 1750, 1781, 1803, 1805, 1906, 1932, 1965, 1999, 2008, 2010, 2047, 2081, 2089, 2174, 2182, 2188, 2270, 2298, 2312, 2317, 2334, 2357, 2387, 2390, 2397, 2398, 2407, 2413, 2431, 2433, 2445, 2448, 2450, 2493, 2551, 2583, 2602, 2637, 2641, 2642, 2645, 2686, 2692, 2711, 2712, 2735, 2784, 2795, 2796, 2797, 2826, 2828, 2863, 2890, 2910, 2959, 2974, 3041, 3055, 3056, 3073, 3082, 3110, 3117, 3120, 3133, 3229, 3249, 3271, 3313, 3316, 3333, 3347, 3354, 3373, 3406, 3464, 3528, 3538, 3565, 3582, 3610, 3612, 3628, 3649, 3674, 3698, 3705, 3706, 3707, 3736, 3798, 3803, 3828, 3856, 4040, 4071, 4204, 4222, 4269, 4374, 4397, 4606, 4666, 4695, 4741, 4830, 5306, 5912, 5918, 5977, 6037, 6163, 6210, 6355, 6482, 6712, 6901, 7588, 8226, 9095, 9118, 9129, 10275, 12427, 12429, 12432, 12461, 12462, 17269, 17497, 17761, 17840, 18147, 20394, 21028, 21056, 0xFFFF,
+3, 9, 11, 12, 15, 16, 17, 22, 29, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 60, 61, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 91, 92, 122, 195, 196, 0xFFFF,
+190, 0xFFFF,
+3, 37, 38, 40, 49, 51, 55, 68, 71, 72, 76, 80, 81, 82, 85, 86, 0xFFFF,
+4, 18, 37, 41, 44, 51, 54, 57, 58, 59, 61, 0xFFFF,
+3, 10, 11, 12, 15, 16, 17, 19, 20, 21, 22, 23, 25, 27, 29, 36, 37, 38, 39, 40, 41, 42, 44, 45, 47, 48, 49, 51, 53, 54, 55, 56, 58, 60, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 120, 139, 0xFFFF,
+3, 17, 36, 37, 38, 39, 40, 41, 42, 43, 44, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 60, 0xFFFF,
+3, 0xFFFF,
+3, 16, 19, 20, 22, 25, 26, 29, 36, 37, 39, 43, 45, 48, 49, 50, 51, 53, 54, 55, 57, 68, 69, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 92, 166, 184, 214, 0xFFFF,
+3, 36, 37, 38, 42, 43, 47, 48, 50, 55, 58, 72, 82, 85, 170, 0xFFFF,
+3, 41, 47, 68, 71, 72, 76, 79, 81, 82, 87, 88, 90, 91, 0xFFFF,
+3, 7, 19, 20, 21, 23, 26, 28, 40, 42, 54, 56, 68, 70, 71, 72, 74, 75, 76, 81, 82, 83, 85, 86, 87, 88, 0xFFFF,
+42, 68, 76, 79, 80, 0xFFFF,
+3, 7, 9, 15, 16, 17, 19, 20, 21, 23, 24, 25, 26, 27, 28, 36, 37, 38, 39, 40, 42, 43, 44, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 60, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 92, 93, 0xFFFF,
+3, 4, 5, 10, 11, 12, 15, 17, 19, 20, 21, 23, 24, 29, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 60, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 182, 190, 0xFFFF,
+3, 4, 5, 6, 7, 9, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 62, 64, 66, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 171, 177, 178, 179, 180, 182, 0xFFFF,
+3, 4, 36, 38, 40, 43, 44, 46, 47, 48, 49, 50, 51, 53, 54, 55, 56, 60, 68, 70, 72, 75, 76, 81, 82, 85, 86, 87, 88, 89, 92, 0xFFFF,
+3, 10, 15, 16, 17, 19, 20, 21, 22, 23, 24, 25, 26, 28, 29, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 170, 0xFFFF,
+3, 16, 36, 40, 41, 46, 71, 76, 79, 80, 82, 85, 86, 87, 88, 92, 0xFFFF,
+3, 7, 10, 17, 21, 23, 24, 26, 28, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 47, 48, 49, 50, 51, 53, 54, 55, 57, 58, 60, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 92, 131, 238, 0xFFFF,
+3, 36, 46, 47, 48, 51, 57, 68, 72, 75, 76, 77, 78, 79, 80, 81, 82, 85, 86, 87, 88, 89, 92, 166, 184, 242, 0xFFFF,
+3, 16, 36, 46, 48, 55, 57, 60, 68, 71, 72, 75, 76, 77, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 166, 184, 214, 0xFFFF,
+3, 36, 44, 46, 48, 50, 51, 54, 55, 56, 60, 103, 0xFFFF,
+3, 5, 29, 36, 43, 68, 72, 75, 76, 78, 79, 81, 82, 83, 85, 86, 87, 88, 89, 108, 0xFFFF,
+3, 19, 20, 22, 26, 27, 28, 46, 51, 54, 68, 69, 70, 72, 75, 76, 79, 82, 85, 86, 87, 88, 92, 0xFFFF,
+3, 10, 14, 15, 17, 19, 20, 21, 22, 24, 26, 29, 32, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 47, 48, 50, 51, 54, 55, 56, 58, 60, 61, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 179, 180, 182, 0xFFFF,
+34, 0xFFFF,
+20, 23, 131, 0xFFFF,
+8, 19, 20, 0xFFFF,
+37, 71, 72, 76, 81, 85, 86, 88, 0xFFFF,
+3, 10, 29, 36, 48, 50, 54, 58, 68, 69, 70, 71, 72, 75, 76, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 92, 0xFFFF,
+38, 39, 40, 42, 44, 49, 50, 53, 54, 55, 0xFFFF,
+3, 17, 36, 54, 68, 72, 75, 76, 78, 81, 82, 83, 84, 85, 86, 87, 88, 90, 92, 0xFFFF,
+3, 4, 15, 29, 34, 36, 40, 43, 45, 46, 47, 51, 54, 55, 61, 68, 70, 71, 72, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 92, 166, 184, 190, 214, 0xFFFF,
+3, 15, 18, 19, 20, 21, 22, 23, 24, 26, 29, 57, 69, 72, 74, 75, 76, 79, 81, 82, 86, 87, 90, 0xFFFF,
+46, 68, 69, 72, 81, 86, 87, 88, 0xFFFF,
+3, 54, 72, 76, 87, 0xFFFF,
+3, 37, 41, 42, 44, 50, 51, 54, 56, 68, 69, 72, 76, 79, 80, 81, 82, 83, 85, 87, 88, 0xFFFF,
+17, 68, 70, 72, 76, 85, 87, 89, 0xFFFF,
+3, 4, 9, 10, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 60, 61, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 95, 120, 139, 0xFFFF,
+3, 38, 68, 69, 72, 76, 81, 82, 85, 86, 87, 88, 90, 92, 0xFFFF,
+3, 15, 16, 17, 19, 20, 21, 22, 23, 25, 26, 27, 28, 29, 36, 37, 38, 40, 41, 42, 44, 46, 47, 48, 49, 50, 51, 54, 55, 56, 58, 62, 64, 66, 68, 69, 70, 71, 72, 73, 74, 75, 76, 79, 81, 82, 83, 85, 86, 87, 88, 90, 0xFFFF,
+3, 15, 17, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 37, 39, 42, 43, 45, 46, 47, 48, 50, 51, 54, 56, 66, 68, 72, 76, 81, 82, 83, 86, 88, 105, 1189, 0xFFFF,
+3, 17, 21, 29, 36, 37, 38, 39, 42, 43, 47, 49, 51, 53, 54, 55, 68, 69, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 85, 86, 87, 88, 89, 92, 93, 95, 106, 111, 124, 213, 248, 250, 1245, 0xFFFF,
+20, 21, 26, 0xFFFF,
+1, 34, 35, 36, 37, 38, 39, 42, 44, 48, 49, 51, 52, 53, 56, 143, 0xFFFF,
+4, 11, 12, 13, 16, 17, 18, 20, 21, 22, 23, 24, 26, 27, 28, 29, 30, 37, 38, 39, 40, 41, 42, 43, 44, 45, 47, 49, 50, 51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 86, 87, 88, 89, 90, 91, 92, 93, 94, 0xFFFF,
+3, 42, 44, 45, 47, 49, 50, 0xFFFF,
+3, 11, 12, 29, 49, 69, 74, 81, 88, 92, 875, 0xFFFF,
+3, 68, 70, 71, 72, 76, 79, 80, 81, 82, 83, 87, 92, 0xFFFF,
+3, 11, 12, 15, 38, 39, 51, 54, 58, 61, 68, 70, 71, 72, 75, 76, 79, 81, 82, 83, 85, 86, 87, 92, 0xFFFF,
+3, 4, 5, 8, 10, 11, 12, 15, 16, 17, 19, 20, 21, 22, 24, 27, 29, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 60, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 91, 92, 93, 312, 0xFFFF,
+3, 10, 11, 12, 15, 16, 17, 19, 20, 21, 23, 29, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 46, 47, 48, 49, 50, 51, 53, 54, 55, 57, 58, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 116, 178, 179, 180, 182, 0xFFFF,
+3, 15, 19, 20, 21, 22, 23, 24, 25, 26, 28, 29, 36, 39, 48, 49, 50, 51, 55, 58, 68, 69, 70, 71, 72, 80, 81, 82, 85, 86, 87, 88, 89, 92, 0xFFFF,
+3, 17, 47, 50, 54, 68, 72, 74, 75, 76, 79, 81, 82, 85, 87, 90, 92, 171, 0xFFFF,
+3, 16, 18, 20, 21, 22, 23, 26, 27, 37, 39, 43, 49, 57, 68, 71, 72, 74, 75, 76, 79, 80, 81, 82, 85, 86, 87, 88, 90, 92, 0xFFFF,
+3, 36, 38, 41, 51, 68, 70, 71, 72, 76, 79, 80, 81, 82, 85, 86, 87, 88, 0xFFFF,
+3, 53, 68, 71, 72, 80, 82, 85, 0xFFFF,
+4, 5, 11, 16, 18, 35, 37, 45, 49, 55, 56, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 86, 87, 88, 89, 90, 91, 93, 0xFFFF,
+3, 20, 26, 39, 41, 44, 51, 72, 76, 82, 85, 86, 87, 88, 0xFFFF,
+51, 56, 68, 70, 72, 76, 78, 79, 80, 81, 82, 86, 87, 88, 0xFFFF,
+4, 16, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 37, 38, 40, 46, 48, 49, 54, 55, 56, 59, 69, 70, 71, 72, 73, 75, 76, 77, 80, 81, 82, 83, 84, 86, 87, 88, 90, 91, 92, 93, 0xFFFF,
+3, 9, 17, 22, 36, 38, 39, 43, 45, 46, 47, 48, 51, 53, 54, 55, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 92, 93, 0xFFFF,
+3, 15, 17, 70, 71, 72, 73, 74, 75, 76, 79, 81, 82, 83, 85, 86, 87, 92, 0xFFFF,
+3, 40, 48, 49, 53, 68, 70, 72, 73, 74, 76, 78, 79, 81, 82, 85, 86, 87, 91, 0xFFFF,
+4, 36, 39, 40, 41, 45, 47, 48, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 69, 70, 71, 72, 73, 74, 75, 77, 79, 80, 82, 83, 86, 87, 88, 89, 90, 91, 0xFFFF,
+4, 17, 37, 39, 41, 43, 48, 52, 54, 55, 56, 57, 69, 70, 71, 72, 73, 75, 76, 77, 80, 81, 82, 83, 84, 86, 87, 88, 89, 0xFFFF,
+4, 8, 12, 13, 15, 16, 20, 21, 22, 23, 24, 27, 28, 29, 37, 38, 39, 40, 41, 42, 44, 45, 48, 49, 51, 52, 54, 55, 56, 58, 59, 69, 71, 72, 73, 75, 76, 77, 79, 80, 81, 82, 83, 84, 86, 87, 88, 89, 90, 91, 102, 0xFFFF,
+4, 10, 18, 21, 27, 37, 38, 39, 40, 41, 43, 44, 45, 47, 48, 50, 51, 52, 54, 55, 56, 57, 58, 59, 61, 0xFFFF,
+226, 227, 229, 231, 232, 233, 235, 236, 238, 241, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 262, 264, 265, 266, 267, 268, 269, 270, 271, 273, 274, 275, 277, 278, 279, 280, 281, 282, 286, 287, 288, 289, 290, 292, 293, 294, 295, 299, 383, 384, 385, 386, 387, 388, 910, 913, 925, 932, 955, 1046, 1091, 1095, 1107, 1111, 1132, 1172, 1344, 1399, 1453, 1465, 1487, 1496, 1533, 1584, 1601, 1660, 1750, 1791, 1820, 1831, 1906, 1912, 1948, 1963, 1969, 2018, 2025, 2029, 2081, 2090, 2186, 2210, 2264, 2265, 2329, 2357, 2368, 2377, 2397, 2536, 2551, 2602, 2610, 2640, 2641, 2681, 2712, 2719, 2735, 2742, 2745, 2797, 2827, 2863, 2901, 2910, 2947, 2966, 3013, 3041, 3078, 3159, 3166, 3214, 3249, 3258, 3281, 3284, 3310, 3314, 3354, 3362, 3406, 3415, 3631, 3643, 3654, 3658, 3708, 3731, 3750, 3764, 3848, 3976, 4329, 4503, 4708, 4741, 5149, 5453, 5705, 5918, 5977, 6108, 6404, 7252, 8101, 8329, 8344, 10275, 10606, 12429, 12432, 12460, 12461, 12462, 13924, 14421, 14422, 14466, 17264, 17773, 18189, 21028, 21303, 23264, 29479, 33487, 0xFFFF,
+3, 18, 41, 48, 54, 58, 68, 69, 70, 71, 72, 73, 76, 78, 81, 82, 83, 85, 86, 171, 0xFFFF,
+3, 4, 5, 7, 9, 10, 11, 12, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 64, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 95, 98, 108, 0xFFFF,
+3, 15, 16, 20, 21, 22, 27, 29, 36, 39, 41, 42, 43, 45, 46, 48, 49, 51, 53, 54, 55, 57, 59, 60, 68, 71, 72, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 92, 166, 171, 184, 214, 0xFFFF,
+3, 29, 37, 68, 72, 79, 85, 86, 87, 88, 0xFFFF,
+55, 72, 75, 80, 86, 0xFFFF,
+3, 10, 15, 36, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 59, 60, 0xFFFF,
+3, 36, 39, 41, 46, 47, 56, 68, 69, 70, 71, 72, 74, 75, 79, 80, 81, 82, 85, 86, 87, 88, 90, 92, 177, 0xFFFF,
+3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 64, 65, 66, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 95, 103, 108, 116, 120, 124, 138, 140, 158, 170, 171, 177, 178, 179, 180, 181, 182, 194, 383, 572, 577, 580, 582, 583, 584, 586, 590, 602, 603, 604, 605, 606, 607, 610, 612, 613, 614, 615, 616, 618, 619, 620, 621, 622, 624, 627, 629, 630, 633, 0xFFFF,
+3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 64, 66, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 95, 98, 103, 108, 110, 112, 124, 129, 138, 139, 170, 171, 177, 178, 179, 180, 181, 182, 190, 194, 1317, 0xFFFF,
+3, 4, 10, 15, 16, 17, 19, 20, 21, 22, 23, 24, 27, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 47, 49, 50, 51, 53, 54, 55, 56, 57, 58, 60, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 0xFFFF,
+3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 64, 66, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 95, 98, 105, 106, 107, 108, 109, 111, 112, 114, 116, 117, 121, 122, 123, 127, 138, 139, 170, 177, 178, 182, 190, 194, 213, 234, 248, 250, 255, 259, 264, 303, 312, 314, 404, 550, 1131, 1133, 1189, 1190, 1191, 1193, 1195, 1196, 1197, 1201, 1203, 1211, 1213, 1215, 1217, 1219, 1221, 1223, 1227, 1231, 1233, 1235, 1237, 1239, 1241, 1245, 1247, 1249, 1251, 1255, 1257, 1259, 1263, 1265, 1267, 1269, 1273, 0xFFFF,
+3, 5, 8, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 32, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 64, 66, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 95, 102, 111, 114, 129, 135, 139, 170, 177, 602, 604, 606, 607, 609, 610, 613, 616, 618, 619, 620, 622, 623, 629, 909, 913, 916, 942, 972, 991, 1012, 0xFFFF,
+3, 4, 6, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 32, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 58, 60, 61, 66, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 91, 92, 135, 194, 572, 583, 602, 606, 607, 608, 610, 611, 612, 613, 614, 615, 616, 617, 620, 621, 625, 626, 629, 0xFFFF,
+40, 55, 57, 0xFFFF,
+131, 0xFFFF,
+3, 16, 20, 21, 23, 39, 68, 72, 76, 81, 82, 86, 87, 89, 0xFFFF,
+3, 9, 10, 15, 16, 17, 19, 20, 21, 22, 23, 36, 38, 39, 41, 42, 44, 45, 47, 50, 54, 58, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 92, 0xFFFF,
+8, 22, 23, 24, 28, 131, 0xFFFF,
+3, 34, 43, 46, 47, 54, 55, 58, 68, 71, 72, 75, 76, 79, 81, 82, 83, 85, 86, 87, 88, 89, 90, 0xFFFF,
+3, 15, 16, 29, 36, 38, 40, 41, 42, 43, 46, 47, 48, 49, 50, 51, 54, 55, 56, 57, 58, 60, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 90, 92, 0xFFFF,
+43, 71, 72, 76, 81, 0xFFFF,
+3, 0xFFFF,
+4, 16, 18, 20, 21, 22, 29, 38, 39, 40, 41, 49, 54, 61, 73, 77, 79, 80, 82, 83, 88, 89, 90, 91, 93, 0xFFFF,
+3, 10, 29, 37, 38, 50, 51, 55, 68, 71, 72, 73, 74, 75, 76, 79, 81, 82, 83, 85, 86, 87, 88, 0xFFFF,
+35, 68, 69, 70, 72, 74, 75, 77, 78, 79, 81, 85, 87, 0xFFFF,
+3, 17, 19, 20, 21, 22, 23, 24, 25, 27, 28, 29, 37, 47, 54, 55, 68, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 0xFFFF,
+3, 34, 36, 37, 46, 48, 68, 71, 72, 74, 76, 78, 79, 80, 81, 85, 86, 87, 88, 89, 92, 0xFFFF,
+3, 4, 15, 16, 17, 29, 34, 36, 37, 38, 39, 41, 43, 44, 47, 48, 49, 51, 54, 55, 56, 60, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 90, 91, 92, 179, 180, 0xFFFF,
+3, 15, 19, 20, 21, 24, 25, 26, 27, 37, 38, 39, 46, 48, 50, 53, 58, 68, 70, 71, 72, 74, 75, 76, 79, 80, 81, 82, 83, 85, 86, 87, 88, 90, 92, 0xFFFF,
+3, 10, 54, 70, 71, 72, 76, 78, 82, 83, 85, 86, 87, 88, 0xFFFF,
+21, 23, 24, 78, 0xFFFF,
+22, 24, 0xFFFF,
+3, 4, 7, 15, 16, 17, 19, 20, 21, 22, 23, 24, 25, 27, 28, 36, 37, 38, 39, 42, 43, 44, 48, 51, 53, 54, 55, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 90, 91, 92, 0xFFFF,
+3, 17, 38, 40, 49, 55, 68, 69, 70, 71, 72, 73, 74, 75, 76, 79, 80, 81, 82, 83, 85, 86, 87, 88, 92, 0xFFFF,
+3, 16, 29, 36, 39, 46, 47, 48, 50, 51, 53, 68, 69, 71, 72, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 92, 166, 0xFFFF,
+3, 4, 10, 15, 16, 17, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 60, 66, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 92, 108, 121, 124, 177, 180, 0xFFFF,
+3, 11, 12, 16, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 37, 41, 44, 48, 50, 54, 55, 58, 59, 68, 69, 70, 72, 73, 75, 76, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 92, 0xFFFF,
+3, 4, 9, 10, 15, 16, 17, 18, 19, 20, 21, 22, 23, 29, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 47, 48, 49, 50, 51, 53, 54, 55, 56, 60, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 91, 92, 93, 112, 179, 180, 0xFFFF,
+3, 4, 5, 16, 19, 21, 23, 29, 48, 49, 54, 56, 68, 70, 71, 72, 73, 76, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 91, 93, 176, 197, 293, 0xFFFF,
+3, 41, 54, 68, 72, 74, 76, 80, 85, 86, 87, 194, 0xFFFF,
+11, 16, 0xFFFF,
+3, 37, 49, 50, 54, 55, 58, 68, 69, 70, 71, 72, 76, 78, 79, 80, 81, 82, 85, 86, 87, 89, 90, 0xFFFF,
+226, 229, 250, 258, 262, 267, 286, 383, 387, 1707, 2008, 3039, 3477, 23264, 29479, 33487, 0xFFFF,
+3, 9, 36, 37, 38, 60, 71, 72, 74, 75, 76, 79, 81, 82, 85, 86, 87, 88, 0xFFFF,
+3, 30, 41, 42, 43, 44, 45, 46, 47, 49, 57, 58, 59, 60, 61, 62, 65, 66, 70, 71, 72, 74, 75, 76, 77, 78, 0xFFFF,
+3, 7, 9, 10, 15, 16, 17, 19, 20, 21, 22, 23, 27, 28, 29, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 60, 61, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 108, 178, 0xFFFF,
+3, 15, 16, 17, 36, 38, 39, 40, 41, 43, 44, 45, 46, 51, 53, 54, 58, 60, 68, 69, 70, 71, 72, 73, 74, 75, 76, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 91, 92, 0xFFFF,
+3, 4, 34, 36, 37, 38, 39, 40, 41, 43, 44, 49, 50, 54, 58, 60, 68, 70, 71, 72, 75, 76, 79, 81, 82, 83, 85, 86, 87, 88, 90, 0xFFFF,
+3, 11, 12, 15, 16, 17, 29, 30, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 0xFFFF,
+4, 19, 0xFFFF,
+3, 7, 10, 15, 16, 17, 19, 20, 21, 22, 23, 24, 25, 26, 29, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 60, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 91, 92, 93, 125, 0xFFFF,
+3, 17, 18, 36, 37, 38, 40, 41, 43, 44, 47, 48, 49, 50, 51, 53, 54, 55, 56, 58, 0xFFFF,
+3, 57, 58, 59, 61, 62, 63, 65, 67, 68, 69, 70, 71, 72, 74, 75, 76, 79, 81, 82, 89, 91, 93, 97, 99, 102, 103, 106, 107, 108, 111, 113, 0xFFFF,
+3, 5, 15, 16, 19, 20, 21, 29, 34, 178, 488, 489, 490, 491, 492, 493, 495, 496, 498, 499, 500, 501, 502, 504, 505, 506, 507, 508, 509, 511, 512, 517, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 547, 548, 550, 551, 0xFFFF,
+3, 4, 5, 15, 16, 17, 20, 21, 22, 23, 28, 29, 36, 37, 38, 39, 40, 41, 42, 44, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 61, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 91, 92, 93, 125, 164, 176, 197, 288, 289, 293, 0xFFFF,
+3, 68, 70, 76, 78, 79, 81, 82, 85, 86, 87, 88, 0xFFFF,
+3, 17, 0xFFFF,
+2797, 0xFFFF,
+3, 9, 16, 43, 51, 53, 60, 68, 70, 71, 72, 73, 75, 76, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 0xFFFF,
+39, 57, 58, 61, 68, 72, 79, 86, 0xFFFF,
+3, 57, 59, 60, 61, 63, 64, 65, 68, 70, 71, 72, 74, 75, 76, 77, 78, 79, 81, 0xFFFF,
+3, 9, 10, 15, 16, 17, 19, 20, 21, 22, 23, 24, 26, 28, 29, 34, 35, 36, 37, 39, 41, 42, 44, 47, 48, 51, 54, 55, 56, 58, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 91, 92, 139, 177, 0xFFFF,
+3, 18, 37, 41, 47, 49, 50, 54, 55, 56, 68, 69, 70, 71, 72, 74, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 90, 93, 112, 0xFFFF,
+3, 0xFFFF,
+1, 27, 38, 51, 53, 55, 66, 69, 70, 73, 79, 81, 83, 85, 86, 0xFFFF,
+3, 36, 40, 42, 49, 51, 55, 59, 0xFFFF,
+36, 39, 70, 72, 76, 78, 81, 82, 85, 86, 89, 90, 0xFFFF,
+3, 4, 8, 10, 16, 17, 19, 20, 21, 25, 26, 29, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 182, 572, 610, 611, 616, 620, 0xFFFF,
+3, 39, 40, 41, 42, 43, 44, 47, 57, 58, 59, 61, 64, 65, 66, 68, 70, 71, 74, 75, 76, 77, 78, 0xFFFF,
+3, 39, 40, 41, 42, 44, 48, 51, 53, 54, 57, 68, 69, 70, 72, 74, 75, 76, 79, 80, 81, 82, 83, 85, 86, 87, 88, 90, 121, 0xFFFF,
+3, 5, 7, 8, 10, 15, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 36, 37, 38, 39, 41, 42, 43, 44, 45, 46, 47, 49, 50, 51, 52, 53, 54, 55, 57, 58, 59, 61, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 178, 179, 180, 182, 0xFFFF,
+3, 4, 10, 11, 12, 15, 16, 17, 19, 21, 27, 29, 30, 31, 33, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 46, 47, 48, 49, 50, 51, 53, 54, 55, 57, 58, 60, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 95, 182, 0xFFFF,
+3, 4, 5, 7, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 32, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 65, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 95, 97, 105, 108, 109, 111, 112, 114, 116, 120, 121, 124, 126, 129, 139, 170, 181, 182, 210, 257, 0xFFFF,
+3, 4, 7, 9, 10, 11, 12, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 60, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 95, 135, 139, 170, 178, 182, 0xFFFF,
+3, 9, 10, 16, 17, 19, 20, 23, 28, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 91, 92, 93, 95, 170, 0xFFFF,
+3, 7, 8, 10, 15, 16, 17, 19, 20, 21, 22, 23, 24, 25, 27, 29, 32, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 60, 61, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 91, 92, 93, 95, 101, 112, 170, 181, 182, 0xFFFF,
+68, 69, 70, 72, 75, 78, 85, 86, 0xFFFF,
+3, 17, 36, 37, 38, 39, 40, 42, 43, 44, 46, 47, 49, 50, 51, 53, 54, 55, 56, 58, 60, 0xFFFF,
+29, 36, 51, 70, 71, 72, 76, 78, 80, 81, 82, 83, 86, 91, 112, 0xFFFF,
+3, 38, 47, 57, 68, 70, 72, 74, 75, 76, 82, 86, 0xFFFF,
+3, 4, 19, 20, 22, 26, 27, 29, 36, 41, 43, 48, 50, 51, 60, 76, 85, 0xFFFF,
+3, 4, 9, 15, 16, 17, 19, 20, 21, 22, 23, 24, 25, 26, 29, 36, 37, 39, 40, 41, 42, 43, 44, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 60, 68, 69, 70, 72, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 170, 0xFFFF,
+3, 4, 6, 9, 10, 11, 12, 15, 16, 17, 19, 20, 21, 22, 23, 24, 25, 26, 27, 29, 30, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 60, 63, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 105, 107, 109, 111, 112, 116, 125, 126, 139, 170, 200, 0xFFFF,
+3, 4, 5, 15, 16, 19, 20, 21, 29, 36, 37, 38, 41, 42, 44, 45, 46, 47, 49, 53, 54, 55, 57, 58, 68, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 91, 92, 93, 95, 108, 124, 0xFFFF,
+3, 40, 41, 42, 43, 46, 57, 58, 59, 60, 61, 63, 64, 65, 68, 69, 70, 71, 72, 74, 75, 76, 77, 78, 80, 81, 89, 91, 92, 93, 96, 97, 100, 102, 104, 106, 107, 108, 109, 111, 0xFFFF,
+3, 36, 37, 38, 39, 44, 47, 51, 54, 58, 68, 70, 71, 72, 74, 75, 76, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 93, 0xFFFF,
+3, 4, 9, 10, 13, 15, 16, 17, 19, 20, 21, 25, 26, 27, 28, 29, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 91, 92, 93, 139, 0xFFFF,
+3, 4, 29, 36, 38, 44, 47, 53, 54, 60, 68, 69, 70, 71, 72, 73, 74, 75, 76, 79, 80, 81, 82, 83, 85, 86, 87, 89, 92, 0xFFFF,
+3, 5, 7, 10, 15, 16, 17, 19, 20, 21, 23, 24, 25, 26, 27, 28, 30, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 60, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 197, 199, 200, 201, 0xFFFF,
+3, 17, 29, 37, 48, 51, 54, 58, 68, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 85, 86, 87, 90, 0xFFFF,
+41, 66, 76, 78, 82, 87, 0xFFFF,
+3, 29, 36, 42, 48, 54, 68, 70, 72, 76, 78, 82, 85, 86, 87, 0xFFFF,
+3, 4, 5, 11, 12, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 53, 54, 55, 57, 58, 60, 65, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 91, 92, 93, 95, 106, 110, 111, 112, 114, 120, 129, 178, 227, 253, 254, 586, 587, 602, 610, 611, 612, 613, 619, 620, 621, 623, 629, 1219, 1227, 0xFFFF,
+3, 15, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 60, 68, 69, 70, 71, 72, 74, 75, 76, 79, 80, 81, 82, 83, 85, 86, 87, 88, 90, 0xFFFF,
+36, 39, 40, 44, 48, 49, 53, 54, 55, 57, 0xFFFF,
+1, 0xFFFF,
+3, 4, 5, 6, 10, 11, 12, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 48, 49, 50, 51, 53, 54, 55, 58, 60, 66, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 91, 92, 93, 95, 0xFFFF,
+71, 75, 79, 82, 86, 88, 0xFFFF,
+3, 37, 42, 51, 54, 68, 70, 71, 72, 74, 76, 81, 83, 85, 86, 87, 88, 0xFFFF,
+1329, 2149, 2201, 2275, 2901, 3253, 3406, 3824, 9106, 9125, 9137, 9172, 12431, 0xFFFF,
+3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 64, 65, 66, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 95, 97, 98, 105, 106, 107, 108, 109, 112, 113, 114, 116, 117, 120, 121, 122, 123, 124, 125, 126, 127, 131, 138, 139, 140, 169, 170, 171, 177, 178, 179, 180, 182, 188, 194, 198, 200, 208, 234, 240, 255, 259, 264, 429, 458, 484, 570, 571, 572, 573, 574, 575, 576, 577, 578, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 593, 594, 595, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 629, 630, 631, 632, 633, 1131, 1133, 1189, 1190, 1191, 1192, 1193, 1195, 1197, 1199, 1201, 1203, 1209, 1211, 1213, 1215, 1217, 1219, 1221, 1223, 1225, 1227, 1229, 1231, 1233, 1235, 1237, 1239, 1241, 1243, 1245, 1247, 1249, 1251, 1253, 1255, 1257, 1259, 1261, 1263, 1265, 1267, 1269, 1273, 1275, 0xFFFF,
+0xFFFF };
diff --git a/chromium/third_party/skia/bench/gen_bench_expectations.py b/chromium/third_party/skia/bench/gen_bench_expectations.py
new file mode 100644
index 00000000000..4edc38c09d2
--- /dev/null
+++ b/chromium/third_party/skia/bench/gen_bench_expectations.py
@@ -0,0 +1,223 @@
+#!/usr/bin/env python
+# Copyright (c) 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+""" Generate bench_expectations file from a given set of bench data files. """
+
+import argparse
+import bench_util
+import json
+import os
+import re
+import sys
+import urllib2
+
+# Parameters for calculating bench ranges.
+RANGE_RATIO_UPPER = 1.5 # Ratio of range for upper bounds.
+RANGE_RATIO_LOWER = 2.0 # Ratio of range for lower bounds.
+ERR_RATIO = 0.08 # Further widens the range by the ratio of average value.
+ERR_UB = 1.0 # Adds an absolute upper error to cope with small benches.
+ERR_LB = 1.5
+
+# List of bench configs to monitor. Ignore all other configs.
+CONFIGS_TO_INCLUDE = ['simple_viewport_1000x1000',
+ 'simple_viewport_1000x1000_angle',
+ 'simple_viewport_1000x1000_gpu',
+ 'simple_viewport_1000x1000_scalar_1.100000',
+ 'simple_viewport_1000x1000_scalar_1.100000_gpu',
+ ]
+
+# List of flaky entries that should be excluded. Each entry is defined by a list
+# of 3 strings, corresponding to the substrings of [bench, config, builder] to
+# search for. A bench expectations line is excluded when each of the 3 strings
+# in the list is a substring of the corresponding element of the given line. For
+# instance, ['desk_yahooanswers', 'gpu', 'Ubuntu'] will skip expectation entries
+# of SKP benchs whose name contains 'desk_yahooanswers' on all gpu-related
+# configs of all Ubuntu builders.
+ENTRIES_TO_EXCLUDE = [
+ ]
+
+_GS_CLOUD_FORMAT = 'http://storage.googleapis.com/chromium-skia-gm/perfdata/%s/%s'
+
+def compute_ranges(benches, more_benches=None):
+ """Given a list of bench numbers, calculate the alert range.
+
+ Args:
+ benches: a list of float bench values.
+ more_benches: a tuple of lists of additional bench values.
+ The first value of each tuple is the number of commits before the current
+ one that set of values is at, and the second value is a list of
+ bench results.
+
+ Returns:
+ a list of float [lower_bound, upper_bound].
+ """
+ avg = sum(benches)/len(benches)
+ minimum = min(benches)
+ maximum = max(benches)
+ diff = maximum - minimum
+
+ return [minimum - diff*RANGE_RATIO_LOWER - avg*ERR_RATIO - ERR_LB,
+ maximum + diff*RANGE_RATIO_UPPER + avg*ERR_RATIO + ERR_UB]
+
+
+def create_expectations_dict(revision_data_points, builder, extra_data=None):
+ """Convert list of bench data points into a dictionary of expectations data.
+
+ Args:
+ revision_data_points: a list of BenchDataPoint objects.
+ builder: string of the corresponding buildbot builder name.
+
+ Returns:
+ a dictionary of this form:
+ keys = tuple of (config, bench) strings.
+ values = list of float [expected, lower_bound, upper_bound] for the key.
+ """
+ bench_dict = {}
+ for point in revision_data_points:
+ if (point.time_type or # Not walltime which has time_type ''
+ not point.config in CONFIGS_TO_INCLUDE):
+ continue
+ to_skip = False
+ for bench_substr, config_substr, builder_substr in ENTRIES_TO_EXCLUDE:
+ if (bench_substr in point.bench and config_substr in point.config and
+ builder_substr in builder):
+ to_skip = True
+ break
+ if to_skip:
+ continue
+ key = (point.config, point.bench)
+
+ extras = []
+ for idx, dataset in extra_data:
+ for data in dataset:
+ if (data.bench == point.bench and data.config == point.config and
+ data.time_type == point.time_type and data.per_iter_time):
+ extras.append((idx, data.per_iter_time))
+
+ if key in bench_dict:
+ raise Exception('Duplicate bench entry: ' + str(key))
+ bench_dict[key] = [point.time] + compute_ranges(point.per_iter_time, extras)
+
+ return bench_dict
+
+
+def get_parent_commits(start_hash, num_back):
+ """Returns a list of commits that are the parent of the commit passed in."""
+ list_commits = urllib2.urlopen(
+ 'https://skia.googlesource.com/skia/+log/%s?format=json&n=%d' %
+ (start_hash, num_back))
+ # NOTE: Very brittle. Removes the four extraneous characters
+ # so json can be read successfully
+ trunc_list = list_commits.read()[4:]
+ json_data = json.loads(trunc_list)
+ return [revision['commit'] for revision in json_data['log']]
+
+
+def get_file_suffixes(commit_hash, directory):
+ """Gets all the suffixes available in the directory"""
+ possible_files = os.listdir(directory)
+ prefix = 'bench_' + commit_hash + '_data_'
+ return [name[len(prefix):] for name in possible_files
+ if name.startswith(prefix)]
+
+
+def download_bench_data(builder, commit_hash, suffixes, directory):
+ """Downloads data, returns the number successfully downloaded"""
+ cur_files = os.listdir(directory)
+ count = 0
+ for suffix in suffixes:
+ file_name = 'bench_'+commit_hash+'_data_'+suffix
+ if file_name in cur_files:
+ continue
+ try:
+ src = urllib2.urlopen(_GS_CLOUD_FORMAT % (builder, file_name))
+ with open(os.path.join(directory, file_name), 'w') as dest:
+ dest.writelines(src)
+ count += 1
+ except urllib2.HTTPError:
+ pass
+ return count
+
+
+def main():
+ """Reads bench data points, then calculate and export expectations.
+ """
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ '-a', '--representation_alg', default='25th',
+ help='bench representation algorithm to use, see bench_util.py.')
+ parser.add_argument(
+ '-b', '--builder', required=True,
+ help='name of the builder whose bench ranges we are computing.')
+ parser.add_argument(
+ '-d', '--input_dir', required=True,
+ help='a directory containing bench data files.')
+ parser.add_argument(
+ '-o', '--output_file', required=True,
+ help='file path and name for storing the output bench expectations.')
+ parser.add_argument(
+ '-r', '--git_revision', required=True,
+ help='the git hash to indicate the revision of input data to use.')
+ parser.add_argument(
+ '-t', '--back_track', required=False, default=10,
+ help='the number of commit hashes backwards to look to include' +
+ 'in the calculations.')
+ parser.add_argument(
+ '-m', '--max_commits', required=False, default=1,
+ help='the number of commit hashes to include in the calculations.')
+ args = parser.parse_args()
+
+ builder = args.builder
+
+ data_points = bench_util.parse_skp_bench_data(
+ args.input_dir, args.git_revision, args.representation_alg)
+
+ parent_commits = get_parent_commits(args.git_revision, args.back_track)
+ print "Using commits: {}".format(parent_commits)
+ suffixes = get_file_suffixes(args.git_revision, args.input_dir)
+ print "Using suffixes: {}".format(suffixes)
+
+ # TODO(kelvinly): Find a better approach to than directly copying from
+ # the GS server?
+ downloaded_commits = []
+ for idx, commit in enumerate(parent_commits):
+ num_downloaded = download_bench_data(
+ builder, commit, suffixes, args.input_dir)
+ if num_downloaded > 0:
+ downloaded_commits.append((num_downloaded, idx, commit))
+
+ if len(downloaded_commits) < args.max_commits:
+ print ('Less than desired number of commits found. Please increase'
+ '--back_track in later runs')
+ trunc_commits = sorted(downloaded_commits, reverse=True)[:args.max_commits]
+ extra_data = []
+ for _, idx, commit in trunc_commits:
+ extra_data.append((idx, bench_util.parse_skp_bench_data(
+ args.input_dir, commit, args.representation_alg)))
+
+ expectations_dict = create_expectations_dict(data_points, builder,
+ extra_data)
+
+ out_lines = []
+ keys = expectations_dict.keys()
+ keys.sort()
+ for (config, bench) in keys:
+ (expected, lower_bound, upper_bound) = expectations_dict[(config, bench)]
+ out_lines.append('%(bench)s_%(config)s_,%(builder)s-%(representation)s,'
+ '%(expected)s,%(lower_bound)s,%(upper_bound)s' % {
+ 'bench': bench,
+ 'config': config,
+ 'builder': builder,
+ 'representation': args.representation_alg,
+ 'expected': expected,
+ 'lower_bound': lower_bound,
+ 'upper_bound': upper_bound})
+
+ with open(args.output_file, 'w') as file_handle:
+ file_handle.write('\n'.join(out_lines))
+
+
+if __name__ == "__main__":
+ main()
diff --git a/chromium/third_party/skia/bench/tile_analyze.py b/chromium/third_party/skia/bench/tile_analyze.py
new file mode 100755
index 00000000000..03fe08673dd
--- /dev/null
+++ b/chromium/third_party/skia/bench/tile_analyze.py
@@ -0,0 +1,279 @@
+#!/usr/bin/env python
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be found
+# in the LICENSE file.
+
+""" Analyze per-tile and viewport bench data, and output visualized results.
+"""
+
+__author__ = 'bensong@google.com (Ben Chen)'
+
+import bench_util
+import boto
+import math
+import optparse
+import os
+import re
+import shutil
+
+from oauth2_plugin import oauth2_plugin
+
+# The default platform to analyze. Used when OPTION_PLATFORM flag is not set.
+DEFAULT_PLATFORM = 'Nexus10_4-1_Float_Bench_32'
+
+# Template for gsutil uri.
+GOOGLE_STORAGE_URI_SCHEME = 'gs'
+URI_BUCKET = 'chromium-skia-gm'
+
+# Maximum number of rows of tiles to track for viewport covering.
+MAX_TILE_ROWS = 8
+
+# Constants for optparse.
+USAGE_STRING = 'USAGE: %s [options]'
+HOWTO_STRING = """
+Note: to read bench data stored in Google Storage, you will need to set up the
+corresponding Python library.
+See http://developers.google.com/storage/docs/gspythonlibrary for details.
+"""
+HELP_STRING = """
+For the given platform and revision number, find corresponding viewport and
+tile benchmarks for each available picture bench, and output visualization and
+analysis in HTML. By default it reads from Skia's Google Storage location where
+bot data are stored, but if --dir is given, will read from local directory
+instead.
+""" + HOWTO_STRING
+
+OPTION_DIR = '--dir'
+OPTION_DIR_SHORT = '-d'
+OPTION_REVISION = '--rev'
+OPTION_REVISION_SHORT = '-r'
+OPTION_PLATFORM = '--platform'
+OPTION_PLATFORM_SHORT = '-p'
+# Bench representation algorithm flag.
+OPTION_REPRESENTATION_ALG = '--algorithm'
+OPTION_REPRESENTATION_ALG_SHORT = '-a'
+
+# Bench representation algorithm. See trunk/bench/bench_util.py.
+REPRESENTATION_ALG = bench_util.ALGORITHM_25TH_PERCENTILE
+
+# Constants for bench file matching.
+GOOGLE_STORAGE_OBJECT_NAME_PREFIX = 'perfdata/Skia_'
+BENCH_FILE_PREFIX_TEMPLATE = 'bench_r%s_'
+TILING_FILE_NAME_INDICATOR = '_tile_'
+VIEWPORT_FILE_NAME_INDICATOR = '_viewport_'
+
+# Regular expression for matching format '<integer>x<integer>'.
+DIMENSIONS_RE = '(\d+)x(\d+)'
+
+# HTML and JS output templates.
+HTML_PREFIX = """
+<html><head><script type="text/javascript" src="https://www.google.com/jsapi">
+</script><script type="text/javascript">google.load("visualization", "1.1",
+{packages:["table"]});google.load("prototype", "1.6");</script>
+<script type="text/javascript" src="https://systemsbiology-visualizations.googlecode.com/svn/trunk/src/main/js/load.js"></script><script
+type="text/javascript"> systemsbiology.load("visualization", "1.0",
+{packages:["bioheatmap"]});</script><script type="text/javascript">
+google.setOnLoadCallback(drawVisualization); function drawVisualization() {
+"""
+HTML_SUFFIX = '</body></html>'
+BAR_CHART_TEMPLATE = ('<img src="https://chart.googleapis.com/chart?chxr=0,0,'
+ '300&chxt=x&chbh=15,0&chs=600x150&cht=bhg&chco=80C65A,224499,FF0000,0A8C8A,'
+ 'EBB671,DE091A,000000,00ffff&chds=a&chdl=%s&chd=t:%s" /><br>\n')
+DRAW_OPTIONS = ('{passThroughBlack:false,useRowLabels:false,cellWidth:30,'
+ 'cellHeight:30}')
+TABLE_OPTIONS = '{showRowNumber:true,firstRowNumber:" ",sort:"disable"}'
+
+def GetFiles(rev, bench_dir, platform):
+ """Reads in bench files of interest into a dictionary.
+
+ If bench_dir is not empty, tries to read in local bench files; otherwise check
+ Google Storage. Filters files by revision (rev) and platform, and ignores
+ non-tile, non-viewport bench files.
+ Outputs dictionary [filename] -> [file content].
+ """
+ file_dic = {}
+ if not bench_dir:
+ uri = boto.storage_uri(URI_BUCKET, GOOGLE_STORAGE_URI_SCHEME)
+ # The boto API does not allow prefix/wildcard matching of Google Storage
+ # objects. And Google Storage has a flat structure instead of being
+ # organized in directories. Therefore, we have to scan all objects in the
+ # Google Storage bucket to find the files we need, which is slow.
+ # The option of implementing prefix matching as in gsutil seems to be
+ # overkill, but gsutil does not provide an API ready for use. If speed is a
+ # big concern, we suggest copying bot bench data from Google Storage using
+ # gsutil and use --log_dir for fast local data reading.
+ for obj in uri.get_bucket():
+ # Filters out files of no interest.
+ if (not obj.name.startswith(GOOGLE_STORAGE_OBJECT_NAME_PREFIX) or
+ (obj.name.find(TILING_FILE_NAME_INDICATOR) < 0 and
+ obj.name.find(VIEWPORT_FILE_NAME_INDICATOR) < 0) or
+ obj.name.find(platform) < 0 or
+ obj.name.find(BENCH_FILE_PREFIX_TEMPLATE % rev) < 0):
+ continue
+ file_dic[
+ obj.name[obj.name.rfind('/') + 1 : ]] = obj.get_contents_as_string()
+ else:
+ for f in os.listdir(bench_dir):
+ if (not os.path.isfile(os.path.join(bench_dir, f)) or
+ (f.find(TILING_FILE_NAME_INDICATOR) < 0 and
+ f.find(VIEWPORT_FILE_NAME_INDICATOR) < 0) or
+ not f.startswith(BENCH_FILE_PREFIX_TEMPLATE % rev)):
+ continue
+ file_dic[f] = open(os.path.join(bench_dir, f)).read()
+
+ if not file_dic:
+ raise Exception('No bench file found in "%s" or Google Storage.' %
+ bench_dir)
+
+ return file_dic
+
+def GetTileMatrix(layout, tile_size, values, viewport):
+ """For the given tile layout and per-tile bench values, returns a matrix of
+ bench values with tiles outside the given viewport set to 0.
+
+ layout, tile_size and viewport are given in string of format <w>x<h>, where
+ <w> is viewport width or number of tile columns, and <h> is viewport height or
+ number of tile rows. We truncate tile rows to MAX_TILE_ROWS to adjust for very
+ long skp's.
+
+ values: per-tile benches ordered row-by-row, starting from the top-left tile.
+
+ Returns [sum, matrix] where sum is the total bench tile time that covers the
+ viewport, and matrix is used for visualizing the tiles.
+ """
+ [tile_cols, tile_rows] = [int(i) for i in layout.split('x')]
+ [tile_x, tile_y] = [int(i) for i in tile_size.split('x')]
+ [viewport_x, viewport_y] = [int(i) for i in viewport.split('x')]
+ viewport_cols = int(math.ceil(viewport_x * 1.0 / tile_x))
+ viewport_rows = int(math.ceil(viewport_y * 1.0 / tile_y))
+ truncated_tile_rows = min(tile_rows, MAX_TILE_ROWS)
+
+ viewport_tile_sum = 0
+ matrix = [[0 for y in range(tile_cols)] for x in range(truncated_tile_rows)]
+ for y in range(min(viewport_cols, tile_cols)):
+ for x in range(min(truncated_tile_rows, viewport_rows)):
+ matrix[x][y] = values[x * tile_cols + y]
+ viewport_tile_sum += values[x * tile_cols + y]
+
+ return [viewport_tile_sum, matrix]
+
+def GetTileVisCodes(suffix, matrix):
+ """Generates and returns strings of [js_codes, row1, row2] which are codes for
+ visualizing the benches from the given tile config and matrix data.
+ row1 is used for the first row of heatmaps; row2 is for corresponding tables.
+ suffix is only used to avoid name conflicts in the whole html output.
+ """
+ this_js = 'var data_%s=new google.visualization.DataTable();' % suffix
+ for i in range(len(matrix[0])):
+ this_js += 'data_%s.addColumn("number","%s");' % (suffix, i)
+ this_js += 'data_%s.addRows(%s);' % (suffix, str(matrix))
+ # Adds heatmap chart.
+ this_js += ('var heat_%s=new org.systemsbiology.visualization' % suffix +
+ '.BioHeatMap(document.getElementById("%s"));' % suffix +
+ 'heat_%s.draw(data_%s,%s);' % (suffix, suffix, DRAW_OPTIONS))
+ # Adds data table chart.
+ this_js += ('var table_%s=new google.visualization.Table(document.' % suffix +
+ 'getElementById("t%s"));table_%s.draw(data_%s,%s);\n' % (
+ suffix, suffix, suffix, TABLE_OPTIONS))
+ table_row1 = '<td>%s<div id="%s"></div></td>' % (suffix, suffix)
+ table_row2 = '<td><div id="t%s"></div></td>' % suffix
+
+ return [this_js, table_row1, table_row2]
+
+def OutputTileAnalysis(rev, representation_alg, bench_dir, platform):
+ """Reads skp bench data and outputs tile vs. viewport analysis for the given
+ platform.
+
+ Ignores data with revisions other than rev. If bench_dir is not empty, read
+ from the local directory instead of Google Storage.
+ Uses the provided representation_alg for calculating bench representations.
+
+ Returns (js_codes, body_codes): strings of js/html codes for stats and
+ visualization.
+ """
+ js_codes = ''
+ body_codes = ('}</script></head><body>'
+ '<h3>PLATFORM: %s REVISION: %s</h3><br>' % (platform, rev))
+ bench_dic = {} # [bench][config] -> [layout, [values]]
+ file_dic = GetFiles(rev, bench_dir, platform)
+ for f in file_dic:
+ for point in bench_util.parse('', file_dic[f].split('\n'),
+ representation_alg):
+ if point.time_type: # Ignores non-walltime time_type.
+ continue
+ bench = point.bench.replace('.skp', '')
+ config = point.config.replace('simple_', '')
+ components = config.split('_')
+ if components[0] == 'viewport':
+ bench_dic.setdefault(bench, {})[config] = [components[1], [point.time]]
+ else: # Stores per-tile benches.
+ bench_dic.setdefault(bench, {})[config] = [
+ point.tile_layout, point.per_tile_values]
+ benches = bench_dic.keys()
+ benches.sort()
+ for bench in benches:
+ body_codes += '<h4>%s</h4><br><table><tr>' % bench
+ heat_plots = '' # For table row of heatmap plots.
+ table_plots = '' # For table row of data table plots.
+ # For bar plot legends and values in URL string.
+ legends = ''
+ values = ''
+ keys = bench_dic[bench].keys()
+ keys.sort()
+ if not keys[-1].startswith('viewport'): # No viewport to analyze; skip.
+ continue
+ else:
+ # Extracts viewport size, which for all viewport configs is the same.
+ viewport = bench_dic[bench][keys[-1]][0]
+ for config in keys:
+ [layout, value_li] = bench_dic[bench][config]
+ if config.startswith('tile_'): # For per-tile data, visualize tiles.
+ tile_size = config.split('_')[1]
+ if (not re.search(DIMENSIONS_RE, layout) or
+ not re.search(DIMENSIONS_RE, tile_size) or
+ not re.search(DIMENSIONS_RE, viewport)):
+ continue # Skip unrecognized formats.
+ [viewport_tile_sum, matrix] = GetTileMatrix(
+ layout, tile_size, value_li, viewport)
+ values += '%s|' % viewport_tile_sum
+ [this_js, row1, row2] = GetTileVisCodes(config + '_' + bench, matrix)
+ heat_plots += row1
+ table_plots += row2
+ js_codes += this_js
+ else: # For viewport data, there is only one element in value_li.
+ values += '%s|' % sum(value_li)
+ legends += '%s:%s|' % (config, sum(value_li))
+ body_codes += (heat_plots + '</tr><tr>' + table_plots + '</tr></table>' +
+ '<br>' + BAR_CHART_TEMPLATE % (legends[:-1], values[:-1]))
+
+ return (js_codes, body_codes)
+
+def main():
+ """Parses flags and outputs expected Skia picture bench results."""
+ parser = optparse.OptionParser(USAGE_STRING % '%prog' + HELP_STRING)
+ parser.add_option(OPTION_PLATFORM_SHORT, OPTION_PLATFORM,
+ dest='plat', default=DEFAULT_PLATFORM,
+ help='Platform to analyze. Set to DEFAULT_PLATFORM if not given.')
+ parser.add_option(OPTION_REVISION_SHORT, OPTION_REVISION,
+ dest='rev',
+ help='(Mandatory) revision number to analyze.')
+ parser.add_option(OPTION_DIR_SHORT, OPTION_DIR,
+ dest='log_dir', default='',
+ help=('(Optional) local directory where bench log files reside. If left '
+ 'empty (by default), will try to read from Google Storage.'))
+ parser.add_option(OPTION_REPRESENTATION_ALG_SHORT, OPTION_REPRESENTATION_ALG,
+ dest='alg', default=REPRESENTATION_ALG,
+ help=('Bench representation algorithm. '
+ 'Default to "%s".' % REPRESENTATION_ALG))
+ (options, args) = parser.parse_args()
+ if not (options.rev and options.rev.isdigit()):
+ parser.error('Please provide correct mandatory flag %s' % OPTION_REVISION)
+ return
+ rev = int(options.rev)
+ (js_codes, body_codes) = OutputTileAnalysis(
+ rev, options.alg, options.log_dir, options.plat)
+ print HTML_PREFIX + js_codes + body_codes + HTML_SUFFIX
+
+
+if '__main__' == __name__:
+ main()