Reland of cc: Add mailbox support to ResourceProvider write locks. (patchset #1 id:1 of https://codereview.chromium.org/2106503002/ )

Original issue's description:
> Revert of cc: Add mailbox support to ResourceProvider write locks. (patchset #5 id:70001 of https://codereview.chromium.org/2081883002/ )
>
> Reason for revert:
> Causing canvas crashes - bug 623101
>
> Original issue's description:
> > Reland of cc: Add mailbox support to ResourceProvider write locks. (patchset #24 id:460001 of https://codereview.chromium.org/1951193002/ )
> >
> > Original issue's description:
> > > cc: Add mailbox support to ResourceProvider write locks.
> > >
> > > This adds support for mailboxes to ScopedWriteLockGL. Using the mailbox
> > > requires using ScopedTextureProvider/ScopedSkSurfaceProvider which
> > > ensures that the texture id for the mailbox is destroyed after use on
> > > the worker context.
> > >
> > > This CL also includes the following cleanup:
> > > 1. ResourceProvider locks don't keep resource pointers around.
> > > 2. ScopedSamplerGL does not inherit from ScopedReadLockGL.
> > > 3. GpuRasterizer is folded back into GpuRasterBufferProvider.
> > > 4. TileTaskManager does not own RasterBufferProvider.
> > >
> > > BUG=525259
> > > R=piman@chromium.org
> > > CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel
> > >
> > > Committed: https://crrev.com/5fa5dbdf25bbec21b84f752d3f0642cd184467e2
> > > Committed: https://crrev.com/3b0f0b8d3db0a9f66864d5b7da87c82f49e74a29
> > > Cr-Original-Commit-Position: refs/heads/master@{#398204}
> > > Cr-Commit-Position: refs/heads/master@{#399983}
> >
> > R=piman@chromium.org
> > BUG=525259, 621422, 621130
> > CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel
> >
> > Committed: https://crrev.com/b3071e4aabd0cb1f29cd624e77eb5f40722be965
> > Cr-Commit-Position: refs/heads/master@{#401717}
>
> TBR=piman@chromium.org
> # Not skipping CQ checks because original CL landed more than 1 days ago.
> BUG=525259, 621422, 621130
>
> Committed: https://crrev.com/4d27a5a3c38c34bfa34e9937ef8e3ea3831d2194
> Cr-Commit-Position: refs/heads/master@{#402290}

TBR=piman@chromium.org
BUG=525259, 621422, 621130

Review-Url: https://codereview.chromium.org/2101043002
Cr-Commit-Position: refs/heads/master@{#402345}
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index 171182b..2064895 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -358,8 +358,6 @@
     "raster/bitmap_raster_buffer_provider.h",
     "raster/gpu_raster_buffer_provider.cc",
     "raster/gpu_raster_buffer_provider.h",
-    "raster/gpu_rasterizer.cc",
-    "raster/gpu_rasterizer.h",
     "raster/one_copy_raster_buffer_provider.cc",
     "raster/one_copy_raster_buffer_provider.h",
     "raster/raster_buffer.cc",
diff --git a/cc/cc.gyp b/cc/cc.gyp
index 9d3a099..fe36578 100644
--- a/cc/cc.gyp
+++ b/cc/cc.gyp
@@ -419,8 +419,6 @@
         'raster/bitmap_raster_buffer_provider.h',
         'raster/gpu_raster_buffer_provider.cc',
         'raster/gpu_raster_buffer_provider.h',
-        'raster/gpu_rasterizer.cc',
-        'raster/gpu_rasterizer.h',
         'raster/one_copy_raster_buffer_provider.cc',
         'raster/one_copy_raster_buffer_provider.h',
         'raster/raster_buffer.cc',
diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc
index 38f6119..1f52d92 100644
--- a/cc/output/gl_renderer.cc
+++ b/cc/output/gl_renderer.cc
@@ -596,8 +596,8 @@
   GrGLTextureInfo texture_info;
   texture_info.fTarget = lock.target();
   texture_info.fID = lock.texture_id();
-  backend_texture_description.fWidth = lock.texture_size().width();
-  backend_texture_description.fHeight = lock.texture_size().height();
+  backend_texture_description.fWidth = lock.size().width();
+  backend_texture_description.fHeight = lock.size().height();
   backend_texture_description.fConfig = kSkia8888_GrPixelConfig;
   backend_texture_description.fTextureHandle =
       skia::GrGLTextureInfoToGrBackendObject(texture_info);
@@ -831,8 +831,8 @@
       bounding_rect.size(), ResourceProvider::TEXTURE_HINT_DEFAULT,
       resource_provider_->best_texture_format());
   {
-    ResourceProvider::ScopedWriteLockGL lock(resource_provider_,
-                                             device_background_texture->id());
+    ResourceProvider::ScopedWriteLockGL lock(
+        resource_provider_, device_background_texture->id(), false);
     GetFramebufferTexture(lock.texture_id(), bounding_rect);
   }
   return device_background_texture;
@@ -2505,7 +2505,7 @@
     uv_transform = UVTransform(quad);
   if (sampler == SAMPLER_TYPE_2D_RECT) {
     // Un-normalize the texture coordiantes for rectangle targets.
-    gfx::Size texture_size = lock.texture_size();
+    gfx::Size texture_size = lock.size();
     uv_transform.data[0] *= texture_size.width();
     uv_transform.data[2] *= texture_size.width();
     uv_transform.data[1] *= texture_size.height();
@@ -3057,7 +3057,7 @@
   gl_->BindFramebuffer(GL_FRAMEBUFFER, offscreen_framebuffer_id_);
   current_framebuffer_lock_ =
       base::WrapUnique(new ResourceProvider::ScopedWriteLockGL(
-          resource_provider_, texture->id()));
+          resource_provider_, texture->id(), false));
   current_framebuffer_format_ = texture->format();
   unsigned texture_id = current_framebuffer_lock_->texture_id();
   gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
diff --git a/cc/raster/gpu_raster_buffer_provider.cc b/cc/raster/gpu_raster_buffer_provider.cc
index 6e5b4c4..12fb55a1 100644
--- a/cc/raster/gpu_raster_buffer_provider.cc
+++ b/cc/raster/gpu_raster_buffer_provider.cc
@@ -12,7 +12,6 @@
 #include "base/memory/ptr_util.h"
 #include "base/trace_event/trace_event.h"
 #include "cc/playback/raster_source.h"
-#include "cc/raster/gpu_rasterizer.h"
 #include "cc/raster/scoped_gpu_raster.h"
 #include "cc/resources/resource.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
@@ -24,89 +23,121 @@
 namespace cc {
 namespace {
 
-class RasterBufferImpl : public RasterBuffer {
- public:
-  RasterBufferImpl(GpuRasterizer* rasterizer,
-                   const Resource* resource,
-                   uint64_t resource_content_id,
-                   uint64_t previous_content_id)
-      : rasterizer_(rasterizer),
-        lock_(rasterizer->resource_provider(), resource->id()),
-        resource_has_previous_content_(
-            resource_content_id && resource_content_id == previous_content_id) {
+static sk_sp<SkPicture> PlaybackToPicture(
+    const RasterSource* raster_source,
+    bool resource_has_previous_content,
+    const gfx::Size& resource_size,
+    const gfx::Rect& raster_full_rect,
+    const gfx::Rect& raster_dirty_rect,
+    float scale,
+    const RasterSource::PlaybackSettings& playback_settings) {
+  // GPU raster doesn't do low res tiles, so should always include images.
+  DCHECK(!playback_settings.skip_images);
+
+  gfx::Rect playback_rect = raster_full_rect;
+  if (resource_has_previous_content) {
+    playback_rect.Intersect(raster_dirty_rect);
   }
+  DCHECK(!playback_rect.IsEmpty())
+      << "Why are we rastering a tile that's not dirty?";
 
-  // Overridden from RasterBuffer:
-  void Playback(
-      const RasterSource* raster_source,
-      const gfx::Rect& raster_full_rect,
-      const gfx::Rect& raster_dirty_rect,
-      uint64_t new_content_id,
-      float scale,
-      const RasterSource::PlaybackSettings& playback_settings) override {
-    TRACE_EVENT0("cc", "GpuRasterBuffer::Playback");
-    // GPU raster doesn't do low res tiles, so should always include images.
-    DCHECK(!playback_settings.skip_images);
+  // Play back raster_source into temp SkPicture.
+  SkPictureRecorder recorder;
+  const int flags = SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag;
+  sk_sp<SkCanvas> canvas = sk_ref_sp(recorder.beginRecording(
+      resource_size.width(), resource_size.height(), NULL, flags));
+  canvas->save();
+  raster_source->PlaybackToCanvas(canvas.get(), raster_full_rect, playback_rect,
+                                  scale, playback_settings);
+  canvas->restore();
+  return recorder.finishRecordingAsPicture();
+}
 
-    ContextProvider::ScopedContextLock scoped_context(
-        rasterizer_->worker_context_provider());
+static void RasterizePicture(SkPicture* picture,
+                             ContextProvider* context_provider,
+                             ResourceProvider::ScopedWriteLockGL* resource_lock,
+                             bool async_worker_context_enabled,
+                             bool use_distance_field_text,
+                             bool can_use_lcd_text,
+                             int msaa_sample_count) {
+  ScopedGpuRaster gpu_raster(context_provider);
 
-    gfx::Rect playback_rect = raster_full_rect;
-    if (resource_has_previous_content_) {
-      playback_rect.Intersect(raster_dirty_rect);
-    }
-    DCHECK(!playback_rect.IsEmpty())
-        << "Why are we rastering a tile that's not dirty?";
+  ResourceProvider::ScopedSkSurfaceProvider scoped_surface(
+      context_provider, resource_lock, async_worker_context_enabled,
+      use_distance_field_text, can_use_lcd_text, msaa_sample_count);
+  SkSurface* sk_surface = scoped_surface.sk_surface();
+  // Allocating an SkSurface will fail after a lost context.  Pretend we
+  // rasterized, as the contents of the resource don't matter anymore.
+  if (!sk_surface)
+    return;
 
-    // TODO(danakj): Implement partial raster with raster_dirty_rect.
-    // Rasterize source into resource.
-    rasterizer_->RasterizeSource(&lock_, raster_source, raster_full_rect,
-                                 playback_rect, scale, playback_settings);
-
-    gpu::gles2::GLES2Interface* gl = scoped_context.ContextGL();
-    const uint64_t fence_sync = gl->InsertFenceSyncCHROMIUM();
-
-    // Barrier to sync worker context output to cc context.
-    gl->OrderingBarrierCHROMIUM();
-
-    // Generate sync token after the barrier for cross context synchronization.
-    gpu::SyncToken sync_token;
-    gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData());
-    lock_.UpdateResourceSyncToken(sync_token);
-  }
-
- private:
-  GpuRasterizer* rasterizer_;
-  ResourceProvider::ScopedWriteLockGr lock_;
-  bool resource_has_previous_content_;
-
-  DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl);
-};
+  SkMultiPictureDraw multi_picture_draw;
+  multi_picture_draw.add(sk_surface->getCanvas(), picture);
+  multi_picture_draw.draw(false);
+}
 
 }  // namespace
 
+GpuRasterBufferProvider::RasterBufferImpl::RasterBufferImpl(
+    GpuRasterBufferProvider* client,
+    ResourceProvider* resource_provider,
+    ResourceId resource_id,
+    bool async_worker_context_enabled,
+    bool resource_has_previous_content)
+    : client_(client),
+      lock_(resource_provider, resource_id, async_worker_context_enabled),
+      resource_has_previous_content_(resource_has_previous_content) {
+  client_->pending_raster_buffers_.insert(this);
+}
+
+GpuRasterBufferProvider::RasterBufferImpl::~RasterBufferImpl() {
+  client_->pending_raster_buffers_.erase(this);
+}
+
+void GpuRasterBufferProvider::RasterBufferImpl::Playback(
+    const RasterSource* raster_source,
+    const gfx::Rect& raster_full_rect,
+    const gfx::Rect& raster_dirty_rect,
+    uint64_t new_content_id,
+    float scale,
+    const RasterSource::PlaybackSettings& playback_settings) {
+  TRACE_EVENT0("cc", "GpuRasterBuffer::Playback");
+  client_->PlaybackOnWorkerThread(&lock_, sync_token_,
+                                  resource_has_previous_content_, raster_source,
+                                  raster_full_rect, raster_dirty_rect,
+                                  new_content_id, scale, playback_settings);
+}
+
 GpuRasterBufferProvider::GpuRasterBufferProvider(
     ContextProvider* compositor_context_provider,
     ContextProvider* worker_context_provider,
     ResourceProvider* resource_provider,
     bool use_distance_field_text,
-    int gpu_rasterization_msaa_sample_count)
+    int gpu_rasterization_msaa_sample_count,
+    bool async_worker_context_enabled)
     : compositor_context_provider_(compositor_context_provider),
-      rasterizer_(new GpuRasterizer(worker_context_provider,
-                                    resource_provider,
-                                    use_distance_field_text,
-                                    gpu_rasterization_msaa_sample_count)) {
-  DCHECK(compositor_context_provider_);
+      worker_context_provider_(worker_context_provider),
+      resource_provider_(resource_provider),
+      use_distance_field_text_(use_distance_field_text),
+      msaa_sample_count_(gpu_rasterization_msaa_sample_count),
+      async_worker_context_enabled_(async_worker_context_enabled) {
+  DCHECK(compositor_context_provider);
+  DCHECK(worker_context_provider);
 }
 
-GpuRasterBufferProvider::~GpuRasterBufferProvider() {}
+GpuRasterBufferProvider::~GpuRasterBufferProvider() {
+  DCHECK(pending_raster_buffers_.empty());
+}
 
 std::unique_ptr<RasterBuffer> GpuRasterBufferProvider::AcquireBufferForRaster(
     const Resource* resource,
     uint64_t resource_content_id,
     uint64_t previous_content_id) {
-  return std::unique_ptr<RasterBuffer>(new RasterBufferImpl(
-      rasterizer_.get(), resource, resource_content_id, previous_content_id));
+  bool resource_has_previous_content =
+      resource_content_id && resource_content_id == previous_content_id;
+  return base::WrapUnique(new RasterBufferImpl(
+      this, resource_provider_, resource->id(), async_worker_context_enabled_,
+      resource_has_previous_content));
 }
 
 void GpuRasterBufferProvider::ReleaseBufferForRaster(
@@ -116,12 +147,29 @@
 
 void GpuRasterBufferProvider::OrderingBarrier() {
   TRACE_EVENT0("cc", "GpuRasterBufferProvider::OrderingBarrier");
-  compositor_context_provider_->ContextGL()->OrderingBarrierCHROMIUM();
+
+  gpu::gles2::GLES2Interface* gl = compositor_context_provider_->ContextGL();
+  if (async_worker_context_enabled_) {
+    GLuint64 fence = gl->InsertFenceSyncCHROMIUM();
+    gl->OrderingBarrierCHROMIUM();
+
+    gpu::SyncToken sync_token;
+    gl->GenUnverifiedSyncTokenCHROMIUM(fence, sync_token.GetData());
+
+    DCHECK(sync_token.HasData() ||
+           gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR);
+
+    for (RasterBufferImpl* buffer : pending_raster_buffers_)
+      buffer->set_sync_token(sync_token);
+  } else {
+    gl->OrderingBarrierCHROMIUM();
+  }
+  pending_raster_buffers_.clear();
 }
 
 ResourceFormat GpuRasterBufferProvider::GetResourceFormat(
     bool must_support_alpha) const {
-  return rasterizer_->resource_provider()->best_render_buffer_format();
+  return resource_provider_->best_render_buffer_format();
 }
 
 bool GpuRasterBufferProvider::GetResourceRequiresSwizzle(
@@ -130,6 +178,56 @@
   return false;
 }
 
-void GpuRasterBufferProvider::Shutdown() {}
+void GpuRasterBufferProvider::Shutdown() {
+  pending_raster_buffers_.clear();
+}
+
+void GpuRasterBufferProvider::PlaybackOnWorkerThread(
+    ResourceProvider::ScopedWriteLockGL* resource_lock,
+    const gpu::SyncToken& sync_token,
+    bool resource_has_previous_content,
+    const RasterSource* raster_source,
+    const gfx::Rect& raster_full_rect,
+    const gfx::Rect& raster_dirty_rect,
+    uint64_t new_content_id,
+    float scale,
+    const RasterSource::PlaybackSettings& playback_settings) {
+  ContextProvider::ScopedContextLock scoped_context(worker_context_provider_);
+  gpu::gles2::GLES2Interface* gl = scoped_context.ContextGL();
+  DCHECK(gl);
+
+  if (async_worker_context_enabled_) {
+    // Early out if sync token is invalid. This happens if the compositor
+    // context was lost before ScheduleTasks was called.
+    if (!sync_token.HasData())
+      return;
+    // Synchronize with compositor.
+    gl->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
+  }
+
+  sk_sp<SkPicture> picture = PlaybackToPicture(
+      raster_source, resource_has_previous_content, resource_lock->size(),
+      raster_full_rect, raster_dirty_rect, scale, playback_settings);
+
+  // Turn on distance fields for layers that have ever animated.
+  bool use_distance_field_text =
+      use_distance_field_text_ ||
+      raster_source->ShouldAttemptToUseDistanceFieldText();
+
+  RasterizePicture(picture.get(), worker_context_provider_, resource_lock,
+                   async_worker_context_enabled_, use_distance_field_text,
+                   raster_source->CanUseLCDText(), msaa_sample_count_);
+
+  const uint64_t fence_sync = gl->InsertFenceSyncCHROMIUM();
+
+  // Barrier to sync worker context output to cc context.
+  gl->OrderingBarrierCHROMIUM();
+
+  // Generate sync token after the barrier for cross context synchronization.
+  gpu::SyncToken resource_sync_token;
+  gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, resource_sync_token.GetData());
+  resource_lock->set_sync_token(resource_sync_token);
+  resource_lock->set_synchronized(!async_worker_context_enabled_);
+}
 
 }  // namespace cc
diff --git a/cc/raster/gpu_raster_buffer_provider.h b/cc/raster/gpu_raster_buffer_provider.h
index b6aea83..ef69754 100644
--- a/cc/raster/gpu_raster_buffer_provider.h
+++ b/cc/raster/gpu_raster_buffer_provider.h
@@ -9,11 +9,11 @@
 
 #include "base/macros.h"
 #include "cc/raster/raster_buffer_provider.h"
+#include "cc/resources/resource_provider.h"
+#include "gpu/command_buffer/common/sync_token.h"
 
 namespace cc {
 class ContextProvider;
-class GpuRasterizer;
-class ResourceProvider;
 
 class CC_EXPORT GpuRasterBufferProvider : public RasterBufferProvider {
  public:
@@ -21,7 +21,8 @@
                           ContextProvider* worker_context_provider,
                           ResourceProvider* resource_provider,
                           bool use_distance_field_text,
-                          int gpu_rasterization_msaa_sample_count);
+                          int gpu_rasterization_msaa_sample_count,
+                          bool async_worker_context_enabled);
   ~GpuRasterBufferProvider() override;
 
   // Overridden from RasterBufferProvider:
@@ -35,9 +36,58 @@
   bool GetResourceRequiresSwizzle(bool must_support_alpha) const override;
   void Shutdown() override;
 
+  void PlaybackOnWorkerThread(
+      ResourceProvider::ScopedWriteLockGL* resource_lock,
+      const gpu::SyncToken& sync_token,
+      bool resource_has_previous_content,
+      const RasterSource* raster_source,
+      const gfx::Rect& raster_full_rect,
+      const gfx::Rect& raster_dirty_rect,
+      uint64_t new_content_id,
+      float scale,
+      const RasterSource::PlaybackSettings& playback_settings);
+
  private:
+  class RasterBufferImpl : public RasterBuffer {
+   public:
+    RasterBufferImpl(GpuRasterBufferProvider* client,
+                     ResourceProvider* resource_provider,
+                     ResourceId resource_id,
+                     bool async_worker_context_enabled,
+                     bool resource_has_previous_content);
+    ~RasterBufferImpl() override;
+
+    // Overridden from RasterBuffer:
+    void Playback(
+        const RasterSource* raster_source,
+        const gfx::Rect& raster_full_rect,
+        const gfx::Rect& raster_dirty_rect,
+        uint64_t new_content_id,
+        float scale,
+        const RasterSource::PlaybackSettings& playback_settings) override;
+
+    void set_sync_token(const gpu::SyncToken& sync_token) {
+      sync_token_ = sync_token;
+    }
+
+   private:
+    GpuRasterBufferProvider* const client_;
+    ResourceProvider::ScopedWriteLockGL lock_;
+    const bool resource_has_previous_content_;
+
+    gpu::SyncToken sync_token_;
+
+    DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl);
+  };
+
   ContextProvider* const compositor_context_provider_;
-  std::unique_ptr<GpuRasterizer> rasterizer_;
+  ContextProvider* const worker_context_provider_;
+  ResourceProvider* const resource_provider_;
+  const bool use_distance_field_text_;
+  const int msaa_sample_count_;
+  const bool async_worker_context_enabled_;
+
+  std::set<RasterBufferImpl*> pending_raster_buffers_;
 
   DISALLOW_COPY_AND_ASSIGN(GpuRasterBufferProvider);
 };
diff --git a/cc/raster/gpu_rasterizer.cc b/cc/raster/gpu_rasterizer.cc
deleted file mode 100644
index 0d08507e..0000000
--- a/cc/raster/gpu_rasterizer.cc
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2015 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 "cc/raster/gpu_rasterizer.h"
-
-#include <algorithm>
-
-#include "base/bind.h"
-#include "base/metrics/histogram.h"
-#include "base/trace_event/trace_event.h"
-#include "cc/debug/devtools_instrumentation.h"
-#include "cc/debug/frame_viewer_instrumentation.h"
-#include "cc/output/context_provider.h"
-#include "cc/playback/raster_source.h"
-#include "cc/raster/raster_buffer.h"
-#include "cc/raster/scoped_gpu_raster.h"
-#include "cc/resources/resource.h"
-#include "cc/tiles/tile_manager.h"
-#include "gpu/command_buffer/client/gles2_interface.h"
-#include "third_party/skia/include/core/SkMultiPictureDraw.h"
-#include "third_party/skia/include/core/SkPictureRecorder.h"
-#include "third_party/skia/include/core/SkSurface.h"
-#include "third_party/skia/include/gpu/GrContext.h"
-
-namespace cc {
-
-GpuRasterizer::GpuRasterizer(ContextProvider* worker_context_provider,
-                             ResourceProvider* resource_provider,
-                             bool use_distance_field_text,
-                             int msaa_sample_count)
-    : worker_context_provider_(worker_context_provider),
-      resource_provider_(resource_provider),
-      use_distance_field_text_(use_distance_field_text),
-      msaa_sample_count_(msaa_sample_count) {
-  DCHECK(worker_context_provider_);
-}
-
-GpuRasterizer::~GpuRasterizer() {}
-
-void GpuRasterizer::RasterizeSource(
-    ResourceProvider::ScopedWriteLockGr* write_lock,
-    const RasterSource* raster_source,
-    const gfx::Rect& raster_full_rect,
-    const gfx::Rect& playback_rect,
-    float scale,
-    const RasterSource::PlaybackSettings& playback_settings) {
-  // Play back raster_source into temp SkPicture.
-  SkPictureRecorder recorder;
-  const gfx::Size size = write_lock->GetResourceSize();
-  const int flags = SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag;
-  sk_sp<SkCanvas> canvas = sk_ref_sp(
-      recorder.beginRecording(size.width(), size.height(), NULL, flags));
-  canvas->save();
-  raster_source->PlaybackToCanvas(canvas.get(), raster_full_rect, playback_rect,
-                                  scale, playback_settings);
-  canvas->restore();
-  sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture();
-
-  // Turn on distance fields for layers that have ever animated.
-  bool use_distance_field_text =
-      use_distance_field_text_ ||
-      raster_source->ShouldAttemptToUseDistanceFieldText();
-
-  // Playback picture into resource.
-  {
-    ScopedGpuRaster gpu_raster(worker_context_provider_);
-    write_lock->InitSkSurface(
-        worker_context_provider_->GrContext(), use_distance_field_text,
-        raster_source->CanUseLCDText(), msaa_sample_count_);
-
-    SkSurface* sk_surface = write_lock->sk_surface();
-
-    // Allocating an SkSurface will fail after a lost context.  Pretend we
-    // rasterized, as the contents of the resource don't matter anymore.
-    if (!sk_surface)
-      return;
-
-    SkMultiPictureDraw multi_picture_draw;
-    multi_picture_draw.add(sk_surface->getCanvas(), picture.get());
-    multi_picture_draw.draw(false);
-    write_lock->ReleaseSkSurface();
-  }
-}
-
-}  // namespace cc
diff --git a/cc/raster/gpu_rasterizer.h b/cc/raster/gpu_rasterizer.h
deleted file mode 100644
index 592dea7..0000000
--- a/cc/raster/gpu_rasterizer.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef CC_RASTER_GPU_RASTERIZER_H_
-#define CC_RASTER_GPU_RASTERIZER_H_
-
-#include <vector>
-
-#include "base/macros.h"
-#include "cc/base/cc_export.h"
-#include "cc/playback/raster_source.h"
-#include "cc/resources/resource_pool.h"
-#include "cc/tiles/tile.h"
-#include "third_party/skia/include/core/SkMultiPictureDraw.h"
-
-namespace cc {
-
-class ContextProvider;
-class RasterSource;
-class ResourceProvider;
-
-class CC_EXPORT GpuRasterizer {
- public:
-  ~GpuRasterizer();
-
-  void RasterizeSource(ResourceProvider::ScopedWriteLockGr* write_lock,
-                       const RasterSource* raster_source,
-                       const gfx::Rect& raster_full_rect,
-                       const gfx::Rect& playback_rect,
-                       float scale,
-                       const RasterSource::PlaybackSettings& playback_settings);
-
-  ResourceProvider* resource_provider() const { return resource_provider_; }
-  ContextProvider* worker_context_provider() const {
-    return worker_context_provider_;
-  }
-
- private:
-  GpuRasterizer(ContextProvider* worker_context_provider,
-                ResourceProvider* resource_provider,
-                bool use_distance_filed_text,
-                int msaa_sample_count);
-
-  ContextProvider* worker_context_provider_;
-  ResourceProvider* resource_provider_;
-
-  bool use_distance_field_text_;
-  int msaa_sample_count_;
-
-  friend class GpuRasterBufferProvider;
-  DISALLOW_COPY_AND_ASSIGN(GpuRasterizer);
-};
-
-}  // namespace cc
-
-#endif  // CC_RASTER_GPU_RASTERIZER_H_
diff --git a/cc/raster/one_copy_raster_buffer_provider.cc b/cc/raster/one_copy_raster_buffer_provider.cc
index f0f95ae..3c7d066 100644
--- a/cc/raster/one_copy_raster_buffer_provider.cc
+++ b/cc/raster/one_copy_raster_buffer_provider.cc
@@ -24,49 +24,43 @@
 namespace cc {
 namespace {
 
-class RasterBufferImpl : public RasterBuffer {
- public:
-  RasterBufferImpl(OneCopyRasterBufferProvider* worker_pool,
-                   ResourceProvider* resource_provider,
-                   ResourceFormat resource_format,
-                   const Resource* resource,
-                   uint64_t previous_content_id)
-      : worker_pool_(worker_pool),
-        resource_(resource),
-        lock_(resource_provider, resource->id()),
-        previous_content_id_(previous_content_id) {}
-
-  ~RasterBufferImpl() override {}
-
-  // Overridden from RasterBuffer:
-  void Playback(
-      const RasterSource* raster_source,
-      const gfx::Rect& raster_full_rect,
-      const gfx::Rect& raster_dirty_rect,
-      uint64_t new_content_id,
-      float scale,
-      const RasterSource::PlaybackSettings& playback_settings) override {
-    TRACE_EVENT0("cc", "OneCopyRasterBuffer::Playback");
-    worker_pool_->PlaybackAndCopyOnWorkerThread(
-        resource_, &lock_, raster_source, raster_full_rect, raster_dirty_rect,
-        scale, playback_settings, previous_content_id_, new_content_id);
-  }
-
- private:
-  OneCopyRasterBufferProvider* worker_pool_;
-  const Resource* resource_;
-  ResourceProvider::ScopedWriteLockGL lock_;
-  uint64_t previous_content_id_;
-
-  DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl);
-};
-
 // 4MiB is the size of 4 512x512 tiles, which has proven to be a good
 // default batch size for copy operations.
 const int kMaxBytesPerCopyOperation = 1024 * 1024 * 4;
 
 }  // namespace
 
+OneCopyRasterBufferProvider::RasterBufferImpl::RasterBufferImpl(
+    OneCopyRasterBufferProvider* client,
+    ResourceProvider* resource_provider,
+    const Resource* resource,
+    uint64_t previous_content_id,
+    bool async_worker_context_enabled)
+    : client_(client),
+      resource_(resource),
+      lock_(resource_provider, resource->id(), async_worker_context_enabled),
+      previous_content_id_(previous_content_id) {
+  client_->pending_raster_buffers_.insert(this);
+}
+
+OneCopyRasterBufferProvider::RasterBufferImpl::~RasterBufferImpl() {
+  client_->pending_raster_buffers_.erase(this);
+}
+
+void OneCopyRasterBufferProvider::RasterBufferImpl::Playback(
+    const RasterSource* raster_source,
+    const gfx::Rect& raster_full_rect,
+    const gfx::Rect& raster_dirty_rect,
+    uint64_t new_content_id,
+    float scale,
+    const RasterSource::PlaybackSettings& playback_settings) {
+  TRACE_EVENT0("cc", "OneCopyRasterBuffer::Playback");
+  client_->PlaybackAndCopyOnWorkerThread(
+      resource_, &lock_, sync_token_, raster_source, raster_full_rect,
+      raster_dirty_rect, scale, playback_settings, previous_content_id_,
+      new_content_id);
+}
+
 OneCopyRasterBufferProvider::OneCopyRasterBufferProvider(
     base::SequencedTaskRunner* task_runner,
     ContextProvider* compositor_context_provider,
@@ -75,7 +69,8 @@
     int max_copy_texture_chromium_size,
     bool use_partial_raster,
     int max_staging_buffer_usage_in_bytes,
-    ResourceFormat preferred_tile_format)
+    ResourceFormat preferred_tile_format,
+    bool async_worker_context_enabled)
     : compositor_context_provider_(compositor_context_provider),
       worker_context_provider_(worker_context_provider),
       resource_provider_(resource_provider),
@@ -91,12 +86,15 @@
                     worker_context_provider,
                     resource_provider,
                     use_partial_raster,
-                    max_staging_buffer_usage_in_bytes) {
-  DCHECK(compositor_context_provider_);
+                    max_staging_buffer_usage_in_bytes),
+      async_worker_context_enabled_(async_worker_context_enabled) {
+  DCHECK(compositor_context_provider);
   DCHECK(worker_context_provider);
 }
 
-OneCopyRasterBufferProvider::~OneCopyRasterBufferProvider() {}
+OneCopyRasterBufferProvider::~OneCopyRasterBufferProvider() {
+  DCHECK(pending_raster_buffers_.empty());
+}
 
 std::unique_ptr<RasterBuffer>
 OneCopyRasterBufferProvider::AcquireBufferForRaster(
@@ -105,9 +103,9 @@
     uint64_t previous_content_id) {
   // TODO(danakj): If resource_content_id != 0, we only need to copy/upload
   // the dirty rect.
-  return base::WrapUnique<RasterBuffer>(
-      new RasterBufferImpl(this, resource_provider_, resource->format(),
-                           resource, previous_content_id));
+  return base::WrapUnique(new RasterBufferImpl(this, resource_provider_,
+                                               resource, previous_content_id,
+                                               async_worker_context_enabled_));
 }
 
 void OneCopyRasterBufferProvider::ReleaseBufferForRaster(
@@ -117,7 +115,24 @@
 
 void OneCopyRasterBufferProvider::OrderingBarrier() {
   TRACE_EVENT0("cc", "OneCopyRasterBufferProvider::OrderingBarrier");
-  compositor_context_provider_->ContextGL()->OrderingBarrierCHROMIUM();
+
+  gpu::gles2::GLES2Interface* gl = compositor_context_provider_->ContextGL();
+  if (async_worker_context_enabled_) {
+    GLuint64 fence = gl->InsertFenceSyncCHROMIUM();
+    gl->OrderingBarrierCHROMIUM();
+
+    gpu::SyncToken sync_token;
+    gl->GenUnverifiedSyncTokenCHROMIUM(fence, sync_token.GetData());
+
+    DCHECK(sync_token.HasData() ||
+           gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR);
+
+    for (RasterBufferImpl* buffer : pending_raster_buffers_)
+      buffer->set_sync_token(sync_token);
+  } else {
+    gl->OrderingBarrierCHROMIUM();
+  }
+  pending_raster_buffers_.clear();
 }
 
 ResourceFormat OneCopyRasterBufferProvider::GetResourceFormat(
@@ -138,11 +153,13 @@
 
 void OneCopyRasterBufferProvider::Shutdown() {
   staging_pool_.Shutdown();
+  pending_raster_buffers_.clear();
 }
 
 void OneCopyRasterBufferProvider::PlaybackAndCopyOnWorkerThread(
     const Resource* resource,
     ResourceProvider::ScopedWriteLockGL* resource_lock,
+    const gpu::SyncToken& sync_token,
     const RasterSource* raster_source,
     const gfx::Rect& raster_full_rect,
     const gfx::Rect& raster_dirty_rect,
@@ -150,6 +167,18 @@
     const RasterSource::PlaybackSettings& playback_settings,
     uint64_t previous_content_id,
     uint64_t new_content_id) {
+  if (async_worker_context_enabled_) {
+    // Early out if sync token is invalid. This happens if the compositor
+    // context was lost before ScheduleTasks was called.
+    if (!sync_token.HasData())
+      return;
+    ContextProvider::ScopedContextLock scoped_context(worker_context_provider_);
+    gpu::gles2::GLES2Interface* gl = scoped_context.ContextGL();
+    DCHECK(gl);
+    // Synchronize with compositor.
+    gl->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
+  }
+
   std::unique_ptr<StagingBuffer> staging_buffer =
       staging_pool_.AcquireStagingBuffer(resource, previous_content_id);
 
@@ -158,7 +187,7 @@
                           playback_settings, previous_content_id,
                           new_content_id);
 
-  CopyOnWorkerThread(staging_buffer.get(), resource, resource_lock,
+  CopyOnWorkerThread(staging_buffer.get(), resource_lock, sync_token,
                      raster_source, previous_content_id, new_content_id);
 
   staging_pool_.ReleaseStagingBuffer(std::move(staging_buffer));
@@ -217,117 +246,118 @@
 
 void OneCopyRasterBufferProvider::CopyOnWorkerThread(
     StagingBuffer* staging_buffer,
-    const Resource* resource,
     ResourceProvider::ScopedWriteLockGL* resource_lock,
+    const gpu::SyncToken& sync_token,
     const RasterSource* raster_source,
     uint64_t previous_content_id,
     uint64_t new_content_id) {
-  {
-    ContextProvider::ScopedContextLock scoped_context(worker_context_provider_);
+  ContextProvider::ScopedContextLock scoped_context(worker_context_provider_);
+  gpu::gles2::GLES2Interface* gl = scoped_context.ContextGL();
+  DCHECK(gl);
 
-    gpu::gles2::GLES2Interface* gl = scoped_context.ContextGL();
-    DCHECK(gl);
+  // Create texture after synchronizing with compositor.
+  ResourceProvider::ScopedTextureProvider scoped_texture(
+      gl, resource_lock, async_worker_context_enabled_);
 
-    unsigned image_target =
-        resource_provider_->GetImageTextureTarget(resource->format());
+  unsigned resource_texture_id = scoped_texture.texture_id();
+  unsigned image_target =
+      resource_provider_->GetImageTextureTarget(resource_lock->format());
 
-    // Create and bind staging texture.
-    if (!staging_buffer->texture_id) {
-      gl->GenTextures(1, &staging_buffer->texture_id);
-      gl->BindTexture(image_target, staging_buffer->texture_id);
-      gl->TexParameteri(image_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-      gl->TexParameteri(image_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-      gl->TexParameteri(image_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-      gl->TexParameteri(image_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-    } else {
-      gl->BindTexture(image_target, staging_buffer->texture_id);
-    }
+  // Create and bind staging texture.
+  if (!staging_buffer->texture_id) {
+    gl->GenTextures(1, &staging_buffer->texture_id);
+    gl->BindTexture(image_target, staging_buffer->texture_id);
+    gl->TexParameteri(image_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    gl->TexParameteri(image_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    gl->TexParameteri(image_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    gl->TexParameteri(image_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+  } else {
+    gl->BindTexture(image_target, staging_buffer->texture_id);
+  }
 
-    // Create and bind image.
-    if (!staging_buffer->image_id) {
-      if (staging_buffer->gpu_memory_buffer) {
-        staging_buffer->image_id = gl->CreateImageCHROMIUM(
-            staging_buffer->gpu_memory_buffer->AsClientBuffer(),
-            staging_buffer->size.width(), staging_buffer->size.height(),
-            GLInternalFormat(resource->format()));
-        gl->BindTexImage2DCHROMIUM(image_target, staging_buffer->image_id);
-      }
-    } else {
-      gl->ReleaseTexImage2DCHROMIUM(image_target, staging_buffer->image_id);
+  // Create and bind image.
+  if (!staging_buffer->image_id) {
+    if (staging_buffer->gpu_memory_buffer) {
+      staging_buffer->image_id = gl->CreateImageCHROMIUM(
+          staging_buffer->gpu_memory_buffer->AsClientBuffer(),
+          staging_buffer->size.width(), staging_buffer->size.height(),
+          GLInternalFormat(resource_lock->format()));
       gl->BindTexImage2DCHROMIUM(image_target, staging_buffer->image_id);
     }
+  } else {
+    gl->ReleaseTexImage2DCHROMIUM(image_target, staging_buffer->image_id);
+    gl->BindTexImage2DCHROMIUM(image_target, staging_buffer->image_id);
+  }
 
-    // Unbind staging texture.
-    gl->BindTexture(image_target, 0);
+  // Unbind staging texture.
+  gl->BindTexture(image_target, 0);
 
-    if (resource_provider_->use_sync_query()) {
-      if (!staging_buffer->query_id)
-        gl->GenQueriesEXT(1, &staging_buffer->query_id);
+  if (resource_provider_->use_sync_query()) {
+    if (!staging_buffer->query_id)
+      gl->GenQueriesEXT(1, &staging_buffer->query_id);
 
 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
-      // TODO(reveman): This avoids a performance problem on ARM ChromeOS
-      // devices. crbug.com/580166
-      gl->BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM, staging_buffer->query_id);
+    // TODO(reveman): This avoids a performance problem on ARM ChromeOS
+    // devices. crbug.com/580166
+    gl->BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM, staging_buffer->query_id);
 #else
-      gl->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM,
-                        staging_buffer->query_id);
+    gl->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, staging_buffer->query_id);
 #endif
-    }
+  }
 
-    // Since compressed texture's cannot be pre-allocated we might have an
-    // unallocated resource in which case we need to perform a full size copy.
-    if (IsResourceFormatCompressed(resource->format())) {
-      gl->CompressedCopyTextureCHROMIUM(staging_buffer->texture_id,
-                                        resource_lock->texture_id());
-    } else {
-      int bytes_per_row = ResourceUtil::UncheckedWidthInBytes<int>(
-          resource->size().width(), resource->format());
-      int chunk_size_in_rows =
-          std::max(1, max_bytes_per_copy_operation_ / bytes_per_row);
-      // Align chunk size to 4. Required to support compressed texture formats.
-      chunk_size_in_rows = MathUtil::UncheckedRoundUp(chunk_size_in_rows, 4);
-      int y = 0;
-      int height = resource->size().height();
-      while (y < height) {
-        // Copy at most |chunk_size_in_rows|.
-        int rows_to_copy = std::min(chunk_size_in_rows, height - y);
-        DCHECK_GT(rows_to_copy, 0);
+  // Since compressed texture's cannot be pre-allocated we might have an
+  // unallocated resource in which case we need to perform a full size copy.
+  if (IsResourceFormatCompressed(resource_lock->format())) {
+    gl->CompressedCopyTextureCHROMIUM(staging_buffer->texture_id,
+                                      resource_texture_id);
+  } else {
+    int bytes_per_row = ResourceUtil::UncheckedWidthInBytes<int>(
+        resource_lock->size().width(), resource_lock->format());
+    int chunk_size_in_rows =
+        std::max(1, max_bytes_per_copy_operation_ / bytes_per_row);
+    // Align chunk size to 4. Required to support compressed texture formats.
+    chunk_size_in_rows = MathUtil::UncheckedRoundUp(chunk_size_in_rows, 4);
+    int y = 0;
+    int height = resource_lock->size().height();
+    while (y < height) {
+      // Copy at most |chunk_size_in_rows|.
+      int rows_to_copy = std::min(chunk_size_in_rows, height - y);
+      DCHECK_GT(rows_to_copy, 0);
 
-        gl->CopySubTextureCHROMIUM(
-            staging_buffer->texture_id, resource_lock->texture_id(), 0, y, 0, y,
-            resource->size().width(), rows_to_copy, false, false, false);
-        y += rows_to_copy;
+      gl->CopySubTextureCHROMIUM(
+          staging_buffer->texture_id, resource_texture_id, 0, y, 0, y,
+          resource_lock->size().width(), rows_to_copy, false, false, false);
+      y += rows_to_copy;
 
-        // Increment |bytes_scheduled_since_last_flush_| by the amount of memory
-        // used for this copy operation.
-        bytes_scheduled_since_last_flush_ += rows_to_copy * bytes_per_row;
+      // Increment |bytes_scheduled_since_last_flush_| by the amount of memory
+      // used for this copy operation.
+      bytes_scheduled_since_last_flush_ += rows_to_copy * bytes_per_row;
 
-        if (bytes_scheduled_since_last_flush_ >=
-            max_bytes_per_copy_operation_) {
-          gl->ShallowFlushCHROMIUM();
-          bytes_scheduled_since_last_flush_ = 0;
-        }
+      if (bytes_scheduled_since_last_flush_ >= max_bytes_per_copy_operation_) {
+        gl->ShallowFlushCHROMIUM();
+        bytes_scheduled_since_last_flush_ = 0;
       }
     }
-
-    if (resource_provider_->use_sync_query()) {
-#if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
-      gl->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM);
-#else
-      gl->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM);
-#endif
-    }
-
-    const uint64_t fence_sync = gl->InsertFenceSyncCHROMIUM();
-
-    // Barrier to sync worker context output to cc context.
-    gl->OrderingBarrierCHROMIUM();
-
-    // Generate sync token after the barrier for cross context synchronization.
-    gpu::SyncToken sync_token;
-    gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData());
-    resource_lock->UpdateResourceSyncToken(sync_token);
   }
+
+  if (resource_provider_->use_sync_query()) {
+#if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
+    gl->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM);
+#else
+    gl->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM);
+#endif
+  }
+
+  const uint64_t fence_sync = gl->InsertFenceSyncCHROMIUM();
+
+  // Barrier to sync worker context output to cc context.
+  gl->OrderingBarrierCHROMIUM();
+
+  // Generate sync token after the barrier for cross context synchronization.
+  gpu::SyncToken resource_sync_token;
+  gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, resource_sync_token.GetData());
+  resource_lock->set_sync_token(resource_sync_token);
+  resource_lock->set_synchronized(!async_worker_context_enabled_);
 }
 
 }  // namespace cc
diff --git a/cc/raster/one_copy_raster_buffer_provider.h b/cc/raster/one_copy_raster_buffer_provider.h
index d30c3b5..44ceb7a 100644
--- a/cc/raster/one_copy_raster_buffer_provider.h
+++ b/cc/raster/one_copy_raster_buffer_provider.h
@@ -12,6 +12,7 @@
 #include "cc/raster/raster_buffer_provider.h"
 #include "cc/raster/staging_buffer_pool.h"
 #include "cc/resources/resource_provider.h"
+#include "gpu/command_buffer/common/sync_token.h"
 
 namespace cc {
 struct StagingBuffer;
@@ -27,7 +28,8 @@
                               int max_copy_texture_chromium_size,
                               bool use_partial_raster,
                               int max_staging_buffer_usage_in_bytes,
-                              ResourceFormat preferred_tile_format);
+                              ResourceFormat preferred_tile_format,
+                              bool async_worker_context_enabled);
   ~OneCopyRasterBufferProvider() override;
 
   // Overridden from RasterBufferProvider:
@@ -45,6 +47,7 @@
   void PlaybackAndCopyOnWorkerThread(
       const Resource* resource,
       ResourceProvider::ScopedWriteLockGL* resource_lock,
+      const gpu::SyncToken& sync_token,
       const RasterSource* raster_source,
       const gfx::Rect& raster_full_rect,
       const gfx::Rect& raster_dirty_rect,
@@ -54,6 +57,39 @@
       uint64_t new_content_id);
 
  private:
+  class RasterBufferImpl : public RasterBuffer {
+   public:
+    RasterBufferImpl(OneCopyRasterBufferProvider* client,
+                     ResourceProvider* resource_provider,
+                     const Resource* resource,
+                     uint64_t previous_content_id,
+                     bool async_worker_context_enabled);
+    ~RasterBufferImpl() override;
+
+    // Overridden from RasterBuffer:
+    void Playback(
+        const RasterSource* raster_source,
+        const gfx::Rect& raster_full_rect,
+        const gfx::Rect& raster_dirty_rect,
+        uint64_t new_content_id,
+        float scale,
+        const RasterSource::PlaybackSettings& playback_settings) override;
+
+    void set_sync_token(const gpu::SyncToken& sync_token) {
+      sync_token_ = sync_token;
+    }
+
+   private:
+    OneCopyRasterBufferProvider* client_;
+    const Resource* resource_;
+    ResourceProvider::ScopedWriteLockGL lock_;
+    uint64_t previous_content_id_;
+
+    gpu::SyncToken sync_token_;
+
+    DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl);
+  };
+
   void PlaybackToStagingBuffer(
       StagingBuffer* staging_buffer,
       const Resource* resource,
@@ -65,8 +101,8 @@
       uint64_t previous_content_id,
       uint64_t new_content_id);
   void CopyOnWorkerThread(StagingBuffer* staging_buffer,
-                          const Resource* resource,
                           ResourceProvider::ScopedWriteLockGL* resource_lock,
+                          const gpu::SyncToken& sync_token,
                           const RasterSource* raster_source,
                           uint64_t previous_content_id,
                           uint64_t new_content_id);
@@ -75,14 +111,18 @@
   ContextProvider* const worker_context_provider_;
   ResourceProvider* const resource_provider_;
   const int max_bytes_per_copy_operation_;
-  bool use_partial_raster_;
+  const bool use_partial_raster_;
 
   // Context lock must be acquired when accessing this member.
   int bytes_scheduled_since_last_flush_;
 
-  ResourceFormat preferred_tile_format_;
+  const ResourceFormat preferred_tile_format_;
   StagingBufferPool staging_pool_;
 
+  const bool async_worker_context_enabled_;
+
+  std::set<RasterBufferImpl*> pending_raster_buffers_;
+
   DISALLOW_COPY_AND_ASSIGN(OneCopyRasterBufferProvider);
 };
 
diff --git a/cc/raster/raster_buffer_provider.h b/cc/raster/raster_buffer_provider.h
index 061740a..1cdfba2 100644
--- a/cc/raster/raster_buffer_provider.h
+++ b/cc/raster/raster_buffer_provider.h
@@ -53,7 +53,7 @@
   // Release raster buffer.
   virtual void ReleaseBufferForRaster(std::unique_ptr<RasterBuffer> buffer) = 0;
 
-  // Barrier to sync resources to the worker context.
+  // Used for syncing resources to the worker context.
   virtual void OrderingBarrier() = 0;
 
   // Returns the format to use for the tiles.
diff --git a/cc/raster/raster_buffer_provider_perftest.cc b/cc/raster/raster_buffer_provider_perftest.cc
index 43e35da..5ebd47a 100644
--- a/cc/raster/raster_buffer_provider_perftest.cc
+++ b/cc/raster/raster_buffer_provider_perftest.cc
@@ -13,11 +13,11 @@
 #include "cc/output/context_provider.h"
 #include "cc/raster/bitmap_raster_buffer_provider.h"
 #include "cc/raster/gpu_raster_buffer_provider.h"
-#include "cc/raster/gpu_rasterizer.h"
 #include "cc/raster/one_copy_raster_buffer_provider.h"
 #include "cc/raster/raster_buffer_provider.h"
 #include "cc/raster/synchronous_task_graph_runner.h"
 #include "cc/raster/zero_copy_raster_buffer_provider.h"
+#include "cc/resources/platform_color.h"
 #include "cc/resources/resource_pool.h"
 #include "cc/resources/resource_provider.h"
 #include "cc/resources/scoped_resource.h"
@@ -29,6 +29,7 @@
 #include "cc/test/test_shared_bitmap_manager.h"
 #include "cc/test/test_web_graphics_context_3d.h"
 #include "cc/tiles/tile_task_manager.h"
+#include "gpu/command_buffer/common/sync_token.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/perf/perf_test.h"
 #include "third_party/khronos/GLES2/gl2.h"
@@ -68,6 +69,13 @@
     if (pname == GL_QUERY_RESULT_AVAILABLE_EXT)
       *params = 1;
   }
+  void GenUnverifiedSyncTokenCHROMIUM(GLuint64 fence_sync,
+                                      GLbyte* sync_token) override {
+    // Copy the data over after setting the data to ensure alignment.
+    gpu::SyncToken sync_token_data(gpu::CommandBufferNamespace::GPU_IO, 0,
+                                   gpu::CommandBufferId(), fence_sync);
+    memcpy(sync_token, &sync_token_data, sizeof(sync_token_data));
+  }
 };
 
 class PerfContextProvider : public ContextProvider {
@@ -311,43 +319,43 @@
  public:
   // Overridden from testing::Test:
   void SetUp() override {
-    std::unique_ptr<RasterBufferProvider> raster_buffer_provider;
     switch (GetParam()) {
       case RASTER_BUFFER_PROVIDER_TYPE_ZERO_COPY:
         Create3dOutputSurfaceAndResourceProvider();
-        raster_buffer_provider = ZeroCopyRasterBufferProvider::Create(
+        raster_buffer_provider_ = ZeroCopyRasterBufferProvider::Create(
             resource_provider_.get(), PlatformColor::BestTextureFormat());
         break;
       case RASTER_BUFFER_PROVIDER_TYPE_ONE_COPY:
         Create3dOutputSurfaceAndResourceProvider();
-        raster_buffer_provider = base::MakeUnique<OneCopyRasterBufferProvider>(
+        raster_buffer_provider_ = base::MakeUnique<OneCopyRasterBufferProvider>(
             task_runner_.get(), compositor_context_provider_.get(),
             worker_context_provider_.get(), resource_provider_.get(),
             std::numeric_limits<int>::max(), false,
-            std::numeric_limits<int>::max(),
-            PlatformColor::BestTextureFormat());
+            std::numeric_limits<int>::max(), PlatformColor::BestTextureFormat(),
+            false);
         break;
       case RASTER_BUFFER_PROVIDER_TYPE_GPU:
         Create3dOutputSurfaceAndResourceProvider();
-        raster_buffer_provider = base::MakeUnique<GpuRasterBufferProvider>(
+        raster_buffer_provider_ = base::MakeUnique<GpuRasterBufferProvider>(
             compositor_context_provider_.get(), worker_context_provider_.get(),
-            resource_provider_.get(), false, 0);
+            resource_provider_.get(), false, 0, false);
         break;
       case RASTER_BUFFER_PROVIDER_TYPE_BITMAP:
         CreateSoftwareOutputSurfaceAndResourceProvider();
-        raster_buffer_provider =
+        raster_buffer_provider_ =
             BitmapRasterBufferProvider::Create(resource_provider_.get());
         break;
     }
 
-    DCHECK(raster_buffer_provider);
+    DCHECK(raster_buffer_provider_);
 
-    tile_task_manager_ = TileTaskManagerImpl::Create(
-        std::move(raster_buffer_provider), task_graph_runner_.get());
+    tile_task_manager_ = TileTaskManagerImpl::Create(task_graph_runner_.get());
   }
   void TearDown() override {
     tile_task_manager_->Shutdown();
     tile_task_manager_->CheckForCompletedTasks();
+
+    raster_buffer_provider_->Shutdown();
   }
 
   // Overridden from PerfRasterBufferProviderHelper:
@@ -355,13 +363,11 @@
       const Resource* resource,
       uint64_t resource_content_id,
       uint64_t previous_content_id) override {
-    return tile_task_manager_->GetRasterBufferProvider()
-        ->AcquireBufferForRaster(resource, resource_content_id,
-                                 previous_content_id);
+    return raster_buffer_provider_->AcquireBufferForRaster(
+        resource, resource_content_id, previous_content_id);
   }
   void ReleaseBufferForRaster(std::unique_ptr<RasterBuffer> buffer) override {
-    tile_task_manager_->GetRasterBufferProvider()->ReleaseBufferForRaster(
-        std::move(buffer));
+    raster_buffer_provider_->ReleaseBufferForRaster(std::move(buffer));
   }
 
   void RunMessageLoopUntilAllTasksHaveCompleted() {
@@ -386,12 +392,14 @@
       graph.Reset();
       ResetRasterTasks(raster_tasks);
       BuildTileTaskGraph(&graph, raster_tasks);
+      raster_buffer_provider_->OrderingBarrier();
       tile_task_manager_->ScheduleTasks(&graph);
       tile_task_manager_->CheckForCompletedTasks();
       timer_.NextLap();
     } while (!timer_.HasTimeLimitExpired());
 
     TaskGraph empty;
+    raster_buffer_provider_->OrderingBarrier();
     tile_task_manager_->ScheduleTasks(&empty);
     RunMessageLoopUntilAllTasksHaveCompleted();
     tile_task_manager_->CheckForCompletedTasks();
@@ -422,6 +430,7 @@
       // Reset the tasks as for scheduling new state tasks are needed.
       ResetRasterTasks(raster_tasks[count % kNumVersions]);
       BuildTileTaskGraph(&graph, raster_tasks[count % kNumVersions]);
+      raster_buffer_provider_->OrderingBarrier();
       tile_task_manager_->ScheduleTasks(&graph);
       tile_task_manager_->CheckForCompletedTasks();
       ++count;
@@ -429,6 +438,7 @@
     } while (!timer_.HasTimeLimitExpired());
 
     TaskGraph empty;
