Home | History | Annotate | Download | only in gpu
      1 // Copyright (c) 2012 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 This view displays information on the current GPU
      8  * hardware.  Its primary usefulness is to allow users to copy-paste
      9  * their data in an easy to read format for bug reports.
     10  */
     11 cr.define('gpu', function() {
     12   /**
     13    * Provides information on the GPU process and underlying graphics hardware.
     14    * @constructor
     15    * @extends {cr.ui.TabPanel}
     16    */
     17   var InfoView = cr.ui.define(cr.ui.TabPanel);
     18 
     19   InfoView.prototype = {
     20     __proto__: cr.ui.TabPanel.prototype,
     21 
     22     decorate: function() {
     23       cr.ui.TabPanel.prototype.decorate.apply(this);
     24 
     25       browserBridge.addEventListener('gpuInfoUpdate', this.refresh.bind(this));
     26       browserBridge.addEventListener('logMessagesChange',
     27                                      this.refresh.bind(this));
     28       browserBridge.addEventListener('clientInfoChange',
     29                                      this.refresh.bind(this));
     30       this.refresh();
     31     },
     32 
     33     /**
     34     * Updates the view based on its currently known data
     35     */
     36     refresh: function(data) {
     37       // Client info
     38       if (browserBridge.clientInfo) {
     39         var clientInfo = browserBridge.clientInfo;
     40 
     41         var commandLineParts = clientInfo.command_line.split(' ');
     42         commandLineParts.shift(); // Pop off the exe path
     43         var commandLineString = commandLineParts.join(' ')
     44 
     45         this.setTable_('client-info', [
     46           {
     47             description: 'Data exported',
     48             value: (new Date()).toLocaleString()
     49           },
     50           {
     51             description: 'Chrome version',
     52             value: clientInfo.version
     53           },
     54           {
     55             description: 'Operating system',
     56             value: clientInfo.operating_system
     57           },
     58           {
     59             description: 'Software rendering list version',
     60             value: clientInfo.blacklist_version
     61           },
     62           {
     63             description: 'Driver bug list version',
     64             value: clientInfo.driver_bug_list_version
     65           },
     66           {
     67             description: 'ANGLE revision',
     68             value: clientInfo.angle_revision
     69           },
     70           {
     71             description: '2D graphics backend',
     72             value: clientInfo.graphics_backend
     73           },
     74           {
     75             description: 'Command Line Args',
     76             value: commandLineString
     77           }]);
     78       } else {
     79         this.setText_('client-info', '... loading...');
     80       }
     81 
     82       // Feature map
     83       var featureLabelMap = {
     84         '2d_canvas': 'Canvas',
     85         '3d_css': '3D CSS',
     86         'css_animation': 'CSS Animation',
     87         'compositing': 'Compositing',
     88         'webgl': 'WebGL',
     89         'multisampling': 'WebGL multisampling',
     90         'flash_3d': 'Flash 3D',
     91         'flash_stage3d': 'Flash Stage3D',
     92         'flash_stage3d_baseline': 'Flash Stage3D Baseline profile',
     93         'texture_sharing': 'Texture Sharing',
     94         'video_decode': 'Video Decode',
     95         'video_encode': 'Video Encode',
     96         'video': 'Video',
     97         // GPU Switching
     98         'gpu_switching': 'GPU Switching',
     99         'panel_fitting': 'Panel Fitting',
    100         'force_compositing_mode': 'Force Compositing Mode',
    101         'raster': 'Rasterization',
    102       };
    103       var statusLabelMap = {
    104         'disabled_software': 'Software only. Hardware acceleration disabled.',
    105         'disabled_software_animated': 'Software animated.',
    106         'disabled_off': 'Unavailable. Hardware acceleration disabled.',
    107         'software': 'Software rendered. Hardware acceleration not enabled.',
    108         'unavailable_off': 'Unavailable. Hardware acceleration unavailable',
    109         'unavailable_software':
    110             'Software only, hardware acceleration unavailable',
    111         'enabled_readback': 'Hardware accelerated, but at reduced performance',
    112         'enabled_force': 'Hardware accelerated on all pages',
    113         'enabled_threaded': 'Hardware accelerated on demand and threaded',
    114         'enabled_force_threaded':
    115             'Hardware accelerated on all pages and threaded',
    116         'enabled': 'Hardware accelerated',
    117         'accelerated': 'Accelerated',
    118         'accelerated_threaded': 'Accelerated and threaded',
    119         // GPU Switching
    120         'gpu_switching_automatic': 'Automatic switching',
    121         'gpu_switching_force_discrete': 'Always on discrete GPU',
    122         'gpu_switching_force_integrated': 'Always on integrated GPU',
    123         'disabled_software_multithreaded': 'Software only, multi-threaded',
    124       };
    125 
    126       var statusClassMap = {
    127         'disabled_software': 'feature-yellow',
    128         'disabled_software_animated': 'feature-yellow',
    129         'disabled_off': 'feature-red',
    130         'software': 'feature-yellow',
    131         'unavailable_off': 'feature-red',
    132         'unavailable_software': 'feature-yellow',
    133         'enabled_force': 'feature-green',
    134         'enabled_readback': 'feature-yellow',
    135         'enabled_threaded': 'feature-green',
    136         'enabled_force_threaded': 'feature-green',
    137         'enabled': 'feature-green',
    138         'accelerated': 'feature-green',
    139         'accelerated_threaded': 'feature-green',
    140         // GPU Switching
    141         'gpu_switching_automatic': 'feature-green',
    142         'gpu_switching_force_discrete': 'feature-red',
    143         'gpu_switching_force_integrated': 'feature-red',
    144         'disabled_software_multithreaded': 'feature-yellow',
    145       };
    146 
    147       // GPU info, basic
    148       var diagnosticsDiv = this.querySelector('.diagnostics');
    149       var diagnosticsLoadingDiv = this.querySelector('.diagnostics-loading');
    150       var featureStatusList = this.querySelector('.feature-status-list');
    151       var problemsDiv = this.querySelector('.problems-div');
    152       var problemsList = this.querySelector('.problems-list');
    153       var workaroundsDiv = this.querySelector('.workarounds-div');
    154       var workaroundsList = this.querySelector('.workarounds-list');
    155       var performanceDiv = this.querySelector('.performance-div');
    156       var gpuInfo = browserBridge.gpuInfo;
    157       var i;
    158       if (gpuInfo) {
    159         // Not using jstemplate here for blacklist status because we construct
    160         // href from data, which jstemplate can't seem to do.
    161         if (gpuInfo.featureStatus) {
    162           // feature status list
    163           featureStatusList.textContent = '';
    164           for (var featureName in gpuInfo.featureStatus.featureStatus) {
    165             var featureStatus =
    166                 gpuInfo.featureStatus.featureStatus[featureName];
    167             var featureEl = document.createElement('li');
    168 
    169             var nameEl = document.createElement('span');
    170             if (!featureLabelMap[featureName])
    171               console.log('Missing featureLabel for', featureName);
    172             nameEl.textContent = featureLabelMap[featureName] + ': ';
    173             featureEl.appendChild(nameEl);
    174 
    175             var statusEl = document.createElement('span');
    176             if (!statusLabelMap[featureStatus])
    177               console.log('Missing statusLabel for', featureStatus);
    178             if (!statusClassMap[featureStatus])
    179               console.log('Missing statusClass for', featureStatus);
    180             statusEl.textContent = statusLabelMap[featureStatus];
    181             statusEl.className = statusClassMap[featureStatus];
    182             featureEl.appendChild(statusEl);
    183 
    184             featureStatusList.appendChild(featureEl);
    185           }
    186 
    187           // problems list
    188           if (gpuInfo.featureStatus.problems.length) {
    189             problemsDiv.hidden = false;
    190             problemsList.textContent = '';
    191             for (i = 0; i < gpuInfo.featureStatus.problems.length; i++) {
    192               var problem = gpuInfo.featureStatus.problems[i];
    193               var problemEl = this.createProblemEl_(problem);
    194               problemsList.appendChild(problemEl);
    195             }
    196           } else {
    197             problemsDiv.hidden = true;
    198           }
    199 
    200           // driver bug workarounds list
    201           if (gpuInfo.featureStatus.workarounds.length) {
    202             workaroundsDiv.hidden = false;
    203             workaroundsList.textContent = '';
    204             for (i = 0; i < gpuInfo.featureStatus.workarounds.length; i++) {
    205               var workaroundEl = document.createElement('li');
    206               workaroundEl.textContent = gpuInfo.featureStatus.workarounds[i];
    207               workaroundsList.appendChild(workaroundEl);
    208             }
    209           } else {
    210             workaroundsDiv.hidden = true;
    211           }
    212 
    213         } else {
    214           featureStatusList.textContent = '';
    215           problemsList.hidden = true;
    216           workaroundsList.hidden = true;
    217         }
    218         if (gpuInfo.basic_info)
    219           this.setTable_('basic-info', gpuInfo.basic_info);
    220         else
    221           this.setTable_('basic-info', []);
    222 
    223         if (gpuInfo.performance_info) {
    224           performanceDiv.hidden = false;
    225           this.setTable_('performance-info', gpuInfo.performance_info);
    226         } else {
    227           performanceDiv.hidden = true;
    228         }
    229 
    230         if (gpuInfo.diagnostics) {
    231           diagnosticsDiv.hidden = false;
    232           diagnosticsLoadingDiv.hidden = true;
    233           $('diagnostics-table').hidden = false;
    234           this.setTable_('diagnostics-table', gpuInfo.diagnostics);
    235         } else if (gpuInfo.diagnostics === null) {
    236           // gpu_internals.cc sets diagnostics to null when it is being loaded
    237           diagnosticsDiv.hidden = false;
    238           diagnosticsLoadingDiv.hidden = false;
    239           $('diagnostics-table').hidden = true;
    240         } else {
    241           diagnosticsDiv.hidden = true;
    242         }
    243       } else {
    244         this.setText_('basic-info', '... loading ...');
    245         diagnosticsDiv.hidden = true;
    246         featureStatusList.textContent = '';
    247         problemsDiv.hidden = true;
    248       }
    249 
    250       // Log messages
    251       jstProcess(new JsEvalContext({values: browserBridge.logMessages}),
    252                  $('log-messages'));
    253     },
    254 
    255     createProblemEl_: function(problem) {
    256       var problemEl;
    257       problemEl = document.createElement('li');
    258 
    259       // Description of issue
    260       var desc = document.createElement('a');
    261       desc.textContent = problem.description;
    262       problemEl.appendChild(desc);
    263 
    264       // Spacing ':' element
    265       if (problem.crBugs.length + problem.webkitBugs.length > 0) {
    266         var tmp = document.createElement('span');
    267         tmp.textContent = ': ';
    268         problemEl.appendChild(tmp);
    269       }
    270 
    271       var nbugs = 0;
    272       var j;
    273 
    274       // crBugs
    275       for (j = 0; j < problem.crBugs.length; ++j) {
    276         if (nbugs > 0) {
    277           var tmp = document.createElement('span');
    278           tmp.textContent = ', ';
    279           problemEl.appendChild(tmp);
    280         }
    281 
    282         var link = document.createElement('a');
    283         var bugid = parseInt(problem.crBugs[j]);
    284         link.textContent = bugid;
    285         link.href = 'http://crbug.com/' + bugid;
    286         problemEl.appendChild(link);
    287         nbugs++;
    288       }
    289 
    290       for (j = 0; j < problem.webkitBugs.length; ++j) {
    291         if (nbugs > 0) {
    292           var tmp = document.createElement('span');
    293           tmp.textContent = ', ';
    294           problemEl.appendChild(tmp);
    295         }
    296 
    297         var link = document.createElement('a');
    298         var bugid = parseInt(problem.webkitBugs[j]);
    299         link.textContent = bugid;
    300 
    301         link.href = 'https://bugs.webkit.org/show_bug.cgi?id=' + bugid;
    302         problemEl.appendChild(link);
    303         nbugs++;
    304       }
    305 
    306       return problemEl;
    307     },
    308 
    309     setText_: function(outputElementId, text) {
    310       var peg = document.getElementById(outputElementId);
    311       peg.textContent = text;
    312     },
    313 
    314     setTable_: function(outputElementId, inputData) {
    315       var template = jstGetTemplate('info-view-table-template');
    316       jstProcess(new JsEvalContext({value: inputData}),
    317                  template);
    318 
    319       var peg = document.getElementById(outputElementId);
    320       if (!peg)
    321         throw new Error('Node ' + outputElementId + ' not found');
    322 
    323       peg.innerHTML = '';
    324       peg.appendChild(template);
    325     }
    326   };
    327 
    328   return {
    329     InfoView: InfoView
    330   };
    331 });
    332