1 // Copyright (c) 2012 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.
8 * @fileoverview This file provides the RenderingStats object, used
9 * to characterize rendering smoothness.
12 var getTimeMs = (function() {
13 if (window.performance)
14 return (performance.now ||
18 performance.webkitNow).bind(window.performance);
20 return function() { return new Date().getTime(); };
23 var requestAnimationFrame = (function() {
24 return window.requestAnimationFrame ||
25 window.webkitRequestAnimationFrame ||
26 window.mozRequestAnimationFrame ||
27 window.oRequestAnimationFrame ||
28 window.msRequestAnimationFrame ||
30 window.setTimeout(callback, 1000 / 60);
35 * Tracks rendering performance using the gpuBenchmarking.renderingStats API.
38 function GpuBenchmarkingRenderingStats() {
41 GpuBenchmarkingRenderingStats.prototype.start = function() {
42 this.startTime_ = getTimeMs();
43 this.initialStats_ = this.getRenderingStats_();
46 GpuBenchmarkingRenderingStats.prototype.stop = function() {
47 this.stopTime_ = getTimeMs();
48 this.finalStats_ = this.getRenderingStats_();
51 GpuBenchmarkingRenderingStats.prototype.getStartValues = function() {
52 if (!this.initialStats_)
53 throw new Error('Start not called.');
55 if (!this.finalStats_)
56 throw new Error('Stop was not called.');
58 return this.initialStats_;
61 GpuBenchmarkingRenderingStats.prototype.getEndValues = function() {
62 if (!this.initialStats_)
63 throw new Error('Start not called.');
65 if (!this.finalStats_)
66 throw new Error('Stop was not called.');
68 return this.finalStats_;
71 GpuBenchmarkingRenderingStats.prototype.getDeltas = function() {
72 if (!this.initialStats_)
73 throw new Error('Start not called.');
75 if (!this.finalStats_)
76 throw new Error('Stop was not called.');
79 for (var key in this.finalStats_)
80 stats[key] = this.finalStats_[key] - this.initialStats_[key];
84 GpuBenchmarkingRenderingStats.prototype.getRenderingStats_ = function() {
85 var stats = chrome.gpuBenchmarking.renderingStats();
86 stats.totalTimeInSeconds = getTimeMs() / 1000;
91 * Tracks rendering performance using requestAnimationFrame.
94 function RafRenderingStats() {
95 this.recording_ = false;
96 this.frameTimes_ = [];
99 RafRenderingStats.prototype.start = function() {
101 throw new Error('Already started.');
102 this.recording_ = true;
103 requestAnimationFrame(this.recordFrameTime_.bind(this));
106 RafRenderingStats.prototype.stop = function() {
107 this.recording_ = false;
110 RafRenderingStats.prototype.getStartValues = function() {
112 results.numAnimationFrames = 0;
113 results.numFramesSentToScreen = 0;
114 results.droppedFrameCount = 0;
118 RafRenderingStats.prototype.getEndValues = function() {
120 results.numAnimationFrames = this.frameTimes_.length - 1;
121 results.numFramesSentToScreen = results.numAnimationFrames;
122 results.droppedFrameCount = this.getDroppedFrameCount_(this.frameTimes_);
126 RafRenderingStats.prototype.getDeltas = function() {
127 var endValues = this.getEndValues();
128 endValues.totalTimeInSeconds = (
129 this.frameTimes_[this.frameTimes_.length - 1] -
130 this.frameTimes_[0]) / 1000;
134 RafRenderingStats.prototype.recordFrameTime_ = function(timestamp) {
135 if (!this.recording_)
138 this.frameTimes_.push(timestamp);
139 requestAnimationFrame(this.recordFrameTime_.bind(this));
142 RafRenderingStats.prototype.getDroppedFrameCount_ = function(frameTimes) {
143 var droppedFrameCount = 0;
144 for (var i = 1; i < frameTimes.length; i++) {
145 var frameTime = frameTimes[i] - frameTimes[i-1];
146 if (frameTime > 1000 / 55)
149 return droppedFrameCount;
152 function RenderingStats() {
153 if (window.chrome && chrome.gpuBenchmarking &&
154 chrome.gpuBenchmarking.renderingStats) {
155 return new GpuBenchmarkingRenderingStats();
157 return new RafRenderingStats();
160 window.__RenderingStats = RenderingStats;