Made the registration and deletion of transfer buffers async.

Added a thread safe way to duplicate a shared memory handle for the GPU process.

Removed synchronous IPC to set the command buffer shared state buffer.

Removed CreateTransferBuffer IPC. Removed request_id arg from transfer buffer IPCs. It wasn't being used.

BUG=166229

Review URL: https://chromiumcodereview.appspot.com/11640008

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@174303 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/content/common/gpu/client/command_buffer_proxy_impl.cc b/content/common/gpu/client/command_buffer_proxy_impl.cc
index c60d84c1..856ef7eb 100644
--- a/content/common/gpu/client/command_buffer_proxy_impl.cc
+++ b/content/common/gpu/client/command_buffer_proxy_impl.cc
@@ -20,29 +20,19 @@
 #include "gpu/command_buffer/common/command_buffer_shared.h"
 #include "ui/gfx/size.h"
 
-#if defined(OS_WIN)
-#include "content/public/common/sandbox_init.h"
-#endif
-
-using gpu::Buffer;
-
 namespace content {
 
 CommandBufferProxyImpl::CommandBufferProxyImpl(
     GpuChannelHost* channel,
     int route_id)
-    : shared_state_(NULL),
-      channel_(channel),
+    : channel_(channel),
       route_id_(route_id),
       flush_count_(0),
       last_put_offset_(-1),
-      next_signal_id_(0),
-      state_buffer_(-1) {
+      next_signal_id_(0) {
 }
 
 CommandBufferProxyImpl::~CommandBufferProxyImpl() {
-  if (state_buffer_ != -1)
-    DestroyTransferBuffer(state_buffer_);
   // Delete all the locally cached shared memory objects, closing the handle
   // in this process.
   for (TransferBufferMap::iterator it = transfer_buffers_.begin();
@@ -52,7 +42,7 @@
     it->second.shared_memory = NULL;
   }
   for (Decoders::iterator it = video_decoder_hosts_.begin();
-       it != video_decoder_hosts_.end(); ++it) {
+      it != video_decoder_hosts_.end(); ++it) {
     if (it->second)
       it->second->OnChannelError();
   }
@@ -62,8 +52,6 @@
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP(CommandBufferProxyImpl, message)
     IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_Destroyed, OnDestroyed);
-    IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_NotifyRepaint,
-                        OnNotifyRepaint);
     IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_EchoAck, OnEchoAck);
     IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_ConsoleMsg, OnConsoleMessage);
     IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_SetMemoryAllocation,
@@ -142,8 +130,26 @@
 }
 
 bool CommandBufferProxyImpl::Initialize() {
+  shared_state_shm_.reset(channel_->factory()->AllocateSharedMemory(
+      sizeof(*shared_state())).release());
+  if (!shared_state_shm_.get())
+    return false;
+
+  if (!shared_state_shm_->Map(sizeof(*shared_state())))
+    return false;
+
+  shared_state()->Initialize();
+
+  // This handle is owned by the GPU process and must be passed to it or it
+  // will leak. In otherwords, do not early out on error between here and the
+  // sending of the Initialize IPC below.
+  base::SharedMemoryHandle handle =
+      channel_->ShareToGpuProcess(shared_state_shm_.get());
+  if (!base::SharedMemory::IsHandleValid(handle))
+    return false;
+
   bool result;
-  if (!Send(new GpuCommandBufferMsg_Initialize(route_id_, &result))) {
+  if (!Send(new GpuCommandBufferMsg_Initialize(route_id_, handle, &result))) {
     LOG(ERROR) << "Could not send GpuCommandBufferMsg_Initialize.";
     return false;
   }
@@ -153,28 +159,6 @@
     return false;
   }
 
-  state_buffer_ = CreateTransferBuffer(sizeof *shared_state_, -1);
-
-  if (state_buffer_ == -1) {
-    LOG(ERROR) << "Failed to create shared state transfer buffer.";
-    return false;
-  }
-
-  gpu::Buffer buffer = GetTransferBuffer(state_buffer_);
-  if (!buffer.ptr) {
-    LOG(ERROR) << "Failed to get shared state transfer buffer";
-    return false;
-  }
-
-  shared_state_ = reinterpret_cast<gpu::CommandBufferSharedState*>(buffer.ptr);
-  shared_state_->Initialize();
-
-  if (!Send(new GpuCommandBufferMsg_SetSharedStateBuffer(route_id_,
-                                                         state_buffer_))) {
-    LOG(ERROR) << "Failed to initialize shared command buffer state.";
-    return false;
-  }
-
   return true;
 }
 
@@ -247,70 +231,48 @@
   NOTREACHED();
 }
 
-int32 CommandBufferProxyImpl::CreateTransferBuffer(
-    size_t size, int32 id_request) {
-  if (last_state_.error != gpu::error::kNoError)
-    return -1;
+gpu::Buffer CommandBufferProxyImpl::CreateTransferBuffer(size_t size,
+                                                         int32* id) {
+  *id = -1;
 
-  // Take ownership of shared memory. This will close the handle if Send below
-  // fails. Otherwise, callee takes ownership before this variable
-  // goes out of scope by duping the handle.
-  scoped_ptr<base::SharedMemory> shm(
+  if (last_state_.error != gpu::error::kNoError)
+    return gpu::Buffer();
+
+  int32 new_id = channel_->ReserveTransferBufferId();
+  DCHECK(transfer_buffers_.find(new_id) == transfer_buffers_.end());
+
+  scoped_ptr<base::SharedMemory> shared_memory(
       channel_->factory()->AllocateSharedMemory(size));
-  if (!shm.get())
-    return -1;
+  if (!shared_memory.get())
+    return gpu::Buffer();
 
-  base::SharedMemoryHandle handle = shm->handle();
-#if defined(OS_WIN)
-  // Windows needs to explicitly duplicate the handle out to another process.
-  if (!BrokerDuplicateHandle(handle, channel_->gpu_pid(), &handle,
-                             FILE_MAP_WRITE, 0)) {
-    return -1;
-  }
-#elif defined(OS_POSIX)
-  DCHECK(!handle.auto_close);
-#endif
+  DCHECK(!shared_memory->memory());
+  if (!shared_memory->Map(size))
+    return gpu::Buffer();
 
-  int32 id;
+  // This handle is owned by the GPU process and must be passed to it or it
+  // will leak. In otherwords, do not early out on error between here and the
+  // sending of the RegisterTransferBuffer IPC below.
+  base::SharedMemoryHandle handle =
+      channel_->ShareToGpuProcess(shared_memory.get());
+  if (!base::SharedMemory::IsHandleValid(handle))
+    return gpu::Buffer();
+
   if (!Send(new GpuCommandBufferMsg_RegisterTransferBuffer(route_id_,
+                                                           new_id,
                                                            handle,
-                                                           size,
-                                                           id_request,
-                                                           &id))) {
-    return -1;
+                                                           size))) {
+    return gpu::Buffer();
   }
 
-  return id;
-}
+  *id = new_id;
+  gpu::Buffer buffer;
+  buffer.ptr = shared_memory->memory();
+  buffer.size = size;
+  buffer.shared_memory = shared_memory.release();
+  transfer_buffers_[new_id] = buffer;
 
-int32 CommandBufferProxyImpl::RegisterTransferBuffer(
-    base::SharedMemory* shared_memory,
-    size_t size,
-    int32 id_request) {
-  if (last_state_.error != gpu::error::kNoError)
-    return -1;
-
-  // Returns FileDescriptor with auto_close off.
-  base::SharedMemoryHandle handle = shared_memory->handle();
-#if defined(OS_WIN)
-  // Windows needs to explicitly duplicate the handle out to another process.
-  if (!BrokerDuplicateHandle(handle, channel_->gpu_pid(), &handle,
-                             FILE_MAP_WRITE, 0)) {
-    return -1;
-  }
-#endif
-
-  int32 id;
-  if (!Send(new GpuCommandBufferMsg_RegisterTransferBuffer(
-      route_id_,
-      handle,
-      size,
-      id_request,
-      &id))) {
-    return -1;
-  }
-
-  return id;
+  return buffer;
 }
 
 void CommandBufferProxyImpl::DestroyTransferBuffer(int32 id) {
@@ -327,9 +289,9 @@
   Send(new GpuCommandBufferMsg_DestroyTransferBuffer(route_id_, id));
 }
 
-Buffer CommandBufferProxyImpl::GetTransferBuffer(int32 id) {
+gpu::Buffer CommandBufferProxyImpl::GetTransferBuffer(int32 id) {
   if (last_state_.error != gpu::error::kNoError)
-    return Buffer();
+    return gpu::Buffer();
 
   // Check local cache to see if there is already a client side shared memory
   // object for this id.
@@ -346,24 +308,23 @@
                                                       id,
                                                       &handle,
                                                       &size))) {
-    return Buffer();
+    return gpu::Buffer();
   }
 
   // Cache the transfer buffer shared memory object client side.
-  base::SharedMemory* shared_memory = new base::SharedMemory(handle, false);
+  scoped_ptr<base::SharedMemory> shared_memory(
+      new base::SharedMemory(handle, false));
 
   // Map the shared memory on demand.
   if (!shared_memory->memory()) {
-    if (!shared_memory->Map(size)) {
-      delete shared_memory;
-      return Buffer();
-    }
+    if (!shared_memory->Map(size))
+      return gpu::Buffer();
   }
 
-  Buffer buffer;
+  gpu::Buffer buffer;
   buffer.ptr = shared_memory->memory();
   buffer.size = size;
