[go: nahoru, domu]

gpu: Skia Graphite build and feature flags

1. Add build and feature flags for Graphite, both disabled by default.
2. Add skia_use_metal buildflag for guarding metal code. This flag is
   only enabled with Graphite on developer builds.
3. Add SkiaGraphiteBackend to GpuPreferences, and parse its value from
   feature and command line flags. Also add a kNone option for Ganesh
   GrContextType for when Graphite is enabled.
4. Cleanup Chromium Skia BUILD.gn - more consistency between the config
   and sources in how we use conditionals. Ensure dawn and metal code is
   only built when Graphite is used, and other miscellaneous cleanup.
5. Remove Ganesh Dawn from Chromium including in blink over WebGPU
   command buffer, so both Dawn and Metal are only used with Graphite.

This doesn't yet rename the cc/viz pixel test enums - that will be a
separate followup change since it would otherwise add a dozen or two
more changed files to this CL.

Bug: 1429361
Change-Id: Ibf129727e03c303bfac85b98c111b08d880f408f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4404275
Reviewed-by: Vasiliy Telezhnikov <vasilyt@chromium.org>
Commit-Queue: Sunny Sachanandani <sunnyps@chromium.org>
Reviewed-by: Kyle Charbonneau <kylechar@chromium.org>
Reviewed-by: Kevin Lubick <kjlubick@chromium.org>
Reviewed-by: Kenneth Russell <kbr@chromium.org>
Reviewed-by: Matthew Denton <mpdenton@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1128336}
diff --git a/cc/paint/paint_image.cc b/cc/paint/paint_image.cc
index 58b98ce..6e774633 100644
--- a/cc/paint/paint_image.cc
+++ b/cc/paint/paint_image.cc
@@ -260,7 +260,8 @@
   auto image = GetSkImageForFrame(frame_index, client_id);
   DCHECK(image);
   if (color_space) {
-    image = image->makeColorSpace(color_space, nullptr);
+    image = image->makeColorSpace(color_space,
+                                  static_cast<GrDirectContext*>(nullptr));
     if (!image)
       return false;
   }
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc
index 6f528bb..01edfcf 100644
--- a/cc/test/layer_tree_test.cc
+++ b/cc/test/layer_tree_test.cc
@@ -715,7 +715,7 @@
     scoped_feature_list_.InitAndEnableFeature(features::kVulkan);
     init_vulkan = true;
   } else if (renderer_type_ == viz::RendererType::kSkiaDawn) {
-    scoped_feature_list_.InitAndEnableFeature(features::kSkiaDawn);
+    scoped_feature_list_.InitAndEnableFeature(features::kSkiaGraphite);
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
     init_vulkan = true;
 #elif BUILDFLAG(IS_WIN)
diff --git a/cc/test/pixel_test.cc b/cc/test/pixel_test.cc
index 9e66dc3..ef90eb4d 100644
--- a/cc/test/pixel_test.cc
+++ b/cc/test/pixel_test.cc
@@ -67,7 +67,7 @@
     scoped_feature_list_.InitAndEnableFeature(features::kVulkan);
     init_vulkan = true;
   } else if (backend == kSkiaDawn) {
-    scoped_feature_list_.InitAndEnableFeature(features::kSkiaDawn);
+    scoped_feature_list_.InitAndEnableFeature(features::kSkiaGraphite);
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
     init_vulkan = true;
 #elif BUILDFLAG(IS_WIN)
diff --git a/components/viz/common/BUILD.gn b/components/viz/common/BUILD.gn
index 44c49e0..1f604cf5e 100644
--- a/components/viz/common/BUILD.gn
+++ b/components/viz/common/BUILD.gn
@@ -67,9 +67,7 @@
   }
 }
 
