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