Sharing one SharedImageManager for WebView


WebView has GPU thread and render thread. So they need use one
SharedImageManager to share resources. This CL creates the SIM on
DeferredGpuCommandService on render thread, and plumbs it to the
GpuChannelManager which will be used on GPU threads. This CL also
enables using SharedImageManager for WebView GLRenderer

Bug: 937060
Change-Id: I650c631cb4d717d4420b54b9d1bb310062c5da8e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1497123
Reviewed-by: danakj <danakj@chromium.org>
Reviewed-by: Fernando Serboncini <fserb@chromium.org>
Reviewed-by: Eric Karl <ericrk@chromium.org>
Reviewed-by: Bo <boliu@chromium.org>
Reviewed-by: Antoine Labour <piman@chromium.org>
Commit-Queue: Peng Huang <penghuang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#637723}
diff --git a/android_webview/browser/gfx/DEPS b/android_webview/browser/gfx/DEPS
index e7494c97..ef91ac3 100644
--- a/android_webview/browser/gfx/DEPS
+++ b/android_webview/browser/gfx/DEPS
@@ -2,6 +2,7 @@
   "-android_webview",
   "-android_webview/browser",
   "+android_webview/browser/gfx",
+  "+android_webview/common/aw_switches.h",
   "+android_webview/public/browser",
 ]
 
diff --git a/android_webview/browser/gfx/deferred_gpu_command_service.cc b/android_webview/browser/gfx/deferred_gpu_command_service.cc
index 8ecf1c3d..9733b7a 100644
--- a/android_webview/browser/gfx/deferred_gpu_command_service.cc
+++ b/android_webview/browser/gfx/deferred_gpu_command_service.cc
@@ -128,16 +128,21 @@
   DCHECK(base::CommandLine::InitializedForCurrentProcess());
   gpu::GpuPreferences gpu_preferences =
       content::GetGpuPreferencesFromCommandLine();
-  bool success = gpu::InitializeGLThreadSafe(
-      base::CommandLine::ForCurrentProcess(), gpu_preferences, &gpu_info,
-      &gpu_feature_info);
+  auto* command_line = base::CommandLine::ForCurrentProcess();
+  bool success = gpu::InitializeGLThreadSafe(command_line, gpu_preferences,
+                                             &gpu_info, &gpu_feature_info);
   if (!success) {
     LOG(FATAL) << "gpu::InitializeGLThreadSafe() failed.";
   }
+  auto sync_point_manager = std::make_unique<gpu::SyncPointManager>();
+  auto mailbox_manager = gpu::gles2::CreateMailboxManager(gpu_preferences);
+  // The shared_image_manager will be shared between renderer thread and GPU
+  // main thread, so it should be thread safe.
+  auto shared_image_manager =
+      std::make_unique<gpu::SharedImageManager>(true /* thread_safe */);
   return new DeferredGpuCommandService(
-      std::make_unique<gpu::SyncPointManager>(),
-      gpu::gles2::CreateMailboxManager(gpu_preferences),
-      std::make_unique<gpu::SharedImageManager>(), gpu_preferences, gpu_info,
+      std::move(sync_point_manager), std::move(mailbox_manager),
+      std::move(shared_image_manager), gpu_preferences, gpu_info,
       gpu_feature_info);
 }
 
diff --git a/android_webview/browser/gfx/surfaces_instance.cc b/android_webview/browser/gfx/surfaces_instance.cc
index dd46a4c7..1169ae6e 100644
--- a/android_webview/browser/gfx/surfaces_instance.cc
+++ b/android_webview/browser/gfx/surfaces_instance.cc
@@ -12,6 +12,8 @@
 #include "android_webview/browser/gfx/aw_render_thread_context_provider.h"
 #include "android_webview/browser/gfx/deferred_gpu_command_service.h"
 #include "android_webview/browser/gfx/parent_output_surface.h"
+#include "android_webview/common/aw_switches.h"
+#include "base/command_line.h"
 #include "base/stl_util.h"
 #include "components/viz/common/display/renderer_settings.h"
 #include "components/viz/common/features.h"
@@ -131,8 +133,11 @@
       nullptr /* shared_bitmap_manager */, settings, frame_sink_id_,
       std::move(output_surface), std::move(scheduler),
       nullptr /* current_task_runner */, skia_output_surface);
+  const bool enable_shared_image =
+      base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kWebViewEnableSharedImage);
   display_->Initialize(this, frame_sink_manager_->surface_manager(),
-                       false /* enable_shared_images */);
+                       enable_shared_image);
   frame_sink_manager_->RegisterBeginFrameSource(begin_frame_source_.get(),
                                                 frame_sink_id_);
 