-# TODO(rivr): To reduce link times, merge these context provider components
-# into a single gr_context_provider component.
-if (is_apple) {
+if (skia_use_metal) {
   viz_component("metal_context_provider") {
     output_name = "viz_metal_context_provider"
 
@@ -366,7 +364,7 @@
   if (enable_vulkan) {
     public_deps += [ ":vulkan_context_provider" ]
   }
-  if (is_apple) {
+  if (skia_use_metal) {
     public_deps += [ ":metal_context_provider" ]
   }
   if (skia_use_dawn) {
diff --git a/components/viz/service/display/software_renderer.cc b/components/viz/service/display/software_renderer.cc
index 0b27e46..f084ef78 100644
--- a/components/viz/service/display/software_renderer.cc
+++ b/components/viz/service/display/software_renderer.cc
@@ -855,8 +855,8 @@
       return nullptr;
     // Crop the source image to the backdrop_filter_bounds.
     sk_sp<SkImage> cropped_image = SkImages::RasterFromBitmap(backdrop_bitmap);
-    cropped_image =
-        cropped_image->makeSubset(RectToSkIRect(filter_clip), nullptr);
+    cropped_image = cropped_image->makeSubset(
+        RectToSkIRect(filter_clip), static_cast<GrDirectContext*>(nullptr));
     cropped_image->asLegacyBitmap(&backdrop_bitmap);
     image_offset = filter_clip.origin();
   }
diff --git a/components/viz/service/display_embedder/skia_output_surface_dependency.h b/components/viz/service/display_embedder/skia_output_surface_dependency.h
index c07b7ef..d7187e3 100644
--- a/components/viz/service/display_embedder/skia_output_surface_dependency.h
+++ b/components/viz/service/display_embedder/skia_output_surface_dependency.h
@@ -118,10 +118,6 @@
   bool IsUsingVulkan() const {
     return gr_context_type() == gpu::GrContextType::kVulkan;
   }
-
-  bool IsUsingDawn() const {
-    return gr_context_type() == gpu::GrContextType::kDawn;
-  }
 };
 
 }  // namespace viz
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.cc b/components/viz/service/display_embedder/skia_output_surface_impl.cc
index 9649a4e..10c7edd 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl.cc
+++ b/components/viz/service/display_embedder/skia_output_surface_impl.cc
@@ -1267,7 +1267,7 @@
     int plane_index,
     uint32_t gl_texture_target,
     const absl::optional<gpu::VulkanYCbCrInfo>& ycbcr_info) {
-  if (dependency_->IsUsingVulkan()) {
+  if (dependency_->gr_context_type() == gpu::GrContextType::kVulkan) {
 #if BUILDFLAG(ENABLE_VULKAN)
     if (!ycbcr_info) {
       return GrBackendFormat::MakeVk(gpu::ToVkFormat(si_format, plane_index));
@@ -1288,19 +1288,8 @@
     return GrBackendFormat::MakeVk(gr_ycbcr_info);
 #endif  // BUILDFLAG(IS_LINUX)
 #endif  // BUILDFLAG(ENABLE_VULKAN)
-  } else if (dependency_->IsUsingDawn()) {
-#if BUILDFLAG(SKIA_USE_DAWN)
-    // TODO(hitawala): Add multiplanar support for Skia-Dawn.
-    wgpu::TextureFormat wgpu_format = gpu::ToDawnFormat(si_format);
-    // Return an invalid backend format if we can't find an appropriate Dawn
-    // format, otherwise Skia will end up calling Dawn CreateTexture with the
-    // wgou::TextureFormat::Undefined which can cause security issues.
-    if (wgpu_format == wgpu::TextureFormat::Undefined) {
-      return GrBackendFormat();
-    }
-    return GrBackendFormat::MakeDawn(wgpu_format);
-#endif
   } else {
+    CHECK_EQ(dependency_->gr_context_type(), gpu::GrContextType::kGL);
     // Convert internal format from GLES2 to platform GL.
     bool use_angle_rgbx_format = impl_on_gpu_->GetFeatureInfo()
                                      ->feature_flags()
@@ -1316,8 +1305,6 @@
 
     return GrBackendFormat::MakeGL(texture_storage_format, gl_texture_target);
   }
-  NOTREACHED();
-  return GrBackendFormat();
 }
 
 bool SkiaOutputSurfaceImpl::IsDisplayedAsOverlayPlane() const {
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
index bb957ee..76ae090 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
+++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -554,9 +554,6 @@
       release_fence = CreateReleaseFenceForGL();
     }
 
-    if (!return_release_fence_cb.is_null() && is_using_dawn())
-      NOTIMPLEMENTED() << "Release fences with dawn are not supported.";
-
     if (!return_release_fence_cb.is_null()) {
       // Returning fences for Vulkan is delayed. See the comment above.
       DCHECK(!is_using_vulkan());
@@ -747,9 +744,6 @@
       release_fence = CreateReleaseFenceForGL();
     }
 
-    if (!return_release_fence_cb.is_null() && is_using_dawn())
-      NOTIMPLEMENTED() << "Release fences with dawn are not supported.";
-
     if (!return_release_fence_cb.is_null()) {
       // Returning fences for Vulkan is delayed. See the comment above.
       DCHECK(!is_using_vulkan());
@@ -1703,9 +1697,6 @@
   if (is_using_vulkan()) {
     if (!InitializeForVulkan())
       return false;
-  } else if (is_using_dawn()) {
-    if (!InitializeForDawn())
-      return false;
   } else {
     if (!InitializeForGL())
       return false;
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
index 261e640..c539eb7 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
+++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
@@ -318,12 +318,10 @@
     return !!vulkan_context_provider_ &&
            gpu_preferences_.gr_context_type == gpu::GrContextType::kVulkan;
   }
-  bool is_using_dawn() const {
-    return !!dawn_context_provider_ &&
-           gpu_preferences_.gr_context_type == gpu::GrContextType::kDawn;
-  }
 
-  bool is_using_gl() const { return !is_using_vulkan() && !is_using_dawn(); }
+  bool is_using_gl() const {
+    return gpu_preferences_.gr_context_type == gpu::GrContextType::kGL;
+  }
 
   // Helper for `CopyOutput()` method, handles the RGBA format.
   void CopyOutputRGBA(SkSurface* surface,
diff --git a/components/viz/service/gl/gpu_service_impl.cc b/components/viz/service/gl/gpu_service_impl.cc
index 81c7d5f..3f15a68 100644
--- a/components/viz/service/gl/gpu_service_impl.cc
+++ b/components/viz/service/gl/gpu_service_impl.cc
@@ -27,7 +27,6 @@
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
 #include "components/viz/common/features.h"
-#include "components/viz/common/gpu/metal_context_provider.h"
 #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
 #include "gpu/command_buffer/service/gpu_switches.h"
 #include "gpu/command_buffer/service/scheduler.h"
@@ -120,6 +119,10 @@
 #include "components/viz/common/gpu/dawn_context_provider.h"
 #endif
 
+#if BUILDFLAG(SKIA_USE_METAL)
+#include "components/viz/common/gpu/metal_context_provider.h"
+#endif
+
 #if BUILDFLAG(CLANG_PROFILING_INSIDE_SANDBOX)
 #include "base/test/clang_profiling.h"
 #endif
@@ -362,7 +365,7 @@
 #endif
 
 #if BUILDFLAG(SKIA_USE_DAWN)
-  if (gpu_preferences_.gr_context_type == gpu::GrContextType::kDawn) {
+  if (gpu_preferences_.gr_context_type == gpu::GrContextType::kGraphiteDawn) {
     dawn_context_provider_ = DawnContextProvider::Create();
     if (!dawn_context_provider_) {
       DLOG(ERROR) << "Failed to create Dawn context provider.";
@@ -585,7 +588,7 @@
       gpu_memory_buffer_factory_.get(), gpu_feature_info_,
       std::move(activity_flags), std::move(default_offscreen_surface),
       image_decode_accelerator_worker_.get(), vulkan_context_provider(),
-      metal_context_provider_.get(), dawn_context_provider());
+      metal_context_provider(), dawn_context_provider());
 
   media_gpu_channel_manager_ = std::make_unique<media::MediaGpuChannelManager>(
       gpu_channel_manager_.get());
diff --git a/components/viz/service/gl/gpu_service_impl.h b/components/viz/service/gl/gpu_service_impl.h
index c00612fa..d6cfd83 100644
--- a/components/viz/service/gl/gpu_service_impl.h
+++ b/components/viz/service/gl/gpu_service_impl.h
@@ -344,26 +344,27 @@
   }
 
 #if BUILDFLAG(ENABLE_VULKAN)
-  bool is_using_vulkan() const {
-    return !!vulkan_context_provider_ &&
-           gpu_preferences_.gr_context_type == gpu::GrContextType::kVulkan;
-  }
-  VulkanContextProvider* vulkan_context_provider() {
+  VulkanContextProvider* vulkan_context_provider() const {
     return vulkan_context_provider_.get();
   }
 #else
-  bool is_using_vulkan() const { return false; }
-  VulkanContextProvider* vulkan_context_provider() { return nullptr; }
+  VulkanContextProvider* vulkan_context_provider() const { return nullptr; }
+#endif
+
+#if BUILDFLAG(SKIA_USE_METAL)
+  MetalContextProvider* metal_context_provider() const {
+    return metal_context_provider_.get();
+  }
+#else
+  MetalContextProvider* metal_context_provider() const { return nullptr; }
 #endif
 
 #if BUILDFLAG(SKIA_USE_DAWN)
-  bool is_using_dawn() const { return !!dawn_context_provider_; }
-  DawnContextProvider* dawn_context_provider() {
+  DawnContextProvider* dawn_context_provider() const {
     return dawn_context_provider_.get();
   }
 #else
-  bool is_using_dawn() const { return false; }
-  DawnContextProvider* dawn_context_provider() { return nullptr; }
+  DawnContextProvider* dawn_context_provider() const { return nullptr; }
 #endif
 
   base::ProcessId host_process_id() const { return host_process_id_; }
@@ -478,7 +479,9 @@
   raw_ptr<gpu::VulkanImplementation> vulkan_implementation_;
   scoped_refptr<VulkanContextProvider> vulkan_context_provider_;
 #endif
+#if BUILDFLAG(SKIA_USE_METAL)
   std::unique_ptr<MetalContextProvider> metal_context_provider_;
+#endif
 #if BUILDFLAG(SKIA_USE_DAWN)
   std::unique_ptr<DawnContextProvider> dawn_context_provider_;
 #endif
diff --git a/components/viz/test/BUILD.gn b/components/viz/test/BUILD.gn
index 4bbb5c8..62b21b8 100644
--- a/components/viz/test/BUILD.gn
+++ b/components/viz/test/BUILD.gn
@@ -17,7 +17,9 @@
   flags = [
     "ENABLE_GL_BACKEND_TESTS=$enable_gl_backend_tests",
     "ENABLE_VULKAN_BACKEND_TESTS=$enable_vulkan_backend_tests",
-    "ENABLE_DAWN_BACKEND_TESTS=$enable_dawn_backend_tests",
+
+    # TODO(sunnyps): Rename define to ENABLE_SKIA_GRAPHITE_TESTS.
+    "ENABLE_DAWN_BACKEND_TESTS=$enable_skia_graphite_tests",
     "IS_ANDROID_EMULATOR=$is_android_emulator",
   ]
 }
diff --git a/components/viz/viz.gni b/components/viz/viz.gni
index c4b5a16a..18b367b 100644
--- a/components/viz/viz.gni
+++ b/components/viz/viz.gni
@@ -17,7 +17,7 @@
     enable_vulkan &&
     ((is_linux && !is_castos && !is_cfi) || (is_fuchsia && target_cpu == "x64"))
 
-enable_dawn_backend_tests = skia_use_dawn && enable_skia_dawn_gtests
+enable_skia_graphite_tests = enable_skia_graphite && enable_skia_graphite_gtests
 
 # TODO(crbug.com/1336055): Determine whether is_cast_android needs this.
 enable_cast_overlay_strategy = is_castos || is_cast_android
diff --git a/content/browser/gpu/compositor_util.cc b/content/browser/gpu/compositor_util.cc
index b113150..2dfdb62 100644
--- a/content/browser/gpu/compositor_util.cc
+++ b/content/browser/gpu/compositor_util.cc
@@ -39,6 +39,7 @@
 #include "gpu/vulkan/buildflags.h"
 #include "media/base/media_switches.h"
 #include "media/media_buildflags.h"
+#include "skia/buildflags.h"
 #include "third_party/blink/public/common/switches.h"
 #include "ui/base/ui_base_features.h"
 #include "ui/gl/gl_switches.h"
@@ -220,6 +221,13 @@
      DisableInfo::Problem(
          "WebGPU has been disabled via blocklist or the command line."),
      false},
+#if BUILDFLAG(ENABLE_SKIA_GRAPHITE)
+    {"skia_graphite",
+     SafeGetFeatureStatus(gpu_feature_info,
+                          gpu::GPU_FEATURE_TYPE_SKIA_GRAPHITE),
+     !base::FeatureList::IsEnabled(features::kSkiaGraphite),
+     DisableInfo::NotProblem(), false},
+#endif  // BUILDFLAG(ENABLE_SKIA_GRAPHITE)
   };
   DCHECK(index < std::size(kGpuFeatureData));
   *eof = (index == std::size(kGpuFeatureData) - 1);
diff --git a/gpu/command_buffer/service/BUILD.gn b/gpu/command_buffer/service/BUILD.gn
index 5ad724d..0f02b5de 100644
--- a/gpu/command_buffer/service/BUILD.gn
+++ b/gpu/command_buffer/service/BUILD.gn
@@ -482,7 +482,6 @@
   }
 
   if (is_apple) {
-    deps += [ "//components/viz/common:metal_context_provider" ]
     sources += [
       "shared_image/iosurface_image_backing.h",
       "shared_image/iosurface_image_backing.mm",
@@ -491,6 +490,10 @@
       "shared_image/shared_image_format_utils_mac.mm",
     ]
 
+    if (skia_use_metal) {
+      deps += [ "//components/viz/common:metal_context_provider" ]
+    }
+
     # Required by gles2_cmd_decoder.cc on Apple.
     frameworks = [
       "IOSurface.framework",
diff --git a/gpu/command_buffer/service/raster_decoder.cc b/gpu/command_buffer/service/raster_decoder.cc
index 2b693fe..bb3ded7 100644
--- a/gpu/command_buffer/service/raster_decoder.cc
+++ b/gpu/command_buffer/service/raster_decoder.cc
@@ -1166,12 +1166,10 @@
 #else
     NOTREACHED();
 #endif
-  } else if (shared_context_state_->GrContextIsDawn()) {
+  } else {
     // TODO(crbug.com/1090476): Query Dawn for this value once an API exists for
     // capabilities.
     caps.max_texture_size = 8192;
-  } else {
-    NOTIMPLEMENTED();
   }
   if (feature_info()->workarounds().webgl_or_caps_max_texture_size) {
     caps.max_texture_size =
diff --git a/gpu/command_buffer/service/service_utils.cc b/gpu/command_buffer/service/service_utils.cc
index 9512d0a..8ba3cac 100644
--- a/gpu/command_buffer/service/service_utils.cc
+++ b/gpu/command_buffer/service/service_utils.cc
@@ -183,7 +183,7 @@
         command_line->GetSwitchValueASCII(switches::kDisableDawnFeatures), ",",
         base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
   }
-  gpu_preferences.gr_context_type = ParseGrContextType();
+  gpu_preferences.gr_context_type = ParseGrContextType(command_line);
   gpu_preferences.use_vulkan = ParseVulkanImplementationName(command_line);
 
 #if BUILDFLAG(IS_FUCHSIA)
@@ -200,14 +200,27 @@
   return gpu_preferences;
 }
 
-GrContextType ParseGrContextType() {
+GrContextType ParseGrContextType(const base::CommandLine* command_line) {
+#if BUILDFLAG(ENABLE_SKIA_GRAPHITE)
+  if (base::FeatureList::IsEnabled(features::kSkiaGraphite)) {
+    [[maybe_unused]] auto value =
+        command_line->GetSwitchValueASCII(switches::kSkiaGraphiteBackend);
 #if BUILDFLAG(SKIA_USE_DAWN)
-  if (base::FeatureList::IsEnabled(features::kSkiaDawn))
-    return GrContextType::kDawn;
-#endif
+    if (value.empty() || value == switches::kSkiaGraphiteBackendDawn) {
+      return GrContextType::kGraphiteDawn;
+    }
+#endif  // BUILDFLAG(SKIA_USE_DAWN)
+#if BUILDFLAG(SKIA_USE_METAL)
+    if (value == switches::kSkiaGraphiteBackendMetal) {
+      return GrContextType::kGraphiteMetal;
+    }
+#endif  // BUILDFLAG(SKIA_USE_METAL)
+  }
+#endif  // BUILDFLAG(ENABLE_SKIA_GRAPHITE)
 
-  if (features::IsUsingVulkan())
+  if (features::IsUsingVulkan()) {
     return GrContextType::kVulkan;
+  }
 
   return GrContextType::kGL;
 }
diff --git a/gpu/command_buffer/service/service_utils.h b/gpu/command_buffer/service/service_utils.h
index 1462fff..32cd4f3 100644
--- a/gpu/command_buffer/service/service_utils.h
+++ b/gpu/command_buffer/service/service_utils.h
@@ -35,9 +35,12 @@
 ParseGpuPreferences(const base::CommandLine* command_line);
 
 // Determine which Skia GrContext backend will be used for GPU compositing and
-// rasterization (if enabled) by checking the feature flags for Vulkan and
-// Metal. If they are not enabled, default to GL.
-GPU_GLES2_EXPORT GrContextType ParseGrContextType();
+// rasterization (if enabled) by checking the feature flags for Vulkan and/or
+// Graphite. If they are not enabled, default to GL.
+// If Graphite is enabled, the backend is Dawn by default or cn be specified
+// using the --skia-graphite-backend flag.
+GPU_GLES2_EXPORT GrContextType
+ParseGrContextType(const base::CommandLine* command_line);
 
 // Parse the value of --use-vulkan from the command line. If unspecified and
 // features::kVulkan is enabled (GrContext is going to use vulkan), default to
diff --git a/gpu/command_buffer/service/shared_context_state.cc b/gpu/command_buffer/service/shared_context_state.cc
index 1aef09f..d18f8cf 100644
--- a/gpu/command_buffer/service/shared_context_state.cc
+++ b/gpu/command_buffer/service/shared_context_state.cc
@@ -44,7 +44,7 @@
 #include "gpu/vulkan/fuchsia/vulkan_fuchsia_ext.h"
 #endif
 
-#if BUILDFLAG(IS_APPLE)
+#if BUILDFLAG(SKIA_USE_METAL)
 #include "components/viz/common/gpu/metal_context_provider.h"
 #endif
 
@@ -174,11 +174,13 @@
       base::StringPrintf("%u", static_cast<uint32_t>(gr_context_type_)));
   // If |gr_context_type_| is not GL, then initialize |gr_context_| here. In
   // the case of GL, |gr_context_| will be initialized in InitializeGrContext.
-  // Note that if |gr_context_| is not GL and also not initialized here (e.g,
-  // due to vk/metal/dawn_context_provider_ being nullptr), then
-  // InitializeGrContext will fail.
+  // Note that if |gr_context_| is not GL and also not initialized here e.g.
+  // due to vk/metal_context_provider_ being nullptr, then InitializeGrContext
+  // will fail.
   switch (gr_context_type_) {
     case GrContextType::kGL:
+    case GrContextType::kGraphiteDawn:
+    case GrContextType::kGraphiteMetal:
       break;
     case GrContextType::kVulkan:
       if (vk_context_provider_) {
@@ -189,15 +191,6 @@
         use_virtualized_gl_contexts_ = false;
       }
       break;
-    case GrContextType::kDawn:
-      if (dawn_context_provider_) {
-#if BUILDFLAG(SKIA_USE_DAWN)
-        gr_context_ = dawn_context_provider_->GetGrContext();
-#endif
-        use_virtualized_gl_contexts_ = false;
-        DCHECK(gr_context_);
-      }
-      break;
   }
 
   if (base::SingleThreadTaskRunner::HasCurrentDefault()) {
@@ -271,7 +264,8 @@
   progress_reporter_ = progress_reporter;
   gr_shader_cache_ = cache;
 
-#if BUILDFLAG(IS_APPLE)
+  // TODO(sunnyps): Move this to InitializeGraphiteContext once that's a thing.
+#if BUILDFLAG(SKIA_USE_METAL)
   if (metal_context_provider_)
     metal_context_provider_->SetProgressReporter(progress_reporter);
 #endif
diff --git a/gpu/command_buffer/service/shared_context_state.h b/gpu/command_buffer/service/shared_context_state.h
index f4544bb..b10aad9 100644
--- a/gpu/command_buffer/service/shared_context_state.h
+++ b/gpu/command_buffer/service/shared_context_state.h
@@ -100,9 +100,6 @@
   bool GrContextIsVulkan() const {
     return gr_context_type_ == GrContextType::kVulkan;
   }
-  bool GrContextIsDawn() const {
-    return gr_context_type_ == GrContextType::kDawn;
-  }
 
   bool InitializeGL(const GpuPreferences& gpu_preferences,
                     scoped_refptr<gles2::FeatureInfo> feature_info);
diff --git a/gpu/command_buffer/service/shared_image/iosurface_image_backing.mm b/gpu/command_buffer/service/shared_image/iosurface_image_backing.mm
index c4b48884..ae8fe7b 100644
--- a/gpu/command_buffer/service/shared_image/iosurface_image_backing.mm
+++ b/gpu/command_buffer/service/shared_image/iosurface_image_backing.mm
@@ -7,7 +7,6 @@
 #include "base/mac/scoped_cftyperef.h"
 #include "base/mac/scoped_nsobject.h"
 #include "base/trace_event/memory_dump_manager.h"
-#include "components/viz/common/gpu/metal_context_provider.h"
 #include "components/viz/common/resources/resource_format_utils.h"
 #include "components/viz/common/resources/resource_sizes.h"
 #include "gpu/command_buffer/common/shared_image_trace_utils.h"
diff --git a/gpu/command_buffer/service/skia_utils.cc b/gpu/command_buffer/service/skia_utils.cc
index 7887148..cfea1853 100644
--- a/gpu/command_buffer/service/skia_utils.cc
+++ b/gpu/command_buffer/service/skia_utils.cc
@@ -385,14 +385,6 @@
       break;
     }
 #endif
-#if BUILDFLAG(SKIA_USE_DAWN)
-    case GrBackendApi::kDawn: {
-      GrDawnTextureInfo tex_info;
-      if (backend_texture.getDawnTextureInfo(&tex_info))
-        return reinterpret_cast<uint64_t>(tex_info.fTexture.Get());
-      break;
-    }
-#endif
     default:
       break;
   }
diff --git a/gpu/config/gpu_blocklist.cc b/gpu/config/gpu_blocklist.cc
index 04fe970..64766d4 100644
--- a/gpu/config/gpu_blocklist.cc
+++ b/gpu/config/gpu_blocklist.cc
@@ -45,6 +45,7 @@
                             GPU_FEATURE_TYPE_CANVAS_OOP_RASTERIZATION);
   list->AddSupportedFeature("accelerated_webgpu",
                             GPU_FEATURE_TYPE_ACCELERATED_WEBGPU);
+  list->AddSupportedFeature("skia_graphite", GPU_FEATURE_TYPE_SKIA_GRAPHITE);
   return list;
 }
 
