[go: nahoru, domu]

Move ownership of gpu texture resources to ResourcePool

This makes allocation of resources in OneCopyRasterBufferProvider
and GpuRasterBufferProvider happen directly instead of through
a ResourceProvider lock, and stores ownership of the resources in the
ResourcePool. For each RasterBufferProvider,
a) When AcquireBufferForRaster is called it creates the GpuBacking
and ensures the sync token is waited on if present, and creates a texture
and mailbox.
b) After playback on the worker, a sync token is created.
c) When the RasterBuffer is destroyed, back on the compositor thread,
it stores that sync token into the GpuBacking.

R=sunnyps@chromium.org, vmpstr@chromium.org

Bug: 730660, 738190
Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.android:android_optional_gpu_tests_rel
Change-Id: Ide0005262435cc4a0925766761221dc8852f0026
Reviewed-on: https://chromium-review.googlesource.com/895806
Commit-Queue: danakj <danakj@chromium.org>
Reviewed-by: Sunny Sachanandani <sunnyps@chromium.org>
Reviewed-by: Eric Karl <ericrk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#535741}
diff --git a/cc/raster/gpu_raster_buffer_provider.cc b/cc/raster/gpu_raster_buffer_provider.cc
index 58f2663b..ed755ba 100644
--- a/cc/raster/gpu_raster_buffer_provider.cc
+++ b/cc/raster/gpu_raster_buffer_provider.cc
@@ -21,15 +21,19 @@
 #include "cc/resources/resource.h"
 #include "components/viz/common/gpu/context_provider.h"
 #include "components/viz/common/gpu/raster_context_provider.h"
+#include "components/viz/common/gpu/texture_allocation.h"
 #include "components/viz/common/resources/resource_format_utils.h"
+#include "gpu/GLES2/gl2extchromium.h"
 #include "gpu/command_buffer/client/context_support.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
 #include "gpu/command_buffer/client/raster_interface.h"
+#include "gpu/command_buffer/common/gpu_memory_buffer_support.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"
 #include "ui/gfx/geometry/axis_transform2d.h"
