Hook up skia makeYUVAPromiseTexture API

Know issues:
 * Skia only draws Y plane.
 * makeYUVAPromiseTexture() will release context, even if it failed.
 * Skia doesn't accept GL_RGBA8 format for a yuva plane

Bug: 824382
Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel
Change-Id: Ic8da2b3de574ef2a0d527c79f34d383a676a3bc0
Reviewed-on: https://chromium-review.googlesource.com/c/1262421
Reviewed-by: Antoine Labour <piman@chromium.org>
Commit-Queue: Peng Huang <penghuang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#599193}
diff --git a/components/viz/service/display/skia_output_surface.h b/components/viz/service/display/skia_output_surface.h
index 9857096..f87a564 100644
--- a/components/viz/service/display/skia_output_surface.h
+++ b/components/viz/service/display/skia_output_surface.h
@@ -43,15 +43,16 @@
   virtual sk_sp<SkImage> MakePromiseSkImage(ResourceMetadata metadata) = 0;
 
   // Make a promise SkImage from the given |metadata| and the |yuv_color_space|.
-  // For YUV format, three resource metadatas should be provided. metadatas[0]
-  // contains pixels from y panel, metadatas[1] contains pixels from u panel,
-  // metadatas[2] contains pixels from v panel.
-  // For NV12 format, two resource metadatas should be provided. metadatas[0]
-  // contains pixels from y panel, metadatas[1] contains pixels from u and v
-  // panels.
+  // For YUV format, at least three resource metadatas should be provided.
+  // metadatas[0] contains pixels from y panel, metadatas[1] contains pixels
+  // from u panel, metadatas[2] contains pixels from v panel. For NV12 format,
+  // at least two resource metadatas should be provided. metadatas[0] contains
+  // pixels from y panel, metadatas[1] contains pixels from u and v panels. If
+  // has_alpha is true, the last item in metadatas contains alpha panel.
   virtual sk_sp<SkImage> MakePromiseSkImageFromYUV(
       std::vector<ResourceMetadata> metadatas,
-      SkYUVColorSpace yuv_color_space) = 0;
+      SkYUVColorSpace yuv_color_space,
+      bool has_alpha) = 0;
 
   // Swaps the current backbuffer to the screen.
   virtual void SkiaSwapBuffers(OutputSurfaceFrame frame) = 0;
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc
index 58fb3ca..80cd796 100644
--- a/components/viz/service/display/skia_renderer.cc
+++ b/components/viz/service/display/skia_renderer.cc
@@ -107,7 +107,7 @@
       DCHECK(!metadata.mailbox.IsZero());
       image = skia_renderer->skia_output_surface_->MakePromiseSkImage(
           std::move(metadata));
-      DCHECK(image);
+      LOG_IF(ERROR, !image) << "Failed to create the promise sk image.";
     }
     sk_image_ = image.get();
   }
@@ -136,30 +136,35 @@
       auto yuv_color_space = kRec601_SkYUVColorSpace;
       quad->video_color_space.ToSkYUVColorSpace(&yuv_color_space);
 
+      const bool is_i420 =
+          quad->u_plane_resource_id() != quad->v_plane_resource_id();
+      const bool has_alpha = quad->a_plane_resource_id() != kInvalidResourceId;
+      const size_t number_of_textures = (is_i420 ? 3 : 2) + (has_alpha ? 1 : 0);
       std::vector<ResourceMetadata> metadatas;
-      bool is_yuv = quad->u_plane_resource_id() != quad->v_plane_resource_id();
-      metadatas.reserve(is_yuv ? 3 : 2);
+      metadatas.reserve(number_of_textures);
       auto y_metadata = skia_renderer->lock_set_for_external_use_.LockResource(
           quad->y_plane_resource_id());
       metadatas.push_back(std::move(y_metadata));
       auto u_metadata = skia_renderer->lock_set_for_external_use_.LockResource(
           quad->u_plane_resource_id());
       metadatas.push_back(std::move(u_metadata));
