Update from chromium https://crrev.com/301315

This updates from chromium commit
060d7dc875cc41f46ab264181d1d622d02c3c8b7 aka commit position 301315. The
following changes from earlier rolls are included:

*) Remove gpu_media.patch, no longer needed thanks to
  https://crrev.com/301048
*) Added skia_build.patch to resolve blink dependency added by
  https://crrev.com/301105
*) Applied mojo changes for https://crrev.com/301165

TBR=ben@chromium.org

Review URL: https://codereview.chromium.org/681713002
diff --git a/gpu/command_buffer/service/BUILD.gn b/gpu/command_buffer/service/BUILD.gn
index e6c58b6..3b2b782 100644
--- a/gpu/command_buffer/service/BUILD.gn
+++ b/gpu/command_buffer/service/BUILD.gn
@@ -75,10 +75,11 @@
     "in_process_command_buffer.h",
     "logger.cc",
     "logger.h",
-    "mailbox_manager.cc",
     "mailbox_manager.h",
-    "mailbox_synchronizer.cc",
-    "mailbox_synchronizer.h",
+    "mailbox_manager_impl.cc",
+    "mailbox_manager_impl.h",
+    "mailbox_manager_sync.cc",
+    "mailbox_manager_sync.h",
     "memory_program_cache.h",
     "memory_program_cache.cc",
     "mocks.h",
diff --git a/gpu/command_buffer/service/context_group.cc b/gpu/command_buffer/service/context_group.cc
index fe692be..00e7ec3 100644
--- a/gpu/command_buffer/service/context_group.cc
+++ b/gpu/command_buffer/service/context_group.cc
@@ -14,7 +14,7 @@
 #include "gpu/command_buffer/service/framebuffer_manager.h"
 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
 #include "gpu/command_buffer/service/gpu_switches.h"
-#include "gpu/command_buffer/service/mailbox_manager.h"
+#include "gpu/command_buffer/service/mailbox_manager_impl.h"
 #include "gpu/command_buffer/service/memory_tracking.h"
 #include "gpu/command_buffer/service/program_manager.h"
 #include "gpu/command_buffer/service/renderbuffer_manager.h"
@@ -52,7 +52,7 @@
       draw_buffer_(GL_BACK) {
   {
     if (!mailbox_manager_.get())
-      mailbox_manager_ = new MailboxManager;
+      mailbox_manager_ = new MailboxManagerImpl;
     if (!feature_info.get())
       feature_info_ = new FeatureInfo;
     TransferBufferManager* manager = new TransferBufferManager();
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 01d20c7..ea5fbdd 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -3580,7 +3580,7 @@
     UpdateParentTextureInfo();
   }
   mailbox_manager()->ProduceTexture(
-      GL_TEXTURE_2D, mailbox, offscreen_saved_color_texture_info_->texture());
+      mailbox, offscreen_saved_color_texture_info_->texture());
 }
 
 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
@@ -10546,7 +10546,7 @@
     return;
   }
 
-  group_->mailbox_manager()->ProduceTexture(target, mailbox, produced);
+  group_->mailbox_manager()->ProduceTexture(mailbox, produced);
 }
 
 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
@@ -10574,7 +10574,7 @@
         "glConsumeTextureCHROMIUM", "unknown texture for target");
     return;
   }
