blob: 01c91d988658ff8e539b6cbad4248e610b2d83a5 [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.
Blink Reformat4c46d092018-04-07 15:32:374
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);
162 this.registerRequiredCSS('timeline/timelinePaintProfiler.css');
163 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
Tim van der Lippecec9b762020-02-13 15:31:22170 this._transformController = new LayerViewer.TransformController.TransformController(this.contentElement, true);
Blink Reformat4c46d092018-04-07 15:32:37171 this._transformController.addEventListener(
172 LayerViewer.TransformController.Events.TransformChanged, this._updateImagePosition, this);
173 }
174
175 /**
176 * @override
177 */
178 onResize() {
Tim van der Lippe1d6e57a2019-09-30 11:55:34179 if (this._imageElement.src) {
Blink Reformat4c46d092018-04-07 15:32:37180 this._updateImagePosition();
Tim van der Lippe1d6e57a2019-09-30 11:55:34181 }
Blink Reformat4c46d092018-04-07 15:32:37182 }
183
184 _updateImagePosition() {
185 const width = this._imageElement.naturalWidth;
186 const height = this._imageElement.naturalHeight;
187 const clientWidth = this.contentElement.clientWidth;
188 const clientHeight = this.contentElement.clientHeight;
189
190 const paddingFraction = 0.1;
191 const paddingX = clientWidth * paddingFraction;
192 const paddingY = clientHeight * paddingFraction;
193 const scaleX = (clientWidth - paddingX) / width;
194 const scaleY = (clientHeight - paddingY) / height;
195 const scale = Math.min(scaleX, scaleY);
196
197 if (this._maskRectangle) {
198 const style = this._maskElement.style;
199 style.width = width + 'px';
200 style.height = height + 'px';
201 style.borderLeftWidth = this._maskRectangle.x + 'px';
202 style.borderTopWidth = this._maskRectangle.y + 'px';
203 style.borderRightWidth = (width - this._maskRectangle.x - this._maskRectangle.width) + 'px';
204 style.borderBottomWidth = (height - this._maskRectangle.y - this._maskRectangle.height) + 'px';
205 }
206 this._transformController.setScaleConstraints(0.5, 10 / scale);
207 let matrix = new WebKitCSSMatrix()
208 .scale(this._transformController.scale(), this._transformController.scale())
209 .translate(clientWidth / 2, clientHeight / 2)
210 .scale(scale, scale)
211 .translate(-width / 2, -height / 2);
212 const bounds = UI.Geometry.boundsForTransformedPoints(matrix, [0, 0, 0, width, height, 0]);
213 this._transformController.clampOffsets(
214 paddingX - bounds.maxX, clientWidth - paddingX - bounds.minX, paddingY - bounds.maxY,
215 clientHeight - paddingY - bounds.minY);
216 matrix = new WebKitCSSMatrix()
217 .translate(this._transformController.offsetX(), this._transformController.offsetY())
218 .multiply(matrix);
219 this._imageContainer.style.webkitTransform = matrix.toString();
220 }
221
222 /**
223 * @param {string=} imageURL
224 */
225 showImage(imageURL) {
226 this._imageContainer.classList.toggle('hidden', !imageURL);
Tim van der Lippe1d6e57a2019-09-30 11:55:34227 if (imageURL) {
Blink Reformat4c46d092018-04-07 15:32:37228 this._imageElement.src = imageURL;
Tim van der Lippe1d6e57a2019-09-30 11:55:34229 }
Blink Reformat4c46d092018-04-07 15:32:37230 }
231
232 /**
233 * @param {?Protocol.DOM.Rect} maskRectangle
234 */
235 setMask(maskRectangle) {
236 this._maskRectangle = maskRectangle;
237 this._maskElement.classList.toggle('hidden', !maskRectangle);
238 }
Tim van der Lippe0176f6c2020-01-08 11:07:01239}