-      if (is_yuv) {
+      if (is_i420) {
         auto v_metadata =
             skia_renderer->lock_set_for_external_use_.LockResource(
                 quad->v_plane_resource_id());
         metadatas.push_back(std::move(v_metadata));
       }
 
-      if (quad->a_plane_resource_id() != kInvalidResourceId) {
-        // TODO(penghuang): Handle alpha channel when Skia supports YUVA format.
-        NOTIMPLEMENTED();
+      if (has_alpha) {
+        auto a_metadata =
+            skia_renderer->lock_set_for_external_use_.LockResource(
+                quad->a_plane_resource_id());
+        metadatas.push_back(std::move(a_metadata));
       }
 
       image = skia_renderer->skia_output_surface_->MakePromiseSkImageFromYUV(
-          std::move(metadatas), yuv_color_space);
-      DCHECK(image);
+          std::move(metadatas), yuv_color_space, has_alpha);
+      LOG_IF(ERROR, !image) << "Failed to create the promise sk yuva image.";
     }
     sk_image_ = image.get();
   }
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 576a5d1..720f435 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl.cc
+++ b/components/viz/service/display_embedder/skia_output_surface_impl.cc
@@ -17,6 +17,7 @@
 #include "components/viz/service/gl/gpu_service_impl.h"
 #include "gpu/command_buffer/common/swap_buffers_complete_params.h"
 #include "gpu/command_buffer/service/scheduler.h"
+#include "third_party/skia/include/core/SkYUVAIndex.h"
 #include "ui/gfx/skia_util.h"
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_context.h"
@@ -43,14 +44,14 @@
 
 }  // namespace
 
-// A helper class for fullfilling promise image on the GPU thread.
-template <class FullfillContextType>
+// A helper class for fulfilling promise image on the GPU thread.
+template <class FulfillContextType>
 class SkiaOutputSurfaceImpl::PromiseTextureHelper {
  public:
-  using HelperType = PromiseTextureHelper<FullfillContextType>;
+  using HelperType = PromiseTextureHelper<FulfillContextType>;
 
   PromiseTextureHelper(base::WeakPtr<SkiaOutputSurfaceImplOnGpu> impl_on_gpu,
-                       FullfillContextType context)
+                       FulfillContextType context)
       : impl_on_gpu_(impl_on_gpu), context_(std::move(context)) {}
   ~PromiseTextureHelper() = default;
 
@@ -64,34 +65,32 @@
       SkColorType color_type,
       SkAlphaType alpha_type,
       sk_sp<SkColorSpace> color_space,
-      FullfillContextType context) {
+      FulfillContextType context) {
     DCHECK_CALLED_ON_VALID_THREAD(impl->thread_checker_);
-    auto helper = std::make_unique<HelperType>(impl->impl_on_gpu_->weak_ptr(),
-                                               std::move(context));
+    // The ownership of the helper will be passed into makePromisTexture(). The
+    // HelperType::Done will always be called. It will delete the helper.
+    auto* helper =
+        new HelperType(impl->impl_on_gpu_->weak_ptr(), std::move(context));
     auto image = recorder->makePromiseTexture(
         backend_format, size.width(), size.height(), mip_mapped, origin,
-        color_type, alpha_type, color_space, HelperType::Fullfill,
-        HelperType::Release, HelperType::Done, helper.get());
-    if (image) {
-      helper->Init(impl);
-      helper.release();
-    }
+        color_type, alpha_type, color_space, HelperType::Fulfill,
+        HelperType::Release, HelperType::Done, helper);
     return image;
   }
 
  private:
-  void Init(SkiaOutputSurfaceImpl* impl);
+  friend class SkiaOutputSurfaceImpl::YUVAPromiseTextureHelper;
 
-  static void Fullfill(void* texture_context,
-                       GrBackendTexture* backend_texture) {
+  static void Fulfill(void* texture_context,
+                      GrBackendTexture* backend_texture) {
     DCHECK(texture_context);
     auto* helper = static_cast<HelperType*>(texture_context);
-    // The fullfill is always called by SkiaOutputSurfaceImplOnGpu::SwapBuffers
+    // The fulfill is always called by SkiaOutputSurfaceImplOnGpu::SwapBuffers
     // or SkiaOutputSurfaceImplOnGpu::FinishPaintRenderPass, so impl_on_gpu_
     // should be always valid.
     DCHECK(helper->impl_on_gpu_);
-    helper->impl_on_gpu_->FullfillPromiseTexture(helper->context_,
-                                                 backend_texture);
+    helper->impl_on_gpu_->FulfillPromiseTexture(helper->context_,
+                                                backend_texture);
   }
 
   static void Release(void* texture_context) { DCHECK(texture_context); }
@@ -104,26 +103,83 @@
 
   base::WeakPtr<SkiaOutputSurfaceImplOnGpu> impl_on_gpu_;
 
-  // The data for calling the fullfill methods in SkiaOutputSurfaceImpl.
-  FullfillContextType context_;
+  // The data for calling the fulfill methods in SkiaOutputSurfaceImpl.
+  FulfillContextType context_;
 
   DISALLOW_COPY_AND_ASSIGN(PromiseTextureHelper);
 };
 
