Skip to content
Permalink
Browse files
Web Inspector: [Canvas] group replay log calls by frames
https://bugs.webkit.org/show_bug.cgi?id=110101

Reviewed by Pavel Feldman.

Source/WebCore:

Group canvas replay log by frames, then by draw calls.

* inspector/InjectedScriptCanvasModuleSource.js:
(.):
* inspector/Inspector.json:
* inspector/front-end/CanvasProfileView.js:
(WebInspector.CanvasProfileView):
(WebInspector.CanvasProfileView.prototype.dispose):
(WebInspector.CanvasProfileView.prototype._appendCallNode):
(WebInspector.CanvasProfileView.prototype._appendDrawCallGroup):

LayoutTests:

* inspector/profiler/canvas-profiler-test.js:
* inspector/profiler/canvas2d/canvas-replay-log-grid-expected.txt:
* inspector/profiler/canvas2d/canvas-replay-log-grid.html:
* inspector/profiler/canvas2d/canvas-stack-trace-expected.txt:


Canonical link: https://commits.webkit.org/128404@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@143206 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
Andrey Adaykin committed Feb 18, 2013
1 parent 7ed5e22 commit 8dcb6c316f5c321ec7cc40d135ecb1af77fc9cfe
Showing 9 changed files with 180 additions and 41 deletions.
@@ -1,3 +1,15 @@
2013-02-18 Andrey Adaikin <aandrey@chromium.org>

Web Inspector: [Canvas] group replay log calls by frames
https://bugs.webkit.org/show_bug.cgi?id=110101

Reviewed by Pavel Feldman.

* inspector/profiler/canvas-profiler-test.js:
* inspector/profiler/canvas2d/canvas-replay-log-grid-expected.txt:
* inspector/profiler/canvas2d/canvas-replay-log-grid.html:
* inspector/profiler/canvas2d/canvas-stack-trace-expected.txt:

2013-02-18 Ádám Kallai <kadam@inf.u-szeged.hu>

[Qt] Deleted extraneous file. It has been added accidentally in r142135.
@@ -64,6 +64,7 @@ InspectorTest.dumpTraceLogCall = function(call, indent)
call.property ? "property:\"" + call.property + "\"" : "",
call.value ? "value:" + call.value.description : "",
call.isDrawingCall ? "isDrawingCall:true" : "",
call.isFrameEndCall ? "isFrameEndCall:true" : "",
"sourceURL:" + formatSourceURL(call.sourceURL),
"lineNumber:" + call.lineNumber,
"columnNumber:" + call.columnNumber
@@ -2,24 +2,31 @@ Tests replay log grid.

Bug 109592

