Add delegated rendering support for software renderer.

This patch adds support to cc/ for delegated rendering with a software compositor. A new SharedBitmapManager is added, which will create SharedBitmaps with unique IDs in shared memory. These can be filled in the child, and their IDs can be sent to the browser so it can map them and draw from them.

No implementations of the SharedBitmapManager are added in this patch, so delegated rendering support won't work in practice yet, and it will fall back to not allocating anything in shared memory.

BUG=

Review URL: https://codereview.chromium.org/24632004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@230245 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/cc/cc.gyp b/cc/cc.gyp
index df268ee2..deb2fbde 100644
--- a/cc/cc.gyp
+++ b/cc/cc.gyp
@@ -360,6 +360,9 @@
         'resources/scoped_resource.h',
         'resources/scoped_ui_resource.cc',
         'resources/scoped_ui_resource.h',
+        'resources/shared_bitmap.cc',
+        'resources/shared_bitmap.h',
+        'resources/shared_bitmap_manager.h',
         'resources/single_release_callback.cc',
         'resources/single_release_callback.h',
         'resources/skpicture_content_layer_updater.cc',
diff --git a/cc/layers/layer_unittest.cc b/cc/layers/layer_unittest.cc
index 3a7a1c1..c66eb855 100644
--- a/cc/layers/layer_unittest.cc
+++ b/cc/layers/layer_unittest.cc
@@ -39,7 +39,7 @@
 class MockLayerTreeHost : public LayerTreeHost {
  public:
   explicit MockLayerTreeHost(LayerTreeHostClient* client)
-      : LayerTreeHost(client, LayerTreeSettings()) {
+      : LayerTreeHost(client, NULL, LayerTreeSettings()) {
     Initialize(NULL);
   }
 
@@ -803,11 +803,12 @@
       : client_(FakeLayerTreeHostClient::DIRECT_3D) {}
 
   scoped_ptr<LayerTreeHost> Create() {
-    return LayerTreeHost::Create(&client_, LayerTreeSettings(), NULL).Pass();
+    return LayerTreeHost::Create(&client_, NULL, LayerTreeSettings(), NULL)
+        .Pass();
   }
 
   scoped_ptr<LayerTreeHost> Create(LayerTreeSettings settings) {
-    return LayerTreeHost::Create(&client_, settings, NULL).Pass();
+    return LayerTreeHost::Create(&client_, NULL, settings, NULL).Pass();
   }
 
  private:
diff --git a/cc/layers/nine_patch_layer_unittest.cc b/cc/layers/nine_patch_layer_unittest.cc
index f616560..7213a51 100644
--- a/cc/layers/nine_patch_layer_unittest.cc
+++ b/cc/layers/nine_patch_layer_unittest.cc
@@ -32,7 +32,7 @@
 class MockLayerTreeHost : public LayerTreeHost {
  public:
   explicit MockLayerTreeHost(LayerTreeHostClient* client)
-      : LayerTreeHost(client, LayerTreeSettings()) {
+      : LayerTreeHost(client, NULL, LayerTreeSettings()) {
     Initialize(NULL);
   }
 };
diff --git a/cc/layers/scrollbar_layer_unittest.cc b/cc/layers/scrollbar_layer_unittest.cc
index 250d610..0423cdc 100644
--- a/cc/layers/scrollbar_layer_unittest.cc
+++ b/cc/layers/scrollbar_layer_unittest.cc
@@ -514,7 +514,7 @@
  public:
   MockLayerTreeHost(LayerTreeHostClient* client,
                     const LayerTreeSettings& settings)
-      : LayerTreeHost(client, settings),
+      : LayerTreeHost(client, NULL, settings),
         next_id_(1),
         total_ui_resource_created_(0),
         total_ui_resource_deleted_(0) {
diff --git a/cc/layers/texture_layer_unittest.cc b/cc/layers/texture_layer_unittest.cc
index bdb1358..c576341 100644
--- a/cc/layers/texture_layer_unittest.cc
+++ b/cc/layers/texture_layer_unittest.cc
@@ -44,7 +44,7 @@
 class MockLayerTreeHost : public LayerTreeHost {
  public:
   explicit MockLayerTreeHost(LayerTreeHostClient* client)
-      : LayerTreeHost(client, LayerTreeSettings()) {
+      : LayerTreeHost(client, NULL, LayerTreeSettings()) {
     Initialize(NULL);
   }
 
diff --git a/cc/layers/tiled_layer_unittest.cc b/cc/layers/tiled_layer_unittest.cc
index 47d694b..9bdb907 100644
--- a/cc/layers/tiled_layer_unittest.cc
+++ b/cc/layers/tiled_layer_unittest.cc
@@ -60,6 +60,7 @@
   virtual void SetUp() {
     impl_thread_.Start();
     layer_tree_host_ = LayerTreeHost::Create(&fake_layer_tree_host_client_,
+                                             NULL,
                                              settings_,
                                              impl_thread_.message_loop_proxy());
     proxy_ = layer_tree_host_->proxy();
@@ -73,7 +74,7 @@
     DebugScopedSetImplThreadAndMainThreadBlocked
         impl_thread_and_main_thread_blocked(proxy_);
     resource_provider_ =
-        ResourceProvider::Create(output_surface_.get(), 0, false);
+        ResourceProvider::Create(output_surface_.get(), NULL, 0, false);
     host_impl_ = make_scoped_ptr(new FakeLayerTreeHostImpl(proxy_));
   }
 
diff --git a/cc/layers/ui_resource_layer_unittest.cc b/cc/layers/ui_resource_layer_unittest.cc
index 1720b81..a2c75c1 100644
--- a/cc/layers/ui_resource_layer_unittest.cc
+++ b/cc/layers/ui_resource_layer_unittest.cc
@@ -32,7 +32,7 @@
 class MockLayerTreeHost : public LayerTreeHost {
  public:
   explicit MockLayerTreeHost(LayerTreeHostClient* client)
-      : LayerTreeHost(client, LayerTreeSettings()) {
+      : LayerTreeHost(client, NULL, LayerTreeSettings()) {
     Initialize(NULL);
   }
 };
diff --git a/cc/output/delegating_renderer.cc b/cc/output/delegating_renderer.cc
index 772a16a..7d95550 100644
--- a/cc/output/delegating_renderer.cc
+++ b/cc/output/delegating_renderer.cc
@@ -60,7 +60,8 @@
   capabilities_.using_offscreen_context3d = false;
 
   if (!output_surface_->context_provider()) {
-    // TODO(danakj): Make software compositing work.
+    capabilities_.using_shared_memory_resources = true;
+    capabilities_.using_map_image = settings_->use_map_image;
     return true;
   }
 
diff --git a/cc/output/gl_renderer_unittest.cc b/cc/output/gl_renderer_unittest.cc
index 7f60c2d..8b71ca4 100644
--- a/cc/output/gl_renderer_unittest.cc
+++ b/cc/output/gl_renderer_unittest.cc
@@ -221,7 +221,7 @@
     CHECK(output_surface_->BindToClient(&output_surface_client_));
 
     resource_provider_ =
-        ResourceProvider::Create(output_surface_.get(), 0, false).Pass();
+        ResourceProvider::Create(output_surface_.get(), NULL, 0, false).Pass();
     renderer_ = make_scoped_ptr(new FakeRendererGL(&renderer_client_,
                                                    &settings_,
                                                    output_surface_.get(),
@@ -312,8 +312,8 @@
             new ShaderCreatorMockGraphicsContext())).Pass();
     CHECK(output_surface_->BindToClient(&output_surface_client_));
 
-    resource_provider_ = ResourceProvider::Create(
-        output_surface_.get(), 0, false).Pass();
+    resource_provider_ =
+        ResourceProvider::Create(output_surface_.get(), NULL, 0, false).Pass();
     renderer_.reset(new FakeRendererGL(&renderer_client_,
                                        &settings_,
                                        output_surface_.get(),
@@ -634,7 +634,7 @@
   CHECK(output_surface->BindToClient(&output_surface_client));
 
   scoped_ptr<ResourceProvider> resource_provider(
-      ResourceProvider::Create(output_surface.get(), 0, false));
+      ResourceProvider::Create(output_surface.get(), NULL, 0, false));
 
   LayerTreeSettings settings;
   FakeRendererClient renderer_client;
@@ -679,7 +679,7 @@
   CHECK(output_surface->BindToClient(&output_surface_client));
 
   scoped_ptr<ResourceProvider> resource_provider(
-      ResourceProvider::Create(output_surface.get(), 0, false));
+      ResourceProvider::Create(output_surface.get(), NULL, 0, false));
 
   LayerTreeSettings settings;
   FakeRendererClient renderer_client;
@@ -714,7 +714,7 @@
   CHECK(output_surface->BindToClient(&output_surface_client));
 
   scoped_ptr<ResourceProvider> resource_provider(
-      ResourceProvider::Create(output_surface.get(), 0, false));
+      ResourceProvider::Create(output_surface.get(), NULL, 0, false));
 
   LayerTreeSettings settings;
   FakeRendererClient renderer_client;
@@ -752,7 +752,7 @@
   CHECK(output_surface->BindToClient(&output_surface_client));
 
   scoped_ptr<ResourceProvider> resource_provider(
-      ResourceProvider::Create(output_surface.get(), 0, false));
+      ResourceProvider::Create(output_surface.get(), NULL, 0, false));
 
   LayerTreeSettings settings;
   FakeRendererClient renderer_client;
@@ -784,7 +784,7 @@
   CHECK(output_surface->BindToClient(&output_surface_client));
 
   scoped_ptr<ResourceProvider> resource_provider(
-      ResourceProvider::Create(output_surface.get(), 0, false));
+      ResourceProvider::Create(output_surface.get(), NULL, 0, false));
 
   LayerTreeSettings settings;
   FakeRendererClient renderer_client;
@@ -860,7 +860,7 @@
   CHECK(output_surface->BindToClient(&output_surface_client));
 
   scoped_ptr<ResourceProvider> resource_provider(
-      ResourceProvider::Create(output_surface.get(), 0, false));
+      ResourceProvider::Create(output_surface.get(), NULL, 0, false));
 
   LayerTreeSettings settings;
   FakeRendererClient renderer_client;
@@ -920,7 +920,7 @@
   CHECK(output_surface->BindToClient(&output_surface_client));
 
   scoped_ptr<ResourceProvider> resource_provider(
-      ResourceProvider::Create(output_surface.get(), 0, false));
+      ResourceProvider::Create(output_surface.get(), NULL, 0, false));
 
   LayerTreeSettings settings;
   FakeRendererClient renderer_client;
@@ -1007,7 +1007,7 @@
   CHECK(output_surface->BindToClient(&output_surface_client));
 
   scoped_ptr<ResourceProvider> resource_provider(
-      ResourceProvider::Create(output_surface.get(), 0, false));
+      ResourceProvider::Create(output_surface.get(), NULL, 0, false));
 
   LayerTreeSettings settings;
   settings.should_clear_root_render_pass = false;
@@ -1095,7 +1095,7 @@
   CHECK(output_surface->BindToClient(&output_surface_client));
 
   scoped_ptr<ResourceProvider> resource_provider(
-      ResourceProvider::Create(output_surface.get(), 0, false));
+      ResourceProvider::Create(output_surface.get(), NULL, 0, false));
 
   LayerTreeSettings settings;
   FakeRendererClient renderer_client;
@@ -1181,7 +1181,7 @@
   output_surface->set_fixed_size(gfx::Size(100, 100));
 
   scoped_ptr<ResourceProvider> resource_provider(
-      ResourceProvider::Create(output_surface.get(), 0, false));
+      ResourceProvider::Create(output_surface.get(), NULL, 0, false));
 
   LayerTreeSettings settings;
   settings.partial_swap_enabled = true;
@@ -1360,7 +1360,7 @@
   CHECK(output_surface->BindToClient(&output_surface_client));
 
   scoped_ptr<ResourceProvider> resource_provider(
-      ResourceProvider::Create(output_surface.get(), 0, false));
+      ResourceProvider::Create(output_surface.get(), NULL, 0, false));
 
   LayerTreeSettings settings;
   FakeRendererClient renderer_client;
@@ -1714,7 +1714,7 @@
     CHECK(output_surface_.BindToClient(&output_surface_client_));
 
     resource_provider_ =
-        ResourceProvider::Create(&output_surface_, 0, false).Pass();
+        ResourceProvider::Create(&output_surface_, NULL, 0, false).Pass();
 
     renderer_.reset(new FakeRendererGL(
         this, &settings_, &output_surface_, resource_provider_.get()));
diff --git a/cc/output/software_renderer_unittest.cc b/cc/output/software_renderer_unittest.cc
index f88a9ee0..450d1fe3 100644
--- a/cc/output/software_renderer_unittest.cc
+++ b/cc/output/software_renderer_unittest.cc
@@ -34,7 +34,7 @@
     CHECK(output_surface_->BindToClient(&output_surface_client_));
 
     resource_provider_ =
-        ResourceProvider::Create(output_surface_.get(), 0, false);
+        ResourceProvider::Create(output_surface_.get(), NULL, 0, false);
     renderer_ = SoftwareRenderer::Create(
         this, &settings_, output_surface_.get(), resource_provider());
   }
diff --git a/cc/resources/picture_layer_tiling_set_unittest.cc b/cc/resources/picture_layer_tiling_set_unittest.cc
index 231e378..c0d6f0d2e 100644
--- a/cc/resources/picture_layer_tiling_set_unittest.cc
+++ b/cc/resources/picture_layer_tiling_set_unittest.cc
@@ -66,7 +66,7 @@
     CHECK(output_surface->BindToClient(&output_surface_client));
 
     scoped_ptr<ResourceProvider> resource_provider =
-        ResourceProvider::Create(output_surface.get(), 0, false);
+        ResourceProvider::Create(output_surface.get(), NULL, 0, false);
 
     FakePictureLayerTilingClient client;
     client.SetTileSize(gfx::Size(256, 256));
diff --git a/cc/resources/prioritized_resource_unittest.cc b/cc/resources/prioritized_resource_unittest.cc
index fb71533..21cafd1 100644
--- a/cc/resources/prioritized_resource_unittest.cc
+++ b/cc/resources/prioritized_resource_unittest.cc
@@ -24,7 +24,7 @@
     DebugScopedSetImplThread impl_thread(&proxy_);
     CHECK(output_surface_->BindToClient(&output_surface_client_));
     resource_provider_ =
-        cc::ResourceProvider::Create(output_surface_.get(), 0, false);
+        cc::ResourceProvider::Create(output_surface_.get(), NULL, 0, false);
   }
 
   virtual ~PrioritizedResourceTest() {
diff --git a/cc/resources/prioritized_tile_set_unittest.cc b/cc/resources/prioritized_tile_set_unittest.cc
index 37c9cc1..4bf27fb 100644
--- a/cc/resources/prioritized_tile_set_unittest.cc
+++ b/cc/resources/prioritized_tile_set_unittest.cc
@@ -57,9 +57,9 @@
     CHECK(output_surface_->BindToClient(&output_surface_client_));
 
     resource_provider_ =
-        ResourceProvider::Create(output_surface_.get(), 0, false).Pass();
-    tile_manager_.reset(new FakeTileManager(&tile_manager_client_,
-                                            resource_provider_.get()));
+        ResourceProvider::Create(output_surface_.get(), NULL, 0, false).Pass();
+    tile_manager_.reset(
+        new FakeTileManager(&tile_manager_client_, resource_provider_.get()));
     picture_pile_ = FakePicturePileImpl::CreatePile();
   }
 
diff --git a/cc/resources/raster_worker_pool_unittest.cc b/cc/resources/raster_worker_pool_unittest.cc
index 61cb324..023be79 100644
--- a/cc/resources/raster_worker_pool_unittest.cc
+++ b/cc/resources/raster_worker_pool_unittest.cc
@@ -68,7 +68,7 @@
     CHECK(output_surface_->BindToClient(&output_surface_client_));
 
     resource_provider_ =
