blob: da5e06bbcd6bca7a7d77dcaf2a7b2dd7cd776e2c [file] [log] [blame]
Blink Reformat4c46d092018-04-07 15:32:371// Copyright 2014 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
Rob Paveza96705c62020-01-08 01:37:485Timeline.TimelinePaintProfilerView = class extends UI.SplitWidget {
Blink Reformat4c46d092018-04-07 15:32:376 /**
7 * @param {!TimelineModel.TimelineFrameModel} frameModel
8 */
9 constructor(frameModel) {
10 super(false, false);
11 this.element.classList.add('timeline-paint-profiler-view');
12 this.setSidebarSize(60);
13 this.setResizable(false);
14
15 this._frameModel = frameModel;
16 this._logAndImageSplitWidget = new UI.SplitWidget(true, false);
17 this._logAndImageSplitWidget.element.classList.add('timeline-paint-profiler-log-split');
18 this.setMainWidget(this._logAndImageSplitWidget);
Rob Paveza96705c62020-01-08 01:37:4819 this._imageView = new Timeline.TimelinePaintImageView();
Blink Reformat4c46d092018-04-07 15:32:3720 this._logAndImageSplitWidget.setMainWidget(this._imageView);
21
22 this._paintProfilerView = new LayerViewer.PaintProfilerView(this._imageView.showImage.bind(this._imageView));
23 this._paintProfilerView.addEventListener(
24 LayerViewer.PaintProfilerView.Events.WindowChanged, this._onWindowChanged, this);
25 this.setSidebarWidget(this._paintProfilerView);
26
27 this._logTreeView = new LayerViewer.PaintProfilerCommandLogView();
28 this._logAndImageSplitWidget.setSidebarWidget(this._logTreeView);
29
30 this._needsUpdateWhenVisible = false;
31 /** @type {?SDK.PaintProfilerSnapshot} */
32 this._pendingSnapshot = null;
33 /** @type {?SDK.TracingModel.Event} */
34 this._event = null;
35 /** @type {?SDK.PaintProfilerModel} */
36 this._paintProfilerModel = null;
37 /** @type {?SDK.PaintProfilerSnapshot} */
38 this._lastLoadedSnapshot = null;
39 }
40
41 /**
42 * @override
43 */
44 wasShown() {
45 if (this._needsUpdateWhenVisible) {
46 this._needsUpdateWhenVisible = false;
47 this._update();
48 }
49 }
50
51 /**
52 * @param {!SDK.PaintProfilerSnapshot} snapshot
53 */
54 setSnapshot(snapshot) {
55 this._releaseSnapshot();
56 this._pendingSnapshot = snapshot;
57 this._event = null;
58 this._updateWhenVisible();
59 }
60
61 /**
62 * @param {!SDK.PaintProfilerModel} paintProfilerModel
63 * @param {!SDK.TracingModel.Event} event
64 * @return {boolean}
65 */
66 setEvent(paintProfilerModel, event) {
67 this._releaseSnapshot();
68 this._paintProfilerModel = paintProfilerModel;
69 this._pendingSnapshot = null;
70 this._event = event;
71
72 this._updateWhenVisible();
Tim van der Lippe1d6e57a2019-09-30 11:55:3473 if (this._event.name === TimelineModel.TimelineModel.RecordType.Paint) {
Blink Reformat4c46d092018-04-07 15:32:3774 return !!TimelineModel.TimelineData.forEvent(event).picture;
Tim van der Lippe1d6e57a2019-09-30 11:55:3475 }
76 if (this._event.name === TimelineModel.TimelineModel.RecordType.RasterTask) {
Blink Reformat4c46d092018-04-07 15:32:3777 return this._frameModel.hasRasterTile(this._event);
Tim van der Lippe1d6e57a2019-09-30 11:55:3478 }
Blink Reformat4c46d092018-04-07 15:32:3779 return false;
80 }
81
82 _updateWhenVisible() {
Tim van der Lippe1d6e57a2019-09-30 11:55:3483 if (this.isShowing()) {
Blink Reformat4c46d092018-04-07 15:32:3784 this._update();
Tim van der Lippe1d6e57a2019-09-30 11:55:3485 } else {
Blink Reformat4c46d092018-04-07 15:32:3786 this._needsUpdateWhenVisible = true;
Tim van der Lippe1d6e57a2019-09-30 11:55:3487 }
Blink Reformat4c46d092018-04-07 15:32:3788 }
89
90 _update() {
91 this._logTreeView.setCommandLog([]);
92 this._paintProfilerView.setSnapshotAndLog(null, [], null);
93
94 let snapshotPromise;
95 if (this._pendingSnapshot) {
96 snapshotPromise = Promise.resolve({rect: null, snapshot: this._pendingSnapshot});
97 } else if (this._event.name === TimelineModel.TimelineModel.RecordType.Paint) {
98 const picture = TimelineModel.TimelineData.forEvent(this._event).picture;
99 snapshotPromise = picture.objectPromise()
100 .then(data => this._paintProfilerModel.loadSnapshot(data['skp64']))
101 .then(snapshot => snapshot && {rect: null, snapshot: snapshot});
102 } else if (this._event.name === TimelineModel.TimelineModel.RecordType.RasterTask) {
103 snapshotPromise = this._frameModel.rasterTilePromise(this._event);
104 } else {
105 console.assert(false, 'Unexpected event type or no snapshot');
106 return;
107 }
108 snapshotPromise.then(snapshotWithRect => {
109 this._releaseSnapshot();
110 if (!snapshotWithRect) {
111 this._imageView.showImage();
112 return;
113 }
114 const snapshot = snapshotWithRect.snapshot;
115 this._lastLoadedSnapshot = snapshot;
116 this._imageView.setMask(snapshotWithRect.rect);
117 snapshot.commandLog().then(log => onCommandLogDone.call(this, snapshot, snapshotWithRect.rect, log));
118 });
119
120 /**
121 * @param {!SDK.PaintProfilerSnapshot} snapshot
122 * @param {?Protocol.DOM.Rect} clipRect
123 * @param {!Array.<!SDK.PaintProfilerLogItem>=} log
Rob Paveza96705c62020-01-08 01:37:48124 * @this {Timeline.TimelinePaintProfilerView}
Blink Reformat4c46d092018-04-07 15:32:37125 */
126 function onCommandLogDone(snapshot, clipRect, log) {
127 this._logTreeView.setCommandLog(log || []);
128 this._paintProfilerView.setSnapshotAndLog(snapshot, log || [], clipRect);
129 }
130 }
131
132 _releaseSnapshot() {
Tim van der Lippe1d6e57a2019-09-30 11:55:34133 if (!this._lastLoadedSnapshot) {
Blink Reformat4c46d092018-04-07 15:32:37134 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34135 }
Blink Reformat4c46d092018-04-07 15:32:37136 this._lastLoadedSnapshot.release();
137 this._lastLoadedSnapshot = null;
138 }
139
140 _onWindowChanged() {
141 this._logTreeView.updateWindow(this._paintProfilerView.selectionWindow());
142 }
Rob Paveza96705c62020-01-08 01:37:48143};
Blink Reformat4c46d092018-04-07 15:32:37144
145/**
146 * @unrestricted
147 */
Rob Paveza96705c62020-01-08 01:37:48148Timeline.TimelinePaintImageView = class extends UI.Widget {
Blink Reformat4c46d092018-04-07 15:32:37149 constructor() {
150 super(true);
151 this.registerRequiredCSS('timeline/timelinePaintProfiler.css');
152 this.contentElement.classList.add('fill', 'paint-profiler-image-view');
153 this._imageContainer = this.contentElement.createChild('div', 'paint-profiler-image-container');
154 this._imageElement = this._imageContainer.createChild('img');
155 this._maskElement = this._imageContainer.createChild('div');
156 this._imageElement.addEventListener('load', this._updateImagePosition.bind(this), false);
157
158 this._transformController = new LayerViewer.TransformController(this.contentElement, true);
159 this._transformController.addEventListener(
160 LayerViewer.TransformController.Events.TransformChanged, this._updateImagePosition, this);
161 }
162
163 /**
164 * @override
165 */
166 onResize() {
Tim van der Lippe1d6e57a2019-09-30 11:55:34167 if (this._imageElement.src) {
Blink Reformat4c46d092018-04-07 15:32:37168 this._updateImagePosition();
Tim van der Lippe1d6e57a2019-09-30 11:55:34169 }
Blink Reformat4c46d092018-04-07 15:32:37170 }
171
172 _updateImagePosition() {
173 const width = this._imageElement.naturalWidth;
174 const height = this._imageElement.naturalHeight;
175 const clientWidth = this.contentElement.clientWidth;
176 const clientHeight = this.contentElement.clientHeight;
177
178 const paddingFraction = 0.1;
179 const paddingX = clientWidth * paddingFraction;
180 const paddingY = clientHeight * paddingFraction;
181 const scaleX = (clientWidth - paddingX) / width;
182 const scaleY = (clientHeight - paddingY) / height;
183 const scale = Math.min(scaleX, scaleY);
184
185 if (this._maskRectangle) {
186 const style = this._maskElement.style;
187 style.width = width + 'px';
188 style.height = height + 'px';
189 style.borderLeftWidth = this._maskRectangle.x + 'px';
190 style.borderTopWidth = this._maskRectangle.y + 'px';
191 style.borderRightWidth = (width - this._maskRectangle.x - this._maskRectangle.width) + 'px';
192 style.borderBottomWidth = (height - this._maskRectangle.y - this._maskRectangle.height) + 'px';
193 }
194 this._transformController.setScaleConstraints(0.5, 10 / scale);
195 let matrix = new WebKitCSSMatrix()
196 .scale(this._transformController.scale(), this._transformController.scale())
197 .translate(clientWidth / 2, clientHeight / 2)
198 .scale(scale, scale)
199 .translate(-width / 2, -height / 2);
200 const bounds = UI.Geometry.boundsForTransformedPoints(matrix, [0, 0, 0, width, height, 0]);
201 this._transformController.clampOffsets(
202 paddingX - bounds.maxX, clientWidth - paddingX - bounds.minX, paddingY - bounds.maxY,
203 clientHeight - paddingY - bounds.minY);
204 matrix = new WebKitCSSMatrix()
205 .translate(this._transformController.offsetX(), this._transformController.offsetY())
206 .multiply(matrix);
207 this._imageContainer.style.webkitTransform = matrix.toString();
208 }
209
210 /**
211 * @param {string=} imageURL
212 */
213 showImage(imageURL) {
214 this._imageContainer.classList.toggle('hidden', !imageURL);
Tim van der Lippe1d6e57a2019-09-30 11:55:34215 if (imageURL) {
Blink Reformat4c46d092018-04-07 15:32:37216 this._imageElement.src = imageURL;
Tim van der Lippe1d6e57a2019-09-30 11:55:34217 }
Blink Reformat4c46d092018-04-07 15:32:37218 }
219
220 /**
221 * @param {?Protocol.DOM.Rect} maskRectangle
222 */
223 setMask(maskRectangle) {
224 this._maskRectangle = maskRectangle;
225 this._maskElement.classList.toggle('hidden', !maskRectangle);
226 }
Rob Paveza96705c62020-01-08 01:37:48227};