Upstream version 5.34.98.0
[platform/framework/web/crosswalk.git] / src / tools / perf / metrics / smoothness.js
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 'use strict';
6
7 /**
8  * @fileoverview This file provides the RenderingStats object, used
9  * to characterize rendering smoothness.
10  */
11 (function() {
12   var getTimeMs = (function() {
13     if (window.performance)
14       return (performance.now       ||
15               performance.mozNow    ||
16               performance.msNow     ||
17               performance.oNow      ||
18               performance.webkitNow).bind(window.performance);
19     else
20       return function() { return new Date().getTime(); };
21   })();
22
23   var requestAnimationFrame = (function() {
24     return window.requestAnimationFrame       ||
25            window.webkitRequestAnimationFrame ||
26            window.mozRequestAnimationFrame    ||
27            window.oRequestAnimationFrame      ||
28            window.msRequestAnimationFrame     ||
29            function(callback) {
30              window.setTimeout(callback, 1000 / 60);
31            };
32   })().bind(window);
33
34   /**
35    * Tracks rendering performance using the gpuBenchmarking.renderingStats API.
36    * @constructor
37    */
38   function GpuBenchmarkingRenderingStats() {
39   }
40
41   GpuBenchmarkingRenderingStats.prototype.start = function() {
42     this.startTime_ = getTimeMs();
43     this.initialStats_ = this.getRenderingStats_();
44   }
45
46   GpuBenchmarkingRenderingStats.prototype.stop = function() {
47     this.stopTime_ = getTimeMs();
48     this.finalStats_ = this.getRenderingStats_();
49   }
50
51   GpuBenchmarkingRenderingStats.prototype.getStartValues = function() {
52     if (!this.initialStats_)
53       throw new Error('Start not called.');
54
55     if (!this.finalStats_)
56       throw new Error('Stop was not called.');
57
58     return this.initialStats_;
59   }
60
61   GpuBenchmarkingRenderingStats.prototype.getEndValues = function() {
62     if (!this.initialStats_)
63       throw new Error('Start not called.');
64
65     if (!this.finalStats_)
66       throw new Error('Stop was not called.');
67
68     return this.finalStats_;
69   }
70
71   GpuBenchmarkingRenderingStats.prototype.getDeltas = function() {
72     if (!this.initialStats_)
73       throw new Error('Start not called.');
74
75     if (!this.finalStats_)
76       throw new Error('Stop was not called.');
77
78     var stats = {}
79     for (var key in this.finalStats_)
80       stats[key] = this.finalStats_[key] - this.initialStats_[key];
81     return stats;
82   };
83
84   GpuBenchmarkingRenderingStats.prototype.isUsingGpuBenchmarking = function() {
85     return true;
86   }
87
88   GpuBenchmarkingRenderingStats.prototype.getRenderingStats_ = function() {
89     var stats = chrome.gpuBenchmarking.renderingStats();
90     stats.totalTimeInSeconds = getTimeMs() / 1000;
91     return stats;
92   };
93
94   /**
95    * Tracks rendering performance using requestAnimationFrame.
96    * @constructor
97    */
98   function RafRenderingStats() {
99     this.recording_ = false;
100     this.frameTimes_ = [];
101   }
102
103   RafRenderingStats.prototype.start = function() {
104     if (this.recording_)
105       throw new Error('Already started.');
106     this.recording_ = true;
107     requestAnimationFrame(this.recordFrameTime_.bind(this));
108   }
109
110   RafRenderingStats.prototype.stop = function() {
111     this.recording_ = false;
112   }
113
114   RafRenderingStats.prototype.getStartValues = function() {
115     var results = {};
116     results.numAnimationFrames = 0;
117     results.numFramesSentToScreen = 0;
118     results.droppedFrameCount = 0;
119     return results;
120   }
121
122   RafRenderingStats.prototype.getEndValues = function() {
123     var results = {};
124     results.numAnimationFrames = this.frameTimes_.length - 1;
125     results.numFramesSentToScreen = results.numAnimationFrames;
126     results.droppedFrameCount = this.getDroppedFrameCount_(this.frameTimes_);
127     return results;
128   }
129
130   RafRenderingStats.prototype.getDeltas = function() {
131     var endValues = this.getEndValues();
132     endValues.totalTimeInSeconds = (
133         this.frameTimes_[this.frameTimes_.length - 1] -
134         this.frameTimes_[0]) / 1000;
135     return endValues;
136   };
137
138   RafRenderingStats.prototype.isUsingGpuBenchmarking = function() {
139     return false;
140   }
141
142   RafRenderingStats.prototype.recordFrameTime_ = function(timestamp) {
143     if (!this.recording_)
144       return;
145
146     this.frameTimes_.push(timestamp);
147     requestAnimationFrame(this.recordFrameTime_.bind(this));
148   };
149
150   RafRenderingStats.prototype.getDroppedFrameCount_ = function(frameTimes) {
151     var droppedFrameCount = 0;
152     var droppedFrameThreshold = 1000 / 55;
153     for (var i = 1; i < frameTimes.length; i++) {
154       var frameTime = frameTimes[i] - frameTimes[i-1];
155       if (frameTime > droppedFrameThreshold)
156         droppedFrameCount += Math.floor(frameTime / droppedFrameThreshold);
157     }
158     return droppedFrameCount;
159   };
160
161   function RenderingStats() {
162     if (window.chrome && chrome.gpuBenchmarking &&
163         chrome.gpuBenchmarking.renderingStats) {
164       return new GpuBenchmarkingRenderingStats();
165     }
166     return new RafRenderingStats();
167   }
168
169   window.__RenderingStats = RenderingStats;
170 })();