+    raster_buffer_provider_->OrderingBarrier();
     tile_task_manager_->ScheduleTasks(&empty);
     RunMessageLoopUntilAllTasksHaveCompleted();
     tile_task_manager_->CheckForCompletedTasks();
@@ -453,12 +463,14 @@
     do {
       graph.Reset();
       BuildTileTaskGraph(&graph, raster_tasks);
+      raster_buffer_provider_->OrderingBarrier();
       tile_task_manager_->ScheduleTasks(&graph);
       RunMessageLoopUntilAllTasksHaveCompleted();
       timer_.NextLap();
     } while (!timer_.HasTimeLimitExpired());
 
     TaskGraph empty;
+    raster_buffer_provider_->OrderingBarrier();
     tile_task_manager_->ScheduleTasks(&empty);
     RunMessageLoopUntilAllTasksHaveCompleted();
 
@@ -499,6 +511,7 @@
   }
 
   std::unique_ptr<TileTaskManager> tile_task_manager_;
+  std::unique_ptr<RasterBufferProvider> raster_buffer_provider_;
   TestGpuMemoryBufferManager gpu_memory_buffer_manager_;
   TestSharedBitmapManager shared_bitmap_manager_;
 };
diff --git a/cc/raster/raster_buffer_provider_unittest.cc b/cc/raster/raster_buffer_provider_unittest.cc
index 1b4d3e5..3fb5713 100644
--- a/cc/raster/raster_buffer_provider_unittest.cc
+++ b/cc/raster/raster_buffer_provider_unittest.cc
@@ -20,10 +20,10 @@
 #include "cc/base/unique_notifier.h"
 #include "cc/raster/bitmap_raster_buffer_provider.h"
 #include "cc/raster/gpu_raster_buffer_provider.h"
