From 36dbfe198cb0eab50ff4a7300fc86b8314d30cde Mon Sep 17 00:00:00 2001
From: "apatrick@chromium.org"
 <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>
Date: Mon, 28 Feb 2011 23:36:54 +0000
Subject: Moved creation of GPU command buffer shared memory into the browser
 process.

This is to allow the GPU process to be sandboxed on all platforms.

TEST=try, run WebGL app on win and mac.
BUG=none

Review URL: http://codereview.chromium.org/6588029

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@76307 0039d316-1c4b-4281-b951-d872f2087c98
---
 .../client/gles2_implementation_unittest.cc        |  5 ++
 gpu/command_buffer/common/command_buffer.h         |  7 +++
 gpu/command_buffer/common/command_buffer_mock.h    |  1 +
 .../service/command_buffer_service.cc              | 57 ++++++++++++++--------
 .../service/command_buffer_service.h               |  3 +-
 gpu/pgl/command_buffer_pepper.cc                   |  5 ++
 gpu/pgl/command_buffer_pepper.h                    |  5 ++
 7 files changed, 63 insertions(+), 20 deletions(-)

(limited to 'gpu')

diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc
index dc088fd..c18c34a 100644
--- a/gpu/command_buffer/client/gles2_implementation_unittest.cc
+++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc
@@ -33,6 +33,11 @@ class GLES2MockCommandBufferHelper : public CommandBuffer {
     return true;
   }
 
+  virtual bool Initialize(base::SharedMemory* buffer, int32 size) {
+    GPU_NOTREACHED();
+    return false;
+  }
+
   virtual Buffer GetRingBuffer() {
     return ring_buffer_buffer_;
   }
diff --git a/gpu/command_buffer/common/command_buffer.h b/gpu/command_buffer/common/command_buffer.h
index b758333..bcc39ea 100644
--- a/gpu/command_buffer/common/command_buffer.h
+++ b/gpu/command_buffer/common/command_buffer.h
@@ -8,6 +8,10 @@
 #include "../common/buffer.h"
 #include "../common/constants.h"
 
