diff options
author | apatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-28 23:36:54 +0000 |
---|---|---|
committer | apatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-28 23:36:54 +0000 |
commit | 36dbfe198cb0eab50ff4a7300fc86b8314d30cde (patch) | |
tree | c7b2271be2e885ca87ac58d53e338cca322276a4 | |
parent | 406e6e22b82ef80e8bc44f45d85efa68799bc552 (diff) | |
download | chromium_src-36dbfe198cb0eab50ff4a7300fc86b8314d30cde.zip chromium_src-36dbfe198cb0eab50ff4a7300fc86b8314d30cde.tar.gz chromium_src-36dbfe198cb0eab50ff4a7300fc86b8314d30cde.tar.bz2 |
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
-rw-r--r-- | chrome/common/gpu_messages_internal.h | 5 | ||||
-rw-r--r-- | chrome/gpu/gpu_command_buffer_stub.cc | 90 | ||||
-rw-r--r-- | chrome/gpu/gpu_command_buffer_stub.h | 4 | ||||
-rw-r--r-- | chrome/plugin/command_buffer_stub.cc | 70 | ||||
-rw-r--r-- | chrome/plugin/command_buffer_stub.h | 4 | ||||
-rw-r--r-- | chrome/renderer/command_buffer_proxy.cc | 62 | ||||
-rw-r--r-- | chrome/renderer/command_buffer_proxy.h | 1 | ||||
-rw-r--r-- | gpu/command_buffer/client/gles2_implementation_unittest.cc | 5 | ||||
-rw-r--r-- | gpu/command_buffer/common/command_buffer.h | 7 | ||||
-rw-r--r-- | gpu/command_buffer/common/command_buffer_mock.h | 1 | ||||
-rw-r--r-- | gpu/command_buffer/service/command_buffer_service.cc | 57 | ||||
-rw-r--r-- | gpu/command_buffer/service/command_buffer_service.h | 3 | ||||
-rw-r--r-- | gpu/pgl/command_buffer_pepper.cc | 5 | ||||
-rw-r--r-- | gpu/pgl/command_buffer_pepper.h | 5 | ||||
-rw-r--r-- | ppapi/proxy/ppb_context_3d_proxy.cc | 7 |
15 files changed, 189 insertions, 137 deletions
diff --git a/chrome/common/gpu_messages_internal.h b/chrome/common/gpu_messages_internal.h index b95a42a..eaf5088 100644 --- a/chrome/common/gpu_messages_internal.h +++ b/chrome/common/gpu_messages_internal.h @@ -225,9 +225,10 @@ IPC_SYNC_MESSAGE_CONTROL1_0(GpuChannelMsg_DestroyVideoDecoder, // 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_ROUTED1_1(GpuCommandBufferMsg_Initialize, +IPC_SYNC_MESSAGE_ROUTED2_1(GpuCommandBufferMsg_Initialize, + base::SharedMemoryHandle /* ring_buffer */, int32 /* size */, - base::SharedMemoryHandle /* ring_buffer */) + bool /* result */) // Get the current state of the command buffer. IPC_SYNC_MESSAGE_ROUTED0_1(GpuCommandBufferMsg_GetState, diff --git a/chrome/gpu/gpu_command_buffer_stub.cc b/chrome/gpu/gpu_command_buffer_stub.cc index 5b81d22..0bf5427 100644 --- a/chrome/gpu/gpu_command_buffer_stub.cc +++ b/chrome/gpu/gpu_command_buffer_stub.cc @@ -192,11 +192,12 @@ bool GpuCommandBufferStub::Send(IPC::Message* message) { } void GpuCommandBufferStub::OnInitialize( + base::SharedMemoryHandle ring_buffer, int32 size, - base::SharedMemoryHandle* ring_buffer) { + bool* result) { DCHECK(!command_buffer_.get()); - *ring_buffer = base::SharedMemory::NULLHandle(); + *result = false; command_buffer_.reset(new gpu::CommandBufferService); @@ -215,50 +216,57 @@ void GpuCommandBufferStub::OnInitialize( gfx::PluginWindowHandle output_window_handle = handle_; #endif // defined(OS_WIN) +#if defined(OS_WIN) + // Windows dups the shared memory handle it receives into the current process + // and closes it when this variable goes out of scope. + base::SharedMemory shared_memory(ring_buffer, + false, + channel_->renderer_process()); +#else + // POSIX receives a dup of the shared memory handle and closes the dup when + // this variable goes out of scope. + base::SharedMemory shared_memory(ring_buffer, false); +#endif + // Initialize the CommandBufferService and GPUProcessor. - if (command_buffer_->Initialize(size)) { - Buffer buffer = command_buffer_->GetRingBuffer(); - if (buffer.shared_memory) { - gpu::GPUProcessor* parent_processor = - parent_ ? parent_->processor_.get() : NULL; - processor_.reset(new gpu::GPUProcessor(command_buffer_.get(), NULL)); - if (processor_->Initialize( - output_window_handle, - initial_size_, - allowed_extensions_.c_str(), - requested_attribs_, - parent_processor, - parent_texture_id_)) { - command_buffer_->SetPutOffsetChangeCallback( - NewCallback(processor_.get(), - &gpu::GPUProcessor::ProcessCommands)); - processor_->SetSwapBuffersCallback( - NewCallback(this, &GpuCommandBufferStub::OnSwapBuffers)); + if (command_buffer_->Initialize(&shared_memory, size)) { + gpu::GPUProcessor* parent_processor = + parent_ ? parent_->processor_.get() : NULL; + processor_.reset(new gpu::GPUProcessor(command_buffer_.get(), NULL)); + if (processor_->Initialize( + output_window_handle, + initial_size_, + allowed_extensions_.c_str(), + requested_attribs_, + parent_processor, + parent_texture_id_)) { + command_buffer_->SetPutOffsetChangeCallback( + NewCallback(processor_.get(), + &gpu::GPUProcessor::ProcessCommands)); + processor_->SetSwapBuffersCallback( + NewCallback(this, &GpuCommandBufferStub::OnSwapBuffers)); - // Assume service is responsible for duplicating the handle from the - // calling process. - buffer.shared_memory->ShareToProcess(channel_->renderer_process(), - ring_buffer); #if defined(OS_MACOSX) - if (handle_) { - // This context conceptually puts its output directly on the - // screen, rendered by the accelerated plugin layer in - // RenderWidgetHostViewMac. Set up a pathway to notify the - // browser process when its contents change. - processor_->SetSwapBuffersCallback( - NewCallback(this, - &GpuCommandBufferStub::SwapBuffersCallback)); - } + if (handle_) { + // This context conceptually puts its output directly on the + // screen, rendered by the accelerated plugin layer in + // RenderWidgetHostViewMac. Set up a pathway to notify the + // browser process when its contents change. + processor_->SetSwapBuffersCallback( + NewCallback(this, + &GpuCommandBufferStub::SwapBuffersCallback)); + } #endif // defined(OS_MACOSX) - // Set up a pathway for resizing the output window or framebuffer at the - // right time relative to other GL commands. - processor_->SetResizeCallback( - NewCallback(this, &GpuCommandBufferStub::ResizeCallback)); - } else { - processor_.reset(); - command_buffer_.reset(); - } + // Set up a pathway for resizing the output window or framebuffer at the + // right time relative to other GL commands. + processor_->SetResizeCallback( + NewCallback(this, &GpuCommandBufferStub::ResizeCallback)); + + *result = true; + } else { + processor_.reset(); + command_buffer_.reset(); } } } diff --git a/chrome/gpu/gpu_command_buffer_stub.h b/chrome/gpu/gpu_command_buffer_stub.h index 2382410..7124e25 100644 --- a/chrome/gpu/gpu_command_buffer_stub.h +++ b/chrome/gpu/gpu_command_buffer_stub.h @@ -68,7 +68,9 @@ class GpuCommandBufferStub private: // Message handlers: - void OnInitialize(int32 size, base::SharedMemoryHandle* ring_buffer); + void OnInitialize(base::SharedMemoryHandle ring_buffer, + int32 size, + bool* result); void OnGetState(gpu::CommandBuffer::State* state); void OnAsyncGetState(); void OnFlush(int32 put_offset, gpu::CommandBuffer::State* state); diff --git a/chrome/plugin/command_buffer_stub.cc b/chrome/plugin/command_buffer_stub.cc index 2ef657a..9aea1ee 100644 --- a/chrome/plugin/command_buffer_stub.cc +++ b/chrome/plugin/command_buffer_stub.cc @@ -2,12 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "chrome/plugin/command_buffer_stub.h" + #include "base/callback.h" #include "base/scoped_open_process.h" #include "base/shared_memory.h" #include "chrome/common/gpu_messages.h" #include "chrome/common/plugin_messages.h" -#include "chrome/plugin/command_buffer_stub.h" #include "chrome/plugin/plugin_channel.h" using gpu::Buffer; @@ -67,66 +68,13 @@ void CommandBufferStub::NotifyRepaint() { Send(new GpuCommandBufferMsg_NotifyRepaint(route_id_)); } -void CommandBufferStub::OnInitialize(int32 size, - base::SharedMemoryHandle* ring_buffer) { - DCHECK(!command_buffer_.get()); - - *ring_buffer = base::SharedMemory::NULLHandle(); - - // Assume service is responsible for duplicating the handle from the calling - // process. - base::ScopedOpenProcess peer_process; - if (!peer_process.Open(channel_->peer_pid())) - return; - - command_buffer_.reset(new gpu::CommandBufferService); - - // Initialize the CommandBufferService. - if (!command_buffer_->Initialize(size)) { - Destroy(); - return; - } - - // Get the ring buffer. - Buffer buffer = command_buffer_->GetRingBuffer(); - if (!buffer.shared_memory) { - Destroy(); - return; - } - - // Initialize the GPUProcessor. - processor_.reset(new gpu::GPUProcessor(command_buffer_.get(), NULL)); - if (!processor_->Initialize(window_, gfx::Size(), NULL, std::vector<int32>(), - NULL, 0)) { - Destroy(); - return; - } - - // Perform platform specific initialization. - if (!InitializePlatformSpecific()) { - Destroy(); - return; - } - - // Share the ring buffer to the client process. - if (!buffer.shared_memory->ShareToProcess(peer_process.handle(), - ring_buffer)) { - Destroy(); - return; - } - - // Setup callbacks for events. - command_buffer_->SetPutOffsetChangeCallback( - NewCallback(processor_.get(), - &gpu::GPUProcessor::ProcessCommands)); -#if defined(OS_MACOSX) - processor_->SetSwapBuffersCallback( - NewCallback(this, - &CommandBufferStub::SwapBuffersCallback)); - processor_->SetTransportDIBAllocAndFree( - NewCallback(this, &CommandBufferStub::AllocTransportDIB), - NewCallback(this, &CommandBufferStub::FreeTransportDIB)); -#endif +void CommandBufferStub::OnInitialize(base::SharedMemoryHandle ring_buffer, + int32 size, + bool* result) { + // TODO(apatrick): Pepper3D v1 is not used anymore. This function is never + // called. Delete the GPU plugin. + NOTREACHED(); + *result = false; } void CommandBufferStub::OnGetState(gpu::CommandBuffer::State* state) { diff --git a/chrome/plugin/command_buffer_stub.h b/chrome/plugin/command_buffer_stub.h index 96974ab..a2667f1 100644 --- a/chrome/plugin/command_buffer_stub.h +++ b/chrome/plugin/command_buffer_stub.h @@ -45,7 +45,9 @@ class CommandBufferStub : public IPC::Channel::Listener, private: // Message handlers: - void OnInitialize(int32 size, base::SharedMemoryHandle* ring_buffer); + void OnInitialize(base::SharedMemoryHandle ring_buffer, + int32 size, + bool* result); void OnGetState(gpu::CommandBuffer::State* state); void OnAsyncGetState(); void OnFlush(int32 put_offset, gpu::CommandBuffer::State* state); diff --git a/chrome/renderer/command_buffer_proxy.cc b/chrome/renderer/command_buffer_proxy.cc index 312cc7f..8414b4e 100644 --- a/chrome/renderer/command_buffer_proxy.cc +++ b/chrome/renderer/command_buffer_proxy.cc @@ -68,22 +68,62 @@ void CommandBufferProxy::SetChannelErrorCallback(Callback0::Type* callback) { bool CommandBufferProxy::Initialize(int32 size) { DCHECK(!ring_buffer_.get()); - // Initialize the service. Assuming we are sandboxed, the GPU - // process is responsible for duplicating the handle. This might not be true - // for NaCl. + RenderThread* render_thread = RenderThread::current(); + if (!render_thread) + return false; + base::SharedMemoryHandle handle; - if (Send(new GpuCommandBufferMsg_Initialize(route_id_, size, &handle)) && - base::SharedMemory::IsHandleValid(handle)) { - ring_buffer_.reset(new base::SharedMemory(handle, false)); - if (ring_buffer_->Map(size)) { - num_entries_ = size / sizeof(gpu::CommandBufferEntry); - return true; - } + if (!render_thread->Send(new ViewHostMsg_AllocateSharedMemoryBuffer( + size, + &handle))) { + return false; + } + + if (!base::SharedMemory::IsHandleValid(handle)) + return false; + +#if defined(OS_POSIX) + handle.auto_close = false; +#endif + // 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. + base::SharedMemory shared_memory(handle, false); + + return Initialize(&shared_memory, size); +} + +bool CommandBufferProxy::Initialize(base::SharedMemory* buffer, int32 size) { + bool result; + if (!Send(new GpuCommandBufferMsg_Initialize(route_id_, + buffer->handle(), + size, + &result))) { + LOG(ERROR) << "Could not send GpuCommandBufferMsg_Initialize."; + return false; + } + + if (!result) { + LOG(ERROR) << "Failed to initialize command buffer service."; + return false; + } + + base::SharedMemoryHandle handle; + if (!buffer->GiveToProcess(base::GetCurrentProcessHandle(), &handle)) { + LOG(ERROR) << "Failed to duplicate command buffer handle."; + return false; + } + + ring_buffer_.reset(new base::SharedMemory(handle, false)); + if (!ring_buffer_->Map(size)) { + LOG(ERROR) << "Failed to map shared memory for command buffer."; ring_buffer_.reset(); + return false; } - return false; + num_entries_ = size / sizeof(gpu::CommandBufferEntry); + return true; } Buffer CommandBufferProxy::GetRingBuffer() { diff --git a/chrome/renderer/command_buffer_proxy.h b/chrome/renderer/command_buffer_proxy.h index bf5edc6..fa3994c 100644 --- a/chrome/renderer/command_buffer_proxy.h +++ b/chrome/renderer/command_buffer_proxy.h @@ -45,6 +45,7 @@ class CommandBufferProxy : 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); 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); diff --git a/ppapi/proxy/ppb_context_3d_proxy.cc b/ppapi/proxy/ppb_context_3d_proxy.cc index 11c8ebb..dcbe943 100644 --- a/ppapi/proxy/ppb_context_3d_proxy.cc +++ b/ppapi/proxy/ppb_context_3d_proxy.cc @@ -177,6 +177,7 @@ class PepperCommandBuffer : 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); @@ -248,6 +249,12 @@ bool PepperCommandBuffer::Initialize(int32 size) { return false; } +bool PepperCommandBuffer::Initialize(base::SharedMemory* buffer, int32 size) { + // Not implemented in proxy. + NOTREACHED(); + return false; +} + gpu::Buffer PepperCommandBuffer::GetRingBuffer() { // Return locally cached ring buffer. gpu::Buffer buffer; |