+#include "ui/gl/trace_util.h"
 
 namespace cc {
 namespace {
@@ -37,21 +41,37 @@
 static void RasterizeSourceOOP(
     const RasterSource* raster_source,
     bool resource_has_previous_content,
+    const gpu::Mailbox& mailbox,
+    GLenum texture_target,
+    bool texture_is_overlay_candidate,
+    bool texture_storage_allocated,
+    const gfx::Size& resource_size,
+    viz::ResourceFormat resource_format,
+    const gfx::ColorSpace& color_space,
     const gfx::Rect& raster_full_rect,
     const gfx::Rect& playback_rect,
     const gfx::AxisTransform2d& transform,
     const RasterSource::PlaybackSettings& playback_settings,
     viz::RasterContextProvider* context_provider,
-    LayerTreeResourceProvider::ScopedWriteLockRaster* resource_lock,
     bool use_distance_field_text,
     int msaa_sample_count) {
   gpu::raster::RasterInterface* ri = context_provider->RasterInterface();
-  GLuint texture_id = resource_lock->ConsumeTexture(ri);
+  GLuint texture_id = ri->CreateAndConsumeTextureCHROMIUM(mailbox.name);
+  if (!texture_storage_allocated) {
+    viz::TextureAllocation alloc = {texture_id, texture_target,
+                                    texture_is_overlay_candidate};
+    viz::TextureAllocation::AllocateStorage(
+        ri, context_provider->ContextCapabilities(), resource_format,
+        resource_size, alloc, color_space);
+  }
 
-  ri->BeginRasterCHROMIUM(texture_id, raster_source->background_color(),
-                          msaa_sample_count, playback_settings.use_lcd_text,
-                          use_distance_field_text, resource_lock->ColorType(),
-                          playback_settings.raster_color_space);
+  // TODO(enne): Use the |texture_target|? GpuMemoryBuffer backed textures don't
+  // use GL_TEXTURE_2D.
+  ri->BeginRasterCHROMIUM(
+      texture_id, raster_source->background_color(), msaa_sample_count,
+      playback_settings.use_lcd_text, use_distance_field_text,
+      viz::ResourceFormatToClosestSkColorType(resource_format),
+      playback_settings.raster_color_space);
   float recording_to_raster_scale =
       transform.scale() / raster_source->recording_scale_factor();
   gfx::Size content_size = raster_source->GetContentSize(transform.scale());
@@ -92,23 +112,36 @@
 static void RasterizeSource(
     const RasterSource* raster_source,
     bool resource_has_previous_content,
+    const gpu::Mailbox& mailbox,
+    GLenum texture_target,
+    bool texture_is_overlay_candidate,
+    bool texture_storage_allocated,
+    const gfx::Size& resource_size,
+    viz::ResourceFormat resource_format,
+    const gfx::ColorSpace& color_space,
     const gfx::Rect& raster_full_rect,
     const gfx::Rect& playback_rect,
     const gfx::AxisTransform2d& transform,
     const RasterSource::PlaybackSettings& playback_settings,
     viz::RasterContextProvider* context_provider,
-    LayerTreeResourceProvider::ScopedWriteLockRaster* resource_lock,
     bool use_distance_field_text,
     int msaa_sample_count) {
   ScopedGrContextAccess gr_context_access(context_provider);
 
   gpu::raster::RasterInterface* ri = context_provider->RasterInterface();
-  GLuint texture_id = resource_lock->ConsumeTexture(ri);
+  GLuint texture_id = ri->CreateAndConsumeTextureCHROMIUM(mailbox.name);
+  if (!texture_storage_allocated) {
+    viz::TextureAllocation alloc = {texture_id, texture_target,
+                                    texture_is_overlay_candidate};
+    viz::TextureAllocation::AllocateStorage(
+        ri, context_provider->ContextCapabilities(), resource_format,
+        resource_size, alloc, color_space);
+  }
 
   {
     LayerTreeResourceProvider::ScopedSkSurface scoped_surface(
-        context_provider->GrContext(), texture_id, resource_lock->target(),
-        resource_lock->size(), resource_lock->format(), use_distance_field_text,
+        context_provider->GrContext(), texture_id, texture_target,
+        resource_size, resource_format, use_distance_field_text,
         playback_settings.use_lcd_text, msaa_sample_count);
 
     SkSurface* surface = scoped_surface.surface();
@@ -127,9 +160,9 @@
       canvas->discard();
 
     gfx::Size content_size = raster_source->GetContentSize(transform.scale());
-    raster_source->PlaybackToCanvas(
-        canvas, resource_lock->color_space_for_raster(), content_size,
-        raster_full_rect, playback_rect, transform, playback_settings);
+    raster_source->PlaybackToCanvas(canvas, color_space, content_size,
+                                    raster_full_rect, playback_rect, transform,
+                                    playback_settings);
   }
 
   ri->DeleteTextures(1, &texture_id);
@@ -137,20 +170,69 @@
 
 }  // namespace
 
+// Subclass for InUsePoolResource that holds ownership of a gpu-rastered backing
+// and does cleanup of the backing when destroyed.
+class GpuRasterBufferProvider::GpuRasterBacking
+    : public ResourcePool::GpuBacking {
+ public:
+  ~GpuRasterBacking() override {
+    gpu::gles2::GLES2Interface* gl = compositor_context_provider->ContextGL();
+    if (returned_sync_token.HasData())
+      gl->WaitSyncTokenCHROMIUM(returned_sync_token.GetConstData());
+    if (mailbox_sync_token.HasData())
+      gl->WaitSyncTokenCHROMIUM(mailbox_sync_token.GetConstData());
+    if (texture_id)
+      gl->DeleteTextures(1, &texture_id);
+  }
+
+  base::trace_event::MemoryAllocatorDumpGuid MemoryDumpGuid(
+      uint64_t tracing_process_id) override {
+    return gl::GetGLTextureClientGUIDForTracing(
+        compositor_context_provider->ContextSupport()->ShareGroupTracingGUID(),
+        texture_id);
+  }
+  base::UnguessableToken SharedMemoryGuid() override { return {}; }
+
+  // The ContextProvider used to clean up the texture id.
+  viz::ContextProvider* compositor_context_provider = nullptr;
+  // The texture backing of the resource.
+  GLuint texture_id = 0;
+  // The allocation of storage for the |texture_id| is deferred, and this tracks
+  // if it has been done.
+  bool storage_allocated = false;
+};
+
 GpuRasterBufferProvider::RasterBufferImpl::RasterBufferImpl(
     GpuRasterBufferProvider* client,
-    LayerTreeResourceProvider* resource_provider,
-    viz::ResourceId resource_id,
+    const ResourcePool::InUsePoolResource& in_use_resource,
+    GpuRasterBacking* backing,
     bool resource_has_previous_content)
     : client_(client),
-      lock_(resource_provider, resource_id),
-      resource_has_previous_content_(resource_has_previous_content) {
+      backing_(backing),
+      resource_size_(in_use_resource.size()),
+      resource_format_(in_use_resource.format()),
+      color_space_(in_use_resource.color_space()),
+      resource_has_previous_content_(resource_has_previous_content),
+      returned_sync_token_(backing->returned_sync_token),
+      mailbox_(backing->mailbox),
+      texture_target_(backing->texture_target),
+      texture_is_overlay_candidate_(backing->overlay_candidate),
+      texture_storage_allocated_(backing->storage_allocated) {
   client_->pending_raster_buffers_.insert(this);
-  lock_.CreateMailbox();
 }
 
 GpuRasterBufferProvider::RasterBufferImpl::~RasterBufferImpl() {
   client_->pending_raster_buffers_.erase(this);
+
+  // This SyncToken was created on the worker context after rastering the
+  // texture content.
+  backing_->mailbox_sync_token = after_raster_sync_token_;
+  if (after_raster_sync_token_.HasData()) {
+    // The returned SyncToken was waited on in Playback. We know Playback
+    // happened if the |after_raster_sync_token_| was set.
+    backing_->returned_sync_token = gpu::SyncToken();
+  }
+  backing_->storage_allocated = texture_storage_allocated_;
 }
 
 void GpuRasterBufferProvider::RasterBufferImpl::Playback(
@@ -161,10 +243,23 @@
     const gfx::AxisTransform2d& transform,
     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, transform, playback_settings);
+  // Either a SyncToken had to be made in OrderingBarrier, because a texture
+  // was made in AcquireBufferForRaster, or a texture already existed and we're
+  // reusing it. In that case a SyncToken was on the GpuBacking that we must
+  // wait on befor using the texture.
+  if (returned_sync_token_.HasData())
+    before_raster_sync_token_ = returned_sync_token_;
+  // The |sync_token_| passed in here was created on the compositor thread, or
+  // given back with the texture for reuse. This call returns another SyncToken
+  // generated on the worker thread to synchronize with after the raster is
+  // complete.
+  after_raster_sync_token_ = client_->PlaybackOnWorkerThread(
+      mailbox_, texture_target_, texture_is_overlay_candidate_,
+      texture_storage_allocated_, before_raster_sync_token_, resource_size_,
+      resource_format_, color_space_, resource_has_previous_content_,
+      raster_source, raster_full_rect, raster_dirty_rect, new_content_id,
+      transform, playback_settings);
+  texture_storage_allocated_ = true;
 }
 
 GpuRasterBufferProvider::GpuRasterBufferProvider(
@@ -172,6 +267,7 @@
     viz::RasterContextProvider* worker_context_provider,
     LayerTreeResourceProvider* resource_provider,
     bool use_distance_field_text,
+    bool use_gpu_memory_buffer_resources,
     int gpu_rasterization_msaa_sample_count,
     viz::ResourceFormat preferred_tile_format,
     bool enable_oop_rasterization)
@@ -179,6 +275,7 @@
       worker_context_provider_(worker_context_provider),
       resource_provider_(resource_provider),
       use_distance_field_text_(use_distance_field_text),
+      use_gpu_memory_buffer_resources_(use_gpu_memory_buffer_resources),
       msaa_sample_count_(gpu_rasterization_msaa_sample_count),
       preferred_tile_format_(preferred_tile_format),
       enable_oop_rasterization_(enable_oop_rasterization) {
@@ -194,10 +291,34 @@
     const ResourcePool::InUsePoolResource& resource,
     uint64_t resource_content_id,
     uint64_t previous_content_id) {
+  if (!resource.gpu_backing()) {
+    auto backing = std::make_unique<GpuRasterBacking>();
+    backing->compositor_context_provider = compositor_context_provider_;
+
+    gpu::gles2::GLES2Interface* gl = compositor_context_provider_->ContextGL();
+    const auto& caps = compositor_context_provider_->ContextCapabilities();
+
+    viz::TextureAllocation alloc = viz::TextureAllocation::MakeTextureId(
+        gl, caps, resource.format(), use_gpu_memory_buffer_resources_,
+        /*for_framebuffer_attachment=*/true);
+    backing->texture_id = alloc.texture_id;
+    backing->texture_target = alloc.texture_target;
+    backing->overlay_candidate = alloc.overlay_candidate;
+    backing->mailbox = gpu::Mailbox::Generate();
+    // The SyncToken in order to use this mailbox on another context will be
+    // generated later by OrderingBarrier(), once for all mailboxes made at a
+    // given time.
+    gl->ProduceTextureDirectCHROMIUM(backing->texture_id,
+                                     backing->mailbox.name);
+
+    resource.set_gpu_backing(std::move(backing));
+  }
+  GpuRasterBacking* backing =
+      static_cast<GpuRasterBacking*>(resource.gpu_backing());
+
   bool resource_has_previous_content =
       resource_content_id && resource_content_id == previous_content_id;
-  return std::make_unique<RasterBufferImpl>(this, resource_provider_,
-                                            resource.gpu_backing_resource_id(),
+  return std::make_unique<RasterBufferImpl>(this, resource, backing,
                                             resource_has_previous_content);
 }
 
@@ -243,10 +364,10 @@
 
 bool GpuRasterBufferProvider::IsResourceReadyToDraw(
     const ResourcePool::InUsePoolResource& resource) const {
-  gpu::SyncToken sync_token = resource_provider_->GetSyncTokenForResources(
-      {resource.gpu_backing_resource_id()});
-  if (!sync_token.HasData())
-    return true;
+  const gpu::SyncToken& sync_token = resource.gpu_backing()->mailbox_sync_token;
+  // This SyncToken() should have been set by calling OrderingBarrier() before
+  // calling this.
+  DCHECK(sync_token.HasData());
 
   // IsSyncTokenSignaled is thread-safe, no need for worker context lock.
   return worker_context_provider_->ContextSupport()->IsSyncTokenSignaled(
@@ -257,23 +378,24 @@
     const std::vector<const ResourcePool::InUsePoolResource*>& resources,
     const base::Closure& callback,
     uint64_t pending_callback_id) const {
-  std::vector<viz::ResourceId> resource_ids;
-  resource_ids.reserve(resources.size());
-  for (auto* resource : resources)
-    resource_ids.push_back(resource->gpu_backing_resource_id());
-  gpu::SyncToken sync_token =
-      resource_provider_->GetSyncTokenForResources(resource_ids);
-  uint64_t callback_id = sync_token.release_count();
+  gpu::SyncToken latest_sync_token;
+  for (const auto* in_use : resources) {
+    const gpu::SyncToken& sync_token =
+        in_use->gpu_backing()->mailbox_sync_token;
+    if (sync_token.release_count() > latest_sync_token.release_count())
+      latest_sync_token = sync_token;
+  }
+  uint64_t callback_id = latest_sync_token.release_count();
   DCHECK_NE(callback_id, 0u);
 
   // If the callback is different from the one the caller is already waiting on,
   // pass the callback through to SignalSyncToken. Otherwise the request is
   // redundant.
   if (callback_id != pending_callback_id) {
-    // Use the compositor context because we want this callback on the impl
-    // thread.
-    compositor_context_provider_->ContextSupport()->SignalSyncToken(sync_token,
-                                                                    callback);
+    // Use the compositor context because we want this callback on the
+    // compositor thread.
+    compositor_context_provider_->ContextSupport()->SignalSyncToken(
+        latest_sync_token, callback);
   }
 
   return callback_id;
@@ -283,9 +405,15 @@
   pending_raster_buffers_.clear();
 }
 
-void GpuRasterBufferProvider::PlaybackOnWorkerThread(
-    LayerTreeResourceProvider::ScopedWriteLockRaster* resource_lock,
+gpu::SyncToken GpuRasterBufferProvider::PlaybackOnWorkerThread(
+    const gpu::Mailbox& mailbox,
+    GLenum texture_target,
+    bool texture_is_overlay_candidate,
+    bool texture_storage_allocated,
     const gpu::SyncToken& sync_token,
+    const gfx::Size& resource_size,
+    viz::ResourceFormat resource_format,
+    const gfx::ColorSpace& color_space,
     bool resource_has_previous_content,
     const RasterSource* raster_source,
     const gfx::Rect& raster_full_rect,
@@ -298,7 +426,9 @@
   gpu::raster::RasterInterface* ri = scoped_context.RasterInterface();
   DCHECK(ri);
 
-  // Synchronize with compositor. Nop if sync token is empty.
+  // Wait on the SyncToken that was created on the compositor thread after
+  // making the mailbox. This ensures that the mailbox we consume here is valid
+  // by the time the consume command executes.
   ri->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
 
   gfx::Rect playback_rect = raster_full_rect;
@@ -324,19 +454,22 @@
 
   if (enable_oop_rasterization_) {
     RasterizeSourceOOP(
-        raster_source, resource_has_previous_content, raster_full_rect,
-        playback_rect, transform, playback_settings, worker_context_provider_,
-        resource_lock, use_distance_field_text_, msaa_sample_count_);
+        raster_source, resource_has_previous_content, mailbox, texture_target,
+        texture_is_overlay_candidate, texture_storage_allocated, resource_size,
+        resource_format, color_space, raster_full_rect, playback_rect,
+        transform, playback_settings, worker_context_provider_,
+        use_distance_field_text_, msaa_sample_count_);
   } else {
-    RasterizeSource(raster_source, resource_has_previous_content,
-                    raster_full_rect, playback_rect, transform,
-                    playback_settings, worker_context_provider_, resource_lock,
+    RasterizeSource(raster_source, resource_has_previous_content, mailbox,
+                    texture_target, texture_is_overlay_candidate,
+                    texture_storage_allocated, resource_size, resource_format,
+                    color_space, raster_full_rect, playback_rect, transform,
+                    playback_settings, worker_context_provider_,
                     use_distance_field_text_, msaa_sample_count_);
   }
 
   // Generate sync token for cross context synchronization.
-  resource_lock->set_sync_token(
-      LayerTreeResourceProvider::GenerateSyncTokenHelper(ri));
+  return LayerTreeResourceProvider::GenerateSyncTokenHelper(ri);
 }
 
 }  // namespace cc
diff --git a/cc/raster/gpu_raster_buffer_provider.h b/cc/raster/gpu_raster_buffer_provider.h
index 074cc55..15b40be 100644
--- a/cc/raster/gpu_raster_buffer_provider.h
+++ b/cc/raster/gpu_raster_buffer_provider.h
@@ -25,6 +25,7 @@
                           viz::RasterContextProvider* worker_context_provider,
                           LayerTreeResourceProvider* resource_provider,
                           bool use_distance_field_text,
+                          bool use_gpu_memory_buffer_resources,
                           int gpu_rasterization_msaa_sample_count,
                           viz::ResourceFormat preferred_tile_format,
                           bool enable_oop_rasterization);
@@ -48,9 +49,15 @@
       uint64_t pending_callback_id) const override;
   void Shutdown() override;
 
-  void PlaybackOnWorkerThread(
-      LayerTreeResourceProvider::ScopedWriteLockRaster* resource_lock,
+  gpu::SyncToken PlaybackOnWorkerThread(
+      const gpu::Mailbox& mailbox,
+      GLenum texture_target,
+      bool texture_is_overlay_candidate,
+      bool texture_storage_allocated,
       const gpu::SyncToken& sync_token,
+      const gfx::Size& resource_size,
+      viz::ResourceFormat resource_format,
+      const gfx::ColorSpace& color_space,
       bool resource_has_previous_content,
       const RasterSource* raster_source,
       const gfx::Rect& raster_full_rect,
@@ -60,11 +67,13 @@
       const RasterSource::PlaybackSettings& playback_settings);
 
  private:
+  class GpuRasterBacking;
+
   class RasterBufferImpl : public RasterBuffer {
    public:
     RasterBufferImpl(GpuRasterBufferProvider* client,
-                     LayerTreeResourceProvider* resource_provider,
-                     viz::ResourceId resource_id,
+                     const ResourcePool::InUsePoolResource& in_use_resource,
+                     GpuRasterBacking* backing,
                      bool resource_has_previous_content);
     ~RasterBufferImpl() override;
 
@@ -78,15 +87,31 @@
         const RasterSource::PlaybackSettings& playback_settings) override;
 
     void set_sync_token(const gpu::SyncToken& sync_token) {
-      sync_token_ = sync_token;
+      before_raster_sync_token_ = sync_token;
     }
 
    private:
+    // These fields may only be used on the compositor thread.
     GpuRasterBufferProvider* const client_;
-    LayerTreeResourceProvider::ScopedWriteLockRaster lock_;
-    const bool resource_has_previous_content_;
+    GpuRasterBacking* backing_;
 
-    gpu::SyncToken sync_token_;
+    // These fields are for use on the worker thread.
+    const gfx::Size resource_size_;
+    const viz::ResourceFormat resource_format_;
+    const gfx::ColorSpace color_space_;
+    const bool resource_has_previous_content_;
+    const gpu::SyncToken returned_sync_token_;
+    const gpu::Mailbox mailbox_;
+    const GLenum texture_target_;
+    const bool texture_is_overlay_candidate_;
+    // Set to true once allocation is done in the worker thread.
+    bool texture_storage_allocated_;
+    // A SyncToken for the worker thread to consume before using the mailbox
+    // texture it is given.
+    gpu::SyncToken before_raster_sync_token_;
+    // A SyncToken to be returned from the worker thread, and waited on before
+    // using the rastered resource.
+    gpu::SyncToken after_raster_sync_token_;
 
     DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl);
   };
@@ -95,6 +120,7 @@
   viz::RasterContextProvider* const worker_context_provider_;
   LayerTreeResourceProvider* const resource_provider_;
   const bool use_distance_field_text_;
+  const bool use_gpu_memory_buffer_resources_;
   const int msaa_sample_count_;
   const viz::ResourceFormat preferred_tile_format_;
   const bool enable_oop_rasterization_;
diff --git a/cc/raster/one_copy_raster_buffer_provider.cc b/cc/raster/one_copy_raster_buffer_provider.cc
index 46d4a4b8..b168c8c 100644
--- a/cc/raster/one_copy_raster_buffer_provider.cc
+++ b/cc/raster/one_copy_raster_buffer_provider.cc
@@ -20,6 +20,7 @@
 #include "cc/resources/scoped_resource.h"
 #include "components/viz/common/gpu/context_provider.h"
 #include "components/viz/common/gpu/raster_context_provider.h"
+#include "components/viz/common/gpu/texture_allocation.h"
 #include "components/viz/common/resources/platform_color.h"
 #include "components/viz/common/resources/resource_format.h"
 #include "gpu/GLES2/gl2extchromium.h"
@@ -28,6 +29,7 @@
 #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
 #include "gpu/command_buffer/client/raster_interface.h"
 #include "ui/gfx/buffer_format_util.h"
+#include "ui/gl/trace_util.h"
 
 namespace cc {
 namespace {
@@ -38,22 +40,70 @@
 
 }  // namespace
 
+// Subclass for InUsePoolResource that holds ownership of a one-copy backing
+// and does cleanup of the backing when destroyed.
+class OneCopyRasterBufferProvider::OneCopyGpuBacking
+    : public ResourcePool::GpuBacking {
+ public:
+  ~OneCopyGpuBacking() override {
+    gpu::gles2::GLES2Interface* gl = compositor_context_provider->ContextGL();
+    if (returned_sync_token.HasData())
+      gl->WaitSyncTokenCHROMIUM(returned_sync_token.GetConstData());
+    if (mailbox_sync_token.HasData())
+      gl->WaitSyncTokenCHROMIUM(mailbox_sync_token.GetConstData());
+    if (texture_id)
+      gl->DeleteTextures(1, &texture_id);
+  }
+
+  base::trace_event::MemoryAllocatorDumpGuid MemoryDumpGuid(
+      uint64_t tracing_process_id) override {
+    return gl::GetGLTextureClientGUIDForTracing(
+        compositor_context_provider->ContextSupport()->ShareGroupTracingGUID(),
+        texture_id);
+  }
+  base::UnguessableToken SharedMemoryGuid() override { return {}; }
+
+  // The ContextProvider used to clean up the texture id.
+  viz::ContextProvider* compositor_context_provider = nullptr;
+  // The texture backing of the resource.
+  GLuint texture_id = 0;
+  // The allocation of storage for the |texture_id| is deferred, and this tracks
+  // if it has been done.
+  bool storage_allocated = false;
+};
+
 OneCopyRasterBufferProvider::RasterBufferImpl::RasterBufferImpl(
     OneCopyRasterBufferProvider* client,
     LayerTreeResourceProvider* resource_provider,
     const ResourcePool::InUsePoolResource& in_use_resource,
+    OneCopyGpuBacking* backing,
     uint64_t previous_content_id)
     : client_(client),
+      backing_(backing),
       resource_size_(in_use_resource.size()),
       resource_format_(in_use_resource.format()),
-      lock_(resource_provider, in_use_resource.gpu_backing_resource_id()),
-      previous_content_id_(previous_content_id) {
+      color_space_(in_use_resource.color_space()),
+      previous_content_id_(previous_content_id),
+      returned_sync_token_(backing->returned_sync_token),
+      mailbox_(backing->mailbox),
+      mailbox_texture_target_(backing->texture_target),
+      mailbox_texture_is_overlay_candidate_(backing->overlay_candidate),
+      mailbox_texture_storage_allocated_(backing->storage_allocated) {
   client_->pending_raster_buffers_.insert(this);
-  lock_.CreateMailbox();
 }
 
 OneCopyRasterBufferProvider::RasterBufferImpl::~RasterBufferImpl() {
   client_->pending_raster_buffers_.erase(this);
+
+  // This SyncToken was created on the worker context after uploading the
+  // texture content.
+  backing_->mailbox_sync_token = after_raster_sync_token_;
+  if (after_raster_sync_token_.HasData()) {
+    // The returned SyncToken was waited on in Playback. We know Playback
+    // happened if the |after_raster_sync_token_| was set.
+    backing_->returned_sync_token = gpu::SyncToken();
+  }
+  backing_->storage_allocated = mailbox_texture_storage_allocated_;
 }
 
 void OneCopyRasterBufferProvider::RasterBufferImpl::Playback(
@@ -64,10 +114,23 @@
     const gfx::AxisTransform2d& transform,
     const RasterSource::PlaybackSettings& playback_settings) {
   TRACE_EVENT0("cc", "OneCopyRasterBuffer::Playback");
-  client_->PlaybackAndCopyOnWorkerThread(
-      &lock_, sync_token_, raster_source, raster_full_rect, raster_dirty_rect,
-      transform, resource_size_, resource_format_, playback_settings,
+  // Either a SyncToken had to be made in OrderingBarrier, because a texture
+  // was made in AcquireBufferForRaster, or a texture already existed and we're
+  // reusing it. In that case a SyncToken was on the GpuBacking that we must
+  // wait on befor using the texture.
+  if (returned_sync_token_.HasData())
+    before_raster_sync_token_ = returned_sync_token_;
+  // The |sync_token_| passed in here was created on the compositor thread, or
+  // given back with the texture for reuse. This call returns another SyncToken
+  // generated on the worker thread to synchronize with after the raster is
+  // complete.
+  after_raster_sync_token_ = client_->PlaybackAndCopyOnWorkerThread(
+      mailbox_, mailbox_texture_target_, mailbox_texture_is_overlay_candidate_,
+      mailbox_texture_storage_allocated_, before_raster_sync_token_,
+      raster_source, raster_full_rect, raster_dirty_rect, transform,
+      resource_size_, resource_format_, color_space_, playback_settings,
       previous_content_id_, new_content_id);
+  mailbox_texture_storage_allocated_ = true;
 }
 
 OneCopyRasterBufferProvider::OneCopyRasterBufferProvider(
@@ -77,6 +140,7 @@
     LayerTreeResourceProvider* resource_provider,
     int max_copy_texture_chromium_size,
     bool use_partial_raster,
+    bool use_gpu_memory_buffer_resources,
     int max_staging_buffer_usage_in_bytes,
     viz::ResourceFormat preferred_tile_format)
     : compositor_context_provider_(compositor_context_provider),
@@ -88,6 +152,7 @@
                          max_copy_texture_chromium_size)
               : kMaxBytesPerCopyOperation),
       use_partial_raster_(use_partial_raster),
+      use_gpu_memory_buffer_resources_(use_gpu_memory_buffer_resources),
       bytes_scheduled_since_last_flush_(0),
       preferred_tile_format_(preferred_tile_format),
       staging_pool_(std::move(task_runner),
@@ -108,10 +173,35 @@
     const ResourcePool::InUsePoolResource& resource,
     uint64_t resource_content_id,
     uint64_t previous_content_id) {
+  if (!resource.gpu_backing()) {
+    auto backing = std::make_unique<OneCopyGpuBacking>();
+    backing->compositor_context_provider = compositor_context_provider_;
+
+    gpu::gles2::GLES2Interface* gl = compositor_context_provider_->ContextGL();
+    const auto& caps = compositor_context_provider_->ContextCapabilities();
+
+    viz::TextureAllocation alloc = viz::TextureAllocation::MakeTextureId(
+        gl, caps, resource.format(), use_gpu_memory_buffer_resources_,
+        /*for_framebuffer_attachment=*/true);
+    backing->texture_id = alloc.texture_id;
+    backing->texture_target = alloc.texture_target;
+    backing->overlay_candidate = alloc.overlay_candidate;
+    backing->mailbox = gpu::Mailbox::Generate();
+    // The SyncToken in order to use this mailbox on another context will be
+    // generated later by OrderingBarrier(), once for all mailboxes made at a
+    // given time.
+    gl->ProduceTextureDirectCHROMIUM(backing->texture_id,
+                                     backing->mailbox.name);
+
+    resource.set_gpu_backing(std::move(backing));
+  }
+  OneCopyGpuBacking* backing =
+      static_cast<OneCopyGpuBacking*>(resource.gpu_backing());
+
   // TODO(danakj): If resource_content_id != 0, we only need to copy/upload
   // the dirty rect.
   return std::make_unique<RasterBufferImpl>(this, resource_provider_, resource,
-                                            previous_content_id);
+                                            backing, previous_content_id);
 }
 
 void OneCopyRasterBufferProvider::OrderingBarrier() {
@@ -164,10 +254,10 @@
 
 bool OneCopyRasterBufferProvider::IsResourceReadyToDraw(
     const ResourcePool::InUsePoolResource& resource) const {
-  gpu::SyncToken sync_token = resource_provider_->GetSyncTokenForResources(
-      {resource.gpu_backing_resource_id()});
-  if (!sync_token.HasData())
-    return true;
+  const gpu::SyncToken& sync_token = resource.gpu_backing()->mailbox_sync_token;
+  // This SyncToken() should have been set by calling OrderingBarrier() before
+  // calling this.
+  DCHECK(sync_token.HasData());
 
   // IsSyncTokenSignaled is thread-safe, no need for worker context lock.
   return worker_context_provider_->ContextSupport()->IsSyncTokenSignaled(
@@ -178,23 +268,24 @@
     const std::vector<const ResourcePool::InUsePoolResource*>& resources,
     const base::Closure& callback,
     uint64_t pending_callback_id) const {
-  std::vector<viz::ResourceId> resource_ids;
-  resource_ids.reserve(resources.size());
-  for (auto* resource : resources)
-    resource_ids.push_back(resource->gpu_backing_resource_id());
-  gpu::SyncToken sync_token =
-      resource_provider_->GetSyncTokenForResources(resource_ids);
-  uint64_t callback_id = sync_token.release_count();
+  gpu::SyncToken latest_sync_token;
+  for (const auto* in_use : resources) {
+    const gpu::SyncToken& sync_token =
+        in_use->gpu_backing()->mailbox_sync_token;
+    if (sync_token.release_count() > latest_sync_token.release_count())
+      latest_sync_token = sync_token;
+  }
+  uint64_t callback_id = latest_sync_token.release_count();
   DCHECK_NE(callback_id, 0u);
 
   // If the callback is different from the one the caller is already waiting on,
   // pass the callback through to SignalSyncToken. Otherwise the request is
   // redundant.
   if (callback_id != pending_callback_id) {
-    // Use the compositor context because we want this callback on the impl
-    // thread.
-    compositor_context_provider_->ContextSupport()->SignalSyncToken(sync_token,
-                                                                    callback);
+    // Use the compositor context because we want this callback on the
+    // compositor thread.
+    compositor_context_provider_->ContextSupport()->SignalSyncToken(
+        latest_sync_token, callback);
   }
 
   return callback_id;
@@ -205,8 +296,11 @@
   pending_raster_buffers_.clear();
 }
 
-void OneCopyRasterBufferProvider::PlaybackAndCopyOnWorkerThread(
-    LayerTreeResourceProvider::ScopedWriteLockRaster* resource_lock,
+gpu::SyncToken OneCopyRasterBufferProvider::PlaybackAndCopyOnWorkerThread(
+    const gpu::Mailbox& mailbox,
+    GLenum mailbox_texture_target,
+    bool mailbox_texture_is_overlay_candidate,
+    bool mailbox_texture_storage_allocated,
     const gpu::SyncToken& sync_token,
     const RasterSource* raster_source,
     const gfx::Rect& raster_full_rect,
@@ -214,34 +308,26 @@
     const gfx::AxisTransform2d& transform,
     const gfx::Size& resource_size,
     viz::ResourceFormat resource_format,
+    const gfx::ColorSpace& color_space,
     const RasterSource::PlaybackSettings& playback_settings,
     uint64_t previous_content_id,
     uint64_t new_content_id) {
-  WaitSyncToken(sync_token);
-
   std::unique_ptr<StagingBuffer> staging_buffer =
       staging_pool_.AcquireStagingBuffer(resource_size, resource_format,
                                          previous_content_id);
 
-  PlaybackToStagingBuffer(
-      staging_buffer.get(), raster_source, raster_full_rect, raster_dirty_rect,
-      transform, resource_format, resource_lock->color_space_for_raster(),
-      playback_settings, previous_content_id, new_content_id);
+  PlaybackToStagingBuffer(staging_buffer.get(), raster_source, raster_full_rect,
+                          raster_dirty_rect, transform, resource_format,
+                          color_space, playback_settings, previous_content_id,
+                          new_content_id);
 
-  CopyOnWorkerThread(staging_buffer.get(), resource_lock, raster_source,
-                     raster_full_rect);
-
+  gpu::SyncToken sync_token_after_upload = CopyOnWorkerThread(
+      staging_buffer.get(), raster_source, raster_full_rect, resource_format,
+      resource_size, mailbox, mailbox_texture_target,
+      mailbox_texture_is_overlay_candidate, mailbox_texture_storage_allocated,
+      sync_token, color_space);
   staging_pool_.ReleaseStagingBuffer(std::move(staging_buffer));
-}
-
-void OneCopyRasterBufferProvider::WaitSyncToken(
-    const gpu::SyncToken& sync_token) {
-  viz::RasterContextProvider::ScopedRasterContextLock scoped_context(
-      worker_context_provider_);
-  gpu::raster::RasterInterface* ri = scoped_context.RasterInterface();
-  DCHECK(ri);
-  // Synchronize with compositor. Nop if sync token is empty.
-  ri->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
+  return sync_token_after_upload;
 }
 
 void OneCopyRasterBufferProvider::PlaybackToStagingBuffer(
@@ -306,17 +392,35 @@
   }
 }
 
-void OneCopyRasterBufferProvider::CopyOnWorkerThread(
+gpu::SyncToken OneCopyRasterBufferProvider::CopyOnWorkerThread(
     StagingBuffer* staging_buffer,
-    LayerTreeResourceProvider::ScopedWriteLockRaster* resource_lock,
     const RasterSource* raster_source,
-    const gfx::Rect& rect_to_copy) {
+    const gfx::Rect& rect_to_copy,
+    viz::ResourceFormat resource_format,
+    const gfx::Size& resource_size,
+    const gpu::Mailbox& mailbox,
+    GLenum mailbox_texture_target,
+    bool mailbox_texture_is_overlay_candidate,
+    bool mailbox_texture_storage_allocated,
+    const gpu::SyncToken& sync_token,
+    const gfx::ColorSpace& color_space) {
   viz::RasterContextProvider::ScopedRasterContextLock scoped_context(
       worker_context_provider_);
   gpu::raster::RasterInterface* ri = scoped_context.RasterInterface();
   DCHECK(ri);
 
-  GLuint texture_id = resource_lock->ConsumeTexture(ri);
+  // Wait on the SyncToken that was created on the compositor thread after
+  // making the mailbox. This ensures that the mailbox we consume here is valid
+  // by the time the consume command executes.
+  ri->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
+  GLuint mailbox_texture_id = ri->CreateAndConsumeTextureCHROMIUM(mailbox.name);
+  if (!mailbox_texture_storage_allocated) {
+    viz::TextureAllocation alloc = {mailbox_texture_id, mailbox_texture_target,
+                                    mailbox_texture_is_overlay_candidate};
+    viz::TextureAllocation::AllocateStorage(
+        ri, worker_context_provider_->ContextCapabilities(), resource_format,
+        resource_size, alloc, color_space);
+  }
 
   GLenum image_target = resource_provider_->GetImageTextureTarget(
       worker_context_provider_->ContextCapabilities(), StagingBufferUsage(),
@@ -340,7 +444,7 @@
       staging_buffer->image_id = ri->CreateImageCHROMIUM(
           staging_buffer->gpu_memory_buffer->AsClientBuffer(),
           staging_buffer->size.width(), staging_buffer->size.height(),
-          GLInternalFormat(resource_lock->format()));
+          GLInternalFormat(staging_buffer->format));
       ri->BindTexImage2DCHROMIUM(image_target, staging_buffer->image_id);
     }
   } else {
@@ -366,11 +470,12 @@
 
   // 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())) {
-    ri->CompressedCopyTextureCHROMIUM(staging_buffer->texture_id, texture_id);
+  if (IsResourceFormatCompressed(staging_buffer->format)) {
+    ri->CompressedCopyTextureCHROMIUM(staging_buffer->texture_id,
+                                      mailbox_texture_id);
   } else {
     int bytes_per_row = ResourceUtil::UncheckedWidthInBytes<int>(
-        rect_to_copy.width(), resource_lock->format());
+        rect_to_copy.width(), staging_buffer->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.
@@ -382,9 +487,10 @@
       int rows_to_copy = std::min(chunk_size_in_rows, height - y);
       DCHECK_GT(rows_to_copy, 0);
 
-      ri->CopySubTextureCHROMIUM(
-          staging_buffer->texture_id, 0, GL_TEXTURE_2D, texture_id, 0, 0, y, 0,
-          y, rect_to_copy.width(), rows_to_copy, false, false, false);
+      ri->CopySubTextureCHROMIUM(staging_buffer->texture_id, 0,
+                                 mailbox_texture_target, mailbox_texture_id, 0,
+                                 0, y, 0, y, rect_to_copy.width(), rows_to_copy,
+                                 false, false, false);
       y += rows_to_copy;
 
       // Increment |bytes_scheduled_since_last_flush_| by the amount of memory
@@ -406,12 +512,11 @@
 #endif
   }
 
-  ri->DeleteTextures(1, &texture_id);
+  ri->DeleteTextures(1, &mailbox_texture_id);
 
   // Generate sync token on the worker context that will be sent to and waited
   // for by the display compositor before using the content generated here.
-  resource_lock->set_sync_token(
-      LayerTreeResourceProvider::GenerateSyncTokenHelper(ri));
+  return LayerTreeResourceProvider::GenerateSyncTokenHelper(ri);
 }
 
 gfx::BufferUsage OneCopyRasterBufferProvider::StagingBufferUsage() const {
diff --git a/cc/raster/one_copy_raster_buffer_provider.h b/cc/raster/one_copy_raster_buffer_provider.h
index c33cdfa..5ad0556 100644
--- a/cc/raster/one_copy_raster_buffer_provider.h
+++ b/cc/raster/one_copy_raster_buffer_provider.h
@@ -31,6 +31,7 @@
       LayerTreeResourceProvider* resource_provider,
       int max_copy_texture_chromium_size,
       bool use_partial_raster,
+      bool use_gpu_memory_buffer_resources,
       int max_staging_buffer_usage_in_bytes,
       viz::ResourceFormat preferred_tile_format);
   ~OneCopyRasterBufferProvider() override;
@@ -54,8 +55,11 @@
   void Shutdown() override;
 
   // Playback raster source and copy result into |resource|.
-  void PlaybackAndCopyOnWorkerThread(
-      LayerTreeResourceProvider::ScopedWriteLockRaster* resource_lock,
+  gpu::SyncToken PlaybackAndCopyOnWorkerThread(
+      const gpu::Mailbox& mailbox,
+      GLenum mailbox_texture_target,
+      bool mailbox_texture_is_overlay_candidate,
+      bool mailbox_texture_storage_allocated,
       const gpu::SyncToken& sync_token,
       const RasterSource* raster_source,
       const gfx::Rect& raster_full_rect,
@@ -63,16 +67,20 @@
       const gfx::AxisTransform2d& transform,
       const gfx::Size& resource_size,
       viz::ResourceFormat resource_format,
+      const gfx::ColorSpace& color_space,
       const RasterSource::PlaybackSettings& playback_settings,
       uint64_t previous_content_id,
       uint64_t new_content_id);
 
  private:
+  class OneCopyGpuBacking;
+
   class RasterBufferImpl : public RasterBuffer {
    public:
     RasterBufferImpl(OneCopyRasterBufferProvider* client,
                      LayerTreeResourceProvider* resource_provider,
                      const ResourcePool::InUsePoolResource& in_use_resource,
+                     OneCopyGpuBacking* backing,
                      uint64_t previous_content_id);
     ~RasterBufferImpl() override;
 
@@ -86,22 +94,35 @@
         const RasterSource::PlaybackSettings& playback_settings) override;
 
     void set_sync_token(const gpu::SyncToken& sync_token) {
-      sync_token_ = sync_token;
+      before_raster_sync_token_ = sync_token;
     }
 
    private:
+    // These fields may only be used on the compositor thread.
     OneCopyRasterBufferProvider* const client_;
+    OneCopyGpuBacking* backing_;
+
+    // These fields are for use on the worker thread.
     const gfx::Size resource_size_;
     const viz::ResourceFormat resource_format_;
-    LayerTreeResourceProvider::ScopedWriteLockRaster lock_;
+    const gfx::ColorSpace color_space_;
     const uint64_t previous_content_id_;
-
-    gpu::SyncToken sync_token_;
+    const gpu::SyncToken returned_sync_token_;
+    const gpu::Mailbox mailbox_;
+    const GLenum mailbox_texture_target_;
+    const bool mailbox_texture_is_overlay_candidate_;
+    // Set to true once allocation is done in the worker thread.
+    bool mailbox_texture_storage_allocated_;
+    // A SyncToken for the worker thread to consume before using the mailbox
+    // texture it is given.
+    gpu::SyncToken before_raster_sync_token_;
+    // A SyncToken to be returned from the worker thread, and waited on before
+    // using the rastered resource.
+    gpu::SyncToken after_raster_sync_token_;
 
     DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl);
   };
 
-  void WaitSyncToken(const gpu::SyncToken& sync_token);
   void PlaybackToStagingBuffer(
       StagingBuffer* staging_buffer,
       const RasterSource* raster_source,
@@ -113,11 +134,17 @@
       const RasterSource::PlaybackSettings& playback_settings,
       uint64_t previous_content_id,
       uint64_t new_content_id);
-  void CopyOnWorkerThread(
-      StagingBuffer* staging_buffer,
-      LayerTreeResourceProvider::ScopedWriteLockRaster* resource_lock,
-      const RasterSource* raster_source,
-      const gfx::Rect& rect_to_copy);
+  gpu::SyncToken CopyOnWorkerThread(StagingBuffer* staging_buffer,
+                                    const RasterSource* raster_source,
+                                    const gfx::Rect& rect_to_copy,
+                                    viz::ResourceFormat resource_format,
+                                    const gfx::Size& resource_size,
+                                    const gpu::Mailbox& mailbox,
+                                    GLenum mailbox_texture_target,
+                                    bool mailbox_texture_is_overlay_candidate,
+                                    bool mailbox_texture_storage_allocated,
+                                    const gpu::SyncToken& sync_token,
+                                    const gfx::ColorSpace& color_space);
   gfx::BufferUsage StagingBufferUsage() const;
 
   viz::ContextProvider* const compositor_context_provider_;
@@ -125,6 +152,7 @@
   LayerTreeResourceProvider* const resource_provider_;
   const int max_bytes_per_copy_operation_;
   const bool use_partial_raster_;
+  const bool use_gpu_memory_buffer_resources_;
 
   // Context lock must be acquired when accessing this member.
   int bytes_scheduled_since_last_flush_;
diff --git a/cc/raster/raster_buffer_provider_perftest.cc b/cc/raster/raster_buffer_provider_perftest.cc
index 0812013..e46cf7a 100644
--- a/cc/raster/raster_buffer_provider_perftest.cc
+++ b/cc/raster/raster_buffer_provider_perftest.cc
@@ -368,7 +368,7 @@
         raster_buffer_provider_ = std::make_unique<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(), false, false,
             std::numeric_limits<int>::max(),
             viz::PlatformColor::BestTextureFormat());
         resource_pool_ = std::make_unique<ResourcePool>(
@@ -380,7 +380,7 @@
         Create3dResourceProvider();
         raster_buffer_provider_ = std::make_unique<GpuRasterBufferProvider>(
             compositor_context_provider_.get(), worker_context_provider_.get(),
-            resource_provider_.get(), false, 0,
+            resource_provider_.get(), false, false, 0,
             viz::PlatformColor::BestTextureFormat(), false);
         resource_pool_ = std::make_unique<ResourcePool>(
             resource_provider_.get(), task_runner_,
diff --git a/cc/raster/raster_buffer_provider_unittest.cc b/cc/raster/raster_buffer_provider_unittest.cc
index 3afd4b87..7523179 100644
--- a/cc/raster/raster_buffer_provider_unittest.cc
+++ b/cc/raster/raster_buffer_provider_unittest.cc
@@ -171,7 +171,7 @@
         raster_buffer_provider_ = std::make_unique<OneCopyRasterBufferProvider>(
             base::ThreadTaskRunnerHandle::Get().get(), context_provider_.get(),
             worker_context_provider_.get(), resource_provider_.get(),
-            kMaxBytesPerCopyOperation, false, kMaxStagingBuffers,
+            kMaxBytesPerCopyOperation, false, false, kMaxStagingBuffers,
             viz::PlatformColor::BestTextureFormat());
         pool_ = std::make_unique<ResourcePool>(
             resource_provider_.get(), base::ThreadTaskRunnerHandle::Get(),
@@ -181,7 +181,7 @@
         Create3dResourceProvider();
         raster_buffer_provider_ = std::make_unique<GpuRasterBufferProvider>(
             context_provider_.get(), worker_context_provider_.get(),
-            resource_provider_.get(), false, 0,
+            resource_provider_.get(), false, false, 0,
             viz::PlatformColor::BestTextureFormat(), false);
         pool_ = std::make_unique<ResourcePool>(
             resource_provider_.get(), base::ThreadTaskRunnerHandle::Get(),
diff --git a/cc/raster/zero_copy_raster_buffer_provider.cc b/cc/raster/zero_copy_raster_buffer_provider.cc
index 505d92e0..5bf8d54 100644
--- a/cc/raster/zero_copy_raster_buffer_provider.cc
+++ b/cc/raster/zero_copy_raster_buffer_provider.cc
@@ -107,6 +107,7 @@
       backing_->mailbox = gpu::Mailbox::Generate();
       gl->ProduceTextureDirectCHROMIUM(backing_->texture_id,
                                        backing_->mailbox.name);
+      backing_->overlay_candidate = true;
 
       gl->BindTexture(backing_->texture_target, backing_->texture_id);
       gl->TexParameteri(backing_->texture_target, GL_TEXTURE_MIN_FILTER,
diff --git a/cc/resources/layer_tree_resource_provider.cc b/cc/resources/layer_tree_resource_provider.cc
index 8a55a5b..38f17c0 100644
--- a/cc/resources/layer_tree_resource_provider.cc
+++ b/cc/resources/layer_tree_resource_provider.cc
@@ -360,7 +360,7 @@
                              size, viz::internal::Resource::INTERNAL, hint,
                              viz::ResourceType::kTexture, format, color_space));
   if (use_overlay && settings_.use_texture_storage_image &&
-      IsGpuMemoryBufferFormatSupported(format, gfx::BufferUsage::SCANOUT)) {
+      viz::IsGpuMemoryBufferFormatSupported(format)) {
     resource->usage = gfx::BufferUsage::SCANOUT;
     resource->target = GetImageTextureTarget(
         compositor_context_provider_->ContextCapabilities(), resource->usage,
@@ -747,29 +747,6 @@
   return false;
 }
 
-bool LayerTreeResourceProvider::IsGpuMemoryBufferFormatSupported(
-    viz::ResourceFormat format,
-    gfx::BufferUsage usage) const {
-  switch (format) {
-    case viz::BGRA_8888:
-    case viz::RED_8:
-    case viz::R16_EXT:
-    case viz::RGBA_4444:
-    case viz::RGBA_8888:
-    case viz::ETC1:
-    case viz::RGBA_F16:
-      return true;
-    // These formats have no BufferFormat equivalent.
-    case viz::ALPHA_8:
-    case viz::LUMINANCE_8:
-    case viz::RGB_565:
-    case viz::LUMINANCE_F16:
-      return false;
-  }
-  NOTREACHED();
-  return false;
-}
-
 viz::ResourceFormat LayerTreeResourceProvider::YuvResourceFormat(
     int bits) const {
   if (bits > 8) {
@@ -785,6 +762,13 @@
 }
 
 void LayerTreeResourceProvider::LoseResourceForTesting(viz::ResourceId id) {
+  auto it = imported_resources_.find(id);
+  if (it != imported_resources_.end()) {
+    ImportedResource& imported = it->second;
+    imported.returned_lost = true;
+    return;
+  }
+
   viz::internal::Resource* resource = GetResource(id);
   DCHECK(resource);
   resource->lost = true;
diff --git a/cc/resources/layer_tree_resource_provider.h b/cc/resources/layer_tree_resource_provider.h
index bc3cf30..92ae354a 100644
--- a/cc/resources/layer_tree_resource_provider.h
+++ b/cc/resources/layer_tree_resource_provider.h
@@ -120,9 +120,6 @@
   // Note that render buffer support implies texture support.
   bool IsRenderBufferFormatSupported(viz::ResourceFormat format) const;
 
-  bool IsGpuMemoryBufferFormatSupported(viz::ResourceFormat format,
-                                        gfx::BufferUsage usage) const;
-
   bool use_sync_query() const { return settings_.use_sync_query; }
 
   int max_texture_size() const { return settings_.max_texture_size; }
diff --git a/cc/resources/resource_pool.cc b/cc/resources/resource_pool.cc
index f114850..2551ca59 100644
--- a/cc/resources/resource_pool.cc
+++ b/cc/resources/resource_pool.cc
@@ -87,7 +87,6 @@
     : resource_provider_(resource_provider),
       use_gpu_resources_(true),
       use_gpu_memory_buffers_(false),
-      hint_(hint),
       task_runner_(std::move(task_runner)),
       resource_expiration_delay_(expiration_delay),
       disallow_non_exact_reuse_(disallow_non_exact_reuse),
@@ -106,7 +105,6 @@
     : resource_provider_(resource_provider),
       use_gpu_resources_(false),
       use_gpu_memory_buffers_(false),
-      hint_(viz::ResourceTextureHint::kDefault),
       task_runner_(std::move(task_runner)),
       resource_expiration_delay_(expiration_delay),
       disallow_non_exact_reuse_(disallow_non_exact_reuse),
@@ -146,14 +144,7 @@
   for (auto it = unused_resources_.begin(); it != unused_resources_.end();
        ++it) {
     PoolResource* resource = it->get();
-// TODO(danakj): When gpu raster buffer providers make their own backings,
-// then they need to switch to the else branch.
-#if DCHECK_IS_ON()
-    if (use_gpu_resources_)
-      DCHECK(resource_provider_->CanLockForWrite(resource->resource_id()));
-    else
-      DCHECK(!resource->resource_id());
-#endif
+    DCHECK(!resource->resource_id());
 
     if (resource->format() != format)
       continue;
@@ -179,17 +170,8 @@
     const gfx::ColorSpace& color_space) {
   DCHECK(ResourceUtil::VerifySizeInBytes<size_t>(size, format));
 
-  viz::ResourceId resource_id;
-  if (use_gpu_memory_buffers_) {
-    resource_id = 0;
-  } else if (use_gpu_resources_) {
-    resource_id = resource_provider_->CreateGpuTextureResource(
-        size, hint_, format, color_space);
-  } else {
-    resource_id = 0;
-  }
   auto pool_resource = std::make_unique<PoolResource>(
-      next_resource_unique_id_++, size, format, color_space, resource_id);
+      next_resource_unique_id_++, size, format, color_space);
 
   total_memory_usage_bytes_ +=
       ResourceUtil::UncheckedSizeInBytes<size_t>(size, format);
@@ -275,14 +257,7 @@
   // |in_use_resources_| and return it.
   if (iter_resource_to_return != unused_resources_.end()) {
     PoolResource* resource = iter_resource_to_return->get();
-// TODO(danakj): When gpu raster buffer providers make their own backings,
-// then they need to switch to the else branch.
-#if DCHECK_IS_ON()
-    if (use_gpu_resources_)
-      DCHECK(resource_provider_->CanLockForWrite(resource->resource_id()));
-    else
-      DCHECK(!resource->resource_id());
-#endif
+    DCHECK(!resource->resource_id());
 
     // Transfer resource to |in_use_resources_|.
     in_use_resources_[resource->unique_id()] =
@@ -331,31 +306,21 @@
   }
 
   resource->set_resource_id(0);
-  // TODO(danakj): Use this branch for gpu resources that aren't gpu memory
-  // buffers.
-  if (use_gpu_memory_buffers_)
+  if (use_gpu_memory_buffers_ || use_gpu_resources_)
     resource->gpu_backing()->returned_sync_token = sync_token;
   DidFinishUsingResource(std::move(*busy_it));
   busy_resources_.erase(busy_it);
 }
 
 void ResourcePool::PrepareForExport(const InUsePoolResource& resource) {
-  // TODO(danakj): Add branches for gpu too once a gpu-backed raster provider
-  // does this.
-  if (use_gpu_resources_)
-    return;
-
   viz::TransferableResource transferable;
-  if (use_gpu_memory_buffers_) {
+  if (use_gpu_memory_buffers_ || use_gpu_resources_) {
     transferable = viz::TransferableResource::MakeGLOverlay(
         resource.resource_->gpu_backing()->mailbox, GL_LINEAR,
         resource.resource_->gpu_backing()->texture_target,
         resource.resource_->gpu_backing()->mailbox_sync_token,
         resource.resource_->size(),
-        /*is_overlay_candidate=*/true);
-    // Clear the SyncToken that we have sent away to the display compositor. It
-    // will be owned by the ResourceProvider now.
-    resource.resource_->gpu_backing()->mailbox_sync_token = gpu::SyncToken();
+        resource.resource_->gpu_backing()->overlay_candidate);
   } else {
     transferable = viz::TransferableResource::MakeSoftware(
         resource.resource_->shared_bitmap()->id(),
@@ -424,15 +389,11 @@
     busy_resources_.push_front(std::move(it->second));
   in_use_resources_.erase(it);
 
-  // TODO(danakj): When gpu raster buffer providers make their own backings,
-  // then they need to switch to this branch.
-  if (!use_gpu_resources_) {
-    // If the resource was exported, then it has a resource id. By removing the
-    // resource id, we will be notified in the ReleaseCallback when the resource
-    // is no longer exported and can be reused.
-    if (pool_resource->resource_id())
-      resource_provider_->RemoveImportedResource(pool_resource->resource_id());
-  }
+  // If the resource was exported, then it has a resource id. By removing the
+  // resource id, we will be notified in the ReleaseCallback when the resource
+  // is no longer exported and can be reused.
+  if (pool_resource->resource_id())
+    resource_provider_->RemoveImportedResource(pool_resource->resource_id());
 
   // Now that we have evictable resources, schedule an eviction call for this
   // resource if necessary.
@@ -485,10 +446,6 @@
       resource->size(), resource->format());
   total_memory_usage_bytes_ -= resource_bytes;
   --total_resource_count_;
-  // TODO(danakj): When gpu raster buffer providers make their own backings,
-  // then they need to switch off this branch.
-  if (use_gpu_resources_)
-    resource_provider_->DeleteResource(resource->resource_id());
 }
 
 void ResourcePool::UpdateResourceContentIdAndInvalidation(
@@ -504,31 +461,7 @@
 }
 
 void ResourcePool::CheckBusyResources() {
-  // TODO(danakj): When gpu raster buffer providers make their own backings,
-  // then they need to switch to this branch.
-  if (!use_gpu_resources_) {
-    // The ReleaseCallback tells ResourcePool when they are no longer busy, so
-    // there is nothing to do here.
-    return;
-  }
-
-  for (auto it = busy_resources_.begin(); it != busy_resources_.end();) {
-    PoolResource* resource = it->get();
-
-    if (resource_provider_->CanLockForWrite(resource->resource_id())) {
-      if (evict_busy_resources_when_unused_)
-        DeleteResource(std::move(*it));
-      else
-        DidFinishUsingResource(std::move(*it));
-      it = busy_resources_.erase(it);
-    } else if (resource_provider_->IsLost(resource->resource_id())) {
-      // Remove lost resources from pool.
-      DeleteResource(std::move(*it));
-      it = busy_resources_.erase(it);
-    } else {
-      ++it;
-    }
-  }
+  // TODO(danakj): Delete this.
 }
 
 void ResourcePool::DidFinishUsingResource(
@@ -603,18 +536,14 @@
                     MemoryAllocatorDump::kUnitsBytes,
                     total_memory_usage_bytes_);
   } else {
-    bool dump_parent = use_gpu_resources_;
     for (const auto& resource : unused_resources_) {
-      resource->OnMemoryDump(pmd, resource_provider_, dump_parent,
-                             true /* is_free */);
+      resource->OnMemoryDump(pmd, resource_provider_, true /* is_free */);
     }
     for (const auto& resource : busy_resources_) {
-      resource->OnMemoryDump(pmd, resource_provider_, dump_parent,
-                             false /* is_free */);
+      resource->OnMemoryDump(pmd, resource_provider_, false /* is_free */);
     }
     for (const auto& entry : in_use_resources_) {
-      entry.second->OnMemoryDump(pmd, resource_provider_, dump_parent,
-                                 false /* is_free */);
+      entry.second->OnMemoryDump(pmd, resource_provider_, false /* is_free */);
     }
   }
   return true;
@@ -634,38 +563,32 @@
 ResourcePool::PoolResource::PoolResource(size_t unique_id,
                                          const gfx::Size& size,
                                          viz::ResourceFormat format,
-                                         const gfx::ColorSpace& color_space,
-                                         viz::ResourceId resource_id)
+                                         const gfx::ColorSpace& color_space)
     : unique_id_(unique_id),
       size_(size),
       format_(format),
-      color_space_(color_space),
-      resource_id_(resource_id) {}
+      color_space_(color_space) {}
 
 ResourcePool::PoolResource::~PoolResource() = default;
 
 void ResourcePool::PoolResource::OnMemoryDump(
     base::trace_event::ProcessMemoryDump* pmd,
     const LayerTreeResourceProvider* resource_provider,
-    bool dump_parent,
     bool is_free) const {
   base::UnguessableToken shm_guid;
   base::trace_event::MemoryAllocatorDumpGuid backing_guid;
-  if (!dump_parent) {
-    if (shared_bitmap_) {
-      // Software resources are in shared memory but are kept closed to avoid
-      // holding an fd open. So there is no SharedMemoryHandle to get a guid
-      // from.
-      DCHECK(!shared_bitmap_->GetSharedMemoryHandle().IsValid());
-      backing_guid = viz::GetSharedBitmapGUIDForTracing(shared_bitmap_->id());
-    } else if (gpu_backing_) {
-      shm_guid = gpu_backing_->SharedMemoryGuid();
-      if (shm_guid.is_empty()) {
-        auto* dump_manager =
-            base::trace_event::MemoryDumpManager::GetInstance();
-        backing_guid =
-            gpu_backing_->MemoryDumpGuid(dump_manager->GetTracingProcessId());
-      }
+  if (shared_bitmap_) {
+    // Software resources are in shared memory but are kept closed to avoid
+    // holding an fd open. So there is no SharedMemoryHandle to get a guid
+    // from.
+    DCHECK(!shared_bitmap_->GetSharedMemoryHandle().IsValid());
+    backing_guid = viz::GetSharedBitmapGUIDForTracing(shared_bitmap_->id());
+  } else if (gpu_backing_) {
+    shm_guid = gpu_backing_->SharedMemoryGuid();
+    if (shm_guid.is_empty()) {
+      auto* dump_manager = base::trace_event::MemoryDumpManager::GetInstance();
+      backing_guid =
+          gpu_backing_->MemoryDumpGuid(dump_manager->GetTracingProcessId());
     }
 
     // If |dump_parent| is false, the ownership of the resource is in the
@@ -681,14 +604,21 @@
       base::StringPrintf("cc/tile_memory/provider_%d/resource_%zd",
                          resource_provider->tracing_id(), unique_id_);
   MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(dump_name);
-  if (dump_parent) {
-    // This string matches the one emitted by ResourceProvider. The one above
-    // has a different name, and does not need to match, it is connected by the
-    // AddSuballocation() call.
-    std::string parent_node =
-        base::StringPrintf("cc/resource_memory/provider_%d/resource_%d",
-                           resource_provider->tracing_id(), resource_id_);
-    pmd->AddSuballocation(dump->guid(), parent_node);
+  // The importance value used here needs to be greater than the importance
+  // used in other places that use this GUID to inform the system that this is
+  // the root ownership. The gpu processes uses 0, so 2 is sufficient, and was
+  // chosen historically and there is no need to adjust it.
+  const int kImportance = 2;
+  if (shared_bitmap_) {
+    // Software resources are in shared memory but are kept closed to avoid
+    // holding an fd open. So there is no SharedMemoryHandle to get a guid
+    // from.
+    DCHECK(!shared_bitmap_->GetSharedMemoryHandle().IsValid());
+    base::trace_event::MemoryAllocatorDumpGuid guid =
+        viz::GetSharedBitmapGUIDForTracing(shared_bitmap_->id());
+    DCHECK(!guid.empty());
+    pmd->CreateSharedGlobalAllocatorDump(guid);
+    pmd->AddOwnershipEdge(dump->guid(), guid, kImportance);
   } else {
     // The importance value used here needs to be greater than the importance
     // used in other places that use this GUID to inform the system that this is
diff --git a/cc/resources/resource_pool.h b/cc/resources/resource_pool.h
index 03c5271..e4b7364 100644
--- a/cc/resources/resource_pool.h
+++ b/cc/resources/resource_pool.h
@@ -26,6 +26,7 @@
 #include "components/viz/common/quads/shared_bitmap.h"
 #include "components/viz/common/resources/resource_format.h"
 #include "gpu/command_buffer/common/sync_token.h"
+#include "third_party/khronos/GLES2/gl2.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/gpu_memory_buffer.h"
 
@@ -52,15 +53,17 @@
 
     gpu::Mailbox mailbox;
     gpu::SyncToken mailbox_sync_token;
-    uint32_t texture_target;
+    GLenum texture_target = 0;
+    bool overlay_candidate = false;
     gpu::SyncToken returned_sync_token;
 
     // Guids for for memory dumps. This guid will be valid once the GpuBacking
-    // has memory allocated.
+    // has memory allocated. Called on the compositor thread.
     virtual base::trace_event::MemoryAllocatorDumpGuid MemoryDumpGuid(
         uint64_t tracing_process_id) = 0;
     // Some gpu resources can be shared memory-backed, and this guid should be
-    // prefered in that case. But if not then this will be empty.
+    // prefered in that case. But if not then this will be empty. Called on the
+    // compositor thread.
     virtual base::UnguessableToken SharedMemoryGuid() = 0;
   };
 
@@ -103,12 +106,6 @@
       return resource_->resource_id();
     }
 
-    // Only valid when the ResourcePool is vending gpu-backed resources.
-    const viz::ResourceId& gpu_backing_resource_id() const {
-      DCHECK(is_gpu_);
-      return resource_->resource_id();
-    }
-
     // Only valid when the ResourcePool is vending texture-backed resources.
     GpuBacking* gpu_backing() const {
       DCHECK(is_gpu_);
@@ -131,6 +128,10 @@
       resource_->set_shared_bitmap(std::move(shared_bitmap));
     }
 
+    // Production code should not be built around these ids, but tests use them
+    // to check for identity.
+    size_t unique_id_for_testing() const { return resource_->unique_id(); }
+
    private:
     friend ResourcePool;
     explicit InUsePoolResource(PoolResource* resource, bool is_gpu)
@@ -151,6 +152,7 @@
   // Constructor for creating standard Gpu resources.
   ResourcePool(LayerTreeResourceProvider* resource_provider,
                scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+               // TODO(danakj): Remove this.
                viz::ResourceTextureHint hint,
                const base::TimeDelta& expiration_delay,
                bool disallow_non_exact_reuse);
@@ -232,8 +234,7 @@
     PoolResource(size_t unique_id,
                  const gfx::Size& size,
                  viz::ResourceFormat format,
-                 const gfx::ColorSpace& color_space,
-                 viz::ResourceId resource_id);
+                 const gfx::ColorSpace& color_space);
     ~PoolResource();
 
     size_t unique_id() const { return unique_id_; }
@@ -267,7 +268,6 @@
 
     void OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd,
                       const LayerTreeResourceProvider* resource_provider,
-                      bool dump_parent,
                       bool is_free) const;
 
    private:
@@ -328,7 +328,6 @@
   const bool use_gpu_resources_ = false;
   const bool use_gpu_memory_buffers_ = false;
   const gfx::BufferUsage usage_ = gfx::BufferUsage::GPU_READ_CPU_READ_WRITE;
-  const viz::ResourceTextureHint hint_ = viz::ResourceTextureHint::kDefault;
   const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
   const base::TimeDelta resource_expiration_delay_;
   const bool disallow_non_exact_reuse_ = false;
diff --git a/cc/resources/resource_pool_unittest.cc b/cc/resources/resource_pool_unittest.cc
index 083e2640..925688f 100644
--- a/cc/resources/resource_pool_unittest.cc
+++ b/cc/resources/resource_pool_unittest.cc
@@ -13,6 +13,7 @@
 #include "cc/resources/scoped_resource.h"
 #include "cc/test/fake_resource_provider.h"
 #include "cc/test/test_context_provider.h"
+#include "cc/test/test_shared_bitmap_manager.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace cc {
@@ -32,12 +33,29 @@
   }
 
  protected:
+  class StubGpuBacking : public ResourcePool::GpuBacking {
+   public:
+    base::trace_event::MemoryAllocatorDumpGuid MemoryDumpGuid(
+        uint64_t tracing_process_id) override {
+      return {};
+    }
+    base::UnguessableToken SharedMemoryGuid() override { return {}; }
+  };
+
+  void SetBackingOnResource(const ResourcePool::InUsePoolResource& resource) {
+    auto backing = std::make_unique<StubGpuBacking>();
+    backing->mailbox_sync_token.Set(
+        gpu::GPU_IO, gpu::CommandBufferId::FromUnsafeValue(1), 1);
+    resource.set_gpu_backing(std::move(backing));
+  }
+
   void CheckAndReturnResource(ResourcePool::InUsePoolResource resource) {
     EXPECT_TRUE(!!resource);
     resource_pool_->ReleaseResource(std::move(resource));
     resource_pool_->CheckBusyResources();
   }
 
+  TestSharedBitmapManager shared_bitmap_manager_;
   scoped_refptr<TestContextProvider> context_provider_;
   std::unique_ptr<LayerTreeResourceProvider> resource_provider_;
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
@@ -52,8 +70,7 @@
       resource_pool_->AcquireResource(size, format, color_space);
   EXPECT_EQ(size, resource.size());
   EXPECT_EQ(format, resource.format());
-  EXPECT_TRUE(
-      resource_provider_->CanLockForWrite(resource.gpu_backing_resource_id()));
+  EXPECT_EQ(color_space, resource.color_space());
 
   resource_pool_->ReleaseResource(std::move(resource));
 }
@@ -80,11 +97,6 @@
 
   resource_pool_->ReleaseResource(std::move(resource));
   EXPECT_EQ(resource_bytes, resource_pool_->GetTotalMemoryUsageForTesting());
-  EXPECT_EQ(1u, resource_pool_->GetTotalResourceCountForTesting());
-  EXPECT_EQ(1u, resource_pool_->GetBusyResourceCountForTesting());
-
-  resource_pool_->CheckBusyResources();
-  EXPECT_EQ(resource_bytes, resource_pool_->GetTotalMemoryUsageForTesting());
   EXPECT_EQ(0u, resource_pool_->memory_usage_bytes());
   EXPECT_EQ(1u, resource_pool_->GetTotalResourceCountForTesting());
   EXPECT_EQ(0u, resource_pool_->resource_count());
@@ -112,27 +124,30 @@
 
   CheckAndReturnResource(
       resource_pool_->AcquireResource(size, format, color_space1));
-  EXPECT_EQ(1u, resource_provider_->num_resources());
+  EXPECT_EQ(1u, resource_pool_->GetTotalResourceCountForTesting());
 
   // Same size/format should re-use resource.
   ResourcePool::InUsePoolResource resource =
       resource_pool_->AcquireResource(size, format, color_space1);
-  EXPECT_EQ(1u, resource_provider_->num_resources());
+  EXPECT_EQ(1u, resource_pool_->GetTotalResourceCountForTesting());
   CheckAndReturnResource(std::move(resource));
-  EXPECT_EQ(1u, resource_provider_->num_resources());
+  EXPECT_EQ(1u, resource_pool_->GetTotalResourceCountForTesting());
+  EXPECT_EQ(0u, resource_pool_->GetBusyResourceCountForTesting());
 
   // Different size/format should allocate new resource.
   resource = resource_pool_->AcquireResource(gfx::Size(50, 50),
                                              viz::LUMINANCE_8, color_space1);
-  EXPECT_EQ(2u, resource_provider_->num_resources());
+  EXPECT_EQ(2u, resource_pool_->GetTotalResourceCountForTesting());
   CheckAndReturnResource(std::move(resource));
-  EXPECT_EQ(2u, resource_provider_->num_resources());
+  EXPECT_EQ(2u, resource_pool_->GetTotalResourceCountForTesting());
+  EXPECT_EQ(0u, resource_pool_->GetBusyResourceCountForTesting());
 
   // Different color space should allocate new resource.
   resource = resource_pool_->AcquireResource(size, format, color_space2);
-  EXPECT_EQ(3u, resource_provider_->num_resources());
+  EXPECT_EQ(3u, resource_pool_->GetTotalResourceCountForTesting());
   CheckAndReturnResource(std::move(resource));
-  EXPECT_EQ(3u, resource_provider_->num_resources());
+  EXPECT_EQ(3u, resource_pool_->GetTotalResourceCountForTesting());
+  EXPECT_EQ(0u, resource_pool_->GetBusyResourceCountForTesting());
 }
 
 TEST_F(ResourcePoolTest, LostResource) {
@@ -147,13 +162,15 @@
 
   ResourcePool::InUsePoolResource resource =
       resource_pool_->AcquireResource(size, format, color_space);
-  EXPECT_EQ(1u, resource_provider_->num_resources());
 
-  resource_provider_->LoseResourceForTesting(
-      resource.gpu_backing_resource_id());
+  SetBackingOnResource(resource);
+  resource_pool_->PrepareForExport(resource);
+
+  resource_provider_->LoseResourceForTesting(resource.resource_id_for_export());
+
+  EXPECT_EQ(1u, resource_pool_->GetTotalResourceCountForTesting());
   resource_pool_->ReleaseResource(std::move(resource));
-  resource_pool_->CheckBusyResources();
-  EXPECT_EQ(0u, resource_provider_->num_resources());
+  EXPECT_EQ(0u, resource_pool_->GetTotalResourceCountForTesting());
 }
 
 TEST_F(ResourcePoolTest, BusyResourcesNotFreed) {
@@ -175,12 +192,17 @@
 
   ResourcePool::InUsePoolResource resource =
       resource_pool_->AcquireResource(size, format, color_space);
-  EXPECT_EQ(1u, resource_provider_->num_resources());
   EXPECT_EQ(40000u, resource_pool_->GetTotalMemoryUsageForTesting());
   EXPECT_EQ(1u, resource_pool_->resource_count());
 
+  SetBackingOnResource(resource);
+  resource_pool_->PrepareForExport(resource);
+
+  std::vector<viz::TransferableResource> transfers;
+  resource_provider_->PrepareSendToParent({resource.resource_id_for_export()},
+                                          &transfers);
+
   resource_pool_->ReleaseResource(std::move(resource));
-  EXPECT_EQ(1u, resource_provider_->num_resources());
   EXPECT_EQ(40000u, resource_pool_->GetTotalMemoryUsageForTesting());
   EXPECT_EQ(0u, resource_pool_->memory_usage_bytes());
   EXPECT_EQ(1u, resource_pool_->GetBusyResourceCountForTesting());
@@ -192,9 +214,8 @@
                                 base::TimeDelta::FromMillisecondsD(200));
   run_loop.Run();
 
-  // Busy resources are still help, since they may be in flight to the display
+  // Busy resources are still held, since they may be in flight to the display
   // compositor and should not be freed.
-  EXPECT_EQ(1u, resource_provider_->num_resources());
   EXPECT_EQ(40000u, resource_pool_->GetTotalMemoryUsageForTesting());
   EXPECT_EQ(0u, resource_pool_->memory_usage_bytes());
   EXPECT_EQ(1u, resource_pool_->GetBusyResourceCountForTesting());
@@ -219,20 +240,27 @@
 
   ResourcePool::InUsePoolResource resource =
       resource_pool_->AcquireResource(size, format, color_space);
-  EXPECT_EQ(1u, resource_provider_->num_resources());
   EXPECT_EQ(40000u, resource_pool_->GetTotalMemoryUsageForTesting());
   EXPECT_EQ(1u, resource_pool_->GetTotalResourceCountForTesting());
   EXPECT_EQ(1u, resource_pool_->resource_count());
+  EXPECT_EQ(0u, resource_pool_->GetBusyResourceCountForTesting());
+
+  // Export the resource to the display compositor.
+  SetBackingOnResource(resource);
+  resource_pool_->PrepareForExport(resource);
+  std::vector<viz::TransferableResource> transfers;
+  resource_provider_->PrepareSendToParent({resource.resource_id_for_export()},
+                                          &transfers);
 
   resource_pool_->ReleaseResource(std::move(resource));
-  EXPECT_EQ(1u, resource_provider_->num_resources());
   EXPECT_EQ(40000u, resource_pool_->GetTotalMemoryUsageForTesting());
   EXPECT_EQ(1u, resource_pool_->GetTotalResourceCountForTesting());
+  EXPECT_EQ(0u, resource_pool_->resource_count());
   EXPECT_EQ(1u, resource_pool_->GetBusyResourceCountForTesting());
 
   // Transfer the resource from the busy pool to the unused pool.
-  resource_pool_->CheckBusyResources();
-  EXPECT_EQ(1u, resource_provider_->num_resources());
+  resource_provider_->ReceiveReturnsFromParent(
+      viz::TransferableResource::ReturnResources(transfers));
   EXPECT_EQ(40000u, resource_pool_->GetTotalMemoryUsageForTesting());
   EXPECT_EQ(1u, resource_pool_->GetTotalResourceCountForTesting());
   EXPECT_EQ(0u, resource_pool_->resource_count());
@@ -245,7 +273,6 @@
                                 base::TimeDelta::FromMillisecondsD(200));
   run_loop.Run();
 
-  EXPECT_EQ(0u, resource_provider_->num_resources());
   EXPECT_EQ(0u, resource_pool_->GetTotalMemoryUsageForTesting());
 }
 
@@ -260,7 +287,7 @@
   ResourcePool::InUsePoolResource resource =
       resource_pool_->AcquireResource(size, format, color_space);
   resource_pool_->OnContentReplaced(resource, content_id);
-  auto original_id = resource.gpu_backing_resource_id();
+  auto original_id = resource.unique_id_for_testing();
   resource_pool_->ReleaseResource(std::move(resource));
   resource_pool_->CheckBusyResources();
 
@@ -269,7 +296,7 @@
   ResourcePool::InUsePoolResource reacquired_resource =
       resource_pool_->TryAcquireResourceForPartialRaster(
           new_content_id, new_invalidated_rect, content_id, &invalidated_rect);
-  EXPECT_EQ(original_id, reacquired_resource.gpu_backing_resource_id());
+  EXPECT_EQ(original_id, reacquired_resource.unique_id_for_testing());
   EXPECT_EQ(new_invalidated_rect, invalidated_rect);
   resource_pool_->ReleaseResource(std::move(reacquired_resource));
 }
@@ -287,7 +314,7 @@
   ResourcePool::InUsePoolResource resource =
       resource_pool_->AcquireResource(size, format, color_space);
   resource_pool_->OnContentReplaced(resource, content_ids[0]);
-  auto original_id = resource.gpu_backing_resource_id();
+  auto original_id = resource.unique_id_for_testing();
 
   // Attempt to acquire this resource. It is in use, so its ID and invalidated
   // rect should be updated, but a new resource will be returned.
@@ -315,7 +342,7 @@
   reacquired_resource = resource_pool_->TryAcquireResourceForPartialRaster(
       content_ids[2], second_invalidated_rect, content_ids[1],
       &total_invalidated_rect);
-  EXPECT_EQ(original_id, reacquired_resource.gpu_backing_resource_id());
+  EXPECT_EQ(original_id, reacquired_resource.unique_id_for_testing());
   EXPECT_EQ(expected_total_invalidated_rect, total_invalidated_rect);
   resource_pool_->ReleaseResource(std::move(reacquired_resource));
 }
@@ -327,7 +354,7 @@
   // Create unused resource with size 100x100.
   ResourcePool::InUsePoolResource original =
       resource_pool_->AcquireResource(gfx::Size(100, 100), format, color_space);
-  auto original_id = original.gpu_backing_resource_id();
+  auto original_id = original.unique_id_for_testing();
   CheckAndReturnResource(std::move(original));
 
   // Try some cases that are too large, none should succeed.
@@ -357,15 +384,15 @@
   if (resource_pool_->AllowsNonExactReUseForTesting()) {
     ResourcePool::InUsePoolResource reused = resource_pool_->AcquireResource(
         gfx::Size(50, 100), format, color_space);
-    EXPECT_EQ(original_id, reused.gpu_backing_resource_id());
+    EXPECT_EQ(original_id, reused.unique_id_for_testing());
     CheckAndReturnResource(std::move(reused));
     reused = resource_pool_->AcquireResource(gfx::Size(100, 50), format,
                                              color_space);
-    EXPECT_EQ(original_id, reused.gpu_backing_resource_id());
+    EXPECT_EQ(original_id, reused.unique_id_for_testing());
     CheckAndReturnResource(std::move(reused));
     reused =
         resource_pool_->AcquireResource(gfx::Size(71, 71), format, color_space);
-    EXPECT_EQ(original_id, reused.gpu_backing_resource_id());
+    EXPECT_EQ(original_id, reused.unique_id_for_testing());
     CheckAndReturnResource(std::move(reused));
   } else {
     EXPECT_EQ(nullptr, resource_pool_->ReuseResource(gfx::Size(50, 100), format,
@@ -396,6 +423,8 @@
   gfx::ColorSpace color_space = gfx::ColorSpace::CreateSRGB();
   ResourcePool::InUsePoolResource resource =
       resource_pool_->AcquireResource(size, format, color_space);
+  SetBackingOnResource(resource);
+  resource_pool_->PrepareForExport(resource);
 
   EXPECT_EQ(1u, resource_pool_->GetTotalResourceCountForTesting());
   EXPECT_EQ(0u, resource_pool_->GetBusyResourceCountForTesting());
@@ -407,6 +436,12 @@
   EXPECT_EQ(0u, resource_pool_->GetBusyResourceCountForTesting());
   resource_pool_->OnMemoryStateChange(base::MemoryState::NORMAL);
 
+  // Export the resource to the display compositor, so it will be busy once
+  // released.
+  std::vector<viz::TransferableResource> transfers;
+  resource_provider_->PrepareSendToParent({resource.resource_id_for_export()},
+                                          &transfers);
+
   // Release the resource making it busy.
   resource_pool_->OnMemoryStateChange(base::MemoryState::NORMAL);
   resource_pool_->ReleaseResource(std::move(resource));
@@ -421,7 +456,8 @@
 
   // The resource moves from busy to available.
   resource_pool_->OnMemoryStateChange(base::MemoryState::NORMAL);
-  resource_pool_->CheckBusyResources();
+  resource_provider_->ReceiveReturnsFromParent(
+      viz::TransferableResource::ReturnResources(transfers));
   EXPECT_EQ(1u, resource_pool_->GetTotalResourceCountForTesting());
   EXPECT_EQ(0u, resource_pool_->GetBusyResourceCountForTesting());
 
@@ -443,6 +479,8 @@
   gfx::ColorSpace color_space = gfx::ColorSpace::CreateSRGB();
   ResourcePool::InUsePoolResource resource =
       resource_pool_->AcquireResource(size, format, color_space);
+  SetBackingOnResource(resource);
+  resource_pool_->PrepareForExport(resource);
 
   EXPECT_EQ(1u, resource_pool_->GetTotalResourceCountForTesting());
   EXPECT_EQ(0u, resource_pool_->GetBusyResourceCountForTesting());
@@ -454,6 +492,12 @@
   EXPECT_EQ(0u, resource_pool_->GetBusyResourceCountForTesting());
   resource_pool_->OnMemoryStateChange(base::MemoryState::NORMAL);
 
+  // Export the resource to the display compositor, so it will be busy once
+  // released.
+  std::vector<viz::TransferableResource> transfers;
+  resource_provider_->PrepareSendToParent({resource.resource_id_for_export()},
+                                          &transfers);
+
   // Release the resource making it busy.
   resource_pool_->OnMemoryStateChange(base::MemoryState::NORMAL);
   resource_pool_->ReleaseResource(std::move(resource));
@@ -468,7 +512,8 @@
 
   // The resource moves from busy to available, but since we are SUSPENDED
   // it is not kept.
-  resource_pool_->CheckBusyResources();
+  resource_provider_->ReceiveReturnsFromParent(
+      viz::TransferableResource::ReturnResources(transfers));
   EXPECT_EQ(0u, resource_pool_->GetTotalResourceCountForTesting());
   EXPECT_EQ(0u, resource_pool_->GetBusyResourceCountForTesting());
 }
diff --git a/cc/test/fake_raster_buffer_provider.cc b/cc/test/fake_raster_buffer_provider.cc
index ab6d3948..88de976 100644
--- a/cc/test/fake_raster_buffer_provider.cc
+++ b/cc/test/fake_raster_buffer_provider.cc
@@ -4,8 +4,19 @@
 
 #include "cc/test/fake_raster_buffer_provider.h"
 
+#include "cc/resources/resource_pool.h"
+
 namespace cc {
 
+class StubGpuBacking : public ResourcePool::GpuBacking {
+ public:
+  base::trace_event::MemoryAllocatorDumpGuid MemoryDumpGuid(
+      uint64_t tracing_process_id) override {
+    return {};
+  }
+  base::UnguessableToken SharedMemoryGuid() override { return {}; }
+};
+
 FakeRasterBufferProviderImpl::FakeRasterBufferProviderImpl() = default;
 
 FakeRasterBufferProviderImpl::~FakeRasterBufferProviderImpl() = default;
@@ -15,6 +26,9 @@
     const ResourcePool::InUsePoolResource& resource,
     uint64_t resource_content_id,
     uint64_t previous_content_id) {
+  auto backing = std::make_unique<StubGpuBacking>();
+  backing->mailbox = gpu::Mailbox::Generate();
+  resource.set_gpu_backing(std::move(backing));
   return nullptr;
 }
 
diff --git a/cc/test/layer_tree_pixel_resource_test.cc b/cc/test/layer_tree_pixel_resource_test.cc
index 3e2c178..cc840d3e 100644
--- a/cc/test/layer_tree_pixel_resource_test.cc
+++ b/cc/test/layer_tree_pixel_resource_test.cc
@@ -75,8 +75,8 @@
 
       *raster_buffer_provider = std::make_unique<GpuRasterBufferProvider>(
           compositor_context_provider, worker_context_provider,
-          resource_provider, false, 0, viz::PlatformColor::BestTextureFormat(),
-          false);
+          resource_provider, false, false, 0,
+          viz::PlatformColor::BestTextureFormat(), false);
       *resource_pool = std::make_unique<ResourcePool>(
           resource_provider, std::move(task_runner),
           viz::ResourceTextureHint::kFramebuffer,
@@ -102,7 +102,7 @@
 
       *raster_buffer_provider = std::make_unique<OneCopyRasterBufferProvider>(
           task_runner, compositor_context_provider, worker_context_provider,
-          resource_provider, max_bytes_per_copy_operation, false,
+          resource_provider, max_bytes_per_copy_operation, false, false,
           max_staging_buffer_usage_in_bytes,
           viz::PlatformColor::BestTextureFormat());
       *resource_pool = std::make_unique<ResourcePool>(
diff --git a/cc/tiles/tile_manager.h b/cc/tiles/tile_manager.h
index 963546e..1c4a90d 100644
--- a/cc/tiles/tile_manager.h
+++ b/cc/tiles/tile_manager.h
@@ -192,12 +192,20 @@
   void InitializeTilesWithResourcesForTesting(const std::vector<Tile*>& tiles) {
     for (size_t i = 0; i < tiles.size(); ++i) {
       TileDrawInfo& draw_info = tiles[i]->draw_info();
-      draw_info.SetResource(
+      ResourcePool::InUsePoolResource resource =
           resource_pool_->AcquireResource(
               tiles[i]->desired_texture_size(),
               raster_buffer_provider_->GetResourceFormat(false),
-              client_->GetRasterColorSpace().color_space),
-          false, false);
+              client_->GetRasterColorSpace().color_space);
+      raster_buffer_provider_->AcquireBufferForRaster(resource, 0, 0);
+      // The raster here never really happened, cuz tests. So just add an
+      // arbitrary sync token.
+      if (resource.gpu_backing()) {
+        resource.gpu_backing()->mailbox_sync_token.Set(
+            gpu::GPU_IO, gpu::CommandBufferId::FromUnsafeValue(1), 1);
+      }
+      resource_pool_->PrepareForExport(resource);
+      draw_info.SetResource(std::move(resource), false, false);
       draw_info.set_resource_ready_for_draw();
     }
   }
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 091fed51..fe76bfdf 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -2640,6 +2640,7 @@
     *raster_buffer_provider = std::make_unique<GpuRasterBufferProvider>(
         compositor_context_provider, worker_context_provider,
         resource_provider_.get(), settings_.use_distance_field_text,
+        settings_.resource_settings.use_gpu_memory_buffer_resources,
         msaa_sample_count, settings_.preferred_tile_format, oop_raster_enabled);
     return;
   }
@@ -2681,7 +2682,9 @@
   *raster_buffer_provider = std::make_unique<OneCopyRasterBufferProvider>(
       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_.use_partial_raster,
+      settings_.resource_settings.use_gpu_memory_buffer_resources,
+      settings_.max_staging_buffer_usage_in_bytes,
       settings_.preferred_tile_format);
 }
 
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index 672b179..9dfbb92 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -6843,7 +6843,7 @@
   DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
                                    LayerTreeHostImpl::FrameData* frame_data,
                                    DrawResult draw_result) override {
-    EXPECT_NE(0u, host_impl->resource_provider()->num_resources());
+    EXPECT_NE(0u, host_impl->resource_pool()->resource_count());
     EndTest();
     return draw_result;
   }