| Draw call group #1 | |
1 | beginPath() | canvas-replay-log-grid.html:26 |
2 | rect(0, 0, 100, 100) | canvas-replay-log-grid.html:27 |
3 | context.fillStyle = red | canvas-replay-log-grid.html:28 |
4 | fill() | canvas-replay-log-grid.html:29 |
| Draw call group #2 | |
5 | beginPath() | canvas-replay-log-grid.html:26 |
6 | rect(5, 5, 95, 95) | canvas-replay-log-grid.html:27 |
7 | context.fillStyle = green | canvas-replay-log-grid.html:28 |
8 | fill() | canvas-replay-log-grid.html:29 |
| Draw call group #3 | |
9 | beginPath() | canvas-replay-log-grid.html:26 |
10 | rect(10, 10, 90, 90) | canvas-replay-log-grid.html:27 |
11 | context.fillStyle = blue | canvas-replay-log-grid.html:28 |
12 | fill() | canvas-replay-log-grid.html:29 |
| Draw call group #4 | |
13 | beginPath() | canvas-replay-log-grid.html:26 |
14 | rect(15, 15, 85, 85) | canvas-replay-log-grid.html:27 |
15 | context.fillStyle = yellow | canvas-replay-log-grid.html:28 |
16 | fill() | canvas-replay-log-grid.html:29 |
| Frame #1 | | |
| Draw call group #1 | | |
1 | beginPath() | canvas-replay-log-grid.html:26 | |
2 | rect(0, 0, 100, 100) | canvas-replay-log-grid.html:27 | |
3 | context.fillStyle = red | canvas-replay-log-grid.html:28 | |
4 | fill() | canvas-replay-log-grid.html:29 | |
| Draw call group #2 | | |
5 | beginPath() | canvas-replay-log-grid.html:26 | |
6 | rect(5, 5, 95, 95) | canvas-replay-log-grid.html:27 | |
7 | context.fillStyle = green | canvas-replay-log-grid.html:28 | |
8 | fill() | canvas-replay-log-grid.html:29 | |
| Frame #2 | | |
| Draw call group #3 | | |
9 | beginPath() | canvas-replay-log-grid.html:26 | |
10 | rect(10, 10, 90, 90) | canvas-replay-log-grid.html:27 | |
11 | context.fillStyle = blue | canvas-replay-log-grid.html:28 | |
12 | fill() | canvas-replay-log-grid.html:29 | |
| Draw call group #4 | | |
13 | beginPath() | canvas-replay-log-grid.html:26 | |
14 | rect(15, 15, 85, 85) | canvas-replay-log-grid.html:27 | |
15 | context.fillStyle = yellow | canvas-replay-log-grid.html:28 | |
16 | fill() | canvas-replay-log-grid.html:29 | |
| Draw call group #5 | | |
17 | beginPath() | canvas-replay-log-grid.html:26 | |
18 | rect(20, 20, 80, 80) | canvas-replay-log-grid.html:27 | |
19 | context.fillStyle = black | canvas-replay-log-grid.html:28 | |
20 | fill() | canvas-replay-log-grid.html:29 | |

@@ -42,6 +42,7 @@
var profileType = profilesPanel.getProfileType(WebInspector.CanvasProfileType.TypeId);
profilesPanel._onProfileTypeSelected({data: profileType});

InspectorTest.override(profileType, "_isSingleFrameMode", function() { return false; }, true /*sticky*/);
InspectorTest.addSniffer(profileType, "_didStartCapturingFrame", didStartCapturingFrame);
profilesPanel.toggleRecordButton();

@@ -52,17 +53,26 @@
profileHeader = profilesPanel.getProfiles(WebInspector.CanvasProfileType.TypeId)[0];
traceLogId = profileHeader.traceLogId();
profilesPanel.showProfile(profileHeader);
InspectorTest.evaluateInConsole("doSomeCanvasCalls(4)", didSomeCanvasCalls);
InspectorTest.addSniffer(profileHeader, "_updateCapturingStatus", didReceiveFirstFrame);
InspectorTest.evaluateInConsole("doSomeCanvasCalls(2)");
}
function didSomeCanvasCalls()
function didReceiveFirstFrame(traceLog)
{
InspectorTest.addSniffer(profileHeader, "_updateCapturingStatus", onUpdateCapturingStatus);
if (!traceLog || traceLog.calls.length < 2) {
InspectorTest.addSniffer(profileHeader, "_updateCapturingStatus", didReceiveFirstFrame);
return;
}
InspectorTest.evaluateInConsole("doSomeCanvasCalls(3)", didSecondFrameCalls);
}
function didSecondFrameCalls()
{
InspectorTest.addSniffer(profileHeader, "_updateCapturingStatus", didReceiveSecondFrame);
profilesPanel.toggleRecordButton();
}
function onUpdateCapturingStatus()
function didReceiveSecondFrame()
{
if (profileHeader._alive) {
InspectorTest.addSniffer(profileHeader, "_updateCapturingStatus", onUpdateCapturingStatus);
InspectorTest.addSniffer(profileHeader, "_updateCapturingStatus", didReceiveSecondFrame);
return;
}

@@ -111,6 +121,8 @@
line += " | ";
line += alignText(textRows[i][j], textWidths[j]);
}
if (line)
line += "|";
InspectorTest.addResult(line);
}
}
@@ -6,5 +6,5 @@ Bug 107805
{Call} functionName:"beginPath" arguments:[] sourceURL:"canvas-stack-trace.html" lineNumber:19 columnNumber:13
{Call} functionName:"rect" arguments:[0,0,100,100] sourceURL:"canvas-stack-trace.html" lineNumber:20 columnNumber:13
{Call} property:"fillStyle" value:red sourceURL:"canvas-stack-trace.html" lineNumber:21 columnNumber:23
{Call} functionName:"fill" arguments:[] isDrawingCall:true sourceURL:"canvas-stack-trace.html" lineNumber:22 columnNumber:13
{Call} functionName:"fill" arguments:[] isDrawingCall:true isFrameEndCall:true sourceURL:"canvas-stack-trace.html" lineNumber:22 columnNumber:13

