f25ca8f5a4d8855c202a80f21b020b592464fefa
[WebKit-https.git] / PerformanceTests / Animometer / tests / master / resources / image-data.js
1 (function() {
2
3 var ImageDataStage = Utilities.createSubclass(Stage,
4     function() {
5         Stage.call(this);
6
7         this.testElements = [];
8         this._offsetIndex = 0;
9     }, {
10
11     imageWidth: 100,
12     imageHeight: 100,
13     pixelStride: 4,
14     rowStride: 400,
15     weightNegativeThreshold: 0.04,
16     weightPositiveThreshold: 0.96,
17     imageSrcs: [
18         "compass",
19         "console",
20         "contribute",
21         "debugger",
22         "inspector",
23         "layout",
24         "performance",
25         "script",
26         "shortcuts",
27         "standards",
28         "storage",
29         "styles",
30         "timeline"
31     ],
32     images: [],
33
34     initialize: function(benchmark)
35     {
36         Stage.prototype.initialize.call(this, benchmark);
37
38         var waitForLoad = new SimplePromise;
39
40         var lastPromise;
41         var images = this.images;
42         this.imageSrcs.forEach(function(imageSrc) {
43             var promise = this._loadImage("resources/" + imageSrc + ".svg");
44             if (!lastPromise)
45                 lastPromise = promise;
46             else {
47                 lastPromise = lastPromise.then(function(img) {
48                     images.push(img);
49                     return promise;
50                 });
51             }
52         }, this);
53
54         lastPromise.then(function(img) {
55             images.push(img);
56             benchmark.readyPromise.resolve();
57         }.bind(this));
58     },
59
60     _loadImage: function(src) {
61         var img = new Image;
62         var promise = new SimplePromise;
63
64         img.addEventListener('load', function onImageLoad(e) {
65             img.removeEventListener('load', onImageLoad);
66             promise.resolve(img);
67         });
68
69         img.src = src;
70         return promise;
71     },
72
73     tune: function(count)
74     {
75         if (count == 0)
76             return;
77
78         if (count < 0) {
79             this._offsetIndex = Math.max(this._offsetIndex + count, 0);
80             for (var i = this._offsetIndex; i < this.testElements.length; ++i)
81                 this.testElements[i].style.display = "none";
82             return;
83         }
84
85         this._offsetIndex = this._offsetIndex + count;
86         var index = Math.min(this._offsetIndex, this.testElements.length);
87         for (var i = 0; i < index; ++i) {
88             this.testElements[i].style.display = "block";
89             this._refreshElement(this.testElements[i]);
90         }
91         if (this._offsetIndex <= this.testElements.length)
92             return;
93
94         index = this._offsetIndex - this.testElements.length;
95         for (var i = 0; i < index; ++i) {
96             var element = this._createTestElement();
97             this.testElements.push(element);
98             this.element.appendChild(element);
99         }
100     },
101
102     _createTestElement: function() {
103         var element = document.createElement('canvas');
104         element.width = this.imageWidth;
105         element.height = this.imageHeight;
106         element.style.width = this.imageWidth + 'px';
107         element.style.height = this.imageHeight + 'px';
108
109         this._refreshElement(element);
110         return element;
111     },
112
113     _refreshElement: function(element) {
114         var top = Stage.randomInt(0, Math.floor((this.size.height - this.imageHeight) / this.imageHeight)) * this.imageHeight;
115         var left = Stage.randomInt(0, Math.floor((this.size.width - this.imageWidth) / this.imageWidth)) * this.imageWidth;
116
117         element.style.top = top + 'px';
118         element.style.left = left + 'px';
119     },
120
121     animate: function(timeDelta) {
122         for (var i = 0; i < this._offsetIndex; ++i) {
123             var element = this.testElements[i];
124             var context = element.getContext("2d");
125
126             // Get image data
127             var imageData = context.getImageData(0, 0, this.imageWidth, this.imageHeight);
128
129             var didDraw = false,
130                 neighborPixelIndex,
131                 dataLen = imageData.data.length;
132             for (var j = 0; j < dataLen; j += this.pixelStride) {
133                 if (imageData.data[j + 3] === 0)
134                     continue;
135
136                 // get random neighboring pixel color
137                 neighborPixelIndex = this._getRandomNeighboringPixelIndex(j, dataLen);
138
139                 // Update the RGB data
140                 imageData.data[j] = imageData.data[neighborPixelIndex];
141                 imageData.data[j + 1] = imageData.data[neighborPixelIndex + 1];
142                 imageData.data[j + 2] = imageData.data[neighborPixelIndex + 2];
143                 imageData.data[j + 3] = imageData.data[neighborPixelIndex + 3];
144                 didDraw = true;
145             }
146
147             if (didDraw)
148                 context.putImageData(imageData, 0, 0);
149             else {
150                 this._refreshElement(element);
151                 element.getContext("2d").drawImage(this.images[Stage.randomInt(0, this.images.length - 1)], 0, 0, this.imageWidth, this.imageHeight);
152             }
153         }
154     },
155
156     _getRandomNeighboringPixelIndex: function(pixelIdx, pixelArrayLength)
157     {
158         var xOffset = Math.floor((Pseudo.random() - this.weightNegativeThreshold) / (this.weightPositiveThreshold - this.weightNegativeThreshold));
159         var yOffset = Math.floor((Pseudo.random() - this.weightNegativeThreshold) / (this.weightPositiveThreshold - this.weightNegativeThreshold));
160         return (pixelIdx + this.pixelStride * xOffset + this.rowStride * yOffset) % pixelArrayLength;
161     },
162
163     complexity: function()
164     {
165         return this._offsetIndex;
166     }
167 });
168
169 var ImageDataBenchmark = Utilities.createSubclass(Benchmark,
170     function(options)
171     {
172         Benchmark.call(this, new ImageDataStage(), options);
173     }, {
174
175     waitUntilReady: function() {
176         this.readyPromise = new SimplePromise;
177         return this.readyPromise;
178     }
179 });
180
181 window.benchmarkClass = ImageDataBenchmark;
182
183 }());