@@ -6884,7 +6884,7 @@
   DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
                                    LayerTreeHostImpl::FrameData* frame_data,
                                    DrawResult draw_result) override {
-    EXPECT_EQ(15u, host_impl->resource_provider()->num_resources());
+    EXPECT_EQ(15u, host_impl->resource_pool()->resource_count());
     EndTest();
     return draw_result;
   }
diff --git a/components/viz/common/BUILD.gn b/components/viz/common/BUILD.gn
index a30f59e..151e96d 100644
--- a/components/viz/common/BUILD.gn
+++ b/components/viz/common/BUILD.gn
@@ -64,6 +64,8 @@
     "gpu/in_process_context_provider.h",
     "gpu/raster_context_provider.cc",
     "gpu/raster_context_provider.h",
+    "gpu/texture_allocation.cc",
+    "gpu/texture_allocation.h",
     "gpu/vulkan_context_provider.h",
     "gpu/vulkan_in_process_context_provider.cc",
     "gpu/vulkan_in_process_context_provider.h",
@@ -150,6 +152,7 @@
     "//gpu/command_buffer/client:gles2_implementation",
     "//gpu/command_buffer/client:gles2_interface",
     "//gpu/command_buffer/client:raster",
+    "//gpu/command_buffer/client:raster_interface",
     "//gpu/command_buffer/service",
     "//gpu/ipc:gl_in_process_context",
     "//gpu/skia_bindings:skia_bindings",
