Home | History | Annotate | Download | only in gpu
      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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    273 bool UseSurfacesEnabled() {
    274   const base::CommandLine& command_line =
    275       *base::CommandLine::ForCurrentProcess();
    276 
    277   return command_line.HasSwitch(switches::kUseSurfaces);
    278 }
    279 
    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 
    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 
    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