@@ -1,3 +1,21 @@
2013-02-18 Andrey Adaikin <aandrey@chromium.org>

Web Inspector: [Canvas] group replay log calls by frames
https://bugs.webkit.org/show_bug.cgi?id=110101

Reviewed by Pavel Feldman.

Group canvas replay log by frames, then by draw calls.

* inspector/InjectedScriptCanvasModuleSource.js:
(.):
* inspector/Inspector.json:
* inspector/front-end/CanvasProfileView.js:
(WebInspector.CanvasProfileView):
(WebInspector.CanvasProfileView.prototype.dispose):
(WebInspector.CanvasProfileView.prototype._appendCallNode):
(WebInspector.CanvasProfileView.prototype._appendDrawCallGroup):

2013-02-18 Christophe Dumez <ch.dumez@sisa.samsung.com>

[Soup] CookieJarSoup::deleteCookie() should stop looking for the cookie after it is removed
@@ -2720,6 +2720,8 @@ function TraceLog()
this._replayableCalls = [];
/** @type {!Cache} */
this._replayablesCache = new Cache();
/** @type {!Object.<number, boolean>} */
this._frameEndCallIndexes = {};
}

TraceLog.prototype = {
@@ -2762,6 +2764,22 @@ TraceLog.prototype = {
addCall: function(call)
{
this._replayableCalls.push(call.toReplayable(this._replayablesCache));
},

addFrameEndMark: function()
{
var index = this._replayableCalls.length - 1;
if (index >= 0)
this._frameEndCallIndexes[index] = true;
},

/**
* @param {number} index
* @return {boolean}
*/
isFrameEndCallAt: function(index)
{
return !!this._frameEndCallIndexes[index];
}
}

@@ -2846,6 +2864,45 @@ TraceLogPlayer.prototype = {
}
}

/**
* @constructor
* @param {function()} callback
*/
function ZeroTimeoutCallback(callback)
{
this._callback = callback;
this._scheduled = false;
}

ZeroTimeoutCallback.prototype = {
schedule: function()
{
if (this._scheduled)
return;
this._scheduled = true;
var callback = this._onCallback.bind(this);
// We need a fastest async callback, whatever fires first.
// Usually a postMessage should be faster than a setTimeout(0).
var channel = new MessageChannel();
channel.port1.onmessage = callback;
channel.port2.postMessage("");
inspectedWindow.setTimeout(callback, 0);
},

cancel: function()
{
this._scheduled = false;
},

_onCallback: function()
{
if (!this._scheduled)
return;
this._scheduled = false;
this._callback();
}
}

/**
* @constructor
*/
@@ -2854,6 +2911,7 @@ function ResourceTrackingManager()
this._capturing = false;
this._stopCapturingOnFrameEnd = false;
this._lastTraceLog = null;
this._frameEndScheduler = new ZeroTimeoutCallback(this.markFrameEnd.bind(this));
}