-  Texture* texture = group_->mailbox_manager()->ConsumeTexture(target, mailbox);
+  Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
   if (!texture) {
     LOCAL_SET_GL_ERROR(
         GL_INVALID_OPERATION,
@@ -10660,7 +10660,7 @@
         "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
     return;
   }
-  Texture* texture = group_->mailbox_manager()->ConsumeTexture(target, mailbox);
+  Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
   if (!texture) {
     LOCAL_SET_GL_ERROR(
         GL_INVALID_OPERATION,
diff --git a/gpu/command_buffer/service/gpu_switches.cc b/gpu/command_buffer/service/gpu_switches.cc
index 0491c41..8f5bc35 100644
--- a/gpu/command_buffer/service/gpu_switches.cc
+++ b/gpu/command_buffer/service/gpu_switches.cc
@@ -56,6 +56,11 @@
 const char kEnableShareGroupAsyncTextureUpload[] =
     "enable-share-group-async-texture-upload";
 
+// Simulates shared textures when share groups are not available. Not available
+// everywhere.
+const char kEnableThreadedTextureMailboxes[] =
+    "enable-threaded-texture-mailboxes";
+
 const char* kGpuSwitches[] = {
   kCompileShaderAlwaysSucceeds,
   kDisableGLErrorLimit,
diff --git a/gpu/command_buffer/service/gpu_switches.h b/gpu/command_buffer/service/gpu_switches.h
index d582b7a..2645543 100644
--- a/gpu/command_buffer/service/gpu_switches.h
+++ b/gpu/command_buffer/service/gpu_switches.h
@@ -26,6 +26,7 @@
 GPU_EXPORT extern const char kGpuProgramCacheSizeKb[];
 GPU_EXPORT extern const char kDisableGpuShaderDiskCache[];
 GPU_EXPORT extern const char kEnableShareGroupAsyncTextureUpload[];
+GPU_EXPORT extern const char kEnableThreadedTextureMailboxes[];
 
 GPU_EXPORT extern const char* kGpuSwitches[];
 GPU_EXPORT extern const int kNumGpuSwitches;
diff --git a/gpu/command_buffer/service/in_process_command_buffer.cc b/gpu/command_buffer/service/in_process_command_buffer.cc
index 1e7cc1f..3da7335 100644
--- a/gpu/command_buffer/service/in_process_command_buffer.cc
+++ b/gpu/command_buffer/service/in_process_command_buffer.cc
@@ -8,15 +8,9 @@
 #include <set>
 #include <utility>
 
-#include <GLES2/gl2.h>
-#ifndef GL_GLEXT_PROTOTYPES
-#define GL_GLEXT_PROTOTYPES 1
-#endif
-#include <GLES2/gl2ext.h>
-#include <GLES2/gl2extchromium.h>
-
 #include "base/bind.h"
 #include "base/bind_helpers.h"
+#include "base/command_line.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/memory/weak_ptr.h"
@@ -28,8 +22,10 @@
 #include "gpu/command_buffer/service/context_group.h"
 #include "gpu/command_buffer/service/gl_context_virtual.h"
 #include "gpu/command_buffer/service/gpu_scheduler.h"
+#include "gpu/command_buffer/service/gpu_switches.h"
 #include "gpu/command_buffer/service/image_manager.h"
-#include "gpu/command_buffer/service/mailbox_manager.h"
+#include "gpu/command_buffer/service/mailbox_manager_impl.h"
+#include "gpu/command_buffer/service/mailbox_manager_sync.h"
 #include "gpu/command_buffer/service/memory_tracking.h"
 #include "gpu/command_buffer/service/query_manager.h"
 #include "gpu/command_buffer/service/transfer_buffer_manager.h"
@@ -185,8 +181,14 @@
 
 scoped_refptr<gles2::MailboxManager>
 InProcessCommandBuffer::Service::mailbox_manager() {
-  if (!mailbox_manager_.get())
-    mailbox_manager_ = new gles2::MailboxManager();
+  if (!mailbox_manager_.get()) {
+    if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+            switches::kEnableThreadedTextureMailboxes)) {
+      mailbox_manager_ = new gles2::MailboxManagerSync();
+    } else {
+      mailbox_manager_ = new gles2::MailboxManagerImpl();
+    }
+  }
   return mailbox_manager_;
 }
 
diff --git a/gpu/command_buffer/service/mailbox_manager.cc b/gpu/command_buffer/service/mailbox_manager.cc
deleted file mode 100644
index b4d6e79..0000000
--- a/gpu/command_buffer/service/mailbox_manager.cc
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright (c) 2012 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 "gpu/command_buffer/service/mailbox_manager.h"
-
-#include <algorithm>
-
-#include "crypto/random.h"
-#include "gpu/command_buffer/service/mailbox_synchronizer.h"
-#include "gpu/command_buffer/service/texture_manager.h"
-
-namespace gpu {
-namespace gles2 {
-
-MailboxManager::MailboxManager()
-    : mailbox_to_textures_(std::ptr_fun(&MailboxManager::TargetNameLess)),
-      sync_(MailboxSynchronizer::GetInstance()) {
-}
-
-MailboxManager::~MailboxManager() {
-  DCHECK(mailbox_to_textures_.empty());
-  DCHECK(textures_to_mailboxes_.empty());
-}
-
-Texture* MailboxManager::ConsumeTexture(unsigned target,
-                                        const Mailbox& mailbox) {
-  TargetName target_name(target, mailbox);
-  MailboxToTextureMap::iterator it =
-      mailbox_to_textures_.find(target_name);
-  if (it != mailbox_to_textures_.end())
-    return it->second->first;
-
-  if (sync_) {
-    // See if it's visible in another mailbox manager, and if so make it visible
-    // here too.
-    Texture* texture = sync_->CreateTextureFromMailbox(target, mailbox);
-    if (texture) {
-      InsertTexture(target_name, texture);
-      DCHECK_EQ(0U, texture->refs_.size());
-    }
-    return texture;
-  }
-
-  return NULL;
-}
-
-void MailboxManager::ProduceTexture(unsigned target,
-                                    const Mailbox& mailbox,
-                                    Texture* texture) {
-  TargetName target_name(target, mailbox);
-  MailboxToTextureMap::iterator it = mailbox_to_textures_.find(target_name);
-  if (it != mailbox_to_textures_.end()) {
-    if (it->second->first == texture)
-      return;
-    TextureToMailboxMap::iterator texture_it = it->second;
-    mailbox_to_textures_.erase(it);
-    textures_to_mailboxes_.erase(texture_it);
-  }
-  InsertTexture(target_name, texture);
-}
-
-void MailboxManager::InsertTexture(TargetName target_name, Texture* texture) {
-  texture->SetMailboxManager(this);
-  TextureToMailboxMap::iterator texture_it =
-      textures_to_mailboxes_.insert(std::make_pair(texture, target_name));
-  mailbox_to_textures_.insert(std::make_pair(target_name, texture_it));
-  DCHECK_EQ(mailbox_to_textures_.size(), textures_to_mailboxes_.size());
-}
-
-void MailboxManager::TextureDeleted(Texture* texture) {
-  std::pair<TextureToMailboxMap::iterator,
-            TextureToMailboxMap::iterator> range =
-      textures_to_mailboxes_.equal_range(texture);
-  for (TextureToMailboxMap::iterator it = range.first;
-       it != range.second; ++it) {
-    size_t count = mailbox_to_textures_.erase(it->second);
-    DCHECK(count == 1);
-  }
-  textures_to_mailboxes_.erase(range.first, range.second);
-  DCHECK_EQ(mailbox_to_textures_.size(), textures_to_mailboxes_.size());
-
-  if (sync_)
-    sync_->TextureDeleted(texture);
-}
-
-void MailboxManager::PushTextureUpdates(uint32 sync_point) {
-  if (sync_)
-    sync_->PushTextureUpdates(this, sync_point);
-}
-
-void MailboxManager::PullTextureUpdates(uint32 sync_point) {
-  if (sync_)
-    sync_->PullTextureUpdates(this, sync_point);
-}
-
-MailboxManager::TargetName::TargetName(unsigned target, const Mailbox& mailbox)
-    : target(target),
-      mailbox(mailbox) {
-}
-
-bool MailboxManager::TargetNameLess(const MailboxManager::TargetName& lhs,
-                                    const MailboxManager::TargetName& rhs) {
-  if (lhs.target != rhs.target)
-    return lhs.target < rhs.target;
-  return lhs.mailbox < rhs.mailbox;
-}
-
-}  // namespace gles2
-}  // namespace gpu
diff --git a/gpu/command_buffer/service/mailbox_manager.h b/gpu/command_buffer/service/mailbox_manager.h
index a00b965..8b53ce4 100644
--- a/gpu/command_buffer/service/mailbox_manager.h
+++ b/gpu/command_buffer/service/mailbox_manager.h
@@ -1,85 +1,48 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2014 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 GPU_COMMAND_BUFFER_SERVICE_MAILBOX_MANAGER_H_
 #define GPU_COMMAND_BUFFER_SERVICE_MAILBOX_MANAGER_H_
 
-#include <functional>
-#include <map>
-
-#include "base/memory/linked_ptr.h"
 #include "base/memory/ref_counted.h"
-#include "gpu/command_buffer/common/constants.h"
 #include "gpu/command_buffer/common/mailbox.h"
 #include "gpu/gpu_export.h"
 
-typedef signed char GLbyte;
-
 namespace gpu {
 namespace gles2 {
 
-class MailboxSynchronizer;
 class Texture;
-class TextureManager;
 
 // Manages resources scoped beyond the context or context group level.
 class GPU_EXPORT MailboxManager : public base::RefCounted<MailboxManager> {
  public:
-  MailboxManager();
-
   // Look up the texture definition from the named mailbox.
-  Texture* ConsumeTexture(unsigned target, const Mailbox& mailbox);
+  virtual Texture* ConsumeTexture(const Mailbox& mailbox) = 0;
 
   // Put the texture into the named mailbox.
-  void ProduceTexture(unsigned target,
-                      const Mailbox& mailbox,
-                      Texture* texture);
+  virtual void ProduceTexture(const Mailbox& mailbox, Texture* texture) = 0;
 
-  // Returns whether this manager synchronizes with other instances.
-  bool UsesSync() { return sync_ != NULL; }
+  // If |true| then Pull/PushTextureUpdates() needs to be called.
+  virtual bool UsesSync() = 0;
 
-  // Used with the MailboxSynchronizer to push/pull texture state to/from
-  // other manager instances.
-  void PushTextureUpdates(uint32 sync_point);
-  void PullTextureUpdates(uint32 sync_point);
+  // Used to synchronize texture state across share groups.
+  virtual void PushTextureUpdates(uint32 sync_point) = 0;
+  virtual void PullTextureUpdates(uint32 sync_point) = 0;
 
   // Destroy any mailbox that reference the given texture.
-  void TextureDeleted(Texture* texture);
+  virtual void TextureDeleted(Texture* texture) = 0;
+
+ protected:
+  MailboxManager() {}
+  virtual ~MailboxManager() {}
 
  private:
   friend class base::RefCounted<MailboxManager>;
-  friend class MailboxSynchronizer;
-
-  ~MailboxManager();
-
-  struct TargetName {
-    TargetName(unsigned target, const Mailbox& mailbox);
-    unsigned target;
-    Mailbox mailbox;
-  };
-  void InsertTexture(TargetName target_name, Texture* texture);
-
-  static bool TargetNameLess(const TargetName& lhs, const TargetName& rhs);
-
-  // This is a bidirectional map between mailbox and textures. We can have
-  // multiple mailboxes per texture, but one texture per mailbox. We keep an
-  // iterator in the MailboxToTextureMap to be able to manage changes to
-  // the TextureToMailboxMap efficiently.
-  typedef std::multimap<Texture*, TargetName> TextureToMailboxMap;
-  typedef std::map<TargetName,
-                   TextureToMailboxMap::iterator,
-                   std::pointer_to_binary_function<const TargetName&,
-                                                   const TargetName&,
-                                                   bool> > MailboxToTextureMap;
-
-  MailboxToTextureMap mailbox_to_textures_;
-  TextureToMailboxMap textures_to_mailboxes_;
-
-  MailboxSynchronizer* sync_;
 
   DISALLOW_COPY_AND_ASSIGN(MailboxManager);
 };
+
 }  // namespage gles2
 }  // namespace gpu
 
diff --git a/gpu/command_buffer/service/mailbox_manager_impl.cc b/gpu/command_buffer/service/mailbox_manager_impl.cc
new file mode 100644
index 0000000..db7b4c2
--- /dev/null
+++ b/gpu/command_buffer/service/mailbox_manager_impl.cc
@@ -0,0 +1,71 @@
+// Copyright 2014 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 "gpu/command_buffer/service/mailbox_manager_impl.h"
+
+#include <algorithm>
+
+#include "gpu/command_buffer/service/texture_manager.h"
+
+namespace gpu {
+namespace gles2 {
+
+MailboxManagerImpl::MailboxManagerImpl() {
+}
+
+MailboxManagerImpl::~MailboxManagerImpl() {
+  DCHECK(mailbox_to_textures_.empty());
+  DCHECK(textures_to_mailboxes_.empty());
+}
+
+bool MailboxManagerImpl::UsesSync() {
+  return false;
+}
+
+Texture* MailboxManagerImpl::ConsumeTexture(const Mailbox& mailbox) {
+  MailboxToTextureMap::iterator it =
+      mailbox_to_textures_.find(mailbox);
+  if (it != mailbox_to_textures_.end())
+    return it->second->first;
+
+  return NULL;
+}
+
+void MailboxManagerImpl::ProduceTexture(const Mailbox& mailbox,
+                                        Texture* texture) {
+  MailboxToTextureMap::iterator it = mailbox_to_textures_.find(mailbox);
+  if (it != mailbox_to_textures_.end()) {
+    if (it->second->first == texture)
+      return;
+    TextureToMailboxMap::iterator texture_it = it->second;
+    mailbox_to_textures_.erase(it);
+    textures_to_mailboxes_.erase(texture_it);
+  }
+  InsertTexture(mailbox, texture);
+}
+
+void MailboxManagerImpl::InsertTexture(const Mailbox& mailbox,
+                                       Texture* texture) {
+  texture->SetMailboxManager(this);
+  TextureToMailboxMap::iterator texture_it =
+      textures_to_mailboxes_.insert(std::make_pair(texture, mailbox));
+  mailbox_to_textures_.insert(std::make_pair(mailbox, texture_it));
+  DCHECK_EQ(mailbox_to_textures_.size(), textures_to_mailboxes_.size());
+}
+
+void MailboxManagerImpl::TextureDeleted(Texture* texture) {
+  std::pair<TextureToMailboxMap::iterator,
+            TextureToMailboxMap::iterator> range =
+      textures_to_mailboxes_.equal_range(texture);
+  for (TextureToMailboxMap::iterator it = range.first;
+       it != range.second; ++it) {
+    size_t count = mailbox_to_textures_.erase(it->second);
+    DCHECK(count == 1);
+  }
+  textures_to_mailboxes_.erase(range.first, range.second);
+  DCHECK_EQ(mailbox_to_textures_.size(), textures_to_mailboxes_.size());
+}
+
+}  // namespace gles2
+}  // namespace gpu
diff --git a/gpu/command_buffer/service/mailbox_manager_impl.h b/gpu/command_buffer/service/mailbox_manager_impl.h
new file mode 100644
index 0000000..5ea906e
--- /dev/null
+++ b/gpu/command_buffer/service/mailbox_manager_impl.h
@@ -0,0 +1,63 @@
+// Copyright 2014 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 GPU_COMMAND_BUFFER_SERVICE_MAILBOX_MANAGER_IMPL_H_
+#define GPU_COMMAND_BUFFER_SERVICE_MAILBOX_MANAGER_IMPL_H_
+
+#include <map>
+#include <utility>
+
+#include "base/memory/linked_ptr.h"
+#include "base/memory/ref_counted.h"
+#include "gpu/command_buffer/common/constants.h"
+#include "gpu/command_buffer/common/mailbox.h"
+#include "gpu/command_buffer/service/mailbox_manager.h"
+#include "gpu/gpu_export.h"
+
+namespace gpu {
+namespace gles2 {
+
+class Texture;
+class TextureManager;
+
+// Manages resources scoped beyond the context or context group level.
+class GPU_EXPORT MailboxManagerImpl : public MailboxManager {
+ public:
+  MailboxManagerImpl();
+
+  // MailboxManager implementation:
+  Texture* ConsumeTexture(const Mailbox& mailbox) override;
+  void ProduceTexture(const Mailbox& mailbox, Texture* texture) override;
+  bool UsesSync() override;
+  void PushTextureUpdates(uint32 sync_point) override {}
+  void PullTextureUpdates(uint32 sync_point) override {}
+  void TextureDeleted(Texture* texture) override;
+
+ protected:
+  ~MailboxManagerImpl() override;
+
+ private:
+  friend class base::RefCounted<MailboxManager>;
+
+  void InsertTexture(const Mailbox& mailbox, Texture* texture);
+
+  // This is a bidirectional map between mailbox and textures. We can have
+  // multiple mailboxes per texture, but one texture per mailbox. We keep an
+  // iterator in the MailboxToTextureMap to be able to manage changes to
+  // the TextureToMailboxMap efficiently.
+  typedef std::multimap<Texture*, Mailbox> TextureToMailboxMap;
+  typedef std::map<Mailbox, TextureToMailboxMap::iterator>
+      MailboxToTextureMap;
+
+  MailboxToTextureMap mailbox_to_textures_;
+  TextureToMailboxMap textures_to_mailboxes_;
+
+  DISALLOW_COPY_AND_ASSIGN(MailboxManagerImpl);
+};
+
+}  // namespage gles2
+}  // namespace gpu
+
+#endif  // GPU_COMMAND_BUFFER_SERVICE_MAILBOX_MANAGER_IMPL_H_
+
diff --git a/gpu/command_buffer/service/mailbox_manager_sync.cc b/gpu/command_buffer/service/mailbox_manager_sync.cc
new file mode 100644
index 0000000..65376af
--- /dev/null
+++ b/gpu/command_buffer/service/mailbox_manager_sync.cc
@@ -0,0 +1,339 @@
+// Copyright 2014 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 "gpu/command_buffer/service/mailbox_manager_sync.h"
+
+#include <algorithm>
+#include <queue>
+
+#include "base/memory/linked_ptr.h"
+#include "base/synchronization/lock.h"
+#include "gpu/command_buffer/service/texture_manager.h"
+#include "ui/gl/gl_fence.h"
+#include "ui/gl/gl_implementation.h"
+
+#if !defined(OS_MACOSX)
+#include "ui/gl/gl_fence_egl.h"
+#endif
+
+namespace gpu {
+namespace gles2 {
+
+namespace {
+
+bool SkipTextureWorkarounds(const Texture* texture) {
+  // TODO(sievers): crbug.com/352274
+  // Should probably only fail if it already *has* mipmaps, while allowing
+  // incomplete textures here.
+  bool needs_mips =
+      texture->min_filter() != GL_NEAREST && texture->min_filter() != GL_LINEAR;
+  if (texture->target() != GL_TEXTURE_2D || needs_mips || !texture->IsDefined())
+    return true;
+
+  // Skip compositor resources/tile textures.
+  // TODO: Remove this, see crbug.com/399226.
+  if (texture->pool() == GL_TEXTURE_POOL_MANAGED_CHROMIUM)
+    return true;
+
+  return false;
+}
+
+base::LazyInstance<base::Lock> g_lock = LAZY_INSTANCE_INITIALIZER;
+
+typedef std::map<uint32, linked_ptr<gfx::GLFence>> SyncPointToFenceMap;
+base::LazyInstance<SyncPointToFenceMap> g_sync_point_to_fence =
+    LAZY_INSTANCE_INITIALIZER;
+#if !defined(OS_MACOSX)
+base::LazyInstance<std::queue<SyncPointToFenceMap::iterator>> g_sync_points =
+    LAZY_INSTANCE_INITIALIZER;
+#endif
+
+void CreateFenceLocked(uint32 sync_point) {
+  g_lock.Get().AssertAcquired();
+  if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL)
+    return;
+
+#if !defined(OS_MACOSX)
+  std::queue<SyncPointToFenceMap::iterator>& sync_points = g_sync_points.Get();
+  SyncPointToFenceMap& sync_point_to_fence = g_sync_point_to_fence.Get();
+  if (sync_point) {
+    while (!sync_points.empty() &&
+           sync_points.front()->second->HasCompleted()) {
+      sync_point_to_fence.erase(sync_points.front());
+      sync_points.pop();
+    }
+    // Need to use EGL fences since we are likely not in a single share group.
+    linked_ptr<gfx::GLFence> fence(make_linked_ptr(new gfx::GLFenceEGL(true)));
+    if (fence.get()) {
+      std::pair<SyncPointToFenceMap::iterator, bool> result =
+          sync_point_to_fence.insert(std::make_pair(sync_point, fence));
+      DCHECK(result.second);
+      sync_points.push(result.first);
+    }
+    DCHECK(sync_points.size() == sync_point_to_fence.size());
+  }
+#endif
+}
+
+void AcquireFenceLocked(uint32 sync_point) {
+  g_lock.Get().AssertAcquired();
+  SyncPointToFenceMap::iterator fence_it =
+      g_sync_point_to_fence.Get().find(sync_point);
+  if (fence_it != g_sync_point_to_fence.Get().end()) {
+    fence_it->second->ServerWait();
+  }
+}
+
+static const unsigned kNewTextureVersion = 1;
+
+}  // anonymous namespace
+
+base::LazyInstance<MailboxManagerSync::TextureGroup::MailboxToGroupMap>
+    MailboxManagerSync::TextureGroup::mailbox_to_group_ =
+        LAZY_INSTANCE_INITIALIZER;
+
+// static
+MailboxManagerSync::TextureGroup*
+MailboxManagerSync::TextureGroup::CreateFromTexture(const Mailbox& name,
+                                                    MailboxManagerSync* manager,
+                                                    Texture* texture) {
+  TextureGroup* group = new TextureGroup();
+  group->AddTexture(manager, texture);
+  group->AddName(name);
+  if (!SkipTextureWorkarounds(texture)) {
+    group->definition_ =
+        TextureDefinition(texture, kNewTextureVersion, NULL);
+  }
+  return group;
+}
+
+// static
+MailboxManagerSync::TextureGroup* MailboxManagerSync::TextureGroup::FromName(
+    const Mailbox& name) {
+  MailboxToGroupMap::iterator it = mailbox_to_group_.Get().find(name);
+  if (it == mailbox_to_group_.Get().end())
+    return NULL;
+
+  return it->second.get();
+}
+
+MailboxManagerSync::TextureGroup::TextureGroup() {
+}
+
+MailboxManagerSync::TextureGroup::~TextureGroup() {
+}
+
+void MailboxManagerSync::TextureGroup::AddName(const Mailbox& name) {
+  g_lock.Get().AssertAcquired();
+  DCHECK(std::find(names_.begin(), names_.end(), name) == names_.end());
+  names_.push_back(name);
+  DCHECK(mailbox_to_group_.Get().find(name) == mailbox_to_group_.Get().end());
+  mailbox_to_group_.Get()[name] = this;
+}
+
+void MailboxManagerSync::TextureGroup::RemoveName(const Mailbox& name) {
+  g_lock.Get().AssertAcquired();
+  std::vector<Mailbox>::iterator names_it =
+      std::find(names_.begin(), names_.end(), name);
+  DCHECK(names_it != names_.end());
+  names_.erase(names_it);
+  MailboxToGroupMap::iterator it = mailbox_to_group_.Get().find(name);
+  DCHECK(it != mailbox_to_group_.Get().end());
+  mailbox_to_group_.Get().erase(it);
+}
+
+void MailboxManagerSync::TextureGroup::AddTexture(MailboxManagerSync* manager,
+                                                  Texture* texture) {
+  g_lock.Get().AssertAcquired();
+  DCHECK(std::find(textures_.begin(), textures_.end(),
+                   std::make_pair(manager, texture)) == textures_.end());
+  textures_.push_back(std::make_pair(manager, texture));
+}
+
+bool MailboxManagerSync::TextureGroup::RemoveTexture(
+    MailboxManagerSync* manager,
+    Texture* texture) {
+  g_lock.Get().AssertAcquired();
+  TextureGroup::TextureList::iterator tex_list_it = std::find(
+      textures_.begin(), textures_.end(), std::make_pair(manager, texture));
+  DCHECK(tex_list_it != textures_.end());
+  if (textures_.size() == 1) {
+    // This is the last texture so the group is going away.
+    for (size_t n = 0; n < names_.size(); n++) {
+      const Mailbox& name = names_[n];
+      MailboxToGroupMap::iterator mbox_it =
+          mailbox_to_group_.Get().find(name);
+      DCHECK(mbox_it != mailbox_to_group_.Get().end());
+      DCHECK(mbox_it->second.get() == this);
+      mailbox_to_group_.Get().erase(mbox_it);
+    }
+    return false;
+  } else {
+    textures_.erase(tex_list_it);
+    return true;
+  }
+}
+
+Texture* MailboxManagerSync::TextureGroup::FindTexture(
+    MailboxManagerSync* manager) {
+  g_lock.Get().AssertAcquired();
+  for (TextureGroup::TextureList::iterator it = textures_.begin();
+       it != textures_.end(); it++) {
+    if (it->first == manager)
+      return it->second;
+  }
+  return NULL;
+}
+
+MailboxManagerSync::TextureGroupRef::TextureGroupRef(unsigned version,
+                                                     TextureGroup* group)
+    : version(version), group(group) {
+}
+
+MailboxManagerSync::TextureGroupRef::~TextureGroupRef() {
+}
+
+MailboxManagerSync::MailboxManagerSync() {
+}
+
+MailboxManagerSync::~MailboxManagerSync() {
+  DCHECK_EQ(0U, texture_to_group_.size());
+}
+
+bool MailboxManagerSync::UsesSync() {
+  return true;
+}
+
+Texture* MailboxManagerSync::ConsumeTexture(const Mailbox& mailbox) {
+  base::AutoLock lock(g_lock.Get());
+  TextureGroup* group = TextureGroup::FromName(mailbox);
+  if (!group)
+    return NULL;
+
+  // Check if a texture already exists in this share group.
+  Texture* texture = group->FindTexture(this);
+  if (texture)
+    return texture;
+
+  // Otherwise create a new texture.
+  texture = group->GetDefinition().CreateTexture();
+  if (texture) {
+    DCHECK(!SkipTextureWorkarounds(texture));
+    texture->SetMailboxManager(this);
+    group->AddTexture(this, texture);
+
+    TextureGroupRef new_ref =
+        TextureGroupRef(group->GetDefinition().version(), group);
+    texture_to_group_.insert(std::make_pair(texture, new_ref));
+  }
+
+  return texture;
+}
+
+void MailboxManagerSync::ProduceTexture(const Mailbox& mailbox,
+                                        Texture* texture) {
+  base::AutoLock lock(g_lock.Get());
+
+  TextureToGroupMap::iterator tex_it = texture_to_group_.find(texture);
+  TextureGroup* group_for_mailbox = TextureGroup::FromName(mailbox);
+  TextureGroup* group_for_texture = NULL;
+
+  if (tex_it != texture_to_group_.end()) {
+    group_for_texture = tex_it->second.group.get();
+    DCHECK(group_for_texture);
+    if (group_for_mailbox == group_for_texture) {
+      // The texture is already known under this name.
+      return;
+    }
+  }
+
+  if (group_for_mailbox) {
+    // Unlink the mailbox from its current group.
+    group_for_mailbox->RemoveName(mailbox);
+  }
+
+  if (group_for_texture) {
+    group_for_texture->AddName(mailbox);
+  } else {
+    // This is a new texture, so create a new group.
+    texture->SetMailboxManager(this);
+    group_for_texture =
+        TextureGroup::CreateFromTexture(mailbox, this, texture);
+    texture_to_group_.insert(std::make_pair(
+        texture, TextureGroupRef(kNewTextureVersion, group_for_texture)));
+  }
+
+  DCHECK(texture->mailbox_manager_ == this);
+}
+
+void MailboxManagerSync::TextureDeleted(Texture* texture) {
+  base::AutoLock lock(g_lock.Get());
+  TextureToGroupMap::iterator tex_it = texture_to_group_.find(texture);
+  DCHECK(tex_it != texture_to_group_.end());
+  TextureGroup* group_for_texture = tex_it->second.group.get();
+  if (group_for_texture->RemoveTexture(this, texture))
+    UpdateDefinitionLocked(texture, &tex_it->second);
+  texture_to_group_.erase(tex_it);
+}
+
+void MailboxManagerSync::UpdateDefinitionLocked(
+    Texture* texture,
+    TextureGroupRef* group_ref) {
+  g_lock.Get().AssertAcquired();
+
+  if (SkipTextureWorkarounds(texture))
+    return;
+
+  gfx::GLImage* gl_image = texture->GetLevelImage(texture->target(), 0);
+  TextureGroup* group = group_ref->group.get();
+  const TextureDefinition& definition = group->GetDefinition();
+  scoped_refptr<NativeImageBuffer> image_buffer = definition.image();
+
+  // Make sure we don't clobber with an older version
+  if (!definition.IsOlderThan(group_ref->version))
+    return;
+
+  // Also don't push redundant updates. Note that it would break the
+  // versioning.
+  if (definition.Matches(texture))
+    return;
+
+  if (gl_image && !image_buffer->IsClient(gl_image)) {
+    LOG(ERROR) << "MailboxSync: Incompatible attachment";
+    return;
+  }
+
+  group->SetDefinition(TextureDefinition(texture, ++group_ref->version,
+                                         gl_image ? image_buffer : NULL));
+}
+
+void MailboxManagerSync::PushTextureUpdates(uint32 sync_point) {
+  base::AutoLock lock(g_lock.Get());
+
+  for (TextureToGroupMap::iterator it = texture_to_group_.begin();
+       it != texture_to_group_.end(); it++) {
+    UpdateDefinitionLocked(it->first, &it->second);
+  }
+  CreateFenceLocked(sync_point);
+}
+
+void MailboxManagerSync::PullTextureUpdates(uint32 sync_point) {
+  base::AutoLock lock(g_lock.Get());
+  AcquireFenceLocked(sync_point);
+
+  for (TextureToGroupMap::iterator it = texture_to_group_.begin();
+       it != texture_to_group_.end(); it++) {
+    const TextureDefinition& definition = it->second.group->GetDefinition();
+    Texture* texture = it->first;
+    unsigned& texture_version = it->second.version;
+    if (texture_version == definition.version() ||
+        definition.IsOlderThan(texture_version))
+      continue;
+    texture_version = definition.version();
+    definition.UpdateTexture(texture);
+  }
+}
+
+}  // namespace gles2
+}  // namespace gpu
diff --git a/gpu/command_buffer/service/mailbox_manager_sync.h b/gpu/command_buffer/service/mailbox_manager_sync.h
new file mode 100644
index 0000000..4727f3b
--- /dev/null
+++ b/gpu/command_buffer/service/mailbox_manager_sync.h
@@ -0,0 +1,99 @@
+// Copyright 2014 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 GPU_COMMAND_BUFFER_SERVICE_MAILBOX_MANAGER_SYNC_H_
+#define GPU_COMMAND_BUFFER_SERVICE_MAILBOX_MANAGER_SYNC_H_
+
+#include <map>
+#include <utility>
+
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "gpu/command_buffer/common/constants.h"
+#include "gpu/command_buffer/common/mailbox.h"
+#include "gpu/command_buffer/service/mailbox_manager.h"
+#include "gpu/command_buffer/service/texture_definition.h"
+#include "gpu/gpu_export.h"
+
+namespace gpu {
+namespace gles2 {
+
+class Texture;
+class TextureManager;
+
+// Manages resources scoped beyond the context or context group level
+// and across threads and driver level share groups by synchronizing
+// texture state.
+class GPU_EXPORT MailboxManagerSync : public MailboxManager {
+ public:
+  MailboxManagerSync();
+
+  // MailboxManager implementation:
+  Texture* ConsumeTexture(const Mailbox& mailbox) override;
+  void ProduceTexture(const Mailbox& mailbox, Texture* texture) override;
+  bool UsesSync() override;
+  void PushTextureUpdates(uint32 sync_point) override;
+  void PullTextureUpdates(uint32 sync_point) override;
+  void TextureDeleted(Texture* texture) override;
+
+ private:
+  friend class base::RefCounted<MailboxManager>;
+
+  ~MailboxManagerSync() override;
+
+  class TextureGroup : public base::RefCounted<TextureGroup> {
+   public:
+    static TextureGroup* CreateFromTexture(const Mailbox& name,
+                                           MailboxManagerSync* manager,
+                                           Texture* texture);
+    static TextureGroup* FromName(const Mailbox& name);
+
+    void AddName(const Mailbox& name);
+    void RemoveName(const Mailbox& name);
+
+    void AddTexture(MailboxManagerSync* manager, Texture* texture);
+    // Returns true if there are other textures left in the group after removal.
+    bool RemoveTexture(MailboxManagerSync* manager, Texture* texture);
+    Texture* FindTexture(MailboxManagerSync* manager);
+
+    const TextureDefinition& GetDefinition() { return definition_; }
+    void SetDefinition(TextureDefinition definition) {
+      definition_ = definition;
+    }
+
+   private:
+    friend class base::RefCounted<TextureGroup>;
+    TextureGroup();
+    ~TextureGroup();
+
+    typedef std::vector<std::pair<MailboxManagerSync*, Texture*>> TextureList;
+    std::vector<Mailbox> names_;
+    TextureList textures_;
+    TextureDefinition definition_;
+
+    typedef std::map<Mailbox, scoped_refptr<TextureGroup>>
+        MailboxToGroupMap;
+    static base::LazyInstance<MailboxToGroupMap> mailbox_to_group_;
+  };
+
+  struct TextureGroupRef {
+    TextureGroupRef(unsigned version, TextureGroup* group);
+    ~TextureGroupRef();
+    unsigned version;
+    scoped_refptr<TextureGroup> group;
+  };
+  static void UpdateDefinitionLocked(Texture* texture,
+                                     TextureGroupRef* group_ref);
+
+  typedef std::map<Texture*, TextureGroupRef> TextureToGroupMap;
+  TextureToGroupMap texture_to_group_;
+
+  DISALLOW_COPY_AND_ASSIGN(MailboxManagerSync);
+};
+
+}  // namespage gles2
+}  // namespace gpu
+
+#endif  // GPU_COMMAND_BUFFER_SERVICE_MAILBOX_MANAGER_SYNC_H_
+
diff --git a/gpu/command_buffer/service/mailbox_manager_unittest.cc b/gpu/command_buffer/service/mailbox_manager_unittest.cc
index 63ffc6d..1aea4c5 100644
--- a/gpu/command_buffer/service/mailbox_manager_unittest.cc
+++ b/gpu/command_buffer/service/mailbox_manager_unittest.cc
@@ -2,11 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "gpu/command_buffer/service/mailbox_manager.h"
-
 #include "gpu/command_buffer/service/feature_info.h"
 #include "gpu/command_buffer/service/gpu_service_test.h"
-#include "gpu/command_buffer/service/mailbox_synchronizer.h"
+#include "gpu/command_buffer/service/mailbox_manager_impl.h"
+#include "gpu/command_buffer/service/mailbox_manager_sync.h"
 #include "gpu/command_buffer/service/texture_manager.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gl/gl_context_stub.h"
@@ -20,27 +19,25 @@
 
 class MailboxManagerTest : public GpuServiceTest {
  public:
-  MailboxManagerTest() : initialized_synchronizer_(false) {}
+  MailboxManagerTest() {}
   virtual ~MailboxManagerTest() {}
 
  protected:
   virtual void SetUp() {
     GpuServiceTest::SetUp();
     feature_info_ = new FeatureInfo;
-    manager_ = new MailboxManager;
+    manager_ = new MailboxManagerImpl;
+    DCHECK(!manager_->UsesSync());
   }
 
   virtual void SetUpWithSynchronizer() {
     GpuServiceTest::SetUp();
-    MailboxSynchronizer::Initialize();
-    initialized_synchronizer_ = true;
     feature_info_ = new FeatureInfo;
-    manager_ = new MailboxManager;
+    manager_ = new MailboxManagerSync();
+    DCHECK(manager_->UsesSync());
   }
 
   virtual void TearDown() {
-    if (initialized_synchronizer_)
-      MailboxSynchronizer::Terminate();
     GpuServiceTest::TearDown();
   }
 
@@ -88,7 +85,6 @@
   scoped_refptr<MailboxManager> manager_;
 
  private:
-  bool initialized_synchronizer_;
   scoped_refptr<FeatureInfo> feature_info_;
 
   DISALLOW_COPY_AND_ASSIGN(MailboxManagerTest);
@@ -99,18 +95,15 @@
   Texture* texture = CreateTexture();
 
   Mailbox name = Mailbox::Generate();
-  manager_->ProduceTexture(0, name, texture);
-  EXPECT_EQ(texture, manager_->ConsumeTexture(0, name));
+  manager_->ProduceTexture(name, texture);
+  EXPECT_EQ(texture, manager_->ConsumeTexture(name));
 
   // We can consume multiple times.
-  EXPECT_EQ(texture, manager_->ConsumeTexture(0, name));
-
-  // Wrong target should fail the consume.
-  EXPECT_EQ(NULL, manager_->ConsumeTexture(1, name));
+  EXPECT_EQ(texture, manager_->ConsumeTexture(name));
 
   // Destroy should cleanup the mailbox.
   DestroyTexture(texture);
-  EXPECT_EQ(NULL, manager_->ConsumeTexture(0, name));
+  EXPECT_EQ(NULL, manager_->ConsumeTexture(name));
 }
 
 // Tests behavior with multiple produce on the same texture.
@@ -119,25 +112,25 @@
 
   Mailbox name1 = Mailbox::Generate();
 
-  manager_->ProduceTexture(0, name1, texture);
-  EXPECT_EQ(texture, manager_->ConsumeTexture(0, name1));
+  manager_->ProduceTexture(name1, texture);
+  EXPECT_EQ(texture, manager_->ConsumeTexture(name1));
 
   // Can produce a second time with the same mailbox.
-  manager_->ProduceTexture(0, name1, texture);
-  EXPECT_EQ(texture, manager_->ConsumeTexture(0, name1));
+  manager_->ProduceTexture(name1, texture);
+  EXPECT_EQ(texture, manager_->ConsumeTexture(name1));
 
   // Can produce again, with a different mailbox.
   Mailbox name2 = Mailbox::Generate();
-  manager_->ProduceTexture(0, name2, texture);
+  manager_->ProduceTexture(name2, texture);
 
   // Still available under all mailboxes.
-  EXPECT_EQ(texture, manager_->ConsumeTexture(0, name1));
-  EXPECT_EQ(texture, manager_->ConsumeTexture(0, name2));
+  EXPECT_EQ(texture, manager_->ConsumeTexture(name1));
+  EXPECT_EQ(texture, manager_->ConsumeTexture(name2));
 
   // Destroy should cleanup all mailboxes.
   DestroyTexture(texture);
-  EXPECT_EQ(NULL, manager_->ConsumeTexture(0, name1));
-  EXPECT_EQ(NULL, manager_->ConsumeTexture(0, name2));
+  EXPECT_EQ(NULL, manager_->ConsumeTexture(name1));
+  EXPECT_EQ(NULL, manager_->ConsumeTexture(name2));
 }
 
 // Tests behavior with multiple produce on the same mailbox with different