diff --git a/gpu/config/gpu_blocklist_unittest.cc b/gpu/config/gpu_blocklist_unittest.cc
index 98f2c99..3d0ee17 100644
--- a/gpu/config/gpu_blocklist_unittest.cc
+++ b/gpu/config/gpu_blocklist_unittest.cc
@@ -107,6 +107,8 @@
 GPU_BLOCKLIST_FEATURE_TEST(AcceleratedWebGPU,
                            GPU_FEATURE_TYPE_ACCELERATED_WEBGPU)
 
+GPU_BLOCKLIST_FEATURE_TEST(SkiaGraphite, GPU_FEATURE_TYPE_SKIA_GRAPHITE)
+
 // Test for invariant "Assume the newly last added entry has the largest ID".
 // See GpuControlList::GpuControlList.
 // It checks software_rendering_list.json
diff --git a/gpu/config/gpu_feature_type.h b/gpu/config/gpu_feature_type.h
index f627940..9c503d8f 100644
--- a/gpu/config/gpu_feature_type.h
+++ b/gpu/config/gpu_feature_type.h
@@ -22,6 +22,7 @@
   GPU_FEATURE_TYPE_VULKAN,
   GPU_FEATURE_TYPE_CANVAS_OOP_RASTERIZATION,
   GPU_FEATURE_TYPE_ACCELERATED_WEBGPU,