-        ResourceProvider::Create(output_surface_.get(), 0, false).Pass();
+        ResourceProvider::Create(output_surface_.get(), NULL, 0, false).Pass();
   }
   virtual ~RasterWorkerPoolTest() {
     resource_provider_.reset();
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc
index d76fc4b..0a214a4 100644
--- a/cc/resources/resource_provider.cc
+++ b/cc/resources/resource_provider.cc
@@ -8,6 +8,7 @@
 #include <limits>
 
 #include "base/containers/hash_tables.h"
+#include "base/debug/trace_event.h"
 #include "base/stl_util.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
@@ -15,6 +16,7 @@
 #include "cc/output/gl_renderer.h"  // For the GLC() macro.
 #include "cc/resources/platform_color.h"
 #include "cc/resources/returned_resource.h"
+#include "cc/resources/shared_bitmap_manager.h"
 #include "cc/resources/transferable_resource.h"
 #include "cc/scheduler/texture_uploader.h"
 #include "gpu/GLES2/gl2extchromium.h"
@@ -118,7 +120,8 @@
       lost(false),
       hint(TextureUsageAny),
       type(static_cast<ResourceType>(0)),
-      format(RGBA_8888) {}
+      format(RGBA_8888),
+      shared_bitmap(NULL) {}
 
 ResourceProvider::Resource::~Resource() {}
 
@@ -159,11 +162,13 @@
       lost(false),
       hint(hint),
       type(GLTexture),
-      format(format) {
+      format(format),
+      shared_bitmap(NULL) {
   DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
 }
 
 ResourceProvider::Resource::Resource(uint8_t* pixels,
+                                     SharedBitmap* bitmap,
                                      gfx::Size size,
                                      GLenum filter,
                                      GLint wrap_mode)
@@ -196,7 +201,8 @@
       lost(false),
       hint(TextureUsageAny),
       type(Bitmap),
-      format(RGBA_8888) {
+      format(RGBA_8888),
+      shared_bitmap(bitmap) {
   DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
 }
 
@@ -206,10 +212,12 @@
 
 scoped_ptr<ResourceProvider> ResourceProvider::Create(
     OutputSurface* output_surface,
+    SharedBitmapManager* shared_bitmap_manager,
     int highp_threshold_min,
     bool use_rgba_4444_texture_format) {
   scoped_ptr<ResourceProvider> resource_provider(
       new ResourceProvider(output_surface,
+                           shared_bitmap_manager,
                            highp_threshold_min,
                            use_rgba_4444_texture_format));
 
@@ -311,10 +319,19 @@
 ResourceProvider::ResourceId ResourceProvider::CreateBitmap(gfx::Size size) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
-  uint8_t* pixels = new uint8_t[4 * size.GetArea()];
+  scoped_ptr<SharedBitmap> bitmap;
+  if (shared_bitmap_manager_)
+    bitmap = shared_bitmap_manager_->AllocateSharedBitmap(size);
+
+  uint8_t* pixels;
+  if (bitmap)
+    pixels = bitmap->pixels();
+  else
+    pixels = new uint8_t[4 * size.GetArea()];
 
   ResourceId id = next_id_++;
-  Resource resource(pixels, size, GL_LINEAR, GL_CLAMP_TO_EDGE);
+  Resource resource(
+      pixels, bitmap.release(), size, GL_LINEAR, GL_CLAMP_TO_EDGE);
   resource.allocated = true;
   resources_[id] = resource;
   return id;
@@ -375,8 +392,16 @@
     base::SharedMemory* shared_memory = mailbox.shared_memory();
     DCHECK(shared_memory->memory());
     uint8_t* pixels = reinterpret_cast<uint8_t*>(shared_memory->memory());
-    resource = Resource(
-        pixels, mailbox.shared_memory_size(), GL_LINEAR, GL_CLAMP_TO_EDGE);
+    scoped_ptr<SharedBitmap> shared_bitmap;
+    if (shared_bitmap_manager_) {
+      shared_bitmap =
+          shared_bitmap_manager_->GetBitmapForSharedMemory(shared_memory);
+    }
+    resource = Resource(pixels,
+                        shared_bitmap.release(),
+                        mailbox.shared_memory_size(),
+                        GL_LINEAR,
+                        GL_CLAMP_TO_EDGE);
   }
   resource.external = true;
   resource.allocated = true;
@@ -407,8 +432,9 @@
 
 void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it,
                                               DeleteStyle style) {
+  TRACE_EVENT0("cc", "ResourceProvider::DeleteResourceInternal");
   Resource* resource = &it->second;
-  bool lost_resource = lost_output_surface_ || resource->lost;
+  bool lost_resource = resource->lost;
 
   DCHECK(resource->exported_count == 0 || style != Normal);
   if (style == ForShutdown && resource->exported_count > 0)
@@ -438,6 +464,7 @@
   if (resource->mailbox.IsValid() && resource->external) {
     unsigned sync_point = resource->mailbox.sync_point();
     if (resource->mailbox.IsTexture()) {
+      lost_resource |= lost_output_surface_;
       WebGraphicsContext3D* context3d = Context3d();
       DCHECK(context3d);
       if (resource->gl_id)
@@ -450,10 +477,16 @@
       if (resource->pixels && shared_memory) {
         DCHECK(shared_memory->memory() == resource->pixels);
         resource->pixels = NULL;
+        delete resource->shared_bitmap;
+        resource->shared_bitmap = NULL;
       }
     }
     resource->release_callback.Run(sync_point, lost_resource);
   }
+  if (resource->shared_bitmap) {
+    delete resource->shared_bitmap;
+    resource->pixels = NULL;
+  }
   if (resource->pixels)
     delete[] resource->pixels;
   if (resource->pixel_buffer)
@@ -754,9 +787,11 @@
 }
 
 ResourceProvider::ResourceProvider(OutputSurface* output_surface,
+                                   SharedBitmapManager* shared_bitmap_manager,
                                    int highp_threshold_min,
                                    bool use_rgba_4444_texture_format)
     : output_surface_(output_surface),
+      shared_bitmap_manager_(shared_bitmap_manager),
       lost_output_surface_(false),
       highp_threshold_min_(highp_threshold_min),
       next_id_(1),
@@ -876,17 +911,15 @@
                                            TransferableResourceArray* list) {
   DCHECK(thread_checker_.CalledOnValidThread());
   WebGraphicsContext3D* context3d = Context3d();
-  if (!context3d || !context3d->makeContextCurrent()) {
-    // TODO(skaslev): Implement this path for software compositing.
-    return;
-  }
+  if (context3d)
+    context3d->makeContextCurrent();
   bool need_sync_point = false;
   for (ResourceIdArray::const_iterator it = resources.begin();
        it != resources.end();
        ++it) {
     TransferableResource resource;
     TransferResource(context3d, *it, &resource);
-    if (!resource.sync_point)
+    if (!resource.sync_point && !resource.is_software)
       need_sync_point = true;
     ++resources_.find(*it)->second.exported_count;
     list->push_back(resource);
@@ -906,10 +939,8 @@
     int child, const TransferableResourceArray& resources) {
   DCHECK(thread_checker_.CalledOnValidThread());
   WebGraphicsContext3D* context3d = Context3d();
-  if (!context3d || !context3d->makeContextCurrent()) {
-    // TODO(skaslev): Implement this path for software compositing.
-    return;
-  }
+  if (context3d)
+    context3d->makeContextCurrent();
   Child& child_info = children_.find(child)->second;
   for (TransferableResourceArray::const_iterator it = resources.begin();
        it != resources.end();
@@ -920,34 +951,58 @@
       resources_[resource_in_map_it->second].imported_count++;
       continue;
     }
-    unsigned texture_id;
-    // NOTE: If the parent is a browser and the child a renderer, the parent
-    // is not supposed to have its context wait, because that could induce
-    // deadlocks and/or security issues. The caller is responsible for
-    // waiting asynchronously, and resetting sync_point before calling this.
-    // However if the parent is a renderer (e.g. browser tag), it may be ok
-    // (and is simpler) to wait.
-    if (it->sync_point)
-      GLC(context3d, context3d->waitSyncPoint(it->sync_point));
-    GLC(context3d, texture_id = context3d->createTexture());
-    GLC(context3d, context3d->bindTexture(it->target, texture_id));
-    GLC(context3d,
-        context3d->consumeTextureCHROMIUM(it->target, it->mailbox.name));
+
+    scoped_ptr<SharedBitmap> bitmap;
+    uint8_t* pixels = NULL;
+    if (it->is_software) {
+      if (shared_bitmap_manager_)
+        bitmap = shared_bitmap_manager_->GetSharedBitmapFromId(it->size,
+                                                               it->mailbox);
+      if (bitmap)
+        pixels = bitmap->pixels();
+    }
+
+    if ((!it->is_software && !context3d) || (it->is_software && !pixels)) {
+      TRACE_EVENT0("cc", "ResourceProvider::ReceiveFromChild dropping invalid");
+      ReturnedResourceArray to_return;
+      to_return.push_back(it->ToReturnedResource());
+      child_info.return_callback.Run(to_return);
+      continue;
+    }
+
     ResourceId local_id = next_id_++;
-    Resource resource(texture_id,
-                      it->size,
-                      it->target,
-                      it->filter,
-                      0,
-                      GL_CLAMP_TO_EDGE,
-                      TextureUsageAny,
-                      it->format);
-    resource.mailbox.SetName(it->mailbox);
+    Resource& resource = resources_[local_id];
+    if (it->is_software) {
+      resource = Resource(
+          pixels, bitmap.release(), it->size, GL_LINEAR, GL_CLAMP_TO_EDGE);
+    } else {
+      unsigned texture_id;
+      // NOTE: If the parent is a browser and the child a renderer, the parent
+      // is not supposed to have its context wait, because that could induce
+      // deadlocks and/or security issues. The caller is responsible for
+      // waiting asynchronously, and resetting sync_point before calling this.
+      // However if the parent is a renderer (e.g. browser tag), it may be ok
+      // (and is simpler) to wait.
+      if (it->sync_point)
+        GLC(context3d, context3d->waitSyncPoint(it->sync_point));
+      GLC(context3d, texture_id = context3d->createTexture());
+      GLC(context3d, context3d->bindTexture(it->target, texture_id));
+      GLC(context3d,
+          context3d->consumeTextureCHROMIUM(it->target, it->mailbox.name));
+      resource = Resource(texture_id,
+                          it->size,
+                          it->target,
+                          it->filter,
+                          0,
+                          GL_CLAMP_TO_EDGE,
+                          TextureUsageAny,
+                          it->format);
+      resource.mailbox.SetName(it->mailbox);
+    }
     resource.child_id = child;
     // Don't allocate a texture for a child.
     resource.allocated = true;
     resource.imported_count = 1;
-    resources_[local_id] = resource;
     child_info.parent_to_child_map[local_id] = it->id;
     child_info.child_to_parent_map[it->id] = local_id;
   }
@@ -997,10 +1052,8 @@
     const ReturnedResourceArray& resources) {
   DCHECK(thread_checker_.CalledOnValidThread());
   WebGraphicsContext3D* context3d = Context3d();
-  if (!context3d || !context3d->makeContextCurrent()) {
-    // TODO(skaslev): Implement this path for software compositing.
-    return;
-  }
+  if (context3d)
+    context3d->makeContextCurrent();
 
   int child_id = 0;
   Child* child_info = NULL;
@@ -1043,7 +1096,7 @@
     if (resource->gl_id) {
       if (returned.sync_point)
         GLC(context3d, context3d->waitSyncPoint(returned.sync_point));
-    } else {
+    } else if (!resource->shared_bitmap) {
       resource->mailbox =
           TextureMailbox(resource->mailbox.name(), returned.sync_point);
     }
@@ -1096,10 +1149,10 @@
   resource->filter = source->filter;
   resource->size = source->size;
 
-  // TODO(skaslev) Implement this path for shared memory resources.
-  DCHECK(!source->mailbox.IsSharedMemory());
-
-  if (!source->mailbox.IsTexture()) {
+  if (source->shared_bitmap) {
+    resource->mailbox = source->shared_bitmap->id();
+    resource->is_software = true;
+  } else if (!source->mailbox.IsValid()) {
     // This is a resource allocated by the compositor, we need to produce it.
     // Don't set a sync point, the caller will do it.
     DCHECK(source->gl_id);
@@ -1110,6 +1163,7 @@
                                         resource->mailbox.name));
     source->mailbox.SetName(resource->mailbox);
   } else {
+    DCHECK(source->mailbox.IsTexture());
     // This is either an external resource, or a compositor resource that we
     // already exported. Make sure to forward the sync point that we were given.
     resource->mailbox = source->mailbox.name();
@@ -1129,10 +1183,8 @@
     return;
 
   WebGraphicsContext3D* context3d = Context3d();
-  if (!context3d || !context3d->makeContextCurrent()) {
-    // TODO(skaslev): Implement this path for software compositing.
-    return;
-  }
+  if (context3d)
+    context3d->makeContextCurrent();
 
   ReturnedResourceArray to_return;
 
@@ -1152,7 +1204,8 @@
     ResourceId child_id = child_info->parent_to_child_map[local_id];
     DCHECK(child_info->child_to_parent_map.count(child_id));
 
-    bool is_lost = resource.lost || lost_output_surface_;
+    bool is_lost =
+        resource.lost || (!resource.shared_bitmap && lost_output_surface_);
     if (resource.exported_count > 0) {
       if (style != ForShutdown) {
         // Defer this until we receive the resource back from the parent.
@@ -1164,7 +1217,7 @@
       is_lost = true;
     }
 
-    if (resource.filter != resource.original_filter) {
+    if (context3d && resource.filter != resource.original_filter) {
       DCHECK(resource.target);
       DCHECK(resource.gl_id);
 
@@ -1182,7 +1235,7 @@
     ReturnedResource returned;
     returned.id = child_id;
     returned.sync_point = resource.mailbox.sync_point();
-    if (!returned.sync_point)
+    if (!returned.sync_point && !resource.shared_bitmap)
       need_sync_point = true;
     returned.count = resource.imported_count;
     returned.lost = is_lost;
@@ -1194,6 +1247,7 @@
     DeleteResourceInternal(it, style);
   }
   if (need_sync_point) {
+    DCHECK(context3d);
     unsigned int sync_point = context3d->insertSyncPoint();
     for (size_t i = 0; i < to_return.size(); ++i) {
       if (!to_return[i].sync_point)
@@ -1646,6 +1700,16 @@
   return stride;
 }
 
+base::SharedMemory* ResourceProvider::GetSharedMemory(ResourceId id) {
+  Resource* resource = GetResource(id);
+  DCHECK(!resource->external);
+  DCHECK_EQ(resource->exported_count, 0);
+
+  if (!resource->shared_bitmap)
+    return NULL;
+  return resource->shared_bitmap->memory();
+}
+
 GLint ResourceProvider::GetActiveTextureUnit(WebGraphicsContext3D* context) {
   GLint active_unit = 0;
   context->getIntegerv(GL_ACTIVE_TEXTURE, &active_unit);
diff --git a/cc/resources/resource_provider.h b/cc/resources/resource_provider.h
index b8cb399..3b9e8e0 100644
--- a/cc/resources/resource_provider.h
+++ b/cc/resources/resource_provider.h
@@ -39,6 +39,8 @@
 }
 
 namespace cc {
+class SharedBitmap;
+class SharedBitmapManager;
 class TextureUploader;
 
 // This class is not thread-safe and can only be called from the thread it was
@@ -59,9 +61,11 @@
     Bitmap,
   };
 
-  static scoped_ptr<ResourceProvider> Create(OutputSurface* output_surface,
-                                             int highp_threshold_min,
-                                             bool use_rgba_4444_texture_format);
+  static scoped_ptr<ResourceProvider> Create(
+      OutputSurface* output_surface,
+      SharedBitmapManager* shared_bitmap_manager,
+      int highp_threshold_min,
+      bool use_rgba_4444_texture_format);
   virtual ~ResourceProvider();
 
   void InitializeSoftware();
@@ -320,6 +324,8 @@
   // Returns the stride for the image.
   int GetImageStride(ResourceId id);
 
+  base::SharedMemory* GetSharedMemory(ResourceId id);
+
   // For tests only! This prevents detecting uninitialized reads.
   // Use SetPixels or LockForWrite to allocate implicitly.
   void AllocateForTesting(ResourceId id);
@@ -359,6 +365,7 @@
              TextureUsageHint hint,
              ResourceFormat format);
     Resource(uint8_t* pixels,
+             SharedBitmap* bitmap,
              gfx::Size size,
              GLenum filter,
              GLint wrap_mode);
@@ -398,6 +405,7 @@
     TextureUsageHint hint;
     ResourceType type;
     ResourceFormat format;
+    SharedBitmap* shared_bitmap;
   };
   typedef base::hash_map<ResourceId, Resource> ResourceMap;
 
@@ -422,6 +430,7 @@
   }
 
   ResourceProvider(OutputSurface* output_surface,
+                   SharedBitmapManager* shared_bitmap_manager,
                    int highp_threshold_min,
                    bool use_rgba_4444_texture_format);
 
@@ -461,6 +470,7 @@
   WebKit::WebGraphicsContext3D* Context3d() const;
 
   OutputSurface* output_surface_;
+  SharedBitmapManager* shared_bitmap_manager_;
   bool lost_output_surface_;
   int highp_threshold_min_;
   ResourceId next_id_;
diff --git a/cc/resources/resource_provider_unittest.cc b/cc/resources/resource_provider_unittest.cc
index 05a10a2..23da024 100644
--- a/cc/resources/resource_provider_unittest.cc
+++ b/cc/resources/resource_provider_unittest.cc
@@ -15,6 +15,7 @@
 #include "cc/debug/test_web_graphics_context_3d.h"
 #include "cc/output/output_surface.h"
 #include "cc/resources/returned_resource.h"
+#include "cc/resources/shared_bitmap_manager.h"
 #include "cc/resources/single_release_callback.h"
 #include "cc/test/fake_output_surface.h"
 #include "cc/test/fake_output_surface_client.h"
@@ -44,6 +45,41 @@
 
 static void EmptyReleaseCallback(unsigned sync_point, bool lost_resource) {}
 
+static void SharedMemoryReleaseCallback(scoped_ptr<base::SharedMemory> memory,
+                                        unsigned sync_point,
+                                        bool lost_resource) {}
+
+static void ReleaseTextureMailbox(unsigned* release_sync_point,
+                                  bool* release_lost_resource,
+                                  unsigned sync_point,
+                                  bool lost_resource) {
+  *release_sync_point = sync_point;
+  *release_lost_resource = lost_resource;
+}
+
+static void ReleaseSharedMemoryCallback(
+    scoped_ptr<base::SharedMemory> shared_memory,
+    bool* release_called,
+    unsigned* release_sync_point,
+    bool* lost_resource_result,
+    unsigned sync_point,
+    bool lost_resource) {
+  *release_called = true;
+  *release_sync_point = sync_point;
+  *lost_resource_result = lost_resource;
+}
+
+static scoped_ptr<base::SharedMemory> CreateAndFillSharedMemory(
+    gfx::Size size,
+    uint32_t value) {
+  scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory);
+  CHECK(shared_memory->CreateAndMapAnonymous(4 * size.GetArea()));
+  uint32_t* pixels = reinterpret_cast<uint32_t*>(shared_memory->memory());
+  CHECK(pixels);
+  std::fill_n(pixels, size.GetArea(), value);
+  return shared_memory.Pass();
+}
+
 class TextureStateTrackingContext : public TestWebGraphicsContext3D {
  public:
   MOCK_METHOD2(bindTexture, void(WGC3Denum target, WebGLId texture));
@@ -323,6 +359,55 @@
   PendingProduceTextureList pending_produce_textures_;
 };
 
+void FreeSharedBitmap(SharedBitmap* shared_bitmap) {
+  delete shared_bitmap->memory();
+}
+
+void IgnoreSharedBitmap(SharedBitmap* shared_bitmap) {}
+
+class TestSharedBitmapManager : public SharedBitmapManager {
+ public:
+  TestSharedBitmapManager() : count_(0) {}
+  virtual ~TestSharedBitmapManager() {}
+
+  virtual scoped_ptr<SharedBitmap> AllocateSharedBitmap(gfx::Size size)
+      OVERRIDE {
+    scoped_ptr<base::SharedMemory> memory(new base::SharedMemory);
+    memory->CreateAndMapAnonymous(size.GetArea() * 4);
+    int8 name[64] = { 0 };
+    name[0] = count_++;
+    SharedBitmapId id;
+    id.SetName(name);
+    bitmap_map_[id] = memory.get();
+    return scoped_ptr<SharedBitmap>(
+        new SharedBitmap(memory.release(), id, base::Bind(&FreeSharedBitmap)));
+  }
+
+  virtual scoped_ptr<SharedBitmap> GetSharedBitmapFromId(
+      gfx::Size,
+      const SharedBitmapId& id) OVERRIDE {
+    if (bitmap_map_.find(id) == bitmap_map_.end())
+      return scoped_ptr<SharedBitmap>();
+    return scoped_ptr<SharedBitmap>(
+        new SharedBitmap(bitmap_map_[id], id, base::Bind(&IgnoreSharedBitmap)));
+  }
+
+  virtual scoped_ptr<SharedBitmap> GetBitmapForSharedMemory(
+      base::SharedMemory* memory) OVERRIDE {
+    int8 name[64] = { 0 };
+    name[0] = count_++;
+    SharedBitmapId id;
+    id.SetName(name);
+    bitmap_map_[id] = memory;
+    return scoped_ptr<SharedBitmap>(
+        new SharedBitmap(memory, id, base::Bind(&IgnoreSharedBitmap)));
+  }
+
+ private:
+  int count_;
+  std::map<SharedBitmapId, base::SharedMemory*> bitmap_map_;
+};
+
 void GetResourcePixels(ResourceProvider* resource_provider,
                        ResourceProviderContext* context,
                        ResourceProvider::ResourceId id,
@@ -356,7 +441,8 @@
  public:
   ResourceProviderTest()
       : shared_data_(ContextSharedData::Create()),
-        context3d_(NULL) {
+        context3d_(NULL),
+        child_context_(NULL) {
     switch (GetParam()) {
       case ResourceProvider::GLTexture: {
         scoped_ptr<ResourceProviderContext> context3d(
@@ -368,19 +454,33 @@
                 context3d.PassAs<TestWebGraphicsContext3D>());
 
         output_surface_ = FakeOutputSurface::Create3d(context_provider);
+
+        scoped_ptr<ResourceProviderContext> child_context_owned =
+            ResourceProviderContext::Create(shared_data_.get());
+        child_context_ = child_context_owned.get();
+        child_output_surface_ = FakeOutputSurface::Create3d(
+            child_context_owned.PassAs<TestWebGraphicsContext3D>());
         break;
       }
       case ResourceProvider::Bitmap:
         output_surface_ = FakeOutputSurface::CreateSoftware(
             make_scoped_ptr(new SoftwareOutputDevice));
+        child_output_surface_ = FakeOutputSurface::CreateSoftware(
+            make_scoped_ptr(new SoftwareOutputDevice));
         break;
       case ResourceProvider::InvalidType:
         NOTREACHED();
         break;
     }
     CHECK(output_surface_->BindToClient(&output_surface_client_));
+    CHECK(child_output_surface_->BindToClient(&child_output_surface_client_));
+
+    shared_bitmap_manager_.reset(new TestSharedBitmapManager());
+
     resource_provider_ = ResourceProvider::Create(
-        output_surface_.get(), 0, false);
+        output_surface_.get(), shared_bitmap_manager_.get(), 0, false);
+    child_resource_provider_ = ResourceProvider::Create(
+        child_output_surface_.get(), shared_bitmap_manager_.get(), 0, false);
   }
 
   static void CollectResources(ReturnedResourceArray* array,
@@ -401,12 +501,56 @@
 
   ResourceProviderContext* context() { return context3d_; }
 
+  ResourceProvider::ResourceId CreateChildMailbox(unsigned* release_sync_point,
+                                                  bool* lost_resource,
+                                                  bool* release_called,
+                                                  unsigned* sync_point) {
+    if (GetParam() == ResourceProvider::GLTexture) {
+      unsigned texture = child_context_->createTexture();
+      gpu::Mailbox gpu_mailbox;
+      child_context_->bindTexture(GL_TEXTURE_2D, texture);
+      child_context_->genMailboxCHROMIUM(gpu_mailbox.name);
+      child_context_->produceTextureCHROMIUM(GL_TEXTURE_2D, gpu_mailbox.name);
+      *sync_point = child_context_->insertSyncPoint();
+      EXPECT_LT(0u, *sync_point);
+
+      scoped_ptr<base::SharedMemory> shared_memory;
+      scoped_ptr<SingleReleaseCallback> callback =
+          SingleReleaseCallback::Create(base::Bind(ReleaseSharedMemoryCallback,
+                                                   base::Passed(&shared_memory),
+                                                   release_called,
+                                                   release_sync_point,
+                                                   lost_resource));
+      return child_resource_provider_->CreateResourceFromTextureMailbox(
+          TextureMailbox(gpu_mailbox, *sync_point), callback.Pass());
+    } else {
+      gfx::Size size(64, 64);
+      scoped_ptr<base::SharedMemory> shared_memory(
+          CreateAndFillSharedMemory(size, 0));
+
+      base::SharedMemory* shared_memory_ptr = shared_memory.get();
+      scoped_ptr<SingleReleaseCallback> callback =
+          SingleReleaseCallback::Create(base::Bind(ReleaseSharedMemoryCallback,
+                                                   base::Passed(&shared_memory),
+                                                   release_called,
+                                                   release_sync_point,
+                                                   lost_resource));
+      return child_resource_provider_->CreateResourceFromTextureMailbox(
+          TextureMailbox(shared_memory_ptr, size), callback.Pass());
+    }
+  }
+
  protected:
   scoped_ptr<ContextSharedData> shared_data_;
   ResourceProviderContext* context3d_;
+  ResourceProviderContext* child_context_;
   FakeOutputSurfaceClient output_surface_client_;
+  FakeOutputSurfaceClient child_output_surface_client_;
   scoped_ptr<OutputSurface> output_surface_;
+  scoped_ptr<OutputSurface> child_output_surface_;
   scoped_ptr<ResourceProvider> resource_provider_;
+  scoped_ptr<ResourceProvider> child_resource_provider_;
+  scoped_ptr<TestSharedBitmapManager> shared_bitmap_manager_;
 };
 
 void CheckCreateResource(ResourceProvider::ResourceType expected_default_type,
@@ -512,50 +656,35 @@
   resource_provider_->DeleteResource(id);
 }
 
-TEST_P(ResourceProviderTest, TransferResources) {
-  // Resource transfer is only supported with GL textures for now.
+TEST_P(ResourceProviderTest, TransferGLResources) {
   if (GetParam() != ResourceProvider::GLTexture)
     return;
-
-  scoped_ptr<ResourceProviderContext> child_context_owned(
-      ResourceProviderContext::Create(shared_data_.get()));
-  ResourceProviderContext* child_context = child_context_owned.get();
-
-  FakeOutputSurfaceClient child_output_surface_client;
-  scoped_ptr<OutputSurface> child_output_surface(
-      FakeOutputSurface::Create3d(
-          child_context_owned.PassAs<TestWebGraphicsContext3D>()));
-  CHECK(child_output_surface->BindToClient(&child_output_surface_client));
-
-  scoped_ptr<ResourceProvider> child_resource_provider(
-      ResourceProvider::Create(child_output_surface.get(), 0, false));
-
   gfx::Size size(1, 1);
   ResourceFormat format = RGBA_8888;
   size_t pixel_size = TextureSizeBytes(size, format);
   ASSERT_EQ(4U, pixel_size);
 
-  ResourceProvider::ResourceId id1 = child_resource_provider->CreateResource(
+  ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
       size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
   uint8_t data1[4] = { 1, 2, 3, 4 };
   gfx::Rect rect(size);
-  child_resource_provider->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
+  child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
 
-  ResourceProvider::ResourceId id2 = child_resource_provider->CreateResource(
+  ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
       size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
   uint8_t data2[4] = { 5, 5, 5, 5 };
-  child_resource_provider->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
+  child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
 
-  WebGLId external_texture_id = child_context->createExternalTexture();
-  child_context->bindTexture(GL_TEXTURE_EXTERNAL_OES, external_texture_id);
+  WebGLId external_texture_id = child_context_->createExternalTexture();
+  child_context_->bindTexture(GL_TEXTURE_EXTERNAL_OES, external_texture_id);
 
   gpu::Mailbox external_mailbox;
-  child_context->genMailboxCHROMIUM(external_mailbox.name);
-  child_context->produceTextureCHROMIUM(GL_TEXTURE_EXTERNAL_OES,
-                                        external_mailbox.name);
-  const unsigned external_sync_point = child_context->insertSyncPoint();
+  child_context_->genMailboxCHROMIUM(external_mailbox.name);
+  child_context_->produceTextureCHROMIUM(GL_TEXTURE_EXTERNAL_OES,
+                                         external_mailbox.name);
+  const unsigned external_sync_point = child_context_->insertSyncPoint();
   ResourceProvider::ResourceId id3 =
-      child_resource_provider->CreateResourceFromTextureMailbox(
+      child_resource_provider_->CreateResourceFromTextureMailbox(
           TextureMailbox(
               external_mailbox, GL_TEXTURE_EXTERNAL_OES, external_sync_point),
           SingleReleaseCallback::Create(base::Bind(&EmptyReleaseCallback)));
@@ -570,8 +699,8 @@
     resource_ids_to_transfer.push_back(id2);
     resource_ids_to_transfer.push_back(id3);
     TransferableResourceArray list;
-    child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
-                                                 &list);
+    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+                                                  &list);
     ASSERT_EQ(3u, list.size());
     EXPECT_NE(0u, list[0].sync_point);
     EXPECT_NE(0u, list[1].sync_point);
@@ -579,9 +708,9 @@
     EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[0].target);
     EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[1].target);
     EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), list[2].target);
-    EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1));
-    EXPECT_TRUE(child_resource_provider->InUseByConsumer(id2));
-    EXPECT_TRUE(child_resource_provider->InUseByConsumer(id3));
+    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
+    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
+    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
     resource_provider_->ReceiveFromChild(child_id, list);
     resource_provider_->DeclareUsedResourcesFromChild(child_id,
                                                       resource_ids_to_transfer);