-#include "cc/raster/gpu_rasterizer.h"
 #include "cc/raster/one_copy_raster_buffer_provider.h"
 #include "cc/raster/synchronous_task_graph_runner.h"
 #include "cc/raster/zero_copy_raster_buffer_provider.h"
+#include "cc/resources/platform_color.h"
 #include "cc/resources/resource_pool.h"
 #include "cc/resources/resource_provider.h"
 #include "cc/resources/scoped_resource.h"
@@ -156,43 +156,43 @@
 
   // Overridden from testing::Test:
   void SetUp() override {
-    std::unique_ptr<RasterBufferProvider> raster_buffer_provider;
     switch (GetParam()) {
       case RASTER_BUFFER_PROVIDER_TYPE_ZERO_COPY:
         Create3dOutputSurfaceAndResourceProvider();
-        raster_buffer_provider = ZeroCopyRasterBufferProvider::Create(
+        raster_buffer_provider_ = ZeroCopyRasterBufferProvider::Create(
             resource_provider_.get(), PlatformColor::BestTextureFormat());
         break;
       case RASTER_BUFFER_PROVIDER_TYPE_ONE_COPY:
         Create3dOutputSurfaceAndResourceProvider();
-        raster_buffer_provider = base::MakeUnique<OneCopyRasterBufferProvider>(
+        raster_buffer_provider_ = base::MakeUnique<OneCopyRasterBufferProvider>(
             base::ThreadTaskRunnerHandle::Get().get(), context_provider_.get(),
             worker_context_provider_.get(), resource_provider_.get(),
             kMaxBytesPerCopyOperation, false, kMaxStagingBuffers,
-            PlatformColor::BestTextureFormat());
+            PlatformColor::BestTextureFormat(), false);
         break;
       case RASTER_BUFFER_PROVIDER_TYPE_GPU:
         Create3dOutputSurfaceAndResourceProvider();
-        raster_buffer_provider = base::MakeUnique<GpuRasterBufferProvider>(
+        raster_buffer_provider_ = base::MakeUnique<GpuRasterBufferProvider>(
             context_provider_.get(), worker_context_provider_.get(),
-            resource_provider_.get(), false, 0);
+            resource_provider_.get(), false, 0, false);
         break;
       case RASTER_BUFFER_PROVIDER_TYPE_BITMAP:
         CreateSoftwareOutputSurfaceAndResourceProvider();
-        raster_buffer_provider =
+        raster_buffer_provider_ =
             BitmapRasterBufferProvider::Create(resource_provider_.get());
         break;
     }
 
-    DCHECK(raster_buffer_provider);
+    DCHECK(raster_buffer_provider_);
 
-    tile_task_manager_ = TileTaskManagerImpl::Create(
-        std::move(raster_buffer_provider), &task_graph_runner_);
+    tile_task_manager_ = TileTaskManagerImpl::Create(&task_graph_runner_);
   }
 
   void TearDown() override {
     tile_task_manager_->Shutdown();
     tile_task_manager_->CheckForCompletedTasks();
+
+    raster_buffer_provider_->Shutdown();
   }
 
   void AllTileTasksFinished() {
@@ -216,6 +216,7 @@
                                 0 /* dependencies */);
     }
 
