| // Copyright (c) 2013 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 "base/command_line.h" |
| #include "base/message_loop/message_loop.h" |
| #include "base/run_loop.h" |
| #include "base/time/time.h" |
| #include "content/browser/gpu/gpu_data_manager_impl_private.h" |
| #include "content/public/browser/gpu_data_manager_observer.h" |
| #include "gpu/command_buffer/service/gpu_switches.h" |
| #include "gpu/config/gpu_feature_type.h" |
| #include "gpu/config/gpu_info.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "url/gurl.h" |
| |
| #if defined(OS_WIN) |
| #include "base/win/windows_version.h" |
| #endif |
| |
| #define LONG_STRING_CONST(...) #__VA_ARGS__ |
| |
| namespace content { |
| namespace { |
| |
| class TestObserver : public GpuDataManagerObserver { |
| public: |
| TestObserver() |
| : gpu_info_updated_(false), |
| video_memory_usage_stats_updated_(false) { |
| } |
| ~TestObserver() override {} |
| |
| bool gpu_info_updated() const { return gpu_info_updated_; } |
| bool video_memory_usage_stats_updated() const { |
| return video_memory_usage_stats_updated_; |
| } |
| |
| void OnGpuInfoUpdate() override { gpu_info_updated_ = true; } |
| |
| void OnVideoMemoryUsageStatsUpdate( |
| const GPUVideoMemoryUsageStats& stats) override { |
| video_memory_usage_stats_updated_ = true; |
| } |
| |
| void Reset() { |
| gpu_info_updated_ = false; |
| video_memory_usage_stats_updated_ = false; |
| } |
| |
| private: |
| bool gpu_info_updated_; |
| bool video_memory_usage_stats_updated_; |
| }; |
| |
| static base::Time GetTimeForTesting() { |
| return base::Time::FromDoubleT(1000); |
| } |
| |
| static GURL GetDomain1ForTesting() { |
| return GURL("http://foo.com/"); |
| } |
| |
| static GURL GetDomain2ForTesting() { |
| return GURL("http://bar.com/"); |
| } |
| |
| } // namespace anonymous |
| |
| class GpuDataManagerImplPrivateTest : public testing::Test { |
| public: |
| GpuDataManagerImplPrivateTest() { } |
| |
| ~GpuDataManagerImplPrivateTest() override {} |
| |
| protected: |
| // scoped_ptr doesn't work with GpuDataManagerImpl because its |
| // destructor is private. GpuDataManagerImplPrivateTest is however a friend |
| // so we can make a little helper class here. |
| class ScopedGpuDataManagerImpl { |
| public: |
| ScopedGpuDataManagerImpl() : impl_(new GpuDataManagerImpl()) { |
| EXPECT_TRUE(impl_); |
| EXPECT_TRUE(impl_->private_.get()); |
| } |
| ~ScopedGpuDataManagerImpl() { delete impl_; } |
| |
| GpuDataManagerImpl* get() const { return impl_; } |
| |
| GpuDataManagerImpl* operator->() const { return impl_; } |
| |
| private: |
| GpuDataManagerImpl* impl_; |
| DISALLOW_COPY_AND_ASSIGN(ScopedGpuDataManagerImpl); |
| }; |
| |
| // We want to test the code path where GpuDataManagerImplPrivate is created |
| // in the GpuDataManagerImpl constructor. |
| class ScopedGpuDataManagerImplPrivate { |
| public: |
| ScopedGpuDataManagerImplPrivate() : impl_(new GpuDataManagerImpl()) { |
| EXPECT_TRUE(impl_); |
| EXPECT_TRUE(impl_->private_.get()); |
| } |
| ~ScopedGpuDataManagerImplPrivate() { delete impl_; } |
| |
| GpuDataManagerImplPrivate* get() const { |
| return impl_->private_.get(); |
| } |
| |
| GpuDataManagerImplPrivate* operator->() const { |
| return impl_->private_.get(); |
| } |
| |
| private: |
| GpuDataManagerImpl* impl_; |
| DISALLOW_COPY_AND_ASSIGN(ScopedGpuDataManagerImplPrivate); |
| }; |
| |
| void SetUp() override {} |
| |
| void TearDown() override {} |
| |
| base::Time JustBeforeExpiration(const GpuDataManagerImplPrivate* manager); |
| base::Time JustAfterExpiration(const GpuDataManagerImplPrivate* manager); |
| void TestBlockingDomainFrom3DAPIs( |
| GpuDataManagerImpl::DomainGuilt guilt_level); |
| void TestUnblockingDomainFrom3DAPIs( |
| GpuDataManagerImpl::DomainGuilt guilt_level); |
| |
| base::MessageLoop message_loop_; |
| }; |
| |
| // We use new method instead of GetInstance() method because we want |
| // each test to be independent of each other. |
| |
| TEST_F(GpuDataManagerImplPrivateTest, GpuSideBlacklisting) { |
| // If a feature is allowed in preliminary step (browser side), but |
| // disabled when GPU process launches and collects full GPU info, |
| // it's too late to let renderer know, so we basically block all GPU |
| // access, to be on the safe side. |
| ScopedGpuDataManagerImplPrivate manager; |
| EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount()); |
| std::string reason; |
| EXPECT_TRUE(manager->GpuAccessAllowed(&reason)); |
| EXPECT_TRUE(reason.empty()); |
| |
| const std::string blacklist_json = LONG_STRING_CONST( |
| { |
| "name": "gpu blacklist", |
| "version": "0.1", |
| "entries": [ |
| { |
| "id": 1, |
| "features": [ |
| "webgl" |
| ] |
| }, |
| { |
| "id": 2, |
| "gl_renderer": ".*GeForce.*", |
| "features": [ |
| "accelerated_2d_canvas" |
| ] |
| } |
| ] |
| } |
| ); |
| |
| gpu::GPUInfo gpu_info; |
| gpu_info.gpu.vendor_id = 0x10de; |
| gpu_info.gpu.device_id = 0x0640; |
| manager->InitializeForTesting(blacklist_json, gpu_info); |
| |
| EXPECT_TRUE(manager->GpuAccessAllowed(&reason)); |
| EXPECT_TRUE(reason.empty()); |
| EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount()); |
| EXPECT_TRUE(manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL)); |
| |
| gpu_info.gl_vendor = "NVIDIA"; |
| gpu_info.gl_renderer = "NVIDIA GeForce GT 120"; |
| manager->UpdateGpuInfo(gpu_info); |
| EXPECT_FALSE(manager->GpuAccessAllowed(&reason)); |
| EXPECT_FALSE(reason.empty()); |
| EXPECT_EQ(2u, manager->GetBlacklistedFeatureCount()); |
| EXPECT_TRUE(manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL)); |
| EXPECT_TRUE(manager->IsFeatureBlacklisted( |
| gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS)); |
| } |
| |
| TEST_F(GpuDataManagerImplPrivateTest, GpuSideExceptions) { |
| ScopedGpuDataManagerImplPrivate manager; |
| EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount()); |
| EXPECT_TRUE(manager->GpuAccessAllowed(NULL)); |
| |
| const std::string blacklist_json = LONG_STRING_CONST( |
| { |
| "name": "gpu blacklist", |
| "version": "0.1", |
| "entries": [ |
| { |
| "id": 1, |
| "exceptions": [ |
| { |
| "gl_renderer": ".*GeForce.*" |
| } |
| ], |
| "features": [ |
| "webgl" |
| ] |
| } |
| ] |
| } |
| ); |
| gpu::GPUInfo gpu_info; |
| gpu_info.gpu.vendor_id = 0x10de; |
| gpu_info.gpu.device_id = 0x0640; |
| manager->InitializeForTesting(blacklist_json, gpu_info); |
| |
| EXPECT_TRUE(manager->GpuAccessAllowed(NULL)); |
| EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount()); |
| |
| // Now assume gpu process launches and full GPU info is collected. |
| gpu_info.gl_renderer = "NVIDIA GeForce GT 120"; |
| manager->UpdateGpuInfo(gpu_info); |
| EXPECT_TRUE(manager->GpuAccessAllowed(NULL)); |
| EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount()); |
| } |
| |
| TEST_F(GpuDataManagerImplPrivateTest, DisableHardwareAcceleration) { |
| ScopedGpuDataManagerImplPrivate manager; |
| EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount()); |
| std::string reason; |
| EXPECT_TRUE(manager->GpuAccessAllowed(&reason)); |
| EXPECT_TRUE(reason.empty()); |
| |
| manager->DisableHardwareAcceleration(); |
| EXPECT_FALSE(manager->GpuAccessAllowed(&reason)); |
| EXPECT_FALSE(reason.empty()); |
| EXPECT_EQ(static_cast<size_t>(gpu::NUMBER_OF_GPU_FEATURE_TYPES), |
| manager->GetBlacklistedFeatureCount()); |
| } |
| |
| TEST_F(GpuDataManagerImplPrivateTest, SwiftShaderRendering) { |
| // Blacklist, then register SwiftShader. |
| ScopedGpuDataManagerImplPrivate manager; |
| EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount()); |
| EXPECT_TRUE(manager->GpuAccessAllowed(NULL)); |
| EXPECT_FALSE(manager->ShouldUseSwiftShader()); |
| |
| manager->DisableHardwareAcceleration(); |
| EXPECT_FALSE(manager->GpuAccessAllowed(NULL)); |
| EXPECT_FALSE(manager->ShouldUseSwiftShader()); |
| |
| // If SwiftShader is enabled, even if we blacklist GPU, |
| // GPU process is still allowed. |
| const base::FilePath test_path(FILE_PATH_LITERAL("AnyPath")); |
| manager->RegisterSwiftShaderPath(test_path); |
| EXPECT_TRUE(manager->ShouldUseSwiftShader()); |
| EXPECT_TRUE(manager->GpuAccessAllowed(NULL)); |
| EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount()); |
| EXPECT_TRUE(manager->IsFeatureBlacklisted( |
| gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS)); |
| } |
| |
| TEST_F(GpuDataManagerImplPrivateTest, SwiftShaderRendering2) { |
| // Register SwiftShader, then blacklist. |
| ScopedGpuDataManagerImplPrivate manager; |
| EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount()); |
| EXPECT_TRUE(manager->GpuAccessAllowed(NULL)); |
| EXPECT_FALSE(manager->ShouldUseSwiftShader()); |
| |
| const base::FilePath test_path(FILE_PATH_LITERAL("AnyPath")); |
| manager->RegisterSwiftShaderPath(test_path); |
| EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount()); |
| EXPECT_TRUE(manager->GpuAccessAllowed(NULL)); |
| EXPECT_FALSE(manager->ShouldUseSwiftShader()); |
| |
| manager->DisableHardwareAcceleration(); |
| EXPECT_TRUE(manager->GpuAccessAllowed(NULL)); |
| EXPECT_TRUE(manager->ShouldUseSwiftShader()); |
| EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount()); |
| EXPECT_TRUE(manager->IsFeatureBlacklisted( |
| gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS)); |
| } |
| |
| TEST_F(GpuDataManagerImplPrivateTest, WarpEnabledOverridesSwiftShader) { |
| // If WARP fallback is enabled on Windows 8 it should not allow SwiftShader |
| // to be enabled. |
| #if defined(OS_WIN) |
| if (base::win::GetVersion() >= base::win::VERSION_WIN8) { |
| ScopedGpuDataManagerImplPrivate manager; |
| manager->ForceWarpModeForTesting(); |
| const base::FilePath test_path(FILE_PATH_LITERAL("AnyPath")); |
| manager->RegisterSwiftShaderPath(test_path); |
| manager->DisableHardwareAcceleration(); |
| EXPECT_TRUE(manager->ShouldUseWarp()); |
| EXPECT_FALSE(manager->ShouldUseSwiftShader()); |
| } |
| #endif |
| } |
| |
| TEST_F(GpuDataManagerImplPrivateTest, GpuInfoUpdate) { |
| ScopedGpuDataManagerImpl manager; |
| |
| TestObserver observer; |
| manager->AddObserver(&observer); |
| |
| { |
| base::RunLoop run_loop; |
| run_loop.RunUntilIdle(); |
| } |
| EXPECT_FALSE(observer.gpu_info_updated()); |
| |
| gpu::GPUInfo gpu_info; |
| manager->UpdateGpuInfo(gpu_info); |
| { |
| base::RunLoop run_loop; |
| run_loop.RunUntilIdle(); |
| } |
| EXPECT_TRUE(observer.gpu_info_updated()); |
| } |
| |
| TEST_F(GpuDataManagerImplPrivateTest, NoGpuInfoUpdateWithSwiftShader) { |
| ScopedGpuDataManagerImpl manager; |
| |
| manager->DisableHardwareAcceleration(); |
| const base::FilePath test_path(FILE_PATH_LITERAL("AnyPath")); |
| manager->RegisterSwiftShaderPath(test_path); |
| EXPECT_TRUE(manager->ShouldUseSwiftShader()); |
| EXPECT_TRUE(manager->GpuAccessAllowed(NULL)); |
| |
| { |
| base::RunLoop run_loop; |
| run_loop.RunUntilIdle(); |
| } |
| |
| TestObserver observer; |
| manager->AddObserver(&observer); |
| { |
| base::RunLoop run_loop; |
| run_loop.RunUntilIdle(); |
| } |
| EXPECT_FALSE(observer.gpu_info_updated()); |
| |
| gpu::GPUInfo gpu_info; |
| manager->UpdateGpuInfo(gpu_info); |
| { |
| base::RunLoop run_loop; |
| run_loop.RunUntilIdle(); |
| } |
| EXPECT_FALSE(observer.gpu_info_updated()); |
| } |
| |
| TEST_F(GpuDataManagerImplPrivateTest, GPUVideoMemoryUsageStatsUpdate) { |
| ScopedGpuDataManagerImpl manager; |
| |
| TestObserver observer; |
| manager->AddObserver(&observer); |
| |
| { |
| base::RunLoop run_loop; |
| run_loop.RunUntilIdle(); |
| } |
| EXPECT_FALSE(observer.video_memory_usage_stats_updated()); |
| |
| GPUVideoMemoryUsageStats vram_stats; |
| manager->UpdateVideoMemoryUsageStats(vram_stats); |
| { |
| base::RunLoop run_loop; |
| run_loop.RunUntilIdle(); |
| } |
| EXPECT_TRUE(observer.video_memory_usage_stats_updated()); |
| } |
| |
| base::Time GpuDataManagerImplPrivateTest::JustBeforeExpiration( |
| const GpuDataManagerImplPrivate* manager) { |
| return GetTimeForTesting() + base::TimeDelta::FromMilliseconds( |
| manager->GetBlockAllDomainsDurationInMs()) - |
| base::TimeDelta::FromMilliseconds(3); |
| } |
| |
| base::Time GpuDataManagerImplPrivateTest::JustAfterExpiration( |
| const GpuDataManagerImplPrivate* manager) { |
| return GetTimeForTesting() + base::TimeDelta::FromMilliseconds( |
| manager->GetBlockAllDomainsDurationInMs()) + |
| base::TimeDelta::FromMilliseconds(3); |
| } |
| |
| void GpuDataManagerImplPrivateTest::TestBlockingDomainFrom3DAPIs( |
| GpuDataManagerImpl::DomainGuilt guilt_level) { |
| ScopedGpuDataManagerImplPrivate manager; |
| |
| manager->BlockDomainFrom3DAPIsAtTime(GetDomain1ForTesting(), |
| guilt_level, |
| GetTimeForTesting()); |
| |
| // This domain should be blocked no matter what. |
| EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_BLOCKED, |
| manager->Are3DAPIsBlockedAtTime(GetDomain1ForTesting(), |
| GetTimeForTesting())); |
| EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_BLOCKED, |
| manager->Are3DAPIsBlockedAtTime( |
| GetDomain1ForTesting(), JustBeforeExpiration(manager.get()))); |
| EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_BLOCKED, |
| manager->Are3DAPIsBlockedAtTime( |
| GetDomain1ForTesting(), JustAfterExpiration(manager.get()))); |
| } |
| |
| void GpuDataManagerImplPrivateTest::TestUnblockingDomainFrom3DAPIs( |
| GpuDataManagerImpl::DomainGuilt guilt_level) { |
| ScopedGpuDataManagerImplPrivate manager; |
| |
| manager->BlockDomainFrom3DAPIsAtTime(GetDomain1ForTesting(), |
| guilt_level, |
| GetTimeForTesting()); |
| |
| // Unblocking the domain should work. |
| manager->UnblockDomainFrom3DAPIs(GetDomain1ForTesting()); |
| EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED, |
| manager->Are3DAPIsBlockedAtTime(GetDomain1ForTesting(), |
| GetTimeForTesting())); |
| EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED, |
| manager->Are3DAPIsBlockedAtTime( |
| GetDomain1ForTesting(), JustBeforeExpiration(manager.get()))); |
| EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED, |
| manager->Are3DAPIsBlockedAtTime( |
| GetDomain1ForTesting(), JustAfterExpiration(manager.get()))); |
| } |
| |
| TEST_F(GpuDataManagerImplPrivateTest, BlockGuiltyDomainFrom3DAPIs) { |
| TestBlockingDomainFrom3DAPIs(GpuDataManagerImpl::DOMAIN_GUILT_KNOWN); |
| } |
| |
| TEST_F(GpuDataManagerImplPrivateTest, BlockDomainOfUnknownGuiltFrom3DAPIs) { |
| TestBlockingDomainFrom3DAPIs(GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN); |
| } |
| |
| TEST_F(GpuDataManagerImplPrivateTest, BlockAllDomainsFrom3DAPIs) { |
| ScopedGpuDataManagerImplPrivate manager; |
| |
| manager->BlockDomainFrom3DAPIsAtTime(GetDomain1ForTesting(), |
| GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN, |
| GetTimeForTesting()); |
| |
| // Blocking of other domains should expire. |
| EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_ALL_DOMAINS_BLOCKED, |
| manager->Are3DAPIsBlockedAtTime( |
| GetDomain2ForTesting(), JustBeforeExpiration(manager.get()))); |
| EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED, |
| manager->Are3DAPIsBlockedAtTime( |
| GetDomain2ForTesting(), JustAfterExpiration(manager.get()))); |
| } |
| |
| TEST_F(GpuDataManagerImplPrivateTest, UnblockGuiltyDomainFrom3DAPIs) { |
| TestUnblockingDomainFrom3DAPIs(GpuDataManagerImpl::DOMAIN_GUILT_KNOWN); |
| } |
| |
| TEST_F(GpuDataManagerImplPrivateTest, UnblockDomainOfUnknownGuiltFrom3DAPIs) { |
| TestUnblockingDomainFrom3DAPIs(GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN); |
| } |
| |
| TEST_F(GpuDataManagerImplPrivateTest, UnblockOtherDomainFrom3DAPIs) { |
| ScopedGpuDataManagerImplPrivate manager; |
| |
| manager->BlockDomainFrom3DAPIsAtTime(GetDomain1ForTesting(), |
| GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN, |
| GetTimeForTesting()); |
| |
| manager->UnblockDomainFrom3DAPIs(GetDomain2ForTesting()); |
| |
| EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED, |
| manager->Are3DAPIsBlockedAtTime( |
| GetDomain2ForTesting(), JustBeforeExpiration(manager.get()))); |
| |
| // The original domain should still be blocked. |
| EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_BLOCKED, |
| manager->Are3DAPIsBlockedAtTime( |
| GetDomain1ForTesting(), JustBeforeExpiration(manager.get()))); |
| } |
| |
| TEST_F(GpuDataManagerImplPrivateTest, UnblockThisDomainFrom3DAPIs) { |
| ScopedGpuDataManagerImplPrivate manager; |
| |
| manager->BlockDomainFrom3DAPIsAtTime(GetDomain1ForTesting(), |
| GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN, |
| GetTimeForTesting()); |
| |
| manager->UnblockDomainFrom3DAPIs(GetDomain1ForTesting()); |
| |
| // This behavior is debatable. Perhaps the GPU reset caused by |
| // domain 1 should still cause other domains to be blocked. |
| EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED, |
| manager->Are3DAPIsBlockedAtTime( |
| GetDomain2ForTesting(), JustBeforeExpiration(manager.get()))); |
| } |
| |
| #if defined(OS_LINUX) |
| TEST_F(GpuDataManagerImplPrivateTest, SetGLStrings) { |
| const char* kGLVendorMesa = "Tungsten Graphics, Inc"; |
| const char* kGLRendererMesa = "Mesa DRI Intel(R) G41"; |
| const char* kGLVersionMesa801 = "2.1 Mesa 8.0.1-DEVEL"; |
| |
| ScopedGpuDataManagerImplPrivate manager; |
| EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount()); |
| EXPECT_TRUE(manager->GpuAccessAllowed(NULL)); |
| |
| const std::string blacklist_json = LONG_STRING_CONST( |
| { |
| "name": "gpu blacklist", |
| "version": "0.1", |
| "entries": [ |
| { |
| "id": 1, |
| "vendor_id": "0x8086", |
| "exceptions": [ |
| { |
| "device_id": ["0x0042"], |
| "driver_version": { |
| "op": ">=", |
| "value": "8.0.2" |
| } |
| } |
| ], |
| "features": [ |
| "webgl" |
| ] |
| } |
| ] |
| } |
| ); |
| gpu::GPUInfo gpu_info; |
| gpu_info.gpu.vendor_id = 0x8086; |
| gpu_info.gpu.device_id = 0x0042; |
| manager->InitializeForTesting(blacklist_json, gpu_info); |
| |
| // Not enough GPUInfo. |
| EXPECT_TRUE(manager->GpuAccessAllowed(NULL)); |
| EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount()); |
| |
| // Now assume browser gets GL strings from local state. |
| // The entry applies, blacklist more features than from the preliminary step. |
| // However, GPU process is not blocked because this is all browser side and |
| // happens before renderer launching. |
| manager->SetGLStrings(kGLVendorMesa, kGLRendererMesa, kGLVersionMesa801); |
| EXPECT_TRUE(manager->GpuAccessAllowed(NULL)); |
| EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount()); |
| EXPECT_TRUE(manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL)); |
| } |
| |
| TEST_F(GpuDataManagerImplPrivateTest, SetGLStringsNoEffects) { |
| const char* kGLVendorMesa = "Tungsten Graphics, Inc"; |
| const char* kGLRendererMesa = "Mesa DRI Intel(R) G41"; |
| const char* kGLVersionMesa801 = "2.1 Mesa 8.0.1-DEVEL"; |
| const char* kGLVersionMesa802 = "2.1 Mesa 8.0.2-DEVEL"; |
| |
| ScopedGpuDataManagerImplPrivate manager; |
| EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount()); |
| EXPECT_TRUE(manager->GpuAccessAllowed(NULL)); |
| |
| const std::string blacklist_json = LONG_STRING_CONST( |
| { |
| "name": "gpu blacklist", |
| "version": "0.1", |
| "entries": [ |
| { |
| "id": 1, |
| "vendor_id": "0x8086", |
| "exceptions": [ |
| { |
| "device_id": ["0x0042"], |
| "driver_version": { |
| "op": ">=", |
| "value": "8.0.2" |
| } |
| } |
| ], |
| "features": [ |
| "webgl" |
| ] |
| } |
| ] |
| } |
| ); |
| gpu::GPUInfo gpu_info; |
| gpu_info.gpu.vendor_id = 0x8086; |
| gpu_info.gpu.device_id = 0x0042; |
| gpu_info.gl_vendor = kGLVendorMesa; |
| gpu_info.gl_renderer = kGLRendererMesa; |
| gpu_info.gl_version = kGLVersionMesa801; |
| gpu_info.driver_vendor = "Mesa"; |
| gpu_info.driver_version = "8.0.1"; |
| manager->InitializeForTesting(blacklist_json, gpu_info); |
| |
| // Full GPUInfo, the entry applies. |
| EXPECT_TRUE(manager->GpuAccessAllowed(NULL)); |
| EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount()); |
| EXPECT_TRUE(manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL)); |
| |
| // Now assume browser gets GL strings from local state. |
| // SetGLStrings() has no effects because GPUInfo already got these strings. |
| // (Otherwise the entry should not apply.) |
| manager->SetGLStrings(kGLVendorMesa, kGLRendererMesa, kGLVersionMesa802); |
| EXPECT_TRUE(manager->GpuAccessAllowed(NULL)); |
| EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount()); |
| EXPECT_TRUE(manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL)); |
| } |
| #endif // OS_LINUX |
| |
| TEST_F(GpuDataManagerImplPrivateTest, GpuDriverBugListSingle) { |
| ScopedGpuDataManagerImplPrivate manager; |
| manager->gpu_driver_bugs_.insert(5); |
| |
| base::CommandLine command_line(0, NULL); |
| manager->AppendGpuCommandLine(&command_line); |
| |
| EXPECT_TRUE(command_line.HasSwitch(switches::kGpuDriverBugWorkarounds)); |
| std::string args = command_line.GetSwitchValueASCII( |
| switches::kGpuDriverBugWorkarounds); |
| EXPECT_STREQ("5", args.c_str()); |
| } |
| |
| TEST_F(GpuDataManagerImplPrivateTest, GpuDriverBugListMultiple) { |
| ScopedGpuDataManagerImplPrivate manager; |
| manager->gpu_driver_bugs_.insert(5); |
| manager->gpu_driver_bugs_.insert(7); |
| |
| base::CommandLine command_line(0, NULL); |
| manager->AppendGpuCommandLine(&command_line); |
| |
| EXPECT_TRUE(command_line.HasSwitch(switches::kGpuDriverBugWorkarounds)); |
| std::string args = command_line.GetSwitchValueASCII( |
| switches::kGpuDriverBugWorkarounds); |
| EXPECT_STREQ("5,7", args.c_str()); |
| } |
| |
| TEST_F(GpuDataManagerImplPrivateTest, BlacklistAllFeatures) { |
| ScopedGpuDataManagerImplPrivate manager; |
| EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount()); |
| std::string reason; |
| EXPECT_TRUE(manager->GpuAccessAllowed(&reason)); |
| EXPECT_TRUE(reason.empty()); |
| |
| const std::string blacklist_json = LONG_STRING_CONST( |
| { |
| "name": "gpu blacklist", |
| "version": "0.1", |
| "entries": [ |
| { |
| "id": 1, |
| "features": [ |
| "all" |
| ] |
| } |
| ] |
| } |
| ); |
| |
| gpu::GPUInfo gpu_info; |
| gpu_info.gpu.vendor_id = 0x10de; |
| gpu_info.gpu.device_id = 0x0640; |
| manager->InitializeForTesting(blacklist_json, gpu_info); |
| |
| EXPECT_EQ(static_cast<size_t>(gpu::NUMBER_OF_GPU_FEATURE_TYPES), |
| manager->GetBlacklistedFeatureCount()); |
| // TODO(zmo): remove the Linux specific behavior once we fix |
| // crbug.com/238466. |
| #if defined(OS_LINUX) |
| EXPECT_TRUE(manager->GpuAccessAllowed(&reason)); |
| EXPECT_TRUE(reason.empty()); |
| #else |
| EXPECT_FALSE(manager->GpuAccessAllowed(&reason)); |
| EXPECT_FALSE(reason.empty()); |
| #endif |
| } |
| |
| TEST_F(GpuDataManagerImplPrivateTest, UpdateActiveGpu) { |
| ScopedGpuDataManagerImpl manager; |
| |
| const std::string blacklist_json = LONG_STRING_CONST( |
| { |
| "name": "gpu blacklist", |
| "version": "0.1", |
| "entries": [ |
| { |
| "id": 1, |
| "vendor_id": "0x8086", |
| "multi_gpu_category": "active", |
| "features": [ |
| "webgl" |
| ] |
| } |
| ] |
| } |
| ); |
| |
| // Two GPUs, the secondary Intel GPU is active. |
| gpu::GPUInfo gpu_info; |
| gpu_info.gpu.vendor_id = 0x10de; |
| gpu_info.gpu.device_id = 0x0640; |
| gpu_info.gpu.active = false; |
| gpu::GPUInfo::GPUDevice intel_gpu; |
| intel_gpu.vendor_id = 0x8086; |
| intel_gpu.device_id = 0x04a1; |
| intel_gpu.active = true; |
| gpu_info.secondary_gpus.push_back(intel_gpu); |
| |
| manager->InitializeForTesting(blacklist_json, gpu_info); |
| TestObserver observer; |
| manager->AddObserver(&observer); |
| |
| EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount()); |
| |
| // Update with the same Intel GPU active. |
| EXPECT_FALSE(manager->UpdateActiveGpu(0x8086, 0x04a1)); |
| { |
| base::RunLoop run_loop; |
| run_loop.RunUntilIdle(); |
| } |
| EXPECT_FALSE(observer.gpu_info_updated()); |
| EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount()); |
| |
| // Set NVIDIA GPU to be active. |
| EXPECT_TRUE(manager->UpdateActiveGpu(0x10de, 0x0640)); |
| { |
| base::RunLoop run_loop; |
| run_loop.RunUntilIdle(); |
| } |
| EXPECT_TRUE(observer.gpu_info_updated()); |
| EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount()); |
| |
| observer.Reset(); |
| EXPECT_FALSE(observer.gpu_info_updated()); |
| |
| // Update with the same NVIDIA GPU active. |
| EXPECT_FALSE(manager->UpdateActiveGpu(0x10de, 0x0640)); |
| { |
| base::RunLoop run_loop; |
| run_loop.RunUntilIdle(); |
| } |
| EXPECT_FALSE(observer.gpu_info_updated()); |
| EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount()); |
| |
| // Set Intel GPU to be active. |
| EXPECT_TRUE(manager->UpdateActiveGpu(0x8086, 0x04a1)); |
| { |
| base::RunLoop run_loop; |
| run_loop.RunUntilIdle(); |
| } |
| EXPECT_TRUE(observer.gpu_info_updated()); |
| EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount()); |
| } |
| |
| } // namespace content |