+  GPU_FEATURE_TYPE_SKIA_GRAPHITE,
   NUMBER_OF_GPU_FEATURE_TYPES
 };
 
diff --git a/gpu/config/gpu_finch_features.cc b/gpu/config/gpu_finch_features.cc
index 25d3fa6..5f322f6 100644
--- a/gpu/config/gpu_finch_features.cc
+++ b/gpu/config/gpu_finch_features.cc
@@ -328,9 +328,12 @@
     &kEnableDrDc, "BlockListByAndroidBuildFP", ""};
 #endif  // BUILDFLAG(IS_ANDROID)
 
-// Enable SkiaRenderer Dawn graphics backend. On Windows this will use D3D12,
-// and on Linux this will use Vulkan.
-BASE_FEATURE(kSkiaDawn, "SkiaDawn", base::FEATURE_DISABLED_BY_DEFAULT);
+// Enable Skia Graphite. This will use the Dawn backend by default, but can be
+// overridden with command line flags for testing on non-official developer
+// builds. See --skia-graphite-backend flag in gpu_switches.h.
+BASE_FEATURE(kSkiaGraphite,
+             "SkiaUseGraphite",
+             base::FEATURE_DISABLED_BY_DEFAULT);
 
 // Enable GrShaderCache to use with Vulkan backend.
 BASE_FEATURE(kEnableGrShaderCacheForVulkan,
diff --git a/gpu/config/gpu_finch_features.h b/gpu/config/gpu_finch_features.h
index 1ed1bae..b34516a0 100644
--- a/gpu/config/gpu_finch_features.h
+++ b/gpu/config/gpu_finch_features.h
@@ -60,7 +60,7 @@
 
 GPU_EXPORT BASE_DECLARE_FEATURE(kVulkan);
 
-GPU_EXPORT BASE_DECLARE_FEATURE(kSkiaDawn);
+GPU_EXPORT BASE_DECLARE_FEATURE(kSkiaGraphite);
 
 GPU_EXPORT BASE_DECLARE_FEATURE(kEnableGrShaderCacheForVulkan);
 
diff --git a/gpu/config/gpu_info_collector.cc b/gpu/config/gpu_info_collector.cc
index 67c7eaa..16c0f810 100644
--- a/gpu/config/gpu_info_collector.cc
+++ b/gpu/config/gpu_info_collector.cc
@@ -269,8 +269,9 @@
 }
 #endif
 #if BUILDFLAG(SKIA_USE_DAWN)