@@ -615,17 +744,17 @@
     ResourceProvider::ResourceIdArray resource_ids_to_transfer;
     resource_ids_to_transfer.push_back(id1);
     TransferableResourceArray list;
-    child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
-                                                 &list);
+    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+                                                  &list);
     EXPECT_EQ(1u, list.size());
     EXPECT_EQ(id1, list[0].id);
     EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[0].target);
     ReturnedResourceArray returned;
     TransferableResource::ReturnResources(list, &returned);
-    child_resource_provider->ReceiveReturnsFromParent(returned);
+    child_resource_provider_->ReceiveReturnsFromParent(returned);
     // id1 was exported twice, we returned it only once, it should still be
     // in-use.
-    EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1));
+    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
   }
   {
     EXPECT_EQ(0u, returned_to_child.size());
@@ -642,25 +771,27 @@
     EXPECT_FALSE(returned_to_child[0].lost);
     EXPECT_FALSE(returned_to_child[1].lost);
     EXPECT_FALSE(returned_to_child[2].lost);
-    child_resource_provider->ReceiveReturnsFromParent(returned_to_child);
+    child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
     returned_to_child.clear();
   }
-  EXPECT_FALSE(child_resource_provider->InUseByConsumer(id1));
-  EXPECT_FALSE(child_resource_provider->InUseByConsumer(id2));
-  EXPECT_FALSE(child_resource_provider->InUseByConsumer(id3));
+  EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
+  EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
+  EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
 
   {
-    ResourceProvider::ScopedReadLockGL lock(child_resource_provider.get(), id1);
+    ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
+                                            id1);
     ASSERT_NE(0U, lock.texture_id());
-    child_context->bindTexture(GL_TEXTURE_2D, lock.texture_id());
-    child_context->GetPixels(size, format, result);
+    child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
+    child_context_->GetPixels(size, format, result);
     EXPECT_EQ(0, memcmp(data1, result, pixel_size));
   }
   {
-    ResourceProvider::ScopedReadLockGL lock(child_resource_provider.get(), id2);
+    ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
+                                            id2);
     ASSERT_NE(0U, lock.texture_id());
-    child_context->bindTexture(GL_TEXTURE_2D, lock.texture_id());
-    child_context->GetPixels(size, format, result);
+    child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
+    child_context_->GetPixels(size, format, result);
     EXPECT_EQ(0, memcmp(data2, result, pixel_size));
   }
   {
@@ -670,8 +801,8 @@
     resource_ids_to_transfer.push_back(id2);
     resource_ids_to_transfer.push_back(id3);
     TransferableResourceArray list;
-    child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
-                                                 &list);
+    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+                                                  &list);
     ASSERT_EQ(3u, list.size());
     EXPECT_EQ(id1, list[0].id);
     EXPECT_EQ(id2, list[1].id);
@@ -682,9 +813,9 @@
     EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[0].target);
     EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[1].target);
     EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), list[2].target);
-    EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1));
-    EXPECT_TRUE(child_resource_provider->InUseByConsumer(id2));
-    EXPECT_TRUE(child_resource_provider->InUseByConsumer(id3));
+    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
+    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
+    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
     resource_provider_->ReceiveFromChild(child_id, list);
     resource_provider_->DeclareUsedResourcesFromChild(child_id,
                                                       resource_ids_to_transfer);
@@ -705,9 +836,234 @@
   EXPECT_FALSE(returned_to_child[2].lost);
 }
 
