OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
11 * copyright notice, this list of conditions and the following disclaimer | 11 * copyright notice, this list of conditions and the following disclaimer |
12 * in the documentation and/or other materials provided with the | 12 * in the documentation and/or other materials provided with the |
13 * distribution. | 13 * distribution. |
14 * * Neither the name of Google Inc. nor the names of its | 14 * * Neither the name of Google Inc. nor the names of its |
15 * contributors may be used to endorse or promote products derived from | 15 * contributors may be used to endorse or promote products derived from |
16 * this software without specific prior written permission. | 16 * this software without specific prior written permission. |
17 * | 17 * |
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 */ | 29 */ |
30 | |
31 /** | 30 /** |
32 * @constructor | 31 * @unrestricted |
33 * @extends {WebInspector.SDKModel} | 32 */ |
34 */ | 33 WebInspector.LayerTreeModel = class extends WebInspector.SDKModel { |
35 WebInspector.LayerTreeModel = function(target) | 34 constructor(target) { |
36 { | 35 super(WebInspector.LayerTreeModel, target); |
37 WebInspector.SDKModel.call(this, WebInspector.LayerTreeModel, target); | |
38 target.registerLayerTreeDispatcher(new WebInspector.LayerTreeDispatcher(this
)); | 36 target.registerLayerTreeDispatcher(new WebInspector.LayerTreeDispatcher(this
)); |
39 WebInspector.targetManager.addEventListener(WebInspector.TargetManager.Event
s.MainFrameNavigated, this._onMainFrameNavigated, this); | 37 WebInspector.targetManager.addEventListener( |
| 38 WebInspector.TargetManager.Events.MainFrameNavigated, this._onMainFrameN
avigated, this); |
40 /** @type {?WebInspector.LayerTreeBase} */ | 39 /** @type {?WebInspector.LayerTreeBase} */ |
41 this._layerTree = null; | 40 this._layerTree = null; |
| 41 } |
| 42 |
| 43 /** |
| 44 * @param {!WebInspector.Target} target |
| 45 * @return {?WebInspector.LayerTreeModel} |
| 46 */ |
| 47 static fromTarget(target) { |
| 48 if (!target.hasDOMCapability()) |
| 49 return null; |
| 50 |
| 51 var model = /** @type {?WebInspector.LayerTreeModel} */ (target.model(WebIns
pector.LayerTreeModel)); |
| 52 if (!model) |
| 53 model = new WebInspector.LayerTreeModel(target); |
| 54 return model; |
| 55 } |
| 56 |
| 57 disable() { |
| 58 if (!this._enabled) |
| 59 return; |
| 60 this._enabled = false; |
| 61 this.target().layerTreeAgent().disable(); |
| 62 } |
| 63 |
| 64 enable() { |
| 65 if (this._enabled) |
| 66 return; |
| 67 this._enabled = true; |
| 68 this._forceEnable(); |
| 69 } |
| 70 |
| 71 _forceEnable() { |
| 72 this._lastPaintRectByLayerId = {}; |
| 73 if (!this._layerTree) |
| 74 this._layerTree = new WebInspector.AgentLayerTree(this.target()); |
| 75 this.target().layerTreeAgent().enable(); |
| 76 } |
| 77 |
| 78 /** |
| 79 * @return {?WebInspector.LayerTreeBase} |
| 80 */ |
| 81 layerTree() { |
| 82 return this._layerTree; |
| 83 } |
| 84 |
| 85 /** |
| 86 * @param {?Array.<!LayerTreeAgent.Layer>} layers |
| 87 */ |
| 88 _layerTreeChanged(layers) { |
| 89 if (!this._enabled) |
| 90 return; |
| 91 var layerTree = /** @type {!WebInspector.AgentLayerTree} */ (this._layerTree
); |
| 92 layerTree.setLayers(layers, onLayersSet.bind(this)); |
| 93 |
| 94 /** |
| 95 * @this {WebInspector.LayerTreeModel} |
| 96 */ |
| 97 function onLayersSet() { |
| 98 for (var layerId in this._lastPaintRectByLayerId) { |
| 99 var lastPaintRect = this._lastPaintRectByLayerId[layerId]; |
| 100 var layer = layerTree.layerById(layerId); |
| 101 if (layer) |
| 102 layer._lastPaintRect = lastPaintRect; |
| 103 } |
| 104 this._lastPaintRectByLayerId = {}; |
| 105 |
| 106 this.dispatchEventToListeners(WebInspector.LayerTreeModel.Events.LayerTree
Changed); |
| 107 } |
| 108 } |
| 109 |
| 110 /** |
| 111 * @param {!LayerTreeAgent.LayerId} layerId |
| 112 * @param {!DOMAgent.Rect} clipRect |
| 113 */ |
| 114 _layerPainted(layerId, clipRect) { |
| 115 if (!this._enabled) |
| 116 return; |
| 117 var layerTree = /** @type {!WebInspector.AgentLayerTree} */ (this._layerTree
); |
| 118 var layer = layerTree.layerById(layerId); |
| 119 if (!layer) { |
| 120 this._lastPaintRectByLayerId[layerId] = clipRect; |
| 121 return; |
| 122 } |
| 123 layer._didPaint(clipRect); |
| 124 this.dispatchEventToListeners(WebInspector.LayerTreeModel.Events.LayerPainte
d, layer); |
| 125 } |
| 126 |
| 127 _onMainFrameNavigated() { |
| 128 this._layerTree = null; |
| 129 if (this._enabled) |
| 130 this._forceEnable(); |
| 131 } |
42 }; | 132 }; |
43 | 133 |
44 /** @enum {symbol} */ | 134 /** @enum {symbol} */ |
45 WebInspector.LayerTreeModel.Events = { | 135 WebInspector.LayerTreeModel.Events = { |
46 LayerTreeChanged: Symbol("LayerTreeChanged"), | 136 LayerTreeChanged: Symbol('LayerTreeChanged'), |
47 LayerPainted: Symbol("LayerPainted"), | 137 LayerPainted: Symbol('LayerPainted'), |
48 }; | 138 }; |
49 | 139 |
50 WebInspector.LayerTreeModel.prototype = { | 140 /** |
51 disable: function() | 141 * @unrestricted |
52 { | 142 */ |
53 if (!this._enabled) | 143 WebInspector.AgentLayerTree = class extends WebInspector.LayerTreeBase { |
54 return; | 144 /** |
55 this._enabled = false; | 145 * @param {?WebInspector.Target} target |
56 this.target().layerTreeAgent().disable(); | 146 */ |
57 }, | 147 constructor(target) { |
58 | 148 super(target); |
59 enable: function() | 149 } |
60 { | 150 |
61 if (this._enabled) | 151 /** |
62 return; | 152 * @param {?Array.<!LayerTreeAgent.Layer>} payload |
63 this._enabled = true; | 153 * @param {function()} callback |
64 this._forceEnable(); | 154 */ |
65 }, | 155 setLayers(payload, callback) { |
66 | 156 if (!payload) { |
67 _forceEnable: function() | 157 onBackendNodeIdsResolved.call(this); |
68 { | 158 return; |
69 this._lastPaintRectByLayerId = {}; | 159 } |
70 if (!this._layerTree) | 160 |
71 this._layerTree = new WebInspector.AgentLayerTree(this.target()); | 161 var idsToResolve = new Set(); |
72 this.target().layerTreeAgent().enable(); | 162 for (var i = 0; i < payload.length; ++i) { |
73 }, | 163 var backendNodeId = payload[i].backendNodeId; |
| 164 if (!backendNodeId || this._backendNodeIdToNode.has(backendNodeId)) |
| 165 continue; |
| 166 idsToResolve.add(backendNodeId); |
| 167 } |
| 168 this._resolveBackendNodeIds(idsToResolve, onBackendNodeIdsResolved.bind(this
)); |
74 | 169 |
75 /** | 170 /** |
76 * @return {?WebInspector.LayerTreeBase} | 171 * @this {WebInspector.AgentLayerTree} |
77 */ | 172 */ |
78 layerTree: function() | 173 function onBackendNodeIdsResolved() { |
79 { | 174 this._innerSetLayers(payload); |
80 return this._layerTree; | 175 callback(); |
81 }, | 176 } |
82 | 177 } |
83 /** | 178 |
84 * @param {?Array.<!LayerTreeAgent.Layer>} layers | 179 /** |
85 */ | 180 * @param {?Array.<!LayerTreeAgent.Layer>} layers |
86 _layerTreeChanged: function(layers) | 181 */ |
87 { | 182 _innerSetLayers(layers) { |
88 if (!this._enabled) | 183 this.setRoot(null); |
89 return; | 184 this.setContentRoot(null); |
90 var layerTree = /** @type {!WebInspector.AgentLayerTree} */ (this._layer
Tree); | 185 // Payload will be null when not in the composited mode. |
91 layerTree.setLayers(layers, onLayersSet.bind(this)); | 186 if (!layers) |
92 | 187 return; |
93 /** | 188 var root; |
94 * @this {WebInspector.LayerTreeModel} | 189 var oldLayersById = this._layersById; |
95 */ | 190 this._layersById = {}; |
96 function onLayersSet() | 191 for (var i = 0; i < layers.length; ++i) { |
97 { | 192 var layerId = layers[i].layerId; |
98 for (var layerId in this._lastPaintRectByLayerId) { | 193 var layer = oldLayersById[layerId]; |
99 var lastPaintRect = this._lastPaintRectByLayerId[layerId]; | 194 if (layer) |
100 var layer = layerTree.layerById(layerId); | 195 layer._reset(layers[i]); |
101 if (layer) | 196 else |
102 layer._lastPaintRect = lastPaintRect; | 197 layer = new WebInspector.AgentLayer(this._target, layers[i]); |
103 } | 198 this._layersById[layerId] = layer; |
104 this._lastPaintRectByLayerId = {}; | 199 var backendNodeId = layers[i].backendNodeId; |
105 | 200 if (backendNodeId) |
106 this.dispatchEventToListeners(WebInspector.LayerTreeModel.Events.Lay
erTreeChanged); | 201 layer._setNode(this._backendNodeIdToNode.get(backendNodeId)); |
107 } | 202 if (!this.contentRoot() && layer.drawsContent()) |
108 }, | 203 this.setContentRoot(layer); |
109 | 204 var parentId = layer.parentId(); |
110 /** | 205 if (parentId) { |
111 * @param {!LayerTreeAgent.LayerId} layerId | 206 var parent = this._layersById[parentId]; |
112 * @param {!DOMAgent.Rect} clipRect | 207 if (!parent) |
113 */ | 208 console.assert(parent, 'missing parent ' + parentId + ' for layer ' +
layerId); |
114 _layerPainted: function(layerId, clipRect) | 209 parent.addChild(layer); |
115 { | 210 } else { |
116 if (!this._enabled) | 211 if (root) |
117 return; | 212 console.assert(false, 'Multiple root layers'); |
118 var layerTree = /** @type {!WebInspector.AgentLayerTree} */ (this._layer
Tree); | 213 root = layer; |
119 var layer = layerTree.layerById(layerId); | 214 } |
120 if (!layer) { | 215 } |
121 this._lastPaintRectByLayerId[layerId] = clipRect; | 216 if (root) { |
122 return; | 217 this.setRoot(root); |
123 } | 218 root._calculateQuad(new WebKitCSSMatrix()); |
124 layer._didPaint(clipRect); | 219 } |
125 this.dispatchEventToListeners(WebInspector.LayerTreeModel.Events.LayerPa
inted, layer); | 220 } |
126 }, | |
127 | |
128 _onMainFrameNavigated: function() | |
129 { | |
130 this._layerTree = null; | |
131 if (this._enabled) | |
132 this._forceEnable(); | |
133 }, | |
134 | |
135 __proto__: WebInspector.SDKModel.prototype | |
136 }; | 221 }; |
137 | 222 |
138 /** | 223 /** |
139 * @constructor | |
140 * @param {?WebInspector.Target} target | |
141 * @extends {WebInspector.LayerTreeBase} | |
142 */ | |
143 WebInspector.AgentLayerTree = function(target) | |
144 { | |
145 WebInspector.LayerTreeBase.call(this, target); | |
146 }; | |
147 | |
148 WebInspector.AgentLayerTree.prototype = { | |
149 /** | |
150 * @param {?Array.<!LayerTreeAgent.Layer>} payload | |
151 * @param {function()} callback | |
152 */ | |
153 setLayers: function(payload, callback) | |
154 { | |
155 if (!payload) { | |
156 onBackendNodeIdsResolved.call(this); | |
157 return; | |
158 } | |
159 | |
160 var idsToResolve = new Set(); | |
161 for (var i = 0; i < payload.length; ++i) { | |
162 var backendNodeId = payload[i].backendNodeId; | |
163 if (!backendNodeId || this._backendNodeIdToNode.has(backendNodeId)) | |
164 continue; | |
165 idsToResolve.add(backendNodeId); | |
166 } | |
167 this._resolveBackendNodeIds(idsToResolve, onBackendNodeIdsResolved.bind(
this)); | |
168 | |
169 /** | |
170 * @this {WebInspector.AgentLayerTree} | |
171 */ | |
172 function onBackendNodeIdsResolved() | |
173 { | |
174 this._innerSetLayers(payload); | |
175 callback(); | |
176 } | |
177 }, | |
178 | |
179 /** | |
180 * @param {?Array.<!LayerTreeAgent.Layer>} layers | |
181 */ | |
182 _innerSetLayers: function(layers) | |
183 { | |
184 this.setRoot(null); | |
185 this.setContentRoot(null); | |
186 // Payload will be null when not in the composited mode. | |
187 if (!layers) | |
188 return; | |
189 var root; | |
190 var oldLayersById = this._layersById; | |
191 this._layersById = {}; | |
192 for (var i = 0; i < layers.length; ++i) { | |
193 var layerId = layers[i].layerId; | |
194 var layer = oldLayersById[layerId]; | |
195 if (layer) | |
196 layer._reset(layers[i]); | |
197 else | |
198 layer = new WebInspector.AgentLayer(this._target, layers[i]); | |
199 this._layersById[layerId] = layer; | |
200 var backendNodeId = layers[i].backendNodeId; | |
201 if (backendNodeId) | |
202 layer._setNode(this._backendNodeIdToNode.get(backendNodeId)); | |
203 if (!this.contentRoot() && layer.drawsContent()) | |
204 this.setContentRoot(layer); | |
205 var parentId = layer.parentId(); | |
206 if (parentId) { | |
207 var parent = this._layersById[parentId]; | |
208 if (!parent) | |
209 console.assert(parent, "missing parent " + parentId + " for
layer " + layerId); | |
210 parent.addChild(layer); | |
211 } else { | |
212 if (root) | |
213 console.assert(false, "Multiple root layers"); | |
214 root = layer; | |
215 } | |
216 } | |
217 if (root) { | |
218 this.setRoot(root); | |
219 root._calculateQuad(new WebKitCSSMatrix()); | |
220 } | |
221 }, | |
222 | |
223 __proto__: WebInspector.LayerTreeBase.prototype | |
224 }; | |
225 | |
226 /** | |
227 * @constructor | |
228 * @implements {WebInspector.Layer} | 224 * @implements {WebInspector.Layer} |
229 * @param {?WebInspector.Target} target | 225 * @unrestricted |
230 * @param {!LayerTreeAgent.Layer} layerPayload | |
231 */ | 226 */ |
232 WebInspector.AgentLayer = function(target, layerPayload) | 227 WebInspector.AgentLayer = class { |
233 { | 228 /** |
| 229 * @param {?WebInspector.Target} target |
| 230 * @param {!LayerTreeAgent.Layer} layerPayload |
| 231 */ |
| 232 constructor(target, layerPayload) { |
234 this._target = target; | 233 this._target = target; |
235 this._reset(layerPayload); | 234 this._reset(layerPayload); |
| 235 } |
| 236 |
| 237 /** |
| 238 * @override |
| 239 * @return {string} |
| 240 */ |
| 241 id() { |
| 242 return this._layerPayload.layerId; |
| 243 } |
| 244 |
| 245 /** |
| 246 * @override |
| 247 * @return {?string} |
| 248 */ |
| 249 parentId() { |
| 250 return this._layerPayload.parentLayerId; |
| 251 } |
| 252 |
| 253 /** |
| 254 * @override |
| 255 * @return {?WebInspector.Layer} |
| 256 */ |
| 257 parent() { |
| 258 return this._parent; |
| 259 } |
| 260 |
| 261 /** |
| 262 * @override |
| 263 * @return {boolean} |
| 264 */ |
| 265 isRoot() { |
| 266 return !this.parentId(); |
| 267 } |
| 268 |
| 269 /** |
| 270 * @override |
| 271 * @return {!Array.<!WebInspector.Layer>} |
| 272 */ |
| 273 children() { |
| 274 return this._children; |
| 275 } |
| 276 |
| 277 /** |
| 278 * @override |
| 279 * @param {!WebInspector.Layer} child |
| 280 */ |
| 281 addChild(child) { |
| 282 if (child._parent) |
| 283 console.assert(false, 'Child already has a parent'); |
| 284 this._children.push(child); |
| 285 child._parent = this; |
| 286 } |
| 287 |
| 288 /** |
| 289 * @param {?WebInspector.DOMNode} node |
| 290 */ |
| 291 _setNode(node) { |
| 292 this._node = node; |
| 293 } |
| 294 |
| 295 /** |
| 296 * @override |
| 297 * @return {?WebInspector.DOMNode} |
| 298 */ |
| 299 node() { |
| 300 return this._node; |
| 301 } |
| 302 |
| 303 /** |
| 304 * @override |
| 305 * @return {?WebInspector.DOMNode} |
| 306 */ |
| 307 nodeForSelfOrAncestor() { |
| 308 for (var layer = this; layer; layer = layer._parent) { |
| 309 if (layer._node) |
| 310 return layer._node; |
| 311 } |
| 312 return null; |
| 313 } |
| 314 |
| 315 /** |
| 316 * @override |
| 317 * @return {number} |
| 318 */ |
| 319 offsetX() { |
| 320 return this._layerPayload.offsetX; |
| 321 } |
| 322 |
| 323 /** |
| 324 * @override |
| 325 * @return {number} |
| 326 */ |
| 327 offsetY() { |
| 328 return this._layerPayload.offsetY; |
| 329 } |
| 330 |
| 331 /** |
| 332 * @override |
| 333 * @return {number} |
| 334 */ |
| 335 width() { |
| 336 return this._layerPayload.width; |
| 337 } |
| 338 |
| 339 /** |
| 340 * @override |
| 341 * @return {number} |
| 342 */ |
| 343 height() { |
| 344 return this._layerPayload.height; |
| 345 } |
| 346 |
| 347 /** |
| 348 * @override |
| 349 * @return {?Array.<number>} |
| 350 */ |
| 351 transform() { |
| 352 return this._layerPayload.transform; |
| 353 } |
| 354 |
| 355 /** |
| 356 * @override |
| 357 * @return {!Array.<number>} |
| 358 */ |
| 359 quad() { |
| 360 return this._quad; |
| 361 } |
| 362 |
| 363 /** |
| 364 * @override |
| 365 * @return {!Array.<number>} |
| 366 */ |
| 367 anchorPoint() { |
| 368 return [ |
| 369 this._layerPayload.anchorX || 0, |
| 370 this._layerPayload.anchorY || 0, |
| 371 this._layerPayload.anchorZ || 0, |
| 372 ]; |
| 373 } |
| 374 |
| 375 /** |
| 376 * @override |
| 377 * @return {boolean} |
| 378 */ |
| 379 invisible() { |
| 380 return this._layerPayload.invisible; |
| 381 } |
| 382 |
| 383 /** |
| 384 * @override |
| 385 * @return {number} |
| 386 */ |
| 387 paintCount() { |
| 388 return this._paintCount || this._layerPayload.paintCount; |
| 389 } |
| 390 |
| 391 /** |
| 392 * @override |
| 393 * @return {?DOMAgent.Rect} |
| 394 */ |
| 395 lastPaintRect() { |
| 396 return this._lastPaintRect; |
| 397 } |
| 398 |
| 399 /** |
| 400 * @override |
| 401 * @return {!Array.<!LayerTreeAgent.ScrollRect>} |
| 402 */ |
| 403 scrollRects() { |
| 404 return this._scrollRects; |
| 405 } |
| 406 |
| 407 /** |
| 408 * @override |
| 409 * @param {function(!Array.<string>)} callback |
| 410 */ |
| 411 requestCompositingReasons(callback) { |
| 412 if (!this._target) { |
| 413 callback([]); |
| 414 return; |
| 415 } |
| 416 |
| 417 var wrappedCallback = |
| 418 InspectorBackend.wrapClientCallback(callback, 'LayerTreeAgent.reasonsFor
CompositingLayer(): ', undefined, []); |
| 419 this._target.layerTreeAgent().compositingReasons(this.id(), wrappedCallback)
; |
| 420 } |
| 421 |
| 422 /** |
| 423 * @override |
| 424 * @return {boolean} |
| 425 */ |
| 426 drawsContent() { |
| 427 return this._layerPayload.drawsContent; |
| 428 } |
| 429 |
| 430 /** |
| 431 * @override |
| 432 * @return {number} |
| 433 */ |
| 434 gpuMemoryUsage() { |
| 435 /** |
| 436 * @const |
| 437 */ |
| 438 var bytesPerPixel = 4; |
| 439 return this.drawsContent() ? this.width() * this.height() * bytesPerPixel :
0; |
| 440 } |
| 441 |
| 442 /** |
| 443 * @override |
| 444 * @return {!Array<!Promise<?WebInspector.SnapshotWithRect>>} |
| 445 */ |
| 446 snapshots() { |
| 447 var rect = {x: 0, y: 0, width: this.width(), height: this.height()}; |
| 448 var promise = this._target.layerTreeAgent().makeSnapshot( |
| 449 this.id(), (error, snapshotId) => error || !this._target ? |
| 450 null : |
| 451 {rect: rect, snapshot: new WebInspector.PaintProfilerSnapshot(this._
target, snapshotId)}); |
| 452 return [promise]; |
| 453 } |
| 454 |
| 455 /** |
| 456 * @param {!DOMAgent.Rect} rect |
| 457 */ |
| 458 _didPaint(rect) { |
| 459 this._lastPaintRect = rect; |
| 460 this._paintCount = this.paintCount() + 1; |
| 461 this._image = null; |
| 462 } |
| 463 |
| 464 /** |
| 465 * @param {!LayerTreeAgent.Layer} layerPayload |
| 466 */ |
| 467 _reset(layerPayload) { |
| 468 /** @type {?WebInspector.DOMNode} */ |
| 469 this._node = null; |
| 470 this._children = []; |
| 471 this._parent = null; |
| 472 this._paintCount = 0; |
| 473 this._layerPayload = layerPayload; |
| 474 this._image = null; |
| 475 this._scrollRects = this._layerPayload.scrollRects || []; |
| 476 } |
| 477 |
| 478 /** |
| 479 * @param {!Array.<number>} a |
| 480 * @return {!CSSMatrix} |
| 481 */ |
| 482 _matrixFromArray(a) { |
| 483 function toFixed9(x) { |
| 484 return x.toFixed(9); |
| 485 } |
| 486 return new WebKitCSSMatrix('matrix3d(' + a.map(toFixed9).join(',') + ')'); |
| 487 } |
| 488 |
| 489 /** |
| 490 * @param {!CSSMatrix} parentTransform |
| 491 * @return {!CSSMatrix} |
| 492 */ |
| 493 _calculateTransformToViewport(parentTransform) { |
| 494 var offsetMatrix = new WebKitCSSMatrix().translate(this._layerPayload.offset
X, this._layerPayload.offsetY); |
| 495 var matrix = offsetMatrix; |
| 496 |
| 497 if (this._layerPayload.transform) { |
| 498 var transformMatrix = this._matrixFromArray(this._layerPayload.transform); |
| 499 var anchorVector = new WebInspector.Geometry.Vector( |
| 500 this._layerPayload.width * this.anchorPoint()[0], this._layerPayload.h
eight * this.anchorPoint()[1], |
| 501 this.anchorPoint()[2]); |
| 502 var anchorPoint = WebInspector.Geometry.multiplyVectorByMatrixAndNormalize
(anchorVector, matrix); |
| 503 var anchorMatrix = new WebKitCSSMatrix().translate(-anchorPoint.x, -anchor
Point.y, -anchorPoint.z); |
| 504 matrix = anchorMatrix.inverse().multiply(transformMatrix.multiply(anchorMa
trix.multiply(matrix))); |
| 505 } |
| 506 |
| 507 matrix = parentTransform.multiply(matrix); |
| 508 return matrix; |
| 509 } |
| 510 |
| 511 /** |
| 512 * @param {number} width |
| 513 * @param {number} height |
| 514 * @return {!Array.<number>} |
| 515 */ |
| 516 _createVertexArrayForRect(width, height) { |
| 517 return [0, 0, 0, width, 0, 0, width, height, 0, 0, height, 0]; |
| 518 } |
| 519 |
| 520 /** |
| 521 * @param {!CSSMatrix} parentTransform |
| 522 */ |
| 523 _calculateQuad(parentTransform) { |
| 524 var matrix = this._calculateTransformToViewport(parentTransform); |
| 525 this._quad = []; |
| 526 var vertices = this._createVertexArrayForRect(this._layerPayload.width, this
._layerPayload.height); |
| 527 for (var i = 0; i < 4; ++i) { |
| 528 var point = WebInspector.Geometry.multiplyVectorByMatrixAndNormalize( |
| 529 new WebInspector.Geometry.Vector(vertices[i * 3], vertices[i * 3 + 1],
vertices[i * 3 + 2]), matrix); |
| 530 this._quad.push(point.x, point.y); |
| 531 } |
| 532 |
| 533 function calculateQuadForLayer(layer) { |
| 534 layer._calculateQuad(matrix); |
| 535 } |
| 536 |
| 537 this._children.forEach(calculateQuadForLayer); |
| 538 } |
236 }; | 539 }; |
237 | 540 |
238 WebInspector.AgentLayer.prototype = { | 541 /** |
239 /** | 542 * @implements {LayerTreeAgent.Dispatcher} |
240 * @override | 543 * @unrestricted |
241 * @return {string} | 544 */ |
242 */ | 545 WebInspector.LayerTreeDispatcher = class { |
243 id: function() | 546 /** |
244 { | 547 * @param {!WebInspector.LayerTreeModel} layerTreeModel |
245 return this._layerPayload.layerId; | 548 */ |
246 }, | 549 constructor(layerTreeModel) { |
247 | 550 this._layerTreeModel = layerTreeModel; |
248 /** | 551 } |
249 * @override | 552 |
250 * @return {?string} | 553 /** |
251 */ | 554 * @override |
252 parentId: function() | 555 * @param {!Array.<!LayerTreeAgent.Layer>=} layers |
253 { | 556 */ |
254 return this._layerPayload.parentLayerId; | 557 layerTreeDidChange(layers) { |
255 }, | 558 this._layerTreeModel._layerTreeChanged(layers || null); |
256 | 559 } |
257 /** | 560 |
258 * @override | 561 /** |
259 * @return {?WebInspector.Layer} | 562 * @override |
260 */ | 563 * @param {!LayerTreeAgent.LayerId} layerId |
261 parent: function() | 564 * @param {!DOMAgent.Rect} clipRect |
262 { | 565 */ |
263 return this._parent; | 566 layerPainted(layerId, clipRect) { |
264 }, | 567 this._layerTreeModel._layerPainted(layerId, clipRect); |
265 | 568 } |
266 /** | |
267 * @override | |
268 * @return {boolean} | |
269 */ | |
270 isRoot: function() | |
271 { | |
272 return !this.parentId(); | |
273 }, | |
274 | |
275 /** | |
276 * @override | |
277 * @return {!Array.<!WebInspector.Layer>} | |
278 */ | |
279 children: function() | |
280 { | |
281 return this._children; | |
282 }, | |
283 | |
284 /** | |
285 * @override | |
286 * @param {!WebInspector.Layer} child | |
287 */ | |
288 addChild: function(child) | |
289 { | |
290 if (child._parent) | |
291 console.assert(false, "Child already has a parent"); | |
292 this._children.push(child); | |
293 child._parent = this; | |
294 }, | |
295 | |
296 /** | |
297 * @param {?WebInspector.DOMNode} node | |
298 */ | |
299 _setNode: function(node) | |
300 { | |
301 this._node = node; | |
302 }, | |
303 | |
304 /** | |
305 * @override | |
306 * @return {?WebInspector.DOMNode} | |
307 */ | |
308 node: function() | |
309 { | |
310 return this._node; | |
311 }, | |
312 | |
313 /** | |
314 * @override | |
315 * @return {?WebInspector.DOMNode} | |
316 */ | |
317 nodeForSelfOrAncestor: function() | |
318 { | |
319 for (var layer = this; layer; layer = layer._parent) { | |
320 if (layer._node) | |
321 return layer._node; | |
322 } | |
323 return null; | |
324 }, | |
325 | |
326 /** | |
327 * @override | |
328 * @return {number} | |
329 */ | |
330 offsetX: function() | |
331 { | |
332 return this._layerPayload.offsetX; | |
333 }, | |
334 | |
335 /** | |
336 * @override | |
337 * @return {number} | |
338 */ | |
339 offsetY: function() | |
340 { | |
341 return this._layerPayload.offsetY; | |
342 }, | |
343 | |
344 /** | |
345 * @override | |
346 * @return {number} | |
347 */ | |
348 width: function() | |
349 { | |
350 return this._layerPayload.width; | |
351 }, | |
352 | |
353 /** | |
354 * @override | |
355 * @return {number} | |
356 */ | |
357 height: function() | |
358 { | |
359 return this._layerPayload.height; | |
360 }, | |
361 | |
362 /** | |
363 * @override | |
364 * @return {?Array.<number>} | |
365 */ | |
366 transform: function() | |
367 { | |
368 return this._layerPayload.transform; | |
369 }, | |
370 | |
371 /** | |
372 * @override | |
373 * @return {!Array.<number>} | |
374 */ | |
375 quad: function() | |
376 { | |
377 return this._quad; | |
378 }, | |
379 | |
380 /** | |
381 * @override | |
382 * @return {!Array.<number>} | |
383 */ | |
384 anchorPoint: function() | |
385 { | |
386 return [ | |
387 this._layerPayload.anchorX || 0, | |
388 this._layerPayload.anchorY || 0, | |
389 this._layerPayload.anchorZ || 0, | |
390 ]; | |
391 }, | |
392 | |
393 /** | |
394 * @override | |
395 * @return {boolean} | |
396 */ | |
397 invisible: function() | |
398 { | |
399 return this._layerPayload.invisible; | |
400 }, | |
401 | |
402 /** | |
403 * @override | |
404 * @return {number} | |
405 */ | |
406 paintCount: function() | |
407 { | |
408 return this._paintCount || this._layerPayload.paintCount; | |
409 }, | |
410 | |
411 /** | |
412 * @override | |
413 * @return {?DOMAgent.Rect} | |
414 */ | |
415 lastPaintRect: function() | |
416 { | |
417 return this._lastPaintRect; | |
418 }, | |
419 | |
420 /** | |
421 * @override | |
422 * @return {!Array.<!LayerTreeAgent.ScrollRect>} | |
423 */ | |
424 scrollRects: function() | |
425 { | |
426 return this._scrollRects; | |
427 }, | |
428 | |
429 /** | |
430 * @override | |
431 * @param {function(!Array.<string>)} callback | |
432 */ | |
433 requestCompositingReasons: function(callback) | |
434 { | |
435 if (!this._target) { | |
436 callback([]); | |
437 return; | |
438 } | |
439 | |
440 var wrappedCallback = InspectorBackend.wrapClientCallback(callback, "Lay
erTreeAgent.reasonsForCompositingLayer(): ", undefined, []); | |
441 this._target.layerTreeAgent().compositingReasons(this.id(), wrappedCallb
ack); | |
442 }, | |
443 | |
444 /** | |
445 * @override | |
446 * @return {boolean} | |
447 */ | |
448 drawsContent: function() | |
449 { | |
450 return this._layerPayload.drawsContent; | |
451 }, | |
452 | |
453 /** | |
454 * @override | |
455 * @return {number} | |
456 */ | |
457 gpuMemoryUsage: function() | |
458 { | |
459 /** | |
460 * @const | |
461 */ | |
462 var bytesPerPixel = 4; | |
463 return this.drawsContent() ? this.width() * this.height() * bytesPerPixe
l : 0; | |
464 }, | |
465 | |
466 /** | |
467 * @override | |
468 * @return {!Array<!Promise<?WebInspector.SnapshotWithRect>>} | |
469 */ | |
470 snapshots: function() | |
471 { | |
472 var rect = {x: 0, y: 0, width: this.width(), height: this.height()}; | |
473 var promise = this._target.layerTreeAgent().makeSnapshot(this.id(), | |
474 (error, snapshotId) => error || !this._target ? null : {rect: rect,
snapshot: new WebInspector.PaintProfilerSnapshot(this._target, snapshotId)}); | |
475 return [promise]; | |
476 }, | |
477 | |
478 /** | |
479 * @param {!DOMAgent.Rect} rect | |
480 */ | |
481 _didPaint: function(rect) | |
482 { | |
483 this._lastPaintRect = rect; | |
484 this._paintCount = this.paintCount() + 1; | |
485 this._image = null; | |
486 }, | |
487 | |
488 /** | |
489 * @param {!LayerTreeAgent.Layer} layerPayload | |
490 */ | |
491 _reset: function(layerPayload) | |
492 { | |
493 /** @type {?WebInspector.DOMNode} */ | |
494 this._node = null; | |
495 this._children = []; | |
496 this._parent = null; | |
497 this._paintCount = 0; | |
498 this._layerPayload = layerPayload; | |
499 this._image = null; | |
500 this._scrollRects = this._layerPayload.scrollRects || []; | |
501 }, | |
502 | |
503 /** | |
504 * @param {!Array.<number>} a | |
505 * @return {!CSSMatrix} | |
506 */ | |
507 _matrixFromArray: function(a) | |
508 { | |
509 function toFixed9(x) { return x.toFixed(9); } | |
510 return new WebKitCSSMatrix("matrix3d(" + a.map(toFixed9).join(",") + ")"
); | |
511 }, | |
512 | |
513 /** | |
514 * @param {!CSSMatrix} parentTransform | |
515 * @return {!CSSMatrix} | |
516 */ | |
517 _calculateTransformToViewport: function(parentTransform) | |
518 { | |
519 var offsetMatrix = new WebKitCSSMatrix().translate(this._layerPayload.of
fsetX, this._layerPayload.offsetY); | |
520 var matrix = offsetMatrix; | |
521 | |
522 if (this._layerPayload.transform) { | |
523 var transformMatrix = this._matrixFromArray(this._layerPayload.trans
form); | |
524 var anchorVector = new WebInspector.Geometry.Vector(this._layerPaylo
ad.width * this.anchorPoint()[0], this._layerPayload.height * this.anchorPoint()
[1], this.anchorPoint()[2]); | |
525 var anchorPoint = WebInspector.Geometry.multiplyVectorByMatrixAndNor
malize(anchorVector, matrix); | |
526 var anchorMatrix = new WebKitCSSMatrix().translate(-anchorPoint.x, -
anchorPoint.y, -anchorPoint.z); | |
527 matrix = anchorMatrix.inverse().multiply(transformMatrix.multiply(an
chorMatrix.multiply(matrix))); | |
528 } | |
529 | |
530 matrix = parentTransform.multiply(matrix); | |
531 return matrix; | |
532 }, | |
533 | |
534 /** | |
535 * @param {number} width | |
536 * @param {number} height | |
537 * @return {!Array.<number>} | |
538 */ | |
539 _createVertexArrayForRect: function(width, height) | |
540 { | |
541 return [0, 0, 0, width, 0, 0, width, height, 0, 0, height, 0]; | |
542 }, | |
543 | |
544 /** | |
545 * @param {!CSSMatrix} parentTransform | |
546 */ | |
547 _calculateQuad: function(parentTransform) | |
548 { | |
549 var matrix = this._calculateTransformToViewport(parentTransform); | |
550 this._quad = []; | |
551 var vertices = this._createVertexArrayForRect(this._layerPayload.width,
this._layerPayload.height); | |
552 for (var i = 0; i < 4; ++i) { | |
553 var point = WebInspector.Geometry.multiplyVectorByMatrixAndNormalize
(new WebInspector.Geometry.Vector(vertices[i * 3], vertices[i * 3 + 1], vertices
[i * 3 + 2]), matrix); | |
554 this._quad.push(point.x, point.y); | |
555 } | |
556 | |
557 function calculateQuadForLayer(layer) | |
558 { | |
559 layer._calculateQuad(matrix); | |
560 } | |
561 | |
562 this._children.forEach(calculateQuadForLayer); | |
563 } | |
564 }; | 569 }; |
565 | 570 |
566 /** | 571 |
567 * @constructor | |
568 * @implements {LayerTreeAgent.Dispatcher} | |
569 * @param {!WebInspector.LayerTreeModel} layerTreeModel | |
570 */ | |
571 WebInspector.LayerTreeDispatcher = function(layerTreeModel) | |
572 { | |
573 this._layerTreeModel = layerTreeModel; | |
574 }; | |
575 | |
576 WebInspector.LayerTreeDispatcher.prototype = { | |
577 /** | |
578 * @override | |
579 * @param {!Array.<!LayerTreeAgent.Layer>=} layers | |
580 */ | |
581 layerTreeDidChange: function(layers) | |
582 { | |
583 this._layerTreeModel._layerTreeChanged(layers || null); | |
584 }, | |
585 | |
586 /** | |
587 * @override | |
588 * @param {!LayerTreeAgent.LayerId} layerId | |
589 * @param {!DOMAgent.Rect} clipRect | |
590 */ | |
591 layerPainted: function(layerId, clipRect) | |
592 { | |
593 this._layerTreeModel._layerPainted(layerId, clipRect); | |
594 } | |
595 }; | |
596 | |
597 /** | |
598 * @param {!WebInspector.Target} target | |
599 * @return {?WebInspector.LayerTreeModel} | |
600 */ | |
601 WebInspector.LayerTreeModel.fromTarget = function(target) | |
602 { | |
603 if (!target.hasDOMCapability()) | |
604 return null; | |
605 | |
606 var model = /** @type {?WebInspector.LayerTreeModel} */ (target.model(WebIns
pector.LayerTreeModel)); | |
607 if (!model) | |
608 model = new WebInspector.LayerTreeModel(target); | |
609 return model; | |
610 }; | |
OLD | NEW |