Enable SwiftShader fallback on desktop Linux.

SwiftShader is an OpenGL ES implementation which runs on the CPU,
and is used as a fallback for WebGL support when the GPU or its driver
have been blacklisted. It has been added to the Chrome installer for
Windows in https://codereview.chromium.org/2715563002/ This CL enables
the integration in Chromium on Linux.

BUG=160392
CQ_INCLUDE_TRYBOTS=master.tryserver.chromium.android:android_optional_gpu_tests_rel;master.tryserver.chromium.linux:linux_optional_gpu_tests_rel;master.tryserver.chromium.mac:mac_optional_gpu_tests_rel;master.tryserver.chromium.win:win_optional_gpu_tests_rel

Review-Url: https://codereview.chromium.org/2777193002
Cr-Commit-Position: refs/heads/master@{#463872}
diff --git a/chrome/tools/build/linux/FILES.cfg b/chrome/tools/build/linux/FILES.cfg
index 3eed7b7..aff7afd 100644
--- a/chrome/tools/build/linux/FILES.cfg
+++ b/chrome/tools/build/linux/FILES.cfg
@@ -124,6 +124,15 @@
     'filename': 'libEGL.so',
     'buildtype': ['dev'],
   },
+  # SwiftShader files:
+  {
+    'filename': 'swiftshader/libGLESv2.so',
+    'buildtype': ['dev, 'official''],
+  },
+  {
+    'filename': 'swiftshader/libEGL.so',
+    'buildtype': ['dev', 'official'],
+  },
   # Native Client plugin files:
   {
     'filename': 'nacl_irt_x86_32.nexe',
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index ba17cbd..5c55a852 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -1773,6 +1773,11 @@
     deps += [ "//ui/gfx/x" ]
   }
 
+  if (is_linux && !is_chromeos && use_x11 &&
+      (target_cpu == "x86" || target_cpu == "x64")) {
+    deps += [ "//third_party/swiftshader" ]
+  }
+
   if (use_pango) {
     configs += [ "//build/config/linux/pangocairo" ]
   }
diff --git a/content/browser/gpu/gpu_data_manager_impl_private.cc b/content/browser/gpu/gpu_data_manager_impl_private.cc
index 335958f..4dbdce1 100644
--- a/content/browser/gpu/gpu_data_manager_impl_private.cc
+++ b/content/browser/gpu/gpu_data_manager_impl_private.cc
@@ -386,6 +386,7 @@
       // TODO(zmo): Other features might also be OK to ignore here.
       feature_diffs.erase(gpu::GPU_FEATURE_TYPE_ACCELERATED_WEBGL);
       feature_diffs.erase(gpu::GPU_FEATURE_TYPE_WEBGL2);
+      feature_diffs.erase(gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS);
     }
     if (feature_diffs.size()) {
       if (reason) {
@@ -1266,12 +1267,33 @@
           switches::kDisableSoftwareRasterizer)) {
     use_swiftshader_ = true;
 
-    // Remove all previously recorded GPU info
-    gpu_info_ = gpu::GPUInfo();
-    // Set some basic info to identify the GPU as SwiftShader
+    // Adjust GPU info for SwiftShader. Most of this data only affects the
+    // chrome://gpu page, so it doesn't require querying the implementation.
+    // It is important to reset the video and image decode/encode capabilities,
+    // to prevent attempts to use them (crbug.com/702417).
+    gpu_info_.driver_vendor = "Google Inc.";
+    gpu_info_.driver_version = "3.3.0.2";
+    gpu_info_.driver_date = "2017/04/07";
+    gpu_info_.pixel_shader_version = "3.0";
+    gpu_info_.vertex_shader_version = "3.0";
+    gpu_info_.max_msaa_samples = "4";
+    gpu_info_.gl_version = "OpenGL ES 2.0 SwiftShader";
     gpu_info_.gl_vendor = "Google Inc.";
     gpu_info_.gl_renderer = "Google SwiftShader";
+    gpu_info_.gl_extensions = "";
+    gpu_info_.gl_reset_notification_strategy = 0;
     gpu_info_.software_rendering = true;
+    gpu_info_.passthrough_cmd_decoder = false;
+    gpu_info_.supports_overlays = false;
+    gpu_info_.basic_info_state = gpu::kCollectInfoSuccess;
+    gpu_info_.context_info_state = gpu::kCollectInfoSuccess;
+    gpu_info_.video_decode_accelerator_capabilities = {};
+    gpu_info_.video_encode_accelerator_supported_profiles = {};
+    gpu_info_.jpeg_decode_accelerator_supported = false;
+
+    gpu_info_.gpu.active = false;
+    for (auto& secondary_gpu : gpu_info_.secondary_gpus)
+      secondary_gpu.active = false;
 
     for (auto& status : gpu_feature_info_.status_values)
       status = gpu::kGpuFeatureStatusBlacklisted;
diff --git a/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc b/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc
index 86c525d..137e9ca 100644
--- a/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc
+++ b/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc
@@ -185,8 +185,8 @@
               manager->GetBlacklistedFeatureCount());
     EXPECT_TRUE(manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL2));
   } else {
-    EXPECT_FALSE(manager->GpuAccessAllowed(&reason));
-    EXPECT_FALSE(reason.empty());
+    EXPECT_TRUE(manager->GpuAccessAllowed(&reason));
+    EXPECT_TRUE(reason.empty());
     EXPECT_EQ(2u, manager->GetBlacklistedFeatureCount());
     EXPECT_FALSE(manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL2));
   }