@@ -148,20 +141,20 @@
 
   Mailbox name = Mailbox::Generate();
 
-  manager_->ProduceTexture(0, name, texture1);
-  EXPECT_EQ(texture1, manager_->ConsumeTexture(0, name));
+  manager_->ProduceTexture(name, texture1);
+  EXPECT_EQ(texture1, manager_->ConsumeTexture(name));
 
   // Can produce a second time with the same mailbox, but different texture.
-  manager_->ProduceTexture(0, name, texture2);
-  EXPECT_EQ(texture2, manager_->ConsumeTexture(0, name));
+  manager_->ProduceTexture(name, texture2);
+  EXPECT_EQ(texture2, manager_->ConsumeTexture(name));
 
   // Destroying the texture that's under no mailbox shouldn't have an effect.
   DestroyTexture(texture1);
-  EXPECT_EQ(texture2, manager_->ConsumeTexture(0, name));
+  EXPECT_EQ(texture2, manager_->ConsumeTexture(name));
 
   // Destroying the texture that's bound should clean up.
   DestroyTexture(texture2);
-  EXPECT_EQ(NULL, manager_->ConsumeTexture(0, name));
+  EXPECT_EQ(NULL, manager_->ConsumeTexture(name));
 }
 
 TEST_F(MailboxManagerTest, ProduceMultipleTextureMailbox) {
@@ -171,23 +164,23 @@
   Mailbox name2 = Mailbox::Generate();
 
   // Put texture1 on name1 and name2.
-  manager_->ProduceTexture(0, name1, texture1);
-  manager_->ProduceTexture(0, name2, texture1);
-  EXPECT_EQ(texture1, manager_->ConsumeTexture(0, name1));
-  EXPECT_EQ(texture1, manager_->ConsumeTexture(0, name2));
+  manager_->ProduceTexture(name1, texture1);
+  manager_->ProduceTexture(name2, texture1);
+  EXPECT_EQ(texture1, manager_->ConsumeTexture(name1));
+  EXPECT_EQ(texture1, manager_->ConsumeTexture(name2));
 
   // Put texture2 on name2.
-  manager_->ProduceTexture(0, name2, texture2);
-  EXPECT_EQ(texture1, manager_->ConsumeTexture(0, name1));
-  EXPECT_EQ(texture2, manager_->ConsumeTexture(0, name2));
+  manager_->ProduceTexture(name2, texture2);
+  EXPECT_EQ(texture1, manager_->ConsumeTexture(name1));
+  EXPECT_EQ(texture2, manager_->ConsumeTexture(name2));
 
   // Destroy texture1, shouldn't affect name2.
   DestroyTexture(texture1);
-  EXPECT_EQ(NULL, manager_->ConsumeTexture(0, name1));
-  EXPECT_EQ(texture2, manager_->ConsumeTexture(0, name2));
+  EXPECT_EQ(NULL, manager_->ConsumeTexture(name1));
+  EXPECT_EQ(texture2, manager_->ConsumeTexture(name2));
 
   DestroyTexture(texture2);
-  EXPECT_EQ(NULL, manager_->ConsumeTexture(0, name2));
+  EXPECT_EQ(NULL, manager_->ConsumeTexture(name2));
 }
 
 const GLsizei kMaxTextureWidth = 64;
