Blacklist Metal on macOS 10.12

Metal has an extremely elevated crash rate on macOS 10.12, across all
GPU vendors.

Bug: 963000
Change-Id: I206f3035d9a1bbf0aa1bb1fefe23278542c58e03
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1614464
Reviewed-by: Eric Karl <ericrk@chromium.org>
Reviewed-by: Zhenyao Mo <zmo@chromium.org>
Commit-Queue: ccameron <ccameron@chromium.org>
Cr-Commit-Position: refs/heads/master@{#660564}
diff --git a/components/viz/service/gl/gpu_service_impl.cc b/components/viz/service/gl/gpu_service_impl.cc
index bdadb11..b683e51 100644
--- a/components/viz/service/gl/gpu_service_impl.cc
+++ b/components/viz/service/gl/gpu_service_impl.cc
@@ -179,8 +179,10 @@
 #endif
 
 #if defined(OS_MACOSX)
-  if (gpu_preferences.enable_metal)
+  if (gpu_feature_info_.status_values[gpu::GPU_FEATURE_TYPE_METAL] ==
+      gpu::kGpuFeatureStatusEnabled) {
     metal_context_provider_ = MetalContextProvider::Create();
+  }
 #endif
 
   gpu_memory_buffer_factory_ =
diff --git a/content/browser/gpu/compositor_util.cc b/content/browser/gpu/compositor_util.cc
index 75be2ce..e850ca4 100644
--- a/content/browser/gpu/compositor_util.cc
+++ b/content/browser/gpu/compositor_util.cc
@@ -169,12 +169,13 @@
        "Out-of-process accelerated rasterization has been disabled, either "
        "via blacklist, about:flags or the command line.",
        false, true},
-      {"metal", gpu::kGpuFeatureStatusEnabled,
+      {"metal",
+       SafeGetFeatureStatus(gpu_feature_info, gpu::GPU_FEATURE_TYPE_METAL),
 #if defined(OS_MACOSX)
        !base::FeatureList::IsEnabled(features::kMetal) /* disabled */,
        "Metal is not enabled by default.",
 #else
-       true /* disabled */, "Metal only available on macOS.",
+       true /* disabled */, "Metal is only available on macOS.",
 #endif
        false /* fallback_to_software */, false /* needs_gpu_access */},
       {"multiple_raster_threads", gpu::kGpuFeatureStatusEnabled,
@@ -239,12 +240,6 @@
     std::string status;
     if (gpu_feature_data.name == "surface_synchronization") {
       status = (!gpu_feature_data.disabled ? "enabled_on" : "disabled_off");
-    } else if (gpu_feature_data.name == "metal") {
-#if defined(OS_MACOSX)
-      status = (!gpu_feature_data.disabled ? "enabled_on" : "disabled_off");
-#else
-      status = "unavailable_off";
-#endif
     } else if (gpu_feature_data.name == "viz_display_compositor") {
       status = (!gpu_feature_data.disabled ? "enabled_on" : "disabled_off");
     } else if (gpu_feature_data.disabled || gpu_access_blocked ||
@@ -284,6 +279,8 @@
         if (features::IsVizHitTestingSurfaceLayerEnabled())
           status += "_on";
       }
+      if (gpu_feature_data.name == "metal")
+        status += "_on";
     }
     feature_status_dict->SetString(gpu_feature_data.name, status);
   }
diff --git a/gpu/config/gpu_blacklist.cc b/gpu/config/gpu_blacklist.cc
index e7e24c8d..66eebdd 100644
--- a/gpu/config/gpu_blacklist.cc
+++ b/gpu/config/gpu_blacklist.cc
@@ -47,7 +47,7 @@
                             GPU_FEATURE_TYPE_OOP_RASTERIZATION);
   list->AddSupportedFeature("android_surface_control",
                             GPU_FEATURE_TYPE_ANDROID_SURFACE_CONTROL);
-
+  list->AddSupportedFeature("metal", GPU_FEATURE_TYPE_METAL);
   return list;
 }
 
diff --git a/gpu/config/gpu_feature_type.h b/gpu/config/gpu_feature_type.h
index a9684b9..5ac3ab5 100644
--- a/gpu/config/gpu_feature_type.h
+++ b/gpu/config/gpu_feature_type.h
@@ -23,6 +23,7 @@
   GPU_FEATURE_TYPE_PROTECTED_VIDEO_DECODE,
   GPU_FEATURE_TYPE_OOP_RASTERIZATION,
   GPU_FEATURE_TYPE_ANDROID_SURFACE_CONTROL,