-  buffer.shared_memory = shared_memory;
+  buffer.shared_memory = shared_memory.release();
   transfer_buffers_[id] = buffer;
 
   return buffer;
@@ -374,13 +335,6 @@
   NOTREACHED();
 }
 
-void CommandBufferProxyImpl::OnNotifyRepaint() {
-  if (!notify_repaint_task_.is_null())
-    MessageLoop::current()->PostNonNestableTask(
-        FROM_HERE, notify_repaint_task_);
-  notify_repaint_task_.Reset();
-}
-
 void CommandBufferProxyImpl::SetParseError(
     gpu::error::Error error) {
   // Not implemented in proxy.
@@ -496,10 +450,6 @@
   return result;
 }
 
-void CommandBufferProxyImpl::SetNotifyRepaintTask(const base::Closure& task) {
-  notify_repaint_task_ = task;
-}
-
 GpuVideoDecodeAcceleratorHost*
 CommandBufferProxyImpl::CreateVideoDecoder(
     media::VideoCodecProfile profile,
@@ -568,7 +518,7 @@
 
 void CommandBufferProxyImpl::TryUpdateState() {
   if (last_state_.error == gpu::error::kNoError)
-    shared_state_->Read(&last_state_);
+    shared_state()->Read(&last_state_);
 }
 
 void CommandBufferProxyImpl::SendManagedMemoryStats(
diff --git a/content/common/gpu/client/command_buffer_proxy_impl.h b/content/common/gpu/client/command_buffer_proxy_impl.h
index 73f53a7..ffbf9b6 100644
--- a/content/common/gpu/client/command_buffer_proxy_impl.h
+++ b/content/common/gpu/client/command_buffer_proxy_impl.h
@@ -76,12 +76,10 @@
   virtual State FlushSync(int32 put_offset, int32 last_known_get) OVERRIDE;
   virtual void SetGetBuffer(int32 shm_id) OVERRIDE;
   virtual void SetGetOffset(int32 get_offset) OVERRIDE;
-  virtual int32 CreateTransferBuffer(size_t size, int32 id_request) OVERRIDE;
-  virtual int32 RegisterTransferBuffer(base::SharedMemory* shared_memory,
-                                       size_t size,
-                                       int32 id_request) OVERRIDE;
+  virtual gpu::Buffer CreateTransferBuffer(size_t size,
+                                           int32* id) OVERRIDE;
   virtual void DestroyTransferBuffer(int32 id) OVERRIDE;
-  virtual gpu::Buffer GetTransferBuffer(int32 handle) OVERRIDE;
+  virtual gpu::Buffer GetTransferBuffer(int32 id) OVERRIDE;
   virtual void SetToken(int32 token) OVERRIDE;
   virtual void SetParseError(gpu::error::Error error) OVERRIDE;
   virtual void SetContextLostReason(
@@ -116,10 +114,6 @@
   // a finish.
   bool GenerateMailboxNames(unsigned num, std::vector<std::string>* names);
 
-  // Set a task that will be invoked the next time the window becomes invalid
-  // and needs to be repainted. Takes ownership of task.
-  void SetNotifyRepaintTask(const base::Closure& callback);
-
   // Sends an IPC message with the new state of surface visibility.
   bool SetSurfaceVisible(bool visible);
 
@@ -148,7 +142,6 @@
 
   // Message handlers:
   void OnUpdateState(const gpu::CommandBuffer::State& state);
-  void OnNotifyRepaint();
   void OnDestroyed(gpu::error::ContextLostReason reason);
   void OnEchoAck();
   void OnConsoleMessage(const GPUCommandBufferConsoleMessage& message);
@@ -159,6 +152,12 @@
   // Try to read an updated copy of the state from shared memory.
   void TryUpdateState();
 
+  // The shared memory area used to update state.
+  gpu::CommandBufferSharedState* shared_state() const {
+    return reinterpret_cast<gpu::CommandBufferSharedState*>(
+        shared_state_shm_->memory());
+  }
+
   // Local cache of id to transfer buffer mapping.
   TransferBufferMap transfer_buffers_;
 
@@ -170,7 +169,7 @@
   State last_state_;
 
   // The shared memory area used to update state.
-  gpu::CommandBufferSharedState* shared_state_;
+  scoped_ptr<base::SharedMemory> shared_state_shm_;
 
   // |*this| is owned by |*channel_| and so is always outlived by it, so using a
   // raw pointer is ok.
@@ -182,8 +181,6 @@
   // Tasks to be invoked in echo responses.
   std::queue<base::Closure> echo_tasks_;
 
-  base::Closure notify_repaint_task_;
-
   base::Closure channel_error_callback_;
 
   base::Callback<void(const GpuMemoryAllocationForRenderer&)>
@@ -195,9 +192,6 @@
   uint32 next_signal_id_;
   SignalTaskMap signal_tasks_;
 
-  // ID of transfer buffer containing shared state.
-  int32 state_buffer_;
-
   DISALLOW_COPY_AND_ASSIGN(CommandBufferProxyImpl);
 };
 
diff --git a/content/common/gpu/client/gpu_channel_host.cc b/content/common/gpu/client/gpu_channel_host.cc
index cb209093..4f9f604 100644
--- a/content/common/gpu/client/gpu_channel_host.cc
+++ b/content/common/gpu/client/gpu_channel_host.cc
@@ -14,6 +14,10 @@
 #include "googleurl/src/gurl.h"
 #include "ipc/ipc_sync_message_filter.h"
 
+#if defined(OS_WIN)
+#include "content/public/common/sandbox_init.h"
+#endif
+
 using base::AutoLock;
 using base::MessageLoopProxy;
 
@@ -29,6 +33,7 @@
       client_id_(client_id),
       gpu_host_id_(gpu_host_id),
       state_(kUnconnected) {
+  next_transfer_buffer_id_.GetNext();
 }
 
 void GpuChannelHost::Connect(
@@ -254,6 +259,31 @@
                                channel_filter_.get(), route_id));
 }
 
+base::SharedMemoryHandle GpuChannelHost::ShareToGpuProcess(
+    base::SharedMemory* shared_memory) {
+  AutoLock lock(context_lock_);
+
+  if (!channel_.get())
+    return base::SharedMemory::NULLHandle();
+
+  base::SharedMemoryHandle handle;
+#if defined(OS_WIN)
+  // Windows needs to explicitly duplicate the handle out to another process.
+  if (!BrokerDuplicateHandle(shared_memory->handle(),
+                             channel_->peer_pid(),
+                             &handle,
+                             FILE_MAP_WRITE,
+                             0)) {
+    return base::SharedMemory::NULLHandle();
+  }
+#else
+  if (!shared_memory->ShareToProcess(channel_->peer_pid(), &handle))
+    return base::SharedMemory::NULLHandle();
+#endif
+
+  return handle;
+}
+
 bool GpuChannelHost::GenerateMailboxNames(unsigned num,
                                           std::vector<std::string>* names) {
   TRACE_EVENT0("gpu", "GenerateMailboxName");
@@ -289,6 +319,10 @@
                             names.end());
 }
 
+int32 GpuChannelHost::ReserveTransferBufferId() {
+  return next_transfer_buffer_id_.GetNext();
+}
+
 GpuChannelHost::~GpuChannelHost() {}
 
 
diff --git a/content/common/gpu/client/gpu_channel_host.h b/content/common/gpu/client/gpu_channel_host.h
index ab5b7a9e..6f433af 100644
--- a/content/common/gpu/client/gpu_channel_host.h
+++ b/content/common/gpu/client/gpu_channel_host.h
@@ -8,6 +8,7 @@
 #include <string>
 #include <vector>
 
+#include "base/atomic_sequence_num.h"
 #include "base/hash_tables.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
@@ -150,15 +151,29 @@
 
   GpuChannelHostFactory* factory() const { return factory_; }
   int gpu_host_id() const { return gpu_host_id_; }
+
+  // Do not use this function! It does not take the context lock and even
+  // if it did the PID might become invalid immediately after releasing it
+  // TODO(apatrick): Make all callers use ShareToGpuProcess().
   base::ProcessId gpu_pid() const { return channel_->peer_pid(); }
+
   int client_id() const { return client_id_; }
 
+  // Returns a handle to the shared memory that can be sent via IPC to the
+  // GPU process. The caller is responsible for ensuring it is closed. Returns
+  // an invalid handle on failure.
+  base::SharedMemoryHandle ShareToGpuProcess(
+      base::SharedMemory* shared_memory);
+
   // Generates n unique mailbox names that can be used with
   // GL_texture_mailbox_CHROMIUM. Unlike genMailboxCHROMIUM, this IPC is
   // handled only on the GPU process' IO thread, and so is not effectively
   // a finish.
   bool GenerateMailboxNames(unsigned num, std::vector<std::string>* names);
 
+  // Reserve one unused transfer buffer ID.
+  int32 ReserveTransferBufferId();
+
  private:
   friend class base::RefCountedThreadSafe<GpuChannelHost>;
   virtual ~GpuChannelHost();
@@ -215,6 +230,9 @@
   // A pool of valid mailbox names.
   std::vector<std::string> mailbox_name_pool_;
 
+  // Transfer buffer IDs are allocated in sequence.
+  base::AtomicSequenceNumber next_transfer_buffer_id_;
+
   DISALLOW_COPY_AND_ASSIGN(GpuChannelHost);
 };
 
diff --git a/content/common/gpu/gpu_command_buffer_stub.cc b/content/common/gpu/gpu_command_buffer_stub.cc
index b8b792a0..0eadd90 100644
--- a/content/common/gpu/gpu_command_buffer_stub.cc
+++ b/content/common/gpu/gpu_command_buffer_stub.cc
@@ -173,8 +173,6 @@
                                     OnInitialize);
     IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_SetGetBuffer,
                                     OnSetGetBuffer);