+    raster_buffer_provider_->OrderingBarrier();
     tile_task_manager_->ScheduleTasks(&graph_);
   }
 
@@ -228,8 +229,7 @@
     // The raster buffer has no tile ids associated with it for partial update,
     // so doesn't need to provide a valid dirty rect.
     std::unique_ptr<RasterBuffer> raster_buffer =
-        tile_task_manager_->GetRasterBufferProvider()->AcquireBufferForRaster(
-            resource.get(), 0, 0);
+        raster_buffer_provider_->AcquireBufferForRaster(resource.get(), 0, 0);
     TileTask::Vector empty;
     tasks_.push_back(new TestRasterTaskImpl(this, std::move(resource), id,
                                             std::move(raster_buffer), &empty));
@@ -246,8 +246,7 @@
                        RGBA_8888);
 
     std::unique_ptr<RasterBuffer> raster_buffer =
-        tile_task_manager_->GetRasterBufferProvider()->AcquireBufferForRaster(
-            resource.get(), 0, 0);
+        raster_buffer_provider_->AcquireBufferForRaster(resource.get(), 0, 0);
     TileTask::Vector empty;
     tasks_.push_back(new BlockingTestRasterTaskImpl(
         this, std::move(resource), id, std::move(raster_buffer), lock, &empty));