+  GPU_FEATURE_TYPE_METAL,
   NUMBER_OF_GPU_FEATURE_TYPES
 };
 
diff --git a/gpu/config/gpu_util.cc b/gpu/config/gpu_util.cc
index f07f9bf..5c76828 100644
--- a/gpu/config/gpu_util.cc
+++ b/gpu/config/gpu_util.cc
@@ -56,6 +56,22 @@
 #endif
 }
 
+GpuFeatureStatus GetMetalFeatureStatus(
+    const std::set<int>& blacklisted_features,
+    const GpuPreferences& gpu_preferences) {
+#if defined(OS_MACOSX)
+  if (blacklisted_features.count(GPU_FEATURE_TYPE_METAL))
+    return kGpuFeatureStatusBlacklisted;
+
+  if (!gpu_preferences.enable_metal)
+    return kGpuFeatureStatusDisabled;
+
+  return kGpuFeatureStatusEnabled;
+#else
+  return kGpuFeatureStatusDisabled;
+#endif
+}
+
 GpuFeatureStatus GetGpuRasterizationFeatureStatus(
     const std::set<int>& blacklisted_features,
     const base::CommandLine& command_line) {
@@ -292,6 +308,8 @@
       kGpuFeatureStatusDisabled;
   gpu_feature_info.status_values[GPU_FEATURE_TYPE_ANDROID_SURFACE_CONTROL] =
       kGpuFeatureStatusDisabled;
+  gpu_feature_info.status_values[GPU_FEATURE_TYPE_METAL] =
+      kGpuFeatureStatusDisabled;
 #if DCHECK_IS_ON()
   for (int ii = 0; ii < NUMBER_OF_GPU_FEATURE_TYPES; ++ii) {
     DCHECK_NE(kGpuFeatureStatusUndefined, gpu_feature_info.status_values[ii]);
@@ -326,6 +344,8 @@
       kGpuFeatureStatusDisabled;
   gpu_feature_info.status_values[GPU_FEATURE_TYPE_ANDROID_SURFACE_CONTROL] =
       kGpuFeatureStatusDisabled;
+  gpu_feature_info.status_values[GPU_FEATURE_TYPE_METAL] =
+      kGpuFeatureStatusDisabled;
 #if DCHECK_IS_ON()
   for (int ii = 0; ii < NUMBER_OF_GPU_FEATURE_TYPES; ++ii) {
     DCHECK_NE(kGpuFeatureStatusUndefined, gpu_feature_info.status_values[ii]);
@@ -360,6 +380,8 @@
       kGpuFeatureStatusDisabled;
   gpu_feature_info.status_values[GPU_FEATURE_TYPE_ANDROID_SURFACE_CONTROL] =
       kGpuFeatureStatusDisabled;
+  gpu_feature_info.status_values[GPU_FEATURE_TYPE_METAL] =
+      kGpuFeatureStatusDisabled;
 #if DCHECK_IS_ON()
   for (int ii = 0; ii < NUMBER_OF_GPU_FEATURE_TYPES; ++ii) {
     DCHECK_NE(kGpuFeatureStatusUndefined, gpu_feature_info.status_values[ii]);
@@ -435,6 +457,8 @@
   gpu_feature_info.status_values[GPU_FEATURE_TYPE_ANDROID_SURFACE_CONTROL] =
       GetAndroidSurfaceControlFeatureStatus(blacklisted_features,
                                             gpu_preferences);
+  gpu_feature_info.status_values[GPU_FEATURE_TYPE_METAL] =
+      GetMetalFeatureStatus(blacklisted_features, gpu_preferences);
 #if DCHECK_IS_ON()
   for (int ii = 0; ii < NUMBER_OF_GPU_FEATURE_TYPES; ++ii) {
     DCHECK_NE(kGpuFeatureStatusUndefined, gpu_feature_info.status_values[ii]);
diff --git a/gpu/config/software_rendering_list.json b/gpu/config/software_rendering_list.json
index d4c3b43..0042a34 100644
--- a/gpu/config/software_rendering_list.json
+++ b/gpu/config/software_rendering_list.json
@@ -1734,6 +1734,21 @@
       "features": [
         "all"
       ]
+    },
+    {
+      "id": 162,
+      "cr_bugs": [963000],
+      "description": "Metal is very crashy on macOS 10.12",
+      "os": {
+        "type": "macosx",
+        "version": {
+          "op": "=",
+          "value": "10.12"
+        }
+      },
+      "features": [
+        "metal"
+      ]
     }
   ]
 }