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 #include "content/browser/gpu/compositor_util.h" 6 7 #include "base/command_line.h" 8 #include "base/logging.h" 9 #include "base/metrics/field_trial.h" 10 #include "build/build_config.h" 11 #include "cc/base/switches.h" 12 #include "content/browser/gpu/gpu_data_manager_impl.h" 13 #include "content/public/common/content_switches.h" 14 #include "gpu/config/gpu_feature_type.h" 15 16 namespace content { 17 18 namespace { 19 20 static bool IsGpuRasterizationBlacklisted() { 21 GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance(); 22 bool field_trial_enabled = 23 (base::FieldTrialList::FindFullName( 24 "GpuRasterizationExpandedDeviceWhitelist") == "Enabled"); 25 26 if (field_trial_enabled) { 27 return manager->IsFeatureBlacklisted( 28 gpu::GPU_FEATURE_TYPE_GPU_RASTERIZATION) && 29 manager->IsFeatureBlacklisted( 30 gpu::GPU_FEATURE_TYPE_GPU_RASTERIZATION_FIELD_TRIAL); 31 } 32 33 return manager->IsFeatureBlacklisted( 34 gpu::GPU_FEATURE_TYPE_GPU_RASTERIZATION); 35 } 36 37 const char* kGpuCompositingFeatureName = "gpu_compositing"; 38 const char* kWebGLFeatureName = "webgl"; 39 const char* kRasterizationFeatureName = "rasterization"; 40 const char* kThreadedRasterizationFeatureName = "threaded_rasterization"; 41 42 struct GpuFeatureInfo { 43 std::string name; 44 bool blocked; 45 bool disabled; 46 std::string disabled_description; 47 bool fallback_to_software; 48 }; 49 50 const GpuFeatureInfo GetGpuFeatureInfo(size_t index, bool* eof) { 51 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 52 GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance(); 53 54 const GpuFeatureInfo kGpuFeatureInfo[] = { 55 { 56 "2d_canvas", 57 manager->IsFeatureBlacklisted( 58 gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS), 59 command_line.HasSwitch(switches::kDisableAccelerated2dCanvas) || 60 !GpuDataManagerImpl::GetInstance()-> 61 GetGPUInfo().SupportsAccelerated2dCanvas(), 62 "Accelerated 2D canvas is unavailable: either disabled at the command" 63 " line or not supported by the current system.", 64 true 65 }, 66 { 67 kGpuCompositingFeatureName, 68 manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING), 69 false, 70 "Gpu compositing has been disabled, either via about:flags or" 71 " command line. The browser will fall back to software compositing" 72 " and hardware acceleration will be unavailable.", 73 true 74 }, 75 { 76 kWebGLFeatureName, 77 manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL), 78 command_line.HasSwitch(switches::kDisableExperimentalWebGL), 79 "WebGL has been disabled, either via about:flags or command line.", 80 false 81 }, 82 { 83 "flash_3d", 84 manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH3D), 85 command_line.HasSwitch(switches::kDisableFlash3d), 86 "Using 3d in flash has been disabled, either via about:flags or" 87 " command line.", 88 true 89 }, 90 { 91 "flash_stage3d", 92 manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D), 93 command_line.HasSwitch(switches::kDisableFlashStage3d), 94 "Using Stage3d in Flash has been disabled, either via about:flags or" 95 " command line.", 96 true 97 }, 98 { 99 "flash_stage3d_baseline", 100 manager->IsFeatureBlacklisted( 101 gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE) || 102 manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D), 103 command_line.HasSwitch(switches::kDisableFlashStage3d), 104 "Using Stage3d Baseline profile in Flash has been disabled, either" 105 " via about:flags or command line.", 106 true 107 }, 108 { 109 "video_decode", 110 manager->IsFeatureBlacklisted( 111 gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE), 112 command_line.HasSwitch(switches::kDisableAcceleratedVideoDecode), 113 "Accelerated video decode has been disabled, either via about:flags" 114 " or command line.", 115 true 116 }, 117 #if defined(ENABLE_WEBRTC) 118 { 119 "video_encode", 120 manager->IsFeatureBlacklisted( 121 gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_ENCODE), 122 command_line.HasSwitch(switches::kDisableWebRtcHWEncoding), 123 "Accelerated video encode has been disabled, either via about:flags" 124 " or command line.", 125 true 126 }, 127 #endif 128 #if defined(OS_CHROMEOS) 129 { 130 "panel_fitting", 131 manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_PANEL_FITTING), 132 command_line.HasSwitch(switches::kDisablePanelFitting), 133 "Panel fitting has been disabled, either via about:flags or command" 134 " line.", 135 false 136 }, 137 #endif 138 { 139 kRasterizationFeatureName, 140 IsGpuRasterizationBlacklisted() && 141 !IsGpuRasterizationEnabled() && !IsForceGpuRasterizationEnabled(), 142 !IsGpuRasterizationEnabled() && !IsForceGpuRasterizationEnabled() && 143 !IsGpuRasterizationBlacklisted(), 144 "Accelerated rasterization has been disabled, either via about:flags" 145 " or command line.", 146 true 147 }, 148 { 149 kThreadedRasterizationFeatureName, 150 false, 151 !IsImplSidePaintingEnabled(), 152 "Threaded rasterization has not been enabled or" 153 " is not supported by the current system.", 154 false 155 } 156 157 }; 158 DCHECK(index < arraysize(kGpuFeatureInfo)); 159 *eof = (index == arraysize(kGpuFeatureInfo) - 1); 160 return kGpuFeatureInfo[index]; 161 } 162 163 } // namespace 164 165 bool IsPinchVirtualViewportEnabled() { 166 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 167 168 // Command line switches take precedence over platform default. 169 if (command_line.HasSwitch(cc::switches::kDisablePinchVirtualViewport)) 170 return false; 171 if (command_line.HasSwitch(cc::switches::kEnablePinchVirtualViewport)) 172 return true; 173 174 #if defined(OS_CHROMEOS) 175 return true; 176 #else 177 return false; 178 #endif 179 } 180 181 bool IsThreadedCompositingEnabled() { 182 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 183 184 // Command line switches take precedence over blacklist. 185 if (command_line.HasSwitch(switches::kDisableThreadedCompositing)) 186 return false; 187 if (command_line.HasSwitch(switches::kEnableThreadedCompositing)) 188 return true; 189 190 #if defined(USE_AURA) || defined(OS_MACOSX) 191 // We always want threaded compositing on Aura and Mac (the fallback is a 192 // threaded software compositor). 193 return true; 194 #else 195 return false; 196 #endif 197 } 198 199 bool IsDelegatedRendererEnabled() { 200 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 201 bool enabled = false; 202 203 #if defined(USE_AURA) 204 // Enable on Aura. 205 enabled = true; 206 #endif 207 208 // Flags override. 209 enabled |= command_line.HasSwitch(switches::kEnableDelegatedRenderer); 210 enabled &= !command_line.HasSwitch(switches::kDisableDelegatedRenderer); 211 212 // Needs compositing, and thread. 213 if (enabled && !IsThreadedCompositingEnabled()) { 214 enabled = false; 215 LOG(ERROR) << "Disabling delegated-rendering because it needs " 216 << "force-compositing-mode and threaded-compositing."; 217 } 218 219 return enabled; 220 } 221 222 bool IsImplSidePaintingEnabled() { 223 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 224 225 if (command_line.HasSwitch(switches::kDisableImplSidePainting)) 226 return false; 227 else if (command_line.HasSwitch(switches::kEnableImplSidePainting)) 228 return true; 229 else if (command_line.HasSwitch( 230 switches::kEnableBleedingEdgeRenderingFastPaths)) 231 return true; 232 233 #if defined(OS_MACOSX) || defined(OS_WIN) 234 return false; 235 #else 236 return IsThreadedCompositingEnabled(); 237 #endif 238 } 239 240 bool IsGpuRasterizationEnabled() { 241 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 242 243 if (!IsImplSidePaintingEnabled()) 244 return false; 245 246 if (command_line.HasSwitch(switches::kDisableGpuRasterization)) 247 return false; 248 else if (command_line.HasSwitch(switches::kEnableGpuRasterization)) 249 return true; 250 251 if (IsGpuRasterizationBlacklisted()) { 252 return false; 253 } 254 255 return true; 256 } 257 258 bool IsForceGpuRasterizationEnabled() { 259 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 260 261 if (!IsImplSidePaintingEnabled()) 262 return false; 263 264 return command_line.HasSwitch(switches::kForceGpuRasterization); 265 } 266 267 base::Value* GetFeatureStatus() { 268 GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance(); 269 std::string gpu_access_blocked_reason; 270 bool gpu_access_blocked = 271 !manager->GpuAccessAllowed(&gpu_access_blocked_reason); 272 273 base::DictionaryValue* feature_status_dict = new base::DictionaryValue(); 274 275 bool eof = false; 276 for (size_t i = 0; !eof; ++i) { 277 const GpuFeatureInfo gpu_feature_info = GetGpuFeatureInfo(i, &eof); 278 std::string status; 279 if (gpu_feature_info.disabled) { 280 status = "disabled"; 281 if (gpu_feature_info.fallback_to_software) 282 status += "_software"; 283 else 284 status += "_off"; 285 if (gpu_feature_info.name == kThreadedRasterizationFeatureName) 286 status += "_ok"; 287 } else if (gpu_feature_info.blocked || 288 gpu_access_blocked) { 289 status = "unavailable"; 290 if (gpu_feature_info.fallback_to_software) { 291 status += "_software"; 292 } else 293 status += "_off"; 294 } else { 295 status = "enabled"; 296 if (gpu_feature_info.name == kWebGLFeatureName && 297 manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING)) 298 status += "_readback"; 299 if (gpu_feature_info.name == kRasterizationFeatureName) { 300 if (IsForceGpuRasterizationEnabled()) 301 status += "_force"; 302 } 303 if (gpu_feature_info.name == kThreadedRasterizationFeatureName) 304 status += "_on"; 305 } 306 if (gpu_feature_info.name == kGpuCompositingFeatureName) { 307 if (IsThreadedCompositingEnabled()) 308 status += "_threaded"; 309 } 310 if (gpu_feature_info.name == kWebGLFeatureName && 311 (gpu_feature_info.blocked || gpu_access_blocked) && 312 manager->ShouldUseSwiftShader()) { 313 status = "unavailable_software"; 314 } 315 316 feature_status_dict->SetString( 317 gpu_feature_info.name.c_str(), status.c_str()); 318 } 319 return feature_status_dict; 320 } 321 322 base::Value* GetProblems() { 323 GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance(); 324 std::string gpu_access_blocked_reason; 325 bool gpu_access_blocked = 326 !manager->GpuAccessAllowed(&gpu_access_blocked_reason); 327 328 base::ListValue* problem_list = new base::ListValue(); 329 manager->GetBlacklistReasons(problem_list); 330 331 if (gpu_access_blocked) { 332 base::DictionaryValue* problem = new base::DictionaryValue(); 333 problem->SetString("description", 334 "GPU process was unable to boot: " + gpu_access_blocked_reason); 335 problem->Set("crBugs", new base::ListValue()); 336 problem->Set("webkitBugs", new base::ListValue()); 337 base::ListValue* disabled_features = new base::ListValue(); 338 disabled_features->AppendString("all"); 339 problem->Set("affectedGpuSettings", disabled_features); 340 problem->SetString("tag", "disabledFeatures"); 341 problem_list->Insert(0, problem); 342 } 343 344 bool eof = false; 345 for (size_t i = 0; !eof; ++i) { 346 const GpuFeatureInfo gpu_feature_info = GetGpuFeatureInfo(i, &eof); 347 if (gpu_feature_info.disabled) { 348 base::DictionaryValue* problem = new base::DictionaryValue(); 349 problem->SetString( 350 "description", gpu_feature_info.disabled_description); 351 problem->Set("crBugs", new base::ListValue()); 352 problem->Set("webkitBugs", new base::ListValue()); 353 base::ListValue* disabled_features = new base::ListValue(); 354 disabled_features->AppendString(gpu_feature_info.name); 355 problem->Set("affectedGpuSettings", disabled_features); 356 problem->SetString("tag", "disabledFeatures"); 357 problem_list->Append(problem); 358 } 359 } 360 return problem_list; 361 } 362 363 base::Value* GetDriverBugWorkarounds() { 364 base::ListValue* workaround_list = new base::ListValue(); 365 GpuDataManagerImpl::GetInstance()->GetDriverBugWorkarounds(workaround_list); 366 return workaround_list; 367 } 368 369 } // namespace content 370