From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- .../MotionMark/tests/3d/resources/webgl.js | 184 ++++ .../MotionMark/tests/3d/webgl.html | 64 ++ .../bouncing-particles/bouncing-canvas-images.html | 26 + .../bouncing-particles/bouncing-canvas-shapes.html | 18 + .../bouncing-particles/bouncing-css-images.html | 22 + .../bouncing-particles/bouncing-css-shapes.html | 33 + .../bouncing-particles/bouncing-svg-images.html | 18 + .../bouncing-particles/bouncing-svg-shapes.html | 18 + .../bouncing-particles/bouncing-tagged-images.html | 22 + .../resources/bouncing-canvas-images.js | 47 ++ .../resources/bouncing-canvas-particles.js | 88 ++ .../resources/bouncing-canvas-shapes.js | 87 ++ .../resources/bouncing-css-images.js | 61 ++ .../resources/bouncing-css-shapes.js | 86 ++ .../resources/bouncing-particles.js | 123 +++ .../resources/bouncing-svg-images.js | 43 + .../resources/bouncing-svg-particles.js | 67 ++ .../resources/bouncing-svg-shapes.js | 101 +++ .../resources/bouncing-tagged-images.js | 106 +++ .../tests/bouncing-particles/resources/image1.jpg | Bin 0 -> 64004 bytes .../tests/bouncing-particles/resources/image2.jpg | Bin 0 -> 71981 bytes .../tests/bouncing-particles/resources/image3.jpg | Bin 0 -> 71319 bytes .../tests/bouncing-particles/resources/image4.jpg | Bin 0 -> 96373 bytes .../tests/bouncing-particles/resources/image5.jpg | Bin 0 -> 135674 bytes .../tests/dom/compositing-transforms.html | 24 + .../MotionMark/tests/dom/focus.html | 51 ++ .../MotionMark/tests/dom/leaves.html | 26 + .../MotionMark/tests/dom/particles.html | 24 + .../tests/dom/resources/compositing-transforms.js | 66 ++ .../tests/dom/resources/dom-particles.js | 73 ++ .../MotionMark/tests/dom/resources/focus.js | 166 ++++ .../MotionMark/tests/dom/resources/leaves.js | 48 ++ .../MotionMark/tests/master/canvas-stage.html | 17 + .../MotionMark/tests/master/focus.html | 29 + .../MotionMark/tests/master/image-data.html | 28 + .../MotionMark/tests/master/leaves.html | 25 + .../MotionMark/tests/master/multiply.html | 53 ++ .../tests/master/resources/canvas-stage.js | 52 ++ .../tests/master/resources/canvas-tests.js | 311 +++++++ .../MotionMark/tests/master/resources/compass.svg | 7 + .../tests/master/resources/compass100.png | Bin 0 -> 3048 bytes .../MotionMark/tests/master/resources/console.svg | 6 + .../tests/master/resources/console100.png | Bin 0 -> 944 bytes .../tests/master/resources/contribute.svg | 6 + .../tests/master/resources/contribute100.png | Bin 0 -> 3599 bytes .../MotionMark/tests/master/resources/debugger.svg | 5 + .../tests/master/resources/debugger100.png | Bin 0 -> 2473 bytes .../MotionMark/tests/master/resources/focus.js | 129 +++ .../tests/master/resources/image-data.js | 181 ++++ .../tests/master/resources/inspector.svg | 6 + .../tests/master/resources/inspector100.png | Bin 0 -> 1477 bytes .../MotionMark/tests/master/resources/layout.svg | 6 + .../tests/master/resources/layout100.png | Bin 0 -> 423 bytes .../MotionMark/tests/master/resources/leaves.js | 135 +++ .../MotionMark/tests/master/resources/multiply.js | 119 +++ .../MotionMark/tests/master/resources/particles.js | 112 +++ .../tests/master/resources/performance.svg | 6 + .../tests/master/resources/performance100.png | Bin 0 -> 2546 bytes .../MotionMark/tests/master/resources/script.svg | 5 + .../tests/master/resources/script100.png | Bin 0 -> 3192 bytes .../tests/master/resources/shortcuts.svg | 5 + .../tests/master/resources/shortcuts100.png | Bin 0 -> 2763 bytes .../tests/master/resources/standards.svg | 6 + .../tests/master/resources/standards100.png | Bin 0 -> 4363 bytes .../MotionMark/tests/master/resources/storage.svg | 5 + .../tests/master/resources/storage100.png | Bin 0 -> 3167 bytes .../MotionMark/tests/master/resources/styles.svg | 5 + .../tests/master/resources/styles100.png | Bin 0 -> 3875 bytes .../tests/master/resources/svg-particles.js | 111 +++ .../MotionMark/tests/master/resources/text.js | 116 +++ .../MotionMark/tests/master/resources/timeline.svg | 6 + .../tests/master/resources/timeline100.png | Bin 0 -> 2039 bytes .../MotionMark/tests/master/svg-particles.html | 38 + .../MotionMark/tests/master/text.html | 82 ++ .../MotionMark/tests/resources/main.js | 934 +++++++++++++++++++++ .../MotionMark/tests/resources/math.js | 268 ++++++ .../MotionMark/tests/resources/stage.css | 27 + .../MotionMark/tests/resources/star.svg | 8 + .../MotionMark/tests/resources/yin-yang.png | Bin 0 -> 4082 bytes .../MotionMark/tests/resources/yin-yang.svg | 17 + .../tests/simple/resources/simple-canvas-paths.js | 453 ++++++++++ .../tests/simple/resources/simple-canvas.js | 35 + .../tests/simple/resources/tiled-canvas-image.js | 119 +++ .../tests/simple/simple-canvas-paths.html | 18 + .../tests/simple/tiled-canvas-image.html | 16 + .../tests/template/resources/template-canvas.js | 89 ++ .../tests/template/resources/template-css.js | 46 + .../tests/template/resources/template-svg.js | 46 + .../MotionMark/tests/template/template-canvas.html | 16 + .../MotionMark/tests/template/template-css.html | 16 + .../MotionMark/tests/template/template-svg.html | 16 + 91 files changed, 5428 insertions(+) create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/3d/resources/webgl.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/3d/webgl.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-canvas-images.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-canvas-shapes.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-css-images.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-css-shapes.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-svg-images.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-svg-shapes.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/bouncing-tagged-images.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-images.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-particles.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-canvas-shapes.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-css-images.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-css-shapes.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-particles.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-svg-images.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-svg-particles.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-svg-shapes.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/bouncing-tagged-images.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image1.jpg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image2.jpg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image3.jpg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image4.jpg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image5.jpg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/dom/compositing-transforms.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/dom/focus.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/dom/leaves.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/dom/particles.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/compositing-transforms.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/dom-particles.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/focus.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/dom/resources/leaves.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/canvas-stage.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/focus.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/image-data.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/leaves.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/multiply.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/canvas-stage.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/canvas-tests.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/compass.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/compass100.png create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/console.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/console100.png create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/contribute.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/contribute100.png create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/debugger.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/debugger100.png create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/focus.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/image-data.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/inspector.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/inspector100.png create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/layout.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/layout100.png create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/leaves.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/multiply.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/particles.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/performance.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/performance100.png create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/script.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/script100.png create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/shortcuts.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/shortcuts100.png create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/standards.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/standards100.png create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/storage.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/storage100.png create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/styles.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/styles100.png create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/svg-particles.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/text.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/timeline.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/timeline100.png create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/svg-particles.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/master/text.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/resources/main.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/resources/math.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/resources/stage.css create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/resources/star.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/resources/yin-yang.png create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/resources/yin-yang.svg create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/simple/resources/simple-canvas-paths.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/simple/resources/simple-canvas.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/simple/resources/tiled-canvas-image.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/simple/simple-canvas-paths.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/simple/tiled-canvas-image.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/template/resources/template-canvas.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/template/resources/template-css.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/template/resources/template-svg.js create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/template/template-canvas.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/template/template-css.html create mode 100644 third_party/webkit/PerformanceTests/MotionMark/tests/template/template-svg.html (limited to 'third_party/webkit/PerformanceTests/MotionMark/tests') 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 + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + +
+ + + + + + + + + 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 @@ + + + + + + + + +
+ + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + +
+ + 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 Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image1.jpg 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 Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image2.jpg 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 Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image3.jpg 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 Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image4.jpg 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 Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/bouncing-particles/resources/image5.jpg 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 @@ + + + + + + + + +
+ + + + + + + + + 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 @@ + + + + + + + + +
+
focus
+
+ + + + + + + + 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 @@ + + + + + + + + +
+ + + + + + + + + + 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 @@ + + + + + + + + +
+ + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + +
+ + + + + + + + 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 @@ + + + + + + + + +
+ + + + + + + + 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 @@ + + + + + + + + +
+ + + + + + + + + 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 @@ + + + + + + + + +
+
+ + + + + + + + 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 @@ + + + + + + + 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 Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/compass100.png 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 @@ + + + + + + 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 Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/console100.png 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 @@ + + + + + + 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 Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/contribute100.png 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 @@ + + + + + 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 Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/debugger100.png 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 @@ + + + + + + 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 Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/inspector100.png 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 @@ + + + + + + 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 Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/layout100.png 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 @@ + + + + + + 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 Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/performance100.png 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 @@ + + + + + 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 Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/script100.png 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 @@ + + + + + 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 Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/shortcuts100.png 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 @@ + + + + + + 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 Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/standards100.png 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 @@ + + + + + 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 Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/storage100.png 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 @@ + + + + + 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 Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/styles100.png 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 @@ + + + + + + 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 Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/master/resources/timeline100.png 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + +
σχέδιο设计suunnittelu
designдизайнتصميم
디자인conceptionデザイン
konstruktionעיצובdiseño
+
+
+ + + + + + + + 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 @@ + + + + + + + + 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 Binary files /dev/null and b/third_party/webkit/PerformanceTests/MotionMark/tests/resources/yin-yang.png 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 @@ + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + 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 @@ + + + + + + + +
+ + + + + + + + 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 @@ + + + + + + + + + + + + + + + + -- cgit v1.2.3