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
GetGpuFeatureInfo(size_t index)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
CanDoAcceleratedCompositing()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
IsForceCompositingModeBlacklisted()204 bool IsForceCompositingModeBlacklisted() {
205 return GpuDataManagerImpl::GetInstance()->IsFeatureBlacklisted(
206 gpu::GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE);
207 }
208
209 } // namespace
210
IsThreadedCompositingEnabled()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
IsForceCompositingModeEnabled()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
IsDelegatedRendererEnabled()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
IsDeadlineSchedulingEnabled()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
GetFeatureStatus()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
GetProblems()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
GetDriverBugWorkarounds()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