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.
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.
11 cr.define('gpu', function() {
13 * Provides information on the GPU process and underlying graphics hardware.
15 * @extends {cr.ui.TabPanel}
17 var InfoView = cr.ui.define(cr.ui.TabPanel);
19 InfoView.prototype = {
20 __proto__: cr.ui.TabPanel.prototype,
22 decorate: function() {
23 cr.ui.TabPanel.prototype.decorate.apply(this);
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));
34 * Updates the view based on its currently known data
36 refresh: function(data) {
38 if (browserBridge.clientInfo) {
39 var clientInfo = browserBridge.clientInfo;
41 var commandLineParts = clientInfo.command_line.split(' ');
42 commandLineParts.shift(); // Pop off the exe path
43 var commandLineString = commandLineParts.join(' ')
45 this.setTable_('client-info', [
47 description: 'Data exported',
48 value: (new Date()).toLocaleString()
51 description: 'Chrome version',
52 value: clientInfo.version
55 description: 'Operating system',
56 value: clientInfo.operating_system
59 description: 'Software rendering list version',
60 value: clientInfo.blacklist_version
63 description: 'Driver bug list version',
64 value: clientInfo.driver_bug_list_version
67 description: 'ANGLE commit id',
68 value: clientInfo.angle_commit_id
71 description: '2D graphics backend',
72 value: clientInfo.graphics_backend
75 description: 'Command Line Args',
76 value: commandLineString
79 this.setText_('client-info', '... loading...');
83 var featureLabelMap = {
84 '2d_canvas': 'Canvas',
85 'gpu_compositing': 'Compositing',
87 'multisampling': 'WebGL multisampling',
88 'flash_3d': 'Flash 3D',
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',
95 'gpu_switching': 'GPU Switching',
96 'panel_fitting': 'Panel Fitting',
97 'rasterization': 'Rasterization',
99 var statusLabelMap = {
100 'disabled_software': 'Software only. Hardware acceleration disabled.',
101 'disabled_software_animated': 'Software animated.',
102 'disabled_software_multithreaded': 'Software only, multi-threaded',
103 'disabled_off': 'Unavailable. Hardware acceleration disabled.',
104 'software': 'Software rendered. Hardware acceleration not enabled.',
105 'unavailable_off': 'Unavailable. Hardware acceleration unavailable',
106 'unavailable_software':
107 'Software only, hardware acceleration unavailable',
108 'unavailable_software_threaded':
109 'Software only and threaded. Hardware acceleration unavailable.',
110 'enabled_readback': 'Hardware accelerated, but at reduced performance',
111 'enabled_force': 'Hardware accelerated',
112 'enabled_threaded': 'Hardware accelerated and threaded.',
113 'enabled': 'Hardware accelerated',
114 'accelerated': 'Accelerated',
115 'accelerated_threaded': 'Accelerated and threaded',
117 'gpu_switching_automatic': 'Automatic switching',
118 'gpu_switching_force_discrete': 'Always on discrete GPU',
119 'gpu_switching_force_integrated': 'Always on integrated GPU',
122 var statusClassMap = {
123 'disabled_software': 'feature-yellow',
124 'disabled_software_animated': 'feature-yellow',
125 'disabled_software_multithreaded': 'feature-yellow',
126 'disabled_off': 'feature-red',
127 'software': 'feature-yellow',
128 'unavailable_off': 'feature-red',
129 'unavailable_software': 'feature-yellow',
130 'unavailable_software_threaded': 'feature-yellow',
131 'enabled_force': 'feature-green',
132 'enabled_readback': 'feature-yellow',
133 'enabled_threaded': 'feature-green',
134 'enabled': 'feature-green',
135 'accelerated': 'feature-green',
136 'accelerated_threaded': 'feature-green',
138 'gpu_switching_automatic': 'feature-green',
139 'gpu_switching_force_discrete': 'feature-red',
140 'gpu_switching_force_integrated': 'feature-red',
144 var diagnosticsDiv = this.querySelector('.diagnostics');
145 var diagnosticsLoadingDiv = this.querySelector('.diagnostics-loading');
146 var featureStatusList = this.querySelector('.feature-status-list');
147 var problemsDiv = this.querySelector('.problems-div');
148 var problemsList = this.querySelector('.problems-list');
149 var workaroundsDiv = this.querySelector('.workarounds-div');
150 var workaroundsList = this.querySelector('.workarounds-list');
151 var performanceDiv = this.querySelector('.performance-div');
152 var gpuInfo = browserBridge.gpuInfo;
155 // Not using jstemplate here for blacklist status because we construct
156 // href from data, which jstemplate can't seem to do.
157 if (gpuInfo.featureStatus) {
158 // feature status list
159 featureStatusList.textContent = '';
160 for (var featureName in gpuInfo.featureStatus.featureStatus) {
162 gpuInfo.featureStatus.featureStatus[featureName];
163 var featureEl = document.createElement('li');
165 var nameEl = document.createElement('span');
166 if (!featureLabelMap[featureName])
167 console.log('Missing featureLabel for', featureName);
168 nameEl.textContent = featureLabelMap[featureName] + ': ';
169 featureEl.appendChild(nameEl);
171 var statusEl = document.createElement('span');
172 if (!statusLabelMap[featureStatus])
173 console.log('Missing statusLabel for', featureStatus);
174 if (!statusClassMap[featureStatus])
175 console.log('Missing statusClass for', featureStatus);
176 statusEl.textContent = statusLabelMap[featureStatus];
177 statusEl.className = statusClassMap[featureStatus];
178 featureEl.appendChild(statusEl);
180 featureStatusList.appendChild(featureEl);
184 if (gpuInfo.featureStatus.problems.length) {
185 problemsDiv.hidden = false;
186 problemsList.textContent = '';
187 for (i = 0; i < gpuInfo.featureStatus.problems.length; i++) {
188 var problem = gpuInfo.featureStatus.problems[i];
189 var problemEl = this.createProblemEl_(problem);
190 problemsList.appendChild(problemEl);
193 problemsDiv.hidden = true;
196 // driver bug workarounds list
197 if (gpuInfo.featureStatus.workarounds.length) {
198 workaroundsDiv.hidden = false;
199 workaroundsList.textContent = '';
200 for (i = 0; i < gpuInfo.featureStatus.workarounds.length; i++) {
201 var workaroundEl = document.createElement('li');
202 workaroundEl.textContent = gpuInfo.featureStatus.workarounds[i];
203 workaroundsList.appendChild(workaroundEl);
206 workaroundsDiv.hidden = true;
210 featureStatusList.textContent = '';
211 problemsList.hidden = true;
212 workaroundsList.hidden = true;
214 if (gpuInfo.basic_info)
215 this.setTable_('basic-info', gpuInfo.basic_info);
217 this.setTable_('basic-info', []);
219 if (gpuInfo.performance_info) {
220 performanceDiv.hidden = false;
221 this.setTable_('performance-info', gpuInfo.performance_info);
223 performanceDiv.hidden = true;
226 if (gpuInfo.diagnostics) {
227 diagnosticsDiv.hidden = false;
228 diagnosticsLoadingDiv.hidden = true;
229 $('diagnostics-table').hidden = false;
230 this.setTable_('diagnostics-table', gpuInfo.diagnostics);
231 } else if (gpuInfo.diagnostics === null) {
232 // gpu_internals.cc sets diagnostics to null when it is being loaded
233 diagnosticsDiv.hidden = false;
234 diagnosticsLoadingDiv.hidden = false;
235 $('diagnostics-table').hidden = true;
237 diagnosticsDiv.hidden = true;
240 this.setText_('basic-info', '... loading ...');
241 diagnosticsDiv.hidden = true;
242 featureStatusList.textContent = '';
243 problemsDiv.hidden = true;
247 jstProcess(new JsEvalContext({values: browserBridge.logMessages}),
251 createProblemEl_: function(problem) {
253 problemEl = document.createElement('li');
255 // Description of issue
256 var desc = document.createElement('a');
257 desc.textContent = problem.description;
258 problemEl.appendChild(desc);
260 // Spacing ':' element
261 if (problem.crBugs.length + problem.webkitBugs.length > 0) {
262 var tmp = document.createElement('span');
263 tmp.textContent = ': ';
264 problemEl.appendChild(tmp);
271 for (j = 0; j < problem.crBugs.length; ++j) {
273 var tmp = document.createElement('span');
274 tmp.textContent = ', ';
275 problemEl.appendChild(tmp);
278 var link = document.createElement('a');
279 var bugid = parseInt(problem.crBugs[j]);
280 link.textContent = bugid;
281 link.href = 'http://crbug.com/' + bugid;
282 problemEl.appendChild(link);
286 for (j = 0; j < problem.webkitBugs.length; ++j) {
288 var tmp = document.createElement('span');
289 tmp.textContent = ', ';
290 problemEl.appendChild(tmp);
293 var link = document.createElement('a');
294 var bugid = parseInt(problem.webkitBugs[j]);
295 link.textContent = bugid;
297 link.href = 'https://bugs.webkit.org/show_bug.cgi?id=' + bugid;
298 problemEl.appendChild(link);
302 if (problem.affectedGpuSettings.length > 0) {
303 var brNode = document.createElement('br');
304 problemEl.appendChild(brNode);
306 var iNode = document.createElement('i');
307 problemEl.appendChild(iNode);
309 var headNode = document.createElement('span');
310 if (problem.tag == 'disabledFeatures')
311 headNode.textContent = 'Disabled Features: ';
312 else // problem.tag == 'workarounds'
313 headNode.textContent = 'Applied Workarounds: ';
314 iNode.appendChild(headNode);
315 for (j = 0; j < problem.affectedGpuSettings.length; ++j) {
317 var separateNode = document.createElement('span');
318 separateNode.textContent = ', ';
319 iNode.appendChild(separateNode);
321 var nameNode = document.createElement('span');
322 if (problem.tag == 'disabledFeatures')
323 nameNode.classList.add('feature-red');
324 else // problem.tag == 'workarounds'
325 nameNode.classList.add('feature-yellow');
326 nameNode.textContent = problem.affectedGpuSettings[j];
327 iNode.appendChild(nameNode);
334 setText_: function(outputElementId, text) {
335 var peg = document.getElementById(outputElementId);
336 peg.textContent = text;
339 setTable_: function(outputElementId, inputData) {
340 var template = jstGetTemplate('info-view-table-template');
341 jstProcess(new JsEvalContext({value: inputData}),
344 var peg = document.getElementById(outputElementId);
346 throw new Error('Node ' + outputElementId + ' not found');
349 peg.appendChild(template);