@@ -268,8 +267,7 @@
   void OnRasterTaskCompleted(std::unique_ptr<RasterBuffer> raster_buffer,
                              unsigned id,
                              bool was_canceled) override {
-    tile_task_manager_->GetRasterBufferProvider()->ReleaseBufferForRaster(
-        std::move(raster_buffer));
+    raster_buffer_provider_->ReleaseBufferForRaster(std::move(raster_buffer));
     RasterTaskResult result;
     result.id = id;
     result.canceled = was_canceled;
@@ -307,6 +305,7 @@
   std::unique_ptr<FakeOutputSurface> output_surface_;
   std::unique_ptr<ResourceProvider> resource_provider_;
   std::unique_ptr<TileTaskManager> tile_task_manager_;
+  std::unique_ptr<RasterBufferProvider> raster_buffer_provider_;
   TestGpuMemoryBufferManager gpu_memory_buffer_manager_;
   TestSharedBitmapManager shared_bitmap_manager_;
   SynchronousTaskGraphRunner task_graph_runner_;
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc
index 18e2f22..a9e8e85 100644
--- a/cc/resources/resource_provider.cc
+++ b/cc/resources/resource_provider.cc
@@ -694,11 +694,25 @@
                                               DeleteStyle style) {
   TRACE_EVENT0("cc", "ResourceProvider::DeleteResourceInternal");
   Resource* resource = &it->second;
-  bool lost_resource = resource->lost;
-
   DCHECK(resource->exported_count == 0 || style != NORMAL);
-  if (style == FOR_SHUTDOWN && resource->exported_count > 0)
-    lost_resource = true;
+
+  // Exported resources are lost on shutdown.
+  bool exported_resource_lost =
+      style == FOR_SHUTDOWN && resource->exported_count > 0;
+  // GPU resources are lost when output surface is lost.
+  bool gpu_resource_lost =
+      IsGpuResourceType(resource->type) && lost_output_surface_;
+  bool lost_resource =
+      resource->lost || exported_resource_lost || gpu_resource_lost;
+
+  if (!lost_resource &&
+      resource->synchronization_state() == Resource::NEEDS_WAIT) {
+    DCHECK(resource->allocated);
+    DCHECK(IsGpuResourceType(resource->type));
+    GLES2Interface* gl = ContextGL();
+    DCHECK(gl);
+    resource->WaitSyncToken(gl);
+  }
 
   if (resource->image_id) {
     DCHECK(resource->origin == Resource::INTERNAL);
@@ -729,7 +743,6 @@
     gpu::SyncToken sync_token = resource->mailbox().sync_token();
     if (IsGpuResourceType(resource->type)) {
       DCHECK(resource->mailbox().IsTexture());
-      lost_resource |= lost_output_surface_;
       GLES2Interface* gl = ContextGL();
       DCHECK(gl);
       if (resource->gl_id) {
@@ -815,11 +828,12 @@
     SkCanvas dest(lock.sk_bitmap());
     dest.writePixels(source_info, image, image_stride, 0, 0);
   } else {
-    ScopedWriteLockGL lock(this, id);
-    DCHECK(lock.texture_id());
+    ScopedWriteLockGL lock(this, id, false);
+    unsigned resource_texture_id = lock.texture_id();
+    DCHECK(resource_texture_id);
     GLES2Interface* gl = ContextGL();
     DCHECK(gl);
-    gl->BindTexture(resource->target, lock.texture_id());
+    gl->BindTexture(resource->target, resource_texture_id);
     if (resource->format == ETC1) {
       DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
       int image_bytes = ResourceUtil::CheckedSizeInBytes<int>(image_size, ETC1);
@@ -835,7 +849,8 @@
     gl->OrderingBarrierCHROMIUM();
     gpu::SyncToken sync_token;
     gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData());
-    lock.UpdateResourceSyncToken(sync_token);
+    lock.set_sync_token(sync_token);
+    lock.set_synchronized(true);
   }
 }
 
@@ -853,6 +868,7 @@
   gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData());
 
   resource->UpdateSyncToken(sync_token);
+  resource->SetSynchronized();
 }
 
 void ResourceProvider::GenerateSyncTokenForResources(
@@ -873,6 +889,7 @@
       }
 
       resource->UpdateSyncToken(sync_token);
+      resource->SetSynchronized();
     }
   }
 }
@@ -965,7 +982,8 @@
 ResourceProvider::Resource* ResourceProvider::LockForWrite(ResourceId id) {
   Resource* resource = GetResource(id);
   DCHECK(CanLockForWrite(id));
-  DCHECK_NE(Resource::NEEDS_WAIT, resource->synchronization_state());
+  if (resource->allocated)
+    WaitSyncTokenIfNeeded(id);
   resource->locked_for_write = true;
   resource->SetLocallyUsed();
   return resource;
@@ -983,12 +1001,11 @@
   return resource->is_overlay_candidate;
 }
 
