1// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/command_line.h"
6#include "base/message_loop/message_loop.h"
7#include "base/run_loop.h"
8#include "base/time/time.h"
9#include "content/browser/gpu/gpu_data_manager_impl_private.h"
10#include "content/public/browser/gpu_data_manager_observer.h"
11#include "gpu/command_buffer/service/gpu_switches.h"
12#include "gpu/config/gpu_feature_type.h"
13#include "gpu/config/gpu_info.h"
14#include "testing/gtest/include/gtest/gtest.h"
15#include "url/gurl.h"
16
17#if defined(OS_WIN)
18#include "base/win/windows_version.h"
19#endif
20
21#define LONG_STRING_CONST(...) #__VA_ARGS__
22
23namespace content {
24namespace {
25
26class TestObserver : public GpuDataManagerObserver {
27 public:
28  TestObserver()
29      : gpu_info_updated_(false),
30        video_memory_usage_stats_updated_(false) {
31  }
32  virtual ~TestObserver() { }
33
34  bool gpu_info_updated() const { return gpu_info_updated_; }
35  bool video_memory_usage_stats_updated() const {
36    return video_memory_usage_stats_updated_;
37  }
38
39  virtual void OnGpuInfoUpdate() OVERRIDE {
40    gpu_info_updated_ = true;
41  }
42
43  virtual void OnVideoMemoryUsageStatsUpdate(
44      const GPUVideoMemoryUsageStats& stats) OVERRIDE {
45    video_memory_usage_stats_updated_ = true;
46  }
47
48  void Reset() {
49    gpu_info_updated_ = false;
50    video_memory_usage_stats_updated_ = false;
51  }
52
53 private:
54  bool gpu_info_updated_;
55  bool video_memory_usage_stats_updated_;
56};
57
58static base::Time GetTimeForTesting() {
59  return base::Time::FromDoubleT(1000);
60}
61
62static GURL GetDomain1ForTesting() {
63  return GURL("http://foo.com/");
64}
65
66static GURL GetDomain2ForTesting() {
67  return GURL("http://bar.com/");
68}
69
70}  // namespace anonymous
71
72class GpuDataManagerImplPrivateTest : public testing::Test {
73 public:
74  GpuDataManagerImplPrivateTest() { }
75
76  virtual ~GpuDataManagerImplPrivateTest() { }
77
78 protected:
79  // scoped_ptr doesn't work with GpuDataManagerImpl because its
80  // destructor is private. GpuDataManagerImplPrivateTest is however a friend
81  // so we can make a little helper class here.
82  class ScopedGpuDataManagerImpl {
83   public:
84    ScopedGpuDataManagerImpl() : impl_(new GpuDataManagerImpl()) {
85      EXPECT_TRUE(impl_);
86      EXPECT_TRUE(impl_->private_.get());
87    }
88    ~ScopedGpuDataManagerImpl() { delete impl_; }
89
90    GpuDataManagerImpl* get() const { return impl_; }
91
92    GpuDataManagerImpl* operator->() const { return impl_; }
93
94   private:
95    GpuDataManagerImpl* impl_;
96    DISALLOW_COPY_AND_ASSIGN(ScopedGpuDataManagerImpl);
97  };
98
99  // We want to test the code path where GpuDataManagerImplPrivate is created
100  // in the GpuDataManagerImpl constructor.
101  class ScopedGpuDataManagerImplPrivate {
102   public:
103    ScopedGpuDataManagerImplPrivate() : impl_(new GpuDataManagerImpl()) {
104      EXPECT_TRUE(impl_);
105      EXPECT_TRUE(impl_->private_.get());
106    }
107    ~ScopedGpuDataManagerImplPrivate() { delete impl_; }
108
109    GpuDataManagerImplPrivate* get() const {
110      return impl_->private_.get();
111    }
112
113    GpuDataManagerImplPrivate* operator->() const {
114      return impl_->private_.get();
115    }
116
117   private:
118    GpuDataManagerImpl* impl_;
119    DISALLOW_COPY_AND_ASSIGN(ScopedGpuDataManagerImplPrivate);
120  };
121
122  virtual void SetUp() {
123  }
124
125  virtual void TearDown() {
126  }
127
128  base::Time JustBeforeExpiration(const GpuDataManagerImplPrivate* manager);
129  base::Time JustAfterExpiration(const GpuDataManagerImplPrivate* manager);
130  void TestBlockingDomainFrom3DAPIs(
131      GpuDataManagerImpl::DomainGuilt guilt_level);
132  void TestUnblockingDomainFrom3DAPIs(
133      GpuDataManagerImpl::DomainGuilt guilt_level);
134
135  base::MessageLoop message_loop_;
136};
137
138// We use new method instead of GetInstance() method because we want
139// each test to be independent of each other.
140
141TEST_F(GpuDataManagerImplPrivateTest, GpuSideBlacklisting) {
142  // If a feature is allowed in preliminary step (browser side), but
143  // disabled when GPU process launches and collects full GPU info,
144  // it's too late to let renderer know, so we basically block all GPU
145  // access, to be on the safe side.
146  ScopedGpuDataManagerImplPrivate manager;
147  EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount());
148  std::string reason;
149  EXPECT_TRUE(manager->GpuAccessAllowed(&reason));
150  EXPECT_TRUE(reason.empty());
151
152  const std::string blacklist_json = LONG_STRING_CONST(
153      {
154        "name": "gpu blacklist",
155        "version": "0.1",
156        "entries": [
157          {
158            "id": 1,
159            "features": [
160              "webgl"
161            ]
162          },
163          {
164            "id": 2,
165            "gl_renderer": ".*GeForce.*",
166            "features": [
167              "accelerated_2d_canvas"
168            ]
169          }
170        ]
171      }
172  );
173
174  gpu::GPUInfo gpu_info;
175  gpu_info.gpu.vendor_id = 0x10de;
176  gpu_info.gpu.device_id = 0x0640;
177  manager->InitializeForTesting(blacklist_json, gpu_info);
178
179  EXPECT_TRUE(manager->GpuAccessAllowed(&reason));
180  EXPECT_TRUE(reason.empty());
181  EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount());
182  EXPECT_TRUE(manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL));
183
184  gpu_info.gl_vendor = "NVIDIA";
185  gpu_info.gl_renderer = "NVIDIA GeForce GT 120";
186  manager->UpdateGpuInfo(gpu_info);
187  EXPECT_FALSE(manager->GpuAccessAllowed(&reason));
188  EXPECT_FALSE(reason.empty());
189  EXPECT_EQ(2u, manager->GetBlacklistedFeatureCount());
190  EXPECT_TRUE(manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL));
191  EXPECT_TRUE(manager->IsFeatureBlacklisted(
192      gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS));
193}
194
195TEST_F(GpuDataManagerImplPrivateTest, GpuSideExceptions) {
196  ScopedGpuDataManagerImplPrivate manager;
197  EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount());
198  EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
199
200  const std::string blacklist_json = LONG_STRING_CONST(
201      {
202        "name": "gpu blacklist",
203        "version": "0.1",
204        "entries": [
205          {
206            "id": 1,
207            "exceptions": [
208              {
209                "gl_renderer": ".*GeForce.*"
210              }
211            ],
212            "features": [
213              "webgl"
214            ]
215          }
216        ]
217      }
218  );
219  gpu::GPUInfo gpu_info;
220  gpu_info.gpu.vendor_id = 0x10de;
221  gpu_info.gpu.device_id = 0x0640;
222  manager->InitializeForTesting(blacklist_json, gpu_info);
223
224  EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
225  EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount());
226
227  // Now assume gpu process launches and full GPU info is collected.
228  gpu_info.gl_renderer = "NVIDIA GeForce GT 120";
229  manager->UpdateGpuInfo(gpu_info);
230  EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
231  EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount());
232}
233
234TEST_F(GpuDataManagerImplPrivateTest, DisableHardwareAcceleration) {
235  ScopedGpuDataManagerImplPrivate manager;
236  EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount());
237  std::string reason;
238  EXPECT_TRUE(manager->GpuAccessAllowed(&reason));
239  EXPECT_TRUE(reason.empty());
240
241  manager->DisableHardwareAcceleration();
242  EXPECT_FALSE(manager->GpuAccessAllowed(&reason));
243  EXPECT_FALSE(reason.empty());
244  EXPECT_EQ(static_cast<size_t>(gpu::NUMBER_OF_GPU_FEATURE_TYPES),
245            manager->GetBlacklistedFeatureCount());
246}
247
248TEST_F(GpuDataManagerImplPrivateTest, SwiftShaderRendering) {
249  // Blacklist, then register SwiftShader.
250  ScopedGpuDataManagerImplPrivate manager;
251  EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount());
252  EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
253  EXPECT_FALSE(manager->ShouldUseSwiftShader());
254
255  manager->DisableHardwareAcceleration();
256  EXPECT_FALSE(manager->GpuAccessAllowed(NULL));
257  EXPECT_FALSE(manager->ShouldUseSwiftShader());
258
259  // If SwiftShader is enabled, even if we blacklist GPU,
260  // GPU process is still allowed.
261  const base::FilePath test_path(FILE_PATH_LITERAL("AnyPath"));
262  manager->RegisterSwiftShaderPath(test_path);
263  EXPECT_TRUE(manager->ShouldUseSwiftShader());
264  EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
265  EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount());
266  EXPECT_TRUE(manager->IsFeatureBlacklisted(
267      gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS));
268}
269
270TEST_F(GpuDataManagerImplPrivateTest, SwiftShaderRendering2) {
271  // Register SwiftShader, then blacklist.
272  ScopedGpuDataManagerImplPrivate manager;
273  EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount());
274  EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
275  EXPECT_FALSE(manager->ShouldUseSwiftShader());
276
277  const base::FilePath test_path(FILE_PATH_LITERAL("AnyPath"));
278  manager->RegisterSwiftShaderPath(test_path);
279  EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount());
280  EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
281  EXPECT_FALSE(manager->ShouldUseSwiftShader());
282
283  manager->DisableHardwareAcceleration();
284  EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
285  EXPECT_TRUE(manager->ShouldUseSwiftShader());
286  EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount());
287  EXPECT_TRUE(manager->IsFeatureBlacklisted(
288      gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS));
289}
290
291TEST_F(GpuDataManagerImplPrivateTest, WarpEnabledOverridesSwiftShader) {
292  // If WARP fallback is enabled on Windows 8 it should not allow SwiftShader
293  // to be enabled.
294#if defined(OS_WIN)
295  if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
296    ScopedGpuDataManagerImplPrivate manager;
297    manager->ForceWarpModeForTesting();
298    const base::FilePath test_path(FILE_PATH_LITERAL("AnyPath"));
299    manager->RegisterSwiftShaderPath(test_path);
300    manager->DisableHardwareAcceleration();
301    EXPECT_TRUE(manager->ShouldUseWarp());
302    EXPECT_FALSE(manager->ShouldUseSwiftShader());
303  }
304#endif
305}
306
307TEST_F(GpuDataManagerImplPrivateTest, GpuInfoUpdate) {
308  ScopedGpuDataManagerImpl manager;
309
310  TestObserver observer;
311  manager->AddObserver(&observer);
312
313  {
314    base::RunLoop run_loop;
315    run_loop.RunUntilIdle();
316  }
317  EXPECT_FALSE(observer.gpu_info_updated());
318
319  gpu::GPUInfo gpu_info;
320  manager->UpdateGpuInfo(gpu_info);
321  {
322    base::RunLoop run_loop;
323    run_loop.RunUntilIdle();
324  }
325  EXPECT_TRUE(observer.gpu_info_updated());
326}
327
328TEST_F(GpuDataManagerImplPrivateTest, NoGpuInfoUpdateWithSwiftShader) {
329  ScopedGpuDataManagerImpl manager;
330
331  manager->DisableHardwareAcceleration();
332  const base::FilePath test_path(FILE_PATH_LITERAL("AnyPath"));
333  manager->RegisterSwiftShaderPath(test_path);
334  EXPECT_TRUE(manager->ShouldUseSwiftShader());
335  EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
336
337  {
338    base::RunLoop run_loop;
339    run_loop.RunUntilIdle();
340  }
341
342  TestObserver observer;
343  manager->AddObserver(&observer);
344  {
345    base::RunLoop run_loop;
346    run_loop.RunUntilIdle();
347  }
348  EXPECT_FALSE(observer.gpu_info_updated());
349
350  gpu::GPUInfo gpu_info;
351  manager->UpdateGpuInfo(gpu_info);
352  {
353    base::RunLoop run_loop;
354    run_loop.RunUntilIdle();
355  }
356  EXPECT_FALSE(observer.gpu_info_updated());
357}
358
359TEST_F(GpuDataManagerImplPrivateTest, GPUVideoMemoryUsageStatsUpdate) {
360  ScopedGpuDataManagerImpl manager;
361
362  TestObserver observer;
363  manager->AddObserver(&observer);
364
365  {
366    base::RunLoop run_loop;
367    run_loop.RunUntilIdle();
368  }
369  EXPECT_FALSE(observer.video_memory_usage_stats_updated());
370
371  GPUVideoMemoryUsageStats vram_stats;
372  manager->UpdateVideoMemoryUsageStats(vram_stats);
373  {
374    base::RunLoop run_loop;
375    run_loop.RunUntilIdle();
376  }
377  EXPECT_TRUE(observer.video_memory_usage_stats_updated());
378}
379
380base::Time GpuDataManagerImplPrivateTest::JustBeforeExpiration(
381    const GpuDataManagerImplPrivate* manager) {
382  return GetTimeForTesting() + base::TimeDelta::FromMilliseconds(
383      manager->GetBlockAllDomainsDurationInMs()) -
384      base::TimeDelta::FromMilliseconds(3);
385}
386
387base::Time GpuDataManagerImplPrivateTest::JustAfterExpiration(
388    const GpuDataManagerImplPrivate* manager) {
389  return GetTimeForTesting() + base::TimeDelta::FromMilliseconds(
390      manager->GetBlockAllDomainsDurationInMs()) +
391      base::TimeDelta::FromMilliseconds(3);
392}
393
394void GpuDataManagerImplPrivateTest::TestBlockingDomainFrom3DAPIs(
395    GpuDataManagerImpl::DomainGuilt guilt_level) {
396  ScopedGpuDataManagerImplPrivate manager;
397
398  manager->BlockDomainFrom3DAPIsAtTime(GetDomain1ForTesting(),
399                                      guilt_level,
400                                      GetTimeForTesting());
401
402  // This domain should be blocked no matter what.
403  EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_BLOCKED,
404            manager->Are3DAPIsBlockedAtTime(GetDomain1ForTesting(),
405                                           GetTimeForTesting()));
406  EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_BLOCKED,
407            manager->Are3DAPIsBlockedAtTime(
408                GetDomain1ForTesting(), JustBeforeExpiration(manager.get())));
409  EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_BLOCKED,
410            manager->Are3DAPIsBlockedAtTime(
411                GetDomain1ForTesting(), JustAfterExpiration(manager.get())));
412}
413
414void GpuDataManagerImplPrivateTest::TestUnblockingDomainFrom3DAPIs(
415    GpuDataManagerImpl::DomainGuilt guilt_level) {
416  ScopedGpuDataManagerImplPrivate manager;
417
418  manager->BlockDomainFrom3DAPIsAtTime(GetDomain1ForTesting(),
419                                       guilt_level,
420                                       GetTimeForTesting());
421
422  // Unblocking the domain should work.
423  manager->UnblockDomainFrom3DAPIs(GetDomain1ForTesting());
424  EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED,
425            manager->Are3DAPIsBlockedAtTime(GetDomain1ForTesting(),
426                                            GetTimeForTesting()));
427  EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED,
428            manager->Are3DAPIsBlockedAtTime(
429                GetDomain1ForTesting(), JustBeforeExpiration(manager.get())));
430  EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED,
431            manager->Are3DAPIsBlockedAtTime(
432                GetDomain1ForTesting(), JustAfterExpiration(manager.get())));
433}
434
435TEST_F(GpuDataManagerImplPrivateTest, BlockGuiltyDomainFrom3DAPIs) {
436  TestBlockingDomainFrom3DAPIs(GpuDataManagerImpl::DOMAIN_GUILT_KNOWN);
437}
438
439TEST_F(GpuDataManagerImplPrivateTest, BlockDomainOfUnknownGuiltFrom3DAPIs) {
440  TestBlockingDomainFrom3DAPIs(GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN);
441}
442
443TEST_F(GpuDataManagerImplPrivateTest, BlockAllDomainsFrom3DAPIs) {
444  ScopedGpuDataManagerImplPrivate manager;
445
446  manager->BlockDomainFrom3DAPIsAtTime(GetDomain1ForTesting(),
447                                       GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN,
448                                       GetTimeForTesting());
449
450  // Blocking of other domains should expire.
451  EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_ALL_DOMAINS_BLOCKED,
452            manager->Are3DAPIsBlockedAtTime(
453                GetDomain2ForTesting(), JustBeforeExpiration(manager.get())));
454  EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED,
455            manager->Are3DAPIsBlockedAtTime(
456                GetDomain2ForTesting(), JustAfterExpiration(manager.get())));
457}
458
459TEST_F(GpuDataManagerImplPrivateTest, UnblockGuiltyDomainFrom3DAPIs) {
460  TestUnblockingDomainFrom3DAPIs(GpuDataManagerImpl::DOMAIN_GUILT_KNOWN);
461}
462
463TEST_F(GpuDataManagerImplPrivateTest, UnblockDomainOfUnknownGuiltFrom3DAPIs) {
464  TestUnblockingDomainFrom3DAPIs(GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN);
465}
466
467TEST_F(GpuDataManagerImplPrivateTest, UnblockOtherDomainFrom3DAPIs) {
468  ScopedGpuDataManagerImplPrivate manager;
469
470  manager->BlockDomainFrom3DAPIsAtTime(GetDomain1ForTesting(),
471                                       GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN,
472                                       GetTimeForTesting());
473
474  manager->UnblockDomainFrom3DAPIs(GetDomain2ForTesting());
475
476  EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED,
477            manager->Are3DAPIsBlockedAtTime(
478                GetDomain2ForTesting(), JustBeforeExpiration(manager.get())));
479
480  // The original domain should still be blocked.
481  EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_BLOCKED,
482            manager->Are3DAPIsBlockedAtTime(
483                GetDomain1ForTesting(), JustBeforeExpiration(manager.get())));
484}
485
486TEST_F(GpuDataManagerImplPrivateTest, UnblockThisDomainFrom3DAPIs) {
487  ScopedGpuDataManagerImplPrivate manager;
488
489  manager->BlockDomainFrom3DAPIsAtTime(GetDomain1ForTesting(),
490                                       GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN,
491                                       GetTimeForTesting());
492
493  manager->UnblockDomainFrom3DAPIs(GetDomain1ForTesting());
494
495  // This behavior is debatable. Perhaps the GPU reset caused by
496  // domain 1 should still cause other domains to be blocked.
497  EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED,
498            manager->Are3DAPIsBlockedAtTime(
499                GetDomain2ForTesting(), JustBeforeExpiration(manager.get())));
500}
501
502#if defined(OS_LINUX)
503TEST_F(GpuDataManagerImplPrivateTest, SetGLStrings) {
504  const char* kGLVendorMesa = "Tungsten Graphics, Inc";
505  const char* kGLRendererMesa = "Mesa DRI Intel(R) G41";
506  const char* kGLVersionMesa801 = "2.1 Mesa 8.0.1-DEVEL";
507
508  ScopedGpuDataManagerImplPrivate manager;
509  EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount());
510  EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
511
512  const std::string blacklist_json = LONG_STRING_CONST(
513      {
514        "name": "gpu blacklist",
515        "version": "0.1",
516        "entries": [
517          {
518            "id": 1,
519            "vendor_id": "0x8086",
520            "exceptions": [
521              {
522                "device_id": ["0x0042"],
523                "driver_version": {
524                  "op": ">=",
525                  "value": "8.0.2"
526                }
527              }
528            ],
529            "features": [
530              "webgl"
531            ]
532          }
533        ]
534      }
535  );
536  gpu::GPUInfo gpu_info;
537  gpu_info.gpu.vendor_id = 0x8086;
538  gpu_info.gpu.device_id = 0x0042;
539  manager->InitializeForTesting(blacklist_json, gpu_info);
540
541  // Not enough GPUInfo.
542  EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
543  EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount());
544
545  // Now assume browser gets GL strings from local state.
546  // The entry applies, blacklist more features than from the preliminary step.
547  // However, GPU process is not blocked because this is all browser side and
548  // happens before renderer launching.
549  manager->SetGLStrings(kGLVendorMesa, kGLRendererMesa, kGLVersionMesa801);
550  EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
551  EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount());
552  EXPECT_TRUE(manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL));
553}
554
555TEST_F(GpuDataManagerImplPrivateTest, SetGLStringsNoEffects) {
556  const char* kGLVendorMesa = "Tungsten Graphics, Inc";
557  const char* kGLRendererMesa = "Mesa DRI Intel(R) G41";
558  const char* kGLVersionMesa801 = "2.1 Mesa 8.0.1-DEVEL";
559  const char* kGLVersionMesa802 = "2.1 Mesa 8.0.2-DEVEL";
560
561  ScopedGpuDataManagerImplPrivate manager;
562  EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount());
563  EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
564
565  const std::string blacklist_json = LONG_STRING_CONST(
566      {
567        "name": "gpu blacklist",
568        "version": "0.1",
569        "entries": [
570          {
571            "id": 1,
572            "vendor_id": "0x8086",
573            "exceptions": [
574              {
575                "device_id": ["0x0042"],
576                "driver_version": {
577                  "op": ">=",
578                  "value": "8.0.2"
579                }
580              }
581            ],
582            "features": [
583              "webgl"
584            ]
585          }
586        ]
587      }
588  );
589  gpu::GPUInfo gpu_info;
590  gpu_info.gpu.vendor_id = 0x8086;
591  gpu_info.gpu.device_id = 0x0042;
592  gpu_info.gl_vendor = kGLVendorMesa;
593  gpu_info.gl_renderer = kGLRendererMesa;
594  gpu_info.gl_version = kGLVersionMesa801;
595  gpu_info.driver_vendor = "Mesa";
596  gpu_info.driver_version = "8.0.1";
597  manager->InitializeForTesting(blacklist_json, gpu_info);
598
599  // Full GPUInfo, the entry applies.
600  EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
601  EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount());
602  EXPECT_TRUE(manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL));
603
604  // Now assume browser gets GL strings from local state.
605  // SetGLStrings() has no effects because GPUInfo already got these strings.
606  // (Otherwise the entry should not apply.)
607  manager->SetGLStrings(kGLVendorMesa, kGLRendererMesa, kGLVersionMesa802);
608  EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
609  EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount());
610  EXPECT_TRUE(manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL));
611}
612#endif  // OS_LINUX
613
614TEST_F(GpuDataManagerImplPrivateTest, GpuDriverBugListSingle) {
615  ScopedGpuDataManagerImplPrivate manager;
616  manager->gpu_driver_bugs_.insert(5);
617
618  base::CommandLine command_line(0, NULL);
619  manager->AppendGpuCommandLine(&command_line);
620
621  EXPECT_TRUE(command_line.HasSwitch(switches::kGpuDriverBugWorkarounds));
622  std::string args = command_line.GetSwitchValueASCII(
623      switches::kGpuDriverBugWorkarounds);
624  EXPECT_STREQ("5", args.c_str());
625}
626
627TEST_F(GpuDataManagerImplPrivateTest, GpuDriverBugListMultiple) {
628  ScopedGpuDataManagerImplPrivate manager;
629  manager->gpu_driver_bugs_.insert(5);
630  manager->gpu_driver_bugs_.insert(7);
631
632  base::CommandLine command_line(0, NULL);
633  manager->AppendGpuCommandLine(&command_line);
634
635  EXPECT_TRUE(command_line.HasSwitch(switches::kGpuDriverBugWorkarounds));
636  std::string args = command_line.GetSwitchValueASCII(
637      switches::kGpuDriverBugWorkarounds);
638  EXPECT_STREQ("5,7", args.c_str());
639}
640
641TEST_F(GpuDataManagerImplPrivateTest, BlacklistAllFeatures) {
642  ScopedGpuDataManagerImplPrivate manager;
643  EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount());
644  std::string reason;
645  EXPECT_TRUE(manager->GpuAccessAllowed(&reason));
646  EXPECT_TRUE(reason.empty());
647
648  const std::string blacklist_json = LONG_STRING_CONST(
649      {
650        "name": "gpu blacklist",
651        "version": "0.1",
652        "entries": [
653          {
654            "id": 1,
655            "features": [
656              "all"
657            ]
658          }
659        ]
660      }
661  );
662
663  gpu::GPUInfo gpu_info;
664  gpu_info.gpu.vendor_id = 0x10de;
665  gpu_info.gpu.device_id = 0x0640;
666  manager->InitializeForTesting(blacklist_json, gpu_info);
667
668  EXPECT_EQ(static_cast<size_t>(gpu::NUMBER_OF_GPU_FEATURE_TYPES),
669            manager->GetBlacklistedFeatureCount());
670  // TODO(zmo): remove the Linux specific behavior once we fix
671  // crbug.com/238466.
672#if defined(OS_LINUX)
673  EXPECT_TRUE(manager->GpuAccessAllowed(&reason));
674  EXPECT_TRUE(reason.empty());
675#else
676  EXPECT_FALSE(manager->GpuAccessAllowed(&reason));
677  EXPECT_FALSE(reason.empty());
678#endif
679}
680
681TEST_F(GpuDataManagerImplPrivateTest, UpdateActiveGpu) {
682  ScopedGpuDataManagerImpl manager;
683
684  const std::string blacklist_json = LONG_STRING_CONST(
685      {
686        "name": "gpu blacklist",
687        "version": "0.1",
688        "entries": [
689          {
690            "id": 1,
691            "vendor_id": "0x8086",
692            "multi_gpu_category": "active",
693            "features": [
694              "webgl"
695            ]
696          }
697        ]
698      }
699  );
700
701  // Two GPUs, the secondary Intel GPU is active.
702  gpu::GPUInfo gpu_info;
703  gpu_info.gpu.vendor_id = 0x10de;
704  gpu_info.gpu.device_id = 0x0640;
705  gpu_info.gpu.active = false;
706  gpu::GPUInfo::GPUDevice intel_gpu;
707  intel_gpu.vendor_id = 0x8086;
708  intel_gpu.device_id = 0x04a1;
709  intel_gpu.active = true;
710  gpu_info.secondary_gpus.push_back(intel_gpu);
711
712  manager->InitializeForTesting(blacklist_json, gpu_info);
713  TestObserver observer;
714  manager->AddObserver(&observer);
715
716  EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount());
717
718  // Update with the same Intel GPU active.
719  EXPECT_FALSE(manager->UpdateActiveGpu(0x8086, 0x04a1));
720  {
721    base::RunLoop run_loop;
722    run_loop.RunUntilIdle();
723  }
724  EXPECT_FALSE(observer.gpu_info_updated());
725  EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount());
726
727  // Set NVIDIA GPU to be active.
728  EXPECT_TRUE(manager->UpdateActiveGpu(0x10de, 0x0640));
729  {
730    base::RunLoop run_loop;
731    run_loop.RunUntilIdle();
732  }
733  EXPECT_TRUE(observer.gpu_info_updated());
734  EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount());
735
736  observer.Reset();
737  EXPECT_FALSE(observer.gpu_info_updated());
738
739  // Update with the same NVIDIA GPU active.
740  EXPECT_FALSE(manager->UpdateActiveGpu(0x10de, 0x0640));
741  {
742    base::RunLoop run_loop;
743    run_loop.RunUntilIdle();
744  }
745  EXPECT_FALSE(observer.gpu_info_updated());
746  EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount());
747
748  // Set Intel GPU to be active.
749  EXPECT_TRUE(manager->UpdateActiveGpu(0x8086, 0x04a1));
750  {
751    base::RunLoop run_loop;
752    run_loop.RunUntilIdle();
753  }
754  EXPECT_TRUE(observer.gpu_info_updated());
755  EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount());
756}
757
758}  // namespace content
759