@@ -202,7 +195,7 @@
  protected:
   virtual void SetUp() {
     MailboxManagerTest::SetUpWithSynchronizer();
-    manager2_ = new MailboxManager;
+    manager2_ = new MailboxManagerSync();
     context_ = new gfx::GLContextStub();
     surface_ = new gfx::GLSurfaceStub();
     context_->MakeCurrent(surface_.get());
@@ -282,12 +275,12 @@
   Mailbox name = Mailbox::Generate();
 
   InSequence sequence;
-  manager_->ProduceTexture(GL_TEXTURE_2D, name, texture);
-  EXPECT_EQ(texture, manager_->ConsumeTexture(GL_TEXTURE_2D, name));
+  manager_->ProduceTexture(name, texture);
+  EXPECT_EQ(texture, manager_->ConsumeTexture(name));
 
   DestroyTexture(texture);
-  EXPECT_EQ(NULL, manager_->ConsumeTexture(GL_TEXTURE_2D, name));
-  EXPECT_EQ(NULL, manager2_->ConsumeTexture(GL_TEXTURE_2D, name));
+  EXPECT_EQ(NULL, manager_->ConsumeTexture(name));
+  EXPECT_EQ(NULL, manager2_->ConsumeTexture(name));
 }
 
 TEST_F(MailboxManagerSyncTest, ProduceSyncDestroy) {
@@ -296,16 +289,36 @@
   Texture* texture = DefineTexture();
   Mailbox name = Mailbox::Generate();
 
-  manager_->ProduceTexture(GL_TEXTURE_2D, name, texture);
-  EXPECT_EQ(texture, manager_->ConsumeTexture(GL_TEXTURE_2D, name));
+  manager_->ProduceTexture(name, texture);
+  EXPECT_EQ(texture, manager_->ConsumeTexture(name));
 
   // Synchronize
   manager_->PushTextureUpdates(0);
   manager2_->PullTextureUpdates(0);
 
   DestroyTexture(texture);
-  EXPECT_EQ(NULL, manager_->ConsumeTexture(GL_TEXTURE_2D, name));
-  EXPECT_EQ(NULL, manager2_->ConsumeTexture(GL_TEXTURE_2D, name));
+  EXPECT_EQ(NULL, manager_->ConsumeTexture(name));
+  EXPECT_EQ(NULL, manager2_->ConsumeTexture(name));
+}
+
+TEST_F(MailboxManagerSyncTest, ProduceSyncClobberDestroy) {
+  InSequence sequence;
+
+  Texture* texture = DefineTexture();
+  Mailbox name = Mailbox::Generate();
+
+  manager_->ProduceTexture(name, texture);
+  manager_->PushTextureUpdates(0);
+
+  // Clobber
+  Texture* old_texture = texture;
+  texture = DefineTexture();
+  manager_->ProduceTexture(name, texture);
+
+  DestroyTexture(old_texture);
+  DestroyTexture(texture);
+  EXPECT_EQ(NULL, manager_->ConsumeTexture(name));
+  EXPECT_EQ(NULL, manager2_->ConsumeTexture(name));
 }
 
 // Duplicates a texture into a second manager instance, and then