-TEST_P(ResourceProviderTest, DeleteExportedResources) {
-  // Resource transfer is only supported with GL textures for now.
-  if (GetParam() != ResourceProvider::GLTexture)
+TEST_P(ResourceProviderTest, TransferSoftwareResources) {
+  if (GetParam() != ResourceProvider::Bitmap)
+    return;
+
+  gfx::Size size(1, 1);
+  ResourceFormat format = RGBA_8888;
+  size_t pixel_size = TextureSizeBytes(size, format);
+  ASSERT_EQ(4U, pixel_size);
+
+  ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
+      size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+  uint8_t data1[4] = { 1, 2, 3, 4 };
+  gfx::Rect rect(size);
+  child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
+
+  ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
+      size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+  uint8_t data2[4] = { 5, 5, 5, 5 };
+  child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
+
+  scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
+  shared_memory->CreateAndMapAnonymous(1);
+  base::SharedMemory* shared_memory_ptr = shared_memory.get();
+  ResourceProvider::ResourceId id3 =
+      child_resource_provider_->CreateResourceFromTextureMailbox(
+          TextureMailbox(shared_memory_ptr, gfx::Size(1, 1)),
+          SingleReleaseCallback::Create(base::Bind(
+              &SharedMemoryReleaseCallback, base::Passed(&shared_memory))));
+
+  ReturnedResourceArray returned_to_child;
+  int child_id =
+      resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
+  {
+    // Transfer some resources to the parent.
+    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
+    resource_ids_to_transfer.push_back(id1);
+    resource_ids_to_transfer.push_back(id2);
+    resource_ids_to_transfer.push_back(id3);
+    TransferableResourceArray list;
+    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+                                                  &list);
+    ASSERT_EQ(3u, list.size());
+    EXPECT_EQ(0u, list[0].sync_point);
+    EXPECT_EQ(0u, list[1].sync_point);
+    EXPECT_EQ(0u, list[2].sync_point);
+    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
+    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
+    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
+    resource_provider_->ReceiveFromChild(child_id, list);
+    resource_provider_->DeclareUsedResourcesFromChild(child_id,
+                                                      resource_ids_to_transfer);
+  }
+
+  EXPECT_EQ(3u, resource_provider_->num_resources());
+  ResourceProvider::ResourceIdMap resource_map =
+      resource_provider_->GetChildToParentMap(child_id);
+  ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
+  ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
+  ResourceProvider::ResourceId mapped_id3 = resource_map[id3];
+  EXPECT_NE(0u, mapped_id1);
+  EXPECT_NE(0u, mapped_id2);
+  EXPECT_NE(0u, mapped_id3);
+  EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
+  EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
+  EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
+
+  uint8_t result[4] = { 0 };
+  GetResourcePixels(
+      resource_provider_.get(), context(), mapped_id1, size, format, result);
+  EXPECT_EQ(0, memcmp(data1, result, pixel_size));
+
+  GetResourcePixels(
+      resource_provider_.get(), context(), mapped_id2, size, format, result);
+  EXPECT_EQ(0, memcmp(data2, result, pixel_size));
+
+  {
+    // Check that transfering again the same resource from the child to the
+    // parent works.
+    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
+    resource_ids_to_transfer.push_back(id1);
+    TransferableResourceArray list;
+    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+                                                  &list);
+    EXPECT_EQ(1u, list.size());
+    EXPECT_EQ(id1, list[0].id);
+    ReturnedResourceArray returned;
+    TransferableResource::ReturnResources(list, &returned);
+    child_resource_provider_->ReceiveReturnsFromParent(returned);
+    // id1 was exported twice, we returned it only once, it should still be
+    // in-use.
+    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
+  }
+  {
+    EXPECT_EQ(0u, returned_to_child.size());
+
+    // Transfer resources back from the parent to the child. Set no resources as
+    // being in use.
+    ResourceProvider::ResourceIdArray no_resources;
+    resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
+
+    ASSERT_EQ(3u, returned_to_child.size());
+    EXPECT_EQ(0u, returned_to_child[0].sync_point);
+    EXPECT_EQ(0u, returned_to_child[1].sync_point);
+    EXPECT_EQ(0u, returned_to_child[2].sync_point);
+    EXPECT_EQ(id1, returned_to_child[0].id);
+    EXPECT_EQ(id2, returned_to_child[1].id);
+    EXPECT_EQ(id3, returned_to_child[2].id);
+    EXPECT_FALSE(returned_to_child[0].lost);
+    EXPECT_FALSE(returned_to_child[1].lost);
+    EXPECT_FALSE(returned_to_child[2].lost);
+    child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
+    returned_to_child.clear();
+  }
+  EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
+  EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
+  EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
+
+  {
+    ResourceProvider::ScopedReadLockSoftware lock(
+        child_resource_provider_.get(), id1);
+    const SkBitmap* sk_bitmap = lock.sk_bitmap();
+    EXPECT_EQ(sk_bitmap->width(), size.width());
+    EXPECT_EQ(sk_bitmap->height(), size.height());
+    EXPECT_EQ(0, memcmp(data1, sk_bitmap->getPixels(), pixel_size));
+  }
+  {
+    ResourceProvider::ScopedReadLockSoftware lock(
+        child_resource_provider_.get(), id2);
+    const SkBitmap* sk_bitmap = lock.sk_bitmap();
+    EXPECT_EQ(sk_bitmap->width(), size.width());
+    EXPECT_EQ(sk_bitmap->height(), size.height());
+    EXPECT_EQ(0, memcmp(data2, sk_bitmap->getPixels(), pixel_size));
+  }
+  {
+    // Transfer resources to the parent again.
+    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
+    resource_ids_to_transfer.push_back(id1);
+    resource_ids_to_transfer.push_back(id2);
+    resource_ids_to_transfer.push_back(id3);
+    TransferableResourceArray list;
+    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+                                                  &list);
+    ASSERT_EQ(3u, list.size());
+    EXPECT_EQ(id1, list[0].id);
+    EXPECT_EQ(id2, list[1].id);
+    EXPECT_EQ(id3, list[2].id);
+    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
+    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
+    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
+    resource_provider_->ReceiveFromChild(child_id, list);
+    resource_provider_->DeclareUsedResourcesFromChild(child_id,
+                                                      resource_ids_to_transfer);
+  }
+
+  EXPECT_EQ(0u, returned_to_child.size());
+
+  EXPECT_EQ(3u, resource_provider_->num_resources());
+  resource_provider_->DestroyChild(child_id);
+  EXPECT_EQ(0u, resource_provider_->num_resources());
+
+  ASSERT_EQ(3u, returned_to_child.size());
+  EXPECT_EQ(0u, returned_to_child[0].sync_point);
+  EXPECT_EQ(0u, returned_to_child[1].sync_point);
+  EXPECT_EQ(0u, returned_to_child[2].sync_point);
+  EXPECT_EQ(id1, returned_to_child[0].id);
+  EXPECT_EQ(id2, returned_to_child[1].id);
+  EXPECT_EQ(id3, returned_to_child[2].id);
+  EXPECT_FALSE(returned_to_child[0].lost);
+  EXPECT_FALSE(returned_to_child[1].lost);
+  EXPECT_FALSE(returned_to_child[2].lost);
+}
+
+TEST_P(ResourceProviderTest, TransferSoftwareToNonUber) {
+  // TODO(jbauman): Remove test when shared bitmap manager available
+  // everywhere.
+  if (GetParam() != ResourceProvider::Bitmap)
+    return;
+
+  scoped_ptr<FakeOutputSurface> parent_output_surface =
+      FakeOutputSurface::CreateSoftware(
+          make_scoped_ptr(new SoftwareOutputDevice));
+  FakeOutputSurfaceClient parent_output_surface_client;
+  CHECK(parent_output_surface->BindToClient(&parent_output_surface_client));
+
+  scoped_ptr<ResourceProvider> parent_resource_provider(
+      ResourceProvider::Create(parent_output_surface.get(), NULL, 0, false));
+
+  gfx::Size size(1, 1);
+  ResourceFormat format = RGBA_8888;
+  size_t pixel_size = TextureSizeBytes(size, format);
+  ASSERT_EQ(4U, pixel_size);
+
+  ResourceProvider::ResourceId id1 = resource_provider_->CreateResource(
+      size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+  uint8_t data1[4] = { 1, 2, 3, 4 };
+  gfx::Rect rect(size);
+  resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
+
+  ReturnedResourceArray returned_to_child;
+  int child_id = parent_resource_provider->CreateChild(
+      GetReturnCallback(&returned_to_child));
+  {
+    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
+    resource_ids_to_transfer.push_back(id1);
+    TransferableResourceArray list;
+    resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
+    ASSERT_EQ(1u, list.size());
+    EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
+    parent_resource_provider->ReceiveFromChild(child_id, list);
+  }
+
+  EXPECT_EQ(0u, parent_resource_provider->num_resources());
+  ASSERT_EQ(1u, returned_to_child.size());
+  EXPECT_EQ(returned_to_child[0].id, id1);
+  ResourceProvider::ResourceIdMap resource_map =
+      parent_resource_provider->GetChildToParentMap(child_id);
+  ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
+  EXPECT_EQ(0u, mapped_id1);
+
+  parent_resource_provider->DestroyChild(child_id);
+  EXPECT_EQ(0u, parent_resource_provider->num_resources());
+
+  ASSERT_EQ(1u, returned_to_child.size());
+  EXPECT_FALSE(returned_to_child[0].lost);
+}
+
+TEST_P(ResourceProviderTest, TransferGLToSoftware) {
+  if (GetParam() != ResourceProvider::Bitmap)
     return;
 
   scoped_ptr<ResourceProviderContext> child_context_owned(
@@ -719,7 +1075,7 @@
   CHECK(child_output_surface->BindToClient(&child_output_surface_client));
 
   scoped_ptr<ResourceProvider> child_resource_provider(
-      ResourceProvider::Create(child_output_surface.get(), 0, false));
+      ResourceProvider::Create(child_output_surface.get(), NULL, 0, false));
 
   gfx::Size size(1, 1);
   ResourceFormat format = RGBA_8888;
@@ -728,14 +1084,103 @@
 
   ResourceProvider::ResourceId id1 = child_resource_provider->CreateResource(
       size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
-  uint8_t data1[4] = {1, 2, 3, 4};
+  uint8_t data1[4] = { 1, 2, 3, 4 };
   gfx::Rect rect(size);
   child_resource_provider->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
 
-  ResourceProvider::ResourceId id2 = child_resource_provider->CreateResource(
+  ReturnedResourceArray returned_to_child;
+  int child_id =
+      resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
+  {
+    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
+    resource_ids_to_transfer.push_back(id1);
+    TransferableResourceArray list;
+    child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
+                                                 &list);
+    ASSERT_EQ(1u, list.size());
+    EXPECT_NE(0u, list[0].sync_point);
+    EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[0].target);
+    EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1));
+    resource_provider_->ReceiveFromChild(child_id, list);
+  }
+
+  EXPECT_EQ(0u, resource_provider_->num_resources());
+  ASSERT_EQ(1u, returned_to_child.size());
+  EXPECT_EQ(returned_to_child[0].id, id1);
+  ResourceProvider::ResourceIdMap resource_map =
+      resource_provider_->GetChildToParentMap(child_id);
+  ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
+  EXPECT_EQ(0u, mapped_id1);
+
+  resource_provider_->DestroyChild(child_id);
+  EXPECT_EQ(0u, resource_provider_->num_resources());
+
+  ASSERT_EQ(1u, returned_to_child.size());
+  EXPECT_FALSE(returned_to_child[0].lost);
+}
+
+TEST_P(ResourceProviderTest, TransferInvalidSoftware) {
+  if (GetParam() != ResourceProvider::Bitmap)
+    return;
+
+  gfx::Size size(1, 1);
+  ResourceFormat format = RGBA_8888;
+  size_t pixel_size = TextureSizeBytes(size, format);
+  ASSERT_EQ(4U, pixel_size);
+
+  ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
+      size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+  uint8_t data1[4] = { 1, 2, 3, 4 };
+  gfx::Rect rect(size);
+  child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
+
+  ReturnedResourceArray returned_to_child;
+  int child_id =
+      resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
+  {
+    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
+    resource_ids_to_transfer.push_back(id1);
+    TransferableResourceArray list;
+    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+                                                  &list);
+    ASSERT_EQ(1u, list.size());
+    // Make invalid.
+    list[0].mailbox.name[1] = 5;
+    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
+    resource_provider_->ReceiveFromChild(child_id, list);
+  }
+
+  EXPECT_EQ(0u, resource_provider_->num_resources());
+  ASSERT_EQ(1u, returned_to_child.size());
+  EXPECT_EQ(returned_to_child[0].id, id1);
+  ResourceProvider::ResourceIdMap resource_map =
+      resource_provider_->GetChildToParentMap(child_id);
+  ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
+  EXPECT_EQ(0u, mapped_id1);
+
+  resource_provider_->DestroyChild(child_id);
+  EXPECT_EQ(0u, resource_provider_->num_resources());
+
+  ASSERT_EQ(1u, returned_to_child.size());
+  EXPECT_FALSE(returned_to_child[0].lost);
+}
+
+TEST_P(ResourceProviderTest, DeleteExportedResources) {
+  gfx::Size size(1, 1);
+  ResourceFormat format = RGBA_8888;
+  size_t pixel_size = TextureSizeBytes(size, format);
+  ASSERT_EQ(4U, pixel_size);
+
+  ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
+      size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+  uint8_t data1[4] = { 1, 2, 3, 4 };
+  gfx::Rect rect(size);
+  child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
+
+  ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
       size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
   uint8_t data2[4] = {5, 5, 5, 5};
-  child_resource_provider->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
+  child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
 
   ReturnedResourceArray returned_to_child;
   int child_id =
@@ -746,13 +1191,15 @@
     resource_ids_to_transfer.push_back(id1);
     resource_ids_to_transfer.push_back(id2);
     TransferableResourceArray list;
-    child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
-                                                 &list);
+    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+                                                  &list);
     ASSERT_EQ(2u, list.size());
-    EXPECT_NE(0u, list[0].sync_point);
-    EXPECT_NE(0u, list[1].sync_point);
-    EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1));
-    EXPECT_TRUE(child_resource_provider->InUseByConsumer(id2));
+    if (GetParam() == ResourceProvider::GLTexture) {
+      EXPECT_NE(0u, list[0].sync_point);
+      EXPECT_NE(0u, list[1].sync_point);
+    }
+    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
+    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
     resource_provider_->ReceiveFromChild(child_id, list);
     resource_provider_->DeclareUsedResourcesFromChild(child_id,
                                                       resource_ids_to_transfer);
@@ -777,8 +1224,10 @@
     resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
 
     ASSERT_EQ(2u, list.size());
-    EXPECT_NE(0u, list[0].sync_point);
-    EXPECT_NE(0u, list[1].sync_point);
+    if (GetParam() == ResourceProvider::GLTexture) {
+      EXPECT_NE(0u, list[0].sync_point);
+      EXPECT_NE(0u, list[1].sync_point);
+    }
     EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
     EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
 
@@ -801,44 +1250,31 @@
 
     EXPECT_EQ(0u, resource_provider_->num_resources());
     ASSERT_EQ(2u, returned_to_child.size());
-    EXPECT_NE(0u, returned_to_child[0].sync_point);
-    EXPECT_NE(0u, returned_to_child[1].sync_point);
+    if (GetParam() == ResourceProvider::GLTexture) {
+      EXPECT_NE(0u, returned_to_child[0].sync_point);
+      EXPECT_NE(0u, returned_to_child[1].sync_point);
+    }
     EXPECT_FALSE(returned_to_child[0].lost);
     EXPECT_FALSE(returned_to_child[1].lost);
   }
 }
 
 TEST_P(ResourceProviderTest, DestroyChildWithExportedResources) {
-  // Resource transfer is only supported with GL textures for now.
-  if (GetParam() != ResourceProvider::GLTexture)
-    return;
-
-  scoped_ptr<ResourceProviderContext> child_context_owned(
-      ResourceProviderContext::Create(shared_data_.get()));
-
-  FakeOutputSurfaceClient child_output_surface_client;
-  scoped_ptr<OutputSurface> child_output_surface(FakeOutputSurface::Create3d(
-      child_context_owned.PassAs<TestWebGraphicsContext3D>()));
-  CHECK(child_output_surface->BindToClient(&child_output_surface_client));
-
-  scoped_ptr<ResourceProvider> child_resource_provider(
-      ResourceProvider::Create(child_output_surface.get(), 0, false));
-
   gfx::Size size(1, 1);
   ResourceFormat format = RGBA_8888;
   size_t pixel_size = TextureSizeBytes(size, format);
   ASSERT_EQ(4U, pixel_size);
 
-  ResourceProvider::ResourceId id1 = child_resource_provider->CreateResource(
+  ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
       size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
   uint8_t data1[4] = {1, 2, 3, 4};
   gfx::Rect rect(size);
-  child_resource_provider->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
+  child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
 
-  ResourceProvider::ResourceId id2 = child_resource_provider->CreateResource(
+  ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
       size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
   uint8_t data2[4] = {5, 5, 5, 5};
-  child_resource_provider->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
+  child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
 
   ReturnedResourceArray returned_to_child;
   int child_id =
@@ -849,13 +1285,15 @@
     resource_ids_to_transfer.push_back(id1);
     resource_ids_to_transfer.push_back(id2);
     TransferableResourceArray list;
-    child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
-                                                 &list);
+    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+                                                  &list);
     ASSERT_EQ(2u, list.size());
-    EXPECT_NE(0u, list[0].sync_point);
-    EXPECT_NE(0u, list[1].sync_point);
-    EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1));
-    EXPECT_TRUE(child_resource_provider->InUseByConsumer(id2));
+    if (GetParam() == ResourceProvider::GLTexture) {
+      EXPECT_NE(0u, list[0].sync_point);
+      EXPECT_NE(0u, list[1].sync_point);
+    }
+    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
+    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
     resource_provider_->ReceiveFromChild(child_id, list);
     resource_provider_->DeclareUsedResourcesFromChild(child_id,
                                                       resource_ids_to_transfer);
