Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(531)

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/layer_viewer/Layers3DView.js

Issue 2466123002: DevTools: reformat front-end code to match chromium style. (Closed)
Patch Set: all done Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2014 Google Inc. All rights reserved. 2 * Copyright (C) 2014 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
33 * @extends {WebInspector.VBox}
34 * @param {!WebInspector.LayerViewHost} layerViewHost
35 * @implements {WebInspector.LayerView} 31 * @implements {WebInspector.LayerView}
32 * @unrestricted
36 */ 33 */
37 WebInspector.Layers3DView = function(layerViewHost) 34 WebInspector.Layers3DView = class extends WebInspector.VBox {
38 { 35 /**
39 WebInspector.VBox.call(this, true); 36 * @param {!WebInspector.LayerViewHost} layerViewHost
40 this.registerRequiredCSS("layer_viewer/layers3DView.css"); 37 */
41 this.contentElement.classList.add("layers-3d-view"); 38 constructor(layerViewHost) {
39 super(true);
40 this.registerRequiredCSS('layer_viewer/layers3DView.css');
41 this.contentElement.classList.add('layers-3d-view');
42 this._failBanner = new WebInspector.VBox(); 42 this._failBanner = new WebInspector.VBox();
43 this._failBanner.element.classList.add("full-widget-dimmed-banner"); 43 this._failBanner.element.classList.add('full-widget-dimmed-banner');
44 this._failBanner.element.createTextChild(WebInspector.UIString("Layer inform ation is not yet available.")); 44 this._failBanner.element.createTextChild(WebInspector.UIString('Layer inform ation is not yet available.'));
45 45
46 this._layerViewHost = layerViewHost; 46 this._layerViewHost = layerViewHost;
47 this._layerViewHost.registerView(this); 47 this._layerViewHost.registerView(this);
48 48
49 this._transformController = new WebInspector.TransformController(this.conten tElement); 49 this._transformController = new WebInspector.TransformController(this.conten tElement);
50 this._transformController.addEventListener(WebInspector.TransformController. Events.TransformChanged, this._update, this); 50 this._transformController.addEventListener(
51 WebInspector.TransformController.Events.TransformChanged, this._update, this);
51 this._initToolbar(); 52 this._initToolbar();
52 53
53 this._canvasElement = this.contentElement.createChild("canvas"); 54 this._canvasElement = this.contentElement.createChild('canvas');
54 this._canvasElement.tabIndex = 0; 55 this._canvasElement.tabIndex = 0;
55 this._canvasElement.addEventListener("dblclick", this._onDoubleClick.bind(th is), false); 56 this._canvasElement.addEventListener('dblclick', this._onDoubleClick.bind(th is), false);
56 this._canvasElement.addEventListener("mousedown", this._onMouseDown.bind(thi s), false); 57 this._canvasElement.addEventListener('mousedown', this._onMouseDown.bind(thi s), false);
57 this._canvasElement.addEventListener("mouseup", this._onMouseUp.bind(this), false); 58 this._canvasElement.addEventListener('mouseup', this._onMouseUp.bind(this), false);
58 this._canvasElement.addEventListener("mouseleave", this._onMouseMove.bind(th is), false); 59 this._canvasElement.addEventListener('mouseleave', this._onMouseMove.bind(th is), false);
59 this._canvasElement.addEventListener("mousemove", this._onMouseMove.bind(thi s), false); 60 this._canvasElement.addEventListener('mousemove', this._onMouseMove.bind(thi s), false);
60 this._canvasElement.addEventListener("contextmenu", this._onContextMenu.bind (this), false); 61 this._canvasElement.addEventListener('contextmenu', this._onContextMenu.bind (this), false);
61 62
62 this._lastSelection = {}; 63 this._lastSelection = {};
63 this._layerTree = null; 64 this._layerTree = null;
64 65
65 this._textureManager = new WebInspector.LayerTextureManager(this._update.bin d(this)); 66 this._textureManager = new WebInspector.LayerTextureManager(this._update.bin d(this));
66 67
67 /** @type Array.<!WebGLTexture|undefined> */ 68 /** @type Array.<!WebGLTexture|undefined> */
68 this._chromeTextures = []; 69 this._chromeTextures = [];
69 this._rects = []; 70 this._rects = [];
70 71
71 this._layerViewHost.showInternalLayersSetting().addChangeListener(this._upda te, this); 72 this._layerViewHost.showInternalLayersSetting().addChangeListener(this._upda te, this);
73 }
74
75 /**
76 * @param {?WebInspector.LayerTreeBase} layerTree
77 * @override
78 */
79 setLayerTree(layerTree) {
80 this._layerTree = layerTree;
81 this._layerTexture = null;
82 delete this._oldTextureScale;
83 if (this._showPaints())
84 this._textureManager.setLayerTree(layerTree);
85 this._update();
86 }
87
88 /**
89 * @param {!WebInspector.Layer} layer
90 * @param {string=} imageURL
91 */
92 showImageForLayer(layer, imageURL) {
93 if (!imageURL) {
94 this._layerTexture = null;
95 this._update();
96 return;
97 }
98 WebInspector.loadImage(imageURL).then(image => {
99 var texture = image && WebInspector.LayerTextureManager._createTextureForI mage(this._gl, image);
100 this._layerTexture = texture ? {layer: layer, texture: texture} : null;
101 this._update();
102 });
103 }
104
105 /**
106 * @override
107 */
108 onResize() {
109 this._resizeCanvas();
110 this._update();
111 }
112
113 /**
114 * @override
115 */
116 willHide() {
117 this._textureManager.suspend();
118 }
119
120 /**
121 * @override
122 */
123 wasShown() {
124 this._textureManager.resume();
125 if (!this._needsUpdate)
126 return;
127 this._resizeCanvas();
128 this._update();
129 }
130
131 /**
132 * @param {!WebInspector.Layer} layer
133 */
134 updateLayerSnapshot(layer) {
135 this._textureManager.layerNeedsUpdate(layer);
136 }
137
138 /**
139 * @param {!WebInspector.Layers3DView.OutlineType} type
140 * @param {?WebInspector.LayerView.Selection} selection
141 */
142 _setOutline(type, selection) {
143 this._lastSelection[type] = selection;
144 this._update();
145 }
146
147 /**
148 * @param {?WebInspector.LayerView.Selection} selection
149 * @override
150 */
151 hoverObject(selection) {
152 this._setOutline(WebInspector.Layers3DView.OutlineType.Hovered, selection);
153 }
154
155 /**
156 * @param {?WebInspector.LayerView.Selection} selection
157 * @override
158 */
159 selectObject(selection) {
160 this._setOutline(WebInspector.Layers3DView.OutlineType.Hovered, null);
161 this._setOutline(WebInspector.Layers3DView.OutlineType.Selected, selection);
162 }
163
164 /**
165 * @param {!WebInspector.LayerView.Selection} selection
166 * @return {!Promise<?WebInspector.SnapshotWithRect>}
167 */
168 snapshotForSelection(selection) {
169 if (selection.type() === WebInspector.LayerView.Selection.Type.Snapshot) {
170 var snapshotWithRect = /** @type {!WebInspector.LayerView.SnapshotSelectio n} */ (selection).snapshot();
171 snapshotWithRect.snapshot.addReference();
172 return /** @type {!Promise<?WebInspector.SnapshotWithRect>} */ (Promise.re solve(snapshotWithRect));
173 }
174 if (selection.layer()) {
175 var promise = selection.layer().snapshots()[0];
176 if (promise)
177 return promise;
178 }
179 return /** @type {!Promise<?WebInspector.SnapshotWithRect>} */ (Promise.reso lve(null));
180 }
181
182 /**
183 * @param {!Element} canvas
184 * @return {?WebGLRenderingContext}
185 */
186 _initGL(canvas) {
187 var gl = canvas.getContext('webgl');
188 if (!gl)
189 return null;
190 gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
191 gl.enable(gl.BLEND);
192 gl.clearColor(0.0, 0.0, 0.0, 0.0);
193 gl.enable(gl.DEPTH_TEST);
194 return gl;
195 }
196
197 /**
198 * @param {!Object} type
199 * @param {string} script
200 */
201 _createShader(type, script) {
202 var shader = this._gl.createShader(type);
203 this._gl.shaderSource(shader, script);
204 this._gl.compileShader(shader);
205 this._gl.attachShader(this._shaderProgram, shader);
206 }
207
208 _initShaders() {
209 this._shaderProgram = this._gl.createProgram();
210 this._createShader(this._gl.FRAGMENT_SHADER, WebInspector.Layers3DView.Fragm entShader);
211 this._createShader(this._gl.VERTEX_SHADER, WebInspector.Layers3DView.VertexS hader);
212 this._gl.linkProgram(this._shaderProgram);
213 this._gl.useProgram(this._shaderProgram);
214
215 this._shaderProgram.vertexPositionAttribute = this._gl.getAttribLocation(thi s._shaderProgram, 'aVertexPosition');
216 this._gl.enableVertexAttribArray(this._shaderProgram.vertexPositionAttribute );
217 this._shaderProgram.vertexColorAttribute = this._gl.getAttribLocation(this._ shaderProgram, 'aVertexColor');
218 this._gl.enableVertexAttribArray(this._shaderProgram.vertexColorAttribute);
219 this._shaderProgram.textureCoordAttribute = this._gl.getAttribLocation(this. _shaderProgram, 'aTextureCoord');
220 this._gl.enableVertexAttribArray(this._shaderProgram.textureCoordAttribute);
221
222 this._shaderProgram.pMatrixUniform = this._gl.getUniformLocation(this._shade rProgram, 'uPMatrix');
223 this._shaderProgram.samplerUniform = this._gl.getUniformLocation(this._shade rProgram, 'uSampler');
224 }
225
226 _resizeCanvas() {
227 this._canvasElement.width = this._canvasElement.offsetWidth * window.deviceP ixelRatio;
228 this._canvasElement.height = this._canvasElement.offsetHeight * window.devic ePixelRatio;
229 }
230
231 _updateTransformAndConstraints() {
232 var paddingFraction = 0.1;
233 var viewport = this._layerTree.viewportSize();
234 var root = this._layerTree.root();
235 var baseWidth = viewport ? viewport.width : this._dimensionsForAutoscale.wid th;
236 var baseHeight = viewport ? viewport.height : this._dimensionsForAutoscale.h eight;
237 var canvasWidth = this._canvasElement.width;
238 var canvasHeight = this._canvasElement.height;
239 var paddingX = canvasWidth * paddingFraction;
240 var paddingY = canvasHeight * paddingFraction;
241 var scaleX = (canvasWidth - 2 * paddingX) / baseWidth;
242 var scaleY = (canvasHeight - 2 * paddingY) / baseHeight;
243 var viewScale = Math.min(scaleX, scaleY);
244 var minScaleConstraint =
245 Math.min(baseWidth / this._dimensionsForAutoscale.width, baseHeight / th is._dimensionsForAutoscale.width) / 2;
246 this._transformController.setScaleConstraints(
247 minScaleConstraint,
248 10 / viewScale); // 1/viewScale is 1:1 in terms of pixels, so allow zoo ming to 10x of native size
249 var scale = this._transformController.scale();
250 var rotateX = this._transformController.rotateX();
251 var rotateY = this._transformController.rotateY();
252
253 this._scale = scale * viewScale;
254 var textureScale = Number.constrain(this._scale, 0.1, 1);
255 if (textureScale !== this._oldTextureScale) {
256 this._oldTextureScale = textureScale;
257 this._textureManager.setScale(textureScale);
258 this.dispatchEventToListeners(WebInspector.Layers3DView.Events.ScaleChange d, textureScale);
259 }
260 var scaleAndRotationMatrix = new WebKitCSSMatrix()
261 .scale(scale, scale, scale)
262 .translate(canvasWidth / 2, canvasHeight / 2, 0)
263 .rotate(rotateX, rotateY, 0)
264 .scale(viewScale, viewScale, viewScale)
265 .translate(-baseWidth / 2, -baseHeight / 2, 0);
266
267 var bounds;
268 for (var i = 0; i < this._rects.length; ++i)
269 bounds =
270 WebInspector.Geometry.boundsForTransformedPoints(scaleAndRotationMatri x, this._rects[i].vertices, bounds);
271
272 this._transformController.clampOffsets(
273 (paddingX - bounds.maxX) / window.devicePixelRatio,
274 (canvasWidth - paddingX - bounds.minX) / window.devicePixelRatio,
275 (paddingY - bounds.maxY) / window.devicePixelRatio,
276 (canvasHeight - paddingY - bounds.minY) / window.devicePixelRatio);
277 var offsetX = this._transformController.offsetX() * window.devicePixelRatio;
278 var offsetY = this._transformController.offsetY() * window.devicePixelRatio;
279 // Multiply to translation matrix on the right rather than translate (which would implicitly multiply on the left).
280 this._projectionMatrix = new WebKitCSSMatrix().translate(offsetX, offsetY, 0 ).multiply(scaleAndRotationMatrix);
281
282 var glProjectionMatrix = new WebKitCSSMatrix()
283 .scale(1, -1, -1)
284 .translate(-1, -1, 0)
285 .scale(2 / this._canvasElement.width, 2 / this. _canvasElement.height, 1 / 1000000)
286 .multiply(this._projectionMatrix);
287 this._gl.uniformMatrix4fv(this._shaderProgram.pMatrixUniform, false, this._a rrayFromMatrix(glProjectionMatrix));
288 }
289
290 /**
291 * @param {!CSSMatrix} m
292 * @return {!Float32Array}
293 */
294 _arrayFromMatrix(m) {
295 return new Float32Array([
296 m.m11, m.m12, m.m13, m.m14, m.m21, m.m22, m.m23, m.m24, m.m31, m.m32, m.m3 3, m.m34, m.m41, m.m42, m.m43, m.m44
297 ]);
298 }
299
300 _initWhiteTexture() {
301 this._whiteTexture = this._gl.createTexture();
302 this._gl.bindTexture(this._gl.TEXTURE_2D, this._whiteTexture);
303 var whitePixel = new Uint8Array([255, 255, 255, 255]);
304 this._gl.texImage2D(
305 this._gl.TEXTURE_2D, 0, this._gl.RGBA, 1, 1, 0, this._gl.RGBA, this._gl. UNSIGNED_BYTE, whitePixel);
306 }
307
308 _initChromeTextures() {
309 /**
310 * @this {WebInspector.Layers3DView}
311 * @param {!WebInspector.Layers3DView.ChromeTexture} index
312 * @param {string} url
313 */
314 function loadChromeTexture(index, url) {
315 WebInspector.loadImage(url).then(image => {
316 this._chromeTextures[index] =
317 image && WebInspector.LayerTextureManager._createTextureForImage(thi s._gl, image) || undefined;
318 });
319 }
320 loadChromeTexture.call(this, WebInspector.Layers3DView.ChromeTexture.Left, ' Images/chromeLeft.png');
321 loadChromeTexture.call(this, WebInspector.Layers3DView.ChromeTexture.Middle, 'Images/chromeMiddle.png');
322 loadChromeTexture.call(this, WebInspector.Layers3DView.ChromeTexture.Right, 'Images/chromeRight.png');
323 }
324
325 /**
326 * @return {?WebGLRenderingContext}
327 */
328 _initGLIfNecessary() {
329 if (this._gl)
330 return this._gl;
331 this._gl = this._initGL(this._canvasElement);
332 if (!this._gl)
333 return null;
334 this._initShaders();
335 this._initWhiteTexture();
336 this._initChromeTextures();
337 this._textureManager.setContext(this._gl);
338 return this._gl;
339 }
340
341 _calculateDepthsAndVisibility() {
342 this._depthByLayerId = {};
343 var depth = 0;
344 var showInternalLayers = this._layerViewHost.showInternalLayersSetting().get ();
345 var root = showInternalLayers ? this._layerTree.root() : (this._layerTree.co ntentRoot() || this._layerTree.root());
346 var queue = [root];
347 this._depthByLayerId[root.id()] = 0;
348 /** @type {!Set<!WebInspector.Layer>} */
349 this._visibleLayers = new Set();
350 while (queue.length > 0) {
351 var layer = queue.shift();
352 if (showInternalLayers || layer.drawsContent())
353 this._visibleLayers.add(layer);
354 var children = layer.children();
355 for (var i = 0; i < children.length; ++i) {
356 this._depthByLayerId[children[i].id()] = ++depth;
357 queue.push(children[i]);
358 }
359 }
360 this._maxDepth = depth;
361 }
362
363 /**
364 * @param {!WebInspector.Layer} layer
365 * @return {number}
366 */
367 _depthForLayer(layer) {
368 return this._depthByLayerId[layer.id()] * WebInspector.Layers3DView.LayerSpa cing;
369 }
370
371 /**
372 * @param {!WebInspector.Layer} layer
373 * @param {number} index
374 * @return {number}
375 */
376 _calculateScrollRectDepth(layer, index) {
377 return this._depthForLayer(layer) + index * WebInspector.Layers3DView.Scroll RectSpacing + 1;
378 }
379
380 /**
381 * @param {!WebInspector.Layer} layer
382 */
383 _updateDimensionsForAutoscale(layer) {
384 // We don't want to be precise, but rather pick something least affected by
385 // animationtransforms, so that we don't change scale too often. So let's
386 // disregard transforms, scrolling and relative layer positioning and choose
387 // the largest dimensions of all layers.
388 this._dimensionsForAutoscale.width = Math.max(layer.width(), this._dimension sForAutoscale.width);
389 this._dimensionsForAutoscale.height = Math.max(layer.height(), this._dimensi onsForAutoscale.height);
390 }
391
392 /**
393 * @param {!WebInspector.Layer} layer
394 */
395 _calculateLayerRect(layer) {
396 if (!this._visibleLayers.has(layer))
397 return;
398 var selection = new WebInspector.LayerView.LayerSelection(layer);
399 var rect = new WebInspector.Layers3DView.Rectangle(selection);
400 rect.setVertices(layer.quad(), this._depthForLayer(layer));
401 this._appendRect(rect);
402 this._updateDimensionsForAutoscale(layer);
403 }
404
405 /**
406 * @param {!WebInspector.Layers3DView.Rectangle} rect
407 */
408 _appendRect(rect) {
409 var selection = rect.relatedObject;
410 var isSelected = WebInspector.LayerView.Selection.isEqual(
411 this._lastSelection[WebInspector.Layers3DView.OutlineType.Selected], sel ection);
412 var isHovered = WebInspector.LayerView.Selection.isEqual(
413 this._lastSelection[WebInspector.Layers3DView.OutlineType.Hovered], sele ction);
414 if (isSelected) {
415 rect.borderColor = WebInspector.Layers3DView.SelectedBorderColor;
416 } else if (isHovered) {
417 rect.borderColor = WebInspector.Layers3DView.HoveredBorderColor;
418 var fillColor = rect.fillColor || [255, 255, 255, 1];
419 var maskColor = WebInspector.Layers3DView.HoveredImageMaskColor;
420 rect.fillColor = [
421 fillColor[0] * maskColor[0] / 255, fillColor[1] * maskColor[1] / 255, fi llColor[2] * maskColor[2] / 255,
422 fillColor[3] * maskColor[3]
423 ];
424 } else {
425 rect.borderColor = WebInspector.Layers3DView.BorderColor;
426 }
427 rect.lineWidth = isSelected ? WebInspector.Layers3DView.SelectedBorderWidth : WebInspector.Layers3DView.BorderWidth;
428 this._rects.push(rect);
429 }
430
431 /**
432 * @param {!WebInspector.Layer} layer
433 */
434 _calculateLayerScrollRects(layer) {
435 var scrollRects = layer.scrollRects();
436 for (var i = 0; i < scrollRects.length; ++i) {
437 var selection = new WebInspector.LayerView.ScrollRectSelection(layer, i);
438 var rect = new WebInspector.Layers3DView.Rectangle(selection);
439 rect.calculateVerticesFromRect(layer, scrollRects[i].rect, this._calculate ScrollRectDepth(layer, i));
440 rect.fillColor = WebInspector.Layers3DView.ScrollRectBackgroundColor;
441 this._appendRect(rect);
442 }
443 }
444
445 /**
446 * @param {!WebInspector.Layer} layer
447 */
448 _calculateLayerTileRects(layer) {
449 var tiles = this._textureManager.tilesForLayer(layer);
450 for (var i = 0; i < tiles.length; ++i) {
451 var tile = tiles[i];
452 if (!tile.texture)
453 continue;
454 var selection = new WebInspector.LayerView.SnapshotSelection(layer, {rect: tile.rect, snapshot: tile.snapshot});
455 var rect = new WebInspector.Layers3DView.Rectangle(selection);
456 rect.calculateVerticesFromRect(layer, tile.rect, this._depthForLayer(layer ) + 1);
457 rect.texture = tile.texture;
458 this._appendRect(rect);
459 }
460 }
461
462 _calculateRects() {
463 this._rects = [];
464 this._dimensionsForAutoscale = {width: 0, height: 0};
465 this._layerTree.forEachLayer(this._calculateLayerRect.bind(this));
466
467 if (this._showSlowScrollRectsSetting.get())
468 this._layerTree.forEachLayer(this._calculateLayerScrollRects.bind(this));
469
470 if (this._layerTexture && this._visibleLayers.has(this._layerTexture.layer)) {
471 var layer = this._layerTexture.layer;
472 var selection = new WebInspector.LayerView.LayerSelection(layer);
473 var rect = new WebInspector.Layers3DView.Rectangle(selection);
474 rect.setVertices(layer.quad(), this._depthForLayer(layer));
475 rect.texture = this._layerTexture.texture;
476 this._appendRect(rect);
477 } else if (this._showPaints()) {
478 this._layerTree.forEachLayer(this._calculateLayerTileRects.bind(this));
479 }
480 }
481
482 /**
483 * @param {!Array.<number>} color
484 * @return {!Array.<number>}
485 */
486 _makeColorsArray(color) {
487 var colors = [];
488 var normalizedColor = [color[0] / 255, color[1] / 255, color[2] / 255, color [3]];
489 for (var i = 0; i < 4; i++)
490 colors = colors.concat(normalizedColor);
491 return colors;
492 }
493
494 /**
495 * @param {!Object} attribute
496 * @param {!Array.<number>} array
497 * @param {number} length
498 */
499 _setVertexAttribute(attribute, array, length) {
500 var gl = this._gl;
501 var buffer = gl.createBuffer();
502 gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
503 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(array), gl.STATIC_DRAW);
504 gl.vertexAttribPointer(attribute, length, gl.FLOAT, false, 0, 0);
505 }
506
507 /**
508 * @param {!Array.<number>} vertices
509 * @param {number} mode
510 * @param {!Array.<number>=} color
511 * @param {!Object=} texture
512 */
513 _drawRectangle(vertices, mode, color, texture) {
514 var gl = this._gl;
515 var white = [255, 255, 255, 1];
516 color = color || white;
517 this._setVertexAttribute(this._shaderProgram.vertexPositionAttribute, vertic es, 3);
518 this._setVertexAttribute(this._shaderProgram.textureCoordAttribute, [0, 1, 1 , 1, 1, 0, 0, 0], 2);
519 this._setVertexAttribute(this._shaderProgram.vertexColorAttribute, this._mak eColorsArray(color), color.length);
520
521 if (texture) {
522 gl.activeTexture(gl.TEXTURE0);
523 gl.bindTexture(gl.TEXTURE_2D, texture);
524 gl.uniform1i(this._shaderProgram.samplerUniform, 0);
525 } else {
526 gl.bindTexture(gl.TEXTURE_2D, this._whiteTexture);
527 }
528
529 var numberOfVertices = vertices.length / 3;
530 gl.drawArrays(mode, 0, numberOfVertices);
531 }
532
533 /**
534 * @param {!Array.<number>} vertices
535 * @param {!WebGLTexture} texture
536 * @param {!Array.<number>=} color
537 */
538 _drawTexture(vertices, texture, color) {
539 this._drawRectangle(vertices, this._gl.TRIANGLE_FAN, color, texture);
540 }
541
542 _drawViewportAndChrome() {
543 var viewport = this._layerTree.viewportSize();
544 if (!viewport)
545 return;
546
547 var drawChrome = !WebInspector.moduleSetting('frameViewerHideChromeWindow'). get() &&
548 this._chromeTextures.length >= 3 && this._chromeTextures.indexOf(undefin ed) < 0;
549 var z = (this._maxDepth + 1) * WebInspector.Layers3DView.LayerSpacing;
550 var borderWidth = Math.ceil(WebInspector.Layers3DView.ViewportBorderWidth * this._scale);
551 var vertices = [viewport.width, 0, z, viewport.width, viewport.height, z, 0, viewport.height, z, 0, 0, z];
552 this._gl.lineWidth(borderWidth);
553 this._drawRectangle(
554 vertices, drawChrome ? this._gl.LINE_STRIP : this._gl.LINE_LOOP, WebInsp ector.Layers3DView.ViewportBorderColor);
555
556 if (!drawChrome)
557 return;
558
559 var borderAdjustment = WebInspector.Layers3DView.ViewportBorderWidth / 2;
560 var viewportWidth = this._layerTree.viewportSize().width + 2 * borderAdjustm ent;
561 var chromeHeight = this._chromeTextures[0].image.naturalHeight;
562 var middleFragmentWidth =
563 viewportWidth - this._chromeTextures[0].image.naturalWidth - this._chrom eTextures[2].image.naturalWidth;
564 var x = -borderAdjustment;
565 var y = -chromeHeight;
566 for (var i = 0; i < this._chromeTextures.length; ++i) {
567 var width = i === WebInspector.Layers3DView.ChromeTexture.Middle ? middleF ragmentWidth :
568 this._c hromeTextures[i].image.naturalWidth;
569 if (width < 0 || x + width > viewportWidth)
570 break;
571 vertices = [x, y, z, x + width, y, z, x + width, y + chromeHeight, z, x, y + chromeHeight, z];
572 this._drawTexture(vertices, /** @type {!WebGLTexture} */ (this._chromeText ures[i]));
573 x += width;
574 }
575 }
576
577 /**
578 * @param {!WebInspector.Layers3DView.Rectangle} rect
579 */
580 _drawViewRect(rect) {
581 var vertices = rect.vertices;
582 if (rect.texture)
583 this._drawTexture(vertices, rect.texture, rect.fillColor || undefined);
584 else if (rect.fillColor)
585 this._drawRectangle(vertices, this._gl.TRIANGLE_FAN, rect.fillColor);
586 this._gl.lineWidth(rect.lineWidth);
587 if (rect.borderColor)
588 this._drawRectangle(vertices, this._gl.LINE_LOOP, rect.borderColor);
589 }
590
591 _update() {
592 if (!this.isShowing()) {
593 this._needsUpdate = true;
594 return;
595 }
596 if (!this._layerTree || !this._layerTree.root()) {
597 this._failBanner.show(this.contentElement);
598 return;
599 }
600 var gl = this._initGLIfNecessary();
601 if (!gl) {
602 this._failBanner.element.removeChildren();
603 this._failBanner.element.appendChild(this._webglDisabledBanner());
604 this._failBanner.show(this.contentElement);
605 return;
606 }
607 this._failBanner.detach();
608 this._gl.viewportWidth = this._canvasElement.width;
609 this._gl.viewportHeight = this._canvasElement.height;
610
611 this._calculateDepthsAndVisibility();
612 this._calculateRects();
613 this._updateTransformAndConstraints();
614
615 gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
616 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
617
618 this._rects.forEach(this._drawViewRect.bind(this));
619 this._drawViewportAndChrome();
620 }
621
622 /**
623 * @return {!Node}
624 */
625 _webglDisabledBanner() {
626 var fragment = this.contentElement.ownerDocument.createDocumentFragment();
627 fragment.createChild('div').textContent = WebInspector.UIString('Can\'t disp lay layers,');
628 fragment.createChild('div').textContent = WebInspector.UIString('WebGL suppo rt is disabled in your browser.');
629 fragment.appendChild(WebInspector.formatLocalized(
630 'Check %s for possible reasons.', [WebInspector.linkifyURLAsNode('about: gpu', undefined, undefined, true)]));
631 return fragment;
632 }
633
634 /**
635 * @param {!Event} event
636 * @return {?WebInspector.LayerView.Selection}
637 */
638 _selectionFromEventPoint(event) {
639 if (!this._layerTree)
640 return null;
641 var closestIntersectionPoint = Infinity;
642 var closestObject = null;
643 var projectionMatrix = new WebKitCSSMatrix().scale(1, -1, -1).translate(-1, -1, 0).multiply(this._projectionMatrix);
644 var x0 = (event.clientX - this._canvasElement.totalOffsetLeft()) * window.de vicePixelRatio;
645 var y0 = -(event.clientY - this._canvasElement.totalOffsetTop()) * window.de vicePixelRatio;
646
647 /**
648 * @param {!WebInspector.Layers3DView.Rectangle} rect
649 */
650 function checkIntersection(rect) {
651 if (!rect.relatedObject)
652 return;
653 var t = rect.intersectWithLine(projectionMatrix, x0, y0);
654 if (t < closestIntersectionPoint) {
655 closestIntersectionPoint = t;
656 closestObject = rect.relatedObject;
657 }
658 }
659
660 this._rects.forEach(checkIntersection);
661 return closestObject;
662 }
663
664 /**
665 * @param {string} caption
666 * @param {string} name
667 * @param {boolean} value
668 * @param {!WebInspector.Toolbar} toolbar
669 * @return {!WebInspector.Setting}
670 */
671 _createVisibilitySetting(caption, name, value, toolbar) {
672 var checkbox = new WebInspector.ToolbarCheckbox(WebInspector.UIString(captio n));
673 toolbar.appendToolbarItem(checkbox);
674 var setting = WebInspector.settings.createSetting(name, value);
675 WebInspector.SettingsUI.bindCheckbox(checkbox.inputElement, setting);
676 setting.addChangeListener(this._update, this);
677 return setting;
678 }
679
680 _initToolbar() {
681 this._panelToolbar = this._transformController.toolbar();
682 this.contentElement.appendChild(this._panelToolbar.element);
683 this._showSlowScrollRectsSetting =
684 this._createVisibilitySetting('Slow scroll rects', 'frameViewerShowSlowS crollRects', true, this._panelToolbar);
685 this._showPaintsSetting =
686 this._createVisibilitySetting('Paints', 'frameViewerShowPaints', true, t his._panelToolbar);
687 this._showPaintsSetting.addChangeListener(this._updatePaints, this);
688 WebInspector.moduleSetting('frameViewerHideChromeWindow').addChangeListener( this._update, this);
689 }
690
691 /**
692 * @param {!Event} event
693 */
694 _onContextMenu(event) {
695 var contextMenu = new WebInspector.ContextMenu(event);
696 contextMenu.appendItem(
697 WebInspector.UIString('Reset View'), this._transformController.resetAndN otify.bind(this._transformController),
698 false);
699 var selection = this._selectionFromEventPoint(event);
700 if (selection && selection.type() === WebInspector.LayerView.Selection.Type. Snapshot)
701 contextMenu.appendItem(
702 WebInspector.UIString('Show Paint Profiler'),
703 this.dispatchEventToListeners.bind(
704 this, WebInspector.Layers3DView.Events.PaintProfilerRequested, sel ection.snapshot()),
705 false);
706 this._layerViewHost.showContextMenu(contextMenu, selection);
707 }
708
709 /**
710 * @param {!Event} event
711 */
712 _onMouseMove(event) {
713 if (event.which)
714 return;
715 this._layerViewHost.hoverObject(this._selectionFromEventPoint(event));
716 }
717
718 /**
719 * @param {!Event} event
720 */
721 _onMouseDown(event) {
722 this._mouseDownX = event.clientX;
723 this._mouseDownY = event.clientY;
724 }
725
726 /**
727 * @param {!Event} event
728 */
729 _onMouseUp(event) {
730 const maxDistanceInPixels = 6;
731 if (this._mouseDownX && Math.abs(event.clientX - this._mouseDownX) < maxDist anceInPixels &&
732 Math.abs(event.clientY - this._mouseDownY) < maxDistanceInPixels)
733 this._layerViewHost.selectObject(this._selectionFromEventPoint(event));
734 delete this._mouseDownX;
735 delete this._mouseDownY;
736 }
737
738 /**
739 * @param {!Event} event
740 */
741 _onDoubleClick(event) {
742 var selection = this._selectionFromEventPoint(event);
743 if (selection && (selection.type() === WebInspector.LayerView.Selection.Type .Snapshot || selection.layer()))
744 this.dispatchEventToListeners(WebInspector.Layers3DView.Events.PaintProfil erRequested, selection);
745 event.stopPropagation();
746 }
747
748 _updatePaints() {
749 if (this._showPaints()) {
750 this._textureManager.setLayerTree(this._layerTree);
751 this._textureManager.forceUpdate();
752 } else {
753 this._textureManager.reset();
754 }
755 this._update();
756 }
757
758 /**
759 * @return {boolean}
760 */
761 _showPaints() {
762 return this._showPaintsSetting.get();
763 }
72 }; 764 };
73 765
74 /** @typedef {{borderColor: !Array<number>, borderWidth: number}} */ 766 /** @typedef {{borderColor: !Array<number>, borderWidth: number}} */
75 WebInspector.Layers3DView.LayerStyle; 767 WebInspector.Layers3DView.LayerStyle;
76 768
77 /** 769 /**
78 * @enum {string} 770 * @enum {string}
79 */ 771 */
80 WebInspector.Layers3DView.OutlineType = { 772 WebInspector.Layers3DView.OutlineType = {
81 Hovered: "hovered", 773 Hovered: 'hovered',
82 Selected: "selected" 774 Selected: 'selected'
83 }; 775 };
84 776
85 /** 777 /**
86 * @enum {string} 778 * @enum {string}
87 */ 779 */
88 /** @enum {symbol} */ 780 /** @enum {symbol} */
89 WebInspector.Layers3DView.Events = { 781 WebInspector.Layers3DView.Events = {
90 PaintProfilerRequested: Symbol("PaintProfilerRequested"), 782 PaintProfilerRequested: Symbol('PaintProfilerRequested'),
91 ScaleChanged: Symbol("ScaleChanged") 783 ScaleChanged: Symbol('ScaleChanged')
92 }; 784 };
93 785
94 /** 786 /**
95 * @enum {number} 787 * @enum {number}
96 */ 788 */
97 WebInspector.Layers3DView.ChromeTexture = { 789 WebInspector.Layers3DView.ChromeTexture = {
98 Left: 0, 790 Left: 0,
99 Middle: 1, 791 Middle: 1,
100 Right: 2 792 Right: 2
101 }; 793 };
102 794
103 /** 795 /**
104 * @enum {string} 796 * @enum {string}
105 */ 797 */
106 WebInspector.Layers3DView.ScrollRectTitles = { 798 WebInspector.Layers3DView.ScrollRectTitles = {
107 RepaintsOnScroll: WebInspector.UIString("repaints on scroll"), 799 RepaintsOnScroll: WebInspector.UIString('repaints on scroll'),
108 TouchEventHandler: WebInspector.UIString("touch event listener"), 800 TouchEventHandler: WebInspector.UIString('touch event listener'),
109 WheelEventHandler: WebInspector.UIString("mousewheel event listener") 801 WheelEventHandler: WebInspector.UIString('mousewheel event listener')
110 }; 802 };
111 803
112 WebInspector.Layers3DView.FragmentShader = "" + 804 WebInspector.Layers3DView.FragmentShader = '' +
113 "precision mediump float;\n" + 805 'precision mediump float;\n' +
114 "varying vec4 vColor;\n" + 806 'varying vec4 vColor;\n' +
115 "varying vec2 vTextureCoord;\n" + 807 'varying vec2 vTextureCoord;\n' +
116 "uniform sampler2D uSampler;\n" + 808 'uniform sampler2D uSampler;\n' +
117 "void main(void)\n" + 809 'void main(void)\n' +
118 "{\n" + 810 '{\n' +
119 " gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord. t)) * vColor;\n" + 811 ' gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord. t)) * vColor;\n' +
120 "}"; 812 '}';
121 813
122 WebInspector.Layers3DView.VertexShader = "" + 814 WebInspector.Layers3DView.VertexShader = '' +
123 "attribute vec3 aVertexPosition;\n" + 815 'attribute vec3 aVertexPosition;\n' +
124 "attribute vec2 aTextureCoord;\n" + 816 'attribute vec2 aTextureCoord;\n' +
125 "attribute vec4 aVertexColor;\n" + 817 'attribute vec4 aVertexColor;\n' +
126 "uniform mat4 uPMatrix;\n" + 818 'uniform mat4 uPMatrix;\n' +
127 "varying vec2 vTextureCoord;\n" + 819 'varying vec2 vTextureCoord;\n' +
128 "varying vec4 vColor;\n" + 820 'varying vec4 vColor;\n' +
129 "void main(void)\n" + 821 'void main(void)\n' +
130 "{\n" + 822 '{\n' +
131 "gl_Position = uPMatrix * vec4(aVertexPosition, 1.0);\n" + 823 'gl_Position = uPMatrix * vec4(aVertexPosition, 1.0);\n' +
132 "vColor = aVertexColor;\n" + 824 'vColor = aVertexColor;\n' +
133 "vTextureCoord = aTextureCoord;\n" + 825 'vTextureCoord = aTextureCoord;\n' +
134 "}"; 826 '}';
135 827
136 WebInspector.Layers3DView.HoveredBorderColor = [0, 0, 255, 1]; 828 WebInspector.Layers3DView.HoveredBorderColor = [0, 0, 255, 1];
137 WebInspector.Layers3DView.SelectedBorderColor = [0, 255, 0, 1]; 829 WebInspector.Layers3DView.SelectedBorderColor = [0, 255, 0, 1];
138 WebInspector.Layers3DView.BorderColor = [0, 0, 0, 1]; 830 WebInspector.Layers3DView.BorderColor = [0, 0, 0, 1];
139 WebInspector.Layers3DView.ViewportBorderColor = [160, 160, 160, 1]; 831 WebInspector.Layers3DView.ViewportBorderColor = [160, 160, 160, 1];
140 WebInspector.Layers3DView.ScrollRectBackgroundColor = [178, 100, 100, 0.6]; 832 WebInspector.Layers3DView.ScrollRectBackgroundColor = [178, 100, 100, 0.6];
141 WebInspector.Layers3DView.HoveredImageMaskColor = [200, 200, 255, 1]; 833 WebInspector.Layers3DView.HoveredImageMaskColor = [200, 200, 255, 1];
142 WebInspector.Layers3DView.BorderWidth = 1; 834 WebInspector.Layers3DView.BorderWidth = 1;
143 WebInspector.Layers3DView.SelectedBorderWidth = 2; 835 WebInspector.Layers3DView.SelectedBorderWidth = 2;
144 WebInspector.Layers3DView.ViewportBorderWidth = 3; 836 WebInspector.Layers3DView.ViewportBorderWidth = 3;
145 837
146 WebInspector.Layers3DView.LayerSpacing = 20; 838 WebInspector.Layers3DView.LayerSpacing = 20;
147 WebInspector.Layers3DView.ScrollRectSpacing = 4; 839 WebInspector.Layers3DView.ScrollRectSpacing = 4;
148 840
149 WebInspector.Layers3DView.prototype = {
150 /**
151 * @param {?WebInspector.LayerTreeBase} layerTree
152 * @override
153 */
154 setLayerTree: function(layerTree)
155 {
156 this._layerTree = layerTree;
157 this._layerTexture = null;
158 delete this._oldTextureScale;
159 if (this._showPaints())
160 this._textureManager.setLayerTree(layerTree);
161 this._update();
162 },
163
164 /**
165 * @param {!WebInspector.Layer} layer
166 * @param {string=} imageURL
167 */
168 showImageForLayer: function(layer, imageURL)
169 {
170 if (!imageURL) {
171 this._layerTexture = null;
172 this._update();
173 return;
174 }
175 WebInspector.loadImage(imageURL).then(image => {
176 var texture = image && WebInspector.LayerTextureManager._createTextu reForImage(this._gl, image);
177 this._layerTexture = texture ? {layer: layer, texture: texture} : nu ll;
178 this._update();
179 });
180 },
181
182 onResize: function()
183 {
184 this._resizeCanvas();
185 this._update();
186 },
187
188 /**
189 * @override
190 */
191 willHide: function()
192 {
193 this._textureManager.suspend();
194 },
195
196 /**
197 * @override
198 */
199 wasShown: function()
200 {
201 this._textureManager.resume();
202 if (!this._needsUpdate)
203 return;
204 this._resizeCanvas();
205 this._update();
206 },
207
208 /**
209 * @param {!WebInspector.Layer} layer
210 */
211 updateLayerSnapshot: function(layer)
212 {
213 this._textureManager.layerNeedsUpdate(layer);
214 },
215
216 /**
217 * @param {!WebInspector.Layers3DView.OutlineType} type
218 * @param {?WebInspector.LayerView.Selection} selection
219 */
220 _setOutline: function(type, selection)
221 {
222 this._lastSelection[type] = selection;
223 this._update();
224 },
225
226 /**
227 * @param {?WebInspector.LayerView.Selection} selection
228 * @override
229 */
230 hoverObject: function(selection)
231 {
232 this._setOutline(WebInspector.Layers3DView.OutlineType.Hovered, selectio n);
233 },
234
235 /**
236 * @param {?WebInspector.LayerView.Selection} selection
237 * @override
238 */
239 selectObject: function(selection)
240 {
241 this._setOutline(WebInspector.Layers3DView.OutlineType.Hovered, null);
242 this._setOutline(WebInspector.Layers3DView.OutlineType.Selected, selecti on);
243 },
244
245 /**
246 * @param {!WebInspector.LayerView.Selection} selection
247 * @return {!Promise<?WebInspector.SnapshotWithRect>}
248 */
249 snapshotForSelection: function(selection)
250 {
251 if (selection.type() === WebInspector.LayerView.Selection.Type.Snapshot) {
252 var snapshotWithRect = /** @type {!WebInspector.LayerView.SnapshotSe lection} */ (selection).snapshot();
253 snapshotWithRect.snapshot.addReference();
254 return /** @type {!Promise<?WebInspector.SnapshotWithRect>} */ (Prom ise.resolve(snapshotWithRect));
255 }
256 if (selection.layer()) {
257 var promise = selection.layer().snapshots()[0];
258 if (promise)
259 return promise;
260 }
261 return /** @type {!Promise<?WebInspector.SnapshotWithRect>} */ (Promise. resolve(null));
262 },
263
264 /**
265 * @param {!Element} canvas
266 * @return {?WebGLRenderingContext}
267 */
268 _initGL: function(canvas)
269 {
270 var gl = canvas.getContext("webgl");
271 if (!gl)
272 return null;
273 gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
274 gl.enable(gl.BLEND);
275 gl.clearColor(0.0, 0.0, 0.0, 0.0);
276 gl.enable(gl.DEPTH_TEST);
277 return gl;
278 },
279
280 /**
281 * @param {!Object} type
282 * @param {string} script
283 */
284 _createShader: function(type, script)
285 {
286 var shader = this._gl.createShader(type);
287 this._gl.shaderSource(shader, script);
288 this._gl.compileShader(shader);
289 this._gl.attachShader(this._shaderProgram, shader);
290 },
291
292 _initShaders: function()
293 {
294 this._shaderProgram = this._gl.createProgram();
295 this._createShader(this._gl.FRAGMENT_SHADER, WebInspector.Layers3DView.F ragmentShader);
296 this._createShader(this._gl.VERTEX_SHADER, WebInspector.Layers3DView.Ver texShader);
297 this._gl.linkProgram(this._shaderProgram);
298 this._gl.useProgram(this._shaderProgram);
299
300 this._shaderProgram.vertexPositionAttribute = this._gl.getAttribLocation (this._shaderProgram, "aVertexPosition");
301 this._gl.enableVertexAttribArray(this._shaderProgram.vertexPositionAttri bute);
302 this._shaderProgram.vertexColorAttribute = this._gl.getAttribLocation(th is._shaderProgram, "aVertexColor");
303 this._gl.enableVertexAttribArray(this._shaderProgram.vertexColorAttribut e);
304 this._shaderProgram.textureCoordAttribute = this._gl.getAttribLocation(t his._shaderProgram, "aTextureCoord");
305 this._gl.enableVertexAttribArray(this._shaderProgram.textureCoordAttribu te);
306
307 this._shaderProgram.pMatrixUniform = this._gl.getUniformLocation(this._s haderProgram, "uPMatrix");
308 this._shaderProgram.samplerUniform = this._gl.getUniformLocation(this._s haderProgram, "uSampler");
309 },
310
311 _resizeCanvas: function()
312 {
313 this._canvasElement.width = this._canvasElement.offsetWidth * window.dev icePixelRatio;
314 this._canvasElement.height = this._canvasElement.offsetHeight * window.d evicePixelRatio;
315 },
316
317 _updateTransformAndConstraints: function()
318 {
319 var paddingFraction = 0.1;
320 var viewport = this._layerTree.viewportSize();
321 var root = this._layerTree.root();
322 var baseWidth = viewport ? viewport.width : this._dimensionsForAutoscale .width;
323 var baseHeight = viewport ? viewport.height : this._dimensionsForAutosca le.height;
324 var canvasWidth = this._canvasElement.width;
325 var canvasHeight = this._canvasElement.height;
326 var paddingX = canvasWidth * paddingFraction;
327 var paddingY = canvasHeight * paddingFraction;
328 var scaleX = (canvasWidth - 2 * paddingX) / baseWidth;
329 var scaleY = (canvasHeight - 2 * paddingY) / baseHeight;
330 var viewScale = Math.min(scaleX, scaleY);
331 var minScaleConstraint = Math.min(baseWidth / this._dimensionsForAutosca le.width, baseHeight / this._dimensionsForAutoscale.width) / 2;
332 this._transformController.setScaleConstraints(minScaleConstraint, 10 / v iewScale); // 1/viewScale is 1:1 in terms of pixels, so allow zooming to 10x of native size
333 var scale = this._transformController.scale();
334 var rotateX = this._transformController.rotateX();
335 var rotateY = this._transformController.rotateY();
336
337 this._scale = scale * viewScale;
338 var textureScale = Number.constrain(this._scale, 0.1, 1);
339 if (textureScale !== this._oldTextureScale) {
340 this._oldTextureScale = textureScale;
341 this._textureManager.setScale(textureScale);
342 this.dispatchEventToListeners(WebInspector.Layers3DView.Events.Scale Changed, textureScale);
343 }
344 var scaleAndRotationMatrix = new WebKitCSSMatrix().scale(scale, scale, s cale).translate(canvasWidth / 2, canvasHeight / 2, 0)
345 .rotate(rotateX, rotateY, 0).scale(viewScale, viewScale, viewScale). translate(-baseWidth / 2, -baseHeight / 2, 0);
346
347 var bounds;
348 for (var i = 0; i < this._rects.length; ++i)
349 bounds = WebInspector.Geometry.boundsForTransformedPoints(scaleAndRo tationMatrix, this._rects[i].vertices, bounds);
350
351 this._transformController.clampOffsets((paddingX - bounds.maxX) / window .devicePixelRatio, (canvasWidth - paddingX - bounds.minX) / window.devicePixelRa tio,
352 (paddingY - bounds.maxY) / window .devicePixelRatio, (canvasHeight - paddingY - bounds.minY) / window.devicePixelR atio);
353 var offsetX = this._transformController.offsetX() * window.devicePixelRa tio;
354 var offsetY = this._transformController.offsetY() * window.devicePixelRa tio;
355 // Multiply to translation matrix on the right rather than translate (wh ich would implicitly multiply on the left).
356 this._projectionMatrix = new WebKitCSSMatrix().translate(offsetX, offset Y, 0).multiply(scaleAndRotationMatrix);
357
358 var glProjectionMatrix = new WebKitCSSMatrix().scale(1, -1, -1).translat e(-1, -1, 0)
359 .scale(2 / this._canvasElement.width, 2 / this._canvasElement.height , 1 / 1000000).multiply(this._projectionMatrix);
360 this._gl.uniformMatrix4fv(this._shaderProgram.pMatrixUniform, false, thi s._arrayFromMatrix(glProjectionMatrix));
361 },
362
363 /**
364 * @param {!CSSMatrix} m
365 * @return {!Float32Array}
366 */
367 _arrayFromMatrix: function(m)
368 {
369 return new Float32Array([m.m11, m.m12, m.m13, m.m14, m.m21, m.m22, m.m23 , m.m24, m.m31, m.m32, m.m33, m.m34, m.m41, m.m42, m.m43, m.m44]);
370 },
371
372 _initWhiteTexture: function()
373 {
374 this._whiteTexture = this._gl.createTexture();
375 this._gl.bindTexture(this._gl.TEXTURE_2D, this._whiteTexture);
376 var whitePixel = new Uint8Array([255, 255, 255, 255]);
377 this._gl.texImage2D(this._gl.TEXTURE_2D, 0, this._gl.RGBA, 1, 1, 0, this ._gl.RGBA, this._gl.UNSIGNED_BYTE, whitePixel);
378 },
379
380 _initChromeTextures: function()
381 {
382 /**
383 * @this {WebInspector.Layers3DView}
384 * @param {!WebInspector.Layers3DView.ChromeTexture} index
385 * @param {string} url
386 */
387 function loadChromeTexture(index, url)
388 {
389 WebInspector.loadImage(url).then(image => {
390 this._chromeTextures[index] = image && WebInspector.LayerTexture Manager._createTextureForImage(this._gl, image) || undefined;
391 });
392 }
393 loadChromeTexture.call(this, WebInspector.Layers3DView.ChromeTexture.Lef t, "Images/chromeLeft.png");
394 loadChromeTexture.call(this, WebInspector.Layers3DView.ChromeTexture.Mid dle, "Images/chromeMiddle.png");
395 loadChromeTexture.call(this, WebInspector.Layers3DView.ChromeTexture.Rig ht, "Images/chromeRight.png");
396 },
397
398 /**
399 * @return {?WebGLRenderingContext}
400 */
401 _initGLIfNecessary: function()
402 {
403 if (this._gl)
404 return this._gl;
405 this._gl = this._initGL(this._canvasElement);
406 if (!this._gl)
407 return null;
408 this._initShaders();
409 this._initWhiteTexture();
410 this._initChromeTextures();
411 this._textureManager.setContext(this._gl);
412 return this._gl;
413 },
414
415 _calculateDepthsAndVisibility: function()
416 {
417 this._depthByLayerId = {};
418 var depth = 0;
419 var showInternalLayers = this._layerViewHost.showInternalLayersSetting() .get();
420 var root = showInternalLayers ? this._layerTree.root() : (this._layerTre e.contentRoot() || this._layerTree.root());
421 var queue = [root];
422 this._depthByLayerId[root.id()] = 0;
423 /** @type {!Set<!WebInspector.Layer>} */
424 this._visibleLayers = new Set();
425 while (queue.length > 0) {
426 var layer = queue.shift();
427 if (showInternalLayers || layer.drawsContent())
428 this._visibleLayers.add(layer);
429 var children = layer.children();
430 for (var i = 0; i < children.length; ++i) {
431 this._depthByLayerId[children[i].id()] = ++depth;
432 queue.push(children[i]);
433 }
434 }
435 this._maxDepth = depth;
436 },
437
438 /**
439 * @param {!WebInspector.Layer} layer
440 * @return {number}
441 */
442 _depthForLayer: function(layer)
443 {
444 return this._depthByLayerId[layer.id()] * WebInspector.Layers3DView.Laye rSpacing;
445 },
446
447 /**
448 * @param {!WebInspector.Layer} layer
449 * @param {number} index
450 * @return {number}
451 */
452 _calculateScrollRectDepth: function(layer, index)
453 {
454 return this._depthForLayer(layer) + index * WebInspector.Layers3DView.Sc rollRectSpacing + 1;
455 },
456
457 /**
458 * @param {!WebInspector.Layer} layer
459 */
460 _updateDimensionsForAutoscale: function(layer)
461 {
462 // We don't want to be precise, but rather pick something least affected by
463 // animationtransforms, so that we don't change scale too often. So let' s
464 // disregard transforms, scrolling and relative layer positioning and ch oose
465 // the largest dimensions of all layers.
466 this._dimensionsForAutoscale.width = Math.max(layer.width(), this._dimen sionsForAutoscale.width);
467 this._dimensionsForAutoscale.height = Math.max(layer.height(), this._dim ensionsForAutoscale.height);
468 },
469
470 /**
471 * @param {!WebInspector.Layer} layer
472 */
473 _calculateLayerRect: function(layer)
474 {
475 if (!this._visibleLayers.has(layer))
476 return;
477 var selection = new WebInspector.LayerView.LayerSelection(layer);
478 var rect = new WebInspector.Layers3DView.Rectangle(selection);
479 rect.setVertices(layer.quad(), this._depthForLayer(layer));
480 this._appendRect(rect);
481 this._updateDimensionsForAutoscale(layer);
482 },
483
484 /**
485 * @param {!WebInspector.Layers3DView.Rectangle} rect
486 */
487 _appendRect: function(rect)
488 {
489 var selection = rect.relatedObject;
490 var isSelected = WebInspector.LayerView.Selection.isEqual(this._lastSele ction[WebInspector.Layers3DView.OutlineType.Selected], selection);
491 var isHovered = WebInspector.LayerView.Selection.isEqual(this._lastSelec tion[WebInspector.Layers3DView.OutlineType.Hovered], selection);
492 if (isSelected) {
493 rect.borderColor = WebInspector.Layers3DView.SelectedBorderColor;
494 } else if (isHovered) {
495 rect.borderColor = WebInspector.Layers3DView.HoveredBorderColor;
496 var fillColor = rect.fillColor || [255, 255, 255, 1];
497 var maskColor = WebInspector.Layers3DView.HoveredImageMaskColor;
498 rect.fillColor = [fillColor[0] * maskColor[0] / 255, fillColor[1] * maskColor[1] / 255, fillColor[2] * maskColor[2] / 255, fillColor[3] * maskColor[ 3]];
499 } else {
500 rect.borderColor = WebInspector.Layers3DView.BorderColor;
501 }
502 rect.lineWidth = isSelected ? WebInspector.Layers3DView.SelectedBorderWi dth : WebInspector.Layers3DView.BorderWidth;
503 this._rects.push(rect);
504 },
505
506 /**
507 * @param {!WebInspector.Layer} layer
508 */
509 _calculateLayerScrollRects: function(layer)
510 {
511 var scrollRects = layer.scrollRects();
512 for (var i = 0; i < scrollRects.length; ++i) {
513 var selection = new WebInspector.LayerView.ScrollRectSelection(layer , i);
514 var rect = new WebInspector.Layers3DView.Rectangle(selection);
515 rect.calculateVerticesFromRect(layer, scrollRects[i].rect, this._cal culateScrollRectDepth(layer, i));
516 rect.fillColor = WebInspector.Layers3DView.ScrollRectBackgroundColor ;
517 this._appendRect(rect);
518 }
519 },
520
521 /**
522 * @param {!WebInspector.Layer} layer
523 */
524 _calculateLayerTileRects: function(layer)
525 {
526 var tiles = this._textureManager.tilesForLayer(layer);
527 for (var i = 0; i < tiles.length; ++i) {
528 var tile = tiles[i];
529 if (!tile.texture)
530 continue;
531 var selection = new WebInspector.LayerView.SnapshotSelection(layer, {rect: tile.rect, snapshot: tile.snapshot});
532 var rect = new WebInspector.Layers3DView.Rectangle(selection);
533 rect.calculateVerticesFromRect(layer, tile.rect, this._depthForLayer (layer) + 1);
534 rect.texture = tile.texture;
535 this._appendRect(rect);
536 }
537 },
538
539 _calculateRects: function()
540 {
541 this._rects = [];
542 this._dimensionsForAutoscale = { width: 0, height: 0 };
543 this._layerTree.forEachLayer(this._calculateLayerRect.bind(this));
544
545 if (this._showSlowScrollRectsSetting.get())
546 this._layerTree.forEachLayer(this._calculateLayerScrollRects.bind(th is));
547
548 if (this._layerTexture && this._visibleLayers.has(this._layerTexture.lay er)) {
549 var layer = this._layerTexture.layer;
550 var selection = new WebInspector.LayerView.LayerSelection(layer);
551 var rect = new WebInspector.Layers3DView.Rectangle(selection);
552 rect.setVertices(layer.quad(), this._depthForLayer(layer));
553 rect.texture = this._layerTexture.texture;
554 this._appendRect(rect);
555 } else if (this._showPaints()) {
556 this._layerTree.forEachLayer(this._calculateLayerTileRects.bind(this ));
557 }
558 },
559
560 /**
561 * @param {!Array.<number>} color
562 * @return {!Array.<number>}
563 */
564 _makeColorsArray: function(color)
565 {
566 var colors = [];
567 var normalizedColor = [color[0] / 255, color[1] / 255, color[2] / 255, c olor[3]];
568 for (var i = 0; i < 4; i++)
569 colors = colors.concat(normalizedColor);
570 return colors;
571 },
572
573 /**
574 * @param {!Object} attribute
575 * @param {!Array.<number>} array
576 * @param {number} length
577 */
578 _setVertexAttribute: function(attribute, array, length)
579 {
580 var gl = this._gl;
581 var buffer = gl.createBuffer();
582 gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
583 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(array), gl.STATIC_DRAW);
584 gl.vertexAttribPointer(attribute, length, gl.FLOAT, false, 0, 0);
585 },
586
587 /**
588 * @param {!Array.<number>} vertices
589 * @param {number} mode
590 * @param {!Array.<number>=} color
591 * @param {!Object=} texture
592 */
593 _drawRectangle: function(vertices, mode, color, texture)
594 {
595 var gl = this._gl;
596 var white = [255, 255, 255, 1];
597 color = color || white;
598 this._setVertexAttribute(this._shaderProgram.vertexPositionAttribute, ve rtices, 3);
599 this._setVertexAttribute(this._shaderProgram.textureCoordAttribute, [0, 1, 1, 1, 1, 0, 0, 0], 2);
600 this._setVertexAttribute(this._shaderProgram.vertexColorAttribute, this. _makeColorsArray(color), color.length);
601
602 if (texture) {
603 gl.activeTexture(gl.TEXTURE0);
604 gl.bindTexture(gl.TEXTURE_2D, texture);
605 gl.uniform1i(this._shaderProgram.samplerUniform, 0);
606 } else {
607 gl.bindTexture(gl.TEXTURE_2D, this._whiteTexture);
608 }
609
610 var numberOfVertices = vertices.length / 3;
611 gl.drawArrays(mode, 0, numberOfVertices);
612 },
613
614 /**
615 * @param {!Array.<number>} vertices
616 * @param {!WebGLTexture} texture
617 * @param {!Array.<number>=} color
618 */
619 _drawTexture: function(vertices, texture, color)
620 {
621 this._drawRectangle(vertices, this._gl.TRIANGLE_FAN, color, texture);
622 },
623
624 _drawViewportAndChrome: function()
625 {
626 var viewport = this._layerTree.viewportSize();
627 if (!viewport)
628 return;
629
630 var drawChrome = !WebInspector.moduleSetting("frameViewerHideChromeWindo w").get() && this._chromeTextures.length >= 3 && this._chromeTextures.indexOf(un defined) < 0;
631 var z = (this._maxDepth + 1) * WebInspector.Layers3DView.LayerSpacing;
632 var borderWidth = Math.ceil(WebInspector.Layers3DView.ViewportBorderWidt h * this._scale);
633 var vertices = [viewport.width, 0, z, viewport.width, viewport.height, z , 0, viewport.height, z, 0, 0, z];
634 this._gl.lineWidth(borderWidth);
635 this._drawRectangle(vertices, drawChrome ? this._gl.LINE_STRIP : this._g l.LINE_LOOP, WebInspector.Layers3DView.ViewportBorderColor);
636
637 if (!drawChrome)
638 return;
639
640 var borderAdjustment = WebInspector.Layers3DView.ViewportBorderWidth / 2 ;
641 var viewportWidth = this._layerTree.viewportSize().width + 2 * borderAdj ustment;
642 var chromeHeight = this._chromeTextures[0].image.naturalHeight;
643 var middleFragmentWidth = viewportWidth - this._chromeTextures[0].image. naturalWidth - this._chromeTextures[2].image.naturalWidth;
644 var x = -borderAdjustment;
645 var y = -chromeHeight;
646 for (var i = 0; i < this._chromeTextures.length; ++i) {
647 var width = i === WebInspector.Layers3DView.ChromeTexture.Middle ? m iddleFragmentWidth : this._chromeTextures[i].image.naturalWidth;
648 if (width < 0 || x + width > viewportWidth)
649 break;
650 vertices = [x, y, z, x + width, y, z, x + width, y + chromeHeight, z , x, y + chromeHeight, z];
651 this._drawTexture(vertices, /** @type {!WebGLTexture} */ (this._chro meTextures[i]));
652 x += width;
653 }
654 },
655
656 /**
657 * @param {!WebInspector.Layers3DView.Rectangle} rect
658 */
659 _drawViewRect: function(rect)
660 {
661 var vertices = rect.vertices;
662 if (rect.texture)
663 this._drawTexture(vertices, rect.texture, rect.fillColor || undefine d);
664 else if (rect.fillColor)
665 this._drawRectangle(vertices, this._gl.TRIANGLE_FAN, rect.fillColor) ;
666 this._gl.lineWidth(rect.lineWidth);
667 if (rect.borderColor)
668 this._drawRectangle(vertices, this._gl.LINE_LOOP, rect.borderColor);
669 },
670
671 _update: function()
672 {
673 if (!this.isShowing()) {
674 this._needsUpdate = true;
675 return;
676 }
677 if (!this._layerTree || !this._layerTree.root()) {
678 this._failBanner.show(this.contentElement);
679 return;
680 }
681 var gl = this._initGLIfNecessary();
682 if (!gl) {
683 this._failBanner.element.removeChildren();
684 this._failBanner.element.appendChild(this._webglDisabledBanner());
685 this._failBanner.show(this.contentElement);
686 return;
687 }
688 this._failBanner.detach();
689 this._gl.viewportWidth = this._canvasElement.width;
690 this._gl.viewportHeight = this._canvasElement.height;
691
692 this._calculateDepthsAndVisibility();
693 this._calculateRects();
694 this._updateTransformAndConstraints();
695
696 gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
697 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
698
699 this._rects.forEach(this._drawViewRect.bind(this));
700 this._drawViewportAndChrome();
701 },
702
703 /**
704 * @return {!Node}
705 */
706 _webglDisabledBanner: function()
707 {
708 var fragment = this.contentElement.ownerDocument.createDocumentFragment( );
709 fragment.createChild("div").textContent = WebInspector.UIString("Can't d isplay layers,");
710 fragment.createChild("div").textContent = WebInspector.UIString("WebGL s upport is disabled in your browser.");
711 fragment.appendChild(WebInspector.formatLocalized("Check %s for possible reasons.", [WebInspector.linkifyURLAsNode("about:gpu", undefined, undefined, tr ue)]));
712 return fragment;
713 },
714
715 /**
716 * @param {!Event} event
717 * @return {?WebInspector.LayerView.Selection}
718 */
719 _selectionFromEventPoint: function(event)
720 {
721 if (!this._layerTree)
722 return null;
723 var closestIntersectionPoint = Infinity;
724 var closestObject = null;
725 var projectionMatrix = new WebKitCSSMatrix().scale(1, -1, -1).translate( -1, -1, 0).multiply(this._projectionMatrix);
726 var x0 = (event.clientX - this._canvasElement.totalOffsetLeft()) * windo w.devicePixelRatio;
727 var y0 = -(event.clientY - this._canvasElement.totalOffsetTop()) * windo w.devicePixelRatio;
728
729 /**
730 * @param {!WebInspector.Layers3DView.Rectangle} rect
731 */
732 function checkIntersection(rect)
733 {
734 if (!rect.relatedObject)
735 return;
736 var t = rect.intersectWithLine(projectionMatrix, x0, y0);
737 if (t < closestIntersectionPoint) {
738 closestIntersectionPoint = t;
739 closestObject = rect.relatedObject;
740 }
741 }
742
743 this._rects.forEach(checkIntersection);
744 return closestObject;
745 },
746
747 /**
748 * @param {string} caption
749 * @param {string} name
750 * @param {boolean} value
751 * @param {!WebInspector.Toolbar} toolbar
752 * @return {!WebInspector.Setting}
753 */
754 _createVisibilitySetting: function(caption, name, value, toolbar)
755 {
756 var checkbox = new WebInspector.ToolbarCheckbox(WebInspector.UIString(ca ption));
757 toolbar.appendToolbarItem(checkbox);
758 var setting = WebInspector.settings.createSetting(name, value);
759 WebInspector.SettingsUI.bindCheckbox(checkbox.inputElement, setting);
760 setting.addChangeListener(this._update, this);
761 return setting;
762 },
763
764 _initToolbar: function()
765 {
766 this._panelToolbar = this._transformController.toolbar();
767 this.contentElement.appendChild(this._panelToolbar.element);
768 this._showSlowScrollRectsSetting = this._createVisibilitySetting("Slow s croll rects", "frameViewerShowSlowScrollRects", true, this._panelToolbar);
769 this._showPaintsSetting = this._createVisibilitySetting("Paints", "frame ViewerShowPaints", true, this._panelToolbar);
770 this._showPaintsSetting.addChangeListener(this._updatePaints, this);
771 WebInspector.moduleSetting("frameViewerHideChromeWindow").addChangeListe ner(this._update, this);
772 },
773
774 /**
775 * @param {!Event} event
776 */
777 _onContextMenu: function(event)
778 {
779 var contextMenu = new WebInspector.ContextMenu(event);
780 contextMenu.appendItem(WebInspector.UIString("Reset View"), this._transf ormController.resetAndNotify.bind(this._transformController), false);
781 var selection = this._selectionFromEventPoint(event);
782 if (selection && selection.type() === WebInspector.LayerView.Selection.T ype.Snapshot)
783 contextMenu.appendItem(WebInspector.UIString("Show Paint Profiler"), this.dispatchEventToListeners.bind(this, WebInspector.Layers3DView.Events.Paint ProfilerRequested, selection.snapshot()), false);
784 this._layerViewHost.showContextMenu(contextMenu, selection);
785 },
786
787 /**
788 * @param {!Event} event
789 */
790 _onMouseMove: function(event)
791 {
792 if (event.which)
793 return;
794 this._layerViewHost.hoverObject(this._selectionFromEventPoint(event));
795 },
796
797 /**
798 * @param {!Event} event
799 */
800 _onMouseDown: function(event)
801 {
802 this._mouseDownX = event.clientX;
803 this._mouseDownY = event.clientY;
804 },
805
806 /**
807 * @param {!Event} event
808 */
809 _onMouseUp: function(event)
810 {
811 const maxDistanceInPixels = 6;
812 if (this._mouseDownX && Math.abs(event.clientX - this._mouseDownX) < max DistanceInPixels && Math.abs(event.clientY - this._mouseDownY) < maxDistanceInPi xels)
813 this._layerViewHost.selectObject(this._selectionFromEventPoint(event ));
814 delete this._mouseDownX;
815 delete this._mouseDownY;
816 },
817
818 /**
819 * @param {!Event} event
820 */
821 _onDoubleClick: function(event)
822 {
823 var selection = this._selectionFromEventPoint(event);
824 if (selection && (selection.type() === WebInspector.LayerView.Selection. Type.Snapshot || selection.layer()))
825 this.dispatchEventToListeners(WebInspector.Layers3DView.Events.Paint ProfilerRequested, selection);
826 event.stopPropagation();
827 },
828
829 _updatePaints: function()
830 {
831 if (this._showPaints()) {
832 this._textureManager.setLayerTree(this._layerTree);
833 this._textureManager.forceUpdate();
834 } else {
835 this._textureManager.reset();
836 }
837 this._update();
838 },
839
840 /**
841 * @return {boolean}
842 */
843 _showPaints: function()
844 {
845 return this._showPaintsSetting.get();
846 },
847
848 __proto__: WebInspector.VBox.prototype
849 };
850
851 /** 841 /**
852 * @constructor 842 * @unrestricted
853 * @param {function()} textureUpdatedCallback
854 */ 843 */
855 WebInspector.LayerTextureManager = function(textureUpdatedCallback) 844 WebInspector.LayerTextureManager = class {
856 { 845 /**
846 * @param {function()} textureUpdatedCallback
847 */
848 constructor(textureUpdatedCallback) {
857 this._textureUpdatedCallback = textureUpdatedCallback; 849 this._textureUpdatedCallback = textureUpdatedCallback;
858 this._throttler = new WebInspector.Throttler(0); 850 this._throttler = new WebInspector.Throttler(0);
859 this._scale = 0; 851 this._scale = 0;
860 this._active = false; 852 this._active = false;
861 this.reset(); 853 this.reset();
854 }
855
856 /**
857 * @param {!Image} image
858 * @param {!WebGLRenderingContext} gl
859 * @return {!WebGLTexture} texture
860 */
861 static _createTextureForImage(gl, image) {
862 var texture = gl.createTexture();
863 texture.image = image;
864 gl.bindTexture(gl.TEXTURE_2D, texture);
865 gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
866 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture. image);
867 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
868 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
869 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
870 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
871 gl.bindTexture(gl.TEXTURE_2D, null);
872 return texture;
873 }
874
875 reset() {
876 if (this._tilesByLayer)
877 this.setLayerTree(null);
878
879 /** @type {!Map<!WebInspector.Layer, !Array<!WebInspector.LayerTextureManage r.Tile>>} */
880 this._tilesByLayer = new Map();
881 /** @type {!Array<!WebInspector.Layer>} */
882 this._queue = [];
883 }
884
885 /**
886 * @param {!WebGLRenderingContext} glContext
887 */
888 setContext(glContext) {
889 this._gl = glContext;
890 if (this._scale)
891 this._updateTextures();
892 }
893
894 suspend() {
895 this._active = false;
896 }
897
898 resume() {
899 this._active = true;
900 if (this._queue.length)
901 this._update();
902 }
903
904 /**
905 * @param {?WebInspector.LayerTreeBase} layerTree
906 */
907 setLayerTree(layerTree) {
908 var newLayers = new Set();
909 var oldLayers = Array.from(this._tilesByLayer.keys());
910 if (layerTree) {
911 layerTree.forEachLayer(layer => {
912 if (!layer.drawsContent())
913 return;
914 newLayers.add(layer);
915 if (!this._tilesByLayer.has(layer)) {
916 this._tilesByLayer.set(layer, []);
917 this.layerNeedsUpdate(layer);
918 }
919 });
920 }
921 if (!oldLayers.length)
922 this.forceUpdate();
923 for (var layer of oldLayers) {
924 if (newLayers.has(layer))
925 continue;
926 this._tilesByLayer.get(layer).forEach(tile => tile.dispose());
927 this._tilesByLayer.delete(layer);
928 }
929 }
930
931 /**
932 * @param {!WebInspector.Layer} layer
933 * @param {!Array<!WebInspector.SnapshotWithRect>} snapshots
934 * @return {!Promise}
935 */
936 _setSnapshotsForLayer(layer, snapshots) {
937 var oldSnapshotsToTiles = new Map((this._tilesByLayer.get(layer) || []).map( tile => [tile.snapshot, tile]));
938 var newTiles = [];
939 var reusedTiles = [];
940 for (var snapshot of snapshots) {
941 var oldTile = oldSnapshotsToTiles.get(snapshot);
942 if (oldTile) {
943 reusedTiles.push(oldTile);
944 oldSnapshotsToTiles.delete(oldTile);
945 } else {
946 newTiles.push(new WebInspector.LayerTextureManager.Tile(snapshot));
947 }
948 }
949 this._tilesByLayer.set(layer, reusedTiles.concat(newTiles));
950 for (var tile of oldSnapshotsToTiles.values())
951 tile.dispose();
952 if (!this._gl || !this._scale)
953 return Promise.resolve();
954 return Promise.all(newTiles.map(tile => tile.update(this._gl, this._scale))) .then(this._textureUpdatedCallback);
955 }
956
957 /**
958 * @param {number} scale
959 */
960 setScale(scale) {
961 if (this._scale && this._scale >= scale)
962 return;
963 this._scale = scale;
964 this._updateTextures();
965 }
966
967 /**
968 * @param {!WebInspector.Layer} layer
969 * @return {!Array<!WebInspector.LayerTextureManager.Tile>}
970 */
971 tilesForLayer(layer) {
972 return this._tilesByLayer.get(layer) || [];
973 }
974
975 /**
976 * @param {!WebInspector.Layer} layer
977 */
978 layerNeedsUpdate(layer) {
979 if (this._queue.indexOf(layer) < 0)
980 this._queue.push(layer);
981 if (this._active)
982 this._throttler.schedule(this._update.bind(this));
983 }
984
985 forceUpdate() {
986 this._queue.forEach(layer => this._updateLayer(layer));
987 this._queue = [];
988 this._throttler.flush();
989 }
990
991 /**
992 * @return {!Promise}
993 */
994 _update() {
995 var layer = this._queue.shift();
996 if (!layer)
997 return Promise.resolve();
998 if (this._queue.length)
999 this._throttler.schedule(this._update.bind(this));
1000 return this._updateLayer(layer);
1001 }
1002
1003 /**
1004 * @param {!WebInspector.Layer} layer
1005 * @return {!Promise}
1006 */
1007 _updateLayer(layer) {
1008 return Promise.all(layer.snapshots())
1009 .then(snapshots => this._setSnapshotsForLayer(layer, snapshots.filter(sn apshot => !!snapshot)));
1010 }
1011
1012 _updateTextures() {
1013 if (!this._gl)
1014 return;
1015 if (!this._scale)
1016 return;
1017
1018 for (var tiles of this._tilesByLayer.values()) {
1019 for (var tile of tiles) {
1020 var promise = tile.updateScale(this._gl, this._scale);
1021 if (promise)
1022 promise.then(this._textureUpdatedCallback);
1023 }
1024 }
1025 }
862 }; 1026 };
863 1027
864 WebInspector.LayerTextureManager.prototype = {
865 reset: function()
866 {
867 if (this._tilesByLayer)
868 this.setLayerTree(null);
869
870 /** @type {!Map<!WebInspector.Layer, !Array<!WebInspector.LayerTextureMa nager.Tile>>} */
871 this._tilesByLayer = new Map();
872 /** @type {!Array<!WebInspector.Layer>} */
873 this._queue = [];
874 },
875
876 /**
877 * @param {!WebGLRenderingContext} glContext
878 */
879 setContext: function(glContext)
880 {
881 this._gl = glContext;
882 if (this._scale)
883 this._updateTextures();
884 },
885
886 suspend: function()
887 {
888 this._active = false;
889 },
890
891 resume: function()
892 {
893 this._active = true;
894 if (this._queue.length)
895 this._update();
896 },
897
898 /**
899 * @param {?WebInspector.LayerTreeBase} layerTree
900 */
901 setLayerTree: function(layerTree)
902 {
903 var newLayers = new Set();
904 var oldLayers = Array.from(this._tilesByLayer.keys());
905 if (layerTree) {
906 layerTree.forEachLayer(layer => {
907 if (!layer.drawsContent())
908 return;
909 newLayers.add(layer);
910 if (!this._tilesByLayer.has(layer)) {
911 this._tilesByLayer.set(layer, []);
912 this.layerNeedsUpdate(layer);
913 }
914 });
915 }
916 if (!oldLayers.length)
917 this.forceUpdate();
918 for (var layer of oldLayers) {
919 if (newLayers.has(layer))
920 continue;
921 this._tilesByLayer.get(layer).forEach(tile => tile.dispose());
922 this._tilesByLayer.delete(layer);
923 }
924 },
925
926 /**
927 * @param {!WebInspector.Layer} layer
928 * @param {!Array<!WebInspector.SnapshotWithRect>} snapshots
929 * @return {!Promise}
930 */
931 _setSnapshotsForLayer: function(layer, snapshots)
932 {
933 var oldSnapshotsToTiles = new Map((this._tilesByLayer.get(layer) || []). map(tile => [tile.snapshot, tile]));
934 var newTiles = [];
935 var reusedTiles = [];
936 for (var snapshot of snapshots) {
937 var oldTile = oldSnapshotsToTiles.get(snapshot);
938 if (oldTile) {
939 reusedTiles.push(oldTile);
940 oldSnapshotsToTiles.delete(oldTile);
941 } else {
942 newTiles.push(new WebInspector.LayerTextureManager.Tile(snapshot ));
943 }
944 }
945 this._tilesByLayer.set(layer, reusedTiles.concat(newTiles));
946 for (var tile of oldSnapshotsToTiles.values())
947 tile.dispose();
948 if (!this._gl || !this._scale)
949 return Promise.resolve();
950 return Promise.all(newTiles.map(tile => tile.update(this._gl, this._scal e))).then(this._textureUpdatedCallback);
951 },
952
953 /**
954 * @param {number} scale
955 */
956 setScale: function(scale)
957 {
958 if (this._scale && this._scale >= scale)
959 return;
960 this._scale = scale;
961 this._updateTextures();
962 },
963
964 /**
965 * @param {!WebInspector.Layer} layer
966 * @return {!Array<!WebInspector.LayerTextureManager.Tile>}
967 */
968 tilesForLayer: function(layer)
969 {
970 return this._tilesByLayer.get(layer) || [];
971 },
972
973 /**
974 * @param {!WebInspector.Layer} layer
975 */
976 layerNeedsUpdate: function(layer)
977 {
978 if (this._queue.indexOf(layer) < 0)
979 this._queue.push(layer);
980 if (this._active)
981 this._throttler.schedule(this._update.bind(this));
982 },
983
984 forceUpdate: function()
985 {
986 this._queue.forEach(layer => this._updateLayer(layer));
987 this._queue = [];
988 this._throttler.flush();
989 },
990
991 /**
992 * @return {!Promise}
993 */
994 _update: function()
995 {
996 var layer = this._queue.shift();
997 if (!layer)
998 return Promise.resolve();
999 if (this._queue.length)
1000 this._throttler.schedule(this._update.bind(this));
1001 return this._updateLayer(layer);
1002 },
1003
1004 /**
1005 * @param {!WebInspector.Layer} layer
1006 * @return {!Promise}
1007 */
1008 _updateLayer: function(layer)
1009 {
1010 return Promise.all(layer.snapshots()).then(snapshots =>
1011 this._setSnapshotsForLayer(layer, snapshots.filter(snapshot => !!sna pshot)));
1012 },
1013
1014 _updateTextures: function()
1015 {
1016 if (!this._gl)
1017 return;
1018 if (!this._scale)
1019 return;
1020
1021 for (var tiles of this._tilesByLayer.values()) {
1022 for (var tile of tiles) {
1023 var promise = tile.updateScale(this._gl, this._scale);
1024 if (promise)
1025 promise.then(this._textureUpdatedCallback);
1026 }
1027 }
1028 }
1029 };
1030
1031 /** 1028 /**
1032 * @constructor 1029 * @unrestricted
1033 * @param {?WebInspector.LayerView.Selection} relatedObject
1034 */ 1030 */
1035 WebInspector.Layers3DView.Rectangle = function(relatedObject) 1031 WebInspector.Layers3DView.Rectangle = class {
1036 { 1032 /**
1033 * @param {?WebInspector.LayerView.Selection} relatedObject
1034 */
1035 constructor(relatedObject) {
1037 this.relatedObject = relatedObject; 1036 this.relatedObject = relatedObject;
1038 /** @type {number} */ 1037 /** @type {number} */
1039 this.lineWidth = 1; 1038 this.lineWidth = 1;
1040 /** @type {?Array.<number>} */ 1039 /** @type {?Array.<number>} */
1041 this.borderColor = null; 1040 this.borderColor = null;
1042 /** @type {?Array.<number>} */ 1041 /** @type {?Array.<number>} */
1043 this.fillColor = null; 1042 this.fillColor = null;
1044 /** @type {?WebGLTexture} */ 1043 /** @type {?WebGLTexture} */
1045 this.texture = null; 1044 this.texture = null;
1045 }
1046
1047 /**
1048 * @param {!Array.<number>} quad
1049 * @param {number} z
1050 */
1051 setVertices(quad, z) {
1052 this.vertices = [quad[0], quad[1], z, quad[2], quad[3], z, quad[4], quad[5], z, quad[6], quad[7], z];
1053 }
1054
1055 /**
1056 * Finds coordinates of point on layer quad, having offsets (ratioX * width) a nd (ratioY * height)
1057 * from the left corner of the initial layer rect, where width and heigth are layer bounds.
1058 * @param {!Array.<number>} quad
1059 * @param {number} ratioX
1060 * @param {number} ratioY
1061 * @return {!Array.<number>}
1062 */
1063 _calculatePointOnQuad(quad, ratioX, ratioY) {
1064 var x0 = quad[0];
1065 var y0 = quad[1];
1066 var x1 = quad[2];
1067 var y1 = quad[3];
1068 var x2 = quad[4];
1069 var y2 = quad[5];
1070 var x3 = quad[6];
1071 var y3 = quad[7];
1072 // Point on the first quad side clockwise
1073 var firstSidePointX = x0 + ratioX * (x1 - x0);
1074 var firstSidePointY = y0 + ratioX * (y1 - y0);
1075 // Point on the third quad side clockwise
1076 var thirdSidePointX = x3 + ratioX * (x2 - x3);
1077 var thirdSidePointY = y3 + ratioX * (y2 - y3);
1078 var x = firstSidePointX + ratioY * (thirdSidePointX - firstSidePointX);
1079 var y = firstSidePointY + ratioY * (thirdSidePointY - firstSidePointY);
1080 return [x, y];
1081 }
1082
1083 /**
1084 * @param {!WebInspector.Layer} layer
1085 * @param {!DOMAgent.Rect} rect
1086 * @param {number} z
1087 */
1088 calculateVerticesFromRect(layer, rect, z) {
1089 var quad = layer.quad();
1090 var rx1 = rect.x / layer.width();
1091 var rx2 = (rect.x + rect.width) / layer.width();
1092 var ry1 = rect.y / layer.height();
1093 var ry2 = (rect.y + rect.height) / layer.height();
1094 var rectQuad = this._calculatePointOnQuad(quad, rx1, ry1)
1095 .concat(this._calculatePointOnQuad(quad, rx2, ry1))
1096 .concat(this._calculatePointOnQuad(quad, rx2, ry2))
1097 .concat(this._calculatePointOnQuad(quad, rx1, ry2));
1098 this.setVertices(rectQuad, z);
1099 }
1100
1101 /**
1102 * Intersects quad with given transform matrix and line l(t) = (x0, y0, t)
1103 * @param {!CSSMatrix} matrix
1104 * @param {number} x0
1105 * @param {number} y0
1106 * @return {(number|undefined)}
1107 */
1108 intersectWithLine(matrix, x0, y0) {
1109 var i;
1110 // Vertices of the quad with transform matrix applied
1111 var points = [];
1112 for (i = 0; i < 4; ++i)
1113 points[i] = WebInspector.Geometry.multiplyVectorByMatrixAndNormalize(
1114 new WebInspector.Geometry.Vector(this.vertices[i * 3], this.vertices[i * 3 + 1], this.vertices[i * 3 + 2]),
1115 matrix);
1116 // Calculating quad plane normal
1117 var normal = WebInspector.Geometry.crossProduct(
1118 WebInspector.Geometry.subtract(points[1], points[0]), WebInspector.Geome try.subtract(points[2], points[1]));
1119 // General form of the equation of the quad plane: A * x + B * y + C * z + D = 0
1120 var A = normal.x;
1121 var B = normal.y;
1122 var C = normal.z;
1123 var D = -(A * points[0].x + B * points[0].y + C * points[0].z);
1124 // Finding t from the equation
1125 var t = -(D + A * x0 + B * y0) / C;
1126 // Point of the intersection
1127 var pt = new WebInspector.Geometry.Vector(x0, y0, t);
1128 // Vectors from the intersection point to vertices of the quad
1129 var tVects = points.map(WebInspector.Geometry.subtract.bind(null, pt));
1130 // Intersection point lies inside of the polygon if scalar products of norma l of the plane and
1131 // cross products of successive tVects are all nonstrictly above or all nons trictly below zero
1132 for (i = 0; i < tVects.length; ++i) {
1133 var product = WebInspector.Geometry.scalarProduct(
1134 normal, WebInspector.Geometry.crossProduct(tVects[i], tVects[(i + 1) % tVects.length]));
1135 if (product < 0)
1136 return undefined;
1137 }
1138 return t;
1139 }
1046 }; 1140 };
1047 1141
1048 WebInspector.Layers3DView.Rectangle.prototype = {
1049 /**
1050 * @param {!Array.<number>} quad
1051 * @param {number} z
1052 */
1053 setVertices: function(quad, z)
1054 {
1055 this.vertices = [quad[0], quad[1], z, quad[2], quad[3], z, quad[4], quad [5], z, quad[6], quad[7], z];
1056 },
1057
1058 /**
1059 * Finds coordinates of point on layer quad, having offsets (ratioX * width) and (ratioY * height)
1060 * from the left corner of the initial layer rect, where width and heigth ar e layer bounds.
1061 * @param {!Array.<number>} quad
1062 * @param {number} ratioX
1063 * @param {number} ratioY
1064 * @return {!Array.<number>}
1065 */
1066 _calculatePointOnQuad: function(quad, ratioX, ratioY)
1067 {
1068 var x0 = quad[0];
1069 var y0 = quad[1];
1070 var x1 = quad[2];
1071 var y1 = quad[3];
1072 var x2 = quad[4];
1073 var y2 = quad[5];
1074 var x3 = quad[6];
1075 var y3 = quad[7];
1076 // Point on the first quad side clockwise
1077 var firstSidePointX = x0 + ratioX * (x1 - x0);
1078 var firstSidePointY = y0 + ratioX * (y1 - y0);
1079 // Point on the third quad side clockwise
1080 var thirdSidePointX = x3 + ratioX * (x2 - x3);
1081 var thirdSidePointY = y3 + ratioX * (y2 - y3);
1082 var x = firstSidePointX + ratioY * (thirdSidePointX - firstSidePointX);
1083 var y = firstSidePointY + ratioY * (thirdSidePointY - firstSidePointY);
1084 return [x, y];
1085 },
1086
1087 /**
1088 * @param {!WebInspector.Layer} layer
1089 * @param {!DOMAgent.Rect} rect
1090 * @param {number} z
1091 */
1092 calculateVerticesFromRect: function(layer, rect, z)
1093 {
1094 var quad = layer.quad();
1095 var rx1 = rect.x / layer.width();
1096 var rx2 = (rect.x + rect.width) / layer.width();
1097 var ry1 = rect.y / layer.height();
1098 var ry2 = (rect.y + rect.height) / layer.height();
1099 var rectQuad = this._calculatePointOnQuad(quad, rx1, ry1).concat(this._c alculatePointOnQuad(quad, rx2, ry1))
1100 .concat(this._calculatePointOnQuad(quad, rx2, ry2)).concat(this._cal culatePointOnQuad(quad, rx1, ry2));
1101 this.setVertices(rectQuad, z);
1102 },
1103
1104 /**
1105 * Intersects quad with given transform matrix and line l(t) = (x0, y0, t)
1106 * @param {!CSSMatrix} matrix
1107 * @param {number} x0
1108 * @param {number} y0
1109 * @return {(number|undefined)}
1110 */
1111 intersectWithLine: function(matrix, x0, y0)
1112 {
1113 var i;
1114 // Vertices of the quad with transform matrix applied
1115 var points = [];
1116 for (i = 0; i < 4; ++i)
1117 points[i] = WebInspector.Geometry.multiplyVectorByMatrixAndNormalize (new WebInspector.Geometry.Vector(this.vertices[i * 3], this.vertices[i * 3 + 1] , this.vertices[i * 3 + 2]), matrix);
1118 // Calculating quad plane normal
1119 var normal = WebInspector.Geometry.crossProduct(WebInspector.Geometry.su btract(points[1], points[0]), WebInspector.Geometry.subtract(points[2], points[1 ]));
1120 // General form of the equation of the quad plane: A * x + B * y + C * z + D = 0
1121 var A = normal.x;
1122 var B = normal.y;
1123 var C = normal.z;
1124 var D = -(A * points[0].x + B * points[0].y + C * points[0].z);
1125 // Finding t from the equation
1126 var t = -(D + A * x0 + B * y0) / C;
1127 // Point of the intersection
1128 var pt = new WebInspector.Geometry.Vector(x0, y0, t);
1129 // Vectors from the intersection point to vertices of the quad
1130 var tVects = points.map(WebInspector.Geometry.subtract.bind(null, pt));
1131 // Intersection point lies inside of the polygon if scalar products of n ormal of the plane and
1132 // cross products of successive tVects are all nonstrictly above or all nonstrictly below zero
1133 for (i = 0; i < tVects.length; ++i) {
1134 var product = WebInspector.Geometry.scalarProduct(normal, WebInspect or.Geometry.crossProduct(tVects[i], tVects[(i + 1) % tVects.length]));
1135 if (product < 0)
1136 return undefined;
1137 }
1138 return t;
1139 }
1140 };
1141 1142
1142 /** 1143 /**
1143 * @param {!Image} image 1144 * @unrestricted
1144 * @param {!WebGLRenderingContext} gl
1145 * @return {!WebGLTexture} texture
1146 */ 1145 */
1147 WebInspector.LayerTextureManager._createTextureForImage = function(gl, image) 1146 WebInspector.LayerTextureManager.Tile = class {
1148 { 1147 /**
1149 var texture = gl.createTexture(); 1148 * @param {!WebInspector.SnapshotWithRect} snapshotWithRect
1150 texture.image = image; 1149 */
1151 gl.bindTexture(gl.TEXTURE_2D, texture); 1150 constructor(snapshotWithRect) {
1152 gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
1153 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture. image);
1154 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
1155 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
1156 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
1157 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
1158 gl.bindTexture(gl.TEXTURE_2D, null);
1159 return texture;
1160 };
1161
1162 /**
1163 * @constructor
1164 * @param {!WebInspector.SnapshotWithRect} snapshotWithRect
1165 */
1166 WebInspector.LayerTextureManager.Tile = function(snapshotWithRect)
1167 {
1168 this.snapshot = snapshotWithRect.snapshot; 1151 this.snapshot = snapshotWithRect.snapshot;
1169 this.rect = snapshotWithRect.rect; 1152 this.rect = snapshotWithRect.rect;
1170 this.scale = 0; 1153 this.scale = 0;
1171 /** @type {?WebGLTexture} */ 1154 /** @type {?WebGLTexture} */
1172 this.texture = null; 1155 this.texture = null;
1156 }
1157
1158 dispose() {
1159 this.snapshot.release();
1160 if (this.texture) {
1161 this._gl.deleteTexture(this.texture);
1162 this.texture = null;
1163 }
1164 }
1165
1166 /**
1167 * @param {!WebGLRenderingContext} glContext
1168 * @param {number} scale
1169 * @return {?Promise}
1170 */
1171 updateScale(glContext, scale) {
1172 if (this.texture && this.scale >= scale)
1173 return null;
1174 return this.update(glContext, scale);
1175 }
1176
1177 /**
1178 * @param {!WebGLRenderingContext} glContext
1179 * @param {number} scale
1180 * @return {!Promise}
1181 */
1182 update(glContext, scale) {
1183 this._gl = glContext;
1184 this.scale = scale;
1185 return this.snapshot.replay(null, null, scale)
1186 .then(imageURL => imageURL && WebInspector.loadImage(imageURL))
1187 .then(image => {
1188 this.texture = image && WebInspector.LayerTextureManager._createTextur eForImage(glContext, image);
1189 });
1190 }
1173 }; 1191 };
1174
1175 WebInspector.LayerTextureManager.Tile.prototype = {
1176 dispose: function()
1177 {
1178 this.snapshot.release();
1179 if (this.texture) {
1180 this._gl.deleteTexture(this.texture);
1181 this.texture = null;
1182 }
1183 },
1184
1185 /**
1186 * @param {!WebGLRenderingContext} glContext
1187 * @param {number} scale
1188 * @return {?Promise}
1189 */
1190 updateScale: function(glContext, scale)
1191 {
1192 if (this.texture && this.scale >= scale)
1193 return null;
1194 return this.update(glContext, scale);
1195 },
1196
1197 /**
1198 * @param {!WebGLRenderingContext} glContext
1199 * @param {number} scale
1200 * @return {!Promise}
1201 */
1202 update: function(glContext, scale)
1203 {
1204 this._gl = glContext;
1205 this.scale = scale;
1206 return this.snapshot.replay(null, null, scale)
1207 .then(imageURL => imageURL && WebInspector.loadImage(imageURL))
1208 .then(image => {
1209 this.texture = image && WebInspector.LayerTextureManager._create TextureForImage(glContext, image);
1210 });
1211 }
1212 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698