blob: c17daa3d761b2203aba4102d2818fc6c7ca96b77 [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
Tim van der Lippecec9b762020-02-13 15:31:225import * as LayerViewer from '../layer_viewer/layer_viewer.js';
6import * as SDK from '../sdk/sdk.js'; // eslint-disable-line no-unused-vars
7import * as TimelineModel from '../timeline_model/timeline_model.js';
8import * as UI from '../ui/ui.js';
9
10export class TimelinePaintProfilerView extends UI.SplitWidget.SplitWidget {
Blink Reformat4c46d092018-04-07 15:32:3711 /**
Tim van der Lippecec9b762020-02-13 15:31:2212 * @param {!TimelineModel.TimelineFrameModel.TimelineFrameModel} frameModel
Blink Reformat4c46d092018-04-07 15:32:3713 */
14 constructor(frameModel) {
15 super(false, false);
16 this.element.classList.add('timeline-paint-profiler-view');
17 this.setSidebarSize(60);
18 this.setResizable(false);
19
20 this._frameModel = frameModel;
Tim van der Lippecec9b762020-02-13 15:31:2221 this._logAndImageSplitWidget = new UI.SplitWidget.SplitWidget(true, false);
Blink Reformat4c46d092018-04-07 15:32:3722 this._logAndImageSplitWidget.element.classList.add('timeline-paint-profiler-log-split');
23 this.setMainWidget(this._logAndImageSplitWidget);
Tim van der Lippe0176f6c2020-01-08 11:07:0124 this._imageView = new TimelinePaintImageView();
Blink Reformat4c46d092018-04-07 15:32:3725 this._logAndImageSplitWidget.setMainWidget(this._imageView);
26
Tim van der Lippecec9b762020-02-13 15:31:2227 this._paintProfilerView =
28 new LayerViewer.PaintProfilerView.PaintProfilerView(this._imageView.showImage.bind(this._imageView));
Blink Reformat4c46d092018-04-07 15:32:3729 this._paintProfilerView.addEventListener(
30 LayerViewer.PaintProfilerView.Events.WindowChanged, this._onWindowChanged, this);
31 this.setSidebarWidget(this._paintProfilerView);
32
Tim van der Lippecec9b762020-02-13 15:31:2233 this._logTreeView = new LayerViewer.PaintProfilerView.PaintProfilerCommandLogView();
Blink Reformat4c46d092018-04-07 15:32:3734 this._logAndImageSplitWidget.setSidebarWidget(this._logTreeView);
35
36 this._needsUpdateWhenVisible = false;
Tim van der Lippecec9b762020-02-13 15:31:2237 /** @type {?SDK.PaintProfiler.PaintProfilerSnapshot} */
Blink Reformat4c46d092018-04-07 15:32:3738 this._pendingSnapshot = null;
39 /** @type {?SDK.TracingModel.Event} */
40 this._event = null;
Tim van der Lippecec9b762020-02-13 15:31:2241 /** @type {?SDK.PaintProfiler.PaintProfilerModel} */
Blink Reformat4c46d092018-04-07 15:32:3742 this._paintProfilerModel = null;
Tim van der Lippecec9b762020-02-13 15:31:2243 /** @type {?SDK.PaintProfiler.PaintProfilerSnapshot} */
Blink Reformat4c46d092018-04-07 15:32:3744 this._lastLoadedSnapshot = null;
45 }
46
47 /**
48 * @override
49 */
50 wasShown() {
51 if (this._needsUpdateWhenVisible) {
52 this._needsUpdateWhenVisible = false;
53 this._update();
54 }
55 }
56
57 /**
Tim van der Lippecec9b762020-02-13 15:31:2258 * @param {!SDK.PaintProfiler.PaintProfilerSnapshot} snapshot
Blink Reformat4c46d092018-04-07 15:32:3759 */
60 setSnapshot(snapshot) {
61 this._releaseSnapshot();
62 this._pendingSnapshot = snapshot;
63 this._event = null;
64 this._updateWhenVisible();
65 }
66
67 /**
Tim van der Lippecec9b762020-02-13 15:31:2268 * @param {!SDK.PaintProfiler.PaintProfilerModel} paintProfilerModel
Blink Reformat4c46d092018-04-07 15:32:3769 * @param {!SDK.TracingModel.Event} event
70 * @return {boolean}
71 */
72 setEvent(paintProfilerModel, event) {
73 this._releaseSnapshot();
74 this._paintProfilerModel = paintProfilerModel;
75 this._pendingSnapshot = null;
76 this._event = event;
77
78 this._updateWhenVisible();
Tim van der Lippe1d6e57a2019-09-30 11:55:3479 if (this._event.name === TimelineModel.TimelineModel.RecordType.Paint) {
Tim van der Lippecec9b762020-02-13 15:31:2280 return !!TimelineModel.TimelineModel.TimelineData.forEvent(event).picture;
Tim van der Lippe1d6e57a2019-09-30 11:55:3481 }
82 if (this._event.name === TimelineModel.TimelineModel.RecordType.RasterTask) {
Blink Reformat4c46d092018-04-07 15:32:3783 return this._frameModel.hasRasterTile(this._event);
Tim van der Lippe1d6e57a2019-09-30 11:55:3484 }
Blink Reformat4c46d092018-04-07 15:32:3785 return false;
86 }
87
88 _updateWhenVisible() {
Tim van der Lippe1d6e57a2019-09-30 11:55:3489 if (this.isShowing()) {
Blink Reformat4c46d092018-04-07 15:32:3790 this._update();
Tim van der Lippe1d6e57a2019-09-30 11:55:3491 } else {
Blink Reformat4c46d092018-04-07 15:32:3792 this._needsUpdateWhenVisible = true;
Tim van der Lippe1d6e57a2019-09-30 11:55:3493 }
Blink Reformat4c46d092018-04-07 15:32:3794 }
95
96 _update() {
97 this._logTreeView.setCommandLog([]);
98 this._paintProfilerView.setSnapshotAndLog(null, [], null);
99
Simon Zündb1a8ca52020-09-29 07:47:22100 /** @type {!Promise<?{rect: ?Protocol.DOM.Rect, snapshot: !SDK.PaintProfiler.PaintProfilerSnapshot}>} */
Blink Reformat4c46d092018-04-07 15:32:37101 let snapshotPromise;
102 if (this._pendingSnapshot) {
103 snapshotPromise = Promise.resolve({rect: null, snapshot: this._pendingSnapshot});
Simon Zündb1a8ca52020-09-29 07:47:22104 } else if (this._event && this._event.name === TimelineModel.TimelineModel.RecordType.Paint) {
105 /** @type {!SDK.TracingModel.ObjectSnapshot} */
106 const picture = /** @type {!SDK.TracingModel.ObjectSnapshot} */ (
107 TimelineModel.TimelineModel.TimelineData.forEvent(this._event).picture);
Blink Reformat4c46d092018-04-07 15:32:37108 snapshotPromise = picture.objectPromise()
Simon Zündb1a8ca52020-09-29 07:47:22109 .then(
110 data => /** @type {!SDK.PaintProfiler.PaintProfilerModel} */ (this._paintProfilerModel)
111 .loadSnapshot(data['skp64']))
Blink Reformat4c46d092018-04-07 15:32:37112 .then(snapshot => snapshot && {rect: null, snapshot: snapshot});
Simon Zündb1a8ca52020-09-29 07:47:22113 } else if (this._event && this._event.name === TimelineModel.TimelineModel.RecordType.RasterTask) {
Blink Reformat4c46d092018-04-07 15:32:37114 snapshotPromise = this._frameModel.rasterTilePromise(this._event);
115 } else {
116 console.assert(false, 'Unexpected event type or no snapshot');
117 return;
118 }
119 snapshotPromise.then(snapshotWithRect => {
120 this._releaseSnapshot();
121 if (!snapshotWithRect) {
122 this._imageView.showImage();
123 return;
124 }
125 const snapshot = snapshotWithRect.snapshot;
126 this._lastLoadedSnapshot = snapshot;
127 this._imageView.setMask(snapshotWithRect.rect);
Simon Zündb1a8ca52020-09-29 07:47:22128 snapshot.commandLog().then(log => onCommandLogDone.call(this, snapshot, snapshotWithRect.rect, log || []));
Blink Reformat4c46d092018-04-07 15:32:37129 });
130
131 /**
Tim van der Lippecec9b762020-02-13 15:31:22132 * @param {!SDK.PaintProfiler.PaintProfilerSnapshot} snapshot
Blink Reformat4c46d092018-04-07 15:32:37133 * @param {?Protocol.DOM.Rect} clipRect
Tim van der Lippecec9b762020-02-13 15:31:22134 * @param {!Array.<!SDK.PaintProfiler.PaintProfilerLogItem>=} log
Tim van der Lippe0176f6c2020-01-08 11:07:01135 * @this {TimelinePaintProfilerView}
Blink Reformat4c46d092018-04-07 15:32:37136 */
137 function onCommandLogDone(snapshot, clipRect, log) {
138 this._logTreeView.setCommandLog(log || []);
139 this._paintProfilerView.setSnapshotAndLog(snapshot, log || [], clipRect);
140 }
141 }
142
143 _releaseSnapshot() {
Tim van der Lippe1d6e57a2019-09-30 11:55:34144 if (!this._lastLoadedSnapshot) {
Blink Reformat4c46d092018-04-07 15:32:37145 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34146 }
Blink Reformat4c46d092018-04-07 15:32:37147 this._lastLoadedSnapshot.release();
148 this._lastLoadedSnapshot = null;
149 }
150
151 _onWindowChanged() {
152 this._logTreeView.updateWindow(this._paintProfilerView.selectionWindow());
153 }
Tim van der Lippe0176f6c2020-01-08 11:07:01154}
Blink Reformat4c46d092018-04-07 15:32:37155
156/**
157 * @unrestricted
158 */
Tim van der Lippecec9b762020-02-13 15:31:22159export class TimelinePaintImageView extends UI.Widget.Widget {
Blink Reformat4c46d092018-04-07 15:32:37160 constructor() {
161 super(true);
Jack Franklin71519f82020-11-03 12:08:59162 this.registerRequiredCSS('timeline/timelinePaintProfiler.css', {enableLegacyPatching: true});
Blink Reformat4c46d092018-04-07 15:32:37163 this.contentElement.classList.add('fill', 'paint-profiler-image-view');
164 this._imageContainer = this.contentElement.createChild('div', 'paint-profiler-image-container');
Simon Zündb1a8ca52020-09-29 07:47:22165 /** @type {!HTMLImageElement} */
166 this._imageElement = /** @type {!HTMLImageElement} */ (this._imageContainer.createChild('img'));
Blink Reformat4c46d092018-04-07 15:32:37167 this._maskElement = this._imageContainer.createChild('div');
168 this._imageElement.addEventListener('load', this._updateImagePosition.bind(this), false);
169
Alex Rudenkob151cb22020-10-12 13:47:05170 this._transformController = new LayerViewer.TransformController.TransformController(
171 /** @type {!HTMLElement} */ (this.contentElement), true);
Blink Reformat4c46d092018-04-07 15:32:37172 this._transformController.addEventListener(
173 LayerViewer.TransformController.Events.TransformChanged, this._updateImagePosition, this);
174 }
175
176 /**
177 * @override
178 */
179 onResize() {
Tim van der Lippe1d6e57a2019-09-30 11:55:34180 if (this._imageElement.src) {
Blink Reformat4c46d092018-04-07 15:32:37181 this._updateImagePosition();
Tim van der Lippe1d6e57a2019-09-30 11:55:34182 }
Blink Reformat4c46d092018-04-07 15:32:37183 }
184
185 _updateImagePosition() {
186 const width = this._imageElement.naturalWidth;
187 const height = this._imageElement.naturalHeight;
188 const clientWidth = this.contentElement.clientWidth;
189 const clientHeight = this.contentElement.clientHeight;
190
191 const paddingFraction = 0.1;
192 const paddingX = clientWidth * paddingFraction;
193 const paddingY = clientHeight * paddingFraction;
194 const scaleX = (clientWidth - paddingX) / width;
195 const scaleY = (clientHeight - paddingY) / height;
196 const scale = Math.min(scaleX, scaleY);
197
198 if (this._maskRectangle) {
199 const style = this._maskElement.style;
200 style.width = width + 'px';
201 style.height = height + 'px';
202 style.borderLeftWidth = this._maskRectangle.x + 'px';
203 style.borderTopWidth = this._maskRectangle.y + 'px';
204 style.borderRightWidth = (width - this._maskRectangle.x - this._maskRectangle.width) + 'px';
205 style.borderBottomWidth = (height - this._maskRectangle.y - this._maskRectangle.height) + 'px';
206 }
207 this._transformController.setScaleConstraints(0.5, 10 / scale);
208 let matrix = new WebKitCSSMatrix()
209 .scale(this._transformController.scale(), this._transformController.scale())
210 .translate(clientWidth / 2, clientHeight / 2)
211 .scale(scale, scale)
212 .translate(-width / 2, -height / 2);
213 const bounds = UI.Geometry.boundsForTransformedPoints(matrix, [0, 0, 0, width, height, 0]);
214 this._transformController.clampOffsets(
215 paddingX - bounds.maxX, clientWidth - paddingX - bounds.minX, paddingY - bounds.maxY,
216 clientHeight - paddingY - bounds.minY);
217 matrix = new WebKitCSSMatrix()
218 .translate(this._transformController.offsetX(), this._transformController.offsetY())
219 .multiply(matrix);
220 this._imageContainer.style.webkitTransform = matrix.toString();
221 }
222
223 /**
224 * @param {string=} imageURL
225 */
226 showImage(imageURL) {
227 this._imageContainer.classList.toggle('hidden', !imageURL);
Tim van der Lippe1d6e57a2019-09-30 11:55:34228 if (imageURL) {
Blink Reformat4c46d092018-04-07 15:32:37229 this._imageElement.src = imageURL;
Tim van der Lippe1d6e57a2019-09-30 11:55:34230 }
Blink Reformat4c46d092018-04-07 15:32:37231 }
232
233 /**
234 * @param {?Protocol.DOM.Rect} maskRectangle
235 */
236 setMask(maskRectangle) {
237 this._maskRectangle = maskRectangle;
238 this._maskElement.classList.toggle('hidden', !maskRectangle);
239 }
Tim van der Lippe0176f6c2020-01-08 11:07:01240}