+namespace base {
+class SharedMemory;
+}
+
 namespace gpu {
 
 // Common interface for CommandBuffer implementations.
@@ -55,6 +59,9 @@ class CommandBuffer {
   // Initialize the command buffer with the given size.
   virtual bool Initialize(int32 size) = 0;
 
+  // Initialize the command buffer using the given preallocated buffer.
+  virtual bool Initialize(base::SharedMemory* buffer, int32 size) = 0;
+
   // Gets the ring buffer for the command buffer.
   virtual Buffer GetRingBuffer() = 0;
 
diff --git a/gpu/command_buffer/common/command_buffer_mock.h b/gpu/command_buffer/common/command_buffer_mock.h
index 99a72d3..2966801 100644
--- a/gpu/command_buffer/common/command_buffer_mock.h
+++ b/gpu/command_buffer/common/command_buffer_mock.h
@@ -22,6 +22,7 @@ class MockCommandBuffer : public CommandBuffer {
   virtual ~MockCommandBuffer();
 
   MOCK_METHOD1(Initialize, bool(int32 size));
+  MOCK_METHOD2(Initialize, bool(base::SharedMemory* buffer, int32 size));
   MOCK_METHOD0(GetRingBuffer, Buffer());
   MOCK_METHOD0(GetState, State());
   MOCK_METHOD1(Flush, void(int32 put_offset));
diff --git a/gpu/command_buffer/service/command_buffer_service.cc b/gpu/command_buffer/service/command_buffer_service.cc
index d806de1..adc5623 100644
--- a/gpu/command_buffer/service/command_buffer_service.cc
+++ b/gpu/command_buffer/service/command_buffer_service.cc
@@ -25,6 +25,8 @@ CommandBufferService::CommandBufferService()
 }
 
 CommandBufferService::~CommandBufferService() {
+  delete ring_buffer_.shared_memory;
+
   for (size_t i = 0; i < registered_objects_.size(); ++i) {
     if (registered_objects_[i].shared_memory)
       delete registered_objects_[i].shared_memory;
@@ -33,42 +35,59 @@ CommandBufferService::~CommandBufferService() {
 
 bool CommandBufferService::Initialize(int32 size) {
   // Fail if already initialized.
-  if (ring_buffer_.get()) {
-    LOG(ERROR) << "CommandBufferService::Initialize "
-               << "failed because already initialized.";
+  if (ring_buffer_.shared_memory) {
+    LOG(ERROR) << "Failed because already initialized.";
     return false;
   }
 
   if (size <= 0 || size > kMaxCommandBufferSize) {
-    LOG(ERROR) << "CommandBufferService::Initialize "
-               << "because command buffer size was invalid.";
+    LOG(ERROR) << "Failed because command buffer size was invalid.";
     return false;
   }
 
   num_entries_ = size / sizeof(CommandBufferEntry);
 
-  ring_buffer_.reset(new SharedMemory);
-  if (ring_buffer_->CreateAndMapAnonymous(size)) {
+  SharedMemory shared_memory;
+  if (!shared_memory.CreateAnonymous(size)) {
+    LOG(ERROR) << "Failed to create shared memory for command buffer.";
     return true;
   }
 
-  num_entries_ = 0;
-  ring_buffer_.reset();
+  return Initialize(&shared_memory, size);
+}
 
-  LOG(ERROR) << "CommandBufferService::Initialize failed because ring buffer "
-             << "could not be created or mapped ";
+bool CommandBufferService::Initialize(base::SharedMemory* buffer, int32 size) {
+  // Fail if already initialized.
+  if (ring_buffer_.shared_memory) {
+    LOG(ERROR) << "Failed because already initialized.";
+    return false;
+  }
+
+  base::SharedMemoryHandle shared_memory_handle;
+  if (!buffer->ShareToProcess(base::GetCurrentProcessHandle(),
+                              &shared_memory_handle)) {
+    LOG(ERROR) << "Failed to duplicate command buffer shared memory handle.";
+    return false;
+  }
 
-  return false;
+  ring_buffer_.shared_memory = new base::SharedMemory(shared_memory_handle,
+                                                      false);
+  if (!ring_buffer_.shared_memory->Map(size)) {
+    LOG(ERROR) << "Failed because ring buffer could not be created or mapped ";
+    delete ring_buffer_.shared_memory;
+    ring_buffer_.shared_memory = NULL;
+    return false;
+  }
+
+  ring_buffer_.ptr = ring_buffer_.shared_memory->memory();
+  ring_buffer_.size = size;
+  num_entries_ = size / sizeof(CommandBufferEntry);
+
+  return true;
 }
 
 Buffer CommandBufferService::GetRingBuffer() {
-  Buffer buffer;
-  if (ring_buffer_.get()) {
-    buffer.ptr = ring_buffer_->memory();
-    buffer.size = ring_buffer_->created_size();
-    buffer.shared_memory = ring_buffer_.get();
-  }
-  return buffer;
+  return ring_buffer_;
 }
 
 CommandBufferService::State CommandBufferService::GetState() {
diff --git a/gpu/command_buffer/service/command_buffer_service.h b/gpu/command_buffer/service/command_buffer_service.h
index 9706008..15b5046 100644
--- a/gpu/command_buffer/service/command_buffer_service.h
+++ b/gpu/command_buffer/service/command_buffer_service.h
@@ -26,6 +26,7 @@ class CommandBufferService : public CommandBuffer {
 
   // CommandBuffer implementation:
   virtual bool Initialize(int32 size);
+  virtual bool Initialize(base::SharedMemory* buffer, int32 size);
   virtual Buffer GetRingBuffer();
   virtual State GetState();
   virtual void Flush(int32 put_offset);
@@ -52,7 +53,7 @@ class CommandBufferService : public CommandBuffer {
   virtual void SetPutOffsetChangeCallback(Callback0::Type* callback);
 
  private:
-  scoped_ptr< base::SharedMemory> ring_buffer_;
+  Buffer ring_buffer_;
   int32 num_entries_;
   int32 get_offset_;
   int32 put_offset_;
diff --git a/gpu/pgl/command_buffer_pepper.cc b/gpu/pgl/command_buffer_pepper.cc
index e4b6ce8..c508b53 100644
--- a/gpu/pgl/command_buffer_pepper.cc
+++ b/gpu/pgl/command_buffer_pepper.cc
@@ -27,6 +27,11 @@ bool CommandBufferPepper::Initialize(int32 size) {
   return false;
 }
 
+bool CommandBufferPepper::Initialize(base::SharedMemory* buffer, int32 size) {
+  GPU_NOTREACHED();
+  return false;
+}
+
 Buffer CommandBufferPepper::GetRingBuffer() {
   Buffer buffer;
 #if defined(ENABLE_NEW_NPDEVICE_API)
diff --git a/gpu/pgl/command_buffer_pepper.h b/gpu/pgl/command_buffer_pepper.h
index 902db36..8f990da 100644
--- a/gpu/pgl/command_buffer_pepper.h
+++ b/gpu/pgl/command_buffer_pepper.h
@@ -15,6 +15,10 @@
 #include "third_party/npapi/bindings/nphostapi.h"
 #endif  // __native_client__
 
+namespace {
+class SharedMemory;
+}
+
 // A CommandBuffer proxy implementation that uses the Pepper API to access
 // the command buffer.
 
@@ -27,6 +31,7 @@ class CommandBufferPepper : public gpu::CommandBuffer {
 
   // CommandBuffer implementation.
   virtual bool Initialize(int32 size);
+  virtual bool Initialize(base::SharedMemory* buffer, int32 size);
   virtual gpu::Buffer GetRingBuffer();
   virtual State GetState();
   virtual void Flush(int32 put_offset);
-- 
cgit v1.1