1<!DOCTYPE html>
2<!--
3Copyright (c) 2013 The Chromium Authors. All rights reserved.
4Use of this source code is governed by a BSD-style license that can be
5found in the LICENSE file.
6-->
7
8<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
9<link rel="import" href="/tracing/extras/chrome/cc/constants.html">
10<link rel="import" href="/tracing/extras/chrome/cc/layer_impl.html">
11<link rel="import" href="/tracing/model/object_instance.html">
12
13<script>
14'use strict';
15
16tr.exportTo('tr.e.cc', function() {
17
18  var constants = tr.e.cc.constants;
19  var ObjectSnapshot = tr.model.ObjectSnapshot;
20
21  /**
22   * @constructor
23   */
24  function LayerTreeImplSnapshot() {
25    ObjectSnapshot.apply(this, arguments);
26  }
27
28  LayerTreeImplSnapshot.prototype = {
29    __proto__: ObjectSnapshot.prototype,
30
31    preInitialize: function() {
32      tr.e.cc.preInitializeObject(this);
33      this.layerTreeHostImpl = undefined;
34      this.whichTree = undefined;
35      this.sourceFrameNumber = undefined;
36    },
37
38    initialize: function() {
39      tr.e.cc.moveRequiredFieldsFromArgsToToplevel(
40          this, ['rootLayer',
41            'renderSurfaceLayerList']);
42      if (this.args.sourceFrameNumber)
43        this.sourceFrameNumber = this.args.sourceFrameNumber;
44      this.rootLayer.layerTreeImpl = this;
45
46      if (this.args.swapPromiseTraceIds &&
47          this.args.swapPromiseTraceIds.length) {
48        this.tracedInputLatencies = [];
49
50        var ownProcess = this.objectInstance.parent;
51        var modelHelper = ownProcess.model.getOrCreateHelper(
52            tr.model.helpers.ChromeModelHelper);
53        if (modelHelper)
54          this._initializeTracedInputLatencies(modelHelper);
55      }
56    },
57
58    _initializeTracedInputLatencies: function(modelHelper) {
59      var latencyEvents = modelHelper.browserHelper.getLatencyEventsInRange(
60          modelHelper.model.bounds);
61
62      // Convert all ids to InputLatency Async objects.
63      latencyEvents.forEach(function(event) {
64        for (var i = 0; i < this.args.swapPromiseTraceIds.length; i++) {
65          if (!event.args.data || !event.args.data.trace_id)
66            continue;
67          if (parseInt(event.args.data.trace_id) ===
68              this.args.swapPromiseTraceIds[i])
69            this.tracedInputLatencies.push(event);
70        }
71      }, this);
72    },
73
74    get hasSourceFrameBeenDrawnBefore() {
75      if (this.whichTree == tr.e.cc.constants.PENDING_TREE)
76        return false;
77
78      // Old chrome's don't produce sourceFrameNumber.
79      if (this.sourceFrameNumber === undefined)
80        return;
81
82      var thisLTHI = this.layerTreeHostImpl;
83      var thisLTHIIndex = thisLTHI.objectInstance.snapshots.indexOf(
84        thisLTHI);
85      var prevLTHIIndex = thisLTHIIndex - 1;
86      if (prevLTHIIndex < 0 ||
87          prevLTHIIndex >= thisLTHI.objectInstance.snapshots.length)
88        return false;
89      var prevLTHI = thisLTHI.objectInstance.snapshots[prevLTHIIndex];
90      if (!prevLTHI.activeTree)
91        return false;
92
93      // Old chrome's don't produce sourceFrameNumber.
94      if (prevLTHI.activeTree.sourceFrameNumber === undefined)
95        return;
96      return prevLTHI.activeTree.sourceFrameNumber == this.sourceFrameNumber;
97    },
98
99    get otherTree() {
100      var other = this.whichTree == constants.ACTIVE_TREE ?
101          constants.PENDING_TREE : constants.ACTIVE_TREE;
102      return this.layerTreeHostImpl.getTree(other);
103    },
104
105    get gpuMemoryUsageInBytes() {
106      var totalBytes = 0;
107      this.iterLayers(function(layer) {
108        if (layer.gpuMemoryUsageInBytes !== undefined)
109          totalBytes += layer.gpuMemoryUsageInBytes;
110      });
111      return totalBytes;
112    },
113
114    iterLayers: function(func, thisArg) {
115      var visitedLayers = {};
116      function visitLayer(layer, depth, isMask, isReplica) {
117        if (visitedLayers[layer.layerId])
118          return;
119        visitedLayers[layer.layerId] = true;
120        func.call(thisArg, layer, depth, isMask, isReplica);
121        if (layer.children) {
122          for (var i = 0; i < layer.children.length; i++)
123            visitLayer(layer.children[i], depth + 1);
124        }
125        if (layer.maskLayer)
126          visitLayer(layer.maskLayer, depth + 1, true, false);
127        if (layer.replicaLayer)
128          visitLayer(layer.replicaLayer, depth + 1, false, true);
129      }
130      visitLayer(this.rootLayer, 0, false, false);
131    },
132    findLayerWithId: function(id) {
133      var foundLayer = undefined;
134      function visitLayer(layer) {
135        if (layer.layerId == id)
136          foundLayer = layer;
137      }
138      this.iterLayers(visitLayer);
139      return foundLayer;
140    }
141  };
142
143  ObjectSnapshot.register(
144      LayerTreeImplSnapshot,
145      {typeName: 'cc::LayerTreeImpl'});
146
147  return {
148    LayerTreeImplSnapshot: LayerTreeImplSnapshot
149  };
150});
151</script>
152