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.
5 #include "content/browser/gpu/compositor_util.h"
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 "base/sys_info.h"
12 #include "build/build_config.h"
13 #include "cc/base/switches.h"
14 #include "content/browser/gpu/gpu_data_manager_impl.h"
15 #include "content/public/common/content_switches.h"
16 #include "gpu/config/gpu_feature_type.h"
22 static bool IsGpuRasterizationBlacklisted() {
23 GpuDataManagerImpl
* manager
= GpuDataManagerImpl::GetInstance();
24 return manager
->IsFeatureBlacklisted(
25 gpu::GPU_FEATURE_TYPE_GPU_RASTERIZATION
);
28 const char* kGpuCompositingFeatureName
= "gpu_compositing";
29 const char* kWebGLFeatureName
= "webgl";
30 const char* kRasterizationFeatureName
= "rasterization";
31 const char* kThreadedRasterizationFeatureName
= "threaded_rasterization";
32 const char* kMultipleRasterThreadsFeatureName
= "multiple_raster_threads";
34 const int kMinRasterThreads
= 1;
35 const int kMaxRasterThreads
= 64;
37 const int kMinMSAASampleCount
= 0;
39 struct GpuFeatureInfo
{
43 std::string disabled_description
;
44 bool fallback_to_software
;
47 const GpuFeatureInfo
GetGpuFeatureInfo(size_t index
, bool* eof
) {
48 const base::CommandLine
& command_line
=
49 *base::CommandLine::ForCurrentProcess();
50 GpuDataManagerImpl
* manager
= GpuDataManagerImpl::GetInstance();
52 const GpuFeatureInfo kGpuFeatureInfo
[] = {
55 manager
->IsFeatureBlacklisted(
56 gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS
),
57 command_line
.HasSwitch(switches::kDisableAccelerated2dCanvas
) ||
58 !GpuDataManagerImpl::GetInstance()->
59 GetGPUInfo().SupportsAccelerated2dCanvas(),
60 "Accelerated 2D canvas is unavailable: either disabled at the command"
61 " line or not supported by the current system.",
65 kGpuCompositingFeatureName
,
66 manager
->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING
),
67 command_line
.HasSwitch(switches::kDisableGpuCompositing
),
68 "Gpu compositing has been disabled, either via about:flags or"
69 " command line. The browser will fall back to software compositing"
70 " and hardware acceleration will be unavailable.",
75 manager
->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL
),
76 command_line
.HasSwitch(switches::kDisableExperimentalWebGL
),
77 "WebGL has been disabled, either via about:flags or command line.",
82 manager
->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH3D
),
83 command_line
.HasSwitch(switches::kDisableFlash3d
),
84 "Using 3d in flash has been disabled, either via about:flags or"
90 manager
->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D
),
91 command_line
.HasSwitch(switches::kDisableFlashStage3d
),
92 "Using Stage3d in Flash has been disabled, either via about:flags or"
97 "flash_stage3d_baseline",
98 manager
->IsFeatureBlacklisted(
99 gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE
) ||
100 manager
->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D
),
101 command_line
.HasSwitch(switches::kDisableFlashStage3d
),
102 "Using Stage3d Baseline profile in Flash has been disabled, either"
103 " via about:flags or command line.",
108 manager
->IsFeatureBlacklisted(
109 gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE
),
110 command_line
.HasSwitch(switches::kDisableAcceleratedVideoDecode
),
111 "Accelerated video decode has been disabled, either via about:flags"
115 #if defined(ENABLE_WEBRTC)
118 manager
->IsFeatureBlacklisted(
119 gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_ENCODE
),
120 command_line
.HasSwitch(switches::kDisableWebRtcHWEncoding
),
121 "Accelerated video encode has been disabled, either via about:flags"
126 #if defined(OS_CHROMEOS)
129 manager
->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_PANEL_FITTING
),
130 command_line
.HasSwitch(switches::kDisablePanelFitting
),
131 "Panel fitting has been disabled, either via about:flags or command"
137 kRasterizationFeatureName
,
138 IsGpuRasterizationBlacklisted() &&
139 !IsGpuRasterizationEnabled() && !IsForceGpuRasterizationEnabled(),
140 !IsGpuRasterizationEnabled() && !IsForceGpuRasterizationEnabled() &&
141 !IsGpuRasterizationBlacklisted(),
142 "Accelerated rasterization has been disabled, either via about:flags"
147 kThreadedRasterizationFeatureName
,
149 !IsImplSidePaintingEnabled(),
150 "Threaded rasterization has not been enabled or"
151 " is not supported by the current system.",
155 kMultipleRasterThreadsFeatureName
,
157 NumberOfRendererRasterThreads() == 1,
158 "Raster is using a single thread.",
162 DCHECK(index
< arraysize(kGpuFeatureInfo
));
163 *eof
= (index
== arraysize(kGpuFeatureInfo
) - 1);
164 return kGpuFeatureInfo
[index
];
169 bool IsPinchVirtualViewportEnabled() {
170 const base::CommandLine
& command_line
=
171 *base::CommandLine::ForCurrentProcess();
173 // Command line switches take precedence over platform default.
174 if (command_line
.HasSwitch(cc::switches::kDisablePinchVirtualViewport
))
176 if (command_line
.HasSwitch(cc::switches::kEnablePinchVirtualViewport
))
182 bool IsPropertyTreeVerificationEnabled() {
183 const base::CommandLine
& command_line
=
184 *base::CommandLine::ForCurrentProcess();
185 return command_line
.HasSwitch(cc::switches::kEnablePropertyTreeVerification
);
188 bool IsDelegatedRendererEnabled() {
189 const base::CommandLine
& command_line
=
190 *base::CommandLine::ForCurrentProcess();
191 bool enabled
= false;
193 #if defined(USE_AURA) || defined(OS_MACOSX)
194 // Enable on Aura and Mac.
199 enabled
|= command_line
.HasSwitch(switches::kEnableDelegatedRenderer
);
200 enabled
&= !command_line
.HasSwitch(switches::kDisableDelegatedRenderer
);
204 bool IsImplSidePaintingEnabled() {
205 const base::CommandLine
& command_line
=
206 *base::CommandLine::ForCurrentProcess();
207 if (command_line
.HasSwitch(switches::kDisableImplSidePainting
))
212 int NumberOfRendererRasterThreads() {
213 int num_raster_threads
= 1;
215 // Async uploads uses its own thread, so allow an extra thread when async
216 // uploads is not in use.
217 bool allow_extra_thread
=
218 IsZeroCopyUploadEnabled() || IsOneCopyUploadEnabled();
219 if (base::SysInfo::NumberOfProcessors() >= 4 && allow_extra_thread
)
220 num_raster_threads
= 2;
222 int force_num_raster_threads
= ForceNumberOfRendererRasterThreads();
223 if (force_num_raster_threads
)
224 num_raster_threads
= force_num_raster_threads
;
226 return num_raster_threads
;
229 bool IsOneCopyUploadEnabled() {
230 if (IsZeroCopyUploadEnabled())
233 const base::CommandLine
& command_line
=
234 *base::CommandLine::ForCurrentProcess();
235 if (command_line
.HasSwitch(switches::kEnableOneCopy
))
237 if (command_line
.HasSwitch(switches::kDisableOneCopy
))
240 #if defined(OS_ANDROID)
246 bool IsZeroCopyUploadEnabled() {
247 const base::CommandLine
& command_line
=
248 *base::CommandLine::ForCurrentProcess();
249 return command_line
.HasSwitch(switches::kEnableZeroCopy
);
252 int ForceNumberOfRendererRasterThreads() {
253 const base::CommandLine
& command_line
=
254 *base::CommandLine::ForCurrentProcess();
256 if (!command_line
.HasSwitch(switches::kNumRasterThreads
))
258 std::string string_value
=
259 command_line
.GetSwitchValueASCII(switches::kNumRasterThreads
);
260 int force_num_raster_threads
= 0;
261 if (base::StringToInt(string_value
, &force_num_raster_threads
) &&
262 force_num_raster_threads
>= kMinRasterThreads
&&
263 force_num_raster_threads
<= kMaxRasterThreads
) {
264 return force_num_raster_threads
;
266 DLOG(WARNING
) << "Failed to parse switch " <<
267 switches::kNumRasterThreads
<< ": " << string_value
;
272 bool IsGpuRasterizationEnabled() {
273 const base::CommandLine
& command_line
=
274 *base::CommandLine::ForCurrentProcess();
276 if (!IsImplSidePaintingEnabled())
279 if (command_line
.HasSwitch(switches::kDisableGpuRasterization
))
281 else if (command_line
.HasSwitch(switches::kEnableGpuRasterization
))
284 if (IsGpuRasterizationBlacklisted()) {
291 bool IsForceGpuRasterizationEnabled() {
292 const base::CommandLine
& command_line
=
293 *base::CommandLine::ForCurrentProcess();
295 if (!IsImplSidePaintingEnabled())
298 return command_line
.HasSwitch(switches::kForceGpuRasterization
);
301 bool IsThreadedGpuRasterizationEnabled() {
302 if (!IsImplSidePaintingEnabled())
304 if (!IsGpuRasterizationEnabled() && !IsForceGpuRasterizationEnabled())
307 const base::CommandLine
& command_line
=
308 *base::CommandLine::ForCurrentProcess();
310 if (command_line
.HasSwitch(switches::kDisableThreadedGpuRasterization
))
316 bool UseSurfacesEnabled() {
317 #if defined(OS_ANDROID)
320 const base::CommandLine
& command_line
=
321 *base::CommandLine::ForCurrentProcess();
323 return command_line
.HasSwitch(switches::kUseSurfaces
);
327 int GpuRasterizationMSAASampleCount() {
328 const base::CommandLine
& command_line
=
329 *base::CommandLine::ForCurrentProcess();
331 if (!command_line
.HasSwitch(switches::kGpuRasterizationMSAASampleCount
))
333 std::string string_value
= command_line
.GetSwitchValueASCII(
334 switches::kGpuRasterizationMSAASampleCount
);
335 int msaa_sample_count
= 0;
336 if (base::StringToInt(string_value
, &msaa_sample_count
) &&
337 msaa_sample_count
>= kMinMSAASampleCount
) {
338 return msaa_sample_count
;
340 DLOG(WARNING
) << "Failed to parse switch "
341 << switches::kGpuRasterizationMSAASampleCount
<< ": "
347 base::DictionaryValue
* GetFeatureStatus() {
348 GpuDataManagerImpl
* manager
= GpuDataManagerImpl::GetInstance();
349 std::string gpu_access_blocked_reason
;
350 bool gpu_access_blocked
=
351 !manager
->GpuAccessAllowed(&gpu_access_blocked_reason
);
353 base::DictionaryValue
* feature_status_dict
= new base::DictionaryValue();
356 for (size_t i
= 0; !eof
; ++i
) {
357 const GpuFeatureInfo gpu_feature_info
= GetGpuFeatureInfo(i
, &eof
);
359 if (gpu_feature_info
.disabled
) {
361 if (gpu_feature_info
.fallback_to_software
)
362 status
+= "_software";
365 if (gpu_feature_info
.name
== kThreadedRasterizationFeatureName
)
367 } else if (gpu_feature_info
.blocked
||
368 gpu_access_blocked
) {
369 status
= "unavailable";
370 if (gpu_feature_info
.fallback_to_software
)
371 status
+= "_software";
376 if (gpu_feature_info
.name
== kWebGLFeatureName
&&
377 manager
->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING
))
378 status
+= "_readback";
379 if (gpu_feature_info
.name
== kRasterizationFeatureName
) {
380 if (IsForceGpuRasterizationEnabled())
383 if (gpu_feature_info
.name
== kMultipleRasterThreadsFeatureName
) {
384 if (ForceNumberOfRendererRasterThreads() > 0)
387 if (gpu_feature_info
.name
== kThreadedRasterizationFeatureName
||
388 gpu_feature_info
.name
== kMultipleRasterThreadsFeatureName
)
391 if (gpu_feature_info
.name
== kWebGLFeatureName
&&
392 (gpu_feature_info
.blocked
|| gpu_access_blocked
) &&
393 manager
->ShouldUseSwiftShader()) {
394 status
= "unavailable_software";
397 feature_status_dict
->SetString(
398 gpu_feature_info
.name
.c_str(), status
.c_str());
400 return feature_status_dict
;
403 base::Value
* GetProblems() {
404 GpuDataManagerImpl
* manager
= GpuDataManagerImpl::GetInstance();
405 std::string gpu_access_blocked_reason
;
406 bool gpu_access_blocked
=
407 !manager
->GpuAccessAllowed(&gpu_access_blocked_reason
);
409 base::ListValue
* problem_list
= new base::ListValue();
410 manager
->GetBlacklistReasons(problem_list
);
412 if (gpu_access_blocked
) {
413 base::DictionaryValue
* problem
= new base::DictionaryValue();
414 problem
->SetString("description",
415 "GPU process was unable to boot: " + gpu_access_blocked_reason
);
416 problem
->Set("crBugs", new base::ListValue());
417 problem
->Set("webkitBugs", new base::ListValue());
418 base::ListValue
* disabled_features
= new base::ListValue();
419 disabled_features
->AppendString("all");
420 problem
->Set("affectedGpuSettings", disabled_features
);
421 problem
->SetString("tag", "disabledFeatures");
422 problem_list
->Insert(0, problem
);
426 for (size_t i
= 0; !eof
; ++i
) {
427 const GpuFeatureInfo gpu_feature_info
= GetGpuFeatureInfo(i
, &eof
);
428 if (gpu_feature_info
.disabled
) {
429 base::DictionaryValue
* problem
= new base::DictionaryValue();
431 "description", gpu_feature_info
.disabled_description
);
432 problem
->Set("crBugs", new base::ListValue());
433 problem
->Set("webkitBugs", new base::ListValue());
434 base::ListValue
* disabled_features
= new base::ListValue();
435 disabled_features
->AppendString(gpu_feature_info
.name
);
436 problem
->Set("affectedGpuSettings", disabled_features
);
437 problem
->SetString("tag", "disabledFeatures");
438 problem_list
->Append(problem
);
444 std::vector
<std::string
> GetDriverBugWorkarounds() {
445 return GpuDataManagerImpl::GetInstance()->GetDriverBugWorkarounds();
448 } // namespace content