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
IsGpuRasterizationBlacklisted()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
GetGpuFeatureInfo(size_t index,bool * eof)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
IsPinchVirtualViewportEnabled()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
IsDelegatedRendererEnabled()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
IsImplSidePaintingEnabled()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
NumberOfRendererRasterThreads()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
ForceNumberOfRendererRasterThreads()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
IsGpuRasterizationEnabled()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
IsForceGpuRasterizationEnabled()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
UseSurfacesEnabled()273 bool UseSurfacesEnabled() {
274 const base::CommandLine& command_line =
275 *base::CommandLine::ForCurrentProcess();
276
277 return command_line.HasSwitch(switches::kUseSurfaces);
278 }
279
GetFeatureStatus()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
GetProblems()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
GetDriverBugWorkarounds()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