@@ -570,7 +570,12 @@
 
   // Not enough GPUInfo.
   EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
-  EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount());
+  if (manager->ShouldUseSwiftShader()) {
+    EXPECT_EQ(static_cast<size_t>(gpu::NUMBER_OF_GPU_FEATURE_TYPES),
+              manager->GetBlacklistedFeatureCount());
+  } else {
+    EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount());
+  }
 
   // Now assume browser gets GL strings from local state.
   // The entry applies, blacklist more features than from the preliminary step.
@@ -578,7 +583,12 @@
   // happens before renderer launching.
   manager->SetGLStrings(kGLVendorMesa, kGLRendererMesa, kGLVersionMesa801);
   EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
-  EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount());
+  if (manager->ShouldUseSwiftShader()) {
+    EXPECT_EQ(static_cast<size_t>(gpu::NUMBER_OF_GPU_FEATURE_TYPES),
+              manager->GetBlacklistedFeatureCount());
+  } else {
+    EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount());
+  }
   EXPECT_TRUE(
       manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_WEBGL));
 }
@@ -611,7 +621,12 @@
 
   // Full GPUInfo, the entry applies.
   EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
-  EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount());
+  if (manager->ShouldUseSwiftShader()) {
+    EXPECT_EQ(static_cast<size_t>(gpu::NUMBER_OF_GPU_FEATURE_TYPES),
+              manager->GetBlacklistedFeatureCount());
+  } else {
+    EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount());
+  }
   EXPECT_TRUE(
       manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_WEBGL));
 
@@ -620,7 +635,12 @@
   // (Otherwise the entry should not apply.)
   manager->SetGLStrings(kGLVendorMesa, kGLRendererMesa, kGLVersionMesa802);
   EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
-  EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount());
+  if (manager->ShouldUseSwiftShader()) {
+    EXPECT_EQ(static_cast<size_t>(gpu::NUMBER_OF_GPU_FEATURE_TYPES),
+              manager->GetBlacklistedFeatureCount());
+  } else {
+    EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount());
+  }
   EXPECT_TRUE(
       manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_WEBGL));
 }
@@ -651,7 +671,13 @@
   manager->InitializeForTesting(kData, gpu_info);
 
   EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
-  EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount());
+  if (manager->ShouldUseSwiftShader()) {
+    EXPECT_EQ(static_cast<size_t>(gpu::NUMBER_OF_GPU_FEATURE_TYPES),
+              manager->GetBlacklistedFeatureCount());
+  } else {
+    EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount());
+  }
+
   EXPECT_TRUE(
       manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_WEBGL));
 }
@@ -745,20 +771,18 @@
       run_loop.RunUntilIdle();
     }
     EXPECT_TRUE(observer.gpu_info_updated());
-
     EXPECT_EQ(static_cast<size_t>(gpu::NUMBER_OF_GPU_FEATURE_TYPES),
               manager->GetBlacklistedFeatureCount());
   } else {
     EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount());
 
-    // Update with the same Intel GPU active.
+    // Update to previous Intel GPU.
     EXPECT_FALSE(manager->UpdateActiveGpu(0x8086, 0x04a1));
     {
       base::RunLoop run_loop;
       run_loop.RunUntilIdle();
     }
     EXPECT_FALSE(observer.gpu_info_updated());
-
     EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount());
   }
 
@@ -779,24 +803,18 @@
   observer.Reset();
   EXPECT_FALSE(observer.gpu_info_updated());
 
+  // Update to previous NVIDIA GPU.
+  EXPECT_FALSE(manager->UpdateActiveGpu(0x10de, 0x0640));
+  {
+    base::RunLoop run_loop;
+    run_loop.RunUntilIdle();
+  }
+  EXPECT_FALSE(observer.gpu_info_updated());
+
   if (manager->ShouldUseSwiftShader()) {
-    // Update to previous NVIDIA GPU.
-    EXPECT_TRUE(manager->UpdateActiveGpu(0x10de, 0x0640));
-    {
-      base::RunLoop run_loop;
-      run_loop.RunUntilIdle();
-    }
-    EXPECT_TRUE(observer.gpu_info_updated());
     EXPECT_EQ(static_cast<size_t>(gpu::NUMBER_OF_GPU_FEATURE_TYPES),
               manager->GetBlacklistedFeatureCount());
   } else {
-    // 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());
   }
 
diff --git a/content/test/gpu/gpu_tests/gpu_process_expectations.py b/content/test/gpu/gpu_tests/gpu_process_expectations.py
index 1706628b..b459316 100644
--- a/content/test/gpu/gpu_tests/gpu_process_expectations.py
+++ b/content/test/gpu/gpu_tests/gpu_process_expectations.py
@@ -17,16 +17,15 @@
     self.Skip('GpuProcess_no_gpu_process', ['android'], bug=643282)
     self.Skip('GpuProcess_skip_gpu_process', ['android'], bug=(610951, 610023))
 
