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 17namespace content { 18 19namespace { 20 21static bool IsGpuRasterizationBlacklisted() { 22 GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance(); 23 return manager->IsFeatureBlacklisted( 24 gpu::GPU_FEATURE_TYPE_GPU_RASTERIZATION); 25} 26 27const char* kGpuCompositingFeatureName = "gpu_compositing"; 28const char* kWebGLFeatureName = "webgl"; 29const char* kRasterizationFeatureName = "rasterization"; 30const char* kThreadedRasterizationFeatureName = "threaded_rasterization"; 31const char* kMultipleRasterThreadsFeatureName = "multiple_raster_threads"; 32 33const int kMinRasterThreads = 1; 34const int kMaxRasterThreads = 64; 35 36struct GpuFeatureInfo { 37 std::string name; 38 bool blocked; 39 bool disabled; 40 std::string disabled_description; 41 bool fallback_to_software; 42}; 43 44const 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 166bool 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 183bool 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 199bool 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 214int 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 224int 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 244bool 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 263bool 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 273bool UseSurfacesEnabled() { 274 const base::CommandLine& command_line = 275 *base::CommandLine::ForCurrentProcess(); 276 277 return command_line.HasSwitch(switches::kUseSurfaces); 278} 279 280base::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 336base::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 377base::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