-    IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_SetSharedStateBuffer,
-                                    OnSetSharedStateBuffer);
     IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_SetParent,
                                     OnSetParent);
     IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_Echo, OnEcho);
@@ -183,12 +181,10 @@
                                     OnGetStateFast);
     IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_AsyncFlush, OnAsyncFlush);
     IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_Rescheduled, OnRescheduled);
-    IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_CreateTransferBuffer,
-                                    OnCreateTransferBuffer);
-    IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_RegisterTransferBuffer,
-                                    OnRegisterTransferBuffer);
-    IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_DestroyTransferBuffer,
-                                    OnDestroyTransferBuffer);
+    IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_RegisterTransferBuffer,
+                        OnRegisterTransferBuffer);
+    IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_DestroyTransferBuffer,
+                        OnDestroyTransferBuffer);
     IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_GetTransferBuffer,
                                     OnGetTransferBuffer);
     IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_CreateVideoDecoder,
@@ -353,10 +349,14 @@
 }
 
 void GpuCommandBufferStub::OnInitialize(
+    base::SharedMemoryHandle shared_state_handle,
     IPC::Message* reply_message) {
   TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnInitialize");
   DCHECK(!command_buffer_.get());
 
+  scoped_ptr<base::SharedMemory> shared_state_shm(
+      new base::SharedMemory(shared_state_handle, false));
+
   command_buffer_.reset(new gpu::CommandBufferService(
       context_group_->transfer_buffer_manager()));
 
@@ -510,6 +510,12 @@
     parent_texture_for_initialization_ = 0;
   }
 
+  if (!command_buffer_->SetSharedStateBuffer(shared_state_shm.Pass())) {
+    DLOG(ERROR) << "Failed to map shared stae buffer.";
+    OnInitializeFailed(reply_message);
+    return;
+  }
+
   GpuCommandBufferMsg_Initialize::WriteReplyParams(reply_message, true);
   Send(reply_message);
 
@@ -520,27 +526,11 @@
   }
 }
 
-void GpuCommandBufferStub::OnSetGetBuffer(
-    int32 shm_id, IPC::Message* reply_message) {
+void GpuCommandBufferStub::OnSetGetBuffer(int32 shm_id,
+                                          IPC::Message* reply_message) {
   TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnSetGetBuffer");
-  if (command_buffer_.get()) {
+  if (command_buffer_.get())
     command_buffer_->SetGetBuffer(shm_id);
-  } else {
-    DLOG(ERROR) << "no command_buffer.";
-    reply_message->set_reply_error();
-  }
-  Send(reply_message);
-}
-
-void GpuCommandBufferStub::OnSetSharedStateBuffer(
-    int32 shm_id, IPC::Message* reply_message) {
-  TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnSetSharedStateBuffer");
-  if (command_buffer_.get()) {
-    command_buffer_->SetSharedStateBuffer(shm_id);
-  } else {
-    DLOG(ERROR) << "no command_buffer.";
-    reply_message->set_reply_error();
-  }
   Send(reply_message);
 }
 
@@ -641,51 +631,22 @@
     ReportState();
 }
 
-void GpuCommandBufferStub::OnCreateTransferBuffer(uint32 size,
-                                                  int32 id_request,
-                                                  IPC::Message* reply_message) {
-  TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnCreateTransferBuffer");
-  if (command_buffer_.get()) {
-    int32 id = command_buffer_->CreateTransferBuffer(size, id_request);
-    GpuCommandBufferMsg_CreateTransferBuffer::WriteReplyParams(
-        reply_message, id);
-  } else {
-    reply_message->set_reply_error();
-  }
-  Send(reply_message);
-}
-
 void GpuCommandBufferStub::OnRegisterTransferBuffer(
+    int32 id,
     base::SharedMemoryHandle transfer_buffer,
-    uint32 size,
-    int32 id_request,
-    IPC::Message* reply_message) {
+    uint32 size) {
   TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnRegisterTransferBuffer");
   base::SharedMemory shared_memory(transfer_buffer, false);
 
-  if (command_buffer_.get()) {
-    int32 id = command_buffer_->RegisterTransferBuffer(&shared_memory,
-                                                       size,
-                                                       id_request);
-    GpuCommandBufferMsg_RegisterTransferBuffer::WriteReplyParams(reply_message,
-                                                                 id);
-  } else {
-    reply_message->set_reply_error();
-  }
-
-  Send(reply_message);
+  if (command_buffer_.get())
+    command_buffer_->RegisterTransferBuffer(id, &shared_memory, size);
 }
 
-void GpuCommandBufferStub::OnDestroyTransferBuffer(
-    int32 id,
-    IPC::Message* reply_message) {
+void GpuCommandBufferStub::OnDestroyTransferBuffer(int32 id) {
   TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnDestroyTransferBuffer");
-  if (command_buffer_.get()) {
+
+  if (command_buffer_.get())
     command_buffer_->DestroyTransferBuffer(id);
-  } else {
-    reply_message->set_reply_error();
-  }
-  Send(reply_message);
 }
 
 void GpuCommandBufferStub::OnGetTransferBuffer(
diff --git a/content/common/gpu/gpu_command_buffer_stub.h b/content/common/gpu/gpu_command_buffer_stub.h
index 0519e8c7..d7c4ea2 100644
--- a/content/common/gpu/gpu_command_buffer_stub.h
+++ b/content/common/gpu/gpu_command_buffer_stub.h
@@ -141,9 +141,9 @@
   void OnInitializeFailed(IPC::Message* reply_message);
 
   // Message handlers:
-  void OnInitialize(IPC::Message* reply_message);
+  void OnInitialize(base::SharedMemoryHandle shared_state_shm,
+                    IPC::Message* reply_message);
   void OnSetGetBuffer(int32 shm_id, IPC::Message* reply_message);
-  void OnSetSharedStateBuffer(int32 shm_id, IPC::Message* reply_message);
   void OnSetParent(int32 parent_route_id,
                    uint32 parent_texture_id,
                    IPC::Message* reply_message);
@@ -152,14 +152,10 @@
   void OnAsyncFlush(int32 put_offset, uint32 flush_count);
   void OnEcho(const IPC::Message& message);
   void OnRescheduled();
-  void OnCreateTransferBuffer(uint32 size,
-                              int32 id_request,
-                              IPC::Message* reply_message);
-  void OnRegisterTransferBuffer(base::SharedMemoryHandle transfer_buffer,
-                                uint32 size,
-                                int32 id_request,
-                                IPC::Message* reply_message);
-  void OnDestroyTransferBuffer(int32 id, IPC::Message* reply_message);
+  void OnRegisterTransferBuffer(int32 id,
+                                base::SharedMemoryHandle transfer_buffer,
+                                uint32 size);
+  void OnDestroyTransferBuffer(int32 id);
   void OnGetTransferBuffer(int32 id, IPC::Message* reply_message);
 
   void OnCreateVideoDecoder(
diff --git a/content/common/gpu/gpu_messages.h b/content/common/gpu/gpu_messages.h
index 35f815035..fc1cc03d 100644
--- a/content/common/gpu/gpu_messages.h
+++ b/content/common/gpu/gpu_messages.h
@@ -478,14 +478,10 @@
 // Initialize a command buffer with the given number of command entries.
 // Returns the shared memory handle for the command buffer mapped to the
 // calling process.
-IPC_SYNC_MESSAGE_ROUTED0_1(GpuCommandBufferMsg_Initialize,
+IPC_SYNC_MESSAGE_ROUTED1_1(GpuCommandBufferMsg_Initialize,
+                           base::SharedMemoryHandle /* shared_state */,
                            bool /* result */)
 
-// Sets the shared memory buffer used to hold the CommandBufferSharedState,
-// used to transmit the current state.
-IPC_SYNC_MESSAGE_ROUTED1_0(GpuCommandBufferMsg_SetSharedStateBuffer,
-                           int32 /* shm_id */)
-
 // Sets the shared memory buffer used for commands.
 IPC_SYNC_MESSAGE_ROUTED1_0(GpuCommandBufferMsg_SetGetBuffer,
                            int32 /* shm_id */)
@@ -522,24 +518,16 @@
 IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_ConsoleMsg,
                     GPUCommandBufferConsoleMessage /* msg */)
 
-// Create a shared memory transfer buffer. Returns an id that can be used to
-// identify the transfer buffer from a comment.
-IPC_SYNC_MESSAGE_ROUTED2_1(GpuCommandBufferMsg_CreateTransferBuffer,
-                           uint32 /* size */,
-                           int32 /* id_request (-1 means any) */,
-                           int32 /* id */)
-
 // Register an existing shared memory transfer buffer. Returns an id that can be
 // used to identify the transfer buffer from a command buffer.
-IPC_SYNC_MESSAGE_ROUTED3_1(GpuCommandBufferMsg_RegisterTransferBuffer,
-                           base::SharedMemoryHandle /* transfer_buffer */,
-                           uint32 /* size */,
-                           int32 /* id_request (-1 means any) */,
-                           int32 /* id */)
+IPC_MESSAGE_ROUTED3(GpuCommandBufferMsg_RegisterTransferBuffer,
+                    int32 /* id */,
+                    base::SharedMemoryHandle /* transfer_buffer */,
+                    uint32 /* size */)
 
 // Destroy a previously created transfer buffer.
-IPC_SYNC_MESSAGE_ROUTED1_0(GpuCommandBufferMsg_DestroyTransferBuffer,
-                           int32 /* id */)
+IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_DestroyTransferBuffer,
+                    int32 /* id */)
 
 // Get the shared memory handle for a transfer buffer mapped to the callers
 // process.
@@ -557,10 +545,6 @@
 IPC_SYNC_MESSAGE_ROUTED1_0(GpuCommandBufferMsg_DestroyVideoDecoder,
                            int /* route_id */)
 
-// Send from command buffer stub to proxy when window is invalid and must be
-// repainted.
-IPC_MESSAGE_ROUTED0(GpuCommandBufferMsg_NotifyRepaint)
-
 // Tells the GPU process to resize an offscreen frame buffer.
 IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_ResizeOffscreenFrameBuffer,
                     gfx::Size /* size */)
diff --git a/gpu/command_buffer/client/client_test_helper.cc b/gpu/command_buffer/client/client_test_helper.cc
index d9942ef..92af99d 100644
--- a/gpu/command_buffer/client/client_test_helper.cc
+++ b/gpu/command_buffer/client/client_test_helper.cc
@@ -60,16 +60,15 @@
   return -1;
 }
 
