| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (C) 2014 Google Inc. All rights reserved. | |
| 3 * | |
| 4 * Redistribution and use in source and binary forms, with or without | |
| 5 * modification, are permitted provided that the following conditions are | |
| 6 * met: | |
| 7 * | |
| 8 * * Redistributions of source code must retain the above copyright | |
| 9 * notice, this list of conditions and the following disclaimer. | |
| 10 * * Redistributions in binary form must reproduce the above | |
| 11 * copyright notice, this list of conditions and the following disclaimer | |
| 12 * in the documentation and/or other materials provided with the | |
| 13 * distribution. | |
| 14 * * Neither the name of Google Inc. nor the names of its | |
| 15 * contributors may be used to endorse or promote products derived from | |
| 16 * this software without specific prior written permission. | |
| 17 * | |
| 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 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. | |
| 29 */ | |
| 30 | |
| 31 /** | |
| 32 * @constructor | |
| 33 * @extends {WebInspector.VBox} | |
| 34 * @param {!WebInspector.LayerViewHost} layerViewHost | |
| 35 * @implements {WebInspector.LayerView} | |
| 36 */ | |
| 37 WebInspector.Layers3DView = function(layerViewHost) | |
| 38 { | |
| 39 WebInspector.VBox.call(this); | |
| 40 this.element.classList.add("layers-3d-view"); | |
| 41 this._failBanner = new WebInspector.VBox(); | |
| 42 this._failBanner.element.classList.add("banner"); | |
| 43 this._failBanner.element.createTextChild(WebInspector.UIString("Layer inform
ation is not yet available.")); | |
| 44 | |
| 45 this._layerViewHost = layerViewHost; | |
| 46 this._layerViewHost.registerView(this); | |
| 47 | |
| 48 this._transformController = new WebInspector.TransformController(this.elemen
t); | |
| 49 this._transformController.addEventListener(WebInspector.TransformController.
Events.TransformChanged, this._update, this); | |
| 50 this._initToolbar(); | |
| 51 | |
| 52 this._canvasElement = this.element.createChild("canvas"); | |
| 53 this._canvasElement.tabIndex = 0; | |
| 54 this._canvasElement.addEventListener("dblclick", this._onDoubleClick.bind(th
is), false); | |
| 55 this._canvasElement.addEventListener("mousedown", this._onMouseDown.bind(thi
s), false); | |
| 56 this._canvasElement.addEventListener("mouseup", this._onMouseUp.bind(this),
false); | |
| 57 this._canvasElement.addEventListener("mouseleave", this._onMouseMove.bind(th
is), false); | |
| 58 this._canvasElement.addEventListener("mousemove", this._onMouseMove.bind(thi
s), false); | |
| 59 this._canvasElement.addEventListener("contextmenu", this._onContextMenu.bind
(this), false); | |
| 60 | |
| 61 this._lastSelection = {}; | |
| 62 this._layerTree = null; | |
| 63 this._textureManager = new WebInspector.LayerTextureManager(); | |
| 64 this._textureManager.addEventListener(WebInspector.LayerTextureManager.Event
s.TextureUpdated, this._update, this); | |
| 65 /** @type Array.<!WebGLTexture|undefined> */ | |
| 66 this._chromeTextures = []; | |
| 67 this._rects = []; | |
| 68 | |
| 69 this._layerViewHost.showInternalLayersSetting().addChangeListener(this._upda
te, this); | |
| 70 } | |
| 71 | |
| 72 /** @typedef {{borderColor: !Array.<number>, borderWidth: number}} */ | |
| 73 WebInspector.Layers3DView.LayerStyle; | |
| 74 | |
| 75 /** @typedef {{layerId: string, rect: !Array.<number>, snapshot: !WebInspector.P
aintProfilerSnapshot, traceEvent: !WebInspector.TracingModel.Event}} */ | |
| 76 WebInspector.Layers3DView.PaintTile; | |
| 77 | |
| 78 /** | |
| 79 * @enum {string} | |
| 80 */ | |
| 81 WebInspector.Layers3DView.OutlineType = { | |
| 82 Hovered: "hovered", | |
| 83 Selected: "selected" | |
| 84 } | |
| 85 | |
| 86 /** | |
| 87 * @enum {string} | |
| 88 */ | |
| 89 /** @enum {symbol} */ | |
| 90 WebInspector.Layers3DView.Events = { | |
| 91 LayerSnapshotRequested: Symbol("LayerSnapshotRequested"), | |
| 92 PaintProfilerRequested: Symbol("PaintProfilerRequested") | |
| 93 } | |
| 94 | |
| 95 /** | |
| 96 * @enum {number} | |
| 97 */ | |
| 98 WebInspector.Layers3DView.ChromeTexture = { | |
| 99 Left: 0, | |
| 100 Middle: 1, | |
| 101 Right: 2 | |
| 102 } | |
| 103 | |
| 104 /** | |
| 105 * @enum {string} | |
| 106 */ | |
| 107 WebInspector.Layers3DView.ScrollRectTitles = { | |
| 108 RepaintsOnScroll: WebInspector.UIString("repaints on scroll"), | |
| 109 TouchEventHandler: WebInspector.UIString("touch event listener"), | |
| 110 WheelEventHandler: WebInspector.UIString("mousewheel event listener") | |
| 111 } | |
| 112 | |
| 113 WebInspector.Layers3DView.FragmentShader = "" + | |
| 114 "precision mediump float;\n" + | |
| 115 "varying vec4 vColor;\n" + | |
| 116 "varying vec2 vTextureCoord;\n" + | |
| 117 "uniform sampler2D uSampler;\n" + | |
| 118 "void main(void)\n" + | |
| 119 "{\n" + | |
| 120 " gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.
t)) * vColor;\n" + | |
| 121 "}"; | |
| 122 | |
| 123 WebInspector.Layers3DView.VertexShader = "" + | |
| 124 "attribute vec3 aVertexPosition;\n" + | |
| 125 "attribute vec2 aTextureCoord;\n" + | |
| 126 "attribute vec4 aVertexColor;\n" + | |
| 127 "uniform mat4 uPMatrix;\n" + | |
| 128 "varying vec2 vTextureCoord;\n" + | |
| 129 "varying vec4 vColor;\n" + | |
| 130 "void main(void)\n" + | |
| 131 "{\n" + | |
| 132 "gl_Position = uPMatrix * vec4(aVertexPosition, 1.0);\n" + | |
| 133 "vColor = aVertexColor;\n" + | |
| 134 "vTextureCoord = aTextureCoord;\n" + | |
| 135 "}"; | |
| 136 | |
| 137 WebInspector.Layers3DView.HoveredBorderColor = [0, 0, 255, 1]; | |
| 138 WebInspector.Layers3DView.SelectedBorderColor = [0, 255, 0, 1]; | |
| 139 WebInspector.Layers3DView.BorderColor = [0, 0, 0, 1]; | |
| 140 WebInspector.Layers3DView.ViewportBorderColor = [160, 160, 160, 1]; | |
| 141 WebInspector.Layers3DView.ScrollRectBackgroundColor = [178, 100, 100, 0.6]; | |
| 142 WebInspector.Layers3DView.HoveredImageMaskColor = [200, 200, 255, 1]; | |
| 143 WebInspector.Layers3DView.BorderWidth = 1; | |
| 144 WebInspector.Layers3DView.SelectedBorderWidth = 2; | |
| 145 WebInspector.Layers3DView.ViewportBorderWidth = 3; | |
| 146 | |
| 147 WebInspector.Layers3DView.LayerSpacing = 20; | |
| 148 WebInspector.Layers3DView.ScrollRectSpacing = 4; | |
| 149 | |
| 150 WebInspector.Layers3DView.prototype = { | |
| 151 /** | |
| 152 * @param {?WebInspector.LayerTreeBase} layerTree | |
| 153 * @override | |
| 154 */ | |
| 155 setLayerTree: function(layerTree) | |
| 156 { | |
| 157 this._layerTree = layerTree; | |
| 158 this._textureManager.reset(); | |
| 159 this._update(); | |
| 160 }, | |
| 161 | |
| 162 /** | |
| 163 * @param {?Array.<!WebInspector.Layers3DView.PaintTile>} tiles | |
| 164 */ | |
| 165 setTiles: function(tiles) | |
| 166 { | |
| 167 this._textureManager.setTiles(tiles); | |
| 168 }, | |
| 169 | |
| 170 /** | |
| 171 * @param {!WebInspector.Layer} layer | |
| 172 * @param {string=} imageURL | |
| 173 */ | |
| 174 showImageForLayer: function(layer, imageURL) | |
| 175 { | |
| 176 if (imageURL) | |
| 177 this._textureManager.createTexture(onTextureCreated.bind(this), imag
eURL); | |
| 178 else | |
| 179 onTextureCreated.call(this, null); | |
| 180 | |
| 181 /** | |
| 182 * @this {WebInspector.Layers3DView} | |
| 183 * @param {?WebGLTexture} texture | |
| 184 */ | |
| 185 function onTextureCreated(texture) | |
| 186 { | |
| 187 this._layerTexture = texture ? {layerId: layer.id(), texture: textur
e} : null; | |
| 188 this._update(); | |
| 189 } | |
| 190 }, | |
| 191 | |
| 192 onResize: function() | |
| 193 { | |
| 194 this._resizeCanvas(); | |
| 195 this._update(); | |
| 196 }, | |
| 197 | |
| 198 wasShown: function() | |
| 199 { | |
| 200 if (!this._needsUpdate) | |
| 201 return; | |
| 202 this._resizeCanvas(); | |
| 203 this._update(); | |
| 204 }, | |
| 205 | |
| 206 /** | |
| 207 * @param {!WebInspector.Layers3DView.OutlineType} type | |
| 208 * @param {?WebInspector.LayerView.Selection} selection | |
| 209 */ | |
| 210 _setOutline: function(type, selection) | |
| 211 { | |
| 212 this._lastSelection[type] = selection; | |
| 213 this._update(); | |
| 214 }, | |
| 215 | |
| 216 /** | |
| 217 * @param {?WebInspector.LayerView.Selection} selection | |
| 218 * @override | |
| 219 */ | |
| 220 hoverObject: function(selection) | |
| 221 { | |
| 222 this._setOutline(WebInspector.Layers3DView.OutlineType.Hovered, selectio
n); | |
| 223 }, | |
| 224 | |
| 225 /** | |
| 226 * @param {?WebInspector.LayerView.Selection} selection | |
| 227 * @override | |
| 228 */ | |
| 229 selectObject: function(selection) | |
| 230 { | |
| 231 this._setOutline(WebInspector.Layers3DView.OutlineType.Hovered, null); | |
| 232 this._setOutline(WebInspector.Layers3DView.OutlineType.Selected, selecti
on); | |
| 233 }, | |
| 234 | |
| 235 /** | |
| 236 * @param {!Element} canvas | |
| 237 * @return {?WebGLRenderingContext} | |
| 238 */ | |
| 239 _initGL: function(canvas) | |
| 240 { | |
| 241 var gl = canvas.getContext("webgl"); | |
| 242 if (!gl) | |
| 243 return null; | |
| 244 gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); | |
| 245 gl.enable(gl.BLEND); | |
| 246 gl.clearColor(0.0, 0.0, 0.0, 0.0); | |
| 247 gl.enable(gl.DEPTH_TEST); | |
| 248 return gl; | |
| 249 }, | |
| 250 | |
| 251 /** | |
| 252 * @param {!Object} type | |
| 253 * @param {string} script | |
| 254 */ | |
| 255 _createShader: function(type, script) | |
| 256 { | |
| 257 var shader = this._gl.createShader(type); | |
| 258 this._gl.shaderSource(shader, script); | |
| 259 this._gl.compileShader(shader); | |
| 260 this._gl.attachShader(this._shaderProgram, shader); | |
| 261 }, | |
| 262 | |
| 263 _initShaders: function() | |
| 264 { | |
| 265 this._shaderProgram = this._gl.createProgram(); | |
| 266 this._createShader(this._gl.FRAGMENT_SHADER, WebInspector.Layers3DView.F
ragmentShader); | |
| 267 this._createShader(this._gl.VERTEX_SHADER, WebInspector.Layers3DView.Ver
texShader); | |
| 268 this._gl.linkProgram(this._shaderProgram); | |
| 269 this._gl.useProgram(this._shaderProgram); | |
| 270 | |
| 271 this._shaderProgram.vertexPositionAttribute = this._gl.getAttribLocation
(this._shaderProgram, "aVertexPosition"); | |
| 272 this._gl.enableVertexAttribArray(this._shaderProgram.vertexPositionAttri
bute); | |
| 273 this._shaderProgram.vertexColorAttribute = this._gl.getAttribLocation(th
is._shaderProgram, "aVertexColor"); | |
| 274 this._gl.enableVertexAttribArray(this._shaderProgram.vertexColorAttribut
e); | |
| 275 this._shaderProgram.textureCoordAttribute = this._gl.getAttribLocation(t
his._shaderProgram, "aTextureCoord"); | |
| 276 this._gl.enableVertexAttribArray(this._shaderProgram.textureCoordAttribu
te); | |
| 277 | |
| 278 this._shaderProgram.pMatrixUniform = this._gl.getUniformLocation(this._s
haderProgram, "uPMatrix"); | |
| 279 this._shaderProgram.samplerUniform = this._gl.getUniformLocation(this._s
haderProgram, "uSampler"); | |
| 280 }, | |
| 281 | |
| 282 _resizeCanvas: function() | |
| 283 { | |
| 284 this._canvasElement.width = this._canvasElement.offsetWidth * window.dev
icePixelRatio; | |
| 285 this._canvasElement.height = this._canvasElement.offsetHeight * window.d
evicePixelRatio; | |
| 286 }, | |
| 287 | |
| 288 _updateTransformAndConstraints: function() | |
| 289 { | |
| 290 var paddingFraction = 0.1; | |
| 291 var viewport = this._layerTree.viewportSize(); | |
| 292 var root = this._layerTree.root(); | |
| 293 var baseWidth = viewport ? viewport.width : this._dimensionsForAutoscale
.width; | |
| 294 var baseHeight = viewport ? viewport.height : this._dimensionsForAutosca
le.height; | |
| 295 var canvasWidth = this._canvasElement.width; | |
| 296 var canvasHeight = this._canvasElement.height; | |
| 297 var paddingX = canvasWidth * paddingFraction; | |
| 298 var paddingY = canvasHeight * paddingFraction; | |
| 299 var scaleX = (canvasWidth - 2 * paddingX) / baseWidth; | |
| 300 var scaleY = (canvasHeight - 2 * paddingY) / baseHeight; | |
| 301 var viewScale = Math.min(scaleX, scaleY); | |
| 302 var minScaleConstraint = Math.min(baseWidth / this._dimensionsForAutosca
le.width, baseHeight / this._dimensionsForAutoscale.width) / 2; | |
| 303 this._transformController.setScaleConstraints(minScaleConstraint, 10 / v
iewScale); // 1/viewScale is 1:1 in terms of pixels, so allow zooming to 10x of
native size | |
| 304 var scale = this._transformController.scale(); | |
| 305 var rotateX = this._transformController.rotateX(); | |
| 306 var rotateY = this._transformController.rotateY(); | |
| 307 this._scale = scale * viewScale; | |
| 308 var scaleAndRotationMatrix = new WebKitCSSMatrix().scale(scale, scale, s
cale).translate(canvasWidth / 2, canvasHeight / 2, 0) | |
| 309 .rotate(rotateX, rotateY, 0).scale(viewScale, viewScale, viewScale).
translate(-baseWidth / 2, -baseHeight / 2, 0); | |
| 310 | |
| 311 var bounds; | |
| 312 for (var i = 0; i < this._rects.length; ++i) | |
| 313 bounds = WebInspector.Geometry.boundsForTransformedPoints(scaleAndRo
tationMatrix, this._rects[i].vertices, bounds); | |
| 314 | |
| 315 this._transformController.clampOffsets((paddingX - bounds.maxX) / window
.devicePixelRatio, (canvasWidth - paddingX - bounds.minX) / window.devicePixelRa
tio, | |
| 316 (paddingY - bounds.maxY) / window
.devicePixelRatio, (canvasHeight - paddingY - bounds.minY) / window.devicePixelR
atio); | |
| 317 var offsetX = this._transformController.offsetX() * window.devicePixelRa
tio; | |
| 318 var offsetY = this._transformController.offsetY() * window.devicePixelRa
tio; | |
| 319 // Multiply to translation matrix on the right rather than translate (wh
ich would implicitly multiply on the left). | |
| 320 this._projectionMatrix = new WebKitCSSMatrix().translate(offsetX, offset
Y, 0).multiply(scaleAndRotationMatrix); | |
| 321 | |
| 322 var glProjectionMatrix = new WebKitCSSMatrix().scale(1, -1, -1).translat
e(-1, -1, 0) | |
| 323 .scale(2 / this._canvasElement.width, 2 / this._canvasElement.height
, 1 / 1000000).multiply(this._projectionMatrix); | |
| 324 this._gl.uniformMatrix4fv(this._shaderProgram.pMatrixUniform, false, thi
s._arrayFromMatrix(glProjectionMatrix)); | |
| 325 }, | |
| 326 | |
| 327 /** | |
| 328 * @param {!CSSMatrix} m | |
| 329 * @return {!Float32Array} | |
| 330 */ | |
| 331 _arrayFromMatrix: function(m) | |
| 332 { | |
| 333 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]); | |
| 334 }, | |
| 335 | |
| 336 _initWhiteTexture: function() | |
| 337 { | |
| 338 this._whiteTexture = this._gl.createTexture(); | |
| 339 this._gl.bindTexture(this._gl.TEXTURE_2D, this._whiteTexture); | |
| 340 var whitePixel = new Uint8Array([255, 255, 255, 255]); | |
| 341 this._gl.texImage2D(this._gl.TEXTURE_2D, 0, this._gl.RGBA, 1, 1, 0, this
._gl.RGBA, this._gl.UNSIGNED_BYTE, whitePixel); | |
| 342 }, | |
| 343 | |
| 344 _initChromeTextures: function() | |
| 345 { | |
| 346 /** | |
| 347 * @this {WebInspector.Layers3DView} | |
| 348 * @param {!WebInspector.Layers3DView.ChromeTexture} index | |
| 349 * @param {?WebGLTexture} value | |
| 350 */ | |
| 351 function saveChromeTexture(index, value) | |
| 352 { | |
| 353 this._chromeTextures[index] = value || undefined; | |
| 354 } | |
| 355 this._textureManager.createTexture(saveChromeTexture.bind(this, WebInspe
ctor.Layers3DView.ChromeTexture.Left), "Images/chromeLeft.png"); | |
| 356 this._textureManager.createTexture(saveChromeTexture.bind(this, WebInspe
ctor.Layers3DView.ChromeTexture.Middle), "Images/chromeMiddle.png"); | |
| 357 this._textureManager.createTexture(saveChromeTexture.bind(this, WebInspe
ctor.Layers3DView.ChromeTexture.Right), "Images/chromeRight.png"); | |
| 358 }, | |
| 359 | |
| 360 /** | |
| 361 * @return {?WebGLRenderingContext} | |
| 362 */ | |
| 363 _initGLIfNecessary: function() | |
| 364 { | |
| 365 if (this._gl) | |
| 366 return this._gl; | |
| 367 this._gl = this._initGL(this._canvasElement); | |
| 368 if (!this._gl) | |
| 369 return null; | |
| 370 this._initShaders(); | |
| 371 this._initWhiteTexture(); | |
| 372 this._initChromeTextures(); | |
| 373 this._textureManager.setContext(this._gl); | |
| 374 return this._gl; | |
| 375 }, | |
| 376 | |
| 377 _calculateDepthsAndVisibility: function() | |
| 378 { | |
| 379 this._depthByLayerId = {}; | |
| 380 var depth = 0; | |
| 381 var showInternalLayers = this._layerViewHost.showInternalLayersSetting()
.get(); | |
| 382 var root = showInternalLayers ? this._layerTree.root() : (this._layerTre
e.contentRoot() || this._layerTree.root()); | |
| 383 var queue = [root]; | |
| 384 this._depthByLayerId[root.id()] = 0; | |
| 385 this._visibleLayers = {}; | |
| 386 while (queue.length > 0) { | |
| 387 var layer = queue.shift(); | |
| 388 this._visibleLayers[layer.id()] = showInternalLayers || layer.drawsC
ontent(); | |
| 389 var children = layer.children(); | |
| 390 for (var i = 0; i < children.length; ++i) { | |
| 391 this._depthByLayerId[children[i].id()] = ++depth; | |
| 392 queue.push(children[i]); | |
| 393 } | |
| 394 } | |
| 395 this._maxDepth = depth; | |
| 396 }, | |
| 397 | |
| 398 /** | |
| 399 * @param {!WebInspector.Layer} layer | |
| 400 * @return {number} | |
| 401 */ | |
| 402 _depthForLayer: function(layer) | |
| 403 { | |
| 404 return this._depthByLayerId[layer.id()] * WebInspector.Layers3DView.Laye
rSpacing; | |
| 405 }, | |
| 406 | |
| 407 /** | |
| 408 * @param {!WebInspector.Layer} layer | |
| 409 * @param {number} index | |
| 410 * @return {number} | |
| 411 */ | |
| 412 _calculateScrollRectDepth: function(layer, index) | |
| 413 { | |
| 414 return this._depthForLayer(layer) + index * WebInspector.Layers3DView.Sc
rollRectSpacing + 1; | |
| 415 }, | |
| 416 | |
| 417 /** | |
| 418 * @param {!WebInspector.Layer} layer | |
| 419 */ | |
| 420 _updateDimensionsForAutoscale: function(layer) | |
| 421 { | |
| 422 // We don't want to be precise, but rather pick something least affected
by | |
| 423 // animationtransforms, so that we don't change scale too often. So let'
s | |
| 424 // disregard transforms, scrolling and relative layer positioning and ch
oose | |
| 425 // the largest dimensions of all layers. | |
| 426 this._dimensionsForAutoscale.width = Math.max(layer.width(), this._dimen
sionsForAutoscale.width); | |
| 427 this._dimensionsForAutoscale.height = Math.max(layer.height(), this._dim
ensionsForAutoscale.height); | |
| 428 }, | |
| 429 | |
| 430 /** | |
| 431 * @param {!WebInspector.Layer} layer | |
| 432 */ | |
| 433 _calculateLayerRect: function(layer) | |
| 434 { | |
| 435 if (!this._visibleLayers[layer.id()]) | |
| 436 return; | |
| 437 var selection = new WebInspector.LayerView.LayerSelection(layer); | |
| 438 var rect = new WebInspector.Layers3DView.Rectangle(selection); | |
| 439 rect.setVertices(layer.quad(), this._depthForLayer(layer)); | |
| 440 this._appendRect(rect); | |
| 441 this._updateDimensionsForAutoscale(layer); | |
| 442 }, | |
| 443 | |
| 444 /** | |
| 445 * @param {!WebInspector.Layers3DView.Rectangle} rect | |
| 446 */ | |
| 447 _appendRect: function(rect) | |
| 448 { | |
| 449 var selection = rect.relatedObject; | |
| 450 var isSelected = WebInspector.LayerView.Selection.isEqual(this._lastSele
ction[WebInspector.Layers3DView.OutlineType.Selected], selection); | |
| 451 var isHovered = WebInspector.LayerView.Selection.isEqual(this._lastSelec
tion[WebInspector.Layers3DView.OutlineType.Hovered], selection); | |
| 452 if (isSelected) { | |
| 453 rect.borderColor = WebInspector.Layers3DView.SelectedBorderColor; | |
| 454 } else if (isHovered) { | |
| 455 rect.borderColor = WebInspector.Layers3DView.HoveredBorderColor; | |
| 456 var fillColor = rect.fillColor || [255, 255, 255, 1]; | |
| 457 var maskColor = WebInspector.Layers3DView.HoveredImageMaskColor; | |
| 458 rect.fillColor = [fillColor[0] * maskColor[0] / 255, fillColor[1] *
maskColor[1] / 255, fillColor[2] * maskColor[2] / 255, fillColor[3] * maskColor[
3]]; | |
| 459 } else { | |
| 460 rect.borderColor = WebInspector.Layers3DView.BorderColor; | |
| 461 } | |
| 462 rect.lineWidth = isSelected ? WebInspector.Layers3DView.SelectedBorderWi
dth : WebInspector.Layers3DView.BorderWidth; | |
| 463 this._rects.push(rect); | |
| 464 }, | |
| 465 | |
| 466 /** | |
| 467 * @param {!WebInspector.Layer} layer | |
| 468 */ | |
| 469 _calculateLayerScrollRects: function(layer) | |
| 470 { | |
| 471 var scrollRects = layer.scrollRects(); | |
| 472 for (var i = 0; i < scrollRects.length; ++i) { | |
| 473 var selection = new WebInspector.LayerView.ScrollRectSelection(layer
, i); | |
| 474 var rect = new WebInspector.Layers3DView.Rectangle(selection); | |
| 475 rect.calculateVerticesFromRect(layer, scrollRects[i].rect, this._cal
culateScrollRectDepth(layer, i)); | |
| 476 rect.fillColor = WebInspector.Layers3DView.ScrollRectBackgroundColor
; | |
| 477 this._appendRect(rect); | |
| 478 } | |
| 479 }, | |
| 480 | |
| 481 /** | |
| 482 * @param {!WebInspector.Layer} layer | |
| 483 */ | |
| 484 _calculateLayerImageRect: function(layer) | |
| 485 { | |
| 486 var layerTexture = this._layerTexture; | |
| 487 if (layer.id() !== layerTexture.layerId) | |
| 488 return; | |
| 489 var selection = new WebInspector.LayerView.LayerSelection(layer); | |
| 490 var rect = new WebInspector.Layers3DView.Rectangle(selection); | |
| 491 rect.setVertices(layer.quad(), this._depthForLayer(layer)); | |
| 492 rect.texture = layerTexture.texture; | |
| 493 this._appendRect(rect); | |
| 494 }, | |
| 495 | |
| 496 /** | |
| 497 * @param {!WebInspector.Layer} layer | |
| 498 */ | |
| 499 _calculateLayerTileRects: function(layer) | |
| 500 { | |
| 501 var tiles = this._textureManager.tilesForLayer(layer.id()); | |
| 502 for (var i = 0; i < tiles.length; ++i) { | |
| 503 var tile = tiles[i]; | |
| 504 if (!tile.texture) | |
| 505 continue; | |
| 506 var selection = new WebInspector.LayerView.TileSelection(layer, tile
.traceEvent); | |
| 507 var rect = new WebInspector.Layers3DView.Rectangle(selection); | |
| 508 rect.calculateVerticesFromRect(layer, {x: tile.rect[0], y: tile.rect
[1], width: tile.rect[2], height: tile.rect[3]}, this._depthForLayer(layer) + 1)
; | |
| 509 rect.texture = tile.texture; | |
| 510 this._appendRect(rect); | |
| 511 } | |
| 512 }, | |
| 513 | |
| 514 _calculateRects: function() | |
| 515 { | |
| 516 this._rects = []; | |
| 517 this._dimensionsForAutoscale = { width: 0, height: 0 }; | |
| 518 this._layerTree.forEachLayer(this._calculateLayerRect.bind(this)); | |
| 519 | |
| 520 if (this._showSlowScrollRectsSetting.get()) | |
| 521 this._layerTree.forEachLayer(this._calculateLayerScrollRects.bind(th
is)); | |
| 522 | |
| 523 if (this._showPaintsSetting.get()) { | |
| 524 if (this._layerTexture) | |
| 525 this._layerTree.forEachLayer(this._calculateLayerImageRect.bind(
this)); | |
| 526 else | |
| 527 this._layerTree.forEachLayer(this._calculateLayerTileRects.bind(
this)); | |
| 528 } | |
| 529 }, | |
| 530 | |
| 531 /** | |
| 532 * @param {!Array.<number>} color | |
| 533 * @return {!Array.<number>} | |
| 534 */ | |
| 535 _makeColorsArray: function(color) | |
| 536 { | |
| 537 var colors = []; | |
| 538 var normalizedColor = [color[0] / 255, color[1] / 255, color[2] / 255, c
olor[3]]; | |
| 539 for (var i = 0; i < 4; i++) | |
| 540 colors = colors.concat(normalizedColor); | |
| 541 return colors; | |
| 542 }, | |
| 543 | |
| 544 /** | |
| 545 * @param {!Object} attribute | |
| 546 * @param {!Array.<number>} array | |
| 547 * @param {number} length | |
| 548 */ | |
| 549 _setVertexAttribute: function(attribute, array, length) | |
| 550 { | |
| 551 var gl = this._gl; | |
| 552 var buffer = gl.createBuffer(); | |
| 553 gl.bindBuffer(gl.ARRAY_BUFFER, buffer); | |
| 554 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(array), gl.STATIC_DRAW); | |
| 555 gl.vertexAttribPointer(attribute, length, gl.FLOAT, false, 0, 0); | |
| 556 }, | |
| 557 | |
| 558 /** | |
| 559 * @param {!Array.<number>} vertices | |
| 560 * @param {number} mode | |
| 561 * @param {!Array.<number>=} color | |
| 562 * @param {!Object=} texture | |
| 563 */ | |
| 564 _drawRectangle: function(vertices, mode, color, texture) | |
| 565 { | |
| 566 var gl = this._gl; | |
| 567 var white = [255, 255, 255, 1]; | |
| 568 color = color || white; | |
| 569 this._setVertexAttribute(this._shaderProgram.vertexPositionAttribute, ve
rtices, 3); | |
| 570 this._setVertexAttribute(this._shaderProgram.textureCoordAttribute, [0,
1, 1, 1, 1, 0, 0, 0], 2); | |
| 571 this._setVertexAttribute(this._shaderProgram.vertexColorAttribute, this.
_makeColorsArray(color), color.length); | |
| 572 | |
| 573 if (texture) { | |
| 574 gl.activeTexture(gl.TEXTURE0); | |
| 575 gl.bindTexture(gl.TEXTURE_2D, texture); | |
| 576 gl.uniform1i(this._shaderProgram.samplerUniform, 0); | |
| 577 } else { | |
| 578 gl.bindTexture(gl.TEXTURE_2D, this._whiteTexture); | |
| 579 } | |
| 580 | |
| 581 var numberOfVertices = vertices.length / 3; | |
| 582 gl.drawArrays(mode, 0, numberOfVertices); | |
| 583 }, | |
| 584 | |
| 585 /** | |
| 586 * @param {!Array.<number>} vertices | |
| 587 * @param {!WebGLTexture} texture | |
| 588 * @param {!Array.<number>=} color | |
| 589 */ | |
| 590 _drawTexture: function(vertices, texture, color) | |
| 591 { | |
| 592 this._drawRectangle(vertices, this._gl.TRIANGLE_FAN, color, texture); | |
| 593 }, | |
| 594 | |
| 595 _drawViewportAndChrome: function() | |
| 596 { | |
| 597 var viewport = this._layerTree.viewportSize(); | |
| 598 if (!viewport) | |
| 599 return; | |
| 600 | |
| 601 var drawChrome = !WebInspector.moduleSetting("frameViewerHideChromeWindo
w").get() && this._chromeTextures.length >= 3 && this._chromeTextures.indexOf(un
defined) < 0; | |
| 602 var z = (this._maxDepth + 1) * WebInspector.Layers3DView.LayerSpacing; | |
| 603 var borderWidth = Math.ceil(WebInspector.Layers3DView.ViewportBorderWidt
h * this._scale); | |
| 604 var vertices = [viewport.width, 0, z, viewport.width, viewport.height, z
, 0, viewport.height, z, 0, 0, z]; | |
| 605 this._gl.lineWidth(borderWidth); | |
| 606 this._drawRectangle(vertices, drawChrome ? this._gl.LINE_STRIP : this._g
l.LINE_LOOP, WebInspector.Layers3DView.ViewportBorderColor); | |
| 607 | |
| 608 if (!drawChrome) | |
| 609 return; | |
| 610 | |
| 611 var borderAdjustment = WebInspector.Layers3DView.ViewportBorderWidth / 2
; | |
| 612 var viewportWidth = this._layerTree.viewportSize().width + 2 * borderAdj
ustment; | |
| 613 var chromeHeight = this._chromeTextures[0].image.naturalHeight; | |
| 614 var middleFragmentWidth = viewportWidth - this._chromeTextures[0].image.
naturalWidth - this._chromeTextures[2].image.naturalWidth; | |
| 615 var x = -borderAdjustment; | |
| 616 var y = -chromeHeight; | |
| 617 for (var i = 0; i < this._chromeTextures.length; ++i) { | |
| 618 var width = i === WebInspector.Layers3DView.ChromeTexture.Middle ? m
iddleFragmentWidth : this._chromeTextures[i].image.naturalWidth; | |
| 619 if (width < 0 || x + width > viewportWidth) | |
| 620 break; | |
| 621 vertices = [x, y, z, x + width, y, z, x + width, y + chromeHeight, z
, x, y + chromeHeight, z]; | |
| 622 this._drawTexture(vertices, /** @type {!WebGLTexture} */ (this._chro
meTextures[i])); | |
| 623 x += width; | |
| 624 } | |
| 625 }, | |
| 626 | |
| 627 /** | |
| 628 * @param {!WebInspector.Layers3DView.Rectangle} rect | |
| 629 */ | |
| 630 _drawViewRect: function(rect) | |
| 631 { | |
| 632 var vertices = rect.vertices; | |
| 633 if (rect.texture) | |
| 634 this._drawTexture(vertices, rect.texture, rect.fillColor || undefine
d); | |
| 635 else if (rect.fillColor) | |
| 636 this._drawRectangle(vertices, this._gl.TRIANGLE_FAN, rect.fillColor)
; | |
| 637 this._gl.lineWidth(rect.lineWidth); | |
| 638 if (rect.borderColor) | |
| 639 this._drawRectangle(vertices, this._gl.LINE_LOOP, rect.borderColor); | |
| 640 }, | |
| 641 | |
| 642 _update: function() | |
| 643 { | |
| 644 if (!this.isShowing()) { | |
| 645 this._needsUpdate = true; | |
| 646 return; | |
| 647 } | |
| 648 if (!this._layerTree || !this._layerTree.root()) { | |
| 649 this._failBanner.show(this.element); | |
| 650 return; | |
| 651 } | |
| 652 var gl = this._initGLIfNecessary(); | |
| 653 if (!gl) { | |
| 654 this._failBanner.element.removeChildren(); | |
| 655 this._failBanner.element.appendChild(this._webglDisabledBanner()); | |
| 656 this._failBanner.show(this.element); | |
| 657 return; | |
| 658 } | |
| 659 this._failBanner.detach(); | |
| 660 this._gl.viewportWidth = this._canvasElement.width; | |
| 661 this._gl.viewportHeight = this._canvasElement.height; | |
| 662 | |
| 663 this._calculateDepthsAndVisibility(); | |
| 664 this._calculateRects(); | |
| 665 this._updateTransformAndConstraints(); | |
| 666 | |
| 667 this._textureManager.setScale(Number.constrain(0.1, 1, this._scale)); | |
| 668 gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight); | |
| 669 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); | |
| 670 | |
| 671 this._rects.forEach(this._drawViewRect.bind(this)); | |
| 672 this._drawViewportAndChrome(); | |
| 673 }, | |
| 674 | |
| 675 /** | |
| 676 * @return {!Node} | |
| 677 */ | |
| 678 _webglDisabledBanner: function() | |
| 679 { | |
| 680 var fragment = this.element.ownerDocument.createDocumentFragment(); | |
| 681 fragment.createChild("div").textContent = WebInspector.UIString("Can't d
isplay layers,"); | |
| 682 fragment.createChild("div").textContent = WebInspector.UIString("WebGL s
upport is disabled in your browser."); | |
| 683 fragment.appendChild(WebInspector.formatLocalized("Check %s for possible
reasons.", [WebInspector.linkifyURLAsNode("about:gpu", undefined, undefined, tr
ue)])); | |
| 684 return fragment; | |
| 685 }, | |
| 686 | |
| 687 /** | |
| 688 * @param {!Event} event | |
| 689 * @return {?WebInspector.LayerView.Selection} | |
| 690 */ | |
| 691 _selectionFromEventPoint: function(event) | |
| 692 { | |
| 693 if (!this._layerTree) | |
| 694 return null; | |
| 695 var closestIntersectionPoint = Infinity; | |
| 696 var closestObject = null; | |
| 697 var projectionMatrix = new WebKitCSSMatrix().scale(1, -1, -1).translate(
-1, -1, 0).multiply(this._projectionMatrix); | |
| 698 var x0 = (event.clientX - this._canvasElement.totalOffsetLeft()) * windo
w.devicePixelRatio; | |
| 699 var y0 = -(event.clientY - this._canvasElement.totalOffsetTop()) * windo
w.devicePixelRatio; | |
| 700 | |
| 701 /** | |
| 702 * @param {!WebInspector.Layers3DView.Rectangle} rect | |
| 703 */ | |
| 704 function checkIntersection(rect) | |
| 705 { | |
| 706 if (!rect.relatedObject) | |
| 707 return; | |
| 708 var t = rect.intersectWithLine(projectionMatrix, x0, y0); | |
| 709 if (t < closestIntersectionPoint) { | |
| 710 closestIntersectionPoint = t; | |
| 711 closestObject = rect.relatedObject; | |
| 712 } | |
| 713 } | |
| 714 | |
| 715 this._rects.forEach(checkIntersection); | |
| 716 return closestObject; | |
| 717 }, | |
| 718 | |
| 719 /** | |
| 720 * @param {string} caption | |
| 721 * @param {string} name | |
| 722 * @param {boolean} value | |
| 723 * @param {!WebInspector.Toolbar} toolbar | |
| 724 * @return {!WebInspector.Setting} | |
| 725 */ | |
| 726 _createVisibilitySetting: function(caption, name, value, toolbar) | |
| 727 { | |
| 728 var checkbox = new WebInspector.ToolbarCheckbox(WebInspector.UIString(ca
ption)); | |
| 729 toolbar.appendToolbarItem(checkbox); | |
| 730 var setting = WebInspector.settings.createSetting(name, value); | |
| 731 WebInspector.SettingsUI.bindCheckbox(checkbox.inputElement, setting); | |
| 732 setting.addChangeListener(this._update, this); | |
| 733 return setting; | |
| 734 }, | |
| 735 | |
| 736 _initToolbar: function() | |
| 737 { | |
| 738 this._panelToolbar = this._transformController.toolbar(); | |
| 739 this.element.appendChild(this._panelToolbar.element); | |
| 740 this._showSlowScrollRectsSetting = this._createVisibilitySetting("Slow s
croll rects", "frameViewerShowSlowScrollRects", true, this._panelToolbar); | |
| 741 this._showPaintsSetting = this._createVisibilitySetting("Paints", "frame
ViewerShowPaints", true, this._panelToolbar); | |
| 742 WebInspector.moduleSetting("frameViewerHideChromeWindow").addChangeListe
ner(this._update, this); | |
| 743 }, | |
| 744 | |
| 745 /** | |
| 746 * @param {!Event} event | |
| 747 */ | |
| 748 _onContextMenu: function(event) | |
| 749 { | |
| 750 var contextMenu = new WebInspector.ContextMenu(event); | |
| 751 contextMenu.appendItem(WebInspector.UIString("Reset View"), this._transf
ormController.resetAndNotify.bind(this._transformController), false); | |
| 752 var selection = this._selectionFromEventPoint(event); | |
| 753 if (selection && selection.type() === WebInspector.LayerView.Selection.T
ype.Tile) | |
| 754 contextMenu.appendItem(WebInspector.UIString("Show Paint Profiler"),
this.dispatchEventToListeners.bind(this, WebInspector.Layers3DView.Events.Paint
ProfilerRequested, selection.traceEvent()), false); | |
| 755 this._layerViewHost.showContextMenu(contextMenu, selection); | |
| 756 }, | |
| 757 | |
| 758 /** | |
| 759 * @param {!Event} event | |
| 760 */ | |
| 761 _onMouseMove: function(event) | |
| 762 { | |
| 763 if (event.which) | |
| 764 return; | |
| 765 this._layerViewHost.hoverObject(this._selectionFromEventPoint(event)); | |
| 766 }, | |
| 767 | |
| 768 /** | |
| 769 * @param {!Event} event | |
| 770 */ | |
| 771 _onMouseDown: function(event) | |
| 772 { | |
| 773 this._mouseDownX = event.clientX; | |
| 774 this._mouseDownY = event.clientY; | |
| 775 }, | |
| 776 | |
| 777 /** | |
| 778 * @param {!Event} event | |
| 779 */ | |
| 780 _onMouseUp: function(event) | |
| 781 { | |
| 782 const maxDistanceInPixels = 6; | |
| 783 if (this._mouseDownX && Math.abs(event.clientX - this._mouseDownX) < max
DistanceInPixels && Math.abs(event.clientY - this._mouseDownY) < maxDistanceInPi
xels) | |
| 784 this._layerViewHost.selectObject(this._selectionFromEventPoint(event
)); | |
| 785 delete this._mouseDownX; | |
| 786 delete this._mouseDownY; | |
| 787 }, | |
| 788 | |
| 789 /** | |
| 790 * @param {!Event} event | |
| 791 */ | |
| 792 _onDoubleClick: function(event) | |
| 793 { | |
| 794 var selection = this._selectionFromEventPoint(event); | |
| 795 if (selection) { | |
| 796 if (selection.type() === WebInspector.LayerView.Selection.Type.Tile) | |
| 797 this.dispatchEventToListeners(WebInspector.Layers3DView.Events.P
aintProfilerRequested, selection.traceEvent()); | |
| 798 else if (selection.layer()) | |
| 799 this.dispatchEventToListeners(WebInspector.Layers3DView.Events.L
ayerSnapshotRequested, selection.layer()); | |
| 800 } | |
| 801 event.stopPropagation(); | |
| 802 }, | |
| 803 | |
| 804 __proto__: WebInspector.VBox.prototype | |
| 805 } | |
| 806 | |
| 807 /** | |
| 808 * @constructor | |
| 809 * @extends {WebInspector.Object} | |
| 810 */ | |
| 811 WebInspector.LayerTextureManager = function() | |
| 812 { | |
| 813 WebInspector.Object.call(this); | |
| 814 this.reset(); | |
| 815 } | |
| 816 | |
| 817 /** @enum {symbol} */ | |
| 818 WebInspector.LayerTextureManager.Events = { | |
| 819 TextureUpdated: Symbol("TextureUpated") | |
| 820 } | |
| 821 | |
| 822 WebInspector.LayerTextureManager.prototype = { | |
| 823 reset: function() | |
| 824 { | |
| 825 /** @type {!Object.<string, !Array.<!WebInspector.LayerTextureManager.Ti
le>>} */ | |
| 826 this._tilesByLayerId = {}; | |
| 827 this._scale = 0; | |
| 828 }, | |
| 829 | |
| 830 /** | |
| 831 * @param {!WebGLRenderingContext} glContext | |
| 832 */ | |
| 833 setContext: function(glContext) | |
| 834 { | |
| 835 this._gl = glContext; | |
| 836 if (this._scale) | |
| 837 this._updateTextures(); | |
| 838 }, | |
| 839 | |
| 840 /** | |
| 841 * @param {?Array.<!WebInspector.Layers3DView.PaintTile>} paintTiles | |
| 842 */ | |
| 843 setTiles: function(paintTiles) | |
| 844 { | |
| 845 this._tilesByLayerId = {}; | |
| 846 if (!paintTiles) | |
| 847 return; | |
| 848 for (var i = 0; i < paintTiles.length; ++i) { | |
| 849 var layerId = paintTiles[i].layerId; | |
| 850 var tilesForLayer = this._tilesByLayerId[layerId]; | |
| 851 if (!tilesForLayer) { | |
| 852 tilesForLayer = []; | |
| 853 this._tilesByLayerId[layerId] = tilesForLayer; | |
| 854 } | |
| 855 var tile = new WebInspector.LayerTextureManager.Tile(paintTiles[i].s
napshot, paintTiles[i].rect, paintTiles[i].traceEvent); | |
| 856 tilesForLayer.push(tile); | |
| 857 if (this._scale && this._gl) | |
| 858 this._updateTile(tile); | |
| 859 } | |
| 860 }, | |
| 861 | |
| 862 /** | |
| 863 * @param {number} scale | |
| 864 */ | |
| 865 setScale: function(scale) | |
| 866 { | |
| 867 if (this._scale && this._scale >= scale) | |
| 868 return; | |
| 869 this._scale = scale; | |
| 870 this._updateTextures(); | |
| 871 }, | |
| 872 | |
| 873 /** | |
| 874 * @param {string} layerId | |
| 875 * @return {!Array.<!WebInspector.LayerTextureManager.Tile>} | |
| 876 */ | |
| 877 tilesForLayer: function(layerId) | |
| 878 { | |
| 879 return this._tilesByLayerId[layerId] || []; | |
| 880 }, | |
| 881 | |
| 882 _updateTextures: function() | |
| 883 { | |
| 884 if (!this._gl) | |
| 885 return; | |
| 886 if (!this._scale) | |
| 887 return; | |
| 888 | |
| 889 for (var layerId in this._tilesByLayerId) { | |
| 890 for (var i = 0; i < this._tilesByLayerId[layerId].length; ++i) { | |
| 891 var tile = this._tilesByLayerId[layerId][i]; | |
| 892 if (!tile.scale || tile.scale < this._scale) | |
| 893 this._updateTile(tile); | |
| 894 } | |
| 895 } | |
| 896 }, | |
| 897 | |
| 898 /** | |
| 899 * @param {!WebInspector.LayerTextureManager.Tile} tile | |
| 900 */ | |
| 901 _updateTile: function(tile) | |
| 902 { | |
| 903 console.assert(this._scale && this._gl); | |
| 904 tile.scale = this._scale; | |
| 905 tile.snapshot.requestImage(null, null, tile.scale, onGotImage.bind(this)
); | |
| 906 | |
| 907 /** | |
| 908 * @this {WebInspector.LayerTextureManager} | |
| 909 * @param {string=} imageURL | |
| 910 */ | |
| 911 function onGotImage(imageURL) | |
| 912 { | |
| 913 if (imageURL) | |
| 914 this.createTexture(onTextureCreated.bind(this), imageURL); | |
| 915 } | |
| 916 | |
| 917 /** | |
| 918 * @this {WebInspector.LayerTextureManager} | |
| 919 * @param {?WebGLTexture} texture | |
| 920 */ | |
| 921 function onTextureCreated(texture) | |
| 922 { | |
| 923 tile.texture = texture; | |
| 924 this.dispatchEventToListeners(WebInspector.LayerTextureManager.Event
s.TextureUpdated); | |
| 925 } | |
| 926 }, | |
| 927 | |
| 928 /** | |
| 929 * @param {function(?WebGLTexture)} textureCreatedCallback | |
| 930 * @param {string} imageURL | |
| 931 */ | |
| 932 createTexture: function(textureCreatedCallback, imageURL) | |
| 933 { | |
| 934 var image = new Image(); | |
| 935 image.addEventListener("load", onImageLoaded.bind(this), false); | |
| 936 image.addEventListener("error", onImageError, false); | |
| 937 image.src = imageURL; | |
| 938 | |
| 939 /** | |
| 940 * @this {WebInspector.LayerTextureManager} | |
| 941 */ | |
| 942 function onImageLoaded() | |
| 943 { | |
| 944 textureCreatedCallback(this._createTextureForImage(image)); | |
| 945 } | |
| 946 | |
| 947 function onImageError() | |
| 948 { | |
| 949 textureCreatedCallback(null); | |
| 950 } | |
| 951 }, | |
| 952 | |
| 953 /** | |
| 954 * @param {!Image} image | |
| 955 * @return {!WebGLTexture} texture | |
| 956 */ | |
| 957 _createTextureForImage: function(image) | |
| 958 { | |
| 959 var texture = this._gl.createTexture(); | |
| 960 texture.image = image; | |
| 961 this._gl.bindTexture(this._gl.TEXTURE_2D, texture); | |
| 962 this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL, true); | |
| 963 this._gl.texImage2D(this._gl.TEXTURE_2D, 0, this._gl.RGBA, this._gl.RGBA
, this._gl.UNSIGNED_BYTE, texture.image); | |
| 964 this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_MIN_FILTER,
this._gl.LINEAR); | |
| 965 this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_MAG_FILTER,
this._gl.LINEAR); | |
| 966 this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_WRAP_S, thi
s._gl.CLAMP_TO_EDGE); | |
| 967 this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_WRAP_T, thi
s._gl.CLAMP_TO_EDGE); | |
| 968 this._gl.bindTexture(this._gl.TEXTURE_2D, null); | |
| 969 return texture; | |
| 970 }, | |
| 971 | |
| 972 __proto__: WebInspector.Object.prototype | |
| 973 } | |
| 974 | |
| 975 /** | |
| 976 * @constructor | |
| 977 * @param {?WebInspector.LayerView.Selection} relatedObject | |
| 978 */ | |
| 979 WebInspector.Layers3DView.Rectangle = function(relatedObject) | |
| 980 { | |
| 981 this.relatedObject = relatedObject; | |
| 982 /** @type {number} */ | |
| 983 this.lineWidth = 1; | |
| 984 /** @type {?Array.<number>} */ | |
| 985 this.borderColor = null; | |
| 986 /** @type {?Array.<number>} */ | |
| 987 this.fillColor = null; | |
| 988 /** @type {?WebGLTexture} */ | |
| 989 this.texture = null; | |
| 990 } | |
| 991 | |
| 992 WebInspector.Layers3DView.Rectangle.prototype = { | |
| 993 /** | |
| 994 * @param {!Array.<number>} quad | |
| 995 * @param {number} z | |
| 996 */ | |
| 997 setVertices: function(quad, z) | |
| 998 { | |
| 999 this.vertices = [quad[0], quad[1], z, quad[2], quad[3], z, quad[4], quad
[5], z, quad[6], quad[7], z]; | |
| 1000 }, | |
| 1001 | |
| 1002 /** | |
| 1003 * Finds coordinates of point on layer quad, having offsets (ratioX * width)
and (ratioY * height) | |
| 1004 * from the left corner of the initial layer rect, where width and heigth ar
e layer bounds. | |
| 1005 * @param {!Array.<number>} quad | |
| 1006 * @param {number} ratioX | |
| 1007 * @param {number} ratioY | |
| 1008 * @return {!Array.<number>} | |
| 1009 */ | |
| 1010 _calculatePointOnQuad: function(quad, ratioX, ratioY) | |
| 1011 { | |
| 1012 var x0 = quad[0]; | |
| 1013 var y0 = quad[1]; | |
| 1014 var x1 = quad[2]; | |
| 1015 var y1 = quad[3]; | |
| 1016 var x2 = quad[4]; | |
| 1017 var y2 = quad[5]; | |
| 1018 var x3 = quad[6]; | |
| 1019 var y3 = quad[7]; | |
| 1020 // Point on the first quad side clockwise | |
| 1021 var firstSidePointX = x0 + ratioX * (x1 - x0); | |
| 1022 var firstSidePointY = y0 + ratioX * (y1 - y0); | |
| 1023 // Point on the third quad side clockwise | |
| 1024 var thirdSidePointX = x3 + ratioX * (x2 - x3); | |
| 1025 var thirdSidePointY = y3 + ratioX * (y2 - y3); | |
| 1026 var x = firstSidePointX + ratioY * (thirdSidePointX - firstSidePointX); | |
| 1027 var y = firstSidePointY + ratioY * (thirdSidePointY - firstSidePointY); | |
| 1028 return [x, y]; | |
| 1029 }, | |
| 1030 | |
| 1031 /** | |
| 1032 * @param {!WebInspector.Layer} layer | |
| 1033 * @param {!DOMAgent.Rect} rect | |
| 1034 * @param {number} z | |
| 1035 */ | |
| 1036 calculateVerticesFromRect: function(layer, rect, z) | |
| 1037 { | |
| 1038 var quad = layer.quad(); | |
| 1039 var rx1 = rect.x / layer.width(); | |
| 1040 var rx2 = (rect.x + rect.width) / layer.width(); | |
| 1041 var ry1 = rect.y / layer.height(); | |
| 1042 var ry2 = (rect.y + rect.height) / layer.height(); | |
| 1043 var rectQuad = this._calculatePointOnQuad(quad, rx1, ry1).concat(this._c
alculatePointOnQuad(quad, rx2, ry1)) | |
| 1044 .concat(this._calculatePointOnQuad(quad, rx2, ry2)).concat(this._cal
culatePointOnQuad(quad, rx1, ry2)); | |
| 1045 this.setVertices(rectQuad, z); | |
| 1046 }, | |
| 1047 | |
| 1048 /** | |
| 1049 * Intersects quad with given transform matrix and line l(t) = (x0, y0, t) | |
| 1050 * @param {!CSSMatrix} matrix | |
| 1051 * @param {number} x0 | |
| 1052 * @param {number} y0 | |
| 1053 * @return {(number|undefined)} | |
| 1054 */ | |
| 1055 intersectWithLine: function(matrix, x0, y0) | |
| 1056 { | |
| 1057 var i; | |
| 1058 // Vertices of the quad with transform matrix applied | |
| 1059 var points = []; | |
| 1060 for (i = 0; i < 4; ++i) | |
| 1061 points[i] = WebInspector.Geometry.multiplyVectorByMatrixAndNormalize
(new WebInspector.Geometry.Vector(this.vertices[i * 3], this.vertices[i * 3 + 1]
, this.vertices[i * 3 + 2]), matrix); | |
| 1062 // Calculating quad plane normal | |
| 1063 var normal = WebInspector.Geometry.crossProduct(WebInspector.Geometry.su
btract(points[1], points[0]), WebInspector.Geometry.subtract(points[2], points[1
])); | |
| 1064 // General form of the equation of the quad plane: A * x + B * y + C * z
+ D = 0 | |
| 1065 var A = normal.x; | |
| 1066 var B = normal.y; | |
| 1067 var C = normal.z; | |
| 1068 var D = -(A * points[0].x + B * points[0].y + C * points[0].z); | |
| 1069 // Finding t from the equation | |
| 1070 var t = -(D + A * x0 + B * y0) / C; | |
| 1071 // Point of the intersection | |
| 1072 var pt = new WebInspector.Geometry.Vector(x0, y0, t); | |
| 1073 // Vectors from the intersection point to vertices of the quad | |
| 1074 var tVects = points.map(WebInspector.Geometry.subtract.bind(null, pt)); | |
| 1075 // Intersection point lies inside of the polygon if scalar products of n
ormal of the plane and | |
| 1076 // cross products of successive tVects are all nonstrictly above or all
nonstrictly below zero | |
| 1077 for (i = 0; i < tVects.length; ++i) { | |
| 1078 var product = WebInspector.Geometry.scalarProduct(normal, WebInspect
or.Geometry.crossProduct(tVects[i], tVects[(i + 1) % tVects.length])); | |
| 1079 if (product < 0) | |
| 1080 return undefined; | |
| 1081 } | |
| 1082 return t; | |
| 1083 } | |
| 1084 } | |
| 1085 | |
| 1086 /** | |
| 1087 * @constructor | |
| 1088 * @param {!WebInspector.PaintProfilerSnapshot} snapshot | |
| 1089 * @param {!Array.<number>} rect | |
| 1090 * @param {!WebInspector.TracingModel.Event} traceEvent | |
| 1091 */ | |
| 1092 WebInspector.LayerTextureManager.Tile = function(snapshot, rect, traceEvent) | |
| 1093 { | |
| 1094 this.snapshot = snapshot; | |
| 1095 this.rect = rect; | |
| 1096 this.traceEvent = traceEvent; | |
| 1097 this.scale = 0; | |
| 1098 /** @type {?WebGLTexture} */ | |
| 1099 this.texture = null; | |
| 1100 } | |
| OLD | NEW |