ResourceTrackingManager.prototype = {
@@ -2898,6 +2956,9 @@ ResourceTrackingManager.prototype = {
return;
this._capturing = false;
this._stopCapturingOnFrameEnd = false;
this._frameEndScheduler.cancel();
if (this._lastTraceLog)
this._lastTraceLog.addFrameEndMark();
},

/**
@@ -2941,23 +3002,16 @@ ResourceTrackingManager.prototype = {
if (!this._capturing)
return;
this._lastTraceLog.addCall(call);
if (this._stopCapturingOnFrameEnd && this._lastTraceLog.size() === 1) {
this._stopCapturingOnFrameEnd = false;
this._setZeroTimeouts(this.stopCapturing.bind(this, this._lastTraceLog));
}
this._frameEndScheduler.schedule();
},

/**
* @param {function()} callback
*/
_setZeroTimeouts: function(callback)
markFrameEnd: function()
{
// We need a fastest async callback, whatever fires first.
// Usually a postMessage should be faster than a setTimeout(0).
var channel = new MessageChannel();
channel.port1.onmessage = callback;
channel.port2.postMessage("");
inspectedWindow.setTimeout(callback, 0);
if (!this._lastTraceLog)
return;
this._lastTraceLog.addFrameEndMark();
if (this._stopCapturingOnFrameEnd)
this.stopCapturing(this._lastTraceLog);
}
}

@@ -3069,6 +3123,9 @@ InjectedCanvasModule.prototype = {
if (!traceLog)
return "Error: Trace log with the given ID not found.";

// Ensure last call ends a frame.
traceLog.addFrameEndMark();

var replayableCalls = traceLog.replayableCalls();
if (typeof startOffset !== "number")
startOffset = 0;
@@ -3097,6 +3154,7 @@ InjectedCanvasModule.prototype = {
item.sourceURL = callFrame.sourceURL;
item.lineNumber = callFrame.lineNumber;
item.columnNumber = callFrame.columnNumber;
item.isFrameEndCall = traceLog.isFrameEndCallAt(i);
result.calls.push(item);
}
return result;
@@ -3493,6 +3493,7 @@
{ "name": "arguments", "type": "array", "items": { "$ref": "CallArgument" }, "optional": true },
{ "name": "result", "$ref": "CallArgument", "optional": true },
{ "name": "isDrawingCall", "type": "boolean", "optional": true },
{ "name": "isFrameEndCall", "type": "boolean", "optional": true },
{ "name": "property", "type": "string", "optional": true },
{ "name": "value", "$ref": "CallArgument", "optional": true },
{ "name": "sourceURL", "type": "string", "optional": true },
@@ -90,6 +90,8 @@ WebInspector.CanvasProfileView = function(profile)
this._logGridNodes = [];
/** @type {!Array.<WebInspector.DataGridNode>} */
this._drawCallGroups = [];
/** @type {!Array.<WebInspector.DataGridNode>} */
this._frameGroups = [];

this._splitView.show(this.element);
this._requestTraceLog();
@@ -106,6 +108,7 @@ WebInspector.CanvasProfileView.prototype = {
{
this._logGridNodes = [];
this._drawCallGroupNodes = [];
this._frameGroups = [];
this._linkifier.reset();
},

@@ -369,11 +372,38 @@ WebInspector.CanvasProfileView.prototype = {
drawCallGroup.selectable = true;
drawCallGroup.drawCallGroupIndex = index;
this._drawCallGroups.push(drawCallGroup);
this._logGrid.rootNode().appendChild(drawCallGroup);
this._appendDrawCallGroup(drawCallGroup);
}
drawCallGroup.appendChild(gridNode);
},

/**
* @param {!WebInspector.DataGridNode} drawCallGroup
*/
_appendDrawCallGroup: function(drawCallGroup)
{
var frameGroup = this._frameGroups.peekLast();
if (frameGroup) {
var lastDrawCallGroup = frameGroup.children.peekLast();
var lastNode = lastDrawCallGroup && lastDrawCallGroup.children.peekLast();
if (lastNode && lastNode.call.isFrameEndCall)
frameGroup = null;
}
if (!frameGroup) {
var index = this._frameGroups.length;
var data = {};
data[0] = "";
data[1] = "Frame #" + (index + 1);
data[2] = "";
frameGroup = new WebInspector.DataGridNode(data);
frameGroup.selectable = true;
frameGroup.frameGroupIndex = index;
this._frameGroups.push(frameGroup);
this._logGrid.rootNode().appendChild(frameGroup);
}
frameGroup.appendChild(drawCallGroup);
},

/**
* @param {number} index
* @param {CanvasAgent.Call} call

0 comments on commit 8dcb6c3

Please sign in to comment.