diff --git a/components/viz/common/gpu/texture_allocation.cc b/components/viz/common/gpu/texture_allocation.cc
new file mode 100644
index 0000000..27778ed
--- /dev/null
+++ b/components/viz/common/gpu/texture_allocation.cc
@@ -0,0 +1,112 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/viz/common/gpu/texture_allocation.h"
+
+#include "components/viz/common/resources/resource_format_utils.h"
+#include "gpu/GLES2/gl2extchromium.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/command_buffer/client/raster_interface.h"
+#include "gpu/command_buffer/common/capabilities.h"
+#include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
+#include "ui/gfx/color_space.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace viz {
+
+// static
+TextureAllocation TextureAllocation::MakeTextureId(
+    gpu::gles2::GLES2Interface* gl,
+    const gpu::Capabilities& caps,
+    ResourceFormat format,
+    bool use_gpu_memory_buffer_resources,
+    bool for_framebuffer_attachment) {
+  bool overlay_textures = use_gpu_memory_buffer_resources &&
+                          caps.texture_storage_image &&
+                          IsGpuMemoryBufferFormatSupported(format);
+
+  uint32_t texture_target = GL_TEXTURE_2D;
+  bool overlay_candidate = false;
+  if (overlay_textures) {
+    texture_target = gpu::GetBufferTextureTarget(gfx::BufferUsage::SCANOUT,
+                                                 BufferFormat(format), caps);
+    overlay_candidate = true;
+  }
+
+  uint32_t texture_id;
+  gl->GenTextures(1, &texture_id);
+  gl->BindTexture(texture_target, texture_id);
+  gl->TexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  gl->TexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+  gl->TexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+  gl->TexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+  if (for_framebuffer_attachment && caps.texture_usage) {
+    // Set GL_FRAMEBUFFER_ATTACHMENT_ANGLE since we'll be binding these
+    // textures as a framebuffer for drawing directly to them on the gpu.
+    gl->TexParameteri(texture_target, GL_TEXTURE_USAGE_ANGLE,
+                      GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
+  }
+  gl->BindTexture(texture_target, 0);
+  return {texture_id, texture_target, overlay_candidate};
+}
+
+// static
+void TextureAllocation::AllocateStorage(gpu::gles2::GLES2Interface* gl,
+                                        const gpu::Capabilities& caps,
+                                        ResourceFormat format,
+                                        const gfx::Size& size,
+                                        const TextureAllocation& alloc,
+                                        const gfx::ColorSpace& color_space) {
+  gl->BindTexture(alloc.texture_target, alloc.texture_id);
+  // Allocate backing storage for the texture. The best choice is to use
+  // GpuMemoryBuffers if we can use the texture as an overlay and its asked
+  // for by the caller. Else we try to make the texture have immutable
+  // storage, and finally fall back to standard storage if we must.
+  if (alloc.overlay_candidate) {
+    // |overlay_candidate| was only set when these were true, and
+    // |use_gpu_memory_buffer_resources| was specified by the caller.
+    DCHECK(caps.texture_storage_image);
+    DCHECK(IsGpuMemoryBufferFormatSupported(format));
+
+    gl->TexStorage2DImageCHROMIUM(
+        alloc.texture_target, TextureStorageFormat(format), GL_SCANOUT_CHROMIUM,
+        size.width(), size.height());
+    if (color_space.IsValid()) {
+      gl->SetColorSpaceMetadataCHROMIUM(
+          alloc.texture_id, reinterpret_cast<GLColorSpace>(
+                                const_cast<gfx::ColorSpace*>(&color_space)));
+    }
+  } else if (caps.texture_storage) {
+    gl->TexStorage2DEXT(alloc.texture_target, 1, TextureStorageFormat(format),
+                        size.width(), size.height());
+  } else {
+    gl->TexImage2D(alloc.texture_target, 0, GLInternalFormat(format),
+                   size.width(), size.height(), 0, GLDataFormat(format),
+                   GLDataType(format), nullptr);
+  }
+}
+
+// static
+void TextureAllocation::AllocateStorage(gpu::raster::RasterInterface* ri,
+                                        const gpu::Capabilities& caps,
+                                        ResourceFormat format,
+                                        const gfx::Size& size,
+                                        const TextureAllocation& alloc,
+                                        const gfx::ColorSpace& color_space) {
+  // ETC1 resources cannot be preallocated.
+  if (format == ETC1)
+    return;
+  ri->BindTexture(alloc.texture_target, alloc.texture_id);
+  ri->TexStorageForRaster(
+      alloc.texture_target, format, size.width(), size.height(),
+      alloc.overlay_candidate ? gpu::raster::kOverlay : gpu::raster::kNone);
+  if (alloc.overlay_candidate && color_space.IsValid()) {
+    ri->SetColorSpaceMetadataCHROMIUM(
+        alloc.texture_id, reinterpret_cast<GLColorSpace>(
+                              const_cast<gfx::ColorSpace*>(&color_space)));
+  }
+}
+
+}  // namespace viz
diff --git a/components/viz/common/gpu/texture_allocation.h b/components/viz/common/gpu/texture_allocation.h
new file mode 100644
index 0000000..61b40e4f
--- /dev/null
+++ b/components/viz/common/gpu/texture_allocation.h
@@ -0,0 +1,65 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_VIZ_COMMON_GPU_TEXTURE_ALLOCATION_H_
+#define COMPONENTS_VIZ_COMMON_GPU_TEXTURE_ALLOCATION_H_
+
+#include "components/viz/common/resources/resource_format.h"
+#include "components/viz/common/viz_common_export.h"
+#include "third_party/khronos/GLES2/gl2.h"
+
+#include <stdint.h>
+
+namespace gfx {
+class ColorSpace;
+class Size;
+}  // namespace gfx
+
+namespace gpu {
+struct Capabilities;
+namespace gles2 {
+class GLES2Interface;
+}
+namespace raster {
+class RasterInterface;
+}
+}  // namespace gpu
+
+namespace viz {
+
+class VIZ_COMMON_EXPORT TextureAllocation {
+ public:
+  GLuint texture_id = 0;
+  GLenum texture_target = 0;
+  bool overlay_candidate = false;
+
+  // Generates a texture id and sets it up for use, but without any storage
+  // allocated pixels.
+  static TextureAllocation MakeTextureId(gpu::gles2::GLES2Interface* gl,
+                                         const gpu::Capabilities& caps,
+                                         ResourceFormat format,
+                                         bool use_gpu_memory_buffer_resources,
+                                         bool for_framebuffer_attachment);
+
+  // Allocates the storage for a texture id previously from MakeTextureId().
+  // Can be called on a different context, if the texture id is mapped to
+  // another context with a mailbox. The |format| should match the one given to
+  // MakeTextureId().
+  static void AllocateStorage(gpu::gles2::GLES2Interface* gl,
+                              const gpu::Capabilities& caps,
+                              ResourceFormat format,
+                              const gfx::Size& size,
+                              const TextureAllocation& alloc,
+                              const gfx::ColorSpace& color_space);
+  static void AllocateStorage(gpu::raster::RasterInterface* ri,
+                              const gpu::Capabilities& caps,
+                              ResourceFormat format,
+                              const gfx::Size& size,
+                              const TextureAllocation& alloc,
+                              const gfx::ColorSpace& color_space);
+};
+
+}  // namespace viz
+
+#endif  // COMPONENTS_VIZ_COMMON_GPU_TEXTURE_ALLOCATION_H_
diff --git a/components/viz/common/resources/resource_format_utils.cc b/components/viz/common/resources/resource_format_utils.cc
index 51275f8..57a37f19 100644
--- a/components/viz/common/resources/resource_format_utils.cc
+++ b/components/viz/common/resources/resource_format_utils.cc
@@ -219,4 +219,25 @@
   return GL_RGBA8_OES;
 }
 