-template <class T>
-void SkiaOutputSurfaceImpl::PromiseTextureHelper<T>::Init(
-    SkiaOutputSurfaceImpl* impl) {}
+// A helper class for fulfilling YUVA promise image on the GPU thread.
+class SkiaOutputSurfaceImpl::YUVAPromiseTextureHelper {
+ public:
+  static sk_sp<SkImage> MakeYUVAPromiseSkImage(
+      SkiaOutputSurfaceImpl* impl,
+      SkDeferredDisplayListRecorder* recorder,
+      SkYUVColorSpace yuv_color_space,
+      std::vector<ResourceMetadata> metadatas,
+      bool has_alpha) {
+    DCHECK_CALLED_ON_VALID_THREAD(impl->thread_checker_);
+    DCHECK_LE(metadatas.size(), 4u);
 
-// For YUVResourceMetadata, we need to record the |context_| pointer in
-// |impl->yuv_resource_metadatas_|, because we have to create SkImage from YUV
-// textures before drawing the ddl to a SKSurface.
-// TODO(penghuang): Remove this hack when Skia supports drawing YUV textures
-// directly.
-template <>
-void SkiaOutputSurfaceImpl::PromiseTextureHelper<YUVResourceMetadata>::Init(
-    SkiaOutputSurfaceImpl* impl) {
-  impl->yuv_resource_metadatas_.push_back(&context_);
-}
+    using PlaneHelper = PromiseTextureHelper<ResourceMetadata>;
+    bool is_i420 = has_alpha ? metadatas.size() == 4 : metadatas.size() == 3;
+    auto size = metadatas[0].size;
+
+    GrBackendFormat formats[4];
+    SkYUVAIndex indices[4] = {
+        {-1, SkColorChannel::kR},
+        {-1, SkColorChannel::kR},
+        {-1, SkColorChannel::kR},
+        {-1, SkColorChannel::kR},
+    };
+    SkDeferredDisplayListRecorder::TextureContext contexts[4] = {
+        nullptr, nullptr, nullptr, nullptr};
+
+    // The ownership of the contexts will be passed into
+    // makeYUVAPromisTexture(). The HelperType::Done will always be called. It
+    // will delete contexts.
+    for (size_t i = 0; i < metadatas.size(); i++) {
+      auto& metadata = metadatas[i];
+      formats[i] = metadata.backend_format;
+      contexts[i] =
+          new PlaneHelper(impl->impl_on_gpu_->weak_ptr(), std::move(metadata));
+    }
+
+    if (is_i420) {
+      indices[SkYUVAIndex::kY_Index].fIndex = 0;
+      indices[SkYUVAIndex::kY_Index].fChannel = SkColorChannel::kR;
+      indices[SkYUVAIndex::kU_Index].fIndex = 1;
+      indices[SkYUVAIndex::kU_Index].fChannel = SkColorChannel::kR;
+      indices[SkYUVAIndex::kV_Index].fIndex = 2;
+      indices[SkYUVAIndex::kV_Index].fChannel = SkColorChannel::kR;
+      if (has_alpha) {
+        indices[SkYUVAIndex::kA_Index].fIndex = 3;
+        indices[SkYUVAIndex::kA_Index].fChannel = SkColorChannel::kA;
+      }
+    } else {
+      indices[SkYUVAIndex::kY_Index].fIndex = 0;
+      indices[SkYUVAIndex::kY_Index].fChannel = SkColorChannel::kR;
+      indices[SkYUVAIndex::kU_Index].fIndex = 1;
+      indices[SkYUVAIndex::kU_Index].fChannel = SkColorChannel::kR;
+      indices[SkYUVAIndex::kV_Index].fIndex = 1;
+      indices[SkYUVAIndex::kV_Index].fChannel = SkColorChannel::kG;
+      if (has_alpha) {
+        indices[SkYUVAIndex::kA_Index].fIndex = 2;
+        indices[SkYUVAIndex::kA_Index].fChannel = SkColorChannel::kA;
+      }
+    }
+
+    auto image = recorder->makeYUVAPromiseTexture(
+        yuv_color_space, formats, indices, size.width(), size.height(),
+        kTopLeft_GrSurfaceOrigin, nullptr /* color_space */,
+        PlaneHelper::Fulfill, PlaneHelper::Release, PlaneHelper::Done,
+        contexts);
+    return image;
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(YUVAPromiseTextureHelper);
+};
 
 SkiaOutputSurfaceImpl::SkiaOutputSurfaceImpl(
     GpuServiceImpl* gpu_service,
@@ -319,34 +375,15 @@
 
 sk_sp<SkImage> SkiaOutputSurfaceImpl::MakePromiseSkImageFromYUV(
     std::vector<ResourceMetadata> metadatas,
-    SkYUVColorSpace yuv_color_space) {
+    SkYUVColorSpace yuv_color_space,
+    bool has_alpha) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   DCHECK(recorder_);
-
-  DCHECK(metadatas.size() == 2 || metadatas.size() == 3);
-
-  // TODO(penghuang): Create SkImage from YUV textures directly when it is
-  // supported by Skia.
-  YUVResourceMetadata yuv_metadata(std::move(metadatas), yuv_color_space);
-
-  GrBackendFormat backend_format;
-  if (!gpu_service_->is_using_vulkan()) {
-    // Convert internal format from GLES2 to platform GL.
-    const auto* version_info = impl_on_gpu_->gl_version_info();
-    backend_format = GrBackendFormat::MakeGL(
-        gl::GetInternalFormat(version_info, GL_BGRA8_EXT), GL_TEXTURE_2D);
-  } else {
-#if BUILDFLAG(ENABLE_VULKAN)
-    backend_format = GrBackendFormat::MakeVk(VK_FORMAT_B8G8R8A8_UNORM);
-#else
-    NOTREACHED();
-#endif
-  }
-
-  return PromiseTextureHelper<YUVResourceMetadata>::MakePromiseSkImage(
-      this, &recorder_.value(), backend_format, yuv_metadata.size(),
-      GrMipMapped::kNo, kTopLeft_GrSurfaceOrigin, kBGRA_8888_SkColorType,
-      kPremul_SkAlphaType, nullptr /* color_space */, std::move(yuv_metadata));
+  DCHECK((has_alpha && (metadatas.size() == 3 || metadatas.size() == 4)) ||
+         (!has_alpha && (metadatas.size() == 2 || metadatas.size() == 3)));
+  return YUVAPromiseTextureHelper::MakeYUVAPromiseSkImage(
+      this, &recorder_.value(), yuv_color_space, std::move(metadatas),
+      has_alpha);
 }
 
 void SkiaOutputSurfaceImpl::SkiaSwapBuffers(OutputSurfaceFrame frame) {
@@ -434,16 +471,15 @@
   // SkiaOutputSurfaceImpl::dtor. So it is safe to use base::Unretained.
   base::OnceCallback<void()> callback;
   if (painting_render_pass) {
-    callback =
-        base::BindOnce(&SkiaOutputSurfaceImplOnGpu::FinishPaintRenderPass,
-                       base::Unretained(impl_on_gpu_.get()),
-                       current_render_pass_id_, std::move(ddl),
-                       std::move(yuv_resource_metadatas_), sync_fence_release_);
+    callback = base::BindOnce(
+        &SkiaOutputSurfaceImplOnGpu::FinishPaintRenderPass,
+        base::Unretained(impl_on_gpu_.get()), current_render_pass_id_,
+        std::move(ddl), sync_fence_release_);
   } else {
     callback =
         base::BindOnce(&SkiaOutputSurfaceImplOnGpu::FinishPaintCurrentFrame,
                        base::Unretained(impl_on_gpu_.get()), std::move(ddl),
-                       std::move(yuv_resource_metadatas_), sync_fence_release_);
+                       sync_fence_release_);
   }
   gpu_service_->scheduler()->ScheduleTask(gpu::Scheduler::Task(
       sequence_id, std::move(callback), std::move(resource_sync_tokens_)));
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.h b/components/viz/service/display_embedder/skia_output_surface_impl.h
index d1c13a7..54122d6 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl.h
+++ b/components/viz/service/display_embedder/skia_output_surface_impl.h
@@ -26,8 +26,6 @@
 class SkiaOutputSurfaceImplOnGpu;
 class SyntheticBeginFrameSource;
 
-class YUVResourceMetadata;
-
 // The SkiaOutputSurface implementation. It is the output surface for
 // SkiaRenderer. It lives on the compositor thread, but it will post tasks
 // to the GPU thread for initializing. Currently, SkiaOutputSurfaceImpl
@@ -77,7 +75,8 @@
   sk_sp<SkImage> MakePromiseSkImage(ResourceMetadata metadata) override;
   sk_sp<SkImage> MakePromiseSkImageFromYUV(
       std::vector<ResourceMetadata> metadatas,
-      SkYUVColorSpace yuv_color_space) override;
+      SkYUVColorSpace yuv_color_space,
+      bool has_alpha) override;
   void SkiaSwapBuffers(OutputSurfaceFrame frame) override;
   SkCanvas* BeginPaintRenderPass(const RenderPassId& id,
                                  const gfx::Size& surface_size,
@@ -96,6 +95,7 @@
  private:
   template <class T>
   class PromiseTextureHelper;
+  class YUVAPromiseTextureHelper;
   void InitializeOnGpuThread(base::WaitableEvent* event);
   void RecreateRecorder();
   void DidSwapBuffersComplete(gpu::SwapBuffersCompleteParams params,
@@ -122,12 +122,6 @@
   // Sync tokens for resources which are used for the current frame.
   std::vector<gpu::SyncToken> resource_sync_tokens_;
 
-  // YUV resource metadatas for the current frame or the current render pass.
-  // They should be preprocessed for playing recorded frame into a surface.
-  // TODO(penghuang): Remove it when Skia supports drawing YUV textures
-  // directly.
-  std::vector<YUVResourceMetadata*> yuv_resource_metadatas_;
-
   // The task runner for running task on the client (compositor) thread.
   scoped_refptr<base::SingleThreadTaskRunner> client_thread_task_runner_;
 
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 ede77553..23145a6 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
@@ -39,20 +39,6 @@
 
 }  // namespace
 
-YUVResourceMetadata::YUVResourceMetadata(
-    std::vector<ResourceMetadata> metadatas,
-    SkYUVColorSpace yuv_color_space)
-    : metadatas_(std::move(metadatas)), yuv_color_space_(yuv_color_space) {
-  DCHECK(metadatas_.size() == 2 || metadatas_.size() == 3);
-}
-
-YUVResourceMetadata::YUVResourceMetadata(YUVResourceMetadata&& other) = default;
-
-YUVResourceMetadata::~YUVResourceMetadata() = default;
-
-YUVResourceMetadata& YUVResourceMetadata::operator=(
-    YUVResourceMetadata&& other) = default;
-
 SkiaOutputSurfaceImplOnGpu::SkiaOutputSurfaceImplOnGpu(
     GpuServiceImpl* gpu_service,
     gpu::SurfaceHandle surface_handle,
@@ -183,7 +169,6 @@
 
 void SkiaOutputSurfaceImplOnGpu::FinishPaintCurrentFrame(
     std::unique_ptr<SkDeferredDisplayList> ddl,
-    std::vector<YUVResourceMetadata*> yuv_resource_metadatas,
     uint64_t sync_fence_release) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   DCHECK(ddl);
@@ -195,7 +180,6 @@
     // TODO(penghuang): Handle the failure.
   }
 
-  PreprocessYUVResources(std::move(yuv_resource_metadatas));
   sk_surface_->draw(ddl.get());
   gr_context_->flush();
   sync_point_client_state_->ReleaseFenceSync(sync_fence_release);
@@ -240,7 +224,6 @@
 void SkiaOutputSurfaceImplOnGpu::FinishPaintRenderPass(
     RenderPassId id,
     std::unique_ptr<SkDeferredDisplayList> ddl,
-    std::vector<YUVResourceMetadata*> yuv_resource_metadatas,
     uint64_t sync_fence_release) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   DCHECK(ddl);
@@ -251,8 +234,6 @@
     // TODO(penghuang): Handle the failure.
   }
 