@@ -317,8 +330,8 @@
   Texture* texture = DefineTexture();
   Mailbox name = Mailbox::Generate();
 
-  manager_->ProduceTexture(GL_TEXTURE_2D, name, texture);
-  EXPECT_EQ(texture, manager_->ConsumeTexture(GL_TEXTURE_2D, name));
+  manager_->ProduceTexture(name, texture);
+  EXPECT_EQ(texture, manager_->ConsumeTexture(name));
 
   // Synchronize
   manager_->PushTextureUpdates(0);
@@ -328,7 +341,7 @@
       .WillOnce(SetArgPointee<1>(kNewTextureId));
   SetupUpdateTexParamExpectations(
       kNewTextureId, GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT);
-  Texture* new_texture = manager2_->ConsumeTexture(GL_TEXTURE_2D, name);
+  Texture* new_texture = manager2_->ConsumeTexture(name);
   EXPECT_FALSE(new_texture == NULL);
   EXPECT_NE(texture, new_texture);
   EXPECT_EQ(kNewTextureId, new_texture->service_id());
@@ -378,7 +391,7 @@
   DestroyTexture(texture);
 
   // Should be still around since there is a ref from manager2
-  EXPECT_EQ(new_texture, manager2_->ConsumeTexture(GL_TEXTURE_2D, name));
+  EXPECT_EQ(new_texture, manager2_->ConsumeTexture(name));
 
   // The last change to the texture should be visible without a sync point (i.e.
   // push).
@@ -388,8 +401,8 @@
   EXPECT_EQ(64, height);
 
   DestroyTexture(new_texture);
-  EXPECT_EQ(NULL, manager_->ConsumeTexture(GL_TEXTURE_2D, name));
-  EXPECT_EQ(NULL, manager2_->ConsumeTexture(GL_TEXTURE_2D, name));
+  EXPECT_EQ(NULL, manager_->ConsumeTexture(name));
+  EXPECT_EQ(NULL, manager2_->ConsumeTexture(name));
 }
 
 // Makes sure changes are correctly published even when updates are
@@ -406,8 +419,8 @@
   Texture* new_texture1 = NULL;
   Texture* new_texture2 = NULL;
 
-  manager_->ProduceTexture(GL_TEXTURE_2D, name1, texture1);
-  manager2_->ProduceTexture(GL_TEXTURE_2D, name2, texture2);
+  manager_->ProduceTexture(name1, texture1);
+  manager2_->ProduceTexture(name2, texture2);
 
   // Make visible.
   manager_->PushTextureUpdates(0);
@@ -422,12 +435,12 @@
         .WillOnce(SetArgPointee<1>(kNewTextureId1));
     SetupUpdateTexParamExpectations(
         kNewTextureId1, GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT);
-    new_texture1 = manager2_->ConsumeTexture(GL_TEXTURE_2D, name1);
+    new_texture1 = manager2_->ConsumeTexture(name1);
     EXPECT_CALL(*gl_, GenTextures(1, _))
         .WillOnce(SetArgPointee<1>(kNewTextureId2));
     SetupUpdateTexParamExpectations(
         kNewTextureId2, GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT);
-    new_texture2 = manager_->ConsumeTexture(GL_TEXTURE_2D, name2);
+    new_texture2 = manager_->ConsumeTexture(name2);
   }
   EXPECT_EQ(kNewTextureId1, new_texture1->service_id());
   EXPECT_EQ(kNewTextureId2, new_texture2->service_id());
@@ -465,9 +478,148 @@
   DestroyTexture(new_texture2);
 }
 
