diff options
24 files changed, 870 insertions, 888 deletions
diff --git a/chrome/browser/chrome_browser_field_trials.cc b/chrome/browser/chrome_browser_field_trials.cc index 2c4c875..4008c4d 100644 --- a/chrome/browser/chrome_browser_field_trials.cc +++ b/chrome/browser/chrome_browser_field_trials.cc @@ -15,9 +15,9 @@ #include "base/utf_string_conversions.h" #include "chrome/browser/auto_launch_trial.h" #include "chrome/browser/autocomplete/autocomplete_field_trial.h" +#include "chrome/browser/chrome_gpu_util.h" #include "chrome/browser/extensions/default_apps_trial.h" #include "chrome/browser/google/google_util.h" -#include "chrome/browser/gpu_util.h" #include "chrome/browser/instant/instant_field_trials.h" #include "chrome/browser/net/predictor.h" #include "chrome/browser/prerender/prerender_field_trial.h" diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc index 3160667..1956e55 100644 --- a/chrome/browser/chrome_browser_main.cc +++ b/chrome/browser/chrome_browser_main.cc @@ -34,6 +34,7 @@ #include "chrome/browser/browser_process_impl.h" #include "chrome/browser/browser_shutdown.h" #include "chrome/browser/chrome_browser_main_extra_parts.h" +#include "chrome/browser/chrome_gpu_util.h" #include "chrome/browser/defaults.h" #include "chrome/browser/extensions/extension_protocols.h" #include "chrome/browser/extensions/extension_service.h" @@ -41,7 +42,6 @@ #include "chrome/browser/first_run/upgrade_util.h" #include "chrome/browser/google/google_search_counter.h" #include "chrome/browser/google/google_util.h" -#include "chrome/browser/gpu_blacklist.h" #include "chrome/browser/jankometer.h" #include "chrome/browser/language_usage_metrics.h" #include "chrome/browser/managed_mode.h" @@ -424,25 +424,6 @@ Profile* CreateProfile(const content::MainFunctionParams& parameters, return NULL; } -// Load GPU Blacklist, collect preliminary gpu info, and compute preliminary -// gpu feature flags. -void InitializeGpuDataManager(const CommandLine& parsed_command_line) { - content::GpuDataManager::GetInstance()->InitializeGpuInfo(); - if (parsed_command_line.HasSwitch(switches::kSkipGpuDataLoading) || - parsed_command_line.HasSwitch(switches::kIgnoreGpuBlacklist)) { - return; - } - - const base::StringPiece gpu_blacklist_json( - ResourceBundle::GetSharedInstance().GetRawDataResource( - IDR_GPU_BLACKLIST, ui::SCALE_FACTOR_NONE)); - GpuBlacklist* gpu_blacklist = GpuBlacklist::GetInstance(); - bool succeed = gpu_blacklist->LoadGpuBlacklist( - gpu_blacklist_json.as_string(), GpuBlacklist::kCurrentOsOnly); - DCHECK(succeed); - gpu_blacklist->UpdateGpuDataManager(); -} - #if defined(OS_MACOSX) OSStatus KeychainCallback(SecKeychainEvent keychain_event, SecKeychainCallbackInfo* info, void* context) { @@ -1355,8 +1336,8 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() { CloudPrintProxyServiceFactory::GetForProfile(profile_); #endif - // Load GPU Blacklist. - InitializeGpuDataManager(parsed_command_line()); + // Load GPU Blacklist; load preliminary GPU info. + gpu_util::InitializeGpuDataManager(parsed_command_line()); // Start watching all browser threads for responsiveness. ThreadWatcherList::StartWatchingAll(parsed_command_line()); diff --git a/chrome/browser/chrome_gpu_util.cc b/chrome/browser/chrome_gpu_util.cc new file mode 100644 index 0000000..0371917 --- /dev/null +++ b/chrome/browser/chrome_gpu_util.cc @@ -0,0 +1,123 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chrome_gpu_util.h" + +#include "base/command_line.h" +#include "base/metrics/field_trial.h" +#include "base/metrics/histogram.h" +#include "base/version.h" +#if defined(OS_WIN) +#include "base/win/windows_version.h" +#endif +#include "chrome/common/chrome_switches.h" +#include "chrome/common/chrome_version_info.h" +#include "content/public/browser/gpu_data_manager.h" +#include "content/public/common/content_constants.h" +#include "content/public/common/content_switches.h" +#include "grit/browser_resources.h" +#include "ui/base/resource/resource_bundle.h" + +using content::GpuDataManager; + +namespace gpu_util { + +void InitializeCompositingFieldTrial() { +// Enable the field trial only on desktop OS's. +#if !(defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)) + return; +#endif +#if defined(OS_WIN) + // Don't run the trial on Windows XP. + if (base::win::GetVersion() < base::win::VERSION_VISTA) + return; +#endif + + // The performance of accelerated compositing is too low with software + // rendering. + if (content::GpuDataManager::GetInstance()->ShouldUseSoftwareRendering()) + return; + + // Don't activate the field trial if force-compositing-mode has been + // explicitly disabled from the command line. + if (CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisableForceCompositingMode)) + return; + + const base::FieldTrial::Probability kDivisor = 3; + scoped_refptr<base::FieldTrial> trial( + base::FieldTrialList::FactoryGetFieldTrial( + content::kGpuCompositingFieldTrialName, kDivisor, + "disable", 2012, 12, 31, NULL)); + + // Produce the same result on every run of this client. + trial->UseOneTimeRandomization(); + + base::FieldTrial::Probability force_compositing_mode_probability = 0; + base::FieldTrial::Probability threaded_compositing_probability = 0; + + chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); + if (channel == chrome::VersionInfo::CHANNEL_STABLE || + channel == chrome::VersionInfo::CHANNEL_BETA) { + // Stable and Beta channels: Non-threaded force-compositing-mode on by + // default (mac and windows only). +#if defined(OS_WIN) || defined(OS_MACOSX) + force_compositing_mode_probability = 3; +#endif + } else if (channel == chrome::VersionInfo::CHANNEL_DEV || + channel == chrome::VersionInfo::CHANNEL_CANARY) { + // Dev and Canary channels: force-compositing-mode and + // threaded-compositing on with 1/3 probability each. + force_compositing_mode_probability = 1; + +#if defined(OS_MACOSX) || defined(OS_LINUX) + // Threaded compositing mode isn't feature complete on mac or linux yet: + // http://crbug.com/133602 for mac + // http://crbug.com/140866 for linux + threaded_compositing_probability = 0; +#else + if (!CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisableThreadedCompositing)) + threaded_compositing_probability = 1; +#endif + } + + int force_compositing_group = trial->AppendGroup( + content::kGpuCompositingFieldTrialForceCompositingEnabledName, + force_compositing_mode_probability); + int thread_group = trial->AppendGroup( + content::kGpuCompositingFieldTrialThreadEnabledName, + threaded_compositing_probability); + + bool force_compositing = (trial->group() == force_compositing_group); + bool thread = (trial->group() == thread_group); + UMA_HISTOGRAM_BOOLEAN("GPU.InForceCompositingModeFieldTrial", + force_compositing); + UMA_HISTOGRAM_BOOLEAN("GPU.InCompositorThreadFieldTrial", thread); +} + +// Load GPU Blacklist, collect preliminary gpu info, and compute preliminary +// gpu feature flags. +void InitializeGpuDataManager(const CommandLine& command_line) { + if (command_line.HasSwitch(switches::kSkipGpuDataLoading)) + return; + + std::string chrome_version_string = "0"; + std::string gpu_blacklist_json_string; + if (!command_line.HasSwitch(switches::kIgnoreGpuBlacklist)) { + chrome::VersionInfo chrome_version_info; + if (chrome_version_info.is_valid()) + chrome_version_string = chrome_version_info.Version(); + + const base::StringPiece gpu_blacklist_json( + ResourceBundle::GetSharedInstance().GetRawDataResource( + IDR_GPU_BLACKLIST, ui::SCALE_FACTOR_NONE)); + gpu_blacklist_json_string = gpu_blacklist_json.as_string(); + } + content::GpuDataManager::GetInstance()->Initialize( + chrome_version_string, gpu_blacklist_json_string); +} + +} // namespace gpu_util; + diff --git a/chrome/browser/chrome_gpu_util.h b/chrome/browser/chrome_gpu_util.h new file mode 100644 index 0000000..b24a3aa --- /dev/null +++ b/chrome/browser/chrome_gpu_util.h @@ -0,0 +1,22 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROME_GPU_UTIL_H_ +#define CHROME_BROWSER_CHROME_GPU_UTIL_H_ + +class CommandLine; + +namespace gpu_util { + +// Sets up force-compositing-mode and threaded compositing field trials. +void InitializeCompositingFieldTrial(); + +// Load GPU Blacklist, collect preliminary gpu info, and compute preliminary +// gpu feature flags. +void InitializeGpuDataManager(const CommandLine& command_line); + +} // namespace gpu_util + +#endif // CHROME_BROWSER_CHROME_GPU_UTIL_H_ + diff --git a/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc b/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc index b15227d..bb2d069 100644 --- a/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc +++ b/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc @@ -16,7 +16,6 @@ #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/api/webstore_private/webstore_private_api.h" #include "chrome/browser/extensions/webstore_installer.h" -#include "chrome/browser/gpu_blacklist.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_notification_types.h" @@ -436,11 +435,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebstoreGetWebGLStatusTest, Blocked) { " }\n" " ]\n" "}"; - GpuBlacklist* blacklist = GpuBlacklist::GetInstance(); - - ASSERT_TRUE(blacklist->LoadGpuBlacklist( - json_blacklist, GpuBlacklist::kAllOs)); - blacklist->UpdateGpuDataManager(); + content::GpuDataManager::GetInstance()->Initialize("0", json_blacklist); GpuFeatureType type = content::GpuDataManager::GetInstance()->GetBlacklistedFeatures(); EXPECT_EQ(type, content::GPU_FEATURE_TYPE_WEBGL); diff --git a/chrome/browser/gpu_util.cc b/chrome/browser/gpu_util.cc deleted file mode 100644 index e81de8e..0000000 --- a/chrome/browser/gpu_util.cc +++ /dev/null @@ -1,631 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/gpu_util.h" - -#include <vector> - -#include "base/command_line.h" -#include "base/metrics/field_trial.h" -#include "base/metrics/histogram.h" -#include "base/string_number_conversions.h" -#include "base/string_util.h" -#include "base/stringprintf.h" -#include "base/sys_info.h" -#include "base/values.h" -#include "base/version.h" -#include "chrome/browser/gpu_blacklist.h" -#include "chrome/common/chrome_version_info.h" -#include "content/public/browser/gpu_data_manager.h" -#include "content/public/common/compositor_util.h" -#include "content/public/common/content_constants.h" -#include "content/public/common/content_switches.h" -#include "content/public/common/gpu_info.h" - -#if defined(OS_WIN) -#include "base/win/windows_version.h" -#endif - -using content::GpuDataManager; -using content::GpuFeatureType; - -namespace { - -const char kGpuFeatureNameAccelerated2dCanvas[] = "accelerated_2d_canvas"; -const char kGpuFeatureNameAcceleratedCompositing[] = "accelerated_compositing"; -const char kGpuFeatureNameWebgl[] = "webgl"; -const char kGpuFeatureNameMultisampling[] = "multisampling"; -const char kGpuFeatureNameFlash3d[] = "flash_3d"; -const char kGpuFeatureNameFlashStage3d[] = "flash_stage3d"; -const char kGpuFeatureNameTextureSharing[] = "texture_sharing"; -const char kGpuFeatureNameAcceleratedVideoDecode[] = "accelerated_video_decode"; -const char kGpuFeatureNameAll[] = "all"; -const char kGpuFeatureNameUnknown[] = "unknown"; - -enum GpuFeatureStatus { - kGpuFeatureEnabled = 0, - kGpuFeatureBlacklisted = 1, - kGpuFeatureDisabled = 2, // disabled by user but not blacklisted - kGpuFeatureNumStatus -}; - -struct GpuFeatureInfo { - std::string name; - uint32 blocked; - bool disabled; - std::string disabled_description; - bool fallback_to_software; -}; - -// Determine if accelerated-2d-canvas is supported, which depends on whether -// lose_context could happen and whether skia is the backend. -bool SupportsAccelerated2dCanvas() { - if (GpuDataManager::GetInstance()->GetGPUInfo().can_lose_context) - return false; -#if defined(USE_SKIA) - return true; -#else - return false; -#endif -} - -DictionaryValue* NewDescriptionValuePair(const std::string& desc, - const std::string& value) { - DictionaryValue* dict = new DictionaryValue(); - dict->SetString("description", desc); - dict->SetString("value", value); - return dict; -} - -DictionaryValue* NewDescriptionValuePair(const std::string& desc, - Value* value) { - DictionaryValue* dict = new DictionaryValue(); - dict->SetString("description", desc); - dict->Set("value", value); - return dict; -} - -Value* NewStatusValue(const char* name, const char* status) { - DictionaryValue* value = new DictionaryValue(); - value->SetString("name", name); - value->SetString("status", status); - return value; -} - -std::string GPUDeviceToString(const content::GPUInfo::GPUDevice& gpu) { - std::string vendor = base::StringPrintf("0x%04x", gpu.vendor_id); - if (!gpu.vendor_string.empty()) - vendor += " [" + gpu.vendor_string + "]"; - std::string device = base::StringPrintf("0x%04x", gpu.device_id); - if (!gpu.device_string.empty()) - device += " [" + gpu.device_string + "]"; - return base::StringPrintf( - "VENDOR = %s, DEVICE= %s", vendor.c_str(), device.c_str()); -} - -#if defined(OS_WIN) - -enum WinSubVersion { - kWinOthers = 0, - kWinXP, - kWinVista, - kWin7, - kNumWinSubVersions -}; - -// Output DxDiagNode tree as nested array of {description,value} pairs -ListValue* DxDiagNodeToList(const content::DxDiagNode& node) { - ListValue* list = new ListValue(); - for (std::map<std::string, std::string>::const_iterator it = - node.values.begin(); - it != node.values.end(); - ++it) { - list->Append(NewDescriptionValuePair(it->first, it->second)); - } - - for (std::map<std::string, content::DxDiagNode>::const_iterator it = - node.children.begin(); - it != node.children.end(); - ++it) { - ListValue* sublist = DxDiagNodeToList(it->second); - list->Append(NewDescriptionValuePair(it->first, sublist)); - } - return list; -} - -int GetGpuBlacklistHistogramValueWin(GpuFeatureStatus status) { - static WinSubVersion sub_version = kNumWinSubVersions; - if (sub_version == kNumWinSubVersions) { - sub_version = kWinOthers; - std::string version_str = base::SysInfo::OperatingSystemVersion(); - size_t pos = version_str.find_first_not_of("0123456789."); - if (pos != std::string::npos) - version_str = version_str.substr(0, pos); - Version os_version(version_str); - if (os_version.IsValid() && os_version.components().size() >= 2) { - const std::vector<uint16>& version_numbers = os_version.components(); - if (version_numbers[0] == 5) - sub_version = kWinXP; - else if (version_numbers[0] == 6 && version_numbers[1] == 0) - sub_version = kWinVista; - else if (version_numbers[0] == 6 && version_numbers[1] == 1) - sub_version = kWin7; - } - } - int entry_index = static_cast<int>(sub_version) * kGpuFeatureNumStatus; - switch (status) { - case kGpuFeatureEnabled: - break; - case kGpuFeatureBlacklisted: - entry_index++; - break; - case kGpuFeatureDisabled: - entry_index += 2; - break; - } - return entry_index; -} -#endif // OS_WIN - -} // namespace - -namespace gpu_util { - -void InitializeCompositingFieldTrial() { -// Enable the field trial only on desktop OS's. -#if !(defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)) - return; -#endif -#if defined(OS_WIN) - // Don't run the trial on Windows XP. - if (base::win::GetVersion() < base::win::VERSION_VISTA) - return; -#endif - - // The performance of accelerated compositing is too low with software - // rendering. - if (content::GpuDataManager::GetInstance()->ShouldUseSoftwareRendering()) - return; - - // Don't activate the field trial if force-compositing-mode has been - // explicitly disabled from the command line. - if (CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableForceCompositingMode)) - return; - - const base::FieldTrial::Probability kDivisor = 3; - scoped_refptr<base::FieldTrial> trial( - base::FieldTrialList::FactoryGetFieldTrial( - content::kGpuCompositingFieldTrialName, kDivisor, - "disable", 2012, 12, 31, NULL)); - - // Produce the same result on every run of this client. - trial->UseOneTimeRandomization(); - - base::FieldTrial::Probability force_compositing_mode_probability = 0; - base::FieldTrial::Probability threaded_compositing_probability = 0; - - chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); - if (channel == chrome::VersionInfo::CHANNEL_STABLE || - channel == chrome::VersionInfo::CHANNEL_BETA) { - // Stable and Beta channels: Non-threaded force-compositing-mode on by - // default (mac and windows only). -#if defined(OS_WIN) || defined(OS_MACOSX) - force_compositing_mode_probability = 3; -#endif - } else if (channel == chrome::VersionInfo::CHANNEL_DEV || - channel == chrome::VersionInfo::CHANNEL_CANARY) { - // Dev and Canary channels: force-compositing-mode and - // threaded-compositing on with 1/3 probability each. - force_compositing_mode_probability = 1; - -#if defined(OS_MACOSX) || defined(OS_LINUX) - // Threaded compositing mode isn't feature complete on mac or linux yet: - // http://crbug.com/133602 for mac - // http://crbug.com/140866 for linux - threaded_compositing_probability = 0; -#else - if (!CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableThreadedCompositing)) - threaded_compositing_probability = 1; -#endif - } - - - int force_compositing_group = trial->AppendGroup( - content::kGpuCompositingFieldTrialForceCompositingEnabledName, - force_compositing_mode_probability); - int thread_group = trial->AppendGroup( - content::kGpuCompositingFieldTrialThreadEnabledName, - threaded_compositing_probability); - - bool force_compositing = (trial->group() == force_compositing_group); - bool thread = (trial->group() == thread_group); - UMA_HISTOGRAM_BOOLEAN("GPU.InForceCompositingModeFieldTrial", - force_compositing); - UMA_HISTOGRAM_BOOLEAN("GPU.InCompositorThreadFieldTrial", thread); -} - -GpuFeatureType StringToGpuFeatureType(const std::string& feature_string) { - if (feature_string == kGpuFeatureNameAccelerated2dCanvas) - return content::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS; - else if (feature_string == kGpuFeatureNameAcceleratedCompositing) - return content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING; - else if (feature_string == kGpuFeatureNameWebgl) - return content::GPU_FEATURE_TYPE_WEBGL; - else if (feature_string == kGpuFeatureNameMultisampling) - return content::GPU_FEATURE_TYPE_MULTISAMPLING; - else if (feature_string == kGpuFeatureNameFlash3d) - return content::GPU_FEATURE_TYPE_FLASH3D; - else if (feature_string == kGpuFeatureNameFlashStage3d) - return content::GPU_FEATURE_TYPE_FLASH_STAGE3D; - else if (feature_string == kGpuFeatureNameTextureSharing) - return content::GPU_FEATURE_TYPE_TEXTURE_SHARING; - else if (feature_string == kGpuFeatureNameAcceleratedVideoDecode) - return content::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE; - else if (feature_string == kGpuFeatureNameAll) - return content::GPU_FEATURE_TYPE_ALL; - return content::GPU_FEATURE_TYPE_UNKNOWN; -} - -std::string GpuFeatureTypeToString(GpuFeatureType type) { - std::vector<std::string> matches; - if (type == content::GPU_FEATURE_TYPE_ALL) { - matches.push_back(kGpuFeatureNameAll); - } else { - if (type & content::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS) - matches.push_back(kGpuFeatureNameAccelerated2dCanvas); - if (type & content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) - matches.push_back(kGpuFeatureNameAcceleratedCompositing); - if (type & content::GPU_FEATURE_TYPE_WEBGL) - matches.push_back(kGpuFeatureNameWebgl); - if (type & content::GPU_FEATURE_TYPE_MULTISAMPLING) - matches.push_back(kGpuFeatureNameMultisampling); - if (type & content::GPU_FEATURE_TYPE_FLASH3D) - matches.push_back(kGpuFeatureNameFlash3d); - if (type & content::GPU_FEATURE_TYPE_FLASH_STAGE3D) - matches.push_back(kGpuFeatureNameFlashStage3d); - if (type & content::GPU_FEATURE_TYPE_TEXTURE_SHARING) - matches.push_back(kGpuFeatureNameTextureSharing); - if (!matches.size()) - matches.push_back(kGpuFeatureNameUnknown); - } - return JoinString(matches, ','); -} - -Value* GetFeatureStatus() { - const CommandLine& command_line = *CommandLine::ForCurrentProcess(); - bool gpu_access_blocked = !GpuDataManager::GetInstance()->GpuAccessAllowed(); - - uint32 flags = GpuDataManager::GetInstance()->GetBlacklistedFeatures(); - DictionaryValue* status = new DictionaryValue(); - - const GpuFeatureInfo kGpuFeatureInfo[] = { - { - "2d_canvas", - flags & content::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS, - command_line.HasSwitch(switches::kDisableAccelerated2dCanvas) || - !SupportsAccelerated2dCanvas(), - "Accelerated 2D canvas is unavailable: either disabled at the command" - " line or not supported by the current system.", - true - }, - { - "compositing", - flags & content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING, - command_line.HasSwitch(switches::kDisableAcceleratedCompositing), - "Accelerated compositing has been disabled, either via about:flags or" - " command line. This adversely affects performance of all hardware" - " accelerated features.", - true - }, - { - "3d_css", - flags & content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING, - command_line.HasSwitch(switches::kDisableAcceleratedLayers), - "Accelerated layers have been disabled at the command line.", - false - }, - { - "css_animation", - flags & content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING, - command_line.HasSwitch(switches::kDisableThreadedAnimation) || - command_line.HasSwitch(switches::kDisableAcceleratedCompositing), - "Accelerated CSS animation has been disabled at the command line.", - true - }, - { - "webgl", - flags & content::GPU_FEATURE_TYPE_WEBGL, -#if defined(OS_ANDROID) - !command_line.HasSwitch(switches::kEnableExperimentalWebGL), -#else - command_line.HasSwitch(switches::kDisableExperimentalWebGL), -#endif - "WebGL has been disabled, either via about:flags or command line.", - false - }, - { - "multisampling", - flags & content::GPU_FEATURE_TYPE_MULTISAMPLING, - command_line.HasSwitch(switches::kDisableGLMultisampling), - "Multisampling has been disabled, either via about:flags or command" - " line.", - false - }, - { - "flash_3d", - flags & content::GPU_FEATURE_TYPE_FLASH3D, - command_line.HasSwitch(switches::kDisableFlash3d), - "Using 3d in flash has been disabled, either via about:flags or" - " command line.", - false - }, - { - "flash_stage3d", - flags & content::GPU_FEATURE_TYPE_FLASH_STAGE3D, - command_line.HasSwitch(switches::kDisableFlashStage3d), - "Using Stage3d in Flash has been disabled, either via about:flags or" - " command line.", - false - }, - { - "texture_sharing", - flags & content::GPU_FEATURE_TYPE_TEXTURE_SHARING, - command_line.HasSwitch(switches::kDisableImageTransportSurface), - "Sharing textures between processes has been disabled, either via" - " about:flags or command line.", - false - }, - { - "video_decode", - flags & content::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE, - command_line.HasSwitch(switches::kDisableAcceleratedVideoDecode), - "Accelerated video decode has been disabled, either via about:flags" - " or command line.", - true - } - }; - const size_t kNumFeatures = sizeof(kGpuFeatureInfo) / sizeof(GpuFeatureInfo); - - // Build the feature_status field. - { - ListValue* feature_status_list = new ListValue(); - - for (size_t i = 0; i < kNumFeatures; ++i) { - std::string status; - if (kGpuFeatureInfo[i].disabled) { - status = "disabled"; - if (kGpuFeatureInfo[i].name == "css_animation") { - status += "_software_animated"; - } else { - if (kGpuFeatureInfo[i].fallback_to_software) - status += "_software"; - else - status += "_off"; - } - } else if (GpuDataManager::GetInstance()->ShouldUseSoftwareRendering()) { - status = "unavailable_software"; - } else if (kGpuFeatureInfo[i].blocked || - gpu_access_blocked) { - status = "unavailable"; - if (kGpuFeatureInfo[i].fallback_to_software) - status += "_software"; - else - status += "_off"; - } else { - status = "enabled"; - if (kGpuFeatureInfo[i].name == "webgl" && - (command_line.HasSwitch(switches::kDisableAcceleratedCompositing) || - (flags & content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING))) - status += "_readback"; - bool has_thread = content::IsThreadedCompositingEnabled(); - if (kGpuFeatureInfo[i].name == "compositing") { - bool force_compositing = - content::IsForceCompositingModeEnabled(); - if (force_compositing) - status += "_force"; - if (has_thread) - status += "_threaded"; - } - if (kGpuFeatureInfo[i].name == "css_animation") { - if (has_thread) - status = "accelerated_threaded"; - else - status = "accelerated"; - } - } - feature_status_list->Append( - NewStatusValue(kGpuFeatureInfo[i].name.c_str(), status.c_str())); - } - - status->Set("featureStatus", feature_status_list); - } - - // Build the problems list. - { - ListValue* problem_list = new ListValue(); - - if (gpu_access_blocked) { - DictionaryValue* problem = new DictionaryValue(); - problem->SetString("description", - "GPU process was unable to boot. Access to GPU disallowed."); - problem->Set("crBugs", new ListValue()); - problem->Set("webkitBugs", new ListValue()); - problem_list->Append(problem); - } - - for (size_t i = 0; i < kNumFeatures; ++i) { - if (kGpuFeatureInfo[i].disabled) { - DictionaryValue* problem = new DictionaryValue(); - problem->SetString( - "description", kGpuFeatureInfo[i].disabled_description); - problem->Set("crBugs", new ListValue()); - problem->Set("webkitBugs", new ListValue()); - problem_list->Append(problem); - } - } - - GpuBlacklist::GetInstance()->GetBlacklistReasons(problem_list); - - status->Set("problems", problem_list); - } - - return status; -} - -DictionaryValue* GpuInfoAsDictionaryValue() { - content::GPUInfo gpu_info = GpuDataManager::GetInstance()->GetGPUInfo(); - ListValue* basic_info = new ListValue(); - basic_info->Append(NewDescriptionValuePair( - "Initialization time", - base::Int64ToString(gpu_info.initialization_time.InMilliseconds()))); - basic_info->Append(NewDescriptionValuePair( - "GPU0", GPUDeviceToString(gpu_info.gpu))); - for (size_t i = 0; i < gpu_info.secondary_gpus.size(); ++i) { - basic_info->Append(NewDescriptionValuePair( - base::StringPrintf("GPU%d", static_cast<int>(i + 1)), - GPUDeviceToString(gpu_info.secondary_gpus[i]))); - } - basic_info->Append(NewDescriptionValuePair( - "Optimus", Value::CreateBooleanValue(gpu_info.optimus))); - basic_info->Append(NewDescriptionValuePair( - "AMD switchable", Value::CreateBooleanValue(gpu_info.amd_switchable))); - basic_info->Append(NewDescriptionValuePair("Driver vendor", - gpu_info.driver_vendor)); - basic_info->Append(NewDescriptionValuePair("Driver version", - gpu_info.driver_version)); - basic_info->Append(NewDescriptionValuePair("Driver date", - gpu_info.driver_date)); - basic_info->Append(NewDescriptionValuePair("Pixel shader version", - gpu_info.pixel_shader_version)); - basic_info->Append(NewDescriptionValuePair("Vertex shader version", - gpu_info.vertex_shader_version)); - basic_info->Append(NewDescriptionValuePair("GL version", - gpu_info.gl_version)); - basic_info->Append(NewDescriptionValuePair("GL_VENDOR", - gpu_info.gl_vendor)); - basic_info->Append(NewDescriptionValuePair("GL_RENDERER", - gpu_info.gl_renderer)); - basic_info->Append(NewDescriptionValuePair("GL_VERSION", - gpu_info.gl_version_string)); - basic_info->Append(NewDescriptionValuePair("GL_EXTENSIONS", - gpu_info.gl_extensions)); - - DictionaryValue* info = new DictionaryValue(); - info->Set("basic_info", basic_info); - -#if defined(OS_WIN) - ListValue* perf_info = new ListValue(); - perf_info->Append(NewDescriptionValuePair( - "Graphics", - base::StringPrintf("%.1f", gpu_info.performance_stats.graphics))); - perf_info->Append(NewDescriptionValuePair( - "Gaming", - base::StringPrintf("%.1f", gpu_info.performance_stats.gaming))); - perf_info->Append(NewDescriptionValuePair( - "Overall", - base::StringPrintf("%.1f", gpu_info.performance_stats.overall))); - info->Set("performance_info", perf_info); - - Value* dx_info; - if (gpu_info.dx_diagnostics.children.size()) - dx_info = DxDiagNodeToList(gpu_info.dx_diagnostics); - else - dx_info = Value::CreateNullValue(); - info->Set("diagnostics", dx_info); -#endif - - return info; -} - -void UpdateStats() { - GpuBlacklist* blacklist = GpuBlacklist::GetInstance(); - uint32 max_entry_id = blacklist->max_entry_id(); - if (max_entry_id == 0) { - // GPU Blacklist was not loaded. No need to go further. - return; - } - - const CommandLine& command_line = *CommandLine::ForCurrentProcess(); - uint32 flags = GpuDataManager::GetInstance()->GetBlacklistedFeatures(); - bool disabled = false; - if (flags == 0) { - UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerEntry", - 0, max_entry_id + 1); - } else { - std::vector<uint32> flag_entries; - blacklist->GetGpuFeatureTypeEntries( - content::GPU_FEATURE_TYPE_ALL, flag_entries, disabled); - DCHECK_GT(flag_entries.size(), 0u); - for (size_t i = 0; i < flag_entries.size(); ++i) { - UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerEntry", - flag_entries[i], max_entry_id + 1); - } - } - - // This counts how many users are affected by a disabled entry - this allows - // us to understand the impact of an entry before enable it. - std::vector<uint32> flag_disabled_entries; - disabled = true; - blacklist->GetGpuFeatureTypeEntries( - content::GPU_FEATURE_TYPE_ALL, flag_disabled_entries, disabled); - for (size_t i = 0; i < flag_disabled_entries.size(); ++i) { - UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerDisabledEntry", - flag_disabled_entries[i], max_entry_id + 1); - } - - const content::GpuFeatureType kGpuFeatures[] = { - content::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS, - content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING, - content::GPU_FEATURE_TYPE_WEBGL - }; - const std::string kGpuBlacklistFeatureHistogramNames[] = { - "GPU.BlacklistFeatureTestResults.Accelerated2dCanvas", - "GPU.BlacklistFeatureTestResults.AcceleratedCompositing", - "GPU.BlacklistFeatureTestResults.Webgl" - }; - const bool kGpuFeatureUserFlags[] = { - command_line.HasSwitch(switches::kDisableAccelerated2dCanvas), - command_line.HasSwitch(switches::kDisableAcceleratedCompositing), -#if defined(OS_ANDROID) - !command_line.HasSwitch(switches::kEnableExperimentalWebGL) -#else - command_line.HasSwitch(switches::kDisableExperimentalWebGL) -#endif - }; -#if defined(OS_WIN) - const std::string kGpuBlacklistFeatureHistogramNamesWin[] = { - "GPU.BlacklistFeatureTestResultsWindows.Accelerated2dCanvas", - "GPU.BlacklistFeatureTestResultsWindows.AcceleratedCompositing", - "GPU.BlacklistFeatureTestResultsWindows.Webgl" - }; -#endif - const size_t kNumFeatures = - sizeof(kGpuFeatures) / sizeof(content::GpuFeatureType); - for (size_t i = 0; i < kNumFeatures; ++i) { - // We can't use UMA_HISTOGRAM_ENUMERATION here because the same name is - // expected if the macro is used within a loop. - GpuFeatureStatus value = kGpuFeatureEnabled; - if (flags & kGpuFeatures[i]) - value = kGpuFeatureBlacklisted; - else if (kGpuFeatureUserFlags[i]) - value = kGpuFeatureDisabled; - base::Histogram* histogram_pointer = base::LinearHistogram::FactoryGet( - kGpuBlacklistFeatureHistogramNames[i], - 1, kGpuFeatureNumStatus, kGpuFeatureNumStatus + 1, - base::Histogram::kUmaTargetedHistogramFlag); - histogram_pointer->Add(value); -#if defined(OS_WIN) - histogram_pointer = base::LinearHistogram::FactoryGet( - kGpuBlacklistFeatureHistogramNamesWin[i], - 1, kNumWinSubVersions * kGpuFeatureNumStatus, - kNumWinSubVersions * kGpuFeatureNumStatus + 1, - base::Histogram::kUmaTargetedHistogramFlag); - histogram_pointer->Add(GetGpuBlacklistHistogramValueWin(value)); -#endif - } -} - -} // namespace gpu_util; diff --git a/chrome/browser/gpu_util.h b/chrome/browser/gpu_util.h deleted file mode 100644 index 89924cf..0000000 --- a/chrome/browser/gpu_util.h +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_GPU_UTIL_H_ -#define CHROME_BROWSER_GPU_UTIL_H_ - -#include <string> - -#include "content/public/common/gpu_feature_type.h" - -namespace base { -class DictionaryValue; -class Value; -} - -namespace gpu_util { - -// Maps string to GpuFeatureType; returns GPU_FEATURE_TYPE_UNKNOWN if none of -// the following is input (case-sensitive): -// "accelerated_2d_canvas" -// "accelerated_compositing" -// "webgl" -// "multisampling" -content::GpuFeatureType StringToGpuFeatureType( - const std::string& feature_string); - -// Gets a string version of a feature type for use in about:gpu. Will yield -// strings from StringToGpuFeatureType, e.g. -// GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS becomes "accelerated_2d_canvas" -std::string GpuFeatureTypeToString(content::GpuFeatureType feature); - -// Returns status of various GPU features. This is two parted: -// { -// featureStatus: [] -// problems: [] -// } -// -// Each entry in feature_status has: -// { -// name: "name of feature" -// status: "enabled" | "unavailable_software" | "unavailable_off" | -// "software" | "disabled_off" | "disabled_softare"; -// } -// -// The features reported are not 1:1 with GpuFeatureType. Rather, they are: -// '2d_canvas' -// '3d_css' -// 'composting', -// 'webgl', -// 'multisampling', -// 'flash_3d', -// 'flash_stage3d', -// 'texture_sharing' -// 'video_decode' -// -// Each problems has: -// { -// "description": "Your GPU is too old", -// "crBugs": [1234], -// "webkitBugs": [] -// } -// -// Caller is responsible for deleting the returned value. -base::Value* GetFeatureStatus(); - -// Returns the GpuInfo as a DictionaryValue. -base::DictionaryValue* GpuInfoAsDictionaryValue(); - -// Send UMA histograms about the enabled features. -void UpdateStats(); - -// Sets up force-compositing-mode and threaded compositing field trials. -void InitializeCompositingFieldTrial(); - -} // namespace gpu_util - -#endif // CHROME_BROWSER_GPU_UTIL_H_ diff --git a/chrome/browser/ui/webui/gpu_internals_ui.cc b/chrome/browser/ui/webui/gpu_internals_ui.cc index 219a75b..287a68c 100644 --- a/chrome/browser/ui/webui/gpu_internals_ui.cc +++ b/chrome/browser/ui/webui/gpu_internals_ui.cc @@ -15,8 +15,6 @@ #include "base/sys_info.h" #include "base/values.h" #include "chrome/browser/crash_upload_list.h" -#include "chrome/browser/gpu_blacklist.h" -#include "chrome/browser/gpu_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/chrome_url_data_manager.h" #include "chrome/browser/ui/webui/chrome_web_ui_data_source.h" @@ -29,6 +27,9 @@ #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_message_handler.h" +#include "content/public/common/compositor_util.h" +#include "content/public/common/content_switches.h" +#include "content/public/common/gpu_info.h" #include "grit/browser_resources.h" #include "grit/generated_resources.h" #include "third_party/angle/src/common/version.h" @@ -41,11 +42,20 @@ using content::BrowserThread; using content::GpuDataManager; +using content::GpuFeatureType; using content::WebContents; using content::WebUIMessageHandler; namespace { +struct GpuFeatureInfo { + std::string name; + uint32 blocked; + bool disabled; + std::string disabled_description; + bool fallback_to_software; +}; + ChromeWebUIDataSource* CreateGpuHTMLSource() { ChromeWebUIDataSource* source = new ChromeWebUIDataSource(chrome::kChromeUIGpuInternalsHost); @@ -56,6 +66,317 @@ ChromeWebUIDataSource* CreateGpuHTMLSource() { return source; } +DictionaryValue* NewDescriptionValuePair(const std::string& desc, + const std::string& value) { + DictionaryValue* dict = new DictionaryValue(); + dict->SetString("description", desc); + dict->SetString("value", value); + return dict; +} + +DictionaryValue* NewDescriptionValuePair(const std::string& desc, + Value* value) { + DictionaryValue* dict = new DictionaryValue(); + dict->SetString("description", desc); + dict->Set("value", value); + return dict; +} + +Value* NewStatusValue(const char* name, const char* status) { + DictionaryValue* value = new DictionaryValue(); + value->SetString("name", name); + value->SetString("status", status); + return value; +} + +// Output DxDiagNode tree as nested array of {description,value} pairs +ListValue* DxDiagNodeToList(const content::DxDiagNode& node) { + ListValue* list = new ListValue(); + for (std::map<std::string, std::string>::const_iterator it = + node.values.begin(); + it != node.values.end(); + ++it) { + list->Append(NewDescriptionValuePair(it->first, it->second)); + } + + for (std::map<std::string, content::DxDiagNode>::const_iterator it = + node.children.begin(); + it != node.children.end(); + ++it) { + ListValue* sublist = DxDiagNodeToList(it->second); + list->Append(NewDescriptionValuePair(it->first, sublist)); + } + return list; +} + +std::string GPUDeviceToString(const content::GPUInfo::GPUDevice& gpu) { + std::string vendor = base::StringPrintf("0x%04x", gpu.vendor_id); + if (!gpu.vendor_string.empty()) + vendor += " [" + gpu.vendor_string + "]"; + std::string device = base::StringPrintf("0x%04x", gpu.device_id); + if (!gpu.device_string.empty()) + device += " [" + gpu.device_string + "]"; + return base::StringPrintf( + "VENDOR = %s, DEVICE= %s", vendor.c_str(), device.c_str()); +} + +DictionaryValue* GpuInfoAsDictionaryValue() { + content::GPUInfo gpu_info = GpuDataManager::GetInstance()->GetGPUInfo(); + ListValue* basic_info = new ListValue(); + basic_info->Append(NewDescriptionValuePair( + "Initialization time", + base::Int64ToString(gpu_info.initialization_time.InMilliseconds()))); + basic_info->Append(NewDescriptionValuePair( + "GPU0", GPUDeviceToString(gpu_info.gpu))); + for (size_t i = 0; i < gpu_info.secondary_gpus.size(); ++i) { + basic_info->Append(NewDescriptionValuePair( + base::StringPrintf("GPU%d", static_cast<int>(i + 1)), + GPUDeviceToString(gpu_info.secondary_gpus[i]))); + } + basic_info->Append(NewDescriptionValuePair( + "Optimus", Value::CreateBooleanValue(gpu_info.optimus))); + basic_info->Append(NewDescriptionValuePair( + "AMD switchable", Value::CreateBooleanValue(gpu_info.amd_switchable))); + basic_info->Append(NewDescriptionValuePair("Driver vendor", + gpu_info.driver_vendor)); + basic_info->Append(NewDescriptionValuePair("Driver version", + gpu_info.driver_version)); + basic_info->Append(NewDescriptionValuePair("Driver date", + gpu_info.driver_date)); + basic_info->Append(NewDescriptionValuePair("Pixel shader version", + gpu_info.pixel_shader_version)); + basic_info->Append(NewDescriptionValuePair("Vertex shader version", + gpu_info.vertex_shader_version)); + basic_info->Append(NewDescriptionValuePair("GL version", + gpu_info.gl_version)); + basic_info->Append(NewDescriptionValuePair("GL_VENDOR", + gpu_info.gl_vendor)); + basic_info->Append(NewDescriptionValuePair("GL_RENDERER", + gpu_info.gl_renderer)); + basic_info->Append(NewDescriptionValuePair("GL_VERSION", + gpu_info.gl_version_string)); + basic_info->Append(NewDescriptionValuePair("GL_EXTENSIONS", + gpu_info.gl_extensions)); + + DictionaryValue* info = new DictionaryValue(); + info->Set("basic_info", basic_info); + +#if defined(OS_WIN) + ListValue* perf_info = new ListValue(); + perf_info->Append(NewDescriptionValuePair( + "Graphics", + base::StringPrintf("%.1f", gpu_info.performance_stats.graphics))); + perf_info->Append(NewDescriptionValuePair( + "Gaming", + base::StringPrintf("%.1f", gpu_info.performance_stats.gaming))); + perf_info->Append(NewDescriptionValuePair( + "Overall", + base::StringPrintf("%.1f", gpu_info.performance_stats.overall))); + info->Set("performance_info", perf_info); + + Value* dx_info; + if (gpu_info.dx_diagnostics.children.size()) + dx_info = DxDiagNodeToList(gpu_info.dx_diagnostics); + else + dx_info = Value::CreateNullValue(); + info->Set("diagnostics", dx_info); +#endif + + return info; +} + +// Determine if accelerated-2d-canvas is supported, which depends on whether +// lose_context could happen and whether skia is the backend. +bool SupportsAccelerated2dCanvas() { + if (GpuDataManager::GetInstance()->GetGPUInfo().can_lose_context) + return false; +#if defined(USE_SKIA) + return true; +#else + return false; +#endif +} + +Value* GetFeatureStatus() { + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + bool gpu_access_blocked = !GpuDataManager::GetInstance()->GpuAccessAllowed(); + + uint32 flags = GpuDataManager::GetInstance()->GetBlacklistedFeatures(); + DictionaryValue* status = new DictionaryValue(); + + const GpuFeatureInfo kGpuFeatureInfo[] = { + { + "2d_canvas", + flags & content::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS, + command_line.HasSwitch(switches::kDisableAccelerated2dCanvas) || + !SupportsAccelerated2dCanvas(), + "Accelerated 2D canvas is unavailable: either disabled at the command" + " line or not supported by the current system.", + true + }, + { + "compositing", + flags & content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING, + command_line.HasSwitch(switches::kDisableAcceleratedCompositing), + "Accelerated compositing has been disabled, either via about:flags or" + " command line. This adversely affects performance of all hardware" + " accelerated features.", + true + }, + { + "3d_css", + flags & content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING, + command_line.HasSwitch(switches::kDisableAcceleratedLayers), + "Accelerated layers have been disabled at the command line.", + false + }, + { + "css_animation", + flags & content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING, + command_line.HasSwitch(switches::kDisableThreadedAnimation) || + command_line.HasSwitch(switches::kDisableAcceleratedCompositing), + "Accelerated CSS animation has been disabled at the command line.", + true + }, + { + "webgl", + flags & content::GPU_FEATURE_TYPE_WEBGL, +#if defined(OS_ANDROID) + !command_line.HasSwitch(switches::kEnableExperimentalWebGL), +#else + command_line.HasSwitch(switches::kDisableExperimentalWebGL), +#endif + "WebGL has been disabled, either via about:flags or command line.", + false + }, + { + "multisampling", + flags & content::GPU_FEATURE_TYPE_MULTISAMPLING, + command_line.HasSwitch(switches::kDisableGLMultisampling), + "Multisampling has been disabled, either via about:flags or command" + " line.", + false + }, + { + "flash_3d", + flags & content::GPU_FEATURE_TYPE_FLASH3D, + command_line.HasSwitch(switches::kDisableFlash3d), + "Using 3d in flash has been disabled, either via about:flags or" + " command line.", + false + }, + { + "flash_stage3d", + flags & content::GPU_FEATURE_TYPE_FLASH_STAGE3D, + command_line.HasSwitch(switches::kDisableFlashStage3d), + "Using Stage3d in Flash has been disabled, either via about:flags or" + " command line.", + false + }, + { + "texture_sharing", + flags & content::GPU_FEATURE_TYPE_TEXTURE_SHARING, + command_line.HasSwitch(switches::kDisableImageTransportSurface), + "Sharing textures between processes has been disabled, either via" + " about:flags or command line.", + false + }, + { + "video_decode", + flags & content::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE, + command_line.HasSwitch(switches::kDisableAcceleratedVideoDecode), + "Accelerated video decode has been disabled, either via about:flags" + " or command line.", + true + } + }; + const size_t kNumFeatures = sizeof(kGpuFeatureInfo) / sizeof(GpuFeatureInfo); + + // Build the feature_status field. + { + ListValue* feature_status_list = new ListValue(); + + for (size_t i = 0; i < kNumFeatures; ++i) { + std::string status; + if (kGpuFeatureInfo[i].disabled) { + status = "disabled"; + if (kGpuFeatureInfo[i].name == "css_animation") { + status += "_software_animated"; + } else { + if (kGpuFeatureInfo[i].fallback_to_software) + status += "_software"; + else + status += "_off"; + } + } else if (GpuDataManager::GetInstance()->ShouldUseSoftwareRendering()) { + status = "unavailable_software"; + } else if (kGpuFeatureInfo[i].blocked || + gpu_access_blocked) { + status = "unavailable"; + if (kGpuFeatureInfo[i].fallback_to_software) + status += "_software"; + else + status += "_off"; + } else { + status = "enabled"; + if (kGpuFeatureInfo[i].name == "webgl" && + (command_line.HasSwitch(switches::kDisableAcceleratedCompositing) || + (flags & content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING))) + status += "_readback"; + bool has_thread = content::IsThreadedCompositingEnabled(); + if (kGpuFeatureInfo[i].name == "compositing") { + bool force_compositing = + content::IsForceCompositingModeEnabled(); + if (force_compositing) + status += "_force"; + if (has_thread) + status += "_threaded"; + } + if (kGpuFeatureInfo[i].name == "css_animation") { + if (has_thread) + status = "accelerated_threaded"; + else + status = "accelerated"; + } + } + feature_status_list->Append( + NewStatusValue(kGpuFeatureInfo[i].name.c_str(), status.c_str())); + } + + status->Set("featureStatus", feature_status_list); + } + + // Build the problems list. + { + ListValue* problem_list = + GpuDataManager::GetInstance()->GetBlacklistReasons(); + + if (gpu_access_blocked) { + DictionaryValue* problem = new DictionaryValue(); + problem->SetString("description", + "GPU process was unable to boot. Access to GPU disallowed."); + problem->Set("crBugs", new ListValue()); + problem->Set("webkitBugs", new ListValue()); + problem_list->Append(problem); + } + + for (size_t i = 0; i < kNumFeatures; ++i) { + if (kGpuFeatureInfo[i].disabled) { + DictionaryValue* problem = new DictionaryValue(); + problem->SetString( + "description", kGpuFeatureInfo[i].disabled_description); + problem->Set("crBugs", new ListValue()); + problem->Set("webkitBugs", new ListValue()); + problem_list->Append(problem); + } + } + + status->Set("problems", problem_list); + } + + return status; +} + // This class receives javascript messages from the renderer. // Note that the WebUI infrastructure runs on the UI thread, therefore all of // this class's methods are expected to run on the UI thread. @@ -240,7 +561,7 @@ Value* GpuMessageHandler::OnRequestClientInfo(const ListValue* list) { dict->SetString("graphics_backend", "Core Graphics"); #endif dict->SetString("blacklist_version", - GpuBlacklist::GetInstance()->GetVersion()); + GpuDataManager::GetInstance()->GetBlacklistVersion()); return dict; } @@ -310,10 +631,10 @@ Value* GpuMessageHandler::OnRequestCrashList(const ListValue*) { void GpuMessageHandler::OnGpuInfoUpdate() { // Get GPU Info. scoped_ptr<base::DictionaryValue> gpu_info_val( - gpu_util::GpuInfoAsDictionaryValue()); + GpuInfoAsDictionaryValue()); // Add in blacklisting features - Value* feature_status = gpu_util::GetFeatureStatus(); + Value* feature_status = GetFeatureStatus(); if (feature_status) gpu_info_val->Set("featureStatus", feature_status); diff --git a/chrome/browser/ui/webui/tracing_ui.cc b/chrome/browser/ui/webui/tracing_ui.cc index 584cd30..9e61fee 100644 --- a/chrome/browser/ui/webui/tracing_ui.cc +++ b/chrome/browser/ui/webui/tracing_ui.cc @@ -15,8 +15,6 @@ #include "base/string_number_conversions.h" #include "base/stringprintf.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/gpu_blacklist.h" -#include "chrome/browser/gpu_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/chrome_select_file_policy.h" #include "chrome/browser/ui/webui/chrome_url_data_manager.h" @@ -70,8 +68,7 @@ class TracingMessageHandler : public WebUIMessageHandler, public ui::SelectFileDialog::Listener, public base::SupportsWeakPtr<TracingMessageHandler>, - public content::TraceSubscriber, - public content::GpuDataManagerObserver { + public content::TraceSubscriber { public: TracingMessageHandler(); virtual ~TracingMessageHandler(); @@ -89,11 +86,6 @@ class TracingMessageHandler const scoped_refptr<base::RefCountedString>& trace_fragment); virtual void OnTraceBufferPercentFullReply(float percent_full); - // GpuDataManagerObserver implementation. - virtual void OnGpuInfoUpdate() OVERRIDE; - virtual void OnVideoMemoryUsageStatsUpdate( - const content::GPUVideoMemoryUsageStats& video_memory) OVERRIDE {} - // Messages. void OnTracingControllerInitialized(const ListValue* list); void OnBeginTracing(const ListValue* list); @@ -123,10 +115,6 @@ class TracingMessageHandler // True while system tracing is active. bool system_trace_in_progress_; - // True if observing the GpuDataManager (re-attaching as observer would - // DCHECK). - bool observing_; - void OnEndSystemTracingAck( const scoped_refptr<base::RefCountedString>& events_str_ptr); @@ -169,13 +157,10 @@ class TaskProxy : public base::RefCountedThreadSafe<TaskProxy> { TracingMessageHandler::TracingMessageHandler() : select_trace_file_dialog_type_(ui::SelectFileDialog::SELECT_NONE), trace_enabled_(false), - system_trace_in_progress_(false), - observing_(false) { + system_trace_in_progress_(false) { } TracingMessageHandler::~TracingMessageHandler() { - GpuDataManager::GetInstance()->RemoveObserver(this); - if (select_trace_file_dialog_) select_trace_file_dialog_->ListenerDestroyed(); @@ -219,19 +204,6 @@ void TracingMessageHandler::OnTracingControllerInitialized( const ListValue* args) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - // Watch for changes in GPUInfo - if (!observing_) - GpuDataManager::GetInstance()->AddObserver(this); - observing_ = true; - - // Tell GpuDataManager it should have full GpuInfo. If the - // Gpu process has not run yet, this will trigger its launch. - GpuDataManager::GetInstance()->RequestCompleteGpuInfoIfNeeded(); - - // Run callback immediately in case the info is ready and no update in the - // future. - OnGpuInfoUpdate(); - // Send the client info to the tracingController { scoped_ptr<DictionaryValue> dict(new DictionaryValue()); @@ -256,7 +228,7 @@ void TracingMessageHandler::OnTracingControllerInitialized( } dict->SetString("blacklist_version", - GpuBlacklist::GetInstance()->GetVersion()); + GpuDataManager::GetInstance()->GetBlacklistVersion()); web_ui()->CallJavascriptFunction("tracingController.onClientInfoUpdate", *dict); } @@ -267,21 +239,6 @@ void TracingMessageHandler::OnBeginRequestBufferPercentFull( TraceController::GetInstance()->GetTraceBufferPercentFullAsync(this); } -void TracingMessageHandler::OnGpuInfoUpdate() { - // Get GPU Info. - scoped_ptr<base::DictionaryValue> gpu_info_val( - gpu_util::GpuInfoAsDictionaryValue()); - - // Add in blacklisting features - Value* feature_status = gpu_util::GetFeatureStatus(); - if (feature_status) - gpu_info_val->Set("featureStatus", feature_status); - - // Send GPU Info to javascript. - web_ui()->CallJavascriptFunction("tracingController.onGpuInfoUpdate", - *(gpu_info_val.get())); -} - // A callback used for asynchronously reading a file to a string. Calls the // TaskProxy callback when reading is complete. void ReadTraceFileCallback(TaskProxy* proxy, const FilePath& path) { diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index abc2fe3..841f067 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -443,6 +443,8 @@ 'browser/chrome_browser_main_x11.h', 'browser/chrome_content_browser_client.cc', 'browser/chrome_content_browser_client.h', + 'browser/chrome_gpu_util.cc', + 'browser/chrome_gpu_util.h', 'browser/chrome_page_zoom.cc', 'browser/chrome_page_zoom.h', 'browser/chrome_page_zoom_constants.cc', @@ -654,12 +656,8 @@ 'browser/google/google_url_tracker_factory.h', 'browser/google/google_util.cc', 'browser/google/google_util.h', - 'browser/gpu_blacklist.cc', - 'browser/gpu_blacklist.h', 'browser/gpu_feature_checker.cc', 'browser/gpu_feature_checker.h', - 'browser/gpu_util.cc', - 'browser/gpu_util.h', 'browser/hang_monitor/hang_crash_dump_win.cc', 'browser/hang_monitor/hang_crash_dump_win.h', 'browser/hang_monitor/hung_plugin_action.cc', diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 6c1da7e..5e9fc82 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -1329,8 +1329,6 @@ 'browser/google/google_update_settings_unittest.cc', 'browser/google/google_url_tracker_unittest.cc', 'browser/google/google_util_unittest.cc', - 'browser/gpu_blacklist_unittest.cc', - 'browser/gpu_util_unittest.cc', 'browser/history/android/android_cache_database_unittest.cc', 'browser/history/android/android_history_provider_service_unittest.cc', 'browser/history/android/android_history_types_unittest.cc', diff --git a/chrome/test/gpu/gpu_feature_browsertest.cc b/chrome/test/gpu/gpu_feature_browsertest.cc index ce486c1..3382f92 100644 --- a/chrome/test/gpu/gpu_feature_browsertest.cc +++ b/chrome/test/gpu/gpu_feature_browsertest.cc @@ -8,7 +8,6 @@ #include "base/path_service.h" #include "base/test/trace_event_analyzer.h" #include "base/version.h" -#include "chrome/browser/gpu_blacklist.h" #include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" @@ -67,10 +66,7 @@ class GpuFeatureTest : public InProcessBrowserTest { } void SetupBlacklist(const std::string& json_blacklist) { - GpuBlacklist* blacklist = GpuBlacklist::GetInstance(); - ASSERT_TRUE(blacklist->LoadGpuBlacklist( - json_blacklist, GpuBlacklist::kAllOs)); - blacklist->UpdateGpuDataManager(); + GpuDataManager::GetInstance()->Initialize("0", json_blacklist); } // If expected_reply is NULL, we don't check the reply content. diff --git a/chrome/browser/gpu_blacklist.cc b/content/browser/gpu/gpu_blacklist.cc index 39f228e..403a894 100644 --- a/chrome/browser/gpu_blacklist.cc +++ b/content/browser/gpu/gpu_blacklist.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/gpu_blacklist.h" +#include "content/browser/gpu/gpu_blacklist.h" #include "base/command_line.h" #include "base/json/json_reader.h" @@ -12,13 +12,10 @@ #include "base/string_util.h" #include "base/sys_info.h" #include "base/version.h" -#include "chrome/browser/gpu_util.h" -#include "chrome/common/chrome_version_info.h" -#include "content/public/browser/gpu_data_manager.h" +#include "content/browser/gpu/gpu_util.h" #include "content/public/common/content_switches.h" #include "content/public/common/gpu_info.h" -using content::GpuDataManager; using content::GpuFeatureType; namespace { @@ -919,28 +916,19 @@ GpuFeatureType GpuBlacklist::GpuBlacklistEntry::GetGpuFeatureType() const { return feature_type_; } -// static -GpuBlacklist* GpuBlacklist::GetInstance() { - return Singleton<GpuBlacklist>::get(); -} - GpuBlacklist::GpuBlacklist() : max_entry_id_(0), contains_unknown_fields_(false) { - GpuDataManager::GetInstance()->AddObserver(this); } GpuBlacklist::~GpuBlacklist() { Clear(); - GpuDataManager::GetInstance()->RemoveObserver(this); } bool GpuBlacklist::LoadGpuBlacklist( const std::string& json_context, GpuBlacklist::OsFilter os_filter) { - chrome::VersionInfo chrome_version_info; - std::string chrome_version_string = - chrome_version_info.is_valid() ? chrome_version_info.Version() : "0"; - return LoadGpuBlacklist(chrome_version_string, json_context, os_filter); + const std::string browser_version_string = "0"; + return LoadGpuBlacklist(browser_version_string, json_context, os_filter); } bool GpuBlacklist::LoadGpuBlacklist( @@ -1050,14 +1038,6 @@ GpuFeatureType GpuBlacklist::DetermineGpuFeatureType( return static_cast<GpuFeatureType>(type); } -void GpuBlacklist::UpdateGpuDataManager() { - content::GpuFeatureType feature_type = DetermineGpuFeatureType( - GpuBlacklist::kOsAny, NULL, GpuDataManager::GetInstance()->GetGPUInfo()); - GpuDataManager::GetInstance()->SetPreliminaryBlacklistedFeatures( - feature_type); - gpu_util::UpdateStats(); -} - void GpuBlacklist::GetGpuFeatureTypeEntries( content::GpuFeatureType feature, std::vector<uint32>& entry_ids, @@ -1163,10 +1143,6 @@ GpuBlacklist::IsEntrySupportedByCurrentBrowserVersion( return kSupported; } -void GpuBlacklist::OnGpuInfoUpdate() { - UpdateGpuDataManager(); -} - // static GpuBlacklist::NumericOp GpuBlacklist::StringToNumericOp( const std::string& op) { diff --git a/chrome/browser/gpu_blacklist.h b/content/browser/gpu/gpu_blacklist.h index c4c72c7..61801c3 100644 --- a/chrome/browser/gpu_blacklist.h +++ b/content/browser/gpu/gpu_blacklist.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_GPU_BLACKLIST_H_ -#define CHROME_BROWSER_GPU_BLACKLIST_H_ +#ifndef CONTENT_BROWSER_GPU_GPU_BLACKLIST_H_ +#define CONTENT_BROWSER_GPU_GPU_BLACKLIST_H_ #include <string> #include <vector> @@ -12,9 +12,9 @@ #include "base/gtest_prod_util.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" -#include "base/memory/singleton.h" #include "base/values.h" -#include "content/public/browser/gpu_data_manager_observer.h" +#include "build/build_config.h" +#include "content/common/content_export.h" #include "content/public/common/gpu_feature_type.h" class Version; @@ -23,7 +23,7 @@ namespace content { struct GPUInfo; } -class GpuBlacklist : public content::GpuDataManagerObserver { +class CONTENT_EXPORT GpuBlacklist { public: enum OsType { kOsLinux, @@ -41,14 +41,14 @@ class GpuBlacklist : public content::GpuDataManagerObserver { kAllOs }; - // Getter for the singleton. This will return NULL on failure. - static GpuBlacklist* GetInstance(); - + GpuBlacklist(); virtual ~GpuBlacklist(); // Loads blacklist information from a json file. // If failed, the current GpuBlacklist is un-touched. - bool LoadGpuBlacklist(const std::string& json_context, + bool LoadGpuBlacklist(const std::string& json_context, OsFilter os_filter); + bool LoadGpuBlacklist(const std::string& browser_version_string, + const std::string& json_context, OsFilter os_filter); // Collects system information and combines them with gpu_info and blacklist @@ -58,10 +58,6 @@ class GpuBlacklist : public content::GpuDataManagerObserver { content::GpuFeatureType DetermineGpuFeatureType( OsType os, Version* os_version, const content::GPUInfo& gpu_info); - // Helper function that calls DetermineGpuFeatureType and sets the updated - // features on GpuDataManager. - void UpdateGpuDataManager(); - // Collects the active entries that set the "feature" flag from the last // DetermineGpuFeatureType() call. This tells which entries are responsible // for raising a certain flag, i.e, for blacklisting a certain feature. @@ -95,7 +91,6 @@ class GpuBlacklist : public content::GpuDataManagerObserver { private: friend class GpuBlacklistTest; - friend struct DefaultSingletonTraits<GpuBlacklist>; FRIEND_TEST_ALL_PREFIXES(GpuBlacklistTest, ChromeVersionEntry); FRIEND_TEST_ALL_PREFIXES(GpuBlacklistTest, CurrentBlacklistValidation); FRIEND_TEST_ALL_PREFIXES(GpuBlacklistTest, UnknownField); @@ -366,12 +361,6 @@ class GpuBlacklist : public content::GpuDataManagerObserver { // Gets the current OS type. static OsType GetOsType(); - GpuBlacklist(); - - bool LoadGpuBlacklist(const std::string& browser_version_string, - const std::string& json_context, - OsFilter os_filter); - bool LoadGpuBlacklist(const base::DictionaryValue& parsed_json, OsFilter os_filter); @@ -383,11 +372,6 @@ class GpuBlacklist : public content::GpuDataManagerObserver { BrowserVersionSupport IsEntrySupportedByCurrentBrowserVersion( const base::DictionaryValue* value); - // GpuDataManager::Observer implementation. - virtual void OnGpuInfoUpdate() OVERRIDE; - virtual void OnVideoMemoryUsageStatsUpdate( - const content::GPUVideoMemoryUsageStats& video_memory) OVERRIDE {} - // Returns the number of entries. This is only for tests. size_t num_entries() const; @@ -413,4 +397,5 @@ class GpuBlacklist : public content::GpuDataManagerObserver { DISALLOW_COPY_AND_ASSIGN(GpuBlacklist); }; -#endif // CHROME_BROWSER_GPU_BLACKLIST_H_ +#endif // CONTENT_BROWSER_GPU_GPU_BLACKLIST_H_ + diff --git a/chrome/browser/gpu_blacklist_unittest.cc b/content/browser/gpu/gpu_blacklist_unittest.cc index 403a81f..6e921b8 100644 --- a/chrome/browser/gpu_blacklist_unittest.cc +++ b/content/browser/gpu/gpu_blacklist_unittest.cc @@ -10,8 +10,7 @@ #include "base/memory/scoped_ptr.h" #include "base/path_service.h" #include "base/version.h" -#include "chrome/browser/gpu_blacklist.h" -#include "content/public/browser/gpu_data_manager.h" +#include "content/browser/gpu/gpu_blacklist.h" #include "content/public/common/gpu_info.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/content/browser/gpu/gpu_data_manager_impl.cc b/content/browser/gpu/gpu_data_manager_impl.cc index 44dfe6a..d1aef13 100644 --- a/content/browser/gpu/gpu_data_manager_impl.cc +++ b/content/browser/gpu/gpu_data_manager_impl.cc @@ -13,6 +13,7 @@ #include "base/values.h" #include "base/version.h" #include "content/browser/gpu/gpu_process_host.h" +#include "content/browser/gpu/gpu_util.h" #include "content/common/gpu/gpu_messages.h" #include "content/gpu/gpu_info_collector.h" #include "content/public/browser/browser_thread.h" @@ -58,14 +59,24 @@ GpuDataManagerImpl::GpuDataManagerImpl() BlacklistCard(); } -void GpuDataManagerImpl::InitializeGpuInfo() { +void GpuDataManagerImpl::Initialize( + const std::string& browser_version_string, + const std::string& gpu_blacklist_json) { content::GPUInfo gpu_info; - if (!CommandLine::ForCurrentProcess()->HasSwitch( - switches::kSkipGpuDataLoading)) - gpu_info_collector::CollectPreliminaryGraphicsInfo(&gpu_info); - else - gpu_info.finalized = true; + gpu_info_collector::CollectPreliminaryGraphicsInfo(&gpu_info); + + if (!gpu_blacklist_json.empty()) { + CHECK(!browser_version_string.empty()); + gpu_blacklist_.reset(new GpuBlacklist()); + bool succeed = gpu_blacklist_->LoadGpuBlacklist( + browser_version_string, + gpu_blacklist_json, + GpuBlacklist::kCurrentOsOnly); + CHECK(succeed); + } + UpdateGpuInfo(gpu_info); + UpdatePreliminaryBlacklistedFeatures(); } GpuDataManagerImpl::~GpuDataManagerImpl() { @@ -92,6 +103,15 @@ void GpuDataManagerImpl::UpdateGpuInfo(const content::GPUInfo& gpu_info) { content::GetContentClient()->SetGpuInfo(gpu_info); + if (gpu_blacklist_.get()) { + GpuFeatureType feature_type = gpu_blacklist_->DetermineGpuFeatureType( + GpuBlacklist::kOsAny, + NULL, + GpuDataManager::GetInstance()->GetGPUInfo()); + gpu_util::UpdateStats(gpu_blacklist_.get(), feature_type); + UpdateBlacklistedFeatures(feature_type); + } + { base::AutoLock auto_lock(gpu_info_lock_); gpu_info_ = gpu_info; @@ -142,6 +162,12 @@ base::ListValue* GpuDataManagerImpl::GetLogMessages() const { return value; } +std::string GpuDataManagerImpl::GetBlacklistVersion() const { + if (gpu_blacklist_.get()) + return gpu_blacklist_->GetVersion(); + return "0"; +} + GpuFeatureType GpuDataManagerImpl::GetBlacklistedFeatures() const { if (software_rendering_) { GpuFeatureType flags; @@ -155,6 +181,13 @@ GpuFeatureType GpuDataManagerImpl::GetBlacklistedFeatures() const { return gpu_feature_type_; } +base::ListValue* GpuDataManagerImpl::GetBlacklistReasons() const { + ListValue* reasons = new ListValue(); + if (gpu_blacklist_.get()) + gpu_blacklist_->GetBlacklistReasons(reasons); + return reasons; +} + bool GpuDataManagerImpl::GpuAccessAllowed() const { if (software_rendering_) return true; @@ -308,9 +341,7 @@ void GpuDataManagerImpl::AppendPluginCommandLine( #endif } -void GpuDataManagerImpl::SetPreliminaryBlacklistedFeatures( - GpuFeatureType feature_type) { - UpdateBlacklistedFeatures(feature_type); +void GpuDataManagerImpl::UpdatePreliminaryBlacklistedFeatures() { preliminary_gpu_feature_type_ = gpu_feature_type_; } diff --git a/content/browser/gpu/gpu_data_manager_impl.h b/content/browser/gpu/gpu_data_manager_impl.h index f7f0989..7015bc9 100644 --- a/content/browser/gpu/gpu_data_manager_impl.h +++ b/content/browser/gpu/gpu_data_manager_impl.h @@ -16,6 +16,7 @@ #include "base/observer_list_threadsafe.h" #include "base/synchronization/lock.h" #include "base/values.h" +#include "content/browser/gpu/gpu_blacklist.h" #include "content/public/browser/gpu_data_manager.h" #include "content/public/common/gpu_info.h" #include "content/public/common/gpu_memory_stats.h" @@ -29,10 +30,12 @@ class CONTENT_EXPORT GpuDataManagerImpl static GpuDataManagerImpl* GetInstance(); // GpuDataManager implementation. - virtual void InitializeGpuInfo() OVERRIDE; + virtual void Initialize( + const std::string& browser_version_string, + const std::string& gpu_blacklist_json) OVERRIDE; virtual content::GpuFeatureType GetBlacklistedFeatures() const OVERRIDE; - virtual void SetPreliminaryBlacklistedFeatures( - content::GpuFeatureType features) OVERRIDE; + virtual base::ListValue* GetBlacklistReasons() const OVERRIDE; + virtual std::string GetBlacklistVersion() const OVERRIDE; virtual content::GPUInfo GetGPUInfo() const OVERRIDE; virtual bool GpuAccessAllowed() const OVERRIDE; virtual void RequestCompleteGpuInfoIfNeeded() OVERRIDE; @@ -47,7 +50,8 @@ class CONTENT_EXPORT GpuDataManagerImpl virtual void RemoveObserver( content::GpuDataManagerObserver* observer) OVERRIDE; - // Only update if the current GPUInfo is not finalized. + // Only update if the current GPUInfo is not finalized. If blacklist is + // loaded, run through blacklist and update blacklisted features. void UpdateGpuInfo(const content::GPUInfo& gpu_info); void UpdateVideoMemoryUsageStats( @@ -91,16 +95,21 @@ class CONTENT_EXPORT GpuDataManagerImpl GpuDataManagerImpl(); virtual ~GpuDataManagerImpl(); - // If flags hasn't been set and GPUInfo is available, run through blacklist - // and compute the flags. void UpdateBlacklistedFeatures(content::GpuFeatureType features); + // This should only be called once at initialization time, when preliminary + // gpu info is collected. + void UpdatePreliminaryBlacklistedFeatures(); + // Notify all observers whenever there is a GPU info update. void NotifyGpuInfoUpdate(); // Try to switch to software rendering, if possible and necessary. void EnableSoftwareRenderingIfNecessary(); + // Send UMA histograms about the disabled/enabled features. + void UpdateStats(); + bool complete_gpu_info_already_requested_; content::GpuFeatureType gpu_feature_type_; @@ -109,6 +118,8 @@ class CONTENT_EXPORT GpuDataManagerImpl content::GPUInfo gpu_info_; mutable base::Lock gpu_info_lock_; + scoped_ptr<GpuBlacklist> gpu_blacklist_; + const scoped_refptr<GpuDataManagerObserverList> observer_list_; ListValue log_messages_; diff --git a/content/browser/gpu/gpu_data_manager_impl_unittest.cc b/content/browser/gpu/gpu_data_manager_impl_unittest.cc index ea3d216..29b37c3 100644 --- a/content/browser/gpu/gpu_data_manager_impl_unittest.cc +++ b/content/browser/gpu/gpu_data_manager_impl_unittest.cc @@ -69,8 +69,9 @@ TEST_F(GpuDataManagerImplTest, GpuSideBlacklisting) { EXPECT_EQ(0, manager->GetBlacklistedFeatures()); EXPECT_TRUE(manager->GpuAccessAllowed()); - manager->SetPreliminaryBlacklistedFeatures( + manager->UpdateBlacklistedFeatures( content::GPU_FEATURE_TYPE_WEBGL); + manager->UpdatePreliminaryBlacklistedFeatures(); EXPECT_TRUE(manager->GpuAccessAllowed()); EXPECT_EQ(content::GPU_FEATURE_TYPE_WEBGL, manager->GetBlacklistedFeatures()); diff --git a/content/browser/gpu/gpu_util.cc b/content/browser/gpu/gpu_util.cc new file mode 100644 index 0000000..267b2b4 --- /dev/null +++ b/content/browser/gpu/gpu_util.cc @@ -0,0 +1,223 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/gpu/gpu_util.h" + +#include <vector> + +#include "base/command_line.h" +#include "base/metrics/histogram.h" +#include "base/string_util.h" +#include "base/sys_info.h" +#include "base/version.h" +#include "content/browser/gpu/gpu_blacklist.h" +#include "content/public/common/content_switches.h" + +using content::GpuFeatureType; + +namespace { + +const char kGpuFeatureNameAccelerated2dCanvas[] = "accelerated_2d_canvas"; +const char kGpuFeatureNameAcceleratedCompositing[] = "accelerated_compositing"; +const char kGpuFeatureNameWebgl[] = "webgl"; +const char kGpuFeatureNameMultisampling[] = "multisampling"; +const char kGpuFeatureNameFlash3d[] = "flash_3d"; +const char kGpuFeatureNameFlashStage3d[] = "flash_stage3d"; +const char kGpuFeatureNameTextureSharing[] = "texture_sharing"; +const char kGpuFeatureNameAcceleratedVideoDecode[] = "accelerated_video_decode"; +const char kGpuFeatureNameAll[] = "all"; +const char kGpuFeatureNameUnknown[] = "unknown"; + +enum GpuFeatureStatus { + kGpuFeatureEnabled = 0, + kGpuFeatureBlacklisted = 1, + kGpuFeatureDisabled = 2, // disabled by user but not blacklisted + kGpuFeatureNumStatus +}; + +#if defined(OS_WIN) + +enum WinSubVersion { + kWinOthers = 0, + kWinXP, + kWinVista, + kWin7, + kNumWinSubVersions +}; + +int GetGpuBlacklistHistogramValueWin(GpuFeatureStatus status) { + static WinSubVersion sub_version = kNumWinSubVersions; + if (sub_version == kNumWinSubVersions) { + sub_version = kWinOthers; + std::string version_str = base::SysInfo::OperatingSystemVersion(); + size_t pos = version_str.find_first_not_of("0123456789."); + if (pos != std::string::npos) + version_str = version_str.substr(0, pos); + Version os_version(version_str); + if (os_version.IsValid() && os_version.components().size() >= 2) { + const std::vector<uint16>& version_numbers = os_version.components(); + if (version_numbers[0] == 5) + sub_version = kWinXP; + else if (version_numbers[0] == 6 && version_numbers[1] == 0) + sub_version = kWinVista; + else if (version_numbers[0] == 6 && version_numbers[1] == 1) + sub_version = kWin7; + } + } + int entry_index = static_cast<int>(sub_version) * kGpuFeatureNumStatus; + switch (status) { + case kGpuFeatureEnabled: + break; + case kGpuFeatureBlacklisted: + entry_index++; + break; + case kGpuFeatureDisabled: + entry_index += 2; + break; + } + return entry_index; +} +#endif // OS_WIN + +} // namespace + +namespace gpu_util { + +GpuFeatureType StringToGpuFeatureType(const std::string& feature_string) { + if (feature_string == kGpuFeatureNameAccelerated2dCanvas) + return content::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS; + else if (feature_string == kGpuFeatureNameAcceleratedCompositing) + return content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING; + else if (feature_string == kGpuFeatureNameWebgl) + return content::GPU_FEATURE_TYPE_WEBGL; + else if (feature_string == kGpuFeatureNameMultisampling) + return content::GPU_FEATURE_TYPE_MULTISAMPLING; + else if (feature_string == kGpuFeatureNameFlash3d) + return content::GPU_FEATURE_TYPE_FLASH3D; + else if (feature_string == kGpuFeatureNameFlashStage3d) + return content::GPU_FEATURE_TYPE_FLASH_STAGE3D; + else if (feature_string == kGpuFeatureNameTextureSharing) + return content::GPU_FEATURE_TYPE_TEXTURE_SHARING; + else if (feature_string == kGpuFeatureNameAcceleratedVideoDecode) + return content::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE; + else if (feature_string == kGpuFeatureNameAll) + return content::GPU_FEATURE_TYPE_ALL; + return content::GPU_FEATURE_TYPE_UNKNOWN; +} + +std::string GpuFeatureTypeToString(GpuFeatureType type) { + std::vector<std::string> matches; + if (type == content::GPU_FEATURE_TYPE_ALL) { + matches.push_back(kGpuFeatureNameAll); + } else { + if (type & content::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS) + matches.push_back(kGpuFeatureNameAccelerated2dCanvas); + if (type & content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) + matches.push_back(kGpuFeatureNameAcceleratedCompositing); + if (type & content::GPU_FEATURE_TYPE_WEBGL) + matches.push_back(kGpuFeatureNameWebgl); + if (type & content::GPU_FEATURE_TYPE_MULTISAMPLING) + matches.push_back(kGpuFeatureNameMultisampling); + if (type & content::GPU_FEATURE_TYPE_FLASH3D) + matches.push_back(kGpuFeatureNameFlash3d); + if (type & content::GPU_FEATURE_TYPE_FLASH_STAGE3D) + matches.push_back(kGpuFeatureNameFlashStage3d); + if (type & content::GPU_FEATURE_TYPE_TEXTURE_SHARING) + matches.push_back(kGpuFeatureNameTextureSharing); + if (type & content::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE) + matches.push_back(kGpuFeatureNameAcceleratedVideoDecode); + if (!matches.size()) + matches.push_back(kGpuFeatureNameUnknown); + } + return JoinString(matches, ','); +} + +void UpdateStats(const GpuBlacklist* blacklist, + uint32 blacklisted_features) { + uint32 max_entry_id = blacklist->max_entry_id(); + if (max_entry_id == 0) { + // GPU Blacklist was not loaded. No need to go further. + return; + } + + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + bool disabled = false; + if (blacklisted_features == 0) { + UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerEntry", + 0, max_entry_id + 1); + } else { + std::vector<uint32> flag_entries; + blacklist->GetGpuFeatureTypeEntries( + content::GPU_FEATURE_TYPE_ALL, flag_entries, disabled); + DCHECK_GT(flag_entries.size(), 0u); + for (size_t i = 0; i < flag_entries.size(); ++i) { + UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerEntry", + flag_entries[i], max_entry_id + 1); + } + } + + // This counts how many users are affected by a disabled entry - this allows + // us to understand the impact of an entry before enable it. + std::vector<uint32> flag_disabled_entries; + disabled = true; + blacklist->GetGpuFeatureTypeEntries( + content::GPU_FEATURE_TYPE_ALL, flag_disabled_entries, disabled); + for (size_t i = 0; i < flag_disabled_entries.size(); ++i) { + UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerDisabledEntry", + flag_disabled_entries[i], max_entry_id + 1); + } + + const content::GpuFeatureType kGpuFeatures[] = { + content::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS, + content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING, + content::GPU_FEATURE_TYPE_WEBGL + }; + const std::string kGpuBlacklistFeatureHistogramNames[] = { + "GPU.BlacklistFeatureTestResults.Accelerated2dCanvas", + "GPU.BlacklistFeatureTestResults.AcceleratedCompositing", + "GPU.BlacklistFeatureTestResults.Webgl" + }; + const bool kGpuFeatureUserFlags[] = { + command_line.HasSwitch(switches::kDisableAccelerated2dCanvas), + command_line.HasSwitch(switches::kDisableAcceleratedCompositing), +#if defined(OS_ANDROID) + !command_line.HasSwitch(switches::kEnableExperimentalWebGL) +#else + command_line.HasSwitch(switches::kDisableExperimentalWebGL) +#endif + }; +#if defined(OS_WIN) + const std::string kGpuBlacklistFeatureHistogramNamesWin[] = { + "GPU.BlacklistFeatureTestResultsWindows.Accelerated2dCanvas", + "GPU.BlacklistFeatureTestResultsWindows.AcceleratedCompositing", + "GPU.BlacklistFeatureTestResultsWindows.Webgl" + }; +#endif + const size_t kNumFeatures = + sizeof(kGpuFeatures) / sizeof(content::GpuFeatureType); + for (size_t i = 0; i < kNumFeatures; ++i) { + // We can't use UMA_HISTOGRAM_ENUMERATION here because the same name is + // expected if the macro is used within a loop. + GpuFeatureStatus value = kGpuFeatureEnabled; + if (blacklisted_features & kGpuFeatures[i]) + value = kGpuFeatureBlacklisted; + else if (kGpuFeatureUserFlags[i]) + value = kGpuFeatureDisabled; + base::Histogram* histogram_pointer = base::LinearHistogram::FactoryGet( + kGpuBlacklistFeatureHistogramNames[i], + 1, kGpuFeatureNumStatus, kGpuFeatureNumStatus + 1, + base::Histogram::kUmaTargetedHistogramFlag); + histogram_pointer->Add(value); +#if defined(OS_WIN) + histogram_pointer = base::LinearHistogram::FactoryGet( + kGpuBlacklistFeatureHistogramNamesWin[i], + 1, kNumWinSubVersions * kGpuFeatureNumStatus, + kNumWinSubVersions * kGpuFeatureNumStatus + 1, + base::Histogram::kUmaTargetedHistogramFlag); + histogram_pointer->Add(GetGpuBlacklistHistogramValueWin(value)); +#endif + } +} + +} // namespace gpu_util; diff --git a/content/browser/gpu/gpu_util.h b/content/browser/gpu/gpu_util.h new file mode 100644 index 0000000..f8245c7 --- /dev/null +++ b/content/browser/gpu/gpu_util.h @@ -0,0 +1,41 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_GPU_GPU_UTIL_H_ +#define CONTENT_BROWSER_GPU_GPU_UTIL_H_ + +#include <string> + +#include "base/basictypes.h" +#include "build/build_config.h" +#include "content/common/content_export.h" +#include "content/public/common/gpu_feature_type.h" + +class GpuBlacklist; + +namespace gpu_util { + +// Maps string to GpuFeatureType; returns GPU_FEATURE_TYPE_UNKNOWN if none of +// the following is input (case-sensitive): +// "accelerated_2d_canvas" +// "accelerated_compositing" +// "webgl" +// "multisampling" +CONTENT_EXPORT content::GpuFeatureType StringToGpuFeatureType( + const std::string& feature_string); + +// Gets a string version of a feature type for use in about:gpu. Will yield +// strings from StringToGpuFeatureType, e.g. +// GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS becomes "accelerated_2d_canvas" +CONTENT_EXPORT std::string GpuFeatureTypeToString( + content::GpuFeatureType feature); + +// Send UMA histograms about the enabled features. +CONTENT_EXPORT void UpdateStats( + const GpuBlacklist* blacklist, uint32 blacklisted_features); + +} // namespace gpu_util + +#endif // CONTENT_BROWSER_GPU_GPU_UTIL_H_ + diff --git a/chrome/browser/gpu_util_unittest.cc b/content/browser/gpu/gpu_util_unittest.cc index affa587..b92b5f8 100644 --- a/chrome/browser/gpu_util_unittest.cc +++ b/content/browser/gpu/gpu_util_unittest.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/gpu_util.h" +#include "content/browser/gpu/gpu_util.h" #include "testing/gtest/include/gtest/gtest.h" using content::GpuFeatureType; @@ -17,6 +17,14 @@ TEST(GpuUtilsTest, GpuFeatureTypFromString) { content::GPU_FEATURE_TYPE_WEBGL); EXPECT_EQ(gpu_util::StringToGpuFeatureType("multisampling"), content::GPU_FEATURE_TYPE_MULTISAMPLING); + EXPECT_EQ(gpu_util::StringToGpuFeatureType("flash_3d"), + content::GPU_FEATURE_TYPE_FLASH3D); + EXPECT_EQ(gpu_util::StringToGpuFeatureType("flash_stage3d"), + content::GPU_FEATURE_TYPE_FLASH_STAGE3D); + EXPECT_EQ(gpu_util::StringToGpuFeatureType("texture_sharing"), + content::GPU_FEATURE_TYPE_TEXTURE_SHARING); + EXPECT_EQ(gpu_util::StringToGpuFeatureType("accelerated_video_decode"), + content::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE); EXPECT_EQ(gpu_util::StringToGpuFeatureType("all"), content::GPU_FEATURE_TYPE_ALL); EXPECT_EQ(gpu_util::StringToGpuFeatureType("xxx"), @@ -43,6 +51,22 @@ TEST(GpuUtilsTest, GpuFeatureTypeToString) { "multisampling"); EXPECT_STREQ( gpu_util::GpuFeatureTypeToString( + content::GPU_FEATURE_TYPE_FLASH3D).c_str(), + "flash_3d"); + EXPECT_STREQ( + gpu_util::GpuFeatureTypeToString( + content::GPU_FEATURE_TYPE_FLASH_STAGE3D).c_str(), + "flash_stage3d"); + EXPECT_STREQ( + gpu_util::GpuFeatureTypeToString( + content::GPU_FEATURE_TYPE_TEXTURE_SHARING).c_str(), + "texture_sharing"); + EXPECT_STREQ( + gpu_util::GpuFeatureTypeToString( + content::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE).c_str(), + "accelerated_video_decode"); + EXPECT_STREQ( + gpu_util::GpuFeatureTypeToString( content::GPU_FEATURE_TYPE_ALL).c_str(), "all"); EXPECT_STREQ(gpu_util::GpuFeatureTypeToString( @@ -54,11 +78,10 @@ TEST(GpuUtilsTest, GpuFeatureTypeToString) { content::GPU_FEATURE_TYPE_WEBGL | content::GPU_FEATURE_TYPE_MULTISAMPLING)).c_str(), "webgl,multisampling"); - - std::string tmp; - tmp = gpu_util::GpuFeatureTypeToString( - static_cast<content::GpuFeatureType>( - content::GPU_FEATURE_TYPE_WEBGL | - content::GPU_FEATURE_TYPE_ALL)); - EXPECT_STREQ(tmp.c_str(), "all"); + EXPECT_STREQ( + gpu_util::GpuFeatureTypeToString( + static_cast<content::GpuFeatureType>( + content::GPU_FEATURE_TYPE_WEBGL | + content::GPU_FEATURE_TYPE_ALL)).c_str(), + "all"); } diff --git a/content/content_browser.gypi b/content/content_browser.gypi index 223ec18..5ed5da3 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi @@ -421,6 +421,8 @@ 'browser/geolocation/win7_location_provider_win.h', 'browser/gpu/browser_gpu_channel_host_factory.cc', 'browser/gpu/browser_gpu_channel_host_factory.h', + 'browser/gpu/gpu_blacklist.cc', + 'browser/gpu/gpu_blacklist.h', 'browser/gpu/gpu_data_manager_impl.cc', 'browser/gpu/gpu_data_manager_impl.h', 'browser/gpu/gpu_process_host.cc', @@ -429,6 +431,8 @@ 'browser/gpu/gpu_process_host_ui_shim.h', 'browser/gpu/gpu_surface_tracker.cc', 'browser/gpu/gpu_surface_tracker.h', + 'browser/gpu/gpu_util.cc', + 'browser/gpu/gpu_util.h', 'browser/histogram_controller.cc', 'browser/histogram_controller.h', 'browser/histogram_internals_request_job.cc', diff --git a/content/content_tests.gypi b/content/content_tests.gypi index fcb9051..d29b03b 100644 --- a/content/content_tests.gypi +++ b/content/content_tests.gypi @@ -271,7 +271,9 @@ 'browser/geolocation/wifi_data_provider_unittest_win.cc', 'browser/geolocation/win7_location_api_unittest_win.cc', 'browser/geolocation/win7_location_provider_unittest_win.cc', + 'browser/gpu/gpu_blacklist_unittest.cc', 'browser/gpu/gpu_data_manager_impl_unittest.cc', + 'browser/gpu/gpu_util_unittest.cc', 'browser/host_zoom_map_impl_unittest.cc', 'browser/hyphenator/hyphenator_message_filter_unittest.cc', 'browser/in_process_webkit/indexed_db_quota_client_unittest.cc', diff --git a/content/public/browser/gpu_data_manager.h b/content/public/browser/gpu_data_manager.h index d1dfafc..efab8d2 100644 --- a/content/public/browser/gpu_data_manager.h +++ b/content/public/browser/gpu_data_manager.h @@ -27,17 +27,21 @@ class GpuDataManager { // Getter for the singleton. CONTENT_EXPORT static GpuDataManager* GetInstance(); - // This collects preliminary GPU info; it should only be called at - // browser startup time in UI thread before the IO restriction is turned - // on. - virtual void InitializeGpuInfo() = 0; + // This collects preliminary GPU info, load GpuBlacklist, and compute the + // preliminary blacklisted features; it should only be called at browser + // startup time in UI thread before the IO restriction is turned on. + virtual void Initialize(const std::string& browser_version_string, + const std::string& gpu_blacklist_json) = 0; + + virtual std::string GetBlacklistVersion() const = 0; - // Can be called on any thread. virtual GpuFeatureType GetBlacklistedFeatures() const = 0; - // Sets the blacklisted feature flags due to preliminary GPU info. - virtual void SetPreliminaryBlacklistedFeatures( - GpuFeatureType feature_type) = 0; + // Returns the reasons for the latest run of blacklisting decisions. + // For the structure of returned value, see documentation for + // GpuBlacklist::GetBlacklistedReasons(). + // Caller is responsible to release the returned value. + virtual base::ListValue* GetBlacklistReasons() const = 0; virtual GPUInfo GetGPUInfo() const = 0; |