-void ForceDawnTogglesForSkia(std::vector<const char*>* force_enabled_toggles,
-                             std::vector<const char*>* force_disabled_toggles) {
+void ForceDawnTogglesForSkiaGraphite(
+    std::vector<const char*>* force_enabled_toggles,
+    std::vector<const char*>* force_disabled_toggles) {
 #if !DCHECK_IS_ON()
   force_enabled_toggles->push_back("skip_validation");
 #endif
@@ -742,12 +743,15 @@
 #endif
 
 #if BUILDFLAG(SKIA_USE_DAWN)
-      if (gpu_preferences.gr_context_type == gpu::GrContextType::kDawn) {
+      if (gpu_preferences.gr_context_type == GrContextType::kGraphiteDawn) {
         // Get the list of forced toggles for Skia.
+        // TODO(sunnyps): Ideally these should come from a single source of
+        // truth e.g. from DawnContextProvider or a common helper, instead of
+        // just assuming some values here.
         std::vector<const char*> force_enabled_toggles_skia;
         std::vector<const char*> force_disabled_toggles_skia;
-        ForceDawnTogglesForSkia(&force_enabled_toggles_skia,
-                                &force_disabled_toggles_skia);
+        ForceDawnTogglesForSkiaGraphite(&force_enabled_toggles_skia,
+                                        &force_disabled_toggles_skia);
 
         if (!force_enabled_toggles_skia.empty()) {
           dawn_info_list->push_back("[Skia Forced Toggles - enabled]");
diff --git a/gpu/config/gpu_preferences.h b/gpu/config/gpu_preferences.h
index f6bec8a9..b404812 100644
--- a/gpu/config/gpu_preferences.h
+++ b/gpu/config/gpu_preferences.h
@@ -59,10 +59,10 @@
 };
 
 enum class GrContextType : uint32_t {
-  kGL,
-  kVulkan,
-  kDawn,
-  kLast = kDawn,
+  kGL,      // Ganesh
+  kVulkan,  // Ganesh
+  kGraphiteDawn,
+  kGraphiteMetal,
 };
 
 enum class DawnBackendValidationLevel : uint32_t {
@@ -218,7 +218,7 @@
 
   // ===================================
   // Settings from //gpu/command_buffer/service/gpu_switches.h
-  // The type of the GrContext.
+  // The type of the GrContext or Graphite Context.
   GrContextType gr_context_type = GrContextType::kGL;
 
   // Use Vulkan for rasterization and display compositing.
diff --git a/gpu/config/gpu_switches.cc b/gpu/config/gpu_switches.cc
index 939598df..04eb1f8 100644
--- a/gpu/config/gpu_switches.cc
+++ b/gpu/config/gpu_switches.cc
@@ -130,4 +130,10 @@
 const char kForceSeparateEGLDisplayForWebGLTesting[] =
     "force-separate-egl-display-for-webgl-testing";
 
+// Specify which backend to use for Skia Graphite - "dawn" (default) or "metal"
+// (only allowed on non-official developer builds).
+const char kSkiaGraphiteBackend[] = "skia-graphite-backend";
+const char kSkiaGraphiteBackendDawn[] = "dawn";
+const char kSkiaGraphiteBackendMetal[] = "metal";
+
 }  // namespace switches
diff --git a/gpu/config/gpu_switches.h b/gpu/config/gpu_switches.h
index 4b2237d..d96bc83 100644
--- a/gpu/config/gpu_switches.h
+++ b/gpu/config/gpu_switches.h
@@ -41,6 +41,9 @@
 GPU_EXPORT extern const char kForceBrowserCrashOnGpuCrash[];
 GPU_EXPORT extern const char kGpuWatchdogTimeoutSeconds[];
 GPU_EXPORT extern const char kForceSeparateEGLDisplayForWebGLTesting[];
+GPU_EXPORT extern const char kSkiaGraphiteBackend[];
+GPU_EXPORT extern const char kSkiaGraphiteBackendDawn[];
+GPU_EXPORT extern const char kSkiaGraphiteBackendMetal[];
 
 }  // namespace switches
 
diff --git a/gpu/config/gpu_util.cc b/gpu/config/gpu_util.cc
index 4218398..3eaebb7 100644
--- a/gpu/config/gpu_util.cc
+++ b/gpu/config/gpu_util.cc
@@ -43,6 +43,7 @@
 #include "gpu/config/gpu_preferences.h"
 #include "gpu/config/gpu_switches.h"
 #include "gpu/vulkan/buildflags.h"
+#include "skia/buildflags.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/extension_set.h"
 #include "ui/gl/buildflags.h"
@@ -293,6 +294,31 @@
   return kGpuFeatureStatusEnabled;
 }
 
+GpuFeatureStatus GetSkiaGraphiteFeatureStatus(
+    const std::set<int>& blocklisted_features,
+    const GpuPreferences& gpu_preferences,
+    bool use_swift_shader) {
+#if BUILDFLAG(ENABLE_SKIA_GRAPHITE)
+  if (use_swift_shader) {
+    return kGpuFeatureStatusDisabled;
+  }
+  if (blocklisted_features.count(GPU_FEATURE_TYPE_SKIA_GRAPHITE)) {
+    return kGpuFeatureStatusDisabled;
+  }
+#if BUILDFLAG(SKIA_USE_DAWN)
+  if (gpu_preferences.gr_context_type == GrContextType::kGraphiteDawn) {
+    return kGpuFeatureStatusEnabled;
+  }
+#endif  // BUILDFLAG(SKIA_USE_DAWN)
+#if BUILDFLAG(SKIA_USE_METAL)
+  if (gpu_preferences.gr_context_type == GrContextType::kGraphiteMetal) {
+    return kGpuFeatureStatusEnabled;
+  }
+#endif  // BUILDFLAG(SKIA_USE_METAL)
+#endif  // BUILDFLAG(ENABLE_SKIA_GRAPHITE)
+  return kGpuFeatureStatusDisabled;
+}
+
 void SetProcessGlWorkaroundsFromGpuFeatures(
     const GpuFeatureInfo& gpu_feature_info) {
   const auto is_enabled =
@@ -428,6 +454,8 @@
       kGpuFeatureStatusDisabled;
   gpu_feature_info.status_values[GPU_FEATURE_TYPE_ACCELERATED_WEBGPU] =
       kGpuFeatureStatusSoftware;
+  gpu_feature_info.status_values[GPU_FEATURE_TYPE_SKIA_GRAPHITE] =
+      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]);
@@ -460,6 +488,8 @@
       kGpuFeatureStatusDisabled;
   gpu_feature_info.status_values[GPU_FEATURE_TYPE_ACCELERATED_WEBGPU] =
       kGpuFeatureStatusSoftware;
+  gpu_feature_info.status_values[GPU_FEATURE_TYPE_SKIA_GRAPHITE] =
+      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]);
@@ -492,6 +522,8 @@
       kGpuFeatureStatusDisabled;
   gpu_feature_info.status_values[GPU_FEATURE_TYPE_ACCELERATED_WEBGPU] =
       kGpuFeatureStatusSoftware;
+  gpu_feature_info.status_values[GPU_FEATURE_TYPE_SKIA_GRAPHITE] =
+      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]);
@@ -598,6 +630,9 @@
       GetGLFeatureStatus(blocklisted_features, use_swift_shader);
   gpu_feature_info.status_values[GPU_FEATURE_TYPE_VULKAN] =
       GetVulkanFeatureStatus(blocklisted_features, gpu_preferences);
+  gpu_feature_info.status_values[GPU_FEATURE_TYPE_SKIA_GRAPHITE] =
+      GetSkiaGraphiteFeatureStatus(blocklisted_features, gpu_preferences,
+                                   use_swift_shader);
 #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/ipc/common/gpu_preferences.mojom b/gpu/ipc/common/gpu_preferences.mojom
index ffd0ab7..6d9487a0a 100644
--- a/gpu/ipc/common/gpu_preferences.mojom
+++ b/gpu/ipc/common/gpu_preferences.mojom
@@ -36,10 +36,10 @@
 
 // Corresponds to gpu::GrContextType.
 enum GrContextType {
-  kGL,
-  kVulkan,
-  kDawn,
-  kLast = kDawn,
+  kGL,  // Ganesh
+  kVulkan,  // Ganesh
+  kGraphiteDawn,
+  kGraphiteMetal,
 };
 
 // Corresponds to gpu::DawnBackendValidationLevel
diff --git a/gpu/ipc/common/gpu_preferences_mojom_traits.h b/gpu/ipc/common/gpu_preferences_mojom_traits.h
index 00bec4c..fecf7fd 100644
--- a/gpu/ipc/common/gpu_preferences_mojom_traits.h
+++ b/gpu/ipc/common/gpu_preferences_mojom_traits.h
@@ -30,8 +30,10 @@
         return gpu::mojom::GrContextType::kGL;
       case gpu::GrContextType::kVulkan:
         return gpu::mojom::GrContextType::kVulkan;
-      case gpu::GrContextType::kDawn:
-        return gpu::mojom::GrContextType::kDawn;
+      case gpu::GrContextType::kGraphiteDawn:
+        return gpu::mojom::GrContextType::kGraphiteDawn;
+      case gpu::GrContextType::kGraphiteMetal:
+        return gpu::mojom::GrContextType::kGraphiteMetal;
     }
     NOTREACHED();
     return gpu::mojom::GrContextType::kGL;
@@ -45,8 +47,11 @@
       case gpu::mojom::GrContextType::kVulkan:
         *out = gpu::GrContextType::kVulkan;
         return true;