-// TODO: different texture into same mailbox
+// If a texture is shared with another manager instance, but the mailbox
+// is then clobbered with a different texture in the source context, this should
+// disconnect the earlier texture from updates.
+TEST_F(MailboxManagerSyncTest, ProduceAndClobber) {
+  const GLuint kNewTextureId = 1234;
+  InSequence sequence;
 
-// TODO: same texture, multiple mailboxes
+  Texture* texture = DefineTexture();
+  Mailbox name = Mailbox::Generate();
+
+  manager_->ProduceTexture(name, texture);
+  EXPECT_EQ(texture, manager_->ConsumeTexture(name));
+
+  // Synchronize
+  manager_->PushTextureUpdates(0);
+  manager2_->PullTextureUpdates(0);
+
+  EXPECT_CALL(*gl_, GenTextures(1, _))
+      .WillOnce(SetArgPointee<1>(kNewTextureId));
+  SetupUpdateTexParamExpectations(
+      kNewTextureId, GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT);
+  Texture* new_texture = manager2_->ConsumeTexture(name);
+  EXPECT_FALSE(new_texture == NULL);
+  EXPECT_NE(texture, new_texture);
+  EXPECT_EQ(kNewTextureId, new_texture->service_id());
+
+  Texture* old_texture = texture;
+  texture = DefineTexture();
+  manager_->ProduceTexture(name, texture);
+
+  // Make a change to the new texture
+  DCHECK_EQ(static_cast<GLuint>(GL_LINEAR), texture->min_filter());
+  EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR),
+            SetParameter(texture, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
+
+  // Synchronize in both directions - no changes, since it's not shared
+  manager_->PushTextureUpdates(0);
+  manager2_->PullTextureUpdates(0);
+  EXPECT_EQ(static_cast<GLuint>(GL_LINEAR), new_texture->min_filter());
+
+  // Make a change to the previously shared texture
+  DCHECK_EQ(static_cast<GLuint>(GL_LINEAR), old_texture->mag_filter());
+  EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR),
+            SetParameter(old_texture, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
+
+  // Synchronize and expect update
+  manager_->PushTextureUpdates(0);
+  SetupUpdateTexParamExpectations(
+      new_texture->service_id(), GL_LINEAR, GL_NEAREST, GL_REPEAT, GL_REPEAT);
+  manager2_->PullTextureUpdates(0);
+
+  EXPECT_CALL(*gl_, GenTextures(1, _))
+      .WillOnce(SetArgPointee<1>(kNewTextureId));
+  SetupUpdateTexParamExpectations(
+      kNewTextureId, GL_NEAREST, GL_LINEAR, GL_REPEAT, GL_REPEAT);
+  Texture* tmp_texture = manager2_->ConsumeTexture(name);
+  EXPECT_NE(new_texture, tmp_texture);
+  DestroyTexture(tmp_texture);
+
+  DestroyTexture(old_texture);
+  DestroyTexture(texture);
+  DestroyTexture(new_texture);
+
+  EXPECT_EQ(NULL, manager_->ConsumeTexture(name));
+  EXPECT_EQ(NULL, manager2_->ConsumeTexture(name));
+}
+
+// Putting the same texture into multiple mailboxes should result in sharing
+// only a single texture also within a synchronized manager instance.
+TEST_F(MailboxManagerSyncTest, SharedThroughMultipleMailboxes) {
+  const GLuint kNewTextureId = 1234;
+  InSequence sequence;
+
+  Texture* texture = DefineTexture();
+  Mailbox name1 = Mailbox::Generate();
+  Mailbox name2 = Mailbox::Generate();
+
+  manager_->ProduceTexture(name1, texture);
+
+  // Share
+  manager_->PushTextureUpdates(0);
+  EXPECT_CALL(*gl_, GenTextures(1, _))
+      .WillOnce(SetArgPointee<1>(kNewTextureId));
+  manager2_->PullTextureUpdates(0);
+  SetupUpdateTexParamExpectations(
+      kNewTextureId, GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT);
+  Texture* new_texture = manager2_->ConsumeTexture(name1);
+  EXPECT_EQ(kNewTextureId, new_texture->service_id());
+
+  manager_->ProduceTexture(name2, texture);
+
+  // Synchronize
+  manager_->PushTextureUpdates(0);
+  manager2_->PullTextureUpdates(0);
+
+  // name2 should return the same texture
+  EXPECT_EQ(new_texture, manager2_->ConsumeTexture(name2));
+
+  // Even after destroying the source texture, the original mailbox should
+  // still exist.
+  DestroyTexture(texture);
+  EXPECT_EQ(new_texture, manager2_->ConsumeTexture(name1));
+  DestroyTexture(new_texture);
+}
+
+// A: produce texture1 into M, B: consume into new_texture
+// B: produce texture2 into M, A: produce texture1 into M
+// B: consume M should return new_texture
+TEST_F(MailboxManagerSyncTest, ProduceBothWays) {
+  const GLuint kNewTextureId = 1234;
+  InSequence sequence;
+
+  Texture* texture1 = DefineTexture();
+  Texture* texture2 = DefineTexture();
+  Mailbox name = Mailbox::Generate();
+
+  manager_->ProduceTexture(name, texture1);
+
+  // Share
+  manager_->PushTextureUpdates(0);
+  EXPECT_CALL(*gl_, GenTextures(1, _))
+      .WillOnce(SetArgPointee<1>(kNewTextureId));
+  SetupUpdateTexParamExpectations(
+      kNewTextureId, GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT);
+  Texture* new_texture = manager2_->ConsumeTexture(name);
+  EXPECT_EQ(kNewTextureId, new_texture->service_id());
+
+  // Clobber
+  manager2_->ProduceTexture(name, texture2);
+  manager_->ProduceTexture(name, texture1);
+
+  // Synchronize manager -> manager2
+  manager_->PushTextureUpdates(0);
+  manager2_->PullTextureUpdates(0);
+
+  // name should return the original texture, and not texture2 or a new one.
+  EXPECT_EQ(new_texture, manager2_->ConsumeTexture(name));
+
+  DestroyTexture(texture1);
+  DestroyTexture(texture2);
+  DestroyTexture(new_texture);
+}
 
 // TODO: Produce incomplete texture
 