@@ -880,8 +1318,10 @@
     resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
 
     ASSERT_EQ(2u, list.size());
-    EXPECT_NE(0u, list[0].sync_point);
-    EXPECT_NE(0u, list[1].sync_point);
+    if (GetParam() == ResourceProvider::GLTexture) {
+      EXPECT_NE(0u, list[0].sync_point);
+      EXPECT_NE(0u, list[1].sync_point);
+    }
     EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
     EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
 
@@ -899,8 +1339,10 @@
 
     EXPECT_EQ(0u, resource_provider_->num_resources());
     ASSERT_EQ(2u, returned_to_child.size());
-    EXPECT_NE(0u, returned_to_child[0].sync_point);
-    EXPECT_NE(0u, returned_to_child[1].sync_point);
+    if (GetParam() == ResourceProvider::GLTexture) {
+      EXPECT_NE(0u, returned_to_child[0].sync_point);
+      EXPECT_NE(0u, returned_to_child[1].sync_point);
+    }
     EXPECT_TRUE(returned_to_child[0].lost);
     EXPECT_TRUE(returned_to_child[1].lost);
     returned_to_child.clear();
@@ -919,32 +1361,16 @@
 }
 
 TEST_P(ResourceProviderTest, DeleteTransferredResources) {
-  // Resource transfer is only supported with GL textures for now.
-  if (GetParam() != ResourceProvider::GLTexture)
-    return;
-
-  scoped_ptr<ResourceProviderContext> child_context_owned(
-      ResourceProviderContext::Create(shared_data_.get()));
-
-  FakeOutputSurfaceClient child_output_surface_client;
-  scoped_ptr<OutputSurface> child_output_surface(
-      FakeOutputSurface::Create3d(
-          child_context_owned.PassAs<TestWebGraphicsContext3D>()));
-  CHECK(child_output_surface->BindToClient(&child_output_surface_client));
-
-  scoped_ptr<ResourceProvider> child_resource_provider(
-      ResourceProvider::Create(child_output_surface.get(), 0, false));
-
   gfx::Size size(1, 1);
   ResourceFormat format = RGBA_8888;
   size_t pixel_size = TextureSizeBytes(size, format);
   ASSERT_EQ(4U, pixel_size);
 
-  ResourceProvider::ResourceId id = child_resource_provider->CreateResource(
+  ResourceProvider::ResourceId id = child_resource_provider_->CreateResource(
       size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
   uint8_t data[4] = { 1, 2, 3, 4 };
   gfx::Rect rect(size);
-  child_resource_provider->SetPixels(id, data, rect, rect, gfx::Vector2d());
+  child_resource_provider_->SetPixels(id, data, rect, rect, gfx::Vector2d());
 
   ReturnedResourceArray returned_to_child;
   int child_id =
@@ -954,19 +1380,20 @@
     ResourceProvider::ResourceIdArray resource_ids_to_transfer;
     resource_ids_to_transfer.push_back(id);
     TransferableResourceArray list;
-    child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
-                                                 &list);
+    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+                                                  &list);
     ASSERT_EQ(1u, list.size());
-    EXPECT_NE(0u, list[0].sync_point);
-    EXPECT_TRUE(child_resource_provider->InUseByConsumer(id));
+    if (GetParam() == ResourceProvider::GLTexture)
+      EXPECT_NE(0u, list[0].sync_point);
+    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
     resource_provider_->ReceiveFromChild(child_id, list);
     resource_provider_->DeclareUsedResourcesFromChild(child_id,
                                                       resource_ids_to_transfer);
   }
 
   // Delete textures in the child, while they are transfered.
-  child_resource_provider->DeleteResource(id);
-  EXPECT_EQ(1u, child_resource_provider->num_resources());
+  child_resource_provider_->DeleteResource(id);
+  EXPECT_EQ(1u, child_resource_provider_->num_resources());
   {
     EXPECT_EQ(0u, returned_to_child.size());
 
@@ -976,10 +1403,11 @@
     resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
 
     ASSERT_EQ(1u, returned_to_child.size());
-    EXPECT_NE(0u, returned_to_child[0].sync_point);
-    child_resource_provider->ReceiveReturnsFromParent(returned_to_child);
+    if (GetParam() == ResourceProvider::GLTexture)
+      EXPECT_NE(0u, returned_to_child[0].sync_point);
+    child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
   }
-  EXPECT_EQ(0u, child_resource_provider->num_resources());
+  EXPECT_EQ(0u, child_resource_provider_->num_resources());
 }
 
 class ResourceProviderTestTextureFilters : public ResourceProviderTest {
@@ -995,7 +1423,7 @@
     CHECK(child_output_surface->BindToClient(&child_output_surface_client));
 
     scoped_ptr<ResourceProvider> child_resource_provider(
-        ResourceProvider::Create(child_output_surface.get(), 0, false));
+        ResourceProvider::Create(child_output_surface.get(), NULL, 0, false));
 
     scoped_ptr<TextureStateTrackingContext> parent_context_owned(
         new TextureStateTrackingContext);
@@ -1007,7 +1435,7 @@
     CHECK(parent_output_surface->BindToClient(&parent_output_surface_client));
 
     scoped_ptr<ResourceProvider> parent_resource_provider(
-        ResourceProvider::Create(parent_output_surface.get(), 0, false));
+        ResourceProvider::Create(parent_output_surface.get(), NULL, 0, false));
 
     gfx::Size size(1, 1);
     ResourceFormat format = RGBA_8888;
@@ -1150,16 +1578,8 @@
   ResourceProviderTestTextureFilters::RunTest(GL_LINEAR, GL_NEAREST);
 }
 
-void ReleaseTextureMailbox(unsigned* release_sync_point,
-                           bool* release_lost_resource,
-                           unsigned sync_point,
-                           bool lost_resource) {
-  *release_sync_point = sync_point;
-  *release_lost_resource = lost_resource;
-}
-
 TEST_P(ResourceProviderTest, TransferMailboxResources) {
-  // Resource transfer is only supported with GL textures for now.
+  // Other mailbox transfers tested elsewhere.
   if (GetParam() != ResourceProvider::GLTexture)
     return;
   unsigned texture = context()->createTexture();
@@ -1279,27 +1699,14 @@
 }
 
 TEST_P(ResourceProviderTest, LostResourceInParent) {
-  // Resource transfer is only supported with GL textures for now.
-  if (GetParam() != ResourceProvider::GLTexture)
-    return;
-
-  scoped_ptr<ResourceProviderContext> child_context_owned(
-      ResourceProviderContext::Create(shared_data_.get()));
-
-  FakeOutputSurfaceClient child_output_surface_client;
-  scoped_ptr<OutputSurface> child_output_surface(FakeOutputSurface::Create3d(
-      child_context_owned.PassAs<TestWebGraphicsContext3D>()));
-  CHECK(child_output_surface->BindToClient(&child_output_surface_client));
-
-  scoped_ptr<ResourceProvider> child_resource_provider(
-      ResourceProvider::Create(child_output_surface.get(), 0, false));
-
   gfx::Size size(1, 1);
   ResourceFormat format = RGBA_8888;
   ResourceProvider::ResourceId resource =
-      child_resource_provider->CreateResource(
+      child_resource_provider_->CreateResource(
           size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
-  child_resource_provider->AllocateForTesting(resource);
+  child_resource_provider_->AllocateForTesting(resource);
+  // Expect a GL resource to be lost.
+  bool should_lose_resource = GetParam() == ResourceProvider::GLTexture;
 
   ReturnedResourceArray returned_to_child;
   int child_id =
@@ -1309,8 +1716,8 @@
     ResourceProvider::ResourceIdArray resource_ids_to_transfer;
     resource_ids_to_transfer.push_back(resource);
     TransferableResourceArray list;
-    child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
-                                                 &list);
+    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+                                                  &list);
     EXPECT_EQ(1u, list.size());
 
     resource_provider_->ReceiveFromChild(child_id, list);
@@ -1329,42 +1736,28 @@
     ResourceProvider::ResourceIdArray no_resources;
     resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
 
-    // Expect the resource to be lost.
+    // Expect a GL resource to be lost.
     ASSERT_EQ(1u, returned_to_child.size());
-    EXPECT_TRUE(returned_to_child[0].lost);
-    child_resource_provider->ReceiveReturnsFromParent(returned_to_child);
+    EXPECT_EQ(should_lose_resource, returned_to_child[0].lost);
+    child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
     returned_to_child.clear();
   }
 
-  // The resource should be lost.
-  EXPECT_TRUE(child_resource_provider->IsLost(resource));
+  // A GL resource should be lost.
+  EXPECT_EQ(should_lose_resource, child_resource_provider_->IsLost(resource));
 
   // Lost resources stay in use in the parent forever.
-  EXPECT_TRUE(child_resource_provider->InUseByConsumer(resource));
+  EXPECT_EQ(should_lose_resource,
+            child_resource_provider_->InUseByConsumer(resource));
 }
 
 TEST_P(ResourceProviderTest, LostResourceInGrandParent) {
-  // Resource transfer is only supported with GL textures for now.
-  if (GetParam() != ResourceProvider::GLTexture)
-    return;
-
-  scoped_ptr<ResourceProviderContext> child_context_owned(
-      ResourceProviderContext::Create(shared_data_.get()));
-
-  FakeOutputSurfaceClient child_output_surface_client;
-  scoped_ptr<OutputSurface> child_output_surface(FakeOutputSurface::Create3d(
-      child_context_owned.PassAs<TestWebGraphicsContext3D>()));
-  CHECK(child_output_surface->BindToClient(&child_output_surface_client));
-
-  scoped_ptr<ResourceProvider> child_resource_provider(
-      ResourceProvider::Create(child_output_surface.get(), 0, false));
-
   gfx::Size size(1, 1);
   ResourceFormat format = RGBA_8888;
   ResourceProvider::ResourceId resource =
-      child_resource_provider->CreateResource(
+      child_resource_provider_->CreateResource(
           size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
-  child_resource_provider->AllocateForTesting(resource);
+  child_resource_provider_->AllocateForTesting(resource);
 
   ReturnedResourceArray returned_to_child;
   int child_id =
@@ -1374,8 +1767,8 @@
     ResourceProvider::ResourceIdArray resource_ids_to_transfer;
     resource_ids_to_transfer.push_back(resource);
     TransferableResourceArray list;
-    child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
-                                                 &list);
+    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+                                                  &list);
     EXPECT_EQ(1u, list.size());
 
     resource_provider_->ReceiveFromChild(child_id, list);
@@ -1423,47 +1816,24 @@
     // Expect the resource to be lost.
     ASSERT_EQ(1u, returned_to_child.size());
     EXPECT_TRUE(returned_to_child[0].lost);
-    child_resource_provider->ReceiveReturnsFromParent(returned_to_child);
+    child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
     returned_to_child.clear();
   }
 
   // The resource should be lost.
-  EXPECT_TRUE(child_resource_provider->IsLost(resource));
+  EXPECT_TRUE(child_resource_provider_->IsLost(resource));
 
   // Lost resources stay in use in the parent forever.
-  EXPECT_TRUE(child_resource_provider->InUseByConsumer(resource));
+  EXPECT_TRUE(child_resource_provider_->InUseByConsumer(resource));
 }
 
 TEST_P(ResourceProviderTest, LostMailboxInParent) {
-  // Resource transfer is only supported with GL textures for now.
-  if (GetParam() != ResourceProvider::GLTexture)
-    return;
-
-  scoped_ptr<ResourceProviderContext> child_context_owned(
-      ResourceProviderContext::Create(shared_data_.get()));
-  ResourceProviderContext* child_context = child_context_owned.get();
-
-  FakeOutputSurfaceClient child_output_surface_client;
-  scoped_ptr<OutputSurface> child_output_surface(FakeOutputSurface::Create3d(
-      child_context_owned.PassAs<TestWebGraphicsContext3D>()));
-  CHECK(child_output_surface->BindToClient(&child_output_surface_client));
-
-  scoped_ptr<ResourceProvider> child_resource_provider(
-      ResourceProvider::Create(child_output_surface.get(), 0, false));
-
-  unsigned texture = child_context->createTexture();
-  gpu::Mailbox gpu_mailbox;
-  child_context->bindTexture(GL_TEXTURE_2D, texture);
-  child_context->genMailboxCHROMIUM(gpu_mailbox.name);
-  child_context->produceTextureCHROMIUM(GL_TEXTURE_2D, gpu_mailbox.name);
-
   unsigned release_sync_point = 0;
   bool lost_resource = false;
-  ReleaseCallback callback =
-      base::Bind(ReleaseTextureMailbox, &release_sync_point, &lost_resource);
-  ResourceProvider::ResourceId resource =
-      child_resource_provider->CreateResourceFromTextureMailbox(
-          TextureMailbox(gpu_mailbox), SingleReleaseCallback::Create(callback));
+  bool release_called = false;
+  unsigned sync_point = 0;
+  ResourceProvider::ResourceId resource = CreateChildMailbox(
+      &release_sync_point, &lost_resource, &release_called, &sync_point);
 
   ReturnedResourceArray returned_to_child;
   int child_id =
@@ -1473,8 +1843,8 @@
     ResourceProvider::ResourceIdArray resource_ids_to_transfer;
     resource_ids_to_transfer.push_back(resource);
     TransferableResourceArray list;
-    child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
-                                                 &list);
+    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+                                                  &list);
     EXPECT_EQ(1u, list.size());
 
     resource_provider_->ReceiveFromChild(child_id, list);
@@ -1493,51 +1863,27 @@
     ResourceProvider::ResourceIdArray no_resources;
     resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
 
-    // Expect the resource to be lost.
     ASSERT_EQ(1u, returned_to_child.size());
-    EXPECT_TRUE(returned_to_child[0].lost);
-    child_resource_provider->ReceiveReturnsFromParent(returned_to_child);
+    // Losing an output surface only loses hardware resources.
+    EXPECT_EQ(returned_to_child[0].lost,
+              GetParam() == ResourceProvider::GLTexture);
+    child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
     returned_to_child.clear();
   }
 
-  // Delete the resource in the child. Expect the resource to be lost.
-  child_resource_provider->DeleteResource(resource);
-  EXPECT_TRUE(lost_resource);
-
-  child_context->waitSyncPoint(release_sync_point);
-  child_context->deleteTexture(texture);
+  // Delete the resource in the child. Expect the resource to be lost if it's
+  // a GL texture.
+  child_resource_provider_->DeleteResource(resource);
+  EXPECT_EQ(lost_resource, GetParam() == ResourceProvider::GLTexture);
 }
 
 TEST_P(ResourceProviderTest, LostMailboxInGrandParent) {
-  // Resource transfer is only supported with GL textures for now.
-  if (GetParam() != ResourceProvider::GLTexture)
-    return;
-
-  scoped_ptr<ResourceProviderContext> child_context_owned(
-      ResourceProviderContext::Create(shared_data_.get()));
-  ResourceProviderContext* child_context = child_context_owned.get();
-
-  FakeOutputSurfaceClient child_output_surface_client;
-  scoped_ptr<OutputSurface> child_output_surface(FakeOutputSurface::Create3d(
-      child_context_owned.PassAs<TestWebGraphicsContext3D>()));
-  CHECK(child_output_surface->BindToClient(&child_output_surface_client));
-
-  scoped_ptr<ResourceProvider> child_resource_provider(
-      ResourceProvider::Create(child_output_surface.get(), 0, false));
-
-  unsigned texture = child_context->createTexture();
-  gpu::Mailbox gpu_mailbox;
-  child_context->bindTexture(GL_TEXTURE_2D, texture);
-  child_context->genMailboxCHROMIUM(gpu_mailbox.name);
-  child_context->produceTextureCHROMIUM(GL_TEXTURE_2D, gpu_mailbox.name);
-
   unsigned release_sync_point = 0;
   bool lost_resource = false;
-  ReleaseCallback callback =
-      base::Bind(ReleaseTextureMailbox, &release_sync_point, &lost_resource);
-  ResourceProvider::ResourceId resource =
-      child_resource_provider->CreateResourceFromTextureMailbox(
-          TextureMailbox(gpu_mailbox), SingleReleaseCallback::Create(callback));
+  bool release_called = false;
+  unsigned sync_point = 0;
+  ResourceProvider::ResourceId resource = CreateChildMailbox(
+      &release_sync_point, &lost_resource, &release_called, &sync_point);
 
   ReturnedResourceArray returned_to_child;
   int child_id =
@@ -1547,8 +1893,8 @@
     ResourceProvider::ResourceIdArray resource_ids_to_transfer;
     resource_ids_to_transfer.push_back(resource);
     TransferableResourceArray list;
-    child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
-                                                 &list);
+    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+                                                  &list);
     EXPECT_EQ(1u, list.size());
 
     resource_provider_->ReceiveFromChild(child_id, list);
@@ -1590,116 +1936,54 @@
     // Expect the resource to be lost.
     ASSERT_EQ(1u, returned_to_child.size());
     EXPECT_TRUE(returned_to_child[0].lost);
