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 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 }; 98 99 var statusMap = { 100 'disabled_software': { 101 'label': 'Software only. Hardware acceleration disabled', 102 'class': 'feature-yellow' 103 }, 104 'disabled_software_threaded': { 105 'label': 'Software only, threaded. Hardware acceleration disabled', 106 'class': 'feature-yellow' 107 }, 108 'disabled_off': { 109 'label': 'Disabled', 110 'class': 'feature-red' 111 }, 112 'disabled_off_ok': { 113 'label': 'Disabled', 114 'class': 'feature-yellow' 115 }, 116 'unavailable_software': { 117 'label': 'Software only, hardware acceleration unavailable', 118 'class': 'feature-yellow' 119 }, 120 'unavailable_software_threaded': { 121 'label': 'Software only, threaded. Hardware acceleration unavailable', 122 'class': 'feature-yellow' 123 }, 124 'unavailable_off': { 125 'label': 'Unavailable', 126 'class': 'feature-red' 127 }, 128 'unavailable_off_ok': { 129 'label': 'Unavailable', 130 'class': 'feature-yellow' 131 }, 132 'enabled_readback': { 133 'label': 'Hardware accelerated but at reduced performance', 134 'class': 'feature-yellow' 135 }, 136 'enabled_force': { 137 'label': 'Hardware accelerated on all pages', 138 'class': 'feature-green' 139 }, 140 'enabled_threaded': { 141 'label': 'Hardware accelerated and threaded', 142 'class': 'feature-green' 143 }, 144 'enabled': { 145 'label': 'Hardware accelerated', 146 'class': 'feature-green' 147 }, 148 'enabled_on': { 149 'label': 'Enabled', 150 'class': 'feature-green' 151 } 152 }; 153 154 // GPU info, basic 155 var diagnosticsDiv = this.querySelector('.diagnostics'); 156 var diagnosticsLoadingDiv = this.querySelector('.diagnostics-loading'); 157 var featureStatusList = this.querySelector('.feature-status-list'); 158 var problemsDiv = this.querySelector('.problems-div'); 159 var problemsList = this.querySelector('.problems-list'); 160 var workaroundsDiv = this.querySelector('.workarounds-div'); 161 var workaroundsList = this.querySelector('.workarounds-list'); 162 var performanceDiv = this.querySelector('.performance-div'); 163 var gpuInfo = browserBridge.gpuInfo; 164 var i; 165 if (gpuInfo) { 166 // Not using jstemplate here for blacklist status because we construct 167 // href from data, which jstemplate can't seem to do. 168 if (gpuInfo.featureStatus) { 169 // feature status list 170 featureStatusList.textContent = ''; 171 for (var featureName in gpuInfo.featureStatus.featureStatus) { 172 var featureStatus = 173 gpuInfo.featureStatus.featureStatus[featureName]; 174 var featureEl = document.createElement('li'); 175 176 var nameEl = document.createElement('span'); 177 if (!featureLabelMap[featureName]) 178 console.log('Missing featureLabel for', featureName); 179 nameEl.textContent = featureLabelMap[featureName] + ': '; 180 featureEl.appendChild(nameEl); 181 182 var statusEl = document.createElement('span'); 183 var statusInfo = statusMap[featureStatus]; 184 if (!statusInfo) { 185 console.log('Missing status for ', featureStatus); 186 statusEl.textContent = 'Unknown'; 187 statusEl.className = 'feature-red'; 188 } else { 189 statusEl.textContent = statusInfo['label']; 190 statusEl.className = statusInfo['class']; 191 } 192 featureEl.appendChild(statusEl); 193 194 featureStatusList.appendChild(featureEl); 195 } 196 197 // problems list 198 if (gpuInfo.featureStatus.problems.length) { 199 problemsDiv.hidden = false; 200 problemsList.textContent = ''; 201 for (i = 0; i < gpuInfo.featureStatus.problems.length; i++) { 202 var problem = gpuInfo.featureStatus.problems[i]; 203 var problemEl = this.createProblemEl_(problem); 204 problemsList.appendChild(problemEl); 205 } 206 } else { 207 problemsDiv.hidden = true; 208 } 209 210 // driver bug workarounds list 211 if (gpuInfo.featureStatus.workarounds.length) { 212 workaroundsDiv.hidden = false; 213 workaroundsList.textContent = ''; 214 for (i = 0; i < gpuInfo.featureStatus.workarounds.length; i++) { 215 var workaroundEl = document.createElement('li'); 216 workaroundEl.textContent = gpuInfo.featureStatus.workarounds[i]; 217 workaroundsList.appendChild(workaroundEl); 218 } 219 } else { 220 workaroundsDiv.hidden = true; 221 } 222 223 } else { 224 featureStatusList.textContent = ''; 225 problemsList.hidden = true; 226 workaroundsList.hidden = true; 227 } 228 if (gpuInfo.basic_info) 229 this.setTable_('basic-info', gpuInfo.basic_info); 230 else 231 this.setTable_('basic-info', []); 232 233 if (gpuInfo.performance_info) { 234 performanceDiv.hidden = false; 235 this.setTable_('performance-info', gpuInfo.performance_info); 236 } else { 237 performanceDiv.hidden = true; 238 } 239 240 if (gpuInfo.diagnostics) { 241 diagnosticsDiv.hidden = false; 242 diagnosticsLoadingDiv.hidden = true; 243 $('diagnostics-table').hidden = false; 244 this.setTable_('diagnostics-table', gpuInfo.diagnostics); 245 } else if (gpuInfo.diagnostics === null) { 246 // gpu_internals.cc sets diagnostics to null when it is being loaded 247 diagnosticsDiv.hidden = false; 248 diagnosticsLoadingDiv.hidden = false; 249 $('diagnostics-table').hidden = true; 250 } else { 251 diagnosticsDiv.hidden = true; 252 } 253 } else { 254 this.setText_('basic-info', '... loading ...'); 255 diagnosticsDiv.hidden = true; 256 featureStatusList.textContent = ''; 257 problemsDiv.hidden = true; 258 } 259 260 // Log messages 261 jstProcess(new JsEvalContext({values: browserBridge.logMessages}), 262 $('log-messages')); 263 }, 264 265 createProblemEl_: function(problem) { 266 var problemEl; 267 problemEl = document.createElement('li'); 268 269 // Description of issue 270 var desc = document.createElement('a'); 271 desc.textContent = problem.description; 272 problemEl.appendChild(desc); 273 274 // Spacing ':' element 275 if (problem.crBugs.length + problem.webkitBugs.length > 0) { 276 var tmp = document.createElement('span'); 277 tmp.textContent = ': '; 278 problemEl.appendChild(tmp); 279 } 280 281 var nbugs = 0; 282 var j; 283 284 // crBugs 285 for (j = 0; j < problem.crBugs.length; ++j) { 286 if (nbugs > 0) { 287 var tmp = document.createElement('span'); 288 tmp.textContent = ', '; 289 problemEl.appendChild(tmp); 290 } 291 292 var link = document.createElement('a'); 293 var bugid = parseInt(problem.crBugs[j]); 294 link.textContent = bugid; 295 link.href = 'http://crbug.com/' + bugid; 296 problemEl.appendChild(link); 297 nbugs++; 298 } 299 300 for (j = 0; j < problem.webkitBugs.length; ++j) { 301 if (nbugs > 0) { 302 var tmp = document.createElement('span'); 303 tmp.textContent = ', '; 304 problemEl.appendChild(tmp); 305 } 306 307 var link = document.createElement('a'); 308 var bugid = parseInt(problem.webkitBugs[j]); 309 link.textContent = bugid; 310 311 link.href = 'https://bugs.webkit.org/show_bug.cgi?id=' + bugid; 312 problemEl.appendChild(link); 313 nbugs++; 314 } 315 316 if (problem.affectedGpuSettings.length > 0) { 317 var brNode = document.createElement('br'); 318 problemEl.appendChild(brNode); 319 320 var iNode = document.createElement('i'); 321 problemEl.appendChild(iNode); 322 323 var headNode = document.createElement('span'); 324 if (problem.tag == 'disabledFeatures') 325 headNode.textContent = 'Disabled Features: '; 326 else // problem.tag == 'workarounds' 327 headNode.textContent = 'Applied Workarounds: '; 328 iNode.appendChild(headNode); 329 for (j = 0; j < problem.affectedGpuSettings.length; ++j) { 330 if (j > 0) { 331 var separateNode = document.createElement('span'); 332 separateNode.textContent = ', '; 333 iNode.appendChild(separateNode); 334 } 335 var nameNode = document.createElement('span'); 336 if (problem.tag == 'disabledFeatures') 337 nameNode.classList.add('feature-red'); 338 else // problem.tag == 'workarounds' 339 nameNode.classList.add('feature-yellow'); 340 nameNode.textContent = problem.affectedGpuSettings[j]; 341 iNode.appendChild(nameNode); 342 } 343 } 344 345 return problemEl; 346 }, 347 348 setText_: function(outputElementId, text) { 349 var peg = document.getElementById(outputElementId); 350 peg.textContent = text; 351 }, 352 353 setTable_: function(outputElementId, inputData) { 354 var template = jstGetTemplate('info-view-table-template'); 355 jstProcess(new JsEvalContext({value: inputData}), 356 template); 357 358 var peg = document.getElementById(outputElementId); 359 if (!peg) 360 throw new Error('Node ' + outputElementId + ' not found'); 361 362 peg.innerHTML = ''; 363 peg.appendChild(template); 364 } 365 }; 366 367 return { 368 InfoView: InfoView 369 }; 370 }); 371