-int32 MockCommandBufferBase::CreateTransferBuffer(
-    size_t size, int32 id_request) {
-  int32 id = GetNextFreeTransferBufferId();
-  if (id >= 0) {
-    int32 ndx = id - kTransferBufferBaseId;
+Buffer MockCommandBufferBase::CreateTransferBuffer(size_t size, int32* id) {
+  *id = GetNextFreeTransferBufferId();
+  if (*id >= 0) {
+    int32 ndx = *id - kTransferBufferBaseId;
     transfer_buffers_[ndx].reset(new int8[size]);
     transfer_buffer_buffers_[ndx].ptr = transfer_buffers_[ndx].get();
     transfer_buffer_buffers_[ndx].size = size;
   }
-  return id;
+  return GetTransferBuffer(*id);
 }
 
 void MockCommandBufferBase::DestroyTransferBufferHelper(int32 id) {
@@ -86,14 +85,6 @@
   return transfer_buffer_buffers_[id - kTransferBufferBaseId];
 }
 
-int32 MockCommandBufferBase::RegisterTransferBuffer(
-    base::SharedMemory* shared_memory,
-    size_t size,
-    int32 id_request) {
-  GPU_NOTREACHED();
-  return -1;
-}
-
 void MockCommandBufferBase::FlushHelper(int32 put_offset) {
   state_.put_offset = put_offset;
 }
diff --git a/gpu/command_buffer/client/client_test_helper.h b/gpu/command_buffer/client/client_test_helper.h
index 25d1014..3302b47 100644
--- a/gpu/command_buffer/client/client_test_helper.h
+++ b/gpu/command_buffer/client/client_test_helper.h
@@ -32,11 +32,8 @@
   virtual State FlushSync(int32 put_offset, int32 last_known_get) OVERRIDE;
   virtual void SetGetBuffer(int transfer_buffer_id) OVERRIDE;
   virtual void SetGetOffset(int32 get_offset) OVERRIDE;
-  virtual int32 CreateTransferBuffer(size_t size, int32 id_request) OVERRIDE;
+  virtual Buffer CreateTransferBuffer(size_t size, int32* id) OVERRIDE;
   virtual Buffer GetTransferBuffer(int32 id) OVERRIDE;
-  virtual int32 RegisterTransferBuffer(base::SharedMemory* shared_memory,
-                                       size_t size,
-                                       int32 id_request) OVERRIDE;
   virtual void SetToken(int32 token) OVERRIDE;
   virtual void SetParseError(error::Error error) OVERRIDE;
   virtual void SetContextLostReason(error::ContextLostReason reason) OVERRIDE;
diff --git a/gpu/command_buffer/client/cmd_buffer_helper.cc b/gpu/command_buffer/client/cmd_buffer_helper.cc
index f7d31c5..756abd5 100644
--- a/gpu/command_buffer/client/cmd_buffer_helper.cc
+++ b/gpu/command_buffer/client/cmd_buffer_helper.cc
@@ -52,18 +52,14 @@
     return true;
   }
 
-  int32 id = command_buffer_->CreateTransferBuffer(ring_buffer_size_, -1);
+  int32 id = -1;
+  Buffer buffer = command_buffer_->CreateTransferBuffer(ring_buffer_size_, &id);
   if (id < 0) {
     ClearUsable();
     return false;
   }
 
-  ring_buffer_ = command_buffer_->GetTransferBuffer(id);
-  if (!ring_buffer_.ptr) {
-    ClearUsable();
-    return false;
-  }
-
+  ring_buffer_ = buffer;
   ring_buffer_id_ = id;
   command_buffer_->SetGetBuffer(id);
 
diff --git a/gpu/command_buffer/client/fenced_allocator_test.cc b/gpu/command_buffer/client/fenced_allocator_test.cc
index 44fb851e..2c6cdc6 100644
--- a/gpu/command_buffer/client/fenced_allocator_test.cc
+++ b/gpu/command_buffer/client/fenced_allocator_test.cc
@@ -52,7 +52,7 @@
     }
     command_buffer_.reset(
         new CommandBufferService(transfer_buffer_manager_.get()));
-    command_buffer_->Initialize();
+    EXPECT_TRUE(command_buffer_->Initialize());
 
     gpu_scheduler_.reset(new GpuScheduler(
         command_buffer_.get(), api_mock_.get(), NULL));
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc
index 581981e1..6176525 100644
--- a/gpu/command_buffer/client/gles2_implementation_unittest.cc
+++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc
@@ -103,10 +103,10 @@
     // we need to know their address before GLES2Implementation::Initialize
     // is called.
     for (int ii = 0; ii < kNumBuffers; ++ii) {
-      buffer_ids_[ii] = command_buffer_->CreateTransferBuffer(
-          size_ + ii * alignment_, -1);
+      buffers_[ii] = command_buffer_->CreateTransferBuffer(
+          size_ + ii * alignment_,
+          &buffer_ids_[ii]);
       EXPECT_NE(-1, buffer_ids_[ii]);
-      buffers_[ii] = command_buffer_->GetTransferBuffer(buffer_ids_[ii]);
     }
   }
 
diff --git a/gpu/command_buffer/client/mapped_memory.cc b/gpu/command_buffer/client/mapped_memory.cc
index c8d400e..5278fc8 100644
--- a/gpu/command_buffer/client/mapped_memory.cc
+++ b/gpu/command_buffer/client/mapped_memory.cc
@@ -56,11 +56,10 @@
   unsigned int chunk_size =
       ((size + chunk_size_multiple_ - 1) / chunk_size_multiple_) *
       chunk_size_multiple_;
-  int32 id = cmd_buf->CreateTransferBuffer(chunk_size, -1);
-  if (id == -1) {
+  int32 id = -1;
+  gpu::Buffer shm = cmd_buf->CreateTransferBuffer(chunk_size, &id);
+  if (id  < 0)
     return NULL;
-  }
-  gpu::Buffer shm = cmd_buf->GetTransferBuffer(id);
   MemoryChunk* mc = new MemoryChunk(id, shm, helper_);
   chunks_.push_back(mc);
   void* mem = mc->Alloc(size);