-    child_resource_provider->ReceiveReturnsFromParent(returned_to_child);
+    child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
     returned_to_child.clear();
   }
 
   // Delete the resource in the child. Expect the resource to be lost.
-  child_resource_provider->DeleteResource(resource);
+  child_resource_provider_->DeleteResource(resource);
   EXPECT_TRUE(lost_resource);
-
-  child_context->waitSyncPoint(release_sync_point);
-  child_context->deleteTexture(texture);
 }
 
 TEST_P(ResourceProviderTest, Shutdown) {
-  // TextureMailbox callbacks only exist for GL textures for now.
-  if (GetParam() != ResourceProvider::GLTexture)
-    return;
-  unsigned texture = context()->createTexture();
-  context()->bindTexture(GL_TEXTURE_2D, texture);
-  gpu::Mailbox mailbox;
-  context()->genMailboxCHROMIUM(mailbox.name);
-  context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
-  unsigned sync_point = context()->insertSyncPoint();
-
-  EXPECT_LT(0u, sync_point);
-
   unsigned release_sync_point = 0;
   bool lost_resource = false;
-  scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
-      base::Bind(ReleaseTextureMailbox, &release_sync_point, &lost_resource));
-  resource_provider_->CreateResourceFromTextureMailbox(
-      TextureMailbox(mailbox, sync_point),
-      callback.Pass());
+  bool release_called = false;
+  unsigned sync_point = 0;
+  CreateChildMailbox(
+      &release_sync_point, &lost_resource, &release_called, &sync_point);
 
   EXPECT_EQ(0u, release_sync_point);
   EXPECT_FALSE(lost_resource);
 
-  resource_provider_.reset();
+  child_resource_provider_.reset();
 
-  EXPECT_LE(sync_point, release_sync_point);
+  if (GetParam() == ResourceProvider::GLTexture) {
+    EXPECT_LE(sync_point, release_sync_point);
+  }
+  EXPECT_TRUE(release_called);
   EXPECT_FALSE(lost_resource);
 }
 
-static scoped_ptr<base::SharedMemory> CreateAndFillSharedMemory(
-    gfx::Size size, uint32_t value) {
-  scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory);
-  CHECK(shared_memory->CreateAndMapAnonymous(4 * size.GetArea()));
-  uint32_t* pixels = reinterpret_cast<uint32_t*>(shared_memory->memory());
-  CHECK(pixels);
-  std::fill_n(pixels, size.GetArea(), value);
-  return shared_memory.Pass();
-}
-
-static void ReleaseSharedMemoryCallback(
-    bool* release_called,
-    unsigned sync_point, bool lost_resource) {
-  *release_called = true;
-}
-
-TEST_P(ResourceProviderTest, ShutdownSharedMemory) {
-  if (GetParam() != ResourceProvider::Bitmap)
-    return;
-
-  gfx::Size size(64, 64);
-  scoped_ptr<base::SharedMemory> shared_memory(
-      CreateAndFillSharedMemory(size, 0));
-
-  bool release_called = false;
-  scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
-      base::Bind(ReleaseSharedMemoryCallback, &release_called));
-  resource_provider_->CreateResourceFromTextureMailbox(
-      TextureMailbox(shared_memory.get(), size),
-      callback.Pass());
-
-  resource_provider_.reset();
-
-  EXPECT_TRUE(release_called);
-}
-
 TEST_P(ResourceProviderTest, ShutdownWithExportedResource) {
-  // TextureMailbox callbacks only exist for GL textures for now.
-  if (GetParam() != ResourceProvider::GLTexture)
-    return;
-  unsigned texture = context()->createTexture();
-  context()->bindTexture(GL_TEXTURE_2D, texture);
-  gpu::Mailbox mailbox;
-  context()->genMailboxCHROMIUM(mailbox.name);
-  context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
-  unsigned sync_point = context()->insertSyncPoint();
-
-  EXPECT_LT(0u, sync_point);
-
   unsigned release_sync_point = 0;
   bool lost_resource = false;
-  scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
-      base::Bind(ReleaseTextureMailbox, &release_sync_point, &lost_resource));
-  ResourceProvider::ResourceId resource =
-      resource_provider_->CreateResourceFromTextureMailbox(
-          TextureMailbox(mailbox, sync_point),
-          callback.Pass());
+  bool release_called = false;
+  unsigned sync_point = 0;
+  ResourceProvider::ResourceId resource = CreateChildMailbox(
+      &release_sync_point, &lost_resource, &release_called, &sync_point);
 
   // Transfer the resource, so we can't release it properly on shutdown.
   ResourceProvider::ResourceIdArray resource_ids_to_transfer;
   resource_ids_to_transfer.push_back(resource);
   TransferableResourceArray list;
-  resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
+  child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+                                                &list);
 
   EXPECT_EQ(0u, release_sync_point);
   EXPECT_FALSE(lost_resource);
 
-  resource_provider_.reset();
+  child_resource_provider_.reset();
 
   // Since the resource is in the parent, the child considers it lost.
   EXPECT_EQ(0u, release_sync_point);
@@ -1752,7 +2036,7 @@
   CHECK(output_surface->BindToClient(&output_surface_client));
 
   scoped_ptr<ResourceProvider> resource_provider(
-      ResourceProvider::Create(output_surface.get(), 0, false));
+      ResourceProvider::Create(output_surface.get(), NULL, 0, false));
 
   gfx::Size size(1, 1);
   ResourceFormat format = RGBA_8888;
@@ -1833,7 +2117,7 @@
   CHECK(output_surface->BindToClient(&output_surface_client));
 
   scoped_ptr<ResourceProvider> resource_provider(
-      ResourceProvider::Create(output_surface.get(), 0, false));
+      ResourceProvider::Create(output_surface.get(), NULL, 0, false));
 
   gfx::Size size(1, 1);
   ResourceFormat format = RGBA_8888;
@@ -1878,7 +2162,7 @@
   CHECK(output_surface->BindToClient(&output_surface_client));
 
   scoped_ptr<ResourceProvider> resource_provider(
-      ResourceProvider::Create(output_surface.get(), 0, false));
+      ResourceProvider::Create(output_surface.get(), NULL, 0, false));
 
   gfx::Size size(1, 1);
   ResourceFormat format = RGBA_8888;
@@ -1931,7 +2215,7 @@
   CHECK(output_surface->BindToClient(&output_surface_client));
 
   scoped_ptr<ResourceProvider> resource_provider(
-      ResourceProvider::Create(output_surface.get(), 0, false));
+      ResourceProvider::Create(output_surface.get(), NULL, 0, false));
 
   scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
       base::Bind(&EmptyReleaseCallback));
@@ -1966,7 +2250,7 @@
   CHECK(output_surface->BindToClient(&output_surface_client));
 
   scoped_ptr<ResourceProvider> resource_provider(
-      ResourceProvider::Create(output_surface.get(), 0, false));
+      ResourceProvider::Create(output_surface.get(), NULL, 0, false));
 
   unsigned texture_id = 1;
   unsigned sync_point = 30;
@@ -2030,7 +2314,7 @@
   CHECK(output_surface->BindToClient(&output_surface_client));
 
   scoped_ptr<ResourceProvider> resource_provider(
-      ResourceProvider::Create(output_surface.get(), 0, false));
+      ResourceProvider::Create(output_surface.get(), NULL, 0, false));
 
   unsigned texture_id = 1;
   unsigned sync_point = 30;
@@ -2150,7 +2434,7 @@
   CHECK(output_surface->BindToClient(&output_surface_client));
 
   scoped_ptr<ResourceProvider> resource_provider(
-      ResourceProvider::Create(output_surface.get(), 0, false));
+      ResourceProvider::Create(output_surface.get(), NULL, 0, false));
 
   gfx::Size size(2, 2);
   gfx::Vector2d offset(0, 0);
@@ -2226,7 +2510,7 @@
   int texture_id = 123;
 
   scoped_ptr<ResourceProvider> resource_provider(
-      ResourceProvider::Create(output_surface.get(), 0, false));
+      ResourceProvider::Create(output_surface.get(), NULL, 0, false));
 
   id = resource_provider->CreateResource(
       size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
@@ -2263,7 +2547,7 @@
   const uint32_t kBadBeef = 0xbadbeef;
 
   scoped_ptr<ResourceProvider> resource_provider(
-      ResourceProvider::Create(output_surface.get(), 0, false));
+      ResourceProvider::Create(output_surface.get(), NULL, 0, false));
 
   id = resource_provider->CreateResource(
       size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
@@ -2309,7 +2593,7 @@
   int texture_id = 123;
 
   scoped_ptr<ResourceProvider> resource_provider(
-      ResourceProvider::Create(output_surface.get(), 0, false));
+      ResourceProvider::Create(output_surface.get(), NULL, 0, false));
 
   id = resource_provider->CreateResource(
       size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
@@ -2350,7 +2634,7 @@
   int texture_id = 123;
 
   scoped_ptr<ResourceProvider> resource_provider(
-      ResourceProvider::Create(output_surface.get(), 0, false));
+      ResourceProvider::Create(output_surface.get(), NULL, 0, false));
 
   EXPECT_CALL(*context, createTexture()).WillRepeatedly(Return(texture_id));
 
@@ -2388,7 +2672,7 @@
   const unsigned kImageId = 234u;
 
   scoped_ptr<ResourceProvider> resource_provider(
-      ResourceProvider::Create(output_surface.get(), 0, false));
+      ResourceProvider::Create(output_surface.get(), NULL, 0, false));
 
   id = resource_provider->CreateResource(
       size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
@@ -2480,7 +2764,7 @@
   const uint32_t kBadBeef = 0xbadbeef;
 
   scoped_ptr<ResourceProvider> resource_provider(
-      ResourceProvider::Create(output_surface.get(), 0, false));
+      ResourceProvider::Create(output_surface.get(), NULL, 0, false));
 
   id = resource_provider->CreateResource(
       size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
@@ -2531,7 +2815,7 @@
           scoped_ptr<SoftwareOutputDevice>(new SoftwareOutputDevice)));
   EXPECT_TRUE(output_surface->BindToClient(&client));
   scoped_ptr<ResourceProvider> resource_provider(
-      ResourceProvider::Create(output_surface.get(), 0, false));
+      ResourceProvider::Create(output_surface.get(), NULL, 0, false));
 
   CheckCreateResource(ResourceProvider::Bitmap, resource_provider.get(), NULL);
 
diff --git a/cc/resources/resource_update_controller_unittest.cc b/cc/resources/resource_update_controller_unittest.cc
index 498d6820..9f43f80 100644
--- a/cc/resources/resource_update_controller_unittest.cc
+++ b/cc/resources/resource_update_controller_unittest.cc
@@ -137,7 +137,7 @@
     CHECK(output_surface_->BindToClient(&output_surface_client_));
 
     resource_provider_ =
-        ResourceProvider::Create(output_surface_.get(), 0, false);
+        ResourceProvider::Create(output_surface_.get(), NULL, 0, false);
   }
 
   void AppendFullUploadsOfIndexedTextureToUpdateQueue(int count,
diff --git a/cc/resources/scoped_resource_unittest.cc b/cc/resources/scoped_resource_unittest.cc
index 8b59995..dc0df8b 100644
--- a/cc/resources/scoped_resource_unittest.cc
+++ b/cc/resources/scoped_resource_unittest.cc
@@ -19,7 +19,7 @@
   CHECK(output_surface->BindToClient(&output_surface_client));
 
   scoped_ptr<ResourceProvider> resource_provider(
-      ResourceProvider::Create(output_surface.get(), 0, false));
+      ResourceProvider::Create(output_surface.get(), NULL, 0, false));
   scoped_ptr<ScopedResource> texture =
       ScopedResource::create(resource_provider.get());
 
@@ -37,7 +37,7 @@
   CHECK(output_surface->BindToClient(&output_surface_client));
 
   scoped_ptr<ResourceProvider> resource_provider(
-      ResourceProvider::Create(output_surface.get(), 0, false));
+      ResourceProvider::Create(output_surface.get(), NULL, 0, false));
   scoped_ptr<ScopedResource> texture =
       ScopedResource::create(resource_provider.get());
   texture->Allocate(gfx::Size(30, 30),
@@ -59,7 +59,7 @@
   CHECK(output_surface->BindToClient(&output_surface_client));
 
   scoped_ptr<ResourceProvider> resource_provider(
-      ResourceProvider::Create(output_surface.get(), 0, false));
+      ResourceProvider::Create(output_surface.get(), NULL, 0, false));
   {
     scoped_ptr<ScopedResource> texture =
         ScopedResource::create(resource_provider.get());
@@ -93,7 +93,7 @@
   CHECK(output_surface->BindToClient(&output_surface_client));
 
   scoped_ptr<ResourceProvider> resource_provider(
-      ResourceProvider::Create(output_surface.get(), 0, false));
+      ResourceProvider::Create(output_surface.get(), NULL, 0, false));
   {
     scoped_ptr<ScopedResource> texture =
         ScopedResource::create(resource_provider.get());
diff --git a/cc/resources/shared_bitmap.cc b/cc/resources/shared_bitmap.cc
new file mode 100644
index 0000000..3a6fc35
--- /dev/null
+++ b/cc/resources/shared_bitmap.cc
@@ -0,0 +1,17 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/resources/shared_bitmap.h"
+
+namespace cc {
+
+SharedBitmap::SharedBitmap(
+    base::SharedMemory* memory,
+    const SharedBitmapId& id,
+    const base::Callback<void(SharedBitmap*)>& free_callback)
+    : memory_(memory), id_(id), free_callback_(free_callback) {}
+
+SharedBitmap::~SharedBitmap() { free_callback_.Run(this); }
+
+}  // namespace cc
diff --git a/cc/resources/shared_bitmap.h b/cc/resources/shared_bitmap.h
new file mode 100644
index 0000000..9575068
--- /dev/null
+++ b/cc/resources/shared_bitmap.h
@@ -0,0 +1,51 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_RESOURCES_SHARED_BITMAP_H_
+#define CC_RESOURCES_SHARED_BITMAP_H_
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/memory/shared_memory.h"
+#include "cc/base/cc_export.h"
+#include "gpu/command_buffer/common/mailbox.h"
+
+namespace base { class SharedMemory; }
+
+namespace cc {
+typedef gpu::Mailbox SharedBitmapId;
+
+class CC_EXPORT SharedBitmap {
+ public:
+  SharedBitmap(base::SharedMemory* memory,
+               const SharedBitmapId& id,
+               const base::Callback<void(SharedBitmap*)>& free_callback);
+
+  ~SharedBitmap();
+
+  bool operator<(const SharedBitmap& right) const {
+    if (memory_ < right.memory_)
+      return true;
+    if (memory_ > right.memory_)
+      return false;
+    return id_ < right.id_;
+  }
+
+  uint8* pixels() { return static_cast<uint8*>(memory_->memory()); }
+
+  base::SharedMemory* memory() { return memory_; }
+
+  SharedBitmapId id() { return id_; }
+
+ private:
+  base::SharedMemory* memory_;
+  SharedBitmapId id_;
+  base::Callback<void(SharedBitmap*)> free_callback_;
+
+  DISALLOW_COPY_AND_ASSIGN(SharedBitmap);
+};
+
+}  // namespace cc
+
+#endif  // CC_RESOURCES_SHARED_BITMAP_H_
diff --git a/cc/resources/shared_bitmap_manager.h b/cc/resources/shared_bitmap_manager.h
new file mode 100644
index 0000000..53dd156
--- /dev/null
+++ b/cc/resources/shared_bitmap_manager.h
@@ -0,0 +1,32 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_RESOURCES_SHARED_BITMAP_MANAGER_H_
+#define CC_RESOURCES_SHARED_BITMAP_MANAGER_H_
+
+#include "base/basictypes.h"
+#include "cc/base/cc_export.h"
+#include "cc/resources/shared_bitmap.h"
+#include "ui/gfx/size.h"
+
+namespace cc {
+
+class CC_EXPORT SharedBitmapManager {
+ public:
+  SharedBitmapManager() {}
+
+  virtual scoped_ptr<SharedBitmap> AllocateSharedBitmap(gfx::Size) = 0;
+  virtual scoped_ptr<SharedBitmap> GetSharedBitmapFromId(
+      gfx::Size,
+      const SharedBitmapId&) = 0;
+  virtual scoped_ptr<SharedBitmap> GetBitmapForSharedMemory(
+      base::SharedMemory*) = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(SharedBitmapManager);
+};
+
+}  // namespace cc
+
+#endif  // CC_RESOURCES_SHARED_BITMAP_MANAGER_H_
diff --git a/cc/resources/tile_manager_perftest.cc b/cc/resources/tile_manager_perftest.cc
index 7292f1de..f533e65 100644
--- a/cc/resources/tile_manager_perftest.cc
+++ b/cc/resources/tile_manager_perftest.cc
@@ -40,7 +40,7 @@
     CHECK(output_surface_->BindToClient(&output_surface_client_));
 
     resource_provider_ =
-        ResourceProvider::Create(output_surface_.get(), 0, false);
+        ResourceProvider::Create(output_surface_.get(), NULL, 0, false);
     tile_manager_ = make_scoped_ptr(
         new FakeTileManager(&tile_manager_client_, resource_provider_.get()));
     picture_pile_ = FakePicturePileImpl::CreatePile();
diff --git a/cc/resources/tile_manager_unittest.cc b/cc/resources/tile_manager_unittest.cc
index 2f9db48..c5bc6da 100644
--- a/cc/resources/tile_manager_unittest.cc
+++ b/cc/resources/tile_manager_unittest.cc
@@ -26,7 +26,7 @@
     CHECK(output_surface_->BindToClient(&output_surface_client_));
 
     resource_provider_ =
-        ResourceProvider::Create(output_surface_.get(), 0, false);
+        ResourceProvider::Create(output_surface_.get(), NULL, 0, false);
     tile_manager_ = make_scoped_ptr(
         new FakeTileManager(&tile_manager_client_, resource_provider_.get()));
 
diff --git a/cc/resources/transferable_resource.cc b/cc/resources/transferable_resource.cc
index 88ad8fd..62f1bdb 100644
--- a/cc/resources/transferable_resource.cc
+++ b/cc/resources/transferable_resource.cc
@@ -9,7 +9,12 @@
 namespace cc {
 
 TransferableResource::TransferableResource()
-    : id(0), sync_point(0), format(RGBA_8888), target(0), filter(0) {}
+    : id(0),
+      sync_point(0),
+      format(RGBA_8888),
+      target(0),
+      filter(0),
+      is_software(false) {}
 
 TransferableResource::~TransferableResource() {
 }
diff --git a/cc/resources/transferable_resource.h b/cc/resources/transferable_resource.h
index cb650a78..5c93d1c0 100644
--- a/cc/resources/transferable_resource.h
+++ b/cc/resources/transferable_resource.h
@@ -35,6 +35,7 @@
   uint32 filter;
   gfx::Size size;
   gpu::Mailbox mailbox;
+  bool is_software;
 };
 
 }  // namespace cc
