blob: 941e3fe2a1a9dc94b9f2b37cfd03ef13dee3f49b [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
100 let snapshotPromise;
101 if (this._pendingSnapshot) {
102 snapshotPromise = Promise.resolve({rect: null, snapshot: this._pendingSnapshot});
103 } else if (this._event.name === TimelineModel.TimelineModel.RecordType.Paint) {
Tim van der Lippecec9b762020-02-13 15:31:22104 const picture = TimelineModel.TimelineModel.TimelineData.forEvent(this._event).picture;
Blink Reformat4c46d092018-04-07 15:32:37105 snapshotPromise = picture.objectPromise()
106 .then(data => this._paintProfilerModel.loadSnapshot(data['skp64']))
107 .then(snapshot => snapshot && {rect: null, snapshot: snapshot});
108 } else if (this._event.name === TimelineModel.TimelineModel.RecordType.RasterTask) {
109 snapshotPromise = this._frameModel.rasterTilePromise(this._event);
110 } else {
111 console.assert(false, 'Unexpected event type or no snapshot');
112 return;
113 }
114 snapshotPromise.then(snapshotWithRect => {
115 this._releaseSnapshot();
116 if (!snapshotWithRect) {
117 this._imageView.showImage();
118 return;
119 }
120 const snapshot = snapshotWithRect.snapshot;
121 this._lastLoadedSnapshot = snapshot;
122 this._imageView.setMask(snapshotWithRect.rect);
123 snapshot.commandLog().then(log => onCommandLogDone.call(this, snapshot, snapshotWithRect.rect, log));
124 });
125
126 /**
Tim van der Lippecec9b762020-02-13 15:31:22127 * @param {!SDK.PaintProfiler.PaintProfilerSnapshot} snapshot
Blink Reformat4c46d092018-04-07 15:32:37128 * @param {?Protocol.DOM.Rect} clipRect
Tim van der Lippecec9b762020-02-13 15:31:22129 * @param {!Array.<!SDK.PaintProfiler.PaintProfilerLogItem>=} log
Tim van der Lippe0176f6c2020-01-08 11:07:01130 * @this {TimelinePaintProfilerView}
Blink Reformat4c46d092018-04-07 15:32:37131 */
132 function onCommandLogDone(snapshot, clipRect, log) {
133 this._logTreeView.setCommandLog(log || []);
134 this._paintProfilerView.setSnapshotAndLog(snapshot, log || [], clipRect);
135 }
136 }
137
138 _releaseSnapshot() {
Tim van der Lippe1d6e57a2019-09-30 11:55:34139 if (!this._lastLoadedSnapshot) {
Blink Reformat4c46d092018-04-07 15:32:37140 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34141 }
Blink Reformat4c46d092018-04-07 15:32:37142 this._lastLoadedSnapshot.release();
143 this._lastLoadedSnapshot = null;
144 }
145
146 _onWindowChanged() {
147 this._logTreeView.updateWindow(this._paintProfilerView.selectionWindow());
148 }
Tim van der Lippe0176f6c2020-01-08 11:07:01149}
Blink Reformat4c46d092018-04-07 15:32:37150
151/**
152 * @unrestricted
153 */
Tim van der Lippecec9b762020-02-13 15:31:22154export class TimelinePaintImageView extends UI.Widget.Widget {
Blink Reformat4c46d092018-04-07 15:32:37155 constructor() {
156 super(true);
157 this.registerRequiredCSS('timeline/timelinePaintProfiler.css');
158 this.contentElement.classList.add('fill', 'paint-profiler-image-view');
159 this._imageContainer = this.contentElement.createChild('div', 'paint-profiler-image-container');
160 this._imageElement = this._imageContainer.createChild('img');
161 this._maskElement = this._imageContainer.createChild('div');
162 this._imageElement.addEventListener('load', this._updateImagePosition.bind(this), false);
163
Tim van der Lippecec9b762020-02-13 15:31:22164 this._transformController = new LayerViewer.TransformController.TransformController(this.contentElement, true);
Blink Reformat4c46d092018-04-07 15:32:37165 this._transformController.addEventListener(
166 LayerViewer.TransformController.Events.TransformChanged, this._updateImagePosition, this);
167 }
168
169 /**
170 * @override
171 */
172 onResize() {
Tim van der Lippe1d6e57a2019-09-30 11:55:34173 if (this._imageElement.src) {
Blink Reformat4c46d092018-04-07 15:32:37174 this._updateImagePosition();
Tim van der Lippe1d6e57a2019-09-30 11:55:34175 }
Blink Reformat4c46d092018-04-07 15:32:37176 }
177
178 _updateImagePosition() {
179 const width = this._imageElement.naturalWidth;
180 const height = this._imageElement.naturalHeight;
181 const clientWidth = this.contentElement.clientWidth;
182 const clientHeight = this.contentElement.clientHeight;
183
184 const paddingFraction = 0.1;
185 const paddingX = clientWidth * paddingFraction;
186 const paddingY = clientHeight * paddingFraction;
187 const scaleX = (clientWidth - paddingX) / width;
188 const scaleY = (clientHeight - paddingY) / height;
189 const scale = Math.min(scaleX, scaleY);
190
191 if (this._maskRectangle) {
192 const style = this._maskElement.style;
193 style.width = width + 'px';
194 style.height = height + 'px';
195 style.borderLeftWidth = this._maskRectangle.x + 'px';
196 style.borderTopWidth = this._maskRectangle.y + 'px';
197 style.borderRightWidth = (width - this._maskRectangle.x - this._maskRectangle.width) + 'px';
198 style.borderBottomWidth = (height - this._maskRectangle.y - this._maskRectangle.height) + 'px';
199 }
200 this._transformController.setScaleConstraints(0.5, 10 / scale);
201 let matrix = new WebKitCSSMatrix()
202 .scale(this._transformController.scale(), this._transformController.scale())
203 .translate(clientWidth / 2, clientHeight / 2)
204 .scale(scale, scale)
205 .translate(-width / 2, -height / 2);
206 const bounds = UI.Geometry.boundsForTransformedPoints(matrix, [0, 0, 0, width, height, 0]);
207 this._transformController.clampOffsets(
208 paddingX - bounds.maxX, clientWidth - paddingX - bounds.minX, paddingY - bounds.maxY,
209 clientHeight - paddingY - bounds.minY);
210 matrix = new WebKitCSSMatrix()
211 .translate(this._transformController.offsetX(), this._transformController.offsetY())
212 .multiply(matrix);
213 this._imageContainer.style.webkitTransform = matrix.toString();
214 }
215
216 /**
217 * @param {string=} imageURL
218 */
219 showImage(imageURL) {
220 this._imageContainer.classList.toggle('hidden', !imageURL);
Tim van der Lippe1d6e57a2019-09-30 11:55:34221 if (imageURL) {
Blink Reformat4c46d092018-04-07 15:32:37222 this._imageElement.src = imageURL;
Tim van der Lippe1d6e57a2019-09-30 11:55:34223 }
Blink Reformat4c46d092018-04-07 15:32:37224 }
225
226 /**
227 * @param {?Protocol.DOM.Rect} maskRectangle
228 */
229 setMask(maskRectangle) {
230 this._maskRectangle = maskRectangle;
231 this._maskElement.classList.toggle('hidden', !maskRectangle);
232 }
Tim van der Lippe0176f6c2020-01-08 11:07:01233}