diff --git a/gpu/command_buffer/service/mailbox_synchronizer.cc b/gpu/command_buffer/service/mailbox_synchronizer.cc
deleted file mode 100644
index 81a2793..0000000
--- a/gpu/command_buffer/service/mailbox_synchronizer.cc
+++ /dev/null
@@ -1,276 +0,0 @@
-// Copyright 2014 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 "gpu/command_buffer/service/mailbox_synchronizer.h"
-
-#include "base/bind.h"
-#include "gpu/command_buffer/service/mailbox_manager.h"
-#include "gpu/command_buffer/service/texture_manager.h"
-#include "ui/gl/gl_fence.h"
-#include "ui/gl/gl_implementation.h"
-
-#if !defined(OS_MACOSX)
-#include "ui/gl/gl_fence_egl.h"
-#endif
-
-namespace gpu {
-namespace gles2 {
-
-namespace {
-
-MailboxSynchronizer* g_instance = NULL;
-
-}  // anonymous namespace
-
-// static
-bool MailboxSynchronizer::Initialize() {
-  DCHECK(!g_instance);
-  DCHECK(gfx::GetGLImplementation() != gfx::kGLImplementationNone)
-      << "GL bindings not initialized";
-  switch (gfx::GetGLImplementation()) {
-    case gfx::kGLImplementationMockGL:
-      break;
-    case gfx::kGLImplementationEGLGLES2:
-#if !defined(OS_MACOSX)
-      {
-        if (!gfx::g_driver_egl.ext.b_EGL_KHR_image_base ||
-            !gfx::g_driver_egl.ext.b_EGL_KHR_gl_texture_2D_image ||
-            !gfx::g_driver_gl.ext.b_GL_OES_EGL_image ||
-            !gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync) {
-          LOG(WARNING) << "MailboxSync not supported due to missing EGL "
-                          "image/fence support";
-          return false;
-        }
-      }
-      break;
-#endif
-    default:
-      NOTREACHED();
-      return false;
-  }
-  g_instance = new MailboxSynchronizer;
-  return true;
-}
-
-// static
-void MailboxSynchronizer::Terminate() {
-  DCHECK(g_instance);
-  delete g_instance;
-  g_instance = NULL;
-}
-
-// static
-MailboxSynchronizer* MailboxSynchronizer::GetInstance() {
-  return g_instance;
-}
-
-MailboxSynchronizer::TargetName::TargetName(unsigned target,
-                                            const Mailbox& mailbox)
-    : target(target), mailbox(mailbox) {}
-
-MailboxSynchronizer::TextureGroup::TextureGroup(
-    const TextureDefinition& definition)
-    : definition(definition) {}
-
-MailboxSynchronizer::TextureGroup::~TextureGroup() {}
-
-MailboxSynchronizer::TextureVersion::TextureVersion(
-    linked_ptr<TextureGroup> group)
-    : version(group->definition.version()), group(group) {}
-
-MailboxSynchronizer::TextureVersion::~TextureVersion() {}
-
-MailboxSynchronizer::MailboxSynchronizer() {}
-
-MailboxSynchronizer::~MailboxSynchronizer() {
-  DCHECK_EQ(0U, textures_.size());
-}
-
-void MailboxSynchronizer::ReassociateMailboxLocked(
-    const TargetName& target_name,
-    TextureGroup* group) {
-  lock_.AssertAcquired();
-  for (TextureMap::iterator it = textures_.begin(); it != textures_.end();
-       it++) {
-    std::set<TargetName>::iterator mb_it =
-        it->second.group->mailboxes.find(target_name);
-    if (it->second.group != group &&
-        mb_it != it->second.group->mailboxes.end()) {
-      it->second.group->mailboxes.erase(mb_it);
-    }
-  }
-  group->mailboxes.insert(target_name);
-}
-
-linked_ptr<MailboxSynchronizer::TextureGroup>
-MailboxSynchronizer::GetGroupForMailboxLocked(const TargetName& target_name) {
-  lock_.AssertAcquired();
-  for (TextureMap::iterator it = textures_.begin(); it != textures_.end();
-       it++) {
-    std::set<TargetName>::const_iterator mb_it =
-        it->second.group->mailboxes.find(target_name);
-    if (mb_it != it->second.group->mailboxes.end())
-      return it->second.group;
-  }
-  return make_linked_ptr<MailboxSynchronizer::TextureGroup>(NULL);
-}
-
-Texture* MailboxSynchronizer::CreateTextureFromMailbox(unsigned target,
-                                                       const Mailbox& mailbox) {
-  base::AutoLock lock(lock_);
-  TargetName target_name(target, mailbox);
-  linked_ptr<TextureGroup> group = GetGroupForMailboxLocked(target_name);
-  if (group.get()) {
-    Texture* new_texture = group->definition.CreateTexture();
-    if (new_texture)
-      textures_.insert(std::make_pair(new_texture, TextureVersion(group)));
-    return new_texture;
-  }
-
-  return NULL;
-}
-
-void MailboxSynchronizer::TextureDeleted(Texture* texture) {
-  base::AutoLock lock(lock_);
-  TextureMap::iterator it = textures_.find(texture);
-  if (it != textures_.end()) {
-    // TODO: We could avoid the update if this was the last ref.
-    UpdateTextureLocked(it->first, it->second);
-    textures_.erase(it);
-  }
-}
-
-void MailboxSynchronizer::PushTextureUpdates(MailboxManager* manager,
-                                             uint32 sync_point) {
-  base::AutoLock lock(lock_);
-  for (MailboxManager::MailboxToTextureMap::const_iterator texture_it =
-           manager->mailbox_to_textures_.begin();
-       texture_it != manager->mailbox_to_textures_.end();
-       texture_it++) {
-    TargetName target_name(texture_it->first.target, texture_it->first.mailbox);
-    Texture* texture = texture_it->second->first;
-    // TODO(sievers): crbug.com/352274
-    // Should probably only fail if it already *has* mipmaps, while allowing
-    // incomplete textures here. Also reconsider how to fail otherwise.
-    bool needs_mips = texture->min_filter() != GL_NEAREST &&
-                      texture->min_filter() != GL_LINEAR;
-    if (target_name.target != GL_TEXTURE_2D || needs_mips)
-      continue;
-
-    TextureMap::iterator it = textures_.find(texture);
-    if (it != textures_.end()) {
-      TextureVersion& texture_version = it->second;
-      TextureGroup* group = texture_version.group.get();
-      std::set<TargetName>::const_iterator mb_it =
-          group->mailboxes.find(target_name);
-      if (mb_it == group->mailboxes.end()) {
-        // We previously did not associate this texture with the given mailbox.
-        // Unlink other texture groups from the mailbox.
-        ReassociateMailboxLocked(target_name, group);
-      }
-      UpdateTextureLocked(texture, texture_version);
-
-    } else {
-      // Skip compositor resources/tile textures.
-      // TODO: Remove this, see crbug.com/399226.
-      if (texture->pool() == GL_TEXTURE_POOL_MANAGED_CHROMIUM)
-        continue;
-
-      linked_ptr<TextureGroup> group = make_linked_ptr(new TextureGroup(
-          TextureDefinition(target_name.target, texture, 1, NULL)));
-
-      // Unlink other textures from this mailbox in case the name is not new.
-      ReassociateMailboxLocked(target_name, group.get());
-      textures_.insert(std::make_pair(texture, TextureVersion(group)));
-    }
-  }
-
-  CreateFenceLocked(sync_point);
-}
-
-void MailboxSynchronizer::CreateFenceLocked(uint32 sync_point) {
-  lock_.AssertAcquired();
-  if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL)
-    return;
-
-#if !defined(OS_MACOSX)
-  if (sync_point) {
-    while (!sync_points_.empty() &&
-           sync_points_.front()->second->HasCompleted()) {
-      sync_point_to_fence_.erase(sync_points_.front());
-      sync_points_.pop();
-    }
-    // Need to use EGL fences since we are likely not in a single share group.
-    linked_ptr<gfx::GLFence> fence(make_linked_ptr(new gfx::GLFenceEGL(true)));
-    if (fence.get()) {
-      std::pair<SyncPointToFenceMap::iterator, bool> result =
-          sync_point_to_fence_.insert(std::make_pair(sync_point, fence));
-      DCHECK(result.second);
-      sync_points_.push(result.first);
-    }
-    DCHECK(sync_points_.size() == sync_point_to_fence_.size());
-  }
-#endif
-}
-
-void MailboxSynchronizer::UpdateTextureLocked(Texture* texture,
-                                              TextureVersion& texture_version) {
-  lock_.AssertAcquired();
-  gfx::GLImage* gl_image = texture->GetLevelImage(texture->target(), 0);
-  TextureGroup* group = texture_version.group.get();
-  scoped_refptr<NativeImageBuffer> image_buffer = group->definition.image();
-
-  // Make sure we don't clobber with an older version
-  if (!group->definition.IsOlderThan(texture_version.version))
-    return;
-
-  // Also don't push redundant updates. Note that it would break the
-  // versioning.
-  if (group->definition.Matches(texture))
-    return;
-
-  if (gl_image && !image_buffer->IsClient(gl_image)) {
-    LOG(ERROR) << "MailboxSync: Incompatible attachment";
-    return;
-  }
-
-  group->definition = TextureDefinition(texture->target(),
-                                        texture,
-                                        ++texture_version.version,
-                                        gl_image ? image_buffer : NULL);
-}
-
-void MailboxSynchronizer::AcquireFenceLocked(uint32 sync_point) {
-  lock_.AssertAcquired();
-  SyncPointToFenceMap::iterator fence_it =
-      sync_point_to_fence_.find(sync_point);
-  if (fence_it != sync_point_to_fence_.end()) {
-    fence_it->second->ServerWait();
-  }
-}
-
-void MailboxSynchronizer::PullTextureUpdates(MailboxManager* manager,
-                                             uint32 sync_point) {
-  base::AutoLock lock(lock_);
-  AcquireFenceLocked(sync_point);
-
-  for (MailboxManager::MailboxToTextureMap::const_iterator texture_it =
-           manager->mailbox_to_textures_.begin();
-       texture_it != manager->mailbox_to_textures_.end();
-       texture_it++) {
-    Texture* texture = texture_it->second->first;
-    TextureMap::iterator it = textures_.find(texture);
-    if (it != textures_.end()) {
-      TextureDefinition& definition = it->second.group->definition;
-      if (it->second.version == definition.version() ||
-          definition.IsOlderThan(it->second.version))
-        continue;
-      it->second.version = definition.version();
-      definition.UpdateTexture(texture);
-    }
-  }
-}
-
-}  // namespace gles2
-}  // namespace gpu
diff --git a/gpu/command_buffer/service/mailbox_synchronizer.h b/gpu/command_buffer/service/mailbox_synchronizer.h
deleted file mode 100644
index 3ddb9d0..0000000
--- a/gpu/command_buffer/service/mailbox_synchronizer.h
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright 2014 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 GPU_COMMAND_BUFFER_SERVICE_MAILBOX_SYNCHRONIZER_H_
-#define GPU_COMMAND_BUFFER_SERVICE_MAILBOX_SYNCHRONIZER_H_
-
-#include "gpu/command_buffer/common/mailbox.h"
-
-#include <map>
-#include <queue>
-#include <set>
-
-#include "base/memory/linked_ptr.h"
-#include "base/synchronization/lock.h"
-#include "gpu/command_buffer/service/texture_definition.h"
-#include "gpu/gpu_export.h"
-
-namespace gfx {
-class GLFence;
-}
-
-namespace gpu {
-namespace gles2 {
-
-class MailboxManager;
-class Texture;
-
-// A thread-safe proxy that can be used to emulate texture sharing across
-// share-groups.
-class MailboxSynchronizer {
- public:
-  ~MailboxSynchronizer();
-
-  GPU_EXPORT static bool Initialize();
-  GPU_EXPORT static void Terminate();
-  static MailboxSynchronizer* GetInstance();
-
-  // Create a texture from a globally visible mailbox.
-  Texture* CreateTextureFromMailbox(unsigned target, const Mailbox& mailbox);
-
-  void PushTextureUpdates(MailboxManager* manager, uint32 sync_point);
-  void PullTextureUpdates(MailboxManager* manager, uint32 sync_point);
-
-  void TextureDeleted(Texture* texture);
-
- private:
-  MailboxSynchronizer();
-
-  struct TargetName {
-    TargetName(unsigned target, const Mailbox& mailbox);
-    bool operator<(const TargetName& rhs) const {
-      return memcmp(this, &rhs, sizeof(rhs)) < 0;
-    }
-    bool operator!=(const TargetName& rhs) const {
-      return memcmp(this, &rhs, sizeof(rhs)) != 0;
-    }
-    bool operator==(const TargetName& rhs) const {
-      return !operator!=(rhs);
-    }
-    unsigned target;
-    Mailbox mailbox;
-  };
-
-  base::Lock lock_;
-
-  struct TextureGroup {
-    explicit TextureGroup(const TextureDefinition& definition);
-    ~TextureGroup();
-
-    TextureDefinition definition;
-    std::set<TargetName> mailboxes;
-   private:
-    DISALLOW_COPY_AND_ASSIGN(TextureGroup);
-  };
-
-  struct TextureVersion {
-    explicit TextureVersion(linked_ptr<TextureGroup> group);
-    ~TextureVersion();
-
-    unsigned int version;
-    linked_ptr<TextureGroup> group;
-  };
-  typedef std::map<Texture*, TextureVersion> TextureMap;
-  TextureMap textures_;
-
-  linked_ptr<TextureGroup> GetGroupForMailboxLocked(
-      const TargetName& target_name);
-  void ReassociateMailboxLocked(
-      const TargetName& target_name,
-      TextureGroup* group);
-  void UpdateTextureLocked(Texture* texture, TextureVersion& texture_version);
-  void CreateFenceLocked(uint32 sync_point);
-  void AcquireFenceLocked(uint32 sync_point);
-
-  typedef std::map<uint32, linked_ptr<gfx::GLFence> > SyncPointToFenceMap;
-  SyncPointToFenceMap sync_point_to_fence_;
-  std::queue<SyncPointToFenceMap::iterator> sync_points_;
-
-  DISALLOW_COPY_AND_ASSIGN(MailboxSynchronizer);
-};
-
-}  // namespage gles2
-}  // namespace gpu
-
-#endif  // GPU_COMMAND_BUFFER_SERVICE_MAILBOX_SYNCHRONIZER_H_
-
diff --git a/gpu/command_buffer/service/texture_definition.cc b/gpu/command_buffer/service/texture_definition.cc
index abde56a..b0cafe2 100644
--- a/gpu/command_buffer/service/texture_definition.cc
+++ b/gpu/command_buffer/service/texture_definition.cc
@@ -278,13 +278,23 @@
 
 TextureDefinition::LevelInfo::~LevelInfo() {}
 
+TextureDefinition::TextureDefinition()
+    : version_(0),
+      target_(0),
+      min_filter_(0),
+      mag_filter_(0),
+      wrap_s_(0),
+      wrap_t_(0),
+      usage_(0),
+      immutable_(true) {
+}
+
 TextureDefinition::TextureDefinition(
-    GLenum target,
     Texture* texture,
     unsigned int version,
     const scoped_refptr<NativeImageBuffer>& image_buffer)
     : version_(version),
-      target_(target),
+      target_(texture->target()),
       image_buffer_(image_buffer.get()
                         ? image_buffer
                         : NativeImageBuffer::Create(texture->service_id())),
@@ -306,7 +316,7 @@
       new GLImageSync(image_buffer_,
                       gfx::Size(first_face.level_infos[0].width,
                                 first_face.level_infos[0].height)));