-void ResourceProvider::UnlockForWrite(ResourceProvider::Resource* resource) {
+void ResourceProvider::UnlockForWrite(Resource* resource) {
   DCHECK(resource->locked_for_write);
   DCHECK_EQ(resource->exported_count, 0);
   DCHECK(resource->origin == Resource::INTERNAL);
   resource->locked_for_write = false;
-  resource->SetSynchronized();
 }
 
 void ResourceProvider::EnableReadLockFencesForTesting(ResourceId id) {
@@ -1000,10 +1017,11 @@
 ResourceProvider::ScopedReadLockGL::ScopedReadLockGL(
     ResourceProvider* resource_provider,
     ResourceId resource_id)
-    : resource_provider_(resource_provider),
-      resource_id_(resource_id),
-      resource_(resource_provider->LockForRead(resource_id)) {
-  DCHECK(resource_);
+    : resource_provider_(resource_provider), resource_id_(resource_id) {
+  const Resource* resource = resource_provider->LockForRead(resource_id);
+  texture_id_ = resource->gl_id;
+  target_ = resource->target;
+  size_ = resource->size;
 }
 
 ResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() {
@@ -1014,7 +1032,7 @@
     ResourceProvider* resource_provider,
     ResourceId resource_id,
     GLenum filter)
-    : ScopedReadLockGL(resource_provider, resource_id),
+    : resource_lock_(resource_provider, resource_id),
       unit_(GL_TEXTURE0),
       target_(resource_provider->BindForSampling(resource_id, unit_, filter)) {}
 
@@ -1023,7 +1041,7 @@
     ResourceId resource_id,
     GLenum unit,
     GLenum filter)
-    : ScopedReadLockGL(resource_provider, resource_id),
+    : resource_lock_(resource_provider, resource_id),
       unit_(unit),
       target_(resource_provider->BindForSampling(resource_id, unit_, filter)) {}
 
@@ -1031,22 +1049,97 @@
 
 ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(
     ResourceProvider* resource_provider,
-    ResourceId resource_id)
+    ResourceId resource_id,
+    bool create_mailbox)
     : resource_provider_(resource_provider),
-      resource_(resource_provider->LockForWrite(resource_id)),
-      texture_id_(0),
-      set_sync_token_(false) {
-  resource_provider_->LazyAllocate(resource_);
-  texture_id_ = resource_->gl_id;
-  DCHECK(texture_id_);
-  if (resource_->image_id && resource_->dirty_image)
-    resource_provider_->BindImageForSampling(resource_);
+      resource_id_(resource_id),
+      synchronized_(false) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  Resource* resource = resource_provider->LockForWrite(resource_id);
+  resource_provider_->LazyAllocate(resource);
+  if (resource->image_id && resource->dirty_image)
+    resource_provider_->BindImageForSampling(resource);
+  if (create_mailbox) {
+    resource_provider_->CreateMailboxAndBindResource(
+        resource_provider_->ContextGL(), resource);
+  }
+  texture_id_ = resource->gl_id;
+  target_ = resource->target;
+  format_ = resource->format;
+  size_ = resource->size;
+  mailbox_ = resource->mailbox();
 }
 
 ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() {
-  if (set_sync_token_)
-    resource_->UpdateSyncToken(sync_token_);
-  resource_provider_->UnlockForWrite(resource_);
+  DCHECK(thread_checker_.CalledOnValidThread());
+  Resource* resource = resource_provider_->GetResource(resource_id_);
+  DCHECK(resource->locked_for_write);
+  if (sync_token_.HasData())
+    resource->UpdateSyncToken(sync_token_);
+  if (synchronized_)
+    resource->SetSynchronized();
+  resource_provider_->UnlockForWrite(resource);
+}
+
+ResourceProvider::ScopedTextureProvider::ScopedTextureProvider(
+    gpu::gles2::GLES2Interface* gl,
+    ScopedWriteLockGL* resource_lock,
+    bool use_mailbox)
+    : gl_(gl), use_mailbox_(use_mailbox) {
+  if (use_mailbox_) {
+    texture_id_ = gl_->CreateAndConsumeTextureCHROMIUM(
+        resource_lock->target(), resource_lock->mailbox().name());
+  } else {
+    texture_id_ = resource_lock->texture_id();
+  }
+  DCHECK(texture_id_);
+}
+
+ResourceProvider::ScopedTextureProvider::~ScopedTextureProvider() {
+  if (use_mailbox_)
+    gl_->DeleteTextures(1, &texture_id_);
+}
+
+ResourceProvider::ScopedSkSurfaceProvider::ScopedSkSurfaceProvider(
+    ContextProvider* context_provider,
+    ScopedWriteLockGL* resource_lock,
+    bool use_mailbox,
+    bool use_distance_field_text,
+    bool can_use_lcd_text,
+    int msaa_sample_count)
+    : texture_provider_(context_provider->ContextGL(),
+                        resource_lock,
+                        use_mailbox) {
+  GrGLTextureInfo texture_info;
+  texture_info.fID = texture_provider_.texture_id();
+  texture_info.fTarget = resource_lock->target();
+  GrBackendTextureDesc desc;
+  desc.fFlags = kRenderTarget_GrBackendTextureFlag;
+  desc.fWidth = resource_lock->size().width();
+  desc.fHeight = resource_lock->size().height();
+  desc.fConfig = ToGrPixelConfig(resource_lock->format());
+  desc.fOrigin = kTopLeft_GrSurfaceOrigin;
+  desc.fTextureHandle = skia::GrGLTextureInfoToGrBackendObject(texture_info);
+  desc.fSampleCnt = msaa_sample_count;
+
+  uint32_t flags =
+      use_distance_field_text ? SkSurfaceProps::kUseDistanceFieldFonts_Flag : 0;
+  // Use unknown pixel geometry to disable LCD text.
+  SkSurfaceProps surface_props(flags, kUnknown_SkPixelGeometry);
+  if (can_use_lcd_text) {
+    // LegacyFontHost will get LCD text and skia figures out what type to use.
+    surface_props =
+        SkSurfaceProps(flags, SkSurfaceProps::kLegacyFontHost_InitType);
+  }
+  sk_surface_ = SkSurface::MakeFromBackendTextureAsRenderTarget(
+      context_provider->GrContext(), desc, &surface_props);
+}
+
+ResourceProvider::ScopedSkSurfaceProvider::~ScopedSkSurfaceProvider() {
+  if (sk_surface_.get()) {
+    sk_surface_->prepareForExternalIO();
+    sk_surface_.reset();
+  }
 }
 
 void ResourceProvider::PopulateSkBitmapWithResource(SkBitmap* sk_bitmap,
@@ -1072,47 +1165,52 @@
 ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware(
     ResourceProvider* resource_provider,
     ResourceId resource_id)
-    : resource_provider_(resource_provider),
-      resource_(resource_provider->LockForWrite(resource_id)) {
-  ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_, resource_);
+    : resource_provider_(resource_provider), resource_id_(resource_id) {
+  ResourceProvider::PopulateSkBitmapWithResource(
+      &sk_bitmap_, resource_provider->LockForWrite(resource_id));
   DCHECK(valid());
 }
 
 ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() {
   DCHECK(thread_checker_.CalledOnValidThread());
-  resource_provider_->UnlockForWrite(resource_);
+  Resource* resource = resource_provider_->GetResource(resource_id_);
+  DCHECK(resource);
+  resource->SetSynchronized();
+  resource_provider_->UnlockForWrite(resource);
 }
 
 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
     ScopedWriteLockGpuMemoryBuffer(ResourceProvider* resource_provider,
                                    ResourceId resource_id)
-    : resource_provider_(resource_provider),
-      resource_(resource_provider->LockForWrite(resource_id)) {
-  DCHECK(IsGpuResourceType(resource_->type));
-  gpu_memory_buffer_ = std::move(resource_->gpu_memory_buffer);
-  resource_->gpu_memory_buffer = nullptr;
+    : resource_provider_(resource_provider), resource_id_(resource_id) {
+  Resource* resource = resource_provider->LockForWrite(resource_id);
+  DCHECK(IsGpuResourceType(resource->type));
+  format_ = resource->format;
+  size_ = resource->size;
+  gpu_memory_buffer_ = std::move(resource->gpu_memory_buffer);
+  resource->gpu_memory_buffer = nullptr;
 }
 
 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
     ~ScopedWriteLockGpuMemoryBuffer() {
   DCHECK(thread_checker_.CalledOnValidThread());
-  resource_provider_->UnlockForWrite(resource_);
-  if (!gpu_memory_buffer_)
-    return;
-
-  DCHECK(!resource_->gpu_memory_buffer);
-  resource_provider_->LazyCreate(resource_);
-  resource_->gpu_memory_buffer = std::move(gpu_memory_buffer_);
-  resource_->allocated = true;
-  resource_provider_->LazyCreateImage(resource_);
-  resource_->dirty_image = true;
-  resource_->is_overlay_candidate = true;
-  resource_->SetSynchronized();
-
-  // GpuMemoryBuffer provides direct access to the memory used by the GPU.
-  // Read lock fences are required to ensure that we're not trying to map a
-  // buffer that is currently in-use by the GPU.
-  resource_->read_lock_fences_enabled = true;
+  Resource* resource = resource_provider_->GetResource(resource_id_);
+  DCHECK(resource);
+  if (gpu_memory_buffer_) {
+    DCHECK(!resource->gpu_memory_buffer);
+    resource_provider_->LazyCreate(resource);
+    resource->gpu_memory_buffer = std::move(gpu_memory_buffer_);
+    resource->allocated = true;
+    resource_provider_->LazyCreateImage(resource);
+    resource->dirty_image = true;
+    resource->is_overlay_candidate = true;
+    // GpuMemoryBuffer provides direct access to the memory used by the GPU.
+    // Read lock fences are required to ensure that we're not trying to map a
+    // buffer that is currently in-use by the GPU.
+    resource->read_lock_fences_enabled = true;
+  }
+  resource->SetSynchronized();
+  resource_provider_->UnlockForWrite(resource);
 }
 
 gfx::GpuMemoryBuffer*
@@ -1120,71 +1218,12 @@
   if (!gpu_memory_buffer_) {
     gpu_memory_buffer_ =
         resource_provider_->gpu_memory_buffer_manager_->AllocateGpuMemoryBuffer(
-            resource_->size, BufferFormat(resource_->format),
+            size_, BufferFormat(format_),
             gfx::BufferUsage::GPU_READ_CPU_READ_WRITE, gpu::kNullSurfaceHandle);
   }
   return gpu_memory_buffer_.get();
 }
 
-ResourceProvider::ScopedWriteLockGr::ScopedWriteLockGr(
-    ResourceProvider* resource_provider,
-    ResourceId resource_id)
-    : resource_provider_(resource_provider),
-      resource_(resource_provider->LockForWrite(resource_id)),
-      set_sync_token_(false) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  resource_provider_->LazyAllocate(resource_);
-  if (resource_->image_id && resource_->dirty_image)
-    resource_provider_->BindImageForSampling(resource_);
-}
-
-ResourceProvider::ScopedWriteLockGr::~ScopedWriteLockGr() {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(resource_->locked_for_write);
-  if (set_sync_token_)
-    resource_->UpdateSyncToken(sync_token_);
-
-  resource_provider_->UnlockForWrite(resource_);
-}
-
-void ResourceProvider::ScopedWriteLockGr::InitSkSurface(
-    GrContext* gr_context,
-    bool use_distance_field_text,
-    bool can_use_lcd_text,
-    int msaa_sample_count) {
-  DCHECK(resource_->locked_for_write);
-
-  GrGLTextureInfo texture_info;
-  texture_info.fID = resource_->gl_id;
-  texture_info.fTarget = resource_->target;
-  GrBackendTextureDesc desc;
-  desc.fFlags = kRenderTarget_GrBackendTextureFlag;
-  desc.fWidth = resource_->size.width();
-  desc.fHeight = resource_->size.height();
-  desc.fConfig = ToGrPixelConfig(resource_->format);
-  desc.fOrigin = kTopLeft_GrSurfaceOrigin;
-  desc.fTextureHandle = skia::GrGLTextureInfoToGrBackendObject(texture_info);
-  desc.fSampleCnt = msaa_sample_count;
-
-  uint32_t flags =
-      use_distance_field_text ? SkSurfaceProps::kUseDistanceFieldFonts_Flag : 0;
-  // Use unknown pixel geometry to disable LCD text.
-  SkSurfaceProps surface_props(flags, kUnknown_SkPixelGeometry);
-  if (can_use_lcd_text) {
-    // LegacyFontHost will get LCD text and skia figures out what type to use.
-    surface_props =
-        SkSurfaceProps(flags, SkSurfaceProps::kLegacyFontHost_InitType);
-  }
-  sk_surface_ = SkSurface::MakeFromBackendTextureAsRenderTarget(
-      gr_context, desc, &surface_props);
-}
-
-void ResourceProvider::ScopedWriteLockGr::ReleaseSkSurface() {
-  DCHECK(sk_surface_);
-  sk_surface_->prepareForExternalIO();
-  sk_surface_.reset();
-}
-
 ResourceProvider::SynchronousFence::SynchronousFence(
     gpu::gles2::GLES2Interface* gl)
     : gl_(gl), has_synchronized_(true) {}
@@ -1733,6 +1772,10 @@
     LazyCreateImage(resource);
     resource->dirty_image = true;
     resource->is_overlay_candidate = true;
+    // GpuMemoryBuffer provides direct access to the memory used by the GPU.
+    // Read lock fences are required to ensure that we're not trying to map a
+    // buffer that is currently in-use by the GPU.
+    resource->read_lock_fences_enabled = true;
   } else if (use_texture_storage_ext_ &&
              IsFormatSupportedForStorage(format, use_texture_format_bgra_) &&
              (resource->hint & TEXTURE_HINT_IMMUTABLE)) {
diff --git a/cc/resources/resource_provider.h b/cc/resources/resource_provider.h
index 96f212f..e2b97c6 100644
--- a/cc/resources/resource_provider.h
+++ b/cc/resources/resource_provider.h
@@ -216,21 +216,23 @@
    public:
     ScopedReadLockGL(ResourceProvider* resource_provider,
                      ResourceId resource_id);
-    virtual ~ScopedReadLockGL();
+    ~ScopedReadLockGL();
 
-    unsigned texture_id() const { return resource_->gl_id; }
-    GLenum target() const { return resource_->target; }
-    const gfx::Size& texture_size() const { return resource_->size; }
+    unsigned texture_id() const { return texture_id_; }
+    GLenum target() const { return target_; }
+    const gfx::Size& size() const { return size_; }
 
    private:
     ResourceProvider* resource_provider_;
     ResourceId resource_id_;
-    const ResourceProvider::Resource* resource_;
+    unsigned texture_id_;
+    GLenum target_;
+    gfx::Size size_;
 
     DISALLOW_COPY_AND_ASSIGN(ScopedReadLockGL);
   };
 
