Index: Source/devtools/front_end/TimelineOverviewPane.js |
diff --git a/Source/devtools/front_end/TimelineOverviewPane.js b/Source/devtools/front_end/TimelineOverviewPane.js |
index aa5af2066f3e007abe4cdf5c336d5c823bae0679..014d185707c9e9abdbdd6f92e4bb563b8a566c20 100644 |
--- a/Source/devtools/front_end/TimelineOverviewPane.js |
+++ b/Source/devtools/front_end/TimelineOverviewPane.js |
@@ -648,6 +648,7 @@ WebInspector.TimelineFrameOverview = function(model) |
this._outerPadding = 4 * window.devicePixelRatio; |
this._maxInnerBarWidth = 10 * window.devicePixelRatio; |
+ this._topPadding = 6 * window.devicePixelRatio; |
// The below two are really computed by update() -- but let's have something so that windowTimes() is happy. |
this._actualPadding = 5 * window.devicePixelRatio; |
@@ -657,6 +658,9 @@ WebInspector.TimelineFrameOverview = function(model) |
var categories = WebInspector.TimelinePresentationModel.categories(); |
for (var category in categories) |
this._fillStyles[category] = WebInspector.TimelinePresentationModel.createFillStyleForCategory(this._context, this._maxInnerBarWidth, 0, categories[category]); |
+ this._frameTopShadeGradient = this._context.createLinearGradient(0, 0, 0, this._topPadding); |
+ this._frameTopShadeGradient.addColorStop(0, "rgba(255, 255, 255, 0.9)"); |
+ this._frameTopShadeGradient.addColorStop(1, "rgba(255, 255, 255, 0.2)"); |
} |
WebInspector.TimelineFrameOverview.prototype = { |
@@ -665,7 +669,9 @@ WebInspector.TimelineFrameOverview.prototype = { |
this._recordsPerBar = 1; |
/** @type {!Array.<{startTime:number, endTime:number}>} */ |
this._barTimes = []; |
- this._frames = []; |
+ this._mainThreadFrames = []; |
+ this._backgroundFrames = []; |
+ this._framesById = {}; |
}, |
update: function() |
@@ -673,15 +679,46 @@ WebInspector.TimelineFrameOverview.prototype = { |
this._resetCanvas(); |
this._barTimes = []; |
+ var backgroundFramesHeight = 15; |
+ var mainThreadFramesHeight = this._canvas.height - backgroundFramesHeight; |
const minBarWidth = 4 * window.devicePixelRatio; |
- var frameCount = this._frames.length; |
+ var frameCount = this._backgroundFrames.length || this._mainThreadFrames.length; |
var framesPerBar = Math.max(1, frameCount * minBarWidth / this._canvas.width); |
- var visibleFrames = this._aggregateFrames(this._frames, framesPerBar); |
- var windowHeight = this._canvas.height; |
- const paddingTop = 4 * window.devicePixelRatio; |
- var scale = (windowHeight - paddingTop) / this._computeTargetFrameLength(visibleFrames); |
- this._renderBars(visibleFrames, scale, windowHeight); |
- this._drawFPSMarks(scale, windowHeight); |
+ |
+ var mainThreadVisibleFrames; |
+ var backgroundVisibleFrames; |
+ if (this._backgroundFrames.length) { |
+ backgroundVisibleFrames = this._aggregateFrames(this._backgroundFrames, framesPerBar); |
+ mainThreadVisibleFrames = new Array(backgroundVisibleFrames.length); |
+ for (var i = 0; i < backgroundVisibleFrames.length; ++i) { |
+ var frameId = backgroundVisibleFrames[i].mainThreadFrameId; |
+ mainThreadVisibleFrames[i] = frameId && this._framesById[frameId]; |
+ } |
+ } else { |
+ mainThreadVisibleFrames = this._aggregateFrames(this._mainThreadFrames, framesPerBar); |
+ } |
+ |
+ this._context.save(); |
+ this._setCanvasWindow(0, backgroundFramesHeight, this._canvas.width, mainThreadFramesHeight); |
+ var scale = (mainThreadFramesHeight - this._topPadding) / this._computeTargetFrameLength(mainThreadVisibleFrames); |
+ this._renderBars(mainThreadVisibleFrames, scale, mainThreadFramesHeight); |
+ this._context.fillStyle = this._frameTopShadeGradient; |
+ this._context.fillRect(0, 0, this._canvas.width, this._topPadding); |
+ this._drawFPSMarks(scale, mainThreadFramesHeight); |
+ this._context.restore(); |
+ |
+ var bottom = backgroundFramesHeight + 0.5; |
+ this._context.strokeStyle = "rgba(120, 120, 120, 0.8)"; |
+ this._context.beginPath(); |
+ this._context.moveTo(0, bottom); |
+ this._context.lineTo(this._canvas.width, bottom); |
+ this._context.stroke(); |
+ |
+ if (backgroundVisibleFrames) { |
+ const targetFPS = 30.0; |
+ scale = (backgroundFramesHeight - this._topPadding) / (1.0 / targetFPS); |
+ this._renderBars(backgroundVisibleFrames, scale, backgroundFramesHeight); |
+ } |
}, |
/** |
@@ -689,9 +726,33 @@ WebInspector.TimelineFrameOverview.prototype = { |
*/ |
addFrame: function(frame) |
{ |
- this._frames.push(frame); |
+ var frames; |
+ if (frame.isBackground) { |
+ frames = this._backgroundFrames; |
+ } else { |
+ frames = this._mainThreadFrames; |
+ this._framesById[frame.id] = frame; |
+ } |
+ frames.push(frame); |
}, |
+ /** |
+ * @param {number} x0 |
+ * @param {number} y0 |
+ * @param {number} width |
+ * @param {number} height |
+ */ |
+ _setCanvasWindow: function(x0, y0, width, height) |
+ { |
+ this._context.translate(x0, y0); |
+ this._context.beginPath(); |
+ this._context.moveTo(0, 0); |
+ this._context.lineTo(width, 0); |
+ this._context.lineTo(width, height); |
+ this._context.lineTo(0, height); |
+ this._context.lineTo(0, 0); |
+ this._context.clip(); |
+ }, |
/** |
* @param {Array.<WebInspector.TimelineFrame>} frames |
@@ -708,7 +769,7 @@ WebInspector.TimelineFrameOverview.prototype = { |
for (var lastFrame = Math.min(Math.floor((barNumber + 1) * framesPerBar), frames.length); |
currentFrame < lastFrame; ++currentFrame) { |
- var duration = frames[currentFrame].duration; |
+ var duration = this._frameDuration(frames[currentFrame]); |
if (!longestFrame || longestDuration < duration) { |
longestFrame = frames[currentFrame]; |
longestDuration = duration; |
@@ -724,12 +785,25 @@ WebInspector.TimelineFrameOverview.prototype = { |
}, |
/** |
+ * @param {WebInspector.TimelineFrame} frame |
+ */ |
+ _frameDuration: function(frame) |
+ { |
+ var relatedFrame = frame.mainThreadFrameId && this._framesById[frame.mainThreadFrameId]; |
+ return frame.duration + (relatedFrame ? relatedFrame.duration : 0); |
+ }, |
+ |
+ /** |
* @param {Array.<WebInspector.TimelineFrame>} frames |
* @return {number} |
*/ |
_computeTargetFrameLength: function(frames) |
{ |
- var durations = frames.select("duration"); |
+ var durations = []; |
+ for (var i = 0; i < frames.length; ++i) { |
+ if (frames[i]) |
+ durations.push(frames[i].duration); |
+ } |
var medianFrameLength = durations.qselect(Math.floor(durations.length / 2)); |
// Optimize appearance for 30fps. However, if at least half frames won't fit at this scale, |
@@ -755,8 +829,10 @@ WebInspector.TimelineFrameOverview.prototype = { |
this._actualPadding = Math.min(Math.floor(this._actualOuterBarWidth / 3), maxPadding); |
var barWidth = this._actualOuterBarWidth - this._actualPadding; |
- for (var i = 0; i < frames.length; ++i) |
- this._renderBar(this._barNumberToScreenPosition(i), barWidth, windowHeight, frames[i], scale); |
+ for (var i = 0; i < frames.length; ++i) { |
+ if (frames[i]) |
+ this._renderBar(this._barNumberToScreenPosition(i), barWidth, windowHeight, frames[i], scale); |
+ } |
}, |
/** |
@@ -810,7 +886,7 @@ WebInspector.TimelineFrameOverview.prototype = { |
this._context.fillText(label, labelX - labelPadding, labelY + lineHeight - baselineHeight); |
labelTopMargin = labelY + lineHeight; |
} |
- this._context.strokeStyle = "rgba(128, 128, 128, 0.5)"; |
+ this._context.strokeStyle = "rgba(60, 60, 60, 0.4)"; |
this._context.stroke(); |
this._context.restore(); |
}, |
@@ -836,7 +912,7 @@ WebInspector.TimelineFrameOverview.prototype = { |
if (!duration) |
continue; |
- var height = duration * scale; |
+ var height = Math.round(duration * scale); |
var y = Math.floor(bottomOffset - height) + 0.5; |
this._context.save(); |