Move CanvasResourceProvider ownership up to CanvasResourceHost

This change pushes HTMLCanvasElement's CanvasResourceProvider
up the class hierachy so that it can be shared with
OffscreenCanvas. The next step is to remove
Canvas2DLayerBridge's resource provider to use this shared one
instead.

BUG=788439
TBR=zmo@chromium.org

Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:mac_optional_gpu_tests_rel;luci.chromium.try:win_optional_gpu_tests_rel;master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.linux:linux_layout_tests_slimming_paint_v2
Change-Id: Ib85237d0ee98205c5da8848cbd861ce6d5d9d4d2
Reviewed-on: https://chromium-review.googlesource.com/1075729
Commit-Queue: Justin Novosad <junov@chromium.org>
Reviewed-by: Fernando Serboncini <fserb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#562433}
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc
index 85f6049..91f52d6 100644
--- a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc
+++ b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc
@@ -4,7 +4,9 @@
 
 #include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h"
 
+#include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h"
+#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
 #include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
 #include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
 #include "third_party/skia/include/core/SkSurface.h"
@@ -41,4 +43,44 @@
     RenderingContext()->RestoreCanvasMatrixClipStack(canvas);
 }
 
+bool CanvasRenderingContextHost::Is3d() const {
+  return RenderingContext() && RenderingContext()->Is3d();
+}
+
+bool CanvasRenderingContextHost::Is2d() const {
+  return RenderingContext() && RenderingContext()->Is2d();
+}
+
+CanvasResourceProvider*
+CanvasRenderingContextHost::GetOrCreateCanvasResourceProvider() {
+  if (!ResourceProvider() && !did_fail_to_create_resource_provider_) {
+    resource_provider_is_clear_ = true;
+    if (IsValidImageSize(Size())) {
+      if (Is3d()) {
+        ReplaceResourceProvider(CanvasResourceProvider::Create(
+            Size(),
+            Platform::Current()->IsGpuCompositingDisabled()
+                ? CanvasResourceProvider::kSoftwareResourceUsage
+                : CanvasResourceProvider::kAcceleratedResourceUsage,
+            SharedGpuContext::ContextProviderWrapper(), 0, ColorParams()));
+      } else {
+        // 2d context
+        // TODO: move resource provider ownership from canvas 2d layer bridge
+        // to here.
+        NOTREACHED();
+      }
+    }
+    if (!ResourceProvider()) {
+      did_fail_to_create_resource_provider_ = true;
+    }
+  }
+  return ResourceProvider();
+}
+
+CanvasColorParams CanvasRenderingContextHost::ColorParams() const {
+  if (RenderingContext())
+    return RenderingContext()->ColorParams();
+  return CanvasColorParams();
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h
index 229fd7f8..b9e29cd 100644
--- a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h
+++ b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h
@@ -18,6 +18,7 @@
 
 namespace blink {
 
+class CanvasColorParams;
 class CanvasRenderingContext;
 class FontSelector;
 class StaticBitmapImage;
@@ -75,10 +76,18 @@
   // Partial CanvasResourceHost implementation
   void RestoreCanvasMatrixClipStack(PaintCanvas*) const final;
 
+  bool Is3d() const;
+  bool Is2d() const;
+  CanvasColorParams ColorParams() const;
+  CanvasResourceProvider* GetOrCreateCanvasResourceProvider();
+
  protected:
   ~CanvasRenderingContextHost() override {}
 
   scoped_refptr<StaticBitmapImage> CreateTransparentImage(const IntSize&) const;
+
+  bool did_fail_to_create_resource_provider_ = false;
+  bool resource_provider_is_clear_ = false;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
index a5d6e6d41..0a5bbca 100644
--- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
+++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
@@ -34,7 +34,6 @@
 #include "base/location.h"
 #include "build/build_config.h"
 #include "gpu/config/gpu_feature_info.h"
-#include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
 #include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
@@ -131,8 +130,6 @@
       context_creation_was_blocked_(false),
       ignore_reset_(false),
       origin_clean_(true),
-      did_fail_to_create_resource_provider_(false),
-      resource_provider_is_clear_(false),
       surface_layer_bridge_(nullptr),
       gpu_memory_usage_(0),
       externally_allocated_memory_(0),
@@ -395,7 +392,7 @@
   // into the canvas, now is a good time to unlock cache entries.
   auto* resource_provider = canvas2d_bridge_
                                 ? canvas2d_bridge_->GetResourceProvider()
-                                : ResourceProviderForWebGL();
+                                : ResourceProvider();
   if (resource_provider)
     resource_provider->ReleaseLockedImages();
 
@@ -613,12 +610,6 @@
   return true;
 }
 
-CanvasColorParams HTMLCanvasElement::ColorParams() const {
-  if (context_)
-    return context_->ColorParams();
-  return CanvasColorParams();
-}
-
 void HTMLCanvasElement::NotifyListenersCanvasChanged() {
   if (listeners_.size() == 0)
     return;
@@ -713,8 +704,7 @@
       scoped_refptr<StaticBitmapImage> snapshot =
           canvas2d_bridge_
               ? canvas2d_bridge_->NewImageSnapshot(kPreferAcceleration)
-              : (webgl_resource_provider_ ? webgl_resource_provider_->Snapshot()
-                                          : nullptr);
+              : (ResourceProvider() ? ResourceProvider()->Snapshot() : nullptr);
       if (snapshot) {
         // GraphicsContext cannot handle gpu resource serialization.
         snapshot = snapshot->MakeUnaccelerated();
@@ -734,14 +724,6 @@
     context_->MarkLayerComposited();
 }
 
-bool HTMLCanvasElement::Is3d() const {
-  return context_ && context_->Is3d();
-}
-
-bool HTMLCanvasElement::Is2d() const {
-  return context_ && context_->Is2d();
-}
-
 bool HTMLCanvasElement::IsAnimated2d() const {
   return Is2d() && canvas2d_bridge_ &&
          canvas2d_bridge_->WasDrawnToAfterSnapshot();
@@ -773,8 +755,8 @@
   if (Is3d()) {
     if (context_->CreationAttributes().premultiplied_alpha) {
       context_->PaintRenderingResultsToCanvas(source_buffer);
-      if (webgl_resource_provider_)
-        image_bitmap = webgl_resource_provider_->Snapshot();
+      if (ResourceProvider())
+        image_bitmap = ResourceProvider()->Snapshot();
     } else {
       scoped_refptr<Uint8Array> data_array =
           context_->PaintRenderingResultsToDataArray(source_buffer);
@@ -1122,28 +1104,6 @@
   return canvas2d_bridge_.get();
 }
 
-CanvasResourceProvider*
-HTMLCanvasElement::GetOrCreateCanvasResourceProviderForWebGL() {
-  DCHECK(Is3d());
-  if (!webgl_resource_provider_ && !did_fail_to_create_resource_provider_) {
-    resource_provider_is_clear_ = true;
-    if (IsValidImageSize(Size())) {
-      webgl_resource_provider_ = CanvasResourceProvider::Create(
-          size_,
-          Platform::Current()->IsGpuCompositingDisabled()
-              ? CanvasResourceProvider::kSoftwareResourceUsage
-              : CanvasResourceProvider::kAcceleratedResourceUsage,
-          SharedGpuContext::ContextProviderWrapper(), 0, ColorParams());
-    }
-    if (!webgl_resource_provider_) {
-      did_fail_to_create_resource_provider_ = true;
-    } else {
-      UpdateMemoryUsage();
-    }
-  }
-  return webgl_resource_provider_.get();
-}
-
 void HTMLCanvasElement::CreateCanvas2DLayerBridgeForTesting(
     std::unique_ptr<Canvas2DLayerBridge> bridge,
     const IntSize& size) {
@@ -1184,8 +1144,8 @@
   if (need_to_update) {
     if (Is2d() && GetOrCreateCanvas2DLayerBridge()) {
       copied_image_ = canvas2d_bridge_->NewImageSnapshot(hint);
-    } else if (Is3d() && GetOrCreateCanvasResourceProviderForWebGL()) {
-      copied_image_ = webgl_resource_provider_->Snapshot();
+    } else if (Is3d() && GetOrCreateCanvasResourceProvider()) {
+      copied_image_ = ResourceProvider()->Snapshot();
     }
     UpdateMemoryUsage();
   }
@@ -1194,7 +1154,7 @@
 
 void HTMLCanvasElement::DiscardResourceProvider() {
   canvas2d_bridge_.reset();
-  webgl_resource_provider_.reset();
+  ReplaceResourceProvider(nullptr);
   dirty_rect_ = FloatRect();
   UpdateMemoryUsage();
 }
@@ -1298,8 +1258,8 @@
     // use paintRenderingResultsToCanvas instead of getImage in order to keep a
     // cached copy of the backing in the canvas's resource provider.
     RenderingContext()->PaintRenderingResultsToCanvas(kBackBuffer);
-    if (webgl_resource_provider_) {
-      image = webgl_resource_provider_->Snapshot();
+    if (ResourceProvider()) {
+      image = ResourceProvider()->Snapshot();
     } else {
       image = CreateTransparentImage(Size());
     }
@@ -1498,9 +1458,9 @@
     non_gpu_buffer_count++;
 
   if (Is3d()) {
-    if (webgl_resource_provider_) {
+    if (ResourceProvider()) {
       non_gpu_buffer_count++;
-      if (webgl_resource_provider_->IsAccelerated()) {
+      if (ResourceProvider()->IsAccelerated()) {
         gpu_buffer_count += 2;
       }
     }
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.h b/third_party/blink/renderer/core/html/canvas/html_canvas_element.h
index 349ebe6..e815509 100644
--- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.h
+++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.h
@@ -63,7 +63,6 @@
 namespace blink {
 
 class Canvas2DLayerBridge;
-class CanvasColorParams;
 class CanvasContextCreationAttributesCore;
 class CanvasDrawListener;
 class CanvasRenderingContext;
@@ -155,18 +154,13 @@
   bool OriginClean() const override;
   void SetOriginTainted() override { origin_clean_ = false; }
 
-  bool Is3d() const;
-  bool Is2d() const;
   bool IsAnimated2d() const;
 
   Canvas2DLayerBridge* GetCanvas2DLayerBridge() {
     return canvas2d_bridge_.get();
   }
   Canvas2DLayerBridge* GetOrCreateCanvas2DLayerBridge();
-  CanvasResourceProvider* GetOrCreateCanvasResourceProviderForWebGL();
-  CanvasResourceProvider* ResourceProviderForWebGL() const {
-    return webgl_resource_provider_.get();
-  }
+
   void DiscardResourceProvider() override;
 
   FontSelector* GetFontSelector() override;
@@ -321,7 +315,6 @@
   void SetSurfaceSize(const IntSize&);
 
   bool PaintsIntoCanvasBuffer() const;
-  CanvasColorParams ColorParams() const;
 
   scoped_refptr<StaticBitmapImage> ToStaticBitmapImage(SourceDrawingBuffer,
                                                        AccelerationHint) const;
@@ -350,17 +343,10 @@
 
   // It prevents repeated attempts in allocating resources after the first
   // attempt failed.
-  mutable bool did_fail_to_create_resource_provider_;
-
   bool HasResourceProvider() {
-    return canvas2d_bridge_ || webgl_resource_provider_;
+    return canvas2d_bridge_ || !!CanvasResourceHost::ResourceProvider();
   }
 
-  bool resource_provider_is_clear_;
-
-  // This is only used by canvas with webgl rendering context.
-  std::unique_ptr<CanvasResourceProvider> webgl_resource_provider_;
-
   // Canvas2DLayerBridge is used when canvas has 2d rendering context
   std::unique_ptr<Canvas2DLayerBridge> canvas2d_bridge_;
   void ReplaceExisting2dLayerBridge(std::unique_ptr<Canvas2DLayerBridge>);
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
index 1d5c925..3b5f110 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
+++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
@@ -1531,18 +1531,18 @@
   canvas()->ClearCopiedImage();
   marked_canvas_dirty_ = false;
 
-  if (!canvas()->GetOrCreateCanvasResourceProviderForWebGL())
+  if (!canvas()->GetOrCreateCanvasResourceProvider())
     return false;
 
-  if (!canvas()->GetOrCreateCanvasResourceProviderForWebGL()->IsAccelerated())
+  if (!canvas()->ResourceProvider()->IsAccelerated())
     return false;
 
   ScopedTexture2DRestorer restorer(this);
   ScopedFramebufferRestorer fbo_restorer(this);
 
   GetDrawingBuffer()->ResolveAndBindForReadAndDraw();
-  if (!CopyRenderingResultsFromDrawingBuffer(
-          canvas()->ResourceProviderForWebGL(), source_buffer)) {
+  if (!CopyRenderingResultsFromDrawingBuffer(canvas()->ResourceProvider(),
+                                             source_buffer)) {
     // Currently, copyRenderingResultsFromDrawingBuffer is expected to always
     // succeed because cases where canvas()-buffer() is not accelerated are
     // handle before reaching this point.  If that assumption ever stops holding
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn
index 4e7d323..14ee69d3 100644
--- a/third_party/blink/renderer/platform/BUILD.gn
+++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -818,6 +818,7 @@
     "graphics/canvas_metrics.h",
     "graphics/canvas_resource.cc",
     "graphics/canvas_resource.h",
+    "graphics/canvas_resource_host.cc",
     "graphics/canvas_resource_host.h",
     "graphics/canvas_resource_provider.cc",
     "graphics/canvas_resource_provider.h",
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_host.cc b/third_party/blink/renderer/platform/graphics/canvas_resource_host.cc
new file mode 100644
index 0000000..32e57c1
--- /dev/null
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource_host.cc
@@ -0,0 +1,25 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/graphics/canvas_resource_host.h"
+
+#include "third_party/blink/renderer/platform/graphics/canvas_resource_provider.h"
+
+namespace blink {
+
+CanvasResourceProvider* CanvasResourceHost::ResourceProvider() const {
+  return resource_provider_.get();
+}
+
+std::unique_ptr<CanvasResourceProvider>
+CanvasResourceHost::ReplaceResourceProvider(
+    std::unique_ptr<CanvasResourceProvider> new_resource_provider) {
+  std::unique_ptr<CanvasResourceProvider> old_resource_provider =
+      std::move(resource_provider_);
+  resource_provider_ = std::move(new_resource_provider);
+  UpdateMemoryUsage();
+  return old_resource_provider;
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_host.h b/third_party/blink/renderer/platform/graphics/canvas_resource_host.h
index a4518f8..ef2ea8b 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource_host.h
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource_host.h
@@ -10,6 +10,8 @@
 
 namespace blink {
 
+class CanvasResourceProvider;
+
 class PLATFORM_EXPORT CanvasResourceHost {
  public:
   virtual ~CanvasResourceHost() = default;
@@ -17,6 +19,14 @@
   virtual void SetNeedsCompositingUpdate() = 0;
   virtual void RestoreCanvasMatrixClipStack(PaintCanvas*) const = 0;
   virtual void UpdateMemoryUsage() = 0;
+
+  CanvasResourceProvider* ResourceProvider() const;
+
+  std::unique_ptr<CanvasResourceProvider> ReplaceResourceProvider(
+      std::unique_ptr<CanvasResourceProvider>);
+
+ private:
+  std::unique_ptr<CanvasResourceProvider> resource_provider_;
 };
 
 }  // namespace blink