-  class CC_EXPORT ScopedSamplerGL : public ScopedReadLockGL {
+  class CC_EXPORT ScopedSamplerGL {
    public:
     ScopedSamplerGL(ResourceProvider* resource_provider,
                     ResourceId resource_id,
@@ -239,11 +241,13 @@
                     ResourceId resource_id,
                     GLenum unit,
                     GLenum filter);
-    ~ScopedSamplerGL() override;
+    ~ScopedSamplerGL();
 
+    unsigned texture_id() const { return resource_lock_.texture_id(); }
     GLenum target() const { return target_; }
 
    private:
+    ScopedReadLockGL resource_lock_;
     GLenum unit_;
     GLenum target_;
 
@@ -253,26 +257,74 @@
   class CC_EXPORT ScopedWriteLockGL {
    public:
     ScopedWriteLockGL(ResourceProvider* resource_provider,
-                      ResourceId resource_id);
+                      ResourceId resource_id,
+                      bool create_mailbox);
     ~ScopedWriteLockGL();
 
     unsigned texture_id() const { return texture_id_; }
+    GLenum target() const { return target_; }
+    ResourceFormat format() const { return format_; }
+    const gfx::Size& size() const { return size_; }
 
-    void UpdateResourceSyncToken(const gpu::SyncToken& sync_token) {
-      set_sync_token_ = true;
+    const TextureMailbox& mailbox() const { return mailbox_; }
+
+    void set_sync_token(const gpu::SyncToken& sync_token) {
       sync_token_ = sync_token;
     }
 
+    void set_synchronized(bool synchronized) { synchronized_ = synchronized; }
+
    private:
     ResourceProvider* resource_provider_;
-    ResourceProvider::Resource* resource_;
+    ResourceId resource_id_;
     unsigned texture_id_;
-    bool set_sync_token_;
+    GLenum target_;
+    ResourceFormat format_;
+    gfx::Size size_;
+    TextureMailbox mailbox_;
     gpu::SyncToken sync_token_;
+    bool synchronized_;
+    base::ThreadChecker thread_checker_;
 
     DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockGL);
   };
 
+  class CC_EXPORT ScopedTextureProvider {
+   public:
+    ScopedTextureProvider(gpu::gles2::GLES2Interface* gl,
+                          ScopedWriteLockGL* resource_lock,
+                          bool use_mailbox);
+    ~ScopedTextureProvider();
+
+    unsigned texture_id() const { return texture_id_; }
+
+   private:
+    gpu::gles2::GLES2Interface* gl_;
+    bool use_mailbox_;
+    unsigned texture_id_;
+
+    DISALLOW_COPY_AND_ASSIGN(ScopedTextureProvider);
+  };
+
+  class CC_EXPORT ScopedSkSurfaceProvider {
+   public:
+    ScopedSkSurfaceProvider(ContextProvider* context_provider,
+                            ScopedWriteLockGL* resource_lock,
+                            bool use_mailbox,
+                            bool use_distance_field_text,
+                            bool can_use_lcd_text,
+                            int msaa_sample_count);
+    ~ScopedSkSurfaceProvider();
+
+    SkSurface* sk_surface() { return sk_surface_.get(); }
+
+   private:
+    ScopedTextureProvider texture_provider_;
+    sk_sp<SkSurface> sk_surface_;
+
+    DISALLOW_COPY_AND_ASSIGN(ScopedSkSurfaceProvider);
+  };
+
   class CC_EXPORT ScopedReadLockSoftware {
    public:
     ScopedReadLockSoftware(ResourceProvider* resource_provider,
@@ -305,7 +357,7 @@
 
    private:
     ResourceProvider* resource_provider_;
-    ResourceProvider::Resource* resource_;
+    ResourceId resource_id_;
     SkBitmap sk_bitmap_;
     base::ThreadChecker thread_checker_;
 
@@ -322,45 +374,15 @@
 
    private:
     ResourceProvider* resource_provider_;
-    ResourceProvider::Resource* resource_;
+    ResourceId resource_id_;
+    ResourceFormat format_;
+    gfx::Size size_;
     std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer_;
     base::ThreadChecker thread_checker_;
 
     DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockGpuMemoryBuffer);
   };
 
-  class CC_EXPORT ScopedWriteLockGr {
-   public:
-    ScopedWriteLockGr(ResourceProvider* resource_provider,
-                      ResourceId resource_id);
-    ~ScopedWriteLockGr();
-
-    void InitSkSurface(GrContext* gr_context,
-                       bool use_distance_field_text,
-                       bool can_use_lcd_text,
-                       int msaa_sample_count);
-    void ReleaseSkSurface();
-
-    SkSurface* sk_surface() { return sk_surface_.get(); }
-
-    gfx::Size GetResourceSize() const { return resource_->size; }
-
-    void UpdateResourceSyncToken(const gpu::SyncToken& sync_token) {
-      set_sync_token_ = true;
-      sync_token_ = sync_token;
-    }
-
-   private:
-    ResourceProvider* resource_provider_;
-    ResourceProvider::Resource* resource_;
-    base::ThreadChecker thread_checker_;
-    sk_sp<SkSurface> sk_surface_;
-    bool set_sync_token_;
-    gpu::SyncToken sync_token_;
-
-    DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockGr);
-  };
-
   class Fence : public base::RefCounted<Fence> {
    public:
     Fence() {}
diff --git a/cc/resources/video_resource_updater.cc b/cc/resources/video_resource_updater.cc
index 319e82e..ae02820 100644
--- a/cc/resources/video_resource_updater.cc
+++ b/cc/resources/video_resource_updater.cc
@@ -191,7 +191,8 @@
     gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
 
     gl->GenMailboxCHROMIUM(mailbox.name);
-    ResourceProvider::ScopedWriteLockGL lock(resource_provider_, resource_id);
+    ResourceProvider::ScopedWriteLockGL lock(resource_provider_, resource_id,
+                                             false);
     gl->ProduceTextureDirectCHROMIUM(
         lock.texture_id(),
         resource_provider_->GetResourceTextureTarget(resource_id),
@@ -584,9 +585,7 @@
   resource->add_ref();
 
   ResourceProvider::ScopedWriteLockGL lock(resource_provider_,
-                                           resource->resource_id());
-  uint32_t texture_id = lock.texture_id();
-
+                                           resource->resource_id(), false);
   DCHECK_EQ(
       resource_provider_->GetResourceTextureTarget(resource->resource_id()),
       (GLenum)GL_TEXTURE_2D);
@@ -594,7 +593,7 @@
   gl->WaitSyncTokenCHROMIUM(mailbox_holder.sync_token.GetConstData());
   uint32_t src_texture_id = gl->CreateAndConsumeTextureCHROMIUM(
       mailbox_holder.texture_target, mailbox_holder.mailbox.name);
-  gl->CopySubTextureCHROMIUM(src_texture_id, texture_id, 0, 0, 0, 0,
+  gl->CopySubTextureCHROMIUM(src_texture_id, lock.texture_id(), 0, 0, 0, 0,
                              output_plane_resource_size.width(),
                              output_plane_resource_size.height(), false, false,
                              false);
diff --git a/cc/test/fake_tile_manager.cc b/cc/test/fake_tile_manager.cc
index 8cf9842..ceb77d6 100644
--- a/cc/test/fake_tile_manager.cc
+++ b/cc/test/fake_tile_manager.cc
@@ -23,6 +23,9 @@
 base::LazyInstance<FakeTileTaskManagerImpl> g_fake_tile_task_manager =
     LAZY_INSTANCE_INITIALIZER;
 
+base::LazyInstance<FakeRasterBufferProviderImpl> g_fake_raster_buffer_provider =
+    LAZY_INSTANCE_INITIALIZER;
+
 }  // namespace
 
 FakeTileManager::FakeTileManager(TileManagerClient* client)
@@ -36,6 +39,7 @@
           LayerTreeSettings().software_decoded_image_budget_bytes) {
   SetResources(
       nullptr, &image_decode_controller_, g_fake_tile_task_manager.Pointer(),
+      g_fake_raster_buffer_provider.Pointer(),
       std::numeric_limits<size_t>::max(), false /* use_gpu_rasterization */);
 }
 
@@ -51,6 +55,7 @@
           LayerTreeSettings().software_decoded_image_budget_bytes) {
   SetResources(resource_pool, &image_decode_controller_,
                g_fake_tile_task_manager.Pointer(),
+               g_fake_raster_buffer_provider.Pointer(),
                std::numeric_limits<size_t>::max(),
                false /* use_gpu_rasterization */);
 }
diff --git a/cc/test/fake_tile_task_manager.cc b/cc/test/fake_tile_task_manager.cc
index cc70198..044de23 100644
--- a/cc/test/fake_tile_task_manager.cc
+++ b/cc/test/fake_tile_task_manager.cc
@@ -8,13 +8,7 @@
 
 namespace cc {
 
-FakeTileTaskManagerImpl::FakeTileTaskManagerImpl()
-    : raster_buffer_provider_(base::WrapUnique<RasterBufferProvider>(
-          new FakeRasterBufferProviderImpl)) {}
-
-FakeTileTaskManagerImpl::FakeTileTaskManagerImpl(
-    std::unique_ptr<RasterBufferProvider> raster_buffer_provider)
-    : raster_buffer_provider_(std::move(raster_buffer_provider)) {}
+FakeTileTaskManagerImpl::FakeTileTaskManagerImpl() {}
 
 FakeTileTaskManagerImpl::~FakeTileTaskManagerImpl() {
   DCHECK_EQ(0u, completed_tasks_.size());
@@ -42,8 +36,4 @@
 
 void FakeTileTaskManagerImpl::Shutdown() {}
 
-RasterBufferProvider* FakeTileTaskManagerImpl::GetRasterBufferProvider() const {
-  return raster_buffer_provider_.get();
-}
-
 }  // namespace cc
diff --git a/cc/test/fake_tile_task_manager.h b/cc/test/fake_tile_task_manager.h
index b6ee2cf..9c97ca0 100644
--- a/cc/test/fake_tile_task_manager.h
+++ b/cc/test/fake_tile_task_manager.h
@@ -15,19 +15,14 @@
 class FakeTileTaskManagerImpl : public TileTaskManager {
  public:
   FakeTileTaskManagerImpl();
-  // Ctor for custom raster buffer provider.
-  FakeTileTaskManagerImpl(
-      std::unique_ptr<RasterBufferProvider> raster_buffer_provider);
   ~FakeTileTaskManagerImpl() override;
 
   // Overridden from TileTaskManager:
   void ScheduleTasks(TaskGraph* graph) override;
   void CheckForCompletedTasks() override;
   void Shutdown() override;
-  RasterBufferProvider* GetRasterBufferProvider() const override;
 
  protected:
-  std::unique_ptr<RasterBufferProvider> raster_buffer_provider_;
   Task::Vector completed_tasks_;
 };
 
diff --git a/cc/test/layer_tree_pixel_resource_test.cc b/cc/test/layer_tree_pixel_resource_test.cc
index 4345d05..ca8cf5b 100644
--- a/cc/test/layer_tree_pixel_resource_test.cc
+++ b/cc/test/layer_tree_pixel_resource_test.cc
@@ -7,7 +7,6 @@
 #include "cc/layers/layer.h"
 #include "cc/raster/bitmap_raster_buffer_provider.h"
 #include "cc/raster/gpu_raster_buffer_provider.h"
-#include "cc/raster/gpu_rasterizer.h"
 #include "cc/raster/one_copy_raster_buffer_provider.h"
 #include "cc/raster/raster_buffer_provider.h"
 #include "cc/raster/zero_copy_raster_buffer_provider.h"
@@ -142,7 +141,7 @@
 
       *raster_buffer_provider = base::MakeUnique<GpuRasterBufferProvider>(
           compositor_context_provider, worker_context_provider,
-          resource_provider, false, 0);
+          resource_provider, false, 0, false);
       break;
     case RASTER_BUFFER_PROVIDER_TYPE_ZERO_COPY:
       EXPECT_TRUE(compositor_context_provider);
@@ -161,8 +160,8 @@
       *raster_buffer_provider = base::MakeUnique<OneCopyRasterBufferProvider>(
           task_runner, compositor_context_provider, worker_context_provider,
           resource_provider, max_bytes_per_copy_operation, false,
-          max_staging_buffer_usage_in_bytes,
-          PlatformColor::BestTextureFormat());
+          max_staging_buffer_usage_in_bytes, PlatformColor::BestTextureFormat(),
+          false);
       break;
   }
 }
diff --git a/cc/tiles/tile_manager.cc b/cc/tiles/tile_manager.cc
index aab3047..3f83286 100644
--- a/cc/tiles/tile_manager.cc
+++ b/cc/tiles/tile_manager.cc
@@ -347,8 +347,9 @@
   // uninitialized resources.
   tile_task_manager_->Shutdown();
 
-  // Now that all tasks have been finished, we can clear any
-  // |orphan_tasks_|.
+  raster_buffer_provider_->Shutdown();
+
+  // Now that all tasks have been finished, we can clear any |orphan_tasks_|.
   orphan_tasks_.clear();
 
   tile_task_manager_->CheckForCompletedTasks();
@@ -370,6 +371,7 @@
 void TileManager::SetResources(ResourcePool* resource_pool,
                                ImageDecodeController* image_decode_controller,
                                TileTaskManager* tile_task_manager,
+                               RasterBufferProvider* raster_buffer_provider,
                                size_t scheduled_raster_task_limit,
                                bool use_gpu_rasterization) {
   DCHECK(!tile_task_manager_);
@@ -380,6 +382,7 @@
   resource_pool_ = resource_pool;
   image_decode_controller_ = image_decode_controller;
   tile_task_manager_ = tile_task_manager;
+  raster_buffer_provider_ = raster_buffer_provider;
 }
 
 void TileManager::Release(Tile* tile) {
@@ -878,6 +881,11 @@
   // below, so we do a swap instead of a move.
   locked_images_.swap(new_locked_images);
 
+  // We must reduce the amount of unused resources before calling
+  // ScheduleTasks to prevent usage from rising above limits.
+  resource_pool_->ReduceResourceUsage();
+  image_decode_controller_->ReduceCacheUsage();
+
   // Insert nodes for our task completion tasks. We enqueue these using
   // NONCONCURRENT_FOREGROUND category this is the highest prioirty category and
   // we'd like to run these tasks as soon as possible.
@@ -892,10 +900,8 @@
                     TASK_CATEGORY_NONCONCURRENT_FOREGROUND,
                     kAllDoneTaskPriority, all_count);
 
-  // We must reduce the amount of unused resoruces before calling
-  // ScheduleTasks to prevent usage from rising above limits.
-  resource_pool_->ReduceResourceUsage();
-  image_decode_controller_->ReduceCacheUsage();
+  // Synchronize worker with compositor.
+  raster_buffer_provider_->OrderingBarrier();
 
   // Schedule running of |raster_queue_|. This replaces any previously
   // scheduled tasks and effectively cancels all tasks not present