diff --git a/gpu/command_buffer/client/transfer_buffer.cc b/gpu/command_buffer/client/transfer_buffer.cc
index 7e0b25f..8348622 100644
--- a/gpu/command_buffer/client/transfer_buffer.cc
+++ b/gpu/command_buffer/client/transfer_buffer.cc
@@ -81,9 +81,11 @@
 
 void TransferBuffer::AllocateRingBuffer(unsigned int size) {
   for (;size >= min_buffer_size_; size /= 2) {
-    int32 id = helper_->command_buffer()->CreateTransferBuffer(size, -1);
+    int32 id = -1;
+    gpu::Buffer buffer =
+        helper_->command_buffer()->CreateTransferBuffer(size, &id);
     if (id != -1) {
-      buffer_ = helper_->command_buffer()->GetTransferBuffer(id);
+      buffer_ = buffer;
       ring_buffer_.reset(new AlignedRingBuffer(
           alignment_,
           id,
diff --git a/gpu/command_buffer/client/transfer_buffer_unittest.cc b/gpu/command_buffer/client/transfer_buffer_unittest.cc
index 469483b9..f40de23 100644
--- a/gpu/command_buffer/client/transfer_buffer_unittest.cc
+++ b/gpu/command_buffer/client/transfer_buffer_unittest.cc
@@ -16,6 +16,7 @@
 using ::testing::_;
 using ::testing::Invoke;
 using ::testing::Return;
+using ::testing::SetArgPointee;
 using ::testing::StrictMock;
 
 namespace gpu {
@@ -211,10 +212,10 @@
   virtual ~MockClientCommandBufferCanFail() {
   }
 
-  MOCK_METHOD2(CreateTransferBuffer, int32(size_t size, int32 id_request));
+  MOCK_METHOD2(CreateTransferBuffer, Buffer(size_t size, int32* id));
 
-  int32 RealCreateTransferBuffer(size_t size, int32 id_request) {
-    return MockCommandBufferBase::CreateTransferBuffer(size, id_request);
+  Buffer RealCreateTransferBuffer(size_t size, int32* id) {
+    return MockCommandBufferBase::CreateTransferBuffer(size, id);
   }
 };
 
@@ -372,7 +373,7 @@
   // Try to allocate again, fail first request
   EXPECT_CALL(*command_buffer(),
               CreateTransferBuffer(kStartTransferBufferSize, _))
-      .WillOnce(Return(-1))
+      .WillOnce(DoAll(SetArgPointee<1>(-1), Return(Buffer())))
       .RetiresOnSaturation();
   EXPECT_CALL(*command_buffer(),
               CreateTransferBuffer(kMinTransferBufferSize, _))
@@ -424,9 +425,9 @@
 
   // Try to allocate again, fail both requests.
   EXPECT_CALL(*command_buffer(), CreateTransferBuffer(_, _))
-      .WillOnce(Return(-1))
-      .WillOnce(Return(-1))
-      .WillOnce(Return(-1))
+      .WillOnce(DoAll(SetArgPointee<1>(-1), Return(Buffer())))
+      .WillOnce(DoAll(SetArgPointee<1>(-1), Return(Buffer())))
+      .WillOnce(DoAll(SetArgPointee<1>(-1), Return(Buffer())))
       .RetiresOnSaturation();
 
   const size_t kSize1 = 512 - kStartingOffset;
diff --git a/gpu/command_buffer/common/command_buffer.h b/gpu/command_buffer/common/command_buffer.h
index 6b19ea2..e100792a 100644
--- a/gpu/command_buffer/common/command_buffer.h
+++ b/gpu/command_buffer/common/command_buffer.h
@@ -101,28 +101,16 @@
   // Sets the current get offset. This can be called from any thread.
   virtual void SetGetOffset(int32 get_offset) = 0;
 
-  // Create a transfer buffer and return a handle that uniquely
-  // identifies it or -1 on error. id_request lets the caller request a
-  // specific id for the transfer buffer, or -1 if the caller does not care.
-  // If the requested id can not be fulfilled, a different id will be returned.
-  // id_request must be either -1 or between 0 and 100.
-  virtual int32 CreateTransferBuffer(size_t size, int32 id_request) = 0;
+  // Create a transfer buffer of the given size. Returns its ID or -1 on
+  // error.
+  virtual Buffer CreateTransferBuffer(size_t size, int32* id) = 0;
 
-  // Register an existing shared memory object and get an ID that can be used
-  // to identify it in the command buffer. Callee dups the handle until
-  // DestroyTransferBuffer is called. id_request lets the caller request a
-  // specific id for the transfer buffer, or -1 if the caller does not care.
-  // If the requested id can not be fulfilled, a different id will be returned.
-  // id_request must be either -1 or between 0 and 100.
-  virtual int32 RegisterTransferBuffer(base::SharedMemory* shared_memory,
-                                       size_t size,
-                                       int32 id_request) = 0;
-
-  // Destroy a transfer buffer and recycle the handle.
+  // Destroy a transfer buffer. The ID must be positive.
   virtual void DestroyTransferBuffer(int32 id) = 0;
 
-  // Get the transfer buffer associated with a handle.
-  virtual Buffer GetTransferBuffer(int32 handle) = 0;
+  // Get the transfer buffer associated with an ID. Returns a null buffer for
+  // ID 0.
+  virtual Buffer GetTransferBuffer(int32 id) = 0;
 
   // Allows the reader to update the current token value.
   virtual void SetToken(int32 token) = 0;
diff --git a/gpu/command_buffer/common/command_buffer_mock.h b/gpu/command_buffer/common/command_buffer_mock.h
index 0379340..b2ee11f 100644
--- a/gpu/command_buffer/common/command_buffer_mock.h
+++ b/gpu/command_buffer/common/command_buffer_mock.h
@@ -28,12 +28,9 @@
   MOCK_METHOD2(FlushSync, State(int32 put_offset, int32 last_known_get));
   MOCK_METHOD1(SetGetBuffer, void(int32 transfer_buffer_id));
   MOCK_METHOD1(SetGetOffset, void(int32 get_offset));
-  MOCK_METHOD2(CreateTransferBuffer, int32(size_t size, int32 id_request));
-  MOCK_METHOD1(DestroyTransferBuffer, void(int32 handle));
-  MOCK_METHOD1(GetTransferBuffer, Buffer(int32 handle));
-  MOCK_METHOD3(RegisterTransferBuffer, int32(base::SharedMemory* shared_memory,
-                                             size_t size,
-                                             int32 id_request));
+  MOCK_METHOD2(CreateTransferBuffer, Buffer(size_t size, int32* id));
+  MOCK_METHOD1(DestroyTransferBuffer, void(int32 id));
+  MOCK_METHOD1(GetTransferBuffer, Buffer(int32 id));
   MOCK_METHOD1(SetToken, void(int32 token));
   MOCK_METHOD1(SetParseError, void(error::Error error));
   MOCK_METHOD1(SetContextLostReason,
diff --git a/gpu/command_buffer/service/command_buffer_service.cc b/gpu/command_buffer/service/command_buffer_service.cc
index 8b00595..cd9d4e1 100644
--- a/gpu/command_buffer/service/command_buffer_service.cc
+++ b/gpu/command_buffer/service/command_buffer_service.cc
@@ -104,11 +104,17 @@
   UpdateState();
 }
 
-void CommandBufferService::SetSharedStateBuffer(int32 transfer_buffer_id) {
-  gpu::Buffer buffer = GetTransferBuffer(transfer_buffer_id);
-  shared_state_ = reinterpret_cast<CommandBufferSharedState*>(buffer.ptr);
+bool CommandBufferService::SetSharedStateBuffer(
+    scoped_ptr<base::SharedMemory> shared_state_shm) {
+  shared_state_shm_.reset(shared_state_shm.release());
+  if (!shared_state_shm_->Map(sizeof(*shared_state_)))
+    return false;
+
+  shared_state_ =
+      static_cast<CommandBufferSharedState*>(shared_state_shm_->memory());
 
   UpdateState();
+  return true;
 }
 
 void CommandBufferService::SetGetOffset(int32 get_offset) {
@@ -116,20 +122,26 @@
   get_offset_ = get_offset;
 }
 
-int32 CommandBufferService::CreateTransferBuffer(size_t size,
-                                                 int32 id_request) {
-  return transfer_buffer_manager_->CreateTransferBuffer(size, id_request);
+Buffer CommandBufferService::CreateTransferBuffer(size_t size,
+                                                  int32* id) {
+  *id = -1;
+
+  SharedMemory buffer;
+  if (!buffer.CreateAnonymous(size))
+    return Buffer();
+
+  static int32 next_id = 1;
+  *id = next_id++;
+
+  if (!RegisterTransferBuffer(*id, &buffer, size))
+    return Buffer();
+
+  return GetTransferBuffer(*id);
 }
 
-int32 CommandBufferService::RegisterTransferBuffer(
-    base::SharedMemory* shared_memory, size_t size, int32 id_request) {
-  return transfer_buffer_manager_->RegisterTransferBuffer(
-      shared_memory, size, id_request);
-}
-
-void CommandBufferService::DestroyTransferBuffer(int32 handle) {
-  transfer_buffer_manager_->DestroyTransferBuffer(handle);
-  if (handle == ring_buffer_id_) {
+void CommandBufferService::DestroyTransferBuffer(int32 id) {
+  transfer_buffer_manager_->DestroyTransferBuffer(id);
+  if (id == ring_buffer_id_) {
     ring_buffer_id_ = -1;
     ring_buffer_ = Buffer();
     num_entries_ = 0;
@@ -138,8 +150,17 @@
   }
 }
 
-Buffer CommandBufferService::GetTransferBuffer(int32 handle) {
-  return transfer_buffer_manager_->GetTransferBuffer(handle);
+Buffer CommandBufferService::GetTransferBuffer(int32 id) {
+  return transfer_buffer_manager_->GetTransferBuffer(id);
+}
+
+bool CommandBufferService::RegisterTransferBuffer(
+    int32 id,
+    base::SharedMemory* shared_memory,
+    size_t size) {
+  return transfer_buffer_manager_->RegisterTransferBuffer(id,
+                                                          shared_memory,
+                                                          size);
 }
 
 void CommandBufferService::SetToken(int32 token) {
diff --git a/gpu/command_buffer/service/command_buffer_service.h b/gpu/command_buffer/service/command_buffer_service.h
index c3bb8413..1b333f3 100644
--- a/gpu/command_buffer/service/command_buffer_service.h
+++ b/gpu/command_buffer/service/command_buffer_service.h
@@ -31,12 +31,9 @@
   virtual State FlushSync(int32 put_offset, int32 last_known_get) OVERRIDE;
   virtual void SetGetBuffer(int32 transfer_buffer_id) OVERRIDE;
   virtual void SetGetOffset(int32 get_offset) OVERRIDE;
-  virtual int32 CreateTransferBuffer(size_t size, int32 id_request) OVERRIDE;
-  virtual int32 RegisterTransferBuffer(base::SharedMemory* shared_memory,
-                                       size_t size,
-                                       int32 id_request) OVERRIDE;
+  virtual Buffer CreateTransferBuffer(size_t size, int32* id) OVERRIDE;
   virtual void DestroyTransferBuffer(int32 id) OVERRIDE;
-  virtual Buffer GetTransferBuffer(int32 handle) OVERRIDE;
+  virtual Buffer GetTransferBuffer(int32 id) OVERRIDE;
   virtual void SetToken(int32 token) OVERRIDE;
   virtual void SetParseError(error::Error error) OVERRIDE;
   virtual void SetContextLostReason(error::ContextLostReason) OVERRIDE;
@@ -55,15 +52,23 @@
       const GetBufferChangedCallback& callback);
   virtual void SetParseErrorCallback(const base::Closure& callback);
 
-  // Setup the transfer buffer that shared state should be copied into.
-  void SetSharedStateBuffer(int32 transfer_buffer_id);
+  // Setup the shared memory that shared state should be copied into.
+  bool SetSharedStateBuffer(scoped_ptr<base::SharedMemory> shared_state_shm);
 
   // Copy the current state into the shared state transfer buffer.
   void UpdateState();
 
+  // Register an existing shared memory object and get an ID that can be used
+  // to identify it in the command buffer. Callee dups the handle until
+  // DestroyTransferBuffer is called.
+  bool RegisterTransferBuffer(int32 id,
+                              base::SharedMemory* shared_memory,
+                              size_t size);
+
  private:
   int32 ring_buffer_id_;
   Buffer ring_buffer_;
+  scoped_ptr<base::SharedMemory> shared_state_shm_;
   CommandBufferSharedState* shared_state_;
   int32 num_entries_;
   int32 get_offset_;
diff --git a/gpu/command_buffer/service/command_buffer_service_unittest.cc b/gpu/command_buffer/service/command_buffer_service_unittest.cc
index 2c9093b..bf4d619f 100644
--- a/gpu/command_buffer/service/command_buffer_service_unittest.cc
+++ b/gpu/command_buffer/service/command_buffer_service_unittest.cc
@@ -50,7 +50,8 @@
   }
 
   bool Initialize(size_t size) {
-    int32 id = command_buffer_->CreateTransferBuffer(size, -1);
+    int32 id;
+    command_buffer_->CreateTransferBuffer(size, &id);
     EXPECT_GT(id, 0);
     command_buffer_->SetGetBuffer(id);
     return true;
@@ -117,7 +118,8 @@
 }
 
 TEST_F(CommandBufferServiceTest, SetGetBuffer) {
-  int32 ring_buffer_id = command_buffer_->CreateTransferBuffer(1024, -1);
+  int32 ring_buffer_id;
+  command_buffer_->CreateTransferBuffer(1024, &ring_buffer_id);
   EXPECT_GT(ring_buffer_id, 0);
 
   scoped_ptr<StrictMock<MockCallbackTest> > change_callback(
diff --git a/gpu/command_buffer/service/transfer_buffer_manager.cc b/gpu/command_buffer/service/transfer_buffer_manager.cc
index 7bde12ab..12c9fb14 100644
--- a/gpu/command_buffer/service/transfer_buffer_manager.cc
+++ b/gpu/command_buffer/service/transfer_buffer_manager.cc
@@ -8,6 +8,7 @@
 
 #include "base/process_util.h"
 #include "base/debug/trace_event.h"
+#include "gpu/command_buffer/common/gles2_cmd_utils.h"
 
 using ::base::SharedMemory;
 
@@ -18,17 +19,15 @@
 
 TransferBufferManager::TransferBufferManager()
     : shared_memory_bytes_allocated_(0) {
-  // Element zero is always NULL.
-  registered_objects_.push_back(Buffer());
 }
 
 TransferBufferManager::~TransferBufferManager() {
-  for (size_t i = 0; i < registered_objects_.size(); ++i) {
-    if (registered_objects_[i].shared_memory) {
-      DCHECK(shared_memory_bytes_allocated_ >= registered_objects_[i].size);
-      shared_memory_bytes_allocated_ -= registered_objects_[i].size;
-      delete registered_objects_[i].shared_memory;
-    }
+  while (!registered_buffers_.empty()) {
+    BufferMap::iterator it = registered_buffers_.begin();
+    DCHECK(shared_memory_bytes_allocated_ >= it->second.size);
+    shared_memory_bytes_allocated_ -= it->second.size;
+    delete it->second.shared_memory;
+    registered_buffers_.erase(it);
   }
   DCHECK(!shared_memory_bytes_allocated_);
 }
@@ -37,42 +36,38 @@
   return true;
 }
 
-int32 TransferBufferManager::CreateTransferBuffer(
-    size_t size, int32 id_request) {
-  SharedMemory buffer;
-  if (!buffer.CreateAnonymous(size))
-    return -1;
-
-  return RegisterTransferBuffer(&buffer, size, id_request);
-}
-
-int32 TransferBufferManager::RegisterTransferBuffer(
-    base::SharedMemory* shared_memory, size_t size, int32 id_request) {
-  // Check we haven't exceeded the range that fits in a 32-bit integer.
-  if (unused_registered_object_elements_.empty()) {
-    if (registered_objects_.size() > std::numeric_limits<uint32>::max())
-      return -1;
+bool TransferBufferManager::RegisterTransferBuffer(
+    int32 id,
+    base::SharedMemory* shared_memory,
+    size_t size) {
+  if (id <= 0) {
+    DVLOG(ERROR) << "Cannot register transfer buffer with non-positive ID.";
+    return false;
   }
 
-  // Check that the requested ID is sane (not too large, or less than -1)
-  if (id_request != -1 && (id_request > 100 || id_request < -1))
-    return -1;
+  // Fail if the ID is in use.
+  if (registered_buffers_.find(id) != registered_buffers_.end()) {
+    DVLOG(ERROR) << "Buffer ID already in use.";
+    return false;
+  }
 
   // Duplicate the handle.
   base::SharedMemoryHandle duped_shared_memory_handle;
   if (!shared_memory->ShareToProcess(base::GetCurrentProcessHandle(),
                                      &duped_shared_memory_handle)) {
-    return -1;
+    DVLOG(ERROR) << "Failed to duplicate shared memory handle.";
+    return false;
   }
   scoped_ptr<SharedMemory> duped_shared_memory(
       new SharedMemory(duped_shared_memory_handle, false));
 
   // Map the shared memory into this process. This validates the size.
-  if (!duped_shared_memory->Map(size))
-    return -1;
+  if (!duped_shared_memory->Map(size)) {
+    DVLOG(ERROR) << "Failed to map shared memory.";
+    return false;
+  }
 
-  // If it could be mapped, allocate an ID and register the shared memory with
-  // that ID.
+  // If it could be mapped register the shared memory with the ID.
   Buffer buffer;
   buffer.ptr = duped_shared_memory->memory();
   buffer.size = size;
@@ -82,73 +77,36 @@
   TRACE_COUNTER_ID1(
       "gpu", "GpuTransferBufferMemory", this, shared_memory_bytes_allocated_);
 
-  // If caller requested specific id, first try to use id_request.
-  if (id_request != -1) {
-    int32 cur_size = static_cast<int32>(registered_objects_.size());
-    if (cur_size <= id_request) {
-      // Pad registered_objects_ to reach id_request.
-      registered_objects_.resize(static_cast<size_t>(id_request + 1));
-      for (int32 id = cur_size; id < id_request; ++id)
-        unused_registered_object_elements_.insert(id);
-      registered_objects_[id_request] = buffer;
-      return id_request;
-    } else if (!registered_objects_[id_request].shared_memory) {
-      // id_request is already in free list.
-      registered_objects_[id_request] = buffer;
-      unused_registered_object_elements_.erase(id_request);
-      return id_request;
-    }
-  }
+  registered_buffers_[id] = buffer;
 
-  if (unused_registered_object_elements_.empty()) {
-    int32 handle = static_cast<int32>(registered_objects_.size());
-    registered_objects_.push_back(buffer);
-    return handle;
-  } else {
-    int32 handle = *unused_registered_object_elements_.begin();
-    unused_registered_object_elements_.erase(
-        unused_registered_object_elements_.begin());
-    DCHECK(!registered_objects_[handle].shared_memory);
-    registered_objects_[handle] = buffer;
-    return handle;
-  }
+  return true;
 }
 
-void TransferBufferManager::DestroyTransferBuffer(int32 handle) {
-  if (handle <= 0)
+void TransferBufferManager::DestroyTransferBuffer(int32 id) {
+  BufferMap::iterator it = registered_buffers_.find(id);
+  if (it == registered_buffers_.end()) {
+    DVLOG(ERROR) << "Transfer buffer ID was not registered.";
     return;
+  }
 
-  if (static_cast<size_t>(handle) >= registered_objects_.size())
-    return;
-
-  DCHECK(shared_memory_bytes_allocated_ >= registered_objects_[handle].size);
-  shared_memory_bytes_allocated_ -= registered_objects_[handle].size;
+  DCHECK(shared_memory_bytes_allocated_ >= it->second.size);
+  shared_memory_bytes_allocated_ -= it->second.size;
   TRACE_COUNTER_ID1(
       "CommandBuffer", "SharedMemory", this, shared_memory_bytes_allocated_);
 
-  delete registered_objects_[handle].shared_memory;
-  registered_objects_[handle] = Buffer();
-  unused_registered_object_elements_.insert(handle);
-
-  // Remove all null objects from the end of the vector. This allows the vector
-  // to shrink when, for example, all objects are unregistered. Note that this
-  // loop never removes element zero, which is always NULL.
-  while (registered_objects_.size() > 1 &&
-      !registered_objects_.back().shared_memory) {
-    registered_objects_.pop_back();
-    unused_registered_object_elements_.erase(
-        static_cast<int32>(registered_objects_.size()));
-  }
+  delete it->second.shared_memory;
+  registered_buffers_.erase(it);
 }
 
-Buffer TransferBufferManager::GetTransferBuffer(int32 handle) {
-  if (handle < 0)
+Buffer TransferBufferManager::GetTransferBuffer(int32 id) {
+  if (id == 0)
     return Buffer();
 
-  if (static_cast<size_t>(handle) >= registered_objects_.size())
+  BufferMap::iterator it = registered_buffers_.find(id);
+  if (it == registered_buffers_.end())
     return Buffer();
 
-  return registered_objects_[handle];
+  return it->second;
 }
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/transfer_buffer_manager.h b/gpu/command_buffer/service/transfer_buffer_manager.h
index 9f24e2cd..b50a5ae 100644
--- a/gpu/command_buffer/service/transfer_buffer_manager.h
+++ b/gpu/command_buffer/service/transfer_buffer_manager.h
@@ -10,6 +10,7 @@
 
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
+#include "base/hash_tables.h"
 #include "base/shared_memory.h"
 #include "gpu/command_buffer/common/command_buffer_shared.h"
 
@@ -19,13 +20,11 @@
  public:
   virtual ~TransferBufferManagerInterface();
 
-  virtual int32 CreateTransferBuffer(size_t size, int32 id_request) = 0;
-  virtual int32 RegisterTransferBuffer(
-      base::SharedMemory* shared_memory,
-      size_t size,
-      int32 id_request) = 0;
+  virtual bool RegisterTransferBuffer(int32 id,
+                                      base::SharedMemory* shared_memory,
+                                      size_t size) = 0;
   virtual void DestroyTransferBuffer(int32 id) = 0;
-  virtual Buffer GetTransferBuffer(int32 handle) = 0;
+  virtual Buffer GetTransferBuffer(int32 id) = 0;
 
 };
 
@@ -35,19 +34,17 @@
   TransferBufferManager();
 
   bool Initialize();
-  virtual int32 CreateTransferBuffer(size_t size, int32 id_request) OVERRIDE;
-  virtual int32 RegisterTransferBuffer(
-      base::SharedMemory* shared_memory,
-      size_t size,
-      int32 id_request) OVERRIDE;
+  virtual bool RegisterTransferBuffer(int32 id,
+                                      base::SharedMemory* shared_memory,
+                                      size_t size) OVERRIDE;
   virtual void DestroyTransferBuffer(int32 id) OVERRIDE;
-  virtual Buffer GetTransferBuffer(int32 handle) OVERRIDE;
+  virtual Buffer GetTransferBuffer(int32 id) OVERRIDE;
 
  private:
   virtual ~TransferBufferManager();
 
-  std::set<int32> unused_registered_object_elements_;
-  std::vector<Buffer> registered_objects_;
+  typedef base::hash_map<int32, Buffer> BufferMap;
+  BufferMap registered_buffers_;
   size_t shared_memory_bytes_allocated_;
 
   DISALLOW_COPY_AND_ASSIGN(TransferBufferManager);
diff --git a/gpu/command_buffer/service/transfer_buffer_manager_unittest.cc b/gpu/command_buffer/service/transfer_buffer_manager_unittest.cc
index 029cb0e..68c5c2ec 100644
--- a/gpu/command_buffer/service/transfer_buffer_manager_unittest.cc
+++ b/gpu/command_buffer/service/transfer_buffer_manager_unittest.cc
@@ -12,14 +12,22 @@
 
 namespace gpu {
 
+const static size_t kBufferSize = 1024;
+
 class TransferBufferManagerTest : public testing::Test {
  protected:
   virtual void SetUp() {
+    for (size_t i = 0; i < arraysize(buffers_); ++i) {
+      buffers_[i].CreateAnonymous(kBufferSize);
+      buffers_[i].Map(kBufferSize);
+    }
+
     TransferBufferManager* manager = new TransferBufferManager();
     transfer_buffer_manager_.reset(manager);
-    manager->Initialize();
+    ASSERT_TRUE(manager->Initialize());
   }
 
+  base::SharedMemory buffers_[3];
   scoped_ptr<TransferBufferManagerInterface> transfer_buffer_manager_;
 };
 
@@ -35,59 +43,73 @@
   EXPECT_TRUE(NULL == transfer_buffer_manager_->GetTransferBuffer(1).ptr);
 }
 
-TEST_F(TransferBufferManagerTest, CanCreateTransferBuffers) {
-  int32 handle = transfer_buffer_manager_->CreateTransferBuffer(1024, -1);
-  EXPECT_EQ(1, handle);
-  Buffer buffer = transfer_buffer_manager_->GetTransferBuffer(handle);
-  ASSERT_TRUE(NULL != buffer.ptr);
-  EXPECT_EQ(1024u, buffer.size);
+TEST_F(TransferBufferManagerTest, CanRegisterTransferBuffer) {
+  EXPECT_TRUE(transfer_buffer_manager_->RegisterTransferBuffer(1,
+                                                               &buffers_[0],
+                                                               kBufferSize));
+  Buffer registered = transfer_buffer_manager_->GetTransferBuffer(1);
+
+  // Distinct memory range and shared memory handle from that originally
+  // registered.
+  EXPECT_NE(static_cast<void*>(NULL), registered.ptr);
+  EXPECT_NE(buffers_[0].memory(), registered.ptr);
+  EXPECT_EQ(kBufferSize, registered.size);
+  EXPECT_NE(&buffers_[0], registered.shared_memory);
+
+  // But maps to the same physical memory.
+  *static_cast<int*>(registered.ptr) = 7;
+  *static_cast<int*>(buffers_[0].memory()) = 8;
+  EXPECT_EQ(8, *static_cast<int*>(registered.ptr));
 }
 
-TEST_F(TransferBufferManagerTest, CreateTransferBufferReturnsDistinctHandles) {
-  EXPECT_EQ(1, transfer_buffer_manager_->CreateTransferBuffer(1024, -1));
-}
-
-TEST_F(TransferBufferManagerTest,
-    CreateTransferBufferReusesUnregisteredHandles) {
-  EXPECT_EQ(1, transfer_buffer_manager_->CreateTransferBuffer(1024, -1));
-  EXPECT_EQ(2, transfer_buffer_manager_->CreateTransferBuffer(1024, -1));
+TEST_F(TransferBufferManagerTest, CanDestroyTransferBuffer) {
+  EXPECT_TRUE(transfer_buffer_manager_->RegisterTransferBuffer(1,
+                                                               &buffers_[0],
+                                                               kBufferSize));
   transfer_buffer_manager_->DestroyTransferBuffer(1);
-  EXPECT_EQ(1, transfer_buffer_manager_->CreateTransferBuffer(1024, -1));
-  EXPECT_EQ(3, transfer_buffer_manager_->CreateTransferBuffer(1024, -1));
+  Buffer registered = transfer_buffer_manager_->GetTransferBuffer(1);
+
+  EXPECT_EQ(static_cast<void*>(NULL), registered.ptr);
+  EXPECT_EQ(0U, registered.size);
+  EXPECT_EQ(static_cast<base::SharedMemory*>(NULL), registered.shared_memory);
 }
 
-TEST_F(TransferBufferManagerTest, CannotUnregisterHandleZero) {
-  transfer_buffer_manager_->DestroyTransferBuffer(0);
-  EXPECT_TRUE(NULL == transfer_buffer_manager_->GetTransferBuffer(0).ptr);
-  EXPECT_EQ(1, transfer_buffer_manager_->CreateTransferBuffer(1024, -1));
+TEST_F(TransferBufferManagerTest, CannotRegregisterTransferBufferId) {
+  EXPECT_TRUE(transfer_buffer_manager_->RegisterTransferBuffer(1,
+                                                               &buffers_[0],
+                                                               kBufferSize));
+  EXPECT_FALSE(transfer_buffer_manager_->RegisterTransferBuffer(1,
+                                                                &buffers_[0],
+                                                                kBufferSize));
+  EXPECT_FALSE(transfer_buffer_manager_->RegisterTransferBuffer(1,
+                                                                &buffers_[1],
+                                                                kBufferSize));
 }
 
-TEST_F(TransferBufferManagerTest, CannotUnregisterNegativeHandles) {
-  transfer_buffer_manager_->DestroyTransferBuffer(-1);
-  EXPECT_EQ(1, transfer_buffer_manager_->CreateTransferBuffer(1024, -1));
-}
-
-TEST_F(TransferBufferManagerTest, CannotUnregisterUnregisteredHandles) {
+TEST_F(TransferBufferManagerTest, CanReuseTransferBufferIdAfterDestroying) {
+  EXPECT_TRUE(transfer_buffer_manager_->RegisterTransferBuffer(1,
+                                                               &buffers_[0],
+                                                               kBufferSize));
   transfer_buffer_manager_->DestroyTransferBuffer(1);
-  EXPECT_EQ(1, transfer_buffer_manager_->CreateTransferBuffer(1024, -1));
+  EXPECT_TRUE(transfer_buffer_manager_->RegisterTransferBuffer(1,
+                                                               &buffers_[1],
+                                                               kBufferSize));
 }
 
-// Testing this case specifically because there is an optimization that takes
-// a different code path in this case.
-TEST_F(TransferBufferManagerTest, UnregistersLastRegisteredHandle) {
-  EXPECT_EQ(1, transfer_buffer_manager_->CreateTransferBuffer(1024, -1));
+TEST_F(TransferBufferManagerTest, DestroyUnusedTransferBufferIdDoesNotCrash) {
   transfer_buffer_manager_->DestroyTransferBuffer(1);
-  EXPECT_EQ(1, transfer_buffer_manager_->CreateTransferBuffer(1024, -1));
 }
 
-// Testing this case specifically because there is an optimization that takes
-// a different code path in this case.
-TEST_F(TransferBufferManagerTest, UnregistersTwoLastRegisteredHandles) {
-  EXPECT_EQ(1, transfer_buffer_manager_->CreateTransferBuffer(1024, -1));
-  EXPECT_EQ(2, transfer_buffer_manager_->CreateTransferBuffer(1024, -1));
-  transfer_buffer_manager_->DestroyTransferBuffer(2);
-  transfer_buffer_manager_->DestroyTransferBuffer(1);
-  EXPECT_EQ(1, transfer_buffer_manager_->CreateTransferBuffer(1024, -1));
+TEST_F(TransferBufferManagerTest, CannotRegisterNullTransferBuffer) {
+  EXPECT_FALSE(transfer_buffer_manager_->RegisterTransferBuffer(0,
+                                                                &buffers_[0],
+                                                                kBufferSize));
+}
+
+TEST_F(TransferBufferManagerTest, CannotRegisterNegativeTransferBufferId) {
+  EXPECT_FALSE(transfer_buffer_manager_->RegisterTransferBuffer(-1,
+                                                                &buffers_[0],
+                                                                kBufferSize));
 }
 
 }  // namespace gpu
diff --git a/ppapi/native_client/src/shared/ppapi_proxy/command_buffer_nacl.cc b/ppapi/native_client/src/shared/ppapi_proxy/command_buffer_nacl.cc
index 95b7028..eef8f0f 100644
--- a/ppapi/native_client/src/shared/ppapi_proxy/command_buffer_nacl.cc
+++ b/ppapi/native_client/src/shared/ppapi_proxy/command_buffer_nacl.cc
@@ -104,18 +104,20 @@
   GPU_NOTREACHED();
 }
 
-int32 CommandBufferNacl::CreateTransferBuffer(size_t size, int32 id_request) {
+gpu::Buffer CommandBufferNacl::CreateTransferBuffer(size_t size, int32* id) {
   DebugPrintf("CommandBufferNacl::CreateTransferBuffer\n");
-  int32_t id;
+  *id = -1;
 
   NaClSrpcChannel* channel = ppapi_proxy::GetMainSrpcChannel();
   NaClSrpcError retval =
       PpbGraphics3DRpcClient::PPB_Graphics3DTrusted_CreateTransferBuffer(
-          channel, graphics_3d_, size, id_request, &id);
+          channel, graphics_3d_, size, -1, id);
   if (NACL_SRPC_RESULT_OK != retval)
-    return 0;
+    return BufferFromShm(-1, 0);
+  if ((*id) <= 0)
+    return BufferFromShm(-1, 0);
 
-  return id;
+  return GetTransferBuffer(*id);
 }
 
 void CommandBufferNacl::DestroyTransferBuffer(int32 id) {
diff --git a/ppapi/native_client/src/shared/ppapi_proxy/command_buffer_nacl.h b/ppapi/native_client/src/shared/ppapi_proxy/command_buffer_nacl.h
index 8806289..eadd3743 100644
--- a/ppapi/native_client/src/shared/ppapi_proxy/command_buffer_nacl.h
+++ b/ppapi/native_client/src/shared/ppapi_proxy/command_buffer_nacl.h
@@ -28,15 +28,9 @@
   virtual State FlushSync(int32 put_offset, int32 last_known_get);
   virtual void SetGetBuffer(int32 transfer_buffer_id);
   virtual void SetGetOffset(int32 get_offset);
-  virtual int32 CreateTransferBuffer(size_t size, int32 id_request);
-  virtual int32 RegisterTransferBuffer(base::SharedMemory* buffer,
-                                       size_t size,
-                                       int32 id_request) {
-    // TODO(neb): support for nacl if neccessary
-    return -1;
-  }
+  virtual gpu::Buffer CreateTransferBuffer(size_t size, int32* id);
   virtual void DestroyTransferBuffer(int32 id);
-  virtual gpu::Buffer GetTransferBuffer(int32 handle);
+  virtual gpu::Buffer GetTransferBuffer(int32 id);
   virtual void SetToken(int32 token);
   virtual void SetParseError(gpu::error::Error error);
   virtual void SetContextLostReason(gpu::error::ContextLostReason);
diff --git a/ppapi/proxy/ppapi_command_buffer_proxy.cc b/ppapi/proxy/ppapi_command_buffer_proxy.cc
index ad80a272..175b8de0 100644
--- a/ppapi/proxy/ppapi_command_buffer_proxy.cc
+++ b/ppapi/proxy/ppapi_command_buffer_proxy.cc
@@ -129,26 +129,22 @@
   NOTREACHED();
 }
 
-int32 PpapiCommandBufferProxy::CreateTransferBuffer(
-    size_t size,
-    int32 id_request) {
-  if (last_state_.error == gpu::error::kNoError) {
-    int32 id;
-    if (Send(new PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer(
-             ppapi::API_ID_PPB_GRAPHICS_3D, resource_, size, &id))) {
-      return id;
-    }
-  }
-  return -1;
-}
+gpu::Buffer PpapiCommandBufferProxy::CreateTransferBuffer(size_t size,
+                                                          int32* id) {
+  *id = -1;
 
-int32 PpapiCommandBufferProxy::RegisterTransferBuffer(
-    base::SharedMemory* shared_memory,
-    size_t size,
-    int32 id_request) {
-  // Not implemented in proxy.
-  NOTREACHED();
-  return -1;
+  if (last_state_.error != gpu::error::kNoError)
+    return gpu::Buffer();
+
+  if (!Send(new PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer(
+            ppapi::API_ID_PPB_GRAPHICS_3D, resource_, size, id))) {
+    return gpu::Buffer();
+  }
+
+  if ((*id) <= 0)
+    return gpu::Buffer();
+
+  return GetTransferBuffer(*id);
 }
 
 void PpapiCommandBufferProxy::DestroyTransferBuffer(int32 id) {
diff --git a/ppapi/proxy/ppapi_command_buffer_proxy.h b/ppapi/proxy/ppapi_command_buffer_proxy.h
index 716d3f3..d1aac55 100644
--- a/ppapi/proxy/ppapi_command_buffer_proxy.h
+++ b/ppapi/proxy/ppapi_command_buffer_proxy.h
@@ -44,12 +44,9 @@
   virtual State FlushSync(int32 put_offset, int32 last_known_get);
   virtual void SetGetBuffer(int32 transfer_buffer_id);
   virtual void SetGetOffset(int32 get_offset);
-  virtual int32 CreateTransferBuffer(size_t size, int32 id_request);
-  virtual int32 RegisterTransferBuffer(base::SharedMemory* shared_memory,
-                                       size_t size,
-                                       int32 id_request);
+  virtual gpu::Buffer CreateTransferBuffer(size_t size, int32* id);
   virtual void DestroyTransferBuffer(int32 id);
-  virtual gpu::Buffer GetTransferBuffer(int32 handle);
+  virtual gpu::Buffer GetTransferBuffer(int32 id);
   virtual void SetToken(int32 token);
   virtual void SetParseError(gpu::error::Error error);
   virtual void SetContextLostReason(gpu::error::ContextLostReason reason);
diff --git a/ppapi/proxy/ppb_graphics_3d_proxy.cc b/ppapi/proxy/ppb_graphics_3d_proxy.cc
index 9919df33..747b459 100644
--- a/ppapi/proxy/ppb_graphics_3d_proxy.cc
+++ b/ppapi/proxy/ppb_graphics_3d_proxy.cc
@@ -146,24 +146,18 @@
     MaybeLock lock(need_to_lock_);
     gpu_command_buffer_->SetGetOffset(get_offset);
   }
-  virtual int32 CreateTransferBuffer(size_t size, int32 id_request) OVERRIDE {
+  virtual gpu::Buffer CreateTransferBuffer(size_t size,
+                                           int32* id) OVERRIDE {
     MaybeLock lock(need_to_lock_);
-    return gpu_command_buffer_->CreateTransferBuffer(size, id_request);
-  }
-  virtual int32 RegisterTransferBuffer(base::SharedMemory* shared_memory,
-                                       size_t size,
-                                       int32 id_request) OVERRIDE {
-    MaybeLock lock(need_to_lock_);
-    return gpu_command_buffer_->RegisterTransferBuffer(shared_memory, size,
-        id_request);
+    return gpu_command_buffer_->CreateTransferBuffer(size, id);
   }
   virtual void DestroyTransferBuffer(int32 id) OVERRIDE {
     MaybeLock lock(need_to_lock_);
     gpu_command_buffer_->DestroyTransferBuffer(id);
   }
-  virtual gpu::Buffer GetTransferBuffer(int32 handle) OVERRIDE {
+  virtual gpu::Buffer GetTransferBuffer(int32 id) OVERRIDE {
     MaybeLock lock(need_to_lock_);
-    return gpu_command_buffer_->GetTransferBuffer(handle);
+    return gpu_command_buffer_->GetTransferBuffer(id);
   }
   virtual void SetToken(int32 token) OVERRIDE {
     MaybeLock lock(need_to_lock_);
@@ -457,7 +451,7 @@
   if (enter.succeeded())
     *id = enter.object()->CreateTransferBuffer(size);
   else
-    *id = 0;
+    *id = -1;
 }
 
 void PPB_Graphics3D_Proxy::OnMsgDestroyTransferBuffer(
diff --git a/webkit/plugins/ppapi/ppb_graphics_3d_impl.cc b/webkit/plugins/ppapi/ppb_graphics_3d_impl.cc
index 5e6592cc..5c6e24a 100644
--- a/webkit/plugins/ppapi/ppb_graphics_3d_impl.cc
+++ b/webkit/plugins/ppapi/ppb_graphics_3d_impl.cc
@@ -141,7 +141,9 @@
 }
 
 int32_t PPB_Graphics3D_Impl::CreateTransferBuffer(uint32_t size) {
-  return GetCommandBuffer()->CreateTransferBuffer(size, -1);
+  int32_t id = -1;
+  GetCommandBuffer()->CreateTransferBuffer(size, &id);
+  return id;
 }
 
 PP_Bool PPB_Graphics3D_Impl::DestroyTransferBuffer(int32_t id) {