+bool IsGpuMemoryBufferFormatSupported(ResourceFormat format) {
+  switch (format) {
+    case BGRA_8888:
+    case RED_8:
+    case R16_EXT:
+    case RGBA_4444:
+    case RGBA_8888:
+    case ETC1:
+    case RGBA_F16:
+      return true;
+    // These formats have no BufferFormat equivalent.
+    case ALPHA_8:
+    case LUMINANCE_8:
+    case RGB_565:
+    case LUMINANCE_F16:
+      return false;
+  }
+  NOTREACHED();
+  return false;
+}
+
 }  // namespace viz
diff --git a/components/viz/common/resources/resource_format_utils.h b/components/viz/common/resources/resource_format_utils.h
index 2dc66bc..1e0a6045 100644
--- a/components/viz/common/resources/resource_format_utils.h
+++ b/components/viz/common/resources/resource_format_utils.h
@@ -36,6 +36,11 @@
 VIZ_RESOURCE_FORMAT_EXPORT unsigned int TextureStorageFormat(
     ResourceFormat format);
 
+// Returns whether the format can be used with GpuMemoryBuffer texture storage,
+// allocated through TexStorage2DImageCHROMIUM.
+VIZ_RESOURCE_FORMAT_EXPORT bool IsGpuMemoryBufferFormatSupported(
+    ResourceFormat format);
+
 }  // namespace viz
 
 #endif  // COMPONENTS_VIZ_COMMON_RESOURCES_RESOURCE_FORMAT_UTILS_H_