• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */
11cr.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 commit id',
68            value: clientInfo.angle_commit_id
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        'gpu_compositing': 'Compositing',
86        'webgl': 'WebGL',
87        'multisampling': 'WebGL multisampling',
88        'flash_3d': 'Flash',
89        'flash_stage3d': 'Flash Stage3D',
90        'flash_stage3d_baseline': 'Flash Stage3D Baseline profile',
91        'texture_sharing': 'Texture Sharing',
92        'video_decode': 'Video Decode',
93        'video_encode': 'Video Encode',
94        'panel_fitting': 'Panel Fitting',
95        'rasterization': 'Rasterization',
96        'threaded_rasterization': 'Threaded Rasterization',
97        'multiple_raster_threads': 'Multiple Raster Threads',
98      };
99
100      var statusMap =  {
101        'disabled_software': {
102          'label': 'Software only. Hardware acceleration disabled',
103          'class': 'feature-yellow'
104        },
105        'disabled_off': {
106          'label': 'Disabled',
107          'class': 'feature-red'
108        },
109        'disabled_off_ok': {
110          'label': 'Disabled',
111          'class': 'feature-yellow'
112        },
113        'unavailable_software': {
114          'label': 'Software only, hardware acceleration unavailable',
115          'class': 'feature-yellow'
116        },
117        'unavailable_off': {
118          'label': 'Unavailable',
119          'class': 'feature-red'
120        },
121        'unavailable_off_ok': {
122          'label': 'Unavailable',
123          'class': 'feature-yellow'
124        },
125        'enabled_readback': {
126          'label': 'Hardware accelerated but at reduced performance',
127          'class': 'feature-yellow'
128        },
129        'enabled_force': {
130          'label': 'Hardware accelerated on all pages',
131          'class': 'feature-green'
132        },
133        'enabled': {
134          'label': 'Hardware accelerated',
135          'class': 'feature-green'
136        },
137        'enabled_on': {
138          'label': 'Enabled',
139          'class': 'feature-green'
140        },
141        'enabled_force_on': {
142          'label': 'Force enabled',
143          'class': 'feature-green'
144        },
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            var statusInfo = statusMap[featureStatus];
177            if (!statusInfo) {
178              console.log('Missing status for ', featureStatus);
179              statusEl.textContent = 'Unknown';
180              statusEl.className = 'feature-red';
181            } else {
182              statusEl.textContent = statusInfo['label'];
183              statusEl.className = statusInfo['class'];
184            }
185            featureEl.appendChild(statusEl);
186
187            featureStatusList.appendChild(featureEl);
188          }
189
190          // problems list
191          if (gpuInfo.featureStatus.problems.length) {
192            problemsDiv.hidden = false;
193            problemsList.textContent = '';
194            for (i = 0; i < gpuInfo.featureStatus.problems.length; i++) {
195              var problem = gpuInfo.featureStatus.problems[i];
196              var problemEl = this.createProblemEl_(problem);
197              problemsList.appendChild(problemEl);
198            }
199          } else {
200            problemsDiv.hidden = true;
201          }
202
203          // driver bug workarounds list
204          if (gpuInfo.featureStatus.workarounds.length) {
205            workaroundsDiv.hidden = false;
206            workaroundsList.textContent = '';
207            for (i = 0; i < gpuInfo.featureStatus.workarounds.length; i++) {
208              var workaroundEl = document.createElement('li');
209              workaroundEl.textContent = gpuInfo.featureStatus.workarounds[i];
210              workaroundsList.appendChild(workaroundEl);
211            }
212          } else {
213            workaroundsDiv.hidden = true;
214          }
215
216        } else {
217          featureStatusList.textContent = '';
218          problemsList.hidden = true;
219          workaroundsList.hidden = true;
220        }
221        if (gpuInfo.basic_info)
222          this.setTable_('basic-info', gpuInfo.basic_info);
223        else
224          this.setTable_('basic-info', []);
225
226        if (gpuInfo.performance_info) {
227          performanceDiv.hidden = false;
228          this.setTable_('performance-info', gpuInfo.performance_info);
229        } else {
230          performanceDiv.hidden = true;
231        }
232
233        if (gpuInfo.diagnostics) {
234          diagnosticsDiv.hidden = false;
235          diagnosticsLoadingDiv.hidden = true;
236          $('diagnostics-table').hidden = false;
237          this.setTable_('diagnostics-table', gpuInfo.diagnostics);
238        } else if (gpuInfo.diagnostics === null) {
239          // gpu_internals.cc sets diagnostics to null when it is being loaded
240          diagnosticsDiv.hidden = false;
241          diagnosticsLoadingDiv.hidden = false;
242          $('diagnostics-table').hidden = true;
243        } else {
244          diagnosticsDiv.hidden = true;
245        }
246      } else {
247        this.setText_('basic-info', '... loading ...');
248        diagnosticsDiv.hidden = true;
249        featureStatusList.textContent = '';
250        problemsDiv.hidden = true;
251      }
252
253      // Log messages
254      jstProcess(new JsEvalContext({values: browserBridge.logMessages}),
255                 $('log-messages'));
256    },
257
258    createProblemEl_: function(problem) {
259      var problemEl;
260      problemEl = document.createElement('li');
261
262      // Description of issue
263      var desc = document.createElement('a');
264      desc.textContent = problem.description;
265      problemEl.appendChild(desc);
266
267      // Spacing ':' element
268      if (problem.crBugs.length + problem.webkitBugs.length > 0) {
269        var tmp = document.createElement('span');
270        tmp.textContent = ': ';
271        problemEl.appendChild(tmp);
272      }
273
274      var nbugs = 0;
275      var j;
276
277      // crBugs
278      for (j = 0; j < problem.crBugs.length; ++j) {
279        if (nbugs > 0) {
280          var tmp = document.createElement('span');
281          tmp.textContent = ', ';
282          problemEl.appendChild(tmp);
283        }
284
285        var link = document.createElement('a');
286        var bugid = parseInt(problem.crBugs[j]);
287        link.textContent = bugid;
288        link.href = 'http://crbug.com/' + bugid;
289        problemEl.appendChild(link);
290        nbugs++;
291      }
292
293      for (j = 0; j < problem.webkitBugs.length; ++j) {
294        if (nbugs > 0) {
295          var tmp = document.createElement('span');
296          tmp.textContent = ', ';
297          problemEl.appendChild(tmp);
298        }
299
300        var link = document.createElement('a');
301        var bugid = parseInt(problem.webkitBugs[j]);
302        link.textContent = bugid;
303
304        link.href = 'https://bugs.webkit.org/show_bug.cgi?id=' + bugid;
305        problemEl.appendChild(link);
306        nbugs++;
307      }
308
309      if (problem.affectedGpuSettings.length > 0) {
310        var brNode = document.createElement('br');
311        problemEl.appendChild(brNode);
312
313        var iNode = document.createElement('i');
314        problemEl.appendChild(iNode);
315
316        var headNode = document.createElement('span');
317        if (problem.tag == 'disabledFeatures')
318          headNode.textContent = 'Disabled Features: ';
319        else  // problem.tag == 'workarounds'
320          headNode.textContent = 'Applied Workarounds: ';
321        iNode.appendChild(headNode);
322        for (j = 0; j < problem.affectedGpuSettings.length; ++j) {
323          if (j > 0) {
324            var separateNode = document.createElement('span');
325            separateNode.textContent = ', ';
326            iNode.appendChild(separateNode);
327          }
328          var nameNode = document.createElement('span');
329          if (problem.tag == 'disabledFeatures')
330            nameNode.classList.add('feature-red');
331          else  // problem.tag == 'workarounds'
332            nameNode.classList.add('feature-yellow');
333          nameNode.textContent = problem.affectedGpuSettings[j];
334          iNode.appendChild(nameNode);
335        }
336      }
337
338      return problemEl;
339    },
340
341    setText_: function(outputElementId, text) {
342      var peg = document.getElementById(outputElementId);
343      peg.textContent = text;
344    },
345
346    setTable_: function(outputElementId, inputData) {
347      var template = jstGetTemplate('info-view-table-template');
348      jstProcess(new JsEvalContext({value: inputData}),
349                 template);
350
351      var peg = document.getElementById(outputElementId);
352      if (!peg)
353        throw new Error('Node ' + outputElementId + ' not found');
354
355      peg.innerHTML = '';
356      peg.appendChild(template);
357    }
358  };
359
360  return {
361    InfoView: InfoView
362  };
363});
364