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/extras/chrome/cc/constants.html">
9<link rel="import" href="/tracing/extras/chrome/cc/layer_tree_impl.html">
10<link rel="import" href="/tracing/extras/chrome/cc/util.html">
11<link rel="import" href="/tracing/base/bbox2.html">
12<link rel="import" href="/tracing/model/object_instance.html">
13
14<script>
15'use strict';
16
17/**
18 * @fileoverview Provides the LayerTreeHostImpl model-level objects.
19 */
20tr.exportTo('tr.e.cc', function() {
21  var constants = tr.e.cc.constants;
22
23  var ObjectSnapshot = tr.model.ObjectSnapshot;
24  var ObjectInstance = tr.model.ObjectInstance;
25
26  /**
27   * @constructor
28   */
29  function LayerTreeHostImplSnapshot() {
30    ObjectSnapshot.apply(this, arguments);
31  }
32
33  LayerTreeHostImplSnapshot.prototype = {
34    __proto__: ObjectSnapshot.prototype,
35
36    preInitialize: function() {
37      tr.e.cc.preInitializeObject(this);
38    },
39
40    initialize: function() {
41      tr.e.cc.moveRequiredFieldsFromArgsToToplevel(
42          this, ['deviceViewportSize',
43            'activeTree']);
44      tr.e.cc.moveOptionalFieldsFromArgsToToplevel(
45          this, ['pendingTree']);
46
47      // Move active_tiles into this.tiles. If that doesn't exist then, then as
48      // a backward compatability move tiles into this.tiles.
49      if (this.args.activeTiles !== undefined) {
50        this.activeTiles = this.args.activeTiles;
51        delete this.args.activeTiles;
52      } else if (this.args.tiles !== undefined) {
53        this.activeTiles = this.args.tiles;
54        delete this.args.tiles;
55      }
56
57      if (!this.activeTiles)
58        this.activeTiles = [];
59
60      this.activeTree.layerTreeHostImpl = this;
61      this.activeTree.whichTree = constants.ACTIVE_TREE;
62      if (this.pendingTree) {
63        this.pendingTree.layerTreeHostImpl = this;
64        this.pendingTree.whichTree = constants.PENDING_TREE;
65      }
66    },
67
68    /**
69     * Get all of tile scales and their associated names.
70     */
71    getContentsScaleNames: function() {
72      var scales = {};
73      for (var i = 0; i < this.activeTiles.length; ++i) {
74        var tile = this.activeTiles[i];
75        // Return scale -> scale name mappings.
76        // Example:
77        //  0.25 -> LOW_RESOLUTION
78        //  1.0 -> HIGH_RESOLUTION
79        //  0.75 -> NON_IDEAL_RESOLUTION
80        scales[tile.contentsScale] = tile.resolution;
81      }
82      return scales;
83    },
84
85    getTree: function(whichTree) {
86      if (whichTree == constants.ACTIVE_TREE)
87        return this.activeTree;
88      if (whichTree == constants.PENDING_TREE)
89        return this.pendingTree;
90      throw new Exception('Unknown tree type + ' + whichTree);
91    },
92
93    get tilesHaveGpuMemoryUsageInfo() {
94      if (this.tilesHaveGpuMemoryUsageInfo_ !== undefined)
95        return this.tilesHaveGpuMemoryUsageInfo_;
96
97      for (var i = 0; i < this.activeTiles.length; i++) {
98        if (this.activeTiles[i].gpuMemoryUsageInBytes === undefined)
99          continue;
100        this.tilesHaveGpuMemoryUsageInfo_ = true;
101        return true;
102      }
103      this.tilesHaveGpuMemoryUsageInfo_ = false;
104      return false;
105    },
106
107    get gpuMemoryUsageInBytes() {
108      if (!this.tilesHaveGpuMemoryUsageInfo)
109        return;
110
111      var usage = 0;
112      for (var i = 0; i < this.activeTiles.length; i++) {
113        var u = this.activeTiles[i].gpuMemoryUsageInBytes;
114        if (u !== undefined)
115          usage += u;
116      }
117      return usage;
118    },
119
120    get userFriendlyName() {
121      var frameNumber;
122      if (!this.activeTree) {
123        frameNumber = this.objectInstance.snapshots.indexOf(this);
124      } else {
125        if (this.activeTree.sourceFrameNumber === undefined)
126          frameNumber = this.objectInstance.snapshots.indexOf(this);
127        else
128          frameNumber = this.activeTree.sourceFrameNumber;
129      }
130      return 'cc::LayerTreeHostImpl frame ' + frameNumber;
131    }
132  };
133
134  ObjectSnapshot.register(
135      LayerTreeHostImplSnapshot,
136      {typeName: 'cc::LayerTreeHostImpl'});
137
138  /**
139   * @constructor
140   */
141  function LayerTreeHostImplInstance() {
142    ObjectInstance.apply(this, arguments);
143
144    this.allLayersBBox_ = undefined;
145  }
146
147  LayerTreeHostImplInstance.prototype = {
148    __proto__: ObjectInstance.prototype,
149
150    get allContentsScales() {
151      if (this.allContentsScales_)
152        return this.allContentsScales_;
153
154      var scales = {};
155      for (var tileID in this.allTileHistories_) {
156        var tileHistory = this.allTileHistories_[tileID];
157        scales[tileHistory.contentsScale] = true;
158      }
159      this.allContentsScales_ = tr.b.dictionaryKeys(scales);
160      return this.allContentsScales_;
161    },
162
163    get allLayersBBox() {
164      if (this.allLayersBBox_)
165        return this.allLayersBBox_;
166      var bbox = new tr.b.BBox2();
167      function handleTree(tree) {
168        tree.renderSurfaceLayerList.forEach(function(layer) {
169          bbox.addQuad(layer.layerQuad);
170        });
171      }
172      this.snapshots.forEach(function(lthi) {
173        handleTree(lthi.activeTree);
174        if (lthi.pendingTree)
175          handleTree(lthi.pendingTree);
176      });
177      this.allLayersBBox_ = bbox;
178      return this.allLayersBBox_;
179    }
180  };
181
182  ObjectInstance.register(
183      LayerTreeHostImplInstance,
184      {typeName: 'cc::LayerTreeHostImpl'});
185
186  return {
187    LayerTreeHostImplSnapshot: LayerTreeHostImplSnapshot,
188    LayerTreeHostImplInstance: LayerTreeHostImplInstance
189
190  };
191});
192</script>
193