-  texture->SetLevelImage(NULL, target, 0, gl_image.get());
+  texture->SetLevelImage(NULL, target_, 0, gl_image.get());
 
   // TODO: all levels
   level_infos_.clear();
diff --git a/gpu/command_buffer/service/texture_definition.h b/gpu/command_buffer/service/texture_definition.h
index cb21abd..ff891fc 100644
--- a/gpu/command_buffer/service/texture_definition.h
+++ b/gpu/command_buffer/service/texture_definition.h
@@ -40,8 +40,8 @@
 // the underlying image buffer(s).
 class TextureDefinition {
  public:
-  TextureDefinition(GLenum target,
-                    Texture* texture,
+  TextureDefinition();
+  TextureDefinition(Texture* texture,
                     unsigned int version,
                     const scoped_refptr<NativeImageBuffer>& image);
   virtual ~TextureDefinition();
@@ -55,7 +55,7 @@
   }
   bool Matches(const Texture* texture) const;
 
-  scoped_refptr<NativeImageBuffer> image() { return image_buffer_; }
+  scoped_refptr<NativeImageBuffer> image() const { return image_buffer_; }
 
  private:
   struct LevelInfo {
diff --git a/gpu/command_buffer/service/texture_manager.h b/gpu/command_buffer/service/texture_manager.h
index 25bc2ff..3ab5467 100644
--- a/gpu/command_buffer/service/texture_manager.h
+++ b/gpu/command_buffer/service/texture_manager.h
@@ -165,7 +165,8 @@
   void OnDidModifyPixels();
 
  private:
-  friend class MailboxManager;
+  friend class MailboxManagerImpl;
+  friend class MailboxManagerSync;
   friend class MailboxManagerTest;
   friend class TextureDefinition;
   friend class TextureManager;
diff --git a/gpu/command_buffer/tests/gl_manager.cc b/gpu/command_buffer/tests/gl_manager.cc
index bb2acbd..ffbc573 100644
--- a/gpu/command_buffer/tests/gl_manager.cc
+++ b/gpu/command_buffer/tests/gl_manager.cc
@@ -24,7 +24,7 @@
 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
 #include "gpu/command_buffer/service/gpu_scheduler.h"
 #include "gpu/command_buffer/service/image_manager.h"
-#include "gpu/command_buffer/service/mailbox_manager.h"
+#include "gpu/command_buffer/service/mailbox_manager_impl.h"
 #include "gpu/command_buffer/service/memory_tracking.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gfx/gpu_memory_buffer.h"
@@ -174,7 +174,7 @@
   }
 
   mailbox_manager_ =
-      mailbox_manager ? mailbox_manager : new gles2::MailboxManager;
+      mailbox_manager ? mailbox_manager : new gles2::MailboxManagerImpl;
   share_group_ =
       share_group ? share_group : new gfx::GLShareGroup;
 
diff --git a/gpu/command_buffer_service.gypi b/gpu/command_buffer_service.gypi
index 2640dad..4814cb2 100644
--- a/gpu/command_buffer_service.gypi
+++ b/gpu/command_buffer_service.gypi
@@ -93,10 +93,11 @@
     'command_buffer/service/in_process_command_buffer.h',
     'command_buffer/service/logger.cc',
     'command_buffer/service/logger.h',
-    'command_buffer/service/mailbox_manager.cc',
     'command_buffer/service/mailbox_manager.h',
-    'command_buffer/service/mailbox_synchronizer.cc',
-    'command_buffer/service/mailbox_synchronizer.h',
+    'command_buffer/service/mailbox_manager_impl.cc',
+    'command_buffer/service/mailbox_manager_impl.h',
+    'command_buffer/service/mailbox_manager_sync.cc',
+    'command_buffer/service/mailbox_manager_sync.h',
     'command_buffer/service/memory_program_cache.h',
     'command_buffer/service/memory_program_cache.cc',
     'command_buffer/service/mocks.h',
diff --git a/gpu/config/DEPS b/gpu/config/DEPS
index 7c0ee4b..39b325a 100644
--- a/gpu/config/DEPS
+++ b/gpu/config/DEPS
@@ -1,5 +1,4 @@
 include_rules = [
   "+third_party/libxml",  # For parsing WinSAT results files.
   "+third_party/libXNVCtrl",  # For NV driver version query.
-  "+media/video",  # For VideoEncodeAccelerator::SupportedProfile.
 ]
diff --git a/gpu/config/gpu_info.cc b/gpu/config/gpu_info.cc
index f560dcb..f1f67ce 100644
--- a/gpu/config/gpu_info.cc
+++ b/gpu/config/gpu_info.cc
@@ -17,6 +17,19 @@
   enumerator->EndGPUDevice();
 }
 
+void EnumerateVideoEncodeAcceleratorSupportedProfile(
+    gpu::GPUInfo::Enumerator* enumerator,
+    const gpu::VideoEncodeAcceleratorSupportedProfile profile) {
+  enumerator->BeginVideoEncodeAcceleratorSupportedProfile();
+  enumerator->AddInt("profile", profile.profile);
+  enumerator->AddInt("maxResolutionWidth", profile.max_resolution.width());
+  enumerator->AddInt("maxResolutionHeight", profile.max_resolution.height());
+  enumerator->AddInt("maxFramerateNumerator", profile.max_framerate_numerator);
+  enumerator->AddInt("maxFramerateDenominator",
+                     profile.max_framerate_denominator);
+  enumerator->EndVideoEncodeAcceleratorSupportedProfile();
+}
+
 }  // namespace
 
 namespace gpu {
@@ -88,6 +101,8 @@
     CollectInfoResult dx_diagnostics_info_state;
     DxDiagNode dx_diagnostics;
 #endif
+    std::vector<VideoEncodeAcceleratorSupportedProfile>
+        video_encode_accelerator_supported_profiles;
   };
 
   // If this assert fails then most likely something below needs to be updated.
@@ -142,6 +157,12 @@
 #if defined(OS_WIN)
   enumerator->AddInt("DxDiagnosticsInfoState", dx_diagnostics_info_state);
 #endif
+  // TODO(kbr): add dx_diagnostics on Windows.
+  for (size_t ii = 0; ii < video_encode_accelerator_supported_profiles.size();
+       ++ii) {
+    EnumerateVideoEncodeAcceleratorSupportedProfile(
+        enumerator, video_encode_accelerator_supported_profiles[ii]);
+  }
   enumerator->EndAuxAttributes();
 }
 
diff --git a/gpu/config/gpu_info.h b/gpu/config/gpu_info.h
index 8f5479b..7c92d3a 100644
--- a/gpu/config/gpu_info.h
+++ b/gpu/config/gpu_info.h
@@ -18,6 +18,7 @@
 #include "gpu/config/dx_diag_node.h"
 #include "gpu/config/gpu_performance_stats.h"
 #include "gpu/gpu_export.h"
+#include "ui/gfx/geometry/size.h"
 
 namespace gpu {
 
@@ -34,6 +35,34 @@
   kCollectInfoFatalFailure = 3
 };
 
+// Video profile.  This *must* match media::VideoCodecProfile.
+enum VideoCodecProfile {
+  VIDEO_CODEC_PROFILE_UNKNOWN = -1,
+  VIDEO_CODEC_PROFILE_MIN = VIDEO_CODEC_PROFILE_UNKNOWN,
+  H264PROFILE_BASELINE = 0,
+  H264PROFILE_MAIN = 1,
+  H264PROFILE_EXTENDED = 2,
+  H264PROFILE_HIGH = 3,
+  H264PROFILE_HIGH10PROFILE = 4,
+  H264PROFILE_HIGH422PROFILE = 5,
+  H264PROFILE_HIGH444PREDICTIVEPROFILE = 6,
+  H264PROFILE_SCALABLEBASELINE = 7,
+  H264PROFILE_SCALABLEHIGH = 8,
+  H264PROFILE_STEREOHIGH = 9,
+  H264PROFILE_MULTIVIEWHIGH = 10,
+  VP8PROFILE_ANY = 11,
+  VP9PROFILE_ANY = 12,
+  VIDEO_CODEC_PROFILE_MAX = VP9PROFILE_ANY,
+};
+
+// Specification of an encoding profile supported by a hardware encoder.
+struct GPU_EXPORT VideoEncodeAcceleratorSupportedProfile {
+  VideoCodecProfile profile;
+  gfx::Size max_resolution;
+  uint32 max_framerate_numerator;
+  uint32 max_framerate_denominator;
+};
+
 struct GPU_EXPORT GPUInfo {
   struct GPU_EXPORT GPUDevice {
     GPUDevice();
@@ -177,6 +206,8 @@
   DxDiagNode dx_diagnostics;
 #endif
 
+  std::vector<VideoEncodeAcceleratorSupportedProfile>
+      video_encode_accelerator_supported_profiles;
   // Note: when adding new members, please remember to update EnumerateFields
   // in gpu_info.cc.
 
@@ -201,7 +232,7 @@
     virtual void BeginGPUDevice() = 0;
     virtual void EndGPUDevice() = 0;
 
-    // Markers indicating that a VideoEncodeAccelerator::SupportedProfile is
+    // Markers indicating that a VideoEncodeAcceleratorSupportedProfile is
     // being described.
     virtual void BeginVideoEncodeAcceleratorSupportedProfile() = 0;
     virtual void EndVideoEncodeAcceleratorSupportedProfile() = 0;
diff --git a/gpu/config/gpu_info_collector.cc b/gpu/config/gpu_info_collector.cc
index 78dfe22..5d25546 100644
--- a/gpu/config/gpu_info_collector.cc
+++ b/gpu/config/gpu_info_collector.cc
@@ -156,6 +156,8 @@
   basic_gpu_info->direct_rendering = context_gpu_info.direct_rendering;
   basic_gpu_info->context_info_state = context_gpu_info.context_info_state;
   basic_gpu_info->initialization_time = context_gpu_info.initialization_time;
+  basic_gpu_info->video_encode_accelerator_supported_profiles =
+      context_gpu_info.video_encode_accelerator_supported_profiles;
 }
 
 }  // namespace gpu
diff --git a/gpu/config/gpu_info_unittest.cc b/gpu/config/gpu_info_unittest.cc
index 48d476f..71d4e5c 100644
--- a/gpu/config/gpu_info_unittest.cc
+++ b/gpu/config/gpu_info_unittest.cc
@@ -32,6 +32,7 @@
 #if defined(OS_WIN)
   EXPECT_EQ(gpu_info.dx_diagnostics_info_state, kCollectInfoNone);
 #endif
+  EXPECT_EQ(gpu_info.video_encode_accelerator_supported_profiles.size(), 0u);
 }
 
 }  // namespace gpu