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 "build/build_config.h" 10 #include "cc/base/switches.h" 11 #include "content/browser/gpu/gpu_data_manager_impl.h" 12 #include "content/public/common/content_switches.h" 13 #include "gpu/config/gpu_feature_type.h" 14 15 namespace content { 16 17 namespace { 18 19 struct GpuFeatureInfo { 20 std::string name; 21 uint32 blocked; 22 bool disabled; 23 std::string disabled_description; 24 bool fallback_to_software; 25 }; 26 27 #if defined(OS_CHROMEOS) 28 const size_t kNumFeatures = 14; 29 #else 30 const size_t kNumFeatures = 13; 31 #endif 32 const GpuFeatureInfo GetGpuFeatureInfo(size_t index) { 33 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 34 GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance(); 35 36 const GpuFeatureInfo kGpuFeatureInfo[] = { 37 { 38 "2d_canvas", 39 manager->IsFeatureBlacklisted( 40 gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS), 41 command_line.HasSwitch(switches::kDisableAccelerated2dCanvas) || 42 !GpuDataManagerImpl::GetInstance()-> 43 GetGPUInfo().SupportsAccelerated2dCanvas(), 44 "Accelerated 2D canvas is unavailable: either disabled at the command" 45 " line or not supported by the current system.", 46 true 47 }, 48 { 49 "compositing", 50 manager->IsFeatureBlacklisted( 51 gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING), 52 command_line.HasSwitch(switches::kDisableAcceleratedCompositing), 53 "Accelerated compositing has been disabled, either via about:flags or" 54 " command line. This adversely affects performance of all hardware" 55 " accelerated features.", 56 true 57 }, 58 { 59 "3d_css", 60 manager->IsFeatureBlacklisted( 61 gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) || 62 manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_3D_CSS), 63 command_line.HasSwitch(switches::kDisableAcceleratedLayers), 64 "Accelerated layers have been disabled at the command line.", 65 false 66 }, 67 { 68 "css_animation", 69 manager->IsFeatureBlacklisted( 70 gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) || 71 manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_3D_CSS), 72 command_line.HasSwitch(cc::switches::kDisableThreadedAnimation) || 73 command_line.HasSwitch(switches::kDisableAcceleratedCompositing) || 74 command_line.HasSwitch(switches::kDisableAcceleratedLayers), 75 "Accelerated CSS animation has been disabled at the command line.", 76 true 77 }, 78 { 79 "webgl", 80 manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL), 81 command_line.HasSwitch(switches::kDisableExperimentalWebGL), 82 "WebGL has been disabled, either via about:flags or command line.", 83 false 84 }, 85 { 86 "multisampling", 87 manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_MULTISAMPLING), 88 command_line.HasSwitch(switches::kDisableGLMultisampling), 89 "Multisampling has been disabled, either via about:flags or command" 90 " line.", 91 false 92 }, 93 { 94 "flash_3d", 95 manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH3D), 96 command_line.HasSwitch(switches::kDisableFlash3d), 97 "Using 3d in flash has been disabled, either via about:flags or" 98 " command line.", 99 false 100 }, 101 { 102 "flash_stage3d", 103 manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D), 104 command_line.HasSwitch(switches::kDisableFlashStage3d), 105 "Using Stage3d in Flash has been disabled, either via about:flags or" 106 " command line.", 107 false 108 }, 109 { 110 "flash_stage3d_baseline", 111 manager->IsFeatureBlacklisted( 112 gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE) || 113 manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D), 114 command_line.HasSwitch(switches::kDisableFlashStage3d), 115 "Using Stage3d Baseline profile in Flash has been disabled, either" 116 " via about:flags or command line.", 117 false 118 }, 119 { 120 "texture_sharing", 121 manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_TEXTURE_SHARING), 122 command_line.HasSwitch(switches::kDisableImageTransportSurface), 123 "Sharing textures between processes has been disabled, either via" 124 " about:flags or command line.", 125 false 126 }, 127 { 128 "video_decode", 129 manager->IsFeatureBlacklisted( 130 gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE), 131 command_line.HasSwitch(switches::kDisableAcceleratedVideoDecode), 132 "Accelerated video decode has been disabled, either via about:flags" 133 " or command line.", 134 true 135 }, 136 #if defined(ENABLE_WEBRTC) 137 { 138 "video_encode", 139 manager->IsFeatureBlacklisted( 140 gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_ENCODE), 141 command_line.HasSwitch(switches::kDisableWebRtcHWEncoding), 142 "Accelerated video encode has been disabled, either via about:flags" 143 " or command line.", 144 true 145 }, 146 #endif 147 { 148 "video", 149 manager->IsFeatureBlacklisted( 150 gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO), 151 command_line.HasSwitch(switches::kDisableAcceleratedVideo) || 152 command_line.HasSwitch(switches::kDisableAcceleratedCompositing), 153 "Accelerated video presentation has been disabled, either via" 154 " about:flags or command line.", 155 true 156 }, 157 #if defined(OS_CHROMEOS) 158 { 159 "panel_fitting", 160 manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_PANEL_FITTING), 161 command_line.HasSwitch(switches::kDisablePanelFitting), 162 "Panel fitting has been disabled, either via about:flags or command" 163 " line.", 164 false 165 }, 166 #endif 167 { 168 "force_compositing_mode", 169 manager->IsFeatureBlacklisted( 170 gpu::GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE) && 171 !IsForceCompositingModeEnabled(), 172 !IsForceCompositingModeEnabled() && 173 !manager->IsFeatureBlacklisted( 174 gpu::GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE), 175 "Force compositing mode is off, either disabled at the command" 176 " line or not supported by the current system.", 177 false 178 }, 179 }; 180 return kGpuFeatureInfo[index]; 181 } 182 183 bool CanDoAcceleratedCompositing() { 184 const GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance(); 185 186 // Don't use force compositing mode if gpu access has been blocked or 187 // accelerated compositing is blacklisted. 188 if (!manager->GpuAccessAllowed(NULL) || 189 manager->IsFeatureBlacklisted( 190 gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING)) 191 return false; 192 193 // Check for SwiftShader. 194 if (manager->ShouldUseSwiftShader()) 195 return false; 196 197 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 198 if (command_line.HasSwitch(switches::kDisableAcceleratedCompositing)) 199 return false; 200 201 return true; 202 } 203 204 bool IsForceCompositingModeBlacklisted() { 205 return GpuDataManagerImpl::GetInstance()->IsFeatureBlacklisted( 206 gpu::GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE); 207 } 208 209 } // namespace 210 211 bool IsThreadedCompositingEnabled() { 212 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 213 214 // Command line switches take precedence over blacklist. 215 if (command_line.HasSwitch(switches::kDisableForceCompositingMode) || 216 command_line.HasSwitch(switches::kDisableThreadedCompositing)) { 217 return false; 218 } else if (command_line.HasSwitch(switches::kEnableThreadedCompositing)) { 219 return true; 220 } 221 222 #if defined(USE_AURA) 223 // We always want threaded compositing on Aura. 224 return true; 225 #endif 226 227 if (!CanDoAcceleratedCompositing() || IsForceCompositingModeBlacklisted()) 228 return false; 229 230 #if defined(OS_MACOSX) || defined(OS_WIN) 231 // Windows Vista+ has been shipping with TCM enabled at 100% since M24 and 232 // Mac OSX 10.8+ since M28. The blacklist check above takes care of returning 233 // false before this hits on unsupported Win/Mac versions. 234 return true; 235 #endif 236 237 return false; 238 } 239 240 bool IsForceCompositingModeEnabled() { 241 // Force compositing mode is a subset of threaded compositing mode. 242 if (IsThreadedCompositingEnabled()) 243 return true; 244 245 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 246 247 // Command line switches take precedence over blacklisting. 248 if (command_line.HasSwitch(switches::kDisableForceCompositingMode)) 249 return false; 250 else if (command_line.HasSwitch(switches::kForceCompositingMode)) 251 return true; 252 253 if (!CanDoAcceleratedCompositing() || IsForceCompositingModeBlacklisted()) 254 return false; 255 256 #if defined(OS_MACOSX) || defined(OS_WIN) 257 // Windows Vista+ has been shipping with TCM enabled at 100% since M24 and 258 // Mac OSX 10.8+ since M28. The blacklist check above takes care of returning 259 // false before this hits on unsupported Win/Mac versions. 260 return true; 261 #endif 262 263 return false; 264 } 265 266 bool IsDelegatedRendererEnabled() { 267 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 268 bool enabled = false; 269 270 #if defined(USE_AURA) 271 // Enable on Aura. 272 enabled = true; 273 #endif 274 275 // Flags override. 276 enabled |= command_line.HasSwitch(switches::kEnableDelegatedRenderer); 277 enabled &= !command_line.HasSwitch(switches::kDisableDelegatedRenderer); 278 279 // Needs compositing, and thread. 280 if (enabled && 281 (!IsForceCompositingModeEnabled() || !IsThreadedCompositingEnabled())) { 282 enabled = false; 283 LOG(ERROR) << "Disabling delegated-rendering because it needs " 284 << "force-compositing-mode and threaded-compositing."; 285 } 286 287 return enabled; 288 } 289 290 bool IsDeadlineSchedulingEnabled() { 291 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 292 293 // Default to enabled. 294 bool enabled = true; 295 296 // Flags override. 297 enabled |= command_line.HasSwitch(switches::kEnableDeadlineScheduling); 298 enabled &= !command_line.HasSwitch(switches::kDisableDeadlineScheduling); 299 300 return enabled; 301 } 302 303 base::Value* GetFeatureStatus() { 304 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 305 GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance(); 306 std::string gpu_access_blocked_reason; 307 bool gpu_access_blocked = 308 !manager->GpuAccessAllowed(&gpu_access_blocked_reason); 309 310 base::DictionaryValue* feature_status_dict = new base::DictionaryValue(); 311 312 for (size_t i = 0; i < kNumFeatures; ++i) { 313 const GpuFeatureInfo gpu_feature_info = GetGpuFeatureInfo(i); 314 // force_compositing_mode status is part of the compositing status. 315 if (gpu_feature_info.name == "force_compositing_mode") 316 continue; 317 318 std::string status; 319 if (gpu_feature_info.disabled) { 320 status = "disabled"; 321 if (gpu_feature_info.name == "css_animation") { 322 status += "_software_animated"; 323 } else if (gpu_feature_info.name == "raster") { 324 if (cc::switches::IsImplSidePaintingEnabled()) 325 status += "_software_multithreaded"; 326 else 327 status += "_software"; 328 } else { 329 if (gpu_feature_info.fallback_to_software) 330 status += "_software"; 331 else 332 status += "_off"; 333 } 334 } else if (manager->ShouldUseSwiftShader()) { 335 status = "unavailable_software"; 336 } else if (gpu_feature_info.blocked || 337 gpu_access_blocked) { 338 status = "unavailable"; 339 if (gpu_feature_info.fallback_to_software) 340 status += "_software"; 341 else 342 status += "_off"; 343 } else { 344 status = "enabled"; 345 if (gpu_feature_info.name == "webgl" && 346 (command_line.HasSwitch(switches::kDisableAcceleratedCompositing) || 347 manager->IsFeatureBlacklisted( 348 gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING))) 349 status += "_readback"; 350 bool has_thread = IsThreadedCompositingEnabled(); 351 if (gpu_feature_info.name == "compositing") { 352 bool force_compositing = IsForceCompositingModeEnabled(); 353 if (force_compositing) 354 status += "_force"; 355 if (has_thread) 356 status += "_threaded"; 357 } 358 if (gpu_feature_info.name == "css_animation") { 359 if (has_thread) 360 status = "accelerated_threaded"; 361 else 362 status = "accelerated"; 363 } 364 } 365 // TODO(reveman): Remove this when crbug.com/223286 has been fixed. 366 if (gpu_feature_info.name == "raster" && 367 cc::switches::IsImplSidePaintingEnabled()) { 368 status = "disabled_software_multithreaded"; 369 } 370 feature_status_dict->SetString( 371 gpu_feature_info.name.c_str(), status.c_str()); 372 } 373 return feature_status_dict; 374 } 375 376 base::Value* GetProblems() { 377 GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance(); 378 std::string gpu_access_blocked_reason; 379 bool gpu_access_blocked = 380 !manager->GpuAccessAllowed(&gpu_access_blocked_reason); 381 382 base::ListValue* problem_list = new base::ListValue(); 383 manager->GetBlacklistReasons(problem_list); 384 385 if (gpu_access_blocked) { 386 base::DictionaryValue* problem = new base::DictionaryValue(); 387 problem->SetString("description", 388 "GPU process was unable to boot: " + gpu_access_blocked_reason); 389 problem->Set("crBugs", new base::ListValue()); 390 problem->Set("webkitBugs", new base::ListValue()); 391 problem_list->Insert(0, problem); 392 } 393 394 for (size_t i = 0; i < kNumFeatures; ++i) { 395 const GpuFeatureInfo gpu_feature_info = GetGpuFeatureInfo(i); 396 if (gpu_feature_info.disabled) { 397 base::DictionaryValue* problem = new base::DictionaryValue(); 398 problem->SetString( 399 "description", gpu_feature_info.disabled_description); 400 problem->Set("crBugs", new base::ListValue()); 401 problem->Set("webkitBugs", new base::ListValue()); 402 problem_list->Append(problem); 403 } 404 } 405 return problem_list; 406 } 407 408 base::Value* GetDriverBugWorkarounds() { 409 base::ListValue* workaround_list = new base::ListValue(); 410 GpuDataManagerImpl::GetInstance()->GetDriverBugWorkarounds(workaround_list); 411 return workaround_list; 412 } 413 414 } // namespace content 415