Home | History | Annotate | Download | only in gpu_internals
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 
      6 /**
      7  * @fileoverview TimelineView visualizes GPU_TRACE events using the
      8  * gpu.Timeline component.
      9  */
     10 cr.define('gpu', function() {
     11   function tsRound(ts) {
     12     return Math.round(ts * 1000.0) / 1000.0;
     13   }
     14   function getPadding(text, width) {
     15     width = width || 0;
     16 
     17     if (typeof text != 'string')
     18       text = String(text);
     19 
     20     if (text.length >= width)
     21       return '';
     22 
     23     var pad = '';
     24     for (var i = 0; i < width - text.length; i++)
     25       pad += ' ';
     26     return pad;
     27   }
     28 
     29   function leftAlign(text, width) {
     30     return text + getPadding(text, width);
     31   }
     32 
     33   function rightAlign(text, width) {
     34     return getPadding(text, width) + text;
     35   }
     36 
     37   /**
     38    * TimelineView
     39    * @constructor
     40    * @extends {HTMLDivElement}
     41    */
     42   TimelineView = cr.ui.define('div');
     43 
     44   TimelineView.prototype = {
     45     __proto__: HTMLDivElement.prototype,
     46 
     47     decorate: function() {
     48       this.className = 'timeline-view';
     49 
     50       this.timelineContainer_ = document.createElement('div');
     51       this.timelineContainer_.className = 'timeline-container';
     52 
     53       var summaryContainer_ = document.createElement('div');
     54       summaryContainer_.className = 'summary-container';
     55 
     56       this.summary_ = document.createElement('pre');
     57       this.summary_.className = 'summary';
     58 
     59       summaryContainer_.appendChild(this.summary_);
     60       this.appendChild(this.timelineContainer_);
     61       this.appendChild(summaryContainer_);
     62 
     63       this.onSelectionChangedBoundToThis_ = this.onSelectionChanged_.bind(this);
     64     },
     65 
     66     set traceEvents(traceEvents) {
     67       console.log('TimelineView.refresh');
     68       this.timelineModel_ = new gpu.TimelineModel(traceEvents);
     69 
     70       // remove old timeline
     71       this.timelineContainer_.textContent = '';
     72 
     73       // create new timeline if needed
     74       if (traceEvents.length) {
     75         this.timeline_ = new gpu.Timeline();
     76         this.timeline_.model = this.timelineModel_;
     77         this.timelineContainer_.appendChild(this.timeline_);
     78         this.timeline_.onResize();
     79         this.timeline_.addEventListener('selectionChange',
     80                                         this.onSelectionChangedBoundToThis_);
     81         this.onSelectionChanged_();
     82       } else {
     83         this.timeline_ = null;
     84       }
     85     },
     86 
     87     onSelectionChanged_: function(e) {
     88       console.log('selection changed');
     89       var timeline = this.timeline_;
     90       var selection = timeline.selection;
     91       var outputDiv = this.summary_;
     92       if (!selection.length) {
     93         outputDiv.textContent = timeline.keyHelp;
     94         return;
     95       }
     96 
     97       var text = '';
     98       if (selection.length == 1) {
     99         var c0Width = 10;
    100         var slice = selection[0].slice;
    101         text = 'Selected item:\n';
    102         text += leftAlign('Title', c0Width) + ': ' + slice.title + '\n';
    103         text += leftAlign('Start', c0Width) + ': ' +
    104             tsRound(slice.start) + ' ms\n';
    105         text += leftAlign('Duration', c0Width) + ': ' +
    106             tsRound(slice.duration) + ' ms\n';
    107 
    108         var n = 0;
    109         for (var argName in slice.args) {
    110           n += 1;
    111         }
    112         if (n > 0) {
    113           text += leftAlign('Args', c0Width) + ':\n';
    114           for (var argName in slice.args) {
    115             var argVal = slice.args[argName];
    116             text += leftAlign(' ' + argName, c0Width) + ': ' + argVal + '\n';
    117           }
    118         }
    119       } else {
    120         var c0Width = 55;
    121         var c1Width = 12;
    122         var c2Width = 5;
    123         text = 'Selection summary:\n';
    124         var tsLo = Math.min.apply(Math, selection.map(
    125             function(s) {return s.slice.start;}));
    126         var tsHi = Math.max.apply(Math, selection.map(
    127             function(s) {return s.slice.end;}));
    128 
    129         // compute total selection duration
    130         var titles = selection.map(function(i) { return i.slice.title; });
    131 
    132         var slicesByTitle = {};
    133         for (var i = 0; i < selection.length; i++) {
    134           var slice = selection[i].slice;
    135           if (!slicesByTitle[slice.title])
    136             slicesByTitle[slice.title] = {
    137               slices: []
    138             };
    139           slicesByTitle[slice.title].slices.push(slice);
    140         }
    141         var totalDuration = 0;
    142         for (var sliceGroupTitle in slicesByTitle) {
    143           var sliceGroup = slicesByTitle[sliceGroupTitle];
    144           var duration = 0;
    145           for (i = 0; i < sliceGroup.slices.length; i++)
    146             duration += sliceGroup.slices[i].duration;
    147           totalDuration += duration;
    148 
    149           text += ' ' +
    150               leftAlign(sliceGroupTitle, c0Width) + ': ' +
    151               rightAlign(tsRound(duration) + 'ms', c1Width) + '   ' +
    152               rightAlign(String(sliceGroup.slices.length), c2Width) +
    153               ' occurrences' + '\n';
    154         }
    155 
    156         text += leftAlign('*Totals', c0Width) + ' : ' +
    157             rightAlign(tsRound(totalDuration) + 'ms', c1Width) + '   ' +
    158             rightAlign(String(selection.length), c2Width) + ' occurrences' +
    159             '\n';
    160 
    161         text += '\n';
    162 
    163         text += leftAlign('Selection start', c0Width) + ' : ' +
    164             rightAlign(tsRound(tsLo) + 'ms', c1Width) +
    165             '\n';
    166         text += leftAlign('Selection extent', c0Width) + ' : ' +
    167             rightAlign(tsRound(tsHi - tsLo) + 'ms', c1Width) +
    168             '\n';
    169       }
    170 
    171       // done
    172       outputDiv.textContent = text;
    173     }
    174   };
    175 
    176   return {
    177     TimelineView: TimelineView
    178   };
    179 });
    180