diff --git a/android_webview/common/aw_switches.cc b/android_webview/common/aw_switches.cc
index 2286d02..c909a27 100644
--- a/android_webview/common/aw_switches.cc
+++ b/android_webview/common/aw_switches.cc
@@ -16,4 +16,7 @@
 const char kWebViewDisableSafeBrowsingSupport[] =
     "webview-disable-safebrowsing-support";
 
+// Used to enable shared image API for webview.
+const char kWebViewEnableSharedImage[] = "webview-enable-shared-image";
+
 }  // namespace switches
diff --git a/android_webview/common/aw_switches.h b/android_webview/common/aw_switches.h
index cb2fc2c..410c1c8 100644
--- a/android_webview/common/aw_switches.h
+++ b/android_webview/common/aw_switches.h
@@ -10,6 +10,7 @@
 extern const char kWebViewSandboxedRenderer[];
 extern const char kWebViewEnableSafeBrowsingSupport[];
 extern const char kWebViewDisableSafeBrowsingSupport[];
+extern const char kWebViewEnableSharedImage[];
 
 // Please note that if you are adding a flag that is intended for a renderer,
 // you also need to add it into
diff --git a/android_webview/gpu/aw_content_gpu_client.cc b/android_webview/gpu/aw_content_gpu_client.cc
index c650652..922f62f 100644
--- a/android_webview/gpu/aw_content_gpu_client.cc
+++ b/android_webview/gpu/aw_content_gpu_client.cc
@@ -7,8 +7,10 @@
 namespace android_webview {
 
 AwContentGpuClient::AwContentGpuClient(
-    const GetSyncPointManagerCallback& sync_point_manager_callback)
-    : sync_point_manager_callback_(sync_point_manager_callback) {}
+    const GetSyncPointManagerCallback& sync_point_manager_callback,
+    const GetSharedImageManagerCallback& shared_image_manager_callback)
+    : sync_point_manager_callback_(sync_point_manager_callback),
+      shared_image_manager_callback_(shared_image_manager_callback) {}
 
 AwContentGpuClient::~AwContentGpuClient() {}
 
@@ -16,4 +18,8 @@
   return sync_point_manager_callback_.Run();
 }
 
+gpu::SharedImageManager* AwContentGpuClient::GetSharedImageManager() {
+  return shared_image_manager_callback_.Run();
+}
+
 }  // namespace android_webview
diff --git a/android_webview/gpu/aw_content_gpu_client.h b/android_webview/gpu/aw_content_gpu_client.h
index b623305d..4819c60 100644
--- a/android_webview/gpu/aw_content_gpu_client.h
+++ b/android_webview/gpu/aw_content_gpu_client.h
@@ -13,17 +13,23 @@
 
 class AwContentGpuClient : public content::ContentGpuClient {
  public:
-  using GetSyncPointManagerCallback = base::Callback<gpu::SyncPointManager*()>;
+  using GetSyncPointManagerCallback =
+      base::RepeatingCallback<gpu::SyncPointManager*()>;
+  using GetSharedImageManagerCallback =
+      base::RepeatingCallback<gpu::SharedImageManager*()>;
 
-  explicit AwContentGpuClient(
-      const GetSyncPointManagerCallback& sync_point_manager_callback);
+  AwContentGpuClient(
+      const GetSyncPointManagerCallback& sync_point_manager_callback,
+      const GetSharedImageManagerCallback& shared_image_manager_callback);
   ~AwContentGpuClient() override;
 
   // content::ContentGpuClient implementation.
   gpu::SyncPointManager* GetSyncPointManager() override;
+  gpu::SharedImageManager* GetSharedImageManager() override;
 
  private:
   GetSyncPointManagerCallback sync_point_manager_callback_;
+  GetSharedImageManagerCallback shared_image_manager_callback_;
   DISALLOW_COPY_AND_ASSIGN(AwContentGpuClient);
 };
 
diff --git a/android_webview/lib/aw_main_delegate.cc b/android_webview/lib/aw_main_delegate.cc
index d90ea5d..b49c21d 100644
--- a/android_webview/lib/aw_main_delegate.cc
+++ b/android_webview/lib/aw_main_delegate.cc
@@ -347,11 +347,21 @@
   DCHECK(DeferredGpuCommandService::GetInstance());
   return DeferredGpuCommandService::GetInstance()->sync_point_manager();
 }