@@ -974,7 +980,7 @@
 
   bool supports_concurrent_execution = !use_gpu_rasterization_;
   std::unique_ptr<RasterBuffer> raster_buffer =
-      tile_task_manager_->GetRasterBufferProvider()->AcquireBufferForRaster(
+      raster_buffer_provider_->AcquireBufferForRaster(
           resource, resource_content_id, tile->invalidated_id());
   return make_scoped_refptr(new RasterTaskImpl(
       this, tile, resource, prioritized_tile.raster_source(), playback_settings,
@@ -989,8 +995,7 @@
     bool was_canceled) {
   DCHECK(tile);
   DCHECK(tiles_.find(tile->id()) != tiles_.end());
-  tile_task_manager_->GetRasterBufferProvider()->ReleaseBufferForRaster(
-      std::move(raster_buffer));
+  raster_buffer_provider_->ReleaseBufferForRaster(std::move(raster_buffer));
 
   TileDrawInfo& draw_info = tile->draw_info();
   DCHECK(tile->raster_task_.get());
@@ -1046,6 +1051,11 @@
   tile_task_manager_ = tile_task_manager;
 }
 
+void TileManager::SetRasterBufferProviderForTesting(
+    RasterBufferProvider* raster_buffer_provider) {
+  raster_buffer_provider_ = raster_buffer_provider;
+}
+
 bool TileManager::AreRequiredTilesReadyToDraw(
     RasterTilePriorityQueue::Type type) const {
   std::unique_ptr<RasterTilePriorityQueue> raster_priority_queue(
@@ -1215,13 +1225,12 @@
 }
 
 ResourceFormat TileManager::DetermineResourceFormat(const Tile* tile) const {
-  return tile_task_manager_->GetRasterBufferProvider()->GetResourceFormat(
-      !tile->is_opaque());
+  return raster_buffer_provider_->GetResourceFormat(!tile->is_opaque());
 }
 
 bool TileManager::DetermineResourceRequiresSwizzle(const Tile* tile) const {
-  return tile_task_manager_->GetRasterBufferProvider()
-      ->GetResourceRequiresSwizzle(!tile->is_opaque());
+  return raster_buffer_provider_->GetResourceRequiresSwizzle(
+      !tile->is_opaque());
 }
 
 std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
diff --git a/cc/tiles/tile_manager.h b/cc/tiles/tile_manager.h
index 588bed8..87a8e5c 100644
--- a/cc/tiles/tile_manager.h
+++ b/cc/tiles/tile_manager.h
@@ -120,6 +120,7 @@
   void SetResources(ResourcePool* resource_pool,
                     ImageDecodeController* image_decode_controller,
                     TileTaskManager* tile_task_manager,
+                    RasterBufferProvider* raster_buffer_provider,
                     size_t scheduled_raster_task_limit,
                     bool use_gpu_rasterization);
 
@@ -148,8 +149,7 @@
       TileDrawInfo& draw_info = tiles[i]->draw_info();
       draw_info.resource_ = resource_pool_->AcquireResource(
           tiles[i]->desired_texture_size(),
-          tile_task_manager_->GetRasterBufferProvider()->GetResourceFormat(
-              false));
+          raster_buffer_provider_->GetResourceFormat(false));
     }
   }
 
@@ -167,6 +167,9 @@
 
   void SetTileTaskManagerForTesting(TileTaskManager* tile_task_manager);
 
+  void SetRasterBufferProviderForTesting(
+      RasterBufferProvider* raster_buffer_provider);
+
   void FreeResourcesAndCleanUpReleasedTilesForTesting() {
     FreeResourcesForReleasedTiles();
     CleanUpReleasedTiles();
@@ -294,6 +297,7 @@
   base::SequencedTaskRunner* task_runner_;
   ResourcePool* resource_pool_;
   TileTaskManager* tile_task_manager_;
+  RasterBufferProvider* raster_buffer_provider_;
   GlobalStateThatImpactsTilePriority global_state_;
   size_t scheduled_raster_task_limit_;
   const bool use_partial_raster_;
diff --git a/cc/tiles/tile_manager_unittest.cc b/cc/tiles/tile_manager_unittest.cc
index f910c7a..0492417 100644
--- a/cc/tiles/tile_manager_unittest.cc
+++ b/cc/tiles/tile_manager_unittest.cc
@@ -1811,15 +1811,6 @@
   uint64_t expected_resource_id_;
 };
 
-class VerifyResourceContentIdTileTaskManager : public FakeTileTaskManagerImpl {
- public:
-  explicit VerifyResourceContentIdTileTaskManager(uint64_t expected_resource_id)
-      : FakeTileTaskManagerImpl(base::WrapUnique<RasterBufferProvider>(
-            new VerifyResourceContentIdRasterBufferProvider(
-                expected_resource_id))) {}
-  ~VerifyResourceContentIdTileTaskManager() override {}
-};
-
 // Runs a test to ensure that partial raster is either enabled or disabled,
 // depending on |partial_raster_enabled|'s value. Takes ownership of host_impl
 // so that cleanup order can be controlled.
@@ -1833,9 +1824,13 @@
 
   // Create a VerifyResourceContentIdTileTaskManager to ensure that the
   // raster task we see is created with |kExpectedId|.
-  VerifyResourceContentIdTileTaskManager verifying_task_manager(kExpectedId);
-  host_impl->tile_manager()->SetTileTaskManagerForTesting(
-      &verifying_task_manager);
+  FakeTileTaskManagerImpl tile_task_manager;
+  host_impl->tile_manager()->SetTileTaskManagerForTesting(&tile_task_manager);
+
+  VerifyResourceContentIdRasterBufferProvider raster_buffer_provider(
+      kExpectedId);
+  host_impl->tile_manager()->SetRasterBufferProviderForTesting(
+      &raster_buffer_provider);
 
   // Ensure there's a resource with our |kInvalidatedId| in the resource pool.
   host_impl->resource_pool()->ReleaseResource(
diff --git a/cc/tiles/tile_task_manager.cc b/cc/tiles/tile_task_manager.cc
index aa6466ff..b57b0572 100644
--- a/cc/tiles/tile_task_manager.cc
+++ b/cc/tiles/tile_task_manager.cc
@@ -15,25 +15,19 @@
 
 // static
 std::unique_ptr<TileTaskManagerImpl> TileTaskManagerImpl::Create(
-    std::unique_ptr<RasterBufferProvider> raster_buffer_provider,
     TaskGraphRunner* task_graph_runner) {
-  return base::WrapUnique<TileTaskManagerImpl>(new TileTaskManagerImpl(
-      std::move(raster_buffer_provider), task_graph_runner));
+  return base::WrapUnique<TileTaskManagerImpl>(
+      new TileTaskManagerImpl(task_graph_runner));
 }
 
-TileTaskManagerImpl::TileTaskManagerImpl(
-    std::unique_ptr<RasterBufferProvider> raster_buffer_provider,
-    TaskGraphRunner* task_graph_runner)
-    : raster_buffer_provider_(std::move(raster_buffer_provider)),
-      task_graph_runner_(task_graph_runner),
+TileTaskManagerImpl::TileTaskManagerImpl(TaskGraphRunner* task_graph_runner)
+    : task_graph_runner_(task_graph_runner),
       namespace_token_(task_graph_runner->GetNamespaceToken()) {}
 
 TileTaskManagerImpl::~TileTaskManagerImpl() {}
 
 void TileTaskManagerImpl::ScheduleTasks(TaskGraph* graph) {
   TRACE_EVENT0("cc", "TileTaskManagerImpl::ScheduleTasks");
-
-  raster_buffer_provider_->OrderingBarrier();
   task_graph_runner_->ScheduleTasks(namespace_token_, graph);
 }
 
@@ -57,12 +51,6 @@
   TaskGraph empty;
   task_graph_runner_->ScheduleTasks(namespace_token_, &empty);
   task_graph_runner_->WaitForTasksToFinishRunning(namespace_token_);
-
-  raster_buffer_provider_->Shutdown();
-}
-
-RasterBufferProvider* TileTaskManagerImpl::GetRasterBufferProvider() const {
-  return raster_buffer_provider_.get();
 }
 
 }  // namespace cc
diff --git a/cc/tiles/tile_task_manager.h b/cc/tiles/tile_task_manager.h
index 60294d6..7f543c1 100644
--- a/cc/tiles/tile_task_manager.h
+++ b/cc/tiles/tile_task_manager.h
@@ -32,9 +32,6 @@
 
   // Shutdown after canceling all previously scheduled tasks.
   virtual void Shutdown() = 0;
-
-  // Get RasterBufferProvider.
-  virtual RasterBufferProvider* GetRasterBufferProvider() const = 0;
 };
 
 class CC_EXPORT TileTaskManagerImpl : public TileTaskManager {
@@ -42,21 +39,16 @@
   ~TileTaskManagerImpl() override;
 
   static std::unique_ptr<TileTaskManagerImpl> Create(
-      std::unique_ptr<RasterBufferProvider> raster_buffer_provider,
       TaskGraphRunner* task_graph_runner);
 
   // Overridden from TileTaskManager:
   void ScheduleTasks(TaskGraph* graph) override;
   void CheckForCompletedTasks() override;
   void Shutdown() override;
-  RasterBufferProvider* GetRasterBufferProvider() const override;
 
  protected:
-  TileTaskManagerImpl(
-      std::unique_ptr<RasterBufferProvider> raster_buffer_provider,
-      TaskGraphRunner* task_graph_runner);
+  explicit TileTaskManagerImpl(TaskGraphRunner* task_graph_runner);
 
-  std::unique_ptr<RasterBufferProvider> raster_buffer_provider_;
   TaskGraphRunner* task_graph_runner_;
   const NamespaceToken namespace_token_;
 
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 6d8aaa6..053ae802 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -62,7 +62,6 @@
 #include "cc/quads/texture_draw_quad.h"
 #include "cc/raster/bitmap_raster_buffer_provider.h"
 #include "cc/raster/gpu_raster_buffer_provider.h"
-#include "cc/raster/gpu_rasterizer.h"
 #include "cc/raster/one_copy_raster_buffer_provider.h"
 #include "cc/raster/raster_buffer_provider.h"
 #include "cc/raster/synchronous_task_graph_runner.h"
@@ -2168,8 +2167,7 @@
 }
 
 void LayerTreeHostImpl::CreateTileManagerResources() {
-  std::unique_ptr<RasterBufferProvider> raster_buffer_provider;
-  CreateResourceAndRasterBufferProvider(&raster_buffer_provider,
+  CreateResourceAndRasterBufferProvider(&raster_buffer_provider_,
                                         &resource_pool_);
 
   if (use_gpu_rasterization_) {
@@ -2194,13 +2192,12 @@
     task_graph_runner = single_thread_synchronous_task_graph_runner_.get();
   }
 
-  tile_task_manager_ = TileTaskManagerImpl::Create(
-      std::move(raster_buffer_provider), task_graph_runner);
+  tile_task_manager_ = TileTaskManagerImpl::Create(task_graph_runner);
 
   // TODO(vmpstr): Initialize tile task limit at ctor time.
   tile_manager_.SetResources(
       resource_pool_.get(), image_decode_controller_.get(),
-      tile_task_manager_.get(),
+      tile_task_manager_.get(), raster_buffer_provider_.get(),
       is_synchronous_single_threaded_ ? std::numeric_limits<size_t>::max()
                                       : settings_.scheduled_raster_task_limit,
       use_gpu_rasterization_);
@@ -2239,7 +2236,7 @@
     *raster_buffer_provider = base::MakeUnique<GpuRasterBufferProvider>(
         compositor_context_provider, worker_context_provider,
         resource_provider_.get(), settings_.use_distance_field_text,
-        msaa_sample_count);
+        msaa_sample_count, settings_.async_worker_context_enabled);
     return;
   }
 
@@ -2275,7 +2272,8 @@
       GetTaskRunner(), compositor_context_provider, worker_context_provider,
       resource_provider_.get(), max_copy_texture_chromium_size,
       settings_.use_partial_raster, settings_.max_staging_buffer_usage_in_bytes,
-      settings_.renderer_settings.preferred_tile_format);
+      settings_.renderer_settings.preferred_tile_format,
+      settings_.async_worker_context_enabled);
 }
 
 void LayerTreeHostImpl::SetLayerTreeMutator(
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index fad9db7b..fc802c8f 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -738,6 +738,7 @@
   bool use_msaa_;
   GpuRasterizationStatus gpu_rasterization_status_;
   bool tree_resources_for_gpu_rasterization_dirty_;
+  std::unique_ptr<RasterBufferProvider> raster_buffer_provider_;
   std::unique_ptr<TileTaskManager> tile_task_manager_;
   std::unique_ptr<ResourcePool> resource_pool_;
   std::unique_ptr<Renderer> renderer_;
diff --git a/cc/trees/layer_tree_host_unittest_context.cc b/cc/trees/layer_tree_host_unittest_context.cc
index 2f4c242..fd9e73f 100644
--- a/cc/trees/layer_tree_host_unittest_context.cc
+++ b/cc/trees/layer_tree_host_unittest_context.cc
@@ -942,7 +942,7 @@
     ResourceId resource = child_resource_provider_->CreateResource(
         gfx::Size(4, 4), ResourceProvider::TEXTURE_HINT_IMMUTABLE, RGBA_8888);
     ResourceProvider::ScopedWriteLockGL lock(child_resource_provider_.get(),
-                                             resource);
+                                             resource, false);
 
     gpu::Mailbox mailbox;
     gl->GenMailboxCHROMIUM(mailbox.name);