-  PreprocessYUVResources(std::move(yuv_resource_metadatas));
-
   auto& surface = offscreen_surfaces_[id];
   SkSurfaceCharacterization characterization;
   // TODO(penghuang): Using characterization != ddl->characterization(), when
@@ -304,7 +285,7 @@
       std::make_unique<CopyOutputSkBitmapResult>(copy_rect, bitmap));
 }
 
-void SkiaOutputSurfaceImplOnGpu::FullfillPromiseTexture(
+void SkiaOutputSurfaceImplOnGpu::FulfillPromiseTexture(
     const ResourceMetadata& metadata,
     GrBackendTexture* backend_texture) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
@@ -329,18 +310,7 @@
                        metadata.mip_mapped, texture_info);
 }
 
-void SkiaOutputSurfaceImplOnGpu::FullfillPromiseTexture(
-    const YUVResourceMetadata& yuv_metadata,
-    GrBackendTexture* backend_texture) {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-
-  if (yuv_metadata.image())
-    *backend_texture = yuv_metadata.image()->getBackendTexture(true);
-  DLOG_IF(ERROR, !backend_texture->isValid())
-      << "Failed to full fill the promise texture from yuv resources.";
-}
-
-void SkiaOutputSurfaceImplOnGpu::FullfillPromiseTexture(
+void SkiaOutputSurfaceImplOnGpu::FulfillPromiseTexture(
     const RenderPassId id,
     GrBackendTexture* backend_texture) {
   auto it = offscreen_surfaces_.find(id);
@@ -481,55 +451,6 @@
   }
 }
 
