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<link rel="import" href="/tracing/extras/chrome/cc/raster_task.html">
8<link rel="import" href="/tracing/model/event_set.html">
9<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
10<link rel="import" href="/tracing/ui/base/table.html">
11<link rel="import" href="/tracing/ui/extras/chrome/cc/selection.html">
12<link rel="import" href="/tracing/value/ui/scalar_span.html">
13<link rel="import" href="/tracing/value/unit.html">
14
15<polymer-element name="tr-ui-e-chrome-cc-raster-task-view">
16  <template>
17    <style>
18    :host {
19      display: flex;
20      flex-direction: column;
21    }
22    #heading {
23      flex: 0 0 auto;
24    }
25    </style>
26
27    <div id="heading">
28      Rasterization costs in
29      <tr-ui-a-analysis-link id="link"></tr-ui-a-analysis-link>
30    </div>
31    <tr-ui-b-table id="content"></tr-ui-b-table>
32  </template>
33
34  <script>
35  'use strict';
36  Polymer({
37    created: function() {
38      this.selection_ = undefined;
39    },
40
41    set selection(selection) {
42      this.selection_ = selection;
43
44      this.updateContents_();
45    },
46
47    updateColumns_: function(hadCpuDurations) {
48      var timeSpanConfig = {
49        unit: tr.v.Unit.byName.timeDurationInMs,
50        ownerDocument: this.ownerDocument
51      };
52
53      var columns = [
54        {
55          title: 'Layer',
56          value: function(row) {
57            if (row.isTotals)
58              return 'Totals';
59            if (row.layer) {
60              var linkEl = document.createElement('tr-ui-a-analysis-link');
61              linkEl.setSelectionAndContent(
62                function() {
63                  return new tr.ui.e.chrome.cc.LayerSelection(costs.layer);
64                },
65                'Layer ' + row.layerId);
66              return linkEl;
67            } else {
68              return 'Layer ' + row.layerId;
69            }
70          },
71          width: '250px'
72        },
73        {
74          title: 'Num Tiles',
75          value: function(row) { return row.numTiles; },
76          cmp: function(a, b) { return a.numTiles - b.numTiles; }
77        },
78        {
79          title: 'Num Analysis Tasks',
80          value: function(row) { return row.numAnalysisTasks; },
81          cmp: function(a, b) {
82            return a.numAnalysisTasks - b.numAnalysisTasks;
83          }
84        },
85        {
86          title: 'Num Raster Tasks',
87          value: function(row) { return row.numRasterTasks; },
88          cmp: function(a, b) { return a.numRasterTasks - b.numRasterTasks; }
89        },
90        {
91          title: 'Wall Duration (ms)',
92          value: function(row) {
93            return tr.v.ui.createScalarSpan(row.duration, timeSpanConfig);
94          },
95          cmp: function(a, b) { return a.duration - b.duration; }
96        }
97      ];
98
99      if (hadCpuDurations) {
100        columns.push({
101          title: 'CPU Duration (ms)',
102          value: function(row) {
103            return tr.v.ui.createScalarSpan(row.cpuDuration, timeSpanConfig);
104          },
105          cmp: function(a, b) { return a.cpuDuration - b.cpuDuration; }
106        });
107      }
108
109      var colWidthPercentage;
110      if (columns.length == 1)
111        colWidthPercentage = '100%';
112      else
113        colWidthPercentage = (100 / (columns.length - 1)).toFixed(3) + '%';
114
115      for (var i = 1; i < columns.length; i++)
116        columns[i].width = colWidthPercentage;
117
118      this.$.content.tableColumns = columns;
119      this.$.content.sortColumnIndex = columns.length - 1;
120    },
121
122    updateContents_: function() {
123      var table = this.$.content;
124
125      if (this.selection_.length === 0) {
126        this.$.link.setSelectionAndContent(undefined, '');
127        table.tableRows = [];
128        table.footerRows = [];
129        table.rebuild();
130        return;
131      }
132
133      // LTHI link.
134      var lthi = tr.e.cc.getTileFromRasterTaskSlice(
135          this.selection_[0]).containingSnapshot;
136      this.$.link.setSelectionAndContent(function() {
137          return new tr.model.EventSet(lthi);
138      }, lthi.userFriendlyName);
139
140      // Get costs by layer.
141      var costsByLayerId = {};
142      function getCurrentCostsForLayerId(tile) {
143        var layerId = tile.layerId;
144        var lthi = tile.containingSnapshot;
145        var layer;
146        if (lthi.activeTree)
147          layer = lthi.activeTree.findLayerWithId(layerId);
148        if (layer === undefined && lthi.pendingTree)
149          layer = lthi.pendingTree.findLayerWithId(layerId);
150        if (costsByLayerId[layerId] === undefined) {
151          costsByLayerId[layerId] = {
152            layerId: layerId,
153            layer: layer,
154            numTiles: 0,
155            numAnalysisTasks: 0,
156            numRasterTasks: 0,
157            duration: 0,
158            cpuDuration: 0
159          };
160        }
161        return costsByLayerId[layerId];
162      }
163
164      var totalDuration = 0;
165      var totalCpuDuration = 0;
166      var totalNumAnalyzeTasks = 0;
167      var totalNumRasterizeTasks = 0;
168      var hadCpuDurations = false;
169
170      var tilesThatWeHaveSeen = {};
171
172      this.selection_.forEach(function(slice) {
173        var tile = tr.e.cc.getTileFromRasterTaskSlice(slice);
174        var curCosts = getCurrentCostsForLayerId(tile);
175
176        if (!tilesThatWeHaveSeen[tile.objectInstance.id]) {
177          tilesThatWeHaveSeen[tile.objectInstance.id] = true;
178          curCosts.numTiles += 1;
179        }
180
181        if (tr.e.cc.isSliceDoingAnalysis(slice)) {
182          curCosts.numAnalysisTasks += 1;
183          totalNumAnalyzeTasks += 1;
184        } else {
185          curCosts.numRasterTasks += 1;
186          totalNumRasterizeTasks += 1;
187        }
188        curCosts.duration += slice.duration;
189        totalDuration += slice.duration;
190        if (slice.cpuDuration !== undefined) {
191          curCosts.cpuDuration += slice.cpuDuration;
192          totalCpuDuration += slice.cpuDuration;
193          hadCpuDurations = true;
194        }
195      });
196
197      // Apply to the table.
198      this.updateColumns_(hadCpuDurations);
199      table.tableRows = tr.b.dictionaryValues(costsByLayerId);
200      table.rebuild();
201
202      // Footer.
203      table.footerRows = [
204        {
205          isTotals: true,
206          numTiles: tr.b.dictionaryLength(tilesThatWeHaveSeen),
207          numAnalysisTasks: totalNumAnalyzeTasks,
208          numRasterTasks: totalNumRasterizeTasks,
209          duration: totalDuration,
210          cpuDuration: totalCpuDuration
211        }
212      ];
213    }
214  });
215  </script>
216</polymer-element>
217