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 State and UI for trace data collection.
      8  */
      9 cr.define('gpu', function() {
     10 
     11   function TracingController() {
     12     this.overlay_ = document.createElement('div');
     13     this.overlay_.className = 'gpu-tracing-overlay';
     14 
     15     cr.ui.decorate(this.overlay_, gpu.Overlay);
     16 
     17     this.statusDiv_ = document.createElement('div');
     18     this.overlay_.appendChild(this.statusDiv_);
     19 
     20     this.bufferPercentDiv_ = document.createElement('div');
     21     this.overlay_.appendChild(this.bufferPercentDiv_);
     22 
     23     this.stopButton_ = document.createElement('button');
     24     this.stopButton_.onclick = this.endTracing.bind(this);
     25     this.stopButton_.innerText = 'Stop tracing';
     26     this.overlay_.appendChild(this.stopButton_);
     27 
     28     this.traceEvents_ = [];
     29 
     30     if (browserBridge.debugMode) {
     31       var tracingControllerTests = document.createElement('script');
     32       tracingControllerTests.src =
     33           './gpu_internals/tracing_controller_tests.js';
     34       document.body.appendChild(tracingControllerTests);
     35     }
     36 
     37     this.onKeydownBoundToThis_ = this.onKeydown_.bind(this);
     38     this.onKeypressBoundToThis_ = this.onKeypress_.bind(this);
     39   }
     40 
     41   TracingController.prototype = {
     42     __proto__: cr.EventTarget.prototype,
     43 
     44     tracingEnabled_: false,
     45     tracingEnding_: false,
     46 
     47     onRequestBufferPercentFullComplete: function(percent_full) {
     48       if (!this.overlay_.visible)
     49         return;
     50 
     51       window.setTimeout(this.beginRequestBufferPercentFull_.bind(this), 250);
     52 
     53       this.bufferPercentDiv_.textContent = 'Buffer usage: ' +
     54           Math.round(100 * percent_full) + '%';
     55     },
     56 
     57     /**
     58      * Begin requesting the buffer fullness
     59      */
     60     beginRequestBufferPercentFull_: function() {
     61       chrome.send('beginRequestBufferPercentFull');
     62     },
     63 
     64     /**
     65      * Called by info_view to empty the trace buffer
     66      */
     67     beginTracing: function() {
     68       if (this.tracingEnabled_)
     69         throw Error('Tracing already begun.');
     70 
     71       this.stopButton_.hidden = false;
     72       this.statusDiv_.textContent = 'Tracing active.';
     73       this.overlay_.visible = true;
     74 
     75       this.tracingEnabled_ = true;
     76       console.log('Beginning to trace...');
     77       this.statusDiv_.textContent = 'Tracing active.';
     78 
     79       this.traceEvents_ = [];
     80       if (!browserBridge.debugMode) {
     81         chrome.send('beginTracing');
     82         this.beginRequestBufferPercentFull_();
     83       }
     84 
     85       this.tracingEnabled_ = true;
     86 
     87       var e = new cr.Event('traceBegun');
     88       e.events = this.traceEvents_;
     89       this.dispatchEvent(e);
     90 
     91       e = new cr.Event('traceEventsChanged');
     92       e.numEvents = this.traceEvents_.length;
     93       this.dispatchEvent(e);
     94 
     95       window.addEventListener('keypress', this.onKeypressBoundToThis_);
     96       window.addEventListener('keydown', this.onKeydownBoundToThis_);
     97 
     98       // In debug mode, stop tracing automatically
     99       if (browserBridge.debugMode)
    100         window.setTimeout(this.endTracing.bind(this), 100);
    101     },
    102 
    103     onKeydown_: function(e) {
    104       if (e.keyCode == 27) {
    105         this.endTracing();
    106       }
    107     },
    108 
    109     onKeypress_: function(e) {
    110       if (e.keyIdentifier == 'Enter') {
    111         this.endTracing();
    112       }
    113     },
    114     /**
    115      * Checks whether tracing is enabled
    116      */
    117     get isTracingEnabled() {
    118       return this.tracingEnabled_;
    119     },
    120 
    121     /**
    122      * Gets the currently traced events. If tracing is active, then
    123      * this can change on the fly.
    124      */
    125     get traceEvents() {
    126       return this.traceEvents_;
    127     },
    128 
    129     /**
    130      * Callbed by gpu c++ code when new GPU trace data arrives.
    131      */
    132     onTraceDataCollected: function(events) {
    133       this.statusDiv_.textContent = 'Processing trace...';
    134       this.traceEvents_.push.apply(this.traceEvents_, events);
    135     },
    136 
    137     /**
    138      * Called by info_view to finish tracing and update all views.
    139      */
    140     endTracing: function() {
    141       if (!this.tracingEnabled_) throw new Error('Tracing not begun.');
    142       if (this.tracingEnding_) return;
    143       this.tracingEnding_ = true;
    144 
    145       this.statusDiv_.textContent = 'Ending trace...';
    146       console.log('Finishing trace');
    147       this.statusDiv_.textContent = 'Downloading trace data...';
    148       this.stopButton_.hidden = true;
    149       if (!browserBridge.debugMode) {
    150         // delay sending endTracingAsync until we get a chance to
    151         // update the screen...
    152         window.setTimeout(function() {
    153           chrome.send('endTracingAsync');
    154         }, 100);
    155       } else {
    156         var events = tracingControllerTestEvents;
    157         this.onTraceDataCollected(events);
    158         window.setTimeout(this.onEndTracingComplete.bind(this), 250);
    159       }
    160     },
    161 
    162 
    163     /**
    164      * Called by the browser when all processes complete tracing.
    165      */
    166     onEndTracingComplete: function() {
    167       window.removeEventListener('keydown', this.onKeydownBoundToThis_);
    168       window.removeEventListener('keypress', this.onKeypressBoundToThis_);
    169       this.overlay_.visible = false;
    170       this.tracingEnabled_ = false;
    171       this.tracingEnding_ = false;
    172       console.log('onEndTracingComplete p1 with ' +
    173                   this.traceEvents_.length + ' events.');
    174       var e = new cr.Event('traceEnded');
    175       e.events = this.traceEvents_;
    176       this.dispatchEvent(e);
    177     },
    178 
    179     /**
    180      * Tells browser to put up a load dialog and load the trace file
    181      */
    182     beginLoadTraceFile: function() {
    183       chrome.send('loadTraceFile');
    184     },
    185 
    186     /**
    187      * Called by the browser when a trace file is loaded.
    188      */
    189     onLoadTraceFileComplete: function(data) {
    190       if (data.traceEvents) {
    191         this.traceEvents_ = data.traceEvents;
    192       } else { // path for loading traces saved without metadata
    193         if (!data.length)
    194           console.log('Expected an array when loading the trace file');
    195         else
    196           this.traceEvents_ = data;
    197       }
    198       var e = new cr.Event('loadTraceFileComplete');
    199       e.events = this.traceEvents_;
    200       this.dispatchEvent(e);
    201     },
    202 
    203     /**
    204      * Called by the browser when loading a trace file was canceled.
    205      */
    206     onLoadTraceFileCanceled: function() {
    207       cr.dispatchSimpleEvent(this, 'loadTraceFileCanceled');
    208     },
    209 
    210     /**
    211      * Tells browser to put up a save dialog and save the trace file
    212      */
    213     beginSaveTraceFile: function(traceEvents) {
    214       var data = {
    215         traceEvents: traceEvents,
    216         clientInfo: browserBridge.clientInfo,
    217         gpuInfo: browserBridge.gpuInfo
    218       };
    219       chrome.send('saveTraceFile', [JSON.stringify(data)]);
    220     },
    221 
    222     /**
    223      * Called by the browser when a trace file is saveed.
    224      */
    225     onSaveTraceFileComplete: function() {
    226       cr.dispatchSimpleEvent(this, 'saveTraceFileComplete');
    227     },
    228 
    229     /**
    230      * Called by the browser when saving a trace file was canceled.
    231      */
    232     onSaveTraceFileCanceled: function() {
    233       cr.dispatchSimpleEvent(this, 'saveTraceFileCanceled');
    234     },
    235 
    236     selfTest: function() {
    237       this.beginTracing();
    238       window.setTimeout(this.endTracing.bind(This), 500);
    239     }
    240   };
    241   return {
    242     TracingController: TracingController
    243   };
    244 });
    245 
    246