Improve canvas perf test accuracy.
[WebKit-https.git] / WebKitSite / demos / canvas-perf / canvas.html
1 <!DOCTYPE html>
2 <body onload="doTest()">
3 <pre id="output">
4 </pre>
5 <img src="kraken.jpg" id="image">
6 <canvas id="original" style="width: 3264px; height: 2448px"></canvas>
7 <canvas id="copy" style="width: 3264px; height: 2448px"></canvas>
8 <canvas id="indirectCopy" style="width: 3264px; height: 2448px"></canvas>
9 <canvas id="scaledUp" style="width: 6528px; height: 4896px"></canvas>
10 <canvas id="scaledDown" style="width: 1632px; height: 1224px"></canvas>
11 <canvas id="rotated" style="width: 2448px; height: 3264px; border: 1px solid red;"></canvas>
12 <script>
13 var width = 3264;
14 var height = 2448;
15 var original = document.getElementById("original");
16 var originalContext = original.getContext("2d");
17 var idleTimer = 20;
18
19 function log(text) {
20     if (typeof text != "string" )
21         text = text.toString();
22     var span = document.createElement("span");
23     document.getElementById("output").appendChild(span);
24     span.innerHTML = text.replace(/</g, "&lt;").replace("/>/g", "&gt;").replace("/&/g", "&amp")+ "<br>";
25 }
26
27 function shouldBe(_a, _b) {
28     if (typeof _a != "string" || typeof _b != "string")
29         log("WARNING: shouldBe() expects string arguments.");
30     var _aValue = eval(_a);
31     var _bValue = eval(_b);
32     if (_aValue !== _bValue)
33         log("FAILURE: " + _a + "should have been " + _bValue + ". Instead it was " + _aValue + ".");
34 }
35
36 function flushOperation(context) {
37    var imageData = context.getImageData(0, 0, context.canvas.width, context.canvas.height);
38 }
39
40 function timeCanvasOperation(context, canvasOperation) {
41     var repetitions = 2;
42     var startDate = new Date();
43
44     for (var i = 0; i < repetitions; ++i) {
45         canvasOperation();
46         flushOperation(context);
47     }
48     var finishDate = new Date();
49     var timeWithOverhead = finishDate - startDate;
50
51     for (var i = 0; i < repetitions; ++i) {
52         flushOperation(context);
53     }
54     var overheadTime = new Date() - finishDate;
55     return (timeWithOverhead - overheadTime) / repetitions;
56 }
57
58 function doTest() {
59     var image =  document.getElementById("image");
60     image.width = width;
61     image.height = height;
62     
63     original.width = width;
64     original.height = height;
65     original.getContext("2d").drawImage(image, 0, 0);
66     window.setTimeout(doCopy, idleTimer);
67 }
68
69 function doCopy() {
70     var copy =  document.getElementById("copy");
71     copy.width = width;
72     copy.height = height;
73     var copyContext = copy.getContext("2d");
74     copyContext.globalCompositeOperation = "copy";
75     var time = timeCanvasOperation(copyContext,
76         function () {
77             copyContext.drawImage(original, 0, 0);
78         });
79     log("Direct image copy: " + time + "ms");
80     window.setTimeout(doIndirectCopy, idleTimer);
81 }
82
83 function doIndirectCopy() {
84     var indirectCopy =  document.getElementById("indirectCopy");
85     indirectCopy.width = width;
86     indirectCopy.height = height;
87     var indirectCopyContext = indirectCopy.getContext("2d");
88     indirectCopyContext.globalCompositeOperation = "copy";
89     time = timeCanvasOperation(indirectCopyContext,
90         function () {
91             var imageData = originalContext.getImageData(0, 0, width, height);
92             indirectCopyContext.putImageData(imageData, 0, 0);
93         });
94     log("Indirect copy with (via ImageData): " + time + "ms");
95     window.setTimeout(doScaleUp, idleTimer);
96 }
97
98 function doScaleUp() {
99     var scaledUp =  document.getElementById("scaledUp");
100     scaledUp.width = width * 2;
101     scaledUp.height = height * 2;
102     var scaledUpContext = scaledUp.getContext("2d");
103     scaledUpContext.globalCompositeOperation = "copy";
104     time = timeCanvasOperation(scaledUpContext,
105         function () {
106             scaledUpContext.drawImage(original, 0, 0, width * 2, height * 2);
107         });
108     log("Copy with 2x scale: " + time + "ms");
109     shouldBe("document.getElementById('scaledUp').width", "width * 2");
110     shouldBe("document.getElementById('scaledUp').height", "height * 2");
111     window.setTimeout(doScaleDown, idleTimer);
112 }
113
114 function doScaleDown() {
115     var scaledDown =  document.getElementById("scaledDown");
116     scaledDown.width = width / 2;
117     scaledDown.height = height / 2;
118     var scaledDownContext = scaledDown.getContext("2d");
119     scaledDownContext.globalCompositeOperation = "copy";
120     time = timeCanvasOperation(scaledDownContext,
121         function () {
122             scaledDownContext.drawImage(original, 0, 0, width / 2, height / 2);
123         });
124     log("Copy with 0.5x scale: " + time + "ms");
125     shouldBe("document.getElementById('scaledDown').width", "width / 2");
126     shouldBe("document.getElementById('scaledDown').height", "height / 2");
127     window.setTimeout(doRotation, idleTimer);
128 }
129
130 function doRotation() {
131     var rotated = document.getElementById("rotated");
132     rotated.width = height;
133     rotated.height = width;
134     var rotatedContext = rotated.getContext("2d");
135     rotatedContext.globalCompositeOperation = "copy";
136     rotatedContext.rotate(Math.PI / 2);
137
138     time = timeCanvasOperation(rotatedContext,
139         function () {
140             rotatedContext.drawImage(original, 0, -original.height);
141         });
142     log("Copy with rotate: " + time + "ms");
143     shouldBe("document.getElementById('rotated').width", "height");
144     shouldBe("document.getElementById('rotated').height", "width");
145     log("DONE!");
146 }
147 </script>
148
149 </body>