-void SkiaOutputSurfaceImplOnGpu::PreprocessYUVResources(
-    std::vector<YUVResourceMetadata*> yuv_resource_metadatas) {
-  if (gpu_service_->is_using_vulkan()) {
-    // TODO(https://crbug.com/838899): Use VkImage for video.
-    // NOTIMPLEMENTED();
-    return;
-  }
-  // Create SkImage for fullfilling YUV promise image, before drawing the ddl.
-  // TODO(penghuang): Remove the extra step when Skia supports drawing YUV
-  // textures directly.
-  auto* mailbox_manager = gpu_service_->mailbox_manager();
-  for (auto* yuv_metadata : yuv_resource_metadatas) {
-    const auto& metadatas = yuv_metadata->metadatas();
-    DCHECK(metadatas.size() == 2 || metadatas.size() == 3);
-    GrBackendTexture backend_textures[3];
-    size_t i = 0;
-    for (const auto& metadata : metadatas) {
-      auto* texture_base = mailbox_manager->ConsumeTexture(metadata.mailbox);
-      if (!texture_base)
-        break;
-      BindOrCopyTextureIfNecessary(texture_base);
-      GrGLTextureInfo texture_info;
-      texture_info.fTarget = texture_base->target();
-      texture_info.fID = texture_base->service_id();
-      texture_info.fFormat = *metadata.backend_format.getGLFormat();
-      backend_textures[i++] =
-          GrBackendTexture(metadata.size.width(), metadata.size.height(),
-                           GrMipMapped::kNo, texture_info);
-    }
-
-    if (i != metadatas.size())
-      continue;
-
-    sk_sp<SkImage> image;
-    if (metadatas.size() == 2) {
-      image = SkImage::MakeFromNV12TexturesCopy(
-          gr_context_, yuv_metadata->yuv_color_space(), backend_textures,
-          kTopLeft_GrSurfaceOrigin, nullptr /* image_color_space */);
-      DCHECK(image);
-    } else {
-      image = SkImage::MakeFromYUVTexturesCopy(
-          gr_context_, yuv_metadata->yuv_color_space(), backend_textures,
-          kTopLeft_GrSurfaceOrigin, nullptr /* image_color_space */);
-      DCHECK(image);
-    }
-    yuv_metadata->set_image(std::move(image));
-  }
-}
-
 void SkiaOutputSurfaceImplOnGpu::OnSwapBuffers() {
   uint64_t swap_id = swap_id_++;
   gfx::Size pixel_size(sk_surface_->width(), sk_surface_->height());
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 507ba3f0..ff24dfb 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
@@ -41,36 +41,6 @@
 
 class GpuServiceImpl;
 
-// Metadata for YUV promise SkImage.
-class YUVResourceMetadata {
- public:
-  YUVResourceMetadata(std::vector<ResourceMetadata> metadatas,
-                      SkYUVColorSpace yuv_color_space);
-  YUVResourceMetadata(YUVResourceMetadata&& other);
-  ~YUVResourceMetadata();
-  YUVResourceMetadata& operator=(YUVResourceMetadata&& other);
-
-  const std::vector<ResourceMetadata>& metadatas() const { return metadatas_; }
-  SkYUVColorSpace yuv_color_space() const { return yuv_color_space_; }
-  const sk_sp<SkImage> image() const { return image_; }
-  void set_image(sk_sp<SkImage> image) { image_ = image; }
-  const gfx::Size size() const { return metadatas_[0].size; }
-
- private:
-  // Metadatas for YUV planes.
-  std::vector<ResourceMetadata> metadatas_;
-
-  SkYUVColorSpace yuv_color_space_;
-
-  // The image copied from YUV textures, it is for fullfilling the promise
-  // image.
-  // TODO(penghuang): Remove it when Skia supports drawing YUV textures
-  // directly.
-  sk_sp<SkImage> image_;
-
-  DISALLOW_COPY_AND_ASSIGN(YUVResourceMetadata);
-};
-
 // The SkiaOutputSurface implementation running on the GPU thread. This class
 // should be created, used and destroyed on the GPU thread.
 class SkiaOutputSurfaceImplOnGpu : public gpu::ImageTransportSurfaceDelegate {
@@ -104,28 +74,23 @@
                base::WaitableEvent* event);
   void FinishPaintCurrentFrame(
       std::unique_ptr<SkDeferredDisplayList> ddl,
-      std::vector<YUVResourceMetadata*> yuv_resource_metadatas,
       uint64_t sync_fence_release);
   void SwapBuffers(OutputSurfaceFrame frame);
   void FinishPaintRenderPass(
       RenderPassId id,
       std::unique_ptr<SkDeferredDisplayList> ddl,
-      std::vector<YUVResourceMetadata*> yuv_resource_metadatas,
       uint64_t sync_fence_release);
   void RemoveRenderPassResource(std::vector<RenderPassId> ids);
   void CopyOutput(RenderPassId id,
                   const gfx::Rect& copy_rect,
                   std::unique_ptr<CopyOutputRequest> request);
 
-  // Fullfill callback for promise SkImage created from a resource.
-  void FullfillPromiseTexture(const ResourceMetadata& metadata,
-                              GrBackendTexture* backend_texture);
-  // Fullfill callback for promise SkImage created from YUV resources.
-  void FullfillPromiseTexture(const YUVResourceMetadata& metadata,
-                              GrBackendTexture* backend_texture);
-  // Fullfill callback for promise SkImage created from a render pass.
-  void FullfillPromiseTexture(const RenderPassId id,
-                              GrBackendTexture* backend_texture);
+  // Fulfill callback for promise SkImage created from a resource.
+  void FulfillPromiseTexture(const ResourceMetadata& metadata,
+                             GrBackendTexture* backend_texture);
+  // Fulfill callback for promise SkImage created from a render pass.
+  void FulfillPromiseTexture(const RenderPassId id,
+                             GrBackendTexture* backend_texture);
 
   sk_sp<GrContextThreadSafeProxy> GetGrContextThreadSafeProxy();
   const gl::GLVersionInfo* gl_version_info() const { return gl_version_info_; }
@@ -148,8 +113,6 @@
   void InitializeForVulkan();
 
   void BindOrCopyTextureIfNecessary(gpu::TextureBase* texture_base);
-  void PreprocessYUVResources(
-      std::vector<YUVResourceMetadata*> yuv_resource_metadatas);
 
   // Generage the next swap ID and push it to our pending swap ID queues.
   void OnSwapBuffers();