diff --git a/cc/resources/video_resource_updater.cc b/cc/resources/video_resource_updater.cc
index 34c7ab65..b819b38 100644
--- a/cc/resources/video_resource_updater.cc
+++ b/cc/resources/video_resource_updater.cc
@@ -261,24 +261,30 @@
                              0xff);
     }
 
-    // In software mode, the resource provider won't be lost. Soon this callback
-    // will be called directly from the resource provider, same as 3d
-    // compositing mode, so this raw unretained resource_provider will always
-    // be valid when the callback is fired.
     RecycleResourceData recycle_data = {
       plane_resources[0].resource_id,
       plane_resources[0].resource_size,
       plane_resources[0].resource_format,
       gpu::Mailbox()
     };
+    base::SharedMemory* shared_memory =
+        resource_provider_->GetSharedMemory(plane_resources[0].resource_id);
+    if (shared_memory) {
+      external_resources.mailboxes.push_back(
+          TextureMailbox(shared_memory, plane_resources[0].resource_size));
+      external_resources.release_callbacks
+          .push_back(base::Bind(&RecycleResource, AsWeakPtr(), recycle_data));
+      external_resources.type = VideoFrameExternalResources::RGB_RESOURCE;
+    } else {
+      // TODO(jbauman): Remove this path once shared memory is available
+      // everywhere.
+      external_resources.software_resources
+          .push_back(plane_resources[0].resource_id);
+      external_resources.software_release_callback =
+          base::Bind(&RecycleResource, AsWeakPtr(), recycle_data);
+      external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE;
+    }
 
-    external_resources.software_resources.push_back(
-        plane_resources[0].resource_id);
-    external_resources.software_release_callback =
-        base::Bind(&RecycleResource, AsWeakPtr(), recycle_data);
-
-
-    external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE;
     return external_resources;
   }
 
diff --git a/cc/resources/video_resource_updater_unittest.cc b/cc/resources/video_resource_updater_unittest.cc
index c36689e..028e0a67 100644
--- a/cc/resources/video_resource_updater_unittest.cc
+++ b/cc/resources/video_resource_updater_unittest.cc
@@ -26,7 +26,7 @@
         FakeOutputSurface::Create3d(context3d.Pass());
     CHECK(output_surface3d_->BindToClient(&client_));
     resource_provider3d_ =
-        ResourceProvider::Create(output_surface3d_.get(), 0, false);
+        ResourceProvider::Create(output_surface3d_.get(), NULL, 0, false);
   }
 
   scoped_refptr<media::VideoFrame> CreateTestYUVVideoFrame() {
diff --git a/cc/test/fake_layer_tree_host.h b/cc/test/fake_layer_tree_host.h
index 074355dd..3acfdd2 100644
--- a/cc/test/fake_layer_tree_host.h
+++ b/cc/test/fake_layer_tree_host.h
@@ -46,7 +46,7 @@
  private:
   FakeLayerTreeHost(LayerTreeHostClient* client,
                     const LayerTreeSettings& settings)
-      : LayerTreeHost(client, settings),
+      : LayerTreeHost(client, NULL, settings),
         host_impl_(settings, &proxy_),
         needs_commit_(false) {}
 
diff --git a/cc/test/fake_layer_tree_host_impl.cc b/cc/test/fake_layer_tree_host_impl.cc
index c1a7326..258617b 100644
--- a/cc/test/fake_layer_tree_host_impl.cc
+++ b/cc/test/fake_layer_tree_host_impl.cc
@@ -11,18 +11,19 @@
     : LayerTreeHostImpl(LayerTreeSettings(),
                         &client_,
                         proxy,
-                        &stats_instrumentation_) {
+                        &stats_instrumentation_,
+                        NULL) {
   // Explicitly clear all debug settings.
   SetDebugState(LayerTreeDebugState());
 }
 
-FakeLayerTreeHostImpl::FakeLayerTreeHostImpl(
-    const LayerTreeSettings& settings,
-    Proxy* proxy)
+FakeLayerTreeHostImpl::FakeLayerTreeHostImpl(const LayerTreeSettings& settings,
+                                             Proxy* proxy)
     : LayerTreeHostImpl(settings,
                         &client_,
                         proxy,
-                        &stats_instrumentation_) {
+                        &stats_instrumentation_,
+                        NULL) {
   // Explicitly clear all debug settings.
   SetDebugState(LayerTreeDebugState());
 }
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc
index da0ed558..f5d7cf3a 100644
--- a/cc/test/layer_tree_test.cc
+++ b/cc/test/layer_tree_test.cc
@@ -68,7 +68,8 @@
       : LayerTreeHostImpl(settings,
                           host_impl_client,
                           proxy,
-                          stats_instrumentation),
+                          stats_instrumentation,
+                          NULL),
         test_hooks_(test_hooks),
         block_notify_ready_to_activate_for_testing_(false),
         notify_ready_to_activate_was_blocked_(false) {}
@@ -233,7 +234,7 @@
   LayerTreeHostForTesting(TestHooks* test_hooks,
                           LayerTreeHostClient* client,
                           const LayerTreeSettings& settings)
-      : LayerTreeHost(client, settings),
+      : LayerTreeHost(client, NULL, settings),
         test_hooks_(test_hooks),
         test_started_(false) {}
 
diff --git a/cc/test/pixel_test.cc b/cc/test/pixel_test.cc
index 05688b1..55ff562 100644
--- a/cc/test/pixel_test.cc
+++ b/cc/test/pixel_test.cc
@@ -165,7 +165,7 @@
   output_surface_->BindToClient(fake_client_.get());
 
   resource_provider_ =
-      ResourceProvider::Create(output_surface_.get(), 0, false);
+      ResourceProvider::Create(output_surface_.get(), NULL, 0, false);
 
   texture_mailbox_deleter_ = make_scoped_ptr(new TextureMailboxDeleter);
 
@@ -208,12 +208,12 @@
   output_surface_.reset(new PixelTestOutputSurface(device.Pass()));
   output_surface_->BindToClient(fake_client_.get());
   resource_provider_ =
-      ResourceProvider::Create(output_surface_.get(), 0, false);
+      ResourceProvider::Create(output_surface_.get(), NULL, 0, false);
   renderer_ = SoftwareRenderer::Create(fake_client_.get(),
                                        &settings_,
                                        output_surface_.get(),
                                        resource_provider_.get())
-                  .PassAs<DirectRenderer>();
+      .PassAs<DirectRenderer>();
 }
 
 }  // namespace cc
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index 2d3c6083..cc92fe3 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -95,10 +95,11 @@
 
 scoped_ptr<LayerTreeHost> LayerTreeHost::Create(
     LayerTreeHostClient* client,
+    SharedBitmapManager* manager,
     const LayerTreeSettings& settings,
     scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) {
-  scoped_ptr<LayerTreeHost> layer_tree_host(new LayerTreeHost(client,
-                                                              settings));
+  scoped_ptr<LayerTreeHost> layer_tree_host(
+      new LayerTreeHost(client, manager, settings));
   if (!layer_tree_host->Initialize(impl_task_runner))
     return scoped_ptr<LayerTreeHost>();
   return layer_tree_host.Pass();
@@ -107,6 +108,7 @@
 static int s_next_tree_id = 1;
 
 LayerTreeHost::LayerTreeHost(LayerTreeHostClient* client,
+                             SharedBitmapManager* manager,
                              const LayerTreeSettings& settings)
     : next_ui_resource_id_(1),
       animating_(false),
@@ -134,7 +136,8 @@
       in_paint_layer_contents_(false),
       total_frames_used_for_lcd_text_metrics_(0),
       tree_id_(s_next_tree_id++),
-      next_commit_forces_redraw_(false) {
+      next_commit_forces_redraw_(false),
+      shared_bitmap_manager_(manager) {
   if (settings_.accelerated_animation_enabled)
     animation_registrar_ = AnimationRegistrar::Create();
   s_num_layer_tree_instances++;
@@ -469,7 +472,9 @@
       LayerTreeHostImpl::Create(settings_,
                                 client,
                                 proxy_.get(),
-                                rendering_stats_instrumentation_.get());
+                                rendering_stats_instrumentation_.get(),
+                                shared_bitmap_manager_);
+  shared_bitmap_manager_ = NULL;
   if (settings_.calculate_top_controls_position &&
       host_impl->top_controls_manager()) {
     top_controls_manager_weak_ptr_ =
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h
index fa025b6..1a035d09 100644
--- a/cc/trees/layer_tree_host.h
+++ b/cc/trees/layer_tree_host.h
@@ -67,6 +67,7 @@
 class RenderingStatsInstrumentation;
 class ResourceProvider;
 class ResourceUpdateQueue;
+class SharedBitmapManager;
 class TopControlsManager;
 struct RenderingStats;
 struct ScrollAndScaleSet;
@@ -123,8 +124,10 @@
 
 class CC_EXPORT LayerTreeHost : NON_EXPORTED_BASE(public RateLimiterClient) {
  public:
+  // The SharedBitmapManager will be used on the compositor thread.
   static scoped_ptr<LayerTreeHost> Create(
       LayerTreeHostClient* client,
+      SharedBitmapManager* manager,
       const LayerTreeSettings& settings,
       scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner);
   virtual ~LayerTreeHost();
@@ -324,7 +327,9 @@
                               const MicroBenchmark::DoneCallback& callback);
 
  protected:
-  LayerTreeHost(LayerTreeHostClient* client, const LayerTreeSettings& settings);
+  LayerTreeHost(LayerTreeHostClient* client,
+                SharedBitmapManager* manager,
+                const LayerTreeSettings& settings);
   bool Initialize(scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner);
   bool InitializeForTesting(scoped_ptr<Proxy> proxy_for_testing);
   void SetOutputSurfaceLostForTesting(bool is_lost) {
@@ -465,6 +470,8 @@
   scoped_refptr<Layer> inner_viewport_scroll_layer_;
   scoped_refptr<Layer> outer_viewport_scroll_layer_;
 
+  SharedBitmapManager* shared_bitmap_manager_;
+
   DISALLOW_COPY_AND_ASSIGN(LayerTreeHost);
 };
 
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index ebc1d83..3b3746f1 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -180,19 +180,18 @@
     const LayerTreeSettings& settings,
     LayerTreeHostImplClient* client,
     Proxy* proxy,
-    RenderingStatsInstrumentation* rendering_stats_instrumentation) {
-  return make_scoped_ptr(
-      new LayerTreeHostImpl(settings,
-                            client,
-                            proxy,
-                            rendering_stats_instrumentation));
+    RenderingStatsInstrumentation* rendering_stats_instrumentation,
+    SharedBitmapManager* manager) {
+  return make_scoped_ptr(new LayerTreeHostImpl(
+      settings, client, proxy, rendering_stats_instrumentation, manager));
 }
 
 LayerTreeHostImpl::LayerTreeHostImpl(
     const LayerTreeSettings& settings,
     LayerTreeHostImplClient* client,
     Proxy* proxy,
-    RenderingStatsInstrumentation* rendering_stats_instrumentation)
+    RenderingStatsInstrumentation* rendering_stats_instrumentation,
+    SharedBitmapManager* manager)
     : client_(client),
       proxy_(proxy),
       input_handler_client_(NULL),
@@ -230,7 +229,8 @@
       external_stencil_test_enabled_(false),
       animation_registrar_(AnimationRegistrar::Create()),
       rendering_stats_instrumentation_(rendering_stats_instrumentation),
-      need_to_update_visible_tiles_before_draw_(false) {
+      need_to_update_visible_tiles_before_draw_(false),
+      shared_bitmap_manager_(manager) {
   DCHECK(proxy_->IsImplThread());
   DidVisibilityChange(this, visible_);
 
@@ -513,7 +513,8 @@
   } else if (output_surface->context_provider()) {
     return DRAW_MODE_HARDWARE;
   } else {
-    DCHECK(output_surface->software_device());
+    DCHECK_EQ(!output_surface->software_device(),
+              output_surface->capabilities().delegated_rendering);
     return DRAW_MODE_SOFTWARE;
   }
 }
@@ -1682,10 +1683,11 @@
   if (!output_surface->BindToClient(this))
     return false;
 
-  scoped_ptr<ResourceProvider> resource_provider = ResourceProvider::Create(
-      output_surface.get(),
-      settings_.highp_threshold_min,
-      settings_.use_rgba_4444_textures);
+  scoped_ptr<ResourceProvider> resource_provider =
+      ResourceProvider::Create(output_surface.get(),
+                               shared_bitmap_manager_,
+                               settings_.highp_threshold_min,
+                               settings_.use_rgba_4444_textures);
   if (!resource_provider)
     return false;
 
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index 555cb24..a2991f21 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -99,7 +99,8 @@
       const LayerTreeSettings& settings,
       LayerTreeHostImplClient* client,
       Proxy* proxy,
-      RenderingStatsInstrumentation* rendering_stats_instrumentation);
+      RenderingStatsInstrumentation* rendering_stats_instrumentation,
+      SharedBitmapManager* manager);
   virtual ~LayerTreeHostImpl();
 
   // InputHandler implementation
@@ -411,7 +412,8 @@
       const LayerTreeSettings& settings,
       LayerTreeHostImplClient* client,
       Proxy* proxy,
-      RenderingStatsInstrumentation* rendering_stats_instrumentation);
+      RenderingStatsInstrumentation* rendering_stats_instrumentation,
+      SharedBitmapManager* manager);
 
   // Virtual for testing.
   virtual void AnimateLayers(base::TimeTicks monotonic_time,
@@ -620,6 +622,8 @@
   // Optional callback to notify of new tree activations.
   base::Closure tree_activation_callback_;
 
+  SharedBitmapManager* shared_bitmap_manager_;
+
   DISALLOW_COPY_AND_ASSIGN(LayerTreeHostImpl);
 };
 
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index f6350255..dd76c06 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -92,10 +92,8 @@
     settings.minimum_occlusion_tracking_size = gfx::Size();
     settings.impl_side_painting = true;
 
-    host_impl_ = LayerTreeHostImpl::Create(settings,
-                                           this,
-                                           &proxy_,
-                                           &stats_instrumentation_);
+    host_impl_ = LayerTreeHostImpl::Create(
+        settings, this, &proxy_, &stats_instrumentation_, NULL);
     host_impl_->InitializeRenderer(CreateOutputSurface());
     host_impl_->SetViewportSize(gfx::Size(10, 10));
   }
@@ -157,10 +155,8 @@
     settings.minimum_occlusion_tracking_size = gfx::Size();
     settings.partial_swap_enabled = partial_swap;
 
-    host_impl_ = LayerTreeHostImpl::Create(settings,
-                                           this,
-                                           &proxy_,
-                                           &stats_instrumentation_);
+    host_impl_ = LayerTreeHostImpl::Create(
+        settings, this, &proxy_, &stats_instrumentation_, NULL);
 
     host_impl_->InitializeRenderer(output_surface.Pass());
     host_impl_->SetViewportSize(gfx::Size(10, 10));