-    # Chrome on Windows creates a GPU process that uses SwiftShader when using
-    # either --disable-gpu or a blacklisted GPU.
+    # Chrome on Windows and Linux create a GPU process that uses SwiftShader
+    # when using either --disable-gpu or a blacklisted GPU.
     self.Skip('GpuProcess_no_gpu_process', ['win', 'debug'], bug=630728)
-    self.Skip('GpuProcess_skip_gpu_process', ['win'], bug=630728)
+    self.Skip('GpuProcess_skip_gpu_process', ['win', 'linux'], bug=630728)
 
-    # Currently SwiftShader's integrated only on Windows. Remove
-    # platforms from this suppression as it is integrated on more
-    # platforms.
+    # Currently SwiftShader is integrated only on Windows and Linux. Remove
+    # platforms from this suppression as it is integrated on more platforms.
     self.Skip('GpuProcess_swiftshader_for_webgl',
-              ['mac', 'linux', 'android', 'chromeos'], bug=630728)
+              ['mac', 'android', 'chromeos'], bug=630728)
 
     # There is no Android multi-gpu configuration and the helper
     # gpu_info_collector.cc::IdentifyActiveGPU is not even called.
diff --git a/content/test/gpu/gpu_tests/gpu_process_integration_test.py b/content/test/gpu/gpu_tests/gpu_process_integration_test.py
index bb144a4..207bbad 100644
--- a/content/test/gpu/gpu_tests/gpu_process_integration_test.py
+++ b/content/test/gpu/gpu_tests/gpu_process_integration_test.py
@@ -469,7 +469,8 @@
       '--gpu-testing-device-id=0x040a',
       '--gpu-testing-secondary-vendor-ids=0x10de',
       '--gpu-testing-secondary-device-ids=0x0de1',
-      '--gpu-testing-gl-vendor=nouveau'])
+      '--gpu-testing-gl-vendor=nouveau',
+      '--disable-software-rasterizer'])
     self._Navigate(test_path)
     self._VerifyActiveAndInactiveGPUs(
       ['VENDOR = 0x10de, DEVICE= 0x0de1 *ACTIVE*'],
@@ -481,7 +482,8 @@
       '--gpu-testing-device-id=0x040a',
       '--gpu-testing-secondary-vendor-ids=0x10de',
       '--gpu-testing-secondary-device-ids=0x0de1',
-      '--gpu-testing-gl-vendor=Intel'])
+      '--gpu-testing-gl-vendor=Intel',
+      '--disable-software-rasterizer'])
     self._Navigate(test_path)
     self._VerifyActiveAndInactiveGPUs(
       ['VENDOR = 0x8086, DEVICE= 0x040a *ACTIVE*'],
@@ -494,7 +496,8 @@
       '--gpu-testing-secondary-vendor-ids=0x10de;0x1002',
       '--gpu-testing-secondary-device-ids=0x0de1;0x6779',
       '--gpu-testing-gl-vendor=X.Org',
-      '--gpu-testing-gl-renderer=AMD R600'])
+      '--gpu-testing-gl-renderer=AMD R600',
+      '--disable-software-rasterizer'])
     self._Navigate(test_path)
     self._VerifyActiveAndInactiveGPUs(
       ['VENDOR = 0x1002, DEVICE= 0x6779 *ACTIVE*'],
@@ -507,7 +510,8 @@
       '--gpu-testing-device-id=0x0de1',
       '--gpu-testing-secondary-vendor-ids=',
       '--gpu-testing-secondary-device-ids=',
-      '--gpu-testing-gl-vendor=nouveau'])
+      '--gpu-testing-gl-vendor=nouveau',
+      '--disable-software-rasterizer'])
     self._Navigate(test_path)
     self._VerifyActiveAndInactiveGPUs(
       ['VENDOR = 0x10de, DEVICE= 0x0de1 *ACTIVE*'],
@@ -561,10 +565,6 @@
     device = gpu.devices[0]
     if not device:
       self.fail("System Info doesn't have a device")
-    if device.vendor_id != 0:
-      self.fail("Wrong vendor ID. Expected 0, got " + hex(device.vendor_id))
-    if device.device_id != 0:
-      self.fail("Wrong device ID. Expected 0, got " + hex(device.device_id))
 
 def load_tests(loader, tests, pattern):
   del loader, tests, pattern  # Unused.
diff --git a/ui/gl/BUILD.gn b/ui/gl/BUILD.gn
index 35cce3c..a36683eb 100644
--- a/ui/gl/BUILD.gn
+++ b/ui/gl/BUILD.gn
@@ -10,7 +10,8 @@
 import("//testing/test.gni")
 
 declare_args() {
-  enable_swiftshader = is_win
+  enable_swiftshader = (is_win || (is_linux && !is_chromeos && use_x11)) &&
+                       (target_cpu == "x86" || target_cpu == "x64")
 }
 
 use_egl = is_win || is_android || is_linux