// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
'use strict';
/**
* @fileoverview This file provides the RenderingStats object, used
* to characterize rendering smoothness.
*/
(function() {
var getTimeMs = (function() {
if (window.performance)
return (performance.now ||
performance.mozNow ||
performance.msNow ||
performance.oNow ||
performance.webkitNow).bind(window.performance);
else
return function() { return new Date().getTime(); };
})();
var requestAnimationFrame = (function() {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
})().bind(window);
/**
* Tracks rendering performance using the gpuBenchmarking.renderingStats API.
* @constructor
*/
function GpuBenchmarkingRenderingStats() {
}
GpuBenchmarkingRenderingStats.prototype.start = function() {
this.startTime_ = getTimeMs();
this.initialStats_ = this.getRenderingStats_();
}
GpuBenchmarkingRenderingStats.prototype.stop = function() {
this.stopTime_ = getTimeMs();
this.finalStats_ = this.getRenderingStats_();
}
GpuBenchmarkingRenderingStats.prototype.getStartValues = function() {
if (!this.initialStats_)
throw new Error('Start not called.');
if (!this.finalStats_)
throw new Error('Stop was not called.');
return this.initialStats_;
}
GpuBenchmarkingRenderingStats.prototype.getEndValues = function() {
if (!this.initialStats_)
throw new Error('Start not called.');
if (!this.finalStats_)
throw new Error('Stop was not called.');
return this.finalStats_;
}
GpuBenchmarkingRenderingStats.prototype.getDeltas = function() {
if (!this.initialStats_)
throw new Error('Start not called.');
if (!this.finalStats_)
throw new Error('Stop was not called.');
var stats = {}
for (var key in this.finalStats_)
stats[key] = this.finalStats_[key] - this.initialStats_[key];
return stats;
};
GpuBenchmarkingRenderingStats.prototype.isUsingGpuBenchmarking = function() {
return true;
}
GpuBenchmarkingRenderingStats.prototype.getRenderingStats_ = function() {
var stats = chrome.gpuBenchmarking.renderingStats();
stats.totalTimeInSeconds = getTimeMs() / 1000;
return stats;
};
/**
* Tracks rendering performance using requestAnimationFrame.
* @constructor
*/
function RafRenderingStats() {
this.recording_ = false;
this.frameTimes_ = [];
}
RafRenderingStats.prototype.start = function() {
if (this.recording_)
throw new Error('Already started.');
this.recording_ = true;
requestAnimationFrame(this.recordFrameTime_.bind(this));
}
RafRenderingStats.prototype.stop = function() {
this.recording_ = false;
}
RafRenderingStats.prototype.getStartValues = function() {
var results = {};
results.numAnimationFrames = 0;
results.numFramesSentToScreen = 0;
results.droppedFrameCount = 0;
return results;
}
RafRenderingStats.prototype.getEndValues = function() {
var results = {};
results.numAnimationFrames = this.frameTimes_.length - 1;
results.numFramesSentToScreen = results.numAnimationFrames;
results.droppedFrameCount = this.getDroppedFrameCount_(this.frameTimes_);
return results;
}
RafRenderingStats.prototype.getDeltas = function() {
var endValues = this.getEndValues();
endValues.totalTimeInSeconds = (
this.frameTimes_[this.frameTimes_.length - 1] -
this.frameTimes_[0]) / 1000;
return endValues;
};
RafRenderingStats.prototype.isUsingGpuBenchmarking = function() {
return false;
}
RafRenderingStats.prototype.recordFrameTime_ = function(timestamp) {
if (!this.recording_)
return;
this.frameTimes_.push(timestamp);
requestAnimationFrame(this.recordFrameTime_.bind(this));
};
RafRenderingStats.prototype.getDroppedFrameCount_ = function(frameTimes) {
var droppedFrameCount = 0;
var droppedFrameThreshold = 1000 / 55;
for (var i = 1; i < frameTimes.length; i++) {
var frameTime = frameTimes[i] - frameTimes[i-1];
if (frameTime > droppedFrameThreshold)
droppedFrameCount += Math.floor(frameTime / droppedFrameThreshold);
}
return droppedFrameCount;
};
function RenderingStats() {
if (window.chrome && chrome.gpuBenchmarking &&
chrome.gpuBenchmarking.renderingStats) {
return new GpuBenchmarkingRenderingStats();
}
return new RafRenderingStats();
}
window.__RenderingStats = RenderingStats;
})();