@@ -391,7 +387,7 @@
   LayerTreeSettings settings;
   settings.impl_side_painting = true;
   host_impl_ = LayerTreeHostImpl::Create(
-      settings, this, &proxy_, &stats_instrumentation_);
+      settings, this, &proxy_, &stats_instrumentation_, NULL);
 
   scoped_ptr<FakeOutputSurface> output_surface(
       FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
@@ -494,10 +490,8 @@
 
 TEST_F(LayerTreeHostImplTest, ScrollWithoutRenderer) {
   LayerTreeSettings settings;
-  host_impl_ = LayerTreeHostImpl::Create(settings,
-                                         this,
-                                         &proxy_,
-                                         &stats_instrumentation_);
+  host_impl_ = LayerTreeHostImpl::Create(
+      settings, this, &proxy_, &stats_instrumentation_, NULL);
   scoped_ptr<TestWebGraphicsContext3D> context_owned =
       TestWebGraphicsContext3D::Create();
   context_owned->set_times_make_current_succeeds(0);
@@ -1152,8 +1146,8 @@
       : LayerTreeHostImpl(settings,
                           client,
                           proxy,
-                          rendering_stats_instrumentation) {}
-
+                          rendering_stats_instrumentation,
+                          NULL) {}
 
   virtual base::TimeTicks CurrentPhysicalTimeTicks() const OVERRIDE {
     return fake_current_physical_time_;
@@ -1286,7 +1280,7 @@
   gfx::Size content_size(1000, 1000);
 
   host_impl_ = LayerTreeHostImpl::Create(
-      settings, this, &proxy_, &stats_instrumentation_);
+      settings, this, &proxy_, &stats_instrumentation_, NULL);
   host_impl_->InitializeRenderer(CreateOutputSurface());
   host_impl_->SetDeviceScaleFactor(device_scale_factor);
   host_impl_->SetViewportSize(device_viewport_size);
@@ -1794,10 +1788,8 @@
   settings.calculate_top_controls_position = true;
   settings.top_controls_height = 50;
 
-  host_impl_ = LayerTreeHostImpl::Create(settings,
-                                         this,
-                                         &proxy_,
-                                         &stats_instrumentation_);
+  host_impl_ = LayerTreeHostImpl::Create(
+      settings, this, &proxy_, &stats_instrumentation_, NULL);
   host_impl_->InitializeRenderer(CreateOutputSurface());
   host_impl_->SetViewportSize(gfx::Size(10, 10));
 
@@ -2759,7 +2751,7 @@
   LayerTreeSettings settings;
   settings.always_overscroll = true;
   host_impl_ = LayerTreeHostImpl::Create(
-      settings, this, &proxy_, &stats_instrumentation_);
+      settings, this, &proxy_, &stats_instrumentation_, NULL);
 
   SetupScrollAndContentsLayers(gfx::Size(50, 50));
   host_impl_->SetViewportSize(gfx::Size(50, 50));
@@ -3112,7 +3104,7 @@
     settings.minimum_occlusion_tracking_size = gfx::Size();
     settings.impl_side_painting = true;
     host_impl_ = LayerTreeHostImpl::Create(
-        settings, this, &proxy_, &stats_instrumentation_);
+        settings, this, &proxy_, &stats_instrumentation_, NULL);
 
     scoped_ptr<FakeOutputSurface> output_surface;
     if (always_draw)
@@ -3532,10 +3524,8 @@
   LayerTreeSettings settings;
   settings.partial_swap_enabled = true;
   scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl =
-      LayerTreeHostImpl::Create(settings,
-                                this,
-                                &proxy_,
-                                &stats_instrumentation_);
+      LayerTreeHostImpl::Create(
+          settings, this, &proxy_, &stats_instrumentation_, NULL);
   layer_tree_host_impl->InitializeRenderer(output_surface.Pass());
   layer_tree_host_impl->SetViewportSize(gfx::Size(500, 500));
 
@@ -3847,8 +3837,8 @@
 
   LayerTreeSettings settings;
   settings.partial_swap_enabled = partial_swap;
-  scoped_ptr<LayerTreeHostImpl> my_host_impl =
-      LayerTreeHostImpl::Create(settings, client, proxy, stats_instrumentation);
+  scoped_ptr<LayerTreeHostImpl> my_host_impl = LayerTreeHostImpl::Create(
+      settings, client, proxy, stats_instrumentation, NULL);
   my_host_impl->InitializeRenderer(output_surface.Pass());
   my_host_impl->SetViewportSize(gfx::Size(100, 100));
 
@@ -4228,10 +4218,8 @@
 TEST_F(LayerTreeHostImplTest, MaskLayerWithScaling) {
   LayerTreeSettings settings;
   settings.layer_transforms_should_scale_layer_contents = true;
-  host_impl_ = LayerTreeHostImpl::Create(settings,
-                                         this,
-                                         &proxy_,
-                                         &stats_instrumentation_);
+  host_impl_ = LayerTreeHostImpl::Create(
+      settings, this, &proxy_, &stats_instrumentation_, NULL);
   host_impl_->InitializeRenderer(CreateOutputSurface());
   host_impl_->SetViewportSize(gfx::Size(10, 10));
 
@@ -5219,10 +5207,8 @@
 // doesn't support memory management extensions.
 TEST_F(LayerTreeHostImplTest, DefaultMemoryAllocation) {
   LayerTreeSettings settings;
-  host_impl_ = LayerTreeHostImpl::Create(settings,
-                                         this,
-                                         &proxy_,
-                                         &stats_instrumentation_);
+  host_impl_ = LayerTreeHostImpl::Create(
+      settings, this, &proxy_, &stats_instrumentation_, NULL);
 
   scoped_ptr<OutputSurface> output_surface(
       FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()));
@@ -5331,12 +5317,10 @@
   scoped_refptr<TestContextProvider> context_provider =
       TestContextProvider::Create();
 
-  host_impl_ = LayerTreeHostImpl::Create(LayerTreeSettings(),
-                                         this,
-                                         &proxy_,
-                                         &stats_instrumentation_);
-  host_impl_->InitializeRenderer(
-      FakeOutputSurface::Create3d(context_provider).PassAs<OutputSurface>());
+  host_impl_ = LayerTreeHostImpl::Create(
+      LayerTreeSettings(), this, &proxy_, &stats_instrumentation_, NULL);
+  host_impl_->InitializeRenderer(FakeOutputSurface::Create3d(context_provider)
+                                     .PassAs<OutputSurface>());
   host_impl_->SetViewportSize(gfx::Size(10, 10));
 
   SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index c5127b1..1029b2e 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -2204,7 +2204,7 @@
   LayerTreeHostWithProxy(FakeLayerTreeHostClient* client,
                          const LayerTreeSettings& settings,
                          scoped_ptr<FakeProxy> proxy)
-      : LayerTreeHost(client, settings) {
+      : LayerTreeHost(client, NULL, settings) {
     proxy->SetLayerTreeHost(this);
     EXPECT_TRUE(InitializeForTesting(proxy.PassAs<Proxy>()));
   }
@@ -2272,7 +2272,7 @@
   settings.max_partial_texture_updates = 4;
 
   scoped_ptr<LayerTreeHost> host =
-      LayerTreeHost::Create(&client, settings, NULL);
+      LayerTreeHost::Create(&client, NULL, settings, NULL);
   EXPECT_TRUE(host->InitializeOutputSurfaceIfNeeded());
   EXPECT_EQ(4u, host->settings().max_partial_texture_updates);
 }
@@ -2284,7 +2284,7 @@
   settings.max_partial_texture_updates = 4;
 
   scoped_ptr<LayerTreeHost> host =
-      LayerTreeHost::Create(&client, settings, NULL);
+      LayerTreeHost::Create(&client, NULL, settings, NULL);
   EXPECT_TRUE(host->InitializeOutputSurfaceIfNeeded());
   EXPECT_EQ(4u, host->settings().max_partial_texture_updates);
 }
@@ -2296,7 +2296,7 @@
   settings.max_partial_texture_updates = 4;
 
   scoped_ptr<LayerTreeHost> host =
-      LayerTreeHost::Create(&client, settings, NULL);
+      LayerTreeHost::Create(&client, NULL, settings, NULL);
   EXPECT_TRUE(host->InitializeOutputSurfaceIfNeeded());
   EXPECT_EQ(0u, host->MaxPartialTextureUpdates());
 }
@@ -2309,7 +2309,7 @@
   settings.max_partial_texture_updates = 4;
 
   scoped_ptr<LayerTreeHost> host =
-      LayerTreeHost::Create(&client, settings, NULL);
+      LayerTreeHost::Create(&client, NULL, settings, NULL);
   EXPECT_TRUE(host->InitializeOutputSurfaceIfNeeded());
   EXPECT_EQ(0u, host->MaxPartialTextureUpdates());
 }
diff --git a/cc/trees/layer_tree_host_unittest_context.cc b/cc/trees/layer_tree_host_unittest_context.cc
index e4a0ca7e..ab6e93e 100644
--- a/cc/trees/layer_tree_host_unittest_context.cc
+++ b/cc/trees/layer_tree_host_unittest_context.cc
@@ -1089,7 +1089,7 @@
     child_output_surface_ = FakeOutputSurface::Create3d();
     child_output_surface_->BindToClient(&output_surface_client_);
     child_resource_provider_ =
-        ResourceProvider::Create(child_output_surface_.get(), 0, false);
+        ResourceProvider::Create(child_output_surface_.get(), NULL, 0, false);
   }
 
   static void EmptyReleaseCallback(unsigned sync_point, bool lost) {}
@@ -1781,6 +1781,7 @@
     settings.impl_side_painting = impl_side_painting;
     scoped_ptr<LayerTreeHost> layer_tree_host = LayerTreeHost::Create(
         this,
+        NULL,
         settings,
         impl_thread ? impl_thread->message_loop_proxy() : NULL);
     EXPECT_FALSE(layer_tree_host);
diff --git a/cc/trees/layer_tree_host_unittest_scroll.cc b/cc/trees/layer_tree_host_unittest_scroll.cc
index ab87be1..88630be 100644
--- a/cc/trees/layer_tree_host_unittest_scroll.cc
+++ b/cc/trees/layer_tree_host_unittest_scroll.cc
@@ -1013,7 +1013,7 @@
 
   ASSERT_TRUE(impl_thread.message_loop_proxy().get());
   scoped_ptr<LayerTreeHost> layer_tree_host = LayerTreeHost::Create(
-      &client, settings, impl_thread.message_loop_proxy());
+      &client, NULL, settings, impl_thread.message_loop_proxy());
 
   impl_thread.message_loop_proxy()
       ->PostTask(FROM_HERE,
diff --git a/cc/trees/tree_synchronizer_unittest.cc b/cc/trees/tree_synchronizer_unittest.cc
index 4e0c89fc..3910bc0 100644
--- a/cc/trees/tree_synchronizer_unittest.cc
+++ b/cc/trees/tree_synchronizer_unittest.cc
@@ -552,11 +552,8 @@
   FakeProxy proxy;
   DebugScopedSetImplThread impl(&proxy);
   FakeRenderingStatsInstrumentation stats_instrumentation;
-  scoped_ptr<LayerTreeHostImpl> host_impl =
-      LayerTreeHostImpl::Create(settings,
-                                NULL,
-                                &proxy,
-                                &stats_instrumentation);
+  scoped_ptr<LayerTreeHostImpl> host_impl = LayerTreeHostImpl::Create(
+      settings, NULL, &proxy, &stats_instrumentation, NULL);
 
   scoped_refptr<Layer> layer_tree_root = Layer::Create();
   host_->SetRootLayer(layer_tree_root);
@@ -587,11 +584,8 @@
   FakeProxy proxy;
   DebugScopedSetImplThread impl(&proxy);
   FakeRenderingStatsInstrumentation stats_instrumentation;
-  scoped_ptr<LayerTreeHostImpl> host_impl =
-      LayerTreeHostImpl::Create(settings,
-                                NULL,
-                                &proxy,
-                                &stats_instrumentation);
+  scoped_ptr<LayerTreeHostImpl> host_impl = LayerTreeHostImpl::Create(
+      settings, NULL, &proxy, &stats_instrumentation, NULL);
 
   scoped_refptr<Layer> layer_tree_root = Layer::Create();
   scoped_refptr<Layer> scroll_parent = Layer::Create();
@@ -665,11 +659,8 @@
   FakeProxy proxy;
   DebugScopedSetImplThread impl(&proxy);
   FakeRenderingStatsInstrumentation stats_instrumentation;
-  scoped_ptr<LayerTreeHostImpl> host_impl =
-      LayerTreeHostImpl::Create(settings,
-                                NULL,
-                                &proxy,
-                                &stats_instrumentation);
+  scoped_ptr<LayerTreeHostImpl> host_impl = LayerTreeHostImpl::Create(
+      settings, NULL, &proxy, &stats_instrumentation, NULL);
 
   scoped_refptr<Layer> layer_tree_root = Layer::Create();
   scoped_refptr<Layer> clip_parent = Layer::Create();
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index da0c00f..fcf8479 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -229,7 +229,8 @@
         g_impl_thread ? g_impl_thread->message_loop()->message_loop_proxy()
                       : NULL;
 
-    host_ = cc::LayerTreeHost::Create(this, settings, impl_thread_task_runner);
+    host_ = cc::LayerTreeHost::Create(
+        this, NULL, settings, impl_thread_task_runner);
     host_->SetRootLayer(root_layer_);
 
     host_->SetVisible(true);
diff --git a/content/common/cc_messages.h b/content/common/cc_messages.h
index b1271b3..7fee1e0b 100644
--- a/content/common/cc_messages.h
+++ b/content/common/cc_messages.h
@@ -222,6 +222,7 @@
   IPC_STRUCT_TRAITS_MEMBER(filter)
   IPC_STRUCT_TRAITS_MEMBER(size)
   IPC_STRUCT_TRAITS_MEMBER(mailbox)
+  IPC_STRUCT_TRAITS_MEMBER(is_software)
 IPC_STRUCT_TRAITS_END()
 
 IPC_STRUCT_TRAITS_BEGIN(cc::ReturnedResource)
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc
index d9ebdcb..42c0eb6 100644
--- a/content/renderer/gpu/render_widget_compositor.cc
+++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -412,9 +412,8 @@
 bool RenderWidgetCompositor::initialize(cc::LayerTreeSettings settings) {
   scoped_refptr<base::MessageLoopProxy> compositor_message_loop_proxy =
       RenderThreadImpl::current()->compositor_message_loop_proxy();
-  layer_tree_host_ = cc::LayerTreeHost::Create(this,
-                                               settings,
-                                               compositor_message_loop_proxy);
+  layer_tree_host_ = cc::LayerTreeHost::Create(
+      this, NULL, settings, compositor_message_loop_proxy);
   return layer_tree_host_;
 }
 
diff --git a/content/test/web_layer_tree_view_impl_for_testing.cc b/content/test/web_layer_tree_view_impl_for_testing.cc
index 1bf4ee5..4fe5c21 100644
--- a/content/test/web_layer_tree_view_impl_for_testing.cc
+++ b/content/test/web_layer_tree_view_impl_for_testing.cc
@@ -44,7 +44,7 @@
 
   // Accelerated animations are enabled for unit tests.
   settings.accelerated_animation_enabled = true;
-  layer_tree_host_ = cc::LayerTreeHost::Create(this, settings, NULL);
+  layer_tree_host_ = cc::LayerTreeHost::Create(this, NULL, settings, NULL);
   if (!layer_tree_host_)
     return false;
   return true;
diff --git a/gpu/command_buffer/common/mailbox.h b/gpu/command_buffer/common/mailbox.h
index d0e4c2c9..938167f 100644
--- a/gpu/command_buffer/common/mailbox.h
+++ b/gpu/command_buffer/common/mailbox.h
@@ -5,6 +5,8 @@
 #ifndef GPU_COMMAND_BUFFER_MAILBOX_H_
 #define GPU_COMMAND_BUFFER_MAILBOX_H_
 
+#include <string.h>
+
 #include "gpu/command_buffer/common/types.h"
 #include "gpu/gpu_export.h"
 
@@ -16,6 +18,9 @@
   void SetZero();
   void SetName(const int8* name);
   int8 name[64];
+  bool operator<(const Mailbox& other) const {
+    return memcmp(this, &other, sizeof other) < 0;
+  }
 };
 
 }  // namespace gpu
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc
index 6266f00..c40fd9e 100644
--- a/ui/compositor/compositor.cc
+++ b/ui/compositor/compositor.cc
@@ -432,7 +432,8 @@
   scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner =
       g_compositor_thread ? g_compositor_thread->message_loop_proxy() : NULL;
 
-  host_ = cc::LayerTreeHost::Create(this, settings, compositor_task_runner);
+  host_ =
+      cc::LayerTreeHost::Create(this, NULL, settings, compositor_task_runner);
   host_->SetRootLayer(root_web_layer_);
   host_->SetLayerTreeHostClientReady();
 }