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