-      case gpu::mojom::GrContextType::kDawn:
-        *out = gpu::GrContextType::kDawn;
+      case gpu::mojom::GrContextType::kGraphiteDawn:
+        *out = gpu::GrContextType::kGraphiteDawn;
+        return true;
+      case gpu::mojom::GrContextType::kGraphiteMetal:
+        *out = gpu::GrContextType::kGraphiteMetal;
         return true;
     }
     return false;
@@ -255,10 +260,12 @@
 
     out->ignore_gpu_blocklist = prefs.ignore_gpu_blocklist();
     out->watchdog_starts_backgrounded = prefs.watchdog_starts_backgrounded();
-    if (!prefs.ReadGrContextType(&out->gr_context_type))
+    if (!prefs.ReadGrContextType(&out->gr_context_type)) {
       return false;
-    if (!prefs.ReadUseVulkan(&out->use_vulkan))
+    }
+    if (!prefs.ReadUseVulkan(&out->use_vulkan)) {
       return false;
+    }
     out->enable_vulkan_protected_memory =
         prefs.enable_vulkan_protected_memory();
     out->disable_vulkan_surface = prefs.disable_vulkan_surface();
diff --git a/gpu/ipc/service/gpu_channel_manager.h b/gpu/ipc/service/gpu_channel_manager.h
index 10436af..2054fbd 100644
--- a/gpu/ipc/service/gpu_channel_manager.h
+++ b/gpu/ipc/service/gpu_channel_manager.h
@@ -391,12 +391,12 @@
   // features::Vulkan is used.
   raw_ptr<viz::VulkanContextProvider> vulkan_context_provider_ = nullptr;
 
-  // If features::Metal, |metal_context_provider_| will be set from
-  // viz::GpuServiceImpl. The raster decoders will use it for rasterization.
+  // If features::SkiaGraphite, |metal_context_provider_| will be set from
+  // viz::GpuServiceImpl. The raster decoders may use it for rasterization.
   raw_ptr<viz::MetalContextProvider> metal_context_provider_ = nullptr;
 
-  // With features::SkiaDawn, |dawn_context_provider_| will be set from
-  // viz::GpuServiceImpl. The raster decoders will use it for rasterization.
+  // With features::SkiaGraphite, |dawn_context_provider_| will be set from
+  // viz::GpuServiceImpl. The raster decoders may use it for rasterization.
   raw_ptr<viz::DawnContextProvider> dawn_context_provider_ = nullptr;
 
   GpuPeakMemoryMonitor peak_memory_monitor_;
diff --git a/gpu/skia_bindings/BUILD.gn b/gpu/skia_bindings/BUILD.gn
index 3958c16..ade50a6 100644
--- a/gpu/skia_bindings/BUILD.gn
+++ b/gpu/skia_bindings/BUILD.gn
@@ -20,16 +20,4 @@
     "//gpu/ipc/common:interfaces",
     "//skia",
   ]
-  if (skia_use_dawn) {
-    sources += [
-      "grcontext_for_webgpu_interface.cc",
-      "grcontext_for_webgpu_interface.h",
-    ]
-    deps += [
-      "//gpu/command_buffer/client:webgpu_interface",
-      "//third_party/dawn/src/dawn:cpp",
-      "//third_party/dawn/src/dawn:proc",
-      "//third_party/dawn/src/dawn/native",
-    ]
-  }
 }
diff --git a/gpu/skia_bindings/grcontext_for_webgpu_interface.cc b/gpu/skia_bindings/grcontext_for_webgpu_interface.cc
deleted file mode 100644
index 951e266..0000000
--- a/gpu/skia_bindings/grcontext_for_webgpu_interface.cc
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "gpu/skia_bindings/grcontext_for_webgpu_interface.h"
-
-#include "base/logging.h"
-#include "gpu/command_buffer/client/context_support.h"
-#include "gpu/command_buffer/client/webgpu_interface.h"
-#include "gpu/command_buffer/common/capabilities.h"
-#include "third_party/skia/include/gpu/GrDirectContext.h"
-
-namespace {
-
-void PrintDeviceError(WGPUErrorType, const char* message, void*) {
-  DLOG(ERROR) << "*** WebGPU client Device error: " << message;
-}
-
-}  // namespace
-
-namespace skia_bindings {
-
-GrContextForWebGPUInterface::GrContextForWebGPUInterface(
-    gpu::webgpu::WebGPUInterface* webgpu,
-    gpu::ContextSupport* context_support,
-    const gpu::Capabilities& capabilities,
-    size_t max_resource_cache_bytes,
-    size_t max_glyph_cache_texture_bytes)
-    : context_support_(context_support) {
-  GrContextOptions options;
-  options.fGlyphCacheTextureMaximumBytes = max_glyph_cache_texture_bytes;
-  options.fAvoidStencilBuffers = capabilities.avoid_stencil_buffers;
-  options.fAllowPathMaskCaching = false;
-  options.fShaderErrorHandler = this;
-  options.fInternalMultisampleCount = 0;
-  // TODO(senorblanco): create an actual passed-in Device, rather than this
-  // default hacky one.  http://crbug.com/1078775
-  WGPUDevice device = webgpu->DeprecatedEnsureDefaultDeviceSync();
-  wgpuDeviceSetUncapturedErrorCallback(device, PrintDeviceError, 0);
-  gr_context_ = GrDirectContext::MakeDawn(device, options);
-  if (gr_context_) {
-    gr_context_->setResourceCacheLimit(max_resource_cache_bytes);
-    context_support_->SetGrContext(gr_context_.get());
-  }
-}
-
-GrContextForWebGPUInterface::~GrContextForWebGPUInterface() {
-  // At this point the WebGPUInterface is going to be destroyed, so have
-  // the GrContext clean up and not try to use it anymore.
-  if (gr_context_) {
-    gr_context_->releaseResourcesAndAbandonContext();
-    context_support_->SetGrContext(nullptr);
-  }
-}
-
-void GrContextForWebGPUInterface::compileError(const char* shader,
-                                               const char* errors) {
-  DLOG(ERROR) << "Skia shader compilation error\n"
-              << "------------------------\n"
-              << shader << "\nErrors:\n"
-              << errors;
-}
-
-GrDirectContext* GrContextForWebGPUInterface::get() {
-  return gr_context_.get();
-}
-
-}  // namespace skia_bindings
diff --git a/gpu/skia_bindings/grcontext_for_webgpu_interface.h b/gpu/skia_bindings/grcontext_for_webgpu_interface.h
deleted file mode 100644
index 6a86f7d7..0000000
--- a/gpu/skia_bindings/grcontext_for_webgpu_interface.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef GPU_SKIA_BINDINGS_GRCONTEXT_FOR_WEBGPU_INTERFACE_H_
-#define GPU_SKIA_BINDINGS_GRCONTEXT_FOR_WEBGPU_INTERFACE_H_
-
-#include "base/memory/raw_ptr.h"
-#include "third_party/skia/include/core/SkRefCnt.h"
-#include "third_party/skia/include/gpu/GrContextOptions.h"
-
-class GrDirectContext;
-
-namespace gpu {
-struct Capabilities;
-class ContextSupport;
-namespace webgpu {
-class WebGPUInterface;
-}
-}  // namespace gpu
-
-namespace skia_bindings {
-
-// This class binds an offscreen GrContext to a WebGPU Device. The Device is
-// used by the GrContext so must be valid as long as this class is alive.
-class GrContextForWebGPUInterface
-    : public GrContextOptions::ShaderErrorHandler {
- public:
-  GrContextForWebGPUInterface(gpu::webgpu::WebGPUInterface* webgpu,
-                              gpu::ContextSupport* context_support,
-                              const gpu::Capabilities& capabilities,
-                              size_t max_resource_cache_bytes,
-                              size_t max_glyph_cache_texture_bytes);
-
-  GrContextForWebGPUInterface(const GrContextForWebGPUInterface&) = delete;
-  GrContextForWebGPUInterface& operator=(const GrContextForWebGPUInterface&) =
-      delete;
-
-  ~GrContextForWebGPUInterface() override;
-
-  // GrContextOptions::ShaderErrorHandler implementation
-  // Handles Skia-reported shader compilation errors.
-  void compileError(const char* shader, const char* errors) override;
-
-  GrDirectContext* get();
-
- private:
-  sk_sp<class GrDirectContext> gr_context_;
-  raw_ptr<gpu::ContextSupport> context_support_;
-};
-
-}  // namespace skia_bindings
-
-#endif  // GPU_SKIA_BINDINGS_GRCONTEXT_FOR_WEBGPU_INTERFACE_H_
diff --git a/services/viz/public/cpp/gpu/context_provider_command_buffer.cc b/services/viz/public/cpp/gpu/context_provider_command_buffer.cc
index 6637a9f..24e2b04 100644
--- a/services/viz/public/cpp/gpu/context_provider_command_buffer.cc
+++ b/services/viz/public/cpp/gpu/context_provider_command_buffer.cc
@@ -44,7 +44,6 @@
 #include "gpu/ipc/client/gpu_channel_host.h"
 #include "gpu/skia_bindings/gles2_implementation_with_grcontext_support.h"
 #include "gpu/skia_bindings/grcontext_for_gles2_interface.h"