+gpu::SharedImageManager* GetSharedImageManager() {
+  DCHECK(DeferredGpuCommandService::GetInstance());
+  const bool enable_shared_image =
+      base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kWebViewEnableSharedImage);
+  return enable_shared_image
+             ? DeferredGpuCommandService::GetInstance()->shared_image_manager()
+             : nullptr;
+}
 }  // namespace
 
 content::ContentGpuClient* AwMainDelegate::CreateContentGpuClient() {
-  content_gpu_client_.reset(
-      new AwContentGpuClient(base::BindRepeating(&GetSyncPointManager)));
+  content_gpu_client_ = std::make_unique<AwContentGpuClient>(
+      base::BindRepeating(&GetSyncPointManager),
+      base::BindRepeating(&GetSharedImageManager));
   return content_gpu_client_.get();
 }
 
diff --git a/cc/layers/heads_up_display_layer_impl.cc b/cc/layers/heads_up_display_layer_impl.cc
index c9c587d..6ede1c05 100644
--- a/cc/layers/heads_up_display_layer_impl.cc
+++ b/cc/layers/heads_up_display_layer_impl.cc
@@ -279,13 +279,13 @@
               ->settings()
               .resource_settings.use_gpu_memory_buffer_resources);
 
-      uint32_t flags = 0;
+      uint32_t flags = gpu::SHARED_IMAGE_USAGE_DISPLAY;
       if (use_oopr) {
-        flags = gpu::SHARED_IMAGE_USAGE_RASTER |
-                gpu::SHARED_IMAGE_USAGE_OOP_RASTERIZATION;
+        flags |= gpu::SHARED_IMAGE_USAGE_RASTER |
+                 gpu::SHARED_IMAGE_USAGE_OOP_RASTERIZATION;
       } else if (gpu_raster) {
-        flags = gpu::SHARED_IMAGE_USAGE_GLES2 |
-                gpu::SHARED_IMAGE_USAGE_GLES2_FRAMEBUFFER_HINT;
+        flags |= gpu::SHARED_IMAGE_USAGE_GLES2 |
+                 gpu::SHARED_IMAGE_USAGE_GLES2_FRAMEBUFFER_HINT;
       }
       if (backing->overlay_candidate)
         flags |= gpu::SHARED_IMAGE_USAGE_SCANOUT;
