diff options
author | apatrick@google.com <apatrick@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-22 23:28:15 +0000 |
---|---|---|
committer | apatrick@google.com <apatrick@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-22 23:28:15 +0000 |
commit | 7477ea6f6a173b586622fd276433a346760ffbf4 (patch) | |
tree | 678229a49ae5c4bb1a54a61374466cdddf57db59 /chrome | |
parent | e4f7cec0a45a803faf00875a070090b165ff1fc5 (diff) | |
download | chromium_src-7477ea6f6a173b586622fd276433a346760ffbf4.zip chromium_src-7477ea6f6a173b586622fd276433a346760ffbf4.tar.gz chromium_src-7477ea6f6a173b586622fd276433a346760ffbf4.tar.bz2 |
Added Pepper 3D device that instantiates the GPU plugin and sends GLES2 commands to it via a command buffer.
Added API for managing buffers to Pepper 3D device.
Removed DCHECK from WebPluginImpl::SetWindow that checks against a windowless plugin being given a window handle. Please check this! Now an initially windowless plugin instance gets a handle when it requests a Pepper 3D context. Perhaps the window handle should be concealed from the underlying plugin isntance.
Removed enable_gpu gyp variable and C macro. GPU code is always built on windows but not mac or linux. It is enabled at runtime with the --enable-gpu-plugin switch.
Redesigned CommandBuffer interface so it exposes shared memory through a Buffer. This was necessary because Pepper has no notion of shared memory handles. The Buffer exposes the shared memory as both a handle (through base::SharedMemory) and the mapped address and size.
Refactored CommandBufferEngine so mapped shared memory addresses and sizes are returned with a single call rather than two separate calls.
Added 3D demo to pepper test plugin.
TEST=try servers
BUG=none
Review URL: http://codereview.chromium.org/367002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@35185 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/DEPS | 2 | ||||
-rw-r--r-- | chrome/browser/plugin_process_host.cc | 1 | ||||
-rw-r--r-- | chrome/browser/plugin_service.cc | 3 | ||||
-rwxr-xr-x | chrome/chrome.gyp | 7 | ||||
-rwxr-xr-x | chrome/chrome_renderer.gypi | 13 | ||||
-rw-r--r-- | chrome/common/chrome_switches.cc | 3 | ||||
-rw-r--r-- | chrome/common/chrome_switches.h | 1 | ||||
-rw-r--r-- | chrome/common/command_buffer_messages_internal.h | 5 | ||||
-rw-r--r-- | chrome/common/gpu_plugin.cc | 43 | ||||
-rw-r--r-- | chrome/common/gpu_plugin.h | 15 | ||||
-rw-r--r-- | chrome/plugin/command_buffer_stub.cc | 44 | ||||
-rw-r--r-- | chrome/plugin/command_buffer_stub.h | 3 | ||||
-rw-r--r-- | chrome/plugin/plugin_main.cc | 3 | ||||
-rw-r--r-- | chrome/plugin/webplugin_delegate_stub.cc | 2 | ||||
-rw-r--r-- | chrome/plugin/webplugin_delegate_stub.h | 2 | ||||
-rw-r--r-- | chrome/renderer/command_buffer_proxy.cc | 70 | ||||
-rw-r--r-- | chrome/renderer/command_buffer_proxy.h | 8 | ||||
-rw-r--r-- | chrome/renderer/render_view.cc | 5 | ||||
-rw-r--r-- | chrome/renderer/webplugin_delegate_pepper.cc | 178 | ||||
-rw-r--r-- | chrome/renderer/webplugin_delegate_pepper.h | 41 | ||||
-rw-r--r-- | chrome/renderer/webplugin_delegate_proxy.cc | 2 |
21 files changed, 359 insertions, 92 deletions
diff --git a/chrome/DEPS b/chrome/DEPS index e96251a..c24006e 100644 --- a/chrome/DEPS +++ b/chrome/DEPS @@ -1,6 +1,6 @@ include_rules = [ "+app", - "+gpu/command_buffer", + "+gpu", "+net", "+printing", "+views", diff --git a/chrome/browser/plugin_process_host.cc b/chrome/browser/plugin_process_host.cc index f187b8c..5ae3715 100644 --- a/chrome/browser/plugin_process_host.cc +++ b/chrome/browser/plugin_process_host.cc @@ -373,6 +373,7 @@ bool PluginProcessHost::Init(const WebPluginInfo& info, switches::kMemoryProfiling, switches::kUseLowFragHeapCrt, switches::kEnableStatsTable, + switches::kEnableGPUPlugin, #if defined(OS_CHROMEOS) switches::kProfile, #endif diff --git a/chrome/browser/plugin_service.cc b/chrome/browser/plugin_service.cc index ba5821e..9c75d5c 100644 --- a/chrome/browser/plugin_service.cc +++ b/chrome/browser/plugin_service.cc @@ -19,6 +19,7 @@ #include "chrome/common/chrome_plugin_lib.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/extension.h" +#include "chrome/common/gpu_plugin.h" #include "chrome/common/logging_chrome.h" #include "chrome/common/notification_type.h" #include "chrome/common/notification_service.h" @@ -71,6 +72,8 @@ PluginService::PluginService() RegisterInternalNaClPlugin(); #endif + chrome::RegisterInternalGPUPlugin(); + #if defined(OS_WIN) hkcu_key_.Create( HKEY_CURRENT_USER, kRegistryMozillaPlugins, KEY_NOTIFY); diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index f231743..989cd4a 100755 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -508,6 +508,8 @@ 'common/dom_storage_type.h', 'common/filter_policy.h', 'common/gears_api.h', + 'common/gpu_plugin.cc', + 'common/gpu_plugin.h', 'common/gtk_tree.cc', 'common/gtk_tree.h', 'common/gtk_util.cc', @@ -772,6 +774,9 @@ # end up using this module as well. 'conditions': [ ['OS=="win"', { + 'dependencies': [ + '../gpu/gpu.gyp:command_buffer_service', + ], 'defines': [ '__STD_C', '_CRT_SECURE_NO_DEPRECATE', @@ -780,8 +785,6 @@ 'include_dirs': [ 'third_party/wtl/include', ], - },], - ['enable_gpu==1', { 'sources': [ 'plugin/command_buffer_stub.cc', 'plugin/command_buffer_stub.h', diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi index a0c8e09..d9cc809 100755 --- a/chrome/chrome_renderer.gypi +++ b/chrome/chrome_renderer.gypi @@ -148,15 +148,6 @@ ], }, 'conditions': [ - ['enable_gpu==1', { - 'dependencies': [ - '../gpu/gpu.gyp:gpu_plugin', - ], - 'sources': [ - 'renderer/command_buffer_proxy.cc', - 'renderer/command_buffer_proxy.h', - ], - }], ['disable_nacl!=1', { 'dependencies': [ 'nacl', @@ -174,6 +165,10 @@ 'include_dirs': [ 'third_party/wtl/include', ], + 'sources': [ + 'renderer/command_buffer_proxy.cc', + 'renderer/command_buffer_proxy.h', + ], 'conditions': [ ['win_use_allocator_shim==1', { 'dependencies': [ diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index ea5208d..5ce3111 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc @@ -204,6 +204,9 @@ const char kEnableFileCookies[] = "enable-file-cookies"; // Enable Geolocation support. const char kEnableGeolocation[] = "enable-geolocation"; +// Enable the GPU plugin and Pepper 3D rendering. +const char kEnableGPUPlugin[] = "enable-gpu-plugin"; + // Disable LocalStorage. const char kDisableLocalStorage[] = "disable-local-storage"; diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index bb9ffc9..0622455 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h @@ -74,6 +74,7 @@ extern const char kEnableExtensionToolstrips[]; extern const char kEnableFastback[]; extern const char kEnableFileCookies[]; extern const char kEnableGeolocation[]; +extern const char kEnableGPUPlugin[]; extern const char kDisableLocalStorage[]; extern const char kEnableLogging[]; extern const char kEnableMonitorProfile[]; diff --git a/chrome/common/command_buffer_messages_internal.h b/chrome/common/command_buffer_messages_internal.h index ae28ecc..cbcda79 100644 --- a/chrome/common/command_buffer_messages_internal.h +++ b/chrome/common/command_buffer_messages_internal.h @@ -43,9 +43,10 @@ IPC_BEGIN_MESSAGES(CommandBuffer) // Get the shared memory handle for a transfer buffer mapped to the callers // process. - IPC_SYNC_MESSAGE_ROUTED1_1(CommandBufferMsg_GetTransferBuffer, + IPC_SYNC_MESSAGE_ROUTED1_2(CommandBufferMsg_GetTransferBuffer, int32 /* id */, - base::SharedMemoryHandle /* transfer_buffer */) + base::SharedMemoryHandle /* transfer_buffer */, + size_t /* size */) // Get the most recently processed token. Used for implementing fences. IPC_SYNC_MESSAGE_ROUTED0_1(CommandBufferMsg_GetToken, diff --git a/chrome/common/gpu_plugin.cc b/chrome/common/gpu_plugin.cc new file mode 100644 index 0000000..fc79cbb --- /dev/null +++ b/chrome/common/gpu_plugin.cc @@ -0,0 +1,43 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/command_line.h" +#include "base/string_util.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/gpu_plugin.h" +#include "gpu/gpu_plugin/gpu_plugin.h" +#include "webkit/glue/plugins/plugin_list.h" + +#if defined(ENABLE_GPU) +#include "webkit/glue/plugins/plugin_constants_win.h" +#endif + +namespace chrome { + +void RegisterInternalGPUPlugin() { +#if defined(ENABLE_GPU) + static const std::wstring kWideMimeType = ASCIIToWide(kGPUPluginMimeType); + static const NPAPI::PluginVersionInfo kGPUPluginInfo = { + FilePath(FILE_PATH_LITERAL("gpu-plugin")), + L"GPU Plug-in", + L"GPU Rendering Plug-in", + L"1", + kWideMimeType.c_str(), + L"", + L"", + { +#if !defined(OS_LINUX) + gpu_plugin::NP_GetEntryPoints, +#endif + gpu_plugin::NP_Initialize, + gpu_plugin::NP_Shutdown + } + }; + + if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableGPUPlugin)) + NPAPI::PluginList::Singleton()->RegisterInternalPlugin(kGPUPluginInfo); +#endif // ENABLE_GPU +} + +} // namespace chrome diff --git a/chrome/common/gpu_plugin.h b/chrome/common/gpu_plugin.h new file mode 100644 index 0000000..3fd609e --- /dev/null +++ b/chrome/common/gpu_plugin.h @@ -0,0 +1,15 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_COMMON_GPU_PLUGIN_H_ +#define CHROME_COMMON_GPU_PLUGIN_H_ + +namespace chrome { + +// Register the GPU plugin as an internal plugin in the PluginList. +void RegisterInternalGPUPlugin(); + +} // namespace chrome + +#endif // CHROME_COMMON_GPU_PLUGIN_H_ diff --git a/chrome/plugin/command_buffer_stub.cc b/chrome/plugin/command_buffer_stub.cc index 632e868..d7dbf9f 100644 --- a/chrome/plugin/command_buffer_stub.cc +++ b/chrome/plugin/command_buffer_stub.cc @@ -8,6 +8,8 @@ #include "chrome/plugin/command_buffer_stub.h" #include "chrome/plugin/plugin_channel.h" +using gpu::Buffer; + CommandBufferStub::CommandBufferStub(PluginChannel* channel, gfx::NativeView view) : channel_(channel), @@ -42,23 +44,25 @@ void CommandBufferStub::OnInitialize(int32 size, // Assume service is responsible for duplicating the handle from the calling // process. base::ProcessHandle peer_handle; - if (base::OpenProcessHandle(channel_->peer_pid(), &peer_handle)) + if (!base::OpenProcessHandle(channel_->peer_pid(), &peer_handle)) return; command_buffer_.reset(new gpu::CommandBufferService); // Initialize the CommandBufferService and GPUProcessor. - base::SharedMemory* shared_memory = command_buffer_->Initialize(size); - if (shared_memory) { - processor_ = new gpu::GPUProcessor(command_buffer_.get()); - if (processor_->Initialize(view_)) { - command_buffer_->SetPutOffsetChangeCallback( - NewCallback(processor_.get(), - &gpu::GPUProcessor::ProcessCommands)); - shared_memory->ShareToProcess(peer_handle, ring_buffer); - } else { - processor_ = NULL; - command_buffer_.reset(); + if (command_buffer_->Initialize(size)) { + Buffer buffer = command_buffer_->GetRingBuffer(); + if (buffer.shared_memory) { + processor_ = new gpu::GPUProcessor(command_buffer_.get()); + if (processor_->Initialize(view_)) { + command_buffer_->SetPutOffsetChangeCallback( + NewCallback(processor_.get(), + &gpu::GPUProcessor::ProcessCommands)); + buffer.shared_memory->ShareToProcess(peer_handle, ring_buffer); + } else { + processor_ = NULL; + command_buffer_.reset(); + } } } @@ -85,19 +89,23 @@ void CommandBufferStub::OnDestroyTransferBuffer(int32 id) { command_buffer_->DestroyTransferBuffer(id); } -void CommandBufferStub::OnGetTransferBuffer(int32 id, - base::SharedMemoryHandle* transfer_buffer) { +void CommandBufferStub::OnGetTransferBuffer( + int32 id, + base::SharedMemoryHandle* transfer_buffer, + size_t* size) { *transfer_buffer = 0; + *size = 0; // Assume service is responsible for duplicating the handle to the calling // process. base::ProcessHandle peer_handle; - if (base::OpenProcessHandle(channel_->peer_pid(), &peer_handle)) + if (!base::OpenProcessHandle(channel_->peer_pid(), &peer_handle)) return; - base::SharedMemory* shared_memory = command_buffer_->GetTransferBuffer(id); - if (shared_memory) { - shared_memory->ShareToProcess(peer_handle, transfer_buffer); + Buffer buffer = command_buffer_->GetTransferBuffer(id); + if (buffer.shared_memory) { + buffer.shared_memory->ShareToProcess(peer_handle, transfer_buffer); + *size = buffer.shared_memory->max_size(); } base::CloseProcessHandle(peer_handle); diff --git a/chrome/plugin/command_buffer_stub.h b/chrome/plugin/command_buffer_stub.h index 2a167c3..c7d765e 100644 --- a/chrome/plugin/command_buffer_stub.h +++ b/chrome/plugin/command_buffer_stub.h @@ -43,7 +43,8 @@ class CommandBufferStub : public IPC::Channel::Listener, void OnCreateTransferBuffer(int32 size, int32* id); void OnDestroyTransferBuffer(int32 id); void OnGetTransferBuffer(int32 id, - base::SharedMemoryHandle* transfer_buffer); + base::SharedMemoryHandle* transfer_buffer, + size_t* size); void OnGetToken(int32* token); void OnResetParseError(int32* parse_error); void OnGetErrorStatus(bool* error_status); diff --git a/chrome/plugin/plugin_main.cc b/chrome/plugin/plugin_main.cc index 5863621..319ccce 100644 --- a/chrome/plugin/plugin_main.cc +++ b/chrome/plugin/plugin_main.cc @@ -15,6 +15,7 @@ #include "chrome/common/child_process.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_switches.h" +#include "chrome/common/gpu_plugin.h" #include "chrome/common/logging_chrome.h" #include "chrome/common/main_function_params.h" #include "chrome/plugin/plugin_thread.h" @@ -112,6 +113,8 @@ int PluginMain(const MainFunctionParams& parameters) { } #endif + chrome::RegisterInternalGPUPlugin(); + MessageLoop::current()->Run(); } diff --git a/chrome/plugin/webplugin_delegate_stub.cc b/chrome/plugin/webplugin_delegate_stub.cc index b2b4b33..49c535c 100644 --- a/chrome/plugin/webplugin_delegate_stub.cc +++ b/chrome/plugin/webplugin_delegate_stub.cc @@ -369,7 +369,7 @@ void WebPluginDelegateStub::OnCreateCommandBuffer(int* route_id) { *route_id = command_buffer_stub_->route_id(); #else *route_id = 0; -#endif +#endif // ENABLE_GPU } void WebPluginDelegateStub::CreateSharedBuffer( diff --git a/chrome/plugin/webplugin_delegate_stub.h b/chrome/plugin/webplugin_delegate_stub.h index d5d3ab0..34358fa 100644 --- a/chrome/plugin/webplugin_delegate_stub.h +++ b/chrome/plugin/webplugin_delegate_stub.h @@ -6,6 +6,8 @@ #define CHROME_PLUGIN_WEBPLUGIN_DELEGATE_STUB_H_ #include <queue> +#include <string> +#include <vector> #include "base/gfx/rect.h" #include "base/ref_counted.h" diff --git a/chrome/renderer/command_buffer_proxy.cc b/chrome/renderer/command_buffer_proxy.cc index 262bb8e..b78fa84 100644 --- a/chrome/renderer/command_buffer_proxy.cc +++ b/chrome/renderer/command_buffer_proxy.cc @@ -8,6 +8,9 @@ #include "chrome/common/plugin_messages.h" #include "chrome/renderer/command_buffer_proxy.h" #include "chrome/renderer/plugin_channel_host.h" +#include "gpu/command_buffer/common/cmd_buffer_common.h" + +using gpu::Buffer; CommandBufferProxy::CommandBufferProxy( PluginChannelHost* channel, @@ -18,6 +21,14 @@ CommandBufferProxy::CommandBufferProxy( } CommandBufferProxy::~CommandBufferProxy() { + // Delete all the locally cached shared memory objects, closing the handle + // in this process. + for (TransferBufferMap::iterator it = transfer_buffers_.begin(); + it != transfer_buffers_.end(); + ++it) { + delete it->second.shared_memory; + it->second.shared_memory = NULL; + } } bool CommandBufferProxy::Send(IPC::Message* msg) { @@ -30,10 +41,10 @@ bool CommandBufferProxy::Send(IPC::Message* msg) { return false; } -base::SharedMemory* CommandBufferProxy::Initialize(int32 size) { +bool CommandBufferProxy::Initialize(int32 size) { DCHECK(!ring_buffer_.get()); - // Initialize the service. Assuming we are in the renderer process, the GPU + // Initialize the service. Assuming we are sandboxed, the GPU // process is responsible for duplicating the handle. This might not be true // for NaCl. base::SharedMemoryHandle handle; @@ -42,18 +53,22 @@ base::SharedMemory* CommandBufferProxy::Initialize(int32 size) { ring_buffer_.reset(new base::SharedMemory(handle, false)); if (ring_buffer_->Map(size * sizeof(int32))) { size_ = size; - return ring_buffer_.get(); + return true; } ring_buffer_.reset(); } - return NULL; + return false; } -base::SharedMemory* CommandBufferProxy::GetRingBuffer() { +Buffer CommandBufferProxy::GetRingBuffer() { // Return locally cached ring buffer. - return ring_buffer_.get(); + Buffer buffer; + buffer.ptr = ring_buffer_->memory(); + buffer.size = size_ * sizeof(gpu::CommandBufferEntry); + buffer.shared_memory = ring_buffer_.get(); + return buffer; } int32 CommandBufferProxy::GetSize() { @@ -107,30 +122,55 @@ int32 CommandBufferProxy::CreateTransferBuffer(size_t size) { void CommandBufferProxy::DestroyTransferBuffer(int32 id) { // Remove the transfer buffer from the client side4 cache. - transfer_buffers_.erase(id); + TransferBufferMap::iterator it = transfer_buffers_.find(id); + DCHECK(it != transfer_buffers_.end()); + + // Delete the shared memory object, closing the handle in this process. + delete it->second.shared_memory; + + transfer_buffers_.erase(it); Send(new CommandBufferMsg_DestroyTransferBuffer(route_id_, id)); } -base::SharedMemory* CommandBufferProxy::GetTransferBuffer(int32 id) { +Buffer CommandBufferProxy::GetTransferBuffer(int32 id) { // Check local cache to see if there is already a client side shared memory // object for this id. TransferBufferMap::iterator it = transfer_buffers_.find(id); - if (it != transfer_buffers_.end()) - return it->second.get(); + if (it != transfer_buffers_.end()) { + return it->second; + } // Assuming we are in the renderer process, the service is responsible for // duplicating the handle. This might not be true for NaCl. base::SharedMemoryHandle handle; - if (!Send(new CommandBufferMsg_GetTransferBuffer(route_id_, id, &handle))) - return NULL; + size_t size; + if (!Send(new CommandBufferMsg_GetTransferBuffer(route_id_, + id, + &handle, + &size))) { + return Buffer(); + } // Cache the transfer buffer shared memory object client side. - base::SharedMemory* transfer_buffer = + base::SharedMemory* shared_memory = new base::SharedMemory(handle, false, base::GetCurrentProcessHandle()); - transfer_buffers_[id].reset(transfer_buffer); - return transfer_buffer; + // Map the shared memory on demand. + if (!shared_memory->memory()) { + if (!shared_memory->Map(shared_memory->max_size())) { + delete shared_memory; + return Buffer(); + } + } + + Buffer buffer; + buffer.ptr = shared_memory->memory(); + buffer.size = size; + buffer.shared_memory = shared_memory; + transfer_buffers_[id] = buffer; + + return buffer; } int32 CommandBufferProxy::GetToken() { diff --git a/chrome/renderer/command_buffer_proxy.h b/chrome/renderer/command_buffer_proxy.h index 5abfead..7453988 100644 --- a/chrome/renderer/command_buffer_proxy.h +++ b/chrome/renderer/command_buffer_proxy.h @@ -33,8 +33,8 @@ class CommandBufferProxy : public gpu::CommandBuffer, virtual bool Send(IPC::Message* msg); // CommandBuffer implementation: - virtual base::SharedMemory* Initialize(int32 size); - virtual base::SharedMemory* GetRingBuffer(); + virtual bool Initialize(int32 size); + virtual gpu::Buffer GetRingBuffer(); virtual int32 GetSize(); virtual int32 SyncOffsets(int32 put_offset); virtual int32 GetGetOffset(); @@ -43,7 +43,7 @@ class CommandBufferProxy : public gpu::CommandBuffer, virtual void SetPutOffsetChangeCallback(Callback0::Type* callback); virtual int32 CreateTransferBuffer(size_t size); virtual void DestroyTransferBuffer(int32 id); - virtual base::SharedMemory* GetTransferBuffer(int32 handle); + virtual gpu::Buffer GetTransferBuffer(int32 handle); virtual int32 GetToken(); virtual void SetToken(int32 token); virtual int32 ResetParseError(); @@ -57,7 +57,7 @@ class CommandBufferProxy : public gpu::CommandBuffer, scoped_ptr<base::SharedMemory> ring_buffer_; // Local cache of id to transfer buffer mapping. - typedef std::map<int32, linked_ptr<base::SharedMemory> > TransferBufferMap; + typedef std::map<int32, gpu::Buffer> TransferBufferMap; TransferBufferMap transfer_buffers_; scoped_refptr<PluginChannelHost> channel_; diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index c4f7483..6313755 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -2671,7 +2671,10 @@ webkit_glue::WebPluginDelegate* RenderView::CreatePluginDelegate( #if defined(OS_WIN) // In-proc plugins aren't supported on Linux or Mac. if (use_pepper_host) { return WebPluginDelegatePepper::Create( - path, *mime_type_to_use, gfx::NativeViewFromId(host_window_)); + path, + *mime_type_to_use, + AsWeakPtr(), + gfx::NativeViewFromId(host_window_)); } else { return WebPluginDelegateImpl::Create( path, *mime_type_to_use, gfx::NativeViewFromId(host_window_)); diff --git a/chrome/renderer/webplugin_delegate_pepper.cc b/chrome/renderer/webplugin_delegate_pepper.cc index 5fc549c..4c32b7b 100644 --- a/chrome/renderer/webplugin_delegate_pepper.cc +++ b/chrome/renderer/webplugin_delegate_pepper.cc @@ -18,6 +18,7 @@ #include "base/string_util.h" #include "chrome/common/render_messages.h" #include "chrome/renderer/render_thread.h" +#include "chrome/renderer/webplugin_delegate_proxy.h" #include "third_party/npapi/bindings/npapi_extensions.h" #include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h" #include "webkit/glue/glue_util.h" @@ -28,6 +29,11 @@ #include "webkit/glue/plugins/plugin_stream_url.h" #include "webkit/glue/webkit_glue.h" +#if defined(ENABLE_GPU) +#include "webkit/glue/plugins/plugin_constants_win.h" +#endif + +using gpu::Buffer; using webkit_glue::WebPlugin; using webkit_glue::WebPluginDelegate; using webkit_glue::WebPluginResourceClient; @@ -53,6 +59,7 @@ uint32 WebPluginDelegatePepper::next_buffer_id = 0; WebPluginDelegatePepper* WebPluginDelegatePepper::Create( const FilePath& filename, const std::string& mime_type, + const base::WeakPtr<RenderView>& render_view, gfx::PluginWindowHandle containing_view) { scoped_refptr<NPAPI::PluginLib> plugin_lib = NPAPI::PluginLib::CreatePluginLib(filename); @@ -65,7 +72,9 @@ WebPluginDelegatePepper* WebPluginDelegatePepper::Create( scoped_refptr<NPAPI::PluginInstance> instance = plugin_lib->CreateInstance(mime_type); - return new WebPluginDelegatePepper(containing_view, instance.get()); + return new WebPluginDelegatePepper(render_view, + containing_view, + instance.get()); } bool WebPluginDelegatePepper::Initialize( @@ -98,9 +107,6 @@ bool WebPluginDelegatePepper::Initialize( // retreived via NPN_GetValue of NPNVnetscapeWindow. instance_->set_window_handle(parent_); - // This is a windowless plugin, so set it to have a NULL handle. - plugin_->SetWindow(NULL); - plugin_url_ = url.spec(); return true; @@ -147,6 +153,10 @@ void WebPluginDelegatePepper::UpdateGeometry( new_committed.allocPixels(); committed_bitmap_ = new_committed; + // Forward the new geometry to the nested plugin instance. + if (nested_delegate_) + nested_delegate_->UpdateGeometry(window_rect, clip_rect); + if (!instance()) return; @@ -247,6 +257,11 @@ NPError WebPluginDelegatePepper::Device2DQueryConfig( NPError WebPluginDelegatePepper::Device2DInitializeContext( const NPDeviceContext2DConfig* config, NPDeviceContext2D* context) { + // This is a windowless plugin, so set it to have a NULL handle. Defer this + // until we know the plugin will use the 2D device. If it uses the 3D device + // it will have a window handle. + plugin_->SetWindow(NULL); + int width = window_rect_.width(); int height = window_rect_.height(); uint32 buffer_size = width * height * kBytesPerPixel; @@ -392,6 +407,49 @@ NPError WebPluginDelegatePepper::Device3DQueryConfig( NPError WebPluginDelegatePepper::Device3DInitializeContext( const NPDeviceContext3DConfig* config, NPDeviceContext3D* context) { +#if defined(ENABLE_GPU) + // Check to see if the GPU plugin is already initialized and fail if so. + if (nested_delegate_) + return NPERR_GENERIC_ERROR; + + // Create an instance of the GPU plugin that is responsible for 3D + // rendering. + nested_delegate_ = new WebPluginDelegateProxy(kGPUPluginMimeType, + render_view_); + + // TODO(apatrick): should the GPU plugin be attached to plugin_? + if (nested_delegate_->Initialize(GURL(), + std::vector<std::string>(), + std::vector<std::string>(), + plugin_, + false)) { + // Ask the GPU plugin to create a command buffer and return a proxy. + command_buffer_.reset(nested_delegate_->CreateCommandBuffer()); + if (command_buffer_.get()) { + // Initialize the proxy command buffer. + if (command_buffer_->Initialize(config->commandBufferEntries)) { + // Initialize the 3D context. + context->reserved = NULL; + Buffer ring_buffer = command_buffer_->GetRingBuffer(); + context->commandBuffer = ring_buffer.ptr; + context->commandBufferEntries = command_buffer_->GetSize(); + context->getOffset = command_buffer_->GetGetOffset(); + context->putOffset = command_buffer_->GetPutOffset(); + + // Ensure the service knows the window size before rendering anything. + nested_delegate_->UpdateGeometry(window_rect_, clip_rect_); + + return NPERR_NO_ERROR; + } + } + + command_buffer_.reset(); + } + + nested_delegate_->PluginDestroyed(); + nested_delegate_ = NULL; +#endif // ENABLE_GPU + return NPERR_GENERIC_ERROR; } @@ -406,7 +464,32 @@ NPError WebPluginDelegatePepper::Device3DGetStateContext( NPDeviceContext3D* context, int32 state, int32* value) { - return NPERR_GENERIC_ERROR; +#if defined(ENABLE_GPU) + if (!command_buffer_.get()) + return NPERR_GENERIC_ERROR; + + switch (state) { + case NPDeviceContext3DState_GetOffset: + context->getOffset = *value = command_buffer_->GetGetOffset(); + break; + case NPDeviceContext3DState_PutOffset: + *value = command_buffer_->GetPutOffset(); + break; + case NPDeviceContext3DState_Token: + *value = command_buffer_->GetToken(); + break; + case NPDeviceContext3DState_ParseError: + *value = command_buffer_->ResetParseError(); + break; + case NPDeviceContext3DState_ErrorStatus: + *value = command_buffer_->GetErrorStatus() ? 1 : 0; + break; + default: + return NPERR_GENERIC_ERROR; + }; +#endif // ENABLE_GPU + + return NPERR_NO_ERROR; } NPError WebPluginDelegatePepper::Device3DFlushContext( @@ -414,37 +497,75 @@ NPError WebPluginDelegatePepper::Device3DFlushContext( NPDeviceContext3D* context, NPDeviceFlushContextCallbackPtr callback, void* user_data) { - return NPERR_GENERIC_ERROR; +#if defined(ENABLE_GPU) + DCHECK(callback == NULL); + context->getOffset = command_buffer_->SyncOffsets(context->putOffset); +#endif // ENABLE_GPU + return NPERR_NO_ERROR; } NPError WebPluginDelegatePepper::Device3DDestroyContext( NPDeviceContext3D* context) { - return NPERR_GENERIC_ERROR; +#if defined(ENABLE_GPU) + command_buffer_.reset(); + + if (nested_delegate_) { + nested_delegate_->PluginDestroyed(); + nested_delegate_ = NULL; + } +#endif // ENABLE_GPU + + return NPERR_NO_ERROR; } -bool WebPluginDelegatePepper::IsPluginDelegateWindow( - gfx::NativeWindow window) { - return false; +NPError WebPluginDelegatePepper::Device3DCreateBuffer( + NPDeviceContext3D* context, + size_t size, + int32* id) { +#if defined(ENABLE_GPU) + *id = command_buffer_->CreateTransferBuffer(size); + if (*id < 0) + return NPERR_GENERIC_ERROR; +#endif // ENABLE_GPU + + return NPERR_NO_ERROR; } -bool WebPluginDelegatePepper::GetPluginNameFromWindow( - gfx::NativeWindow window, std::wstring *plugin_name) { - return false; +NPError WebPluginDelegatePepper::Device3DDestroyBuffer( + NPDeviceContext3D* context, + int32 id) { +#if defined(ENABLE_GPU) + command_buffer_->DestroyTransferBuffer(id); +#endif // ENABLE_GPU + return NPERR_NO_ERROR; } -bool WebPluginDelegatePepper::IsDummyActivationWindow( - gfx::NativeWindow window) { - return false; +NPError WebPluginDelegatePepper::Device3DMapBuffer( + NPDeviceContext3D* context, + int32 id, + NPDeviceBuffer* np_buffer) { +#if defined(ENABLE_GPU) + Buffer gpu_buffer = command_buffer_->GetTransferBuffer(id); + np_buffer->ptr = gpu_buffer.ptr; + np_buffer->size = gpu_buffer.size; + if (!np_buffer->ptr) + return NPERR_GENERIC_ERROR; +#endif // ENABLE_GPU + + return NPERR_NO_ERROR; } WebPluginDelegatePepper::WebPluginDelegatePepper( + const base::WeakPtr<RenderView>& render_view, gfx::PluginWindowHandle containing_view, NPAPI::PluginInstance *instance) - : plugin_(NULL), + : render_view_(render_view), + plugin_(NULL), instance_(instance), parent_(containing_view), buffer_size_(0), - plugin_buffer_(0) { + plugin_buffer_(0), + nested_delegate_(NULL) { // For now we keep a window struct, although it isn't used. memset(&window_, 0, sizeof(window_)); // All Pepper plugins are windowless and transparent. @@ -458,18 +579,27 @@ WebPluginDelegatePepper::~WebPluginDelegatePepper() { } void WebPluginDelegatePepper::PluginDestroyed() { + if (nested_delegate_) { + nested_delegate_->PluginDestroyed(); + nested_delegate_ = NULL; + } delete this; } void WebPluginDelegatePepper::Paint(WebKit::WebCanvas* canvas, const gfx::Rect& rect) { #if defined(OS_WIN) - // Blit from background_context to context. - if (!committed_bitmap_.isNull()) { - gfx::Point origin(window_rect_.origin().x(), window_rect_.origin().y()); - canvas->drawBitmap(committed_bitmap_, - SkIntToScalar(window_rect_.origin().x()), - SkIntToScalar(window_rect_.origin().y())); + if (nested_delegate_) { + // TODO(apatrick): The GPU plugin will render to an offscreen render target. + // Need to copy it to the screen here. + } else { + // Blit from background_context to context. + if (!committed_bitmap_.isNull()) { + gfx::Point origin(window_rect_.origin().x(), window_rect_.origin().y()); + canvas->drawBitmap(committed_bitmap_, + SkIntToScalar(window_rect_.origin().x()), + SkIntToScalar(window_rect_.origin().y())); + } } #endif } diff --git a/chrome/renderer/webplugin_delegate_pepper.h b/chrome/renderer/webplugin_delegate_pepper.h index aa798d7..2e78500 100644 --- a/chrome/renderer/webplugin_delegate_pepper.h +++ b/chrome/renderer/webplugin_delegate_pepper.h @@ -18,7 +18,10 @@ #include "base/ref_counted.h" #include "base/scoped_ptr.h" #include "base/task.h" +#include "base/weak_ptr.h" #include "chrome/common/transport_dib.h" +#include "chrome/renderer/render_view.h" +#include "chrome/renderer/command_buffer_proxy.h" #include "skia/ext/platform_canvas.h" #include "third_party/npapi/bindings/npapi.h" #include "third_party/npapi/bindings/npapi_extensions.h" @@ -32,16 +35,11 @@ class PluginInstance; // An implementation of WebPluginDelegate for Pepper in-process plugins. class WebPluginDelegatePepper : public webkit_glue::WebPluginDelegate { public: - static WebPluginDelegatePepper* Create(const FilePath& filename, - const std::string& mime_type, gfx::PluginWindowHandle containing_view); - - static bool IsPluginDelegateWindow(gfx::NativeWindow window); - static bool GetPluginNameFromWindow(gfx::NativeWindow window, - std::wstring *plugin_name); - - // Returns true if the window handle passed in is that of the dummy - // activation window for windowless plugins. - static bool IsDummyActivationWindow(gfx::NativeWindow window); + static WebPluginDelegatePepper* Create( + const FilePath& filename, + const std::string& mime_type, + const base::WeakPtr<RenderView>& render_view, + gfx::PluginWindowHandle containing_view); // WebPluginDelegate implementation virtual bool Initialize(const GURL& url, @@ -118,9 +116,16 @@ class WebPluginDelegatePepper : public webkit_glue::WebPluginDelegate { NPDeviceFlushContextCallbackPtr callback, void* user_data); virtual NPError Device3DDestroyContext(NPDeviceContext3D* context); + virtual NPError Device3DCreateBuffer(NPDeviceContext3D* context, + size_t size, + int32* id); + virtual NPError Device3DDestroyBuffer(NPDeviceContext3D* context, + int32 id); + virtual NPError Device3DMapBuffer(NPDeviceContext3D* context, + int32 id, + NPDeviceBuffer* buffer); // End of WebPluginDelegate implementation. - bool IsWindowless() const { return true; } gfx::Rect GetRect() const { return window_rect_; } gfx::Rect GetClipRect() const { return clip_rect_; } @@ -128,8 +133,10 @@ class WebPluginDelegatePepper : public webkit_glue::WebPluginDelegate { FilePath GetPluginPath(); private: - WebPluginDelegatePepper(gfx::PluginWindowHandle containing_view, - NPAPI::PluginInstance *instance); + WebPluginDelegatePepper( + const base::WeakPtr<RenderView>& render_view, + gfx::PluginWindowHandle containing_view, + NPAPI::PluginInstance *instance); ~WebPluginDelegatePepper(); // Tells the plugin about the current state of the window. @@ -144,6 +151,8 @@ class WebPluginDelegatePepper : public webkit_glue::WebPluginDelegate { // Closes down and destroys our plugin instance. void DestroyInstance(); + base::WeakPtr<RenderView> render_view_; + webkit_glue::WebPlugin* plugin_; scoped_refptr<NPAPI::PluginInstance> instance_; @@ -176,6 +185,12 @@ class WebPluginDelegatePepper : public webkit_glue::WebPluginDelegate { // The url with which the plugin was instantiated. std::string plugin_url_; + // The nested GPU plugin and its command buffer proxy. + WebPluginDelegateProxy* nested_delegate_; +#if defined(ENABLE_GPU) + scoped_ptr<CommandBufferProxy> command_buffer_; +#endif + DISALLOW_COPY_AND_ASSIGN(WebPluginDelegatePepper); }; diff --git a/chrome/renderer/webplugin_delegate_proxy.cc b/chrome/renderer/webplugin_delegate_proxy.cc index 78f3dfe..f459b51 100644 --- a/chrome/renderer/webplugin_delegate_proxy.cc +++ b/chrome/renderer/webplugin_delegate_proxy.cc @@ -1153,7 +1153,7 @@ CommandBufferProxy* WebPluginDelegateProxy::CreateCommandBuffer() { return new CommandBufferProxy(channel_host_, command_buffer_id); #else return NULL; -#endif +#endif // ENABLE_GPU } void WebPluginDelegateProxy::OnCancelDocumentLoad() { |