1 // Copyright (c) 2011 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 {Tab} 16 */ 17 var InfoView = cr.ui.define(gpu.Tab); 18 19 InfoView.prototype = { 20 __proto__: gpu.Tab.prototype, 21 22 decorate: function() { 23 gpu.Tab.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 var chromeVersion = clientInfo.version + 41 ' (' + clientInfo.official + 42 ' ' + clientInfo.cl + 43 ') ' + clientInfo.version_mod; 44 this.setTable_('client-info', [ 45 { 46 description: 'Data exported', 47 value: (new Date()).toLocaleString() 48 }, 49 { 50 description: 'Chrome version', 51 value: chromeVersion 52 }, 53 { 54 description: 'Software rendering list version', 55 value: clientInfo.blacklist_version 56 }]); 57 } else { 58 this.setText_('client-info', '... loading...'); 59 } 60 61 // Feature map 62 var featureLabelMap = { 63 '2d_canvas': 'Canvas', 64 '3d_css': '3D CSS', 65 'compositing': 'Compositing', 66 'webgl': 'WebGL', 67 'multisampling': 'WebGL multisampling' 68 }; 69 var statusLabelMap = { 70 'disabled_software': 'Software only. Hardware acceleration disabled.', 71 'disabled_off': 'Unavailable. Hardware acceleration disabled.', 72 'software': 'Software rendered. Hardware acceleration not enabled.', 73 'unavailable_off': 'Unavailable. Hardware acceleration unavailable', 74 'unavailable_software': 75 'Software only, hardware acceleration unavailable', 76 'enabled': 'Hardware accelerated' 77 }; 78 var statusClassMap = { 79 'disabled_software': 'feature-yellow', 80 'disabled_off': 'feature-red', 81 'software': 'feature-yellow', 82 'unavailable_off': 'feature-red', 83 'unavailable_software': 'feature-yellow', 84 'enabled': 'feature-green' 85 }; 86 87 // GPU info, basic 88 var diagnosticsDiv = this.querySelector('.diagnostics'); 89 var diagnosticsLoadingDiv = this.querySelector('.diagnostics-loading'); 90 var featureStatusList = this.querySelector('.feature-status-list'); 91 var problemsDiv = this.querySelector('.problems-div'); 92 var problemsList = this.querySelector('.problems-list'); 93 var gpuInfo = browserBridge.gpuInfo; 94 var i; 95 if (gpuInfo) { 96 // Not using jstemplate here for blacklist status because we construct 97 // href from data, which jstemplate can't seem to do. 98 if (gpuInfo.featureStatus) { 99 // feature status list 100 featureStatusList.textContent = ''; 101 for (i = 0; i < gpuInfo.featureStatus.featureStatus.length; 102 i++) { 103 var feature = gpuInfo.featureStatus.featureStatus[i]; 104 var featureEl = document.createElement('li'); 105 106 var nameEl = document.createElement('span'); 107 if (!featureLabelMap[feature.name]) 108 console.log('Missing featureLabel for', feature.name); 109 nameEl.textContent = featureLabelMap[feature.name] + ': '; 110 featureEl.appendChild(nameEl); 111 112 var statusEl = document.createElement('span'); 113 if (!statusLabelMap[feature.status]) 114 console.log('Missing statusLabel for', feature.status); 115 if (!statusClassMap[feature.status]) 116 console.log('Missing statusClass for', feature.status); 117 statusEl.textContent = statusLabelMap[feature.status]; 118 statusEl.className = statusClassMap[feature.status]; 119 featureEl.appendChild(statusEl); 120 121 featureStatusList.appendChild(featureEl); 122 } 123 124 // problems list 125 if (gpuInfo.featureStatus.problems.length) { 126 problemsDiv.hidden = false; 127 problemsList.textContent = ''; 128 for (i = 0; i < gpuInfo.featureStatus.problems.length; i++) { 129 var problem = gpuInfo.featureStatus.problems[i]; 130 var problemEl = this.createProblemEl_(problem); 131 problemsList.appendChild(problemEl); 132 } 133 } else { 134 problemsDiv.hidden = true; 135 } 136 137 } else { 138 featureStatusList.textContent = ''; 139 problemsList.hidden = true; 140 } 141 if (gpuInfo.basic_info) 142 this.setTable_('basic-info', gpuInfo.basic_info); 143 else 144 this.setTable_('basic-info', []); 145 146 if (gpuInfo.diagnostics) { 147 diagnosticsDiv.hidden = false; 148 diagnosticsLoadingDiv.hidden = true; 149 $('diagnostics-table').hidden = false; 150 this.setTable_('diagnostics-table', gpuInfo.diagnostics); 151 this.querySelector('diagnostics-status').hidden = true; 152 } else if (gpuInfo.diagnostics === null) { 153 // gpu_internals.cc sets diagnostics to null when it is being loaded 154 diagnosticsDiv.hidden = false; 155 diagnosticsLoadingDiv.hidden = false; 156 $('diagnostics-table').hidden = true; 157 } else { 158 diagnosticsDiv.hidden = true; 159 } 160 } else { 161 this.setText_('basic-info', '... loading ...'); 162 diagnosticsDiv.hidden = true; 163 featureStatusList.textContent = ''; 164 problemsDiv.hidden = true; 165 } 166 167 // Log messages 168 jstProcess(new JsEvalContext({values: browserBridge.logMessages}), 169 document.getElementById('log-messages')); 170 }, 171 172 createProblemEl_: function(problem) { 173 var problemEl; 174 problemEl = document.createElement('li'); 175 176 // Description of issue 177 var desc = document.createElement('a'); 178 desc.textContent = problem.description; 179 problemEl.appendChild(desc); 180 181 // Spacing ':' element 182 if (problem.crBugs.length + problem.webkitBugs.length > 0) { 183 var tmp = document.createElement('span'); 184 tmp.textContent = ': '; 185 problemEl.appendChild(tmp); 186 } 187 188 var nbugs = 0; 189 var j; 190 191 // crBugs 192 for (j = 0; j < problem.crBugs.length; ++j) { 193 if (nbugs > 0) { 194 var tmp = document.createElement('span'); 195 tmp.textContent = ', '; 196 problemEl.appendChild(tmp); 197 } 198 199 var link = document.createElement('a'); 200 var bugid = parseInt(problem.crBugs[j]); 201 link.textContent = bugid; 202 link.href = 'http://crbug.com/' + bugid; 203 problemEl.appendChild(link); 204 nbugs++; 205 } 206 207 for (j = 0; j < problem.webkitBugs.length; ++j) { 208 if (nbugs > 0) { 209 var tmp = document.createElement('span'); 210 tmp.textContent = ', '; 211 problemEl.appendChild(tmp); 212 } 213 214 var link = document.createElement('a'); 215 var bugid = parseInt(problem.webkitBugs[j]); 216 link.textContent = bugid; 217 218 link.href = 'https://bugs.webkit.org/show_bug.cgi?id=' + bugid; 219 problemEl.appendChild(link); 220 nbugs++; 221 } 222 223 return problemEl; 224 }, 225 226 setText_: function(outputElementId, text) { 227 var peg = document.getElementById(outputElementId); 228 peg.innerText = text; 229 }, 230 231 setTable_: function(outputElementId, inputData) { 232 var template = jstGetTemplate('info-view-table-template'); 233 jstProcess(new JsEvalContext({value: inputData}), 234 template); 235 236 var peg = document.getElementById(outputElementId); 237 if (!peg) 238 throw new Error('Node ' + outputElementId + ' not found'); 239 240 peg.innerHTML = ''; 241 peg.appendChild(template); 242 } 243 }; 244 245 return { 246 InfoView: InfoView 247 }; 248 }); 249