summaryrefslogtreecommitdiffstats
path: root/third_party/webkit/PerformanceTests/MotionMark/tests
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/webkit/PerformanceTests/MotionMark/tests')
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/3d/resources/webgl.js184
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/3d/webgl.html64
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-canvas-images.html26
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-canvas-shapes.html18
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-css-images.html22
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-css-shapes.html33
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-svg-images.html18
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-svg-shapes.html18
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-tagged-images.html22
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-images.js47
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-particles.js88
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-shapes.js87
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-css-images.js61
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-css-shapes.js86
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-particles.js123
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-svg-images.js43
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-svg-particles.js67
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-svg-shapes.js101
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-tagged-images.js106
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image1.jpgbin0 -> 64004 bytes
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image2.jpgbin0 -> 71981 bytes
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image3.jpgbin0 -> 71319 bytes
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image4.jpgbin0 -> 96373 bytes
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image5.jpgbin0 -> 135674 bytes
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/dom/compositing-transforms.html24
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/dom/focus.html51
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/dom/leaves.html26
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/dom/particles.html24
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/compositing-transforms.js66
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/dom-particles.js73
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/focus.js166
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/leaves.js48
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/canvas-stage.html17
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/focus.html29
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/image-data.html28
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/leaves.html25
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/multiply.html53
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/canvas-stage.js52
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/canvas-tests.js311
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/compass.svg7
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/compass100.pngbin0 -> 3048 bytes
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/console.svg6
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/console100.pngbin0 -> 944 bytes
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/contribute.svg6
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/contribute100.pngbin0 -> 3599 bytes
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/debugger.svg5
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/debugger100.pngbin0 -> 2473 bytes
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/focus.js129
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/image-data.js181
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/inspector.svg6
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/inspector100.pngbin0 -> 1477 bytes
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/layout.svg6
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/layout100.pngbin0 -> 423 bytes
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/leaves.js135
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/multiply.js119
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/particles.js112
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/performance.svg6
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/performance100.pngbin0 -> 2546 bytes
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/script.svg5
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/script100.pngbin0 -> 3192 bytes
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/shortcuts.svg5
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/shortcuts100.pngbin0 -> 2763 bytes
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/standards.svg6
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/standards100.pngbin0 -> 4363 bytes
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/storage.svg5
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/storage100.pngbin0 -> 3167 bytes
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/styles.svg5
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/styles100.pngbin0 -> 3875 bytes
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/svg-particles.js111
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/text.js116
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/timeline.svg6
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/timeline100.pngbin0 -> 2039 bytes
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/svg-particles.html38
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/master/text.html82
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/resources/main.js934
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/resources/math.js268
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/resources/stage.css27
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/resources/star.svg8
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/resources/yin-yang.pngbin0 -> 4082 bytes
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/resources/yin-yang.svg17
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/simple/resources/simple-canvas-paths.js453
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/simple/resources/simple-canvas.js35
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/simple/resources/tiled-canvas-image.js119
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/simple/simple-canvas-paths.html18
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/simple/tiled-canvas-image.html16
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/template/resources/template-canvas.js89
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/template/resources/template-css.js46
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/template/resources/template-svg.js46
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/template/template-canvas.html16
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/template/template-css.html16
-rw-r--r--third_party/webkit/PerformanceTests/MotionMark/tests/template/template-svg.html16
91 files changed, 5428 insertions, 0 deletions
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/3d/resources/webgl.js b/third_party/webkit/PerformanceTests/MotionMark/tests/3d/resources/webgl.js
new file mode 100644
index 0000000000..58f5df385e
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/3d/resources/webgl.js
@@ -0,0 +1,184 @@
+(function() {
+
+WebGLStage = Utilities.createSubclass(Stage,
+ function(element, options)
+ {
+ Stage.call(this);
+ },
+ {
+
+ initialize: function(benchmark, options)
+ {
+ Stage.prototype.initialize.call(this, benchmark, options);
+
+ this._numTriangles = 0;
+ this._bufferSize = 0;
+
+ this._gl = this.element.getContext("webgl");
+ var gl = this._gl;
+
+ gl.clearColor(0.5, 0.5, 0.5, 1);
+
+ // Create the vertex shader object.
+ var vertexShader = gl.createShader(gl.VERTEX_SHADER);
+
+ // The source code for the shader is extracted from the <script> element above.
+ gl.shaderSource(vertexShader, this._getFunctionSource("vertex"));
+
+ // Compile the shader.
+ gl.compileShader(vertexShader);
+ if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
+ // We failed to compile. Output to the console and quit.
+ console.error("Vertex Shader failed to compile.");
+ console.error(gl.getShaderInfoLog(vertexShader));
+ return;
+ }
+
+ // Now do the fragment shader.
+ var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
+ gl.shaderSource(fragmentShader, this._getFunctionSource("fragment"));
+ gl.compileShader(fragmentShader);
+ if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
+ console.error("Fragment Shader failed to compile.");
+ console.error(gl.getShaderInfoLog(fragmentShader));
+ return;
+ }
+
+ // We have two compiled shaders. Time to make the program.
+ var program = gl.createProgram();
+ gl.attachShader(program, vertexShader);
+ gl.attachShader(program, fragmentShader);
+ gl.linkProgram(program);
+
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
+ console.error("Unable to link shaders into program.");
+ return;
+ }
+
+ // Our program has two inputs. We have a single uniform "color",
+ // and one vertex attribute "position".
+
+ gl.useProgram(program);
+ this._uScale = gl.getUniformLocation(program, "scale");
+ this._uTime = gl.getUniformLocation(program, "time");
+ this._uOffsetX = gl.getUniformLocation(program, "offsetX");
+ this._uOffsetY = gl.getUniformLocation(program, "offsetY");
+ this._uScalar = gl.getUniformLocation(program, "scalar");
+ this._uScalarOffset = gl.getUniformLocation(program, "scalarOffset");
+
+ this._aPosition = gl.getAttribLocation(program, "position");
+ gl.enableVertexAttribArray(this._aPosition);
+
+ this._aColor = gl.getAttribLocation(program, "color");
+ gl.enableVertexAttribArray(this._aColor);
+
+ this._positionData = new Float32Array([
+ // x y z 1
+ 0, 0.1, 0, 1,
+ -0.1, -0.1, 0, 1,
+ 0.1, -0.1, 0, 1
+ ]);
+ this._positionBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, this._positionBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, this._positionData, gl.STATIC_DRAW);
+
+ this._colorData = new Float32Array([
+ 1, 0, 0, 1,
+ 0, 1, 0, 1,
+ 0, 0, 1, 1
+ ]);
+ this._colorBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, this._colorBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, this._colorData, gl.STATIC_DRAW);
+
+ this._resetIfNecessary();
+ },
+
+ _getFunctionSource: function(id)
+ {
+ return document.getElementById(id).text;
+ },
+
+ _resetIfNecessary: function()
+ {
+ if (this._numTriangles <= this._bufferSize)
+ return;
+
+ if (!this._bufferSize)
+ this._bufferSize = 128;
+
+ while (this._numTriangles > this._bufferSize)
+ this._bufferSize *= 4;
+
+ this._uniformData = new Float32Array(this._bufferSize * 6);
+ for (var i = 0; i < this._bufferSize; ++i) {
+ this._uniformData[i * 6 + 0] = Stage.random(0.2, 0.4);
+ this._uniformData[i * 6 + 1] = 0;
+ this._uniformData[i * 6 + 2] = Stage.random(-0.9, 0.9);
+ this._uniformData[i * 6 + 3] = Stage.random(-0.9, 0.9);
+ this._uniformData[i * 6 + 4] = Stage.random(0.5, 2);
+ this._uniformData[i * 6 + 5] = Stage.random(0, 10);
+ }
+ },
+
+ tune: function(count)
+ {
+ if (!count)
+ return;
+
+ this._numTriangles += count;
+ this._numTriangles = Math.max(this._numTriangles, 0);
+
+ this._resetIfNecessary();
+ },
+
+ animate: function(timeDelta)
+ {
+ var gl = this._gl;
+
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ if (!this._startTime)
+ this._startTime = Stage.dateCounterValue(1000);
+ var elapsedTime = Stage.dateCounterValue(1000) - this._startTime;
+
+ for (var i = 0; i < this._numTriangles; ++i) {
+
+ this._uniformData[i * 6 + 1] = elapsedTime;
+
+ var uniformDataOffset = i * 6;
+ gl.uniform1f(this._uScale, this._uniformData[uniformDataOffset++]);
+ gl.uniform1f(this._uTime, this._uniformData[uniformDataOffset++]);
+ gl.uniform1f(this._uOffsetX, this._uniformData[uniformDataOffset++]);
+ gl.uniform1f(this._uOffsetY, this._uniformData[uniformDataOffset++]);
+ gl.uniform1f(this._uScalar, this._uniformData[uniformDataOffset++]);
+ gl.uniform1f(this._uScalarOffset, this._uniformData[uniformDataOffset++]);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, this._positionBuffer);
+ gl.vertexAttribPointer(this._aPosition, 4, gl.FLOAT, false, 0, 0);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, this._colorBuffer);
+ gl.vertexAttribPointer(this._aColor, 4, gl.FLOAT, false, 0, 0);
+
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
+ }
+
+ },
+
+ complexity: function()
+ {
+ return this._numTriangles;
+ }
+ }
+);
+
+WebGLBenchmark = Utilities.createSubclass(Benchmark,
+ function(options)
+ {
+ Benchmark.call(this, new WebGLStage(), options);
+ }
+);
+
+window.benchmarkClass = WebGLBenchmark;
+
+})();
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/3d/webgl.html b/third_party/webkit/PerformanceTests/MotionMark/tests/3d/webgl.html
new file mode 100644
index 0000000000..cf6442a07a
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/3d/webgl.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+</head>
+<body>
+ <canvas id="stage"></canvas>
+ <script id="vertex" type="x-shader/x-glsl">
+attribute vec4 position;
+attribute vec4 color;
+
+uniform float scale;
+uniform float time;
+uniform float offsetX;
+uniform float offsetY;
+uniform float scalar;
+uniform float scalarOffset;
+
+varying vec4 v_color;
+
+void main() {
+
+ float fade = mod(scalarOffset + time * scalar / 10.0, 1.0);
+
+ if (fade < 0.5) {
+ fade = fade * 2.0;
+ } else {
+ fade = (1.0 - fade) * 2.0;
+ }
+
+ float xpos = position.x * scale;
+ float ypos = position.y * scale;
+
+ float angle = 3.14159 * 2.0 * fade;
+ float xrot = xpos * cos(angle) - ypos * sin(angle);
+ float yrot = xpos * sin(angle) + ypos * cos(angle);
+
+ xpos = xrot + offsetX;
+ ypos = yrot + offsetY;
+
+ v_color = vec4(fade, 1.0 - fade, 0.0, 1.0) + color;
+ gl_Position = vec4(xpos, ypos, 0.0, 1.0);
+}
+ </script>
+ <script id="fragment" type="x-shader/x-glsl">
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+varying vec4 v_color;
+
+void main() {
+ gl_FragColor = v_color;
+}
+ </script>
+ <script src="../../resources/strings.js"></script>
+ <script src="../../resources/extensions.js"></script>
+ <script src="../../resources/statistics.js"></script>
+ <script src="../resources/math.js"></script>
+ <script src="../resources/main.js"></script>
+ <script src="resources/webgl.js"></script>
+</body>
+</html>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-canvas-images.html b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-canvas-images.html
new file mode 100644
index 0000000000..864c19adcd
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-canvas-images.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+ <style>
+ img.hidden {
+ position: absolute;
+ visibility: hidden;
+ }
+ </style>
+</head>
+<body>
+ <img class="hidden" src="../resources/yin-yang.svg">
+ <img class="hidden" src="../resources/yin-yang.png">
+ <canvas id="stage"></canvas>
+ <script src="../../resources/strings.js"></script>
+ <script src="../../resources/extensions.js"></script>
+ <script src="../../resources/statistics.js"></script>
+ <script src="../resources/math.js"></script>
+ <script src="../resources/main.js"></script>
+ <script src="resources/bouncing-particles.js"></script>
+ <script src="resources/bouncing-canvas-particles.js"></script>
+ <script src="resources/bouncing-canvas-images.js"></script>
+</body>
+</html>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-canvas-shapes.html b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-canvas-shapes.html
new file mode 100644
index 0000000000..c759d45c08
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-canvas-shapes.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+</head>
+<body>
+ <canvas id="stage"></canvas>
+ <script src="../../resources/strings.js"></script>
+ <script src="../../resources/extensions.js"></script>
+ <script src="../../resources/statistics.js"></script>
+ <script src="../resources/math.js"></script>
+ <script src="../resources/main.js"></script>
+ <script src="resources/bouncing-particles.js"></script>
+ <script src="resources/bouncing-canvas-particles.js"></script>
+ <script src="resources/bouncing-canvas-shapes.js"></script>
+</body>
+</html>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-css-images.html b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-css-images.html
new file mode 100644
index 0000000000..058de486de
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-css-images.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+ <style>
+ img {
+ position: absolute;
+ }
+ </style>
+</head>
+<body>
+ <div id="stage"></div>
+ <script src="../../resources/strings.js"></script>
+ <script src="../../resources/extensions.js"></script>
+ <script src="../../resources/statistics.js"></script>
+ <script src="../resources/math.js"></script>
+ <script src="../resources/main.js"></script>
+ <script src="resources/bouncing-particles.js"></script>
+ <script src="resources/bouncing-css-images.js"></script>
+</body>
+</html>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-css-shapes.html b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-css-shapes.html
new file mode 100644
index 0000000000..0c1248f490
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-css-shapes.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+ <style>
+ .circle {
+ position: absolute;
+ background-color: #000000;
+ border-radius: 50% 50%;
+ }
+ .rect {
+ position: absolute;
+ background-color: #000000;
+ }
+ .star {
+ -webkit-clip-path: polygon(50% 0%, 38% 38%, 0% 38%, 30% 60%, 18% 100%, 50% 75%, 82% 100%, 70% 60%, 100% 38%, 62% 38%);
+ -ms-clip-path: polygon(50% 0%, 38% 38%, 0% 38%, 30% 60%, 18% 100%, 50% 75%, 82% 100%, 70% 60%, 100% 38%, 62% 38%);
+ clip-path: polygon(50% 0%, 38% 38%, 0% 38%, 30% 60%, 18% 100%, 50% 75%, 82% 100%, 70% 60%, 100% 38%, 62% 38%);
+ }
+ </style>
+</head>
+<body>
+ <div id="stage"></div>
+ <script src="../../resources/strings.js"></script>
+ <script src="../../resources/extensions.js"></script>
+ <script src="../../resources/statistics.js"></script>
+ <script src="../resources/math.js"></script>
+ <script src="../resources/main.js"></script>
+ <script src="resources/bouncing-particles.js"></script>
+ <script src="resources/bouncing-css-shapes.js"></script>
+</body>
+</html>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-svg-images.html b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-svg-images.html
new file mode 100644
index 0000000000..2b6a0b9db5
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-svg-images.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+</head>
+<body>
+ <svg id="stage"></svg>
+ <script src="../../resources/strings.js"></script>
+ <script src="../../resources/extensions.js"></script>
+ <script src="../../resources/statistics.js"></script>
+ <script src="../resources/math.js"></script>
+ <script src="../resources/main.js"></script>
+ <script src="resources/bouncing-particles.js"></script>
+ <script src="resources/bouncing-svg-particles.js"></script>
+ <script src="resources/bouncing-svg-images.js"></script>
+</body>
+</html>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-svg-shapes.html b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-svg-shapes.html
new file mode 100644
index 0000000000..a821231672
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-svg-shapes.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+</head>
+<body>
+ <svg id="stage"></svg>
+ <script src="../../resources/strings.js"></script>
+ <script src="../../resources/extensions.js"></script>
+ <script src="../../resources/statistics.js"></script>
+ <script src="../resources/math.js"></script>
+ <script src="../resources/main.js"></script>
+ <script src="resources/bouncing-particles.js"></script>
+ <script src="resources/bouncing-svg-particles.js"></script>
+ <script src="resources/bouncing-svg-shapes.js"></script>
+</body>
+</html>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-tagged-images.html b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-tagged-images.html
new file mode 100644
index 0000000000..f67f14ad36
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-tagged-images.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <style>
+ img {
+ position: absolute;
+ }
+ </style>
+ <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+
+ <script src="../../resources/strings.js"></script>
+ <script src="../../resources/extensions.js"></script>
+ <script src="../../resources/statistics.js"></script>
+ <script src="../resources/math.js"></script>
+ <script src="../resources/main.js"></script>
+ <script src="resources/bouncing-particles.js"></script>
+ <script src="resources/bouncing-tagged-images.js"></script>
+</head>
+<body>
+ <div id="stage"></div>
+</body>
+</html>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-images.js b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-images.js
new file mode 100644
index 0000000000..5fba5ad761
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-images.js
@@ -0,0 +1,47 @@
+(function() {
+
+BouncingCanvasImage = Utilities.createSubclass(BouncingCanvasParticle,
+ function(stage)
+ {
+ BouncingCanvasParticle.call(this, stage, "image");
+ this._imageElement = stage.imageElement;
+ }, {
+
+ _draw: function()
+ {
+ this.context.save();
+ this.applyRotation();
+ this.context.drawImage(this._imageElement, 0, 0, this.size.x, this.size.y);
+ this.context.restore();
+ }
+});
+
+BouncingCanvasImagesStage = Utilities.createSubclass(BouncingCanvasParticlesStage,
+ function()
+ {
+ BouncingCanvasParticlesStage.call(this);
+ }, {
+
+ initialize: function(benchmark, options)
+ {
+ BouncingCanvasParticlesStage.prototype.initialize.call(this, benchmark, options);
+ var imageSrc = options["imageSrc"] || "resources/yin-yang.svg";
+ this.imageElement = document.querySelector(".hidden[src=\"" + imageSrc + "\"]");
+ },
+
+ createParticle: function()
+ {
+ return new BouncingCanvasImage(this);
+ }
+});
+
+BouncingCanvasImagesBenchmark = Utilities.createSubclass(Benchmark,
+ function(options)
+ {
+ Benchmark.call(this, new BouncingCanvasImagesStage(), options);
+ }
+);
+
+window.benchmarkClass = BouncingCanvasImagesBenchmark;
+
+})();
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-particles.js b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-particles.js
new file mode 100644
index 0000000000..0a76ba05c3
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-particles.js
@@ -0,0 +1,88 @@
+BouncingCanvasParticle = Utilities.createSubclass(BouncingParticle,
+ function(stage, shape)
+ {
+ BouncingParticle.call(this, stage);
+ this.context = stage.context;
+ this._shape = shape;
+ this._clip = stage.clip;
+ }, {
+
+ applyRotation: function()
+ {
+ if (this._shape == "circle")
+ return;
+
+ this.context.translate(this.size.x / 2, this.size.y / 2);
+ this.context.rotate(this.rotater.degree() * Math.PI / 180);
+ this.context.translate(-this.size.x / 2, -this.size.y / 2);
+ },
+
+ applyClipping: function()
+ {
+ var clipPoints = BouncingCanvasParticle.clips[this._clip];
+ if (!clipPoints)
+ return;
+
+ this.context.beginPath();
+ clipPoints.forEach(function(point, index) {
+ var point = this.size.multiply(point);
+ if (!index)
+ this.context.moveTo(point.x, point.y);
+ else
+ this.context.lineTo(point.x, point.y);
+ }, this);
+
+ this.context.closePath();
+ this.context.clip();
+ },
+
+ _draw: function()
+ {
+ throw "Not implemented";
+ },
+
+ animate: function(timeDelta)
+ {
+ BouncingParticle.prototype.animate.call(this, timeDelta);
+ this.context.save();
+ this.context.translate(this.position.x, this.position.y);
+ this._draw();
+ this.context.restore();
+ }
+});
+
+BouncingCanvasParticle.clips = {
+ star: [
+ new Point(0.50, 0.00),
+ new Point(0.38, 0.38),
+ new Point(0.00, 0.38),
+ new Point(0.30, 0.60),
+ new Point(0.18, 1.00),
+ new Point(0.50, 0.75),
+ new Point(0.82, 1.00),
+ new Point(0.70, 0.60),
+ new Point(1.00, 0.38),
+ new Point(0.62, 0.38)
+ ]
+};
+
+BouncingCanvasParticlesStage = Utilities.createSubclass(BouncingParticlesStage,
+ function()
+ {
+ BouncingParticlesStage.call(this);
+ }, {
+
+ initialize: function(benchmark, options)
+ {
+ BouncingParticlesStage.prototype.initialize.call(this, benchmark, options);
+ this.context = this.element.getContext("2d");
+ },
+
+ animate: function(timeDelta)
+ {
+ this.context.clearRect(0, 0, this.size.x, this.size.y);
+ this.particles.forEach(function(particle) {
+ particle.animate(timeDelta);
+ });
+ }
+});
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-shapes.js b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-shapes.js
new file mode 100644
index 0000000000..49a31cf40d
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-shapes.js
@@ -0,0 +1,87 @@
+(function() {
+
+BouncingCanvasShape = Utilities.createSubclass(BouncingCanvasParticle,
+ function(stage)
+ {
+ BouncingCanvasParticle.call(this, stage, stage.shape);
+ this._fill = stage.fill;
+ this._color0 = Stage.randomColor();
+ this._color1 = Stage.randomColor();
+ }, {
+
+ _applyFill: function()
+ {
+ switch (this._fill) {
+ case "gradient":
+ var gradient = this.context.createLinearGradient(0, 0, this.size.width, 0);
+ gradient.addColorStop(0, this._color0);
+ gradient.addColorStop(1, this._color1);
+ this.context.fillStyle = gradient;
+ break;
+
+ case "solid":
+ default:
+ this.context.fillStyle = this._color0;
+ break;
+ }
+ },
+
+ _drawShape: function()
+ {
+ this.context.beginPath();
+
+ switch (this._shape) {
+ case "rect":
+ this.context.rect(0, 0, this.size.width, this.size.height);
+ break;
+
+ case "circle":
+ default:
+ var center = this.size.center;
+ var radius = Math.min(this.size.x, this.size.y) / 2;
+ this.context.arc(center.x, center.y, radius, 0, Math.PI * 2, true);
+ break;
+ }
+
+ this.context.fill();
+ },
+
+ _draw: function()
+ {
+ this.context.save();
+ this._applyFill();
+ this.applyRotation();
+ this.applyClipping();
+ this._drawShape();
+ this.context.restore();
+ }
+});
+
+BouncingCanvasShapesStage = Utilities.createSubclass(BouncingCanvasParticlesStage,
+ function ()
+ {
+ BouncingCanvasParticlesStage.call(this);
+ }, {
+
+ initialize: function(benchmark, options)
+ {
+ BouncingCanvasParticlesStage.prototype.initialize.call(this, benchmark, options);
+ this.parseShapeParameters(options);
+ },
+
+ createParticle: function()
+ {
+ return new BouncingCanvasShape(this);
+ }
+});
+
+BouncingCanvasShapesBenchmark = Utilities.createSubclass(Benchmark,
+ function(options)
+ {
+ Benchmark.call(this, new BouncingCanvasShapesStage(), options);
+ }
+);
+
+window.benchmarkClass = BouncingCanvasShapesBenchmark;
+
+})(); \ No newline at end of file
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-css-images.js b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-css-images.js
new file mode 100644
index 0000000000..ce9a48c276
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-css-images.js
@@ -0,0 +1,61 @@
+(function() {
+
+BouncingCssImage = Utilities.createSubclass(BouncingParticle,
+ function(stage)
+ {
+ BouncingParticle.call(this, stage);
+
+ this.element = document.createElement("img");
+ this.element.style.width = this.size.x + "px";
+ this.element.style.height = this.size.y + "px";
+ this.element.setAttribute("src", stage.imageSrc);
+
+ stage.element.appendChild(this.element);
+ this._move();
+ }, {
+
+ _move: function()
+ {
+ this.element.style.transform = "translate(" + this.position.x + "px," + this.position.y + "px) " + this.rotater.rotateZ();
+ },
+
+ animate: function(timeDelta)
+ {
+ BouncingParticle.prototype.animate.call(this, timeDelta);
+ this._move();
+ }
+});
+
+BouncingCssImagesStage = Utilities.createSubclass(BouncingParticlesStage,
+ function()
+ {
+ BouncingParticlesStage.call(this);
+ }, {
+
+ initialize: function(benchmark, options)
+ {
+ BouncingParticlesStage.prototype.initialize.call(this, benchmark, options);
+ this.imageSrc = options["imageSrc"] || "../resources/yin-yang.svg";
+ },
+
+ createParticle: function()
+ {
+ return new BouncingCssImage(this);
+ },
+
+ particleWillBeRemoved: function(particle)
+ {
+ particle.element.remove();
+ }
+});
+
+BouncingCssImagesBenchmark = Utilities.createSubclass(Benchmark,
+ function(options)
+ {
+ Benchmark.call(this, new BouncingCssImagesStage(), options);
+ }
+);
+
+window.benchmarkClass = BouncingCssImagesBenchmark;
+
+})();
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-css-shapes.js b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-css-shapes.js
new file mode 100644
index 0000000000..a1f81863f9
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-css-shapes.js
@@ -0,0 +1,86 @@
+(function() {
+
+BouncingCssShape = Utilities.createSubclass(BouncingParticle,
+ function(stage)
+ {
+ BouncingParticle.call(this, stage);
+
+ this.element = this._createSpan(stage);
+
+ switch (stage.fill) {
+ case "solid":
+ default:
+ this.element.style.backgroundColor = Stage.randomColor();
+ break;
+
+ case "gradient":
+ this.element.style.background = "linear-gradient(" + Stage.randomColor() + ", " + Stage.randomColor() + ")";
+ break;
+ }
+
+ if (stage.blend)
+ this.element.style.mixBlendMode = Stage.randomStyleMixBlendMode();
+
+ // Some browsers have not un-prefixed the css filter yet.
+ if (stage.filter)
+ Utilities.setElementPrefixedProperty(this.element, "filter", Stage.randomStyleFilter());
+
+ this._move();
+ }, {
+
+ _createSpan: function(stage)
+ {
+ var span = document.createElement("span");
+ span.className = stage.shape + " " + stage.clip;
+ span.style.width = this.size.x + "px";
+ span.style.height = this.size.y + "px";
+ stage.element.appendChild(span);
+ return span;
+ },
+
+ _move: function()
+ {
+ this.element.style.transform = "translate(" + this.position.x + "px," + this.position.y + "px)" + this.rotater.rotateZ();
+ },
+
+ animate: function(timeDelta)
+ {
+ BouncingParticle.prototype.animate.call(this, timeDelta);
+ this.rotater.next(timeDelta);
+ this._move();
+ }
+});
+
+BouncingCssShapesStage = Utilities.createSubclass(BouncingParticlesStage,
+ function()
+ {
+ BouncingParticlesStage.call(this);
+ }, {
+
+ initialize: function(benchmark, options)
+ {
+ BouncingParticlesStage.prototype.initialize.call(this, benchmark, options);
+ this.parseShapeParameters(options);
+ },
+
+ createParticle: function()
+ {
+ return new BouncingCssShape(this);
+ },
+
+ particleWillBeRemoved: function(particle)
+ {
+ particle.element.remove();
+ }
+});
+
+BouncingCssShapesBenchmark = Utilities.createSubclass(Benchmark,
+ function(options)
+ {
+ Benchmark.call(this, new BouncingCssShapesStage(), options);
+ }
+);
+
+window.benchmarkClass = BouncingCssShapesBenchmark;
+
+})();
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-particles.js b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-particles.js
new file mode 100644
index 0000000000..27e02a7085
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-particles.js
@@ -0,0 +1,123 @@
+function BouncingParticle(stage)
+{
+ this._stageSize = stage.size;
+ this.size = stage.particleSize;
+
+ this.position = Stage.randomPosition(stage.size.subtract(stage.particleSize));
+ this._angle = Stage.randomAngle();
+ this._velocity = Stage.randomVelocity(stage.maxVelocity);
+ this.rotater = Stage.randomRotater();
+}
+
+BouncingParticle.prototype =
+{
+ get center()
+ {
+ return this.position.add(this.size.center);
+ },
+
+ animate: function(timeDelta)
+ {
+ this.position = this.position.move(this._angle, this._velocity, timeDelta);
+ this.rotater.next(timeDelta);
+
+ // If particle is going to move off right side
+ if (this.position.x + this.size.x > this._stageSize.x) {
+ // If direction is East-South, go West-South.
+ if (this._angle >= 0 && this._angle < Math.PI / 2)
+ this._angle = Math.PI - this._angle;
+ // If angle is East-North, go West-North.
+ else if (this._angle > Math.PI / 2 * 3)
+ this._angle = this._angle - (this._angle - Math.PI / 2 * 3) * 2;
+ // Make sure the particle does not go outside the stage boundaries.
+ this.position.x = this._stageSize.x - this.size.x;
+ }
+
+ // If particle is going to move off left side
+ if (this.position.x < 0) {
+ // If angle is West-South, go East-South.
+ if (this._angle > Math.PI / 2 && this._angle < Math.PI)
+ this._angle = Math.PI - this._angle;
+ // If angle is West-North, go East-North.
+ else if (this._angle > Math.PI && this._angle < Math.PI / 2 * 3)
+ this._angle = this._angle + (Math.PI / 2 * 3 - this._angle) * 2;
+ // Make sure the particle does not go outside the stage boundaries.
+ this.position.x = 0;
+ }
+
+ // If particle is going to move off bottom side
+ if (this.position.y + this.size.y > this._stageSize.y) {
+ // If direction is South, go North.
+ if (this._angle > 0 && this._angle < Math.PI)
+ this._angle = Math.PI * 2 - this._angle;
+ // Make sure the particle does not go outside the stage boundaries.
+ this.position.y = this._stageSize.y - this.size.y;
+ }
+
+ // If particle is going to move off top side
+ if (this.position.y < 0) {
+ // If direction is North, go South.
+ if (this._angle > Math.PI && this._angle < Math.PI * 2)
+ this._angle = this._angle - (this._angle - Math.PI) * 2;
+ // Make sure the particle does not go outside the stage boundaries.
+ this.position.y = 0;
+ }
+ }
+}
+
+BouncingParticlesStage = Utilities.createSubclass(Stage,
+ function()
+ {
+ Stage.call(this);
+ this.particles = [];
+ }, {
+
+ initialize: function(benchmark, options)
+ {
+ Stage.prototype.initialize.call(this, benchmark, options);
+ this.particleSize = new Point(parseInt(options["particleWidth"]) || 10, parseInt(options["particleHeight"]) || 10);
+ this.maxVelocity = Math.max(parseInt(options["maxVelocity"]) || 500, 100);
+ },
+
+ parseShapeParameters: function(options)
+ {
+ this.shape = options["shape"] || "circle";
+ this.fill = options["fill"] || "solid";
+ this.clip = options["clip"] || "";
+ this.blend = options["blend"] || false;
+ this.filter = options["filter"] || false;
+ },
+
+ animate: function(timeDelta)
+ {
+ this.particles.forEach(function(particle) {
+ particle.animate(timeDelta);
+ });
+ },
+
+ tune: function(count)
+ {
+ if (count == 0)
+ return;
+
+ if (count > 0) {
+ for (var i = 0; i < count; ++i)
+ this.particles.push(this.createParticle());
+ return;
+ }
+
+ count = Math.min(-count, this.particles.length);
+
+ if (typeof(this.particleWillBeRemoved) == "function") {
+ for (var i = 0; i < count; ++i)
+ this.particleWillBeRemoved(this.particles[this.particles.length - 1 - i]);
+ }
+
+ this.particles.splice(-count, count);
+ },
+
+ complexity: function()
+ {
+ return this.particles.length;
+ }
+});
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-svg-images.js b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-svg-images.js
new file mode 100644
index 0000000000..2239557312
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-svg-images.js
@@ -0,0 +1,43 @@
+(function() {
+
+BouncingSvgImage = Utilities.createSubclass(BouncingSvgParticle,
+ function(stage)
+ {
+ BouncingSvgParticle.call(this, stage, "image");
+
+ var attrs = { x: 0, y: 0, width: this.size.x, height: this.size.y };
+ var xlinkAttrs = { href: stage.imageSrc };
+ this.element = Utilities.createSVGElement("image", attrs, xlinkAttrs, stage.element);
+ this._move();
+ }
+);
+
+BouncingSvgImagesStage = Utilities.createSubclass(BouncingSvgParticlesStage,
+ function()
+ {
+ BouncingSvgParticlesStage.call(this);
+ }, {
+
+ initialize: function(benchmark, options)
+ {
+ BouncingSvgParticlesStage.prototype.initialize.call(this, benchmark, options);
+ this.imageSrc = options["imageSrc"] || "resources/yin-yang.svg";
+ },
+
+ createParticle: function()
+ {
+ return new BouncingSvgImage(this);
+ }
+});
+
+BouncingSvgImagesBenchmark = Utilities.createSubclass(Benchmark,
+ function(options)
+ {
+ Benchmark.call(this, new BouncingSvgImagesStage(), options);
+ }
+);
+
+window.benchmarkClass = BouncingSvgImagesBenchmark;
+
+})();
+
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-svg-particles.js b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-svg-particles.js
new file mode 100644
index 0000000000..0988c42d8e
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-svg-particles.js
@@ -0,0 +1,67 @@
+BouncingSvgParticle = Utilities.createSubclass(BouncingParticle,
+ function(stage, shape)
+ {
+ BouncingParticle.call(this, stage);
+ this._shape = shape;
+ }, {
+
+ _applyClipping: function(stage)
+ {
+ if (stage.clip != "star")
+ return;
+
+ stage.ensureClipStarIsCreated();
+ this.element.setAttribute("clip-path", "url(#star-clip)");
+ },
+
+ _move: function()
+ {
+ var transform = "translate(" + this.position.x + ", " + this.position.y + ")";
+ if (this._shape != "circle")
+ transform += this.rotater.rotate(this.size.center);
+ this.element.setAttribute("transform", transform);
+ },
+
+ animate: function(timeDelta)
+ {
+ BouncingParticle.prototype.animate.call(this, timeDelta);
+ this._move();
+ }
+});
+
+BouncingSvgParticlesStage = Utilities.createSubclass(BouncingParticlesStage,
+ function()
+ {
+ BouncingParticlesStage.call(this);
+ }, {
+
+ _createDefs: function()
+ {
+ return Utilities.createSVGElement("defs", {}, {}, this.element);
+ },
+
+ _ensureDefsIsCreated: function()
+ {
+ return this.element.querySelector("defs") || this._createDefs();
+ },
+
+ _createClipStar: function()
+ {
+ var attrs = { id: "star-clip", clipPathUnits: "objectBoundingBox" };
+ var clipPath = Utilities.createSVGElement("clipPath", attrs, {}, this._ensureDefsIsCreated());
+
+ attrs = { d: "M.50,0L.38,.38L0,.38L.30,.60L.18,1L.50,.75L.82,1L.70,.60L1,.38L.62,.38z" };
+ Utilities.createSVGElement("path", attrs, {}, clipPath);
+ return clipPath;
+ },
+
+ ensureClipStarIsCreated: function()
+ {
+ return this.element.querySelector("#star-clip") || this._createClipStar();
+ },
+
+ particleWillBeRemoved: function(particle)
+ {
+ particle.element.remove();
+ }
+});
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-svg-shapes.js b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-svg-shapes.js
new file mode 100644
index 0000000000..14c917cc31
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-svg-shapes.js
@@ -0,0 +1,101 @@
+(function() {
+
+BouncingSvgShape = Utilities.createSubclass(BouncingSvgParticle,
+ function(stage)
+ {
+ BouncingSvgParticle.call(this, stage, stage.shape);
+ this._fill = stage.fill;
+
+ this._createShape(stage);
+ this._applyClipping(stage);
+ this._applyFill(stage);
+
+ this._move();
+ }, {
+
+ _createShape: function(stage)
+ {
+ switch (this._shape) {
+ case "rect":
+ var attrs = { x: 0, y: 0, width: this.size.x, height: this.size.y };
+ this.element = Utilities.createSVGElement("rect", attrs, {}, stage.element);
+ break;
+
+ case "circle":
+ default:
+ var attrs = { cx: this.size.x / 2, cy: this.size.y / 2, r: Math.min(this.size.x, this.size.y) / 2 };
+ this.element = Utilities.createSVGElement("circle", attrs, {}, stage.element);
+ break;
+ }
+ },
+
+ _applyFill: function(stage)
+ {
+ switch (this._fill) {
+ case "gradient":
+ var gradient = stage.createGradient(2);
+ this.element.setAttribute("fill", "url(#" + gradient.getAttribute("id") + ")");
+ break;
+
+ case "solid":
+ default:
+ this.element.setAttribute("fill", Stage.randomColor());
+ break;
+ }
+ }
+});
+
+BouncingSvgShapesStage = Utilities.createSubclass(BouncingSvgParticlesStage,
+ function()
+ {
+ BouncingSvgParticlesStage.call(this);
+ }, {
+
+ initialize: function(benchmark, options)
+ {
+ BouncingSvgParticlesStage.prototype.initialize.call(this, benchmark, options);
+ this.parseShapeParameters(options);
+ this._gradientsCount = 0;
+ },
+
+ createGradient: function(stops)
+ {
+ var attrs = { id: "gradient-" + ++this._gradientsCount };
+ var gradient = Utilities.createSVGElement("linearGradient", attrs, {}, this._ensureDefsIsCreated());
+
+ for (var i = 0; i < stops; ++i) {
+ attrs = { offset: i * 100 / (stops - 1) + "%", 'stop-color': Stage.randomColor() };
+ Utilities.createSVGElement("stop", attrs, {}, gradient);
+ }
+
+ return gradient;
+ },
+
+ createParticle: function()
+ {
+ return new BouncingSvgShape(this);
+ },
+
+ particleWillBeRemoved: function(particle)
+ {
+ BouncingSvgParticlesStage.prototype.particleWillBeRemoved.call(this, particle);
+
+ var fill = particle.element.getAttribute("fill");
+ if (fill.indexOf("url(#") != 0)
+ return;
+
+ var gradient = this.element.querySelector(fill.substring(4, fill.length - 1));
+ this._ensureDefsIsCreated().removeChild(gradient);
+ }
+});
+
+BouncingSvgShapesBenchmark = Utilities.createSubclass(Benchmark,
+ function(options)
+ {
+ Benchmark.call(this, new BouncingSvgShapesStage(), options);
+ }
+);
+
+window.benchmarkClass = BouncingSvgShapesBenchmark;
+
+})();
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-tagged-images.js b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-tagged-images.js
new file mode 100644
index 0000000000..1ef6a091d2
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-tagged-images.js
@@ -0,0 +1,106 @@
+(function() {
+
+BouncingTaggedImage = Utilities.createSubclass(BouncingParticle,
+ function(stage)
+ {
+ BouncingParticle.call(this, stage);
+
+ this.element = document.createElement("img");
+ this.element.style.width = this.size.x + "px";
+ this.element.style.height = this.size.y + "px";
+ this.element.setAttribute("src", Stage.randomElementInArray(stage.images).src);
+
+ stage.element.appendChild(this.element);
+ this._move();
+ }, {
+
+ _move: function()
+ {
+ this.element.style.transform = "translate(" + this.position.x + "px," + this.position.y + "px) " + this.rotater.rotateZ();
+ },
+
+ animate: function(timeDelta)
+ {
+ BouncingParticle.prototype.animate.call(this, timeDelta);
+ this._move();
+ }
+});
+
+BouncingTaggedImagesStage = Utilities.createSubclass(BouncingParticlesStage,
+
+ function()
+ {
+ BouncingParticlesStage.call(this);
+ }, {
+
+ imageSrcs: [
+ "image1",
+ "image2",
+ "image3",
+ "image4",
+ "image5",
+ ],
+ images: [],
+
+ initialize: function(benchmark, options)
+ {
+ BouncingParticlesStage.prototype.initialize.call(this, benchmark, options);
+
+ var lastPromise;
+ var images = this.images;
+ this.imageSrcs.forEach(function(imageSrc) {
+ var promise = this._loadImage("resources/" + imageSrc + ".jpg");
+ if (!lastPromise)
+ lastPromise = promise;
+ else {
+ lastPromise = lastPromise.then(function(img) {
+ images.push(img);
+ return promise;
+ });
+ }
+ }, this);
+
+ lastPromise.then(function(img) {
+ images.push(img);
+ benchmark.readyPromise.resolve();
+ });
+ },
+
+ _loadImage: function(src) {
+ var img = new Image;
+ var promise = new SimplePromise;
+
+ img.onload = function(e) {
+ promise.resolve(e.target);
+ };
+
+ img.src = src;
+ return promise;
+ },
+
+ createParticle: function()
+ {
+ return new BouncingTaggedImage(this);
+ },
+
+ particleWillBeRemoved: function(particle)
+ {
+ particle.element.remove();
+ }
+});
+
+BouncingTaggedImagesBenchmark = Utilities.createSubclass(Benchmark,
+ function(options)
+ {
+ Benchmark.call(this, new BouncingTaggedImagesStage(), options);
+ }, {
+
+ waitUntilReady: function() {
+ this.readyPromise = new SimplePromise;
+ return this.readyPromise;
+ }
+});
+
+window.benchmarkClass = BouncingTaggedImagesBenchmark;
+
+})();
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image1.jpg b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image1.jpg
new file mode 100644
index 0000000000..ea7a4c1303
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image1.jpg
Binary files differ
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image2.jpg b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image2.jpg
new file mode 100644
index 0000000000..697272dcb0
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image2.jpg
Binary files differ
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image3.jpg b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image3.jpg
new file mode 100644
index 0000000000..6e5964e7a9
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image3.jpg
Binary files differ
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image4.jpg b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image4.jpg
new file mode 100644
index 0000000000..806f548c44
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image4.jpg
Binary files differ
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image5.jpg b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image5.jpg
new file mode 100644
index 0000000000..d7971f6bcb
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image5.jpg
Binary files differ
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/dom/compositing-transforms.html b/third_party/webkit/PerformanceTests/MotionMark/tests/dom/compositing-transforms.html
new file mode 100644
index 0000000000..6d5b0bf5e6
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/dom/compositing-transforms.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+ <style>
+ img {
+ position: absolute;
+ width: 80px;
+ height: 80px;
+ }
+ </style>
+</head>
+<body>
+ <div id="stage"></div>
+ <script src="../../resources/strings.js"></script>
+ <script src="../../resources/extensions.js"></script>
+ <script src="../../resources/statistics.js"></script>
+ <script src="../resources/math.js"></script>
+ <script src="../resources/main.js"></script>
+ <script src="../bouncing-particles/resources/bouncing-particles.js"></script>
+ <script src="resources/compositing-transforms.js"></script>
+</body>
+</html>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/dom/focus.html b/third_party/webkit/PerformanceTests/MotionMark/tests/dom/focus.html
new file mode 100644
index 0000000000..02264d746f
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/dom/focus.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+ <style type="text/css">
+
+ #stage {
+ background-color: #201A1F;
+ z-index: -10000;
+ }
+
+ #stage > div {
+ position: absolute;
+ overflow: hidden;
+ }
+ #stage div div {
+ position: absolute;
+ background-color: #DEDADD;
+ border-radius: 50%;
+ }
+
+ #center-text {
+ font-size: 90%;
+ transform: translate3d(-50%, -50%, 0);
+ }
+
+ #center-text span {
+ position: absolute;
+ color: #201A1F;
+ font-weight: 400;
+ font-size: 2em;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ }
+
+ </style>
+</head>
+<body>
+ <div id="stage">
+ <div id="center-text"><div><span>focus</span></div></div>
+ </div>
+ <script src="../../resources/strings.js"></script>
+ <script src="../../resources/extensions.js"></script>
+ <script src="../../resources/statistics.js"></script>
+ <script src="../resources/math.js"></script>
+ <script src="../resources/main.js"></script>
+ <script src="resources/focus.js"></script>
+</body>
+</html>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/dom/leaves.html b/third_party/webkit/PerformanceTests/MotionMark/tests/dom/leaves.html
new file mode 100644
index 0000000000..625882ebef
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/dom/leaves.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+ <style>
+ #stage {
+ background-color: #23282B;
+ }
+ #stage img {
+ position: absolute;
+ }
+ </style>
+</head>
+<body>
+ <div id="stage"></div>
+ <script src="../../resources/strings.js"></script>
+ <script src="../../resources/extensions.js"></script>
+ <script src="../../resources/statistics.js"></script>
+ <script src="../resources/math.js"></script>
+ <script src="../resources/main.js"></script>
+ <script src="../master/resources/particles.js"></script>
+ <script src="../master/resources/leaves.js"></script>
+ <script src="resources/leaves.js"></script>
+</body>
+</html>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/dom/particles.html b/third_party/webkit/PerformanceTests/MotionMark/tests/dom/particles.html
new file mode 100644
index 0000000000..fdc09399c9
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/dom/particles.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+ <style>
+ #stage div {
+ position: absolute;
+ -webkit-mask-image: url(../resources/star.svg);
+ mask: url(../resources/star.svg#star-mask);
+ }
+ </style>
+</head>
+<body>
+ <div id="stage"></div>
+ <script src="../../resources/strings.js"></script>
+ <script src="../../resources/extensions.js"></script>
+ <script src="../../resources/statistics.js"></script>
+ <script src="../resources/math.js"></script>
+ <script src="../resources/main.js"></script>
+ <script src="../master/resources/particles.js"></script>
+ <script src="resources/dom-particles.js"></script>
+</body>
+</html>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/compositing-transforms.js b/third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/compositing-transforms.js
new file mode 100644
index 0000000000..9fd401eeeb
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/compositing-transforms.js
@@ -0,0 +1,66 @@
+(function() {
+
+BouncingCompositedImage = Utilities.createSubclass(BouncingParticle,
+ function(stage)
+ {
+ BouncingParticle.call(this, stage);
+
+ this.element = document.createElement("img");
+ this.element.style.width = this.size.x + "px";
+ this.element.style.height = this.size.y + "px";
+ this.element.setAttribute("src", stage.imageSrc);
+
+ if (stage.useFilters)
+ this.element.style.filter = "hue-rotate(" + Stage.randomAngle() + "rad)";
+
+ stage.element.appendChild(this.element);
+ this._move();
+ }, {
+
+ _move: function()
+ {
+ this.element.style.transform = "translate3d(" + this.position.x + "px," + this.position.y + "px, 0) " + this.rotater.rotateZ();
+ },
+
+ animate: function(timeDelta)
+ {
+ BouncingParticle.prototype.animate.call(this, timeDelta);
+ this._move();
+ }
+});
+
+CompositingTransformsStage = Utilities.createSubclass(BouncingParticlesStage,
+ function()
+ {
+ BouncingParticlesStage.call(this);
+ }, {
+
+ initialize: function(benchmark, options)
+ {
+ BouncingParticlesStage.prototype.initialize.call(this, benchmark, options);
+
+ this.imageSrc = options["imageSrc"] || "../resources/yin-yang.svg";
+ this.useFilters = options["filters"] == "yes";
+ },
+
+ createParticle: function()
+ {
+ return new BouncingCompositedImage(this);
+ },
+
+ particleWillBeRemoved: function(particle)
+ {
+ particle.element.remove();
+ }
+});
+
+CompositedTransformsBenchmark = Utilities.createSubclass(Benchmark,
+ function(options)
+ {
+ Benchmark.call(this, new CompositingTransformsStage(), options);
+ }
+);
+
+window.benchmarkClass = CompositedTransformsBenchmark;
+
+})();
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/dom-particles.js b/third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/dom-particles.js
new file mode 100644
index 0000000000..471444b2e7
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/dom-particles.js
@@ -0,0 +1,73 @@
+(function() {
+
+DOMParticle = Utilities.createSubclass(Particle,
+ function(stage)
+ {
+ this.element = document.createElement("div");
+ stage.element.appendChild(this.element);
+
+ Particle.call(this, stage);
+ }, {
+
+ reset: function()
+ {
+ Particle.prototype.reset.call(this);
+
+ this.position = Stage.randomElementInArray(this.stage.emitLocation);
+
+ var angle = Stage.randomInt(0, this.stage.emitSteps) / this.stage.emitSteps * Math.PI * 2 + Stage.dateCounterValue(100) * this.stage.emissionSpin;
+ this.velocity = new Point(Math.sin(angle), Math.cos(angle))
+ .multiply(Stage.random(.5, 2.5));
+
+ this.element.style.width = this.size.x + "px";
+ this.element.style.height = this.size.y + "px";
+ this.stage.colorOffset = (this.stage.colorOffset + 1) % 360;
+ this.element.style.backgroundColor = "hsl(" + this.stage.colorOffset + ", 70%, 45%)";
+ },
+
+ move: function()
+ {
+ this.element.style.transform = "translate(" + this.position.x + "px, " + this.position.y + "px)" + this.rotater.rotateZ();
+ }
+});
+
+DOMParticleStage = Utilities.createSubclass(ParticlesStage,
+ function()
+ {
+ ParticlesStage.call(this);
+ }, {
+
+ initialize: function(benchmark)
+ {
+ ParticlesStage.prototype.initialize.call(this, benchmark);
+ this.emissionSpin = Stage.random(0, 3);
+ this.emitSteps = Stage.randomInt(4, 6);
+ this.emitLocation = [
+ new Point(this.size.x * .25, this.size.y * .333),
+ new Point(this.size.x * .5, this.size.y * .25),
+ new Point(this.size.x * .75, this.size.y * .333)
+ ];
+ this.colorOffset = Stage.randomInt(0, 359);
+ },
+
+ createParticle: function()
+ {
+ return new DOMParticle(this);
+ },
+
+ willRemoveParticle: function(particle)
+ {
+ particle.element.remove();
+ }
+});
+
+DOMParticleBenchmark = Utilities.createSubclass(Benchmark,
+ function(options)
+ {
+ Benchmark.call(this, new DOMParticleStage(), options);
+ }
+);
+
+window.benchmarkClass = DOMParticleBenchmark;
+
+})();
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/focus.js b/third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/focus.js
new file mode 100644
index 0000000000..d7722cdff4
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/focus.js
@@ -0,0 +1,166 @@
+(function() {
+
+var maxVerticalOffset = 50;
+var minimumDiameter = 30;
+var centerDiameter = 90;
+var sizeVariance = 60;
+var travelDistance = 50;
+
+var opacityMultiplier = 30;
+
+var FocusElement = Utilities.createClass(
+ function(stage)
+ {
+ var size = minimumDiameter + sizeVariance;
+
+ // Size and blurring are a function of depth.
+ this._depth = Pseudo.random();
+ var distance = Utilities.lerp(this._depth, 0, sizeVariance);
+ size -= distance;
+
+ var top = Stage.random(0, stage.size.height - size) - stage.maxBlurValue * 3;
+ var left = Stage.random(0, stage.size.width - size) - stage.maxBlurValue * 3;
+
+ this.container = document.createElement('div');
+ this.container.style.width = (size + stage.maxBlurValue * 6) + "px";
+ this.container.style.height = (size + stage.maxBlurValue * 6) + "px";
+ this.container.style.top = top + "px";
+ this.container.style.left = left + "px";
+ this.container.style.zIndex = Math.round((1 - this._depth) * 10);
+
+ this.particle = Utilities.createElement("div", {}, this.container);
+ this.particle.style.width = size + "px";
+ this.particle.style.height = size + "px";
+ this.particle.style.top = (stage.maxBlurValue * 3) + "px";
+ this.particle.style.left = (stage.maxBlurValue * 3) + "px";
+
+ var depthMultiplier = Utilities.lerp(1 - this._depth, 0.8, 1);
+ this._sinMultiplier = Pseudo.random() * Stage.randomSign() * depthMultiplier * travelDistance;
+ this._cosMultiplier = Pseudo.random() * Stage.randomSign() * depthMultiplier * travelDistance;
+ }, {
+
+ hide: function()
+ {
+ this.container.style.display = "none";
+ },
+
+ show: function()
+ {
+ this.container.style.display = "block";
+ },
+
+ animate: function(stage, sinFactor, cosFactor)
+ {
+ var top = sinFactor * this._sinMultiplier;
+ var left = cosFactor * this._cosMultiplier;
+
+ Utilities.setElementPrefixedProperty(this.container, "filter", "blur(" + stage.getBlurValue(this._depth) + "px) opacity(" + stage.getOpacityValue(this._depth) + "%)");
+ this.container.style.transform = "translate3d(" + left + "%, " + top + "%, 0)";
+ }
+});
+
+var FocusStage = Utilities.createSubclass(Stage,
+ function()
+ {
+ Stage.call(this);
+ }, {
+
+ movementDuration: 2500,
+ focusDuration: 1000,
+
+ centerObjectDepth: 0.0,
+
+ minBlurValue: 1.5,
+ maxBlurValue: 15,
+ maxCenterObjectBlurValue: 5,
+
+ initialize: function(benchmark, options)
+ {
+ Stage.prototype.initialize.call(this, benchmark, options);
+
+ this._testElements = [];
+ this._focalPoint = 0.5;
+ this._offsetIndex = 0;
+
+ this._centerElement = document.getElementById("center-text");
+ this._centerElement.style.width = (centerDiameter + this.maxCenterObjectBlurValue * 6) + "px";
+ this._centerElement.style.height = (centerDiameter + this.maxCenterObjectBlurValue * 6) + "px";
+ this._centerElement.style.zIndex = Math.round(10 * this.centerObjectDepth);
+
+ var particle = document.querySelector("#center-text div");
+ particle.style.width = centerDiameter + "px";
+ particle.style.height = centerDiameter + "px";
+ particle.style.top = (this.maxCenterObjectBlurValue * 3) + "px";
+ particle.style.left = (this.maxCenterObjectBlurValue * 3) + "px";
+
+ var blur = this.getBlurValue(this.centerObjectDepth, true);
+ Utilities.setElementPrefixedProperty(this._centerElement, "filter", "blur(" + blur + "px)");
+ },
+
+ complexity: function()
+ {
+ return 1 + this._offsetIndex;
+ },
+
+ tune: function(count)
+ {
+ if (count == 0)
+ return;
+
+ if (count < 0) {
+ this._offsetIndex = Math.max(0, this._offsetIndex + count);
+ for (var i = this._offsetIndex; i < this._testElements.length; ++i)
+ this._testElements[i].hide();
+ return;
+ }
+
+ var newIndex = this._offsetIndex + count;
+ for (var i = this._testElements.length; i < newIndex; ++i) {
+ var obj = new FocusElement(this);
+ this._testElements.push(obj);
+ this.element.appendChild(obj.container);
+ }
+ for (var i = this._offsetIndex; i < newIndex; ++i)
+ this._testElements[i].show();
+ this._offsetIndex = newIndex;
+ },
+
+ animate: function()
+ {
+ var time = this._benchmark.timestamp;
+ var sinFactor = Math.sin(time / this.movementDuration);
+ var cosFactor = Math.cos(time / this.movementDuration);
+
+ var focusProgress = 0.5 + 0.5 * Math.sin(time / this.focusDuration);
+ this._focalPoint = focusProgress;
+
+ Utilities.setElementPrefixedProperty(this._centerElement, "filter", "blur(" + this.getBlurValue(this.centerObjectDepth, true) + "px)");
+
+ for (var i = 0; i < this._offsetIndex; ++i)
+ this._testElements[i].animate(this, sinFactor, cosFactor);
+ },
+
+ getBlurValue: function(depth, isCenter)
+ {
+ if (isCenter)
+ return 1 + Math.abs(depth - this._focalPoint) * (this.maxCenterObjectBlurValue - 1);
+
+ return Utilities.lerp(Math.abs(depth - this._focalPoint), this.minBlurValue, this.maxBlurValue);
+ },
+
+ getOpacityValue: function(depth)
+ {
+ return Math.max(1, opacityMultiplier * (1 - Math.abs(depth - this._focalPoint)));
+ },
+});
+
+var FocusBenchmark = Utilities.createSubclass(Benchmark,
+ function(options)
+ {
+ Benchmark.call(this, new FocusStage(), options);
+ }
+);
+
+window.benchmarkClass = FocusBenchmark;
+
+}());
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/leaves.js b/third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/leaves.js
new file mode 100644
index 0000000000..604c973667
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/leaves.js
@@ -0,0 +1,48 @@
+Leaf = Utilities.createSubclass(Particle,
+ function(stage)
+ {
+ this.element = document.createElement("img");
+ this.element.setAttribute("src", Stage.randomElementInArray(stage.images).src);
+ stage.element.appendChild(this.element);
+
+ Particle.call(this, stage);
+ }, {
+
+ sizeMinimum: 20,
+ sizeRange: 40,
+
+ reset: function()
+ {
+ Particle.prototype.reset.call(this);
+ this.element.style.width = this.size.x + "px";
+ this.element.style.height = this.size.y + "px";
+ this._opacity = .01;
+ this._opacityRate = 0.02 * Stage.random(1, 6);
+ this._position = new Point(Stage.random(0, this.maxPosition.x), Stage.random(-this.size.height, this.maxPosition.y));
+ this._velocity = new Point(Stage.random(-6, -2), .1 * this.size.y + Stage.random(-1, 1));
+ },
+
+ animate: function(timeDelta)
+ {
+ this.rotater.next(timeDelta);
+
+ this._position.x += this._velocity.x + 8 * this.stage.focusX;
+ this._position.y += this._velocity.y;
+ this._opacity += this._opacityRate;
+ if (this._opacity > 1) {
+ this._opacity = 1;
+ this._opacityRate *= -1;
+ } else if (this._opacity < 0 || this._position.y > this.stage.size.height)
+ this.reset();
+
+ if (this._position.x < -this.size.width || this._position.x > this.stage.size.width)
+ this._position.x = this._position.x - Math.sign(this._position.x) * (this.size.width + this.stage.size.width);
+ this.move();
+ },
+
+ move: function()
+ {
+ this.element.style.transform = "translate(" + this._position.x + "px, " + this._position.y + "px)" + this.rotater.rotateZ();
+ this.element.style.opacity = this._opacity;
+ }
+});
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/canvas-stage.html b/third_party/webkit/PerformanceTests/MotionMark/tests/master/canvas-stage.html
new file mode 100644
index 0000000000..f86cb44e10
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/canvas-stage.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+</head>
+<body>
+ <canvas id="stage"></canvas>
+ <script src="../../resources/strings.js"></script>
+ <script src="../../resources/extensions.js"></script>
+ <script src="../../resources/statistics.js"></script>
+ <script src="../resources/math.js"></script>
+ <script src="../resources/main.js"></script>
+ <script src="resources/canvas-stage.js"></script>
+ <script src="resources/canvas-tests.js"></script>
+</body>
+</html>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/focus.html b/third_party/webkit/PerformanceTests/MotionMark/tests/master/focus.html
new file mode 100644
index 0000000000..e97a7cd79f
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/focus.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+ <style type="text/css">
+
+ #stage {
+ background-color: #201A1F;
+ }
+
+ #stage div {
+ position: absolute;
+ background-color: #DEDADD;
+ border-radius: 50%;
+ display: none;
+ }
+ </style>
+</head>
+<body>
+ <div id="stage"></div>
+ <script src="../../resources/strings.js"></script>
+ <script src="../../resources/extensions.js"></script>
+ <script src="../../resources/statistics.js"></script>
+ <script src="../resources/math.js"></script>
+ <script src="../resources/main.js"></script>
+ <script src="resources/focus.js"></script>
+</body>
+</html>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/image-data.html b/third_party/webkit/PerformanceTests/MotionMark/tests/master/image-data.html
new file mode 100644
index 0000000000..36b52c9d87
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/image-data.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+ <style type="text/css">
+
+ #stage {
+ background-color: #000;
+ }
+
+ #stage canvas {
+ position: absolute;
+ transform: translateZ(0);
+ }
+
+ </style>
+</head>
+<body>
+ <div id="stage"></div>
+ <script src="../../resources/strings.js"></script>
+ <script src="../../resources/extensions.js"></script>
+ <script src="../../resources/statistics.js"></script>
+ <script src="../resources/math.js"></script>
+ <script src="../resources/main.js"></script>
+ <script src="resources/image-data.js"></script>
+</body>
+</html>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/leaves.html b/third_party/webkit/PerformanceTests/MotionMark/tests/master/leaves.html
new file mode 100644
index 0000000000..ada054025c
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/leaves.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+ <style>
+ #stage {
+ background-color: #23282B;
+ }
+ #stage img {
+ position: absolute;
+ }
+ </style>
+</head>
+<body>
+ <div id="stage"></div>
+ <script src="../../resources/strings.js"></script>
+ <script src="../../resources/extensions.js"></script>
+ <script src="../../resources/statistics.js"></script>
+ <script src="../resources/math.js"></script>
+ <script src="../resources/main.js"></script>
+ <script src="resources/particles.js"></script>
+ <script src="resources/leaves.js"></script>
+</body>
+</html>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/multiply.html b/third_party/webkit/PerformanceTests/MotionMark/tests/master/multiply.html
new file mode 100644
index 0000000000..717aff7d8b
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/multiply.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+ <style type="text/css">
+
+ #stage {
+ background-color: #000;
+ }
+
+ #stage div {
+ position: absolute;
+ }
+
+ #stage .div-0 {
+ border-top-right-radius: 100%;
+ }
+
+ #stage .div-1 {
+ border-top-left-radius: 100%;
+ }
+
+ #stage .div-2 {
+ border-bottom-left-radius: 100%;
+ }
+
+ #stage .div-3 {
+ border-bottom-right-radius: 100%;
+ }
+
+ #stage .div-4 {
+ border-bottom-left-radius: 100%;
+ border-top-right-radius: 100%;
+ }
+
+ #stage .div-5 {
+ border-bottom-right-radius: 100%;
+ border-top-left-radius: 100%;
+ }
+ </style>
+</head>
+<body>
+ <div id="stage">
+ </div>
+ <script src="../../resources/strings.js"></script>
+ <script src="../../resources/extensions.js"></script>
+ <script src="../../resources/statistics.js"></script>
+ <script src="../resources/math.js"></script>
+ <script src="../resources/main.js"></script>
+ <script src="resources/multiply.js"></script>
+</body>
+</html>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/canvas-stage.js b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/canvas-stage.js
new file mode 100644
index 0000000000..22002eccd6
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/canvas-stage.js
@@ -0,0 +1,52 @@
+SimpleCanvasStage = Utilities.createSubclass(Stage,
+ function(canvasObject)
+ {
+ Stage.call(this);
+ this._canvasObject = canvasObject;
+ this.objects = [];
+ this.offsetIndex = 0;
+ }, {
+
+ initialize: function(benchmark, options)
+ {
+ Stage.prototype.initialize.call(this, benchmark, options);
+ this.context = this.element.getContext("2d");
+ },
+
+ tune: function(count)
+ {
+ if (count == 0)
+ return;
+
+ if (count < 0) {
+ this.offsetIndex = Math.min(this.offsetIndex - count, this.objects.length);
+ return;
+ }
+
+ var newIndex = this.offsetIndex - count;
+ if (newIndex < 0) {
+ this.offsetIndex = 0;
+ newIndex = -newIndex;
+ for (var i = 0; i < newIndex; ++i) {
+ if (this._canvasObject.constructor === Array)
+ this.objects.push(new (Stage.randomElementInArray(this._canvasObject))(this));
+ else
+ this.objects.push(new this._canvasObject(this));
+ }
+ } else
+ this.offsetIndex = newIndex;
+ },
+
+ animate: function()
+ {
+ var context = this.context;
+ context.clearRect(0, 0, this.size.x, this.size.y);
+ for (var i = this.offsetIndex, length = this.objects.length; i < length; ++i)
+ this.objects[i].draw(context);
+ },
+
+ complexity: function()
+ {
+ return this.objects.length - this.offsetIndex;
+ }
+});
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/canvas-tests.js b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/canvas-tests.js
new file mode 100644
index 0000000000..79fc867082
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/canvas-tests.js
@@ -0,0 +1,311 @@
+(function() {
+
+// === PAINT OBJECTS ===
+
+CanvasLineSegment = Utilities.createClass(
+ function(stage)
+ {
+ var circle = Stage.randomInt(0, 3);
+ this._color = ["#e01040", "#10c030", "#744CBA", "#e05010"][circle];
+ this._lineWidth = Math.pow(Pseudo.random(), 12) * 20 + 3;
+ this._omega = Pseudo.random() * 3 + 0.2;
+ var theta = Stage.randomAngle();
+ this._cosTheta = Math.cos(theta);
+ this._sinTheta = Math.sin(theta);
+ this._startX = stage.circleRadius * this._cosTheta + stage.circleX[circle];
+ this._startY = stage.circleRadius * this._sinTheta + stage.circleY[circle];
+ this._length = Math.pow(Pseudo.random(), 8) * stage.lineLengthMaximum + stage.lineMinimum;
+ this._segmentDirection = Pseudo.random() > 0.5 ? -1 : 1;
+ }, {
+
+ draw: function(context)
+ {
+ context.strokeStyle = this._color;
+ context.lineWidth = this._lineWidth;
+
+ this._length += Math.sin(Stage.dateCounterValue(100) * this._omega);
+
+ context.beginPath();
+ context.moveTo(this._startX, this._startY);
+ context.lineTo(this._startX + this._segmentDirection * this._length * this._cosTheta,
+ this._startY + this._segmentDirection * this._length * this._sinTheta);
+ context.stroke();
+ }
+});
+
+CanvasArc = Utilities.createClass(
+ function(stage)
+ {
+ var maxX = 6, maxY = 3;
+ var distanceX = stage.size.x / maxX;
+ var distanceY = stage.size.y / (maxY + 1);
+ var randY = Stage.randomInt(0, maxY);
+ var randX = Stage.randomInt(0, maxX - 1 * (randY % 2));
+
+ this._point = new Point(distanceX * (randX + (randY % 2) / 2), distanceY * (randY + .5));
+
+ this._radius = 20 + Math.pow(Pseudo.random(), 5) * (Math.min(distanceX, distanceY) / 1.8);
+ this._startAngle = Stage.randomAngle();
+ this._endAngle = Stage.randomAngle();
+ this._omega = (Pseudo.random() - 0.5) * 0.3;
+ this._counterclockwise = Stage.randomBool();
+ var colors = ["#101010", "#808080", "#c0c0c0"];
+ colors.push(["#e01040", "#10c030", "#e05010"][(randX + Math.ceil(randY / 2)) % 3]);
+ this._color = colors[Math.floor(Pseudo.random() * colors.length)];
+ this._lineWidth = 1 + Math.pow(Pseudo.random(), 5) * 30;
+ this._doStroke = Stage.randomInt(0, 3) != 0;
+ }, {
+
+ draw: function(context)
+ {
+ this._startAngle += this._omega;
+ this._endAngle += this._omega / 2;
+
+ if (this._doStroke) {
+ context.strokeStyle = this._color;
+ context.lineWidth = this._lineWidth;
+ context.beginPath();
+ context.arc(this._point.x, this._point.y, this._radius, this._startAngle, this._endAngle, this._counterclockwise);
+ context.stroke();
+ } else {
+ context.fillStyle = this._color;
+ context.beginPath();
+ context.lineTo(this._point.x, this._point.y);
+ context.arc(this._point.x, this._point.y, this._radius, this._startAngle, this._endAngle, this._counterclockwise);
+ context.lineTo(this._point.x, this._point.y);
+ context.fill();
+ }
+ }
+});
+
+// CanvasLinePoint contains no draw() method since it is either moveTo or
+// lineTo depending on its index.
+CanvasLinePoint = Utilities.createClass(
+ function(stage)
+ {
+ var colors = ["#101010", "#808080", "#c0c0c0", "#101010", "#808080", "#c0c0c0", "#e01040"];
+ this.color = Stage.randomElementInArray(colors);
+ this.width = Math.pow(Pseudo.random(), 5) * 20 + 1;
+ this.isSplit = Pseudo.random() > 0.95;
+
+ var nextPoint;
+ if (stage.objects.length)
+ nextPoint = this.randomPoint(stage, stage.objects[stage.objects.length - 1].coordinate);
+ else
+ nextPoint = this.randomPoint(stage, this.gridSize.center);
+ this.point = nextPoint.point;
+ this.coordinate = nextPoint.coordinate;
+ }, {
+
+ gridSize: new Point(80, 40),
+ offsets: [
+ new Point(-4, 0),
+ new Point(2, 0),
+ new Point(1, -2),
+ new Point(1, 2),
+ ],
+
+ randomPoint: function(stage, startCoordinate)
+ {
+ var coordinate = startCoordinate;
+ if (stage.objects.length) {
+ var offset = Stage.randomElementInArray(this.offsets);
+
+ coordinate = coordinate.add(offset);
+ if (coordinate.x < 0 || coordinate.x > this.gridSize.width)
+ coordinate.x -= offset.x * 2;
+ if (coordinate.y < 0 || coordinate.y > this.gridSize.height)
+ coordinate.y -= offset.y * 2;
+ }
+
+ var x = (coordinate.x + .5) * stage.size.x / (this.gridSize.width + 1);
+ var y = (coordinate.y + .5) * stage.size.y / (this.gridSize.height + 1);
+ return {
+ point: new Point(x, y),
+ coordinate: coordinate
+ };
+ },
+
+ draw: function(context)
+ {
+ context.lineTo(this.point.x, this.point.y);
+ }
+});
+
+CanvasQuadraticSegment = Utilities.createSubclass(CanvasLinePoint,
+ function(stage)
+ {
+ CanvasLinePoint.call(this, stage);
+ // The chosen point is instead the control point.
+ this._point2 = this.point;
+
+ // Get another random point for the actual end point of the segment.
+ var nextPoint = this.randomPoint(stage, this.coordinate);
+ this.point = nextPoint.point;
+ this.coordinate = nextPoint.coordinate;
+ }, {
+
+ draw: function(context)
+ {
+ context.quadraticCurveTo(this._point2.x, this._point2.y, this.point.x, this.point.y);
+ }
+});
+
+CanvasBezierSegment = Utilities.createSubclass(CanvasLinePoint,
+ function(stage)
+ {
+ CanvasLinePoint.call(this, stage);
+ // The chosen point is instead the first control point.
+ this._point2 = this.point;
+ var nextPoint = this.randomPoint(stage, this.coordinate);
+ this._point3 = nextPoint.point;
+
+ nextPoint = this.randomPoint(stage, nextPoint.coordinate);
+ this.point = nextPoint.point;
+ this.coordinate = nextPoint.coordinate;
+ }, {
+
+ draw: function(context, off)
+ {
+ context.bezierCurveTo(this._point2.x, this._point2.y, this._point3.x, this._point3.y, this.point.x, this.point.y);
+ }
+});
+
+// === STAGES ===
+
+CanvasLineSegmentStage = Utilities.createSubclass(SimpleCanvasStage,
+ function()
+ {
+ SimpleCanvasStage.call(this, CanvasLineSegment);
+ }, {
+
+ initialize: function(benchmark, options)
+ {
+ SimpleCanvasStage.prototype.initialize.call(this, benchmark, options);
+ this.context.lineCap = options["lineCap"] || "butt";
+ this.lineMinimum = 20;
+ this.lineLengthMaximum = 40;
+ this.circleRadius = this.size.x / 8 - .4 * (this.lineMinimum + this.lineLengthMaximum);
+ this.circleX = [
+ 5.5 / 32 * this.size.x,
+ 12.5 / 32 * this.size.x,
+ 19.5 / 32 * this.size.x,
+ 26.5 / 32 * this.size.x,
+ ];
+ this.circleY = [
+ 2.1 / 3 * this.size.y,
+ 0.9 / 3 * this.size.y,
+ 2.1 / 3 * this.size.y,
+ 0.9 / 3 * this.size.y
+ ];
+ this.halfSize = this.size.multiply(.5);
+ this.twoFifthsSizeX = this.size.x * .4;
+ },
+
+ animate: function()
+ {
+ var context = this.context;
+ context.clearRect(0, 0, this.size.x, this.size.y);
+
+ var angle = Stage.dateFractionalValue(3000) * Math.PI * 2;
+ var dx = this.twoFifthsSizeX * Math.cos(angle);
+ var dy = this.twoFifthsSizeX * Math.sin(angle);
+
+ var gradient = context.createLinearGradient(this.halfSize.x + dx, this.halfSize.y + dy, this.halfSize.x - dx, this.halfSize.y - dy);
+ var gradientStep = 0.5 + 0.5 * Math.sin(Stage.dateFractionalValue(5000) * Math.PI * 2);
+ var colorStopStep = Utilities.lerp(gradientStep, -.1, .1);
+ var brightnessStep = Math.round(Utilities.lerp(gradientStep, 32, 64));
+ var color1Step = "rgba(" + brightnessStep + "," + brightnessStep + "," + (brightnessStep << 1) + ",.4)";
+ var color2Step = "rgba(" + (brightnessStep << 1) + "," + (brightnessStep << 1) + "," + brightnessStep + ",.4)";
+ gradient.addColorStop(0, color1Step);
+ gradient.addColorStop(.2 + colorStopStep, color1Step);
+ gradient.addColorStop(.8 - colorStopStep, color2Step);
+ gradient.addColorStop(1, color2Step);
+
+ context.lineWidth = 15;
+ for(var i = 0; i < 4; i++) {
+ context.strokeStyle = ["#e01040", "#10c030", "#744CBA", "#e05010"][i];
+ context.fillStyle = ["#70051d", "#016112", "#2F0C6E", "#702701"][i];
+ context.beginPath();
+ context.arc(this.circleX[i], this.circleY[i], this.circleRadius, 0, Math.PI*2);
+ context.stroke();
+ context.fill();
+ context.fillStyle = gradient;
+ context.fill();
+ }
+
+ for (var i = this.offsetIndex, length = this.objects.length; i < length; ++i)
+ this.objects[i].draw(context);
+ }
+});
+
+CanvasLinePathStage = Utilities.createSubclass(SimpleCanvasStage,
+ function()
+ {
+ SimpleCanvasStage.call(this, [CanvasLinePoint, CanvasLinePoint, CanvasQuadraticSegment, CanvasBezierSegment]);
+ }, {
+
+ initialize: function(benchmark, options)
+ {
+ SimpleCanvasStage.prototype.initialize.call(this, benchmark, options);
+ this.context.lineJoin = options["lineJoin"] || "bevel";
+ this.context.lineCap = options["lineCap"] || "butt";
+ },
+
+ animate: function() {
+ var context = this.context;
+
+ context.clearRect(0, 0, this.size.x, this.size.y);
+ context.beginPath();
+ for (var i = this.offsetIndex, length = this.objects.length; i < length; ++i) {
+ var object = this.objects[i];
+ if (i == this.offsetIndex) {
+ context.lineWidth = object.width;
+ context.strokeStyle = object.color;
+ context.beginPath();
+ context.moveTo(object.point.x, object.point.y);
+ } else {
+ object.draw(context);
+
+ if (object.isSplit) {
+ context.stroke();
+
+ context.lineWidth = object.width;
+ context.strokeStyle = object.color;
+ context.beginPath();
+ context.moveTo(object.point.x, object.point.y);
+ }
+
+ if (Pseudo.random() > 0.995)
+ object.isSplit = !object.isSplit;
+ }
+ }
+ context.stroke();
+ }
+});
+
+// === BENCHMARK ===
+
+CanvasPathBenchmark = Utilities.createSubclass(Benchmark,
+ function(options)
+ {
+ var stage;
+ switch (options["pathType"]) {
+ case "line":
+ stage = new CanvasLineSegmentStage();
+ break;
+ case "linePath":
+ stage = new CanvasLinePathStage();
+ break;
+ case "arcs":
+ stage = new SimpleCanvasStage(CanvasArc);
+ break;
+ }
+
+ Benchmark.call(this, stage, options);
+ }
+);
+
+window.benchmarkClass = CanvasPathBenchmark;
+
+})(); \ No newline at end of file
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/compass.svg b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/compass.svg
new file mode 100644
index 0000000000..3f94e7a4b2
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/compass.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright © 2016 Apple Inc. All rights reserved. -->
+<svg width="48px" height="48px" viewBox="0 0 48 48" version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <path d="M 24 45.7600002 L 24 45.7600002 C 36.0177159 45.7600002 45.7599999 36.0177161 45.7599999 24.0000001 C 45.7599999 11.9822838 36.0177159 2.24000001 24 2.24000001 C 11.9822838 2.24000001 2.23999999 11.9822838 2.23999999 24.0000001 C 2.23999999 36.0177161 11.9822838 45.7600002 24 45.7600002 L 24 45.7600002 L 24 45.7600002 L 24 45.7600002 Z M 24 48 L 24 48 C 10.745166 48 8.52651283e-14 37.254834 8.52651283e-14 24.0000001 C 8.52651283e-14 10.745166 10.745166 0 24 0 C 37.254834 0 48 10.745166 48 24.0000001 C 48 37.254834 37.254834 48 24 48 L 24 48 L 24 48 L 24 48 Z" fill="rgb(142, 142, 147)"/>
+ <path fill="white" d="M 19.2141787 30.7527044 C 20.0566026 31.3582067 21.0164459 31.8087988 22.052466 32.0629879 L 24.0150243 38.3621108 L 25.9644157 32.0671275 C 28.9532689 31.3397602 31.304042 28.97474 32.0270276 25.9677724 L 38.2840894 24.0065666 L 32.38318 22.1457238 L 30.1049072 24.2136546 C 29.9995478 27.5073249 27.2907334 30.1510903 24.0134391 30.1359337 C 23.1661809 30.1431339 22.3840431 29.959524 21.6645278 29.6641888 L 19.2141787 30.7527044 L 19.2141787 30.7527044 L 19.2141787 30.7527044 Z M 28.8019182 17.2563866 C 27.4120183 16.2548466 25.9438825 15.9331447 25.9438825 15.9331447 L 23.9849759 9.63788916 L 22.0355845 15.9328727 C 19.0467312 16.6602398 16.695958 19.0252601 15.9729726 22.0322277 L 9.71591065 23.9934336 C 9.71591065 23.9934336 13.7573684 25.2679011 15.7780972 25.9051349 L 17.8923556 23.9486543 C 17.9116726 20.5783691 20.6200789 17.8803136 23.9912031 17.8674375 C 24.8266313 17.8130168 26.1806153 18.2277657 26.3381938 18.3358993 C 26.3381937 18.3358993 28.8019182 17.2563866 28.8019182 17.2563866 L 28.8019182 17.2563866 L 28.8019182 17.2563866 Z"/>
+ <path fill="white" d="M 22.4528571 21.5612813 L 10.1267612 32.8610634 L 25.4820204 26.3285511 L 37.8732388 15.1389366 L 22.4528571 21.5612813 L 22.4528571 21.5612813 L 22.4528571 21.5612813 Z"/>
+</svg>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/compass100.png b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/compass100.png
new file mode 100644
index 0000000000..e513ce11e3
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/compass100.png
Binary files differ
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/console.svg b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/console.svg
new file mode 100644
index 0000000000..e3c7611d2a
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/console.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright © 2016 Apple Inc. All rights reserved. -->
+<svg width="48px" height="48px" viewBox="0 0 48 48" version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <rect stroke="rgb(0, 136, 204)" stroke-width="2.5" x="5.03735352" y="5.03735352" width="37.925293" height="37.925293" rx="4" fill="none"/>
+ <path d="M 13.164202 13.164202 L 24 24 L 13.164202 34.835798 M 24 14 L 35 14 M 29.5 24 L 34.9999999 24 M 24 34 L 35 34" stroke="white" stroke-width="2.5" fill="none" />
+</svg>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/console100.png b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/console100.png
new file mode 100644
index 0000000000..81f9c1641d
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/console100.png
Binary files differ
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/contribute.svg b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/contribute.svg
new file mode 100644
index 0000000000..68860efa86
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/contribute.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright © 2016 Apple Inc. All rights reserved. -->
+<svg width="48px" height="48px" viewBox="0 0 48 48" version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <path fill="rgb(203, 170, 68)" d="M 24 45.76 L 24 45.76 C 36.0177161 45.76 45.76 36.0177162 45.76 24 C 45.76 11.9822838 36.0177161 2.24 24 2.24 C 11.9822838 2.24 2.24 11.9822838 2.24 24 C 2.24 36.0177162 11.9822838 45.76 24 45.76 L 24 45.76 L 24 45.76 L 24 45.76 Z M 24 48 L 24 48 C 10.745166 48 -1.77635684e-14 37.254834 -1.77635684e-14 24 C -1.77635684e-14 10.745166 10.745166 2.84217094e-14 24 2.84217094e-14 C 37.254834 2.84217094e-14 48 10.745166 48 24 C 48 37.254834 37.254834 48 24 48 L 24 48 L 24 48 L 24 48 Z"/>
+ <path d="M 29.4897098 23.3065925 L 26.2706917 20.9393745 L 26.6482584 24.3031351 L 28.4802897 29.4247528 L 29.4897098 33.8205977 L 30.4989581 29.4247528 L 32.3309894 24.3031351 L 32.7087278 20.9393745 L 29.4897098 23.3065925 Z M 18.8503641 23.3065925 L 15.631346 20.9393745 L 16.0090845 24.3031351 L 17.8411157 29.4247528 L 18.8503641 33.8205977 L 19.8597841 29.4247528 L 21.6916437 24.3031351 L 22.0693821 20.9393745 L 18.8503641 23.3065925 Z M 37.2876041 24.3031351 L 39.1196354 29.4247528 L 40.3400738 34.740219 L 38.3454433 35 L 36.6368638 29.562799 C 36.6368638 29.562799 34.8092967 25.6310573 34.8092967 25.4866582 C 34.8092967 25.6310573 32.9819013 29.562799 32.9819013 29.562799 L 31.2733218 35 L 29.4897098 34.7676909 L 27.7060977 35 L 25.9975182 29.562799 C 25.9975182 29.562799 24.1701228 25.6310573 24.1701228 25.4866582 C 24.1701228 25.6310573 22.3425557 29.562799 22.3425557 29.562799 L 20.6339762 35 L 18.8503641 34.7676909 L 17.066752 35 L 15.3581725 29.562799 C 15.3581725 29.562799 13.5307771 25.6310573 13.5307771 25.4866582 C 13.5307771 25.6310573 11.7033817 29.562799 11.7033817 29.562799 L 9.9946305 35 L 8 34.740219 L 9.22043846 29.4247528 L 11.0524697 24.3031351 L 11.4302081 20.9393745 L 8.21101841 23.3065925 L 8.21101841 21.228001 L 11.6719607 18.326455 L 12.3810787 18.2218901 L 12.3810787 17.9233051 C 11.4619725 17.51054 10.825655 16.6183906 10.825655 15.5839024 C 10.825655 14.156738 12.0368217 13 13.5307771 13 C 15.0247325 13 16.2358992 14.156738 16.2358992 15.5839024 C 16.2358992 16.6183906 15.5995817 17.51054 14.6804755 17.9233051 L 14.6804755 18.2218901 L 15.3895935 18.326455 L 18.8503641 21.228001 L 22.3113064 18.326455 L 23.0204244 18.2218901 L 23.0204244 17.9233051 C 22.1013182 17.51054 21.4650007 16.6183906 21.4650007 15.5839024 C 21.4650007 14.156738 22.6761674 13 24.1701228 13 C 25.6640782 13 26.8750732 14.156738 26.8750732 15.5839024 C 26.8750732 16.6183906 26.2387556 17.51054 25.3198211 17.9233051 L 25.3198211 18.2218901 L 26.0289391 18.326455 L 29.4897098 21.228001 L 32.9504804 18.326455 L 33.6595984 18.2218901 L 33.6595984 17.9233051 C 32.7406639 17.51054 32.1043463 16.6183906 32.1043463 15.5839024 C 32.1043463 14.156738 33.3153413 13 34.8092967 13 C 36.3034238 13 37.5142471 14.156738 37.5144188 15.5839024 C 37.5144188 16.6183906 36.8781013 17.51054 35.9591668 17.9233051 L 35.9591668 18.2218901 L 36.6682848 18.326455 L 40.1290554 21.228001 L 40.1290554 23.3065925 L 36.9100374 20.9393745 L 37.2876041 24.3031351 Z" fill="white"/>
+</svg>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/contribute100.png b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/contribute100.png
new file mode 100644
index 0000000000..790e3dcfca
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/contribute100.png
Binary files differ
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/debugger.svg b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/debugger.svg
new file mode 100644
index 0000000000..646ddf446c
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/debugger.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright © 2016 Apple Inc. All rights reserved. -->
+<svg width="48px" height="48px" viewBox="0 0 48 48" version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <path d="M 24.1320008 44.328125 C 32.1512251 44.328125 38.6520901 35.226914 38.6520901 24 C 38.6520901 12.773086 32.1512251 3.671875 24.1320008 3.671875 C 16.1127765 3.671875 9.61191153 12.773086 9.61191153 24 C 9.61191153 35.226914 16.1127765 44.328125 24.1320008 44.328125 Z M 13.7861328 10.5 L 34.4768075 10.5 L 13.7861328 10.5 Z M 24.25 11 L 24.25 44.328125 M 34.1640625 37.0680804 L 39.9720982 42.8761161 M 38.5200893 22.25 L 44.328125 22.25 M 9.47991071 22.25 L 3.671875 22.25 M 13.8359375 10.9319196 L 8.02790179 5.12388393 M 34.1640625 10.9319196 L 39.9720982 5.12388393 M 13.972 37.068 L 8.164 42.876" fill="none" stroke="rgb(0, 136, 204)" stroke-width="2.5"/>
+</svg>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/debugger100.png b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/debugger100.png
new file mode 100644
index 0000000000..e2652096dc
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/debugger100.png
Binary files differ
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/focus.js b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/focus.js
new file mode 100644
index 0000000000..04842e744e
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/focus.js
@@ -0,0 +1,129 @@
+(function() {
+
+var minimumDiameter = 30;
+var sizeVariance = 20;
+var travelDistance = 50;
+
+var minBlurValue = 1;
+var maxBlurValue = 10;
+
+var opacityMultiplier = 30;
+var focusDuration = 1000;
+var movementDuration = 2500;
+
+var FocusElement = Utilities.createClass(
+ function(stage)
+ {
+ var size = minimumDiameter + sizeVariance;
+
+ // Size and blurring are a function of depth.
+ this._depth = Pseudo.random();
+ var distance = Utilities.lerp(this._depth, 0, sizeVariance);
+ size -= distance;
+
+ var top = Stage.random(0, stage.size.height - size);
+ var left = Stage.random(0, stage.size.width - size);
+
+ this.particle = document.createElement("div");
+ this.particle.style.width = size + "px";
+ this.particle.style.height = size + "px";
+ this.particle.style.top = top + "px";
+ this.particle.style.left = left + "px";
+ this.particle.style.zIndex = Math.round((1 - this._depth) * 10);
+
+ var depthMultiplier = Utilities.lerp(1 - this._depth, 0.8, 1);
+ this._sinMultiplier = Pseudo.random() * Stage.randomSign() * depthMultiplier * travelDistance;
+ this._cosMultiplier = Pseudo.random() * Stage.randomSign() * depthMultiplier * travelDistance;
+
+ this.animate(stage, 0, 0);
+ }, {
+
+ hide: function()
+ {
+ this.particle.style.display = "none";
+ },
+
+ show: function()
+ {
+ this.particle.style.display = "block";
+ },
+
+ animate: function(stage, sinFactor, cosFactor)
+ {
+ var top = sinFactor * this._sinMultiplier;
+ var left = cosFactor * this._cosMultiplier;
+ var distance = Math.abs(this._depth - stage.focalPoint);
+ var blur = Utilities.lerp(distance, minBlurValue, maxBlurValue);
+ var opacity = Math.max(5, opacityMultiplier * (1 - distance));
+
+ Utilities.setElementPrefixedProperty(this.particle, "filter", "blur(" + blur + "px) opacity(" + opacity + "%)");
+ this.particle.style.transform = "translate3d(" + left + "%, " + top + "%, 0)";
+ }
+});
+
+var FocusStage = Utilities.createSubclass(Stage,
+ function()
+ {
+ Stage.call(this);
+ }, {
+
+ initialize: function(benchmark, options)
+ {
+ Stage.prototype.initialize.call(this, benchmark, options);
+
+ this._testElements = [];
+ this._offsetIndex = 0;
+ this.focalPoint = 0.5;
+ },
+
+ complexity: function()
+ {
+ return this._offsetIndex;
+ },
+
+ tune: function(count)
+ {
+ if (count == 0)
+ return;
+
+ if (count < 0) {
+ this._offsetIndex = Math.max(0, this._offsetIndex + count);
+ for (var i = this._offsetIndex; i < this._testElements.length; ++i)
+ this._testElements[i].hide();
+ return;
+ }
+
+ var newIndex = this._offsetIndex + count;
+ for (var i = this._testElements.length; i < newIndex; ++i) {
+ var obj = new FocusElement(this);
+ this._testElements.push(obj);
+ this.element.appendChild(obj.particle);
+ }
+ for (var i = this._offsetIndex; i < newIndex; ++i)
+ this._testElements[i].show();
+ this._offsetIndex = newIndex;
+ },
+
+ animate: function()
+ {
+ var time = this._benchmark.timestamp;
+ var sinFactor = Math.sin(time / movementDuration);
+ var cosFactor = Math.cos(time / movementDuration);
+
+ this.focalPoint = 0.5 + 0.5 * Math.sin(time / focusDuration);
+
+ for (var i = 0; i < this._offsetIndex; ++i)
+ this._testElements[i].animate(this, sinFactor, cosFactor);
+ }
+});
+
+var FocusBenchmark = Utilities.createSubclass(Benchmark,
+ function(options)
+ {
+ Benchmark.call(this, new FocusStage(), options);
+ }
+);
+
+window.benchmarkClass = FocusBenchmark;
+
+}());
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/image-data.js b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/image-data.js
new file mode 100644
index 0000000000..6de5d068bb
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/image-data.js
@@ -0,0 +1,181 @@
+(function() {
+
+var ImageDataStage = Utilities.createSubclass(Stage,
+ function() {
+ Stage.call(this);
+
+ this.testElements = [];
+ this._offsetIndex = 0;
+ }, {
+
+ imageWidth: 50,
+ imageHeight: 50,
+ pixelStride: 4,
+ rowStride: 200,
+ weightNegativeThreshold: 0.04,
+ weightPositiveThreshold: 0.96,
+ imageSrcs: [
+ "compass",
+ "console",
+ "contribute",
+ "debugger",
+ "inspector",
+ "layout",
+ "performance",
+ "script",
+ "shortcuts",
+ "standards",
+ "storage",
+ "styles",
+ "timeline"
+ ],
+ images: [],
+
+ initialize: function(benchmark)
+ {
+ Stage.prototype.initialize.call(this, benchmark);
+
+ var lastPromise;
+ var images = this.images;
+ this.imageSrcs.forEach(function(imageSrc) {
+ var promise = this._loadImage("resources/" + imageSrc + ".svg");
+ if (!lastPromise)
+ lastPromise = promise;
+ else {
+ lastPromise = lastPromise.then(function(img) {
+ images.push(img);
+ return promise;
+ });
+ }
+ }, this);
+
+ lastPromise.then(function(img) {
+ images.push(img);
+ benchmark.readyPromise.resolve();
+ }.bind(this));
+ },
+
+ _loadImage: function(src) {
+ var img = new Image;
+ var promise = new SimplePromise;
+
+ img.addEventListener('load', function onImageLoad(e) {
+ img.removeEventListener('load', onImageLoad);
+ promise.resolve(img);
+ });
+
+ img.src = src;
+ return promise;
+ },
+
+ tune: function(count)
+ {
+ if (count == 0)
+ return;
+
+ if (count < 0) {
+ this._offsetIndex = Math.max(this._offsetIndex + count, 0);
+ for (var i = this._offsetIndex; i < this.testElements.length; ++i)
+ this.testElements[i].style.display = "none";
+ return;
+ }
+
+ this._offsetIndex = this._offsetIndex + count;
+ var index = Math.min(this._offsetIndex, this.testElements.length);
+ for (var i = 0; i < index; ++i) {
+ this.testElements[i].style.display = "block";
+ this._refreshElement(this.testElements[i]);
+ }
+ if (this._offsetIndex <= this.testElements.length)
+ return;
+
+ index = this._offsetIndex - this.testElements.length;
+ for (var i = 0; i < index; ++i) {
+ var element = this._createTestElement();
+ this.testElements.push(element);
+ this.element.appendChild(element);
+ }
+ },
+
+ _createTestElement: function() {
+ var element = document.createElement('canvas');
+ element.width = this.imageWidth;
+ element.height = this.imageHeight;
+ element.style.width = this.imageWidth + 'px';
+ element.style.height = this.imageHeight + 'px';
+
+ this._refreshElement(element);
+ return element;
+ },
+
+ _refreshElement: function(element) {
+ var top = Stage.randomInt(0, Math.floor((this.size.height - this.imageHeight) / this.imageHeight)) * this.imageHeight;
+ var left = Stage.randomInt(0, Math.floor((this.size.width - this.imageWidth) / this.imageWidth)) * this.imageWidth;
+
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ },
+
+ animate: function(timeDelta) {
+ for (var i = 0; i < this._offsetIndex; ++i) {
+ var element = this.testElements[i];
+ var context = element.getContext("2d");
+
+ // Get image data
+ var imageData = context.getImageData(0, 0, this.imageWidth, this.imageHeight);
+
+ var didDraw = false,
+ neighborPixelIndex,
+ dataLen = imageData.data.length;
+ for (var j = 0; j < dataLen; j += this.pixelStride) {
+ if (imageData.data[j + 3] === 0)
+ continue;
+
+ // get random neighboring pixel color
+ neighborPixelIndex = this._getRandomNeighboringPixelIndex(j, dataLen);
+
+ // Update the RGB data
+ imageData.data[j] = imageData.data[neighborPixelIndex];
+ imageData.data[j + 1] = imageData.data[neighborPixelIndex + 1];
+ imageData.data[j + 2] = imageData.data[neighborPixelIndex + 2];
+ imageData.data[j + 3] = imageData.data[neighborPixelIndex + 3];
+ didDraw = true;
+ }
+
+ if (didDraw)
+ context.putImageData(imageData, 0, 0);
+ else {
+ this._refreshElement(element);
+ element.getContext("2d").drawImage(Stage.randomElementInArray(this.images), 0, 0, this.imageWidth, this.imageHeight);
+ }
+ }
+ },
+
+ _getRandomNeighboringPixelIndex: function(pixelIdx, pixelArrayLength)
+ {
+ var xOffset = Math.floor((Pseudo.random() - this.weightNegativeThreshold) / (this.weightPositiveThreshold - this.weightNegativeThreshold));
+ var yOffset = Math.floor((Pseudo.random() - this.weightNegativeThreshold) / (this.weightPositiveThreshold - this.weightNegativeThreshold));
+ return (pixelIdx + this.pixelStride * xOffset + this.rowStride * yOffset) % pixelArrayLength;
+ },
+
+ complexity: function()
+ {
+ return this._offsetIndex;
+ }
+});
+
+var ImageDataBenchmark = Utilities.createSubclass(Benchmark,
+ function(options)
+ {
+ Benchmark.call(this, new ImageDataStage(), options);
+ }, {
+
+ waitUntilReady: function() {
+ this.readyPromise = new SimplePromise;
+ return this.readyPromise;
+ }
+});
+
+window.benchmarkClass = ImageDataBenchmark;
+
+}());
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/inspector.svg b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/inspector.svg
new file mode 100644
index 0000000000..68cc413052
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/inspector.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright © 2016 Apple Inc. All rights reserved. -->
+<svg width="48px" height="48px" viewBox="0 0 48 48" version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <circle fill="none" stroke="rgb(0, 136, 204)" stroke-width="2.5" cx="24" cy="24" r="18"/>
+ <path d="M 28.5 25.5 L 48 25.5 L 48 23 L 28.5 23 L 28.5 25.5 M 23 28.5 L 23 48 L 25.5 48 L 25.5 28.5 L 23 28.5 M 0 25.5 L 19.5 25.5 L 19.5 23 L 5.99520433e-15 23 L 0 25.5 M 23 0 L 23 19.5 L 25.5 19.5 L 25.5 0 L 23 0" fill="white"/>
+</svg>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/inspector100.png b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/inspector100.png
new file mode 100644
index 0000000000..26d1a7d592
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/inspector100.png
Binary files differ
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/layout.svg b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/layout.svg
new file mode 100644
index 0000000000..73db97eb46
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/layout.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright © 2016 Apple Inc. All rights reserved. -->
+<svg width="48px" height="48px" viewBox="0 0 48 48" version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <path d="M 44.5086986 24.2230775 L 24.1090229 24.2230775 L 24.1090229 4.50363839 L 24.1090229 4.50363839" fill="none" stroke="white" stroke-width="2.5"/>
+ <rect x="3.71000004" y="4.50363839" width="40.7993514" height="39.4388783" fill="none" stroke="rgb(191, 109, 113)" stroke-width="2.5"/>
+</svg>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/layout100.png b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/layout100.png
new file mode 100644
index 0000000000..5b1ec2806b
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/layout100.png
Binary files differ
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/leaves.js b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/leaves.js
new file mode 100644
index 0000000000..7a049836ff
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/leaves.js
@@ -0,0 +1,135 @@
+Leaf = Utilities.createSubclass(Particle,
+ function(stage)
+ {
+ this.element = document.createElement("img");
+ this.element.setAttribute("src", Stage.randomElementInArray(stage.images).src);
+ var sizeString = this.sizeMinimum + "px";
+ this.element.style.width = sizeString;
+ this.element.style.height = sizeString;
+ stage.element.appendChild(this.element);
+
+ Particle.call(this, stage);
+ }, {
+
+ sizeMinimum: 25,
+ sizeRange: 0,
+
+ reset: function()
+ {
+ Particle.prototype.reset.call(this);
+ this._life = Stage.randomInt(20, 100);
+ this._position = new Point(Stage.random(0, this.maxPosition.x), Stage.random(-this.size.height, this.maxPosition.y));
+ this._velocity = new Point(Stage.random(-6, -2), .1 * this.size.y + Stage.random(-1, 1));
+ },
+
+ animate: function(timeDelta)
+ {
+ this.rotater.next(timeDelta);
+
+ this._position.x += this._velocity.x + 8 * this.stage.focusX;
+ this._position.y += this._velocity.y;
+
+ this._life--;
+ if (!this._life || this._position.y > this.stage.size.height)
+ this.reset();
+
+ if (this._position.x < -this.size.width || this._position.x > this.stage.size.width)
+ this._position.x = this._position.x - Math.sign(this._position.x) * (this.size.width + this.stage.size.width);
+ this.move();
+ },
+
+ move: function()
+ {
+ this.element.style.transform = "translate(" + this._position.x + "px, " + this._position.y + "px)" + this.rotater.rotateZ();
+ }
+});
+
+Utilities.extendObject(ParticlesStage.prototype, {
+
+ imageSrcs: [
+ "compass",
+ "console",
+ "contribute",
+ "debugger",
+ "inspector",
+ "layout",
+ "performance",
+ "script",
+ "shortcuts",
+ "standards",
+ "storage",
+ "styles",
+ "timeline"
+ ],
+ images: [],
+
+ initialize: function(benchmark)
+ {
+ Stage.prototype.initialize.call(this, benchmark);
+
+ var lastPromise;
+ var images = this.images;
+ this.imageSrcs.forEach(function(imageSrc) {
+ var promise = this._loadImage("../master/resources/" + imageSrc + "100.png");
+ if (!lastPromise)
+ lastPromise = promise;
+ else {
+ lastPromise = lastPromise.then(function(img) {
+ images.push(img);
+ return promise;
+ });
+ }
+ }, this);
+
+ lastPromise.then(function(img) {
+ images.push(img);
+ benchmark.readyPromise.resolve();
+ });
+ },
+
+ _loadImage: function(src) {
+ var img = new Image;
+ var promise = new SimplePromise;
+
+ img.onload = function(e) {
+ promise.resolve(e.target);
+ };
+
+ img.src = src;
+ return promise;
+ },
+
+ animate: function(timeDelta)
+ {
+ this.focusX = 0.5 + 0.5 * Math.sin(Stage.dateFractionalValue(10000) * Math.PI * 2);
+ timeDelta /= 4;
+ this.particles.forEach(function(particle) {
+ particle.animate(timeDelta);
+ });
+ },
+
+ createParticle: function()
+ {
+ return new Leaf(this);
+ },
+
+ willRemoveParticle: function(particle)
+ {
+ particle.element.remove();
+ }
+});
+
+LeavesBenchmark = Utilities.createSubclass(Benchmark,
+ function(options)
+ {
+ Benchmark.call(this, new ParticlesStage(), options);
+ }, {
+
+ waitUntilReady: function() {
+ this.readyPromise = new SimplePromise;
+ return this.readyPromise;
+ }
+
+});
+
+window.benchmarkClass = LeavesBenchmark;
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/multiply.js b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/multiply.js
new file mode 100644
index 0000000000..e93cfbb5b9
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/multiply.js
@@ -0,0 +1,119 @@
+(function() {
+
+var MultiplyStage = Utilities.createSubclass(Stage,
+ function()
+ {
+ Stage.call(this);
+ this.tiles = [];
+ this._offsetIndex = 0;
+ }, {
+
+ initialize: function(benchmark, options)
+ {
+ Stage.prototype.initialize.call(this, benchmark, options);
+ var tileSize = Math.round(this.size.height / 25);
+
+ // Fill the scene with elements
+ var x = Math.round((this.size.width - tileSize) / 2);
+ var y = Math.round((this.size.height - tileSize) / 2);
+ var tileStride = tileSize;
+ var direction = 0;
+ var spiralCounter = 2;
+ var nextIndex = 1;
+ var maxSide = Math.floor(y / tileStride) * 2 + 1;
+ this._centerSpiralCount = maxSide * maxSide;
+ for (var i = 0; i < this._centerSpiralCount; ++i) {
+ this._addTile(x, y, tileSize, Stage.randomInt(0, 359));
+
+ if (i == nextIndex) {
+ direction = (direction + 1) % 4;
+ spiralCounter++;
+ nextIndex += spiralCounter >> 1;
+ }
+ if (direction == 0)
+ x += tileStride;
+ else if (direction == 1)
+ y -= tileStride;
+ else if (direction == 2)
+ x -= tileStride;
+ else
+ y += tileStride;
+ }
+
+ this._sidePanelCount = maxSide * Math.floor((this.size.width - x) / tileStride) * 2;
+ for (var i = 0; i < this._sidePanelCount; ++i) {
+ var sideX = x + Math.floor(Math.floor(i / maxSide) / 2) * tileStride;
+ var sideY = y - tileStride * (i % maxSide);
+
+ if (Math.floor(i / maxSide) % 2 == 1)
+ sideX = this.size.width - sideX - tileSize + 1;
+ this._addTile(sideX, sideY, tileSize, Stage.randomInt(0, 359));
+ }
+ },
+
+ _addTile: function(x, y, tileSize, rotateDeg)
+ {
+ var tile = Utilities.createElement("div", { class: "div-" + Stage.randomInt(0,6) }, this.element);
+ var halfTileSize = tileSize / 2;
+ tile.style.left = x + 'px';
+ tile.style.top = y + 'px';
+ tile.style.width = tileSize + 'px';
+ tile.style.height = tileSize + 'px';
+ tile.style.visibility = "hidden";
+
+ var distance = 1 / tileSize * this.size.multiply(0.5).subtract(new Point(x + halfTileSize, y + halfTileSize)).length();
+ this.tiles.push({
+ element: tile,
+ rotate: rotateDeg,
+ step: Math.max(3, distance / 1.5),
+ distance: distance,
+ active: false
+ });
+ },
+
+ complexity: function()
+ {
+ return this._offsetIndex;
+ },
+
+ tune: function(count)
+ {
+ this._offsetIndex = Math.max(0, Math.min(this._offsetIndex + count, this.tiles.length));
+ this._distanceFactor = 1.5 * (1 - 0.5 * Math.max(this._offsetIndex - this._centerSpiralCount, 0) / this._sidePanelCount) / Math.sqrt(this._offsetIndex);
+ },
+
+ animate: function()
+ {
+ var progress = this._benchmark.timestamp % 10000 / 10000;
+ var bounceProgress = Math.sin(2 * Math.abs( 0.5 - progress));
+ var l = Utilities.lerp(bounceProgress, 20, 50);
+ var hslPrefix = "hsla(" + Utilities.lerp(progress, 0, 360) + ",100%,";
+
+ for (var i = 0; i < this._offsetIndex; ++i) {
+ var tile = this.tiles[i];
+ tile.active = true;
+ tile.element.style.visibility = "";
+ tile.rotate += tile.step;
+ tile.element.style.transform = "rotate(" + tile.rotate + "deg)";
+
+ var influence = Math.max(.01, 1 - (tile.distance * this._distanceFactor));
+ tile.element.style.backgroundColor = hslPrefix + l * Math.tan(influence / 1.25) + "%," + influence + ")";
+ }
+
+ for (var i = this._offsetIndex; i < this.tiles.length && this.tiles[i].active; ++i) {
+ this.tiles[i].active = false;
+ this.tiles[i].element.style.visibility = "hidden";
+ }
+ }
+});
+
+var MultiplyBenchmark = Utilities.createSubclass(Benchmark,
+ function(options)
+ {
+ Benchmark.call(this, new MultiplyStage(), options);
+ }
+);
+
+window.benchmarkClass = MultiplyBenchmark;
+
+}());
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/particles.js b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/particles.js
new file mode 100644
index 0000000000..cf474e4142
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/particles.js
@@ -0,0 +1,112 @@
+function Particle(stage)
+{
+ this.stage = stage;
+ this.rotater = Stage.randomRotater();
+ this.reset();
+ this.move();
+}
+
+Particle.prototype =
+{
+ sizeMinimum: 40,
+ sizeRange: 10,
+
+ reset: function()
+ {
+ var randSize = Math.round(Math.pow(Pseudo.random(), 4) * this.sizeRange + this.sizeMinimum);
+ this.size = new Point(randSize, randSize);
+ this.minPosition = this.size.center;
+ this.maxPosition = this.stage.size.subtract(this.minPosition);
+ },
+
+ animate: function(timeDelta)
+ {
+ this.rotater.next(timeDelta);
+
+ this.position = this.position.add(this.velocity.multiply(timeDelta));
+ this.velocity.y += 0.03;
+
+ // If particle is going to move off right side
+ if (this.position.x > this.maxPosition.x) {
+ if (this.velocity.x > 0)
+ this.velocity.x *= -1;
+ this.position.x = this.maxPosition.x;
+ } else if (this.position.x < this.minPosition.x) {
+ // If particle is going to move off left side
+ if (this.velocity.x < 0)
+ this.velocity.x *= -1;
+ this.position.x = this.minPosition.x;
+ }
+
+ // If particle is going to move off bottom side
+ if (this.position.y > this.maxPosition.y) {
+ // Adjust direction but maintain magnitude
+ var magnitude = this.velocity.length();
+ this.velocity.x *= 1.5 + .005 * this.size.x;
+ this.velocity = this.velocity.normalize().multiply(magnitude);
+ if (Math.abs(this.velocity.y) < 0.7)
+ this.reset();
+ else {
+ if (this.velocity.y > 0)
+ this.velocity.y *= -0.999;
+ this.position.y = this.maxPosition.y;
+ }
+ } else if (this.position.y < this.minPosition.y) {
+ // If particle is going to move off top side
+ var magnitude = this.velocity.length();
+ this.velocity.x *= 1.5 + .005 * this.size.x;
+ this.velocity = this.velocity.normalize().multiply(magnitude);
+ if (this.velocity.y < 0)
+ this.velocity.y *= -0.998;
+ this.position.y = this.minPosition.y;
+ }
+
+ this.move();
+ },
+
+ move: function()
+ {
+ }
+}
+
+ParticlesStage = Utilities.createSubclass(Stage,
+ function()
+ {
+ Stage.call(this);
+ this.particles = [];
+ }, {
+
+ animate: function(timeDelta)
+ {
+ timeDelta /= 4;
+ this.particles.forEach(function(particle) {
+ particle.animate(timeDelta);
+ });
+ },
+
+ tune: function(count)
+ {
+ if (count == 0)
+ return;
+
+ if (count > 0) {
+ for (var i = 0; i < count; ++i)
+ this.particles.push(this.createParticle());
+ return;
+ }
+
+ count = Math.min(-count, this.particles.length);
+
+ if (typeof(this.willRemoveParticle) == "function") {
+ for (var i = 0; i < count; ++i)
+ this.willRemoveParticle(this.particles[i]);
+ }
+
+ this.particles.splice(0, count);
+ },
+
+ complexity: function()
+ {
+ return this.particles.length;
+ }
+});
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/performance.svg b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/performance.svg
new file mode 100644
index 0000000000..37c4e952c1
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/performance.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright © 2016 Apple Inc. All rights reserved. -->
+<svg width="48px" height="48px" viewBox="0 0 48 48" version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <path d="M 24 45.76 L 24 45.76 C 36.0177161 45.76 45.76 36.0177162 45.76 24 C 45.76 11.9822838 36.0177161 2.24 24 2.24 C 11.9822838 2.24 2.24 11.9822838 2.24 24 C 2.24 36.0177162 11.9822838 45.76 24 45.76 L 24 45.76 L 24 45.76 L 24 45.76 Z M 24 48 L 24 48 C 10.745166 48 -1.77635684e-14 37.254834 -1.77635684e-14 24 C -1.77635684e-14 10.745166 10.745166 2.84217094e-14 24 2.84217094e-14 C 37.254834 2.84217094e-14 48 10.745166 48 24 C 48 37.254834 37.254834 48 24 48 L 24 48 L 24 48 L 24 48 Z" fill="rgb(152, 188, 77)"/>
+ <path d="M 25.4586474 22.9633529 L 36.6273818 12.9367924 L 19.3784717 20.0882179 L 22.54035 25.0378408 L 11.3720064 35.0646845 L 28.6179627 27.9103051 L 25.4586474 22.9633529 L 25.4586474 22.9633529 Z" fill="white"/>
+</svg>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/performance100.png b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/performance100.png
new file mode 100644
index 0000000000..3f8a187596
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/performance100.png
Binary files differ
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/script.svg b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/script.svg
new file mode 100644
index 0000000000..5e3f9c1b03
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/script.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright © 2016 Apple Inc. All rights reserved. -->
+<svg width="48px" height="48px" viewBox="0 0 48 48" version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <path d="M 9.4057939 17.7395629 C 10.1528885 17.0482595 11.14598 16.6062505 12.2562501 16.6062505 C 14.6587038 16.6062505 16.5125003 18.7103026 16.5125003 20.8625007 C 16.5125003 20.8625007 18.178953 19.2008056 19.0121793 18.369958 C 21.6138782 15.7756868 26.817276 10.5871443 26.817276 10.5871443 C 26.817276 10.5871443 37.1931445 21.9632427 37.5748423 22.4630973 C 38.0895548 23.1371422 39.2154452 24.3686768 39.2154452 26.5456407 C 39.2154452 27.6292862 38.7691081 28.6850409 38.0240604 29.4729943 C 37.2725506 30.267782 21.5041804 45.9478026 22.256517 45.2395774 C 23.0871144 44.4575043 23.6062505 43.3509701 23.6062505 42.1437514 C 23.6062505 39.8308355 22.4995839 38.7247751 21.9516194 38.0693479 C 21.9377433 38.0527505 21.4369464 37.5002693 20.6469581 36.6292772 L 15.0937502 42.1437514 C 15.0937502 44.4944134 16.9993383 46.4000015 19.3500004 46.4000015 C 20.4737422 46.4000015 21.4957691 45.9558816 22.256517 45.2395774 L 22.256517 45.2395773 C 22.2567055 45.2393999 22.256895 45.2392214 22.2570855 45.2390419 C 23.0873513 44.4569993 23.6062505 43.3506946 23.6062505 42.1437514 C 23.6062505 39.8308355 22.4995839 38.7247751 21.9516194 38.0693479 C 21.4036549 37.4139207 10.6902909 25.670612 9.9591809 24.8251984 C 9.2280709 23.9797848 8 23.049163 8 20.8625007 C 8 19.6863826 8.5362909 18.5441335 9.4057939 17.7395629 C 8.5362926 18.5441317 24.254167 2.7911567 25.2247918 1.98986582 C 25.9645636 1.37915353 26.8917931 1 27.8625007 1 C 30.1068344 1 32.1634331 3.09747093 32.1634331 5.25625015 L 16.5125003 20.8625007 C 16.5125003 18.7103026 14.6587038 16.6062505 12.2562501 16.6062505 C 11.1459801 16.6062505 10.1528886 17.0482595 9.405794 17.7395627 L 9.4057939 17.7395629 Z" fill="none" stroke="rgb(153, 127, 166)" stroke-width="2.5"/>
+</svg>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/script100.png b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/script100.png
new file mode 100644
index 0000000000..c2ea55ead7
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/script100.png
Binary files differ
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/shortcuts.svg b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/shortcuts.svg
new file mode 100644
index 0000000000..edaa84963b
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/shortcuts.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright © 2016 Apple Inc. All rights reserved. -->
+<svg width="48px" height="48px" viewBox="0 0 48 48" version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <path d="M 5 35.8242187 C 5 39.7527757 8.1847243 42.9375 12.1132812 42.9375 C 16.0418382 42.9375 19.2265625 39.7527757 19.2265625 35.8242187 L 19.2265625 11.9442883 C 19.2265625 8.1847243 16.0418382 5 12.1132812 5 C 8.1847243 5 5 8.1847243 5 12.1132812 C 5 16.0418382 8.1847243 19.2265625 12.1132812 19.2265625 L 35.8928161 19.2265625 C 39.7527757 19.2265625 42.9375 16.0418382 42.9375 12.1132812 C 42.9375 8.1847243 39.7527757 5 35.8242188 5 C 31.8956618 5 28.7109375 8.1847243 28.7109375 12.1132812 L 28.7109375 35.8190088 C 28.7109375 39.7527757 31.8956618 42.9375 35.8242187 42.9375 C 39.7527757 42.9375 42.9375 39.7527757 42.9375 35.8242188 C 42.9375 31.8956618 39.7527757 28.7109375 35.8242187 28.7109375 L 12.1184912 28.7109375 C 8.1847243 28.7109375 5 31.8956618 5 35.8242187 Z" fill="none" stroke="rgb(0, 136, 204)" stroke-width="2.5"/>
+</svg>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/shortcuts100.png b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/shortcuts100.png
new file mode 100644
index 0000000000..aeb23e0a40
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/shortcuts100.png
Binary files differ
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/standards.svg b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/standards.svg
new file mode 100644
index 0000000000..ac1e6934d8
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/standards.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright © 2016 Apple Inc. All rights reserved. -->
+<svg width="48px" height="48px" viewBox="0 0 48 48" version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <path d="M 42.0710239 24.0177617 C 39.1538386 16.9070258 32.1617573 11.8990479 24 11.8990479 C 16.3635634 11.8990479 9.75107907 16.2831086 6.54212676 22.6716502 M 30.9761247 44.4830419 C 32.2260967 41.0462637 32.9749756 36.6675422 32.9749756 31.8990479 C 32.9749756 20.8533529 28.9567421 11.8990479 24 11.8990479 C 19.0432579 11.8990479 15.0250244 20.8533529 15.0250244 31.8990479 C 15.0250244 36.5317055 15.7318455 40.7964804 16.9182797 44.1870585 L 16.9182797 44.1870585 M 6.58618164 23.392334 C 6.58618164 25.4881886 14.5338788 27.1872144 24.3378601 27.1872144 C 34.1418414 27.1872144 42.0895386 25.4881886 42.0895386 23.392334 M 7.57792629 35.5492537 C 10.9596878 37.443268 17.049483 38.7070228 24 38.7070228 C 31.5250917 38.7070228 38.041274 37.2256916 41.204187 35.0669761 M 24.25 12.9990234 L 24.25 45" fill="none" stroke="white" stroke-width="2.5"/>
+ <path d="M 8.20156221 41.7446204 L 4.60455725 1.39999998 L 44.1294427 1.39999998 L 40.5286241 41.7383005 L 24.34281 46.2255399 L 8.20156221 41.7446204 Z" fill="none" stroke="#BF7600" stroke-width="2.5"/>
+</svg>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/standards100.png b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/standards100.png
new file mode 100644
index 0000000000..ff386ff163
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/standards100.png
Binary files differ
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/storage.svg b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/storage.svg
new file mode 100644
index 0000000000..c34a9ed255
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/storage.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright © 2016 Apple Inc. All rights reserved. -->
+<svg width="48px" height="48px" viewBox="0 0 48 48" version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <path d="M 39.9236499 31.5126111 C 41.869091 32.6498521 43 34.0625041 43 35.6923077 C 43 40.1632127 34.4896382 43 24 43 C 13.5103618 43 5 40.1632127 5 35.6923077 C 5 34.0625041 6.130909 32.6498521 8.07635005 31.5126111 C 9.14708175 31.9858647 10.3798534 32.4104194 11.7445378 32.7755154 C 9.22593316 33.7562269 7.92307692 34.9214488 7.92307692 35.6923077 C 7.92307692 36.4947878 9.3350136 37.7246485 12.0606138 38.728817 C 15.168606 39.8738668 19.433505 40.5384615 24 40.5384615 C 28.566495 40.5384615 32.831394 39.8738668 35.9393862 38.728817 C 38.6649864 37.7246485 40.0769231 36.4947878 40.0769231 35.6923077 C 40.0769231 34.9214488 38.7740668 33.7562269 36.2554622 32.7755154 C 37.6201466 32.4104194 38.8529182 31.9858647 39.9236499 31.5126111 Z M 39.9236499 19.8203034 C 41.869091 20.9575444 43 22.3701964 43 24 C 43 28.470905 34.4896382 31.3076923 24 31.3076923 C 13.5103618 31.3076923 5 28.470905 5 24 C 5 22.3701964 6.130909 20.9575444 8.07635005 19.8203034 C 9.06881359 20.2589632 10.2004933 20.6557834 11.4473978 21.0021956 C 9.12353139 22.0250817 7.92307692 23.2072017 7.92307692 24 C 7.92307692 24.8598001 9.3350136 26.177508 12.0606138 27.2534028 C 15.168606 28.4802419 19.433505 29.1923077 24 29.1923077 C 28.566495 29.1923077 32.831394 28.4802419 35.9393862 27.2534028 C 38.6649864 26.177508 40.0769231 24.8598001 40.0769231 24 C 40.0769231 23.2072017 38.8764686 22.0250817 36.5526022 21.0021956 C 37.7995067 20.6557834 38.9311864 20.2589632 39.9236499 19.8203034 Z M 43 12.3076923 C 43 7.83678727 34.4896382 5 24 5 C 13.5103618 5 5 7.83678727 5 12.3076923 C 5 16.7785973 13.5103618 19.6153846 24 19.6153846 C 34.4896382 19.6153846 43 16.7785973 43 12.3076923 Z M 12.0606138 15.3442016 C 9.3350136 14.3400331 7.92307692 13.1101724 7.92307692 12.3076923 C 7.92307692 11.5052122 9.3350136 10.2753515 12.0606138 9.27118298 C 15.168606 8.12613322 19.433505 7.46153846 24 7.46153846 C 28.566495 7.46153846 32.831394 8.12613322 35.9393862 9.27118298 C 38.6649864 10.2753515 40.0769231 11.5052122 40.0769231 12.3076923 C 40.0769231 13.1101724 38.6649864 14.3400331 35.9393862 15.3442016 C 32.831394 16.4892514 28.566495 17.1538462 24 17.1538462 C 19.433505 17.1538462 15.168606 16.4892514 12.0606138 15.3442016 Z" fill="rgb(153, 127, 166)"/>
+</svg>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/storage100.png b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/storage100.png
new file mode 100644
index 0000000000..bc59d92fcf
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/storage100.png
Binary files differ
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/styles.svg b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/styles.svg
new file mode 100644
index 0000000000..f50cff7d6d
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/styles.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright © 2016 Apple Inc. All rights reserved. -->
+<svg width="48px" height="48px" viewBox="0 0 48 48" version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <path d="M 32.2807541 19.800573 C 30.8515632 18.9532817 29.6775632 16.9314716 29.6582461 15.2582558 L 29.5886562 9.2305008 C 29.5694759 7.56913954 30.7023175 6.90315961 32.1417063 7.75649663 L 37.3271003 10.8306408 C 38.7562912 11.677932 39.9302912 13.6997422 39.9496083 15.3729579 L 40.0191983 21.400713 C 40.0383785 23.0620742 38.905537 23.7280542 37.4661481 22.8747171 L 32.2807541 19.800573 L 32.2807541 19.800573 L 32.2807541 19.800573 Z M 22.7106927 25.0325153 C 21.2837011 24.186528 20.1113895 22.1575845 20.0922204 20.4971883 L 19.9529996 8.43813667 C 19.9338489 6.77933205 21.0737602 6.11960178 22.5021209 6.96640082 L 32.8759556 13.1164953 C 34.3029471 13.9624827 35.4752587 15.9914262 35.4944279 17.6518224 L 35.6336486 29.710874 C 35.6527994 31.3696786 34.512888 32.0294089 33.0845273 31.1826098 L 22.7106927 25.0325153 L 22.7106927 25.0325153 L 22.7106927 25.0325153 Z M 11.6578029 32.7104298 C 9.75514746 31.5824467 8.19206532 28.8771886 8.16650648 26.6633271 L 7.98087883 10.5845916 C 7.95534449 8.37285211 9.47522625 7.49321175 11.3797072 8.62227714 L 25.2114868 16.8224031 C 27.1141422 17.9503863 28.6772243 20.6556443 28.7027831 22.8695059 L 28.8884108 38.9482414 C 28.9139451 41.1599809 27.3940634 42.0396212 25.4895824 40.9105558 L 11.6578029 32.7104298 L 11.6578029 32.7104298 L 11.6578029 32.7104298 Z" fill="none" stroke="rgb(191, 109, 113)" stroke-width="2.5"/>
+</svg>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/styles100.png b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/styles100.png
new file mode 100644
index 0000000000..7bc9fffe9c
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/styles100.png
Binary files differ
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/svg-particles.js b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/svg-particles.js
new file mode 100644
index 0000000000..2ce24b56f1
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/svg-particles.js
@@ -0,0 +1,111 @@
+(function() {
+
+SVGParticle = Utilities.createSubclass(Particle,
+ function(stage)
+ {
+ var shapeId = "#shape-" + Stage.randomInt(1, stage.particleTypeCount);
+ this.isClipPath = Stage.randomBool();
+ if (this.isClipPath) {
+ this.element = Utilities.createSVGElement("rect", {
+ x: 0,
+ y: 0,
+ "clip-path": "url(" + shapeId + ")"
+ }, {}, stage.element);
+ } else {
+ var shapePath = document.querySelector(shapeId + " path");
+ this.element = shapePath.cloneNode();
+ stage.element.appendChild(this.element);
+ }
+
+ this.gradient = document.getElementById("default-gradient").cloneNode(true);
+ this.gradient.id = "gradient-" + stage.gradientsCounter++;
+ stage.gradientsDefs.appendChild(this.gradient);
+ this.element.setAttribute("fill", "url(#" + this.gradient.id + ")");
+
+ Particle.call(this, stage);
+ }, {
+
+ sizeMinimum: 30,
+ sizeRange: 40,
+
+ reset: function()
+ {
+ Particle.prototype.reset.call(this);
+
+ this.position = Stage.randomElementInArray(this.stage.emitLocation);
+
+ var velocityMagnitude = Stage.random(.5, 2.5);
+ var angle = Stage.randomInt(0, this.stage.emitSteps) / this.stage.emitSteps * Math.PI * 2 + Stage.dateCounterValue(1000) * this.stage.emissionSpin + velocityMagnitude;
+ this.velocity = new Point(Math.sin(angle), Math.cos(angle))
+ .multiply(velocityMagnitude);
+
+ if (this.isClipPath) {
+ this.element.setAttribute("width", this.size.x);
+ this.element.setAttribute("height", this.size.y);
+ this.transformSuffix = " translate(-" + this.size.center.x + ",-" + this.size.center.y + ")";
+ } else
+ this.transformSuffix = " scale(" + this.size.x + ") translate(-.5,-.5)";
+
+ this.stage.colorOffset = (this.stage.colorOffset + .5) % 360;
+
+ var transform = this.stage.element.createSVGTransform();
+ transform.setRotate(Stage.randomInt(0, 359), 0, 0);
+ this.gradient.gradientTransform.baseVal.initialize(transform);
+
+ var stops = this.gradient.querySelectorAll("stop");
+ stops[0].setAttribute("stop-color", "hsl(" + this.stage.colorOffset + ", 70%, 45%)");
+ stops[1].setAttribute("stop-color", "hsl(" + ((this.stage.colorOffset + Stage.randomInt(50,100)) % 360) + ", 70%, 65%)");
+ },
+
+ move: function()
+ {
+ this.element.setAttribute("transform", "translate(" + this.position.x + "," + this.position.y + ") " + this.rotater.rotate(Point.zero) + this.transformSuffix);
+ }
+});
+
+SVGParticleStage = Utilities.createSubclass(ParticlesStage,
+ function()
+ {
+ ParticlesStage.call(this);
+ }, {
+
+ initialize: function(benchmark)
+ {
+ ParticlesStage.prototype.initialize.call(this, benchmark);
+ this.emissionSpin = Stage.random(0, 3);
+ this.emitSteps = Stage.randomInt(4, 6);
+ this.emitLocation = [
+ new Point(this.size.x * .25, this.size.y * .333),
+ new Point(this.size.x * .5, this.size.y * .25),
+ new Point(this.size.x * .75, this.size.y * .333)
+ ];
+ this.colorOffset = Stage.randomInt(0, 359);
+
+ this.particleTypeCount = document.querySelectorAll(".shape").length;
+ this.gradientsDefs = document.getElementById("gradients");
+ this.gradientsCounter = 0;
+ },
+
+ createParticle: function()
+ {
+ return new SVGParticle(this);
+ },
+
+ willRemoveParticle: function(particle)
+ {
+ particle.element.remove();
+ if (particle.gradient)
+ particle.gradient.remove();
+ }
+});
+
+SVGParticleBenchmark = Utilities.createSubclass(Benchmark,
+ function(options)
+ {
+ Benchmark.call(this, new SVGParticleStage(), options);
+ }
+);
+
+window.benchmarkClass = SVGParticleBenchmark;
+
+})();
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/text.js b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/text.js
new file mode 100644
index 0000000000..c7ebe464b3
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/text.js
@@ -0,0 +1,116 @@
+(function() {
+
+var TextStage = Utilities.createSubclass(Stage,
+ function()
+ {
+ Stage.call(this);
+
+ this.testElements = [];
+ this._offsetIndex = 0;
+ }, {
+
+ shadowFalloff: new UnitBezier(new Point(0.015, 0.750), new Point(0.755, 0.235)),
+ shimmerAverage: 0,
+ shimmerMax: 0.5,
+ millisecondsPerRotation: 1000 / (.26 * Math.PI * 2),
+ particleDistanceX: 1.5,
+ particleDistanceY: .5,
+ lightnessMin: 13,
+ lightnessMax: 94,
+ gradients: [
+ [10, 176, 176, 209, 148, 140],
+ [171, 120, 154, 245, 196, 154],
+ [224, 99, 99, 71, 134, 148],
+ [101, 100, 117, 80, 230, 175],
+ [232, 165, 30, 69, 186, 172]
+ ],
+
+ initialize: function(benchmark)
+ {
+ Stage.prototype.initialize.call(this, benchmark);
+
+ this._template = document.getElementById("template");
+ this._offset = this.size.subtract(Point.elementClientSize(this._template)).multiply(.5);
+ this._template.style.left = this._offset.width + "px";
+ this._template.style.top = this._offset.height + "px";
+
+ this._stepProgress = 0;
+ },
+
+ tune: function(count)
+ {
+ if (count == 0)
+ return;
+
+ if (count < 0) {
+ this._offsetIndex = Math.max(this._offsetIndex + count, 0);
+ for (var i = this._offsetIndex; i < this.testElements.length; ++i)
+ this.testElements[i].style.visibility = "hidden";
+
+ this._stepProgress = 1 / this._offsetIndex;
+ return;
+ }
+
+ this._offsetIndex = this._offsetIndex + count;
+ this._stepProgress = 1 / this._offsetIndex;
+
+ var index = Math.min(this._offsetIndex, this.testElements.length);
+ for (var i = 0; i < index; ++i)
+ this.testElements[i].style.visibility = "visible";
+
+ if (this._offsetIndex <= this.testElements.length)
+ return;
+
+ for (var i = this.testElements.length; i < this._offsetIndex; ++i) {
+ var clone = this._template.cloneNode(true);
+ this.testElements.push(clone);
+ this.element.insertBefore(clone, this.element.firstChild);
+ }
+ },
+
+ animate: function(timeDelta) {
+ var angle = Stage.dateCounterValue(this.millisecondsPerRotation);
+
+ var progress = 0;
+ var stepX = Math.sin(angle) * this.particleDistanceX;
+ var stepY = Math.cos(angle) * this.particleDistanceY;
+ var x = -stepX * 3;
+ var y = -stepY * 3;
+ var gradient = this.gradients[Math.floor(angle/(Math.PI * 2)) % this.gradients.length];
+ var offset = Stage.dateCounterValue(200);
+ this._template.style.transform = "translate(" + Math.floor(x) + "px," + Math.floor(y) + "px)";
+ for (var i = 0; i < this._offsetIndex; ++i) {
+ var element = this.testElements[i];
+
+ var colorProgress = this.shadowFalloff.solve(progress);
+ var shimmer = Math.sin(offset - colorProgress);
+ colorProgress = Math.max(Math.min(colorProgress + Utilities.lerp(shimmer, this.shimmerAverage, this.shimmerMax), 1), 0);
+ var r = Math.round(Utilities.lerp(colorProgress, gradient[0], gradient[3]));
+ var g = Math.round(Utilities.lerp(colorProgress, gradient[1], gradient[4]));
+ var b = Math.round(Utilities.lerp(colorProgress, gradient[2], gradient[5]));
+ element.style.color = "rgb(" + r + "," + g + "," + b + ")";
+
+ x += stepX;
+ y += stepY;
+ element.style.transform = "translate(" + Math.floor(x) + "px," + Math.floor(y) + "px)";
+
+ progress += this._stepProgress;
+ }
+ },
+
+ complexity: function()
+ {
+ return 1 + this._offsetIndex;
+ }
+});
+
+var TextBenchmark = Utilities.createSubclass(Benchmark,
+ function(options)
+ {
+ Benchmark.call(this, new TextStage(), options);
+ }
+);
+
+window.benchmarkClass = TextBenchmark;
+
+}());
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/timeline.svg b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/timeline.svg
new file mode 100644
index 0000000000..cd1e8a4e20
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/timeline.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright © 2016 Apple Inc. All rights reserved. -->
+<svg width="48px" height="48px" viewBox="0 0 48 48" version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <path d="M 24 45.76 L 24 45.76 C 36.0177161 45.76 45.76 36.0177162 45.76 24 C 45.76 11.9822838 36.0177161 2.24 24 2.24 C 11.9822838 2.24 2.24 11.9822838 2.24 24 C 2.24 36.0177162 11.9822838 45.76 24 45.76 L 24 45.76 L 24 45.76 L 24 45.76 Z M 24 48 L 24 48 C 10.745166 48 0 37.254834 0 24 C 0 10.745166 10.745166 0 24 0 C 37.254834 0 48 10.745166 48 24 C 48 37.254834 37.254834 48 24 48 L 24 48 L 24 48 L 24 48 Z" fill="rgb(0, 136, 204)"/>
+ <path d="M 24.625 7.57617187 L 24.625 24.5833333 L 15 24.5833333" fill="none" stroke="white" stroke-width="2.5"/>
+</svg>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/timeline100.png b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/timeline100.png
new file mode 100644
index 0000000000..b9839f8447
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/timeline100.png
Binary files differ
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/svg-particles.html b/third_party/webkit/PerformanceTests/MotionMark/tests/master/svg-particles.html
new file mode 100644
index 0000000000..46a19369da
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/svg-particles.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+</head>
+<body>
+ <svg id="stage">
+ <defs id="gradients">
+ <linearGradient id="default-gradient">
+ <stop offset="0%"/>
+ <stop offset="100%"/>
+ </linearGradient>
+ </defs>
+ <defs id="shapes">
+ <clipPath id="shape-1" class="shape heart" clipPathUnits="objectBoundingBox">
+ <path d="M0.5,0.214 C0.466,0.164 0.369,0.09 0.267,0.092 C0.137,0.093 -0,0.186 -0,0.345 C-0,0.659 0.395,0.655 0.5,0.938 C0.605,0.655 1,0.659 1,0.345 C1,0.186 0.863,0.093 0.733,0.092 C0.631,0.09 0.534,0.164 0.5,0.214 z"/>
+ </clipPath>
+ <clipPath id="shape-2" class="shape club" clipPathUnits="objectBoundingBox">
+ <path d="M0.5,0.018 C0.62,0.018 0.718,0.115 0.718,0.235 C0.718,0.31 0.679,0.377 0.618,0.418 C0.657,0.393 0.703,0.382 0.749,0.381 C0.869,0.381 0.967,0.468 0.967,0.588 C0.967,0.709 0.869,0.806 0.749,0.806 C0.664,0.805 0.578,0.756 0.542,0.677 C0.538,0.799 0.605,0.918 0.708,0.982 C0.593,0.941 0.407,0.941 0.292,0.982 C0.397,0.917 0.461,0.799 0.459,0.676 C0.422,0.756 0.337,0.804 0.251,0.806 C0.131,0.806 0.033,0.709 0.033,0.588 C0.033,0.468 0.131,0.381 0.251,0.381 C0.298,0.38 0.342,0.395 0.382,0.418 C0.319,0.378 0.284,0.309 0.282,0.235 C0.282,0.115 0.38,0.018 0.5,0.018 z"/>
+ </clipPath>
+ <clipPath id="shape-3" class="shape spade" clipPathUnits="objectBoundingBox">
+ <path d="M0.301,0.982 C0.374,0.941 0.469,0.804 0.469,0.72 C0.374,0.857 0.039,0.825 0.049,0.563 C0.059,0.28 0.406,0.269 0.5,0.018 C0.594,0.269 0.941,0.28 0.951,0.563 C0.961,0.825 0.626,0.857 0.531,0.72 C0.531,0.804 0.626,0.941 0.699,0.982 C0.584,0.941 0.416,0.941 0.301,0.982"/>
+ </clipPath>
+ <clipPath id="shape-4" class="shape diamond" clipPathUnits="objectBoundingBox">
+ <path d="M0.495,0 C0.424,0.153 0.199,0.439 0.128,0.5 C0.199,0.561 0.424,0.847 0.495,1 C0.566,0.847 0.791,0.561 0.862,0.5 C0.791,0.439 0.566,0.153 0.495,0 z"/>
+ </clipPath>
+ </defs>
+ </svg>
+ <script src="../../resources/strings.js"></script>
+ <script src="../../resources/extensions.js"></script>
+ <script src="../../resources/statistics.js"></script>
+ <script src="../resources/math.js"></script>
+ <script src="../resources/main.js"></script>
+ <script src="resources/particles.js"></script>
+ <script src="resources/svg-particles.js"></script>
+</body>
+</html>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/master/text.html b/third_party/webkit/PerformanceTests/MotionMark/tests/master/text.html
new file mode 100644
index 0000000000..5e94b8ce95
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/master/text.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+ <style type="text/css">
+
+ #stage {
+ font-family: Helvetica;
+ font-size: 52px;
+ background-color: #313534;
+ }
+ @media (max-width: 900px) {
+ #stage {
+ font-size: 40px;
+ }
+ }
+ @media (max-width: 568px) {
+ #stage {
+ font-size: 28px;
+ }
+ }
+
+ #stage div {
+ width: 80%;
+ height: 90%;
+ position: absolute;
+ text-align: center;
+ }
+ #template {
+ color: #FCFCFC;
+ }
+ table {
+ position: relative;
+ width: 100%;
+ height: 100%;
+ }
+ td {
+ width: 33%;
+ }
+ tr {
+ height: 20%;
+ }
+ </style>
+</head>
+<body>
+ <div id="stage">
+ <div id="template">
+ <table>
+ <tbody>
+ <tr>
+ <td>σχέδιο</td>
+ <td>设计</td>
+ <td>suunnittelu</td>
+ </tr>
+ <tr>
+ <td>design</td>
+ <td>дизайн</td>
+ <td class="rtl">تصميم</td>
+ </tr>
+ <tr>
+ <td>디자인</td>
+ <td>conception</td>
+ <td>デザイン</td>
+ </tr>
+ <tr>
+ <td>konstruktion</td>
+ <td class="rtl">עיצוב</td>
+ <td>diseño</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ <script src="../../resources/strings.js"></script>
+ <script src="../../resources/extensions.js"></script>
+ <script src="../../resources/statistics.js"></script>
+ <script src="../resources/math.js"></script>
+ <script src="../resources/main.js"></script>
+ <script src="resources/text.js"></script>
+</body>
+</html>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/resources/main.js b/third_party/webkit/PerformanceTests/MotionMark/tests/resources/main.js
new file mode 100644
index 0000000000..b9776d571e
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/resources/main.js
@@ -0,0 +1,934 @@
+Sampler = Utilities.createClass(
+ function(seriesCount, expectedSampleCount, processor)
+ {
+ this._processor = processor;
+
+ this.samples = [];
+ for (var i = 0; i < seriesCount; ++i) {
+ var array = new Array(expectedSampleCount);
+ array.fill(0);
+ this.samples[i] = array;
+ }
+ this.sampleCount = 0;
+ }, {
+
+ record: function() {
+ // Assume that arguments.length == this.samples.length
+ for (var i = 0; i < arguments.length; i++) {
+ this.samples[i][this.sampleCount] = arguments[i];
+ }
+ ++this.sampleCount;
+ },
+
+ processSamples: function()
+ {
+ var results = {};
+
+ // Remove unused capacity
+ this.samples = this.samples.map(function(array) {
+ return array.slice(0, this.sampleCount);
+ }, this);
+
+ this._processor.processSamples(results);
+
+ return results;
+ }
+});
+
+Controller = Utilities.createClass(
+ function(benchmark, options)
+ {
+ // Initialize timestamps relative to the start of the benchmark
+ // In start() the timestamps are offset by the start timestamp
+ this._startTimestamp = 0;
+ this._endTimestamp = options["test-interval"];
+ // Default data series: timestamp, complexity, estimatedFrameLength
+ var sampleSize = options["sample-capacity"] || (60 * options["test-interval"] / 1000);
+ this._sampler = new Sampler(options["series-count"] || 3, sampleSize, this);
+ this._marks = {};
+
+ this._frameLengthEstimator = new SimpleKalmanEstimator(options["kalman-process-error"], options["kalman-measurement-error"]);
+ this._isFrameLengthEstimatorEnabled = true;
+
+ // Length of subsequent intervals; a value of 0 means use no intervals
+ this.intervalSamplingLength = 100;
+
+ this.initialComplexity = 1;
+ }, {
+
+ set isFrameLengthEstimatorEnabled(enabled) {
+ this._isFrameLengthEstimatorEnabled = enabled;
+ },
+
+ start: function(startTimestamp, stage)
+ {
+ this._startTimestamp = startTimestamp;
+ this._endTimestamp += startTimestamp;
+ this._previousTimestamp = startTimestamp;
+ this._measureAndResetInterval(startTimestamp);
+ this.recordFirstSample(startTimestamp, stage);
+ },
+
+ recordFirstSample: function(startTimestamp, stage)
+ {
+ this._sampler.record(startTimestamp, stage.complexity(), -1);
+ this.mark(Strings.json.samplingStartTimeOffset, startTimestamp);
+ },
+
+ mark: function(comment, timestamp, data) {
+ data = data || {};
+ data.time = timestamp;
+ data.index = this._sampler.sampleCount;
+ this._marks[comment] = data;
+ },
+
+ containsMark: function(comment) {
+ return comment in this._marks;
+ },
+
+ _measureAndResetInterval: function(currentTimestamp)
+ {
+ var sampleCount = this._sampler.sampleCount;
+ var averageFrameLength = 0;
+
+ if (this._intervalEndTimestamp) {
+ var intervalStartTimestamp = this._sampler.samples[0][this._intervalStartIndex];
+ averageFrameLength = (currentTimestamp - intervalStartTimestamp) / (sampleCount - this._intervalStartIndex);
+ }
+
+ this._intervalStartIndex = sampleCount;
+ this._intervalEndTimestamp = currentTimestamp + this.intervalSamplingLength;
+
+ return averageFrameLength;
+ },
+
+ update: function(timestamp, stage)
+ {
+ var lastFrameLength = timestamp - this._previousTimestamp;
+ this._previousTimestamp = timestamp;
+
+ var frameLengthEstimate = -1, intervalAverageFrameLength = -1;
+ var didFinishInterval = false;
+ if (!this.intervalSamplingLength) {
+ if (this._isFrameLengthEstimatorEnabled) {
+ this._frameLengthEstimator.sample(lastFrameLength);
+ frameLengthEstimate = this._frameLengthEstimator.estimate;
+ }
+ } else if (timestamp >= this._intervalEndTimestamp) {
+ var intervalStartTimestamp = this._sampler.samples[0][this._intervalStartIndex];
+ intervalAverageFrameLength = this._measureAndResetInterval(timestamp);
+ if (this._isFrameLengthEstimatorEnabled) {
+ this._frameLengthEstimator.sample(intervalAverageFrameLength);
+ frameLengthEstimate = this._frameLengthEstimator.estimate;
+ }
+ didFinishInterval = true;
+ this.didFinishInterval(timestamp, stage, intervalAverageFrameLength);
+ }
+
+ this._sampler.record(timestamp, stage.complexity(), frameLengthEstimate);
+ this.tune(timestamp, stage, lastFrameLength, didFinishInterval, intervalAverageFrameLength);
+ },
+
+ didFinishInterval: function(timestamp, stage, intervalAverageFrameLength)
+ {
+ },
+
+ tune: function(timestamp, stage, lastFrameLength, didFinishInterval, intervalAverageFrameLength)
+ {
+ },
+
+ shouldStop: function(timestamp)
+ {
+ return timestamp > this._endTimestamp;
+ },
+
+ results: function()
+ {
+ return this._sampler.processSamples();
+ },
+
+ _processComplexitySamples: function(complexitySamples, complexityAverageSamples)
+ {
+ complexityAverageSamples.addField(Strings.json.complexity, 0);
+ complexityAverageSamples.addField(Strings.json.frameLength, 1);
+ complexityAverageSamples.addField(Strings.json.measurements.stdev, 2);
+
+ complexitySamples.sort(function(a, b) {
+ return complexitySamples.getFieldInDatum(a, Strings.json.complexity) - complexitySamples.getFieldInDatum(b, Strings.json.complexity);
+ });
+
+ // Samples averaged based on complexity
+ var currentComplexity = -1;
+ var experimentAtComplexity;
+ function addSample() {
+ var mean = experimentAtComplexity.mean();
+ var stdev = experimentAtComplexity.standardDeviation();
+
+ var averageSample = complexityAverageSamples.createDatum();
+ complexityAverageSamples.push(averageSample);
+ complexityAverageSamples.setFieldInDatum(averageSample, Strings.json.complexity, currentComplexity);
+ complexityAverageSamples.setFieldInDatum(averageSample, Strings.json.frameLength, mean);
+ complexityAverageSamples.setFieldInDatum(averageSample, Strings.json.measurements.stdev, stdev);
+ }
+ complexitySamples.forEach(function(sample) {
+ var sampleComplexity = complexitySamples.getFieldInDatum(sample, Strings.json.complexity);
+ if (sampleComplexity != currentComplexity) {
+ if (currentComplexity > -1)
+ addSample();
+
+ currentComplexity = sampleComplexity;
+ experimentAtComplexity = new Experiment;
+ }
+ experimentAtComplexity.sample(complexitySamples.getFieldInDatum(sample, Strings.json.frameLength));
+ });
+ // Finish off the last one
+ addSample();
+ },
+
+ processSamples: function(results)
+ {
+ var complexityExperiment = new Experiment;
+ var smoothedFrameLengthExperiment = new Experiment;
+
+ var samples = this._sampler.samples;
+
+ for (var markName in this._marks)
+ this._marks[markName].time -= this._startTimestamp;
+ results[Strings.json.marks] = this._marks;
+
+ results[Strings.json.samples] = {};
+
+ var controllerSamples = new SampleData;
+ results[Strings.json.samples][Strings.json.controller] = controllerSamples;
+
+ controllerSamples.addField(Strings.json.time, 0);
+ controllerSamples.addField(Strings.json.complexity, 1);
+ controllerSamples.addField(Strings.json.frameLength, 2);
+ controllerSamples.addField(Strings.json.smoothedFrameLength, 3);
+
+ var complexitySamples = new SampleData(controllerSamples.fieldMap);
+ results[Strings.json.samples][Strings.json.complexity] = complexitySamples;
+
+ samples[0].forEach(function(timestamp, i) {
+ var sample = controllerSamples.createDatum();
+ controllerSamples.push(sample);
+ complexitySamples.push(sample);
+
+ // Represent time in milliseconds
+ controllerSamples.setFieldInDatum(sample, Strings.json.time, timestamp - this._startTimestamp);
+ controllerSamples.setFieldInDatum(sample, Strings.json.complexity, samples[1][i]);
+
+ if (i == 0)
+ controllerSamples.setFieldInDatum(sample, Strings.json.frameLength, 1000/60);
+ else
+ controllerSamples.setFieldInDatum(sample, Strings.json.frameLength, timestamp - samples[0][i - 1]);
+
+ if (samples[2][i] != -1)
+ controllerSamples.setFieldInDatum(sample, Strings.json.smoothedFrameLength, samples[2][i]);
+ }, this);
+
+ var complexityAverageSamples = new SampleData;
+ results[Strings.json.samples][Strings.json.complexityAverage] = complexityAverageSamples;
+ this._processComplexitySamples(complexitySamples, complexityAverageSamples);
+ }
+});
+
+FixedController = Utilities.createSubclass(Controller,
+ function(benchmark, options)
+ {
+ Controller.call(this, benchmark, options);
+ this.initialComplexity = options["complexity"];
+ this.intervalSamplingLength = 0;
+ }
+);
+
+StepController = Utilities.createSubclass(Controller,
+ function(benchmark, options)
+ {
+ Controller.call(this, benchmark, options);
+ this.initialComplexity = options["complexity"];
+ this.intervalSamplingLength = 0;
+ this._stepped = false;
+ this._stepTime = options["test-interval"] / 2;
+ }, {
+
+ start: function(startTimestamp, stage)
+ {
+ Controller.prototype.start.call(this, startTimestamp, stage);
+ this._stepTime += startTimestamp;
+ },
+
+ tune: function(timestamp, stage)
+ {
+ if (this._stepped || timestamp < this._stepTime)
+ return;
+
+ this.mark(Strings.json.samplingEndTimeOffset, timestamp);
+ this._stepped = true;
+ stage.tune(stage.complexity() * 3);
+ }
+});
+
+AdaptiveController = Utilities.createSubclass(Controller,
+ function(benchmark, options)
+ {
+ // Data series: timestamp, complexity, estimatedIntervalFrameLength
+ Controller.call(this, benchmark, options);
+
+ // All tests start at 0, so we expect to see 60 fps quickly.
+ this._samplingTimestamp = options["test-interval"] / 2;
+ this._startedSampling = false;
+ this._targetFrameRate = options["frame-rate"];
+ this._pid = new PIDController(this._targetFrameRate);
+
+ this._intervalFrameCount = 0;
+ this._numberOfFramesToMeasurePerInterval = 4;
+ }, {
+
+ start: function(startTimestamp, stage)
+ {
+ Controller.prototype.start.call(this, startTimestamp, stage);
+
+ this._samplingTimestamp += startTimestamp;
+ this._intervalTimestamp = startTimestamp;
+ },
+
+ recordFirstSample: function(startTimestamp, stage)
+ {
+ this._sampler.record(startTimestamp, stage.complexity(), -1);
+ },
+
+ update: function(timestamp, stage)
+ {
+ if (!this._startedSampling && timestamp >= this._samplingTimestamp) {
+ this._startedSampling = true;
+ this.mark(Strings.json.samplingStartTimeOffset, this._samplingTimestamp);
+ }
+
+ // Start the work for the next frame.
+ ++this._intervalFrameCount;
+
+ if (this._intervalFrameCount < this._numberOfFramesToMeasurePerInterval) {
+ this._sampler.record(timestamp, stage.complexity(), -1);
+ return;
+ }
+
+ // Adjust the test to reach the desired FPS.
+ var intervalLength = timestamp - this._intervalTimestamp;
+ this._frameLengthEstimator.sample(intervalLength / this._numberOfFramesToMeasurePerInterval);
+ var intervalEstimatedFrameRate = 1000 / this._frameLengthEstimator.estimate;
+ var tuneValue = -this._pid.tune(timestamp - this._startTimestamp, intervalLength, intervalEstimatedFrameRate);
+ tuneValue = tuneValue > 0 ? Math.floor(tuneValue) : Math.ceil(tuneValue);
+ stage.tune(tuneValue);
+
+ this._sampler.record(timestamp, stage.complexity(), this._frameLengthEstimator.estimate);
+
+ // Start the next interval.
+ this._intervalFrameCount = 0;
+ this._intervalTimestamp = timestamp;
+ }
+});
+
+RampController = Utilities.createSubclass(Controller,
+ function(benchmark, options)
+ {
+ // The tier warmup takes at most 5 seconds
+ options["sample-capacity"] = (options["test-interval"] / 1000 + 5) * 60;
+ Controller.call(this, benchmark, options);
+
+ // Initially start with a tier test to find the bounds
+ // The number of objects in a tier test is 10^|_tier|
+ this._tier = -.5;
+ // The timestamp is first set after the first interval completes
+ this._tierStartTimestamp = 0;
+ this._minimumComplexity = 1;
+ this._maximumComplexity = 1;
+
+ // After the tier range is determined, figure out the number of ramp iterations
+ var minimumRampLength = 3000;
+ var totalRampIterations = Math.max(1, Math.floor(this._endTimestamp / minimumRampLength));
+ // Give a little extra room to run since the ramps won't be exactly this length
+ this._rampLength = Math.floor((this._endTimestamp - totalRampIterations * this.intervalSamplingLength) / totalRampIterations);
+ this._rampDidWarmup = false;
+ this._rampRegressions = [];
+
+ this._finishedTierSampling = false;
+ this._changePointEstimator = new Experiment;
+ this._minimumComplexityEstimator = new Experiment;
+ // Estimates all frames within an interval
+ this._intervalFrameLengthEstimator = new Experiment;
+ }, {
+
+ // If the engine can handle the tier's complexity at the desired frame rate, test for a short
+ // period, then move on to the next tier
+ tierFastTestLength: 250,
+ // If the engine is under stress, let the test run a little longer to let the measurement settle
+ tierSlowTestLength: 750,
+
+ rampWarmupLength: 200,
+
+ // Used for regression calculations in the ramps
+ frameLengthDesired: 1000/60,
+ // Add some tolerance; frame lengths shorter than this are considered to be @ the desired frame length
+ frameLengthDesiredThreshold: 1000/58,
+ // During tier sampling get at least this slow to find the right complexity range
+ frameLengthTierThreshold: 1000/30,
+ // Try to make each ramp get this slow so that we can cross the break point
+ frameLengthRampLowerThreshold: 1000/45,
+ // Do not let the regression calculation at the maximum complexity of a ramp get slower than this threshold
+ frameLengthRampUpperThreshold: 1000/20,
+
+ start: function(startTimestamp, stage)
+ {
+ Controller.prototype.start.call(this, startTimestamp, stage);
+ this._rampStartTimestamp = 0;
+ this.intervalSamplingLength = 100;
+ },
+
+ didFinishInterval: function(timestamp, stage, intervalAverageFrameLength)
+ {
+ if (!this._finishedTierSampling) {
+ if (this._tierStartTimestamp > 0 && timestamp < this._tierStartTimestamp + this.tierFastTestLength)
+ return;
+
+ var currentComplexity = stage.complexity();
+ var currentFrameLength = this._frameLengthEstimator.estimate;
+ if (currentFrameLength < this.frameLengthTierThreshold) {
+ var isAnimatingAt60FPS = currentFrameLength < this.frameLengthDesiredThreshold;
+ var hasFinishedSlowTierTest = timestamp > this._tierStartTimestamp + this.tierSlowTestLength;
+
+ if (!isAnimatingAt60FPS && !hasFinishedSlowTierTest)
+ return;
+
+ // We're measuring at 60 fps, so quickly move on to the next tier, or
+ // we've slower than 60 fps, but we've let this tier run long enough to
+ // get an estimate
+ this._lastTierComplexity = currentComplexity;
+ this._lastTierFrameLength = currentFrameLength;
+
+ this._tier += .5;
+ var nextTierComplexity = Math.round(Math.pow(10, this._tier));
+ stage.tune(nextTierComplexity - currentComplexity);
+
+ // Some tests may be unable to go beyond a certain capacity. If so, don't keep moving up tiers
+ if (stage.complexity() - currentComplexity > 0 || nextTierComplexity == 1) {
+ this._tierStartTimestamp = timestamp;
+ this.mark("Complexity: " + nextTierComplexity, timestamp);
+ return;
+ }
+ } else if (timestamp < this._tierStartTimestamp + this.tierSlowTestLength)
+ return;
+
+ this._finishedTierSampling = true;
+ this.isFrameLengthEstimatorEnabled = false;
+ this.intervalSamplingLength = 120;
+
+ // Extend the test length so that the full test length is made of the ramps
+ this._endTimestamp += timestamp;
+ this.mark(Strings.json.samplingStartTimeOffset, timestamp);
+
+ this._minimumComplexity = 1;
+ this._possibleMinimumComplexity = this._minimumComplexity;
+ this._minimumComplexityEstimator.sample(this._minimumComplexity);
+
+ // Sometimes this last tier will drop the frame length well below the threshold.
+ // Avoid going down that far since it means fewer measurements are taken in the 60 fps area.
+ // Interpolate a maximum complexity that gets us around the lowest threshold.
+ // Avoid doing this calculation if we never get out of the first tier (where this._lastTierComplexity is undefined).
+ if (this._lastTierComplexity && this._lastTierComplexity != currentComplexity)
+ this._maximumComplexity = Math.floor(Utilities.lerp(Utilities.progressValue(this.frameLengthTierThreshold, this._lastTierFrameLength, currentFrameLength), this._lastTierComplexity, currentComplexity));
+ else {
+ // If the browser is capable of handling the most complex version of the test, use that
+ this._maximumComplexity = currentComplexity;
+ }
+ this._possibleMaximumComplexity = this._maximumComplexity;
+
+ // If we get ourselves onto a ramp where the maximum complexity does not yield slow enough FPS,
+ // We'll use this as a boundary to find a higher maximum complexity for the next ramp
+ this._lastTierComplexity = currentComplexity;
+ this._lastTierFrameLength = currentFrameLength;
+
+ // First ramp
+ stage.tune(this._maximumComplexity - currentComplexity);
+ this._rampDidWarmup = false;
+ // Start timestamp represents start of ramp iteration and warm up
+ this._rampStartTimestamp = timestamp;
+ return;
+ }
+
+ if ((timestamp - this._rampStartTimestamp) < this.rampWarmupLength)
+ return;
+
+ if (this._rampDidWarmup)
+ return;
+
+ this._rampDidWarmup = true;
+ this._currentRampLength = this._rampStartTimestamp + this._rampLength - timestamp;
+ // Start timestamp represents start of ramp down, after warm up
+ this._rampStartTimestamp = timestamp;
+ this._rampStartIndex = this._sampler.sampleCount;
+ },
+
+ tune: function(timestamp, stage, lastFrameLength, didFinishInterval, intervalAverageFrameLength)
+ {
+ if (!this._rampDidWarmup)
+ return;
+
+ this._intervalFrameLengthEstimator.sample(lastFrameLength);
+ if (!didFinishInterval)
+ return;
+
+ var currentComplexity = stage.complexity();
+ var intervalFrameLengthMean = this._intervalFrameLengthEstimator.mean();
+ var intervalFrameLengthStandardDeviation = this._intervalFrameLengthEstimator.standardDeviation();
+
+ if (intervalFrameLengthMean < this.frameLengthDesiredThreshold && this._intervalFrameLengthEstimator.cdf(this.frameLengthDesiredThreshold) > .9) {
+ this._possibleMinimumComplexity = Math.max(this._possibleMinimumComplexity, currentComplexity);
+ } else if (intervalFrameLengthStandardDeviation > 2) {
+ // In the case where we might have found a previous interval where 60fps was reached. We hit a significant blip,
+ // so we should resample this area in the next ramp.
+ this._possibleMinimumComplexity = 1;
+ }
+ if (intervalFrameLengthMean - intervalFrameLengthStandardDeviation > this.frameLengthRampLowerThreshold)
+ this._possibleMaximumComplexity = Math.min(this._possibleMaximumComplexity, currentComplexity);
+ this._intervalFrameLengthEstimator.reset();
+
+ var progress = (timestamp - this._rampStartTimestamp) / this._currentRampLength;
+
+ if (progress < 1) {
+ // Reframe progress percentage so that the last interval of the ramp can sample at minimum complexity
+ progress = (timestamp - this._rampStartTimestamp) / (this._currentRampLength - this.intervalSamplingLength);
+ stage.tune(Math.max(this._minimumComplexity, Math.floor(Utilities.lerp(progress, this._maximumComplexity, this._minimumComplexity))) - currentComplexity);
+ return;
+ }
+
+ var regression = new Regression(this._sampler.samples, this._getComplexity, this._getFrameLength,
+ this._sampler.sampleCount - 1, this._rampStartIndex, { desiredFrameLength: this.frameLengthDesired });
+ this._rampRegressions.push(regression);
+
+ var frameLengthAtMaxComplexity = regression.valueAt(this._maximumComplexity);
+ if (frameLengthAtMaxComplexity < this.frameLengthRampLowerThreshold)
+ this._possibleMaximumComplexity = Math.floor(Utilities.lerp(Utilities.progressValue(this.frameLengthRampLowerThreshold, frameLengthAtMaxComplexity, this._lastTierFrameLength), this._maximumComplexity, this._lastTierComplexity));
+ // If the regression doesn't fit the first segment at all, keep the minimum bound at 1
+ if ((timestamp - this._sampler.samples[0][this._sampler.sampleCount - regression.n1]) / this._currentRampLength < .25)
+ this._possibleMinimumComplexity = 1;
+
+ this._minimumComplexityEstimator.sample(this._possibleMinimumComplexity);
+ this._minimumComplexity = Math.round(this._minimumComplexityEstimator.mean());
+
+ if (frameLengthAtMaxComplexity < this.frameLengthRampUpperThreshold) {
+ this._changePointEstimator.sample(regression.complexity);
+ // Ideally we'll target the change point in the middle of the ramp. If the range of the ramp is too small, there isn't enough
+ // range along the complexity (x) axis for a good regression calculation to be made, so force at least a range of 5
+ // particles. Make it possible to increase the maximum complexity in case unexpected noise caps the regression too low.
+ this._maximumComplexity = Math.round(this._minimumComplexity +
+ Math.max(5,
+ this._possibleMaximumComplexity - this._minimumComplexity,
+ (this._changePointEstimator.mean() - this._minimumComplexity) * 2));
+ } else {
+ // The slowest samples weighed the regression too heavily
+ this._maximumComplexity = Math.max(Math.round(.8 * this._maximumComplexity), this._minimumComplexity + 5);
+ }
+
+ // Next ramp
+ stage.tune(this._maximumComplexity - stage.complexity());
+ this._rampDidWarmup = false;
+ // Start timestamp represents start of ramp iteration and warm up
+ this._rampStartTimestamp = timestamp;
+ this._possibleMinimumComplexity = 1;
+ this._possibleMaximumComplexity = this._maximumComplexity;
+ },
+
+ _getComplexity: function(samples, i) {
+ return samples[1][i];
+ },
+
+ _getFrameLength: function(samples, i) {
+ return samples[0][i] - samples[0][i - 1];
+ },
+
+ processSamples: function(results)
+ {
+ Controller.prototype.processSamples.call(this, results);
+
+ // Have samplingTimeOffset represent time 0
+ var startTimestamp = this._marks[Strings.json.samplingStartTimeOffset].time;
+
+ for (var markName in results[Strings.json.marks]) {
+ results[Strings.json.marks][markName].time -= startTimestamp;
+ }
+
+ var controllerSamples = results[Strings.json.samples][Strings.json.controller];
+ controllerSamples.forEach(function(timeSample) {
+ controllerSamples.setFieldInDatum(timeSample, Strings.json.time, controllerSamples.getFieldInDatum(timeSample, Strings.json.time) - startTimestamp);
+ });
+
+ // Aggregate all of the ramps into one big complexity-frameLength dataset
+ var complexitySamples = new SampleData(controllerSamples.fieldMap);
+ results[Strings.json.samples][Strings.json.complexity] = complexitySamples;
+
+ results[Strings.json.controller] = [];
+ this._rampRegressions.forEach(function(ramp) {
+ var startIndex = ramp.startIndex, endIndex = ramp.endIndex;
+ var startTime = controllerSamples.getFieldInDatum(startIndex, Strings.json.time);
+ var endTime = controllerSamples.getFieldInDatum(endIndex, Strings.json.time);
+ var startComplexity = controllerSamples.getFieldInDatum(startIndex, Strings.json.complexity);
+ var endComplexity = controllerSamples.getFieldInDatum(endIndex, Strings.json.complexity);
+
+ var regression = {};
+ results[Strings.json.controller].push(regression);
+
+ var percentage = (ramp.complexity - startComplexity) / (endComplexity - startComplexity);
+ var inflectionTime = startTime + percentage * (endTime - startTime);
+
+ regression[Strings.json.regressions.segment1] = [
+ [startTime, ramp.s2 + ramp.t2 * startComplexity],
+ [inflectionTime, ramp.s2 + ramp.t2 * ramp.complexity]
+ ];
+ regression[Strings.json.regressions.segment2] = [
+ [inflectionTime, ramp.s1 + ramp.t1 * ramp.complexity],
+ [endTime, ramp.s1 + ramp.t1 * endComplexity]
+ ];
+ regression[Strings.json.complexity] = ramp.complexity;
+ regression[Strings.json.regressions.startIndex] = startIndex;
+ regression[Strings.json.regressions.endIndex] = endIndex;
+ regression[Strings.json.regressions.profile] = ramp.profile;
+
+ for (var j = startIndex; j <= endIndex; ++j)
+ complexitySamples.push(controllerSamples.at(j));
+ });
+
+ var complexityAverageSamples = new SampleData;
+ results[Strings.json.samples][Strings.json.complexityAverage] = complexityAverageSamples;
+ this._processComplexitySamples(complexitySamples, complexityAverageSamples);
+ }
+});
+
+Ramp30Controller = Utilities.createSubclass(RampController,
+ function(benchmark, options)
+ {
+ RampController.call(this, benchmark, options);
+ }, {
+
+ frameLengthDesired: 1000/30,
+ frameLengthDesiredThreshold: 1000/29,
+ frameLengthTierThreshold: 1000/20,
+ frameLengthRampLowerThreshold: 1000/20,
+ frameLengthRampUpperThreshold: 1000/12
+});
+
+Stage = Utilities.createClass(
+ function()
+ {
+ }, {
+
+ initialize: function(benchmark)
+ {
+ this._benchmark = benchmark;
+ this._element = document.getElementById("stage");
+ this._element.setAttribute("width", document.body.offsetWidth);
+ this._element.setAttribute("height", document.body.offsetHeight);
+ this._size = Point.elementClientSize(this._element).subtract(Insets.elementPadding(this._element).size);
+ },
+
+ get element()
+ {
+ return this._element;
+ },
+
+ get size()
+ {
+ return this._size;
+ },
+
+ complexity: function()
+ {
+ return 0;
+ },
+
+ tune: function()
+ {
+ throw "Not implemented";
+ },
+
+ animate: function()
+ {
+ throw "Not implemented";
+ },
+
+ clear: function()
+ {
+ return this.tune(-this.tune(0));
+ }
+});
+
+Utilities.extendObject(Stage, {
+ random: function(min, max)
+ {
+ return (Pseudo.random() * (max - min)) + min;
+ },
+
+ randomBool: function()
+ {
+ return !!Math.round(Pseudo.random());
+ },
+
+ randomSign: function()
+ {
+ return Pseudo.random() >= .5 ? 1 : -1;
+ },
+
+ randomInt: function(min, max)
+ {
+ return Math.floor(this.random(min, max + 1));
+ },
+
+ randomPosition: function(maxPosition)
+ {
+ return new Point(this.randomInt(0, maxPosition.x), this.randomInt(0, maxPosition.y));
+ },
+
+ randomSquareSize: function(min, max)
+ {
+ var side = this.random(min, max);
+ return new Point(side, side);
+ },
+
+ randomVelocity: function(maxVelocity)
+ {
+ return this.random(maxVelocity / 8, maxVelocity);
+ },
+
+ randomAngle: function()
+ {
+ return this.random(0, Math.PI * 2);
+ },
+
+ randomColor: function()
+ {
+ var min = 32;
+ var max = 256 - 32;
+ return "#"
+ + this.randomInt(min, max).toString(16)
+ + this.randomInt(min, max).toString(16)
+ + this.randomInt(min, max).toString(16);
+ },
+
+ randomStyleMixBlendMode: function()
+ {
+ var mixBlendModeList = [
+ 'normal',
+ 'multiply',
+ 'screen',
+ 'overlay',
+ 'darken',
+ 'lighten',
+ 'color-dodge',
+ 'color-burn',
+ 'hard-light',
+ 'soft-light',
+ 'difference',
+ 'exclusion',
+ 'hue',
+ 'saturation',
+ 'color',
+ 'luminosity'
+ ];
+
+ return mixBlendModeList[this.randomInt(0, mixBlendModeList.length)];
+ },
+
+ randomStyleFilter: function()
+ {
+ var filterList = [
+ 'grayscale(50%)',
+ 'sepia(50%)',
+ 'saturate(50%)',
+ 'hue-rotate(180)',
+ 'invert(50%)',
+ 'opacity(50%)',
+ 'brightness(50%)',
+ 'contrast(50%)',
+ 'blur(10px)',
+ 'drop-shadow(10px 10px 10px gray)'
+ ];
+
+ return filterList[this.randomInt(0, filterList.length)];
+ },
+
+ randomElementInArray: function(array)
+ {
+ return array[Stage.randomInt(0, array.length - 1)];
+ },
+
+ rotatingColor: function(cycleLengthMs, saturation, lightness)
+ {
+ return "hsl("
+ + Stage.dateFractionalValue(cycleLengthMs) * 360 + ", "
+ + ((saturation || .8) * 100).toFixed(0) + "%, "
+ + ((lightness || .35) * 100).toFixed(0) + "%)";
+ },
+
+ // Returns a fractional value that wraps around within [0,1]
+ dateFractionalValue: function(cycleLengthMs)
+ {
+ return (Date.now() / (cycleLengthMs || 2000)) % 1;
+ },
+
+ // Returns an increasing value slowed down by factor
+ dateCounterValue: function(factor)
+ {
+ return Date.now() / factor;
+ },
+
+ randomRotater: function()
+ {
+ return new Rotater(this.random(1000, 10000));
+ }
+});
+
+Rotater = Utilities.createClass(
+ function(rotateInterval)
+ {
+ this._timeDelta = 0;
+ this._rotateInterval = rotateInterval;
+ this._isSampling = false;
+ }, {
+
+ get interval()
+ {
+ return this._rotateInterval;
+ },
+
+ next: function(timeDelta)
+ {
+ this._timeDelta = (this._timeDelta + timeDelta) % this._rotateInterval;
+ },
+
+ degree: function()
+ {
+ return (360 * this._timeDelta) / this._rotateInterval;
+ },
+
+ rotateZ: function()
+ {
+ return "rotateZ(" + Math.floor(this.degree()) + "deg)";
+ },
+
+ rotate: function(center)
+ {
+ return "rotate(" + Math.floor(this.degree()) + ", " + center.x + "," + center.y + ")";
+ }
+});
+
+Benchmark = Utilities.createClass(
+ function(stage, options)
+ {
+ this._animateLoop = this._animateLoop.bind(this);
+
+ this._stage = stage;
+ this._stage.initialize(this, options);
+
+ switch (options["time-measurement"])
+ {
+ case "performance":
+ if (window.performance && window.performance.now)
+ this._getTimestamp = performance.now.bind(performance);
+ else
+ this._getTimestamp = null;
+ break;
+ case "raf":
+ this._getTimestamp = null;
+ break;
+ case "date":
+ this._getTimestamp = Date.now;
+ break;
+ }
+
+ options["test-interval"] *= 1000;
+ switch (options["controller"])
+ {
+ case "fixed":
+ this._controller = new FixedController(this, options);
+ break;
+ case "step":
+ this._controller = new StepController(this, options);
+ break;
+ case "adaptive":
+ this._controller = new AdaptiveController(this, options);
+ break;
+ case "ramp":
+ this._controller = new RampController(this, options);
+ break;
+ case "ramp30":
+ this._controller = new Ramp30Controller(this, options);
+ }
+ }, {
+
+ get stage()
+ {
+ return this._stage;
+ },
+
+ get timestamp()
+ {
+ return this._currentTimestamp - this._startTimestamp;
+ },
+
+ backgroundColor: function()
+ {
+ var stage = window.getComputedStyle(document.getElementById("stage"));
+ return stage["background-color"];
+ },
+
+ run: function()
+ {
+ return this.waitUntilReady().then(function() {
+ this._finishPromise = new SimplePromise;
+ this._previousTimestamp = undefined;
+ this._didWarmUp = false;
+ this._stage.tune(this._controller.initialComplexity - this._stage.complexity());
+ this._animateLoop();
+ return this._finishPromise;
+ }.bind(this));
+ },
+
+ // Subclasses should override this if they have setup to do prior to commencing.
+ waitUntilReady: function()
+ {
+ var promise = new SimplePromise;
+ promise.resolve();
+ return promise;
+ },
+
+ _animateLoop: function(timestamp)
+ {
+ timestamp = (this._getTimestamp && this._getTimestamp()) || timestamp;
+ this._currentTimestamp = timestamp;
+
+ if (this._controller.shouldStop(timestamp)) {
+ this._finishPromise.resolve(this._controller.results());
+ return;
+ }
+
+ if (!this._didWarmUp) {
+ if (!this._previousTimestamp)
+ this._previousTimestamp = timestamp;
+ else if (timestamp - this._previousTimestamp >= 100) {
+ this._didWarmUp = true;
+ this._startTimestamp = timestamp;
+ this._controller.start(timestamp, this._stage);
+ this._previousTimestamp = timestamp;
+ }
+
+ this._stage.animate(0);
+ requestAnimationFrame(this._animateLoop);
+ return;
+ }
+
+ this._controller.update(timestamp, this._stage);
+ this._stage.animate(timestamp - this._previousTimestamp);
+ this._previousTimestamp = timestamp;
+ requestAnimationFrame(this._animateLoop);
+ }
+});
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/resources/math.js b/third_party/webkit/PerformanceTests/MotionMark/tests/resources/math.js
new file mode 100644
index 0000000000..9c2706e2a3
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/resources/math.js
@@ -0,0 +1,268 @@
+SimpleKalmanEstimator = Utilities.createSubclass(Experiment,
+ function(processError, measurementError) {
+ Experiment.call(this, false);
+ var error = .5 * (Math.sqrt(processError * processError + 4 * processError * measurementError) - processError);
+ this._gain = error / (error + measurementError);
+ }, {
+
+ sample: function(newMeasurement)
+ {
+ if (!this._initialized) {
+ this._initialized = true;
+ this.estimate = newMeasurement;
+ return;
+ }
+
+ this.estimate = this.estimate + this._gain * (newMeasurement - this.estimate);
+ },
+
+ reset: function()
+ {
+ Experiment.prototype.reset.call(this);
+ this._initialized = false;
+ this.estimate = 0;
+ }
+});
+
+PIDController = Utilities.createClass(
+ function(ysp)
+ {
+ this._ysp = ysp;
+ this._out = 0;
+
+ this._Kp = 0;
+ this._stage = PIDController.stages.WARMING;
+
+ this._eold = 0;
+ this._I = 0;
+ }, {
+
+ // Determines whether the current y is
+ // before ysp => (below ysp if ysp > y0) || (above ysp if ysp < y0)
+ // after ysp => (above ysp if ysp > y0) || (below ysp if ysp < y0)
+ _yPosition: function(y)
+ {
+ return (y < this._ysp) == (this._y0 < this._ysp)
+ ? PIDController.yPositions.BEFORE_SETPOINT
+ : PIDController.yPositions.AFTER_SETPOINT;
+ },
+
+ // Calculate the ultimate distance from y0 after time t. We want to move very
+ // slowly at the beginning to see how adding few items to the test can affect
+ // its output. The complexity of a single item might be big enough to keep the
+ // proportional gain very small but achieves the desired progress. But if y does
+ // not change significantly after adding few items, that means we need a much
+ // bigger gain. So we need to move over a cubic curve which increases very
+ // slowly with small t values but moves very fast with larger t values.
+ // The basic formula is: y = t^3
+ // Change the formula to reach y=1 after 1000 ms: y = (t/1000)^3
+ // Change the formula to reach y=(ysp - y0) after 1000 ms: y = (ysp - y0) * (t/1000)^3
+ _distanceUltimate: function(t)
+ {
+ return (this._ysp - this._y0) * Math.pow(t / 1000, 3);
+ },
+
+ // Calculates the distance of y relative to y0. It also ensures we do not return
+ // zero by returning a epsilon value in the same direction as ultimate distance.
+ _distance: function(y, du)
+ {
+ const epsilon = 0.0001;
+ var d = y - this._y0;
+ return du < 0 ? Math.min(d, -epsilon) : Math.max(d, epsilon);
+ },
+
+ // Decides how much the proportional gain should be increased during the manual
+ // gain stage. We choose to use the ratio of the ultimate distance to the current
+ // distance as an indication of how much the system is responsive. We want
+ // to keep the increment under control so it does not cause the system instability
+ // So we choose to take the natural logarithm of this ratio.
+ _gainIncrement: function(t, y, e)
+ {
+ var du = this._distanceUltimate(t);
+ var d = this._distance(y, du);
+ return Math.log(du / d) * 0.1;
+ },
+
+ // Update the stage of the controller based on its current stage and the system output
+ _updateStage: function(y)
+ {
+ var yPosition = this._yPosition(y);
+
+ switch (this._stage) {
+ case PIDController.stages.WARMING:
+ if (yPosition == PIDController.yPositions.AFTER_SETPOINT)
+ this._stage = PIDController.stages.OVERSHOOT;
+ break;
+
+ case PIDController.stages.OVERSHOOT:
+ if (yPosition == PIDController.yPositions.BEFORE_SETPOINT)
+ this._stage = PIDController.stages.UNDERSHOOT;
+ break;
+
+ case PIDController.stages.UNDERSHOOT:
+ if (yPosition == PIDController.yPositions.AFTER_SETPOINT)
+ this._stage = PIDController.stages.SATURATE;
+ break;
+ }
+ },
+
+ // Manual tuning is used before calculating the PID controller gains.
+ _tuneP: function(e)
+ {
+ // The output is the proportional term only.
+ return this._Kp * e;
+ },
+
+ // PID tuning function. Kp, Ti and Td were already calculated
+ _tunePID: function(h, y, e)
+ {
+ // Proportional term.
+ var P = this._Kp * e;
+
+ // Integral term is the area under the curve starting from the beginning
+ // till the current time.
+ this._I += (this._Kp / this._Ti) * ((e + this._eold) / 2) * h;
+
+ // Derivative term is the slope of the curve at the current time.
+ var D = (this._Kp * this._Td) * (e - this._eold) / h;
+
+ // The ouput is a PID function.
+ return P + this._I + D;
+ },
+
+ // Apply different strategies for the tuning based on the stage of the controller.
+ _tune: function(t, h, y, e)
+ {
+ switch (this._stage) {
+ case PIDController.stages.WARMING:
+ // This is the first stage of the Zieglerâ€Nichols method. It increments
+ // the proportional gain till the system output passes the set-point value.
+ if (typeof this._y0 == "undefined") {
+ // This is the first time a tuning value is required. We want the test
+ // to add only one item. So we need to return -1 which forces us to
+ // choose the initial value of Kp to be = -1 / e
+ this._y0 = y;
+ this._Kp = -1 / e;
+ } else {
+ // Keep incrementing the Kp as long as we have not reached the
+ // set-point yet
+ this._Kp += this._gainIncrement(t, y, e);
+ }
+
+ return this._tuneP(e);
+
+ case PIDController.stages.OVERSHOOT:
+ // This is the second stage of the Zieglerâ€Nichols method. It measures the
+ // oscillation period.
+ if (typeof this._t0 == "undefined") {
+ // t is the time of the begining of the first overshot
+ this._t0 = t;
+ this._Kp /= 2;
+ }
+
+ return this._tuneP(e);
+
+ case PIDController.stages.UNDERSHOOT:
+ // This is the end of the Zieglerâ€Nichols method. We need to calculate the
+ // integral and derivative periods.
+ if (typeof this._Ti == "undefined") {
+ // t is the time of the end of the first overshot
+ var Tu = t - this._t0;
+
+ // Calculate the system parameters from Kp and Tu assuming
+ // a "some overshoot" control type. See:
+ // https://en.wikipedia.org/wiki/Ziegler%E2%80%93Nichols_method
+ this._Ti = Tu / 2;
+ this._Td = Tu / 3;
+ this._Kp = 0.33 * this._Kp;
+
+ // Calculate the tracking time.
+ this._Tt = Math.sqrt(this._Ti * this._Td);
+ }
+
+ return this._tunePID(h, y, e);
+
+ case PIDController.stages.SATURATE:
+ return this._tunePID(h, y, e);
+ }
+
+ return 0;
+ },
+
+ // Ensures the system does not fluctuates.
+ _saturate: function(v, e)
+ {
+ var u = v;
+
+ switch (this._stage) {
+ case PIDController.stages.OVERSHOOT:
+ case PIDController.stages.UNDERSHOOT:
+ // Calculate the min-max values of the saturation actuator.
+ if (typeof this._min == "undefined")
+ this._min = this._max = this._out;
+ else {
+ this._min = Math.min(this._min, this._out);
+ this._max = Math.max(this._max, this._out);
+ }
+ break;
+
+ case PIDController.stages.SATURATE:
+ const limitPercentage = 0.90;
+ var min = this._min > 0 ? Math.min(this._min, this._max * limitPercentage) : this._min;
+ var max = this._max < 0 ? Math.max(this._max, this._min * limitPercentage) : this._max;
+ var out = this._out + u;
+
+ // Clip the controller output to the min-max values
+ out = Math.max(Math.min(max, out), min);
+ u = out - this._out;
+
+ // Apply the back-calculation and tracking
+ if (u != v)
+ u += (this._Kp * this._Tt / this._Ti) * e;
+ break;
+ }
+
+ this._out += u;
+ return u;
+ },
+
+ // Called from the benchmark to tune its test. It uses Ziegler-Nichols method
+ // to calculate the controller parameters. It then returns a PID tuning value.
+ tune: function(t, h, y)
+ {
+ this._updateStage(y);
+
+ // Current error.
+ var e = this._ysp - y;
+ var v = this._tune(t, h, y, e);
+
+ // Save e for the next call.
+ this._eold = e;
+
+ // Apply back-calculation and tracking to avoid integrator windup
+ return this._saturate(v, e);
+ }
+});
+
+Utilities.extendObject(PIDController, {
+ // This enum will be used to tell whether the system output (or the controller input)
+ // is moving towards the set-point or away from it.
+ yPositions: {
+ BEFORE_SETPOINT: 0,
+ AFTER_SETPOINT: 1
+ },
+
+ // The Ziegler-Nichols method for is used tuning the PID controller. The workflow of
+ // the tuning is split into four stages. The first two stages determine the values
+ // of the PID controller gains. During these two stages we return the proportional
+ // term only. The third stage is used to determine the min-max values of the
+ // saturation actuator. In the last stage back-calculation and tracking are applied
+ // to avoid integrator windup. During the last two stages, we return a PID control
+ // value.
+ stages: {
+ WARMING: 0, // Increase the value of the Kp until the system output reaches ysp.
+ OVERSHOOT: 1, // Measure the oscillation period and the overshoot value
+ UNDERSHOOT: 2, // Return PID value and measure the undershoot value
+ SATURATE: 3 // Return PID value and apply back-calculation and tracking.
+ }
+});
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/resources/stage.css b/third_party/webkit/PerformanceTests/MotionMark/tests/resources/stage.css
new file mode 100644
index 0000000000..0b6ffdc4a2
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/resources/stage.css
@@ -0,0 +1,27 @@
+html {
+ height: 100%;
+}
+body {
+ width: 100%;
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ background-color: rgb(241, 241, 241);
+ font-family: "Helvetica Neue", Helvetica, Verdana, sans-serif;
+}
+
+#stage {
+ position: relative;
+ width: 100%;
+ height: 100%;
+ background-color: rgb(241, 241, 241);
+ overflow: hidden;
+}
+
+#center-text {
+ position: absolute;
+ z-index: 3;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+}
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/resources/star.svg b/third_party/webkit/PerformanceTests/MotionMark/tests/resources/star.svg
new file mode 100644
index 0000000000..3c46ae0419
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/resources/star.svg
@@ -0,0 +1,8 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1 1">
+ <defs>
+ <mask id="star-mask" maskUnits="objectBoundingBox" maskContentUnits="objectBoundingBox">
+ <path fill="white" d="M.50,0L.38,.38L0,.38L.30,.60L.18,1L.50,.75L.82,1L.70,.60L1,.38L.62,.38z" />
+ </mask>
+ </defs>
+ <path d="M.50,0L.38,.38L0,.38L.30,.60L.18,1L.50,.75L.82,1L.70,.60L1,.38L.62,.38z" fill="white" />
+</svg>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/resources/yin-yang.png b/third_party/webkit/PerformanceTests/MotionMark/tests/resources/yin-yang.png
new file mode 100644
index 0000000000..3162f6ec00
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/resources/yin-yang.png
Binary files differ
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/resources/yin-yang.svg b/third_party/webkit/PerformanceTests/MotionMark/tests/resources/yin-yang.svg
new file mode 100644
index 0000000000..4412626774
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/resources/yin-yang.svg
@@ -0,0 +1,17 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 200 200">
+ <defs>
+ <clipPath id="left-half">
+ <rect width="100" height="200"/>
+ </clipPath>
+ <clipPath id="right-half">
+ <rect x="100" width="100" height="200"/>
+ </clipPath>
+ </defs>
+ <circle cx="100" cy="100" r="98" fill="none" stroke="green" stroke-width="2"/>
+ <circle cx="100" cy="100" r="98" fill="white" clip-path="url(#left-half)"/>
+ <circle cx="100" cy="100" r="98" fill="green" clip-path="url(#right-half)"/>
+ <circle cx="100" cy="50" r="49" fill="green"/>
+ <circle cx="100" cy="148" r="49" fill="white"/>
+ <circle cx="100" cy="50" r="10" fill="white"/>
+ <circle cx="100" cy="148" r="10" fill="green"/>
+</svg>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/simple/resources/simple-canvas-paths.js b/third_party/webkit/PerformanceTests/MotionMark/tests/simple/resources/simple-canvas-paths.js
new file mode 100644
index 0000000000..cda985b221
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/simple/resources/simple-canvas-paths.js
@@ -0,0 +1,453 @@
+(function() {
+
+// === PAINT OBJECTS ===
+
+CanvasLineSegment = Utilities.createClass(
+ function(stage) {
+ var radius = Stage.randomInt(10, 100);
+ var center = Stage.randomPosition(stage.size);
+ var delta = Point.pointOnCircle(Stage.randomAngle(), radius/2);
+
+ this._point1 = center.add(delta);
+ this._point2 = center.subtract(delta);
+ this._color = Stage.randomColor();
+ this._lineWidth = Stage.randomInt(1, 100);
+ }, {
+
+ draw: function(context) {
+ context.strokeStyle = this._color;
+ context.lineWidth = this._lineWidth;
+ context.beginPath();
+ context.moveTo(this._point1.x, this._point1.y);
+ context.lineTo(this._point2.x, this._point2.y);
+ context.stroke();
+ }
+});
+
+CanvasLinePoint = Utilities.createClass(
+ function(stage, coordinateMaximumFactor) {
+ var pointMaximum = new Point(Math.min(stage.size.x, coordinateMaximumFactor * stage.size.x), Math.min(stage.size.y, coordinateMaximumFactor * stage.size.y));
+ this._point = Stage.randomPosition(pointMaximum).add(new Point((stage.size.x - pointMaximum.x) / 2, (stage.size.y - pointMaximum.y) / 2));
+ }, {
+
+ draw: function(context) {
+ context.lineTo(this._point.x, this._point.y);
+ }
+})
+
+CanvasQuadraticSegment = Utilities.createClass(
+ function(stage) {
+ var maxSize = Stage.randomInt(20, 200);
+ var toCenter = Stage.randomPosition(stage.size).subtract(new Point(maxSize/2, maxSize/2));
+
+ this._point1 = Stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter);
+ this._point2 = Stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter);
+ this._point3 = Stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter);
+ this._color = Stage.randomColor();
+ this._lineWidth = Stage.randomInt(1, 50);
+ }, {
+
+ draw: function(context) {
+ context.strokeStyle = this._color;
+ context.lineWidth = this._lineWidth;
+ context.beginPath();
+ context.moveTo(this._point1.x, this._point1.y);
+ context.quadraticCurveTo(this._point2.x, this._point2.y, this._point3.x, this._point3.y);
+ context.stroke();
+ }
+});
+
+CanvasQuadraticPoint = Utilities.createClass(
+ function(stage, coordinateMaximumFactor) {
+ var pointMaximum = Stage.randomPosition(new Point(Math.min(stage.size.x, coordinateMaximumFactor * stage.size.x), Math.min(stage.size.y, coordinateMaximumFactor * stage.size.y)));
+ this._point1 = Stage.randomPosition(pointMaximum).add(new Point((stage.size.x - pointMaximum.x) / 2, (stage.size.y - pointMaximum.y) / 2));
+ this._point2 = Stage.randomPosition(pointMaximum).add(new Point((stage.size.x - pointMaximum.x) / 2, (stage.size.y - pointMaximum.y) / 2));
+ }, {
+
+ draw: function(context) {
+ context.quadraticCurveTo(this._point1.x, this._point1.y, this._point2.x, this._point2.y);
+ }
+});
+
+CanvasBezierSegment = Utilities.createClass(
+ function(stage) {
+ var maxSize = Stage.randomInt(20, 200);
+ var toCenter = Stage.randomPosition(stage.size).subtract(new Point(maxSize/2, maxSize/2));
+
+ this._point1 = Stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter);
+ this._point2 = Stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter);
+ this._point3 = Stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter);
+ this._point4 = Stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter);
+ this._color = Stage.randomColor();
+ this._lineWidth = Stage.randomInt(1, 50);
+ }, {
+
+ draw: function(context) {
+ context.strokeStyle = this._color;
+ context.lineWidth = this._lineWidth;
+ context.beginPath();
+ context.moveTo(this._point1.x, this._point1.y);
+ context.bezierCurveTo(this._point2.x, this._point2.y, this._point3.x, this._point3.y, this._point4.x, this._point4.y);
+ context.stroke();
+ }
+});
+
+CanvasBezierPoint = Utilities.createClass(
+ function(stage, coordinateMaximumFactor) {
+ var pointMaximum = Stage.randomPosition(new Point(Math.min(stage.size.x, coordinateMaximumFactor * stage.size.x), Math.min(stage.size.y, coordinateMaximumFactor * stage.size.y)));
+ this._point1 = Stage.randomPosition(pointMaximum).add(new Point((stage.size.x - pointMaximum.x) / 2, (stage.size.y - pointMaximum.y) / 2));
+ this._point2 = Stage.randomPosition(pointMaximum).add(new Point((stage.size.x - pointMaximum.x) / 2, (stage.size.y - pointMaximum.y) / 2));
+ this._point3 = Stage.randomPosition(pointMaximum).add(new Point((stage.size.x - pointMaximum.x) / 2, (stage.size.y - pointMaximum.y) / 2));
+ }, {
+
+ draw: function(context) {
+ context.bezierCurveTo(this._point1.x, this._point1.y, this._point2.x, this._point2.y, this._point3.x, this._point3.y);
+ }
+});
+
+CanvasArcToSegment = Utilities.createClass(
+ function(stage) {
+ var maxSize = Stage.randomInt(20, 200);
+ var toCenter = Stage.randomPosition(stage.size).subtract(new Point(maxSize/2, maxSize/2));
+
+ this._point1 = Stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter);
+ this._point2 = Stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter);
+ this._point3 = Stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter);
+ this._radius = Stage.randomInt(20, 200);
+ this._color = Stage.randomColor();
+ this._lineWidth = Stage.randomInt(1, 50);
+ }, {
+
+ draw: function(context) {
+ context.strokeStyle = this._color;
+ context.lineWidth = this._lineWidth;
+ context.beginPath();
+ context.moveTo(this._point1.x, this._point1.y);
+ context.arcTo(this._point2.x, this._point2.y, this._point3.x, this._point3.y, this._radius);
+ context.stroke();
+ }
+});
+
+CanvasArcToSegmentFill = Utilities.createClass(
+ function(stage) {
+ CanvasArcToSegment.call(this, stage);
+ }, {
+
+ draw: function(context) {
+ context.fillStyle = this._color;
+ context.beginPath();
+ context.moveTo(this._point1.x, this._point1.y);
+ context.arcTo(this._point2.x, this._point2.y, this._point3.x, this._point3.y, this._radius);
+ context.fill();
+ }
+});
+
+CanvasArcSegment = Utilities.createClass(
+ function(stage) {
+ var maxSize = Stage.randomInt(20, 200);
+ var toCenter = Stage.randomPosition(stage.size).subtract(new Point(maxSize/2, maxSize/2));
+
+ this._point = Stage.randomPosition(new Point(maxSize, maxSize)).add(toCenter);
+ this._radius = Stage.randomInt(20, 200);
+ this._startAngle = Stage.randomAngle();
+ this._endAngle = Stage.randomAngle();
+ this._counterclockwise = Stage.randomBool();
+ this._color = Stage.randomColor();
+ this._lineWidth = Stage.randomInt(1, 50);
+ }, {
+
+ draw: function(context) {
+ context.strokeStyle = this._color;
+ context.lineWidth = this._lineWidth;
+ context.beginPath();
+ context.arc(this._point.x, this._point.y, this._radius, this._startAngle, this._endAngle, this._counterclockwise);
+ context.stroke();
+ }
+});
+
+CanvasArcSegmentFill = Utilities.createClass(
+ function(stage) {
+ CanvasArcSegment.call(this, stage);
+ }, {
+
+ draw: function(context) {
+ context.fillStyle = this._color;
+ context.beginPath();
+ context.arc(this._point.x, this._point.y, this._radius, this._startAngle, this._endAngle, this._counterclockwise);
+ context.fill();
+ }
+});
+
+CanvasRect = Utilities.createClass(
+ function(stage) {
+ this._width = Stage.randomInt(20, 200);
+ this._height = Stage.randomInt(20, 200);
+ this._point = Stage.randomPosition(stage.size).subtract(new Point(this._width/2, this._height/2));
+ this._color = Stage.randomColor();
+ this._lineWidth = Stage.randomInt(1, 20);
+ }, {
+
+ draw: function(context) {
+ context.strokeStyle = this._color;
+ context.lineWidth = this._lineWidth;
+ context.beginPath();
+ context.rect(this._point.x, this._point.y, this._width, this._height);
+ context.stroke();
+ }
+});
+
+CanvasRectFill = Utilities.createClass(
+ function(stage) {
+ CanvasRect.call(this, stage);
+ }, {
+
+ draw: function(context) {
+ context.fillStyle = this._color;
+ context.beginPath();
+ context.rect(this._point.x, this._point.y, this._width, this._height);
+ context.fill();
+ }
+});
+
+CanvasEllipse = Utilities.createClass(
+ function(stage) {
+ this._radius = new Point(Stage.randomInt(20, 200), Stage.randomInt(20, 200));
+ var toCenter = Stage.randomPosition(stage.size).subtract(this._radius.multiply(.5));
+
+ this._center = Stage.randomPosition(this._radius).add(toCenter);
+ this._rotation = Stage.randomAngle();
+ this._startAngle = Stage.randomAngle();
+ this._endAngle = Stage.randomAngle();
+ this._anticlockwise = Stage.randomBool();
+ this._color = Stage.randomColor();
+ this._lineWidth = Stage.randomInt(1, 20);
+ }, {
+
+ draw: function(context) {
+ context.strokeStyle = this._color;
+ context.lineWidth = this._lineWidth;
+ context.beginPath();
+ context.ellipse(this._center.x, this._center.y, this._radius.width, this._radius.height, this._rotation, this._startAngle, this._endAngle, this._anticlockwise);
+ context.stroke();
+ }
+});
+
+CanvasEllipseFill = Utilities.createClass(
+ function(stage) {
+ CanvasEllipse.call(this, stage);
+ }, {
+
+ draw: function(context) {
+ context.fillStyle = this._color;
+ context.beginPath();
+ context.ellipse(this._center.x, this._center.y, this._radius.width, this._radius.height, this._rotation, this._startAngle, this._endAngle, this._anticlockwise);
+ context.fill();
+ }
+});
+
+CanvasStroke = Utilities.createClass(
+ function (stage) {
+ this._object = new (Stage.randomElementInArray(this.objectTypes))(stage);
+ }, {
+
+ objectTypes: [
+ CanvasQuadraticSegment,
+ CanvasBezierSegment,
+ CanvasArcToSegment,
+ CanvasArcSegment,
+ CanvasRect,
+ CanvasEllipse
+ ],
+
+ draw: function(context) {
+ this._object.draw(context);
+ }
+});
+
+CanvasFill = Utilities.createClass(
+ function (stage) {
+ this._object = new (Stage.randomElementInArray(this.objectTypes))(stage);
+ }, {
+
+ objectTypes: [
+ CanvasArcToSegmentFill,
+ CanvasArcSegmentFill,
+ CanvasRectFill,
+ CanvasEllipseFill
+ ],
+
+ draw: function(context) {
+ this._object.draw(context);
+ }
+});
+
+// === STAGES ===
+
+SimpleCanvasPathStrokeStage = Utilities.createSubclass(SimpleCanvasStage,
+ function(canvasObject) {
+ SimpleCanvasStage.call(this, canvasObject);
+ }, {
+
+ animate: function()
+ {
+ var context = this.context;
+ context.clearRect(0, 0, this.size.x, this.size.y);
+ context.lineWidth = Stage.randomInt(1, 20);
+ context.strokeStyle = Stage.rotatingColor();
+ context.beginPath();
+ context.moveTo(this.size.x / 2, this.size.y / 2);
+ for (var i = 0, length = this.offsetIndex; i < length; ++i)
+ this.objects[i].draw(context);
+ context.stroke();
+ }
+});
+
+SimpleCanvasPathFillStage = Utilities.createSubclass(SimpleCanvasStage,
+ function(canvasObject) {
+ SimpleCanvasStage.call(this, canvasObject);
+ }, {
+
+ animate: function()
+ {
+ var context = this.context;
+ context.clearRect(0, 0, this.size.x, this.size.y);
+ context.fillStyle = Stage.rotatingColor();
+ context.beginPath();
+ context.moveTo(this.size.x / 2, this.size.y / 2);
+ for (var i = 0, length = this.offsetIndex; i < length; ++i)
+ this.objects[i].draw(context);
+ context.fill();
+ }
+});
+
+CanvasLineSegmentStage = Utilities.createSubclass(SimpleCanvasStage,
+ function()
+ {
+ SimpleCanvasStage.call(this, CanvasLineSegment);
+ }, {
+
+ initialize: function(benchmark, options)
+ {
+ SimpleCanvasStage.prototype.initialize.call(this, benchmark, options);
+ this.context.lineCap = options["lineCap"] || "butt";
+ }
+});
+
+CanvasLinePathStage = Utilities.createSubclass(SimpleCanvasPathStrokeStage,
+ function()
+ {
+ SimpleCanvasPathStrokeStage.call(this, CanvasLinePoint);
+ }, {
+
+ initialize: function(benchmark, options)
+ {
+ SimpleCanvasPathStrokeStage.prototype.initialize.call(this, benchmark, options);
+ this.context.lineJoin = options["lineJoin"] || "bevel";
+ }
+});
+
+CanvasLineDashStage = Utilities.createSubclass(SimpleCanvasStage,
+ function()
+ {
+ SimpleCanvasStage.call(this, CanvasLinePoint);
+ this._step = 0;
+ }, {
+
+ initialize: function(benchmark, options)
+ {
+ SimpleCanvasStage.prototype.initialize.call(this, benchmark, options);
+ this.context.setLineDash([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
+ this.context.lineWidth = 1;
+ this.context.strokeStyle = "#000";
+ },
+
+ animate: function()
+ {
+ var context = this.context;
+ context.clearRect(0, 0, this.size.x, this.size.y);
+ context.lineDashOffset = this._step++;
+ context.beginPath();
+ context.moveTo(this.size.x / 2, this.size.y / 2);
+ for (var i = 0, length = this.offsetIndex; i < length; ++i)
+ this.objects[i].draw(context);
+ context.stroke();
+ }
+});
+
+// === BENCHMARK ===
+
+CanvasPathBenchmark = Utilities.createSubclass(Benchmark,
+ function(options)
+ {
+ var stage;
+ switch (options["pathType"]) {
+ case "line":
+ stage = new CanvasLineSegmentStage();
+ break;
+ case "linePath": {
+ if ("lineJoin" in options)
+ stage = new CanvasLinePathStage();
+ if ("lineDash" in options)
+ stage = new CanvasLineDashStage();
+ break;
+ }
+ case "quadratic":
+ stage = new SimpleCanvasStage(CanvasQuadraticSegment);
+ break;
+ case "quadraticPath":
+ stage = new SimpleCanvasPathStrokeStage(CanvasQuadraticPoint);
+ break;
+ case "bezier":
+ stage = new SimpleCanvasStage(CanvasBezierSegment);
+ break;
+ case "bezierPath":
+ stage = new SimpleCanvasPathStrokeStage(CanvasBezierPoint);
+ break;
+ case "arcTo":
+ stage = new SimpleCanvasStage(CanvasArcToSegment);
+ break;
+ case "arc":
+ stage = new SimpleCanvasStage(CanvasArcSegment);
+ break;
+ case "rect":
+ stage = new SimpleCanvasStage(CanvasRect);
+ break;
+ case "ellipse":
+ stage = new SimpleCanvasStage(CanvasEllipse);
+ break;
+ case "lineFill":
+ stage = new SimpleCanvasPathFillStage(CanvasLinePoint);
+ break;
+ case "quadraticFill":
+ stage = new SimpleCanvasPathFillStage(CanvasQuadraticPoint);
+ break;
+ case "bezierFill":
+ stage = new SimpleCanvasPathFillStage(CanvasBezierPoint);
+ break;
+ case "arcToFill":
+ stage = new SimpleCanvasStage(CanvasArcToSegmentFill);
+ break;
+ case "arcFill":
+ stage = new SimpleCanvasStage(CanvasArcSegmentFill);
+ break;
+ case "rectFill":
+ stage = new SimpleCanvasStage(CanvasRectFill);
+ break;
+ case "ellipseFill":
+ stage = new SimpleCanvasStage(CanvasEllipseFill);
+ break;
+ case "strokes":
+ stage = new SimpleCanvasStage(CanvasStroke);
+ break;
+ case "fills":
+ stage = new SimpleCanvasStage(CanvasFill);
+ break;
+ }
+
+ Benchmark.call(this, stage, options);
+ }
+);
+
+window.benchmarkClass = CanvasPathBenchmark;
+
+})(); \ No newline at end of file
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/simple/resources/simple-canvas.js b/third_party/webkit/PerformanceTests/MotionMark/tests/simple/resources/simple-canvas.js
new file mode 100644
index 0000000000..483d535d75
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/simple/resources/simple-canvas.js
@@ -0,0 +1,35 @@
+Utilities.extendObject(SimpleCanvasStage.prototype, {
+ tune: function(count)
+ {
+ if (count == 0)
+ return;
+
+ if (count < 0) {
+ this.offsetIndex = Math.max(this.offsetIndex + count, 0);
+ return;
+ }
+
+ this.offsetIndex = this.offsetIndex + count;
+ if (this.offsetIndex > this.objects.length) {
+ // For some tests, it may be easier to see how well the test is going
+ // by limiting the range of coordinates in which new objects can reside
+ var coordinateMaximumFactor = Math.min(this.objects.length, Math.min(this.size.x, this.size.y)) / Math.min(this.size.x, this.size.y);
+ var newIndex = this.offsetIndex - this.objects.length;
+ for (var i = 0; i < newIndex; ++i)
+ this.objects.push(new this._canvasObject(this, coordinateMaximumFactor));
+ }
+ },
+
+ animate: function()
+ {
+ var context = this.context;
+ context.clearRect(0, 0, this.size.x, this.size.y);
+ for (var i = 0, length = this.offsetIndex; i < length; ++i)
+ this.objects[i].draw(context);
+ },
+
+ complexity: function()
+ {
+ return this.offsetIndex;
+ }
+});
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/simple/resources/tiled-canvas-image.js b/third_party/webkit/PerformanceTests/MotionMark/tests/simple/resources/tiled-canvas-image.js
new file mode 100644
index 0000000000..f5d02b68a4
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/simple/resources/tiled-canvas-image.js
@@ -0,0 +1,119 @@
+(function() {
+
+CanvasImageTile = Utilities.createClass(
+ function(stage, source)
+ {
+ this._context = stage.context;
+ this._size = stage.tileSize;
+ this.source = source;
+ }, {
+
+ getImageData: function()
+ {
+ this._imagedata = this._context.getImageData(this.source.x, this.source.y, this._size.width, this._size.height);
+ },
+
+ putImageData: function(destination)
+ {
+ this._context.putImageData(this._imagedata, destination.x, destination.y);
+ }
+});
+
+TiledCanvasImageStage = Utilities.createSubclass(Stage,
+ function(element, options)
+ {
+ Stage.call(this);
+ }, {
+
+ initialize: function(benchmark, options)
+ {
+ Stage.prototype.initialize.call(this, benchmark, options);
+ this.context = this.element.getContext("2d");
+ this._setupTiles();
+ },
+
+ _setupTiles: function()
+ {
+ const maxTilesPerRow = 50;
+ const maxTilesPerCol = 50;
+
+ this.tileSize = this.size.multiply(new Point(1 / maxTilesPerRow, 1 / maxTilesPerCol));
+
+ this._tiles = new Array(maxTilesPerRow * maxTilesPerCol);
+
+ var source = Point.zero;
+ for (var index = 0; index < this._tiles.length; ++index) {
+ this._tiles[index] = new CanvasImageTile(this, source);
+ source = this._nextTilePosition(source);
+ }
+
+ this._ctiles = 0;
+ },
+
+ _nextTilePosition: function(destination)
+ {
+ var next = destination.add(this.tileSize);
+
+ if (next.x >= this._size.width)
+ return new Point(0, next.y >= this._size.height ? 0 : next.y);
+
+ return new Point(next.x, destination.y);
+ },
+
+ tune: function(count)
+ {
+ this._ctiles += count;
+
+ this._ctiles = Math.max(this._ctiles, 0);
+ this._ctiles = Math.min(this._ctiles, this._tiles.length);
+ },
+
+ _drawBackground: function()
+ {
+ var size = this._benchmark._stage.size;
+ var gradient = this.context.createLinearGradient(0, 0, size.width, 0);
+ gradient.addColorStop(0, "red");
+ gradient.addColorStop(1, "white");
+ this.context.save();
+ this.context.fillStyle = gradient;
+ this.context.fillRect(0, 0, size.width, size.height);
+ this.context.restore();
+ },
+
+ animate: function(timeDelta)
+ {
+ this._drawBackground();
+
+ if (!this._ctiles)
+ return;
+
+ this._tiles.shuffle();
+
+ var destinations = new Array(this._ctiles);
+ for (var index = 0; index < this._ctiles; ++index) {
+ this._tiles[index].getImageData();
+ destinations[index] = this._tiles[index].source;
+ }
+
+ destinations.shuffle();
+
+ for (var index = 0; index < this._ctiles; ++index)
+ this._tiles[index].putImageData(destinations[index]);
+ },
+
+ complexity: function()
+ {
+ return this._ctiles;
+ }
+});
+
+TiledCanvasImageBenchmark = Utilities.createSubclass(Benchmark,
+ function(options)
+ {
+ Benchmark.call(this, new TiledCanvasImageStage(), options);
+ }
+);
+
+window.benchmarkClass = TiledCanvasImageBenchmark;
+
+})();
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/simple/simple-canvas-paths.html b/third_party/webkit/PerformanceTests/MotionMark/tests/simple/simple-canvas-paths.html
new file mode 100644
index 0000000000..5bb69bc54f
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/simple/simple-canvas-paths.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+</head>
+<body>
+ <canvas id="stage"></canvas>
+ <script src="../../resources/strings.js"></script>
+ <script src="../../resources/extensions.js"></script>
+ <script src="../../resources/statistics.js"></script>
+ <script src="../resources/math.js"></script>
+ <script src="../resources/main.js"></script>
+ <script src="../master/resources/canvas-stage.js"></script>
+ <script src="resources/simple-canvas.js"></script>
+ <script src="resources/simple-canvas-paths.js"></script>
+</body>
+</html>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/simple/tiled-canvas-image.html b/third_party/webkit/PerformanceTests/MotionMark/tests/simple/tiled-canvas-image.html
new file mode 100644
index 0000000000..c7c0fef774
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/simple/tiled-canvas-image.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+</head>
+<body>
+ <canvas id="stage"></canvas>
+ <script src="../../resources/strings.js"></script>
+ <script src="../../resources/extensions.js"></script>
+ <script src="../../resources/statistics.js"></script>
+ <script src="../resources/math.js"></script>
+ <script src="../resources/main.js"></script>
+ <script src="resources/tiled-canvas-image.js"></script>
+</body>
+</html>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/template/resources/template-canvas.js b/third_party/webkit/PerformanceTests/MotionMark/tests/template/resources/template-canvas.js
new file mode 100644
index 0000000000..b74984c010
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/template/resources/template-canvas.js
@@ -0,0 +1,89 @@
+(function() {
+
+function TemplateCanvasObject(stage)
+{
+ // For the canvas stage, most likely you will need to create your
+ // animated object since it's only draw time thing.
+
+ // Fill in your object data.
+}
+
+TemplateCanvasObject.prototype = {
+ _draw: function()
+ {
+ // Draw your object.
+ },
+
+ animate: function(timeDelta)
+ {
+ // Redraw the animated object. The last time this animated
+ // item was drawn before 'timeDelta'.
+
+ // Move your object.
+
+ // Redraw your object.
+ this._draw();
+ }
+};
+
+TemplateCanvasStage = Utilities.createSubclass(Stage,
+ function()
+ {
+ Stage.call(this);
+ }, {
+
+ initialize: function(benchmark, options)
+ {
+ Stage.prototype.initialize.call(this, benchmark, options);
+ this.context = this.element.getContext("2d");
+
+ // Define a collection for your objects.
+ },
+
+ tune: function(count)
+ {
+ // If count is -ve, -count elements need to be removed form the
+ // stage. If count is +ve, +count elements need to be added to
+ // the stage.
+
+ // Change objects in the stage.
+ },
+
+ animate: function(timeDelta)
+ {
+ // Animate the elements such that all of them are redrawn. Most
+ // likely you will need to call TemplateCanvasObject.animate()
+ // for all your animated objects here.
+
+ // Most likely you will need to clear the canvas with every redraw.
+ this.context.clearRect(0, 0, this.size.x, this.size.y);
+
+ // Loop through all your objects and ask them to animate.
+ }
+});
+
+TemplateCanvasBenchmark = Utilities.createSubclass(Benchmark,
+ function(options)
+ {
+ Benchmark.call(this, new TemplateCanvasStage(), options);
+ }, {
+
+ // Override this function if the benchmark needs to wait for resources to be
+ // loaded.
+ //
+ // Default implementation returns a resolved promise, so that the benchmark
+ // benchmark starts right away. Here's an example where we're waiting 5
+ // seconds before starting the benchmark.
+ waitUntilReady: function()
+ {
+ var promise = new SimplePromise;
+ window.setTimeout(function() {
+ promise.resolve();
+ }, 5000);
+ return promise;
+ }
+});
+
+window.benchmarkClass = TemplateCanvasBenchmark;
+
+})(); \ No newline at end of file
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/template/resources/template-css.js b/third_party/webkit/PerformanceTests/MotionMark/tests/template/resources/template-css.js
new file mode 100644
index 0000000000..cdaa814af0
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/template/resources/template-css.js
@@ -0,0 +1,46 @@
+(function() {
+
+TemplateCssStage = Utilities.createSubclass(Stage,
+ function()
+ {
+ Stage.call(this);
+ }, {
+
+ initialize: function(benchmark, options)
+ {
+ Stage.prototype.initialize.call(this, benchmark, options);
+
+ // Do initialization here.
+ },
+
+ tune: function(count)
+ {
+ // If count is -ve, -count elements need to be removed form the
+ // stage. If count is +ve, +count elements need to be added to
+ // the stage.
+
+ // Change objects in the stage.
+ },
+
+ animate: function(timeDelta)
+ {
+ // Animate the elements such that all of them are redrawn. You
+ // may need to define your object so it keeps its animation data.
+ // This object should encapsulate a corrosponding HTMLElement.
+ // You may also define a method called animate() in this object
+ // and just call this function here for all the elements.
+
+ // Loop through all your objects and ask them to animate.
+ }
+});
+
+TemplateCssBenchmark = Utilities.createSubclass(Benchmark,
+ function(options)
+ {
+ Benchmark.call(this, new TemplateCssStage(), options);
+ }
+);
+
+window.benchmarkClass = TemplateCssBenchmark;
+
+})();
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/template/resources/template-svg.js b/third_party/webkit/PerformanceTests/MotionMark/tests/template/resources/template-svg.js
new file mode 100644
index 0000000000..8fee9c3478
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/template/resources/template-svg.js
@@ -0,0 +1,46 @@
+(function() {
+
+TemplateSvgStage = Utilities.createSubclass(Stage,
+ function()
+ {
+ Stage.call(this);
+ }, {
+
+ initialize: function(benchmark, options)
+ {
+ Stage.prototype.initialize.call(this, benchmark, options);
+
+ // Do initialization here.
+ },
+
+ tune: function(count)
+ {
+ // If count is -ve, -count elements need to be removed form the
+ // stage. If count is +ve, +count elements need to be added to
+ // the stage.
+
+ // TODO: Change objects in the stage.
+ },
+
+ animate: function(timeDelta)
+ {
+ // Animate the elements such that all of them are redrawn. You
+ // may need to define your object so it keeps its animation data.
+ // This object should encapsulate a corrosponding SVGElement.
+ // You may also define a method called animate() in this object
+ // and just call this function here for all the elements.
+
+ // TODO: Loop through all your objects and ask them to animate.
+ }
+});
+
+TemplateSvgBenchmark = Utilities.createSubclass(Benchmark,
+ function(options)
+ {
+ Benchmark.call(this, new TemplateSvgStage(), options);
+ }
+);
+
+window.benchmarkClass = TemplateSvgBenchmark;
+
+})();
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/template/template-canvas.html b/third_party/webkit/PerformanceTests/MotionMark/tests/template/template-canvas.html
new file mode 100644
index 0000000000..dcb7f52861
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/template/template-canvas.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+</head>
+<body>
+ <canvas id="stage"></canvas>
+ <script src="../../resources/strings.js"></script>
+ <script src="../../resources/extensions.js"></script>
+ <script src="../../resources/statistics.js"></script>
+ <script src="../resources/math.js"></script>
+ <script src="../resources/main.js"></script>
+ <script src="resources/template-canvas.js"></script>
+</body>
+</html>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/template/template-css.html b/third_party/webkit/PerformanceTests/MotionMark/tests/template/template-css.html
new file mode 100644
index 0000000000..70eb214e95
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/template/template-css.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+</head>
+<body>
+ <div id="stage"></div>
+ <script src="../../resources/strings.js"></script>
+ <script src="../../resources/extensions.js"></script>
+ <script src="../../resources/statistics.js"></script>
+ <script src="../resources/math.js"></script>
+ <script src="../resources/main.js"></script>
+ <script src="resources/template-css.js"></script>
+</body>
+</html>
diff --git a/third_party/webkit/PerformanceTests/MotionMark/tests/template/template-svg.html b/third_party/webkit/PerformanceTests/MotionMark/tests/template/template-svg.html
new file mode 100644
index 0000000000..7a14fc45d6
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/MotionMark/tests/template/template-svg.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+</head>
+<body>
+ <svg id="stage"></svg>
+ <script src="../../resources/strings.js"></script>
+ <script src="../../resources/extensions.js"></script>
+ <script src="../../resources/statistics.js"></script>
+ <script src="../resources/math.js"></script>
+ <script src="../resources/main.js"></script>
+ <script src="resources/template-svg.js"></script>
+</body>
+</html>