diff --git a/cc/raster/gpu_raster_buffer_provider.cc b/cc/raster/gpu_raster_buffer_provider.cc
index 2053c56d..23159f6 100644
--- a/cc/raster/gpu_raster_buffer_provider.cc
+++ b/cc/raster/gpu_raster_buffer_provider.cc
@@ -132,7 +132,8 @@
   if (mailbox->IsZero()) {
     DCHECK(!sync_token.HasData());
     auto* sii = context_provider->SharedImageInterface();
-    uint32_t flags = gpu::SHARED_IMAGE_USAGE_RASTER |
+    uint32_t flags = gpu::SHARED_IMAGE_USAGE_DISPLAY |
+                     gpu::SHARED_IMAGE_USAGE_RASTER |
                      gpu::SHARED_IMAGE_USAGE_OOP_RASTERIZATION;
     if (texture_is_overlay_candidate)
       flags |= gpu::SHARED_IMAGE_USAGE_SCANOUT;
@@ -187,7 +188,8 @@
   gpu::raster::RasterInterface* ri = context_provider->RasterInterface();
   if (mailbox->IsZero()) {
     auto* sii = context_provider->SharedImageInterface();
-    uint32_t flags = gpu::SHARED_IMAGE_USAGE_GLES2 |
+    uint32_t flags = gpu::SHARED_IMAGE_USAGE_DISPLAY |
+                     gpu::SHARED_IMAGE_USAGE_GLES2 |
                      gpu::SHARED_IMAGE_USAGE_GLES2_FRAMEBUFFER_HINT;
     if (texture_is_overlay_candidate)
       flags |= gpu::SHARED_IMAGE_USAGE_SCANOUT;
diff --git a/cc/raster/one_copy_raster_buffer_provider.cc b/cc/raster/one_copy_raster_buffer_provider.cc
index f134a48b..f16e9083 100644
--- a/cc/raster/one_copy_raster_buffer_provider.cc
+++ b/cc/raster/one_copy_raster_buffer_provider.cc
@@ -382,7 +382,8 @@
   }
 
   if (mailbox->IsZero()) {
-    uint32_t flags = gpu::SHARED_IMAGE_USAGE_RASTER;
+    uint32_t flags =
+        gpu::SHARED_IMAGE_USAGE_DISPLAY | gpu::SHARED_IMAGE_USAGE_RASTER;
     if (mailbox_texture_is_overlay_candidate)
       flags |= gpu::SHARED_IMAGE_USAGE_SCANOUT;
     *mailbox = sii->CreateSharedImage(resource_format, resource_size,
@@ -391,9 +392,11 @@
 
   // Create staging shared image.
   if (staging_buffer->mailbox.IsZero()) {
-    staging_buffer->mailbox = sii->CreateSharedImage(
-        staging_buffer->gpu_memory_buffer.get(), gpu_memory_buffer_manager_,
-        color_space, gpu::SHARED_IMAGE_USAGE_RASTER);
+    uint32_t flags =
+        gpu::SHARED_IMAGE_USAGE_DISPLAY | gpu::SHARED_IMAGE_USAGE_RASTER;
+    staging_buffer->mailbox =
+        sii->CreateSharedImage(staging_buffer->gpu_memory_buffer.get(),
+                               gpu_memory_buffer_manager_, color_space, flags);
   } else {
     sii->UpdateSharedImage(staging_buffer->sync_token, staging_buffer->mailbox);
   }
diff --git a/cc/test/pixel_test.cc b/cc/test/pixel_test.cc
index 9916553..9a51bec 100644
--- a/cc/test/pixel_test.cc
+++ b/cc/test/pixel_test.cc
@@ -286,7 +286,8 @@
   gpu_service_->InitializeWithHost(
       std::move(gpu_host_proxy), gpu::GpuProcessActivityFlags(),
       gl::init::CreateOffscreenGLSurface(gfx::Size()),
-      nullptr /* sync_point_manager */, nullptr /* shutdown_event */);
+      nullptr /* sync_point_manager */, nullptr /* shared_image_manager */,
+      nullptr /* shutdown_event */);
   task_executor_ = base::MakeRefCounted<gpu::GpuInProcessThreadService>(
       gpu_thread_->task_runner(), gpu_service_->scheduler(),
       gpu_service_->sync_point_manager(), gpu_service_->mailbox_manager(),
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 cfd219e1..5e1af789 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
@@ -18,6 +18,7 @@
 #include "components/viz/service/display/texture_deleter.h"
 #include "components/viz/service/display_embedder/direct_context_provider.h"
 #include "components/viz/service/gl/gpu_service_impl.h"
+#include "gpu/command_buffer/common/shared_image_usage.h"
 #include "gpu/command_buffer/common/swap_buffers_complete_params.h"
 #include "gpu/command_buffer/service/context_state.h"
 #include "gpu/command_buffer/service/gr_shader_cache.h"
@@ -183,7 +184,9 @@
 std::unique_ptr<gpu::SharedImageRepresentationFactory>
 CreateSharedImageRepresentationFactory(
     gpu::CommandBufferTaskExecutor* task_executor) {
-  return nullptr;
+  // TODO(https://crbug.com/899905): Use a real MemoryTracker, not nullptr.
+  return std::make_unique<gpu::SharedImageRepresentationFactory>(
+      task_executor->shared_image_manager(), nullptr);
 }
 
 class ScopedSurfaceToTexture {
@@ -931,10 +934,7 @@
     std::unique_ptr<gpu::SharedImageRepresentationSkia>* shared_image_out) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 
-  if (!shared_image_representation_factory_) {
-    // TODO(https://crbug.com/900973): support shared image for Android
-    // WebView.
-  } else if (!*shared_image_out && mailbox_holder.mailbox.IsSharedImage()) {
+  if (!*shared_image_out && mailbox_holder.mailbox.IsSharedImage()) {
     std::unique_ptr<gpu::SharedImageRepresentationSkia> shared_image =
         shared_image_representation_factory_->ProduceSkia(
             mailbox_holder.mailbox);
@@ -943,6 +943,11 @@
                      "mailbox not found in SharedImageManager.";
       return nullptr;
     }
+    if (!(shared_image->usage() & gpu::SHARED_IMAGE_USAGE_DISPLAY)) {
+      DLOG(ERROR) << "Failed to fulfill the promise texture - SharedImage "
+                     "was not created with display usage.";
+      return nullptr;
+    }
     *shared_image_out = std::move(shared_image);
   }
   if (*shared_image_out) {
@@ -1190,6 +1195,8 @@
 
 void SkiaOutputSurfaceImplOnGpu::PullTextureUpdates(
     std::vector<gpu::SyncToken> sync_tokens) {
+  // TODO(https://crbug.com/900973): Remove it when MailboxManager is replaced
+  // with SharedImage API.
   if (mailbox_manager_->UsesSync()) {
     for (auto& sync_token : sync_tokens)
       mailbox_manager_->PullTextureUpdates(sync_token);
@@ -1198,6 +1205,8 @@
 
 void SkiaOutputSurfaceImplOnGpu::ReleaseFenceSyncAndPushTextureUpdates(
     uint64_t sync_fence_release) {
+  // TODO(https://crbug.com/900973): Remove it when MailboxManager is replaced
+  // with SharedImage API.
   if (mailbox_manager_->UsesSync()) {
     // If MailboxManagerSync is used, we are sharing textures between threads.
     // In this case, sync point can only guarantee GL commands are issued in
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_unittest.cc b/components/viz/service/display_embedder/skia_output_surface_impl_unittest.cc
index b35ca51..a85a117 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl_unittest.cc
+++ b/components/viz/service/display_embedder/skia_output_surface_impl_unittest.cc
@@ -134,7 +134,8 @@
   gpu_service_->InitializeWithHost(
       std::move(gpu_host_proxy), gpu::GpuProcessActivityFlags(),
       gl::init::CreateOffscreenGLSurface(gfx::Size()),
-      nullptr /* sync_point_manager */, nullptr /* shutdown_event */);
+      nullptr /* sync_point_manager */, nullptr /* shared_image_manager */,
+      nullptr /* shutdown_event */);
   task_executor_ = base::MakeRefCounted<gpu::GpuInProcessThreadService>(
       gpu_thread_->task_runner(), gpu_service_->scheduler(),
       gpu_service_->sync_point_manager(), gpu_service_->mailbox_manager(),
diff --git a/components/viz/service/gl/gpu_service_impl.cc b/components/viz/service/gl/gpu_service_impl.cc
index c4d8779..6d8a6f9 100644
--- a/components/viz/service/gl/gpu_service_impl.cc
+++ b/components/viz/service/gl/gpu_service_impl.cc
@@ -190,6 +190,7 @@
   // Scheduler must be destroyed before sync point manager is destroyed.
   scheduler_.reset();
   owned_sync_point_manager_.reset();
+  owned_shared_image_manager_.reset();
 
   // Signal this event before destroying the child process. That way all
   // background threads can cleanup. For example, in the renderer the
@@ -223,6 +224,7 @@
     gpu::GpuProcessActivityFlags activity_flags,
     scoped_refptr<gl::GLSurface> default_offscreen_surface,
     gpu::SyncPointManager* sync_point_manager,
+    gpu::SharedImageManager* shared_image_manager,
     base::WaitableEvent* shutdown_event) {
   DCHECK(main_runner_->BelongsToCurrentThread());
   gpu_host->DidInitialize(gpu_info_, gpu_feature_info_,
@@ -245,6 +247,14 @@
     sync_point_manager_ = owned_sync_point_manager_.get();
   }
 
+  if (!shared_image_manager) {
+    // The shared image will be only used on GPU main thread, so it doesn't need
+    // to be thread safe.
+    owned_shared_image_manager_ =
+        std::make_unique<gpu::SharedImageManager>(false /* thread_safe */);
+    shared_image_manager = owned_shared_image_manager_.get();
+  }
+
   shutdown_event_ = shutdown_event;
   if (!shutdown_event_) {
     owned_shutdown_event_ = std::make_unique<base::WaitableEvent>(
@@ -264,9 +274,9 @@
   // initialization has succeeded.
   gpu_channel_manager_ = std::make_unique<gpu::GpuChannelManager>(
       gpu_preferences_, this, watchdog_thread_.get(), main_runner_, io_runner_,
-      scheduler_.get(), sync_point_manager_, gpu_memory_buffer_factory_.get(),
-      gpu_feature_info_, std::move(activity_flags),
-      std::move(default_offscreen_surface),
+      scheduler_.get(), sync_point_manager_, shared_image_manager,
+      gpu_memory_buffer_factory_.get(), gpu_feature_info_,
+      std::move(activity_flags), std::move(default_offscreen_surface),
       nullptr /* image_decode_accelerator_worker */, vulkan_context_provider());
 
   media_gpu_channel_manager_.reset(
diff --git a/components/viz/service/gl/gpu_service_impl.h b/components/viz/service/gl/gpu_service_impl.h
index aa3dfcf..ff10d91 100644
--- a/components/viz/service/gl/gpu_service_impl.h
+++ b/components/viz/service/gl/gpu_service_impl.h
@@ -44,6 +44,7 @@
 class GpuWatchdogThread;
 class Scheduler;
 class SyncPointManager;
+class SharedImageManager;
 class VulkanImplementation;
 }  // namespace gpu
 
@@ -85,6 +86,7 @@
       gpu::GpuProcessActivityFlags activity_flags,
       scoped_refptr<gl::GLSurface> default_offscreen_surface,
       gpu::SyncPointManager* sync_point_manager = nullptr,
+      gpu::SharedImageManager* shared_image_manager = nullptr,
       base::WaitableEvent* shutdown_event = nullptr);
   void Bind(mojom::GpuServiceRequest request);
 
@@ -292,11 +294,13 @@
   std::unique_ptr<gpu::GpuChannelManager> gpu_channel_manager_;
   std::unique_ptr<media::MediaGpuChannelManager> media_gpu_channel_manager_;
 
-  // On some platforms (e.g. android webview), the SyncPointManager comes from
-  // external sources.
+  // On some platforms (e.g. android webview), the SyncPointManager and
+  // SharedImageManager comes from external sources.
   std::unique_ptr<gpu::SyncPointManager> owned_sync_point_manager_;
   gpu::SyncPointManager* sync_point_manager_ = nullptr;
 
+  std::unique_ptr<gpu::SharedImageManager> owned_shared_image_manager_;
+
   std::unique_ptr<gpu::Scheduler> scheduler_;
 
   // sequence id for running tasks from SkiaOutputSurface;
diff --git a/components/viz/service/main/viz_main_impl.cc b/components/viz/service/main/viz_main_impl.cc
index f652a94..2b1af6b 100644
--- a/components/viz/service/main/viz_main_impl.cc
+++ b/components/viz/service/main/viz_main_impl.cc
@@ -197,7 +197,8 @@
       std::move(gpu_host),
       gpu::GpuProcessActivityFlags(std::move(activity_flags)),
       gpu_init_->TakeDefaultOffscreenSurface(),
-      dependencies_.sync_point_manager, dependencies_.shutdown_event);
+      dependencies_.sync_point_manager, dependencies_.shared_image_manager,
+      dependencies_.shutdown_event);
 
   if (!pending_frame_sink_manager_params_.is_null()) {
     CreateFrameSinkManagerInternal(
diff --git a/components/viz/service/main/viz_main_impl.h b/components/viz/service/main/viz_main_impl.h
index f8d3c8a..5c7dbd94 100644
--- a/components/viz/service/main/viz_main_impl.h
+++ b/components/viz/service/main/viz_main_impl.h
@@ -28,6 +28,7 @@
 namespace gpu {
 class GpuInit;
 class SyncPointManager;
+class SharedImageManager;
 }  // namespace gpu
 
 namespace service_manager {
@@ -77,6 +78,7 @@
 
     bool create_display_compositor = false;
     gpu::SyncPointManager* sync_point_manager = nullptr;
+    gpu::SharedImageManager* shared_image_manager = nullptr;
     base::WaitableEvent* shutdown_event = nullptr;
     scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner;
     service_manager::Connector* connector = nullptr;
diff --git a/content/gpu/gpu_child_thread.cc b/content/gpu/gpu_child_thread.cc
index d88f309..5d8413f 100644
--- a/content/gpu/gpu_child_thread.cc
+++ b/content/gpu/gpu_child_thread.cc
@@ -168,8 +168,11 @@
     service_manager::Connector* connector) {
   viz::VizMainImpl::ExternalDependencies deps;
   deps.create_display_compositor = features::IsVizDisplayCompositorEnabled();
-  if (GetContentClient()->gpu())
+  if (GetContentClient()->gpu()) {
     deps.sync_point_manager = GetContentClient()->gpu()->GetSyncPointManager();
+    deps.shared_image_manager =
+        GetContentClient()->gpu()->GetSharedImageManager();
+  }
   auto* process = ChildProcess::current();
   deps.shutdown_event = process->GetShutDownEvent();
   deps.io_thread_task_runner = process->io_task_runner();
diff --git a/content/public/gpu/content_gpu_client.cc b/content/public/gpu/content_gpu_client.cc
index b354769..19addbb 100644
--- a/content/public/gpu/content_gpu_client.cc
+++ b/content/public/gpu/content_gpu_client.cc
@@ -14,6 +14,10 @@
   return nullptr;
 }
 
+gpu::SharedImageManager* ContentGpuClient::GetSharedImageManager() {
+  return nullptr;
+}
+
 #if BUILDFLAG(ENABLE_LIBRARY_CDMS)
 std::unique_ptr<media::CdmProxy> ContentGpuClient::CreateCdmProxy(
     const base::Token& cdm_guid) {
diff --git a/content/public/gpu/content_gpu_client.h b/content/public/gpu/content_gpu_client.h
index 28f7970..20e31e1b 100644
--- a/content/public/gpu/content_gpu_client.h
+++ b/content/public/gpu/content_gpu_client.h
@@ -20,6 +20,7 @@
 
 namespace gpu {
 struct GpuPreferences;
+class SharedImageManager;
 class SyncPointManager;
 }
 
@@ -52,9 +53,10 @@
   virtual void PostCompositorThreadCreated(
       base::SingleThreadTaskRunner* task_runner) {}
 
-  // Allows client to supply a SyncPointManager instance instead of having
-  // content internally create one.
+  // Allows client to supply SyncPointManager and SharedImageManager instance
+  // instead of having content internally create one.
   virtual gpu::SyncPointManager* GetSyncPointManager();
+  virtual gpu::SharedImageManager* GetSharedImageManager();
 
 #if BUILDFLAG(ENABLE_LIBRARY_CDMS)
   // Creates a media::CdmProxy for the type of Content Decryption Module (CDM)
diff --git a/gpu/command_buffer/service/shared_image_factory.cc b/gpu/command_buffer/service/shared_image_factory.cc
index e1f2b67..8605158 100644
--- a/gpu/command_buffer/service/shared_image_factory.cc
+++ b/gpu/command_buffer/service/shared_image_factory.cc
@@ -105,9 +105,17 @@
   std::unique_ptr<SharedImageBacking> backing;
   bool using_wrapped_sk_image = wrapped_sk_image_factory_ &&
                                 (usage & SHARED_IMAGE_USAGE_OOP_RASTERIZATION);
-  bool using_interop_factory = using_vulkan_ &&
-                               (usage & SHARED_IMAGE_USAGE_GLES2) &&
+  // If |shared_image_manager_| is thread safe, it means the display is running
+  // on a separate thread (which uses a separate GL context or VkDeviceQueue).
+  bool share_between_threads = shared_image_manager_->is_thread_safe() &&
                                (usage & SHARED_IMAGE_USAGE_DISPLAY);
+  bool share_between_gl_vulkan = using_vulkan_ &&
+                                 (usage & SHARED_IMAGE_USAGE_GLES2) &&
+                                 (usage & SHARED_IMAGE_USAGE_DISPLAY);
+  bool using_interop_factory = share_between_threads || share_between_gl_vulkan;
+  // TODO(penghuang): make sure all shared image are created with correct usage.
+  // https://crbug.com/937480
+  // using_interop_factory = shared_image_manager_->is_thread_safe();
   if (using_wrapped_sk_image) {
     backing = wrapped_sk_image_factory_->CreateSharedImage(
         mailbox, format, size, color_space, usage);
diff --git a/gpu/ipc/service/gpu_channel_manager.cc b/gpu/ipc/service/gpu_channel_manager.cc
index c87ddfb..c185b57 100644
--- a/gpu/ipc/service/gpu_channel_manager.cc
+++ b/gpu/ipc/service/gpu_channel_manager.cc
@@ -60,6 +60,7 @@
     scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
     Scheduler* scheduler,
     SyncPointManager* sync_point_manager,
+    SharedImageManager* shared_image_manager,
     GpuMemoryBufferFactory* gpu_memory_buffer_factory,
     const GpuFeatureInfo& gpu_feature_info,
     GpuProcessActivityFlags activity_flags,
@@ -77,6 +78,7 @@
       mailbox_manager_(gles2::CreateMailboxManager(gpu_preferences)),
       scheduler_(scheduler),
       sync_point_manager_(sync_point_manager),
+      shared_image_manager_(shared_image_manager),
       shader_translator_cache_(gpu_preferences_),
       default_offscreen_surface_(std::move(default_offscreen_surface)),
       gpu_memory_buffer_factory_(gpu_memory_buffer_factory),
diff --git a/gpu/ipc/service/gpu_channel_manager.h b/gpu/ipc/service/gpu_channel_manager.h
index cae718b..5b00e29d 100644
--- a/gpu/ipc/service/gpu_channel_manager.h
+++ b/gpu/ipc/service/gpu_channel_manager.h
@@ -27,7 +27,6 @@
 #include "gpu/command_buffer/service/service_discardable_manager.h"
 #include "gpu/command_buffer/service/shader_translator_cache.h"
 #include "gpu/command_buffer/service/shared_context_state.h"
-#include "gpu/command_buffer/service/shared_image_manager.h"
 #include "gpu/config/gpu_driver_bug_workarounds.h"
 #include "gpu/config/gpu_feature_info.h"
 #include "gpu/config/gpu_preferences.h"
@@ -75,6 +74,7 @@
       scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
       Scheduler* scheduler,
       SyncPointManager* sync_point_manager,
+      SharedImageManager* shared_image_manager,
       GpuMemoryBufferFactory* gpu_memory_buffer_factory,
       const GpuFeatureInfo& gpu_feature_info,
       GpuProcessActivityFlags activity_flags,
@@ -150,7 +150,7 @@
 
   SyncPointManager* sync_point_manager() const { return sync_point_manager_; }
 
-  SharedImageManager* shared_image_manager() { return &shared_image_manager_; }
+  SharedImageManager* shared_image_manager() { return shared_image_manager_; }
 
   // Retrieve GPU Resource consumption statistics for the task manager
   void GetVideoMemoryUsageStats(
@@ -203,7 +203,8 @@
   std::unique_ptr<gles2::Outputter> outputter_;
   Scheduler* scheduler_;
   // SyncPointManager guaranteed to outlive running MessageLoop.
-  SyncPointManager* sync_point_manager_;
+  SyncPointManager* const sync_point_manager_;
+  SharedImageManager* const shared_image_manager_;
   std::unique_ptr<gles2::ProgramCache> program_cache_;
   gles2::ShaderTranslatorCache shader_translator_cache_;
   gles2::FramebufferCompletenessCache framebuffer_completeness_cache_;
@@ -212,7 +213,6 @@
   GpuFeatureInfo gpu_feature_info_;
   ServiceDiscardableManager discardable_manager_;
   PassthroughDiscardableManager passthrough_discardable_manager_;
-  SharedImageManager shared_image_manager_;
 #if defined(OS_ANDROID)
   // Last time we know the GPU was powered on. Global for tracking across all
   // transport surfaces.
diff --git a/gpu/ipc/service/gpu_channel_test_common.cc b/gpu/ipc/service/gpu_channel_test_common.cc
index 2d970a8..c9e8273 100644
--- a/gpu/ipc/service/gpu_channel_test_common.cc
+++ b/gpu/ipc/service/gpu_channel_test_common.cc
@@ -9,6 +9,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "gpu/command_buffer/common/activity_flags.h"
 #include "gpu/command_buffer/service/scheduler.h"
+#include "gpu/command_buffer/service/shared_image_manager.h"
 #include "gpu/command_buffer/service/sync_point_manager.h"
 #include "gpu/ipc/service/gpu_channel.h"
 #include "gpu/ipc/service/gpu_channel_manager.h"
@@ -58,6 +59,7 @@
     : task_runner_(new base::TestSimpleTaskRunner),
       io_task_runner_(new base::TestSimpleTaskRunner),
       sync_point_manager_(new SyncPointManager()),
+      shared_image_manager_(new SharedImageManager(false /* thread_safe */)),
       scheduler_(new Scheduler(task_runner_, sync_point_manager_.get())),
       channel_manager_delegate_(new TestGpuChannelManagerDelegate()) {
   // We need GL bindings to actually initialize command buffers.
@@ -73,7 +75,8 @@
   channel_manager_.reset(new GpuChannelManager(
       GpuPreferences(), channel_manager_delegate_.get(), nullptr, /* watchdog */
       task_runner_.get(), io_task_runner_.get(), scheduler_.get(),
-      sync_point_manager_.get(), nullptr, /* gpu_memory_buffer_factory */
+      sync_point_manager_.get(), shared_image_manager_.get(),
+      nullptr, /* gpu_memory_buffer_factory */
       std::move(feature_info), GpuProcessActivityFlags(),
       gl::init::CreateOffscreenGLSurface(gfx::Size()),
       nullptr /* image_decode_accelerator_worker */));
diff --git a/gpu/ipc/service/gpu_channel_test_common.h b/gpu/ipc/service/gpu_channel_test_common.h
index fc54ec0..9ab01faf 100644
--- a/gpu/ipc/service/gpu_channel_test_common.h
+++ b/gpu/ipc/service/gpu_channel_test_common.h
@@ -26,6 +26,7 @@
 class GpuChannelManager;
 class Scheduler;
 class SyncPointManager;
+class SharedImageManager;
 class TestGpuChannelManagerDelegate;
 
 class GpuChannelTestCommon : public testing::Test {
@@ -55,6 +56,7 @@
   scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
   scoped_refptr<base::TestSimpleTaskRunner> io_task_runner_;
   std::unique_ptr<SyncPointManager> sync_point_manager_;
+  std::unique_ptr<SharedImageManager> shared_image_manager_;
   std::unique_ptr<Scheduler> scheduler_;
   std::unique_ptr<TestGpuChannelManagerDelegate> channel_manager_delegate_;
   std::unique_ptr<GpuChannelManager> channel_manager_;
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource.cc b/third_party/blink/renderer/platform/graphics/canvas_resource.cc
index 4604821..1a2d4d4 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource.cc
@@ -680,7 +680,8 @@
       context_provider_wrapper_->ContextProvider()->GetSharedImageInterface();
   DCHECK(shared_image_interface);
 
-  uint32_t flags = gpu::SHARED_IMAGE_USAGE_GLES2 |
+  uint32_t flags = gpu::SHARED_IMAGE_USAGE_DISPLAY |
+                   gpu::SHARED_IMAGE_USAGE_GLES2 |
                    gpu::SHARED_IMAGE_USAGE_GLES2_FRAMEBUFFER_HINT;
   if (is_overlay_candidate_)
     flags |= gpu::SHARED_IMAGE_USAGE_SCANOUT;