-#include "gpu/skia_bindings/grcontext_for_webgpu_interface.h"
 #include "services/viz/public/cpp/gpu/command_buffer_metrics.h"
 #include "skia/buildflags.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -384,19 +383,22 @@
 class GrDirectContext* ContextProviderCommandBuffer::GrContext() {
   DCHECK(bind_tried_);
   DCHECK_EQ(bind_result_, gpu::ContextResult::kSuccess);
-  if (!support_grcontext_ || !ContextSupport()->HasGrContextSupport())
+  if (!support_grcontext_ || !ContextSupport()->HasGrContextSupport()) {
     return nullptr;
+  }
   CheckValidSequenceOrLockAcquired();
 
-  if (gr_context_)
+  if (gr_context_) {
     return gr_context_->get();
-#if BUILDFLAG(SKIA_USE_DAWN)
-  else if (webgpu_gr_context_)
-    return webgpu_gr_context_->get();
-#endif
+  }
 
-  if (attributes_.enable_oop_rasterization)
+  if (attributes_.enable_oop_rasterization) {
     return nullptr;
+  }
+
+  if (attributes_.context_type == gpu::CONTEXT_TYPE_WEBGPU) {
+    return nullptr;
+  }
 
   // TODO(vmiura): crbug.com/793508 Disable access to GrContext if
   // enable_gles2_interface is disabled, after removing any dependencies on
@@ -407,23 +409,12 @@
   gpu::DetermineGrCacheLimitsFromAvailableMemory(
       &max_resource_cache_bytes, &max_glyph_cache_texture_bytes);
 
-  if (attributes_.context_type == gpu::CONTEXT_TYPE_WEBGPU) {
-#if BUILDFLAG(SKIA_USE_DAWN)
-    webgpu_gr_context_ =
-        std::make_unique<skia_bindings::GrContextForWebGPUInterface>(
-            webgpu_interface_.get(), ContextSupport(), ContextCapabilities(),
-            max_resource_cache_bytes, max_glyph_cache_texture_bytes);
-    cache_controller_->SetGrContext(webgpu_gr_context_->get());
-    return webgpu_gr_context_->get();
-#else
-    return nullptr;
-#endif
-  }
   gpu::gles2::GLES2Interface* gl_interface;
-  if (trace_impl_)
+  if (trace_impl_) {
     gl_interface = trace_impl_.get();
-  else
+  } else {
     gl_interface = gles2_impl_.get();
+  }
 
   gr_context_ = std::make_unique<skia_bindings::GrContextForGLES2Interface>(
       gl_interface, ContextSupport(), ContextCapabilities(),
@@ -432,8 +423,9 @@
 
   // If GlContext is already lost, also abandon the new GrContext.
   if (gr_context_->get() &&
-      gles2_impl_->GetGraphicsResetStatusKHR() != GL_NO_ERROR)
+      gles2_impl_->GetGraphicsResetStatusKHR() != GL_NO_ERROR) {
     gr_context_->get()->abandonContext();
+  }
 
   return gr_context_->get();
 }
diff --git a/services/viz/public/cpp/gpu/context_provider_command_buffer.h b/services/viz/public/cpp/gpu/context_provider_command_buffer.h
index e434c1b..1ad11ba 100644
--- a/services/viz/public/cpp/gpu/context_provider_command_buffer.h
+++ b/services/viz/public/cpp/gpu/context_provider_command_buffer.h
@@ -56,7 +56,6 @@
 
 namespace skia_bindings {
 class GrContextForGLES2Interface;
-class GrContextForWebGPUInterface;
 }
 
 namespace viz {
@@ -177,10 +176,7 @@
   raw_ptr<gpu::ImplementationBase> impl_;
 
   std::unique_ptr<skia_bindings::GrContextForGLES2Interface> gr_context_;
-#if BUILDFLAG(SKIA_USE_DAWN)
-  std::unique_ptr<skia_bindings::GrContextForWebGPUInterface>
-      webgpu_gr_context_;
-#endif
+
   std::unique_ptr<ContextCacheController> cache_controller_;
 
   base::ObserverList<ContextLostObserver>::Unchecked observers_;
diff --git a/skia/BUILD.gn b/skia/BUILD.gn
index 8d4d027..99e75953 100644
--- a/skia/BUILD.gn
+++ b/skia/BUILD.gn
@@ -8,7 +8,6 @@
 import("//build/config/freetype/freetype.gni")
 import("//build/config/sanitizers/sanitizers.gni")
 import("//gpu/vulkan/features.gni")
-import("//printing/buildflags/buildflags.gni")
 import("//testing/test.gni")
 import("//third_party/skia/gn/shared_sources.gni")
 import("//third_party/skia/modules/skcms/skcms.gni")
@@ -22,14 +21,13 @@
   import("//build/config/mips.gni")
 }
 
-skia_support_gpu = use_blink
-skia_support_pdf = !is_ios && enable_printing
-
 buildflag_header("buildflags") {
   header = "buildflags.h"
   flags = [
     "SKIA_SUPPORT_SKOTTIE=$skia_support_skottie",
+    "ENABLE_SKIA_GRAPHITE=$enable_skia_graphite",
     "SKIA_USE_DAWN=$skia_use_dawn",
+    "SKIA_USE_METAL=$skia_use_metal",
   ]
 }
 
@@ -53,30 +51,12 @@
   include_dirs = [ "//third_party/skia" ]
 
   if (use_blink) {
-    include_dirs += [ "//third_party/wuffs/src/release/c" ]
-  }
-  if (enable_vulkan) {
-    include_dirs += [ "//third_party/vulkan/include" ]
-    configs =
-        [ "//third_party/vulkan-deps/vulkan-headers/src:vulkan_headers_config" ]
-  }
-
-  if (skia_use_gl) {
-    defines += [ "SK_GL" ]
-  }
-
-  if (use_blink) {
     defines += [
       "SK_CODEC_DECODES_JPEG",
       "SK_ENCODE_JPEG",
       "SK_HAS_WUFFS_LIBRARY",
     ]
-  }
-  if (enable_vulkan) {
-    defines += [ "SK_VULKAN=1" ]
-  }
-  if (skia_use_dawn) {
-    defines += [ "SK_DAWN" ]
+    include_dirs += [ "//third_party/wuffs/src/release/c" ]
   }
 
   if (is_component_build) {
@@ -88,14 +68,6 @@
     }
   }
 
