| <!DOCTYPE html> |
| <!-- |
| Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| Use of this source code is governed by a BSD-style license that can be |
| found in the LICENSE file. |
| --> |
| |
| <link rel="import" href="/extras/audits/chrome_model_helper.html"> |
| <link rel="import" href="/extras/cc/constants.html"> |
| <link rel="import" href="/extras/cc/layer_impl.html"> |
| <link rel="import" href="/core/trace_model/object_instance.html"> |
| |
| <script> |
| 'use strict'; |
| |
| tv.exportTo('tv.e.cc', function() { |
| |
| var constants = tv.e.cc.constants; |
| var ObjectSnapshot = tv.c.trace_model.ObjectSnapshot; |
| |
| /** |
| * @constructor |
| */ |
| function LayerTreeImplSnapshot() { |
| ObjectSnapshot.apply(this, arguments); |
| } |
| |
| LayerTreeImplSnapshot.prototype = { |
| __proto__: ObjectSnapshot.prototype, |
| |
| preInitialize: function() { |
| tv.e.cc.preInitializeObject(this); |
| this.layerTreeHostImpl = undefined; |
| this.whichTree = undefined; |
| this.sourceFrameNumber = undefined; |
| }, |
| |
| initialize: function() { |
| tv.e.cc.moveRequiredFieldsFromArgsToToplevel( |
| this, ['rootLayer', |
| 'renderSurfaceLayerList']); |
| if (this.args.sourceFrameNumber) |
| this.sourceFrameNumber = this.args.sourceFrameNumber; |
| this.rootLayer.layerTreeImpl = this; |
| |
| if (this.args.swapPromiseTraceIds && |
| this.args.swapPromiseTraceIds.length) { |
| this.tracedInputLatencies = []; |
| |
| var ownProcess = this.objectInstance.parent; |
| var traceModel = ownProcess.model; |
| if (tv.e.audits.ChromeModelHelper.supportsModel(traceModel)) |
| this._initializeTracedInputLatencies(traceModel); |
| } |
| }, |
| |
| _initializeTracedInputLatencies: function(traceModel) { |
| var modelHelper = new tv.e.audits.ChromeModelHelper(traceModel); |
| if (!modelHelper.browser) |
| return; |
| |
| var latencyEvents = modelHelper.browser.getLatencyEventsInRange( |
| traceModel.range); |
| |
| // Convert all ids to InputLatency Async objects. |
| latencyEvents.forEach(function(event) { |
| for (var i = 0; i < this.args.swapPromiseTraceIds.length; i++) { |
| if (!event.args.data || !event.args.data.trace_id) |
| continue; |
| if (parseInt(event.args.data.trace_id) === |
| this.args.swapPromiseTraceIds[i]) |
| this.tracedInputLatencies.push(event); |
| } |
| }, this); |
| }, |
| |
| get hasSourceFrameBeenDrawnBefore() { |
| if (this.whichTree == tv.e.cc.constants.PENDING_TREE) |
| return false; |
| |
| // Old chrome's don't produce sourceFrameNumber. |
| if (this.sourceFrameNumber === undefined) |
| return; |
| |
| var thisLTHI = this.layerTreeHostImpl; |
| var thisLTHIIndex = thisLTHI.objectInstance.snapshots.indexOf( |
| thisLTHI); |
| var prevLTHIIndex = thisLTHIIndex - 1; |
| if (prevLTHIIndex < 0 || |
| prevLTHIIndex >= thisLTHI.objectInstance.snapshots.length) |
| return false; |
| var prevLTHI = thisLTHI.objectInstance.snapshots[prevLTHIIndex]; |
| if (!prevLTHI.activeTree) |
| return false; |
| |
| // Old chrome's don't produce sourceFrameNumber. |
| if (prevLTHI.activeTree.sourceFrameNumber === undefined) |
| return; |
| return prevLTHI.activeTree.sourceFrameNumber == this.sourceFrameNumber; |
| }, |
| |
| get otherTree() { |
| var other = this.whichTree == constants.ACTIVE_TREE ? |
| constants.PENDING_TREE : constants.ACTIVE_TREE; |
| return this.layerTreeHostImpl.getTree(other); |
| }, |
| |
| get gpuMemoryUsageInBytes() { |
| var totalBytes = 0; |
| this.iterLayers(function(layer) { |
| if (layer.gpuMemoryUsageInBytes !== undefined) |
| totalBytes += layer.gpuMemoryUsageInBytes; |
| }); |
| return totalBytes; |
| }, |
| |
| iterLayers: function(func, thisArg) { |
| var visitedLayers = {}; |
| function visitLayer(layer, depth, isMask, isReplica) { |
| if (visitedLayers[layer.layerId]) |
| return; |
| visitedLayers[layer.layerId] = true; |
| func.call(thisArg, layer, depth, isMask, isReplica); |
| if (layer.children) { |
| for (var i = 0; i < layer.children.length; i++) |
| visitLayer(layer.children[i], depth + 1); |
| } |
| if (layer.maskLayer) |
| visitLayer(layer.maskLayer, depth + 1, true, false); |
| if (layer.replicaLayer) |
| visitLayer(layer.replicaLayer, depth + 1, false, true); |
| } |
| visitLayer(this.rootLayer, 0, false, false); |
| }, |
| findLayerWithId: function(id) { |
| var foundLayer = undefined; |
| function visitLayer(layer) { |
| if (layer.layerId == id) |
| foundLayer = layer; |
| } |
| this.iterLayers(visitLayer); |
| return foundLayer; |
| } |
| }; |
| |
| ObjectSnapshot.register( |
| LayerTreeImplSnapshot, |
| {typeName: 'cc::LayerTreeImpl'}); |
| |
| return { |
| LayerTreeImplSnapshot: LayerTreeImplSnapshot |
| }; |
| }); |
| </script> |