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
IsGpuRasterizationBlacklisted()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
GetGpuFeatureInfo(size_t index,bool * eof)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
IsPinchVirtualViewportEnabled()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
IsThreadedCompositingEnabled()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
IsDelegatedRendererEnabled()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
IsImplSidePaintingEnabled()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
IsGpuRasterizationEnabled()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
IsForceGpuRasterizationEnabled()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
GetFeatureStatus()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
GetProblems()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
GetDriverBugWorkarounds()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