-  if (skia_support_gpu) {
-    workaround_header = "gpu/config/gpu_driver_bug_workaround_autogen.h"
-    defines += [
-      "SK_GANESH",
-      "SK_GPU_WORKAROUNDS_HEADER=\"$workaround_header\"",
-    ]
-  }
-
   if (is_android) {
     defines += [
       "SK_BUILD_FOR_ANDROID",
@@ -104,21 +76,44 @@
   }
 
   if (is_mac) {
-    defines += [
-      "SK_BUILD_FOR_MAC",
-      "SK_METAL",
-    ]
+    defines += [ "SK_BUILD_FOR_MAC" ]
   }
   if (is_ios) {
-    defines += [
-      "SK_BUILD_FOR_IOS",
-      "SK_METAL",
-    ]
+    defines += [ "SK_BUILD_FOR_IOS" ]
   }
 
   if (is_win) {
     defines += [ "GR_GL_FUNCTION_TYPE=__stdcall" ]
   }
+
+  if (skia_support_gpu) {
+    workaround_header = "gpu/config/gpu_driver_bug_workaround_autogen.h"
+    configs = []
+    defines += [
+      "SK_GANESH",
+      "SK_GPU_WORKAROUNDS_HEADER=\"$workaround_header\"",
+    ]
+    if (skia_use_gl) {
+      defines += [ "SK_GL" ]
+    }
+    if (enable_vulkan) {
+      defines += [ "SK_VULKAN=1" ]
+      include_dirs += [ "//third_party/vulkan/include" ]
+      configs += [
+        "//third_party/vulkan-deps/vulkan-headers/src:vulkan_headers_config",
+      ]
+    }
+    if (enable_skia_graphite) {
+      defines += [ "SK_GRAPHITE" ]
+      if (skia_use_dawn) {
+        defines += [ "SK_DAWN" ]
+        configs += [ "//third_party/dawn/include/dawn:public" ]
+      }
+      if (skia_use_metal) {
+        defines += [ "SK_METAL" ]
+      }
+    }
+  }
 }
 
 # Internal-facing config for Skia library code.
@@ -488,14 +483,6 @@
     ":buildflags",
     ":skia_core_and_effects",
   ]
-  if (skia_use_dawn) {
-    public_deps += [ "//third_party/dawn/include/dawn:cpp_headers" ]
-    deps += [
-      "//third_party/dawn/src/dawn:cpp",
-      "//third_party/dawn/src/dawn:proc",
-      "//third_party/dawn/src/dawn/native",
-    ]
-  }
 
   if (use_blink) {
     deps += [
@@ -524,34 +511,23 @@
     configs += [ "//build/config/compiler:optimize_max" ]
   }
 
-  if (use_blink && is_apple) {
-    deps += [ ":skia_metal" ]
-    defines += [ "SK_METAL" ]
-    sources += skia_gpu_metal_cpp
-    frameworks = [
+  frameworks = []
+  if (is_ios) {
+    frameworks += [ "ImageIO.framework" ]
+  }
+  if (is_apple && skia_support_gpu) {
+    frameworks += [
       "CoreFoundation.framework",
       "CoreGraphics.framework",
       "CoreText.framework",
-      "Metal.framework",
       "Foundation.framework",
     ]
     if (is_mac) {
       frameworks += [ "AppKit.framework" ]
     }
     if (is_ios) {
-      frameworks += [
-        "ImageIO.framework",
-        "IOSurface.framework",
-      ]
+      frameworks += [ "IOSurface.framework" ]
     }
-  } else if (is_ios) {
-    frameworks = [ "ImageIO.framework" ]
-  }
-
-  if (skia_use_dawn) {
-    public += skia_gpu_dawn_public
-    sources += skia_gpu_dawn_private
-    sources += skia_shared_dawn_sources
   }
 
   if (is_fuchsia) {
@@ -576,6 +552,9 @@
       sources += skia_shared_vk_sources
       sources += skia_gpu_vk_chromium_private
     }
+    if (enable_skia_graphite) {
+      deps += [ ":skia_graphite" ]
+    }
     deps += [ "//gpu/config:workaround_list" ]
   }
 
@@ -652,10 +631,6 @@
   if (skia_support_gpu) {
     deps = [ "//gpu/config:workaround_list" ]
   }
-  if (skia_use_dawn) {
-    deps += [ "//third_party/dawn/include/dawn:cpp_headers" ]
-  }
-
   visibility = [ ":skia" ]
 }
 
@@ -776,20 +751,51 @@
   visibility = [ ":skia" ]
 }
 
-# Split out metal sources, because they require ARC.
-if (use_blink && is_apple) {
-  skia_source_set("skia_metal") {
-    defines = [ "SK_METAL" ]
-    public = skia_gpu_metal_public
-    sources = skia_gpu_metal_private
-    sources += skia_shared_mtl_sources
-    cflags_objcc = [
-      "-Wno-unguarded-availability",
-      "-fobjc-arc",
-    ]
-    deps = [ "//gpu/config:workaround_list" ]
+# Split out Graphite sources because of conflicting file names with Ganesh.
+if (enable_skia_graphite) {
+  skia_source_set("skia_graphite") {
+    public = skia_graphite_public
+    sources = skia_graphite_sources
+    deps = []
     if (skia_use_dawn) {
-      deps += [ "//third_party/dawn/include/dawn:cpp_headers" ]
+      sources += skia_shared_dawn_sources
+      sources += skia_graphite_dawn_sources
+      deps += [
+        ":skia_ganesh_dawn",
+        "//third_party/dawn/src/dawn:cpp",
+        "//third_party/dawn/src/dawn:proc",
+      ]
+    }
+    if (skia_use_metal) {
+      sources += skia_shared_mtl_sources
+      sources += skia_graphite_mtl_sources
+      deps += [ ":skia_ganesh_metal" ]
+      frameworks = [ "Metal.framework" ]
+    }
+  }
+
+  # Even though we only use Dawn and Metal with Graphite, we need to build the
+  # Ganesh sources, since both Ganesh and Graphite use the same defines for
+  # enabling backends, or else we'll get undefined symbol errors in some cases.
+  if (skia_use_dawn) {
+    skia_source_set("skia_ganesh_dawn") {
+      public = skia_gpu_dawn_public
+      sources = skia_gpu_dawn_private
+
+      # Ganesh Dawn backend has SkASSERT(!"umimplemented") calls which cause
+      # -Wstring-conversion to fail - exempt this code since it's unused anyway.
+      cflags_cc = [ "-Wno-string-conversion" ]
+    }
+  }
+  if (skia_use_metal) {
+    # Split out Ganesh Metal sources, because they require ARC.
+    skia_source_set("skia_ganesh_metal") {
+      public = skia_gpu_metal_public
+      sources = skia_gpu_metal_private
+      cflags_objcc = [
+        "-Wno-unguarded-availability",
+        "-fobjc-arc",
+      ]
     }
   }
 }
diff --git a/skia/features.gni b/skia/features.gni
index af28159..e902a88 100644
--- a/skia/features.gni
+++ b/skia/features.gni
@@ -2,17 +2,37 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-declare_args() {
-  # Enable experimental SkiaRenderer Dawn backend.
-  skia_use_dawn = is_win && !is_official_build
-  skia_use_gl = true
+import("//build/config/features.gni")
+import("//printing/buildflags/buildflags.gni")
 
-  # Enable gtests using SkiaRenderer Dawn.
+declare_args() {
+  # Enable experimental Skia Graphite backend.
+  enable_skia_graphite = false
+
+  # Enable gtests using SkiaRenderer on Skia Graphite.
   # TODO(rivr): Remove this and enable the tests by default once a software
   # path for D3D12 is available.
-  enable_skia_dawn_gtests = false
+  enable_skia_graphite_gtests = false
 }
 
+# Skia only needs to support GPU rasterization if we use the full Chromium
+# rendering stack i.e. |use_blink| is true.
+# TODO(crbug.com/1431198): Split out into separate enable_skia_ganesh flag.
+skia_support_gpu = use_blink
+
+# Skia Ganesh GL backend is always enabled on all platforms - applies only when
+# GPU rasterization is enabled.
+skia_use_gl = true
+
+# Dawn is used with Skia Graphite by default.
+skia_use_dawn = enable_skia_graphite
+
+# Metal is only used with Skia Graphite on Mac and iOS blink developer builds.
+skia_use_metal =
+    enable_skia_graphite && is_apple && use_blink && !is_official_build
+
+skia_support_pdf = !is_ios && enable_printing
+
 # Skottie is not used on Android. To keep apk size small the skottie library is
 # excluded from the binary. At the time this comment was written, it adds ~200KB
 # to the APK.
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn
index b5916f1..508bbc7 100644
--- a/third_party/blink/renderer/platform/BUILD.gn
+++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -1840,10 +1840,6 @@
     deps += [ "//third_party/pffft" ]
   }
 
-  if (skia_use_dawn) {
-    deps += [ "//third_party/dawn/src/dawn:cpp" ]
-  }
-
   if (!is_debug && !optimize_for_size) {
     configs -= [ "//build/config/compiler:default_optimization" ]
     configs += [ "//build/config/compiler:optimize_max" ]